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 23d9f53676SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24d9f53676SMatthias Ringwald * RINGWALD 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 51e0bb66f8SMatthias Ringwald #define NVM_NUM_LINK_KEYS 1 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 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 78d9f53676SMatthias Ringwald static void btstack_link_key_db_tlv_open(void){ 79d9f53676SMatthias Ringwald } 80d9f53676SMatthias Ringwald 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 85d9f53676SMatthias Ringwald static void btstack_link_key_db_tlv_close(void){ 86d9f53676SMatthias Ringwald } 87d9f53676SMatthias Ringwald 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; 95d9f53676SMatthias Ringwald log_info("tag %x, addr %s", tag, bd_addr_to_str(entry.bd_addr)); 96d9f53676SMatthias Ringwald if (memcmp(bd_addr, entry.bd_addr, 6)) continue; 97d9f53676SMatthias Ringwald // found, pass back 98d9f53676SMatthias Ringwald 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 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 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 151d9f53676SMatthias 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); 152d9f53676SMatthias Ringwald 153d9f53676SMatthias Ringwald uint32_t tag_to_use = 0; 154d9f53676SMatthias Ringwald if (tag_for_addr){ 155d9f53676SMatthias Ringwald tag_to_use = tag_for_addr; 156d9f53676SMatthias Ringwald } else if (tag_for_empty){ 157d9f53676SMatthias Ringwald tag_to_use = tag_for_empty; 158d9f53676SMatthias Ringwald } else if (tag_for_lowest_seq_nr){ 159d9f53676SMatthias Ringwald tag_to_use = tag_for_lowest_seq_nr; 160d9f53676SMatthias Ringwald } else { 161d9f53676SMatthias Ringwald // should not happen 162d9f53676SMatthias Ringwald return; 163d9f53676SMatthias Ringwald } 164d9f53676SMatthias Ringwald 165d9f53676SMatthias Ringwald log_info("store with tag %x", tag_to_use); 166d9f53676SMatthias Ringwald 167d9f53676SMatthias Ringwald link_key_nvm_t entry; 168d9f53676SMatthias Ringwald 169d9f53676SMatthias Ringwald memcpy(entry.bd_addr, bd_addr, 6); 170d9f53676SMatthias Ringwald memcpy(entry.link_key, link_key, 16); 171d9f53676SMatthias Ringwald entry.link_key_type = link_key_type; 172d9f53676SMatthias Ringwald entry.seq_nr = highest_seq_nr + 1; 173d9f53676SMatthias Ringwald 174*0fe46bc1SMatthias Ringwald int result = self->btstack_tlv_impl->store_tag(self->btstack_tlv_context, tag_to_use, (uint8_t*) &entry, sizeof(entry)); 175*0fe46bc1SMatthias Ringwald if (result != 0){ 176*0fe46bc1SMatthias Ringwald log_error("store link key failed"); 177*0fe46bc1SMatthias Ringwald } 178d9f53676SMatthias Ringwald } 179d9f53676SMatthias Ringwald 1806b9d8000SMatthias Ringwald static int btstack_link_key_db_tlv_iterator_init(btstack_link_key_iterator_t * it){ 1816b9d8000SMatthias Ringwald it->context = (void*) 0; 1826b9d8000SMatthias Ringwald return 1; 1836b9d8000SMatthias Ringwald } 1846b9d8000SMatthias Ringwald 1856b9d8000SMatthias 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){ 1866b9d8000SMatthias Ringwald uintptr_t i = (uintptr_t) it->context; 1876b9d8000SMatthias Ringwald int found = 0; 1886b9d8000SMatthias Ringwald while (i<NVM_NUM_LINK_KEYS){ 1896b9d8000SMatthias Ringwald link_key_nvm_t entry; 1906b9d8000SMatthias Ringwald uint32_t tag = btstack_link_key_db_tag_for_index(i++); 1916b9d8000SMatthias Ringwald int size = self->btstack_tlv_impl->get_tag(self->btstack_tlv_context, tag, (uint8_t*) &entry, sizeof(entry)); 1926b9d8000SMatthias Ringwald if (size == 0) continue; 1936b9d8000SMatthias Ringwald memcpy(bd_addr, entry.bd_addr, 6); 1946b9d8000SMatthias Ringwald memcpy(link_key, entry.link_key, 16); 1956b9d8000SMatthias Ringwald *link_key_type = entry.link_key_type; 1966b9d8000SMatthias Ringwald found = 1; 1976b9d8000SMatthias Ringwald break; 1986b9d8000SMatthias Ringwald } 1996b9d8000SMatthias Ringwald it->context = (void*) i; 2006b9d8000SMatthias Ringwald return found; 2016b9d8000SMatthias Ringwald } 2026b9d8000SMatthias Ringwald 2036b9d8000SMatthias Ringwald static void btstack_link_key_db_tlv_iterator_done(btstack_link_key_iterator_t * it){ 2046b9d8000SMatthias Ringwald UNUSED(it); 2056b9d8000SMatthias Ringwald } 2066b9d8000SMatthias Ringwald 207e2717974SMatthias Ringwald static const btstack_link_key_db_t btstack_link_key_db_tlv = { 208d9f53676SMatthias Ringwald btstack_link_key_db_tlv_open, 209d9f53676SMatthias Ringwald btstack_link_key_db_tlv_set_bd_addr, 210d9f53676SMatthias Ringwald btstack_link_key_db_tlv_close, 211d9f53676SMatthias Ringwald btstack_link_key_db_tlv_get_link_key, 212d9f53676SMatthias Ringwald btstack_link_key_db_tlv_put_link_key, 213d9f53676SMatthias Ringwald btstack_link_key_db_tlv_delete_link_key, 2146b9d8000SMatthias Ringwald btstack_link_key_db_tlv_iterator_init, 2156b9d8000SMatthias Ringwald btstack_link_key_db_tlv_iterator_get_next, 2166b9d8000SMatthias Ringwald btstack_link_key_db_tlv_iterator_done, 217d9f53676SMatthias Ringwald }; 218d9f53676SMatthias Ringwald 219d9f53676SMatthias 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){ 220d9f53676SMatthias Ringwald self->btstack_tlv_impl = btstack_tlv_impl; 221d9f53676SMatthias Ringwald self->btstack_tlv_context = btstack_tlv_context; 222d9f53676SMatthias Ringwald return &btstack_link_key_db_tlv; 223d9f53676SMatthias Ringwald } 224d9f53676SMatthias Ringwald 225d9f53676SMatthias Ringwald 226