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