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