summaryrefslogtreecommitdiff
path: root/system/stack/gatt/gatt_int.h
blob: 0641d4c95083464bcabee73d299be67b98e6a58b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
/******************************************************************************
 *
 *  Copyright 1999-2012 Broadcom Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 ******************************************************************************/

#ifndef GATT_INT_H
#define GATT_INT_H

#include <base/bind.h>
#include <base/strings/stringprintf.h>
#include <string.h>

#include <list>
#include <queue>
#include <unordered_set>
#include <vector>

#include "bt_target.h"
#include "btm_ble_api.h"
#include "btu.h"
#include "gatt_api.h"
#include "osi/include/fixed_queue.h"
#include "stack/include/bt_hdr.h"
#include "types/bluetooth/uuid.h"
#include "types/raw_address.h"

#define GATT_CREATE_CONN_ID(tcb_idx, gatt_if) \
  ((uint16_t)((((uint8_t)(tcb_idx)) << 8) | ((uint8_t)(gatt_if))))
#define GATT_GET_TCB_IDX(conn_id) ((uint8_t)(((uint16_t)(conn_id)) >> 8))
#define GATT_GET_GATT_IF(conn_id) ((tGATT_IF)((uint8_t)(conn_id)))

#define GATT_TRANS_ID_MAX 0x0fffffff /* 4 MSB is reserved */

/* security action for GATT write and read request */
typedef enum : uint8_t {
  GATT_SEC_NONE = 0,
  GATT_SEC_OK = 1,
  GATT_SEC_SIGN_DATA = 2,       /* compute the signature for the write cmd */
  GATT_SEC_ENCRYPT = 3,         /* encrypt the link with current key */
  GATT_SEC_ENCRYPT_NO_MITM = 4, /* unauthenticated encryption or better */
  GATT_SEC_ENCRYPT_MITM = 5,    /* authenticated encryption */
  GATT_SEC_ENC_PENDING = 6,     /* wait for link encryption pending */
} tGATT_SEC_ACTION;

#define CASE_RETURN_TEXT(code) \
  case code:                   \
    return #code

inline std::string gatt_security_action_text(const tGATT_SEC_ACTION& action) {
  switch (action) {
    CASE_RETURN_TEXT(GATT_SEC_NONE);
    CASE_RETURN_TEXT(GATT_SEC_OK);
    CASE_RETURN_TEXT(GATT_SEC_SIGN_DATA);
    CASE_RETURN_TEXT(GATT_SEC_ENCRYPT);
    CASE_RETURN_TEXT(GATT_SEC_ENCRYPT_NO_MITM);
    CASE_RETURN_TEXT(GATT_SEC_ENCRYPT_MITM);
    CASE_RETURN_TEXT(GATT_SEC_ENC_PENDING);
    default:
      return base::StringPrintf("UNKNOWN[%hhu]", action);
  }
}

#undef CASE_RETURN_TEXT

#define GATT_INDEX_INVALID 0xff

#define GATT_WRITE_CMD_MASK 0xc0 /*0x1100-0000*/
#define GATT_AUTH_SIGN_MASK 0x80 /*0x1000-0000*/
#define GATT_AUTH_SIGN_LEN 12

#define GATT_HDR_SIZE 3 /* 1B opcode + 2B handle */

/* wait for ATT cmd response timeout value */
#define GATT_WAIT_FOR_RSP_TIMEOUT_MS (30 * 1000)
#define GATT_WAIT_FOR_DISC_RSP_TIMEOUT_MS (5 * 1000)
#define GATT_REQ_RETRY_LIMIT 2

typedef struct {
  bool is_link_key_known;
  bool is_link_key_authed;
  bool is_encrypted;
} tGATT_SEC_FLAG;

/* Find Information Response Type
*/
#define GATT_INFO_TYPE_PAIR_16 0x01
#define GATT_INFO_TYPE_PAIR_128 0x02

constexpr bool kGattConnected = true;
constexpr bool kGattDisconnected = !kGattConnected;

