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