1 /******************************************************************************
2 *
3 * Copyright 2009-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 utility functions
22 *
23 ******************************************************************************/
24 #define LOG_TAG "gatt_utils"
25
26 #include <base/logging.h>
27 #include <base/strings/stringprintf.h>
28
29 #include <cstdint>
30 #include <deque>
31
32 #include "bt_target.h" // Must be first to define build configuration
33 #include "osi/include/allocator.h"
34 #include "osi/include/log.h"
35 #include "stack/btm/btm_sec.h"
36 #include "stack/eatt/eatt.h"
37 #include "stack/gatt/connection_manager.h"
38 #include "stack/gatt/gatt_int.h"
39 #include "stack/include/acl_api.h"
40 #include "stack/include/bt_hdr.h"
41 #include "stack/include/l2cdefs.h"
42 #include "stack/include/sdp_api.h"
43 #include "types/bluetooth/uuid.h"
44 #include "types/raw_address.h"
45
46 uint8_t btm_ble_read_sec_key_size(const RawAddress& bd_addr);
47
48 using base::StringPrintf;
49 using bluetooth::Uuid;
50 using bluetooth::eatt::EattExtension;
51 using bluetooth::eatt::EattChannel;
52
53 /* check if [x, y] and [a, b] have overlapping range */
54 #define GATT_VALIDATE_HANDLE_RANGE(x, y, a, b) ((y) >= (a) && (x) <= (b))
55
56 #define GATT_GET_NEXT_VALID_HANDLE(x) (((x) / 10 + 1) * 10)
57
58 const char* const op_code_name[] = {"UNKNOWN",
59 "ATT_RSP_ERROR",
60 "ATT_REQ_MTU",
61 "ATT_RSP_MTU",
62 "ATT_REQ_READ_INFO",
63 "ATT_RSP_READ_INFO",
64 "ATT_REQ_FIND_TYPE_VALUE",
65 "ATT_RSP_FIND_TYPE_VALUE",
66 "ATT_REQ_READ_BY_TYPE",
67 "ATT_RSP_READ_BY_TYPE",
68 "ATT_REQ_READ",
69 "ATT_RSP_READ",
70 "ATT_REQ_READ_BLOB",
71 "ATT_RSP_READ_BLOB",
72 "GATT_REQ_READ_MULTI",
73 "GATT_RSP_READ_MULTI",
74 "GATT_REQ_READ_BY_GRP_TYPE",
75 "GATT_RSP_READ_BY_GRP_TYPE",
76 "ATT_REQ_WRITE",
77 "ATT_RSP_WRITE",
78 "ATT_CMD_WRITE",
79 "ATT_SIGN_CMD_WRITE",
80 "ATT_REQ_PREPARE_WRITE",
81 "ATT_RSP_PREPARE_WRITE",
82 "ATT_REQ_EXEC_WRITE",
83 "ATT_RSP_EXEC_WRITE",
84 "Reserved",
85 "ATT_HANDLE_VALUE_NOTIF",
86 "Reserved",
87 "ATT_HANDLE_VALUE_IND",
88 "ATT_HANDLE_VALUE_CONF",
89 "ATT_OP_CODE_MAX"};
90
91 /*******************************************************************************
92 *
93 * Function gatt_free_pending_ind
94 *
95 * Description Free all pending indications
96 *
97 * Returns None
98 *
99 ******************************************************************************/
gatt_free_pending_ind(tGATT_TCB * p_tcb)100 void gatt_free_pending_ind(tGATT_TCB* p_tcb) {
101 VLOG(1) << __func__;
102
103 if (p_tcb->pending_ind_q == NULL) return;
104
105 /* release all queued indications */
106 while (!fixed_queue_is_empty(p_tcb->pending_ind_q))
107 osi_free(fixed_queue_try_dequeue(p_tcb->pending_ind_q));
108 fixed_queue_free(p_tcb->pending_ind_q, NULL);
109 p_tcb->pending_ind_q = NULL;
110 }
111
112 /*******************************************************************************
113 *
114 * Function gatt_delete_dev_from_srv_chg_clt_list
115 *
116 * Description Delete a device from the service changed client lit
117 *
118 * Returns None
119 *
120 ******************************************************************************/
gatt_delete_dev_from_srv_chg_clt_list(const RawAddress & bd_addr)121 void gatt_delete_dev_from_srv_chg_clt_list(const RawAddress& bd_addr) {
122 VLOG(1) << __func__;
123
124 tGATTS_SRV_CHG* p_buf = gatt_is_bda_in_the_srv_chg_clt_list(bd_addr);
125 if (p_buf != NULL) {
126 if (gatt_cb.cb_info.p_srv_chg_callback) {
127 /* delete from NV */
128 tGATTS_SRV_CHG_REQ req;
129 req.srv_chg.bda = bd_addr;
130 (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_REMOVE_CLIENT,
131 &req, NULL);
132 }
133 osi_free(fixed_queue_try_remove_from_queue(gatt_cb.srv_chg_clt_q, p_buf));
134 }
135 }
136
137 /*******************************************************************************
138 *
139 * Function gatt_set_srv_chg
140 *
141 * Description Set the service changed flag to true
142 *
143 * Returns None
144 *
145 ******************************************************************************/
gatt_set_srv_chg(void)146 void gatt_set_srv_chg(void) {
147 VLOG(1) << __func__;
148
149 if (fixed_queue_is_empty(gatt_cb.srv_chg_clt_q)) return;
150
151 list_t* list = fixed_queue_get_list(gatt_cb.srv_chg_clt_q);
152 for (const list_node_t* node = list_begin(list); node != list_end(list);
153 node = list_next(node)) {
154 VLOG(1) << "found a srv_chg clt";
155
156 tGATTS_SRV_CHG* p_buf = (tGATTS_SRV_CHG*)list_node(node);
157 if (!p_buf->srv_changed) {
158 VLOG(1) << "set srv_changed to true";
159 p_buf->srv_changed = true;
160 tGATTS_SRV_CHG_REQ req;
161 memcpy(&req.srv_chg, p_buf, sizeof(tGATTS_SRV_CHG));
162 if (gatt_cb.cb_info.p_srv_chg_callback)
163 (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_UPDATE_CLIENT,
164 &req, NULL);
165 }
166 }
167 }
168
169 /** Add a pending indication */
gatt_add_pending_ind(tGATT_TCB * p_tcb,tGATT_VALUE * p_ind)170 void gatt_add_pending_ind(tGATT_TCB* p_tcb, tGATT_VALUE* p_ind) {
171 VLOG(1) << __func__ << "enqueue a pending indication";
172
173 tGATT_VALUE* p_buf = (tGATT_VALUE*)osi_malloc(sizeof(tGATT_VALUE));
174 memcpy(p_buf, p_ind, sizeof(tGATT_VALUE));
175 fixed_queue_enqueue(p_tcb->pending_ind_q, p_buf);
176 }
177
178 /*******************************************************************************
179 *
180 * Function gatt_add_srv_chg_clt
181 *
182 * Description Add a service chnage client to the service change client queue
183 *
184 * Returns Pointer to the service change client buffer; Null no buffer
185 * available
186 *
187 ******************************************************************************/
gatt_add_srv_chg_clt(tGATTS_SRV_CHG * p_srv_chg)188 tGATTS_SRV_CHG* gatt_add_srv_chg_clt(tGATTS_SRV_CHG* p_srv_chg) {
189 tGATTS_SRV_CHG* p_buf = (tGATTS_SRV_CHG*)osi_malloc(sizeof(tGATTS_SRV_CHG));
190 VLOG(1) << __func__ << "enqueue a srv chg client";
191
192 memcpy(p_buf, p_srv_chg, sizeof(tGATTS_SRV_CHG));
193 fixed_queue_enqueue(gatt_cb.srv_chg_clt_q, p_buf);
194
195 return p_buf;
196 }
197
198 /**
199 * Returns pointer to the handle range buffer starting at handle |handle|,
200 * nullptr
201 * if no buffer available
202 */
gatt_find_hdl_buffer_by_handle(uint16_t handle)203 tGATT_HDL_LIST_ELEM* gatt_find_hdl_buffer_by_handle(uint16_t handle) {
204 for (auto& elem : *gatt_cb.hdl_list_info) {
205 if (elem.asgn_range.s_handle == handle) return &elem;
206 }
207
208 return nullptr;
209 }
210 /*******************************************************************************
211 *
212 * Description Find handle range buffer by app ID, service and service instance
213 * ID.
214 *
215 * Returns Pointer to the buffer, NULL no buffer available
216 *
217 ******************************************************************************/
gatt_find_hdl_buffer_by_app_id(const Uuid & app_uuid128,Uuid * p_svc_uuid,uint16_t start_handle)218 std::list<tGATT_HDL_LIST_ELEM>::iterator gatt_find_hdl_buffer_by_app_id(
219 const Uuid& app_uuid128, Uuid* p_svc_uuid, uint16_t start_handle) {
220 auto end_it = gatt_cb.hdl_list_info->end();
221 auto it = gatt_cb.hdl_list_info->begin();
222 for (; it != end_it; it++) {
223 if (app_uuid128 == it->asgn_range.app_uuid128 &&
224 *p_svc_uuid == it->asgn_range.svc_uuid &&
225 (start_handle == it->asgn_range.s_handle)) {
226 return it;
227 }
228 }
229
230 return it;
231 }
232
233 /**
234 * free the service attribute database buffers by the owner of the service app
235 * ID.
236 */
gatt_free_srvc_db_buffer_app_id(const Uuid & app_id)237 void gatt_free_srvc_db_buffer_app_id(const Uuid& app_id) {
238 auto it = gatt_cb.hdl_list_info->begin();
239 auto end = gatt_cb.hdl_list_info->end();
240 while (it != end) {
241 if (app_id == it->asgn_range.app_uuid128) {
242 it = gatt_cb.hdl_list_info->erase(it);
243 } else {
244 it++;
245 }
246 }
247 }
248
249 /*******************************************************************************
250 *
251 * Function gatt_find_the_connected_bda
252 *
253 * Description This function find the connected bda
254 *
255 * Returns true if found
256 *
257 ******************************************************************************/
gatt_find_the_connected_bda(uint8_t start_idx,RawAddress & bda,uint8_t * p_found_idx,tBT_TRANSPORT * p_transport)258 bool gatt_find_the_connected_bda(uint8_t start_idx, RawAddress& bda,
259 uint8_t* p_found_idx,
260 tBT_TRANSPORT* p_transport) {
261 uint8_t i;
262 bool found = false;
263 LOG_DEBUG("start_idx=%d", +start_idx);
264
265 for (i = start_idx; i < GATT_MAX_PHY_CHANNEL; i++) {
266 if (gatt_cb.tcb[i].in_use && gatt_cb.tcb[i].ch_state == GATT_CH_OPEN) {
267 bda = gatt_cb.tcb[i].peer_bda;
268 *p_found_idx = i;
269 *p_transport = gatt_cb.tcb[i].transport;
270 found = true;
271 LOG_DEBUG("bda: %s", bda.ToString().c_str());
272 break;
273 }
274 }
275 LOG_DEBUG("found=%d found_idx=%d", found, +i);
276 return found;
277 }
278
279 /*******************************************************************************
280 *
281 * Function gatt_is_srv_chg_ind_pending
282 *
283 * Description Check whether a service chnaged is in the indication pending
284 * queue or waiting for an Ack already
285 *
286 * Returns bool
287 *
288 ******************************************************************************/
gatt_is_srv_chg_ind_pending(tGATT_TCB * p_tcb)289 bool gatt_is_srv_chg_ind_pending(tGATT_TCB* p_tcb) {
290 VLOG(1) << __func__
291 << " is_queue_empty=" << fixed_queue_is_empty(p_tcb->pending_ind_q);
292
293 if (p_tcb->indicate_handle == gatt_cb.handle_of_h_r) return true;
294
295 if (p_tcb->eatt && EattExtension::GetInstance()->IsIndicationPending(
296 p_tcb->peer_bda, gatt_cb.handle_of_h_r))
297 return true;
298
299 if (fixed_queue_is_empty(p_tcb->pending_ind_q)) return false;
300
301 list_t* list = fixed_queue_get_list(p_tcb->pending_ind_q);
302 for (const list_node_t* node = list_begin(list); node != list_end(list);
303 node = list_next(node)) {
304 tGATT_VALUE* p_buf = (tGATT_VALUE*)list_node(node);
305 if (p_buf->handle == gatt_cb.handle_of_h_r) {
306 return true;
307 }
308 }
309
310 return false;
311 }
312
313 /*******************************************************************************
314 *
315 * Function gatt_is_bda_in_the_srv_chg_clt_list
316 *
317 * Description This function check the specified bda is in the srv chg
318 * client list or not
319 *
320 * Returns pointer to the found elemenet otherwise NULL
321 *
322 ******************************************************************************/
gatt_is_bda_in_the_srv_chg_clt_list(const RawAddress & bda)323 tGATTS_SRV_CHG* gatt_is_bda_in_the_srv_chg_clt_list(const RawAddress& bda) {
324
325 VLOG(1) << __func__ << ": " << bda;
326
327 if (fixed_queue_is_empty(gatt_cb.srv_chg_clt_q)) return NULL;
328
329 list_t* list = fixed_queue_get_list(gatt_cb.srv_chg_clt_q);
330 for (const list_node_t* node = list_begin(list); node != list_end(list);
331 node = list_next(node)) {
332 tGATTS_SRV_CHG* p_buf = (tGATTS_SRV_CHG*)list_node(node);
333 if (bda == p_buf->bda) {
334 VLOG(1) << "bda is in the srv chg clt list";
335 return p_buf;
336 }
337 }
338
339 return NULL;
340 }
341
342 /*******************************************************************************
343 *
344 * Function gatt_is_bda_connected
345 *
346 * Description
347 *
348 * Returns GATT_INDEX_INVALID if not found. Otherwise index to the tcb.
349 *
350 ******************************************************************************/
gatt_is_bda_connected(const RawAddress & bda)351 bool gatt_is_bda_connected(const RawAddress& bda) {
352 uint8_t i = 0;
353 bool connected = false;
354
355 for (i = 0; i < GATT_MAX_PHY_CHANNEL; i++) {
356 if (gatt_cb.tcb[i].in_use && gatt_cb.tcb[i].peer_bda == bda) {
357 connected = true;
358 break;
359 }
360 }
361 return connected;
362 }
363
364 /*******************************************************************************
365 *
366 * Function gatt_find_i_tcb_by_addr
367 *
368 * Description Search for an empty tcb entry, and return the index.
369 *
370 * Returns GATT_INDEX_INVALID if not found. Otherwise index to the tcb.
371 *
372 ******************************************************************************/
gatt_find_i_tcb_by_addr(const RawAddress & bda,tBT_TRANSPORT transport)373 uint8_t gatt_find_i_tcb_by_addr(const RawAddress& bda,
374 tBT_TRANSPORT transport) {
375 uint8_t i = 0;
376
377 for (; i < GATT_MAX_PHY_CHANNEL; i++) {
378 if (gatt_cb.tcb[i].peer_bda == bda &&
379 gatt_cb.tcb[i].transport == transport) {
380 return i;
381 }
382 }
383 return GATT_INDEX_INVALID;
384 }
385
386 /*******************************************************************************
387 *
388 * Function gatt_get_tcb_by_idx
389 *
390 * Description The function get TCB using the TCB index
391 *
392 * Returns NULL if not found. Otherwise index to the tcb.
393 *
394 ******************************************************************************/
gatt_get_tcb_by_idx(uint8_t tcb_idx)395 tGATT_TCB* gatt_get_tcb_by_idx(uint8_t tcb_idx) {
396 tGATT_TCB* p_tcb = NULL;
397
398 if ((tcb_idx < GATT_MAX_PHY_CHANNEL) && gatt_cb.tcb[tcb_idx].in_use)
399 p_tcb = &gatt_cb.tcb[tcb_idx];
400
401 return p_tcb;
402 }
403
404 /*******************************************************************************
405 *
406 * Function gatt_find_tcb_by_addr
407 *
408 * Description Search for an empty tcb entry, and return pointer.
409 *
410 * Returns NULL if not found. Otherwise index to the tcb.
411 *
412 ******************************************************************************/
gatt_find_tcb_by_addr(const RawAddress & bda,tBT_TRANSPORT transport)413 tGATT_TCB* gatt_find_tcb_by_addr(const RawAddress& bda,
414 tBT_TRANSPORT transport) {
415 tGATT_TCB* p_tcb = nullptr;
416 uint8_t i = 0;
417
418 i = gatt_find_i_tcb_by_addr(bda, transport);
419 if (i != GATT_INDEX_INVALID) p_tcb = &gatt_cb.tcb[i];
420
421 return p_tcb;
422 }
423
424 /*******************************************************************************
425 *
426 * Function gatt_allocate_tcb_by_bdaddr
427 *
428 * Description Locate or allocate a new tcb entry for matching bda.
429 *
430 * Returns GATT_INDEX_INVALID if not found. Otherwise index to the tcb.
431 *
432 ******************************************************************************/
gatt_allocate_tcb_by_bdaddr(const RawAddress & bda,tBT_TRANSPORT transport)433 tGATT_TCB* gatt_allocate_tcb_by_bdaddr(const RawAddress& bda,
434 tBT_TRANSPORT transport) {
435 /* search for existing tcb with matching bda */
436 uint8_t j = gatt_find_i_tcb_by_addr(bda, transport);
437 if (j != GATT_INDEX_INVALID) return &gatt_cb.tcb[j];
438
439 /* find free tcb */
440 for (int i = 0; i < GATT_MAX_PHY_CHANNEL; i++) {
441 tGATT_TCB* p_tcb = &gatt_cb.tcb[i];
442 if (p_tcb->in_use) continue;
443
444 *p_tcb = tGATT_TCB();
445
446 p_tcb->pending_ind_q = fixed_queue_new(SIZE_MAX);
447 p_tcb->conf_timer = alarm_new("gatt.conf_timer");
448 p_tcb->ind_ack_timer = alarm_new("gatt.ind_ack_timer");
449 p_tcb->in_use = true;
450 p_tcb->tcb_idx = i;
451 p_tcb->transport = transport;
452 p_tcb->peer_bda = bda;
453 p_tcb->eatt = 0;
454 gatt_sr_init_cl_status(*p_tcb);
455 gatt_cl_init_sr_status(*p_tcb);
456
457 return p_tcb;
458 }
459
460 return NULL;
461 }
462
463 /** gatt_build_uuid_to_stream will convert 32bit UUIDs to 128bit. This function
464 * will return lenght required to build uuid, either |UUID:kNumBytes16| or
465 * |UUID::kNumBytes128| */
gatt_build_uuid_to_stream_len(const Uuid & uuid)466 uint8_t gatt_build_uuid_to_stream_len(const Uuid& uuid) {
467 size_t len = uuid.GetShortestRepresentationSize();
468 return len == Uuid::kNumBytes32 ? Uuid::kNumBytes128 : len;
469 }
470
471 /** Add UUID into stream. Returns UUID length. */
gatt_build_uuid_to_stream(uint8_t ** p_dst,const Uuid & uuid)472 uint8_t gatt_build_uuid_to_stream(uint8_t** p_dst, const Uuid& uuid) {
473 uint8_t* p = *p_dst;
474 size_t len = uuid.GetShortestRepresentationSize();
475
476 if (uuid.IsEmpty()) {
477 return 0;
478 }
479
480 if (len == Uuid::kNumBytes16) {
481 UINT16_TO_STREAM(p, uuid.As16Bit());
482 } else if (len == Uuid::kNumBytes32) {
483 /* always convert 32 bits into 128 bits */
484 ARRAY_TO_STREAM(p, uuid.To128BitLE(), (int)Uuid::kNumBytes128);
485 len = Uuid::kNumBytes128;
486 } else if (len == Uuid::kNumBytes128) {
487 ARRAY_TO_STREAM(p, uuid.To128BitLE(), (int)Uuid::kNumBytes128);
488 }
489
490 *p_dst = p;
491 return len;
492 }
493
gatt_parse_uuid_from_cmd(Uuid * p_uuid_rec,uint16_t uuid_size,uint8_t ** p_data)494 bool gatt_parse_uuid_from_cmd(Uuid* p_uuid_rec, uint16_t uuid_size,
495 uint8_t** p_data) {
496 bool ret = true;
497 uint8_t* p_uuid = *p_data;
498
499 switch (uuid_size) {
500 case Uuid::kNumBytes16: {
501 uint16_t val;
502 STREAM_TO_UINT16(val, p_uuid);
503 *p_uuid_rec = Uuid::From16Bit(val);
504 *p_data += Uuid::kNumBytes16;
505 return true;
506 }
507
508 case Uuid::kNumBytes128: {
509 *p_uuid_rec = Uuid::From128BitLE(p_uuid);
510 *p_data += Uuid::kNumBytes128;
511 return true;
512 }
513
514 /* do not allow 32 bits UUID in ATT PDU now */
515 case Uuid::kNumBytes32:
516 LOG(ERROR) << "DO NOT ALLOW 32 BITS UUID IN ATT PDU";
517 return false;
518 case 0:
519 default:
520 if (uuid_size != 0) ret = false;
521 LOG(WARNING) << __func__ << ": invalid uuid size";
522 break;
523 }
524
525 return (ret);
526 }
527
528 /*******************************************************************************
529 *
530 * Function gatt_start_rsp_timer
531 *
532 * Description Start a wait_for_response timer.
533 *
534 * Returns void
535 *
536 ******************************************************************************/
gatt_start_rsp_timer(tGATT_CLCB * p_clcb)537 void gatt_start_rsp_timer(tGATT_CLCB* p_clcb) {
538 uint64_t timeout_ms = GATT_WAIT_FOR_RSP_TIMEOUT_MS;
539
540 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
541 p_clcb->op_subtype == GATT_DISC_SRVC_ALL) {
542 timeout_ms = GATT_WAIT_FOR_DISC_RSP_TIMEOUT_MS;
543 }
544
545 // TODO: The tGATT_CLCB memory and state management needs cleanup,
546 // and then the timers can be allocated elsewhere.
547 if (p_clcb->gatt_rsp_timer_ent == NULL) {
548 p_clcb->gatt_rsp_timer_ent = alarm_new("gatt.gatt_rsp_timer_ent");
549 }
550 alarm_set_on_mloop(p_clcb->gatt_rsp_timer_ent, timeout_ms, gatt_rsp_timeout,
551 p_clcb);
552 }
553
554 /*******************************************************************************
555 *
556 * Function gatt_stop_rsp_timer
557 *
558 * Description Stops a GATT response timer.
559 *
560 * Returns void
561 *
562 ******************************************************************************/
gatt_stop_rsp_timer(tGATT_CLCB * p_clcb)563 void gatt_stop_rsp_timer(tGATT_CLCB* p_clcb) {
564 alarm_cancel(p_clcb->gatt_rsp_timer_ent);
565 }
566
567 /*******************************************************************************
568 *
569 * Function gatt_start_conf_timer
570 *
571 * Description Start a wait_for_confirmation timer.
572 *
573 * Returns void
574 *
575 ******************************************************************************/
gatt_start_conf_timer(tGATT_TCB * p_tcb,uint16_t cid)576 void gatt_start_conf_timer(tGATT_TCB* p_tcb, uint16_t cid) {
577 /* start notification cache timer */
578 if (p_tcb->eatt && cid != L2CAP_ATT_CID)
579 EattExtension::GetInstance()->StartIndicationConfirmationTimer(p_tcb->peer_bda, cid);
580 else
581 alarm_set_on_mloop(p_tcb->conf_timer, GATT_WAIT_FOR_RSP_TIMEOUT_MS,
582 gatt_indication_confirmation_timeout, p_tcb);
583 }
584
585 /*******************************************************************************
586 *
587 * Function gatt_stop_conf_timer
588 *
589 * Description Start a wait_for_confirmation timer.
590 *
591 * Returns void
592 *
593 ******************************************************************************/
gatt_stop_conf_timer(tGATT_TCB & tcb,uint16_t cid)594 void gatt_stop_conf_timer(tGATT_TCB& tcb, uint16_t cid) {
595 /* start notification cache timer */
596 if (tcb.eatt && cid != L2CAP_ATT_CID)
597 EattExtension::GetInstance()->StopIndicationConfirmationTimer(tcb.peer_bda, cid);
598 else
599 alarm_cancel(tcb.conf_timer);
600 }
601
602 /*******************************************************************************
603 *
604 * Function gatt_start_ind_ack_timer
605 *
606 * Description start the application ack timer
607 *
608 * Returns void
609 *
610 ******************************************************************************/
gatt_start_ind_ack_timer(tGATT_TCB & tcb,uint16_t cid)611 void gatt_start_ind_ack_timer(tGATT_TCB& tcb, uint16_t cid) {
612 /* start notification cache timer */
613 if (tcb.eatt && cid != L2CAP_ATT_CID)
614 EattExtension::GetInstance()->StartAppIndicationTimer(tcb.peer_bda, cid);
615 else
616 alarm_set_on_mloop(tcb.ind_ack_timer, GATT_WAIT_FOR_RSP_TIMEOUT_MS,
617 gatt_ind_ack_timeout, &tcb);
618 }
619
620 /*******************************************************************************
621 *
622 * Function gatt_stop_ind_ack_timer
623 *
624 * Description stop the application ack timer
625 *
626 * Returns void
627 *
628 ******************************************************************************/
gatt_stop_ind_ack_timer(tGATT_TCB * p_tcb,uint16_t cid)629 void gatt_stop_ind_ack_timer(tGATT_TCB* p_tcb, uint16_t cid) {
630 /* start notification cache timer */
631 if (p_tcb->eatt && cid != L2CAP_ATT_CID) {
632 EattExtension::GetInstance()->StopAppIndicationTimer(p_tcb->peer_bda, cid);
633 } else {
634 alarm_cancel(p_tcb->ind_ack_timer);
635 p_tcb->ind_count = 0;
636 }
637 }
638 /*******************************************************************************
639 *
640 * Function gatt_rsp_timeout
641 *
642 * Description Called when GATT wait for ATT command response timer expires
643 *
644 * Returns void
645 *
646 ******************************************************************************/
gatt_rsp_timeout(void * data)647 void gatt_rsp_timeout(void* data) {
648 tGATT_CLCB* p_clcb = (tGATT_CLCB*)data;
649
650 if (p_clcb == NULL || p_clcb->p_tcb == NULL) {
651 LOG(WARNING) << __func__ << " clcb is already deleted";
652 return;
653 }
654 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
655 p_clcb->op_subtype == GATT_DISC_SRVC_ALL &&
656 p_clcb->retry_count < GATT_REQ_RETRY_LIMIT) {
657 uint8_t rsp_code;
658 LOG(WARNING) << __func__ << " retry discovery primary service";
659 if (p_clcb != gatt_cmd_dequeue(*p_clcb->p_tcb, p_clcb->cid, &rsp_code)) {
660 LOG(ERROR) << __func__ << " command queue out of sync, disconnect";
661 } else {
662 p_clcb->retry_count++;
663 gatt_act_discovery(p_clcb);
664 return;
665 }
666 }
667
668 auto eatt_channel = EattExtension::GetInstance()->FindEattChannelByCid(
669 p_clcb->p_tcb->peer_bda, p_clcb->cid);
670 if (eatt_channel) {
671 LOG_WARN("disconnecting EATT cid: %d", p_clcb->cid);
672 EattExtension::GetInstance()->Disconnect(p_clcb->p_tcb->peer_bda,
673 p_clcb->cid);
674 } else {
675 LOG_WARN("disconnecting GATT...");
676 gatt_disconnect(p_clcb->p_tcb);
677 }
678 }
679
680 extern void gatts_proc_srv_chg_ind_ack(tGATT_TCB tcb);
681
682 /*******************************************************************************
683 *
684 * Function gatt_indication_confirmation_timeout
685 *
686 * Description Called when the indication confirmation timer expires
687 *
688 * Returns void
689 *
690 ******************************************************************************/
gatt_indication_confirmation_timeout(void * data)691 void gatt_indication_confirmation_timeout(void* data) {
692 tGATT_TCB* p_tcb = (tGATT_TCB*)data;
693
694 if (p_tcb->indicate_handle == gatt_cb.handle_of_h_r) {
695 /* There are some GATT Server only devices, that don't implement GATT client
696 * functionalities, and ignore "Service Changed" indication. Android does
697 * not have CCC in "Service Changed" characteristic, and sends it to all
698 * bonded devices. This leads to situation where remote can ignore the
699 * indication, and trigger 30s timeout, then reconnection in a loop.
700 *
701 * Since chances of healthy Client device keeping connection for 30 seconds
702 * and not responding to "Service Changed" indication are very low, assume
703 * we are dealing with Server only device, and don't trigger disconnection.
704 *
705 * TODO: In future, we should properly expose CCC, and send indication only
706 * to devices that register for it.
707 */
708 LOG(WARNING) << " Service Changed notification timed out in 30 "
709 "seconds, assuming server-only remote, not disconnecting";
710 gatts_proc_srv_chg_ind_ack(*p_tcb);
711 return;
712 }
713
714 LOG(WARNING) << __func__ << " disconnecting...";
715 gatt_disconnect(p_tcb);
716 }
717
718 /*******************************************************************************
719 *
720 * Function gatt_ind_ack_timeout
721 *
722 * Description Called when GATT wait for ATT handle confirmation timeout
723 *
724 * Returns void
725 *
726 ******************************************************************************/
gatt_ind_ack_timeout(void * data)727 void gatt_ind_ack_timeout(void* data) {
728 tGATT_TCB* p_tcb = (tGATT_TCB*)data;
729 CHECK(p_tcb);
730
731 LOG(WARNING) << __func__ << ": send ack now";
732 p_tcb->ind_count = 0;
733 /*TODO: For now ATT used only, but we need to have timeout per CID
734 * and use it here corretly.
735 */
736 attp_send_cl_confirmation_msg(*p_tcb, L2CAP_ATT_CID);
737 }
738 /*******************************************************************************
739 *
740 * Description Search for a service that owns a specific handle.
741 *
742 * Returns GATT_MAX_SR_PROFILES if not found. Otherwise the index of
743 * the service.
744 *
745 ******************************************************************************/
gatt_sr_find_i_rcb_by_handle(uint16_t handle)746 std::list<tGATT_SRV_LIST_ELEM>::iterator gatt_sr_find_i_rcb_by_handle(
747 uint16_t handle) {
748 auto it = gatt_cb.srv_list_info->begin();
749
750 for (; it != gatt_cb.srv_list_info->end(); it++) {
751 if (it->s_hdl <= handle && it->e_hdl >= handle) {
752 return it;
753 }
754 }
755
756 return it;
757 }
758
759 /*******************************************************************************
760 *
761 * Function gatt_sr_get_sec_info
762 *
763 * Description Get the security flag and key size information for the peer
764 * device.
765 *
766 * Returns void
767 *
768 ******************************************************************************/
gatt_sr_get_sec_info(const RawAddress & rem_bda,tBT_TRANSPORT transport,tGATT_SEC_FLAG * p_sec_flag,uint8_t * p_key_size)769 void gatt_sr_get_sec_info(const RawAddress& rem_bda, tBT_TRANSPORT transport,
770 tGATT_SEC_FLAG* p_sec_flag, uint8_t* p_key_size) {
771 tGATT_SEC_FLAG flags = {};
772 flags.is_link_key_known = BTM_IsLinkKeyKnown(rem_bda, transport);
773 flags.is_link_key_authed = BTM_IsLinkKeyAuthed(rem_bda, transport);
774 flags.is_encrypted = BTM_IsEncrypted(rem_bda, transport);
775
776 *p_key_size = btm_ble_read_sec_key_size(rem_bda);
777 *p_sec_flag = flags;
778 }
779 /*******************************************************************************
780 *
781 * Function gatt_sr_send_req_callback
782 *
783 * Description
784 *
785 *
786 * Returns void
787 *
788 ******************************************************************************/
gatt_sr_send_req_callback(uint16_t conn_id,uint32_t trans_id,tGATTS_REQ_TYPE type,tGATTS_DATA * p_data)789 void gatt_sr_send_req_callback(uint16_t conn_id, uint32_t trans_id,
790 tGATTS_REQ_TYPE type, tGATTS_DATA* p_data) {
791 tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
792 tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
793
794 if (!p_reg) {
795 LOG(ERROR) << "p_reg not found discard request";
796 return;
797 }
798
799 if (p_reg->in_use && p_reg->app_cb.p_req_cb) {
800 (*p_reg->app_cb.p_req_cb)(conn_id, trans_id, type, p_data);
801 } else {
802 LOG(WARNING) << "Call back not found for application conn_id=" << conn_id;
803 }
804 }
805
806 /*******************************************************************************
807 *
808 * Function gatt_send_error_rsp
809 *
810 * Description This function sends an error response.
811 *
812 * Returns void
813 *
814 ******************************************************************************/
gatt_send_error_rsp(tGATT_TCB & tcb,uint16_t cid,uint8_t err_code,uint8_t op_code,uint16_t handle,bool deq)815 tGATT_STATUS gatt_send_error_rsp(tGATT_TCB& tcb, uint16_t cid, uint8_t err_code,
816 uint8_t op_code, uint16_t handle, bool deq) {
817 tGATT_STATUS status;
818 BT_HDR* p_buf;
819
820 tGATT_SR_MSG msg;
821 msg.error.cmd_code = op_code;
822 msg.error.reason = err_code;
823 msg.error.handle = handle;
824
825 uint16_t payload_size = gatt_tcb_get_payload_size_tx(tcb, cid);
826 p_buf = attp_build_sr_msg(tcb, GATT_RSP_ERROR, &msg, payload_size);
827 if (p_buf != NULL) {
828 status = attp_send_sr_msg(tcb, cid, p_buf);
829 } else
830 status = GATT_INSUF_RESOURCE;
831
832 if (deq)
833 gatt_dequeue_sr_cmd(tcb, cid);
834
835 return status;
836 }
837
838 /*******************************************************************************
839 *
840 * Function gatt_add_sdp_record
841 *
842 * Description This function add a SDP record for a GATT primary service
843 *
844 * Returns 0 if error else sdp handle for the record.
845 *
846 ******************************************************************************/
gatt_add_sdp_record(const Uuid & uuid,uint16_t start_hdl,uint16_t end_hdl)847 uint32_t gatt_add_sdp_record(const Uuid& uuid, uint16_t start_hdl,
848 uint16_t end_hdl) {
849 uint8_t buff[60];
850 uint8_t* p = buff;
851
852 VLOG(1) << __func__
853 << StringPrintf(" s_hdl=0x%x s_hdl=0x%x", start_hdl, end_hdl);
854
855 uint32_t sdp_handle = SDP_CreateRecord();
856 if (sdp_handle == 0) return 0;
857
858 switch (uuid.GetShortestRepresentationSize()) {
859 case Uuid::kNumBytes16: {
860 uint16_t tmp = uuid.As16Bit();
861 SDP_AddServiceClassIdList(sdp_handle, 1, &tmp);
862 break;
863 }
864
865 case Uuid::kNumBytes32: {
866 UINT8_TO_BE_STREAM(p, (UUID_DESC_TYPE << 3) | SIZE_FOUR_BYTES);
867 uint32_t tmp = uuid.As32Bit();
868 UINT32_TO_BE_STREAM(p, tmp);
869 SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_CLASS_ID_LIST,
870 DATA_ELE_SEQ_DESC_TYPE, (uint32_t)(p - buff), buff);
871 break;
872 }
873
874 case Uuid::kNumBytes128:
875 UINT8_TO_BE_STREAM(p, (UUID_DESC_TYPE << 3) | SIZE_SIXTEEN_BYTES);
876 ARRAY_TO_BE_STREAM(p, uuid.To128BitBE().data(), (int)Uuid::kNumBytes128);
877 SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_CLASS_ID_LIST,
878 DATA_ELE_SEQ_DESC_TYPE, (uint32_t)(p - buff), buff);
879 break;
880 }
881
882 /*** Fill out the protocol element sequence for SDP ***/
883 tSDP_PROTOCOL_ELEM proto_elem_list[2];
884 proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
885 proto_elem_list[0].num_params = 1;
886 proto_elem_list[0].params[0] = BT_PSM_ATT;
887 proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_ATT;
888 proto_elem_list[1].num_params = 2;
889 proto_elem_list[1].params[0] = start_hdl;
890 proto_elem_list[1].params[1] = end_hdl;
891
892 SDP_AddProtocolList(sdp_handle, 2, proto_elem_list);
893
894 /* Make the service browseable */
895 uint16_t list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
896 SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &list);
897
898 return (sdp_handle);
899 }
900
901 #if GATT_CONFORMANCE_TESTING == TRUE
902 /*******************************************************************************
903 *
904 * Function gatt_set_err_rsp
905 *
906 * Description This function is called to set the test confirm value
907 *
908 * Returns void
909 *
910 ******************************************************************************/
gatt_set_err_rsp(bool enable,uint8_t req_op_code,uint8_t err_status)911 void gatt_set_err_rsp(bool enable, uint8_t req_op_code, uint8_t err_status) {
912 VLOG(1) << __func__
913 << StringPrintf(" enable=%d op_code=%d, err_status=%d", enable,
914 req_op_code, err_status);
915 gatt_cb.enable_err_rsp = enable;
916 gatt_cb.req_op_code = req_op_code;
917 gatt_cb.err_status = err_status;
918 }
919 #endif
920
921 /*******************************************************************************
922 *
923 * Function gatt_get_regcb
924 *
925 * Description The function returns the registration control block.
926 *
927 * Returns pointer to the registration control block or NULL
928 *
929 ******************************************************************************/
gatt_get_regcb(tGATT_IF gatt_if)930 tGATT_REG* gatt_get_regcb(tGATT_IF gatt_if) {
931 uint8_t ii = (uint8_t)gatt_if;
932 tGATT_REG* p_reg = NULL;
933
934 if (ii < 1 || ii > GATT_MAX_APPS) {
935 LOG(WARNING) << "gatt_if out of range = " << +ii;
936 return NULL;
937 }
938
939 // Index for cl_rcb is always 1 less than gatt_if.
940 p_reg = &gatt_cb.cl_rcb[ii - 1];
941
942 if (!p_reg->in_use) {
943 LOG(WARNING) << "gatt_if found but not in use.";
944 return NULL;
945 }
946
947 return p_reg;
948 }
949
950 /*******************************************************************************
951 *
952 * Function gatt_tcb_is_cid_busy
953 *
954 * Description The function check if channel with given cid is busy
955 *
956 * Returns True when busy
957 *
958 ******************************************************************************/
959
gatt_tcb_is_cid_busy(tGATT_TCB & tcb,uint16_t cid)960 bool gatt_tcb_is_cid_busy(tGATT_TCB& tcb, uint16_t cid) {
961 if (cid == tcb.att_lcid) return !tcb.cl_cmd_q.empty();
962
963 EattChannel* channel =
964 EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
965 if (!channel) return false;
966
967 return !channel->cl_cmd_q_.empty();
968 }
969 /*******************************************************************************
970 *
971 * Function gatt_clcb_alloc
972 *
973 * Description The function allocates a GATT connection link control block
974 *
975 * Returns NULL if not found. Otherwise pointer to the connection link
976 * block.
977 *
978 ******************************************************************************/
gatt_clcb_alloc(uint16_t conn_id)979 tGATT_CLCB* gatt_clcb_alloc(uint16_t conn_id) {
980 tGATT_CLCB clcb = {};
981 tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
982 uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
983 tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
984 tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
985
986 clcb.conn_id = conn_id;
987 clcb.p_reg = p_reg;
988 clcb.p_tcb = p_tcb;
989 /* Use eatt only when clients wants that */
990 clcb.cid = gatt_tcb_get_att_cid(*p_tcb, p_reg->eatt_support);
991
992 gatt_cb.clcb_queue.emplace_back(clcb);
993 auto p_clcb = &(gatt_cb.clcb_queue.back());
994
995 if (gatt_cb.clcb_queue.size() > GATT_CL_MAX_LCB) {
996 /* GATT_CL_MAX_LCB is here from the historical reasons. We believe this
997 * limitation is not needed. In addition, number of clcb should not be
998 * bigger than that and also if it is bigger, we believe it should not
999 * cause the problem. This WARN is just to monitor number of CLCB and will
1000 * help in debugging in case we are wrong */
1001 LOG_WARN("Number of CLCB: %zu > %d", gatt_cb.clcb_queue.size(),
1002 GATT_CL_MAX_LCB);
1003 }
1004 return p_clcb;
1005 }
1006
1007 /*******************************************************************************
1008 *
1009 * Function gatt_tcb_get_cid_available_for_indication
1010 *
1011 * Description This function checks if indication can be send
1012 *
1013 * Returns true when stack is busy with waiting on indication
1014 * confirmation, false otherwise
1015 *
1016 ******************************************************************************/
gatt_tcb_get_cid_available_for_indication(tGATT_TCB * p_tcb,bool eatt_support,uint16_t ** indicated_handle_p,uint16_t * cid_p)1017 bool gatt_tcb_get_cid_available_for_indication(tGATT_TCB* p_tcb,
1018 bool eatt_support,
1019 uint16_t** indicated_handle_p,
1020 uint16_t* cid_p) {
1021 if (p_tcb->eatt && eatt_support) {
1022 EattChannel* channel =
1023 EattExtension::GetInstance()->GetChannelAvailableForIndication(p_tcb->peer_bda);
1024 if (channel) {
1025 *indicated_handle_p = &channel->indicate_handle_;
1026 *cid_p = channel->cid_;
1027 return true;
1028 }
1029 }
1030
1031 if (!GATT_HANDLE_IS_VALID(p_tcb->indicate_handle)) {
1032 *indicated_handle_p = &p_tcb->indicate_handle;
1033 *cid_p = p_tcb->att_lcid;
1034 return true;
1035 }
1036
1037 return false;
1038 }
1039
1040 /*******************************************************************************
1041 *
1042 * Function gatt_tcb_find_indicate_handle
1043 *
1044 * Description This function checks if indication can be send
1045 *
1046 * Returns true when indication handle found, false otherwise
1047 *
1048 ******************************************************************************/
gatt_tcb_find_indicate_handle(tGATT_TCB & tcb,uint16_t cid,uint16_t * indicated_handle_p)1049 bool gatt_tcb_find_indicate_handle(tGATT_TCB& tcb, uint16_t cid,
1050 uint16_t* indicated_handle_p) {
1051 if (cid == tcb.att_lcid) {
1052 *indicated_handle_p = tcb.indicate_handle;
1053 tcb.indicate_handle = 0;
1054 return true;
1055 }
1056
1057 if (tcb.eatt) {
1058 EattChannel* channel =
1059 EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
1060 if (channel) {
1061 *indicated_handle_p = channel->indicate_handle_;
1062 channel->indicate_handle_ = 0;
1063 return true;
1064 }
1065 }
1066
1067 return false;
1068 }
1069
1070 /*******************************************************************************
1071 *
1072 * Function gatt_tcb_get_att_cid
1073 *
1074 * Description This function gets cid for the GATT operation
1075 *
1076 * Returns Available CID
1077 *
1078 ******************************************************************************/
1079
gatt_tcb_get_att_cid(tGATT_TCB & tcb,bool eatt_support)1080 uint16_t gatt_tcb_get_att_cid(tGATT_TCB& tcb, bool eatt_support) {
1081 if (eatt_support && tcb.eatt) {
1082 EattChannel* channel =
1083 EattExtension::GetInstance()->GetChannelAvailableForClientRequest(tcb.peer_bda);
1084 if (channel) {
1085 return channel->cid_;
1086 }
1087 }
1088 return tcb.att_lcid;
1089 }
1090
1091 /*******************************************************************************
1092 *
1093 * Function gatt_tcb_get_payload_size_tx
1094 *
1095 * Description This function gets payload size for the GATT operation
1096 *
1097 * Returns Payload size for sending data
1098 *
1099 ******************************************************************************/
gatt_tcb_get_payload_size_tx(tGATT_TCB & tcb,uint16_t cid)1100 uint16_t gatt_tcb_get_payload_size_tx(tGATT_TCB& tcb, uint16_t cid) {
1101 if (!tcb.eatt || (cid == tcb.att_lcid)) return tcb.payload_size;
1102
1103 EattChannel* channel =
1104 EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
1105
1106 return channel->tx_mtu_;
1107 }
1108
1109 /*******************************************************************************
1110 *
1111 * Function gatt_tcb_get_payload_size_rx
1112 *
1113 * Description This function gets payload size for the GATT operation
1114 *
1115 * Returns Payload size for receiving data
1116 *
1117 ******************************************************************************/
1118
gatt_tcb_get_payload_size_rx(tGATT_TCB & tcb,uint16_t cid)1119 uint16_t gatt_tcb_get_payload_size_rx(tGATT_TCB& tcb, uint16_t cid) {
1120 if (!tcb.eatt || (cid == tcb.att_lcid)) return tcb.payload_size;
1121
1122 EattChannel* channel =
1123 EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
1124
1125 return channel->rx_mtu_;
1126 }
1127
1128 /*******************************************************************************
1129 *
1130 * Function gatt_clcb_dealloc
1131 *
1132 * Description The function de-allocates a GATT connection link control
1133 * block
1134 *
1135 * Returns None
1136 *
1137 ******************************************************************************/
gatt_clcb_dealloc(tGATT_CLCB * p_clcb)1138 void gatt_clcb_dealloc(tGATT_CLCB* p_clcb) {
1139 if (p_clcb) {
1140 alarm_free(p_clcb->gatt_rsp_timer_ent);
1141 gatt_clcb_invalidate(p_clcb->p_tcb, p_clcb);
1142 for (auto clcb_it = gatt_cb.clcb_queue.begin();
1143 clcb_it != gatt_cb.clcb_queue.end(); clcb_it++) {
1144 if (&(*clcb_it) == p_clcb) {
1145 gatt_cb.clcb_queue.erase(clcb_it);
1146 return;
1147 }
1148 }
1149 }
1150 }
1151
1152 /*******************************************************************************
1153 *
1154 * Function gatt_clcb_invalidate
1155 *
1156 * Description The function invalidates already scheduled p_clcb.
1157 *
1158 * Returns None
1159 *
1160 ******************************************************************************/
gatt_clcb_invalidate(tGATT_TCB * p_tcb,const tGATT_CLCB * p_clcb)1161 void gatt_clcb_invalidate(tGATT_TCB* p_tcb, const tGATT_CLCB* p_clcb) {
1162 std::deque<tGATT_CMD_Q>* cl_cmd_q_p;
1163 uint16_t cid = p_clcb->cid;
1164
1165 if (!p_tcb->pending_enc_clcb.empty()) {
1166 for (size_t i = 0; i < p_tcb->pending_enc_clcb.size(); i++) {
1167 if (p_tcb->pending_enc_clcb.at(i) == p_clcb) {
1168 LOG_WARN("Removing clcb (%p) for conn id=0x%04x from pending_enc_clcb",
1169 p_clcb, p_clcb->conn_id);
1170 p_tcb->pending_enc_clcb.at(i) = NULL;
1171 break;
1172 }
1173 }
1174 }
1175
1176 if (cid == p_tcb->att_lcid) {
1177 cl_cmd_q_p = &p_tcb->cl_cmd_q;
1178 } else {
1179 EattChannel* channel = EattExtension::GetInstance()->FindEattChannelByCid(
1180 p_tcb->peer_bda, cid);
1181 if (channel == nullptr) {
1182 return;
1183 }
1184 cl_cmd_q_p = &channel->cl_cmd_q_;
1185 }
1186
1187 if (cl_cmd_q_p->empty()) {
1188 return;
1189 }
1190
1191 auto iter = std::find_if(cl_cmd_q_p->begin(), cl_cmd_q_p->end(),
1192 [p_clcb](auto& el) { return el.p_clcb == p_clcb; });
1193
1194 if (iter == cl_cmd_q_p->end()) {
1195 return;
1196 }
1197
1198 if (iter->to_send) {
1199 /* If command was not send, just remove the entire element */
1200 cl_cmd_q_p->erase(iter);
1201 LOG_WARN("Removing scheduled clcb (%p) for conn_id=0x%04x", p_clcb,
1202 p_clcb->conn_id);
1203 } else {
1204 /* If command has been sent, just invalidate p_clcb pointer for proper
1205 * response handling */
1206 iter->p_clcb = NULL;
1207 LOG_WARN(
1208 "Invalidating clcb (%p) for already sent request on conn_id=0x%04x",
1209 p_clcb, p_clcb->conn_id);
1210 }
1211 }
1212 /*******************************************************************************
1213 *
1214 * Function gatt_find_tcb_by_cid
1215 *
1216 * Description The function searches for an empty entry
1217 * in registration info table for GATT client
1218 *
1219 * Returns NULL if not found. Otherwise pointer to the rcb.
1220 *
1221 ******************************************************************************/
gatt_find_tcb_by_cid(uint16_t lcid)1222 tGATT_TCB* gatt_find_tcb_by_cid(uint16_t lcid) {
1223 uint16_t xx = 0;
1224 tGATT_TCB* p_tcb = NULL;
1225
1226 for (xx = 0; xx < GATT_MAX_PHY_CHANNEL; xx++) {
1227 if (gatt_cb.tcb[xx].in_use &&
1228 ((gatt_cb.tcb[xx].att_lcid == lcid) ||
1229 ((EattExtension::GetInstance()->FindEattChannelByCid(gatt_cb.tcb[xx].peer_bda,
1230 lcid) != nullptr)))) {
1231 p_tcb = &gatt_cb.tcb[xx];
1232 break;
1233 }
1234 }
1235 return p_tcb;
1236 }
1237
1238 /*******************************************************************************
1239 *
1240 * Function gatt_num_clcb_by_bd_addr
1241 *
1242 * Description The function searches all LCB with macthing bd address
1243 *
1244 * Returns total number of clcb found.
1245 *
1246 ******************************************************************************/
gatt_num_clcb_by_bd_addr(const RawAddress & bda)1247 uint8_t gatt_num_clcb_by_bd_addr(const RawAddress& bda) {
1248 uint8_t num = 0;
1249
1250 for (auto const& clcb : gatt_cb.clcb_queue) {
1251 if (clcb.p_tcb->peer_bda == bda) num++;
1252 }
1253 return num;
1254 }
1255
gatt_sr_copy_prep_cnt_to_cback_cnt(tGATT_TCB & tcb)1256 void gatt_sr_copy_prep_cnt_to_cback_cnt(tGATT_TCB& tcb) {
1257 for (uint8_t i = 0; i < GATT_MAX_APPS; i++) {
1258 if (tcb.prep_cnt[i]) {
1259 tcb.sr_cmd.cback_cnt[i] = 1;
1260 }
1261 }
1262 }
1263
1264 /* Get outstanding server command pointer by the transaction id */
gatt_sr_get_cmd_by_trans_id(tGATT_TCB * p_tcb,uint32_t trans_id)1265 tGATT_SR_CMD* gatt_sr_get_cmd_by_trans_id(tGATT_TCB* p_tcb, uint32_t trans_id) {
1266 if (p_tcb->sr_cmd.trans_id == trans_id) return &p_tcb->sr_cmd;
1267
1268 if (!p_tcb->eatt) return nullptr;
1269
1270 EattChannel* channel =
1271 EattExtension::GetInstance()->FindEattChannelByTransId(p_tcb->peer_bda, trans_id);
1272 if (!channel) return nullptr;
1273
1274 return &channel->server_outstanding_cmd_;
1275 }
1276 /*******************************************************************************
1277 *
1278 * Function gatt_sr_is_cback_cnt_zero
1279 *
1280 * Description The function searches all LCB with macthing bd address
1281 *
1282 * Returns True if thetotal application callback count is zero
1283 *
1284 ******************************************************************************/
gatt_sr_is_cback_cnt_zero(tGATT_TCB & tcb)1285 bool gatt_sr_is_cback_cnt_zero(tGATT_TCB& tcb) {
1286 for (uint8_t i = 0; i < GATT_MAX_APPS; i++) {
1287 if (tcb.sr_cmd.cback_cnt[i]) {
1288 return false;
1289 }
1290 }
1291 return true;
1292 }
1293
1294 /*******************************************************************************
1295 *
1296 * Function gatt_sr_is_prep_cnt_zero
1297 *
1298 * Description Check the prepare write request count is zero or not
1299 *
1300 * Returns True no prepare write request
1301 *
1302 ******************************************************************************/
gatt_sr_is_prep_cnt_zero(tGATT_TCB & tcb)1303 bool gatt_sr_is_prep_cnt_zero(tGATT_TCB& tcb) {
1304 for (uint8_t i = 0; i < GATT_MAX_APPS; i++) {
1305 if (tcb.prep_cnt[i]) {
1306 return false;
1307 }
1308 }
1309 return true;
1310 }
1311
1312 /*******************************************************************************
1313 *
1314 * Function gatt_sr_reset_cback_cnt
1315 *
1316 * Description Reset the application callback count to zero
1317 *
1318 * Returns None
1319 *
1320 ******************************************************************************/
gatt_sr_reset_cback_cnt(tGATT_TCB & tcb,uint16_t cid)1321 void gatt_sr_reset_cback_cnt(tGATT_TCB& tcb, uint16_t cid) {
1322 for (uint8_t i = 0; i < GATT_MAX_APPS; i++) {
1323 if (cid == tcb.att_lcid) {
1324 tcb.sr_cmd.cback_cnt[i] = 0;
1325 } else {
1326 EattChannel* channel =
1327 EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
1328 channel->server_outstanding_cmd_.cback_cnt[i] = 0;
1329 }
1330 }
1331 }
1332
1333 /*******************************************************************************
1334 *
1335 * Function gatt_sr_reset_prep_cnt
1336 *
1337 * Description Reset the prep write count to zero
1338 *
1339 * Returns None
1340 *
1341 ******************************************************************************/
gatt_sr_reset_prep_cnt(tGATT_TCB & tcb)1342 void gatt_sr_reset_prep_cnt(tGATT_TCB& tcb) {
1343 for (uint8_t i = 0; i < GATT_MAX_APPS; i++) {
1344 tcb.prep_cnt[i] = 0;
1345 }
1346 }
1347
1348 /* Get pointer to server command on given cid */
gatt_sr_get_cmd_by_cid(tGATT_TCB & tcb,uint16_t cid)1349 tGATT_SR_CMD* gatt_sr_get_cmd_by_cid(tGATT_TCB& tcb, uint16_t cid) {
1350 tGATT_SR_CMD* sr_cmd_p;
1351
1352 LOG(INFO) << __func__ << " cid: " << int(cid) << " tcb cid " << tcb.att_lcid;
1353 if (cid == tcb.att_lcid) {
1354 sr_cmd_p = &tcb.sr_cmd;
1355 } else {
1356 EattChannel* channel =
1357 EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
1358 sr_cmd_p = &channel->server_outstanding_cmd_;
1359 }
1360
1361 return sr_cmd_p;
1362 }
1363
1364 /* Get pointer to the context of outstanding multi request */
gatt_sr_get_read_multi(tGATT_TCB & tcb,uint16_t cid)1365 tGATT_READ_MULTI* gatt_sr_get_read_multi(tGATT_TCB& tcb, uint16_t cid) {
1366 tGATT_READ_MULTI* read_multi_p;
1367
1368 LOG(INFO) << __func__ << " cid: " << int(cid) << " tcb cid " << tcb.att_lcid;
1369 if (cid == tcb.att_lcid) {
1370 read_multi_p = &tcb.sr_cmd.multi_req;
1371 } else {
1372 EattChannel* channel =
1373 EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
1374 read_multi_p = &channel->server_outstanding_cmd_.multi_req;
1375 }
1376
1377 return read_multi_p;
1378 }
1379
1380 /*******************************************************************************
1381 *
1382 * Function gatt_sr_update_cback_cnt
1383 *
1384 * Description Update the teh applicaiton callback count
1385 *
1386 * Returns None
1387 *
1388 ******************************************************************************/
gatt_sr_update_cback_cnt(tGATT_TCB & tcb,uint16_t cid,tGATT_IF gatt_if,bool is_inc,bool is_reset_first)1389 void gatt_sr_update_cback_cnt(tGATT_TCB& tcb, uint16_t cid, tGATT_IF gatt_if,
1390 bool is_inc, bool is_reset_first) {
1391 uint8_t idx = ((uint8_t)gatt_if) - 1;
1392 tGATT_SR_CMD* sr_cmd_p;
1393
1394 if (cid == tcb.att_lcid) {
1395 sr_cmd_p = &tcb.sr_cmd;
1396 } else {
1397 EattChannel* channel =
1398 EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
1399 sr_cmd_p = &channel->server_outstanding_cmd_;
1400 }
1401
1402 if (is_reset_first) {
1403 gatt_sr_reset_cback_cnt(tcb, cid);
1404 }
1405 if (is_inc) {
1406 sr_cmd_p->cback_cnt[idx]++;
1407 } else {
1408 if (sr_cmd_p->cback_cnt[idx]) {
1409 sr_cmd_p->cback_cnt[idx]--;
1410 }
1411 }
1412 }
1413
1414 /*******************************************************************************
1415 *
1416 * Function gatt_sr_update_prep_cnt
1417 *
1418 * Description Update the teh prepare write request count
1419 *
1420 * Returns None
1421 *
1422 ******************************************************************************/
gatt_sr_update_prep_cnt(tGATT_TCB & tcb,tGATT_IF gatt_if,bool is_inc,bool is_reset_first)1423 void gatt_sr_update_prep_cnt(tGATT_TCB& tcb, tGATT_IF gatt_if, bool is_inc,
1424 bool is_reset_first) {
1425 uint8_t idx = ((uint8_t)gatt_if) - 1;
1426
1427 VLOG(1) << StringPrintf(
1428 "%s tcb idx=%d gatt_if=%d is_inc=%d is_reset_first=%d", __func__,
1429 tcb.tcb_idx, gatt_if, is_inc, is_reset_first);
1430
1431 if (is_reset_first) {
1432 gatt_sr_reset_prep_cnt(tcb);
1433 }
1434 if (is_inc) {
1435 tcb.prep_cnt[idx]++;
1436 } else {
1437 if (tcb.prep_cnt[idx]) {
1438 tcb.prep_cnt[idx]--;
1439 }
1440 }
1441 }
1442
1443 /** Cancel LE Create Connection request */
gatt_cancel_open(tGATT_IF gatt_if,const RawAddress & bda)1444 bool gatt_cancel_open(tGATT_IF gatt_if, const RawAddress& bda) {
1445 tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bda, BT_TRANSPORT_LE);
1446 if (!p_tcb) {
1447 LOG_WARN(
1448 "Unable to cancel open for unknown connection gatt_if:%hhu peer:%s",
1449 gatt_if, PRIVATE_ADDRESS(bda));
1450 return true;
1451 }
1452
1453 if (gatt_get_ch_state(p_tcb) == GATT_CH_OPEN) {
1454 LOG(ERROR) << __func__ << ": link connected Too late to cancel";
1455 return false;
1456 }
1457
1458 gatt_update_app_use_link_flag(gatt_if, p_tcb, false, false);
1459
1460 if (p_tcb->app_hold_link.empty()) {
1461 LOG_DEBUG(
1462 "Client reference count is zero disconnecting device gatt_if:%hhu "
1463 "peer:%s",
1464 gatt_if, PRIVATE_ADDRESS(bda));
1465 gatt_disconnect(p_tcb);
1466 }
1467
1468 if (!connection_manager::direct_connect_remove(gatt_if, bda)) {
1469 if (!connection_manager::is_background_connection(bda)) {
1470 BTM_AcceptlistRemove(bda);
1471 LOG_INFO(
1472 "Gatt connection manager has no background record but "
1473 " removed filter acceptlist gatt_if:%hhu peer:%s",
1474 gatt_if, PRIVATE_ADDRESS(bda));
1475 } else {
1476 LOG_INFO(
1477 "Gatt connection manager maintains a background record"
1478 " preserving filter acceptlist gatt_if:%hhu peer:%s",
1479 gatt_if, PRIVATE_ADDRESS(bda));
1480 }
1481 }
1482 return true;
1483 }
1484
1485 /** Enqueue this command */
gatt_cmd_enq(tGATT_TCB & tcb,tGATT_CLCB * p_clcb,bool to_send,uint8_t op_code,BT_HDR * p_buf)1486 void gatt_cmd_enq(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, bool to_send,
1487 uint8_t op_code, BT_HDR* p_buf) {
1488 tGATT_CMD_Q cmd;
1489 cmd.to_send = to_send; /* waiting to be sent */
1490 cmd.op_code = op_code;
1491 cmd.p_cmd = p_buf;
1492 cmd.p_clcb = p_clcb;
1493 cmd.cid = p_clcb->cid;
1494
1495 if (p_clcb->cid == tcb.att_lcid) {
1496 tcb.cl_cmd_q.push_back(cmd);
1497 } else {
1498 EattChannel* channel =
1499 EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cmd.cid);
1500 CHECK(channel);
1501 channel->cl_cmd_q_.push_back(cmd);
1502 }
1503 }
1504
1505 /** dequeue the command in the client CCB command queue */
gatt_cmd_dequeue(tGATT_TCB & tcb,uint16_t cid,uint8_t * p_op_code)1506 tGATT_CLCB* gatt_cmd_dequeue(tGATT_TCB& tcb, uint16_t cid, uint8_t* p_op_code) {
1507 std::deque<tGATT_CMD_Q>* cl_cmd_q_p;
1508
1509 if (cid == tcb.att_lcid) {
1510 cl_cmd_q_p = &tcb.cl_cmd_q;
1511 } else {
1512 EattChannel* channel =
1513 EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
1514 CHECK(channel);
1515 cl_cmd_q_p = &channel->cl_cmd_q_;
1516 }
1517
1518 if (cl_cmd_q_p->empty()) return nullptr;
1519
1520 tGATT_CMD_Q cmd = cl_cmd_q_p->front();
1521 tGATT_CLCB* p_clcb = cmd.p_clcb;
1522 *p_op_code = cmd.op_code;
1523
1524 /* Note: If GATT client deregistered while the ATT request was on the way to
1525 * peer, device p_clcb will be null.
1526 */
1527 if (p_clcb && p_clcb->cid != cid) {
1528 LOG_WARN(" CID does not match (%d!=%d), conn_id=0x%04x", p_clcb->cid, cid,
1529 p_clcb->conn_id);
1530 }
1531
1532 cl_cmd_q_p->pop_front();
1533
1534 return p_clcb;
1535 }
1536
1537 /** Send out the ATT message for write */
gatt_send_write_msg(tGATT_TCB & tcb,tGATT_CLCB * p_clcb,uint8_t op_code,uint16_t handle,uint16_t len,uint16_t offset,uint8_t * p_data)1538 tGATT_STATUS gatt_send_write_msg(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
1539 uint8_t op_code, uint16_t handle, uint16_t len,
1540 uint16_t offset, uint8_t* p_data) {
1541 tGATT_CL_MSG msg;
1542 msg.attr_value.handle = handle;
1543 msg.attr_value.len = len;
1544 msg.attr_value.offset = offset;
1545 memcpy(msg.attr_value.value, p_data, len);
1546
1547 /* write by handle */
1548 return attp_send_cl_msg(tcb, p_clcb, op_code, &msg);
1549 }
1550
1551 /*******************************************************************************
1552 *
1553 * Function gatt_is_outstanding_msg_in_att_send_queue
1554 *
1555 * Description checks if there is message on the ATT fixed channel to send
1556 *
1557 * Returns true: on success; false otherwise
1558 *
1559 ******************************************************************************/
gatt_is_outstanding_msg_in_att_send_queue(const tGATT_TCB & tcb)1560 bool gatt_is_outstanding_msg_in_att_send_queue(const tGATT_TCB& tcb) {
1561 return (!tcb.cl_cmd_q.empty() && (tcb.cl_cmd_q.front()).to_send);
1562 }
1563 /*******************************************************************************
1564 *
1565 * Function gatt_end_operation
1566 *
1567 * Description This function ends a discovery, send callback and finalize
1568 * some control value.
1569 *
1570 * Returns 16 bits uuid.
1571 *
1572 ******************************************************************************/
gatt_end_operation(tGATT_CLCB * p_clcb,tGATT_STATUS status,void * p_data)1573 void gatt_end_operation(tGATT_CLCB* p_clcb, tGATT_STATUS status, void* p_data) {
1574 tGATT_CL_COMPLETE cb_data;
1575 tGATT_CMPL_CBACK* p_cmpl_cb =
1576 (p_clcb->p_reg) ? p_clcb->p_reg->app_cb.p_cmpl_cb : NULL;
1577 tGATTC_OPTYPE op = p_clcb->operation;
1578 tGATT_DISC_TYPE disc_type = GATT_DISC_MAX;
1579 tGATT_DISC_CMPL_CB* p_disc_cmpl_cb =
1580 (p_clcb->p_reg) ? p_clcb->p_reg->app_cb.p_disc_cmpl_cb : NULL;
1581 uint16_t conn_id;
1582 uint8_t operation;
1583
1584 VLOG(1) << __func__
1585 << StringPrintf(" status=%d op=%d subtype=%d", status,
1586 p_clcb->operation, p_clcb->op_subtype);
1587 memset(&cb_data.att_value, 0, sizeof(tGATT_VALUE));
1588
1589 if (p_cmpl_cb != NULL && p_clcb->operation != 0) {
1590 if (p_clcb->operation == GATTC_OPTYPE_READ) {
1591 cb_data.att_value.handle = p_clcb->s_handle;
1592 cb_data.att_value.len = p_clcb->counter;
1593
1594 if (cb_data.att_value.len > GATT_MAX_ATTR_LEN) {
1595 LOG(WARNING) << __func__
1596 << StringPrintf(" Large cb_data.att_value, size=%d",
1597 cb_data.att_value.len);
1598 cb_data.att_value.len = GATT_MAX_ATTR_LEN;
1599 }
1600
1601 if (p_data && p_clcb->counter)
1602 memcpy(cb_data.att_value.value, p_data, cb_data.att_value.len);
1603 }
1604
1605 if (p_clcb->operation == GATTC_OPTYPE_WRITE) {
1606 memset(&cb_data.att_value, 0, sizeof(tGATT_VALUE));
1607 cb_data.handle = cb_data.att_value.handle = p_clcb->s_handle;
1608 if (p_clcb->op_subtype == GATT_WRITE_PREPARE) {
1609 if (p_data) {
1610 cb_data.att_value = *((tGATT_VALUE*)p_data);
1611 } else {
1612 VLOG(1) << "Rcv Prepare write rsp but no data";
1613 }
1614 }
1615 }
1616
1617 if (p_clcb->operation == GATTC_OPTYPE_CONFIG)
1618 cb_data.mtu = p_clcb->p_tcb->payload_size;
1619
1620 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY) {
1621 disc_type = static_cast<tGATT_DISC_TYPE>(p_clcb->op_subtype);
1622 }
1623 }
1624
1625 osi_free_and_reset((void**)&p_clcb->p_attr_buf);
1626
1627 operation = p_clcb->operation;
1628 conn_id = p_clcb->conn_id;
1629 gatt_stop_rsp_timer(p_clcb);
1630
1631 gatt_clcb_dealloc(p_clcb);
1632
1633 if (p_disc_cmpl_cb && (op == GATTC_OPTYPE_DISCOVERY))
1634 (*p_disc_cmpl_cb)(conn_id, disc_type, status);
1635 else if (p_cmpl_cb && op)
1636 (*p_cmpl_cb)(conn_id, op, status, &cb_data);
1637 else
1638 LOG(WARNING) << __func__
1639 << StringPrintf(
1640 ": not sent out op=%d p_disc_cmpl_cb:%p p_cmpl_cb:%p",
1641 operation, p_disc_cmpl_cb, p_cmpl_cb);
1642 }
1643
1644 /** This function cleans up the control blocks when L2CAP channel disconnect */
gatt_cleanup_upon_disc(const RawAddress & bda,tGATT_DISCONN_REASON reason,tBT_TRANSPORT transport)1645 void gatt_cleanup_upon_disc(const RawAddress& bda, tGATT_DISCONN_REASON reason,
1646 tBT_TRANSPORT transport) {
1647 VLOG(1) << __func__;
1648
1649 tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bda, transport);
1650 if (!p_tcb) {
1651 LOG_ERROR(
1652 "Disconnect for unknown connection bd_addr:%s reason:%s transport:%s",
1653 PRIVATE_ADDRESS(bda), gatt_disconnection_reason_text(reason).c_str(),
1654 bt_transport_text(transport).c_str());
1655 return;
1656 }
1657
1658 gatt_set_ch_state(p_tcb, GATT_CH_CLOSE);
1659
1660 /* Notify EATT about disconnection. */
1661 EattExtension::GetInstance()->Disconnect(p_tcb->peer_bda);
1662
1663 for (auto clcb_it = gatt_cb.clcb_queue.begin();
1664 clcb_it != gatt_cb.clcb_queue.end();) {
1665 if (clcb_it->p_tcb != p_tcb) {
1666 ++clcb_it;
1667 continue;
1668 }
1669
1670 gatt_stop_rsp_timer(&(*clcb_it));
1671 VLOG(1) << "found p_clcb conn_id=" << +clcb_it->conn_id;
1672 if (clcb_it->operation == GATTC_OPTYPE_NONE) {
1673 clcb_it = gatt_cb.clcb_queue.erase(clcb_it);
1674 continue;
1675 }
1676
1677 tGATT_CLCB* p_clcb = &(*clcb_it);
1678 ++clcb_it;
1679 gatt_end_operation(p_clcb, GATT_ERROR, NULL);
1680 }
1681
1682 /* Remove the outstanding ATT commnads if any */
1683 p_tcb->cl_cmd_q.clear();
1684
1685 alarm_free(p_tcb->ind_ack_timer);
1686 p_tcb->ind_ack_timer = NULL;
1687 alarm_free(p_tcb->conf_timer);
1688 p_tcb->conf_timer = NULL;
1689 gatt_free_pending_ind(p_tcb);
1690 fixed_queue_free(p_tcb->sr_cmd.multi_rsp_q, NULL);
1691 p_tcb->sr_cmd.multi_rsp_q = NULL;
1692
1693 for (uint8_t i = 0; i < GATT_MAX_APPS; i++) {
1694 tGATT_REG* p_reg = &gatt_cb.cl_rcb[i];
1695 if (p_reg->in_use && p_reg->app_cb.p_conn_cb) {
1696 uint16_t conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
1697 (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, bda, conn_id,
1698 kGattDisconnected, reason, transport);
1699 }
1700 }
1701
1702 *p_tcb = tGATT_TCB();
1703 VLOG(1) << __func__ << ": exit";
1704 }
1705 /*******************************************************************************
1706 *
1707 * Function gatt_dbg_req_op_name
1708 *
1709 * Description Get op code description name, for debug information.
1710 *
1711 * Returns uint8_t *: name of the operation.
1712 *
1713 ******************************************************************************/
gatt_dbg_op_name(uint8_t op_code)1714 uint8_t* gatt_dbg_op_name(uint8_t op_code) {
1715 uint8_t pseduo_op_code_idx = op_code & (~GATT_WRITE_CMD_MASK);
1716
1717 if (op_code == GATT_CMD_WRITE) {
1718 pseduo_op_code_idx = 0x14; /* just an index to op_code_name */
1719 }
1720
1721 if (op_code == GATT_SIGN_CMD_WRITE) {
1722 pseduo_op_code_idx = 0x15; /* just an index to op_code_name */
1723 }
1724
1725 #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
1726 if (pseduo_op_code_idx < ARR_SIZE(op_code_name))
1727 return (uint8_t*)op_code_name[pseduo_op_code_idx];
1728 else
1729 return (uint8_t*)"Op Code Exceed Max";
1730 #undef ARR_SIZE
1731 }
1732
1733 /** Remove the application interface for the specified background device */
gatt_auto_connect_dev_remove(tGATT_IF gatt_if,const RawAddress & bd_addr)1734 bool gatt_auto_connect_dev_remove(tGATT_IF gatt_if, const RawAddress& bd_addr) {
1735 tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
1736 if (p_tcb) gatt_update_app_use_link_flag(gatt_if, p_tcb, false, false);
1737 return connection_manager::background_connect_remove(gatt_if, bd_addr);
1738 }
1739