/*  GATT client FIND_TYPE_VALUE_Request data */
typedef struct {
  bluetooth::Uuid uuid; /* type of attribute to be found */
  uint16_t s_handle;  /* starting handle */
  uint16_t e_handle;  /* ending handle */
  uint16_t value_len; /* length of the attribute value */
  uint8_t
      value[GATT_MAX_MTU_SIZE]; /* pointer to the attribute value to be found */
} tGATT_FIND_TYPE_VALUE;

/* client request message to ATT protocol
*/
typedef union {
  tGATT_READ_BY_TYPE browse;             /* read by type request */
  tGATT_FIND_TYPE_VALUE find_type_value; /* find by type value */
  tGATT_READ_MULTI read_multi;           /* read multiple request */
  tGATT_READ_PARTIAL read_blob;          /* read blob */
  tGATT_VALUE attr_value;                /* write request */
                                         /* prepare write */
  /* write blob */
  uint16_t handle; /* read,  handle value confirmation */
  uint16_t mtu;
  tGATT_EXEC_FLAG exec_write; /* execute write */
} tGATT_CL_MSG;

/* error response strucutre */
typedef struct {
  uint16_t handle;
  uint8_t cmd_code;
  uint8_t reason;
} tGATT_ERROR;

/* server response message to ATT protocol
*/
typedef union {
  /* data type            member          event   */
  tGATT_VALUE attr_value; /* READ, HANDLE_VALUE_IND, PREPARE_WRITE */
                          /* READ_BLOB, READ_BY_TYPE */
  tGATT_ERROR error;      /* ERROR_RSP */
  uint16_t handle;        /* WRITE, WRITE_BLOB */
  uint16_t mtu;           /* exchange MTU request */
} tGATT_SR_MSG;

/* Characteristic declaration attribute value
*/
typedef struct {
  tGATT_CHAR_PROP property;
  uint16_t char_val_handle;
} tGATT_CHAR_DECL;

/* attribute value maintained in the server database
*/
typedef union {
  bluetooth::Uuid uuid;        /* service declaration */
  tGATT_CHAR_DECL char_decl;   /* characteristic declaration */
  tGATT_INCL_SRVC incl_handle; /* included service */
  uint16_t char_ext_prop;      /* Characteristic Extended Properties */
} tGATT_ATTR_VALUE;

/* Attribute UUID type
*/
#define GATT_ATTR_UUID_TYPE_16 0
#define GATT_ATTR_UUID_TYPE_128 1
#define GATT_ATTR_UUID_TYPE_32 2
typedef uint8_t tGATT_ATTR_UUID_TYPE;

/* 16 bits UUID Attribute in server database
*/
typedef struct {
  std::unique_ptr<tGATT_ATTR_VALUE> p_value;
  tGATT_PERM permission;
  uint16_t handle;
  bluetooth::Uuid uuid;
  bt_gatt_db_attribute_type_t gatt_type;
} tGATT_ATTR;

/* Service Database definition
*/
typedef struct {
  std::vector<tGATT_ATTR> attr_list; /* pointer to the attributes */
  uint16_t end_handle;       /* Last handle number           */
  uint16_t next_handle;      /* Next usable handle value     */
} tGATT_SVC_DB;

/* Data Structure used for GATT server */
/* An GATT registration record consists of a handle, and 1 or more attributes */
/* A service registration information record consists of beginning and ending */
/* attribute handle, service UUID and a set of GATT server callback.          */

typedef struct {
  bluetooth::Uuid app_uuid128;
  tGATT_CBACK app_cb{};
  tGATT_IF gatt_if{0}; /* one based */
  bool in_use{false};
  uint8_t listening{0}; /* if adv for all has been enabled */
  bool eatt_support{false};
  std::string name;
} tGATT_REG;

struct tGATT_CLCB;

/* command queue for each connection */
typedef struct {
  BT_HDR* p_cmd;
  tGATT_CLCB* p_clcb;
  uint8_t op_code;
  bool to_send;
  uint16_t cid;
} tGATT_CMD_Q;

#if GATT_MAX_SR_PROFILES <= 8
typedef uint8_t tGATT_APP_MASK;
#elif GATT_MAX_SR_PROFILES <= 16
typedef uint16_t tGATT_APP_MASK;
#elif GATT_MAX_SR_PROFILES <= 32
typedef uint32_t tGATT_APP_MASK;
#endif

