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