• 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 
712   switch (type) {
713     case GATT_READ_BY_TYPE:
714     case GATT_READ_CHAR_VALUE:
715       p_clcb->s_handle = p_read->service.s_handle;
716       p_clcb->e_handle = p_read->service.e_handle;
717       p_clcb->uuid = p_read->service.uuid;
718       break;
719     case GATT_READ_MULTIPLE: {
720       p_clcb->s_handle = 0;
721       /* copy multiple handles in CB */
722       tGATT_READ_MULTI* p_read_multi =
723           (tGATT_READ_MULTI*)osi_malloc(sizeof(tGATT_READ_MULTI));
724       p_clcb->p_attr_buf = (uint8_t*)p_read_multi;
725       memcpy(p_read_multi, &p_read->read_multiple, sizeof(tGATT_READ_MULTI));
726       break;
727     }
728     case GATT_READ_BY_HANDLE:
729     case GATT_READ_PARTIAL:
730       p_clcb->uuid = Uuid::kEmpty;
731       p_clcb->s_handle = p_read->by_handle.handle;
732 
733       if (type == GATT_READ_PARTIAL) {
734         p_clcb->counter = p_read->partial.offset;
735       }
736 
737       break;
738     default:
739       break;
740   }
741 
742   /* start security check */
743   if (gatt_security_check_start(p_clcb)) p_tcb->pending_enc_clcb.push(p_clcb);
744   return GATT_SUCCESS;
745 }
746 
747 /*******************************************************************************
748  *
749  * Function         GATTC_Write
750  *
751  * Description      This function is called to write the value of an attribute
752  *                  to the server.
753  *
754  * Parameters       conn_id: connection identifier.
755  *                  type    - attribute write type.
756  *                  p_write  - write operation parameters.
757  *
758  * Returns          GATT_SUCCESS if command started successfully.
759  *
760  ******************************************************************************/
GATTC_Write(uint16_t conn_id,tGATT_WRITE_TYPE type,tGATT_VALUE * p_write)761 tGATT_STATUS GATTC_Write(uint16_t conn_id, tGATT_WRITE_TYPE type,
762                          tGATT_VALUE* p_write) {
763   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
764   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
765   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
766   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
767 
768   if ((p_tcb == NULL) || (p_reg == NULL) || (p_write == NULL) ||
769       ((type != GATT_WRITE) && (type != GATT_WRITE_PREPARE) &&
770        (type != GATT_WRITE_NO_RSP))) {
771     LOG(ERROR) << __func__ << " Illegal param: conn_id=" << loghex(conn_id)
772                << ", type=" << loghex(type);
773     return GATT_ILLEGAL_PARAMETER;
774   }
775 
776   if (gatt_is_clcb_allocated(conn_id)) {
777     LOG(ERROR) << "GATT_BUSY conn_id=" << loghex(conn_id);
778     return GATT_BUSY;
779   }
780 
781   tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
782   if (!p_clcb) return GATT_NO_RESOURCES;
783 
784   p_clcb->operation = GATTC_OPTYPE_WRITE;
785   p_clcb->op_subtype = type;
786   p_clcb->auth_req = p_write->auth_req;
787 
788   p_clcb->p_attr_buf = (uint8_t*)osi_malloc(sizeof(tGATT_VALUE));
789   memcpy(p_clcb->p_attr_buf, (void*)p_write, sizeof(tGATT_VALUE));
790 
791   tGATT_VALUE* p = (tGATT_VALUE*)p_clcb->p_attr_buf;
792   if (type == GATT_WRITE_PREPARE) {
793     p_clcb->start_offset = p_write->offset;
794     p->offset = 0;
795   }
796 
797   if (gatt_security_check_start(p_clcb)) p_tcb->pending_enc_clcb.push(p_clcb);
798   return GATT_SUCCESS;
799 }
800 
801 /*******************************************************************************
802  *
803  * Function         GATTC_ExecuteWrite
804  *
805  * Description      This function is called to send an Execute write request to
806  *                  the server.
807  *
808  * Parameters       conn_id: connection identifier.
809  *                  is_execute - to execute or cancel the prepared write
810  *                               request(s)
811  *
812  * Returns          GATT_SUCCESS if command started successfully.
813  *
814  ******************************************************************************/
GATTC_ExecuteWrite(uint16_t conn_id,bool is_execute)815 tGATT_STATUS GATTC_ExecuteWrite(uint16_t conn_id, bool is_execute) {
816   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
817   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
818   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
819   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
820 
821   VLOG(1) << __func__ << ": conn_id=" << loghex(conn_id)
822           << ", is_execute=" << +is_execute;
823 
824   if ((p_tcb == NULL) || (p_reg == NULL)) {
825     LOG(ERROR) << " Illegal param: conn_id=" << loghex(conn_id);
826     return GATT_ILLEGAL_PARAMETER;
827   }
828 
829   if (gatt_is_clcb_allocated(conn_id)) {
830     LOG(ERROR) << " GATT_BUSY conn_id=" << loghex(conn_id);
831     return GATT_BUSY;
832   }
833 
834   tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
835   if (!p_clcb) return GATT_NO_RESOURCES;
836 
837   p_clcb->operation = GATTC_OPTYPE_EXE_WRITE;
838   tGATT_EXEC_FLAG flag =
839       is_execute ? GATT_PREP_WRITE_EXEC : GATT_PREP_WRITE_CANCEL;
840   gatt_send_queue_write_cancel(*p_clcb->p_tcb, p_clcb, flag);
841   return GATT_SUCCESS;
842 }
843 
844 /*******************************************************************************
845  *
846  * Function         GATTC_SendHandleValueConfirm
847  *
848  * Description      This function is called to send a handle value confirmation
849  *                  as response to a handle value notification from server.
850  *
851  * Parameters       conn_id: connection identifier.
852  *                  handle: the handle of the attribute confirmation.
853  *
854  * Returns          GATT_SUCCESS if command started successfully.
855  *
856  ******************************************************************************/
GATTC_SendHandleValueConfirm(uint16_t conn_id,uint16_t handle)857 tGATT_STATUS GATTC_SendHandleValueConfirm(uint16_t conn_id, uint16_t handle) {
858   VLOG(1) << __func__ << " conn_id=" << loghex(conn_id)
859           << ", handle=" << loghex(handle);
860 
861   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(GATT_GET_TCB_IDX(conn_id));
862   if (!p_tcb) {
863     LOG(ERROR) << "Unknown conn_id=" << loghex(conn_id);
864     return GATT_ILLEGAL_PARAMETER;
865   }
866 
867   if (p_tcb->ind_count == 0) {
868     VLOG(1) << " conn_id: " << loghex(conn_id)
869             << " ignored not waiting for indicaiton ack";
870     return GATT_SUCCESS;
871   }
872 
873   alarm_cancel(p_tcb->ind_ack_timer);
874 
875   VLOG(1) << "notif_count= " << p_tcb->ind_count;
876   /* send confirmation now */
877   tGATT_CL_MSG gatt_cl_msg;
878   gatt_cl_msg.handle = handle;
879   tGATT_STATUS ret =
880       attp_send_cl_msg(*p_tcb, nullptr, GATT_HANDLE_VALUE_CONF, &gatt_cl_msg);
881 
882   p_tcb->ind_count = 0;
883 
884   return ret;
885 }
886 
887 /******************************************************************************/
888 /*                                                                            */
889 /*                  GATT  APIs                                                */
890 /*                                                                            */
891 /******************************************************************************/
892 /*******************************************************************************
893  *
894  * Function         GATT_SetIdleTimeout
895  *
896  * Description      This function (common to both client and server) sets the
897  *                  idle timeout for a tansport connection
898  *
899  * Parameter        bd_addr:   target device bd address.
900  *                  idle_tout: timeout value in seconds.
901  *
902  * Returns          void
903  *
904  ******************************************************************************/
GATT_SetIdleTimeout(const RawAddress & bd_addr,uint16_t idle_tout,tBT_TRANSPORT transport)905 void GATT_SetIdleTimeout(const RawAddress& bd_addr, uint16_t idle_tout,
906                          tBT_TRANSPORT transport) {
907   bool status = false;
908 
909   tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
910   if (p_tcb != NULL) {
911     if (p_tcb->att_lcid == L2CAP_ATT_CID) {
912       status = L2CA_SetFixedChannelTout(bd_addr, L2CAP_ATT_CID, idle_tout);
913 
914       if (idle_tout == GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP)
915         L2CA_SetIdleTimeoutByBdAddr(p_tcb->peer_bda,
916                                     GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP,
917                                     BT_TRANSPORT_LE);
918     } else {
919       status = L2CA_SetIdleTimeout(p_tcb->att_lcid, idle_tout, false);
920     }
921   }
922 
923   VLOG(1) << __func__ << " idle_tout=" << idle_tout << ", status=" << +status
924           << " (1-OK 0-not performed)";
925 }
926 
927 /*******************************************************************************
928  *
929  * Function         GATT_Register
930  *
931  * Description      This function is called to register an  application
932  *                  with GATT
933  *
934  * Parameter        p_app_uuid128: Application UUID
935  *                  p_cb_info: callback functions.
936  *
937  * Returns          0 for error, otherwise the index of the client registered
938  *                  with GATT
939  *
940  ******************************************************************************/
GATT_Register(const Uuid & app_uuid128,tGATT_CBACK * p_cb_info)941 tGATT_IF GATT_Register(const Uuid& app_uuid128, tGATT_CBACK* p_cb_info) {
942   tGATT_REG* p_reg;
943   uint8_t i_gatt_if = 0;
944   tGATT_IF gatt_if = 0;
945 
946   LOG(INFO) << __func__ << " " << app_uuid128;
947 
948   for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS;
949        i_gatt_if++, p_reg++) {
950     if (p_reg->in_use && p_reg->app_uuid128 == app_uuid128) {
951       LOG(ERROR) << "application already registered.";
952       return 0;
953     }
954   }
955 
956   for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS;
957        i_gatt_if++, p_reg++) {
958     if (!p_reg->in_use) {
959       memset(p_reg, 0, sizeof(tGATT_REG));
960       i_gatt_if++; /* one based number */
961       p_reg->app_uuid128 = app_uuid128;
962       gatt_if = p_reg->gatt_if = (tGATT_IF)i_gatt_if;
963       p_reg->app_cb = *p_cb_info;
964       p_reg->in_use = true;
965 
966       LOG(INFO) << "allocated gatt_if=" << +gatt_if;
967       return gatt_if;
968     }
969   }
970 
971   LOG(ERROR) << "can't Register GATT client, MAX client reached: "
972              << GATT_MAX_APPS;
973   return 0;
974 }
975 
976 /*******************************************************************************
977  *
978  * Function         GATT_Deregister
979  *
980  * Description      This function deregistered the application from GATT.
981  *
982  * Parameters       gatt_if: applicaiton interface.
983  *
984  * Returns          None.
985  *
986  ******************************************************************************/
GATT_Deregister(tGATT_IF gatt_if)987 void GATT_Deregister(tGATT_IF gatt_if) {
988   VLOG(1) << __func__ << " gatt_if=" << +gatt_if;
989 
990   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
991   /* Index 0 is GAP and is never deregistered */
992   if ((gatt_if == 0) || (p_reg == NULL)) {
993     LOG(ERROR) << "invalid gatt_if=" << +gatt_if;
994     return;
995   }
996 
997   /* stop all services  */
998   /* todo an applcaiton can not be deregistered if its services is also used by
999     other application
1000     deregisteration need to bed performed in an orderly fashion
1001     no check for now */
1002   for (auto it = gatt_cb.srv_list_info->begin();
1003        it != gatt_cb.srv_list_info->end();) {
1004     if (it->gatt_if == gatt_if) {
1005       GATTS_StopService(it++->s_hdl);
1006     } else {
1007       ++it;
1008     }
1009   }
1010 
1011   /* free all services db buffers if owned by this application */
1012   gatt_free_srvc_db_buffer_app_id(p_reg->app_uuid128);
1013 
1014   /* When an application deregisters, check remove the link associated with the
1015    * app */
1016   tGATT_TCB* p_tcb;
1017   int i, j;
1018   for (i = 0, p_tcb = gatt_cb.tcb; i < GATT_MAX_PHY_CHANNEL; i++, p_tcb++) {
1019     if (!p_tcb->in_use) continue;
1020 
1021     if (gatt_get_ch_state(p_tcb) != GATT_CH_CLOSE) {
1022       gatt_update_app_use_link_flag(gatt_if, p_tcb, false, true);
1023     }
1024 
1025     tGATT_CLCB* p_clcb;
1026     for (j = 0, p_clcb = &gatt_cb.clcb[j]; j < GATT_CL_MAX_LCB; j++, p_clcb++) {
1027       if (p_clcb->in_use && (p_clcb->p_reg->gatt_if == gatt_if) &&
1028           (p_clcb->p_tcb->tcb_idx == p_tcb->tcb_idx)) {
1029         alarm_cancel(p_clcb->gatt_rsp_timer_ent);
1030         gatt_clcb_dealloc(p_clcb);
1031         break;
1032       }
1033     }
1034   }
1035 
1036   connection_manager::on_app_deregistered(gatt_if);
1037 
1038   memset(p_reg, 0, sizeof(tGATT_REG));
1039 }
1040 
1041 /*******************************************************************************
1042  *
1043  * Function         GATT_StartIf
1044  *
1045  * Description      This function is called after registration to start
1046  *                  receiving callbacks for registered interface.  Function may
1047  *                  call back with connection status and queued notifications
1048  *
1049  * Parameter        gatt_if: applicaiton interface.
1050  *
1051  * Returns          None.
1052  *
1053  ******************************************************************************/
GATT_StartIf(tGATT_IF gatt_if)1054 void GATT_StartIf(tGATT_IF gatt_if) {
1055   tGATT_REG* p_reg;
1056   tGATT_TCB* p_tcb;
1057   RawAddress bda;
1058   uint8_t start_idx, found_idx;
1059   uint16_t conn_id;
1060   tGATT_TRANSPORT transport;
1061 
1062   VLOG(1) << __func__ << " gatt_if=" << +gatt_if;
1063   p_reg = gatt_get_regcb(gatt_if);
1064   if (p_reg != NULL) {
1065     start_idx = 0;
1066     while (
1067         gatt_find_the_connected_bda(start_idx, bda, &found_idx, &transport)) {
1068       p_tcb = gatt_find_tcb_by_addr(bda, transport);
1069       if (p_reg->app_cb.p_conn_cb && p_tcb) {
1070         conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
1071         (*p_reg->app_cb.p_conn_cb)(gatt_if, bda, conn_id, true, 0, transport);
1072       }
1073       start_idx = ++found_idx;
1074     }
1075   }
1076 }
1077 
1078 /*******************************************************************************
1079  *
1080  * Function         GATT_Connect
1081  *
1082  * Description      This function initiate a connecttion to a remote device on
1083  *                  GATT channel.
1084  *
1085  * Parameters       gatt_if: applicaiton interface
1086  *                  bd_addr: peer device address.
1087  *                  is_direct: is a direct conenection or a background auto
1088  *                             connection
1089  *
1090  * Returns          true if connection started; false if connection start
1091  *                  failure.
1092  *
1093  ******************************************************************************/
GATT_Connect(tGATT_IF gatt_if,const RawAddress & bd_addr,bool is_direct,tBT_TRANSPORT transport,bool opportunistic)1094 bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, bool is_direct,
1095                   tBT_TRANSPORT transport, bool opportunistic) {
1096   uint8_t phy = controller_get_interface()->get_le_all_initiating_phys();
1097   return GATT_Connect(gatt_if, bd_addr, is_direct, transport, opportunistic,
1098                       phy);
1099 }
1100 
GATT_Connect(tGATT_IF gatt_if,const RawAddress & bd_addr,bool is_direct,tBT_TRANSPORT transport,bool opportunistic,uint8_t initiating_phys)1101 bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, bool is_direct,
1102                   tBT_TRANSPORT transport, bool opportunistic,
1103                   uint8_t initiating_phys) {
1104   LOG(INFO) << __func__ << "gatt_if=" << +gatt_if << ", address=" << bd_addr;
1105 
1106   /* Make sure app is registered */
1107   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
1108   if (!p_reg) {
1109     LOG(ERROR) << "gatt_if = " << +gatt_if << " is not registered";
1110     return false;
1111   }
1112 
1113   if (!is_direct && transport != BT_TRANSPORT_LE) {
1114     LOG(ERROR) << "Unsupported transport for background connection";
1115     return false;
1116   }
1117 
1118   if (opportunistic) {
1119     LOG(INFO) << __func__ << " opportunistic connection";
1120     return true;
1121   }
1122 
1123   bool ret;
1124   if (is_direct) {
1125     ret = gatt_act_connect(p_reg, bd_addr, transport, initiating_phys);
1126   } else {
1127     if (!BTM_BackgroundConnectAddressKnown(bd_addr)) {
1128       //  RPA can rotate, causing address to "expire" in the background
1129       //  connection list. RPA is allowed for direct connect, as such request
1130       //  times out after 30 seconds
1131       LOG(INFO) << "Can't add RPA to background connection.";
1132       ret = true;
1133     } else {
1134       ret = connection_manager::background_connect_add(gatt_if, bd_addr);
1135     }
1136   }
1137 
1138   tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
1139   // background connections don't necessarily create tcb
1140   if (p_tcb && ret)
1141     gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, true, !is_direct);
1142 
1143   return ret;
1144 }
1145 
1146 /*******************************************************************************
1147  *
1148  * Function         GATT_CancelConnect
1149  *
1150  * Description      This function terminate the connection initaition to a
1151  *                  remote device on GATT channel.
1152  *
1153  * Parameters       gatt_if: client interface. If 0 used as unconditionally
1154  *                           disconnect, typically used for direct connection
1155  *                           cancellation.
1156  *                  bd_addr: peer device address.
1157  *
1158  * Returns          true if the connection started; false otherwise.
1159  *
1160  ******************************************************************************/
GATT_CancelConnect(tGATT_IF gatt_if,const RawAddress & bd_addr,bool is_direct)1161 bool GATT_CancelConnect(tGATT_IF gatt_if, const RawAddress& bd_addr,
1162                         bool is_direct) {
1163   LOG(INFO) << __func__ << ": gatt_if:" << +gatt_if << ", address: " << bd_addr
1164             << ", direct:" << is_direct;
1165 
1166   tGATT_REG* p_reg;
1167   if (gatt_if) {
1168     p_reg = gatt_get_regcb(gatt_if);
1169     if (!p_reg) {
1170       LOG(ERROR) << "gatt_if=" << +gatt_if << " is not registered";
1171       return false;
1172     }
1173 
1174     if (is_direct)
1175       return gatt_cancel_open(gatt_if, bd_addr);
1176     else
1177       return gatt_auto_connect_dev_remove(p_reg->gatt_if, bd_addr);
1178   }
1179 
1180   VLOG(1) << " unconditional";
1181 
1182   /* only LE connection can be cancelled */
1183   tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
1184   if (p_tcb && !p_tcb->app_hold_link.empty()) {
1185     for (auto it = p_tcb->app_hold_link.begin();
1186          it != p_tcb->app_hold_link.end();) {
1187       auto next = std::next(it);
1188       // gatt_cancel_open modifies the app_hold_link.
1189       gatt_cancel_open(*it, bd_addr);
1190 
1191       it = next;
1192     }
1193   }
1194 
1195   if (!connection_manager::remove_unconditional(bd_addr)) {
1196     LOG(ERROR)
1197         << __func__
1198         << ": no app associated with the bg device for unconditional removal";
1199     return false;
1200   }
1201 
1202   return true;
1203 }
1204 
1205 /*******************************************************************************
1206  *
1207  * Function         GATT_Disconnect
1208  *
1209  * Description      This function disconnects the GATT channel for this
1210  *                  registered application.
1211  *
1212  * Parameters       conn_id: connection identifier.
1213  *
1214  * Returns          GATT_SUCCESS if disconnected.
1215  *
1216  ******************************************************************************/
GATT_Disconnect(uint16_t conn_id)1217 tGATT_STATUS GATT_Disconnect(uint16_t conn_id) {
1218   LOG(INFO) << __func__ << " conn_id=" << loghex(conn_id);
1219 
1220   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
1221   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
1222   if (!p_tcb) return GATT_ILLEGAL_PARAMETER;
1223 
1224   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
1225   gatt_update_app_use_link_flag(gatt_if, p_tcb, false, true);
1226   return GATT_SUCCESS;
1227 }
1228 
1229 /*******************************************************************************
1230  *
1231  * Function         GATT_GetConnectionInfor
1232  *
1233  * Description      This function uses conn_id to find its associated BD address
1234  *                  and application interface
1235  *
1236  * Parameters        conn_id: connection id  (input)
1237  *                   p_gatt_if: applicaiton interface (output)
1238  *                   bd_addr: peer device address. (output)
1239  *
1240  * Returns          true the ligical link information is found for conn_id
1241  *
1242  ******************************************************************************/
GATT_GetConnectionInfor(uint16_t conn_id,tGATT_IF * p_gatt_if,RawAddress & bd_addr,tBT_TRANSPORT * p_transport)1243 bool GATT_GetConnectionInfor(uint16_t conn_id, tGATT_IF* p_gatt_if,
1244                              RawAddress& bd_addr, tBT_TRANSPORT* p_transport) {
1245   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
1246   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
1247   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
1248   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
1249 
1250   VLOG(1) << __func__ << " conn_id=" << loghex(conn_id);
1251 
1252   if (!p_tcb || !p_reg) return false;
1253 
1254   bd_addr = p_tcb->peer_bda;
1255   *p_gatt_if = gatt_if;
1256   *p_transport = p_tcb->transport;
1257   return true;
1258 }
1259 
1260 /*******************************************************************************
1261  *
1262  * Function         GATT_GetConnIdIfConnected
1263  *
1264  * Description      This function find the conn_id if the logical link for BD
1265  *                  address and applciation interface is connected
1266  *
1267  * Parameters        gatt_if: applicaiton interface (input)
1268  *                   bd_addr: peer device address. (input)
1269  *                   p_conn_id: connection id  (output)
1270  *                   transport: transport option
1271  *
1272  * Returns          true the logical link is connected
1273  *
1274  ******************************************************************************/
GATT_GetConnIdIfConnected(tGATT_IF gatt_if,const RawAddress & bd_addr,uint16_t * p_conn_id,tBT_TRANSPORT transport)1275 bool GATT_GetConnIdIfConnected(tGATT_IF gatt_if, const RawAddress& bd_addr,
1276                                uint16_t* p_conn_id, tBT_TRANSPORT transport) {
1277   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
1278   tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
1279   bool status = false;
1280 
1281   if (p_reg && p_tcb && (gatt_get_ch_state(p_tcb) == GATT_CH_OPEN)) {
1282     *p_conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
1283     status = true;
1284   }
1285 
1286   VLOG(1) << __func__ << " status= " << +status;
1287   return status;
1288 }
1289