/* command details for each connection */
typedef struct {
  BT_HDR* p_rsp_msg;
  uint32_t trans_id;
  tGATT_READ_MULTI multi_req;
  fixed_queue_t* multi_rsp_q;
  uint16_t handle;
  uint8_t op_code;
  uint8_t status;
  uint8_t cback_cnt[GATT_MAX_APPS];
  uint16_t cid;
} tGATT_SR_CMD;

typedef enum : uint8_t {
  GATT_CH_CLOSE = 0,
  GATT_CH_CLOSING = 1,
  GATT_CH_CONN = 2,
  GATT_CH_CFG = 3,
  GATT_CH_OPEN = 4,
} tGATT_CH_STATE;

#define CASE_RETURN_TEXT(code) \
  case code:                   \
    return #code

inline std::string gatt_channel_state_text(const tGATT_CH_STATE& state) {
  switch (state) {
    CASE_RETURN_TEXT(GATT_CH_CLOSE);
    CASE_RETURN_TEXT(GATT_CH_CLOSING);
    CASE_RETURN_TEXT(GATT_CH_CONN);
    CASE_RETURN_TEXT(GATT_CH_CFG);
    CASE_RETURN_TEXT(GATT_CH_OPEN);
    default:
      return base::StringPrintf("UNKNOWN[%hhu]", state);
  }
}
#undef CASE_RETURN_TEXT

#define GATT_GATT_START_HANDLE 1
#define GATT_GAP_START_HANDLE 20
#define GATT_GMCS_START_HANDLE 40
#define GATT_GTBS_START_HANDLE 90
#define GATT_TMAS_START_HANDLE 130
#define GATT_APP_START_HANDLE 134

#ifndef GATT_DEFAULT_START_HANDLE
#define GATT_DEFAULT_START_HANDLE GATT_GATT_START_HANDLE
#endif

#ifndef GATT_LAST_HANDLE
#define GATT_LAST_HANDLE 0xFFFF
#endif

typedef struct hdl_cfg {
  uint16_t gatt_start_hdl;
  uint16_t gap_start_hdl;
  uint16_t gmcs_start_hdl;
  uint16_t gtbs_start_hdl;
  uint16_t tmas_start_hdl;
  uint16_t app_start_hdl;
} tGATT_HDL_CFG;

typedef struct hdl_list_elem {
  tGATTS_HNDL_RANGE asgn_range; /* assigned handle range */
  tGATT_SVC_DB svc_db;
} tGATT_HDL_LIST_ELEM;

/* Data Structure used for GATT server                                        */
/* A GATT registration record consists of a handle, and 1 or more attributes  */
/* A service registration information record consists of beginning and ending */
/* attribute handle, service UUID and a set of GATT server callback.          */
typedef struct {
  tGATT_SVC_DB* p_db;  /* pointer to the service database */
  bluetooth::Uuid app_uuid; /* application UUID */
  uint32_t sdp_handle; /* primamry service SDP handle */
  uint16_t type;       /* service type UUID, primary or secondary */
  uint16_t s_hdl;      /* service starting handle */
  uint16_t e_hdl;      /* service ending handle */
  tGATT_IF gatt_if;    /* this service is belong to which application */
  bool is_primary;
} tGATT_SRV_LIST_ELEM;

typedef struct {
  std::queue<tGATT_CLCB*> pending_enc_clcb; /* pending encryption channel q */
  tGATT_SEC_ACTION sec_act;
  RawAddress peer_bda;
  tBT_TRANSPORT transport;
  uint32_t trans_id;

  /* Indicates number of available eatt channels */
  uint8_t eatt;

  uint16_t att_lcid; /* L2CAP channel ID for ATT */
  uint16_t payload_size;

  tGATT_CH_STATE ch_state;

  std::unordered_set<uint8_t> app_hold_link;

  /* server needs */
  /* server response data */
  tGATT_SR_CMD sr_cmd;
  uint16_t indicate_handle;
  fixed_queue_t* pending_ind_q;

  alarm_t* conf_timer; /* peer confirm to indication timer */

  uint8_t prep_cnt[GATT_MAX_APPS];
  uint8_t ind_count;

  std::queue<tGATT_CMD_Q> cl_cmd_q;
  alarm_t* ind_ack_timer; /* local app confirm to indication timer */

  // TODO(hylo): support byte array data
  /* Client supported feature*/
  uint8_t cl_supp_feat;
  /* Server supported features */
  uint8_t sr_supp_feat;
  /* Use for server. if false, should handle database out of sync. */
  bool is_robust_cache_change_aware;

  bool in_use;
  uint8_t tcb_idx;
} tGATT_TCB;

