• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2003-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 GATT client discovery procedures and cache
22  *  related functions.
23  *
24  ******************************************************************************/
25 
26 #define LOG_TAG "bt_bta_gattc"
27 
28 #include "bt_target.h"
29 
30 #include <errno.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <unistd.h>
34 
35 #include "bt_common.h"
36 #include "bta_gattc_int.h"
37 #include "bta_sys.h"
38 #include "btm_api.h"
39 #include "btm_ble_api.h"
40 #include "btm_int.h"
41 #include "osi/include/log.h"
42 #include "osi/include/osi.h"
43 #include "sdp_api.h"
44 #include "sdpdefs.h"
45 #include "utl.h"
46 
47 static void bta_gattc_cache_write(const RawAddress& server_bda,
48                                   uint16_t num_attr, tBTA_GATTC_NV_ATTR* attr);
49 static void bta_gattc_char_dscpt_disc_cmpl(uint16_t conn_id,
50                                            tBTA_GATTC_SERV* p_srvc_cb);
51 static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(
52     uint16_t conn_id, tBTA_GATTC_SERV* p_server_cb);
53 extern void bta_to_btif_uuid(bt_uuid_t* p_dest, tBT_UUID* p_src);
54 tBTA_GATTC_SERVICE* bta_gattc_find_matching_service(const list_t* services,
55                                                     uint16_t handle);
56 tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor_srcb(tBTA_GATTC_SERV* p_srcb,
57                                                      uint16_t handle);
58 tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic_srcb(
59     tBTA_GATTC_SERV* p_srcb, uint16_t handle);
60 
61 #define BTA_GATT_SDP_DB_SIZE 4096
62 
63 #define GATT_CACHE_PREFIX "/data/misc/bluetooth/gatt_cache_"
64 #define GATT_CACHE_VERSION 2
65 
bta_gattc_generate_cache_file_name(char * buffer,size_t buffer_len,const RawAddress & bda)66 static void bta_gattc_generate_cache_file_name(char* buffer, size_t buffer_len,
67                                                const RawAddress& bda) {
68   snprintf(buffer, buffer_len, "%s%02x%02x%02x%02x%02x%02x", GATT_CACHE_PREFIX,
69            bda.address[0], bda.address[1], bda.address[2], bda.address[3],
70            bda.address[4], bda.address[5]);
71 }
72 
73 /*****************************************************************************
74  *  Constants and data types
75  ****************************************************************************/
76 
77 typedef struct {
78   tSDP_DISCOVERY_DB* p_sdp_db;
79   uint16_t sdp_conn_id;
80 } tBTA_GATTC_CB_DATA;
81 
82 #if (BTA_GATT_DEBUG == TRUE)
83 static char* bta_gattc_attr_type[] = {
84     "I", /* Included Service */
85     "C", /* Characteristic */
86     "D"  /* Characteristic Descriptor */
87 };
88 /* utility functions */
89 
display_cache_attribute(void * data,void * context)90 bool display_cache_attribute(void* data, void* context) {
91   tBTA_GATTC_CACHE_ATTR* p_attr = data;
92   APPL_TRACE_ERROR("\t Attr handle[%d] uuid[0x%04x] type[%s] prop[0x%1x]",
93                    p_attr->handle, p_attr->uuid.uu.uuid16,
94                    bta_gattc_attr_type[p_attr->attr_type], p_attr->property);
95   return true;
96 }
97 
display_cache_service(void * data,void * context)98 bool display_cache_service(void* data, void* context) {
99   tBTA_GATTC_SERVICE* p_cur_srvc = data;
100   APPL_TRACE_ERROR("Service: handle[%d ~ %d] %s[0x%04x] inst[%d]",
101                    p_cur_srvc->s_handle, p_cur_srvc->e_handle,
102                    ((p_cur_srvc->uuid.len == 2) ? "uuid16" : "uuid128"),
103                    p_cur_srvc->uuid.uu.uuid16, p_cur_srvc->handle);
104 
105   if (p_cur_srvc->characteristics != NULL) {
106     list_foreach(p_cur_srvc->characteristics, display_cache_attribute, NULL);
107   }
108 
109   return true;
110 }
111 
112 /*******************************************************************************
113  *
114  * Function         bta_gattc_display_cache_server
115  *
116  * Description      debug function to display the server cache.
117  *
118  * Returns          none.
119  *
120  ******************************************************************************/
bta_gattc_display_cache_server(list_t * p_cache)121 static void bta_gattc_display_cache_server(list_t* p_cache) {
122   APPL_TRACE_ERROR("<================Start Server Cache =============>");
123   list_foreach(p_cache, display_cache_service, NULL);
124   APPL_TRACE_ERROR("<================End Server Cache =============>");
125   APPL_TRACE_ERROR(" ");
126 }
127 
128 /*******************************************************************************
129  *
130  * Function         bta_gattc_display_explore_record
131  *
132  * Description      debug function to display the exploration list
133  *
134  * Returns          none.
135  *
136  ******************************************************************************/
bta_gattc_display_explore_record(tBTA_GATTC_ATTR_REC * p_rec,uint8_t num_rec)137 static void bta_gattc_display_explore_record(tBTA_GATTC_ATTR_REC* p_rec,
138                                              uint8_t num_rec) {
139   uint8_t i;
140   tBTA_GATTC_ATTR_REC* pp = p_rec;
141 
142   APPL_TRACE_ERROR("<================Start Explore Queue =============>");
143   for (i = 0; i < num_rec; i++, pp++) {
144     APPL_TRACE_ERROR(
145         "\t rec[%d] uuid[0x%04x] s_handle[%d] e_handle[%d] is_primary[%d]",
146         i + 1, pp->uuid.uu.uuid16, pp->s_handle, pp->e_handle, pp->is_primary);
147   }
148   APPL_TRACE_ERROR("<================ End Explore Queue =============>");
149   APPL_TRACE_ERROR(" ");
150 }
151 #endif /* BTA_GATT_DEBUG == TRUE */
152 
153 /*******************************************************************************
154  *
155  * Function         bta_gattc_init_cache
156  *
157  * Description      Initialize the database cache and discovery related
158  *                  resources.
159  *
160  * Returns          status
161  *
162  ******************************************************************************/
bta_gattc_init_cache(tBTA_GATTC_SERV * p_srvc_cb)163 tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV* p_srvc_cb) {
164   if (p_srvc_cb->p_srvc_cache != NULL) {
165     list_free(p_srvc_cb->p_srvc_cache);
166     p_srvc_cb->p_srvc_cache = NULL;
167   }
168 
169   osi_free(p_srvc_cb->p_srvc_list);
170   p_srvc_cb->p_srvc_list =
171       (tBTA_GATTC_ATTR_REC*)osi_malloc(BTA_GATTC_ATTR_LIST_SIZE);
172   p_srvc_cb->total_srvc = 0;
173   p_srvc_cb->cur_srvc_idx = 0;
174   p_srvc_cb->cur_char_idx = 0;
175   p_srvc_cb->next_avail_idx = 0;
176 
177   return BTA_GATT_OK;
178 }
179 
characteristic_free(void * ptr)180 static void characteristic_free(void* ptr) {
181   tBTA_GATTC_CHARACTERISTIC* p_char = (tBTA_GATTC_CHARACTERISTIC*)ptr;
182   list_free(p_char->descriptors);
183   osi_free(p_char);
184 }
185 
service_free(void * ptr)186 static void service_free(void* ptr) {
187   tBTA_GATTC_SERVICE* srvc = (tBTA_GATTC_SERVICE*)ptr;
188   list_free(srvc->characteristics);
189   list_free(srvc->included_svc);
190   osi_free(srvc);
191 }
192 
193 /*******************************************************************************
194  *
195  * Function         bta_gattc_add_srvc_to_cache
196  *
197  * Description      Add a service into database cache.
198  *
199  * Returns          status
200  *
201  ******************************************************************************/
bta_gattc_add_srvc_to_cache(tBTA_GATTC_SERV * p_srvc_cb,uint16_t s_handle,uint16_t e_handle,tBT_UUID * p_uuid,bool is_primary)202 static tBTA_GATT_STATUS bta_gattc_add_srvc_to_cache(tBTA_GATTC_SERV* p_srvc_cb,
203                                                     uint16_t s_handle,
204                                                     uint16_t e_handle,
205                                                     tBT_UUID* p_uuid,
206                                                     bool is_primary) {
207 #if (BTA_GATT_DEBUG == TRUE)
208   APPL_TRACE_DEBUG("Add a service into Service");
209 #endif
210 
211   tBTA_GATTC_SERVICE* p_new_srvc =
212       (tBTA_GATTC_SERVICE*)osi_malloc(sizeof(tBTA_GATTC_SERVICE));
213 
214   /* update service information */
215   p_new_srvc->s_handle = s_handle;
216   p_new_srvc->e_handle = e_handle;
217   p_new_srvc->is_primary = is_primary;
218   memcpy(&p_new_srvc->uuid, p_uuid, sizeof(tBT_UUID));
219   p_new_srvc->handle = s_handle;
220   p_new_srvc->characteristics = list_new(characteristic_free);
221   p_new_srvc->included_svc = list_new(osi_free);
222 
223   if (p_srvc_cb->p_srvc_cache == NULL) {
224     p_srvc_cb->p_srvc_cache = list_new(service_free);
225   }
226 
227   list_append(p_srvc_cb->p_srvc_cache, p_new_srvc);
228   return BTA_GATT_OK;
229 }
230 
bta_gattc_add_char_to_cache(tBTA_GATTC_SERV * p_srvc_cb,uint16_t attr_handle,uint16_t value_handle,tBT_UUID * p_uuid,uint8_t property)231 static tBTA_GATT_STATUS bta_gattc_add_char_to_cache(tBTA_GATTC_SERV* p_srvc_cb,
232                                                     uint16_t attr_handle,
233                                                     uint16_t value_handle,
234                                                     tBT_UUID* p_uuid,
235                                                     uint8_t property) {
236 #if (BTA_GATT_DEBUG == TRUE)
237   APPL_TRACE_DEBUG("%s: Add a characteristic into Service", __func__);
238   APPL_TRACE_DEBUG("handle=%d uuid16=0x%x property=0x%x", value_handle,
239                    p_uuid->uu.uuid16, property);
240 #endif
241 
242   tBTA_GATTC_SERVICE* service =
243       bta_gattc_find_matching_service(p_srvc_cb->p_srvc_cache, attr_handle);
244   if (!service) {
245     APPL_TRACE_ERROR(
246         "Illegal action to add char/descr/incl srvc for non-existing service!");
247     return GATT_WRONG_STATE;
248   }
249 
250   /* TODO(jpawlowski): We should use attribute handle, not value handle to refer
251      to characteristic.
252      This is just a temporary workaround.
253   */
254   if (service->e_handle < value_handle) service->e_handle = value_handle;
255 
256   tBTA_GATTC_CHARACTERISTIC* characteristic =
257       (tBTA_GATTC_CHARACTERISTIC*)osi_malloc(sizeof(tBTA_GATTC_CHARACTERISTIC));
258 
259   characteristic->handle = value_handle;
260   characteristic->properties = property;
261   characteristic->descriptors = list_new(osi_free);
262   memcpy(&characteristic->uuid, p_uuid, sizeof(tBT_UUID));
263 
264   characteristic->service = service;
265   list_append(service->characteristics, characteristic);
266 
267   return BTA_GATT_OK;
268 }
269 
270 /*******************************************************************************
271  *
272  * Function         bta_gattc_add_attr_to_cache
273  *
274  * Description      Add an attribute into database cache buffer.
275  *
276  * Returns          status
277  *
278  ******************************************************************************/
bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV * p_srvc_cb,uint16_t handle,tBT_UUID * p_uuid,uint8_t property,uint16_t incl_srvc_s_handle,tBTA_GATTC_ATTR_TYPE type)279 static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(
280     tBTA_GATTC_SERV* p_srvc_cb, uint16_t handle, tBT_UUID* p_uuid,
281     uint8_t property, uint16_t incl_srvc_s_handle, tBTA_GATTC_ATTR_TYPE type) {
282 #if (BTA_GATT_DEBUG == TRUE)
283   APPL_TRACE_DEBUG("%s: Add a [%s] into Service", __func__,
284                    bta_gattc_attr_type[type]);
285   APPL_TRACE_DEBUG("handle=%d uuid16=0x%x property=0x%x type=%d", handle,
286                    p_uuid->uu.uuid16, property, type);
287 #endif
288 
289   tBTA_GATTC_SERVICE* service =
290       bta_gattc_find_matching_service(p_srvc_cb->p_srvc_cache, handle);
291   if (!service) {
292     APPL_TRACE_ERROR(
293         "Illegal action to add char/descr/incl srvc for non-existing service!");
294     return GATT_WRONG_STATE;
295   }
296 
297   if (type == BTA_GATTC_ATTR_TYPE_INCL_SRVC) {
298     tBTA_GATTC_INCLUDED_SVC* isvc =
299         (tBTA_GATTC_INCLUDED_SVC*)osi_malloc(sizeof(tBTA_GATTC_INCLUDED_SVC));
300 
301     isvc->handle = handle;
302     memcpy(&isvc->uuid, p_uuid, sizeof(tBT_UUID));
303 
304     isvc->owning_service = service;
305     isvc->included_service = bta_gattc_find_matching_service(
306         p_srvc_cb->p_srvc_cache, incl_srvc_s_handle);
307     if (!isvc->included_service) {
308       APPL_TRACE_ERROR(
309           "%s: Illegal action to add non-existing included service!", __func__);
310       osi_free(isvc);
311       return GATT_WRONG_STATE;
312     }
313 
314     list_append(service->included_svc, isvc);
315   } else if (type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) {
316     tBTA_GATTC_DESCRIPTOR* descriptor =
317         (tBTA_GATTC_DESCRIPTOR*)osi_malloc(sizeof(tBTA_GATTC_DESCRIPTOR));
318 
319     descriptor->handle = handle;
320     memcpy(&descriptor->uuid, p_uuid, sizeof(tBT_UUID));
321 
322     if (service->characteristics == NULL ||
323         list_is_empty(service->characteristics)) {
324       APPL_TRACE_ERROR(
325           "%s: Illegal action to add descriptor before adding a "
326           "characteristic!",
327           __func__);
328       osi_free(descriptor);
329       return GATT_WRONG_STATE;
330     }
331 
332     tBTA_GATTC_CHARACTERISTIC* char_node =
333         (tBTA_GATTC_CHARACTERISTIC*)list_back(service->characteristics);
334 
335     descriptor->characteristic = char_node;
336     list_append(char_node->descriptors, descriptor);
337   }
338   return BTA_GATT_OK;
339 }
340 
341 /*******************************************************************************
342  *
343  * Function         bta_gattc_get_disc_range
344  *
345  * Description      get discovery stating and ending handle range.
346  *
347  * Returns          None.
348  *
349  ******************************************************************************/
bta_gattc_get_disc_range(tBTA_GATTC_SERV * p_srvc_cb,uint16_t * p_s_hdl,uint16_t * p_e_hdl,bool is_srvc)350 void bta_gattc_get_disc_range(tBTA_GATTC_SERV* p_srvc_cb, uint16_t* p_s_hdl,
351                               uint16_t* p_e_hdl, bool is_srvc) {
352   tBTA_GATTC_ATTR_REC* p_rec = NULL;
353 
354   if (is_srvc) {
355     p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
356     *p_s_hdl = p_rec->s_handle;
357   } else {
358     p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
359     *p_s_hdl = p_rec->s_handle + 1;
360   }
361 
362   *p_e_hdl = p_rec->e_handle;
363 #if (BTA_GATT_DEBUG == TRUE)
364   APPL_TRACE_DEBUG("discover range [%d ~ %d]", p_rec->s_handle,
365                    p_rec->e_handle);
366 #endif
367   return;
368 }
369 /*******************************************************************************
370  *
371  * Function         bta_gattc_discover_pri_service
372  *
373  * Description      Start primary service discovery
374  *
375  * Returns          status of the operation.
376  *
377  ******************************************************************************/
bta_gattc_discover_pri_service(uint16_t conn_id,tBTA_GATTC_SERV * p_server_cb,uint8_t disc_type)378 tBTA_GATT_STATUS bta_gattc_discover_pri_service(uint16_t conn_id,
379                                                 tBTA_GATTC_SERV* p_server_cb,
380                                                 uint8_t disc_type) {
381   tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
382   tBTA_GATT_STATUS status = BTA_GATT_ERROR;
383 
384   if (p_clcb) {
385     if (p_clcb->transport == BTA_TRANSPORT_LE)
386       status = bta_gattc_discover_procedure(conn_id, p_server_cb, disc_type);
387     else
388       status = bta_gattc_sdp_service_disc(conn_id, p_server_cb);
389   }
390 
391   return status;
392 }
393 /*******************************************************************************
394  *
395  * Function         bta_gattc_discover_procedure
396  *
397  * Description      Start a particular type of discovery procedure on server.
398  *
399  * Returns          status of the operation.
400  *
401  ******************************************************************************/
bta_gattc_discover_procedure(uint16_t conn_id,tBTA_GATTC_SERV * p_server_cb,uint8_t disc_type)402 tBTA_GATT_STATUS bta_gattc_discover_procedure(uint16_t conn_id,
403                                               tBTA_GATTC_SERV* p_server_cb,
404                                               uint8_t disc_type) {
405   tGATT_DISC_PARAM param;
406   bool is_service = true;
407 
408   memset(&param, 0, sizeof(tGATT_DISC_PARAM));
409 
410   if (disc_type == GATT_DISC_SRVC_ALL || disc_type == GATT_DISC_SRVC_BY_UUID) {
411     param.s_handle = 1;
412     param.e_handle = 0xFFFF;
413   } else {
414     if (disc_type == GATT_DISC_CHAR_DSCPT) is_service = false;
415 
416     bta_gattc_get_disc_range(p_server_cb, &param.s_handle, &param.e_handle,
417                              is_service);
418 
419     if (param.s_handle > param.e_handle) {
420       return GATT_ERROR;
421     }
422   }
423   return GATTC_Discover(conn_id, disc_type, &param);
424 }
425 /*******************************************************************************
426  *
427  * Function         bta_gattc_start_disc_include_srvc
428  *
429  * Description      Start discovery for included service
430  *
431  * Returns          status of the operation.
432  *
433  ******************************************************************************/
bta_gattc_start_disc_include_srvc(uint16_t conn_id,tBTA_GATTC_SERV * p_srvc_cb)434 tBTA_GATT_STATUS bta_gattc_start_disc_include_srvc(uint16_t conn_id,
435                                                    tBTA_GATTC_SERV* p_srvc_cb) {
436   return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_INC_SRVC);
437 }
438 /*******************************************************************************
439  *
440  * Function         bta_gattc_start_disc_char
441  *
442  * Description      Start discovery for characteristic
443  *
444  * Returns          status of the operation.
445  *
446  ******************************************************************************/
bta_gattc_start_disc_char(uint16_t conn_id,tBTA_GATTC_SERV * p_srvc_cb)447 tBTA_GATT_STATUS bta_gattc_start_disc_char(uint16_t conn_id,
448                                            tBTA_GATTC_SERV* p_srvc_cb) {
449   p_srvc_cb->total_char = 0;
450 
451   return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR);
452 }
453 /*******************************************************************************
454  *
455  * Function         bta_gattc_start_disc_char_dscp
456  *
457  * Description      Start discovery for characteristic descriptor
458  *
459  * Returns          none.
460  *
461  ******************************************************************************/
bta_gattc_start_disc_char_dscp(uint16_t conn_id,tBTA_GATTC_SERV * p_srvc_cb)462 void bta_gattc_start_disc_char_dscp(uint16_t conn_id,
463                                     tBTA_GATTC_SERV* p_srvc_cb) {
464   APPL_TRACE_DEBUG("starting discover characteristics descriptor");
465 
466   if (bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR_DSCPT) !=
467       0)
468     bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
469 }
470 /*******************************************************************************
471  *
472  * Function         bta_gattc_explore_srvc
473  *
474  * Description      process the service discovery complete event
475  *
476  * Returns          status
477  *
478  ******************************************************************************/
bta_gattc_explore_srvc(uint16_t conn_id,tBTA_GATTC_SERV * p_srvc_cb)479 static void bta_gattc_explore_srvc(uint16_t conn_id,
480                                    tBTA_GATTC_SERV* p_srvc_cb) {
481   tBTA_GATTC_ATTR_REC* p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
482   tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
483 
484   APPL_TRACE_DEBUG("Start service discovery: srvc_idx = %d",
485                    p_srvc_cb->cur_srvc_idx);
486 
487   p_srvc_cb->cur_char_idx = p_srvc_cb->next_avail_idx = p_srvc_cb->total_srvc;
488 
489   if (p_clcb == NULL) {
490     APPL_TRACE_ERROR("unknown connection ID");
491     return;
492   }
493   /* start expore a service if there is service not been explored */
494   if (p_srvc_cb->cur_srvc_idx < p_srvc_cb->total_srvc) {
495     /* add the first service into cache */
496     if (bta_gattc_add_srvc_to_cache(p_srvc_cb, p_rec->s_handle, p_rec->e_handle,
497                                     &p_rec->uuid, p_rec->is_primary) == 0) {
498       /* start discovering included services */
499       bta_gattc_start_disc_include_srvc(conn_id, p_srvc_cb);
500       return;
501     }
502   }
503   /* no service found at all, the end of server discovery*/
504   LOG_WARN(LOG_TAG, "%s no more services found", __func__);
505 
506 #if (BTA_GATT_DEBUG == TRUE)
507   bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache);
508 #endif
509   /* save cache to NV */
510   p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE;
511 
512   if (btm_sec_is_a_bonded_dev(p_srvc_cb->server_bda)) {
513     bta_gattc_cache_save(p_clcb->p_srcb, p_clcb->bta_conn_id);
514   }
515 
516   bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_OK);
517 }
518 /*******************************************************************************
519  *
520  * Function         bta_gattc_incl_srvc_disc_cmpl
521  *
522  * Description      process the relationship discovery complete event
523  *
524  * Returns          status
525  *
526  ******************************************************************************/
bta_gattc_incl_srvc_disc_cmpl(uint16_t conn_id,tBTA_GATTC_SERV * p_srvc_cb)527 static void bta_gattc_incl_srvc_disc_cmpl(uint16_t conn_id,
528                                           tBTA_GATTC_SERV* p_srvc_cb) {
529   p_srvc_cb->cur_char_idx = p_srvc_cb->total_srvc;
530 
531   /* start discoverying characteristic */
532   bta_gattc_start_disc_char(conn_id, p_srvc_cb);
533 }
534 /*******************************************************************************
535  *
536  * Function         bta_gattc_char_disc_cmpl
537  *
538  * Description      process the characteristic discovery complete event
539  *
540  * Returns          status
541  *
542  ******************************************************************************/
bta_gattc_char_disc_cmpl(uint16_t conn_id,tBTA_GATTC_SERV * p_srvc_cb)543 static void bta_gattc_char_disc_cmpl(uint16_t conn_id,
544                                      tBTA_GATTC_SERV* p_srvc_cb) {
545   tBTA_GATTC_ATTR_REC* p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
546 
547   /* if there are characteristic needs to be explored */
548   if (p_srvc_cb->total_char > 0) {
549     /* add the first characteristic into cache */
550     bta_gattc_add_char_to_cache(p_srvc_cb, p_rec->char_decl_handle,
551                                 p_rec->s_handle, &p_rec->uuid, p_rec->property);
552 
553     /* start discoverying characteristic descriptor , if failed, disc for next
554      * char*/
555     bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
556   } else /* otherwise start with next service */
557   {
558     p_srvc_cb->cur_srvc_idx++;
559 
560     bta_gattc_explore_srvc(conn_id, p_srvc_cb);
561   }
562 }
563 /*******************************************************************************
564  *
565  * Function         bta_gattc_char_dscpt_disc_cmpl
566  *
567  * Description      process the char descriptor discovery complete event
568  *
569  * Returns          status
570  *
571  ******************************************************************************/
bta_gattc_char_dscpt_disc_cmpl(uint16_t conn_id,tBTA_GATTC_SERV * p_srvc_cb)572 static void bta_gattc_char_dscpt_disc_cmpl(uint16_t conn_id,
573                                            tBTA_GATTC_SERV* p_srvc_cb) {
574   tBTA_GATTC_ATTR_REC* p_rec = NULL;
575 
576   if (--p_srvc_cb->total_char > 0) {
577     p_rec = p_srvc_cb->p_srvc_list + (++p_srvc_cb->cur_char_idx);
578     /* add the next characteristic into cache */
579     bta_gattc_add_char_to_cache(p_srvc_cb, p_rec->char_decl_handle,
580                                 p_rec->s_handle, &p_rec->uuid, p_rec->property);
581 
582     /* start discoverying next characteristic for char descriptor */
583     bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
584   } else
585   /* all characteristic has been explored, start with next service if any */
586   {
587 #if (BTA_GATT_DEBUG == TRUE)
588     APPL_TRACE_ERROR("all char has been explored");
589 #endif
590     p_srvc_cb->cur_srvc_idx++;
591     bta_gattc_explore_srvc(conn_id, p_srvc_cb);
592   }
593 }
bta_gattc_srvc_in_list(tBTA_GATTC_SERV * p_srvc_cb,uint16_t s_handle,uint16_t e_handle,UNUSED_ATTR tBT_UUID uuid)594 static bool bta_gattc_srvc_in_list(tBTA_GATTC_SERV* p_srvc_cb,
595                                    uint16_t s_handle, uint16_t e_handle,
596                                    UNUSED_ATTR tBT_UUID uuid) {
597   tBTA_GATTC_ATTR_REC* p_rec = NULL;
598   uint8_t i;
599   bool exist_srvc = false;
600 
601   if (!GATT_HANDLE_IS_VALID(s_handle) || !GATT_HANDLE_IS_VALID(e_handle)) {
602     APPL_TRACE_ERROR("invalid included service handle: [0x%04x ~ 0x%04x]",
603                      s_handle, e_handle);
604     exist_srvc = true;
605   } else {
606     for (i = 0; i < p_srvc_cb->next_avail_idx; i++) {
607       p_rec = p_srvc_cb->p_srvc_list + i;
608 
609       /* a new service should not have any overlap with other service handle
610        * range */
611       if (p_rec->s_handle == s_handle || p_rec->e_handle == e_handle) {
612         exist_srvc = true;
613         break;
614       }
615     }
616   }
617   return exist_srvc;
618 }
619 /*******************************************************************************
620  *
621  * Function         bta_gattc_add_srvc_to_list
622  *
623  * Description      Add a service into explore pending list
624  *
625  * Returns          status
626  *
627  ******************************************************************************/
bta_gattc_add_srvc_to_list(tBTA_GATTC_SERV * p_srvc_cb,uint16_t s_handle,uint16_t e_handle,tBT_UUID uuid,bool is_primary)628 static tBTA_GATT_STATUS bta_gattc_add_srvc_to_list(tBTA_GATTC_SERV* p_srvc_cb,
629                                                    uint16_t s_handle,
630                                                    uint16_t e_handle,
631                                                    tBT_UUID uuid,
632                                                    bool is_primary) {
633   tBTA_GATTC_ATTR_REC* p_rec = NULL;
634   tBTA_GATT_STATUS status = BTA_GATT_OK;
635 
636   if (p_srvc_cb->p_srvc_list &&
637       p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR) {
638     p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;
639 
640     APPL_TRACE_DEBUG("%s handle=%d, service type=0x%04x", __func__, s_handle,
641                      uuid.uu.uuid16);
642 
643     p_rec->s_handle = s_handle;
644     p_rec->e_handle = e_handle;
645     p_rec->is_primary = is_primary;
646     memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
647 
648     p_srvc_cb->total_srvc++;
649     p_srvc_cb->next_avail_idx++;
650   } else { /* allocate bigger buffer ?? */
651     status = GATT_DB_FULL;
652 
653     APPL_TRACE_ERROR("service not added, no resources or wrong state");
654   }
655   return status;
656 }
657 /*******************************************************************************
658  *
659  * Function         bta_gattc_add_char_to_list
660  *
661  * Description      Add a characteristic into explore pending list
662  *
663  * Returns          status
664  *
665  ******************************************************************************/
bta_gattc_add_char_to_list(tBTA_GATTC_SERV * p_srvc_cb,uint16_t decl_handle,uint16_t value_handle,tBT_UUID uuid,uint8_t property)666 static tBTA_GATT_STATUS bta_gattc_add_char_to_list(tBTA_GATTC_SERV* p_srvc_cb,
667                                                    uint16_t decl_handle,
668                                                    uint16_t value_handle,
669                                                    tBT_UUID uuid,
670                                                    uint8_t property) {
671   tBTA_GATTC_ATTR_REC* p_rec = NULL;
672   tBTA_GATT_STATUS status = BTA_GATT_OK;
673 
674   if (p_srvc_cb->p_srvc_list == NULL) {
675     APPL_TRACE_ERROR("No service available, unexpected char discovery result");
676     status = BTA_GATT_INTERNAL_ERROR;
677   } else if (p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR) {
678     p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;
679 
680     p_srvc_cb->total_char++;
681 
682     p_rec->s_handle = value_handle;
683     p_rec->char_decl_handle = decl_handle;
684     p_rec->property = property;
685     p_rec->e_handle =
686         (p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx)->e_handle;
687     memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
688 
689     /* update the endind handle of pervious characteristic if available */
690     if (p_srvc_cb->total_char > 1) {
691       p_rec -= 1;
692       p_rec->e_handle = decl_handle - 1;
693     }
694     p_srvc_cb->next_avail_idx++;
695   } else {
696     APPL_TRACE_ERROR("char not added, no resources");
697     /* allocate bigger buffer ?? */
698     status = BTA_GATT_DB_FULL;
699   }
700   return status;
701 }
702 
703 /*******************************************************************************
704  *
705  * Function         bta_gattc_sdp_callback
706  *
707  * Description      Process the discovery result from sdp
708  *
709  * Returns          void
710  *
711  ******************************************************************************/
bta_gattc_sdp_callback(uint16_t sdp_status,void * user_data)712 void bta_gattc_sdp_callback(uint16_t sdp_status, void* user_data) {
713   tSDP_DISC_REC* p_sdp_rec = NULL;
714   tBT_UUID service_uuid;
715   tSDP_PROTOCOL_ELEM pe;
716   uint16_t start_handle = 0, end_handle = 0;
717   tBTA_GATTC_CB_DATA* cb_data = (tBTA_GATTC_CB_DATA*)user_data;
718   tBTA_GATTC_SERV* p_srvc_cb = bta_gattc_find_scb_by_cid(cb_data->sdp_conn_id);
719 
720   if (((sdp_status == SDP_SUCCESS) || (sdp_status == SDP_DB_FULL)) &&
721       p_srvc_cb != NULL) {
722     do {
723       /* find a service record, report it */
724       p_sdp_rec = SDP_FindServiceInDb(cb_data->p_sdp_db, 0, p_sdp_rec);
725       if (p_sdp_rec) {
726         if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid)) {
727           if (SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_ATT,
728                                             &pe)) {
729             start_handle = (uint16_t)pe.params[0];
730             end_handle = (uint16_t)pe.params[1];
731 
732 #if (BTA_GATT_DEBUG == TRUE)
733             APPL_TRACE_EVENT(
734                 "Found ATT service [0x%04x] handle[0x%04x ~ 0x%04x]",
735                 service_uuid.uu.uuid16, start_handle, end_handle);
736 #endif
737 
738             if (GATT_HANDLE_IS_VALID(start_handle) &&
739                 GATT_HANDLE_IS_VALID(end_handle) && p_srvc_cb != NULL) {
740               /* discover services result, add services into a service list */
741               bta_gattc_add_srvc_to_list(p_srvc_cb, start_handle, end_handle,
742                                          service_uuid, true);
743             } else {
744               APPL_TRACE_ERROR("invalid start_handle = %d end_handle = %d",
745                                start_handle, end_handle);
746             }
747           }
748         }
749       }
750     } while (p_sdp_rec);
751   }
752 
753   if (p_srvc_cb != NULL) {
754     /* start discover primary service */
755     bta_gattc_explore_srvc(cb_data->sdp_conn_id, p_srvc_cb);
756   } else {
757     APPL_TRACE_ERROR("GATT service discovery is done on unknown connection");
758   }
759 
760   /* both were allocated in bta_gattc_sdp_service_disc */
761   osi_free(cb_data->p_sdp_db);
762   osi_free(cb_data);
763 }
764 /*******************************************************************************
765  *
766  * Function         bta_gattc_sdp_service_disc
767  *
768  * Description      Start DSP Service Discovert
769  *
770  * Returns          void
771  *
772  ******************************************************************************/
bta_gattc_sdp_service_disc(uint16_t conn_id,tBTA_GATTC_SERV * p_server_cb)773 static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(
774     uint16_t conn_id, tBTA_GATTC_SERV* p_server_cb) {
775   tSDP_UUID uuid;
776   uint16_t num_attrs = 2;
777   uint16_t attr_list[2];
778 
779   memset(&uuid, 0, sizeof(tSDP_UUID));
780 
781   uuid.len = LEN_UUID_16;
782   uuid.uu.uuid16 = UUID_PROTOCOL_ATT;
783 
784   /*
785    * On success, cb_data will be freed inside bta_gattc_sdp_callback,
786    * otherwise it will be freed within this function.
787    */
788   tBTA_GATTC_CB_DATA* cb_data =
789       (tBTA_GATTC_CB_DATA*)osi_malloc(sizeof(tBTA_GATTC_CB_DATA));
790 
791   cb_data->p_sdp_db = (tSDP_DISCOVERY_DB*)osi_malloc(BTA_GATT_SDP_DB_SIZE);
792   attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
793   attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
794 
795   SDP_InitDiscoveryDb(cb_data->p_sdp_db, BTA_GATT_SDP_DB_SIZE, 1, &uuid,
796                       num_attrs, attr_list);
797 
798   if (!SDP_ServiceSearchAttributeRequest2(p_server_cb->server_bda,
799                                           cb_data->p_sdp_db,
800                                           &bta_gattc_sdp_callback, cb_data)) {
801     osi_free(cb_data->p_sdp_db);
802     osi_free(cb_data);
803     return BTA_GATT_ERROR;
804   }
805 
806   cb_data->sdp_conn_id = conn_id;
807   return BTA_GATT_OK;
808 }
809 /*******************************************************************************
810  *
811  * Function         bta_gattc_disc_res_cback
812  *                  bta_gattc_disc_cmpl_cback
813  *
814  * Description      callback functions to GATT client stack.
815  *
816  * Returns          void
817  *
818  ******************************************************************************/
bta_gattc_disc_res_cback(uint16_t conn_id,tGATT_DISC_TYPE disc_type,tGATT_DISC_RES * p_data)819 void bta_gattc_disc_res_cback(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
820                               tGATT_DISC_RES* p_data) {
821   tBTA_GATTC_SERV* p_srvc_cb = NULL;
822   bool pri_srvc;
823   tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
824 
825   p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
826 
827   if (p_srvc_cb != NULL && p_clcb != NULL &&
828       p_clcb->state == BTA_GATTC_DISCOVER_ST) {
829     switch (disc_type) {
830       case GATT_DISC_SRVC_ALL:
831         /* discover services result, add services into a service list */
832         bta_gattc_add_srvc_to_list(
833             p_srvc_cb, p_data->handle, p_data->value.group_value.e_handle,
834             p_data->value.group_value.service_type, true);
835 
836         break;
837       case GATT_DISC_SRVC_BY_UUID:
838         bta_gattc_add_srvc_to_list(
839             p_srvc_cb, p_data->handle, p_data->value.group_value.e_handle,
840             p_data->value.group_value.service_type, true);
841         break;
842 
843       case GATT_DISC_INC_SRVC:
844         /* add included service into service list if it's secondary or it never
845            showed up
846            in the primary service search */
847         pri_srvc = bta_gattc_srvc_in_list(
848             p_srvc_cb, p_data->value.incl_service.s_handle,
849             p_data->value.incl_service.e_handle,
850             p_data->value.incl_service.service_type);
851 
852         if (!pri_srvc)
853           bta_gattc_add_srvc_to_list(
854               p_srvc_cb, p_data->value.incl_service.s_handle,
855               p_data->value.incl_service.e_handle,
856               p_data->value.incl_service.service_type, false);
857         /* add into database */
858         bta_gattc_add_attr_to_cache(
859             p_srvc_cb, p_data->handle, &p_data->value.incl_service.service_type,
860             pri_srvc, p_data->value.incl_service.s_handle,
861             BTA_GATTC_ATTR_TYPE_INCL_SRVC);
862         break;
863 
864       case GATT_DISC_CHAR:
865         /* add char value into database */
866         bta_gattc_add_char_to_list(p_srvc_cb, p_data->handle,
867                                    p_data->value.dclr_value.val_handle,
868                                    p_data->value.dclr_value.char_uuid,
869                                    p_data->value.dclr_value.char_prop);
870         break;
871 
872       case GATT_DISC_CHAR_DSCPT:
873         bta_gattc_add_attr_to_cache(p_srvc_cb, p_data->handle, &p_data->type, 0,
874                                     0 /* incl_srvc_handle */,
875                                     BTA_GATTC_ATTR_TYPE_CHAR_DESCR);
876         break;
877     }
878   }
879 }
bta_gattc_disc_cmpl_cback(uint16_t conn_id,tGATT_DISC_TYPE disc_type,tGATT_STATUS status)880 void bta_gattc_disc_cmpl_cback(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
881                                tGATT_STATUS status) {
882   tBTA_GATTC_SERV* p_srvc_cb;
883   tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
884 
885   if (p_clcb && (status != GATT_SUCCESS || p_clcb->status != GATT_SUCCESS)) {
886     if (status == GATT_SUCCESS) p_clcb->status = status;
887     bta_gattc_sm_execute(p_clcb, BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
888     return;
889   }
890   p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
891 
892   if (p_srvc_cb != NULL) {
893     switch (disc_type) {
894       case GATT_DISC_SRVC_ALL:
895       case GATT_DISC_SRVC_BY_UUID:
896 #if (BTA_GATT_DEBUG == TRUE)
897         bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list,
898                                          p_srvc_cb->next_avail_idx);
899 #endif
900         bta_gattc_explore_srvc(conn_id, p_srvc_cb);
901         break;
902 
903       case GATT_DISC_INC_SRVC:
904         bta_gattc_incl_srvc_disc_cmpl(conn_id, p_srvc_cb);
905 
906         break;
907 
908       case GATT_DISC_CHAR:
909 #if (BTA_GATT_DEBUG == TRUE)
910         bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list,
911                                          p_srvc_cb->next_avail_idx);
912 #endif
913         bta_gattc_char_disc_cmpl(conn_id, p_srvc_cb);
914         break;
915 
916       case GATT_DISC_CHAR_DSCPT:
917         bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
918         break;
919     }
920   }
921 }
922 
923 /*******************************************************************************
924  *
925  * Function         bta_gattc_search_service
926  *
927  * Description      search local cache for matching service record.
928  *
929  * Returns          false if map can not be found.
930  *
931  ******************************************************************************/
bta_gattc_search_service(tBTA_GATTC_CLCB * p_clcb,tBT_UUID * p_uuid)932 void bta_gattc_search_service(tBTA_GATTC_CLCB* p_clcb, tBT_UUID* p_uuid) {
933   tBTA_GATTC cb_data;
934 
935   if (!p_clcb->p_srcb->p_srvc_cache ||
936       list_is_empty(p_clcb->p_srcb->p_srvc_cache))
937     return;
938 
939   for (list_node_t* sn = list_begin(p_clcb->p_srcb->p_srvc_cache);
940        sn != list_end(p_clcb->p_srcb->p_srvc_cache); sn = list_next(sn)) {
941     tBTA_GATTC_SERVICE* p_cache = (tBTA_GATTC_SERVICE*)list_node(sn);
942 
943     if (!bta_gattc_uuid_compare(p_uuid, &p_cache->uuid, false)) continue;
944 
945 #if (BTA_GATT_DEBUG == TRUE)
946     APPL_TRACE_DEBUG("found service [0x%04x], inst[%d] handle [%d]",
947                      p_cache->uuid.uu.uuid16, p_cache->handle,
948                      p_cache->s_handle);
949 #endif
950     if (!p_clcb->p_rcb->p_cback) continue;
951 
952     memset(&cb_data, 0, sizeof(tBTA_GATTC));
953 
954     cb_data.srvc_res.conn_id = p_clcb->bta_conn_id;
955     cb_data.srvc_res.service_uuid.inst_id = p_cache->handle;
956     memcpy(&cb_data.srvc_res.service_uuid.uuid, &p_cache->uuid,
957            sizeof(tBTA_GATT_ID));
958 
959     (*p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_RES_EVT, &cb_data);
960   }
961 }
962 
bta_gattc_get_services_srcb(tBTA_GATTC_SERV * p_srcb)963 list_t* bta_gattc_get_services_srcb(tBTA_GATTC_SERV* p_srcb) {
964   if (!p_srcb || !p_srcb->p_srvc_cache || list_is_empty(p_srcb->p_srvc_cache))
965     return NULL;
966 
967   return p_srcb->p_srvc_cache;
968 }
969 
bta_gattc_get_services(uint16_t conn_id)970 const list_t* bta_gattc_get_services(uint16_t conn_id) {
971   tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
972 
973   if (p_clcb == NULL) return NULL;
974 
975   tBTA_GATTC_SERV* p_srcb = p_clcb->p_srcb;
976 
977   return bta_gattc_get_services_srcb(p_srcb);
978 }
979 
bta_gattc_find_matching_service(const list_t * services,uint16_t handle)980 tBTA_GATTC_SERVICE* bta_gattc_find_matching_service(const list_t* services,
981                                                     uint16_t handle) {
982   if (!services || list_is_empty(services)) return NULL;
983 
984   for (list_node_t* sn = list_begin(services); sn != list_end(services);
985        sn = list_next(sn)) {
986     tBTA_GATTC_SERVICE* service = (tBTA_GATTC_SERVICE*)list_node(sn);
987 
988     if (handle >= service->s_handle && handle <= service->e_handle)
989       return service;
990   }
991 
992   return NULL;
993 }
994 
bta_gattc_get_service_for_handle_srcb(tBTA_GATTC_SERV * p_srcb,uint16_t handle)995 const tBTA_GATTC_SERVICE* bta_gattc_get_service_for_handle_srcb(
996     tBTA_GATTC_SERV* p_srcb, uint16_t handle) {
997   const list_t* services = bta_gattc_get_services_srcb(p_srcb);
998 
999   return bta_gattc_find_matching_service(services, handle);
1000 }
1001 
bta_gattc_get_service_for_handle(uint16_t conn_id,uint16_t handle)1002 const tBTA_GATTC_SERVICE* bta_gattc_get_service_for_handle(uint16_t conn_id,
1003                                                            uint16_t handle) {
1004   const list_t* services = bta_gattc_get_services(conn_id);
1005 
1006   return bta_gattc_find_matching_service(services, handle);
1007 }
1008 
bta_gattc_get_characteristic_srcb(tBTA_GATTC_SERV * p_srcb,uint16_t handle)1009 tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic_srcb(
1010     tBTA_GATTC_SERV* p_srcb, uint16_t handle) {
1011   const tBTA_GATTC_SERVICE* service =
1012       bta_gattc_get_service_for_handle_srcb(p_srcb, handle);
1013 
1014   if (!service) return NULL;
1015 
1016   for (list_node_t* cn = list_begin(service->characteristics);
1017        cn != list_end(service->characteristics); cn = list_next(cn)) {
1018     tBTA_GATTC_CHARACTERISTIC* p_char =
1019         (tBTA_GATTC_CHARACTERISTIC*)list_node(cn);
1020     if (handle == p_char->handle) return p_char;
1021   }
1022 
1023   return NULL;
1024 }
1025 
bta_gattc_get_characteristic(uint16_t conn_id,uint16_t handle)1026 tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic(uint16_t conn_id,
1027                                                         uint16_t handle) {
1028   tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
1029 
1030   if (p_clcb == NULL) return NULL;
1031 
1032   tBTA_GATTC_SERV* p_srcb = p_clcb->p_srcb;
1033   return bta_gattc_get_characteristic_srcb(p_srcb, handle);
1034 }
1035 
bta_gattc_get_descriptor_srcb(tBTA_GATTC_SERV * p_srcb,uint16_t handle)1036 tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor_srcb(tBTA_GATTC_SERV* p_srcb,
1037                                                      uint16_t handle) {
1038   const tBTA_GATTC_SERVICE* service =
1039       bta_gattc_get_service_for_handle_srcb(p_srcb, handle);
1040 
1041   if (!service) {
1042     return NULL;
1043   }
1044 
1045   for (list_node_t* cn = list_begin(service->characteristics);
1046        cn != list_end(service->characteristics); cn = list_next(cn)) {
1047     tBTA_GATTC_CHARACTERISTIC* p_char =
1048         (tBTA_GATTC_CHARACTERISTIC*)list_node(cn);
1049     for (list_node_t* dn = list_begin(p_char->descriptors);
1050          dn != list_end(p_char->descriptors); dn = list_next(dn)) {
1051       tBTA_GATTC_DESCRIPTOR* p_desc = (tBTA_GATTC_DESCRIPTOR*)list_node(dn);
1052       if (handle == p_desc->handle) return p_desc;
1053     }
1054   }
1055 
1056   return NULL;
1057 }
1058 
bta_gattc_get_descriptor(uint16_t conn_id,uint16_t handle)1059 tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor(uint16_t conn_id,
1060                                                 uint16_t handle) {
1061   tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
1062 
1063   if (p_clcb == NULL) return NULL;
1064 
1065   tBTA_GATTC_SERV* p_srcb = p_clcb->p_srcb;
1066   return bta_gattc_get_descriptor_srcb(p_srcb, handle);
1067 }
1068 
1069 /*******************************************************************************
1070  *
1071  * Function         bta_gattc_fill_gatt_db_el
1072  *
1073  * Description      fill a btgatt_db_element_t value
1074  *
1075  * Returns          None.
1076  *
1077  ******************************************************************************/
bta_gattc_fill_gatt_db_el(btgatt_db_element_t * p_attr,bt_gatt_db_attribute_type_t type,uint16_t att_handle,uint16_t s_handle,uint16_t e_handle,uint16_t id,tBT_UUID uuid,uint8_t prop)1078 void bta_gattc_fill_gatt_db_el(btgatt_db_element_t* p_attr,
1079                                bt_gatt_db_attribute_type_t type,
1080                                uint16_t att_handle, uint16_t s_handle,
1081                                uint16_t e_handle, uint16_t id, tBT_UUID uuid,
1082                                uint8_t prop) {
1083   p_attr->type = type;
1084   p_attr->attribute_handle = att_handle;
1085   p_attr->start_handle = s_handle;
1086   p_attr->end_handle = e_handle;
1087   p_attr->id = id;
1088   p_attr->properties = prop;
1089 
1090   // Permissions are not discoverable using the attribute protocol.
1091   // Core 5.0, Part F, 3.2.5 Attribute Permissions
1092   p_attr->permissions = 0;
1093   bta_to_btif_uuid(&p_attr->uuid, &uuid);
1094 }
1095 
1096 /*******************************************************************************
1097  * Returns          number of elements inside db from start_handle to end_handle
1098  ******************************************************************************/
bta_gattc_get_db_size(list_t * services,uint16_t start_handle,uint16_t end_handle)1099 static size_t bta_gattc_get_db_size(list_t* services, uint16_t start_handle,
1100                                     uint16_t end_handle) {
1101   if (!services || list_is_empty(services)) return 0;
1102 
1103   size_t db_size = 0;
1104 
1105   for (list_node_t* sn = list_begin(services); sn != list_end(services);
1106        sn = list_next(sn)) {
1107     tBTA_GATTC_SERVICE* p_cur_srvc = (tBTA_GATTC_SERVICE*)list_node(sn);
1108 
1109     if (p_cur_srvc->s_handle < start_handle) continue;
1110 
1111     if (p_cur_srvc->e_handle > end_handle) break;
1112 
1113     db_size++;
1114     if (!p_cur_srvc->characteristics ||
1115         list_is_empty(p_cur_srvc->characteristics))
1116       continue;
1117 
1118     for (list_node_t* cn = list_begin(p_cur_srvc->characteristics);
1119          cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
1120       tBTA_GATTC_CHARACTERISTIC* p_char =
1121           (tBTA_GATTC_CHARACTERISTIC*)list_node(cn);
1122       db_size++;
1123 
1124       if (p_char->descriptors) db_size += list_length(p_char->descriptors);
1125     }
1126 
1127     if (p_cur_srvc->included_svc) {
1128       db_size += list_length(p_cur_srvc->included_svc);
1129     }
1130   }
1131 
1132   return db_size;
1133 }
1134 
1135 /*******************************************************************************
1136  *
1137  * Function         bta_gattc_get_gatt_db_impl
1138  *
1139  * Description      copy the server GATT database into db parameter.
1140  *
1141  * Parameters       p_srvc_cb: server.
1142  *                  db: output parameter which will contain GATT database copy.
1143  *                      Caller is responsible for freeing it.
1144  *                  count: output parameter which will contain number of
1145  *                  elements in database.
1146  *
1147  * Returns          None.
1148  *
1149  ******************************************************************************/
bta_gattc_get_gatt_db_impl(tBTA_GATTC_SERV * p_srvc_cb,uint16_t start_handle,uint16_t end_handle,btgatt_db_element_t ** db,int * count)1150 static void bta_gattc_get_gatt_db_impl(tBTA_GATTC_SERV* p_srvc_cb,
1151                                        uint16_t start_handle,
1152                                        uint16_t end_handle,
1153                                        btgatt_db_element_t** db, int* count) {
1154   APPL_TRACE_DEBUG("%s: start_handle 0x%04x, end_handle 0x%04x", __func__,
1155                    start_handle, end_handle);
1156 
1157   if (!p_srvc_cb->p_srvc_cache || list_is_empty(p_srvc_cb->p_srvc_cache)) {
1158     *count = 0;
1159     *db = NULL;
1160     return;
1161   }
1162 
1163   size_t db_size =
1164       bta_gattc_get_db_size(p_srvc_cb->p_srvc_cache, start_handle, end_handle);
1165 
1166   void* buffer = osi_malloc(db_size * sizeof(btgatt_db_element_t));
1167   btgatt_db_element_t* curr_db_attr = (btgatt_db_element_t*)buffer;
1168 
1169   for (list_node_t* sn = list_begin(p_srvc_cb->p_srvc_cache);
1170        sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) {
1171     tBTA_GATTC_SERVICE* p_cur_srvc = (tBTA_GATTC_SERVICE*)list_node(sn);
1172 
1173     if (p_cur_srvc->s_handle < start_handle) continue;
1174 
1175     if (p_cur_srvc->e_handle > end_handle) break;
1176 
1177     bta_gattc_fill_gatt_db_el(
1178         curr_db_attr, p_cur_srvc->is_primary ? BTGATT_DB_PRIMARY_SERVICE
1179                                              : BTGATT_DB_SECONDARY_SERVICE,
1180         0 /* att_handle */, p_cur_srvc->s_handle, p_cur_srvc->e_handle,
1181         p_cur_srvc->s_handle, p_cur_srvc->uuid, 0 /* prop */);
1182     curr_db_attr++;
1183 
1184     if (!p_cur_srvc->characteristics ||
1185         list_is_empty(p_cur_srvc->characteristics))
1186       continue;
1187 
1188     for (list_node_t* cn = list_begin(p_cur_srvc->characteristics);
1189          cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
1190       tBTA_GATTC_CHARACTERISTIC* p_char =
1191           (tBTA_GATTC_CHARACTERISTIC*)list_node(cn);
1192 
1193       bta_gattc_fill_gatt_db_el(curr_db_attr, BTGATT_DB_CHARACTERISTIC,
1194                                 p_char->handle, 0 /* s_handle */,
1195                                 0 /* e_handle */, p_char->handle, p_char->uuid,
1196                                 p_char->properties);
1197       curr_db_attr++;
1198 
1199       if (!p_char->descriptors || list_is_empty(p_char->descriptors)) continue;
1200 
1201       for (list_node_t* dn = list_begin(p_char->descriptors);
1202            dn != list_end(p_char->descriptors); dn = list_next(dn)) {
1203         tBTA_GATTC_DESCRIPTOR* p_desc = (tBTA_GATTC_DESCRIPTOR*)list_node(dn);
1204 
1205         bta_gattc_fill_gatt_db_el(curr_db_attr, BTGATT_DB_DESCRIPTOR,
1206                                   p_desc->handle, 0 /* s_handle */,
1207                                   0 /* e_handle */, p_desc->handle,
1208                                   p_desc->uuid, 0 /* property */);
1209         curr_db_attr++;
1210       }
1211     }
1212 
1213     if (!p_cur_srvc->included_svc || list_is_empty(p_cur_srvc->included_svc))
1214       continue;
1215 
1216     for (list_node_t* isn = list_begin(p_cur_srvc->included_svc);
1217          isn != list_end(p_cur_srvc->included_svc); isn = list_next(isn)) {
1218       tBTA_GATTC_INCLUDED_SVC* p_isvc =
1219           (tBTA_GATTC_INCLUDED_SVC*)list_node(isn);
1220 
1221       bta_gattc_fill_gatt_db_el(curr_db_attr, BTGATT_DB_INCLUDED_SERVICE,
1222                                 p_isvc->handle, 0 /* s_handle */,
1223                                 0 /* e_handle */, p_isvc->handle, p_isvc->uuid,
1224                                 0 /* property */);
1225       curr_db_attr++;
1226     }
1227   }
1228 
1229   *db = (btgatt_db_element_t*)buffer;
1230   *count = db_size;
1231 }
1232 
1233 /*******************************************************************************
1234  *
1235  * Function         bta_gattc_get_gatt_db
1236  *
1237  * Description      copy the server GATT database into db parameter.
1238  *
1239  * Parameters       conn_id: connection ID which identify the server.
1240  *                  db: output parameter which will contain GATT database copy.
1241  *                      Caller is responsible for freeing it.
1242  *                  count: number of elements in database.
1243  *
1244  * Returns          None.
1245  *
1246  ******************************************************************************/
bta_gattc_get_gatt_db(uint16_t conn_id,uint16_t start_handle,uint16_t end_handle,btgatt_db_element_t ** db,int * count)1247 void bta_gattc_get_gatt_db(uint16_t conn_id, uint16_t start_handle,
1248                            uint16_t end_handle, btgatt_db_element_t** db,
1249                            int* count) {
1250   tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
1251 
1252   LOG_DEBUG(LOG_TAG, "%s", __func__);
1253   if (p_clcb == NULL) {
1254     APPL_TRACE_ERROR("Unknown conn ID: %d", conn_id);
1255     return;
1256   }
1257 
1258   if (p_clcb->state != BTA_GATTC_CONN_ST) {
1259     APPL_TRACE_ERROR("server cache not available, CLCB state = %d",
1260                      p_clcb->state);
1261     return;
1262   }
1263 
1264   if (!p_clcb->p_srcb ||
1265       p_clcb->p_srcb->p_srvc_list || /* no active discovery */
1266       !p_clcb->p_srcb->p_srvc_cache) {
1267     APPL_TRACE_ERROR("No server cache available");
1268     return;
1269   }
1270 
1271   bta_gattc_get_gatt_db_impl(p_clcb->p_srcb, start_handle, end_handle, db,
1272                              count);
1273 }
1274 
1275 /*******************************************************************************
1276  *
1277  * Function         bta_gattc_rebuild_cache
1278  *
1279  * Description      rebuild server cache from NV cache.
1280  *
1281  * Parameters
1282  *
1283  * Returns          None.
1284  *
1285  ******************************************************************************/
bta_gattc_rebuild_cache(tBTA_GATTC_SERV * p_srvc_cb,uint16_t num_attr,tBTA_GATTC_NV_ATTR * p_attr)1286 void bta_gattc_rebuild_cache(tBTA_GATTC_SERV* p_srvc_cb, uint16_t num_attr,
1287                              tBTA_GATTC_NV_ATTR* p_attr) {
1288   /* first attribute loading, initialize buffer */
1289   APPL_TRACE_ERROR("%s: bta_gattc_rebuild_cache", __func__);
1290 
1291   list_free(p_srvc_cb->p_srvc_cache);
1292   p_srvc_cb->p_srvc_cache = NULL;
1293 
1294   while (num_attr > 0 && p_attr != NULL) {
1295     switch (p_attr->attr_type) {
1296       case BTA_GATTC_ATTR_TYPE_SRVC:
1297         bta_gattc_add_srvc_to_cache(p_srvc_cb, p_attr->s_handle,
1298                                     p_attr->e_handle, &p_attr->uuid,
1299                                     p_attr->is_primary);
1300         break;
1301 
1302       case BTA_GATTC_ATTR_TYPE_CHAR:
1303         // TODO(jpawlowski): store decl_handle properly.
1304         bta_gattc_add_char_to_cache(p_srvc_cb, p_attr->s_handle,
1305                                     p_attr->s_handle, &p_attr->uuid,
1306                                     p_attr->prop);
1307         break;
1308 
1309       case BTA_GATTC_ATTR_TYPE_CHAR_DESCR:
1310       case BTA_GATTC_ATTR_TYPE_INCL_SRVC:
1311         bta_gattc_add_attr_to_cache(p_srvc_cb, p_attr->s_handle, &p_attr->uuid,
1312                                     p_attr->prop, p_attr->incl_srvc_handle,
1313                                     p_attr->attr_type);
1314         break;
1315     }
1316     p_attr++;
1317     num_attr--;
1318   }
1319 }
1320 
1321 /*******************************************************************************
1322  *
1323  * Function         bta_gattc_fill_nv_attr
1324  *
1325  * Description      fill a NV attribute entry value
1326  *
1327  * Returns          None.
1328  *
1329  ******************************************************************************/
bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR * p_attr,uint8_t type,uint16_t s_handle,uint16_t e_handle,tBT_UUID uuid,uint8_t prop,uint16_t incl_srvc_handle,bool is_primary)1330 void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR* p_attr, uint8_t type,
1331                             uint16_t s_handle, uint16_t e_handle, tBT_UUID uuid,
1332                             uint8_t prop, uint16_t incl_srvc_handle,
1333                             bool is_primary) {
1334   p_attr->s_handle = s_handle;
1335   p_attr->e_handle = e_handle;
1336   p_attr->attr_type = type;
1337   p_attr->is_primary = is_primary;
1338   p_attr->id = 0;
1339   p_attr->prop = prop;
1340   p_attr->incl_srvc_handle = incl_srvc_handle;
1341 
1342   memcpy(&p_attr->uuid, &uuid, sizeof(tBT_UUID));
1343 }
1344 
1345 /*******************************************************************************
1346  *
1347  * Function         bta_gattc_cache_save
1348  *
1349  * Description      save the server cache into NV
1350  *
1351  * Returns          None.
1352  *
1353  ******************************************************************************/
bta_gattc_cache_save(tBTA_GATTC_SERV * p_srvc_cb,uint16_t conn_id)1354 void bta_gattc_cache_save(tBTA_GATTC_SERV* p_srvc_cb, uint16_t conn_id) {
1355   if (!p_srvc_cb->p_srvc_cache || list_is_empty(p_srvc_cb->p_srvc_cache))
1356     return;
1357 
1358   int i = 0;
1359   size_t db_size =
1360       bta_gattc_get_db_size(p_srvc_cb->p_srvc_cache, 0x0000, 0xFFFF);
1361   tBTA_GATTC_NV_ATTR* nv_attr =
1362       (tBTA_GATTC_NV_ATTR*)osi_malloc(db_size * sizeof(tBTA_GATTC_NV_ATTR));
1363 
1364   for (list_node_t* sn = list_begin(p_srvc_cb->p_srvc_cache);
1365        sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) {
1366     tBTA_GATTC_SERVICE* p_cur_srvc = (tBTA_GATTC_SERVICE*)list_node(sn);
1367 
1368     bta_gattc_fill_nv_attr(&nv_attr[i++], BTA_GATTC_ATTR_TYPE_SRVC,
1369                            p_cur_srvc->s_handle, p_cur_srvc->e_handle,
1370                            p_cur_srvc->uuid, 0 /* properties */,
1371                            0 /* incl_srvc_handle */, p_cur_srvc->is_primary);
1372   }
1373 
1374   for (list_node_t* sn = list_begin(p_srvc_cb->p_srvc_cache);
1375        sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) {
1376     tBTA_GATTC_SERVICE* p_cur_srvc = (tBTA_GATTC_SERVICE*)list_node(sn);
1377 
1378     if (!p_cur_srvc->characteristics ||
1379         list_is_empty(p_cur_srvc->characteristics))
1380       continue;
1381 
1382     for (list_node_t* cn = list_begin(p_cur_srvc->characteristics);
1383          cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
1384       tBTA_GATTC_CHARACTERISTIC* p_char =
1385           (tBTA_GATTC_CHARACTERISTIC*)list_node(cn);
1386 
1387       bta_gattc_fill_nv_attr(
1388           &nv_attr[i++], BTA_GATTC_ATTR_TYPE_CHAR, p_char->handle, 0,
1389           p_char->uuid, p_char->properties, 0 /* incl_srvc_handle */, false);
1390 
1391       if (!p_char->descriptors || list_is_empty(p_char->descriptors)) continue;
1392 
1393       for (list_node_t* dn = list_begin(p_char->descriptors);
1394            dn != list_end(p_char->descriptors); dn = list_next(dn)) {
1395         tBTA_GATTC_DESCRIPTOR* p_desc = (tBTA_GATTC_DESCRIPTOR*)list_node(dn);
1396 
1397         bta_gattc_fill_nv_attr(
1398             &nv_attr[i++], BTA_GATTC_ATTR_TYPE_CHAR_DESCR, p_desc->handle, 0,
1399             p_desc->uuid, 0 /* properties */, 0 /* incl_srvc_handle */, false);
1400       }
1401     }
1402 
1403     if (!p_cur_srvc->included_svc || list_is_empty(p_cur_srvc->included_svc))
1404       continue;
1405 
1406     for (list_node_t* an = list_begin(p_cur_srvc->included_svc);
1407          an != list_end(p_cur_srvc->included_svc); an = list_next(an)) {
1408       tBTA_GATTC_INCLUDED_SVC* p_isvc = (tBTA_GATTC_INCLUDED_SVC*)list_node(an);
1409 
1410       bta_gattc_fill_nv_attr(&nv_attr[i++], BTA_GATTC_ATTR_TYPE_INCL_SRVC,
1411                              p_isvc->handle, 0, p_isvc->uuid,
1412                              0 /* properties */,
1413                              p_isvc->included_service->s_handle, false);
1414     }
1415   }
1416 
1417   bta_gattc_cache_write(p_srvc_cb->server_bda, db_size, nv_attr);
1418   osi_free(nv_attr);
1419 }
1420 
1421 /*******************************************************************************
1422  *
1423  * Function         bta_gattc_cache_load
1424  *
1425  * Description      Load GATT cache from storage for server.
1426  *
1427  * Parameter        p_clcb: pointer to server clcb, that will
1428  *                          be filled from storage
1429  * Returns          true on success, false otherwise
1430  *
1431  ******************************************************************************/
bta_gattc_cache_load(tBTA_GATTC_CLCB * p_clcb)1432 bool bta_gattc_cache_load(tBTA_GATTC_CLCB* p_clcb) {
1433   char fname[255] = {0};
1434   bta_gattc_generate_cache_file_name(fname, sizeof(fname),
1435                                      p_clcb->p_srcb->server_bda);
1436 
1437   FILE* fd = fopen(fname, "rb");
1438   if (!fd) {
1439     APPL_TRACE_ERROR("%s: can't open GATT cache file %s for reading, error: %s",
1440                      __func__, fname, strerror(errno));
1441     return false;
1442   }
1443 
1444   uint16_t cache_ver = 0;
1445   tBTA_GATTC_NV_ATTR* attr = NULL;
1446   bool success = false;
1447   uint16_t num_attr = 0;
1448 
1449   if (fread(&cache_ver, sizeof(uint16_t), 1, fd) != 1) {
1450     APPL_TRACE_ERROR("%s: can't read GATT cache version from: %s", __func__,
1451                      fname);
1452     goto done;
1453   }
1454 
1455   if (cache_ver != GATT_CACHE_VERSION) {
1456     APPL_TRACE_ERROR("%s: wrong GATT cache version: %s", __func__, fname);
1457     goto done;
1458   }
1459 
1460   if (fread(&num_attr, sizeof(uint16_t), 1, fd) != 1) {
1461     APPL_TRACE_ERROR("%s: can't read number of GATT attributes: %s", __func__,
1462                      fname);
1463     goto done;
1464   }
1465 
1466   if (num_attr > 0xFFFF) {
1467     APPL_TRACE_ERROR("%s: more than 0xFFFF GATT attributes: %s", __func__, fname);
1468     goto done;
1469   }
1470 
1471   attr = (tBTA_GATTC_NV_ATTR*)osi_malloc(sizeof(tBTA_GATTC_NV_ATTR) * num_attr);
1472 
1473   if (fread(attr, sizeof(tBTA_GATTC_NV_ATTR), num_attr, fd) != num_attr) {
1474     APPL_TRACE_ERROR("%s: can't read GATT attributes: %s", __func__, fname);
1475     goto done;
1476   }
1477 
1478   bta_gattc_rebuild_cache(p_clcb->p_srcb, num_attr, attr);
1479 
1480   success = true;
1481 
1482 done:
1483   osi_free(attr);
1484   fclose(fd);
1485   return success;
1486 }
1487 
1488 /*******************************************************************************
1489  *
1490  * Function         bta_gattc_cache_write
1491  *
1492  * Description      This callout function is executed by GATT when a server
1493  *                  cache is available to save.
1494  *
1495  * Parameter        server_bda: server bd address of this cache belongs to
1496  *                  num_attr: number of attribute to be save.
1497  *                  attr: pointer to the list of attributes to save.
1498  * Returns
1499  *
1500  ******************************************************************************/
bta_gattc_cache_write(const RawAddress & server_bda,uint16_t num_attr,tBTA_GATTC_NV_ATTR * attr)1501 static void bta_gattc_cache_write(const RawAddress& server_bda,
1502                                   uint16_t num_attr, tBTA_GATTC_NV_ATTR* attr) {
1503   char fname[255] = {0};
1504   bta_gattc_generate_cache_file_name(fname, sizeof(fname), server_bda);
1505 
1506   FILE* fd = fopen(fname, "wb");
1507   if (!fd) {
1508     APPL_TRACE_ERROR("%s: can't open GATT cache file for writing: %s", __func__,
1509                      fname);
1510     return;
1511   }
1512 
1513   uint16_t cache_ver = GATT_CACHE_VERSION;
1514   if (fwrite(&cache_ver, sizeof(uint16_t), 1, fd) != 1) {
1515     APPL_TRACE_ERROR("%s: can't write GATT cache version: %s", __func__, fname);
1516     fclose(fd);
1517     return;
1518   }
1519 
1520   if (fwrite(&num_attr, sizeof(uint16_t), 1, fd) != 1) {
1521     APPL_TRACE_ERROR("%s: can't write GATT cache attribute count: %s", __func__,
1522                      fname);
1523     fclose(fd);
1524     return;
1525   }
1526 
1527   if (fwrite(attr, sizeof(tBTA_GATTC_NV_ATTR), num_attr, fd) != num_attr) {
1528     APPL_TRACE_ERROR("%s: can't write GATT cache attributes: %s", __func__,
1529                      fname);
1530     fclose(fd);
1531     return;
1532   }
1533 
1534   fclose(fd);
1535 }
1536 
1537 /*******************************************************************************
1538  *
1539  * Function         bta_gattc_cache_reset
1540  *
1541  * Description      This callout function is executed by GATTC to reset cache in
1542  *                  application
1543  *
1544  * Parameter        server_bda: server bd address of this cache belongs to
1545  *
1546  * Returns          void.
1547  *
1548  ******************************************************************************/
bta_gattc_cache_reset(const RawAddress & server_bda)1549 void bta_gattc_cache_reset(const RawAddress& server_bda) {
1550   BTIF_TRACE_DEBUG("%s", __func__);
1551   char fname[255] = {0};
1552   bta_gattc_generate_cache_file_name(fname, sizeof(fname), server_bda);
1553   unlink(fname);
1554 }
1555