1 // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include <string.h>
15 
16 #include "btc/btc_storage.h"
17 #include "btc/btc_util.h"
18 #include "osi/osi.h"
19 #include "osi/allocator.h"
20 #include "common/bt_trace.h"
21 #include "esp_system.h"
22 #include "bta/bta_api.h"
23 #include "device/bdaddr.h"
24 #include "btc/btc_config.h"
25 #include "btc_hh.h"
26 
27 /*******************************************************************************
28 **
29 ** Function         btc_storage_add_bonded_device
30 **
31 ** Description      BTIF storage API - Adds the newly bonded device to NVRAM
32 **                  along with the link-key, Key type and Pin key length
33 **
34 ** Returns          BT_STATUS_SUCCESS if the store was successful,
35 **                  BT_STATUS_FAIL otherwise
36 **
37 *******************************************************************************/
38 
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)39 bt_status_t btc_storage_add_bonded_device(bt_bdaddr_t *remote_bd_addr,
40         LINK_KEY link_key,
41         uint8_t key_type,
42         uint8_t pin_length,
43         BOOLEAN sc_support)
44 {
45     bdstr_t bdstr;
46 
47     bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
48     BTC_TRACE_DEBUG("add to storage: Remote device:%s\n", bdstr);
49 
50     btc_config_lock();
51     int ret = btc_config_set_int(bdstr, BTC_STORAGE_LINK_KEY_TYPE_STR, (int)key_type);
52     ret &= btc_config_set_int(bdstr, BTC_STORAGE_PIN_LENGTH_STR, (int)pin_length);
53     ret &= btc_config_set_bin(bdstr, BTC_STORAGE_LINK_KEY_STR, link_key, sizeof(LINK_KEY));
54     ret &= btc_config_set_bin(bdstr, BTC_STORAGE_SC_SUPPORT, (uint8_t *)&sc_support, sizeof(sc_support));
55     /* write bonded info immediately */
56     btc_config_flush();
57     btc_config_unlock();
58 
59     BTC_TRACE_DEBUG("Storage add rslt %d\n", ret);
60     return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
61 }
62 
63 /*******************************************************************************
64 **
65 ** Function         btc_in_fetch_bonded_devices
66 **
67 ** Description      Internal helper function to fetch the bonded devices
68 **                  from NVRAM
69 **
70 ** Returns          BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
71 **
72 *******************************************************************************/
btc_in_fetch_bonded_devices(int add)73 static bt_status_t btc_in_fetch_bonded_devices(int add)
74 {
75     BOOLEAN bt_linkkey_file_found = FALSE;
76     UINT8 sc_support = 0;
77 
78     btc_config_lock();
79     for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end(); iter = btc_config_section_next(iter)) {
80         const char *name = btc_config_section_name(iter);
81         if (!string_is_bdaddr(name)) {
82             continue;
83         }
84 
85         BTC_TRACE_DEBUG("Remote device:%s\n", name);
86         LINK_KEY link_key;
87         size_t size = sizeof(link_key);
88         if (btc_config_get_bin(name, BTC_STORAGE_LINK_KEY_STR, link_key, &size)) {
89             int linkkey_type;
90             if (btc_config_get_int(name, BTC_STORAGE_LINK_KEY_TYPE_STR, &linkkey_type)) {
91                 bt_bdaddr_t bd_addr;
92                 string_to_bdaddr(name, &bd_addr);
93                 if (add) {
94                     DEV_CLASS dev_class = {0, 0, 0};
95                     int cod;
96                     int pin_length = 0;
97                     if (btc_config_get_int(name, BTC_STORAGE_DEV_CLASS_STR, &cod)) {
98                         uint2devclass((UINT32)cod, dev_class);
99                     }
100                     btc_config_get_int(name, BTC_STORAGE_PIN_LENGTH_STR, &pin_length);
101                     size = sizeof(sc_support);
102                     btc_config_get_bin(name, BTC_STORAGE_SC_SUPPORT, &sc_support, &size);
103 #if (SMP_INCLUDED == TRUE)
104                     BTA_DmAddDevice(bd_addr.address, dev_class, link_key, 0, 0,
105                                     (UINT8)linkkey_type, 0, pin_length, (UINT8)sc_support);
106 #endif  ///SMP_INCLUDED == TRUE
107                 }
108                 bt_linkkey_file_found = TRUE;
109             } else {
110                 BTC_TRACE_ERROR("bounded device:%s, LinkKeyType or PinLength is invalid\n", name);
111             }
112         }
113         if (!bt_linkkey_file_found) {
114             BTC_TRACE_DEBUG("Remote device:%s, no link key\n", name);
115         }
116     }
117     btc_config_unlock();
118 
119     return BT_STATUS_SUCCESS;
120 }
121 
122 
123 /*******************************************************************************
124 **
125 ** Function         btc_storage_load_bonded_devices
126 **
127 ** Description      BTC storage API - Loads all the bonded devices from NVRAM
128 **                  and adds to the BTA.
129 **                  Additionally, this API also invokes the adaper_properties_cb
130 **                  and remote_device_properties_cb for each of the bonded devices.
131 **
132 ** Returns          BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
133 **
134 *******************************************************************************/
btc_storage_load_bonded_devices(void)135 bt_status_t btc_storage_load_bonded_devices(void)
136 {
137     bt_status_t status;
138     status = btc_in_fetch_bonded_devices(1);
139     BTC_TRACE_DEBUG("Storage load rslt %d\n", status);
140     return status;
141 }
142 
143 /*******************************************************************************
144 **
145 ** Function         btc_storage_remove_bonded_device
146 **
147 ** Description      BTC storage API - Deletes the bonded device from NVRAM
148 **
149 ** Returns          BT_STATUS_SUCCESS if the deletion was successful,
150 **                  BT_STATUS_FAIL otherwise
151 **
152 *******************************************************************************/
btc_storage_remove_bonded_device(bt_bdaddr_t * remote_bd_addr)153 bt_status_t btc_storage_remove_bonded_device(bt_bdaddr_t *remote_bd_addr)
154 {
155     bdstr_t bdstr;
156     bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
157     int ret = 1;
158     BTC_TRACE_DEBUG("Add to storage: Remote device:%s\n", bdstr);
159 
160     btc_config_lock();
161     if (btc_config_exist(bdstr, BTC_STORAGE_LINK_KEY_TYPE_STR)) {
162         ret &= btc_config_remove(bdstr, BTC_STORAGE_LINK_KEY_TYPE_STR);
163     }
164     if (btc_config_exist(bdstr, BTC_STORAGE_PIN_LENGTH_STR)) {
165         ret &= btc_config_remove(bdstr, BTC_STORAGE_PIN_LENGTH_STR);
166     }
167     if (btc_config_exist(bdstr, BTC_STORAGE_LINK_KEY_STR)) {
168         ret &= btc_config_remove(bdstr, BTC_STORAGE_LINK_KEY_STR);
169     }
170     if (btc_config_exist(bdstr, BTC_STORAGE_SC_SUPPORT)) {
171         ret &= btc_config_remove(bdstr, BTC_STORAGE_SC_SUPPORT);
172     }
173     /* write bonded info immediately */
174     btc_config_flush();
175     btc_config_unlock();
176 
177     return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
178 }
179 
180 /*******************************************************************************
181 **
182 ** Function         btc_storage_get_num_bt_bond_devices
183 **
184 ** Description      BTC storage API - get the num of the bonded device from NVRAM
185 **
186 ** Returns          the num of the bonded device
187 **
188 *******************************************************************************/
btc_storage_get_num_bt_bond_devices(void)189 int btc_storage_get_num_bt_bond_devices(void)
190 {
191     int num_dev = 0;
192 
193     btc_config_lock();
194     for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
195             iter = btc_config_section_next(iter)) {
196         const char *name = btc_config_section_name(iter);
197         if (string_is_bdaddr(name) &&
198             btc_config_exist(name, BTC_STORAGE_LINK_KEY_TYPE_STR) &&
199             btc_config_exist(name, BTC_STORAGE_PIN_LENGTH_STR) &&
200             btc_config_exist(name, BTC_STORAGE_SC_SUPPORT) &&
201             btc_config_exist(name, BTC_STORAGE_LINK_KEY_STR)) {
202             num_dev++;
203         }
204     }
205     btc_config_unlock();
206     return num_dev;
207 }
208 
209 /*******************************************************************************
210 **
211 ** Function         btc_storage_get_bonded_bt_devices_list
212 **
213 ** Description      BTC storage API - get the list of the bonded device from NVRAM
214 **
215 ** Returns          BT_STATUS_SUCCESS if get the list successful,
216 **                  BT_STATUS_FAIL otherwise
217 **
218 *******************************************************************************/
btc_storage_get_bonded_bt_devices_list(bt_bdaddr_t * bond_dev,int * dev_num)219 bt_status_t btc_storage_get_bonded_bt_devices_list(bt_bdaddr_t *bond_dev, int *dev_num)
220 {
221     bt_bdaddr_t bd_addr;
222     int in_dev_num = *dev_num; /* buffer size */
223     int out_dev_num = 0; /* bond_dev size */
224 
225     btc_config_lock();
226     for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
227             iter = btc_config_section_next(iter)) {
228 
229         if (in_dev_num <= 0) {
230             break;
231         }
232 
233         const char *name = btc_config_section_name(iter);
234 
235         if (string_is_bdaddr(name) &&
236             btc_config_exist(name, BTC_STORAGE_LINK_KEY_TYPE_STR) &&
237             btc_config_exist(name, BTC_STORAGE_PIN_LENGTH_STR) &&
238             btc_config_exist(name, BTC_STORAGE_SC_SUPPORT) &&
239             btc_config_exist(name, BTC_STORAGE_LINK_KEY_STR)) {
240             string_to_bdaddr(name, &bd_addr);
241             memcpy(bond_dev, &bd_addr, sizeof(bt_bdaddr_t));
242             in_dev_num--;
243             out_dev_num++;
244             bond_dev++;
245         }
246     }
247     *dev_num = out_dev_num; /* out_dev_num <= in_dev_num */
248     btc_config_unlock();
249 
250     return BT_STATUS_SUCCESS;
251 }
252 
253 #if (defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE)
254 /*******************************************************************************
255  *
256  * Function         btc_storage_add_hid_device_info
257  *
258  * Description      BTC storage API - Adds the hid information of bonded hid
259  *                  devices-to NVRAM
260  *
261  * Returns          BT_STATUS_SUCCESS if the store was successful,
262  *                  BT_STATUS_FAIL otherwise
263  *
264  ******************************************************************************/
265 
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)266 bt_status_t btc_storage_add_hid_device_info(bt_bdaddr_t *remote_bd_addr, uint16_t attr_mask, uint8_t sub_class,
267                                              uint8_t app_id, uint16_t vendor_id, uint16_t product_id, uint16_t version,
268                                              uint8_t ctry_code, uint16_t ssr_max_latency, uint16_t ssr_min_tout,
269                                              uint16_t dl_len, uint8_t *dsc_list)
270 {
271     BTC_TRACE_DEBUG("btc_storage_add_hid_device_info:");
272     bdstr_t bdstr;
273     bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
274     btc_config_lock();
275     int ret = btc_config_set_int(bdstr, "HidAttrMask", attr_mask);
276     ret &= btc_config_set_int(bdstr, "HidSubClass", sub_class);
277     ret &= btc_config_set_int(bdstr, "HidAppId", app_id);
278     ret &= btc_config_set_int(bdstr, "HidVendorId", vendor_id);
279     ret &= btc_config_set_int(bdstr, "HidProductId", product_id);
280     ret &= btc_config_set_int(bdstr, "HidVersion", version);
281     ret &= btc_config_set_int(bdstr, "HidCountryCode", ctry_code);
282     ret &= btc_config_set_int(bdstr, "HidSSRMaxLatency", ssr_max_latency);
283     ret &= btc_config_set_int(bdstr, "HidSSRMinTimeout", ssr_min_tout);
284     if (dl_len > 0)
285         btc_config_set_bin(bdstr, "HidDescriptor", dsc_list, dl_len);
286     btc_config_flush();
287     btc_config_unlock();
288 
289     BTC_TRACE_DEBUG("Storage add hid device info %d\n", ret);
290     return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
291 }
292 
293 /*******************************************************************************
294  *
295  * Function         btc_storage_load_bonded_hid_info
296  *
297  * Description      BTIF storage API - Loads hid info for all the bonded devices
298  *                  from NVRAM and adds those devices  to the BTA_HH.
299  *
300  * Returns          BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
301  *
302  ******************************************************************************/
btc_storage_load_bonded_hid_info(void)303 bt_status_t btc_storage_load_bonded_hid_info(void)
304 {
305     int value;
306     btc_config_lock();
307     for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
308          iter = btc_config_section_next(iter)) {
309         const char *name = btc_config_section_name(iter);
310         if (string_is_bdaddr(name) && btc_config_exist(name, BTC_STORAGE_LINK_KEY_TYPE_STR) &&
311             btc_config_exist(name, BTC_STORAGE_PIN_LENGTH_STR) && btc_config_exist(name, BTC_STORAGE_SC_SUPPORT) &&
312             btc_config_exist(name, BTC_STORAGE_LINK_KEY_STR) && btc_config_exist(name, "HidAttrMask")) {
313             btc_config_get_int(name, "HidAttrMask", &value);
314             uint16_t attr_mask = (uint16_t)value;
315 
316             tBTA_HH_DEV_DSCP_INFO dscp_info;
317             memset(&dscp_info, 0, sizeof(dscp_info));
318 
319             btc_config_get_int(name, "HidSubClass", &value);
320             uint8_t sub_class = (uint8_t)value;
321 
322             btc_config_get_int(name, "HidAppId", &value);
323             uint8_t app_id = (uint8_t)value;
324 
325             btc_config_get_int(name, "HidVendorId", &value);
326             dscp_info.vendor_id = (uint16_t)value;
327 
328             btc_config_get_int(name, "HidProductId", &value);
329             dscp_info.product_id = (uint16_t)value;
330 
331             btc_config_get_int(name, "HidVersion", &value);
332             dscp_info.version = (uint8_t)value;
333 
334             btc_config_get_int(name, "HidCountryCode", &value);
335             dscp_info.ctry_code = (uint8_t)value;
336 
337             value = 0;
338             btc_config_get_int(name, "HidSSRMaxLatency", &value);
339             dscp_info.ssr_max_latency = (uint16_t)value;
340 
341             value = 0;
342             btc_config_get_int(name, "HidSSRMinTimeout", &value);
343             dscp_info.ssr_min_tout = (uint16_t)value;
344 
345             size_t len = btc_config_get_bin_length(name, "HidDescriptor");
346             if (len > 0) {
347                 dscp_info.descriptor.dl_len = (uint16_t)len;
348                 dscp_info.descriptor.dsc_list = (uint8_t *)osi_malloc(len);
349                 btc_config_get_bin(name, "HidDescriptor", (uint8_t *)dscp_info.descriptor.dsc_list, &len);
350             }
351 
352             // add extracted information to BTA HH
353             bt_bdaddr_t bd_addr;
354             if (string_to_bdaddr(name, &bd_addr) && btc_hh_add_added_dev(*(BD_ADDR *)&bd_addr, attr_mask)) {
355                 BTA_HhAddDev(*(BD_ADDR *)&bd_addr, attr_mask, sub_class, app_id, dscp_info);
356             }
357 
358             if (dscp_info.descriptor.dsc_list) {
359                 osi_free(dscp_info.descriptor.dsc_list);
360                 dscp_info.descriptor.dsc_list = NULL;
361             }
362         }
363     }
364     btc_config_unlock();
365     return BT_STATUS_SUCCESS;
366 }
367 
368 /*******************************************************************************
369  *
370  * Function         btc_storage_remove_hid_info
371  *
372  * Description      BTC storage API - Deletes the bonded hid device info from
373  *                  NVRAM
374  *
375  * Returns          BT_STATUS_SUCCESS if the deletion was successful,
376  *                  BT_STATUS_FAIL otherwise
377  *
378  ******************************************************************************/
btc_storage_remove_hid_info(bt_bdaddr_t * remote_bd_addr)379 bt_status_t btc_storage_remove_hid_info(bt_bdaddr_t *remote_bd_addr)
380 {
381     bdstr_t bdstr;
382     bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
383     int ret = 1;
384     btc_config_lock();
385     if (btc_config_exist(bdstr, "HidAttrMask")) {
386         ret &= btc_config_remove(bdstr, "HidAttrMask");
387     }
388     if (btc_config_exist(bdstr, "HidSubClass")) {
389         ret &= btc_config_remove(bdstr, "HidSubClass");
390     }
391     if (btc_config_exist(bdstr, "HidAppId")) {
392         ret &= btc_config_remove(bdstr, "HidAppId");
393     }
394     if (btc_config_exist(bdstr, "HidVendorId")) {
395         ret &= btc_config_remove(bdstr, "HidVendorId");
396     }
397     if (btc_config_exist(bdstr, "HidProductId")) {
398         ret &= btc_config_remove(bdstr, "HidProductId");
399     }
400     if (btc_config_exist(bdstr, "HidVersion")) {
401         ret &= btc_config_remove(bdstr, "HidVersion");
402     }
403     if (btc_config_exist(bdstr, "HidCountryCode")) {
404         ret &= btc_config_remove(bdstr, "HidCountryCode");
405     }
406     if (btc_config_exist(bdstr, "HidSSRMaxLatency")) {
407         ret &= btc_config_remove(bdstr, "HidSSRMaxLatency");
408     }
409     if (btc_config_exist(bdstr, "HidSSRMinTimeout")) {
410         ret &= btc_config_remove(bdstr, "HidSSRMinTimeout");
411     }
412     if (btc_config_exist(bdstr, "HidDescriptor")) {
413         ret &= btc_config_remove(bdstr, "HidDescriptor");
414     }
415     btc_config_flush();
416     btc_config_unlock();
417     BTC_TRACE_DEBUG("%s ret:%d", __func__, ret);
418     return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
419 }
420 #endif //(defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE)
421 
422 #if (defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE)
423 #include "bta/bta_hd_api.h"
424 /*******************************************************************************
425  * Function         btc_storage_load_hidd
426  *
427  * Description      Loads hidd bonded device and "plugs" it into hidd
428  *
429  * Returns          BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
430  *
431  ******************************************************************************/
btc_storage_load_hidd(void)432 bt_status_t btc_storage_load_hidd(void)
433 {
434     bt_bdaddr_t bd_addr;
435     int value;
436     btc_config_lock();
437     for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
438          iter = btc_config_section_next(iter)) {
439         const char *name = btc_config_section_name(iter);
440         if (string_is_bdaddr(name) && btc_config_exist(name, BTC_STORAGE_LINK_KEY_TYPE_STR) &&
441             btc_config_exist(name, BTC_STORAGE_PIN_LENGTH_STR) && btc_config_exist(name, BTC_STORAGE_SC_SUPPORT) &&
442             btc_config_exist(name, BTC_STORAGE_LINK_KEY_STR)) {
443             BTC_TRACE_DEBUG("Remote device:%s", name);
444             if (btc_config_get_int(name, "HidDeviceCabled", &value)) {
445                 string_to_bdaddr(name, &bd_addr);
446                 BTA_HdAddDevice(bd_addr.address);
447                 break;
448             }
449         }
450     }
451     btc_config_unlock();
452     return BT_STATUS_SUCCESS;
453 }
454 
455 /*******************************************************************************
456  *
457  * Function         btc_storage_set_hidd
458  *
459  * Description      Stores hidd bonded device info in nvram.
460  *
461  * Returns          BT_STATUS_SUCCESS
462  *
463  ******************************************************************************/
btc_storage_set_hidd(bt_bdaddr_t * remote_bd_addr)464 bt_status_t btc_storage_set_hidd(bt_bdaddr_t *remote_bd_addr)
465 {
466     bdstr_t bdstr = {0};
467     bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
468     btc_config_lock();
469     int ret = btc_config_set_int(bdstr, "HidDeviceCabled", 1);
470     btc_config_flush();
471     btc_config_unlock();
472     BTC_TRACE_DEBUG("%s ret:%d", __func__, ret);
473     return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
474 }
475 
476 /*******************************************************************************
477  *
478  * Function         btc_storage_remove_hidd
479  *
480  * Description      Removes hidd bonded device info from nvram
481  *
482  * Returns          BT_STATUS_SUCCESS
483  *
484  ******************************************************************************/
btc_storage_remove_hidd(bt_bdaddr_t * remote_bd_addr)485 bt_status_t btc_storage_remove_hidd(bt_bdaddr_t *remote_bd_addr)
486 {
487     bdstr_t bdstr;
488     int ret = 0;
489     bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
490     btc_config_lock();
491     if (btc_config_exist(bdstr, "HidVersion")) {
492         ret = btc_config_remove(bdstr, "HidDeviceCabled");
493     }
494     btc_config_flush();
495     btc_config_unlock();
496 
497     BTC_TRACE_DEBUG("%s ret:%d", __func__, ret);
498     return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
499 }
500 #endif //(defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE)
501