/* logic channel */
typedef struct {
  uint16_t
      next_disc_start_hdl; /* starting handle for the next inc srvv discovery */
  tGATT_DISC_RES result;
  bool wait_for_read_rsp;
} tGATT_READ_INC_UUID128;
struct tGATT_CLCB {
  tGATT_TCB* p_tcb; /* associated TCB of this CLCB */
  tGATT_REG* p_reg; /* owner of this CLCB */
  uint8_t sccb_idx;
  uint8_t* p_attr_buf; /* attribute buffer for read multiple, prepare write */
  bluetooth::Uuid uuid;
  uint16_t conn_id; /* connection handle */
  uint16_t s_handle; /* starting handle of the active request */
  uint16_t e_handle; /* ending handle of the active request */
  uint16_t counter; /* used as offset, attribute length, num of prepare write */
  uint16_t start_offset;
  tGATT_AUTH_REQ auth_req; /* authentication requirement */
  tGATTC_OPTYPE operation; /* one logic channel can have one operation active */
  uint8_t op_subtype;      /* operation subtype */
  tGATT_STATUS status;     /* operation status */
  bool first_read_blob_after_read;
  tGATT_READ_INC_UUID128 read_uuid128;
  bool in_use;
  alarm_t* gatt_rsp_timer_ent; /* peer response timer */
  uint8_t retry_count;
  uint16_t read_req_current_mtu; /* This is the MTU value that the read was
                                    initiated with */
  uint16_t cid;
};

typedef struct {
  uint16_t handle;
  uint16_t uuid;
  uint32_t service_change;
} tGATT_SVC_CHG;

#define GATT_SVC_CHANGED_CONNECTING 1     /* wait for connection */
#define GATT_SVC_CHANGED_SERVICE 2        /* GATT service discovery */
#define GATT_SVC_CHANGED_CHARACTERISTIC 3 /* service change char discovery */
#define GATT_SVC_CHANGED_DESCRIPTOR 4     /* service change CCC discoery */
#define GATT_SVC_CHANGED_CONFIGURE_CCCD 5 /* config CCC */

typedef struct {
  uint16_t conn_id;
  bool in_use;
  bool connected;
  RawAddress bda;
  tBT_TRANSPORT transport;

  /* GATT service change CCC related variables */
  uint8_t ccc_stage;
  uint8_t ccc_result;
  uint16_t s_handle;
  uint16_t e_handle;
} tGATT_PROFILE_CLCB;

typedef struct {
  tGATT_TCB tcb[GATT_MAX_PHY_CHANNEL];
  fixed_queue_t* sign_op_queue;

  uint16_t next_handle;     /* next available handle */
  uint16_t last_service_handle; /* handle of last service */
  tGATT_SVC_CHG gattp_attr; /* GATT profile attribute service change */
  tGATT_IF gatt_if;
  std::list<tGATT_HDL_LIST_ELEM>* hdl_list_info;
  std::list<tGATT_SRV_LIST_ELEM>* srv_list_info;

  fixed_queue_t* srv_chg_clt_q; /* service change clients queue */
  tGATT_REG cl_rcb[GATT_MAX_APPS];
  tGATT_CLCB clcb[GATT_CL_MAX_LCB]; /* connection link control block*/

#if (GATT_CONFORMANCE_TESTING == TRUE)
  bool enable_err_rsp;
  uint8_t req_op_code;
  uint8_t err_status;
  uint16_t handle;
#endif

  tGATT_PROFILE_CLCB profile_clcb[GATT_MAX_APPS];
  uint16_t
      handle_of_h_r; /* Handle of the handles reused characteristic value */
  uint16_t handle_cl_supported_feat;
  uint16_t handle_sr_supported_feat;
  uint8_t
      gatt_svr_supported_feat_mask; /* Local supported features as a server */

  /* Supported features as a client. To be written to remote device.
   * Note this is NOT a value of the characteristic with handle
   * handle_cl_support_feat, as that one should be written by remote device.
   */
  uint8_t gatt_cl_supported_feat_mask;

  uint16_t handle_of_database_hash;
  Octet16 database_hash;

  tGATT_APPL_INFO cb_info;

  tGATT_HDL_CFG hdl_cfg;
} tGATT_CB;

