mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-31 19:20:26 +00:00
le_device_db_tlv: le_device_db.h implementation on top of btstack_tlv.h interface
This commit is contained in:
parent
5389404447
commit
1f5ff4332f
@ -47,11 +47,11 @@ extern "C" {
|
||||
|
||||
/**
|
||||
|
||||
LE Device DB for pure LE Peripherals is only required for signed writes
|
||||
Note: LE Device DB for pure LE Peripherals is not required if only LE Legacy Pairing without signed writes is used
|
||||
|
||||
Per bonded device, it can store
|
||||
Per bonded device:
|
||||
- it stores the Identity Resolving Key (IRK) and its address to resolve private addresses
|
||||
- it stores the LTK + EDIV, RAND. EDIV + RAND allow a LE Perihperal to reconstruct the LTK
|
||||
- it stores the LTK + EDIV, RAND. EDIV + RAND allows a LE Peripheral to reconstruct the LTK
|
||||
- it stores the Connection Signature Resolving Key (CSRK) and the last used counter.
|
||||
The CSRK is used to generate the signatur on the remote device and is needed to verify the signature itself
|
||||
The Counter is necessary to prevent reply attacks
|
||||
|
439
src/ble/le_device_db_tlv.c
Normal file
439
src/ble/le_device_db_tlv.c
Normal file
@ -0,0 +1,439 @@
|
||||
/*
|
||||
* Copyright (C) 2017 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
||||
#define __BTSTACK_FILE__ "le_device_db_tlv.c"
|
||||
|
||||
#include "ble/le_device_db.h"
|
||||
#include "ble/le_device_db_tlv.h"
|
||||
|
||||
#include "ble/core.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "btstack_debug.h"
|
||||
|
||||
// LE Device DB Implementation storing entries in btstack_tlv
|
||||
|
||||
// Local cache is used to keep track of deleted entries in TLV
|
||||
|
||||
#define INVALID_ENTRY_ADDR_TYPE 0xff
|
||||
|
||||
// Single stored entry
|
||||
typedef struct le_device_db_entry_t {
|
||||
|
||||
// Identification
|
||||
int addr_type;
|
||||
bd_addr_t addr;
|
||||
sm_key_t irk;
|
||||
|
||||
// Stored pairing information allows to re-establish an enncrypted connection
|
||||
// with a peripheral that doesn't have any persistent memory
|
||||
sm_key_t ltk;
|
||||
uint16_t ediv;
|
||||
uint8_t rand[8];
|
||||
uint8_t key_size;
|
||||
uint8_t authenticated;
|
||||
uint8_t authorized;
|
||||
|
||||
#ifdef ENABLE_LE_SIGNED_WRITE
|
||||
// Signed Writes by remote
|
||||
sm_key_t remote_csrk;
|
||||
uint32_t remote_counter;
|
||||
|
||||
// Signed Writes by us
|
||||
sm_key_t local_csrk;
|
||||
uint32_t local_counter;
|
||||
#endif
|
||||
|
||||
} le_device_db_entry_t;
|
||||
|
||||
|
||||
#ifndef MAX_NR_LE_DEVICE_DB_ENTRIES
|
||||
#error "MAX_NR_LE_DEVICE_DB_ENTRIES not defined, please define in btstack_config.h"
|
||||
#endif
|
||||
|
||||
#if MAX_NR_LE_DEVICE_DB_ENTRIES == 0
|
||||
#error "MAX_NR_LE_DEVICE_DB_ENTRIES must not be 0, please update in btstack_config.h"
|
||||
#endif
|
||||
|
||||
static uint8_t entry_map[MAX_NR_LE_DEVICE_DB_ENTRIES];
|
||||
static uint32_t num_valid_entries;
|
||||
|
||||
static const btstack_tlv_t * le_device_db_tlv_btstack_tlv_impl;
|
||||
static void * le_device_db_tlv_btstack_tlv_context;
|
||||
|
||||
static const char tag_0 = 'B';
|
||||
static const char tag_1 = 'T';
|
||||
static const char tag_2 = 'D';
|
||||
|
||||
static uint32_t le_device_db_tlv_tag_for_index(uint8_t index){
|
||||
return (tag_0 << 24) | (tag_1 << 16) | (tag_2 << 8) | index;
|
||||
}
|
||||
|
||||
// @returns success
|
||||
// @param index = entry_pos
|
||||
static int le_device_db_tlv_fetch(int index, le_device_db_entry_t * entry){
|
||||
if (index < 0 || index >= MAX_NR_LE_DEVICE_DB_ENTRIES){
|
||||
log_error("le_device_db_tlv_fetch called with invalid index %d", index);
|
||||
return 0;
|
||||
}
|
||||
uint32_t tag = le_device_db_tlv_tag_for_index(index);
|
||||
int size = le_device_db_tlv_btstack_tlv_impl->get_tag(le_device_db_tlv_btstack_tlv_context, tag, (uint8_t*) entry, sizeof(le_device_db_entry_t));
|
||||
return size != 0;
|
||||
}
|
||||
|
||||
// @returns success
|
||||
// @param index = entry_pos
|
||||
static int le_device_db_tlv_store(int index, le_device_db_entry_t * entry){
|
||||
if (index < 0 || index >= MAX_NR_LE_DEVICE_DB_ENTRIES){
|
||||
log_error("le_device_db_tlv_store called with invalid index %d", index);
|
||||
return 0;
|
||||
}
|
||||
uint32_t tag = le_device_db_tlv_tag_for_index(index);
|
||||
le_device_db_tlv_btstack_tlv_impl->store_tag(le_device_db_tlv_btstack_tlv_context, tag, (uint8_t*) entry, sizeof(le_device_db_entry_t));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// @param index = entry_pos
|
||||
static int le_device_db_tlv_delete(int index){
|
||||
if (index < 0 || index >= MAX_NR_LE_DEVICE_DB_ENTRIES){
|
||||
log_error("le_device_db_tlv_delete called with invalid index %d", index);
|
||||
return 0;
|
||||
}
|
||||
uint32_t tag = le_device_db_tlv_tag_for_index(index);
|
||||
le_device_db_tlv_btstack_tlv_impl->delete_tag(le_device_db_tlv_btstack_tlv_context, tag);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int le_device_db_tlv_fetch_mapped(int index, le_device_db_entry_t * entry){
|
||||
if (index < 0 || index >= num_valid_entries){
|
||||
log_error("le_device_db_tlv_fetch_mapped called with invalid index %d", index);
|
||||
return 0;
|
||||
}
|
||||
return le_device_db_tlv_fetch(entry_map[index], entry);
|
||||
}
|
||||
|
||||
static int le_device_db_tlv_store_mapped(int index, le_device_db_entry_t * entry){
|
||||
if (index < 0 || index >= num_valid_entries){
|
||||
log_error("le_device_tlv_store_mapped called with invalid index %d", index);
|
||||
return 0;
|
||||
}
|
||||
return le_device_db_tlv_store_mapped(entry_map[index], entry);
|
||||
}
|
||||
|
||||
|
||||
void le_device_db_init(void){
|
||||
int i;
|
||||
num_valid_entries = 0;
|
||||
memset(entry_map, 0, sizeof(entry_map));
|
||||
for (i=0;i<MAX_NR_LE_DEVICE_DB_ENTRIES;i++){
|
||||
// lookup entry
|
||||
le_device_db_entry_t entry;
|
||||
int ok = le_device_db_tlv_fetch(i, &entry);
|
||||
if (!ok) continue;
|
||||
// if valid, store entry_pos in entry_map
|
||||
entry_map[num_valid_entries++] = i;
|
||||
}
|
||||
log_info("num valid le device entries %u", num_valid_entries);
|
||||
}
|
||||
|
||||
// not used
|
||||
void le_device_db_set_local_bd_addr(bd_addr_t bd_addr){
|
||||
(void)bd_addr;
|
||||
}
|
||||
|
||||
// @returns number of device in db
|
||||
int le_device_db_count(void){
|
||||
return num_valid_entries;
|
||||
}
|
||||
|
||||
void le_device_db_remove(int index){
|
||||
|
||||
// delete entry in TLV
|
||||
int entry_pos = entry_map[index];
|
||||
le_device_db_tlv_delete(entry_pos);
|
||||
|
||||
// shift all entries down by one
|
||||
int i;
|
||||
for (i=index;i<MAX_NR_LE_DEVICE_DB_ENTRIES - 1;i++){
|
||||
entry_map[i] = entry_map[i+1];
|
||||
}
|
||||
entry_map[MAX_NR_LE_DEVICE_DB_ENTRIES-1] = 0;
|
||||
|
||||
// keep track
|
||||
num_valid_entries--;
|
||||
}
|
||||
|
||||
int le_device_db_add(int addr_type, bd_addr_t addr, sm_key_t irk){
|
||||
// find unused entry in the used list
|
||||
int i;
|
||||
int index = -1;
|
||||
int expected_index = 0;
|
||||
int new_index = -1;
|
||||
for (i=0;i<num_valid_entries;i++){
|
||||
if (entry_map[i] == expected_index){
|
||||
expected_index++;
|
||||
continue;
|
||||
}
|
||||
index = i;
|
||||
new_index = expected_index;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == num_valid_entries && num_valid_entries < MAX_NR_LE_DEVICE_DB_ENTRIES){
|
||||
index = num_valid_entries;
|
||||
new_index = num_valid_entries;
|
||||
}
|
||||
|
||||
// no free entry found
|
||||
if (index < 0) return -1;
|
||||
|
||||
log_info("new entry pos %u used for index %u", index, new_index);
|
||||
|
||||
// shift all entries up by one
|
||||
for (i = MAX_NR_LE_DEVICE_DB_ENTRIES - 1; i > index; i--){
|
||||
entry_map[i] = entry_map[i-1];
|
||||
}
|
||||
|
||||
// set in entry_mape
|
||||
entry_map[index] = new_index;
|
||||
|
||||
// store entry at entry_pos = index
|
||||
le_device_db_entry_t entry;
|
||||
log_info("LE Device DB adding type %u - %s", addr_type, bd_addr_to_str(addr));
|
||||
log_info_key("irk", irk);
|
||||
|
||||
entry.addr_type = addr_type;
|
||||
memcpy(entry.addr, addr, 6);
|
||||
memcpy(entry.irk, irk, 16);
|
||||
#ifdef ENABLE_LE_SIGNED_WRITE
|
||||
entry.remote_counter = 0;
|
||||
#endif
|
||||
|
||||
// store
|
||||
le_device_db_tlv_store(index, &entry);
|
||||
|
||||
// keep track
|
||||
num_valid_entries++;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
// get device information: addr type and address
|
||||
void le_device_db_info(int index, int * addr_type, bd_addr_t addr, sm_key_t irk){
|
||||
|
||||
// fetch entry
|
||||
le_device_db_entry_t entry;
|
||||
int ok = le_device_db_tlv_fetch_mapped(index, &entry);
|
||||
if (!ok) return;
|
||||
|
||||
if (addr_type) *addr_type = entry.addr_type;
|
||||
if (addr) memcpy(addr, entry.addr, 6);
|
||||
if (irk) memcpy(irk, entry.irk, 16);
|
||||
}
|
||||
|
||||
void le_device_db_encryption_set(int index, uint16_t ediv, uint8_t rand[8], sm_key_t ltk, int key_size, int authenticated, int authorized){
|
||||
|
||||
// fetch entry
|
||||
le_device_db_entry_t entry;
|
||||
int ok = le_device_db_tlv_fetch_mapped(index, &entry);
|
||||
if (!ok) return;
|
||||
|
||||
// update
|
||||
log_info("LE Device DB set encryption for %u, ediv x%04x, key size %u, authenticated %u, authorized %u",
|
||||
index, ediv, key_size, authenticated, authorized);
|
||||
entry.ediv = ediv;
|
||||
if (rand) memcpy(entry.rand, rand, 8);
|
||||
if (ltk) memcpy(entry.ltk, ltk, 16);
|
||||
entry.key_size = key_size;
|
||||
entry.authenticated = authenticated;
|
||||
entry.authorized = authorized;
|
||||
|
||||
// store
|
||||
le_device_db_tlv_store_mapped(index, &entry);
|
||||
}
|
||||
|
||||
void le_device_db_encryption_get(int index, uint16_t * ediv, uint8_t rand[8], sm_key_t ltk, int * key_size, int * authenticated, int * authorized){
|
||||
|
||||
// fetch entry
|
||||
le_device_db_entry_t entry;
|
||||
int ok = le_device_db_tlv_fetch_mapped(index, &entry);
|
||||
if (!ok) return;
|
||||
|
||||
// update user fields
|
||||
log_info("LE Device DB encryption for %u, ediv x%04x, keysize %u, authenticated %u, authorized %u",
|
||||
index, entry.ediv, entry.key_size, entry.authenticated, entry.authorized);
|
||||
if (ediv) *ediv = entry.ediv;
|
||||
if (rand) memcpy(rand, entry.rand, 8);
|
||||
if (ltk) memcpy(ltk, entry.ltk, 16);
|
||||
if (key_size) *key_size = entry.key_size;
|
||||
if (authenticated) *authenticated = entry.authenticated;
|
||||
if (authorized) *authorized = entry.authorized;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_LE_SIGNED_WRITE
|
||||
|
||||
// get signature key
|
||||
void le_device_db_remote_csrk_get(int index, sm_key_t csrk){
|
||||
|
||||
// fetch entry
|
||||
le_device_db_entry_t entry;
|
||||
int ok = le_device_db_tlv_fetch_mapped(index, &entry);
|
||||
if (!ok) return;
|
||||
|
||||
if (csrk) memcpy(csrk, entry.remote_csrk, 16);
|
||||
}
|
||||
|
||||
void le_device_db_remote_csrk_set(int index, sm_key_t csrk){
|
||||
|
||||
// fetch entry
|
||||
le_device_db_entry_t entry;
|
||||
int ok = le_device_db_tlv_fetch_mapped(index, &entry);
|
||||
if (!ok) return;
|
||||
|
||||
if (!csrk) return;
|
||||
|
||||
// update
|
||||
memcpy(entry.remote_csrk, csrk, 16);
|
||||
|
||||
// store
|
||||
le_device_db_tlv_store_mapped(index, &entry);
|
||||
}
|
||||
|
||||
void le_device_db_local_csrk_get(int index, sm_key_t csrk){
|
||||
|
||||
// fetch entry
|
||||
le_device_db_entry_t entry;
|
||||
int ok = le_device_db_tlv_fetch_mapped(index, &entry);
|
||||
if (!ok) return;
|
||||
|
||||
if (!csrk) return;
|
||||
|
||||
// fill
|
||||
memcpy(csrk, entry.local_csrk, 16);
|
||||
}
|
||||
|
||||
void le_device_db_local_csrk_set(int index, sm_key_t csrk){
|
||||
|
||||
// fetch entry
|
||||
le_device_db_entry_t entry;
|
||||
int ok = le_device_db_tlv_fetch_mapped(index, &entry);
|
||||
if (!ok) return;
|
||||
|
||||
if (!csrk) return;
|
||||
|
||||
// update
|
||||
memcpy(entry.local_csrk, csrk, 16);
|
||||
|
||||
// store
|
||||
le_device_db_tlv_store_mapped(index, &entry);
|
||||
}
|
||||
|
||||
// query last used/seen signing counter
|
||||
uint32_t le_device_db_remote_counter_get(int index){
|
||||
|
||||
// fetch entry
|
||||
le_device_db_entry_t entry;
|
||||
int ok = le_device_db_tlv_fetch_mapped(index, &entry);
|
||||
if (!ok) return 0;
|
||||
|
||||
return entry.remote_counter;
|
||||
}
|
||||
|
||||
// update signing counter
|
||||
void le_device_db_remote_counter_set(int index, uint32_t counter){
|
||||
|
||||
// fetch entry
|
||||
le_device_db_entry_t entry;
|
||||
int ok = le_device_db_tlv_fetch_mapped(index, &entry);
|
||||
if (!ok) return;
|
||||
|
||||
entry.remote_counter = counter;
|
||||
|
||||
// store
|
||||
le_device_db_tlv_store_mapped(index, &entry);
|
||||
}
|
||||
|
||||
// query last used/seen signing counter
|
||||
uint32_t le_device_db_local_counter_get(int index){
|
||||
|
||||
// fetch entry
|
||||
le_device_db_entry_t entry;
|
||||
int ok = le_device_db_tlv_fetch_mapped(index, &entry);
|
||||
if (!ok) return 0;
|
||||
|
||||
return entry.local_counter;
|
||||
}
|
||||
|
||||
// update signing counter
|
||||
void le_device_db_local_counter_set(int index, uint32_t counter){
|
||||
|
||||
// fetch entry
|
||||
le_device_db_entry_t entry;
|
||||
int ok = le_device_db_tlv_fetch_mapped(index, &entry);
|
||||
if (!ok) return;
|
||||
|
||||
// update
|
||||
entry.local_counter = counter;
|
||||
|
||||
// store
|
||||
le_device_db_tlv_store_mapped(index, &entry);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void le_device_db_dump(void){
|
||||
log_info("LE Device DB dump, devices: %d", le_device_db_count());
|
||||
int i;
|
||||
for (i=0;i<num_valid_entries;i++){
|
||||
// fetch entry
|
||||
le_device_db_entry_t entry;
|
||||
le_device_db_tlv_fetch_mapped(i, &entry);
|
||||
log_info("%u: %u %s", i, entry.addr_type, bd_addr_to_str(entry.addr));
|
||||
log_info_key("irk", entry.irk);
|
||||
#ifdef ENABLE_LE_SIGNED_WRITE
|
||||
log_info_key("local csrk", entry.local_csrk);
|
||||
log_info_key("remote csrk", entry.remote_csrk);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void le_device_db_tlv_configure(const btstack_tlv_t * btstack_tlv_impl, void * btstack_tlv_context){
|
||||
le_device_db_tlv_btstack_tlv_impl = btstack_tlv_impl;
|
||||
le_device_db_tlv_btstack_tlv_context = btstack_tlv_context;
|
||||
}
|
64
src/ble/le_device_db_tlv.h
Normal file
64
src/ble/le_device_db_tlv.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2014 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LE_DEVICE_DB_TLV_H
|
||||
#define __LE_DEVICE_DB_TLV_H
|
||||
|
||||
#include "btstack_util.h"
|
||||
#include "btstack_tlv.h"
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* API_START */
|
||||
|
||||
/**
|
||||
* @brief configure le device db for use with btstack tlv instance
|
||||
* @param btstack_tlv_impl to use
|
||||
* @param btstack_tlv_context
|
||||
*/
|
||||
|
||||
void le_device_db_tlv_configure(const btstack_tlv_t * btstack_tlv_impl, void * btstack_tlv_context);
|
||||
|
||||
/* API_END */
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __LE_DEVICE_DB_TLV_H
|
2
test/flash_tlv/.gitignore
vendored
2
test/flash_tlv/.gitignore
vendored
@ -1,2 +1,4 @@
|
||||
tlv_test
|
||||
*.pklg
|
||||
tlv_le_test
|
||||
tlv_le_test.pklg
|
||||
|
@ -3,18 +3,16 @@ CC=g++
|
||||
BTSTACK_ROOT = ../..
|
||||
CPPUTEST_HOME = ${BTSTACK_ROOT}/test/cpputest
|
||||
|
||||
COMMON = \
|
||||
btstack_link_key_db_tlv.c \
|
||||
btstack_tlv_flash_sector.c \
|
||||
btstack_util.c \
|
||||
hal_flash_sector_memory.c \
|
||||
hci_dump.c \
|
||||
|
||||
COMMON_OBJ = $(COMMON:.c=.o)
|
||||
COMMON_OBJ = \
|
||||
btstack_tlv_flash_sector.o \
|
||||
btstack_util.o \
|
||||
hal_flash_sector_memory.o \
|
||||
hci_dump.o \
|
||||
|
||||
VPATH = \
|
||||
${BTSTACK_ROOT}/src \
|
||||
${BTSTACK_ROOT}/src/classic \
|
||||
${BTSTACK_ROOT}/src/ble \
|
||||
${BTSTACK_ROOT}/platform/embedded \
|
||||
|
||||
CFLAGS = \
|
||||
@ -30,14 +28,17 @@ CFLAGS = \
|
||||
|
||||
LDFLAGS += -lCppUTest -lCppUTestExt
|
||||
|
||||
TESTS = tlv_test
|
||||
TESTS = tlv_test tlv_le_test
|
||||
|
||||
all: ${TESTS}
|
||||
|
||||
clean:
|
||||
rm -rf *.o $(TESTS) *.dSYM *.pklg
|
||||
|
||||
tlv_test: ${COMMON_OBJ} tlv_test.o
|
||||
tlv_test: ${COMMON_OBJ} btstack_link_key_db_tlv.o tlv_test.o
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
tlv_le_test: ${COMMON_OBJ} le_device_db_tlv.o tlv_le_test.o
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
test: all
|
||||
|
123
test/flash_tlv/tlv_le_test.c
Normal file
123
test/flash_tlv/tlv_le_test.c
Normal file
@ -0,0 +1,123 @@
|
||||
|
||||
#include "CppUTest/TestHarness.h"
|
||||
#include "CppUTest/CommandLineTestRunner.h"
|
||||
|
||||
#include "hal_flash_sector.h"
|
||||
#include "hal_flash_sector_memory.h"
|
||||
#include "btstack_tlv.h"
|
||||
#include "btstack_tlv_flash_sector.h"
|
||||
#include "hci_dump.h"
|
||||
#include "ble/le_device_db.h"
|
||||
#include "ble/le_device_db_tlv.h"
|
||||
#include "btstack_util.h"
|
||||
#include "btstack_config.h"
|
||||
#include "btstack_debug.h"
|
||||
|
||||
#define HAL_FLASH_SECTOR_MEMORY_STORAGE_SIZE 512
|
||||
static uint8_t hal_flash_sector_memory_storage[HAL_FLASH_SECTOR_MEMORY_STORAGE_SIZE];
|
||||
|
||||
static void CHECK_EQUAL_ARRAY(uint8_t * expected, uint8_t * actual, int size){
|
||||
int i;
|
||||
for (i=0; i<size; i++){
|
||||
if (expected[i] != actual[i]) {
|
||||
printf("offset %u wrong\n", i);
|
||||
printf("expected: "); printf_hexdump(expected, size);
|
||||
printf("actual: "); printf_hexdump(actual, size);
|
||||
}
|
||||
BYTES_EQUAL(expected[i], actual[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
TEST_GROUP(LE_DEVICE_DB){
|
||||
const hal_flash_sector_t * hal_flash_sector_impl;
|
||||
hal_flash_sector_memory_t hal_flash_sector_context;
|
||||
|
||||
const btstack_tlv_t * btstack_tlv_impl;
|
||||
btstack_tlv_flash_sector_t btstack_tlv_context;
|
||||
|
||||
bd_addr_t addr_aa, addr_bb, addr_cc;
|
||||
sm_key_t sm_key_aa, sm_key_bb, sm_key_cc;
|
||||
|
||||
void setup(void){
|
||||
// hal_flash_sector
|
||||
hal_flash_sector_impl = hal_flash_sector_memory_init_instance(&hal_flash_sector_context, hal_flash_sector_memory_storage, HAL_FLASH_SECTOR_MEMORY_STORAGE_SIZE);
|
||||
hal_flash_sector_impl->erase(&hal_flash_sector_context, 0);
|
||||
hal_flash_sector_impl->erase(&hal_flash_sector_context, 1);
|
||||
// btstack_tlv
|
||||
btstack_tlv_impl = btstack_tlv_flash_sector_init_instance(&btstack_tlv_context, hal_flash_sector_impl, &hal_flash_sector_context);
|
||||
// le_device_db_tlv
|
||||
le_device_db_tlv_configure(btstack_tlv_impl, &btstack_tlv_context);
|
||||
le_device_db_init();
|
||||
|
||||
bd_addr_t addr_1 = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa };
|
||||
bd_addr_t addr_2 = { 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb };
|
||||
bd_addr_t addr_3 = { 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc };
|
||||
bd_addr_copy(addr_aa, addr_1);
|
||||
bd_addr_copy(addr_bb, addr_2);
|
||||
bd_addr_copy(addr_cc, addr_3);
|
||||
memset(sm_key_aa, 0xaa, 16);
|
||||
memset(sm_key_bb, 0xbb, 16);
|
||||
memset(sm_key_cc, 0xcc, 16);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(LE_DEVICE_DB, Empty){
|
||||
CHECK_EQUAL(0, le_device_db_count());
|
||||
}
|
||||
|
||||
TEST(LE_DEVICE_DB, AddOne){
|
||||
le_device_db_add(BD_ADDR_TYPE_LE_PUBLIC, addr_aa, sm_key_aa);
|
||||
CHECK_EQUAL(1, le_device_db_count());
|
||||
}
|
||||
|
||||
TEST(LE_DEVICE_DB, RetrieveOne){
|
||||
le_device_db_add(BD_ADDR_TYPE_LE_PUBLIC, addr_aa, sm_key_aa);
|
||||
CHECK_EQUAL(1, le_device_db_count());
|
||||
bd_addr_t addr;
|
||||
sm_key_t sm_key;
|
||||
int addr_type;
|
||||
le_device_db_info(0, &addr_type, addr, sm_key);
|
||||
CHECK_EQUAL_ARRAY(sm_key_aa, sm_key, 16);
|
||||
CHECK_EQUAL_ARRAY(addr_aa, addr, 6);
|
||||
}
|
||||
|
||||
TEST(LE_DEVICE_DB, AddOTwo){
|
||||
le_device_db_add(BD_ADDR_TYPE_LE_PUBLIC, addr_aa, sm_key_aa);
|
||||
le_device_db_add(BD_ADDR_TYPE_LE_PUBLIC, addr_bb, sm_key_bb);
|
||||
CHECK_EQUAL(2, le_device_db_count());
|
||||
}
|
||||
|
||||
TEST(LE_DEVICE_DB, AddOTwoRemoveOne){
|
||||
le_device_db_add(BD_ADDR_TYPE_LE_PUBLIC, addr_aa, sm_key_aa);
|
||||
le_device_db_add(BD_ADDR_TYPE_LE_PUBLIC, addr_bb, sm_key_bb);
|
||||
le_device_db_remove(0);
|
||||
CHECK_EQUAL(1, le_device_db_count());
|
||||
bd_addr_t addr;
|
||||
sm_key_t sm_key;
|
||||
int addr_type;
|
||||
le_device_db_info(0, &addr_type, addr, sm_key);
|
||||
CHECK_EQUAL_ARRAY(sm_key_bb, sm_key, 16);
|
||||
CHECK_EQUAL_ARRAY(addr_bb, addr, 6);
|
||||
}
|
||||
|
||||
TEST(LE_DEVICE_DB, AddOTwoRemoveOneAddOne){
|
||||
le_device_db_add(BD_ADDR_TYPE_LE_PUBLIC, addr_aa, sm_key_aa);
|
||||
le_device_db_add(BD_ADDR_TYPE_LE_PUBLIC, addr_bb, sm_key_bb);
|
||||
le_device_db_remove(0);
|
||||
le_device_db_add(BD_ADDR_TYPE_LE_PUBLIC, addr_cc, sm_key_cc);
|
||||
CHECK_EQUAL(2, le_device_db_count());
|
||||
bd_addr_t addr;
|
||||
sm_key_t sm_key;
|
||||
int addr_type;
|
||||
le_device_db_info(0, &addr_type, addr, sm_key);
|
||||
CHECK_EQUAL_ARRAY(sm_key_cc, sm_key, 16);
|
||||
CHECK_EQUAL_ARRAY(addr_cc, addr, 6);
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, const char * argv[]){
|
||||
hci_dump_open("tlv_le_test.pklg", HCI_DUMP_PACKETLOGGER);
|
||||
return CommandLineTestRunner::RunAllTests(argc, argv);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user