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