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