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