1/* 2 * Copyright (C) 2009-2012 by Matthias Ringwald 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at [email protected] 34 * 35 */ 36 37#define __BTSTACK_FILE__ "btstack_link_key_db_corefoundation.c" 38 39#include "btstack_link_key_db_corefoundation.h" 40#include "btstack_debug.h" 41 42#import <Foundation/Foundation.h> 43 44#define BTdaemonID "ch.ringwald.btdaemon" 45#define BTDaemonPrefsPath "Library/Preferences/ch.ringwald.btdaemon.plist" 46 47#define DEVICES_KEY "devices" 48#define PREFS_LINK_KEY @"LinkKey" 49 50static NSMutableDictionary *remote_devices = nil; 51 52// Device info 53static void db_open(void){ 54 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 55 56 // NSUserDefaults didn't work 57 // 58 // NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 59 // NSDictionary * dict = [defaults persistentDomainForName:BTdaemonID]; 60 61 // NSDictionary * dict = (NSDictionary*) CFPreferencesCopyAppValue(CFSTR(DEVICES_KEY), CFSTR(BTdaemonID)); 62 NSDictionary * dict; 63 dict = (NSDictionary*) CFPreferencesCopyAppValue(CFSTR(DEVICES_KEY), CFSTR(BTdaemonID)); 64 remote_devices = [[NSMutableDictionary alloc] initWithCapacity:([dict count]+5)]; 65 66 // copy entries 67 for (id key in dict) { 68 NSDictionary *value = [dict objectForKey:key]; 69 NSMutableDictionary *deviceEntry = [NSMutableDictionary dictionaryWithCapacity:[value count]]; 70 [deviceEntry addEntriesFromDictionary:value]; 71 [remote_devices setObject:deviceEntry forKey:key]; 72 } 73 74 log_info("read prefs for %u devices\n", (unsigned int) [dict count]); 75 76 [pool release]; 77} 78 79static void db_set_local_bd_addr(bd_addr_t bd_addr){ 80} 81 82static void db_synchronize(void){ 83 log_info("stored prefs for %u devices\n", (unsigned int) [remote_devices count]); 84 85 // 3 different ways 86 87 // Core Foundation 88 CFPreferencesSetValue(CFSTR(DEVICES_KEY), (CFPropertyListRef) remote_devices, CFSTR(BTdaemonID), kCFPreferencesCurrentUser, kCFPreferencesCurrentHost); 89 CFPreferencesSynchronize(CFSTR(BTdaemonID), kCFPreferencesCurrentUser, kCFPreferencesCurrentHost); 90 91 // NSUserDefaults didn't work 92 // 93 // NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 94 // [defaults setPersistentDomain:remote_devices forName:BTdaemonID]; 95 // [defaults synchronize]; 96} 97 98static void db_close(void){ 99 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 100 101 // don't call db_synchronize(); 102 // a) we're calling db_synchronize() after each change already 103 // b) db_close is called during the SIGINT handler which causes a corrupt prefs file 104 105 [remote_devices release]; 106 remote_devices = nil; 107 [pool release]; 108} 109 110static NSString * stringForAddress(bd_addr_t addr) { 111 return [NSString stringWithFormat:@"%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2], 112 addr[3], addr[4], addr[5]]; 113} 114 115static void set_value(bd_addr_t bd_addr, NSString *key, id value){ 116 NSString *devAddress = stringForAddress(bd_addr); 117 NSMutableDictionary * deviceDict = [remote_devices objectForKey:devAddress]; 118 if (!deviceDict){ 119 deviceDict = [NSMutableDictionary dictionaryWithCapacity:3]; 120 [remote_devices setObject:deviceDict forKey:devAddress]; 121 } 122 [deviceDict setObject:value forKey:key]; 123 db_synchronize(); 124} 125 126static void delete_value(bd_addr_t bd_addr, NSString *key){ 127 NSString *devAddress = stringForAddress(bd_addr); 128 NSMutableDictionary * deviceDict = [remote_devices objectForKey:devAddress]; 129 [deviceDict removeObjectForKey:key]; 130 db_synchronize(); 131 132} 133 134static id get_value(bd_addr_t bd_addr, NSString *key){ 135 NSString *devAddress = stringForAddress(bd_addr); 136 NSMutableDictionary * deviceDict = [remote_devices objectForKey:devAddress]; 137 if (!deviceDict) return nil; 138 return [deviceDict objectForKey:key]; 139} 140 141static int get_link_key(bd_addr_t bd_addr, link_key_t link_key, link_key_type_t * link_key_type) { 142 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 143 NSData *linkKey = get_value(bd_addr, PREFS_LINK_KEY); 144 if ([linkKey length] == LINK_KEY_LEN){ 145 memcpy(link_key, [linkKey bytes], LINK_KEY_LEN); 146 if (link_key_type){ 147 *link_key_type = COMBINATION_KEY; 148 } 149 } 150 [pool release]; 151 return (linkKey != nil); 152} 153 154static void put_link_key(bd_addr_t bd_addr, link_key_t link_key, link_key_type_t link_key_type){ 155 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 156 NSData *linkKey = [NSData dataWithBytes:link_key length:16]; 157 set_value(bd_addr, PREFS_LINK_KEY, linkKey); 158 [pool release]; 159} 160 161static void delete_link_key(bd_addr_t bd_addr){ 162 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 163 delete_value(bd_addr, PREFS_LINK_KEY); 164 [pool release]; 165} 166 167const btstack_link_key_db_t btstack_link_key_db_cocoa = { 168 db_open, 169 db_set_local_bd_addr, 170 db_close, 171 get_link_key, 172 put_link_key, 173 delete_link_key, 174}; 175 176const btstack_link_key_db_t * btstack_link_key_db_corefoundation_instance(void){ 177 return &btstack_link_key_db_cocoa; 178} 179