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