#define GATT_SIZE_OF_SRV_CHG_HNDL_RANGE 4

/* Global GATT data */
extern tGATT_CB gatt_cb;

#if (GATT_CONFORMANCE_TESTING == TRUE)
extern void gatt_set_err_rsp(bool enable, uint8_t req_op_code,
                             uint8_t err_status);
#endif

/* from gatt_main.cc */
extern bool gatt_disconnect(tGATT_TCB* p_tcb);
extern bool gatt_act_connect(tGATT_REG* p_reg, const RawAddress& bd_addr,
                             tBT_TRANSPORT transport, int8_t initiating_phys);
extern bool gatt_connect(const RawAddress& rem_bda, tGATT_TCB* p_tcb,
                         tBT_TRANSPORT transport, uint8_t initiating_phys,
                         tGATT_IF gatt_if);
extern void gatt_data_process(tGATT_TCB& p_tcb, uint16_t cid, BT_HDR* p_buf);
extern void gatt_update_app_use_link_flag(tGATT_IF gatt_if, tGATT_TCB* p_tcb,
                                          bool is_add, bool check_acl_link);

extern void gatt_profile_db_init(void);
extern void gatt_set_ch_state(tGATT_TCB* p_tcb, tGATT_CH_STATE ch_state);
extern tGATT_CH_STATE gatt_get_ch_state(tGATT_TCB* p_tcb);
extern void gatt_init_srv_chg(void);
extern void gatt_proc_srv_chg(void);
extern void gatt_send_srv_chg_ind(const RawAddress& peer_bda);
extern void gatt_chk_srv_chg(tGATTS_SRV_CHG* p_srv_chg_clt);
extern void gatt_add_a_bonded_dev_for_srv_chg(const RawAddress& bda);

/* from gatt_attr.cc */
extern uint16_t gatt_profile_find_conn_id_by_bd_addr(const RawAddress& bda);

extern bool gatt_profile_get_eatt_support(const RawAddress& remote_bda);
extern void gatt_cl_init_sr_status(tGATT_TCB& tcb);
extern bool gatt_cl_read_sr_supp_feat_req(
    const RawAddress& peer_bda,
    base::OnceCallback<void(const RawAddress&, uint8_t)> cb);

extern bool gatt_sr_is_cl_change_aware(tGATT_TCB& tcb);
extern void gatt_sr_init_cl_status(tGATT_TCB& tcb);
extern void gatt_sr_update_cl_status(tGATT_TCB& tcb, bool chg_unaware);

/* Functions provided by att_protocol.cc */
extern tGATT_STATUS attp_send_cl_confirmation_msg(tGATT_TCB& tcb, uint16_t cid);
extern tGATT_STATUS attp_send_cl_msg(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
                                     uint8_t op_code, tGATT_CL_MSG* p_msg);
extern BT_HDR* attp_build_sr_msg(tGATT_TCB& tcb, uint8_t op_code,
                                 tGATT_SR_MSG* p_msg);
extern tGATT_STATUS attp_send_sr_msg(tGATT_TCB& tcb, uint16_t cid,
                                     BT_HDR* p_msg);
extern tGATT_STATUS attp_send_msg_to_l2cap(tGATT_TCB& tcb, uint16_t cid,
                                           BT_HDR* p_toL2CAP);

