summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/dbus.c385
-rw-r--r--common/dbus.h11
-rw-r--r--cups/Makefile.am4
-rw-r--r--cups/main.c5
-rw-r--r--daemon/Makefile.am16
-rw-r--r--daemon/echo.c448
-rw-r--r--daemon/echo.service4
-rw-r--r--daemon/main.c5
-rw-r--r--gdbus/gdbus.h21
-rw-r--r--gdbus/mainloop.c280
-rw-r--r--hcid/dbus-common.c5
11 files changed, 316 insertions, 868 deletions
diff --git a/common/dbus.c b/common/dbus.c
index beb97a07..4ea56c9f 100644
--- a/common/dbus.c
+++ b/common/dbus.c
@@ -48,35 +48,9 @@
#include "dbus.h"
#include "logging.h"
-#define DISPATCH_TIMEOUT 0
-
static guint listener_id = 0;
static GSList *name_listeners = NULL;
-#ifndef HAVE_DBUS_GLIB
-typedef struct {
- uint32_t id;
- DBusTimeout *timeout;
-} timeout_handler_t;
-
-struct watch_info {
- guint watch_id;
- GIOChannel *io;
- DBusConnection *conn;
-};
-
-struct server_info {
- guint watch_id;
- GIOChannel *io;
- DBusServer *server;
-};
-#endif
-
-struct disconnect_data {
- void (*disconnect_cb)(void *);
- void *user_data;
-};
-
struct name_callback {
name_cb_t func;
void *user_data;
@@ -415,362 +389,3 @@ int name_listener_indicate_disconnect(DBusConnection *connection)
return 0;
}
-
-static DBusHandlerResult disconnect_filter(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- struct disconnect_data *dc_data = data;
-
- if (dbus_message_is_signal(msg,
- DBUS_INTERFACE_LOCAL, "Disconnected") == TRUE) {
- error("Got disconnected from the system message bus");
- dbus_connection_unref(conn);
- dc_data->disconnect_cb(dc_data->user_data);
- }
-
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-#ifndef HAVE_DBUS_GLIB
-static dbus_int32_t server_slot = -1;
-
-static gboolean server_func(GIOChannel *chan, GIOCondition cond, gpointer data)
-{
- DBusWatch *watch = data;
- int flags = 0;
-
- if (cond & G_IO_IN) flags |= DBUS_WATCH_READABLE;
- if (cond & G_IO_OUT) flags |= DBUS_WATCH_WRITABLE;
- if (cond & G_IO_HUP) flags |= DBUS_WATCH_HANGUP;
- if (cond & G_IO_ERR) flags |= DBUS_WATCH_ERROR;
-
- dbus_watch_handle(watch, flags);
-
- return TRUE;
-}
-
-static dbus_bool_t add_server(DBusWatch *watch, void *data)
-{
- GIOCondition cond = G_IO_HUP | G_IO_ERR;
- DBusServer *server = data;
- struct server_info *info;
- int fd, flags;
-
- if (!dbus_watch_get_enabled(watch))
- return TRUE;
-
- info = g_new(struct server_info, 1);
-
- fd = dbus_watch_get_unix_fd(watch);
- info->io = g_io_channel_unix_new(fd);
- info->server = dbus_server_ref(server);
-
- dbus_watch_set_data(watch, info, NULL);
-
- flags = dbus_watch_get_flags(watch);
-
- if (flags & DBUS_WATCH_READABLE) cond |= G_IO_IN;
- if (flags & DBUS_WATCH_WRITABLE) cond |= G_IO_OUT;
-
- info->watch_id = g_io_add_watch(info->io, cond, server_func, watch);
-
- return TRUE;
-}
-
-static void remove_server(DBusWatch *watch, void *data)
-{
- struct server_info *info = dbus_watch_get_data(watch);
-
- dbus_watch_set_data(watch, NULL, NULL);
-
- if (info) {
- g_source_remove(info->watch_id);
- g_io_channel_unref(info->io);
- dbus_server_unref(info->server);
- g_free(info);
- }
-}
-
-static void server_toggled(DBusWatch *watch, void *data)
-{
- /* Because we just exit on OOM, enable/disable is
- * no different from add/remove */
- if (dbus_watch_get_enabled(watch))
- add_server(watch, data);
- else
- remove_server(watch, data);
-}
-
-static gboolean message_dispatch_cb(void *data)
-{
- DBusConnection *connection = data;
-
- dbus_connection_ref(connection);
-
- /* Dispatch messages */
- while (dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS);
-
- dbus_connection_unref(connection);
-
- return FALSE;
-}
-
-static gboolean watch_func(GIOChannel *chan, GIOCondition cond, gpointer data)
-{
- DBusWatch *watch = data;
- struct watch_info *info = dbus_watch_get_data(watch);
- int flags = 0;
-
- if (cond & G_IO_IN) flags |= DBUS_WATCH_READABLE;
- if (cond & G_IO_OUT) flags |= DBUS_WATCH_WRITABLE;
- if (cond & G_IO_HUP) flags |= DBUS_WATCH_HANGUP;
- if (cond & G_IO_ERR) flags |= DBUS_WATCH_ERROR;
-
- dbus_watch_handle(watch, flags);
-
- if (dbus_connection_get_dispatch_status(info->conn) == DBUS_DISPATCH_DATA_REMAINS)
- g_timeout_add(DISPATCH_TIMEOUT, message_dispatch_cb, info->conn);
-
- return TRUE;
-}
-
-static dbus_bool_t add_watch(DBusWatch *watch, void *data)
-{
- GIOCondition cond = G_IO_HUP | G_IO_ERR;
- DBusConnection *conn = data;
- struct watch_info *info;
- int fd, flags;
-
- if (!dbus_watch_get_enabled(watch))
- return TRUE;
-
- info = g_new(struct watch_info, 1);
-
- fd = dbus_watch_get_unix_fd(watch);
- info->io = g_io_channel_unix_new(fd);
- info->conn = dbus_connection_ref(conn);
-
- dbus_watch_set_data(watch, info, NULL);
-
- flags = dbus_watch_get_flags(watch);
-
- if (flags & DBUS_WATCH_READABLE) cond |= G_IO_IN;
- if (flags & DBUS_WATCH_WRITABLE) cond |= G_IO_OUT;
-
- info->watch_id = g_io_add_watch(info->io, cond, watch_func, watch);
-
- return TRUE;
-}
-
-static void remove_watch(DBusWatch *watch, void *data)
-{
- struct watch_info *info = dbus_watch_get_data(watch);
-
- dbus_watch_set_data(watch, NULL, NULL);
-
- if (info) {
- g_source_remove(info->watch_id);
- g_io_channel_unref(info->io);
- dbus_connection_unref(info->conn);
- g_free(info);
- }
-}
-
-static void watch_toggled(DBusWatch *watch, void *data)
-{
- /* Because we just exit on OOM, enable/disable is
- * no different from add/remove */
- if (dbus_watch_get_enabled(watch))
- add_watch(watch, data);
- else
- remove_watch(watch, data);
-}
-
-static gboolean timeout_handler_dispatch(gpointer data)
-{
- timeout_handler_t *handler = data;
-
- /* if not enabled should not be polled by the main loop */
- if (dbus_timeout_get_enabled(handler->timeout) != TRUE)
- return FALSE;
-
- dbus_timeout_handle(handler->timeout);
-
- return FALSE;
-}
-
-static void timeout_handler_free(void *data)
-{
- timeout_handler_t *handler = data;
- if (!handler)
- return;
-
- g_source_remove(handler->id);
- g_free(handler);
-}
-
-static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data)
-{
- timeout_handler_t *handler;
-
- if (!dbus_timeout_get_enabled(timeout))
- return TRUE;
-
- handler = g_new0(timeout_handler_t, 1);
-
- handler->timeout = timeout;
- handler->id = g_timeout_add(dbus_timeout_get_interval(timeout),
- timeout_handler_dispatch, handler);
-
- dbus_timeout_set_data(timeout, handler, timeout_handler_free);
-
- return TRUE;
-}
-
-static void remove_timeout(DBusTimeout *timeout, void *data)
-{
-}
-
-static void timeout_toggled(DBusTimeout *timeout, void *data)
-{
- if (dbus_timeout_get_enabled(timeout))
- add_timeout(timeout, data);
- else
- remove_timeout(timeout, data);
-}
-
-static void dispatch_status_cb(DBusConnection *conn,
- DBusDispatchStatus new_status, void *data)
-{
- if (!dbus_connection_get_is_connected(conn))
- return;
-
- if (new_status == DBUS_DISPATCH_DATA_REMAINS)
- g_timeout_add(DISPATCH_TIMEOUT, message_dispatch_cb, data);
-}
-#endif
-
-void setup_dbus_server_with_main_loop(DBusServer *server)
-{
-#ifdef HAVE_DBUS_GLIB
- debug("Using D-Bus GLib server setup");
-
- dbus_server_setup_with_g_main(server, NULL);
-#else
- dbus_server_allocate_data_slot(&server_slot);
- if (server_slot < 0)
- return;
-
- dbus_server_set_data(server, server_slot, server, NULL);
-
- dbus_server_set_watch_functions(server, add_server, remove_server,
- server_toggled, server, NULL);
-
- dbus_server_set_timeout_functions(server, add_timeout, remove_timeout,
- timeout_toggled, server, NULL);
-#endif
-}
-
-void setup_dbus_with_main_loop(DBusConnection *conn)
-{
-#ifdef HAVE_DBUS_GLIB
- debug("Using D-Bus GLib connection setup");
-
- dbus_connection_setup_with_g_main(conn, NULL);
-#else
- dbus_connection_set_watch_functions(conn, add_watch, remove_watch,
- watch_toggled, conn, NULL);
-
- dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout,
- timeout_toggled, conn, NULL);
-
- dbus_connection_set_dispatch_status_function(conn, dispatch_status_cb,
- conn, NULL);
-#endif
-}
-
-DBusConnection *init_dbus(const char *name,
- void (*disconnect_cb)(void *), void *user_data)
-{
- struct disconnect_data *dc_data;
- DBusConnection *conn;
- DBusError err;
-
- dbus_error_init(&err);
-
- conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
-
- if (dbus_error_is_set(&err)) {
- error("Can't connect to system message bus: %s", err.message);
- dbus_error_free(&err);
- return NULL;
- }
-
- setup_dbus_with_main_loop(conn);
-
- if (name) {
- dbus_error_init(&err);
-
- if (dbus_bus_request_name(conn, name, 0, &err) !=
- DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER ) {
- error("Could not become the primary owner of %s", name);
- dbus_connection_unref(conn);
- return NULL;
- }
-
- if (dbus_error_is_set(&err)) {
- error("Can't get bus name %s: %s", name, err.message);
- dbus_error_free(&err);
- dbus_connection_unref(conn);
- return NULL;
- }
- }
-
- if (!disconnect_cb)
- return conn;
-
- dc_data = g_new(struct disconnect_data, 1);
-
- dc_data->disconnect_cb = disconnect_cb;
- dc_data->user_data = user_data;
-
- dbus_connection_set_exit_on_disconnect(conn, FALSE);
-
- if (!dbus_connection_add_filter(conn, disconnect_filter,
- dc_data, g_free)) {
- error("Can't add D-Bus disconnect filter");
- g_free(dc_data);
- dbus_connection_unref(conn);
- return NULL;
- }
-
- return conn;
-}
-
-DBusConnection *init_dbus_direct(const char *address)
-{
- DBusConnection *conn;
- DBusError err;
-
- dbus_error_init(&err);
-
- conn = dbus_connection_open(address, &err);
-
- if (dbus_error_is_set(&err)) {
- error("Can't connect to message server: %s", err.message);
- dbus_error_free(&err);
- return NULL;
- }
-
- setup_dbus_with_main_loop(conn);
-
- dbus_connection_set_exit_on_disconnect(conn, FALSE);
-
- return conn;
-}
-
-DBusConnection *dbus_bus_system_setup_with_main_loop(const char *name,
- void (*disconnect_cb)(void *), void *user_data)
-{
- return init_dbus(name, disconnect_cb, user_data);
-}
diff --git a/common/dbus.h b/common/dbus.h
index 94244eb6..5976a479 100644
--- a/common/dbus.h
+++ b/common/dbus.h
@@ -27,17 +27,6 @@
#include <dbus/dbus.h>
#include <glib.h>
-void setup_dbus_server_with_main_loop(DBusServer *server);
-void setup_dbus_with_main_loop(DBusConnection *conn);
-
-DBusConnection *init_dbus(const char *name,
- void (*disconnect_cb)(void *), void *user_data);
-
-DBusConnection *init_dbus_direct(const char *address);
-
-DBusConnection *dbus_bus_system_setup_with_main_loop(const char *name,
- void (*disconnect_cb)(void *), void *user_data);
-
typedef void (*name_cb_t)(const char *name, void *user_data);
guint name_listener_add(DBusConnection *connection, const char *name,
diff --git a/cups/Makefile.am b/cups/Makefile.am
index 853c436d..f01665ee 100644
--- a/cups/Makefile.am
+++ b/cups/Makefile.am
@@ -7,10 +7,10 @@ cups_PROGRAMS = bluetooth
bluetooth_SOURCES = main.c cups.h sdp.c spp.c hcrp.c
bluetooth_LDADD = $(top_builddir)/common/libhelper.a \
- @DBUS_LIBS@ @GLIB_LIBS@ @BLUEZ_LIBS@
+ @GDBUS_LIBS@ @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@
endif
-AM_CFLAGS = @BLUEZ_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@
+AM_CFLAGS = @BLUEZ_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@ @GDBUS_CFLAGS@
INCLUDES = -I$(top_srcdir)/common
diff --git a/cups/main.c b/cups/main.c
index ac77e85d..b36b2074 100644
--- a/cups/main.c
+++ b/cups/main.c
@@ -38,10 +38,9 @@
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
-#include <glib.h>
+#include <gdbus.h>
#include "cups.h"
-#include "dbus.h"
#include "sdp-xml.h"
extern int sdp_search_spp(sdp_session_t *sdp, uint8_t *channel);
@@ -456,7 +455,7 @@ static gboolean list_printers(void)
char *adapter, *match;
guint len;
- conn = init_dbus(NULL, NULL, NULL);
+ conn = dbus_bus_system_setup_with_main_loop("org.bluez", NULL, NULL);
if (conn == NULL)
return FALSE;
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 8b2bba31..e2a16be2 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -1,12 +1,5 @@
-noinst_PROGRAMS = bluetoothd passkey-agent auth-agent \
- bluetoothd-service-echo
-
-bluetoothd_service_echo_SOURCES = echo.c
-
-bluetoothd_service_echo_LDADD = \
- $(top_builddir)/common/libhelper.a \
- @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@
+noinst_PROGRAMS = bluetoothd passkey-agent auth-agent
if CONFIGFILES
dbusdir = $(sysconfdir)/dbus-1/system.d
@@ -21,7 +14,7 @@ bluetoothd_SOURCES = main.c system.h \
bluetoothd_LDADD = \
$(top_builddir)/common/libhelper.a \
$(top_builddir)/sdpd/libsdpserver.a \
- @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@
+ @GDBUS_LIBS@ @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@
passkey_agent_SOURCES = passkey-agent.c
@@ -31,11 +24,10 @@ auth_agent_SOURCES = auth-agent.c
auth_agent_LDADD = @DBUS_LIBS@
-AM_CFLAGS = @BLUEZ_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@
+AM_CFLAGS = @BLUEZ_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@ @GDBUS_CFLAGS@
INCLUDES = -I$(top_srcdir)/common -I$(top_srcdir)/sdpd
-EXTRA_DIST = bluetooth.conf echo.service \
- test-manager test-database
+EXTRA_DIST = bluetooth.conf test-manager test-database
MAINTAINERCLEANFILES = Makefile.in
diff --git a/daemon/echo.c b/daemon/echo.c
deleted file mode 100644
index 09ceef31..00000000
--- a/daemon/echo.c
+++ /dev/null
@@ -1,448 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2004-2008 Marcel Holtmann <marcel@holtmann.org>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/socket.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/rfcomm.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
-
-#include <glib.h>
-
-#include <dbus/dbus.h>
-
-#include "dbus.h"
-#include "logging.h"
-
-struct auth_data {
- DBusConnection *conn;
- GIOChannel *io;
- char *address;
-};
-
-static gboolean session_event(GIOChannel *chan,
- GIOCondition cond, gpointer data)
-{
- unsigned char buf[672];
- gsize len, written;
- GIOError err;
-
- if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL))
- return FALSE;
-
- err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len);
- if (err == G_IO_ERROR_AGAIN)
- return TRUE;
-
- g_io_channel_write(chan, (const gchar *) buf, len, &written);
-
- return TRUE;
-}
-
-static void cancel_authorization(DBusConnection *conn, const char *address)
-{
- DBusMessage *msg;
- const char *string = "";
-
- info("Canceling authorization for %s", address);
-
- msg = dbus_message_new_method_call("org.bluez", "/org/bluez",
- "org.bluez.Database", "CancelAuthorizationRequest");
- if (!msg) {
- error("Allocation of method message failed");
- return;
- }
-
- dbus_message_append_args(msg, DBUS_TYPE_STRING, &address,
- DBUS_TYPE_STRING, &string, DBUS_TYPE_INVALID);
-
- dbus_connection_send(conn, msg, NULL);
-
- dbus_message_unref(msg);
-}
-
-static void authorization_callback(DBusPendingCall *call, void *data)
-{
- DBusMessage *reply = dbus_pending_call_steal_reply(call);
- struct auth_data *auth = data;
- DBusError err;
-
- dbus_error_init(&err);
-
- if (dbus_set_error_from_message(&err, reply)) {
- error("Access denied: %s", err.message);
- if (dbus_error_has_name(&err, DBUS_ERROR_NO_REPLY))
- cancel_authorization(auth->conn, auth->address);
- dbus_error_free(&err);
- } else {
- info("Accepting incoming connection");
- g_io_add_watch(auth->io,
- G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- session_event, NULL);
- }
-
- g_io_channel_unref(auth->io);
-
- dbus_message_unref(reply);
-}
-
-static void authorization_free(void *data)
-{
- struct auth_data *auth = data;
-
- g_free(auth->address);
- g_free(auth);
-}
-
-static int request_authorization(DBusConnection *conn,
- GIOChannel *io, const char *address)
-{
- DBusMessage *msg;
- DBusPendingCall *pending;
- struct auth_data *auth;
- const char *string = "";
-
- info("Requesting authorization for %s", address);
-
- auth = g_try_malloc0(sizeof(*auth));
- if (!auth) {
- error("Allocation of auth object failed");
- return -1;
- }
-
- msg = dbus_message_new_method_call("org.bluez", "/org/bluez",
- "org.bluez.Database", "RequestAuthorization");
- if (!msg) {
- error("Allocation of method message failed");
- g_free(auth);
- return -1;
- }
-
- dbus_message_append_args(msg, DBUS_TYPE_STRING, &address,
- DBUS_TYPE_STRING, &string, DBUS_TYPE_INVALID);
-
- if (dbus_connection_send_with_reply(conn, msg, &pending, -1) == FALSE) {
- error("Sending of authorization request failed");
- dbus_message_unref(msg);
- g_free(auth);
- return -1;
- }
-
- auth->conn = conn;
- auth->io = io;
- auth->address = g_strdup(address);
-
- dbus_pending_call_set_notify(pending, authorization_callback,
- auth, authorization_free);
-
- dbus_pending_call_unref(pending);
-
- dbus_message_unref(msg);
-
- return 0;
-}
-
-static gboolean connect_event(GIOChannel *chan,
- GIOCondition cond, gpointer data)
-{
- DBusConnection *conn = data;
- GIOChannel *io;
- struct sockaddr_rc addr;
- socklen_t optlen;
- char address[18];
- int sk, nsk;
-
- sk = g_io_channel_unix_get_fd(chan);
-
- memset(&addr, 0, sizeof(addr));
- optlen = sizeof(addr);
-
- nsk = accept(sk, (struct sockaddr *) &addr, &optlen);
- if (nsk < 0)
- return TRUE;
-
- io = g_io_channel_unix_new(nsk);
- g_io_channel_set_close_on_unref(io, TRUE);
-
- ba2str(&addr.rc_bdaddr, address);
-
- if (request_authorization(conn, io, address) < 0) {
- close(nsk);
- return TRUE;
- }
-
- return TRUE;
-}
-
-static GIOChannel *setup_rfcomm(DBusConnection *conn, uint8_t channel)
-{
- GIOChannel *io;
- struct sockaddr_rc addr;
- int sk;
-
- sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
- if (sk < 0)
- return NULL;
-
- memset(&addr, 0, sizeof(addr));
- addr.rc_family = AF_BLUETOOTH;
- bacpy(&addr.rc_bdaddr, BDADDR_ANY);
- addr.rc_channel = channel;
-
- if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- close(sk);
- return NULL;
- }
-
- if (listen(sk, 10) < 0) {
- close(sk);
- return NULL;
- }
-
- io = g_io_channel_unix_new(sk);
- g_io_channel_set_close_on_unref(io, TRUE);
-
- g_io_add_watch(io, G_IO_IN, connect_event, conn);
-
- return io;
-}
-
-static int setup_sdp(DBusConnection *conn, uint8_t channel)
-{
- DBusMessage *msg, *reply;
- DBusError err;
- sdp_record_t *record;
- sdp_buf_t buf;
- sdp_list_t *svclass, *pfseq, *apseq, *root, *aproto;
- uuid_t root_uuid, l2cap, rfcomm, spp;
- sdp_profile_desc_t profile[1];
- sdp_list_t *proto[2];
- sdp_data_t *chan;
-
- record = sdp_record_alloc();
- if (!record) {
- error("Allocation of service record failed");
- return -1;
- }
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(record, root);
-
- sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(NULL, &l2cap);
- apseq = sdp_list_append(NULL, proto[0]);
-
- chan = sdp_data_alloc(SDP_UINT8, &channel);
- sdp_uuid16_create(&rfcomm, RFCOMM_UUID);
- proto[1] = sdp_list_append(NULL, &rfcomm);
- proto[1] = sdp_list_append(proto[1], chan);
- apseq = sdp_list_append(apseq, proto[1]);
-
- aproto = sdp_list_append(NULL, apseq);
- sdp_set_access_protos(record, aproto);
-
- sdp_uuid16_create(&spp, SERIAL_PORT_SVCLASS_ID);
- svclass = sdp_list_append(NULL, &spp);
- sdp_set_service_classes(record, svclass);
-
- sdp_uuid16_create(&profile[0].uuid, SERIAL_PORT_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(NULL, &profile[0]);
- sdp_set_profile_descs(record, pfseq);
-
- sdp_set_info_attr(record, "Echo service", NULL, NULL);
-
- if (sdp_gen_record_pdu(record, &buf) < 0) {
- error("Generation of service record failed");
- sdp_record_free(record);
- return -1;
- }
-
- sdp_data_free(chan);
- sdp_list_free(root, NULL);
- sdp_list_free(apseq, NULL);
- sdp_list_free(pfseq, NULL);
- sdp_list_free(aproto, NULL);
- sdp_list_free(svclass, NULL);
- sdp_list_free(proto[0], NULL);
- sdp_list_free(proto[1], NULL);
-
- sdp_record_free(record);
-
- msg = dbus_message_new_method_call("org.bluez", "/org/bluez",
- "org.bluez.Database", "AddServiceRecord");
- if (!msg) {
- error("Allocation of method message failed");
- return -1;
- }
-
- dbus_message_append_args(msg, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
- &buf.data, buf.data_size, DBUS_TYPE_INVALID);
-
- dbus_error_init(&err);
-
- reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err);
-
- dbus_message_unref(msg);
-
- free(buf.data);
-
- if (!reply) {
- error("Registration of service record failed");
- error("%s", err.message);
- dbus_error_free(&err);
- return -1;
- }
-
- dbus_message_unref(reply);
-
- dbus_connection_flush(conn);
-
- return 0;
-}
-
-static int register_standalone(DBusConnection *conn)
-{
- DBusMessage *msg, *reply;
- DBusError err;
- const char *ident = "echo", *name = "Echo service", *desc = "";
-
- info("Registering service");
-
- msg = dbus_message_new_method_call("org.bluez", "/org/bluez",
- "org.bluez.Database", "RegisterService");
- if (!msg) {
- error("Allocation of method message failed");
- return -1;
- }
-
- dbus_message_append_args(msg, DBUS_TYPE_STRING, &ident,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_STRING, &desc, DBUS_TYPE_INVALID);
-
- dbus_error_init(&err);
-
- reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err);
-
- dbus_message_unref(msg);
-
- if (!reply) {
- error("Registration of service failed");
- error("%s", err.message);
- dbus_error_free(&err);
- return -1;
- }
-
- dbus_message_unref(reply);
-
- dbus_connection_flush(conn);
-
- return 0;
-}
-
-static GMainLoop *main_loop = NULL;
-
-static void sig_term(int sig)
-{
- g_main_loop_quit(main_loop);
-}
-
-int main(int argc, char *argv[])
-{
- DBusConnection *conn;
- GIOChannel *io;
- struct sigaction sa;
- char *addr;
-
- start_logging("echo", "Bluetooth echo service ver %s", VERSION);
-
- memset(&sa, 0, sizeof(sa));
- sa.sa_flags = SA_NOCLDSTOP;
- sa.sa_handler = sig_term;
- sigaction(SIGTERM, &sa, NULL);
- sigaction(SIGINT, &sa, NULL);
-
- sa.sa_handler = SIG_IGN;
- sigaction(SIGCHLD, &sa, NULL);
- sigaction(SIGPIPE, &sa, NULL);
-
- enable_debug();
-
- addr = getenv("BLUETOOTHD_ADDRESS");
- if (!addr) {
- error("No D-Bus server address available");
- exit(1);
- }
-
- debug("Bluetooth daemon at %s", addr);
-
- main_loop = g_main_loop_new(NULL, FALSE);
-
- if (argc > 1 && !strcmp(argv[1], "-s"))
- conn = init_dbus_direct(addr);
- else
- conn = init_dbus(NULL, NULL, NULL);
-
- if (!conn) {
- error("Connection to bus failed");
- g_main_loop_unref(main_loop);
- exit(1);
- }
-
- io = setup_rfcomm(conn, 23);
- if (!io) {
- error("Creation of server channel failed");
- dbus_connection_unref(conn);
- g_main_loop_unref(main_loop);
- exit(1);
- }
-
- setup_sdp(conn, 23);
-
- if (argc > 1 && !strcmp(argv[1], "-s"))
- register_standalone(conn);
-
- g_main_loop_run(main_loop);
-
- g_io_channel_unref(io);
-
- dbus_connection_unref(conn);
-
- g_main_loop_unref(main_loop);
-
- info("Exit");
-
- stop_logging();
-
- return 0;
-}
diff --git a/daemon/echo.service b/daemon/echo.service
deleted file mode 100644
index bd13d649..00000000
--- a/daemon/echo.service
+++ /dev/null
@@ -1,4 +0,0 @@
-[Bluetooth Service]
-Identifier=echo
-Name=Echo service
-Description=Bluetooth RFCOMM based Echo service
diff --git a/daemon/main.c b/daemon/main.c
index 94eba19a..be731b14 100644
--- a/daemon/main.c
+++ b/daemon/main.c
@@ -37,6 +37,8 @@
#include <dbus/dbus.h>
+#include <gdbus.h>
+
#include "dbus-helper.h"
#include "dbus.h"
@@ -56,7 +58,8 @@ static DBusConnection *system_bus = NULL;
static int setup_dbus(void)
{
- system_bus = init_dbus("org.bluez", NULL, NULL);
+ system_bus = dbus_bus_system_setup_with_main_loop("org.bluez",
+ NULL, NULL);
if (!system_bus)
return -1;
diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h
index 71377516..d749d5e2 100644
--- a/gdbus/gdbus.h
+++ b/gdbus/gdbus.h
@@ -20,3 +20,24 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
+
+#ifndef __GDBUS_H
+#define __GDBUS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <dbus/dbus.h>
+#include <glib.h>
+
+void setup_dbus_with_main_loop(DBusConnection *conn);
+
+DBusConnection *dbus_bus_system_setup_with_main_loop(const char *name,
+ void (*disconnect_cb)(void *), void *user_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GDBUS_H */
diff --git a/gdbus/mainloop.c b/gdbus/mainloop.c
index f08299f0..e8e7e0af 100644
--- a/gdbus/mainloop.c
+++ b/gdbus/mainloop.c
@@ -25,8 +25,9 @@
#include <config.h>
#endif
-#include <glib.h>
+#include <stdint.h>
+#include <glib.h>
#include <dbus/dbus.h>
#ifdef NEED_DBUS_WATCH_GET_UNIX_FD
@@ -38,3 +39,280 @@
#endif
#include "gdbus.h"
+
+#define DISPATCH_TIMEOUT 0
+
+#define info(fmt...)
+#define error(fmt...)
+#define debug(fmt...)
+
+#ifndef HAVE_DBUS_GLIB
+typedef struct {
+ uint32_t id;
+ DBusTimeout *timeout;
+} timeout_handler_t;
+
+struct watch_info {
+ guint watch_id;
+ GIOChannel *io;
+ DBusConnection *conn;
+};
+
+struct server_info {
+ guint watch_id;
+ GIOChannel *io;
+ DBusServer *server;
+};
+#endif
+
+struct disconnect_data {
+ void (*disconnect_cb)(void *);
+ void *user_data;
+};
+
+static DBusHandlerResult disconnect_filter(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ struct disconnect_data *dc_data = data;
+
+ if (dbus_message_is_signal(msg,
+ DBUS_INTERFACE_LOCAL, "Disconnected") == TRUE) {
+ error("Got disconnected from the system message bus");
+ dbus_connection_unref(conn);
+ dc_data->disconnect_cb(dc_data->user_data);
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+#ifndef HAVE_DBUS_GLIB
+static gboolean message_dispatch_cb(void *data)
+{
+ DBusConnection *connection = data;
+
+ dbus_connection_ref(connection);
+
+ /* Dispatch messages */
+ while (dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS);
+
+ dbus_connection_unref(connection);
+
+ return FALSE;
+}
+
+static gboolean watch_func(GIOChannel *chan, GIOCondition cond, gpointer data)
+{
+ DBusWatch *watch = data;
+ struct watch_info *info = dbus_watch_get_data(watch);
+ int flags = 0;
+
+ if (cond & G_IO_IN) flags |= DBUS_WATCH_READABLE;
+ if (cond & G_IO_OUT) flags |= DBUS_WATCH_WRITABLE;
+ if (cond & G_IO_HUP) flags |= DBUS_WATCH_HANGUP;
+ if (cond & G_IO_ERR) flags |= DBUS_WATCH_ERROR;
+
+ dbus_watch_handle(watch, flags);
+
+ if (dbus_connection_get_dispatch_status(info->conn) == DBUS_DISPATCH_DATA_REMAINS)
+ g_timeout_add(DISPATCH_TIMEOUT, message_dispatch_cb, info->conn);
+
+ return TRUE;
+}
+
+static dbus_bool_t add_watch(DBusWatch *watch, void *data)
+{
+ GIOCondition cond = G_IO_HUP | G_IO_ERR;
+ DBusConnection *conn = data;
+ struct watch_info *info;
+ int fd, flags;
+
+ if (!dbus_watch_get_enabled(watch))
+ return TRUE;
+
+ info = g_new(struct watch_info, 1);
+
+ fd = dbus_watch_get_unix_fd(watch);
+ info->io = g_io_channel_unix_new(fd);
+ info->conn = dbus_connection_ref(conn);
+
+ dbus_watch_set_data(watch, info, NULL);
+
+ flags = dbus_watch_get_flags(watch);
+
+ if (flags & DBUS_WATCH_READABLE) cond |= G_IO_IN;
+ if (flags & DBUS_WATCH_WRITABLE) cond |= G_IO_OUT;
+
+ info->watch_id = g_io_add_watch(info->io, cond, watch_func, watch);
+
+ return TRUE;
+}
+
+static void remove_watch(DBusWatch *watch, void *data)
+{
+ struct watch_info *info = dbus_watch_get_data(watch);
+
+ dbus_watch_set_data(watch, NULL, NULL);
+
+ if (info) {
+ g_source_remove(info->watch_id);
+ g_io_channel_unref(info->io);
+ dbus_connection_unref(info->conn);
+ g_free(info);
+ }
+}
+
+static void watch_toggled(DBusWatch *watch, void *data)
+{
+ /* Because we just exit on OOM, enable/disable is
+ * no different from add/remove */
+ if (dbus_watch_get_enabled(watch))
+ add_watch(watch, data);
+ else
+ remove_watch(watch, data);
+}
+
+static gboolean timeout_handler_dispatch(gpointer data)
+{
+ timeout_handler_t *handler = data;
+
+ /* if not enabled should not be polled by the main loop */
+ if (dbus_timeout_get_enabled(handler->timeout) != TRUE)
+ return FALSE;
+
+ dbus_timeout_handle(handler->timeout);
+
+ return FALSE;
+}
+
+static void timeout_handler_free(void *data)
+{
+ timeout_handler_t *handler = data;
+ if (!handler)
+ return;
+
+ g_source_remove(handler->id);
+ g_free(handler);
+}
+
+static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data)
+{
+ timeout_handler_t *handler;
+
+ if (!dbus_timeout_get_enabled(timeout))
+ return TRUE;
+
+ handler = g_new0(timeout_handler_t, 1);
+
+ handler->timeout = timeout;
+ handler->id = g_timeout_add(dbus_timeout_get_interval(timeout),
+ timeout_handler_dispatch, handler);
+
+ dbus_timeout_set_data(timeout, handler, timeout_handler_free);
+
+ return TRUE;
+}
+
+static void remove_timeout(DBusTimeout *timeout, void *data)
+{
+}
+
+static void timeout_toggled(DBusTimeout *timeout, void *data)
+{
+ if (dbus_timeout_get_enabled(timeout))
+ add_timeout(timeout, data);
+ else
+ remove_timeout(timeout, data);
+}
+
+static void dispatch_status_cb(DBusConnection *conn,
+ DBusDispatchStatus new_status, void *data)
+{
+ if (!dbus_connection_get_is_connected(conn))
+ return;
+
+ if (new_status == DBUS_DISPATCH_DATA_REMAINS)
+ g_timeout_add(DISPATCH_TIMEOUT, message_dispatch_cb, data);
+}
+#endif
+
+void setup_dbus_with_main_loop(DBusConnection *conn)
+{
+#ifdef HAVE_DBUS_GLIB
+ debug("Using D-Bus GLib connection setup");
+
+ dbus_connection_setup_with_g_main(conn, NULL);
+#else
+ dbus_connection_set_watch_functions(conn, add_watch, remove_watch,
+ watch_toggled, conn, NULL);
+
+ dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout,
+ timeout_toggled, conn, NULL);
+
+ dbus_connection_set_dispatch_status_function(conn, dispatch_status_cb,
+ conn, NULL);
+#endif
+}
+
+static DBusConnection *init_dbus(const char *name,
+ void (*disconnect_cb)(void *), void *user_data)
+{
+ struct disconnect_data *dc_data;
+ DBusConnection *conn;
+ DBusError err;
+
+ dbus_error_init(&err);
+
+ conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
+
+ if (dbus_error_is_set(&err)) {
+ error("Can't connect to system message bus: %s", err.message);
+ dbus_error_free(&err);
+ return NULL;
+ }
+
+ setup_dbus_with_main_loop(conn);
+
+ if (name) {
+ dbus_error_init(&err);
+
+ if (dbus_bus_request_name(conn, name, 0, &err) !=
+ DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER ) {
+ error("Could not become the primary owner of %s", name);
+ dbus_connection_unref(conn);
+ return NULL;
+ }
+
+ if (dbus_error_is_set(&err)) {
+ error("Can't get bus name %s: %s", name, err.message);
+ dbus_error_free(&err);
+ dbus_connection_unref(conn);
+ return NULL;
+ }
+ }
+
+ if (!disconnect_cb)
+ return conn;
+
+ dc_data = g_new(struct disconnect_data, 1);
+
+ dc_data->disconnect_cb = disconnect_cb;
+ dc_data->user_data = user_data;
+
+ dbus_connection_set_exit_on_disconnect(conn, FALSE);
+
+ if (!dbus_connection_add_filter(conn, disconnect_filter,
+ dc_data, g_free)) {
+ error("Can't add D-Bus disconnect filter");
+ g_free(dc_data);
+ dbus_connection_unref(conn);
+ return NULL;
+ }
+
+ return conn;
+}
+
+DBusConnection *dbus_bus_system_setup_with_main_loop(const char *name,
+ void (*disconnect_cb)(void *), void *user_data)
+{
+ return init_dbus(name, disconnect_cb, user_data);
+}
diff --git a/hcid/dbus-common.c b/hcid/dbus-common.c
index 20453c82..8a8a721a 100644
--- a/hcid/dbus-common.c
+++ b/hcid/dbus-common.c
@@ -49,6 +49,8 @@
#include <dbus/dbus.h>
+#include <gdbus.h>
+
#include "hcid.h"
#include "dbus.h"
#include "dbus-helper.h"
@@ -336,7 +338,8 @@ int hcid_dbus_init(void)
{
DBusConnection *conn;
- conn = init_dbus(BLUEZ_NAME, disconnect_callback, NULL);
+ conn = dbus_bus_system_setup_with_main_loop(BLUEZ_NAME,
+ disconnect_callback, NULL);
if (!conn)
return -1;