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