/* utility functions */
extern uint8_t* gatt_dbg_op_name(uint8_t op_code);
extern uint32_t gatt_add_sdp_record(const bluetooth::Uuid& uuid,
                                    uint16_t start_hdl, uint16_t end_hdl);
extern bool gatt_parse_uuid_from_cmd(bluetooth::Uuid* p_uuid, uint16_t len,
                                     uint8_t** p_data);
extern uint8_t gatt_build_uuid_to_stream_len(const bluetooth::Uuid& uuid);
extern uint8_t gatt_build_uuid_to_stream(uint8_t** p_dst,
                                         const bluetooth::Uuid& uuid);
extern void gatt_sr_get_sec_info(const RawAddress& rem_bda,
                                 tBT_TRANSPORT transport,
                                 tGATT_SEC_FLAG* p_sec_flag,
                                 uint8_t* p_key_size);
extern void gatt_start_rsp_timer(tGATT_CLCB* p_clcb);
extern void gatt_stop_rsp_timer(tGATT_CLCB* p_clcb);
extern void gatt_start_conf_timer(tGATT_TCB* p_tcb, uint16_t cid);
extern void gatt_stop_conf_timer(tGATT_TCB& tcb, uint16_t cid);
extern void gatt_rsp_timeout(void* data);
extern void gatt_indication_confirmation_timeout(void* data);
extern void gatt_ind_ack_timeout(void* data);
extern void gatt_start_ind_ack_timer(tGATT_TCB& tcb, uint16_t cid);
extern void gatt_stop_ind_ack_timer(tGATT_TCB* p_tcb, uint16_t cid);
extern tGATT_STATUS gatt_send_error_rsp(tGATT_TCB& tcb, uint16_t cid,
                                        uint8_t err_code, uint8_t op_code,
                                        uint16_t handle, bool deq);

extern bool gatt_is_srv_chg_ind_pending(tGATT_TCB* p_tcb);
extern tGATTS_SRV_CHG* gatt_is_bda_in_the_srv_chg_clt_list(
    const RawAddress& bda);

extern bool gatt_find_the_connected_bda(uint8_t start_idx, RawAddress& bda,
                                        uint8_t* p_found_idx,
                                        tBT_TRANSPORT* p_transport);
extern void gatt_set_srv_chg(void);
extern void gatt_delete_dev_from_srv_chg_clt_list(const RawAddress& bd_addr);
extern void gatt_add_pending_ind(tGATT_TCB* p_tcb, tGATT_VALUE* p_ind);
extern void gatt_free_srvc_db_buffer_app_id(const bluetooth::Uuid& app_id);
extern bool gatt_cl_send_next_cmd_inq(tGATT_TCB& tcb);

/* reserved handle list */
extern std::list<tGATT_HDL_LIST_ELEM>::iterator gatt_find_hdl_buffer_by_app_id(
    const bluetooth::Uuid& app_uuid128, bluetooth::Uuid* p_svc_uuid,
    uint16_t svc_inst);
extern tGATT_HDL_LIST_ELEM* gatt_find_hdl_buffer_by_handle(uint16_t handle);
extern tGATTS_SRV_CHG* gatt_add_srv_chg_clt(tGATTS_SRV_CHG* p_srv_chg);

/* for background connection */
extern bool gatt_auto_connect_dev_remove(tGATT_IF gatt_if,
                                         const RawAddress& bd_addr);

/* server function */
extern std::list<tGATT_SRV_LIST_ELEM>::iterator gatt_sr_find_i_rcb_by_handle(
    uint16_t handle);
extern tGATT_STATUS gatt_sr_process_app_rsp(tGATT_TCB& tcb, tGATT_IF gatt_if,
                                            uint32_t trans_id, uint8_t op_code,
                                            tGATT_STATUS status,
                                            tGATTS_RSP* p_msg,
                                            tGATT_SR_CMD* sr_res_p);
extern void gatt_server_handle_client_req(tGATT_TCB& p_tcb, uint16_t cid,
                                          uint8_t op_code, uint16_t len,
                                          uint8_t* p_data);
extern void gatt_sr_send_req_callback(uint16_t conn_id, uint32_t trans_id,
                                      uint8_t op_code, tGATTS_DATA* p_req_data);
