db.c revision 1.1 1 1.1 plunky /* $NetBSD: db.c,v 1.1 2006/09/10 15:45:56 plunky Exp $ */
2 1.1 plunky
3 1.1 plunky /*-
4 1.1 plunky * Copyright (c) 2006 Itronix Inc.
5 1.1 plunky * All rights reserved.
6 1.1 plunky *
7 1.1 plunky * Written by Iain Hibbert for Itronix Inc.
8 1.1 plunky *
9 1.1 plunky * Redistribution and use in source and binary forms, with or without
10 1.1 plunky * modification, are permitted provided that the following conditions
11 1.1 plunky * are met:
12 1.1 plunky * 1. Redistributions of source code must retain the above copyright
13 1.1 plunky * notice, this list of conditions and the following disclaimer.
14 1.1 plunky * 2. Redistributions in binary form must reproduce the above copyright
15 1.1 plunky * notice, this list of conditions and the following disclaimer in the
16 1.1 plunky * documentation and/or other materials provided with the distribution.
17 1.1 plunky * 3. The name of Itronix Inc. may not be used to endorse
18 1.1 plunky * or promote products derived from this software without specific
19 1.1 plunky * prior written permission.
20 1.1 plunky *
21 1.1 plunky * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
22 1.1 plunky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 1.1 plunky * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 1.1 plunky * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
25 1.1 plunky * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 1.1 plunky * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 1.1 plunky * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 1.1 plunky * ON ANY THEORY OF LIABILITY, WHETHER IN
29 1.1 plunky * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 1.1 plunky * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 1.1 plunky * POSSIBILITY OF SUCH DAMAGE.
32 1.1 plunky */
33 1.1 plunky
34 1.1 plunky #include <sys/cdefs.h>
35 1.1 plunky __RCSID("$NetBSD: db.c,v 1.1 2006/09/10 15:45:56 plunky Exp $");
36 1.1 plunky
37 1.1 plunky #include <bluetooth.h>
38 1.1 plunky #include <err.h>
39 1.1 plunky #include <stdlib.h>
40 1.1 plunky
41 1.1 plunky #include <prop/proplib.h>
42 1.1 plunky
43 1.1 plunky #include <dev/bluetooth/btdev.h>
44 1.1 plunky #include <dev/bluetooth/btsco.h>
45 1.1 plunky
46 1.1 plunky #include "btdevctl.h"
47 1.1 plunky
48 1.1 plunky #define BTDEVCTL_PLIST "/var/db/btdevctl.plist"
49 1.1 plunky #define BTDEVCTL_VERSION 1
50 1.1 plunky
51 1.1 plunky static prop_dictionary_t db = NULL;
52 1.1 plunky static int db_flush = TRUE; /* write db on set */
53 1.1 plunky
54 1.1 plunky static void db_update0(void);
55 1.1 plunky
56 1.1 plunky /*
57 1.1 plunky * lookup laddr/raddr/service in database and return dictionary
58 1.1 plunky */
59 1.1 plunky prop_dictionary_t
60 1.1 plunky db_get(bdaddr_t *laddr, bdaddr_t *raddr, const char *service)
61 1.1 plunky {
62 1.1 plunky prop_dictionary_t ldev, rdev, dev;
63 1.1 plunky prop_object_t obj;
64 1.1 plunky
65 1.1 plunky if (db == NULL) {
66 1.1 plunky db = prop_dictionary_internalize_from_file(BTDEVCTL_PLIST);
67 1.1 plunky if (db == NULL) {
68 1.1 plunky db = prop_dictionary_create();
69 1.1 plunky if (db == NULL)
70 1.1 plunky err(EXIT_FAILURE, "prop_dictionary_create");
71 1.1 plunky
72 1.1 plunky return NULL;
73 1.1 plunky } else {
74 1.1 plunky obj = prop_dictionary_get(db, "btdevctl-version");
75 1.1 plunky switch(prop_number_integer_value(obj)) {
76 1.1 plunky case 0:
77 1.1 plunky db_update0();
78 1.1 plunky break;
79 1.1 plunky
80 1.1 plunky case BTDEVCTL_VERSION:
81 1.1 plunky break;
82 1.1 plunky
83 1.1 plunky default:
84 1.1 plunky errx(EXIT_FAILURE, "unknown btdevctl-version");
85 1.1 plunky }
86 1.1 plunky }
87 1.1 plunky }
88 1.1 plunky
89 1.1 plunky ldev = prop_dictionary_get(db, bt_ntoa(laddr, NULL));
90 1.1 plunky if (prop_object_type(ldev) != PROP_TYPE_DICTIONARY)
91 1.1 plunky return NULL;
92 1.1 plunky
93 1.1 plunky rdev = prop_dictionary_get(ldev, bt_ntoa(raddr, NULL));
94 1.1 plunky if (prop_object_type(rdev) != PROP_TYPE_DICTIONARY)
95 1.1 plunky return NULL;
96 1.1 plunky
97 1.1 plunky dev = prop_dictionary_get(rdev, service);
98 1.1 plunky if (prop_object_type(dev) != PROP_TYPE_DICTIONARY)
99 1.1 plunky return NULL;
100 1.1 plunky
101 1.1 plunky return dev;
102 1.1 plunky }
103 1.1 plunky
104 1.1 plunky /*
105 1.1 plunky * store dictionary in database at laddr/raddr/service
106 1.1 plunky */
107 1.1 plunky int
108 1.1 plunky db_set(prop_dictionary_t dev, bdaddr_t *laddr, bdaddr_t *raddr, const char *service)
109 1.1 plunky {
110 1.1 plunky prop_dictionary_t ldev, rdev;
111 1.1 plunky prop_number_t version;
112 1.1 plunky
113 1.1 plunky ldev = prop_dictionary_get(db, bt_ntoa(laddr, NULL));
114 1.1 plunky if (ldev == NULL) {
115 1.1 plunky ldev = prop_dictionary_create();
116 1.1 plunky if (ldev == NULL)
117 1.1 plunky return 0;
118 1.1 plunky
119 1.1 plunky if (!prop_dictionary_set(db, bt_ntoa(laddr, NULL), ldev))
120 1.1 plunky return 0;
121 1.1 plunky
122 1.1 plunky prop_object_release(ldev);
123 1.1 plunky }
124 1.1 plunky
125 1.1 plunky rdev = prop_dictionary_get(ldev, bt_ntoa(raddr, NULL));
126 1.1 plunky if (rdev == NULL) {
127 1.1 plunky rdev = prop_dictionary_create();
128 1.1 plunky if (rdev == NULL)
129 1.1 plunky return 0;
130 1.1 plunky
131 1.1 plunky if (!prop_dictionary_set(ldev, bt_ntoa(raddr, NULL), rdev))
132 1.1 plunky return 0;
133 1.1 plunky
134 1.1 plunky prop_object_release(rdev);
135 1.1 plunky }
136 1.1 plunky
137 1.1 plunky if (!prop_dictionary_set(rdev, service, dev))
138 1.1 plunky return 0;
139 1.1 plunky
140 1.1 plunky if (db_flush == TRUE) {
141 1.1 plunky version = prop_number_create_integer(BTDEVCTL_VERSION);
142 1.1 plunky if (version == NULL)
143 1.1 plunky err(EXIT_FAILURE, "prop_number_create_integer");
144 1.1 plunky
145 1.1 plunky if (!prop_dictionary_set(db, "btdevctl-version", version))
146 1.1 plunky err(EXIT_FAILURE, "prop_dictionary_set");
147 1.1 plunky
148 1.1 plunky prop_object_release(version);
149 1.1 plunky
150 1.1 plunky if (!prop_dictionary_externalize_to_file(db, BTDEVCTL_PLIST))
151 1.1 plunky warn("%s", BTDEVCTL_PLIST);
152 1.1 plunky }
153 1.1 plunky
154 1.1 plunky return 1;
155 1.1 plunky }
156 1.1 plunky
157 1.1 plunky /*
158 1.1 plunky * update database from version 0. This was a flat file using
159 1.1 plunky * btdevN as an index, and local-bdaddr and remote-bdaddr stored
160 1.1 plunky * as data objects. Step through and add them to the new dictionary.
161 1.1 plunky * We have to generate the service, but only HID, HF and HSET
162 1.1 plunky * were supported, so thats not too difficult.
163 1.1 plunky */
164 1.1 plunky static void
165 1.1 plunky db_update0(void)
166 1.1 plunky {
167 1.1 plunky prop_dictionary_t old, dev;
168 1.1 plunky prop_dictionary_keysym_t key;
169 1.1 plunky prop_object_iterator_t iter;
170 1.1 plunky prop_object_t obj;
171 1.1 plunky bdaddr_t laddr, raddr;
172 1.1 plunky char *service;
173 1.1 plunky
174 1.1 plunky db_flush = FALSE; /* no write on set */
175 1.1 plunky old = db;
176 1.1 plunky
177 1.1 plunky db = prop_dictionary_create();
178 1.1 plunky if (db == NULL)
179 1.1 plunky err(EXIT_FAILURE, "prop_dictionary_create");
180 1.1 plunky
181 1.1 plunky iter = prop_dictionary_iterator(old);
182 1.1 plunky if (iter == NULL)
183 1.1 plunky err(EXIT_FAILURE, "prop_dictionary_iterator");
184 1.1 plunky
185 1.1 plunky while ((key = prop_object_iterator_next(iter)) != NULL) {
186 1.1 plunky dev = prop_dictionary_get_keysym(old, key);
187 1.1 plunky if (prop_object_type(dev) != PROP_TYPE_DICTIONARY)
188 1.1 plunky errx(EXIT_FAILURE, "invalid device dictionary");
189 1.1 plunky
190 1.1 plunky obj = prop_dictionary_get(dev, BTDEVladdr);
191 1.1 plunky if (prop_data_size(obj) != sizeof(laddr))
192 1.1 plunky errx(EXIT_FAILURE, "invalid %s", BTDEVladdr);
193 1.1 plunky
194 1.1 plunky bdaddr_copy(&laddr, prop_data_data_nocopy(obj));
195 1.1 plunky prop_dictionary_remove(dev, BTDEVladdr);
196 1.1 plunky
197 1.1 plunky obj = prop_dictionary_get(dev, BTDEVraddr);
198 1.1 plunky if (prop_data_size(obj) != sizeof(raddr))
199 1.1 plunky errx(EXIT_FAILURE, "invalid %s", BTDEVraddr);
200 1.1 plunky
201 1.1 plunky bdaddr_copy(&raddr, prop_data_data_nocopy(obj));
202 1.1 plunky prop_dictionary_remove(dev, BTDEVraddr);
203 1.1 plunky
204 1.1 plunky obj = prop_dictionary_get(dev, BTDEVtype);
205 1.1 plunky if (prop_string_equals_cstring(obj, "bthidev"))
206 1.1 plunky service = "HID";
207 1.1 plunky else if (prop_string_equals_cstring(obj, "btsco")) {
208 1.1 plunky obj = prop_dictionary_get(dev, BTSCOlisten);
209 1.1 plunky if (prop_bool_true(obj))
210 1.1 plunky service = "HF";
211 1.1 plunky else
212 1.1 plunky service = "HSET";
213 1.1 plunky } else
214 1.1 plunky errx(EXIT_FAILURE, "invalid %s", BTDEVtype);
215 1.1 plunky
216 1.1 plunky if (!db_set(dev, &laddr, &raddr, service))
217 1.1 plunky err(EXIT_FAILURE, "service store failed");
218 1.1 plunky }
219 1.1 plunky
220 1.1 plunky prop_object_iterator_release(iter);
221 1.1 plunky prop_object_release(old);
222 1.1 plunky
223 1.1 plunky db_flush = TRUE; /* write on set */
224 1.1 plunky }
225