113e71c7bSMatthias Ringwald /*
213e71c7bSMatthias Ringwald * Copyright (C) 2016 BlueKitchen GmbH
313e71c7bSMatthias Ringwald *
413e71c7bSMatthias Ringwald * Redistribution and use in source and binary forms, with or without
513e71c7bSMatthias Ringwald * modification, are permitted provided that the following conditions
613e71c7bSMatthias Ringwald * are met:
713e71c7bSMatthias Ringwald *
813e71c7bSMatthias Ringwald * 1. Redistributions of source code must retain the above copyright
913e71c7bSMatthias Ringwald * notice, this list of conditions and the following disclaimer.
1013e71c7bSMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright
1113e71c7bSMatthias Ringwald * notice, this list of conditions and the following disclaimer in the
1213e71c7bSMatthias Ringwald * documentation and/or other materials provided with the distribution.
1313e71c7bSMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of
1413e71c7bSMatthias Ringwald * contributors may be used to endorse or promote products derived
1513e71c7bSMatthias Ringwald * from this software without specific prior written permission.
1613e71c7bSMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for
1713e71c7bSMatthias Ringwald * personal benefit and not for any commercial purpose or for
1813e71c7bSMatthias Ringwald * monetary gain.
1913e71c7bSMatthias Ringwald *
2013e71c7bSMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
2113e71c7bSMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2213e71c7bSMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*2fca4dadSMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24*2fca4dadSMilanka Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2513e71c7bSMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2613e71c7bSMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
2713e71c7bSMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2813e71c7bSMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2913e71c7bSMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
3013e71c7bSMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3113e71c7bSMatthias Ringwald * SUCH DAMAGE.
3213e71c7bSMatthias Ringwald *
3313e71c7bSMatthias Ringwald * Please inquire about commercial licensing options at
3413e71c7bSMatthias Ringwald * [email protected]
3513e71c7bSMatthias Ringwald *
3613e71c7bSMatthias Ringwald */
3713e71c7bSMatthias Ringwald
38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "le_device_db_wiced_dct.c"
3913e71c7bSMatthias Ringwald
4013e71c7bSMatthias Ringwald /*
4113e71c7bSMatthias Ringwald * le_device_db_wiced_dct.c
4213e71c7bSMatthias Ringwald *
4313e71c7bSMatthias Ringwald * Persistent LE Device DB implemenetation for WICED using DCT mechanism
4413e71c7bSMatthias Ringwald */
4513e71c7bSMatthias Ringwald
4613e71c7bSMatthias Ringwald #include "stdint.h"
4713e71c7bSMatthias Ringwald #include "string.h"
4813e71c7bSMatthias Ringwald #include "inttypes.h"
4913e71c7bSMatthias Ringwald
5013e71c7bSMatthias Ringwald #include "wiced.h"
5113e71c7bSMatthias Ringwald
5213e71c7bSMatthias Ringwald #include "ble/le_device_db.h"
5313e71c7bSMatthias Ringwald #include "btstack_link_key_db_wiced_dct.h" // for size of
5413e71c7bSMatthias Ringwald
5513e71c7bSMatthias Ringwald #include "btstack_debug.h"
5613e71c7bSMatthias Ringwald #include "btstack_util.h"
5713e71c7bSMatthias Ringwald
5813e71c7bSMatthias Ringwald // Link Key Magic
5913e71c7bSMatthias Ringwald #define LE_DEVICE_MAGIC ((uint32_t) 'L' << 24 | 'E' << 16 | 'D' << 8 | 'B')
6013e71c7bSMatthias Ringwald
6113e71c7bSMatthias Ringwald typedef struct le_device_nvm {
6213e71c7bSMatthias Ringwald uint32_t magic;
6313e71c7bSMatthias Ringwald uint32_t seq_nr; // used for "last recently stored" eviction strategy
6413e71c7bSMatthias Ringwald
6513e71c7bSMatthias Ringwald // Identification
6613e71c7bSMatthias Ringwald sm_key_t irk;
6713e71c7bSMatthias Ringwald bd_addr_t addr;
6813e71c7bSMatthias Ringwald uint8_t addr_type;
6913e71c7bSMatthias Ringwald
7013e71c7bSMatthias Ringwald // pairing information
7113e71c7bSMatthias Ringwald uint8_t key_size;
7213e71c7bSMatthias Ringwald uint8_t authenticated;
7313e71c7bSMatthias Ringwald uint8_t authorized;
743dc3a67dSMatthias Ringwald uint8_t secure_connection;
753dc3a67dSMatthias Ringwald
7613e71c7bSMatthias Ringwald sm_key_t ltk;
7713e71c7bSMatthias Ringwald
7813e71c7bSMatthias Ringwald // Stored pairing information allows to re-establish an enncrypted connection
7913e71c7bSMatthias Ringwald // with a peripheral that doesn't have any persistent memory
8013e71c7bSMatthias Ringwald uint16_t ediv;
8113e71c7bSMatthias Ringwald uint8_t rand[8];
8213e71c7bSMatthias Ringwald
8313e71c7bSMatthias Ringwald } le_device_nvm_t;
8413e71c7bSMatthias Ringwald
8513e71c7bSMatthias Ringwald static uint32_t start_of_le_device_db;
8613e71c7bSMatthias Ringwald
8713e71c7bSMatthias Ringwald // calculate address
le_device_db_address_for_absolute_index(int abolute_index)8813e71c7bSMatthias Ringwald static int le_device_db_address_for_absolute_index(int abolute_index){
8913e71c7bSMatthias Ringwald return start_of_le_device_db + abolute_index * sizeof(le_device_nvm_t);
9013e71c7bSMatthias Ringwald }
9113e71c7bSMatthias Ringwald
le_device_db_entry_valid(int absolute_index)9213e71c7bSMatthias Ringwald static int le_device_db_entry_valid(int absolute_index){
9313e71c7bSMatthias Ringwald // read lock
9413e71c7bSMatthias Ringwald le_device_nvm_t * entry;
9513e71c7bSMatthias Ringwald wiced_dct_read_lock((void*) &entry, WICED_FALSE, DCT_APP_SECTION, le_device_db_address_for_absolute_index(absolute_index), sizeof(le_device_nvm_t));
9613e71c7bSMatthias Ringwald int valid = entry->magic == LE_DEVICE_MAGIC;
9713e71c7bSMatthias Ringwald // read unlock
9813e71c7bSMatthias Ringwald wiced_dct_read_unlock((void*) entry, WICED_FALSE);
9913e71c7bSMatthias Ringwald return valid;
10013e71c7bSMatthias Ringwald }
10113e71c7bSMatthias Ringwald
10213e71c7bSMatthias Ringwald // @return valid
le_device_db_entry_read(int absolute_index,le_device_nvm_t * out_entry)10313e71c7bSMatthias Ringwald static int le_device_db_entry_read(int absolute_index, le_device_nvm_t * out_entry){
10413e71c7bSMatthias Ringwald
10513e71c7bSMatthias Ringwald // read lock
10613e71c7bSMatthias Ringwald le_device_nvm_t * entry;
10713e71c7bSMatthias Ringwald wiced_dct_read_lock((void*) &entry, WICED_FALSE, DCT_APP_SECTION, le_device_db_address_for_absolute_index(absolute_index), sizeof(le_device_nvm_t));
10813e71c7bSMatthias Ringwald
10913e71c7bSMatthias Ringwald if (entry->magic == LE_DEVICE_MAGIC){
11013e71c7bSMatthias Ringwald memcpy(out_entry, entry, sizeof(le_device_nvm_t));
11113e71c7bSMatthias Ringwald } else {
11213e71c7bSMatthias Ringwald memset(out_entry, 0, sizeof(le_device_nvm_t));
11313e71c7bSMatthias Ringwald }
11413e71c7bSMatthias Ringwald
11513e71c7bSMatthias Ringwald // read unlock
11613e71c7bSMatthias Ringwald wiced_dct_read_unlock((void*) entry, WICED_FALSE);
11713e71c7bSMatthias Ringwald
11813e71c7bSMatthias Ringwald return out_entry->magic == LE_DEVICE_MAGIC;
11913e71c7bSMatthias Ringwald }
12013e71c7bSMatthias Ringwald
le_device_db_entry_write(int absolute_index,le_device_nvm_t * entry)12113e71c7bSMatthias Ringwald static void le_device_db_entry_write(int absolute_index, le_device_nvm_t * entry){
12213e71c7bSMatthias Ringwald // write block
12313e71c7bSMatthias Ringwald wiced_dct_write((void*)entry, DCT_APP_SECTION, le_device_db_address_for_absolute_index(absolute_index), sizeof(le_device_nvm_t));
12413e71c7bSMatthias Ringwald }
12513e71c7bSMatthias Ringwald
le_device_db_highest_seq_nr(void)12613e71c7bSMatthias Ringwald static uint32_t le_device_db_highest_seq_nr(void){
12713e71c7bSMatthias Ringwald le_device_nvm_t entry;
12813e71c7bSMatthias Ringwald int i;
12913e71c7bSMatthias Ringwald uint32_t seq_nr = 0;
13013e71c7bSMatthias Ringwald for (i=0;i<NVM_NUM_LE_DEVICES;i++){
13113e71c7bSMatthias Ringwald le_device_db_entry_read(i, &entry);
13213e71c7bSMatthias Ringwald if (entry.magic != LE_DEVICE_MAGIC) continue;
13313e71c7bSMatthias Ringwald if (entry.seq_nr < seq_nr) continue;
13413e71c7bSMatthias Ringwald seq_nr = entry.seq_nr;
13513e71c7bSMatthias Ringwald }
13613e71c7bSMatthias Ringwald return seq_nr;
13713e71c7bSMatthias Ringwald }
13813e71c7bSMatthias Ringwald
13913e71c7bSMatthias Ringwald // returns absoulte index
le_device_db_find_free_entry(void)14013e71c7bSMatthias Ringwald static int le_device_db_find_free_entry(void){
14113e71c7bSMatthias Ringwald le_device_nvm_t entry;
14213e71c7bSMatthias Ringwald int i;
14313e71c7bSMatthias Ringwald uint32_t seq_nr = 0;
14413e71c7bSMatthias Ringwald int lowest_index = -1;
14513e71c7bSMatthias Ringwald for (i=0;i<NVM_NUM_LE_DEVICES;i++){
14613e71c7bSMatthias Ringwald le_device_db_entry_read(i, &entry);
14713e71c7bSMatthias Ringwald if (entry.magic != LE_DEVICE_MAGIC) return i;
14813e71c7bSMatthias Ringwald if ((lowest_index < 0) || (entry.seq_nr < seq_nr)){
14913e71c7bSMatthias Ringwald lowest_index = i;
15013e71c7bSMatthias Ringwald seq_nr= entry.seq_nr;
15113e71c7bSMatthias Ringwald }
15213e71c7bSMatthias Ringwald }
15313e71c7bSMatthias Ringwald return lowest_index;
15413e71c7bSMatthias Ringwald }
15513e71c7bSMatthias Ringwald
15613e71c7bSMatthias Ringwald // returns absolute index
le_device_db_get_absolute_index_for_device_index(int device_index)15713e71c7bSMatthias Ringwald static int le_device_db_get_absolute_index_for_device_index(int device_index){
15813e71c7bSMatthias Ringwald int i;
15913e71c7bSMatthias Ringwald int counter = 0;
16013e71c7bSMatthias Ringwald for (i=0;i<NVM_NUM_LE_DEVICES;i++){
16113e71c7bSMatthias Ringwald if (le_device_db_entry_valid(i)) {
16213e71c7bSMatthias Ringwald // found
16313e71c7bSMatthias Ringwald if (counter == device_index) return i;
16413e71c7bSMatthias Ringwald counter++;
16513e71c7bSMatthias Ringwald }
16613e71c7bSMatthias Ringwald }
16713e71c7bSMatthias Ringwald return 0;
16813e71c7bSMatthias Ringwald }
16913e71c7bSMatthias Ringwald
17013e71c7bSMatthias Ringwald // PUBLIC API
17113e71c7bSMatthias Ringwald
le_device_db_wiced_dct_set_start_address(uint32_t start_address)17213e71c7bSMatthias Ringwald void le_device_db_wiced_dct_set_start_address(uint32_t start_address){
17313e71c7bSMatthias Ringwald log_info("set start address: %"PRIu32, start_address);
17413e71c7bSMatthias Ringwald start_of_le_device_db = start_address;
17513e71c7bSMatthias Ringwald }
17613e71c7bSMatthias Ringwald
le_device_db_init(void)17713e71c7bSMatthias Ringwald void le_device_db_init(void){
17813e71c7bSMatthias Ringwald }
17913e71c7bSMatthias Ringwald
le_device_db_set_local_bd_addr(bd_addr_t addr)18013e71c7bSMatthias Ringwald void le_device_db_set_local_bd_addr(bd_addr_t addr){
18113e71c7bSMatthias Ringwald (void) addr;
18213e71c7bSMatthias Ringwald }
18313e71c7bSMatthias Ringwald
18413e71c7bSMatthias Ringwald // @returns number of device in db
le_device_db_count(void)18513e71c7bSMatthias Ringwald int le_device_db_count(void){
18613e71c7bSMatthias Ringwald int i;
18713e71c7bSMatthias Ringwald int counter = 0;
18813e71c7bSMatthias Ringwald for (i=0;i<NVM_NUM_LE_DEVICES;i++){
18913e71c7bSMatthias Ringwald if (le_device_db_entry_valid(i)) counter++;
19013e71c7bSMatthias Ringwald }
19113e71c7bSMatthias Ringwald return counter;
19213e71c7bSMatthias Ringwald }
19313e71c7bSMatthias Ringwald
le_device_db_max_count(void)1946fc9dda1SMatthias Ringwald int le_device_db_max_count(void){
1956fc9dda1SMatthias Ringwald return NVM_NUM_LE_DEVICES;
1966fc9dda1SMatthias Ringwald }
1976fc9dda1SMatthias Ringwald
19813e71c7bSMatthias Ringwald // get device information: addr type and address
le_device_db_info(int device_index,int * addr_type,bd_addr_t addr,sm_key_t irk)19913e71c7bSMatthias Ringwald void le_device_db_info(int device_index, int * addr_type, bd_addr_t addr, sm_key_t irk){
20013e71c7bSMatthias Ringwald int absolute_index = le_device_db_get_absolute_index_for_device_index(device_index);
20113e71c7bSMatthias Ringwald le_device_nvm_t entry;
202d14ceebfSMatthias Ringwald int valid = le_device_db_entry_read(absolute_index, &entry);
203d14ceebfSMatthias Ringwald
204d14ceebfSMatthias Ringwald // set defaults if not found
205d14ceebfSMatthias Ringwald if (!valid) {
206e90da8a6SMatthias Ringwald memset(&entry, 0, sizeof(le_device_nvm_t));
207d14ceebfSMatthias Ringwald entry.addr_type = BD_ADDR_TYPE_UNKNOWN;
208d14ceebfSMatthias Ringwald }
209d14ceebfSMatthias Ringwald
21013e71c7bSMatthias Ringwald if (addr_type) *addr_type = entry.addr_type;
21113e71c7bSMatthias Ringwald if (addr) memcpy(addr, entry.addr, 6);
21213e71c7bSMatthias Ringwald if (irk) memcpy(irk, entry.irk, 16);
21313e71c7bSMatthias Ringwald }
21413e71c7bSMatthias Ringwald
21513e71c7bSMatthias Ringwald // free device
le_device_db_remove(int device_index)21613e71c7bSMatthias Ringwald void le_device_db_remove(int device_index){
21713e71c7bSMatthias Ringwald int absolute_index = le_device_db_get_absolute_index_for_device_index(device_index);
21813e71c7bSMatthias Ringwald le_device_nvm_t entry;
21913e71c7bSMatthias Ringwald memset(&entry, 0, sizeof(le_device_nvm_t));
22013e71c7bSMatthias Ringwald le_device_db_entry_write(absolute_index, &entry);
22113e71c7bSMatthias Ringwald }
22213e71c7bSMatthias Ringwald
22313e71c7bSMatthias Ringwald // custom function
le_device_db_wiced_dct_delete_all(void)22413e71c7bSMatthias Ringwald void le_device_db_wiced_dct_delete_all(void){
22513e71c7bSMatthias Ringwald int i;
22613e71c7bSMatthias Ringwald le_device_nvm_t entry;
22713e71c7bSMatthias Ringwald memset(&entry, 0, sizeof(le_device_nvm_t));
22813e71c7bSMatthias Ringwald for (i=0;i<NVM_NUM_LE_DEVICES;i++){
22913e71c7bSMatthias Ringwald le_device_db_entry_write(i, &entry);
23013e71c7bSMatthias Ringwald }
23113e71c7bSMatthias Ringwald }
23213e71c7bSMatthias Ringwald
le_device_db_add(int addr_type,bd_addr_t addr,sm_key_t irk)23313e71c7bSMatthias Ringwald int le_device_db_add(int addr_type, bd_addr_t addr, sm_key_t irk){
23413e71c7bSMatthias Ringwald int absolute_index = le_device_db_find_free_entry();
23513e71c7bSMatthias Ringwald uint32_t seq_nr = le_device_db_highest_seq_nr() + 1;
23613e71c7bSMatthias Ringwald log_info("adding type %u - %s, seq nr %u, as #%u", addr_type, bd_addr_to_str(addr), (int) seq_nr, absolute_index);
23713e71c7bSMatthias Ringwald log_info_key("irk", irk);
23813e71c7bSMatthias Ringwald
23913e71c7bSMatthias Ringwald le_device_nvm_t entry;
24013e71c7bSMatthias Ringwald memset(&entry, 0, sizeof(le_device_nvm_t));
24113e71c7bSMatthias Ringwald
24213e71c7bSMatthias Ringwald entry.magic = LE_DEVICE_MAGIC;
24313e71c7bSMatthias Ringwald entry.seq_nr = seq_nr;
24413e71c7bSMatthias Ringwald entry.addr_type = addr_type;
24513e71c7bSMatthias Ringwald memcpy(entry.addr, addr, 6);
24613e71c7bSMatthias Ringwald memcpy(entry.irk, irk, 16);
24713e71c7bSMatthias Ringwald
24813e71c7bSMatthias Ringwald le_device_db_entry_write(absolute_index, &entry);
24913e71c7bSMatthias Ringwald
25013e71c7bSMatthias Ringwald return absolute_index;
25113e71c7bSMatthias Ringwald }
25213e71c7bSMatthias Ringwald
le_device_db_encryption_set(int device_index,uint16_t ediv,uint8_t rand[8],sm_key_t ltk,int key_size,int authenticated,int authorized,int secure_connection)2533dc3a67dSMatthias Ringwald void le_device_db_encryption_set(int device_index, uint16_t ediv, uint8_t rand[8], sm_key_t ltk, int key_size, int authenticated, int authorized, int secure_connection){
25413e71c7bSMatthias Ringwald
25513e71c7bSMatthias Ringwald int absolute_index = le_device_db_get_absolute_index_for_device_index(device_index);
25613e71c7bSMatthias Ringwald le_device_nvm_t entry;
25713e71c7bSMatthias Ringwald le_device_db_entry_read(absolute_index, &entry);
25813e71c7bSMatthias Ringwald
2593dc3a67dSMatthias Ringwald log_info("LE Device DB set encryption for %u, ediv x%04x, key size %u, authenticated %u, authorized %u, secure connection %u",
2603dc3a67dSMatthias Ringwald device_index, ediv, key_size, authenticated, authorized, secure_connection);
26113e71c7bSMatthias Ringwald
26213e71c7bSMatthias Ringwald entry.ediv = ediv;
26313e71c7bSMatthias Ringwald if (rand) memcpy(entry.rand, rand, 8);
26413e71c7bSMatthias Ringwald if (ltk) memcpy(entry.ltk, ltk, 16);
26513e71c7bSMatthias Ringwald entry.key_size = key_size;
26613e71c7bSMatthias Ringwald entry.authenticated = authenticated;
26713e71c7bSMatthias Ringwald entry.authorized = authorized;
2683dc3a67dSMatthias Ringwald entry.secure_connection = secure_connection;
26913e71c7bSMatthias Ringwald
27013e71c7bSMatthias Ringwald le_device_db_entry_write(absolute_index, &entry);
27113e71c7bSMatthias Ringwald }
27213e71c7bSMatthias Ringwald
le_device_db_encryption_get(int device_index,uint16_t * ediv,uint8_t rand[8],sm_key_t ltk,int * key_size,int * authenticated,int * authorized,int * secure_connection)2733dc3a67dSMatthias Ringwald void le_device_db_encryption_get(int device_index, uint16_t * ediv, uint8_t rand[8], sm_key_t ltk, int * key_size, int * authenticated, int * authorized, int * secure_connection){
27413e71c7bSMatthias Ringwald
27513e71c7bSMatthias Ringwald int absolute_index = le_device_db_get_absolute_index_for_device_index(device_index);
27613e71c7bSMatthias Ringwald le_device_nvm_t entry;
27713e71c7bSMatthias Ringwald le_device_db_entry_read(absolute_index, &entry);
27813e71c7bSMatthias Ringwald
2793dc3a67dSMatthias Ringwald log_info("LE Device DB encryption for %u, ediv x%04x, keysize %u, authenticated %u, authorized %u, secure connection %u",
2803dc3a67dSMatthias Ringwald device_index, entry.ediv, entry.key_size, entry.authenticated, entry.authorized, entry.secure_connection);
28113e71c7bSMatthias Ringwald
28213e71c7bSMatthias Ringwald if (ediv) *ediv = entry.ediv;
28313e71c7bSMatthias Ringwald if (rand) memcpy(rand, entry.rand, 8);
28413e71c7bSMatthias Ringwald if (ltk) memcpy(ltk, entry.ltk, 16);
28513e71c7bSMatthias Ringwald if (key_size) *key_size = entry.key_size;
28613e71c7bSMatthias Ringwald if (authenticated) *authenticated = entry.authenticated;
28713e71c7bSMatthias Ringwald if (authorized) *authorized = entry.authorized;
2883dc3a67dSMatthias Ringwald if (secure_connection) *secure_connection = entry.secure_connection;
28913e71c7bSMatthias Ringwald }
29013e71c7bSMatthias Ringwald
le_device_db_dump(void)29113e71c7bSMatthias Ringwald void le_device_db_dump(void){
29213e71c7bSMatthias Ringwald log_info("dump, devices: %d", le_device_db_count());
29313e71c7bSMatthias Ringwald int i;
29413e71c7bSMatthias Ringwald for (i=0;i<NVM_NUM_LE_DEVICES;i++){
29513e71c7bSMatthias Ringwald le_device_nvm_t entry;
29613e71c7bSMatthias Ringwald int valid = le_device_db_entry_read(i, &entry);
29713e71c7bSMatthias Ringwald
29813e71c7bSMatthias Ringwald if (!valid) continue;
29913e71c7bSMatthias Ringwald
30013e71c7bSMatthias Ringwald log_info("#%u: %u %s", i, entry.addr_type, bd_addr_to_str(entry.addr));
30113e71c7bSMatthias Ringwald log_info_key("ltk", entry.ltk);
30213e71c7bSMatthias Ringwald log_info_key("irk", entry.irk);
30313e71c7bSMatthias Ringwald }
30413e71c7bSMatthias Ringwald }
305ad1a357bSMatthias Ringwald
le_device_db_wiced_dct_get_storage_size(void)306ad1a357bSMatthias Ringwald int le_device_db_wiced_dct_get_storage_size(void){
307ad1a357bSMatthias Ringwald return NVM_NUM_LE_DEVICES * sizeof(le_device_nvm_t);
308ad1a357bSMatthias Ringwald }
309