extern uint32_t gatt_sr_enqueue_cmd(tGATT_TCB& tcb, uint16_t cid,
                                    uint8_t op_code, uint16_t handle);
extern bool gatt_cancel_open(tGATT_IF gatt_if, const RawAddress& bda);
extern void gatt_notify_phy_updated(tGATT_STATUS status, uint16_t handle,
                                    uint8_t tx_phy, uint8_t rx_phy);
/*   */

extern bool gatt_tcb_is_cid_busy(tGATT_TCB& tcb, uint16_t cid);

extern tGATT_REG* gatt_get_regcb(tGATT_IF gatt_if);
extern bool gatt_is_clcb_allocated(uint16_t conn_id);
extern tGATT_CLCB* gatt_clcb_alloc(uint16_t conn_id);

extern bool gatt_tcb_get_cid_available_for_indication(
    tGATT_TCB* p_tcb, bool eatt_support, uint16_t** indicate_handle_p,
    uint16_t* cid_p);
extern bool gatt_tcb_find_indicate_handle(tGATT_TCB& tcb, uint16_t cid,
                                          uint16_t* indicated_handle_p);
extern uint16_t gatt_tcb_get_att_cid(tGATT_TCB& tcb, bool eatt_support);
extern uint16_t gatt_tcb_get_payload_size_tx(tGATT_TCB& tcb, uint16_t cid);
extern uint16_t gatt_tcb_get_payload_size_rx(tGATT_TCB& tcb, uint16_t cid);
extern void gatt_clcb_dealloc(tGATT_CLCB* p_clcb);

extern void gatt_sr_copy_prep_cnt_to_cback_cnt(tGATT_TCB& p_tcb);
extern bool gatt_sr_is_cback_cnt_zero(tGATT_TCB& p_tcb);
extern bool gatt_sr_is_prep_cnt_zero(tGATT_TCB& p_tcb);
extern void gatt_sr_reset_cback_cnt(tGATT_TCB& p_tcb, uint16_t cid);
extern void gatt_sr_reset_prep_cnt(tGATT_TCB& tcb);
extern tGATT_SR_CMD* gatt_sr_get_cmd_by_trans_id(tGATT_TCB* p_tcb,
                                                 uint32_t trans_id);
extern tGATT_SR_CMD* gatt_sr_get_cmd_by_cid(tGATT_TCB& tcb, uint16_t cid);
extern tGATT_READ_MULTI* gatt_sr_get_read_multi(tGATT_TCB& tcb, uint16_t cid);
extern void gatt_sr_update_cback_cnt(tGATT_TCB& p_tcb, uint16_t cid,
                                     tGATT_IF gatt_if, bool is_inc,
                                     bool is_reset_first);
extern void gatt_sr_update_prep_cnt(tGATT_TCB& tcb, tGATT_IF gatt_if,
                                    bool is_inc, bool is_reset_first);

extern uint8_t gatt_num_clcb_by_bd_addr(const RawAddress& bda);
extern tGATT_TCB* gatt_find_tcb_by_cid(uint16_t lcid);
extern tGATT_TCB* gatt_allocate_tcb_by_bdaddr(const RawAddress& bda,
                                              tBT_TRANSPORT transport);
extern tGATT_TCB* gatt_get_tcb_by_idx(uint8_t tcb_idx);
extern tGATT_TCB* gatt_find_tcb_by_addr(const RawAddress& bda,
                                        tBT_TRANSPORT transport);
extern bool gatt_send_ble_burst_data(const RawAddress& remote_bda,
                                     BT_HDR* p_buf);

/* GATT client functions */
extern void gatt_dequeue_sr_cmd(tGATT_TCB& tcb, uint16_t cid);
extern tGATT_STATUS gatt_send_write_msg(tGATT_TCB& p_tcb, tGATT_CLCB* p_clcb,
                                        uint8_t op_code, uint16_t handle,
                                        uint16_t len, uint16_t offset,
                                        uint8_t* p_data);
extern void gatt_cleanup_upon_disc(const RawAddress& bda,
                                   tGATT_DISCONN_REASON reason,
                                   tBT_TRANSPORT transport);
