1 /*
2  * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <string.h>
7 
8 #include "btc/btc_storage.h"
9 #include "btc/btc_ble_storage.h"
10 #include "btc/btc_util.h"
11 #include "osi/osi.h"
12 #include "osi/allocator.h"
13 #include "common/bt_trace.h"
14 #include "esp_system.h"
15 #include "bta/bta_api.h"
16 #include "device/bdaddr.h"
17 #include "btc/btc_config.h"
18 #include "btc_hh.h"
19 
20 /*******************************************************************************
21 **
22 ** Function         btc_storage_add_bonded_device
23 **
24 ** Description      BTIF storage API - Adds the newly bonded device to NVRAM
25 **                  along with the link-key, Key type and Pin key length
26 **
27 ** Returns          BT_STATUS_SUCCESS if the store was successful,
28 **                  BT_STATUS_FAIL otherwise
29 **
30 *******************************************************************************/
31 
btc_storage_add_bonded_device(bt_bdaddr_t * remote_bd_addr,LINK_KEY link_key,uint8_t key_type,uint8_t pin_length,BOOLEAN sc_support)32 bt_status_t btc_storage_add_bonded_device(bt_bdaddr_t *remote_bd_addr,
33         LINK_KEY link_key,
34         uint8_t key_type,
35         uint8_t pin_length,
36         BOOLEAN sc_support)
37 {
38     bdstr_t bdstr;
39     bt_bdaddr_t bd_addr;
40     bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
41 
42     /* device not in bond list and exceed the maximum number of bonded devices, delete the inactive bonded device */
43     if (btc_storage_get_num_all_bond_devices() >= BTM_SEC_MAX_DEVICE_RECORDS && !btc_config_has_section(bdstr)) {
44         const btc_config_section_iter_t *iter = btc_config_section_begin();
45         const btc_config_section_iter_t *remove_iter = iter;
46         /* find the first device(the last node) */
47         while (iter != btc_config_section_end()) {
48             remove_iter = iter;
49             iter = btc_config_section_next(iter);
50         }
51         const char *remove_section = btc_config_section_name(remove_iter);
52 
53         // delete device info
54         string_to_bdaddr(remove_section, &bd_addr);
55         BTA_DmRemoveDevice(bd_addr.address, BT_TRANSPORT_BR_EDR);
56         BTA_DmRemoveDevice(bd_addr.address, BT_TRANSPORT_LE);
57 
58         // delete config info
59         if (btc_config_remove_section(remove_section)) {
60             BTC_TRACE_WARNING("exceeded the maximum nubmer of bonded devices, delete the first device info : %02x:%02x:%02x:%02x:%02x:%02x",
61                                 bd_addr.address[0], bd_addr.address[1], bd_addr.address[2], bd_addr.address[3], bd_addr.address[4], bd_addr.address[5]);
62         }
63     }
64 
65     BTC_TRACE_DEBUG("add to storage: Remote device:%s\n", bdstr);
66 
67     btc_config_lock();
68     int ret = btc_config_set_int(bdstr, BTC_STORAGE_LINK_KEY_TYPE_STR, (int)key_type);
69     ret &= btc_config_set_int(bdstr, BTC_STORAGE_PIN_LENGTH_STR, (int)pin_length);
70     ret &= btc_config_set_bin(bdstr, BTC_STORAGE_LINK_KEY_STR, link_key, sizeof(LINK_KEY));
71     ret &= btc_config_set_bin(bdstr, BTC_STORAGE_SC_SUPPORT, (uint8_t *)&sc_support, sizeof(sc_support));
72     /* write bonded info immediately */
73     btc_config_flush();
74     btc_config_unlock();
75 
76     BTC_TRACE_DEBUG("Storage add rslt %d\n", ret);
77     return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
78 }
79 
80 #if (SMP_INCLUDED == TRUE)
_btc_storage_in_fetch_bonded_bt_device(const char * remote_bd_addr,int add)81 static bt_status_t _btc_storage_in_fetch_bonded_bt_device(const char *remote_bd_addr, int add)
82 {
83     BOOLEAN bt_linkkey_file_found = FALSE;
84     UINT8 sc_support = 0;
85 
86     BTC_TRACE_DEBUG("Remote device:%s\n", remote_bd_addr);
87     LINK_KEY link_key;
88         size_t size = sizeof(link_key);
89         if (btc_config_get_bin(remote_bd_addr, BTC_STORAGE_LINK_KEY_STR, link_key, &size)) {
90             int linkkey_type;
91             if (btc_config_get_int(remote_bd_addr, BTC_STORAGE_LINK_KEY_TYPE_STR, &linkkey_type)) {
92                 bt_bdaddr_t bd_addr;
93                 string_to_bdaddr(remote_bd_addr, &bd_addr);
94                 if (add) {
95                     DEV_CLASS dev_class = {0, 0, 0};
96                     int cod;
97                     int pin_length = 0;
98                     if (btc_config_get_int(remote_bd_addr, BTC_STORAGE_DEV_CLASS_STR, &cod)) {
99                         uint2devclass((UINT32)cod, dev_class);
100                     }
101                     btc_config_get_int(remote_bd_addr, BTC_STORAGE_PIN_LENGTH_STR, &pin_length);
102                     size = sizeof(sc_support);
103                     btc_config_get_bin(remote_bd_addr, BTC_STORAGE_SC_SUPPORT, &sc_support, &size);
104 
105                     BTA_DmAddDevice(bd_addr.address, dev_class, link_key, 0, 0,
106                                     (UINT8)linkkey_type, 0, pin_length, (UINT8)sc_support);
107                 }
108                 bt_linkkey_file_found = TRUE;
109             } else {
110                 BTC_TRACE_ERROR("bounded device:%s, LinkKeyType or PinLength is invalid\n", remote_bd_addr);
111             }
112         }
113         if (!bt_linkkey_file_found) {
114             BTC_TRACE_DEBUG("Remote device:%s, no link key\n", remote_bd_addr);
115         }
116 
117     return BT_STATUS_SUCCESS;
118 }
119 
120 /*******************************************************************************
121 **
122 ** Function         btc_in_fetch_bonded_devices
123 **
124 ** Description      Internal helper function to fetch the bonded devices
125 **                  from NVRAM
126 **
127 ** Returns          BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
128 **
129 *******************************************************************************/
btc_in_fetch_bonded_devices(int add)130 static bt_status_t btc_in_fetch_bonded_devices(int add)
131 {
132     bt_status_t status = BT_STATUS_FAIL;
133     uint16_t dev_cnt = 0;
134     const btc_config_section_iter_t *remove_iter = NULL;
135     bt_bdaddr_t bd_addr;
136 
137     btc_config_lock();
138     for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end(); iter = btc_config_section_next(iter)) {
139         const char *name = btc_config_section_name(iter);
140         if (!string_is_bdaddr(name)) {
141             continue;
142         }
143         dev_cnt ++;
144         /* if the number of device stored in nvs not exceed to BTM_SEC_MAX_DEVICE_RECORDS, load it */
145         if (dev_cnt <= BTM_SEC_MAX_DEVICE_RECORDS) {
146             if (btc_config_exist(name, BTC_STORAGE_LINK_KEY_TYPE_STR) && btc_config_exist(name, BTC_STORAGE_PIN_LENGTH_STR) &&
147                 btc_config_exist(name, BTC_STORAGE_SC_SUPPORT) && btc_config_exist(name, BTC_STORAGE_LINK_KEY_STR)) {
148                 /* load bt device */
149                 status = _btc_storage_in_fetch_bonded_bt_device(name, add);
150             }
151             if (btc_config_exist(name, BTC_BLE_STORAGE_DEV_TYPE_STR)) {
152 #if (BLE_INCLUDED == TRUE)
153                 /* load ble device */
154                 status = _btc_storage_in_fetch_bonded_ble_device(name, add);
155 #endif  ///BLE_INCLUDED == TRUE
156             }
157         } else {
158             /* delete the exceeded device info from nvs */
159             remove_iter = iter;
160             while (remove_iter != btc_config_section_end()) {
161                 const char *remove_section = btc_config_section_name(remove_iter);
162                 string_to_bdaddr(remove_section, &bd_addr);
163                 if (!string_is_bdaddr(remove_section)) {
164                     remove_iter = btc_config_section_next(remove_iter);
165                     continue;
166                 }
167                 remove_iter = btc_config_section_next(remove_iter);
168                 /* delete config info */
169                 if (btc_config_remove_section(remove_section)) {
170                     BTC_TRACE_WARNING("exceeded the maximum number of bonded devices, delete the exceed device info : %02x:%02x:%02x:%02x:%02x:%02x",
171                                 bd_addr.address[0], bd_addr.address[1], bd_addr.address[2], bd_addr.address[3], bd_addr.address[4], bd_addr.address[5]);
172                 }
173             }
174             /* write into nvs */
175             btc_config_flush();
176             break;
177         }
178     }
179     btc_config_unlock();
180 
181     return status;
182 }
183 
184 /*******************************************************************************
185 **
186 ** Function         btc_storage_load_bonded_devices
187 **
188 ** Description      BTC storage API - Loads all the bonded devices from NVRAM
189 **                  and adds to the BTA.
190 **                  Additionally, this API also invokes the adaper_properties_cb
191 **                  and remote_device_properties_cb for each of the bonded devices.
192 **
193 ** Returns          BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
194 **
195 *******************************************************************************/
btc_storage_load_bonded_devices(void)196 bt_status_t btc_storage_load_bonded_devices(void)
197 {
198     bt_status_t status;
199     status = btc_in_fetch_bonded_devices(1);
200     BTC_TRACE_DEBUG("Storage load rslt %d\n", status);
201     return status;
202 }
203 
204 /*******************************************************************************
205 **
206 ** Function         btc_storage_update_active_device
207 **
208 ** Description      BTC storage API - Once an ACL link is established and remote
209 **                  bd_addr is already stored in NVRAM, update the config and update
210 **                  the remote device to be the newest active device, The updates will
211 **                  not be stored into NVRAM immediately.
212 **
213 ** Returns          BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
214 **
215 *******************************************************************************/
btc_storage_update_active_device(bt_bdaddr_t * remote_bd_addr)216 bool btc_storage_update_active_device(bt_bdaddr_t *remote_bd_addr)
217 {
218     bdstr_t bdstr;
219     bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
220     bool ret = false;
221     BTC_TRACE_DEBUG("Update active device: Remote device:%s\n", bdstr);
222 
223     btc_config_lock();
224     ret = btc_config_update_newest_section(bdstr);
225     btc_config_unlock();
226 
227     return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
228 }
229 #endif  ///SMP_INCLUDED == TRUE
230 
231 /*******************************************************************************
232 **
233 ** Function         btc_storage_remove_bonded_device
234 **
235 ** Description      BTC storage API - Deletes the bonded device from NVRAM
236 **
237 ** Returns          BT_STATUS_SUCCESS if the deletion was successful,
238 **                  BT_STATUS_FAIL otherwise
239 **
240 *******************************************************************************/
btc_storage_remove_bonded_device(bt_bdaddr_t * remote_bd_addr)241 bt_status_t btc_storage_remove_bonded_device(bt_bdaddr_t *remote_bd_addr)
242 {
243     bdstr_t bdstr;
244     bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
245     int ret = 1;
246     BTC_TRACE_DEBUG("Add to storage: Remote device:%s\n", bdstr);
247 
248     btc_config_lock();
249     if (btc_config_exist(bdstr, BTC_STORAGE_LINK_KEY_TYPE_STR)) {
250         ret &= btc_config_remove(bdstr, BTC_STORAGE_LINK_KEY_TYPE_STR);
251     }
252     if (btc_config_exist(bdstr, BTC_STORAGE_PIN_LENGTH_STR)) {
253         ret &= btc_config_remove(bdstr, BTC_STORAGE_PIN_LENGTH_STR);
254     }
255     if (btc_config_exist(bdstr, BTC_STORAGE_LINK_KEY_STR)) {
256         ret &= btc_config_remove(bdstr, BTC_STORAGE_LINK_KEY_STR);
257     }
258     if (btc_config_exist(bdstr, BTC_STORAGE_SC_SUPPORT)) {
259         ret &= btc_config_remove(bdstr, BTC_STORAGE_SC_SUPPORT);
260     }
261     /* write bonded info immediately */
262     btc_config_flush();
263     btc_config_unlock();
264 
265     return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
266 }
267 
268 /*******************************************************************************
269 **
270 ** Function         btc_storage_get_num_bt_bond_devices
271 **
272 ** Description      BTC storage API - get the num of the bonded device from NVRAM
273 **
274 ** Returns          the num of the bonded device
275 **
276 *******************************************************************************/
btc_storage_get_num_bt_bond_devices(void)277 int btc_storage_get_num_bt_bond_devices(void)
278 {
279     int num_dev = 0;
280 
281     btc_config_lock();
282     for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
283             iter = btc_config_section_next(iter)) {
284         const char *name = btc_config_section_name(iter);
285         if (string_is_bdaddr(name) &&
286             btc_config_exist(name, BTC_STORAGE_LINK_KEY_TYPE_STR) &&
287             btc_config_exist(name, BTC_STORAGE_PIN_LENGTH_STR) &&
288             btc_config_exist(name, BTC_STORAGE_SC_SUPPORT) &&
289             btc_config_exist(name, BTC_STORAGE_LINK_KEY_STR)) {
290             num_dev++;
291         }
292     }
293     btc_config_unlock();
294     return num_dev;
295 }
296 
297 /*******************************************************************************
298 **
299 ** Function         btc_storage_get_bonded_bt_devices_list
300 **
301 ** Description      BTC storage API - get the list of the bonded device from NVRAM
302 **
303 ** Returns          BT_STATUS_SUCCESS if get the list successful,
304 **                  BT_STATUS_FAIL otherwise
305 **
306 *******************************************************************************/
btc_storage_get_bonded_bt_devices_list(bt_bdaddr_t * bond_dev,int * dev_num)307 bt_status_t btc_storage_get_bonded_bt_devices_list(bt_bdaddr_t *bond_dev, int *dev_num)
308 {
309     bt_bdaddr_t bd_addr;
310     int in_dev_num = *dev_num; /* buffer size */
311     int out_dev_num = 0; /* bond_dev size */
312 
313     btc_config_lock();
314     for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
315             iter = btc_config_section_next(iter)) {
316 
317         if (in_dev_num <= 0) {
318             break;
319         }
320 
321         const char *name = btc_config_section_name(iter);
322 
323         if (string_is_bdaddr(name) &&
324             btc_config_exist(name, BTC_STORAGE_LINK_KEY_TYPE_STR) &&
325             btc_config_exist(name, BTC_STORAGE_PIN_LENGTH_STR) &&
326             btc_config_exist(name, BTC_STORAGE_SC_SUPPORT) &&
327             btc_config_exist(name, BTC_STORAGE_LINK_KEY_STR)) {
328             string_to_bdaddr(name, &bd_addr);
329             memcpy(bond_dev, &bd_addr, sizeof(bt_bdaddr_t));
330             in_dev_num--;
331             out_dev_num++;
332             bond_dev++;
333         }
334     }
335     *dev_num = out_dev_num; /* out_dev_num <= in_dev_num */
336     btc_config_unlock();
337 
338     return BT_STATUS_SUCCESS;
339 }
340 
341 #if (defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE)
342 /*******************************************************************************
343  *
344  * Function         btc_storage_add_hid_device_info
345  *
346  * Description      BTC storage API - Adds the hid information of bonded hid
347  *                  devices-to NVRAM
348  *
349  * Returns          BT_STATUS_SUCCESS if the store was successful,
350  *                  BT_STATUS_FAIL otherwise
351  *
352  ******************************************************************************/
353 
btc_storage_add_hid_device_info(bt_bdaddr_t * remote_bd_addr,uint16_t attr_mask,uint8_t sub_class,uint8_t app_id,uint16_t vendor_id,uint16_t product_id,uint16_t version,uint8_t ctry_code,uint16_t ssr_max_latency,uint16_t ssr_min_tout,uint16_t dl_len,uint8_t * dsc_list)354 bt_status_t btc_storage_add_hid_device_info(bt_bdaddr_t *remote_bd_addr, uint16_t attr_mask, uint8_t sub_class,
355                                              uint8_t app_id, uint16_t vendor_id, uint16_t product_id, uint16_t version,
356                                              uint8_t ctry_code, uint16_t ssr_max_latency, uint16_t ssr_min_tout,
357                                              uint16_t dl_len, uint8_t *dsc_list)
358 {
359     BTC_TRACE_DEBUG("btc_storage_add_hid_device_info:");
360     bdstr_t bdstr;
361     bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
362     btc_config_lock();
363     int ret = btc_config_set_int(bdstr, "HidAttrMask", attr_mask);
364     ret &= btc_config_set_int(bdstr, "HidSubClass", sub_class);
365     ret &= btc_config_set_int(bdstr, "HidAppId", app_id);
366     ret &= btc_config_set_int(bdstr, "HidVendorId", vendor_id);
367     ret &= btc_config_set_int(bdstr, "HidProductId", product_id);
368     ret &= btc_config_set_int(bdstr, "HidVersion", version);
369     ret &= btc_config_set_int(bdstr, "HidCountryCode", ctry_code);
370     ret &= btc_config_set_int(bdstr, "HidSSRMaxLatency", ssr_max_latency);
371     ret &= btc_config_set_int(bdstr, "HidSSRMinTimeout", ssr_min_tout);
372     if (dl_len > 0)
373         btc_config_set_bin(bdstr, "HidDescriptor", dsc_list, dl_len);
374     btc_config_flush();
375     btc_config_unlock();
376 
377     BTC_TRACE_DEBUG("Storage add hid device info %d\n", ret);
378     return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
379 }
380 
381 /*******************************************************************************
382  *
383  * Function         btc_storage_load_bonded_hid_info
384  *
385  * Description      BTIF storage API - Loads hid info for all the bonded devices
386  *                  from NVRAM and adds those devices  to the BTA_HH.
387  *
388  * Returns          BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
389  *
390  ******************************************************************************/
btc_storage_load_bonded_hid_info(void)391 bt_status_t btc_storage_load_bonded_hid_info(void)
392 {
393     int value;
394     btc_config_lock();
395     for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
396          iter = btc_config_section_next(iter)) {
397         const char *name = btc_config_section_name(iter);
398         if (string_is_bdaddr(name) && btc_config_exist(name, BTC_STORAGE_LINK_KEY_TYPE_STR) &&
399             btc_config_exist(name, BTC_STORAGE_PIN_LENGTH_STR) && btc_config_exist(name, BTC_STORAGE_SC_SUPPORT) &&
400             btc_config_exist(name, BTC_STORAGE_LINK_KEY_STR) && btc_config_exist(name, "HidAttrMask")) {
401             btc_config_get_int(name, "HidAttrMask", &value);
402             uint16_t attr_mask = (uint16_t)value;
403 
404             tBTA_HH_DEV_DSCP_INFO dscp_info;
405             memset(&dscp_info, 0, sizeof(dscp_info));
406 
407             btc_config_get_int(name, "HidSubClass", &value);
408             uint8_t sub_class = (uint8_t)value;
409 
410             btc_config_get_int(name, "HidAppId", &value);
411             uint8_t app_id = (uint8_t)value;
412 
413             btc_config_get_int(name, "HidVendorId", &value);
414             dscp_info.vendor_id = (uint16_t)value;
415 
416             btc_config_get_int(name, "HidProductId", &value);
417             dscp_info.product_id = (uint16_t)value;
418 
419             btc_config_get_int(name, "HidVersion", &value);
420             dscp_info.version = (uint8_t)value;
421 
422             btc_config_get_int(name, "HidCountryCode", &value);
423             dscp_info.ctry_code = (uint8_t)value;
424 
425             value = 0;
426             btc_config_get_int(name, "HidSSRMaxLatency", &value);
427             dscp_info.ssr_max_latency = (uint16_t)value;
428 
429             value = 0;
430             btc_config_get_int(name, "HidSSRMinTimeout", &value);
431             dscp_info.ssr_min_tout = (uint16_t)value;
432 
433             size_t len = btc_config_get_bin_length(name, "HidDescriptor");
434             if (len > 0) {
435                 dscp_info.descriptor.dl_len = (uint16_t)len;
436                 dscp_info.descriptor.dsc_list = (uint8_t *)osi_malloc(len);
437                 btc_config_get_bin(name, "HidDescriptor", (uint8_t *)dscp_info.descriptor.dsc_list, &len);
438             }
439 
440             // add extracted information to BTA HH
441             bt_bdaddr_t bd_addr;
442             if (string_to_bdaddr(name, &bd_addr) && btc_hh_add_added_dev(*(BD_ADDR *)&bd_addr, attr_mask)) {
443                 BTA_HhAddDev(*(BD_ADDR *)&bd_addr, attr_mask, sub_class, app_id, dscp_info);
444             }
445 
446             if (dscp_info.descriptor.dsc_list) {
447                 osi_free(dscp_info.descriptor.dsc_list);
448                 dscp_info.descriptor.dsc_list = NULL;
449             }
450         }
451     }
452     btc_config_unlock();
453     return BT_STATUS_SUCCESS;
454 }
455 
456 /*******************************************************************************
457  *
458  * Function         btc_storage_remove_hid_info
459  *
460  * Description      BTC storage API - Deletes the bonded hid device info from
461  *                  NVRAM
462  *
463  * Returns          BT_STATUS_SUCCESS if the deletion was successful,
464  *                  BT_STATUS_FAIL otherwise
465  *
466  ******************************************************************************/
btc_storage_remove_hid_info(bt_bdaddr_t * remote_bd_addr)467 bt_status_t btc_storage_remove_hid_info(bt_bdaddr_t *remote_bd_addr)
468 {
469     bdstr_t bdstr;
470     bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
471     int ret = 1;
472     btc_config_lock();
473     if (btc_config_exist(bdstr, "HidAttrMask")) {
474         ret &= btc_config_remove(bdstr, "HidAttrMask");
475     }
476     if (btc_config_exist(bdstr, "HidSubClass")) {
477         ret &= btc_config_remove(bdstr, "HidSubClass");
478     }
479     if (btc_config_exist(bdstr, "HidAppId")) {
480         ret &= btc_config_remove(bdstr, "HidAppId");
481     }
482     if (btc_config_exist(bdstr, "HidVendorId")) {
483         ret &= btc_config_remove(bdstr, "HidVendorId");
484     }
485     if (btc_config_exist(bdstr, "HidProductId")) {
486         ret &= btc_config_remove(bdstr, "HidProductId");
487     }
488     if (btc_config_exist(bdstr, "HidVersion")) {
489         ret &= btc_config_remove(bdstr, "HidVersion");
490     }
491     if (btc_config_exist(bdstr, "HidCountryCode")) {
492         ret &= btc_config_remove(bdstr, "HidCountryCode");
493     }
494     if (btc_config_exist(bdstr, "HidSSRMaxLatency")) {
495         ret &= btc_config_remove(bdstr, "HidSSRMaxLatency");
496     }
497     if (btc_config_exist(bdstr, "HidSSRMinTimeout")) {
498         ret &= btc_config_remove(bdstr, "HidSSRMinTimeout");
499     }
500     if (btc_config_exist(bdstr, "HidDescriptor")) {
501         ret &= btc_config_remove(bdstr, "HidDescriptor");
502     }
503     btc_config_flush();
504     btc_config_unlock();
505     BTC_TRACE_DEBUG("%s ret:%d", __func__, ret);
506     return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
507 }
508 #endif //(defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE)
509 
510 #if (defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE)
511 #include "bta/bta_hd_api.h"
512 /*******************************************************************************
513  * Function         btc_storage_load_hidd
514  *
515  * Description      Loads hidd bonded device and "plugs" it into hidd
516  *
517  * Returns          BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
518  *
519  ******************************************************************************/
btc_storage_load_hidd(void)520 bt_status_t btc_storage_load_hidd(void)
521 {
522     bt_bdaddr_t bd_addr;
523     int value;
524     btc_config_lock();
525     for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
526          iter = btc_config_section_next(iter)) {
527         const char *name = btc_config_section_name(iter);
528         if (string_is_bdaddr(name) && btc_config_exist(name, BTC_STORAGE_LINK_KEY_TYPE_STR) &&
529             btc_config_exist(name, BTC_STORAGE_PIN_LENGTH_STR) && btc_config_exist(name, BTC_STORAGE_SC_SUPPORT) &&
530             btc_config_exist(name, BTC_STORAGE_LINK_KEY_STR)) {
531             BTC_TRACE_DEBUG("Remote device:%s", name);
532             if (btc_config_get_int(name, "HidDeviceCabled", &value)) {
533                 string_to_bdaddr(name, &bd_addr);
534                 BTA_HdAddDevice(bd_addr.address);
535                 break;
536             }
537         }
538     }
539     btc_config_unlock();
540     return BT_STATUS_SUCCESS;
541 }
542 
543 /*******************************************************************************
544  *
545  * Function         btc_storage_set_hidd
546  *
547  * Description      Stores hidd bonded device info in nvram.
548  *
549  * Returns          BT_STATUS_SUCCESS
550  *
551  ******************************************************************************/
btc_storage_set_hidd(bt_bdaddr_t * remote_bd_addr)552 bt_status_t btc_storage_set_hidd(bt_bdaddr_t *remote_bd_addr)
553 {
554     bdstr_t bdstr = {0};
555     bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
556     btc_config_lock();
557     int ret = btc_config_set_int(bdstr, "HidDeviceCabled", 1);
558     btc_config_flush();
559     btc_config_unlock();
560     BTC_TRACE_DEBUG("%s ret:%d", __func__, ret);
561     return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
562 }
563 
564 /*******************************************************************************
565  *
566  * Function         btc_storage_remove_hidd
567  *
568  * Description      Removes hidd bonded device info from nvram
569  *
570  * Returns          BT_STATUS_SUCCESS
571  *
572  ******************************************************************************/
btc_storage_remove_hidd(bt_bdaddr_t * remote_bd_addr)573 bt_status_t btc_storage_remove_hidd(bt_bdaddr_t *remote_bd_addr)
574 {
575     bdstr_t bdstr;
576     int ret = 0;
577     bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
578     btc_config_lock();
579     if (btc_config_exist(bdstr, "HidVersion")) {
580         ret = btc_config_remove(bdstr, "HidDeviceCabled");
581     }
582     btc_config_flush();
583     btc_config_unlock();
584 
585     BTC_TRACE_DEBUG("%s ret:%d", __func__, ret);
586     return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
587 }
588 #endif //(defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE)
589 
btc_storage_get_num_all_bond_devices(void)590 int btc_storage_get_num_all_bond_devices(void) {
591     int num_dev = 0;
592 
593     btc_config_lock();
594     for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
595         iter = btc_config_section_next(iter)) {
596         const char *name = btc_config_section_name(iter);
597         if (string_is_bdaddr(name)) {
598             num_dev++;
599         }
600     }
601     btc_config_unlock();
602     return num_dev;
603 }
604