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 p_clcb->read_req_current_mtu = p_tcb->payload_size;
712
713 switch (type) {
714 case GATT_READ_BY_TYPE:
715 case GATT_READ_CHAR_VALUE:
716 p_clcb->s_handle = p_read->service.s_handle;
717 p_clcb->e_handle = p_read->service.e_handle;
718 p_clcb->uuid = p_read->service.uuid;
719 break;
720 case GATT_READ_MULTIPLE: {
721 p_clcb->s_handle = 0;
722 /* copy multiple handles in CB */
723 tGATT_READ_MULTI* p_read_multi =
724 (tGATT_READ_MULTI*)osi_malloc(sizeof(tGATT_READ_MULTI));
725 p_clcb->p_attr_buf = (uint8_t*)p_read_multi;
726 memcpy(p_read_multi, &p_read->read_multiple, sizeof(tGATT_READ_MULTI));
727 break;
728 }
729 case GATT_READ_BY_HANDLE:
730 case GATT_READ_PARTIAL:
731 p_clcb->uuid = Uuid::kEmpty;
732 p_clcb->s_handle = p_read->by_handle.handle;
733
734 if (type == GATT_READ_PARTIAL) {
735 p_clcb->counter = p_read->partial.offset;
736 }
737
738 break;
739 default:
740 break;
741 }
742
743 /* start security check */
744 if (gatt_security_check_start(p_clcb)) p_tcb->pending_enc_clcb.push(p_clcb);
745 return GATT_SUCCESS;
746 }
747
748 /*******************************************************************************
749 *
750 * Function GATTC_Write
751 *
752 * Description This function is called to write the value of an attribute
753 * to the server.
754 *
755 * Parameters conn_id: connection identifier.
756 * type - attribute write type.
757 * p_write - write operation parameters.
758 *
759 * Returns GATT_SUCCESS if command started successfully.
760 *
761 ******************************************************************************/
GATTC_Write(uint16_t conn_id,tGATT_WRITE_TYPE type,tGATT_VALUE * p_write)762 tGATT_STATUS GATTC_Write(uint16_t conn_id, tGATT_WRITE_TYPE type,
763 tGATT_VALUE* p_write) {
764 tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
765 uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
766 tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
767 tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
768
769 if ((p_tcb == NULL) || (p_reg == NULL) || (p_write == NULL) ||
770 ((type != GATT_WRITE) && (type != GATT_WRITE_PREPARE) &&
771 (type != GATT_WRITE_NO_RSP))) {
772 LOG(ERROR) << __func__ << " Illegal param: conn_id=" << loghex(conn_id)
773 << ", type=" << loghex(type);
774 return GATT_ILLEGAL_PARAMETER;
775 }
776
777 if (gatt_is_clcb_allocated(conn_id)) {
778 LOG(ERROR) << "GATT_BUSY conn_id=" << loghex(conn_id);
779 return GATT_BUSY;
780 }
781
782 tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
783 if (!p_clcb) return GATT_NO_RESOURCES;
784
785 p_clcb->operation = GATTC_OPTYPE_WRITE;
786 p_clcb->op_subtype = type;
787 p_clcb->auth_req = p_write->auth_req;
788
789 p_clcb->p_attr_buf = (uint8_t*)osi_malloc(sizeof(tGATT_VALUE));
790 memcpy(p_clcb->p_attr_buf, (void*)p_write, sizeof(tGATT_VALUE));
791
792 tGATT_VALUE* p = (tGATT_VALUE*)p_clcb->p_attr_buf;
793 if (type == GATT_WRITE_PREPARE) {
794 p_clcb->start_offset = p_write->offset;
795 p->offset = 0;
796 }
797
798 if (gatt_security_check_start(p_clcb)) p_tcb->pending_enc_clcb.push(p_clcb);
799 return GATT_SUCCESS;
800 }
801
802 /*******************************************************************************
803 *
804 * Function GATTC_ExecuteWrite
805 *
806 * Description This function is called to send an Execute write request to
807 * the server.
808 *
809 * Parameters conn_id: connection identifier.
810 * is_execute - to execute or cancel the prepared write
811 * request(s)
812 *
813 * Returns GATT_SUCCESS if command started successfully.
814 *
815 ******************************************************************************/
GATTC_ExecuteWrite(uint16_t conn_id,bool is_execute)816 tGATT_STATUS GATTC_ExecuteWrite(uint16_t conn_id, bool is_execute) {
817 tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
818 uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
819 tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
820 tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
821
822 VLOG(1) << __func__ << ": conn_id=" << loghex(conn_id)
823 << ", is_execute=" << +is_execute;
824
825 if ((p_tcb == NULL) || (p_reg == NULL)) {
826 LOG(ERROR) << " Illegal param: conn_id=" << loghex(conn_id);
827 return GATT_ILLEGAL_PARAMETER;
828 }
829
830 if (gatt_is_clcb_allocated(conn_id)) {
831 LOG(ERROR) << " GATT_BUSY conn_id=" << loghex(conn_id);
832 return GATT_BUSY;
833 }
834
835 tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
836 if (!p_clcb) return GATT_NO_RESOURCES;
837
838 p_clcb->operation = GATTC_OPTYPE_EXE_WRITE;
839 tGATT_EXEC_FLAG flag =
840 is_execute ? GATT_PREP_WRITE_EXEC : GATT_PREP_WRITE_CANCEL;
841 gatt_send_queue_write_cancel(*p_clcb->p_tcb, p_clcb, flag);
842 return GATT_SUCCESS;
843 }
844
845 /*******************************************************************************
846 *
847 * Function GATTC_SendHandleValueConfirm
848 *
849 * Description This function is called to send a handle value confirmation
850 * as response to a handle value notification from server.
851 *
852 * Parameters conn_id: connection identifier.
853 * handle: the handle of the attribute confirmation.
854 *
855 * Returns GATT_SUCCESS if command started successfully.
856 *
857 ******************************************************************************/
GATTC_SendHandleValueConfirm(uint16_t conn_id,uint16_t handle)858 tGATT_STATUS GATTC_SendHandleValueConfirm(uint16_t conn_id, uint16_t handle) {
859 VLOG(1) << __func__ << " conn_id=" << loghex(conn_id)
860 << ", handle=" << loghex(handle);
861
862 tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(GATT_GET_TCB_IDX(conn_id));
863 if (!p_tcb) {
864 LOG(ERROR) << "Unknown conn_id=" << loghex(conn_id);
865 return GATT_ILLEGAL_PARAMETER;
866 }
867
868 if (p_tcb->ind_count == 0) {
869 VLOG(1) << " conn_id: " << loghex(conn_id)
870 << " ignored not waiting for indicaiton ack";
871 return GATT_SUCCESS;
872 }
873
874 alarm_cancel(p_tcb->ind_ack_timer);
875
876 VLOG(1) << "notif_count= " << p_tcb->ind_count;
877 /* send confirmation now */
878 tGATT_CL_MSG gatt_cl_msg;
879 gatt_cl_msg.handle = handle;
880 tGATT_STATUS ret =
881 attp_send_cl_msg(*p_tcb, nullptr, GATT_HANDLE_VALUE_CONF, &gatt_cl_msg);
882
883 p_tcb->ind_count = 0;
884
885 return ret;
886 }
887
888 /******************************************************************************/
889 /* */
890 /* GATT APIs */
891 /* */
892 /******************************************************************************/
893 /*******************************************************************************
894 *
895 * Function GATT_SetIdleTimeout
896 *
897 * Description This function (common to both client and server) sets the
898 * idle timeout for a tansport connection
899 *
900 * Parameter bd_addr: target device bd address.
901 * idle_tout: timeout value in seconds.
902 *
903 * Returns void
904 *
905 ******************************************************************************/
GATT_SetIdleTimeout(const RawAddress & bd_addr,uint16_t idle_tout,tBT_TRANSPORT transport)906 void GATT_SetIdleTimeout(const RawAddress& bd_addr, uint16_t idle_tout,
907 tBT_TRANSPORT transport) {
908 bool status = false;
909
910 tGATT_TCB* 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__ << " idle_tout=" << idle_tout << ", status=" << +status
925 << " (1-OK 0-not performed)";
926 }
927
928 /*******************************************************************************
929 *
930 * Function GATT_Register
931 *
932 * Description This function is called to register an application
933 * with GATT
934 *
935 * Parameter p_app_uuid128: Application UUID
936 * p_cb_info: callback functions.
937 *
938 * Returns 0 for error, otherwise the index of the client registered
939 * with GATT
940 *
941 ******************************************************************************/
GATT_Register(const Uuid & app_uuid128,tGATT_CBACK * p_cb_info)942 tGATT_IF GATT_Register(const Uuid& app_uuid128, tGATT_CBACK* p_cb_info) {
943 tGATT_REG* p_reg;
944 uint8_t i_gatt_if = 0;
945 tGATT_IF gatt_if = 0;
946
947 LOG(INFO) << __func__ << " " << app_uuid128;
948
949 for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS;
950 i_gatt_if++, p_reg++) {
951 if (p_reg->in_use && p_reg->app_uuid128 == app_uuid128) {
952 LOG(ERROR) << "application already registered.";
953 return 0;
954 }
955 }
956
957 for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS;
958 i_gatt_if++, p_reg++) {
959 if (!p_reg->in_use) {
960 memset(p_reg, 0, sizeof(tGATT_REG));
961 i_gatt_if++; /* one based number */
962 p_reg->app_uuid128 = app_uuid128;
963 gatt_if = p_reg->gatt_if = (tGATT_IF)i_gatt_if;
964 p_reg->app_cb = *p_cb_info;
965 p_reg->in_use = true;
966
967 LOG(INFO) << "allocated gatt_if=" << +gatt_if;
968 return gatt_if;
969 }
970 }
971
972 LOG(ERROR) << "can't Register GATT client, MAX client reached: "
973 << GATT_MAX_APPS;
974 return 0;
975 }
976
977 /*******************************************************************************
978 *
979 * Function GATT_Deregister
980 *
981 * Description This function deregistered the application from GATT.
982 *
983 * Parameters gatt_if: applicaiton interface.
984 *
985 * Returns None.
986 *
987 ******************************************************************************/
GATT_Deregister(tGATT_IF gatt_if)988 void GATT_Deregister(tGATT_IF gatt_if) {
989 VLOG(1) << __func__ << " gatt_if=" << +gatt_if;
990
991 tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
992 /* Index 0 is GAP and is never deregistered */
993 if ((gatt_if == 0) || (p_reg == NULL)) {
994 LOG(ERROR) << "invalid gatt_if=" << +gatt_if;
995 return;
996 }
997
998 /* stop all services */
999 /* todo an applcaiton can not be deregistered if its services is also used by
1000 other application
1001 deregisteration need to bed performed in an orderly fashion
1002 no check for now */
1003 for (auto it = gatt_cb.srv_list_info->begin();
1004 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) continue;
1021
1022 if (gatt_get_ch_state(p_tcb) != GATT_CH_CLOSE) {
1023 gatt_update_app_use_link_flag(gatt_if, p_tcb, false, true);
1024 }
1025
1026 tGATT_CLCB* p_clcb;
1027 for (j = 0, p_clcb = &gatt_cb.clcb[j]; j < GATT_CL_MAX_LCB; 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 connection_manager::on_app_deregistered(gatt_if);
1038
1039 memset(p_reg, 0, sizeof(tGATT_REG));
1040 }
1041
1042 /*******************************************************************************
1043 *
1044 * Function GATT_StartIf
1045 *
1046 * Description This function is called after registration to start
1047 * receiving callbacks for registered interface. Function may
1048 * call back with connection status and queued notifications
1049 *
1050 * Parameter gatt_if: applicaiton interface.
1051 *
1052 * Returns None.
1053 *
1054 ******************************************************************************/
GATT_StartIf(tGATT_IF gatt_if)1055 void GATT_StartIf(tGATT_IF gatt_if) {
1056 tGATT_REG* p_reg;
1057 tGATT_TCB* p_tcb;
1058 RawAddress bda;
1059 uint8_t start_idx, found_idx;
1060 uint16_t conn_id;
1061 tGATT_TRANSPORT transport;
1062
1063 VLOG(1) << __func__ << " gatt_if=" << +gatt_if;
1064 p_reg = gatt_get_regcb(gatt_if);
1065 if (p_reg != NULL) {
1066 start_idx = 0;
1067 while (
1068 gatt_find_the_connected_bda(start_idx, bda, &found_idx, &transport)) {
1069 p_tcb = gatt_find_tcb_by_addr(bda, transport);
1070 if (p_reg->app_cb.p_conn_cb && p_tcb) {
1071 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
1072 (*p_reg->app_cb.p_conn_cb)(gatt_if, bda, conn_id, true, 0, transport);
1073 }
1074 start_idx = ++found_idx;
1075 }
1076 }
1077 }
1078
1079 /*******************************************************************************
1080 *
1081 * Function GATT_Connect
1082 *
1083 * Description This function initiate a connecttion to a remote device on
1084 * GATT channel.
1085 *
1086 * Parameters gatt_if: applicaiton interface
1087 * bd_addr: peer device address.
1088 * is_direct: is a direct conenection or a background auto
1089 * connection
1090 *
1091 * Returns true if connection started; false if connection start
1092 * failure.
1093 *
1094 ******************************************************************************/
GATT_Connect(tGATT_IF gatt_if,const RawAddress & bd_addr,bool is_direct,tBT_TRANSPORT transport,bool opportunistic)1095 bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, bool is_direct,
1096 tBT_TRANSPORT transport, bool opportunistic) {
1097 uint8_t phy = controller_get_interface()->get_le_all_initiating_phys();
1098 return GATT_Connect(gatt_if, bd_addr, is_direct, transport, opportunistic,
1099 phy);
1100 }
1101
GATT_Connect(tGATT_IF gatt_if,const RawAddress & bd_addr,bool is_direct,tBT_TRANSPORT transport,bool opportunistic,uint8_t initiating_phys)1102 bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, bool is_direct,
1103 tBT_TRANSPORT transport, bool opportunistic,
1104 uint8_t initiating_phys) {
1105 LOG(INFO) << __func__ << "gatt_if=" << +gatt_if << ", address=" << bd_addr;
1106
1107 /* Make sure app is registered */
1108 tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
1109 if (!p_reg) {
1110 LOG(ERROR) << "gatt_if = " << +gatt_if << " is not registered";
1111 return false;
1112 }
1113
1114 if (!is_direct && transport != BT_TRANSPORT_LE) {
1115 LOG(ERROR) << "Unsupported transport for background connection";
1116 return false;
1117 }
1118
1119 if (opportunistic) {
1120 LOG(INFO) << __func__ << " opportunistic connection";
1121 return true;
1122 }
1123
1124 bool ret;
1125 if (is_direct) {
1126 ret = gatt_act_connect(p_reg, bd_addr, transport, initiating_phys);
1127 } else {
1128 if (!BTM_BackgroundConnectAddressKnown(bd_addr)) {
1129 // RPA can rotate, causing address to "expire" in the background
1130 // connection list. RPA is allowed for direct connect, as such request
1131 // times out after 30 seconds
1132 LOG(INFO) << "Can't add RPA to background connection.";
1133 ret = true;
1134 } else {
1135 ret = connection_manager::background_connect_add(gatt_if, bd_addr);
1136 }
1137 }
1138
1139 tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
1140 // background connections don't necessarily create tcb
1141 if (p_tcb && ret)
1142 gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, true, !is_direct);
1143
1144 return ret;
1145 }
1146
1147 /*******************************************************************************
1148 *
1149 * Function GATT_CancelConnect
1150 *
1151 * Description This function terminate the connection initaition to a
1152 * remote device on GATT channel.
1153 *
1154 * Parameters gatt_if: client interface. If 0 used as unconditionally
1155 * disconnect, typically used for direct connection
1156 * cancellation.
1157 * bd_addr: peer device address.
1158 *
1159 * Returns true if the connection started; false otherwise.
1160 *
1161 ******************************************************************************/
GATT_CancelConnect(tGATT_IF gatt_if,const RawAddress & bd_addr,bool is_direct)1162 bool GATT_CancelConnect(tGATT_IF gatt_if, const RawAddress& bd_addr,
1163 bool is_direct) {
1164 LOG(INFO) << __func__ << ": gatt_if:" << +gatt_if << ", address: " << bd_addr
1165 << ", direct:" << is_direct;
1166
1167 tGATT_REG* p_reg;
1168 if (gatt_if) {
1169 p_reg = gatt_get_regcb(gatt_if);
1170 if (!p_reg) {
1171 LOG(ERROR) << "gatt_if=" << +gatt_if << " is not registered";
1172 return false;
1173 }
1174
1175 if (is_direct)
1176 return gatt_cancel_open(gatt_if, bd_addr);
1177 else
1178 return gatt_auto_connect_dev_remove(p_reg->gatt_if, bd_addr);
1179 }
1180
1181 VLOG(1) << " unconditional";
1182
1183 /* only LE connection can be cancelled */
1184 tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
1185 if (p_tcb && !p_tcb->app_hold_link.empty()) {
1186 for (auto it = p_tcb->app_hold_link.begin();
1187 it != p_tcb->app_hold_link.end();) {
1188 auto next = std::next(it);
1189 // gatt_cancel_open modifies the app_hold_link.
1190 gatt_cancel_open(*it, bd_addr);
1191
1192 it = next;
1193 }
1194 }
1195
1196 if (!connection_manager::remove_unconditional(bd_addr)) {
1197 LOG(ERROR)
1198 << __func__
1199 << ": no app associated with the bg device for unconditional removal";
1200 return false;
1201 }
1202
1203 return true;
1204 }
1205
1206 /*******************************************************************************
1207 *
1208 * Function GATT_Disconnect
1209 *
1210 * Description This function disconnects the GATT channel for this
1211 * registered application.
1212 *
1213 * Parameters conn_id: connection identifier.
1214 *
1215 * Returns GATT_SUCCESS if disconnected.
1216 *
1217 ******************************************************************************/
GATT_Disconnect(uint16_t conn_id)1218 tGATT_STATUS GATT_Disconnect(uint16_t conn_id) {
1219 LOG(INFO) << __func__ << " conn_id=" << loghex(conn_id);
1220
1221 uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
1222 tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
1223 if (!p_tcb) return GATT_ILLEGAL_PARAMETER;
1224
1225 tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
1226 gatt_update_app_use_link_flag(gatt_if, p_tcb, false, true);
1227 return GATT_SUCCESS;
1228 }
1229
1230 /*******************************************************************************
1231 *
1232 * Function GATT_GetConnectionInfor
1233 *
1234 * Description This function uses conn_id to find its associated BD address
1235 * and application interface
1236 *
1237 * Parameters conn_id: connection id (input)
1238 * p_gatt_if: applicaiton interface (output)
1239 * bd_addr: peer device address. (output)
1240 *
1241 * Returns true the ligical link information is found for conn_id
1242 *
1243 ******************************************************************************/
GATT_GetConnectionInfor(uint16_t conn_id,tGATT_IF * p_gatt_if,RawAddress & bd_addr,tBT_TRANSPORT * p_transport)1244 bool GATT_GetConnectionInfor(uint16_t conn_id, tGATT_IF* p_gatt_if,
1245 RawAddress& bd_addr, tBT_TRANSPORT* p_transport) {
1246 tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
1247 tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
1248 uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
1249 tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
1250
1251 VLOG(1) << __func__ << " conn_id=" << loghex(conn_id);
1252
1253 if (!p_tcb || !p_reg) return false;
1254
1255 bd_addr = p_tcb->peer_bda;
1256 *p_gatt_if = gatt_if;
1257 *p_transport = p_tcb->transport;
1258 return true;
1259 }
1260
1261 /*******************************************************************************
1262 *
1263 * Function GATT_GetConnIdIfConnected
1264 *
1265 * Description This function find the conn_id if the logical link for BD
1266 * address and applciation interface is connected
1267 *
1268 * Parameters gatt_if: applicaiton interface (input)
1269 * bd_addr: peer device address. (input)
1270 * p_conn_id: connection id (output)
1271 * transport: transport option
1272 *
1273 * Returns true the logical link is connected
1274 *
1275 ******************************************************************************/
GATT_GetConnIdIfConnected(tGATT_IF gatt_if,const RawAddress & bd_addr,uint16_t * p_conn_id,tBT_TRANSPORT transport)1276 bool GATT_GetConnIdIfConnected(tGATT_IF gatt_if, const RawAddress& bd_addr,
1277 uint16_t* p_conn_id, tBT_TRANSPORT transport) {
1278 tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
1279 tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
1280 bool status = false;
1281
1282 if (p_reg && p_tcb && (gatt_get_ch_state(p_tcb) == GATT_CH_OPEN)) {
1283 *p_conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
1284 status = true;
1285 }
1286
1287 VLOG(1) << __func__ << " status= " << +status;
1288 return status;
1289 }
1290