extern void gatt_end_operation(tGATT_CLCB* p_clcb, tGATT_STATUS status,
                               void* p_data);

extern void gatt_act_discovery(tGATT_CLCB* p_clcb);
extern void gatt_act_read(tGATT_CLCB* p_clcb, uint16_t offset);
extern void gatt_act_write(tGATT_CLCB* p_clcb, uint8_t sec_act);
extern tGATT_CLCB* gatt_cmd_dequeue(tGATT_TCB& tcb, uint16_t cid,
                                    uint8_t* p_opcode);
extern void gatt_cmd_enq(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, bool to_send,
                         uint8_t op_code, BT_HDR* p_buf);
extern void gatt_client_handle_server_rsp(tGATT_TCB& tcb, uint16_t cid,
                                          uint8_t op_code, uint16_t len,
                                          uint8_t* p_data);
extern void gatt_send_queue_write_cancel(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
                                         tGATT_EXEC_FLAG flag);

/* gatt_auth.cc */
extern bool gatt_security_check_start(tGATT_CLCB* p_clcb);
extern void gatt_verify_signature(tGATT_TCB& tcb, uint16_t cid, BT_HDR* p_buf);
extern tGATT_STATUS gatt_get_link_encrypt_status(tGATT_TCB& tcb);
extern tGATT_SEC_ACTION gatt_get_sec_act(tGATT_TCB* p_tcb);
extern void gatt_set_sec_act(tGATT_TCB* p_tcb, tGATT_SEC_ACTION sec_act);

/* gatt_db.cc */
extern void gatts_init_service_db(tGATT_SVC_DB& db,
                                  const bluetooth::Uuid& service, bool is_pri,
                                  uint16_t s_hdl, uint16_t num_handle);
extern uint16_t gatts_add_included_service(tGATT_SVC_DB& db, uint16_t s_handle,
                                           uint16_t e_handle,
                                           const bluetooth::Uuid& service);
extern uint16_t gatts_add_characteristic(tGATT_SVC_DB& db, tGATT_PERM perm,
                                         tGATT_CHAR_PROP property,
                                         const bluetooth::Uuid& char_uuid);
extern uint16_t gatts_add_char_ext_prop_descr(tGATT_SVC_DB& db,
                                              uint16_t extended_properties);
extern uint16_t gatts_add_char_descr(tGATT_SVC_DB& db, tGATT_PERM perm,
                                     const bluetooth::Uuid& dscp_uuid);
extern tGATT_STATUS gatts_db_read_attr_value_by_type(
    tGATT_TCB& tcb, uint16_t cid, tGATT_SVC_DB* p_db, uint8_t op_code,
    BT_HDR* p_rsp, uint16_t s_handle, uint16_t e_handle,
    const bluetooth::Uuid& type, uint16_t* p_len, tGATT_SEC_FLAG sec_flag,
    uint8_t key_size, uint32_t trans_id, uint16_t* p_cur_handle);
extern tGATT_STATUS gatts_read_attr_value_by_handle(
    tGATT_TCB& tcb, uint16_t cid, tGATT_SVC_DB* p_db, uint8_t op_code,
    uint16_t handle, uint16_t offset, uint8_t* p_value, uint16_t* p_len,
    uint16_t mtu, tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id);
extern tGATT_STATUS gatts_write_attr_perm_check(
    tGATT_SVC_DB* p_db, uint8_t op_code, uint16_t handle, uint16_t offset,
    uint8_t* p_data, uint16_t len, tGATT_SEC_FLAG sec_flag, uint8_t key_size);
extern tGATT_STATUS gatts_read_attr_perm_check(tGATT_SVC_DB* p_db, bool is_long,
                                               uint16_t handle,
                                               tGATT_SEC_FLAG sec_flag,
                                               uint8_t key_size);
extern bluetooth::Uuid* gatts_get_service_uuid(tGATT_SVC_DB* p_db);

/* gatt_sr_hash.cc */
extern Octet16 gatts_calculate_database_hash(
    std::list<tGATT_SRV_LIST_ELEM>* lst_ptr);

#endif