1 /******************************************************************************
2  *
3  *  Copyright (C) 2009-2013 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 #ifdef  BT_SUPPORT_NVM
19 #include <unistd.h>
20 #endif /* BT_SUPPORT_NVM */
21 #include <string.h>
22 #include <stdio.h>
23 #include "bta/bta_gattc_co.h"
24 #include "bta/bta_gattc_ci.h"
25 
26 // #include "btif_util.h"
27 #include "btm_int.h"
28 #include "nvs.h"
29 #include "nvs_flash.h"
30 #include "osi/list.h"
31 #include "esp_err.h"
32 #include "osi/allocator.h"
33 
34 #if( defined BLE_INCLUDED ) && (BLE_INCLUDED == TRUE)
35 #if( defined BTA_GATT_INCLUDED ) && (GATTC_INCLUDED == TRUE)
36 // #if( defined GATTC_CACHE_NVS ) && (GATTC_CACHE_NVS == TRUE)
37 
38 #define GATT_CACHE_PREFIX "gatt_"
39 #define INVALID_ADDR_NUM 0xff
40 #define MAX_DEVICE_IN_CACHE 50
41 #define MAX_ADDR_LIST_CACHE_BUF 2048
42 
43 #ifdef BT_SUPPORT_NVM
44 static FILE *sCacheFD = 0;
getFilename(char * buffer,BD_ADDR bda)45 static void getFilename(char *buffer, BD_ADDR bda)
46 {
47     sprintf(buffer, "%s%02x%02x%02x%02x%02x%02x", GATT_CACHE_PREFIX
48             , bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
49 }
50 
cacheClose(void)51 static void cacheClose(void)
52 {
53     if (sCacheFD != 0) {
54         fclose(sCacheFD);
55         sCacheFD = 0;
56     }
57 }
58 
cacheOpen(BD_ADDR bda,bool to_save)59 static bool cacheOpen(BD_ADDR bda, bool to_save)
60 {
61     char fname[255] = {0};
62     getFilename(fname, bda);
63 
64     cacheClose();
65     sCacheFD = fopen(fname, to_save ? "w" : "r");
66 
67     return (sCacheFD != 0);
68 }
69 
cacheReset(BD_ADDR bda)70 static void cacheReset(BD_ADDR bda)
71 {
72     char fname[255] = {0};
73     getFilename(fname, bda);
74     unlink(fname);
75 }
76 
77 #else
78 
79 static const char *cache_key = "gattc_cache_key";
80 static const char *cache_addr = "cache_addr_tab";
81 
82 typedef struct {
83     //save the service data in the list according to the address
84     nvs_handle_t cache_fp;
85     BOOLEAN is_open;
86     BD_ADDR addr;
87     hash_key_t hash_key;
88     list_t *assoc_addr;
89 }cache_addr_info_t;
90 
91 typedef struct {
92     //save the address list in the cache
93     nvs_handle_t addr_fp;
94     BOOLEAN is_open;
95     UINT8 num_addr;
96     cache_addr_info_t cache_addr[MAX_DEVICE_IN_CACHE];
97 }cache_env_t;
98 
99 static cache_env_t *cache_env = NULL;
100 
getFilename(char * buffer,hash_key_t hash)101 static void getFilename(char *buffer, hash_key_t hash)
102 {
103     sprintf(buffer, "%s%02x%02x%02x%02x", GATT_CACHE_PREFIX,
104             hash[0], hash[1], hash[2], hash[3]);
105 }
106 
cacheClose(BD_ADDR bda)107 static void cacheClose(BD_ADDR bda)
108 {
109     UINT8 index = 0;
110     if ((index = bta_gattc_co_find_addr_in_cache(bda)) != INVALID_ADDR_NUM) {
111         if (cache_env->cache_addr[index].is_open) {
112             nvs_close(cache_env->cache_addr[index].cache_fp);
113             cache_env->cache_addr[index].is_open = FALSE;
114         }
115     }
116 }
117 
cacheOpen(BD_ADDR bda,bool to_save,UINT8 * index)118 static bool cacheOpen(BD_ADDR bda, bool to_save, UINT8 *index)
119 {
120     UNUSED(to_save);
121     char fname[255] = {0};
122     UINT8 *assoc_addr = NULL;
123     esp_err_t status = ESP_FAIL;
124     hash_key_t hash_key = {0};
125     if (((*index = bta_gattc_co_find_addr_in_cache(bda)) != INVALID_ADDR_NUM) ||
126         ((assoc_addr = bta_gattc_co_cache_find_src_addr(bda, index)) != NULL)) {
127         if (cache_env->cache_addr[*index].is_open) {
128             return TRUE;
129         } else {
130             memcpy(hash_key, cache_env->cache_addr[*index].hash_key, sizeof(hash_key_t));
131             getFilename(fname, hash_key);
132             if ((status = nvs_open(fname, NVS_READWRITE, &cache_env->cache_addr[*index].cache_fp)) == ESP_OK) {
133                 // Set the open flag to TRUE when success to open the hash file.
134                 cache_env->cache_addr[*index].is_open = TRUE;
135             }
136         }
137     }
138 
139     return ((status == ESP_OK) ? true : false);
140 }
141 
cacheReset(BD_ADDR bda,BOOLEAN update)142 static void cacheReset(BD_ADDR bda, BOOLEAN update)
143 {
144     char fname[255] = {0};
145     getFilename(fname, bda);
146     UINT8 index = 0;
147     //cache_env->cache_addr
148     if ((index = bta_gattc_co_find_addr_in_cache(bda)) != INVALID_ADDR_NUM) {
149         //clear the association address pending in the source address.
150         bta_gattc_co_cache_clear_assoc_addr(bda);
151         if (cache_env->cache_addr[index].is_open) {
152             nvs_erase_all(cache_env->cache_addr[index].cache_fp);
153             nvs_close(cache_env->cache_addr[index].cache_fp);
154             cache_env->cache_addr[index].is_open = FALSE;
155         } else {
156             cacheOpen(bda, false, &index);
157             if (index == INVALID_ADDR_NUM) {
158                 APPL_TRACE_ERROR("%s INVALID ADDR NUM", __func__);
159                 return;
160             }
161             if (cache_env->cache_addr[index].is_open) {
162                 nvs_erase_all(cache_env->cache_addr[index].cache_fp);
163                 nvs_close(cache_env->cache_addr[index].cache_fp);
164                 cache_env->cache_addr[index].is_open = FALSE;
165             } else {
166                 APPL_TRACE_ERROR("%s cacheOpen failed", __func__);
167                 return;
168             }
169         }
170         if(cache_env->num_addr == 0) {
171             APPL_TRACE_ERROR("%s cache addr list error", __func__);
172             return;
173         }
174 
175         UINT8 num = cache_env->num_addr;
176         //delete the server_bda in the addr_info list.
177         for(UINT8 i = index; i < (num - 1); i++) {
178             memcpy(&cache_env->cache_addr[i], &cache_env->cache_addr[i+1], sizeof(cache_addr_info_t));
179         }
180         //clear the last cache when delete a addr
181         memset(&cache_env->cache_addr[num-1], 0, sizeof(cache_addr_info_t));
182         //reduced the number address counter also
183         cache_env->num_addr--;
184 
185         //don't need to update addr list to nvs flash
186         if (!update) {
187             return;
188         }
189 
190         //update addr list to nvs flash
191         if(cache_env->num_addr > 0) {
192             //update
193             UINT8 *p_buf = osi_malloc(MAX_ADDR_LIST_CACHE_BUF);
194             if(!p_buf) {
195                 APPL_TRACE_ERROR("%s malloc error", __func__);
196                 return;
197             }
198             UINT16 length = cache_env->num_addr*(sizeof(BD_ADDR) + sizeof(hash_key_t));
199             for (UINT8 i = 0; i < cache_env->num_addr; i++) {
200                 //copy the address to the buffer.
201                 memcpy(p_buf + i*(sizeof(BD_ADDR) + sizeof(hash_key_t)), cache_env->cache_addr[i].addr, sizeof(BD_ADDR));
202                 //copy the hash key to the buffer.
203                 memcpy(p_buf + i*(sizeof(BD_ADDR) + sizeof(hash_key_t)) + sizeof(BD_ADDR),
204                         cache_env->cache_addr[i].hash_key, sizeof(hash_key_t));
205             }
206             if (cache_env->is_open) {
207                 if (nvs_set_blob(cache_env->addr_fp, cache_key, p_buf, length) != ESP_OK) {
208                     APPL_TRACE_WARNING("%s, nvs set blob failed", __func__);
209                 }
210             }
211             osi_free(p_buf);
212 
213         } else {
214             //erase
215             if (cache_env->is_open) {
216                 nvs_erase_all(cache_env->addr_fp);
217                 nvs_close(cache_env->addr_fp);
218                 cache_env->is_open = FALSE;
219             } else {
220                 APPL_TRACE_WARNING("cache_env status is error");
221             }
222         }
223     }
224 }
225 
226 #endif /* BT_SUPPORT_NVM */
227 /*****************************************************************************
228 **  Function Declarations
229 *****************************************************************************/
230 
231 /*******************************************************************************
232 **
233 ** Function         bta_gattc_co_cache_open
234 **
235 ** Description      This callout function is executed by GATTC when a GATT server
236 **                  cache is ready to be sent.
237 **
238 ** Parameter        server_bda: server bd address of this cache belongs to
239 **                  evt: call in event to be passed in when cache open is done.
240 **                  conn_id: connection ID of this cache operation attach to.
241 **                  to_save: open cache to save or to load.
242 **
243 ** Returns          void.
244 **
245 *******************************************************************************/
bta_gattc_co_cache_open(BD_ADDR server_bda,BOOLEAN to_save,UINT8 * index)246 tBTA_GATT_STATUS bta_gattc_co_cache_open(BD_ADDR server_bda, BOOLEAN to_save, UINT8 *index)
247 {
248     /* open NV cache and send call in */
249     tBTA_GATT_STATUS status = BTA_GATT_OK;
250     if (!cacheOpen(server_bda, to_save, index)) {
251         status = BTA_GATT_ERROR;
252     }
253 
254     APPL_TRACE_DEBUG("%s() - status=%d", __func__, status);
255     return status;
256 }
257 
258 /*******************************************************************************
259 **
260 ** Function         bta_gattc_co_cache_load
261 **
262 ** Description      This callout function is executed by GATT when server cache
263 **                  is required to load.
264 **
265 ** Parameter        server_bda: server bd address of this cache belongs to
266 **                  evt: call in event to be passed in when cache save is done.
267 **                  num_attr: number of attribute to be save.
268 **                  attr_index: starting attribute index of the save operation.
269 **                  conn_id: connection ID of this cache operation attach to.
270 ** Returns
271 **
272 *******************************************************************************/
bta_gattc_co_cache_load(tBTA_GATTC_NV_ATTR * attr,UINT8 index)273 tBTA_GATT_STATUS bta_gattc_co_cache_load(tBTA_GATTC_NV_ATTR *attr, UINT8 index)
274 {
275 #if (!CONFIG_BT_STACK_NO_LOG)
276     UINT16              num_attr = 0;
277 #endif
278     tBTA_GATT_STATUS    status = BTA_GATT_ERROR;
279     size_t length = 0;
280     // Read the size of memory space required for blob
281     nvs_get_blob(cache_env->cache_addr[index].cache_fp, cache_key, NULL, &length);
282     // Read previously saved blob if available
283     esp_err_t err_code = nvs_get_blob(cache_env->cache_addr[index].cache_fp, cache_key, attr, &length);
284 #if (!CONFIG_BT_STACK_NO_LOG)
285     num_attr = length / sizeof(tBTA_GATTC_NV_ATTR);
286 #endif
287     status = (err_code == ESP_OK && length != 0) ? BTA_GATT_OK : BTA_GATT_ERROR;
288     APPL_TRACE_DEBUG("%s() - read=%d, status=%d, err_code = %d",
289                      __func__, num_attr, status, err_code);
290 
291     return status;
292  }
293 
bta_gattc_get_cache_attr_length(UINT8 index)294 size_t bta_gattc_get_cache_attr_length(UINT8 index)
295 {
296     size_t length = 0;
297     if (index == INVALID_ADDR_NUM) {
298         return 0;
299     }
300 
301     // Read the size of memory space required for blob
302     nvs_get_blob(cache_env->cache_addr[index].cache_fp, cache_key, NULL, &length);
303     return length;
304 }
305 
306 /*******************************************************************************
307 **
308 ** Function         bta_gattc_co_cache_save
309 **
310 ** Description      This callout function is executed by GATT when a server cache
311 **                  is available to save.
312 **
313 ** Parameter        server_bda: server bd address of this cache belongs to
314 **                  evt: call in event to be passed in when cache save is done.
315 **                  num_attr: number of attribute to be save.
316 **                  p_attr: pointer to the list of attributes to save.
317 **                  attr_index: starting attribute index of the save operation.
318 **                  conn_id: connection ID of this cache operation attach to.
319 ** Returns
320 **
321 *******************************************************************************/
bta_gattc_co_cache_save(BD_ADDR server_bda,UINT16 num_attr,tBTA_GATTC_NV_ATTR * p_attr_list)322 void bta_gattc_co_cache_save (BD_ADDR server_bda, UINT16 num_attr,
323                               tBTA_GATTC_NV_ATTR *p_attr_list)
324 {
325     tBTA_GATT_STATUS    status = BTA_GATT_OK;
326     hash_key_t hash_key = {0};
327     UINT8 index = INVALID_ADDR_NUM;
328     //calculate  the hash value of the attribute table which should be added to the nvs flash.
329     hash_function_blob((unsigned char *)p_attr_list, sizeof(tBTA_GATTC_NV_ATTR)*num_attr, hash_key);
330     //save the address list to the nvs flash
331     bta_gattc_co_cache_addr_save(server_bda, hash_key);
332 
333     if (cacheOpen(server_bda, TRUE, &index)) {
334         esp_err_t err_code = nvs_set_blob(cache_env->cache_addr[index].cache_fp, cache_key,
335                                           p_attr_list, sizeof(tBTA_GATTC_NV_ATTR)*num_attr);
336         status = (err_code == ESP_OK) ? BTA_GATT_OK : BTA_GATT_ERROR;
337     } else {
338         status = BTA_GATT_ERROR;
339     }
340 
341 #if CONFIG_BT_STACK_NO_LOG
342     (void) status;
343 #endif
344     APPL_TRACE_DEBUG("%s() wrote hash_key = %x%x%x%x, num_attr = %d, status = %d.", __func__, hash_key[0], hash_key[1], hash_key[2], hash_key[3], num_attr, status);
345 }
346 
347 /*******************************************************************************
348 **
349 ** Function         bta_gattc_co_cache_close
350 **
351 ** Description      This callout function is executed by GATTC when a GATT server
352 **                  cache is written completely.
353 **
354 ** Parameter        server_bda: server bd address of this cache belongs to
355 **                  conn_id: connection ID of this cache operation attach to.
356 **
357 ** Returns          void.
358 **
359 *******************************************************************************/
bta_gattc_co_cache_close(BD_ADDR server_bda,UINT16 conn_id)360 void bta_gattc_co_cache_close(BD_ADDR server_bda, UINT16 conn_id)
361 {
362     UNUSED(conn_id);
363 //#ifdef BT_SUPPORT_NVM
364     cacheClose(server_bda);
365 //#endif /* BT_SUPPORT_NVM */
366     /* close NV when server cache is done saving or loading,
367        does not need to do anything for now on Insight */
368 
369     BTIF_TRACE_DEBUG("%s()", __FUNCTION__);
370 }
371 
372 /*******************************************************************************
373 **
374 ** Function         bta_gattc_co_cache_reset
375 **
376 ** Description      This callout function is executed by GATTC to reset cache in
377 **                  application
378 **
379 ** Parameter        server_bda: server bd address of this cache belongs to
380 **
381 ** Returns          void.
382 **
383 *******************************************************************************/
bta_gattc_co_cache_reset(BD_ADDR server_bda)384 void bta_gattc_co_cache_reset(BD_ADDR server_bda)
385 {
386     cacheReset(server_bda, TRUE);
387 }
388 
bta_gattc_co_cache_addr_init(void)389 void bta_gattc_co_cache_addr_init(void)
390 {
391     nvs_handle_t fp;
392     esp_err_t err_code;
393     UINT8 num_addr;
394     size_t length = MAX_ADDR_LIST_CACHE_BUF;
395     UINT8 *p_buf = osi_malloc(MAX_ADDR_LIST_CACHE_BUF);
396     if (p_buf == NULL) {
397         APPL_TRACE_ERROR("%s malloc failed!", __func__);
398         return;
399     }
400 
401     cache_env = (cache_env_t *)osi_malloc(sizeof(cache_env_t));
402     if (cache_env == NULL) {
403         APPL_TRACE_ERROR("%s malloc failed!", __func__);
404         osi_free(p_buf);
405         return;
406     }
407 
408     memset(cache_env, 0x0, sizeof(cache_env_t));
409 
410     if ((err_code = nvs_open(cache_addr, NVS_READWRITE, &fp)) == ESP_OK) {
411         cache_env->addr_fp = fp;
412         cache_env->is_open = TRUE;
413         // Read previously saved blob if available
414         if ((err_code = nvs_get_blob(fp, cache_key, p_buf, &length)) != ESP_OK) {
415             if(err_code != ESP_ERR_NVS_NOT_FOUND) {
416                 APPL_TRACE_ERROR("%s, Line = %d, nvs flash get blob data fail, err_code = 0x%x", __func__, __LINE__, err_code);
417             }
418             osi_free(p_buf);
419             return;
420         }
421         num_addr = length / (sizeof(BD_ADDR) + sizeof(hash_key_t));
422         cache_env->num_addr = num_addr;
423         //read the address from nvs flash to cache address list.
424         for (UINT8 i = 0; i < num_addr; i++) {
425             memcpy(cache_env->cache_addr[i].addr, p_buf + i*(sizeof(BD_ADDR) + sizeof(hash_key_t)), sizeof(BD_ADDR));
426             memcpy(cache_env->cache_addr[i].hash_key,
427                     p_buf + i*(sizeof(BD_ADDR) + sizeof(hash_key_t)) + sizeof(BD_ADDR), sizeof(hash_key_t));
428 
429             APPL_TRACE_DEBUG("cache_addr[%x] = %x:%x:%x:%x:%x:%x", i, cache_env->cache_addr[i].addr[0], cache_env->cache_addr[i].addr[1], cache_env->cache_addr[i].addr[2],
430                              cache_env->cache_addr[i].addr[3], cache_env->cache_addr[i].addr[4], cache_env->cache_addr[i].addr[5]);
431             APPL_TRACE_DEBUG("hash_key[%x] = %x%x%x%x", i, cache_env->cache_addr[i].hash_key[0], cache_env->cache_addr[i].hash_key[1],
432                              cache_env->cache_addr[i].hash_key[2], cache_env->cache_addr[i].hash_key[3]);
433             bta_gattc_co_cache_new_assoc_list(cache_env->cache_addr[i].addr, i);
434         }
435     } else {
436         APPL_TRACE_ERROR("%s, Line = %d, nvs flash open fail, err_code = %x", __func__, __LINE__, err_code);
437         osi_free(p_buf);
438         return;
439     }
440 
441     osi_free(p_buf);
442     return;
443 }
444 
bta_gattc_co_cache_addr_deinit(void)445 void bta_gattc_co_cache_addr_deinit(void)
446 {
447     if(!cache_env->is_open) {
448         return;
449     }
450     nvs_close(cache_env->addr_fp);
451     cache_env->is_open = false;
452 
453     for(UINT8 i = 0; i< cache_env->num_addr; i++) {
454         cache_addr_info_t *addr_info = &cache_env->cache_addr[i];
455         if(addr_info) {
456             nvs_close(addr_info->cache_fp);
457             addr_info->is_open = false;
458             if(addr_info->assoc_addr) {
459                 list_free(addr_info->assoc_addr);
460             }
461         }
462     }
463 
464     osi_free(cache_env);
465     cache_env = NULL;
466 }
467 
bta_gattc_co_addr_in_cache(BD_ADDR bda)468 BOOLEAN bta_gattc_co_addr_in_cache(BD_ADDR bda)
469 {
470     UINT8 addr_index = 0;
471     UINT8 num = cache_env->num_addr;
472     cache_addr_info_t *addr_info = &cache_env->cache_addr[0];
473     for (addr_index = 0; addr_index < num; addr_index++) {
474         if (!memcmp(addr_info->addr, bda, sizeof(BD_ADDR))) {
475             return TRUE;
476         }
477     }
478 
479     return FALSE;
480 }
481 
bta_gattc_co_find_addr_in_cache(BD_ADDR bda)482 UINT8 bta_gattc_co_find_addr_in_cache(BD_ADDR bda)
483 {
484     UINT8 addr_index = 0;
485     UINT8 num = cache_env->num_addr;
486     cache_addr_info_t *addr_info = &cache_env->cache_addr[0];
487 
488     for (addr_index = 0; addr_index < num; addr_index++, addr_info++) {
489         if (!memcmp(addr_info->addr, bda, sizeof(BD_ADDR))) {
490             return addr_index;
491         }
492     }
493 
494     return INVALID_ADDR_NUM;
495 }
496 
bta_gattc_co_find_hash_in_cache(hash_key_t hash_key)497 UINT8 bta_gattc_co_find_hash_in_cache(hash_key_t hash_key)
498 {
499     UINT8 index = 0;
500     UINT8 num = cache_env->num_addr;
501     cache_addr_info_t *addr_info = &cache_env->cache_addr[0];
502     for (index = 0; index < num; index++) {
503         if (!memcmp(addr_info->hash_key, hash_key, sizeof(hash_key_t))) {
504             return index;
505         }
506     }
507 
508     return INVALID_ADDR_NUM;
509 }
510 
bta_gattc_co_get_addr_num(void)511 UINT8 bta_gattc_co_get_addr_num(void)
512 {
513     if (cache_env == NULL) {
514         return 0;
515     }
516 
517     return cache_env->num_addr;
518 }
519 
bta_gattc_co_get_addr_list(BD_ADDR * addr_list)520 void bta_gattc_co_get_addr_list(BD_ADDR *addr_list)
521 {
522     UINT8 num = cache_env->num_addr;
523     for (UINT8 i = 0; i < num; i++) {
524         memcpy(addr_list[i], cache_env->cache_addr[i].addr, sizeof(BD_ADDR));
525     }
526 }
527 
bta_gattc_co_cache_addr_save(BD_ADDR bd_addr,hash_key_t hash_key)528 void bta_gattc_co_cache_addr_save(BD_ADDR bd_addr, hash_key_t hash_key)
529 {
530     esp_err_t err_code;
531     UINT8 index = 0;
532     UINT8 new_index = cache_env->num_addr;
533     UINT8 *p_buf = osi_malloc(MAX_ADDR_LIST_CACHE_BUF);
534     if (p_buf == NULL) {
535         APPL_TRACE_ERROR("%s malloc failed!", __func__);
536         return;
537     }
538 
539     // check the address list has the same address or not
540     // for the same address, it's hash key may be change due to service change
541     if ((index = bta_gattc_co_find_addr_in_cache(bd_addr)) != INVALID_ADDR_NUM) {
542         APPL_TRACE_DEBUG("%s the bd_addr already in the cache list, index = %x", __func__, index);
543         //if the bd_addr already in the address list, update the hash key in it.
544         memcpy(cache_env->cache_addr[index].addr, bd_addr, sizeof(BD_ADDR));
545         memcpy(cache_env->cache_addr[index].hash_key, hash_key, sizeof(hash_key_t));
546     } else {
547         if (cache_env->num_addr >= MAX_DEVICE_IN_CACHE) {
548             APPL_TRACE_WARNING("%s cache list full and remove the oldest addr info", __func__);
549             cacheReset(cache_env->cache_addr[0].addr, FALSE);
550         }
551         new_index = cache_env->num_addr;
552         assert(new_index < MAX_DEVICE_IN_CACHE);
553         memcpy(cache_env->cache_addr[new_index].addr, bd_addr, sizeof(BD_ADDR));
554         memcpy(cache_env->cache_addr[new_index].hash_key, hash_key, sizeof(hash_key_t));
555         cache_env->num_addr++;
556         APPL_TRACE_DEBUG("%s(), num = %d", __func__, cache_env->num_addr);
557     }
558 
559     nvs_handle_t *fp = &cache_env->addr_fp;
560     UINT16 length = cache_env->num_addr * (sizeof(BD_ADDR) + sizeof(hash_key_t));
561 
562     for (UINT8 i = 0; i < cache_env->num_addr; i++) {
563         //copy the address to the buffer.
564         memcpy(p_buf + i*(sizeof(BD_ADDR) + sizeof(hash_key_t)), cache_env->cache_addr[i].addr, sizeof(BD_ADDR));
565         //copy the hash key to the buffer.
566         memcpy(p_buf + i*(sizeof(BD_ADDR) + sizeof(hash_key_t)) + sizeof(BD_ADDR),
567                 cache_env->cache_addr[i].hash_key, sizeof(hash_key_t));
568     }
569 
570     if (cache_env->is_open) {
571         if ((err_code = nvs_set_blob(cache_env->addr_fp, cache_key, p_buf, length)) != ESP_OK) {
572             APPL_TRACE_WARNING("%s(), nvs set blob fail, err %d", __func__, err_code);
573         }
574     } else {
575         if ((err_code = nvs_open(cache_addr, NVS_READWRITE , fp)) == ESP_OK) {
576             cache_env->is_open = true;
577             if (( err_code = nvs_set_blob(cache_env->addr_fp, cache_key, p_buf, length)) != ESP_OK) {
578                 APPL_TRACE_WARNING("%s(), nvs set blob fail, err %d", __func__, err_code);
579             }
580         } else {
581             APPL_TRACE_ERROR("%s, Line = %d, nvs flash open fail, err_code = %x", __func__, __LINE__, err_code);
582         }
583     }
584 
585     //free the buffer after used.
586     osi_free(p_buf);
587     return;
588 }
589 
bta_gattc_co_cache_new_assoc_list(BD_ADDR src_addr,UINT8 index)590 BOOLEAN bta_gattc_co_cache_new_assoc_list(BD_ADDR src_addr, UINT8 index)
591 {
592     cache_addr_info_t *addr_info = &cache_env->cache_addr[index];
593     addr_info->assoc_addr = list_new(osi_free_func);
594     return (addr_info->assoc_addr != NULL ? TRUE : FALSE);
595 }
596 
bta_gattc_co_cache_append_assoc_addr(BD_ADDR src_addr,BD_ADDR assoc_addr)597 BOOLEAN bta_gattc_co_cache_append_assoc_addr(BD_ADDR src_addr, BD_ADDR assoc_addr)
598 {
599     UINT8 addr_index = 0;
600     cache_addr_info_t *addr_info;
601     UINT8 *p_assoc_buf = osi_malloc(sizeof(BD_ADDR));
602     if(!p_assoc_buf) {
603         return FALSE;
604     }
605     memcpy(p_assoc_buf, assoc_addr, sizeof(BD_ADDR));
606     if ((addr_index = bta_gattc_co_find_addr_in_cache(src_addr)) != INVALID_ADDR_NUM) {
607         addr_info = &cache_env->cache_addr[addr_index];
608         if (addr_info->assoc_addr == NULL) {
609             addr_info->assoc_addr =list_new(NULL);
610         }
611         return list_append(addr_info->assoc_addr, p_assoc_buf);
612     } else {
613         osi_free(p_assoc_buf);
614     }
615 
616     return FALSE;
617 }
618 
bta_gattc_co_cache_remove_assoc_addr(BD_ADDR src_addr,BD_ADDR assoc_addr)619 BOOLEAN bta_gattc_co_cache_remove_assoc_addr(BD_ADDR src_addr, BD_ADDR assoc_addr)
620 {
621     UINT8 addr_index = 0;
622     cache_addr_info_t *addr_info;
623     if ((addr_index = bta_gattc_co_find_addr_in_cache(src_addr)) != INVALID_ADDR_NUM) {
624         addr_info = &cache_env->cache_addr[addr_index];
625         if (addr_info->assoc_addr != NULL) {
626             for (list_node_t *sn = list_begin(addr_info->assoc_addr);
627              sn != list_end(addr_info->assoc_addr); sn = list_next(sn)) {
628                 void *addr = list_node(sn);
629                 if (!memcmp(addr, assoc_addr, sizeof(BD_ADDR))) {
630                     return list_remove(addr_info->assoc_addr, addr);
631                 }
632             }
633             //return list_remove(addr_info->assoc_addr, assoc_addr);
634         } else {
635             return FALSE;
636         }
637     }
638 
639     return FALSE;
640 }
641 
bta_gattc_co_cache_find_src_addr(BD_ADDR assoc_addr,UINT8 * index)642 UINT8* bta_gattc_co_cache_find_src_addr(BD_ADDR assoc_addr, UINT8 *index)
643 {
644     UINT8 num = cache_env->num_addr;
645     cache_addr_info_t *addr_info = &cache_env->cache_addr[0];
646     UINT8 *addr_data;
647     //Check the assoc_addr list is NULL or not
648     if (addr_info->assoc_addr == NULL) {
649         *index = INVALID_ADDR_NUM;
650         return NULL;
651     }
652 
653     for (int i = 0; i < num; i++) {
654        for (const list_node_t *node = list_begin(addr_info->assoc_addr); node != list_end(addr_info->assoc_addr);
655             node = list_next(node)) {
656             addr_data = (UINT8 *)list_node(node);
657            if (!memcmp(addr_data, assoc_addr, sizeof(BD_ADDR))) {
658                *index = i;
659                return (UINT8 *)addr_info->addr;
660            }
661        }
662        addr_info++;
663 
664        if (addr_info->assoc_addr == NULL) {
665            *index = INVALID_ADDR_NUM;
666            return NULL;
667        }
668     }
669 
670     *index = INVALID_ADDR_NUM;
671     return NULL;
672 }
673 
bta_gattc_co_cache_clear_assoc_addr(BD_ADDR src_addr)674 BOOLEAN bta_gattc_co_cache_clear_assoc_addr(BD_ADDR src_addr)
675 {
676     UINT8 addr_index = 0;
677     cache_addr_info_t *addr_info;
678     if ((addr_index = bta_gattc_co_find_addr_in_cache(src_addr)) != INVALID_ADDR_NUM) {
679         addr_info = &cache_env->cache_addr[addr_index];
680         if (addr_info->assoc_addr != NULL) {
681             list_clear(addr_info->assoc_addr);
682         } else {
683             return FALSE;
684         }
685         return TRUE;
686     }
687 
688     return FALSE;
689 }
690 
691 // #endif /* #if( defined GATTC_CACHE_NVS ) && (GATTC_CACHE_NVS == TRUE) */
692 #endif /* #if( defined BLE_INCLUDED ) && (BLE_INCLUDED == TRUE) */
693 #endif /* #if( defined BTA_GATT_INCLUDED ) && (BTA_GATT_INCLUDED == TRUE) */
694