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(¬if, 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