xref: /btstack/src/classic/btstack_link_key_db_tlv.c (revision b56e8b561bce450f5cd8828749be22a67c2bd9ec)
1d9f53676SMatthias Ringwald /*
2d9f53676SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
3d9f53676SMatthias Ringwald  *
4d9f53676SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5d9f53676SMatthias Ringwald  * modification, are permitted provided that the following conditions
6d9f53676SMatthias Ringwald  * are met:
7d9f53676SMatthias Ringwald  *
8d9f53676SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9d9f53676SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10d9f53676SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11d9f53676SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12d9f53676SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13d9f53676SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14d9f53676SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15d9f53676SMatthias Ringwald  *    from this software without specific prior written permission.
16d9f53676SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17d9f53676SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18d9f53676SMatthias Ringwald  *    monetary gain.
19d9f53676SMatthias Ringwald  *
20d9f53676SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21d9f53676SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22d9f53676SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
232fca4dadSMilanka Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
242fca4dadSMilanka Ringwald  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25d9f53676SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26d9f53676SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27d9f53676SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28d9f53676SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29d9f53676SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30d9f53676SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31d9f53676SMatthias Ringwald  * SUCH DAMAGE.
32d9f53676SMatthias Ringwald  *
33d9f53676SMatthias Ringwald  * Please inquire about commercial licensing options at
34d9f53676SMatthias Ringwald  * [email protected]
35d9f53676SMatthias Ringwald  *
36d9f53676SMatthias Ringwald  */
37d9f53676SMatthias Ringwald 
38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "btstack_link_key_db_tlv.c"
390c2f4953SMatthias Ringwald 
40d9f53676SMatthias Ringwald #include <string.h>
41d9f53676SMatthias Ringwald #include <stdlib.h>
42d9f53676SMatthias Ringwald 
431d90e892SMatthias Ringwald #include "classic/btstack_link_key_db_tlv.h"
44d9f53676SMatthias Ringwald 
45d9f53676SMatthias Ringwald #include "btstack_debug.h"
46d9f53676SMatthias Ringwald #include "btstack_util.h"
47d9f53676SMatthias Ringwald #include "classic/core.h"
48d9f53676SMatthias Ringwald 
49d9f53676SMatthias Ringwald // NVM_NUM_LINK_KEYS defines number of stored link keys
50e0bb66f8SMatthias Ringwald #ifndef NVM_NUM_LINK_KEYS
51dbe92de6SMatthias Ringwald #error "Please set NVM_NUM_LINK_KEYS in btstack_config.h - number of link keys that can be stored in TLV"
52e0bb66f8SMatthias Ringwald #endif
53d9f53676SMatthias Ringwald 
54d9f53676SMatthias Ringwald typedef struct {
55d9f53676SMatthias Ringwald     const btstack_tlv_t * btstack_tlv_impl;
56d9f53676SMatthias Ringwald     void * btstack_tlv_context;
57d9f53676SMatthias Ringwald } btstack_link_key_db_tlv_h;
58d9f53676SMatthias Ringwald 
59d9f53676SMatthias Ringwald typedef struct link_key_nvm {
60d9f53676SMatthias Ringwald     uint32_t seq_nr;    // used for "least recently stored" eviction strategy
61d9f53676SMatthias Ringwald     bd_addr_t bd_addr;
62d9f53676SMatthias Ringwald     link_key_t link_key;
63d9f53676SMatthias Ringwald     link_key_type_t link_key_type;
64d9f53676SMatthias Ringwald } link_key_nvm_t;   // sizeof(link_key_nvm_t) = 27 bytes
65d9f53676SMatthias Ringwald 
66d9f53676SMatthias Ringwald static btstack_link_key_db_tlv_h singleton;
67d9f53676SMatthias Ringwald static btstack_link_key_db_tlv_h * self = &singleton;
68d9f53676SMatthias Ringwald 
691d90e892SMatthias Ringwald static const char tag_0 = 'B';
701d90e892SMatthias Ringwald static const char tag_1 = 'T';
711d90e892SMatthias Ringwald static const char tag_2 = 'L';
721d90e892SMatthias Ringwald 
btstack_link_key_db_tag_for_index(uint8_t index)73d9f53676SMatthias Ringwald static uint32_t btstack_link_key_db_tag_for_index(uint8_t index){
741d90e892SMatthias Ringwald     return (tag_0 << 24) | (tag_1 << 16) | (tag_2 << 8) | index;
75d9f53676SMatthias Ringwald }
76d9f53676SMatthias Ringwald 
77d9f53676SMatthias Ringwald // Device info
btstack_link_key_db_tlv_open(void)78d9f53676SMatthias Ringwald static void btstack_link_key_db_tlv_open(void){
79d9f53676SMatthias Ringwald }
80d9f53676SMatthias Ringwald 
btstack_link_key_db_tlv_set_bd_addr(bd_addr_t bd_addr)81d9f53676SMatthias Ringwald static void btstack_link_key_db_tlv_set_bd_addr(bd_addr_t bd_addr){
82d9f53676SMatthias Ringwald     (void)bd_addr;
83d9f53676SMatthias Ringwald }
84d9f53676SMatthias Ringwald 
btstack_link_key_db_tlv_close(void)85d9f53676SMatthias Ringwald static void btstack_link_key_db_tlv_close(void){
86d9f53676SMatthias Ringwald }
87d9f53676SMatthias Ringwald 
btstack_link_key_db_tlv_get_link_key(bd_addr_t bd_addr,link_key_t link_key,link_key_type_t * link_key_type)88d9f53676SMatthias Ringwald static int btstack_link_key_db_tlv_get_link_key(bd_addr_t bd_addr, link_key_t link_key, link_key_type_t * link_key_type) {
89d9f53676SMatthias Ringwald     int i;
90d9f53676SMatthias Ringwald     for (i=0;i<NVM_NUM_LINK_KEYS;i++){
91d9f53676SMatthias Ringwald         link_key_nvm_t entry;
92d9f53676SMatthias Ringwald         uint32_t tag = btstack_link_key_db_tag_for_index(i);
93d9f53676SMatthias Ringwald         int size = self->btstack_tlv_impl->get_tag(self->btstack_tlv_context, tag, (uint8_t*) &entry, sizeof(entry));
94d9f53676SMatthias Ringwald         if (size == 0) continue;
9597d2cfbcSMatthias Ringwald         log_info("tag %x, addr %s", (unsigned int) tag, bd_addr_to_str(entry.bd_addr));
96d9f53676SMatthias Ringwald         if (memcmp(bd_addr, entry.bd_addr, 6)) continue;
97d9f53676SMatthias Ringwald         // found, pass back
986535961aSMatthias Ringwald         (void)memcpy(link_key, entry.link_key, 16);
99d9f53676SMatthias Ringwald         *link_key_type = entry.link_key_type;
100d9f53676SMatthias Ringwald         return 1;
101d9f53676SMatthias Ringwald     }
102d9f53676SMatthias Ringwald 	return 0;
103d9f53676SMatthias Ringwald }
104d9f53676SMatthias Ringwald 
btstack_link_key_db_tlv_delete_link_key(bd_addr_t bd_addr)105d9f53676SMatthias Ringwald static void btstack_link_key_db_tlv_delete_link_key(bd_addr_t bd_addr){
106d9f53676SMatthias Ringwald     int i;
107d9f53676SMatthias Ringwald     for (i=0;i<NVM_NUM_LINK_KEYS;i++){
108d9f53676SMatthias Ringwald         link_key_nvm_t entry;
109d9f53676SMatthias Ringwald         uint32_t tag = btstack_link_key_db_tag_for_index(i);
110d9f53676SMatthias Ringwald         int size = self->btstack_tlv_impl->get_tag(self->btstack_tlv_context, tag, (uint8_t*) &entry, sizeof(entry));
111d9f53676SMatthias Ringwald         if (size == 0) continue;
112d9f53676SMatthias Ringwald         if (memcmp(bd_addr, entry.bd_addr, 6)) continue;
113d9f53676SMatthias Ringwald         // found, delete tag
114d9f53676SMatthias Ringwald         self->btstack_tlv_impl->delete_tag(self->btstack_tlv_context, tag);
115d9f53676SMatthias Ringwald         break;
116d9f53676SMatthias Ringwald     }
117d9f53676SMatthias Ringwald }
118d9f53676SMatthias Ringwald 
btstack_link_key_db_tlv_put_link_key(bd_addr_t bd_addr,link_key_t link_key,link_key_type_t link_key_type)119d9f53676SMatthias Ringwald static void btstack_link_key_db_tlv_put_link_key(bd_addr_t bd_addr, link_key_t link_key, link_key_type_t link_key_type){
120d9f53676SMatthias Ringwald     int i;
121d9f53676SMatthias Ringwald     uint32_t highest_seq_nr = 0;
122d9f53676SMatthias Ringwald     uint32_t lowest_seq_nr = 0;
123d9f53676SMatthias Ringwald     uint32_t tag_for_lowest_seq_nr = 0;
124d9f53676SMatthias Ringwald     uint32_t tag_for_addr = 0;
125d9f53676SMatthias Ringwald     uint32_t tag_for_empty = 0;
126d9f53676SMatthias Ringwald 
127d9f53676SMatthias Ringwald     for (i=0;i<NVM_NUM_LINK_KEYS;i++){
128d9f53676SMatthias Ringwald         link_key_nvm_t entry;
129d9f53676SMatthias Ringwald         uint32_t tag = btstack_link_key_db_tag_for_index(i);
130d9f53676SMatthias Ringwald         int size = self->btstack_tlv_impl->get_tag(self->btstack_tlv_context, tag, (uint8_t*) &entry, sizeof(entry));
131d9f53676SMatthias Ringwald         // empty/deleted tag
132d9f53676SMatthias Ringwald         if (size == 0) {
133d9f53676SMatthias Ringwald             tag_for_empty = tag;
134d9f53676SMatthias Ringwald             continue;
135d9f53676SMatthias Ringwald         }
136d9f53676SMatthias Ringwald         // found addr?
137d9f53676SMatthias Ringwald         if (memcmp(bd_addr, entry.bd_addr, 6) == 0){
138d9f53676SMatthias Ringwald             tag_for_addr = tag;
139d9f53676SMatthias Ringwald         }
140d9f53676SMatthias Ringwald         // update highest seq nr
141d9f53676SMatthias Ringwald         if (entry.seq_nr > highest_seq_nr){
142d9f53676SMatthias Ringwald             highest_seq_nr = entry.seq_nr;
143d9f53676SMatthias Ringwald         }
144d9f53676SMatthias Ringwald         // find entry with lowest seq nr
145d9f53676SMatthias Ringwald         if ((tag_for_lowest_seq_nr == 0) || (entry.seq_nr < lowest_seq_nr)){
146d9f53676SMatthias Ringwald             tag_for_lowest_seq_nr = tag;
147d9f53676SMatthias Ringwald             lowest_seq_nr = entry.seq_nr;
148d9f53676SMatthias Ringwald         }
149d9f53676SMatthias Ringwald     }
150d9f53676SMatthias Ringwald 
15197d2cfbcSMatthias Ringwald     log_info("tag_for_addr %x, tag_for_empy %x, tag_for_lowest_seq_nr %x",
15297d2cfbcSMatthias Ringwald              (unsigned int) tag_for_addr, (unsigned int) tag_for_empty, (unsigned int) tag_for_lowest_seq_nr);
153d9f53676SMatthias Ringwald 
154d9f53676SMatthias Ringwald     uint32_t tag_to_use = 0;
155d9f53676SMatthias Ringwald     if (tag_for_addr){
156d9f53676SMatthias Ringwald         tag_to_use = tag_for_addr;
157d9f53676SMatthias Ringwald     } else if (tag_for_empty){
158d9f53676SMatthias Ringwald         tag_to_use = tag_for_empty;
159d9f53676SMatthias Ringwald     } else if (tag_for_lowest_seq_nr){
160d9f53676SMatthias Ringwald         tag_to_use = tag_for_lowest_seq_nr;
161d9f53676SMatthias Ringwald     } else {
162d9f53676SMatthias Ringwald         // should not happen
163d9f53676SMatthias Ringwald         return;
164d9f53676SMatthias Ringwald     }
165d9f53676SMatthias Ringwald 
16697d2cfbcSMatthias Ringwald     log_info("store with tag %x", (unsigned int) tag_to_use);
167d9f53676SMatthias Ringwald 
168d9f53676SMatthias Ringwald     link_key_nvm_t entry;
169d9f53676SMatthias Ringwald 
1706535961aSMatthias Ringwald     (void)memcpy(entry.bd_addr, bd_addr, 6);
1716535961aSMatthias Ringwald     (void)memcpy(entry.link_key, link_key, 16);
172d9f53676SMatthias Ringwald     entry.link_key_type = link_key_type;
173d9f53676SMatthias Ringwald     entry.seq_nr = highest_seq_nr + 1;
174d9f53676SMatthias Ringwald 
1750fe46bc1SMatthias Ringwald     int result = self->btstack_tlv_impl->store_tag(self->btstack_tlv_context, tag_to_use, (uint8_t*) &entry, sizeof(entry));
1760fe46bc1SMatthias Ringwald     if (result != 0){
1770fe46bc1SMatthias Ringwald         log_error("store link key failed");
1780fe46bc1SMatthias Ringwald     }
179d9f53676SMatthias Ringwald }
180d9f53676SMatthias Ringwald 
btstack_link_key_db_tlv_iterator_init(btstack_link_key_iterator_t * it)1816b9d8000SMatthias Ringwald static int btstack_link_key_db_tlv_iterator_init(btstack_link_key_iterator_t * it){
1826b9d8000SMatthias Ringwald     it->context = (void*) 0;
1836b9d8000SMatthias Ringwald     return 1;
1846b9d8000SMatthias Ringwald }
1856b9d8000SMatthias Ringwald 
btstack_link_key_db_tlv_iterator_get_next(btstack_link_key_iterator_t * it,bd_addr_t bd_addr,link_key_t link_key,link_key_type_t * link_key_type)1866b9d8000SMatthias Ringwald static int  btstack_link_key_db_tlv_iterator_get_next(btstack_link_key_iterator_t * it, bd_addr_t bd_addr, link_key_t link_key, link_key_type_t * link_key_type){
187*b56e8b56SMatthias Ringwald     uint8_t i = (uint8_t)(uintptr_t) it->context;
1886b9d8000SMatthias Ringwald     int found = 0;
1896b9d8000SMatthias Ringwald     while (i<NVM_NUM_LINK_KEYS){
1906b9d8000SMatthias Ringwald         link_key_nvm_t entry;
1916b9d8000SMatthias Ringwald         uint32_t tag = btstack_link_key_db_tag_for_index(i++);
1926b9d8000SMatthias Ringwald         int size = self->btstack_tlv_impl->get_tag(self->btstack_tlv_context, tag, (uint8_t*) &entry, sizeof(entry));
1936b9d8000SMatthias Ringwald         if (size == 0) continue;
1946535961aSMatthias Ringwald         (void)memcpy(bd_addr, entry.bd_addr, 6);
1956535961aSMatthias Ringwald         (void)memcpy(link_key, entry.link_key, 16);
1966b9d8000SMatthias Ringwald         *link_key_type = entry.link_key_type;
1976b9d8000SMatthias Ringwald         found = 1;
1986b9d8000SMatthias Ringwald         break;
1996b9d8000SMatthias Ringwald     }
200*b56e8b56SMatthias Ringwald     it->context = (void*)(uintptr_t) i;
2016b9d8000SMatthias Ringwald     return found;
2026b9d8000SMatthias Ringwald }
2036b9d8000SMatthias Ringwald 
btstack_link_key_db_tlv_iterator_done(btstack_link_key_iterator_t * it)2046b9d8000SMatthias Ringwald static void btstack_link_key_db_tlv_iterator_done(btstack_link_key_iterator_t * it){
2056b9d8000SMatthias Ringwald     UNUSED(it);
2066b9d8000SMatthias Ringwald }
2076b9d8000SMatthias Ringwald 
208e2717974SMatthias Ringwald static const btstack_link_key_db_t btstack_link_key_db_tlv = {
209d9f53676SMatthias Ringwald     btstack_link_key_db_tlv_open,
210d9f53676SMatthias Ringwald     btstack_link_key_db_tlv_set_bd_addr,
211d9f53676SMatthias Ringwald     btstack_link_key_db_tlv_close,
212d9f53676SMatthias Ringwald     btstack_link_key_db_tlv_get_link_key,
213d9f53676SMatthias Ringwald     btstack_link_key_db_tlv_put_link_key,
214d9f53676SMatthias Ringwald     btstack_link_key_db_tlv_delete_link_key,
2156b9d8000SMatthias Ringwald     btstack_link_key_db_tlv_iterator_init,
2166b9d8000SMatthias Ringwald     btstack_link_key_db_tlv_iterator_get_next,
2176b9d8000SMatthias Ringwald     btstack_link_key_db_tlv_iterator_done,
218d9f53676SMatthias Ringwald };
219d9f53676SMatthias Ringwald 
btstack_link_key_db_tlv_get_instance(const btstack_tlv_t * btstack_tlv_impl,void * btstack_tlv_context)220d9f53676SMatthias Ringwald const btstack_link_key_db_t * btstack_link_key_db_tlv_get_instance(const btstack_tlv_t * btstack_tlv_impl, void * btstack_tlv_context){
221d9f53676SMatthias Ringwald     self->btstack_tlv_impl = btstack_tlv_impl;
222d9f53676SMatthias Ringwald     self->btstack_tlv_context = btstack_tlv_context;
223d9f53676SMatthias Ringwald     return &btstack_link_key_db_tlv;
224d9f53676SMatthias Ringwald }
225d9f53676SMatthias Ringwald 
226d9f53676SMatthias Ringwald 
227