xref: /btstack/src/classic/btstack_link_key_db_tlv.c (revision d9f53676a5b1911619269e9d31f823cd6a3ac49d)
1*d9f53676SMatthias Ringwald /*
2*d9f53676SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
3*d9f53676SMatthias Ringwald  *
4*d9f53676SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5*d9f53676SMatthias Ringwald  * modification, are permitted provided that the following conditions
6*d9f53676SMatthias Ringwald  * are met:
7*d9f53676SMatthias Ringwald  *
8*d9f53676SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9*d9f53676SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10*d9f53676SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11*d9f53676SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12*d9f53676SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13*d9f53676SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14*d9f53676SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15*d9f53676SMatthias Ringwald  *    from this software without specific prior written permission.
16*d9f53676SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17*d9f53676SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18*d9f53676SMatthias Ringwald  *    monetary gain.
19*d9f53676SMatthias Ringwald  *
20*d9f53676SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21*d9f53676SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*d9f53676SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*d9f53676SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24*d9f53676SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25*d9f53676SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26*d9f53676SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27*d9f53676SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28*d9f53676SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29*d9f53676SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30*d9f53676SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*d9f53676SMatthias Ringwald  * SUCH DAMAGE.
32*d9f53676SMatthias Ringwald  *
33*d9f53676SMatthias Ringwald  * Please inquire about commercial licensing options at
34*d9f53676SMatthias Ringwald  * [email protected]
35*d9f53676SMatthias Ringwald  *
36*d9f53676SMatthias Ringwald  */
37*d9f53676SMatthias Ringwald 
38*d9f53676SMatthias Ringwald #include <string.h>
39*d9f53676SMatthias Ringwald #include <stdlib.h>
40*d9f53676SMatthias Ringwald 
41*d9f53676SMatthias Ringwald #include "btstack_link_key_db_tlv.h"
42*d9f53676SMatthias Ringwald 
43*d9f53676SMatthias Ringwald #include "btstack_debug.h"
44*d9f53676SMatthias Ringwald #include "btstack_util.h"
45*d9f53676SMatthias Ringwald #include "classic/core.h"
46*d9f53676SMatthias Ringwald 
47*d9f53676SMatthias Ringwald // NVM_NUM_LINK_KEYS defines number of stored link keys
48*d9f53676SMatthias Ringwald 
49*d9f53676SMatthias Ringwald typedef struct {
50*d9f53676SMatthias Ringwald     const btstack_tlv_t * btstack_tlv_impl;
51*d9f53676SMatthias Ringwald     void * btstack_tlv_context;
52*d9f53676SMatthias Ringwald } btstack_link_key_db_tlv_h;
53*d9f53676SMatthias Ringwald 
54*d9f53676SMatthias Ringwald typedef struct link_key_nvm {
55*d9f53676SMatthias Ringwald     uint32_t seq_nr;    // used for "least recently stored" eviction strategy
56*d9f53676SMatthias Ringwald     bd_addr_t bd_addr;
57*d9f53676SMatthias Ringwald     link_key_t link_key;
58*d9f53676SMatthias Ringwald     link_key_type_t link_key_type;
59*d9f53676SMatthias Ringwald } link_key_nvm_t;   // sizeof(link_key_nvm_t) = 27 bytes
60*d9f53676SMatthias Ringwald 
61*d9f53676SMatthias Ringwald static btstack_link_key_db_tlv_h singleton;
62*d9f53676SMatthias Ringwald static btstack_link_key_db_tlv_h * self = &singleton;
63*d9f53676SMatthias Ringwald 
64*d9f53676SMatthias Ringwald static uint32_t btstack_link_key_db_tag_for_index(uint8_t index){
65*d9f53676SMatthias Ringwald     return ('B' << 24) | ('T' << 16) | ('L' << 8) | index;
66*d9f53676SMatthias Ringwald }
67*d9f53676SMatthias Ringwald 
68*d9f53676SMatthias Ringwald // Device info
69*d9f53676SMatthias Ringwald static void btstack_link_key_db_tlv_open(void){
70*d9f53676SMatthias Ringwald }
71*d9f53676SMatthias Ringwald 
72*d9f53676SMatthias Ringwald static void btstack_link_key_db_tlv_set_bd_addr(bd_addr_t bd_addr){
73*d9f53676SMatthias Ringwald     (void)bd_addr;
74*d9f53676SMatthias Ringwald }
75*d9f53676SMatthias Ringwald 
76*d9f53676SMatthias Ringwald static void btstack_link_key_db_tlv_close(void){
77*d9f53676SMatthias Ringwald }
78*d9f53676SMatthias Ringwald 
79*d9f53676SMatthias 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) {
80*d9f53676SMatthias Ringwald     int i;
81*d9f53676SMatthias Ringwald     for (i=0;i<NVM_NUM_LINK_KEYS;i++){
82*d9f53676SMatthias Ringwald         link_key_nvm_t entry;
83*d9f53676SMatthias Ringwald         uint32_t tag = btstack_link_key_db_tag_for_index(i);
84*d9f53676SMatthias Ringwald         int size = self->btstack_tlv_impl->get_tag(self->btstack_tlv_context, tag, (uint8_t*) &entry, sizeof(entry));
85*d9f53676SMatthias Ringwald         if (size == 0) continue;
86*d9f53676SMatthias Ringwald         log_info("tag %x, addr %s", tag, bd_addr_to_str(entry.bd_addr));
87*d9f53676SMatthias Ringwald         if (memcmp(bd_addr, entry.bd_addr, 6)) continue;
88*d9f53676SMatthias Ringwald         // found, pass back
89*d9f53676SMatthias Ringwald         memcpy(link_key, entry.link_key, 16);
90*d9f53676SMatthias Ringwald         *link_key_type = entry.link_key_type;
91*d9f53676SMatthias Ringwald         return 1;
92*d9f53676SMatthias Ringwald     }
93*d9f53676SMatthias Ringwald 	return 0;
94*d9f53676SMatthias Ringwald }
95*d9f53676SMatthias Ringwald 
96*d9f53676SMatthias Ringwald static void btstack_link_key_db_tlv_delete_link_key(bd_addr_t bd_addr){
97*d9f53676SMatthias Ringwald     int i;
98*d9f53676SMatthias Ringwald     for (i=0;i<NVM_NUM_LINK_KEYS;i++){
99*d9f53676SMatthias Ringwald         link_key_nvm_t entry;
100*d9f53676SMatthias Ringwald         uint32_t tag = btstack_link_key_db_tag_for_index(i);
101*d9f53676SMatthias Ringwald         int size = self->btstack_tlv_impl->get_tag(self->btstack_tlv_context, tag, (uint8_t*) &entry, sizeof(entry));
102*d9f53676SMatthias Ringwald         if (size == 0) continue;
103*d9f53676SMatthias Ringwald         if (memcmp(bd_addr, entry.bd_addr, 6)) continue;
104*d9f53676SMatthias Ringwald         // found, delete tag
105*d9f53676SMatthias Ringwald         self->btstack_tlv_impl->delete_tag(self->btstack_tlv_context, tag);
106*d9f53676SMatthias Ringwald         break;
107*d9f53676SMatthias Ringwald     }
108*d9f53676SMatthias Ringwald }
109*d9f53676SMatthias Ringwald 
110*d9f53676SMatthias 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){
111*d9f53676SMatthias Ringwald     int i;
112*d9f53676SMatthias Ringwald     uint32_t highest_seq_nr = 0;
113*d9f53676SMatthias Ringwald     uint32_t lowest_seq_nr = 0;
114*d9f53676SMatthias Ringwald     uint32_t tag_for_lowest_seq_nr = 0;
115*d9f53676SMatthias Ringwald     uint32_t tag_for_addr = 0;
116*d9f53676SMatthias Ringwald     uint32_t tag_for_empty = 0;
117*d9f53676SMatthias Ringwald 
118*d9f53676SMatthias Ringwald     for (i=0;i<NVM_NUM_LINK_KEYS;i++){
119*d9f53676SMatthias Ringwald         link_key_nvm_t entry;
120*d9f53676SMatthias Ringwald         uint32_t tag = btstack_link_key_db_tag_for_index(i);
121*d9f53676SMatthias Ringwald         int size = self->btstack_tlv_impl->get_tag(self->btstack_tlv_context, tag, (uint8_t*) &entry, sizeof(entry));
122*d9f53676SMatthias Ringwald         // empty/deleted tag
123*d9f53676SMatthias Ringwald         if (size == 0) {
124*d9f53676SMatthias Ringwald             tag_for_empty = tag;
125*d9f53676SMatthias Ringwald             continue;
126*d9f53676SMatthias Ringwald         }
127*d9f53676SMatthias Ringwald         // found addr?
128*d9f53676SMatthias Ringwald         if (memcmp(bd_addr, entry.bd_addr, 6) == 0){
129*d9f53676SMatthias Ringwald             tag_for_addr = tag;
130*d9f53676SMatthias Ringwald         }
131*d9f53676SMatthias Ringwald         // update highest seq nr
132*d9f53676SMatthias Ringwald         if (entry.seq_nr > highest_seq_nr){
133*d9f53676SMatthias Ringwald             highest_seq_nr = entry.seq_nr;
134*d9f53676SMatthias Ringwald         }
135*d9f53676SMatthias Ringwald         // find entry with lowest seq nr
136*d9f53676SMatthias Ringwald         if ((tag_for_lowest_seq_nr == 0) || (entry.seq_nr < lowest_seq_nr)){
137*d9f53676SMatthias Ringwald             tag_for_lowest_seq_nr = tag;
138*d9f53676SMatthias Ringwald             lowest_seq_nr = entry.seq_nr;
139*d9f53676SMatthias Ringwald         }
140*d9f53676SMatthias Ringwald     }
141*d9f53676SMatthias Ringwald 
142*d9f53676SMatthias Ringwald     log_info("tag_for_addr %x, tag_for_empy %x, tag_for_lowest_seq_nr %x", tag_for_addr, tag_for_empty, tag_for_lowest_seq_nr);
143*d9f53676SMatthias Ringwald 
144*d9f53676SMatthias Ringwald     uint32_t tag_to_use = 0;
145*d9f53676SMatthias Ringwald     if (tag_for_addr){
146*d9f53676SMatthias Ringwald         tag_to_use = tag_for_addr;
147*d9f53676SMatthias Ringwald     } else if (tag_for_empty){
148*d9f53676SMatthias Ringwald         tag_to_use = tag_for_empty;
149*d9f53676SMatthias Ringwald     } else if (tag_for_lowest_seq_nr){
150*d9f53676SMatthias Ringwald         tag_to_use = tag_for_lowest_seq_nr;
151*d9f53676SMatthias Ringwald     } else {
152*d9f53676SMatthias Ringwald         // should not happen
153*d9f53676SMatthias Ringwald         return;
154*d9f53676SMatthias Ringwald     }
155*d9f53676SMatthias Ringwald 
156*d9f53676SMatthias Ringwald     log_info("store with tag %x", tag_to_use);
157*d9f53676SMatthias Ringwald 
158*d9f53676SMatthias Ringwald     link_key_nvm_t entry;
159*d9f53676SMatthias Ringwald 
160*d9f53676SMatthias Ringwald     memcpy(entry.bd_addr, bd_addr, 6);
161*d9f53676SMatthias Ringwald     memcpy(entry.link_key, link_key, 16);
162*d9f53676SMatthias Ringwald     entry.link_key_type = link_key_type;
163*d9f53676SMatthias Ringwald     entry.seq_nr = highest_seq_nr + 1;
164*d9f53676SMatthias Ringwald 
165*d9f53676SMatthias Ringwald     self->btstack_tlv_impl->store_tag(self->btstack_tlv_context, tag_to_use, (uint8_t*) &entry, sizeof(entry));
166*d9f53676SMatthias Ringwald }
167*d9f53676SMatthias Ringwald 
168*d9f53676SMatthias Ringwald const btstack_link_key_db_t btstack_link_key_db_tlv = {
169*d9f53676SMatthias Ringwald     btstack_link_key_db_tlv_open,
170*d9f53676SMatthias Ringwald     btstack_link_key_db_tlv_set_bd_addr,
171*d9f53676SMatthias Ringwald     btstack_link_key_db_tlv_close,
172*d9f53676SMatthias Ringwald     btstack_link_key_db_tlv_get_link_key,
173*d9f53676SMatthias Ringwald     btstack_link_key_db_tlv_put_link_key,
174*d9f53676SMatthias Ringwald     btstack_link_key_db_tlv_delete_link_key,
175*d9f53676SMatthias Ringwald };
176*d9f53676SMatthias Ringwald 
177*d9f53676SMatthias 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){
178*d9f53676SMatthias Ringwald     self->btstack_tlv_impl = btstack_tlv_impl;
179*d9f53676SMatthias Ringwald     self->btstack_tlv_context = btstack_tlv_context;
180*d9f53676SMatthias Ringwald     return &btstack_link_key_db_tlv;
181*d9f53676SMatthias Ringwald }
182*d9f53676SMatthias Ringwald 
183*d9f53676SMatthias Ringwald 
184