3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2001-2002 Nokia Corporation
6 * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
7 * Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
8 * Copyright (C) 2002-2003 Stephen Crane <steve.crane@rococosoft.com>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include <sys/socket.h>
36 #include <bluetooth/bluetooth.h>
37 #include <bluetooth/l2cap.h>
38 #include <bluetooth/sdp.h>
39 #include <bluetooth/sdp_lib.h>
46 static sdp_list_t *service_db;
47 static sdp_list_t *access_db;
55 * Ordering function called when inserting a service record.
56 * The service repository is a linked list in sorted order
57 * and the service record handle is the sort key
59 int record_sort(const void *r1, const void *r2)
61 const sdp_record_t *rec1 = r1;
62 const sdp_record_t *rec2 = r2;
65 error("NULL RECORD LIST FATAL");
69 return rec1->handle - rec2->handle;
72 static int access_sort(const void *r1, const void *r2)
74 const sdp_access_t *rec1 = r1;
75 const sdp_access_t *rec2 = r2;
78 error("NULL RECORD LIST FATAL");
82 return rec1->handle - rec2->handle;
85 static void access_free(void *p)
91 * Reset the service repository by deleting its contents
93 void sdp_svcdb_reset(void)
95 sdp_list_free(service_db, (sdp_free_func_t) sdp_record_free);
96 sdp_list_free(access_db, access_free);
99 typedef struct _indexed {
101 sdp_record_t *record;
104 static sdp_list_t *socket_index;
107 * collect all services registered over this socket
109 void sdp_svcdb_collect_all(int sock)
113 for (p = socket_index, q = 0; p; ) {
114 sdp_indexed_t *item = p->data;
115 if (item->sock == sock) {
116 sdp_list_t *next = p->next;
117 sdp_record_remove(item->record->handle);
118 sdp_record_free(item->record);
126 } else if (item->sock > sock)
135 void sdp_svcdb_collect(sdp_record_t *rec)
139 for (p = socket_index, q = 0; p; q = p, p = p->next) {
140 sdp_indexed_t *item = p->data;
141 if (rec == item->record) {
146 socket_index = p->next;
153 static int compare_indices(const void *i1, const void *i2)
155 const sdp_indexed_t *s1 = i1;
156 const sdp_indexed_t *s2 = i2;
157 return s1->sock - s2->sock;
160 void sdp_svcdb_set_collectable(sdp_record_t *record, int sock)
162 sdp_indexed_t *item = malloc(sizeof(sdp_indexed_t));
164 item->record = record;
165 socket_index = sdp_list_insert_sorted(socket_index, item, compare_indices);
169 * Add a service record to the repository
171 void sdp_record_add(const bdaddr_t *device, sdp_record_t *rec)
173 struct btd_adapter *adapter;
176 SDPDBG("Adding rec : 0x%lx", (long) rec);
177 SDPDBG("with handle : 0x%x", rec->handle);
179 service_db = sdp_list_insert_sorted(service_db, rec, record_sort);
181 dev = malloc(sizeof(*dev));
185 bacpy(&dev->device, device);
186 dev->handle = rec->handle;
188 access_db = sdp_list_insert_sorted(access_db, dev, access_sort);
190 if (bacmp(device, BDADDR_ANY) == 0) {
191 manager_foreach_adapter(adapter_service_insert, rec);
195 adapter = manager_find_adapter(device);
197 adapter_service_insert(adapter, rec);
200 static sdp_list_t *record_locate(uint32_t handle)
207 p = sdp_list_find(service_db, &r, record_sort);
211 SDPDBG("Could not find svcRec for : 0x%x", handle);
215 static sdp_list_t *access_locate(uint32_t handle)
222 p = sdp_list_find(access_db, &a, access_sort);
226 SDPDBG("Could not find access data for : 0x%x", handle);
231 * Given a service record handle, find the record associated with it.
233 sdp_record_t *sdp_record_find(uint32_t handle)
235 sdp_list_t *p = record_locate(handle);
238 SDPDBG("Couldn't find record for : 0x%x", handle);
246 * Given a service record handle, remove its record from the repository
248 int sdp_record_remove(uint32_t handle)
250 sdp_list_t *p = record_locate(handle);
255 error("Remove : Couldn't find record for : 0x%x", handle);
261 service_db = sdp_list_remove(service_db, r);
263 p = access_locate(handle);
264 if (p == NULL || p->data == NULL)
269 if (bacmp(&a->device, BDADDR_ANY) != 0) {
270 struct btd_adapter *adapter = manager_find_adapter(&a->device);
272 adapter_service_remove(adapter, r);
274 manager_foreach_adapter(adapter_service_remove, r);
276 access_db = sdp_list_remove(access_db, a);
283 * Return a pointer to the linked list containing the records in sorted order
285 sdp_list_t *sdp_get_record_list(void)
290 sdp_list_t *sdp_get_access_list(void)
295 int sdp_check_access(uint32_t handle, bdaddr_t *device)
297 sdp_list_t *p = access_locate(handle);
307 if (bacmp(&a->device, device) &&
308 bacmp(&a->device, BDADDR_ANY) &&
309 bacmp(device, BDADDR_ANY))
315 uint32_t sdp_next_handle(void)
317 uint32_t handle = 0x10000;
319 while (sdp_record_find(handle))
325 void sdp_init_services_list(bdaddr_t *device)
331 for (p = access_db; p != NULL; p = p->next) {
332 sdp_access_t *access = p->data;
335 if (bacmp(BDADDR_ANY, &access->device))
338 rec = sdp_record_find(access->handle);
342 SDPDBG("adding record with handle %x", access->handle);
344 manager_foreach_adapter(adapter_service_insert, rec);