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