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