1 /******************************************************************************
2 *
3 * Copyright 2008-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 the main GATT server attributes access request
22 * handling functions.
23 *
24 ******************************************************************************/
25
26 #include <bluetooth/log.h>
27
28 #include <deque>
29 #include <map>
30
31 #include "base/functional/callback.h"
32 #include "btif/include/btif_storage.h"
33 #include "eatt/eatt.h"
34 #include "gatt_api.h"
35 #include "gatt_int.h"
36 #include "device/include/interop.h"
37 #include "internal_include/bt_target.h"
38 #include "stack/include/bt_types.h"
39 #include "stack/include/bt_uuid16.h"
40 #include "stack/include/btm_sec_api.h"
41 #include "stack/include/btm_ble_addr.h"
42 #include "types/bluetooth/uuid.h"
43 #include "types/raw_address.h"
44
45 using bluetooth::Uuid;
46 using namespace bluetooth;
47
48 #define BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK 0x01
49
50 #define BLE_GATT_CL_SUP_FEAT_CACHING_BITMASK 0x01
51 #define BLE_GATT_CL_SUP_FEAT_EATT_BITMASK 0x02
52 #define BLE_GATT_CL_SUP_FEAT_MULTI_NOTIF_BITMASK 0x04
53
54 #define BLE_GATT_CL_ANDROID_SUP_FEAT \
55 (BLE_GATT_CL_SUP_FEAT_EATT_BITMASK | BLE_GATT_CL_SUP_FEAT_MULTI_NOTIF_BITMASK)
56
57 using gatt_sr_supported_feat_cb = base::OnceCallback<void(const RawAddress&, uint8_t)>;
58 using gatt_sirk_cb = base::OnceCallback<void(tGATT_STATUS status, const RawAddress&,
59 uint8_t sirk_type, Octet16& sirk)>;
60
61 typedef struct {
62 uint16_t op_uuid;
63 gatt_sr_supported_feat_cb cb;
64 gatt_sirk_cb sirk_cb;
65 } gatt_op_cb_data;
66
67 static std::map<tCONN_ID, std::deque<gatt_op_cb_data>> OngoingOps;
68
69 static void gatt_request_cback(tCONN_ID conn_id, uint32_t trans_id, uint8_t op_code,
70 tGATTS_DATA* p_data);
71 static void gatt_connect_cback(tGATT_IF /* gatt_if */, const RawAddress& bda, tCONN_ID conn_id,
72 bool connected, tGATT_DISCONN_REASON reason,
73 tBT_TRANSPORT transport);
74 static void gatt_disc_res_cback(tCONN_ID conn_id, tGATT_DISC_TYPE disc_type,
75 tGATT_DISC_RES* p_data);
76 static void gatt_disc_cmpl_cback(tCONN_ID conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status);
77 static void gatt_cl_op_cmpl_cback(tCONN_ID conn_id, tGATTC_OPTYPE op, tGATT_STATUS status,
78 tGATT_CL_COMPLETE* p_data);
79
80 static void gatt_cl_start_config_ccc(tGATT_PROFILE_CLCB* p_clcb);
81
82 static bool gatt_sr_is_robust_caching_enabled();
83
84 static bool read_sr_supported_feat_req(tCONN_ID conn_id,
85 base::OnceCallback<void(const RawAddress&, uint8_t)> cb);
86 static bool read_sr_sirk_req(tCONN_ID conn_id,
87 base::OnceCallback<void(tGATT_STATUS status, const RawAddress&,
88 uint8_t sirk_type, Octet16& sirk)>
89 cb);
90
91 static tGATT_STATUS gatt_sr_read_db_hash(tCONN_ID conn_id, tGATT_VALUE* p_value);
92 static tGATT_STATUS gatt_sr_read_cl_supp_feat(tCONN_ID conn_id, tGATT_VALUE* p_value);
93 static tGATT_STATUS gatt_sr_write_cl_supp_feat(tCONN_ID conn_id, tGATT_WRITE_REQ* p_data);
94
95 static tGATT_CBACK gatt_profile_cback = {
96 .p_conn_cb = gatt_connect_cback,
97 .p_cmpl_cb = gatt_cl_op_cmpl_cback,
98 .p_disc_res_cb = gatt_disc_res_cback,
99 .p_disc_cmpl_cb = gatt_disc_cmpl_cback,
100 .p_req_cb = gatt_request_cback,
101 .p_enc_cmpl_cb = nullptr,
102 .p_congestion_cb = nullptr,
103 .p_phy_update_cb = nullptr,
104 .p_conn_update_cb = nullptr,
105 .p_subrate_chg_cb = nullptr,
106 };
107
108 /*******************************************************************************
109 *
110 * Function gatt_profile_find_conn_id_by_bd_addr
111 *
112 * Description Find the connection ID by remote address
113 *
114 * Returns Connection ID
115 *
116 ******************************************************************************/
gatt_profile_find_conn_id_by_bd_addr(const RawAddress & remote_bda)117 tCONN_ID gatt_profile_find_conn_id_by_bd_addr(const RawAddress& remote_bda) {
118 tCONN_ID conn_id = GATT_INVALID_CONN_ID;
119 if (!GATT_GetConnIdIfConnected(gatt_cb.gatt_if, remote_bda, &conn_id, BT_TRANSPORT_LE)) {
120 log::warn(
121 "Unable to get GATT connection id if connected peer:{} gatt_if:{} "
122 "transport:{}",
123 remote_bda, gatt_cb.gatt_if, bt_transport_text(BT_TRANSPORT_LE));
124 }
125 if (conn_id == GATT_INVALID_CONN_ID) {
126 if (!GATT_GetConnIdIfConnected(gatt_cb.gatt_if, remote_bda, &conn_id, BT_TRANSPORT_BR_EDR)) {
127 log::warn(
128 "Unable to get GATT connection id if connected peer:{} gatt_if:{} "
129 "transport:{}",
130 remote_bda, gatt_cb.gatt_if, bt_transport_text(BT_TRANSPORT_BR_EDR));
131 }
132 }
133 return conn_id;
134 }
135
136 /*******************************************************************************
137 *
138 * Function gatt_profile_find_clcb_by_conn_id
139 *
140 * Description find clcb by Connection ID
141 *
142 * Returns Pointer to the found link conenction control block.
143 *
144 ******************************************************************************/
gatt_profile_find_clcb_by_conn_id(tCONN_ID conn_id)145 static tGATT_PROFILE_CLCB* gatt_profile_find_clcb_by_conn_id(tCONN_ID conn_id) {
146 uint8_t i_clcb;
147 tGATT_PROFILE_CLCB* p_clcb = NULL;
148
149 for (i_clcb = 0, p_clcb = gatt_cb.profile_clcb; i_clcb < GATT_MAX_APPS; i_clcb++, p_clcb++) {
150 if (p_clcb->in_use && p_clcb->conn_id == conn_id) {
151 return p_clcb;
152 }
153 }
154
155 return NULL;
156 }
157
158 /*******************************************************************************
159 *
160 * Function gatt_profile_find_clcb_by_bd_addr
161 *
162 * Description The function searches all LCBs with macthing bd address.
163 *
164 * Returns Pointer to the found link conenction control block.
165 *
166 ******************************************************************************/
gatt_profile_find_clcb_by_bd_addr(const RawAddress & bda,tBT_TRANSPORT transport)167 static tGATT_PROFILE_CLCB* gatt_profile_find_clcb_by_bd_addr(const RawAddress& bda,
168 tBT_TRANSPORT transport) {
169 uint8_t i_clcb;
170 tGATT_PROFILE_CLCB* p_clcb = NULL;
171
172 for (i_clcb = 0, p_clcb = gatt_cb.profile_clcb; i_clcb < GATT_MAX_APPS; i_clcb++, p_clcb++) {
173 if (p_clcb->in_use && p_clcb->transport == transport && p_clcb->connected &&
174 p_clcb->bda == bda) {
175 return p_clcb;
176 }
177 }
178
179 return NULL;
180 }
181
182 /*******************************************************************************
183 *
184 * Function gatt_profile_clcb_alloc
185 *
186 * Description The function allocates a GATT profile connection link
187 * control block
188 *
189 * Returns NULL if not found. Otherwise pointer to the connection link
190 * block.
191 *
192 ******************************************************************************/
gatt_profile_clcb_alloc(tCONN_ID conn_id,const RawAddress & bda,tBT_TRANSPORT tranport)193 static tGATT_PROFILE_CLCB* gatt_profile_clcb_alloc(tCONN_ID conn_id, const RawAddress& bda,
194 tBT_TRANSPORT tranport) {
195 uint8_t i_clcb = 0;
196 tGATT_PROFILE_CLCB* p_clcb = NULL;
197
198 for (i_clcb = 0, p_clcb = gatt_cb.profile_clcb; i_clcb < GATT_MAX_APPS; i_clcb++, p_clcb++) {
199 if (!p_clcb->in_use) {
200 p_clcb->in_use = true;
201 p_clcb->conn_id = conn_id;
202 p_clcb->connected = true;
203 p_clcb->transport = tranport;
204 p_clcb->bda = bda;
205 break;
206 }
207 }
208 if (i_clcb < GATT_MAX_APPS) {
209 return p_clcb;
210 }
211
212 return NULL;
213 }
214
215 /*******************************************************************************
216 *
217 * Function gatt_profile_clcb_dealloc
218 *
219 * Description The function deallocates a GATT profile connection link
220 * control block
221 *
222 * Returns void
223 *
224 ******************************************************************************/
gatt_profile_clcb_dealloc(tGATT_PROFILE_CLCB * p_clcb)225 static void gatt_profile_clcb_dealloc(tGATT_PROFILE_CLCB* p_clcb) {
226 memset(p_clcb, 0, sizeof(tGATT_PROFILE_CLCB));
227 }
228
229 /** GAP Attributes Database Request callback */
read_attr_value(tCONN_ID conn_id,uint16_t handle,tGATT_VALUE * p_value,bool is_long)230 static tGATT_STATUS read_attr_value(tCONN_ID conn_id, uint16_t handle, tGATT_VALUE* p_value,
231 bool is_long) {
232 uint8_t* p = p_value->value;
233
234 if (handle == gatt_cb.handle_sr_supported_feat) {
235 /* GATT_UUID_SERVER_SUP_FEAT*/
236 if (is_long) {
237 return GATT_NOT_LONG;
238 }
239
240 UINT8_TO_STREAM(p, gatt_cb.gatt_svr_supported_feat_mask);
241 p_value->len = sizeof(gatt_cb.gatt_svr_supported_feat_mask);
242 return GATT_SUCCESS;
243 }
244
245 if (handle == gatt_cb.handle_cl_supported_feat) {
246 /*GATT_UUID_CLIENT_SUP_FEAT */
247 if (is_long) {
248 return GATT_NOT_LONG;
249 }
250
251 return gatt_sr_read_cl_supp_feat(conn_id, p_value);
252 }
253
254 if (handle == gatt_cb.handle_of_database_hash) {
255 /* GATT_UUID_DATABASE_HASH */
256 if (is_long) {
257 return GATT_NOT_LONG;
258 }
259
260 return gatt_sr_read_db_hash(conn_id, p_value);
261 }
262
263 if (handle == gatt_cb.handle_of_h_r) {
264 /* GATT_UUID_GATT_SRV_CHGD */
265 return GATT_READ_NOT_PERMIT;
266 }
267
268 return GATT_NOT_FOUND;
269 }
270
271 /** GAP Attributes Database Read/Read Blob Request process */
proc_read_req(tCONN_ID conn_id,tGATTS_REQ_TYPE,tGATT_READ_REQ * p_data,tGATTS_RSP * p_rsp)272 static tGATT_STATUS proc_read_req(tCONN_ID conn_id, tGATTS_REQ_TYPE, tGATT_READ_REQ* p_data,
273 tGATTS_RSP* p_rsp) {
274 if (p_data->is_long) {
275 p_rsp->attr_value.offset = p_data->offset;
276 }
277
278 p_rsp->attr_value.handle = p_data->handle;
279
280 return read_attr_value(conn_id, p_data->handle, &p_rsp->attr_value, p_data->is_long);
281 }
282
283 /** GAP ATT server process a write request */
proc_write_req(tCONN_ID conn_id,tGATTS_REQ_TYPE,tGATT_WRITE_REQ * p_data)284 static tGATT_STATUS proc_write_req(tCONN_ID conn_id, tGATTS_REQ_TYPE, tGATT_WRITE_REQ* p_data) {
285 uint16_t handle = p_data->handle;
286
287 /* GATT_UUID_SERVER_SUP_FEAT*/
288 if (handle == gatt_cb.handle_sr_supported_feat) {
289 return GATT_WRITE_NOT_PERMIT;
290 }
291
292 /* GATT_UUID_CLIENT_SUP_FEAT*/
293 if (handle == gatt_cb.handle_cl_supported_feat) {
294 return gatt_sr_write_cl_supp_feat(conn_id, p_data);
295 }
296
297 /* GATT_UUID_DATABASE_HASH */
298 if (handle == gatt_cb.handle_of_database_hash) {
299 return GATT_WRITE_NOT_PERMIT;
300 }
301
302 /* GATT_UUID_GATT_SRV_CHGD */
303 if (handle == gatt_cb.handle_of_h_r) {
304 return GATT_WRITE_NOT_PERMIT;
305 }
306
307 return GATT_NOT_FOUND;
308 }
309
310 /*******************************************************************************
311 *
312 * Function gatt_request_cback
313 *
314 * Description GATT profile attribute access request callback.
315 *
316 * Returns void.
317 *
318 ******************************************************************************/
gatt_request_cback(tCONN_ID conn_id,uint32_t trans_id,tGATTS_REQ_TYPE type,tGATTS_DATA * p_data)319 static void gatt_request_cback(tCONN_ID conn_id, uint32_t trans_id, tGATTS_REQ_TYPE type,
320 tGATTS_DATA* p_data) {
321 tGATT_STATUS status = GATT_INVALID_PDU;
322 tGATTS_RSP rsp_msg;
323 bool rsp_needed = true;
324
325 memset(&rsp_msg, 0, sizeof(tGATTS_RSP));
326
327 switch (type) {
328 case GATTS_REQ_TYPE_READ_CHARACTERISTIC:
329 case GATTS_REQ_TYPE_READ_DESCRIPTOR:
330 status = proc_read_req(conn_id, type, &p_data->read_req, &rsp_msg);
331 break;
332
333 case GATTS_REQ_TYPE_WRITE_CHARACTERISTIC:
334 case GATTS_REQ_TYPE_WRITE_DESCRIPTOR:
335 case GATTS_REQ_TYPE_WRITE_EXEC:
336 case GATT_CMD_WRITE:
337 if (!p_data->write_req.need_rsp) {
338 rsp_needed = false;
339 }
340
341 status = proc_write_req(conn_id, type, &p_data->write_req);
342 break;
343
344 case GATTS_REQ_TYPE_MTU:
345 log::verbose("Get MTU exchange new mtu size: {}", p_data->mtu);
346 rsp_needed = false;
347 break;
348
349 default:
350 log::verbose("Unknown/unexpected LE GAP ATT request: 0x{:x}", type);
351 break;
352 }
353
354 if (rsp_needed) {
355 if (GATTS_SendRsp(conn_id, trans_id, status, &rsp_msg) != GATT_SUCCESS) {
356 log::warn("Unable to send GATT server response conn_id:{}", conn_id);
357 }
358 }
359 }
360
361 /*******************************************************************************
362 *
363 * Function gatt_connect_cback
364 *
365 * Description Gatt profile connection callback.
366 *
367 * Returns void
368 *
369 ******************************************************************************/
gatt_connect_cback(tGATT_IF,const RawAddress & bda,tCONN_ID conn_id,bool connected,tGATT_DISCONN_REASON,tBT_TRANSPORT transport)370 static void gatt_connect_cback(tGATT_IF /* gatt_if */, const RawAddress& bda, tCONN_ID conn_id,
371 bool connected, tGATT_DISCONN_REASON /* reason */,
372 tBT_TRANSPORT transport) {
373 log::verbose("from {} connected: {}, conn_id: 0x{:x}", bda, connected, conn_id);
374
375 // if the device is not trusted, remove data when the link is disconnected
376 if (!connected && !btm_sec_is_a_bonded_dev(bda)) {
377 log::info("remove untrusted client status, bda={}", bda);
378 btif_storage_remove_gatt_cl_supp_feat(bda);
379 btif_storage_remove_gatt_cl_db_hash(bda);
380 }
381
382 tGATT_PROFILE_CLCB* p_clcb = gatt_profile_find_clcb_by_bd_addr(bda, transport);
383 if (p_clcb == NULL) {
384 return;
385 }
386
387 if (connected) {
388 p_clcb->conn_id = conn_id;
389 p_clcb->connected = true;
390
391 if (p_clcb->ccc_stage == GATT_SVC_CHANGED_CONNECTING) {
392 p_clcb->ccc_stage++;
393 gatt_cl_start_config_ccc(p_clcb);
394 }
395 } else {
396 gatt_profile_clcb_dealloc(p_clcb);
397 }
398 }
399
400 /*******************************************************************************
401 *
402 * Function gatt_profile_db_init
403 *
404 * Description Initializa the GATT profile attribute database.
405 *
406 ******************************************************************************/
gatt_profile_db_init(void)407 void gatt_profile_db_init(void) {
408 /* Fill our internal UUID with a fixed pattern 0x81 */
409 std::array<uint8_t, Uuid::kNumBytes128> tmp;
410 tmp.fill(0x81);
411
412 OngoingOps.clear();
413
414 /* Create a GATT profile service */
415 gatt_cb.gatt_if =
416 GATT_Register(Uuid::From128BitBE(tmp), "GattProfileDb", &gatt_profile_cback, false);
417 GATT_StartIf(gatt_cb.gatt_if);
418
419 Uuid service_uuid = Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER);
420
421 Uuid srv_changed_char_uuid = Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD);
422 Uuid svr_sup_feat_uuid = Uuid::From16Bit(GATT_UUID_SERVER_SUP_FEAT);
423 Uuid cl_sup_feat_uuid = Uuid::From16Bit(GATT_UUID_CLIENT_SUP_FEAT);
424 Uuid database_hash_uuid = Uuid::From16Bit(GATT_UUID_DATABASE_HASH);
425
426 btgatt_db_element_t service[] = {
427 {
428 .uuid = service_uuid,
429 .type = BTGATT_DB_PRIMARY_SERVICE,
430 },
431 {
432 .uuid = srv_changed_char_uuid,
433 .type = BTGATT_DB_CHARACTERISTIC,
434 .properties = GATT_CHAR_PROP_BIT_INDICATE,
435 .permissions = 0,
436 },
437 {
438 .uuid = svr_sup_feat_uuid,
439 .type = BTGATT_DB_CHARACTERISTIC,
440 .properties = GATT_CHAR_PROP_BIT_READ,
441 .permissions = GATT_PERM_READ,
442 },
443 {
444 .uuid = cl_sup_feat_uuid,
445 .type = BTGATT_DB_CHARACTERISTIC,
446 .properties = GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_WRITE,
447 .permissions = GATT_PERM_READ | GATT_PERM_WRITE,
448 },
449 {
450 .uuid = database_hash_uuid,
451 .type = BTGATT_DB_CHARACTERISTIC,
452 .properties = GATT_CHAR_PROP_BIT_READ,
453 .permissions = GATT_PERM_READ,
454 }};
455
456 if (GATTS_AddService(gatt_cb.gatt_if, service, sizeof(service) / sizeof(btgatt_db_element_t)) !=
457 GATT_SERVICE_STARTED) {
458 log::warn("Unable to add GATT server service gatt_if:{}", gatt_cb.gatt_if);
459 }
460
461 gatt_cb.handle_of_h_r = service[1].attribute_handle;
462 gatt_cb.handle_sr_supported_feat = service[2].attribute_handle;
463 gatt_cb.handle_cl_supported_feat = service[3].attribute_handle;
464 gatt_cb.handle_of_database_hash = service[4].attribute_handle;
465
466 gatt_cb.gatt_svr_supported_feat_mask |= BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK;
467 gatt_cb.gatt_cl_supported_feat_mask |= BLE_GATT_CL_ANDROID_SUP_FEAT;
468 gatt_cb.gatt_cl_supported_feat_mask |= BLE_GATT_CL_SUP_FEAT_CACHING_BITMASK;
469
470 log::verbose("gatt_if={} EATT supported", gatt_cb.gatt_if);
471 }
472
473 /*******************************************************************************
474 *
475 * Function gatt_disc_res_cback
476 *
477 * Description Gatt profile discovery result callback
478 *
479 * Returns void
480 *
481 ******************************************************************************/
gatt_disc_res_cback(tCONN_ID conn_id,tGATT_DISC_TYPE disc_type,tGATT_DISC_RES * p_data)482 static void gatt_disc_res_cback(tCONN_ID conn_id, tGATT_DISC_TYPE disc_type,
483 tGATT_DISC_RES* p_data) {
484 tGATT_PROFILE_CLCB* p_clcb = gatt_profile_find_clcb_by_conn_id(conn_id);
485
486 if (p_clcb == NULL) {
487 return;
488 }
489
490 switch (disc_type) {
491 case GATT_DISC_SRVC_BY_UUID: /* stage 1 */
492 p_clcb->e_handle = p_data->value.group_value.e_handle;
493 p_clcb->ccc_result++;
494 break;
495
496 case GATT_DISC_CHAR: /* stage 2 */
497 p_clcb->s_handle = p_data->value.dclr_value.val_handle;
498 p_clcb->ccc_result++;
499 break;
500
501 case GATT_DISC_CHAR_DSCPT: /* stage 3 */
502 if (p_data->type == Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG)) {
503 p_clcb->s_handle = p_data->handle;
504 p_clcb->ccc_result++;
505 }
506 break;
507
508 case GATT_DISC_SRVC_ALL:
509 case GATT_DISC_INC_SRVC:
510 case GATT_DISC_MAX:
511 log::error("Illegal discovery item handled");
512 break;
513 }
514 }
515
516 /*******************************************************************************
517 *
518 * Function gatt_disc_cmpl_cback
519 *
520 * Description Gatt profile discovery complete callback
521 *
522 * Returns void
523 *
524 ******************************************************************************/
gatt_disc_cmpl_cback(tCONN_ID conn_id,tGATT_DISC_TYPE,tGATT_STATUS status)525 static void gatt_disc_cmpl_cback(tCONN_ID conn_id, tGATT_DISC_TYPE /* disc_type */,
526 tGATT_STATUS status) {
527 tGATT_PROFILE_CLCB* p_clcb = gatt_profile_find_clcb_by_conn_id(conn_id);
528 if (p_clcb == NULL) {
529 log::warn("Unable to find gatt profile after discovery complete");
530 return;
531 }
532
533 if (status != GATT_SUCCESS) {
534 log::warn("Gatt discovery completed with errors status:{}", status);
535 return;
536 }
537 if (p_clcb->ccc_result == 0) {
538 log::warn("Gatt discovery completed but connection was idle id:{}", conn_id);
539 return;
540 }
541
542 p_clcb->ccc_result = 0;
543 p_clcb->ccc_stage++;
544 gatt_cl_start_config_ccc(p_clcb);
545 }
546
gatt_svc_read_cl_supp_feat_req(tCONN_ID conn_id)547 static bool gatt_svc_read_cl_supp_feat_req(tCONN_ID conn_id) {
548 tGATT_READ_PARAM param;
549
550 memset(¶m, 0, sizeof(tGATT_READ_PARAM));
551
552 param.service.s_handle = 1;
553 param.service.e_handle = 0xFFFF;
554 param.service.auth_req = 0;
555
556 param.service.uuid = bluetooth::Uuid::From16Bit(GATT_UUID_CLIENT_SUP_FEAT);
557
558 tGATT_STATUS status = GATTC_Read(conn_id, GATT_READ_BY_TYPE, ¶m);
559 if (status != GATT_SUCCESS) {
560 log::error("Read failed. Status: 0x{:x}", static_cast<uint8_t>(status));
561 return false;
562 }
563
564 gatt_op_cb_data cb_data;
565
566 cb_data.cb =
567 base::BindOnce([](const RawAddress& /* bdaddr */, uint8_t /* support */) { return; });
568 cb_data.op_uuid = GATT_UUID_CLIENT_SUP_FEAT;
569 OngoingOps[conn_id].emplace_back(std::move(cb_data));
570
571 return true;
572 }
573
gatt_att_write_cl_supp_feat(tCONN_ID conn_id,uint16_t handle)574 static bool gatt_att_write_cl_supp_feat(tCONN_ID conn_id, uint16_t handle) {
575 tGATT_VALUE attr;
576
577 memset(&attr, 0, sizeof(tGATT_VALUE));
578
579 attr.conn_id = conn_id;
580 attr.handle = handle;
581 attr.len = 1;
582 attr.value[0] = gatt_cb.gatt_cl_supported_feat_mask;
583
584 tGATT_STATUS status = GATTC_Write(conn_id, GATT_WRITE, &attr);
585 if (status != GATT_SUCCESS) {
586 log::error("Write failed. Status: 0x{:x}", static_cast<uint8_t>(status));
587 return false;
588 }
589
590 return true;
591 }
592
593 /*******************************************************************************
594 *
595 * Function gatt_cl_op_cmpl_cback
596 *
597 * Description Gatt profile client operation complete callback
598 *
599 * Returns void
600 *
601 ******************************************************************************/
gatt_cl_op_cmpl_cback(tCONN_ID conn_id,tGATTC_OPTYPE op,tGATT_STATUS status,tGATT_CL_COMPLETE * p_data)602 static void gatt_cl_op_cmpl_cback(tCONN_ID conn_id, tGATTC_OPTYPE op, tGATT_STATUS status,
603 tGATT_CL_COMPLETE* p_data) {
604 auto iter = OngoingOps.find(conn_id);
605
606 log::verbose("opcode: 0x{:x} status: {} conn id: 0x{:x}", static_cast<uint8_t>(op), status,
607 static_cast<int>(conn_id));
608
609 if (op != GATTC_OPTYPE_READ && op != GATTC_OPTYPE_WRITE) {
610 log::verbose("Not interested in opcode {}", op);
611 return;
612 }
613
614 if (iter == OngoingOps.end() || (iter->second.size() == 0)) {
615 /* If OngoingOps is empty it means we are not interested in the result here.
616 */
617 log::debug("Unexpected read complete");
618 return;
619 }
620
621 uint16_t cl_op_uuid = iter->second.front().op_uuid;
622
623 if (op == GATTC_OPTYPE_WRITE) {
624 if (cl_op_uuid == GATT_UUID_GATT_SRV_CHGD) {
625 log::debug("Write response from Service Changed CCC");
626 iter->second.pop_front();
627 /* Read server supported features here supported */
628 read_sr_supported_feat_req(conn_id, base::BindOnce([](const RawAddress& /* bdaddr */,
629 uint8_t /* support */) { return; }));
630 } else {
631 log::debug("Not interested in that write response");
632 }
633 return;
634 }
635
636 /* Handle Read operations */
637 uint8_t* pp = p_data->att_value.value;
638
639 log::verbose("cl_op_uuid 0x{:x}", cl_op_uuid);
640
641 switch (cl_op_uuid) {
642 case GATT_UUID_SERVER_SUP_FEAT: {
643 uint8_t tcb_idx = gatt_get_tcb_idx(conn_id);
644 tGATT_TCB& tcb = gatt_cb.tcb[tcb_idx];
645
646 auto operation_callback_data = std::move(iter->second.front());
647 iter->second.pop_front();
648
649 /* Check if EATT is supported */
650 if (status == GATT_SUCCESS) {
651 STREAM_TO_UINT8(tcb.sr_supp_feat, pp);
652 btif_storage_set_gatt_sr_supp_feat(tcb.peer_bda, tcb.sr_supp_feat);
653 }
654
655 /* Notify user about the supported features */
656 std::move(operation_callback_data.cb).Run(tcb.peer_bda, tcb.sr_supp_feat);
657
658 /* If server supports EATT lets try to find handle for the
659 * client supported features characteristic, where we could write
660 * our supported features as a client.
661 */
662 if (tcb.sr_supp_feat & BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK) {
663 gatt_svc_read_cl_supp_feat_req(conn_id);
664 }
665
666 break;
667 }
668 case GATT_UUID_CSIS_SIRK: {
669 uint8_t tcb_idx = gatt_get_tcb_idx(conn_id);
670 tGATT_TCB& tcb = gatt_cb.tcb[tcb_idx];
671
672 auto operation_callback_data = std::move(iter->second.front());
673 iter->second.pop_front();
674 tcb.gatt_status = status;
675
676 if (status == GATT_SUCCESS) {
677 STREAM_TO_UINT8(tcb.sirk_type, pp);
678 STREAM_TO_ARRAY(tcb.sirk.data(), pp, 16);
679 }
680
681 std::move(operation_callback_data.sirk_cb)
682 .Run(tcb.gatt_status, tcb.peer_bda, tcb.sirk_type, tcb.sirk);
683
684 break;
685 }
686 case GATT_UUID_CLIENT_SUP_FEAT:
687 /*We don't need callback data anymore */
688 iter->second.pop_front();
689
690 if (status != GATT_SUCCESS) {
691 log::info("Client supported features charcteristic not found");
692 return;
693 }
694
695 /* Write our client supported features to the remote device */
696 gatt_att_write_cl_supp_feat(conn_id, p_data->att_value.handle);
697 break;
698 }
699 }
700
701 /*******************************************************************************
702 *
703 * Function gatt_cl_start_config_ccc
704 *
705 * Description Gatt profile start configure service change CCC
706 *
707 * Returns void
708 *
709 ******************************************************************************/
gatt_cl_start_config_ccc(tGATT_PROFILE_CLCB * p_clcb)710 static void gatt_cl_start_config_ccc(tGATT_PROFILE_CLCB* p_clcb) {
711 log::verbose("stage: {}", p_clcb->ccc_stage);
712
713 switch (p_clcb->ccc_stage) {
714 case GATT_SVC_CHANGED_SERVICE: /* discover GATT service */
715 if (GATTC_Discover(p_clcb->conn_id, GATT_DISC_SRVC_BY_UUID, 0x0001, 0xffff,
716 Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER)) != GATT_SUCCESS) {
717 log::warn("Unable to discovery GATT client conn_id:{}", p_clcb->conn_id);
718 }
719 break;
720
721 case GATT_SVC_CHANGED_CHARACTERISTIC: /* discover service change char */
722 if (GATTC_Discover(p_clcb->conn_id, GATT_DISC_CHAR, 0x0001, p_clcb->e_handle,
723 Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD)) != GATT_SUCCESS) {
724 log::warn("Unable to discovery GATT client conn_id:{}", p_clcb->conn_id);
725 }
726 break;
727
728 case GATT_SVC_CHANGED_DESCRIPTOR: /* discover service change ccc */
729 if (GATTC_Discover(p_clcb->conn_id, GATT_DISC_CHAR_DSCPT, p_clcb->s_handle,
730 p_clcb->e_handle) != GATT_SUCCESS) {
731 log::warn("Unable to discovery GATT client conn_id:{}", p_clcb->conn_id);
732 }
733 break;
734
735 case GATT_SVC_CHANGED_CONFIGURE_CCCD: /* write ccc */
736 {
737 tGATT_VALUE ccc_value;
738 memset(&ccc_value, 0, sizeof(tGATT_VALUE));
739 ccc_value.handle = p_clcb->s_handle;
740 ccc_value.len = 2;
741 ccc_value.value[0] = GATT_CLT_CONFIG_INDICATION;
742 if (GATTC_Write(p_clcb->conn_id, GATT_WRITE, &ccc_value) != GATT_SUCCESS) {
743 log::warn("Unable to write GATT client data conn_id:{}", p_clcb->conn_id);
744 }
745
746 gatt_op_cb_data cb_data;
747 cb_data.cb =
748 base::BindOnce([](const RawAddress& /* bdaddr */, uint8_t /* support */) { return; });
749 cb_data.op_uuid = GATT_UUID_GATT_SRV_CHGD;
750 OngoingOps[p_clcb->conn_id].emplace_back(std::move(cb_data));
751
752 break;
753 }
754 }
755 }
756
757 /*******************************************************************************
758 *
759 * Function GATT_ConfigServiceChangeCCC
760 *
761 * Description Configure service change indication on remote device
762 *
763 * Returns none
764 *
765 ******************************************************************************/
GATT_ConfigServiceChangeCCC(const RawAddress & remote_bda,bool,tBT_TRANSPORT transport)766 void GATT_ConfigServiceChangeCCC(const RawAddress& remote_bda, bool /* enable */,
767 tBT_TRANSPORT transport) {
768 tGATT_PROFILE_CLCB* p_clcb = gatt_profile_find_clcb_by_bd_addr(remote_bda, transport);
769
770 if (p_clcb == NULL) {
771 p_clcb = gatt_profile_clcb_alloc(0, remote_bda, transport);
772 }
773
774 if (p_clcb == NULL) {
775 return;
776 }
777
778 if (GATT_GetConnIdIfConnected(gatt_cb.gatt_if, remote_bda, &p_clcb->conn_id, transport)) {
779 p_clcb->connected = true;
780 } else {
781 log::warn(
782 "Unable to get GATT connection id if connected peer:{} gatt_if:{} "
783 "transport:{}",
784 remote_bda, gatt_cb.gatt_if, bt_transport_text(BT_TRANSPORT_LE));
785 }
786
787 /* hold the link here */
788 if (!GATT_Connect(gatt_cb.gatt_if, remote_bda, BTM_BLE_DIRECT_CONNECTION, transport, true)) {
789 log::warn(
790 "Unable to connect GATT client gatt_if:{} peer:{} transport:{} "
791 "connection_tyoe:{} opporunistic:{}",
792 gatt_cb.gatt_if, remote_bda, bt_transport_text(transport), "BTM_BLE_DIRECT_CONNECTION",
793 true);
794 }
795 p_clcb->ccc_stage = GATT_SVC_CHANGED_CONNECTING;
796
797 if (!p_clcb->connected) {
798 /* wait for connection */
799 return;
800 }
801
802 p_clcb->ccc_stage++;
803 gatt_cl_start_config_ccc(p_clcb);
804 }
805
806 /*******************************************************************************
807 *
808 * Function gatt_cl_init_sr_status
809 *
810 * Description Restore status for trusted GATT Server device
811 *
812 * Returns none
813 *
814 ******************************************************************************/
gatt_cl_init_sr_status(tGATT_TCB & tcb)815 void gatt_cl_init_sr_status(tGATT_TCB& tcb) {
816 tcb.sr_supp_feat = btif_storage_get_sr_supp_feat(tcb.peer_bda);
817
818 if (tcb.sr_supp_feat & BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK) {
819 bluetooth::eatt::EattExtension::AddFromStorage(tcb.peer_bda);
820 }
821 }
822
read_sr_supported_feat_req(tCONN_ID conn_id,base::OnceCallback<void (const RawAddress &,uint8_t)> cb)823 static bool read_sr_supported_feat_req(tCONN_ID conn_id,
824 base::OnceCallback<void(const RawAddress&, uint8_t)> cb) {
825 tGATT_READ_PARAM param = {};
826
827 param.service.s_handle = 1;
828 param.service.e_handle = 0xFFFF;
829 param.service.auth_req = 0;
830
831 param.service.uuid = bluetooth::Uuid::From16Bit(GATT_UUID_SERVER_SUP_FEAT);
832
833 if (GATTC_Read(conn_id, GATT_READ_BY_TYPE, ¶m) != GATT_SUCCESS) {
834 log::error("Read GATT Support features GATT_Read Failed");
835 return false;
836 }
837
838 gatt_op_cb_data cb_data;
839
840 cb_data.cb = std::move(cb);
841 cb_data.op_uuid = GATT_UUID_SERVER_SUP_FEAT;
842 OngoingOps[conn_id].emplace_back(std::move(cb_data));
843
844 return true;
845 }
846
read_sr_sirk_req(tCONN_ID conn_id,base::OnceCallback<void (tGATT_STATUS status,const RawAddress &,uint8_t sirk_type,Octet16 & sirk)> cb)847 static bool read_sr_sirk_req(tCONN_ID conn_id,
848 base::OnceCallback<void(tGATT_STATUS status, const RawAddress&,
849 uint8_t sirk_type, Octet16& sirk)>
850 cb) {
851 tGATT_READ_PARAM param = {};
852 tBLE_ADDR_TYPE address_type = BLE_ADDR_PUBLIC;
853
854 param.service.s_handle = 1;
855 param.service.e_handle = 0xFFFF;
856 param.service.auth_req = 0;
857
858 param.service.uuid = bluetooth::Uuid::From16Bit(GATT_UUID_CSIS_SIRK);
859
860 uint8_t tcb_idx = gatt_get_tcb_idx(conn_id);
861 tGATT_TCB& tcb = gatt_cb.tcb[tcb_idx];
862
863 RawAddress identity_address = tcb.peer_bda;
864
865 btm_random_pseudo_to_identity_addr(&identity_address, &address_type);
866
867 if (address_type == BLE_ADDR_PUBLIC &&
868 interop_match_addr(INTEROP_DISABLE_SIRK_READ_BY_TYPE, &identity_address)) {
869 if (GATTC_Read(conn_id, GATT_READ_CHAR_VALUE, ¶m) != GATT_SUCCESS) {
870 log::error("Read GATT Support features GATT_Read Failed, conn_id: {}",
871 static_cast<int>(conn_id));
872 return false;
873 }
874 }
875 else{
876 if (GATTC_Read(conn_id, GATT_READ_BY_TYPE, ¶m) != GATT_SUCCESS) {
877 log::error("Read GATT Support features GATT_Read Failed, conn_id: {}",
878 static_cast<int>(conn_id));
879 return false;
880 }
881 }
882
883 gatt_op_cb_data cb_data;
884
885 cb_data.sirk_cb = std::move(cb);
886 cb_data.op_uuid = GATT_UUID_CSIS_SIRK;
887 OngoingOps[conn_id].emplace_back(std::move(cb_data));
888
889 return true;
890 }
891
892 /*******************************************************************************
893 *
894 * Function gatt_cl_read_sr_supp_feat_req
895 *
896 * Description Read remote device supported GATT feature mask.
897 *
898 * Returns bool
899 *
900 ******************************************************************************/
gatt_cl_read_sr_supp_feat_req(const RawAddress & peer_bda,base::OnceCallback<void (const RawAddress &,uint8_t)> cb)901 bool gatt_cl_read_sr_supp_feat_req(const RawAddress& peer_bda,
902 base::OnceCallback<void(const RawAddress&, uint8_t)> cb) {
903 tGATT_PROFILE_CLCB* p_clcb;
904 tCONN_ID conn_id;
905
906 if (!cb) {
907 return false;
908 }
909
910 log::verbose("BDA: {} read gatt supported features", peer_bda);
911
912 if (!GATT_GetConnIdIfConnected(gatt_cb.gatt_if, peer_bda, &conn_id, BT_TRANSPORT_LE)) {
913 log::warn(
914 "Unable to get GATT connection id if connected peer:{} gatt_if:{} "
915 "transport:{}",
916 peer_bda, gatt_cb.gatt_if, bt_transport_text(BT_TRANSPORT_LE));
917 }
918
919 if (conn_id == GATT_INVALID_CONN_ID) {
920 return false;
921 }
922
923 p_clcb = gatt_profile_find_clcb_by_conn_id(conn_id);
924 if (!p_clcb) {
925 p_clcb = gatt_profile_clcb_alloc(conn_id, peer_bda, BT_TRANSPORT_LE);
926 }
927
928 if (!p_clcb) {
929 log::verbose("p_clcb is NULL 0x{:x}", conn_id);
930 return false;
931 }
932
933 auto it = OngoingOps.find(conn_id);
934 if (it == OngoingOps.end()) {
935 OngoingOps[conn_id] = std::deque<gatt_op_cb_data>();
936 }
937
938 return read_sr_supported_feat_req(conn_id, std::move(cb));
939 }
940
941 /*******************************************************************************
942 *
943 * Function gatt_cl_read_sirk_req
944 *
945 * Description Read remote SIRK if it's a set member device.
946 *
947 * Returns bool
948 *
949 ******************************************************************************/
gatt_cl_read_sirk_req(const RawAddress & peer_bda,base::OnceCallback<void (tGATT_STATUS status,const RawAddress &,uint8_t sirk_type,Octet16 & sirk)> cb)950 bool gatt_cl_read_sirk_req(const RawAddress& peer_bda,
951 base::OnceCallback<void(tGATT_STATUS status, const RawAddress&,
952 uint8_t sirk_type, Octet16& sirk)>
953 cb) {
954 tGATT_PROFILE_CLCB* p_clcb;
955 tCONN_ID conn_id;
956
957 if (!cb) {
958 return false;
959 }
960
961 log::debug("BDA: {}, read SIRK", peer_bda);
962
963 if (!GATT_GetConnIdIfConnected(gatt_cb.gatt_if, peer_bda, &conn_id, BT_TRANSPORT_LE)) {
964 log::warn(
965 "Unable to get GATT connection id if connected peer:{} gatt_if:{} "
966 "transport:{}",
967 peer_bda, gatt_cb.gatt_if, bt_transport_text(BT_TRANSPORT_LE));
968 }
969 if (conn_id == GATT_INVALID_CONN_ID) {
970 return false;
971 }
972
973 p_clcb = gatt_profile_find_clcb_by_conn_id(conn_id);
974 if (!p_clcb) {
975 p_clcb = gatt_profile_clcb_alloc(conn_id, peer_bda, BT_TRANSPORT_LE);
976 }
977
978 if (!p_clcb) {
979 log::verbose("p_clcb is NULL, conn_id: {:04x}", conn_id);
980 return false;
981 }
982
983 auto it = OngoingOps.find(conn_id);
984
985 if (it == OngoingOps.end()) {
986 OngoingOps[conn_id] = std::deque<gatt_op_cb_data>();
987 }
988
989 return read_sr_sirk_req(conn_id, std::move(cb));
990 }
991
992 /*******************************************************************************
993 *
994 * Function gatt_profile_get_eatt_support
995 *
996 * Description Check if EATT is supported with remote device.
997 *
998 * Returns if EATT is supported.
999 *
1000 ******************************************************************************/
gatt_profile_get_eatt_support(const RawAddress & remote_bda)1001 bool gatt_profile_get_eatt_support(const RawAddress& remote_bda) {
1002 tCONN_ID conn_id;
1003
1004 log::verbose("BDA: {} read GATT support", remote_bda);
1005
1006 if (!GATT_GetConnIdIfConnected(gatt_cb.gatt_if, remote_bda, &conn_id, BT_TRANSPORT_LE)) {
1007 log::warn(
1008 "Unable to get GATT connection id if connected peer:{} gatt_if:{} "
1009 "transport:{}",
1010 remote_bda, gatt_cb.gatt_if, bt_transport_text(BT_TRANSPORT_LE));
1011 }
1012
1013 /* This read is important only when connected */
1014 if (conn_id == GATT_INVALID_CONN_ID) {
1015 return false;
1016 }
1017
1018 return gatt_profile_get_eatt_support_by_conn_id(conn_id);
1019 }
1020
gatt_profile_get_eatt_support_by_conn_id(tCONN_ID conn_id)1021 bool gatt_profile_get_eatt_support_by_conn_id(tCONN_ID conn_id) {
1022 /* Get tcb info */
1023 uint8_t tcb_idx = gatt_get_tcb_idx(conn_id);
1024 tGATT_TCB& tcb = gatt_cb.tcb[tcb_idx];
1025 return tcb.sr_supp_feat & BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK;
1026 }
1027
1028 /*******************************************************************************
1029 *
1030 * Function gatt_sr_is_robust_caching_enabled
1031 *
1032 * Description Check if Robust Caching is enabled on server side.
1033 *
1034 * Returns true if enabled in gd flag, otherwise false
1035 *
1036 ******************************************************************************/
gatt_sr_is_robust_caching_enabled()1037 static bool gatt_sr_is_robust_caching_enabled() { return false; }
1038
1039 /*******************************************************************************
1040 *
1041 * Function gatt_sr_is_cl_robust_caching_supported
1042 *
1043 * Description Check if Robust Caching is supported for the connection
1044 *
1045 * Returns true if enabled by client side, otherwise false
1046 *
1047 ******************************************************************************/
gatt_sr_is_cl_robust_caching_supported(tGATT_TCB & tcb)1048 static bool gatt_sr_is_cl_robust_caching_supported(tGATT_TCB& tcb) {
1049 // if robust caching is not enabled, should always return false
1050 if (!gatt_sr_is_robust_caching_enabled()) {
1051 return false;
1052 }
1053 return tcb.cl_supp_feat & BLE_GATT_CL_SUP_FEAT_CACHING_BITMASK;
1054 }
1055
1056 /*******************************************************************************
1057 *
1058 * Function gatt_sr_is_cl_multi_variable_len_notif_supported
1059 *
1060 * Description Check if Multiple Variable Length Notifications
1061 * supported for the connection
1062 *
1063 * Returns true if enabled by client side, otherwise false
1064 *
1065 ******************************************************************************/
gatt_sr_is_cl_multi_variable_len_notif_supported(tGATT_TCB & tcb)1066 bool gatt_sr_is_cl_multi_variable_len_notif_supported(tGATT_TCB& tcb) {
1067 return tcb.cl_supp_feat & BLE_GATT_CL_SUP_FEAT_MULTI_NOTIF_BITMASK;
1068 }
1069
1070 /*******************************************************************************
1071 *
1072 * Function gatt_sr_is_cl_change_aware
1073 *
1074 * Description Check if the connection is change-aware
1075 *
1076 * Returns true if change aware, otherwise false
1077 *
1078 ******************************************************************************/
gatt_sr_is_cl_change_aware(tGATT_TCB & tcb)1079 bool gatt_sr_is_cl_change_aware(tGATT_TCB& tcb) {
1080 // if robust caching is not supported, should always return true by default
1081 if (!gatt_sr_is_cl_robust_caching_supported(tcb)) {
1082 return true;
1083 }
1084 return tcb.is_robust_cache_change_aware;
1085 }
1086
1087 /*******************************************************************************
1088 *
1089 * Function gatt_sr_init_cl_status
1090 *
1091 * Description Restore status for trusted device
1092 *
1093 * Returns none
1094 *
1095 ******************************************************************************/
gatt_sr_init_cl_status(tGATT_TCB & tcb)1096 void gatt_sr_init_cl_status(tGATT_TCB& tcb) {
1097 tcb.cl_supp_feat = btif_storage_get_gatt_cl_supp_feat(tcb.peer_bda);
1098 // This is used to reset bit when robust caching is disabled
1099 if (!gatt_sr_is_robust_caching_enabled()) {
1100 tcb.cl_supp_feat &= ~BLE_GATT_CL_SUP_FEAT_CACHING_BITMASK;
1101 }
1102
1103 if (gatt_sr_is_cl_robust_caching_supported(tcb)) {
1104 Octet16 stored_hash = btif_storage_get_gatt_cl_db_hash(tcb.peer_bda);
1105 tcb.is_robust_cache_change_aware = (stored_hash == gatt_cb.database_hash);
1106 } else {
1107 // set default value for untrusted device
1108 tcb.is_robust_cache_change_aware = true;
1109 }
1110
1111 log::info("bda={}, cl_supp_feat=0x{:x}, aware={}", tcb.peer_bda, tcb.cl_supp_feat,
1112 tcb.is_robust_cache_change_aware);
1113 }
1114
1115 /*******************************************************************************
1116 *
1117 * Function gatt_sr_update_cl_status
1118 *
1119 * Description Update change-aware status for the remote device
1120 *
1121 * Returns none
1122 *
1123 ******************************************************************************/
gatt_sr_update_cl_status(tGATT_TCB & tcb,bool chg_aware)1124 void gatt_sr_update_cl_status(tGATT_TCB& tcb, bool chg_aware) {
1125 // if robust caching is not supported, do nothing
1126 if (!gatt_sr_is_cl_robust_caching_supported(tcb)) {
1127 return;
1128 }
1129
1130 // only when client status is changed from change-unaware to change-aware, we
1131 // can then store database hash into btif_storage
1132 if (!tcb.is_robust_cache_change_aware && chg_aware) {
1133 btif_storage_set_gatt_cl_db_hash(tcb.peer_bda, gatt_cb.database_hash);
1134 }
1135
1136 // only when the status is changed, print the log
1137 if (tcb.is_robust_cache_change_aware != chg_aware) {
1138 log::info("bda={}, chg_aware={}", tcb.peer_bda, chg_aware);
1139 }
1140
1141 tcb.is_robust_cache_change_aware = chg_aware;
1142 }
1143
1144 /* handle request for reading database hash */
gatt_sr_read_db_hash(tCONN_ID conn_id,tGATT_VALUE * p_value)1145 static tGATT_STATUS gatt_sr_read_db_hash(tCONN_ID conn_id, tGATT_VALUE* p_value) {
1146 log::info("conn_id=0x{:x}", conn_id);
1147
1148 uint8_t* p = p_value->value;
1149 Octet16& db_hash = gatt_cb.database_hash;
1150 ARRAY_TO_STREAM(p, db_hash.data(), (uint16_t)db_hash.size());
1151 p_value->len = (uint16_t)db_hash.size();
1152
1153 // Every time when database hash is requested, reset flag.
1154 uint8_t tcb_idx = gatt_get_tcb_idx(conn_id);
1155 gatt_sr_update_cl_status(gatt_cb.tcb[tcb_idx], /* chg_aware= */ true);
1156 return GATT_SUCCESS;
1157 }
1158
1159 /* handle request for reading client supported features */
gatt_sr_read_cl_supp_feat(tCONN_ID conn_id,tGATT_VALUE * p_value)1160 static tGATT_STATUS gatt_sr_read_cl_supp_feat(tCONN_ID conn_id, tGATT_VALUE* p_value) {
1161 // Get tcb info
1162 uint8_t tcb_idx = gatt_get_tcb_idx(conn_id);
1163 tGATT_TCB& tcb = gatt_cb.tcb[tcb_idx];
1164
1165 uint8_t* p = p_value->value;
1166 UINT8_TO_STREAM(p, tcb.cl_supp_feat);
1167 p_value->len = 1;
1168
1169 return GATT_SUCCESS;
1170 }
1171
1172 /* handle request for writing client supported features */
gatt_sr_write_cl_supp_feat(tCONN_ID conn_id,tGATT_WRITE_REQ * p_data)1173 static tGATT_STATUS gatt_sr_write_cl_supp_feat(tCONN_ID conn_id, tGATT_WRITE_REQ* p_data) {
1174 std::list<uint8_t> tmp;
1175 uint16_t len = p_data->len;
1176 uint8_t value, *p = p_data->value;
1177 // Read all octets into list
1178 while (len > 0) {
1179 STREAM_TO_UINT8(value, p);
1180 tmp.push_back(value);
1181 len--;
1182 }
1183 // Remove trailing zero octets
1184 while (!tmp.empty()) {
1185 if (tmp.back() != 0x00) {
1186 break;
1187 }
1188 tmp.pop_back();
1189 }
1190
1191 // Get tcb info
1192 uint8_t tcb_idx = gatt_get_tcb_idx(conn_id);
1193 tGATT_TCB& tcb = gatt_cb.tcb[tcb_idx];
1194
1195 std::list<uint8_t> feature_list;
1196 feature_list.push_back(tcb.cl_supp_feat);
1197
1198 // If input length is zero, return value_not_allowed
1199 if (tmp.empty()) {
1200 log::info("zero length, conn_id=0x{:x}, bda={}", conn_id, tcb.peer_bda);
1201 return GATT_VALUE_NOT_ALLOWED;
1202 }
1203 // if original length is longer than new one, it must be the bit reset case.
1204 if (feature_list.size() > tmp.size()) {
1205 log::info("shorter length, conn_id=0x{:x}, bda={}", conn_id, tcb.peer_bda);
1206 return GATT_VALUE_NOT_ALLOWED;
1207 }
1208 // new length is longer or equals to the original, need to check bits
1209 // one by one. Here we use bit-wise operation.
1210 // 1. Use XOR to locate the change bit, val_xor is the change bit mask
1211 // 2. Use AND for val_xor and *it_new to get val_and
1212 // 3. If val_and != val_xor, it means the change is from 1 to 0
1213 auto it_old = feature_list.cbegin();
1214 auto it_new = tmp.cbegin();
1215 for (; it_old != feature_list.cend(); it_old++, it_new++) {
1216 uint8_t val_xor = *it_old ^ *it_new;
1217 uint8_t val_and = val_xor & *it_new;
1218 if (val_and != val_xor) {
1219 log::info("bit cannot be reset, conn_id=0x{:x}, bda={}", conn_id, tcb.peer_bda);
1220 return GATT_VALUE_NOT_ALLOWED;
1221 }
1222 }
1223
1224 // get current robust caching status before setting new one
1225 bool curr_caching_state = gatt_sr_is_cl_robust_caching_supported(tcb);
1226
1227 tcb.cl_supp_feat = tmp.front();
1228 if (!gatt_sr_is_robust_caching_enabled()) {
1229 // remove robust caching bit
1230 tcb.cl_supp_feat &= ~BLE_GATT_CL_SUP_FEAT_CACHING_BITMASK;
1231 log::info("reset robust caching bit, conn_id=0x{:x}, bda={}", conn_id, tcb.peer_bda);
1232 }
1233 // TODO(hylo): save data as byte array
1234 btif_storage_set_gatt_cl_supp_feat(tcb.peer_bda, tcb.cl_supp_feat);
1235
1236 // get new robust caching status after setting new one
1237 bool new_caching_state = gatt_sr_is_cl_robust_caching_supported(tcb);
1238 // only when the first time robust caching request, print the log
1239 if (!curr_caching_state && new_caching_state) {
1240 log::info("robust caching enabled by client, conn_id=0x{:x}", conn_id);
1241 }
1242
1243 return GATT_SUCCESS;
1244 }
1245