service.c revision 3df548164d179e08032c82b90cc56edbf83ef9bf
1/*
2 *
3 *  BlueZ - Bluetooth protocol stack for Linux
4 *
5 *  Copyright (C) 2006-2010  Nokia Corporation
6 *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
7 *
8 *
9 *  This program is free software; you can redistribute it and/or modify
10 *  it under the terms of the GNU General Public License as published by
11 *  the Free Software Foundation; either version 2 of the License, or
12 *  (at your option) any later version.
13 *
14 *  This program is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this program; if not, write to the Free Software
21 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22 *
23 */
24
25#ifdef HAVE_CONFIG_H
26#include <config.h>
27#endif
28
29#include <errno.h>
30#include <stdlib.h>
31#include <string.h>
32
33#include <bluetooth/bluetooth.h>
34#include <bluetooth/sdp.h>
35#include <bluetooth/sdp_lib.h>
36
37#include <gdbus.h>
38
39#include "sdpd.h"
40#include "sdp-xml.h"
41#include "plugin.h"
42#include "adapter.h"
43#include "error.h"
44#include "log.h"
45
46#define SERVICE_INTERFACE "org.bluez.Service"
47
48static DBusConnection *connection;
49
50struct record_data {
51	uint32_t handle;
52	char *sender;
53	guint listener_id;
54	struct service_adapter *serv_adapter;
55};
56
57struct context_data {
58	sdp_record_t *record;
59	sdp_data_t attr_data;
60	struct sdp_xml_data *stack_head;
61	uint16_t attr_id;
62};
63
64struct pending_auth {
65	DBusConnection *conn;
66	DBusMessage *msg;
67	char *sender;
68	bdaddr_t dst;
69	char uuid[MAX_LEN_UUID_STR];
70};
71
72struct service_adapter {
73	struct btd_adapter *adapter;
74	GSList *pending_list;
75	GSList *records;
76};
77
78static struct service_adapter *serv_adapter_any = NULL;
79
80static int compute_seq_size(sdp_data_t *data)
81{
82	int unit_size = data->unitSize;
83	sdp_data_t *seq = data->val.dataseq;
84
85	for (; seq; seq = seq->next)
86		unit_size += seq->unitSize;
87
88	return unit_size;
89}
90
91static void element_start(GMarkupParseContext *context,
92		const gchar *element_name, const gchar **attribute_names,
93		const gchar **attribute_values, gpointer user_data, GError **err)
94{
95	struct context_data *ctx_data = user_data;
96
97	if (!strcmp(element_name, "record"))
98		return;
99
100	if (!strcmp(element_name, "attribute")) {
101		int i;
102		for (i = 0; attribute_names[i]; i++) {
103			if (!strcmp(attribute_names[i], "id")) {
104				ctx_data->attr_id = strtol(attribute_values[i], 0, 0);
105				break;
106			}
107		}
108		DBG("New attribute 0x%04x", ctx_data->attr_id);
109		return;
110	}
111
112	if (ctx_data->stack_head) {
113		struct sdp_xml_data *newelem = sdp_xml_data_alloc();
114		newelem->next = ctx_data->stack_head;
115		ctx_data->stack_head = newelem;
116	} else {
117		ctx_data->stack_head = sdp_xml_data_alloc();
118		ctx_data->stack_head->next = NULL;
119	}
120
121	if (!strcmp(element_name, "sequence"))
122		ctx_data->stack_head->data = sdp_data_alloc(SDP_SEQ8, NULL);
123	else if (!strcmp(element_name, "alternate"))
124		ctx_data->stack_head->data = sdp_data_alloc(SDP_ALT8, NULL);
125	else {
126		int i;
127		/* Parse value, name, encoding */
128		for (i = 0; attribute_names[i]; i++) {
129			if (!strcmp(attribute_names[i], "value")) {
130				int curlen = strlen(ctx_data->stack_head->text);
131				int attrlen = strlen(attribute_values[i]);
132
133				/* Ensure we're big enough */
134				while ((curlen + 1 + attrlen) > ctx_data->stack_head->size) {
135					sdp_xml_data_expand(ctx_data->stack_head);
136				}
137
138				memcpy(ctx_data->stack_head->text + curlen,
139						attribute_values[i], attrlen);
140				ctx_data->stack_head->text[curlen + attrlen] = '\0';
141			}
142
143			if (!strcmp(attribute_names[i], "encoding")) {
144				if (!strcmp(attribute_values[i], "hex"))
145					ctx_data->stack_head->type = 1;
146			}
147
148			if (!strcmp(attribute_names[i], "name")) {
149				ctx_data->stack_head->name = strdup(attribute_values[i]);
150			}
151		}
152
153		ctx_data->stack_head->data = sdp_xml_parse_datatype(element_name,
154				ctx_data->stack_head, ctx_data->record);
155
156		if (ctx_data->stack_head->data == NULL)
157			error("Can't parse element %s", element_name);
158	}
159}
160
161static void element_end(GMarkupParseContext *context,
162		const gchar *element_name, gpointer user_data, GError **err)
163{
164	struct context_data *ctx_data = user_data;
165	struct sdp_xml_data *elem;
166
167	if (!strcmp(element_name, "record"))
168		return;
169
170	if (!strcmp(element_name, "attribute")) {
171		if (ctx_data->stack_head && ctx_data->stack_head->data) {
172			int ret = sdp_attr_add(ctx_data->record, ctx_data->attr_id,
173							ctx_data->stack_head->data);
174			if (ret == -1)
175				DBG("Trouble adding attribute\n");
176
177			ctx_data->stack_head->data = NULL;
178			sdp_xml_data_free(ctx_data->stack_head);
179			ctx_data->stack_head = NULL;
180		} else {
181			DBG("No data for attribute 0x%04x\n", ctx_data->attr_id);
182		}
183		return;
184	}
185
186	if (!strcmp(element_name, "sequence")) {
187		ctx_data->stack_head->data->unitSize = compute_seq_size(ctx_data->stack_head->data);
188
189		if (ctx_data->stack_head->data->unitSize > USHRT_MAX) {
190			ctx_data->stack_head->data->unitSize += sizeof(uint32_t);
191			ctx_data->stack_head->data->dtd = SDP_SEQ32;
192		} else if (ctx_data->stack_head->data->unitSize > UCHAR_MAX) {
193			ctx_data->stack_head->data->unitSize += sizeof(uint16_t);
194			ctx_data->stack_head->data->dtd = SDP_SEQ16;
195		} else {
196			ctx_data->stack_head->data->unitSize += sizeof(uint8_t);
197		}
198	} else if (!strcmp(element_name, "alternate")) {
199		ctx_data->stack_head->data->unitSize = compute_seq_size(ctx_data->stack_head->data);
200
201		if (ctx_data->stack_head->data->unitSize > USHRT_MAX) {
202			ctx_data->stack_head->data->unitSize += sizeof(uint32_t);
203			ctx_data->stack_head->data->dtd = SDP_ALT32;
204		} else if (ctx_data->stack_head->data->unitSize > UCHAR_MAX) {
205			ctx_data->stack_head->data->unitSize += sizeof(uint16_t);
206			ctx_data->stack_head->data->dtd = SDP_ALT16;
207		} else {
208			ctx_data->stack_head->data->unitSize += sizeof(uint8_t);
209		}
210	}
211
212	if (ctx_data->stack_head->next && ctx_data->stack_head->data &&
213					ctx_data->stack_head->next->data) {
214		switch (ctx_data->stack_head->next->data->dtd) {
215		case SDP_SEQ8:
216		case SDP_SEQ16:
217		case SDP_SEQ32:
218		case SDP_ALT8:
219		case SDP_ALT16:
220		case SDP_ALT32:
221			ctx_data->stack_head->next->data->val.dataseq =
222				sdp_seq_append(ctx_data->stack_head->next->data->val.dataseq,
223								ctx_data->stack_head->data);
224			ctx_data->stack_head->data = NULL;
225			break;
226		}
227
228		elem = ctx_data->stack_head;
229		ctx_data->stack_head = ctx_data->stack_head->next;
230
231		sdp_xml_data_free(elem);
232	}
233}
234
235static GMarkupParser parser = {
236	element_start, element_end, NULL, NULL, NULL
237};
238
239static sdp_record_t *sdp_xml_parse_record(const char *data, int size)
240{
241	GMarkupParseContext *ctx;
242	struct context_data *ctx_data;
243	sdp_record_t *record;
244
245	ctx_data = malloc(sizeof(*ctx_data));
246	if (!ctx_data)
247		return NULL;
248
249	record = sdp_record_alloc();
250	if (!record) {
251		free(ctx_data);
252		return NULL;
253	}
254
255	memset(ctx_data, 0, sizeof(*ctx_data));
256	ctx_data->record = record;
257
258	ctx = g_markup_parse_context_new(&parser, 0, ctx_data, NULL);
259
260	if (g_markup_parse_context_parse(ctx, data, size, NULL) == FALSE) {
261		error("XML parsing error");
262		g_markup_parse_context_free(ctx);
263		sdp_record_free(record);
264		free(ctx_data);
265		return NULL;
266	}
267
268	g_markup_parse_context_free(ctx);
269
270	free(ctx_data);
271
272	return record;
273}
274
275static struct record_data *find_record(struct service_adapter *serv_adapter,
276					uint32_t handle, const char *sender)
277{
278	GSList *list;
279
280	for (list = serv_adapter->records; list; list = list->next) {
281		struct record_data *data = list->data;
282		if (handle == data->handle && !strcmp(sender, data->sender))
283			return data;
284	}
285
286	return NULL;
287}
288
289static struct pending_auth *next_pending(struct service_adapter *serv_adapter)
290{
291	GSList *l = serv_adapter->pending_list;
292
293	if (l) {
294		struct pending_auth *auth = l->data;
295		return auth;
296	}
297
298	return NULL;
299}
300
301static struct pending_auth *find_pending_by_sender(
302			struct service_adapter *serv_adapter,
303			const char *sender)
304{
305	GSList *l = serv_adapter->pending_list;
306
307	for (; l; l = l->next) {
308		struct pending_auth *auth = l->data;
309		if (g_str_equal(auth->sender, sender))
310			return auth;
311	}
312
313	return NULL;
314}
315
316static void exit_callback(DBusConnection *conn, void *user_data)
317{
318	struct record_data *user_record = user_data;
319	struct service_adapter *serv_adapter = user_record->serv_adapter;
320	struct pending_auth *auth;
321
322	DBG("remove record");
323
324	serv_adapter->records = g_slist_remove(serv_adapter->records,
325						user_record);
326
327	auth = find_pending_by_sender(serv_adapter, user_record->sender);
328	if (auth) {
329		serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list,
330							auth);
331		g_free(auth);
332	}
333
334	remove_record_from_server(user_record->handle);
335
336	g_free(user_record->sender);
337	g_free(user_record);
338}
339
340static inline DBusMessage *failed(DBusMessage *msg)
341{
342	return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", "Failed");
343}
344
345static inline DBusMessage *failed_strerror(DBusMessage *msg, int err)
346{
347	return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
348							"%s", strerror(err));
349}
350
351static int add_xml_record(DBusConnection *conn, const char *sender,
352			struct service_adapter *serv_adapter,
353			const char *record, dbus_uint32_t *handle)
354{
355	struct record_data *user_record;
356	sdp_record_t *sdp_record;
357	bdaddr_t src;
358
359	sdp_record = sdp_xml_parse_record(record, strlen(record));
360	if (!sdp_record) {
361		error("Parsing of XML service record failed");
362		return -EIO;
363	}
364
365	if (serv_adapter->adapter)
366		adapter_get_address(serv_adapter->adapter, &src);
367	else
368		bacpy(&src, BDADDR_ANY);
369
370	if (add_record_to_server(&src, sdp_record) < 0) {
371		error("Failed to register service record");
372		sdp_record_free(sdp_record);
373		return -EIO;
374	}
375
376	user_record = g_new0(struct record_data, 1);
377	user_record->handle = sdp_record->handle;
378	user_record->sender = g_strdup(sender);
379	user_record->serv_adapter = serv_adapter;
380	user_record->listener_id = g_dbus_add_disconnect_watch(conn, sender,
381					exit_callback, user_record, NULL);
382
383	serv_adapter->records = g_slist_append(serv_adapter->records,
384								user_record);
385
386	DBG("listener_id %d", user_record->listener_id);
387
388	*handle = user_record->handle;
389
390	return 0;
391}
392
393static DBusMessage *update_record(DBusConnection *conn, DBusMessage *msg,
394		struct service_adapter *serv_adapter,
395		dbus_uint32_t handle, sdp_record_t *sdp_record)
396{
397	bdaddr_t src;
398	int err;
399
400	if (remove_record_from_server(handle) < 0) {
401		sdp_record_free(sdp_record);
402		return btd_error_not_available(msg);
403	}
404
405	if (serv_adapter->adapter)
406		adapter_get_address(serv_adapter->adapter, &src);
407	else
408		bacpy(&src, BDADDR_ANY);
409
410	sdp_record->handle = handle;
411	err = add_record_to_server(&src, sdp_record);
412	if (err < 0) {
413		sdp_record_free(sdp_record);
414		error("Failed to update the service record");
415		return g_dbus_create_error(msg,
416				ERROR_INTERFACE ".Failed",
417				"%s", strerror(EIO));
418	}
419
420	return dbus_message_new_method_return(msg);
421}
422
423static DBusMessage *update_xml_record(DBusConnection *conn,
424				DBusMessage *msg,
425				struct service_adapter *serv_adapter)
426{
427	struct record_data *user_record;
428	sdp_record_t *sdp_record;
429	const char *record;
430	dbus_uint32_t handle;
431	int len;
432
433	if (dbus_message_get_args(msg, NULL,
434				DBUS_TYPE_UINT32, &handle,
435				DBUS_TYPE_STRING, &record,
436				DBUS_TYPE_INVALID) == FALSE)
437		return NULL;
438
439	len = (record ? strlen(record) : 0);
440	if (len == 0)
441		return btd_error_invalid_args(msg);
442
443	user_record = find_record(serv_adapter, handle,
444				dbus_message_get_sender(msg));
445	if (!user_record)
446		return btd_error_not_available(msg);
447
448	sdp_record = sdp_xml_parse_record(record, len);
449	if (!sdp_record) {
450		error("Parsing of XML service record failed");
451		sdp_record_free(sdp_record);
452		return g_dbus_create_error(msg,
453				ERROR_INTERFACE ".Failed",
454				"%s", strerror(EIO));
455	}
456
457	return update_record(conn, msg, serv_adapter, handle, sdp_record);
458}
459
460static int remove_record(DBusConnection *conn, const char *sender,
461			struct service_adapter *serv_adapter,
462			dbus_uint32_t handle)
463{
464	struct record_data *user_record;
465
466	DBG("remove record 0x%x", handle);
467
468	user_record = find_record(serv_adapter, handle, sender);
469	if (!user_record)
470		return -1;
471
472	DBG("listner_id %d", user_record->listener_id);
473
474	g_dbus_remove_watch(conn, user_record->listener_id);
475
476	exit_callback(conn, user_record);
477
478	return 0;
479}
480
481static DBusMessage *add_service_record(DBusConnection *conn,
482					DBusMessage *msg, void *data)
483{
484	struct service_adapter *serv_adapter = data;
485	DBusMessage *reply;
486	const char *sender, *record;
487	dbus_uint32_t handle;
488	int err;
489
490	if (dbus_message_get_args(msg, NULL,
491			DBUS_TYPE_STRING, &record, DBUS_TYPE_INVALID) == FALSE)
492		return NULL;
493
494	sender = dbus_message_get_sender(msg);
495	err = add_xml_record(conn, sender, serv_adapter, record, &handle);
496	if (err < 0)
497		return failed_strerror(msg, err);
498
499	reply = dbus_message_new_method_return(msg);
500	if (!reply)
501		return NULL;
502
503	dbus_message_append_args(reply, DBUS_TYPE_UINT32, &handle,
504							DBUS_TYPE_INVALID);
505
506	return reply;
507}
508
509static DBusMessage *update_service_record(DBusConnection *conn,
510					DBusMessage *msg, void *data)
511{
512	struct service_adapter *serv_adapter = data;
513
514	return update_xml_record(conn, msg, serv_adapter);
515}
516
517static DBusMessage *remove_service_record(DBusConnection *conn,
518					DBusMessage *msg, void *data)
519{
520	struct service_adapter *serv_adapter = data;
521	dbus_uint32_t handle;
522	const char *sender;
523
524	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle,
525						DBUS_TYPE_INVALID) == FALSE)
526		return NULL;
527
528	sender = dbus_message_get_sender(msg);
529
530	if (remove_record(conn, sender, serv_adapter, handle) < 0)
531		return btd_error_not_available(msg);
532
533	return dbus_message_new_method_return(msg);
534}
535
536static void auth_cb(DBusError *derr, void *user_data)
537{
538	struct service_adapter *serv_adapter = user_data;
539	DBusMessage *reply;
540	struct pending_auth *auth;
541	bdaddr_t src;
542
543	auth = next_pending(serv_adapter);
544	if (auth == NULL) {
545		info("Authorization cancelled: Client exited");
546		return;
547	}
548
549	if (derr) {
550		error("Access denied: %s", derr->message);
551
552		reply = btd_error_not_authorized(auth->msg);
553		dbus_message_unref(auth->msg);
554		g_dbus_send_message(auth->conn, reply);
555		goto done;
556	}
557
558	g_dbus_send_reply(auth->conn, auth->msg,
559			DBUS_TYPE_INVALID);
560
561done:
562	dbus_connection_unref(auth->conn);
563
564	serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list,
565									auth);
566	g_free(auth);
567
568	auth = next_pending(serv_adapter);
569	if (auth == NULL)
570		return;
571
572	if (serv_adapter->adapter)
573		adapter_get_address(serv_adapter->adapter, &src);
574	else
575		bacpy(&src, BDADDR_ANY);
576
577	btd_request_authorization(&src, &auth->dst,
578					auth->uuid, auth_cb, serv_adapter);
579}
580
581static DBusMessage *request_authorization(DBusConnection *conn,
582						DBusMessage *msg, void *data)
583{
584	struct record_data *user_record;
585	struct service_adapter *serv_adapter = data;
586	sdp_record_t *record;
587	sdp_list_t *services;
588	const char *sender;
589	dbus_uint32_t handle;
590	const char *address;
591	struct pending_auth *auth;
592	char uuid_str[MAX_LEN_UUID_STR];
593	uuid_t *uuid, *uuid128;
594	bdaddr_t src;
595
596	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address,
597					DBUS_TYPE_UINT32, &handle,
598					DBUS_TYPE_INVALID) == FALSE)
599		return NULL;
600
601	sender = dbus_message_get_sender(msg);
602	if (find_pending_by_sender(serv_adapter, sender))
603		return btd_error_does_not_exist(msg);
604
605	user_record = find_record(serv_adapter, handle, sender);
606	if (!user_record) {
607		user_record = find_record(serv_adapter_any, handle, sender);
608		if (!user_record)
609			return btd_error_not_authorized(msg);
610	}
611
612	record = sdp_record_find(user_record->handle);
613	if (record == NULL)
614		return btd_error_not_authorized(msg);
615
616	if (sdp_get_service_classes(record, &services) < 0) {
617		sdp_record_free(record);
618		return btd_error_not_authorized(msg);
619	}
620
621	if (services == NULL)
622		return btd_error_not_authorized(msg);
623
624	uuid = services->data;
625	uuid128 = sdp_uuid_to_uuid128(uuid);
626
627	sdp_list_free(services, bt_free);
628
629	if (sdp_uuid2strn(uuid128, uuid_str, MAX_LEN_UUID_STR) < 0) {
630		bt_free(uuid128);
631		return btd_error_not_authorized(msg);
632	}
633	bt_free(uuid128);
634
635	auth = g_new0(struct pending_auth, 1);
636	auth->msg = dbus_message_ref(msg);
637	auth->conn = dbus_connection_ref(connection);
638	auth->sender = user_record->sender;
639	memcpy(auth->uuid, uuid_str, MAX_LEN_UUID_STR);
640	str2ba(address, &auth->dst);
641
642	serv_adapter->pending_list = g_slist_append(serv_adapter->pending_list,
643									auth);
644
645	auth = next_pending(serv_adapter);
646	if (auth == NULL)
647		return btd_error_does_not_exist(msg);
648
649	if (serv_adapter->adapter)
650		adapter_get_address(serv_adapter->adapter, &src);
651	else
652		bacpy(&src, BDADDR_ANY);
653
654	if (btd_request_authorization(&src, &auth->dst, auth->uuid, auth_cb,
655							serv_adapter) < 0) {
656		serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list,
657									auth);
658		g_free(auth);
659		return btd_error_not_authorized(msg);
660	}
661
662	return NULL;
663}
664
665static DBusMessage *cancel_authorization(DBusConnection *conn,
666						DBusMessage *msg, void *data)
667{
668	DBusMessage *reply;
669	struct service_adapter *serv_adapter = data;
670	struct pending_auth *auth;
671	const gchar *sender;
672	bdaddr_t src;
673
674	sender = dbus_message_get_sender(msg);
675
676	auth = find_pending_by_sender(serv_adapter, sender);
677	if (auth == NULL)
678		return btd_error_does_not_exist(msg);
679
680	if (serv_adapter->adapter)
681		adapter_get_address(serv_adapter->adapter, &src);
682	else
683		bacpy(&src, BDADDR_ANY);
684
685	btd_cancel_authorization(&src, &auth->dst);
686
687	reply = btd_error_not_authorized(auth->msg);
688	dbus_message_unref(auth->msg);
689	g_dbus_send_message(auth->conn, reply);
690
691	dbus_connection_unref(auth->conn);
692
693	serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list,
694									auth);
695	g_free(auth);
696
697	auth = next_pending(serv_adapter);
698	if (auth == NULL)
699		goto done;
700
701	if (serv_adapter->adapter)
702		adapter_get_address(serv_adapter->adapter, &src);
703	else
704		bacpy(&src, BDADDR_ANY);
705
706	btd_request_authorization(&src, &auth->dst,
707					auth->uuid, auth_cb, serv_adapter);
708
709done:
710	return dbus_message_new_method_return(msg);
711}
712
713static GDBusMethodTable service_methods[] = {
714	{ "AddRecord",		"s",	"u",	add_service_record	},
715	{ "UpdateRecord",	"us",	"",	update_service_record	},
716	{ "RemoveRecord",	"u",	"",	remove_service_record	},
717	{ "RequestAuthorization","su",	"",	request_authorization,
718						G_DBUS_METHOD_FLAG_ASYNC},
719	{ "CancelAuthorization", "",	"",	cancel_authorization	},
720	{ }
721};
722
723static void path_unregister(void *data)
724{
725	struct service_adapter *serv_adapter = data;
726	GSList *l, *next = NULL;
727
728	for (l = serv_adapter->records; l != NULL; l = next) {
729		struct record_data *user_record = l->data;
730
731		next = l->next;
732
733		g_dbus_remove_watch(connection, user_record->listener_id);
734		exit_callback(connection, user_record);
735	}
736
737	g_free(serv_adapter);
738}
739
740static int register_interface(const char *path, struct btd_adapter *adapter)
741{
742	struct service_adapter *serv_adapter;
743
744	DBG("path %s", path);
745
746	serv_adapter = g_try_new0(struct service_adapter, 1);
747	if (serv_adapter == NULL)
748		return -ENOMEM;
749
750	serv_adapter->adapter = adapter;
751	serv_adapter->pending_list = NULL;
752
753	if (g_dbus_register_interface(connection, path, SERVICE_INTERFACE,
754				service_methods, NULL, NULL, serv_adapter,
755						path_unregister) == FALSE) {
756		error("D-Bus failed to register %s interface",
757							SERVICE_INTERFACE);
758		g_free(serv_adapter);
759		return -EIO;
760	}
761
762	DBG("Registered interface %s on path %s", SERVICE_INTERFACE, path);
763
764	if (serv_adapter->adapter == NULL)
765		serv_adapter_any = serv_adapter;
766
767	return 0;
768}
769
770static void unregister_interface(const char *path)
771{
772	DBG("path %s", path);
773
774	g_dbus_unregister_interface(connection, path, SERVICE_INTERFACE);
775}
776
777static int service_probe(struct btd_adapter *adapter)
778{
779	register_interface(adapter_get_path(adapter), adapter);
780
781	return 0;
782}
783
784static void service_remove(struct btd_adapter *adapter)
785{
786	unregister_interface(adapter_get_path(adapter));
787}
788
789static struct btd_adapter_driver service_driver = {
790	.name	= "service",
791	.probe	= service_probe,
792	.remove	= service_remove,
793};
794
795static const char *any_path;
796
797static int service_init(void)
798{
799	int err;
800
801	connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
802	if (connection == NULL)
803		return -EIO;
804
805	any_path = btd_adapter_any_request_path();
806	if (any_path != NULL) {
807		if (register_interface(any_path, NULL) < 0) {
808			btd_adapter_any_release_path();
809			any_path = NULL;
810		}
811	}
812
813	err = btd_register_adapter_driver(&service_driver);
814	if (err < 0) {
815		dbus_connection_unref(connection);
816		return err;
817	}
818
819	return 0;
820}
821
822static void service_exit(void)
823{
824	btd_unregister_adapter_driver(&service_driver);
825
826	if (any_path != NULL) {
827		unregister_interface(any_path);
828
829		btd_adapter_any_release_path();
830		any_path = NULL;
831	}
832
833	dbus_connection_unref(connection);
834}
835
836BLUETOOTH_PLUGIN_DEFINE(service, VERSION,
837		BLUETOOTH_PLUGIN_PRIORITY_HIGH, service_init, service_exit)
838