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 <base/strings/stringprintf.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include "bt_common.h"
31 #include "btm_int.h"
32 #include "device/include/controller.h"
33 #include "gatt_api.h"
34 #include "gatt_int.h"
35 #include "l2c_api.h"
36 
37 using base::StringPrintf;
38 using bluetooth::Uuid;
39 
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) << StringPrintf(
188         "GATTS_ReserveHandles: no handles, s_hdl: %u  needed: %u", s_hdl,
189         num_handles);
190     return GATT_INTERNAL_ERROR;
191   }
192 
193   tGATT_HDL_LIST_ELEM& list = gatt_add_an_item_to_list(s_hdl);
194   list.asgn_range.app_uuid128 = p_reg->app_uuid128;
195   list.asgn_range.svc_uuid = svc_uuid;
196   list.asgn_range.s_handle = s_hdl;
197   list.asgn_range.e_handle = s_hdl + num_handles - 1;
198   list.asgn_range.is_primary = is_pri;
199 
200   if (save_hdl) {
201     if (gatt_cb.cb_info.p_nv_save_callback)
202       (*gatt_cb.cb_info.p_nv_save_callback)(true, &list.asgn_range);
203   }
204 
205   gatts_init_service_db(list.svc_db, svc_uuid, is_pri, s_hdl, num_handles);
206 
207   VLOG(1) << StringPrintf(
208       "%s: handles needed:%u s_hdl=%u e_hdl=%u %s is_primary=%d", __func__,
209       num_handles, list.asgn_range.s_handle, list.asgn_range.e_handle,
210       list.asgn_range.svc_uuid.ToString().c_str(), 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) << StringPrintf(
225             "Invalid configuration property=0x%02x perm=0x%04x ",
226             el->properties, el->permissions);
227         return GATT_INTERNAL_ERROR;
228       }
229 
230       if (is_gatt_attr_type(uuid)) {
231         LOG(ERROR) << StringPrintf(
232             "%s: attept to add characteristic with UUID equal to GATT "
233             "Attribute Type %s ",
234             __func__, uuid.ToString().c_str());
235         return GATT_INTERNAL_ERROR;
236       }
237 
238       el->attribute_handle = gatts_add_characteristic(
239           list.svc_db, el->permissions, el->properties, uuid);
240     } else if (el->type == BTGATT_DB_DESCRIPTOR) {
241       if (is_gatt_attr_type(uuid)) {
242         LOG(ERROR) << StringPrintf(
243             "%s: attept to add descriptor with UUID equal to GATT "
244             "Attribute Type %s",
245             __func__, uuid.ToString().c_str());
246         return GATT_INTERNAL_ERROR;
247       }
248 
249       el->attribute_handle =
250           gatts_add_char_descr(list.svc_db, el->permissions, uuid);
251     } else if (el->type == BTGATT_DB_INCLUDED_SERVICE) {
252       tGATT_HDL_LIST_ELEM* p_incl_decl;
253       p_incl_decl = gatt_find_hdl_buffer_by_handle(el->attribute_handle);
254       if (p_incl_decl == nullptr) {
255         VLOG(1) << "Included Service not created";
256         return GATT_INTERNAL_ERROR;
257       }
258 
259       el->attribute_handle = gatts_add_included_service(
260           list.svc_db, p_incl_decl->asgn_range.s_handle,
261           p_incl_decl->asgn_range.e_handle, p_incl_decl->asgn_range.svc_uuid);
262     }
263   }
264 
265   LOG(INFO) << __func__ << ": service parsed correctly, now starting";
266 
267   /*this is a new application service start */
268 
269   // find a place for this service in the list
270   auto lst_ptr = gatt_cb.srv_list_info;
271   auto it = lst_ptr->begin();
272   for (; it != lst_ptr->end(); it++) {
273     if (list.asgn_range.s_handle < it->s_hdl) break;
274   }
275   auto rit = lst_ptr->emplace(it);
276 
277   tGATT_SRV_LIST_ELEM& elem = *rit;
278   elem.gatt_if = gatt_if;
279   elem.s_hdl = list.asgn_range.s_handle;
280   elem.e_hdl = list.asgn_range.e_handle;
281   elem.p_db = &list.svc_db;
282   elem.is_primary = list.asgn_range.is_primary;
283 
284   elem.app_uuid = list.asgn_range.app_uuid128;
285   elem.type = list.asgn_range.is_primary ? GATT_UUID_PRI_SERVICE
286                                          : GATT_UUID_SEC_SERVICE;
287 
288   if (elem.type == GATT_UUID_PRI_SERVICE) {
289     Uuid* p_uuid = gatts_get_service_uuid(elem.p_db);
290     elem.sdp_handle = gatt_add_sdp_record(*p_uuid, elem.s_hdl, elem.e_hdl);
291   } else {
292     elem.sdp_handle = 0;
293   }
294 
295   gatt_update_last_srv_info();
296 
297   VLOG(1) << StringPrintf(
298       "%s: allocated el: s_hdl=%d e_hdl=%d type=0x%x sdp_hdl=0x%x", __func__,
299       elem.s_hdl, elem.e_hdl, elem.type, elem.sdp_handle);
300 
301   gatt_proc_srv_chg();
302 
303   return GATT_SERVICE_STARTED;
304 }
305 
is_active_service(const Uuid & app_uuid128,Uuid * p_svc_uuid,uint16_t start_handle)306 bool is_active_service(const Uuid& app_uuid128, Uuid* p_svc_uuid,
307                        uint16_t start_handle) {
308   for (auto& info : *gatt_cb.srv_list_info) {
309     Uuid* p_this_uuid = gatts_get_service_uuid(info.p_db);
310 
311     if (p_this_uuid && app_uuid128 == info.app_uuid &&
312         *p_svc_uuid == *p_this_uuid && (start_handle == info.s_hdl)) {
313       LOG(ERROR) << "Active Service Found: " << *p_svc_uuid;
314       return true;
315     }
316   }
317   return false;
318 }
319 
320 /*******************************************************************************
321  *
322  * Function         GATTS_DeleteService
323  *
324  * Description      This function is called to delete a service.
325  *
326  * Parameter        gatt_if       : application interface
327  *                  p_svc_uuid    : service UUID
328  *                  start_handle  : start handle of the service
329  *
330  * Returns          true if the operation succeeded, false if the handle block
331  *                  was not found.
332  *
333  ******************************************************************************/
GATTS_DeleteService(tGATT_IF gatt_if,Uuid * p_svc_uuid,uint16_t svc_inst)334 bool GATTS_DeleteService(tGATT_IF gatt_if, Uuid* p_svc_uuid,
335                          uint16_t svc_inst) {
336   VLOG(1) << __func__;
337 
338   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
339   if (p_reg == NULL) {
340     LOG(ERROR) << "Applicaiton not foud";
341     return false;
342   }
343 
344   auto it =
345       gatt_find_hdl_buffer_by_app_id(p_reg->app_uuid128, p_svc_uuid, svc_inst);
346   if (it == gatt_cb.hdl_list_info->end()) {
347     LOG(ERROR) << "No Service found";
348     return false;
349   }
350 
351   gatt_proc_srv_chg();
352 
353   if (is_active_service(p_reg->app_uuid128, p_svc_uuid, svc_inst)) {
354     GATTS_StopService(it->asgn_range.s_handle);
355   }
356 
357   VLOG(1) << StringPrintf("released handles s_hdl=%u e_hdl=%u",
358                           it->asgn_range.s_handle, it->asgn_range.e_handle);
359 
360   if ((it->asgn_range.s_handle >= gatt_cb.hdl_cfg.app_start_hdl) &&
361       gatt_cb.cb_info.p_nv_save_callback)
362     (*gatt_cb.cb_info.p_nv_save_callback)(false, &it->asgn_range);
363 
364   gatt_cb.hdl_list_info->erase(it);
365   return true;
366 }
367 
368 /*******************************************************************************
369  *
370  * Function         GATTS_StopService
371  *
372  * Description      This function is called to stop a service
373  *
374  * Parameter         service_handle : this is the start handle of a service
375  *
376  * Returns          None.
377  *
378  ******************************************************************************/
GATTS_StopService(uint16_t service_handle)379 void GATTS_StopService(uint16_t service_handle) {
380   LOG(INFO) << __func__ << ": 0x" << std::hex << +service_handle;
381 
382   auto it = gatt_sr_find_i_rcb_by_handle(service_handle);
383   if (it == gatt_cb.srv_list_info->end()) {
384     LOG(ERROR) << StringPrintf("%s: service_handle: %u is not in use", __func__,
385                                service_handle);
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_STATUS cmd_status = GATT_NO_RESOURCES;
414 
415   tGATT_VALUE indication;
416   BT_HDR* p_msg;
417   tGATT_VALUE* p_buf;
418   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
419   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
420   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
421   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
422 
423   VLOG(1) << __func__;
424   if ((p_reg == NULL) || (p_tcb == NULL)) {
425     LOG(ERROR) << __func__ << ": Unknown  conn_id: " << +conn_id;
426     return (tGATT_STATUS)GATT_INVALID_CONN_ID;
427   }
428 
429   if (!GATT_HANDLE_IS_VALID(attr_handle)) return GATT_ILLEGAL_PARAMETER;
430 
431   indication.conn_id = conn_id;
432   indication.handle = attr_handle;
433   indication.len = val_len;
434   memcpy(indication.value, p_val, val_len);
435   indication.auth_req = GATT_AUTH_REQ_NONE;
436 
437   if (GATT_HANDLE_IS_VALID(p_tcb->indicate_handle)) {
438     VLOG(1) << "Add a pending indication";
439     p_buf = gatt_add_pending_ind(p_tcb, &indication);
440     if (p_buf != NULL) {
441       cmd_status = GATT_SUCCESS;
442     } else {
443       cmd_status = GATT_NO_RESOURCES;
444     }
445   } else {
446     tGATT_SR_MSG gatt_sr_msg;
447     gatt_sr_msg.attr_value = indication;
448     p_msg = attp_build_sr_msg(*p_tcb, GATT_HANDLE_VALUE_IND, &gatt_sr_msg);
449     if (p_msg != NULL) {
450       cmd_status = attp_send_sr_msg(*p_tcb, p_msg);
451 
452       if (cmd_status == GATT_SUCCESS || cmd_status == GATT_CONGESTED) {
453         p_tcb->indicate_handle = indication.handle;
454         gatt_start_conf_timer(p_tcb);
455       }
456     }
457   }
458   return cmd_status;
459 }
460 
461 /*******************************************************************************
462  *
463  * Function         GATTS_HandleValueNotification
464  *
465  * Description      This function sends a handle value notification to a client.
466  *
467  * Parameter        conn_id: connection identifier.
468  *                  attr_handle: Attribute handle of this handle value
469  *                               indication.
470  *                  val_len: Length of the indicated attribute value.
471  *                  p_val: Pointer to the indicated attribute value data.
472  *
473  * Returns          GATT_SUCCESS if sucessfully sent; otherwise error code.
474  *
475  ******************************************************************************/
GATTS_HandleValueNotification(uint16_t conn_id,uint16_t attr_handle,uint16_t val_len,uint8_t * p_val)476 tGATT_STATUS GATTS_HandleValueNotification(uint16_t conn_id,
477                                            uint16_t attr_handle,
478                                            uint16_t val_len, uint8_t* p_val) {
479   tGATT_VALUE notif;
480   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
481   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
482   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
483   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
484 
485   VLOG(1) << __func__;
486 
487   if ((p_reg == NULL) || (p_tcb == NULL)) {
488     LOG(ERROR) << __func__ << "Unknown  conn_id: " << conn_id;
489     return (tGATT_STATUS)GATT_INVALID_CONN_ID;
490   }
491 
492   if (!GATT_HANDLE_IS_VALID(attr_handle)) {
493     return GATT_ILLEGAL_PARAMETER;
494   }
495 
496   notif.handle = attr_handle;
497   notif.len = val_len;
498   memcpy(notif.value, p_val, val_len);
499   notif.auth_req = GATT_AUTH_REQ_NONE;
500 
501   tGATT_STATUS cmd_sent;
502   tGATT_SR_MSG gatt_sr_msg;
503   gatt_sr_msg.attr_value = notif;
504   BT_HDR* p_buf =
505       attp_build_sr_msg(*p_tcb, GATT_HANDLE_VALUE_NOTIF, &gatt_sr_msg);
506   if (p_buf != NULL) {
507     cmd_sent = attp_send_sr_msg(*p_tcb, p_buf);
508   } else
509     cmd_sent = GATT_NO_RESOURCES;
510   return cmd_sent;
511 }
512 
513 /*******************************************************************************
514  *
515  * Function         GATTS_SendRsp
516  *
517  * Description      This function sends the server response to client.
518  *
519  * Parameter        conn_id: connection identifier.
520  *                  trans_id: transaction id
521  *                  status: response status
522  *                  p_msg: pointer to message parameters structure.
523  *
524  * Returns          GATT_SUCCESS if sucessfully sent; otherwise error code.
525  *
526  ******************************************************************************/
GATTS_SendRsp(uint16_t conn_id,uint32_t trans_id,tGATT_STATUS status,tGATTS_RSP * p_msg)527 tGATT_STATUS GATTS_SendRsp(uint16_t conn_id, uint32_t trans_id,
528                            tGATT_STATUS status, tGATTS_RSP* p_msg) {
529   tGATT_STATUS cmd_sent = GATT_ILLEGAL_PARAMETER;
530   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
531   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
532   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
533   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
534 
535   VLOG(1) << __func__
536           << StringPrintf(": conn_id: %u  trans_id: %u  Status: 0x%04x",
537                           conn_id, trans_id, status);
538 
539   if ((p_reg == NULL) || (p_tcb == NULL)) {
540     LOG(ERROR) << StringPrintf("Unknown  conn_id: %u ", conn_id);
541     return (tGATT_STATUS)GATT_INVALID_CONN_ID;
542   }
543 
544   if (p_tcb->sr_cmd.trans_id != trans_id) {
545     LOG(ERROR) << StringPrintf("conn_id: %u  waiting for op_code = %02x",
546                                conn_id, p_tcb->sr_cmd.op_code);
547 
548     return (GATT_WRONG_STATE);
549   }
550   /* Process App response */
551   cmd_sent = gatt_sr_process_app_rsp(*p_tcb, gatt_if, trans_id,
552                                      p_tcb->sr_cmd.op_code, status, p_msg);
553 
554   return cmd_sent;
555 }
556 
557 /******************************************************************************/
558 /* GATT Profile Srvr Functions */
559 /******************************************************************************/
560 
561 /******************************************************************************/
562 /*                                                                            */
563 /*                  GATT CLIENT APIs                                          */
564 /*                                                                            */
565 /******************************************************************************/
566 
567 /*******************************************************************************
568  *
569  * Function         GATTC_ConfigureMTU
570  *
571  * Description      This function is called to configure the ATT MTU size.
572  *
573  * Parameters       conn_id: connection identifier.
574  *                  mtu    - attribute MTU size..
575  *
576  * Returns          GATT_SUCCESS if command started successfully.
577  *
578  ******************************************************************************/
GATTC_ConfigureMTU(uint16_t conn_id,uint16_t mtu)579 tGATT_STATUS GATTC_ConfigureMTU(uint16_t conn_id, uint16_t mtu) {
580   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
581   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
582   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
583   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
584 
585   VLOG(1) << __func__ << StringPrintf("conn_id=%d mtu=%d", conn_id, mtu);
586 
587   if ((p_tcb == NULL) || (p_reg == NULL) || (mtu < GATT_DEF_BLE_MTU_SIZE) ||
588       (mtu > GATT_MAX_MTU_SIZE)) {
589     return GATT_ILLEGAL_PARAMETER;
590   }
591 
592   /* Validate that the link is BLE, not BR/EDR */
593   if (p_tcb->transport != BT_TRANSPORT_LE) {
594     return GATT_ERROR;
595   }
596 
597   if (gatt_is_clcb_allocated(conn_id)) {
598     LOG(ERROR) << "GATT_BUSY conn_id = " << +conn_id;
599     return GATT_BUSY;
600   }
601 
602   tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
603   if (!p_clcb) return GATT_NO_RESOURCES;
604 
605   p_clcb->p_tcb->payload_size = mtu;
606   p_clcb->operation = GATTC_OPTYPE_CONFIG;
607   tGATT_CL_MSG gatt_cl_msg;
608   gatt_cl_msg.mtu = mtu;
609   return attp_send_cl_msg(*p_clcb->p_tcb, p_clcb, GATT_REQ_MTU, &gatt_cl_msg);
610 }
611 
612 /*******************************************************************************
613  *
614  * Function         GATTC_Discover
615  *
616  * Description      This function is called to do a discovery procedure on ATT
617  *                  server.
618  *
619  * Parameters       conn_id: connection identifier.
620  *                  disc_type:discovery type.
621  *                  p_param: parameters of discovery requirement.
622  *
623  * Returns          GATT_SUCCESS if command received/sent successfully.
624  *
625  ******************************************************************************/
GATTC_Discover(uint16_t conn_id,tGATT_DISC_TYPE disc_type,tGATT_DISC_PARAM * p_param)626 tGATT_STATUS GATTC_Discover(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
627                             tGATT_DISC_PARAM* p_param) {
628   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
629   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
630   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
631   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
632 
633   LOG(INFO) << __func__
634             << StringPrintf(" conn_id=%d disc_type=%d", conn_id, disc_type);
635 
636   if ((p_tcb == NULL) || (p_reg == NULL) || (p_param == NULL) ||
637       (disc_type >= GATT_DISC_MAX)) {
638     LOG(ERROR) << StringPrintf("Illegal param: disc_type %d conn_id = %d",
639                                disc_type, conn_id);
640     return GATT_ILLEGAL_PARAMETER;
641   }
642 
643   if (!GATT_HANDLE_IS_VALID(p_param->s_handle) ||
644       !GATT_HANDLE_IS_VALID(p_param->e_handle) ||
645       /* search by type does not have a valid UUID param */
646       (disc_type == GATT_DISC_SRVC_BY_UUID && p_param->service.IsEmpty())) {
647     return GATT_ILLEGAL_PARAMETER;
648   }
649 
650   if (gatt_is_clcb_allocated(conn_id)) {
651     LOG(ERROR) << __func__ << "GATT_BUSY conn_id = " << +conn_id;
652     return GATT_BUSY;
653   }
654 
655   tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
656   if (!p_clcb) return GATT_NO_RESOURCES;
657 
658   p_clcb->operation = GATTC_OPTYPE_DISCOVERY;
659   p_clcb->op_subtype = disc_type;
660   p_clcb->s_handle = p_param->s_handle;
661   p_clcb->e_handle = p_param->e_handle;
662   p_clcb->uuid = p_param->service;
663 
664   gatt_act_discovery(p_clcb);
665   return GATT_SUCCESS;
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__ << StringPrintf(" conn_id=%d type=%d", conn_id, type);
690 
691   if ((p_tcb == NULL) || (p_reg == NULL) || (p_read == NULL) ||
692       ((type >= GATT_READ_MAX) || (type == 0))) {
693     LOG(ERROR) << StringPrintf(" Illegal param: conn_id %d, type 0%d,", conn_id,
694                                type);
695     return GATT_ILLEGAL_PARAMETER;
696   }
697 
698   if (gatt_is_clcb_allocated(conn_id)) {
699     LOG(ERROR) << StringPrintf(" GATT_BUSY conn_id = %d", conn_id);
700     return GATT_BUSY;
701   }
702 
703   tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
704   if (!p_clcb) return GATT_NO_RESOURCES;
705 
706   p_clcb->operation = GATTC_OPTYPE_READ;
707   p_clcb->op_subtype = type;
708   p_clcb->auth_req = p_read->by_handle.auth_req;
709   p_clcb->counter = 0;
710 
711   switch (type) {
712     case GATT_READ_BY_TYPE:
713     case GATT_READ_CHAR_VALUE:
714       p_clcb->s_handle = p_read->service.s_handle;
715       p_clcb->e_handle = p_read->service.e_handle;
716       p_clcb->uuid = p_read->service.uuid;
717       break;
718     case GATT_READ_MULTIPLE: {
719       p_clcb->s_handle = 0;
720       /* copy multiple handles in CB */
721       tGATT_READ_MULTI* p_read_multi =
722           (tGATT_READ_MULTI*)osi_malloc(sizeof(tGATT_READ_MULTI));
723       p_clcb->p_attr_buf = (uint8_t*)p_read_multi;
724       memcpy(p_read_multi, &p_read->read_multiple, sizeof(tGATT_READ_MULTI));
725       break;
726     }
727     case GATT_READ_BY_HANDLE:
728     case GATT_READ_PARTIAL:
729       p_clcb->uuid = Uuid::kEmpty;
730       p_clcb->s_handle = p_read->by_handle.handle;
731 
732       if (type == GATT_READ_PARTIAL) {
733         p_clcb->counter = p_read->partial.offset;
734       }
735 
736       break;
737     default:
738       break;
739   }
740 
741   /* start security check */
742   gatt_security_check_start(p_clcb);
743   return GATT_SUCCESS;
744 }
745 
746 /*******************************************************************************
747  *
748  * Function         GATTC_Write
749  *
750  * Description      This function is called to write the value of an attribute
751  *                  to the server.
752  *
753  * Parameters       conn_id: connection identifier.
754  *                  type    - attribute write type.
755  *                  p_write  - write operation parameters.
756  *
757  * Returns          GATT_SUCCESS if command started successfully.
758  *
759  ******************************************************************************/
GATTC_Write(uint16_t conn_id,tGATT_WRITE_TYPE type,tGATT_VALUE * p_write)760 tGATT_STATUS GATTC_Write(uint16_t conn_id, tGATT_WRITE_TYPE type,
761                          tGATT_VALUE* p_write) {
762   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
763   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
764   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
765   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
766 
767   if ((p_tcb == NULL) || (p_reg == NULL) || (p_write == NULL) ||
768       ((type != GATT_WRITE) && (type != GATT_WRITE_PREPARE) &&
769        (type != GATT_WRITE_NO_RSP))) {
770     LOG(ERROR) << __func__
771                << StringPrintf(" Illegal param: conn_id %d, type 0%d,", conn_id,
772                                type);
773     return GATT_ILLEGAL_PARAMETER;
774   }
775 
776   if (gatt_is_clcb_allocated(conn_id)) {
777     LOG(ERROR) << StringPrintf("GATT_BUSY conn_id = %d", 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   gatt_security_check_start(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__
822           << StringPrintf(": conn_id=%d is_execute=%d", conn_id, is_execute);
823 
824   if ((p_tcb == NULL) || (p_reg == NULL)) {
825     LOG(ERROR) << StringPrintf(" Illegal param: conn_id %d", conn_id);
826     return GATT_ILLEGAL_PARAMETER;
827   }
828 
829   if (gatt_is_clcb_allocated(conn_id)) {
830     LOG(ERROR) << StringPrintf(" GATT_BUSY conn_id = %d", 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__
859           << StringPrintf(" conn_id=%d handle=0x%x", conn_id, 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) << StringPrintf(" Unknown conn_id: %u", conn_id);
864     return GATT_ILLEGAL_PARAMETER;
865   }
866 
867   if (p_tcb->ind_count == 0) {
868     VLOG(1) << " conn_id: " << +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   tGATT_TCB* p_tcb;
908   bool status = false;
909 
910   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__
925           << StringPrintf(" idle_tout=%d status=%d(1-OK 0-not performed)",
926                           idle_tout, status);
927 }
928 
929 /*******************************************************************************
930  *
931  * Function         GATT_Register
932  *
933  * Description      This function is called to register an  application
934  *                  with GATT
935  *
936  * Parameter        p_app_uuid128: Application UUID
937  *                  p_cb_info: callback functions.
938  *
939  * Returns          0 for error, otherwise the index of the client registered
940  *                  with GATT
941  *
942  ******************************************************************************/
GATT_Register(const Uuid & app_uuid128,tGATT_CBACK * p_cb_info)943 tGATT_IF GATT_Register(const Uuid& app_uuid128, tGATT_CBACK* p_cb_info) {
944   tGATT_REG* p_reg;
945   uint8_t i_gatt_if = 0;
946   tGATT_IF gatt_if = 0;
947 
948   LOG(INFO) << __func__ << " " << app_uuid128;
949 
950   for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS;
951        i_gatt_if++, p_reg++) {
952     if (p_reg->in_use && p_reg->app_uuid128 == app_uuid128) {
953       LOG(ERROR) << "application already registered.";
954       return 0;
955     }
956   }
957 
958   for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS;
959        i_gatt_if++, p_reg++) {
960     if (!p_reg->in_use) {
961       memset(p_reg, 0, sizeof(tGATT_REG));
962       i_gatt_if++; /* one based number */
963       p_reg->app_uuid128 = app_uuid128;
964       gatt_if = p_reg->gatt_if = (tGATT_IF)i_gatt_if;
965       p_reg->app_cb = *p_cb_info;
966       p_reg->in_use = true;
967 
968       LOG(INFO) << "allocated gatt_if=" << +gatt_if;
969       return gatt_if;
970     }
971   }
972 
973   LOG(ERROR) << "can't Register GATT client, MAX client reached: "
974              << GATT_MAX_APPS;
975   return 0;
976 }
977 
978 /*******************************************************************************
979  *
980  * Function         GATT_Deregister
981  *
982  * Description      This function deregistered the application from GATT.
983  *
984  * Parameters       gatt_if: applicaiton interface.
985  *
986  * Returns          None.
987  *
988  ******************************************************************************/
GATT_Deregister(tGATT_IF gatt_if)989 void GATT_Deregister(tGATT_IF gatt_if) {
990   VLOG(1) << __func__ << " gatt_if=" << +gatt_if;
991 
992   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
993   /* Index 0 is GAP and is never deregistered */
994   if ((gatt_if == 0) || (p_reg == NULL)) {
995     LOG(ERROR) << "invalid gatt_if: " << +gatt_if;
996     return;
997   }
998 
999   /* stop all services  */
1000   /* todo an applcaiton can not be deregistered if its services is also used by
1001     other application
1002     deregisteration need to bed performed in an orderly fashion
1003     no check for now */
1004   for (auto it = gatt_cb.srv_list_info->begin(); 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) {
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;
1027            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 
1038   gatt_deregister_bgdev_list(gatt_if);
1039 
1040   memset(p_reg, 0, sizeof(tGATT_REG));
1041 }
1042 
1043 /*******************************************************************************
1044  *
1045  * Function         GATT_StartIf
1046  *
1047  * Description      This function is called after registration to start
1048  *                  receiving callbacks for registered interface.  Function may
1049  *                  call back with connection status and queued notifications
1050  *
1051  * Parameter        gatt_if: applicaiton interface.
1052  *
1053  * Returns          None.
1054  *
1055  ******************************************************************************/
GATT_StartIf(tGATT_IF gatt_if)1056 void GATT_StartIf(tGATT_IF gatt_if) {
1057   tGATT_REG* p_reg;
1058   tGATT_TCB* p_tcb;
1059   RawAddress bda;
1060   uint8_t start_idx, found_idx;
1061   uint16_t conn_id;
1062   tGATT_TRANSPORT transport;
1063 
1064   VLOG(1) << __func__ << " gatt_if=" << gatt_if;
1065   p_reg = gatt_get_regcb(gatt_if);
1066   if (p_reg != NULL) {
1067     start_idx = 0;
1068     while (
1069         gatt_find_the_connected_bda(start_idx, bda, &found_idx, &transport)) {
1070       p_tcb = gatt_find_tcb_by_addr(bda, transport);
1071       if (p_reg->app_cb.p_conn_cb && p_tcb) {
1072         conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
1073         (*p_reg->app_cb.p_conn_cb)(gatt_if, bda, conn_id, true, 0, transport);
1074       }
1075       start_idx = ++found_idx;
1076     }
1077   }
1078 }
1079 
1080 /*******************************************************************************
1081  *
1082  * Function         GATT_Connect
1083  *
1084  * Description      This function initiate a connecttion to a remote device on
1085  *                  GATT channel.
1086  *
1087  * Parameters       gatt_if: applicaiton interface
1088  *                  bd_addr: peer device address.
1089  *                  is_direct: is a direct conenection or a background auto
1090  *                             connection
1091  *
1092  * Returns          true if connection started; false if connection start
1093  *                  failure.
1094  *
1095  ******************************************************************************/
GATT_Connect(tGATT_IF gatt_if,const RawAddress & bd_addr,bool is_direct,tBT_TRANSPORT transport,bool opportunistic)1096 bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, bool is_direct,
1097                   tBT_TRANSPORT transport, bool opportunistic) {
1098   uint8_t phy = controller_get_interface()->get_le_all_initiating_phys();
1099   return GATT_Connect(gatt_if, bd_addr, is_direct, transport, opportunistic,
1100                       phy);
1101 }
1102 
GATT_Connect(tGATT_IF gatt_if,const RawAddress & bd_addr,bool is_direct,tBT_TRANSPORT transport,bool opportunistic,uint8_t initiating_phys)1103 bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, bool is_direct,
1104                   tBT_TRANSPORT transport, bool opportunistic,
1105                   uint8_t initiating_phys) {
1106   tGATT_REG* p_reg;
1107   bool status = false;
1108 
1109   LOG(INFO) << __func__ << "gatt_if=" << +gatt_if << " " << bd_addr;
1110 
1111   /* Make sure app is registered */
1112   p_reg = gatt_get_regcb(gatt_if);
1113   if (p_reg == NULL) {
1114     LOG(ERROR) << "gatt_if = " << gatt_if << " is not registered";
1115     return (false);
1116   }
1117 
1118   if (is_direct)
1119     status = gatt_act_connect(p_reg, bd_addr, transport, opportunistic,
1120                               initiating_phys);
1121   else {
1122     if (transport == BT_TRANSPORT_LE)
1123       status = gatt_update_auto_connect_dev(gatt_if, true, bd_addr);
1124     else {
1125       LOG(ERROR) << "Unsupported transport for background connection";
1126     }
1127   }
1128 
1129   return status;
1130 }
1131 
1132 /*******************************************************************************
1133  *
1134  * Function         GATT_CancelConnect
1135  *
1136  * Description      This function terminate the connection initaition to a
1137  *                  remote device on GATT channel.
1138  *
1139  * Parameters       gatt_if: client interface. If 0 used as unconditionally
1140  *                           disconnect, typically used for direct connection
1141  *                           cancellation.
1142  *                  bd_addr: peer device address.
1143  *
1144  * Returns          true if the connection started; false otherwise.
1145  *
1146  ******************************************************************************/
GATT_CancelConnect(tGATT_IF gatt_if,const RawAddress & bd_addr,bool is_direct)1147 bool GATT_CancelConnect(tGATT_IF gatt_if, const RawAddress& bd_addr,
1148                         bool is_direct) {
1149   LOG(INFO) << __func__ << ": gatt_if=" << +gatt_if;
1150 
1151   if (gatt_if && !gatt_get_regcb(gatt_if)) {
1152     LOG(ERROR) << "gatt_if =" << +gatt_if << " is not registered";
1153     return false;
1154   }
1155 
1156   if (is_direct) {
1157     if (gatt_if) {
1158       return gatt_cancel_open(gatt_if, bd_addr);
1159     }
1160 
1161     VLOG(1) << " unconditional";
1162     /* only LE connection can be cancelled */
1163     tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
1164     if (!p_tcb || p_tcb->app_hold_link.empty()) {
1165       LOG(ERROR) << __func__ << " no app found";
1166       return false;
1167     }
1168 
1169     for (auto it = p_tcb->app_hold_link.begin();
1170          it != p_tcb->app_hold_link.end();) {
1171       auto next = std::next(it);
1172       // gatt_cancel_open modifies the app_hold_link.
1173       if (!gatt_cancel_open(*it, bd_addr)) return false;
1174 
1175       it = next;
1176     }
1177 
1178     return true;
1179   }
1180   // is not direct
1181 
1182   if (gatt_if) return gatt_remove_bg_dev_for_app(gatt_if, bd_addr);
1183 
1184   if (!gatt_clear_bg_dev_for_addr(bd_addr)) {
1185     LOG(ERROR)
1186         << __func__
1187         << ": no app associated with the bg device for unconditional removal";
1188     return false;
1189   }
1190 
1191   return true;
1192 }
1193 
1194 /*******************************************************************************
1195  *
1196  * Function         GATT_Disconnect
1197  *
1198  * Description      This function disconnects the GATT channel for this
1199  *                  registered application.
1200  *
1201  * Parameters       conn_id: connection identifier.
1202  *
1203  * Returns          GATT_SUCCESS if disconnected.
1204  *
1205  ******************************************************************************/
GATT_Disconnect(uint16_t conn_id)1206 tGATT_STATUS GATT_Disconnect(uint16_t conn_id) {
1207   tGATT_STATUS ret = GATT_ILLEGAL_PARAMETER;
1208   tGATT_TCB* p_tcb = NULL;
1209   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
1210   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
1211 
1212   LOG(INFO) << __func__ << " conn_id=" << +conn_id;
1213 
1214   p_tcb = gatt_get_tcb_by_idx(tcb_idx);
1215 
1216   if (p_tcb) {
1217     gatt_update_app_use_link_flag(gatt_if, p_tcb, false, true);
1218     ret = GATT_SUCCESS;
1219   }
1220   return ret;
1221 }
1222 
1223 /*******************************************************************************
1224  *
1225  * Function         GATT_GetConnectionInfor
1226  *
1227  * Description      This function uses conn_id to find its associated BD address
1228  *                  and application interface
1229  *
1230  * Parameters        conn_id: connection id  (input)
1231  *                   p_gatt_if: applicaiton interface (output)
1232  *                   bd_addr: peer device address. (output)
1233  *
1234  * Returns          true the ligical link information is found for conn_id
1235  *
1236  ******************************************************************************/
GATT_GetConnectionInfor(uint16_t conn_id,tGATT_IF * p_gatt_if,RawAddress & bd_addr,tBT_TRANSPORT * p_transport)1237 bool GATT_GetConnectionInfor(uint16_t conn_id, tGATT_IF* p_gatt_if,
1238                              RawAddress& bd_addr, tBT_TRANSPORT* p_transport) {
1239   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
1240   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
1241   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
1242   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
1243   bool status = false;
1244 
1245   VLOG(1) << __func__ << " conn_id=" << +conn_id;
1246 
1247   if (p_tcb && p_reg) {
1248     bd_addr = p_tcb->peer_bda;
1249     *p_gatt_if = gatt_if;
1250     *p_transport = p_tcb->transport;
1251     status = true;
1252   }
1253   return status;
1254 }
1255 
1256 /*******************************************************************************
1257  *
1258  * Function         GATT_GetConnIdIfConnected
1259  *
1260  * Description      This function find the conn_id if the logical link for BD
1261  *                  address and applciation interface is connected
1262  *
1263  * Parameters        gatt_if: applicaiton interface (input)
1264  *                   bd_addr: peer device address. (input)
1265  *                   p_conn_id: connection id  (output)
1266  *                   transport: transport option
1267  *
1268  * Returns          true the logical link is connected
1269  *
1270  ******************************************************************************/
GATT_GetConnIdIfConnected(tGATT_IF gatt_if,const RawAddress & bd_addr,uint16_t * p_conn_id,tBT_TRANSPORT transport)1271 bool GATT_GetConnIdIfConnected(tGATT_IF gatt_if, const RawAddress& bd_addr,
1272                                uint16_t* p_conn_id, tBT_TRANSPORT transport) {
1273   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
1274   tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
1275   bool status = false;
1276 
1277   if (p_reg && p_tcb && (gatt_get_ch_state(p_tcb) == GATT_CH_OPEN)) {
1278     *p_conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
1279     status = true;
1280   }
1281 
1282   VLOG(1) << __func__ << " status= " << +status;
1283   return status;
1284 }
1285