summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2008-08-05 23:36:14 +0200
committerMarcel Holtmann <marcel@holtmann.org>2008-08-05 23:36:14 +0200
commit32cf081aa948793869822c9634751bced245f01c (patch)
treebd6281604d6d256625c615b98cf2a3d19fe0be0e
parent161915e640404db7a46321e59127a666b992b0df (diff)
parent00acfa685e3e73c619146b7ca39068eb304f1ce8 (diff)
Merge branch 'bluez4' of git://git.infradead.org/users/vudentz/bluez-utils
-rw-r--r--audio/manager.c1
-rw-r--r--input/manager.c1
-rw-r--r--network/manager.c1
-rw-r--r--serial/manager.c1
-rw-r--r--src/Makefile.am4
-rw-r--r--src/agent.c323
-rw-r--r--src/device.c28
-rw-r--r--src/device.h14
-rw-r--r--src/driver.c82
-rw-r--r--src/driver.h54
-rw-r--r--src/manager.c19
11 files changed, 344 insertions, 184 deletions
diff --git a/audio/manager.c b/audio/manager.c
index b1da8426..695c6ba0 100644
--- a/audio/manager.c
+++ b/audio/manager.c
@@ -51,6 +51,7 @@
#include "glib-helper.h"
#include "../src/adapter.h"
#include "../src/device.h"
+#include "../src/driver.h"
#include "dbus-service.h"
#include "logging.h"
diff --git a/input/manager.c b/input/manager.c
index 08609601..b18da8e0 100644
--- a/input/manager.c
+++ b/input/manager.c
@@ -46,6 +46,7 @@
#include "textfile.h"
#include "../src/adapter.h"
#include "../src/device.h"
+#include "../src/driver.h"
#include "device.h"
#include "server.h"
diff --git a/network/manager.c b/network/manager.c
index 22a6e70c..c0af5d34 100644
--- a/network/manager.c
+++ b/network/manager.c
@@ -47,6 +47,7 @@
#include "adapter.h"
#include "device.h"
+#include "driver.h"
#include "error.h"
#include "bridge.h"
#include "manager.h"
diff --git a/serial/manager.c b/serial/manager.c
index 79d7cb8e..9df3caaa 100644
--- a/serial/manager.c
+++ b/serial/manager.c
@@ -54,6 +54,7 @@
#include "../src/dbus-common.h"
#include "adapter.h"
#include "device.h"
+#include "driver.h"
#include "logging.h"
#include "textfile.h"
diff --git a/src/Makefile.am b/src/Makefile.am
index 473c86f9..4b504add 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,11 +18,11 @@ sbin_PROGRAMS = bluetoothd
bluetoothd_SOURCES = main.c hcid.h sdpd.h \
sdpd-server.c sdpd-request.c sdpd-service.c \
sdpd-database.c security.c storage.c \
- server.h server.c manager.h manager.c error.h error.c \
+ manager.h manager.c error.h error.c \
adapter.h adapter.c device.h device.c plugin.h plugin.c \
dbus-common.c dbus-common.h dbus-hci.h dbus-hci.c \
dbus-database.c dbus-database.h dbus-service.c dbus-service.h \
- telephony.h telephony.c agent.h agent.c
+ telephony.h telephony.c agent.h agent.c driver.h driver.c
bluetoothd_LDADD = $(top_builddir)/common/libhelper.a \
@GDBUS_LIBS@ @GMODULE_LIBS@ @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@
diff --git a/src/agent.c b/src/agent.c
index 3cae00a5..f0a6a44d 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -75,6 +75,7 @@ struct agent {
struct agent_request {
agent_request_type_t type;
struct agent *agent;
+ DBusMessage *msg;
DBusPendingCall *call;
void *cb;
void *user_data;
@@ -82,6 +83,9 @@ struct agent_request {
static DBusConnection *connection = NULL;
+static int request_fallback(struct agent_request *req,
+ DBusPendingCallNotifyFunction function);
+
static void agent_release(struct agent *agent)
{
DBusMessage *message;
@@ -127,6 +131,8 @@ static int send_cancel_request(struct agent_request *req)
static void agent_request_free(struct agent_request *req)
{
+ if (req->msg)
+ dbus_message_unref(req->msg);
if (req->call)
dbus_pending_call_unref(req->call);
if (req->agent && req->agent->request)
@@ -251,36 +257,6 @@ int agent_cancel(struct agent *agent)
return 0;
}
-static DBusPendingCall *agent_call_authorize(struct agent *agent,
- const char *device_path,
- const char *uuid)
-{
- DBusMessage *message;
- DBusPendingCall *call;
-
- message = dbus_message_new_method_call(agent->name, agent->path,
- "org.bluez.Agent", "Authorize");
- if (!message) {
- error("Couldn't allocate D-Bus message");
- return NULL;
- }
-
- dbus_message_append_args(message,
- DBUS_TYPE_OBJECT_PATH, &device_path,
- DBUS_TYPE_STRING, &uuid,
- DBUS_TYPE_INVALID);
-
- if (dbus_connection_send_with_reply(connection, message,
- &call, REQUEST_TIMEOUT) == FALSE) {
- error("D-Bus send failed");
- dbus_message_unref(message);
- return NULL;
- }
-
- dbus_message_unref(message);
- return call;
-}
-
static void simple_agent_reply(DBusPendingCall *call, void *user_data)
{
struct agent_request *req = user_data;
@@ -295,6 +271,12 @@ static void simple_agent_reply(DBusPendingCall *call, void *user_data)
dbus_error_init(&err);
if (dbus_set_error_from_message(&err, message)) {
+ if ((g_str_equal(DBUS_ERROR_UNKNOWN_METHOD, err.name) ||
+ g_str_equal(DBUS_ERROR_NO_REPLY, err.name)) &&
+ request_fallback(req, simple_agent_reply) == 0) {
+ dbus_error_free(&err);
+ return;
+ }
error("Agent replied with an error: %s, %s",
err.name, err.message);
@@ -320,6 +302,34 @@ done:
agent_request_free(req);
}
+static int agent_call_authorize(struct agent_request *req,
+ const char *device_path,
+ const char *uuid)
+{
+ struct agent *agent = req->agent;
+
+ req->msg = dbus_message_new_method_call(agent->name, agent->path,
+ "org.bluez.Agent", "Authorize");
+ if (!req->msg) {
+ error("Couldn't allocate D-Bus message");
+ return -ENOMEM;
+ }
+
+ dbus_message_append_args(req->msg,
+ DBUS_TYPE_OBJECT_PATH, &device_path,
+ DBUS_TYPE_STRING, &uuid,
+ DBUS_TYPE_INVALID);
+
+ if (dbus_connection_send_with_reply(connection, req->msg,
+ &req->call, REQUEST_TIMEOUT) == FALSE) {
+ error("D-Bus send failed");
+ return -EIO;
+ }
+
+ dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL);
+ return 0;
+}
+
int agent_authorize(struct agent *agent,
const char *path,
const char *uuid,
@@ -327,19 +337,19 @@ int agent_authorize(struct agent *agent,
void *user_data)
{
struct agent_request *req;
+ int err;
if (agent->request)
return -EBUSY;
req = agent_request_new(agent, AGENT_REQUEST_AUTHORIZE, cb, user_data);
- req->call = agent_call_authorize(agent, path, uuid);
- if (!req->call) {
+ err = agent_call_authorize(req, path, uuid);
+ if (err < 0) {
agent_request_free(req);
return DBUS_HANDLER_RESULT_NEED_MEMORY;
}
- dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL);
agent->request = req;
debug("authorize request was sent for %s", path);
@@ -347,34 +357,6 @@ int agent_authorize(struct agent *agent,
return 0;
}
-static DBusPendingCall *pincode_request_new(struct agent *agent,
- const char *device_path,
- dbus_bool_t numeric)
-{
- DBusMessage *message;
- DBusPendingCall *call;
-
- message = dbus_message_new_method_call(agent->name, agent->path,
- "org.bluez.Agent", "RequestPinCode");
- if (message == NULL) {
- error("Couldn't allocate D-Bus message");
- return NULL;
- }
-
- dbus_message_append_args(message, DBUS_TYPE_OBJECT_PATH, &device_path,
- DBUS_TYPE_INVALID);
-
- if (dbus_connection_send_with_reply(connection, message,
- &call, REQUEST_TIMEOUT) == FALSE) {
- error("D-Bus send failed");
- dbus_message_unref(message);
- return NULL;
- }
-
- dbus_message_unref(message);
- return call;
-}
-
static void pincode_reply(DBusPendingCall *call, void *user_data)
{
struct agent_request *req = user_data;
@@ -394,6 +376,13 @@ static void pincode_reply(DBusPendingCall *call, void *user_data)
dbus_error_init(&err);
if (dbus_set_error_from_message(&err, message)) {
+ if ((g_str_equal(DBUS_ERROR_UNKNOWN_METHOD, err.name) ||
+ g_str_equal(DBUS_ERROR_NO_REPLY, err.name)) &&
+ request_fallback(req, pincode_reply) == 0) {
+ dbus_error_free(&err);
+ return;
+ }
+
error("Agent replied with an error: %s, %s",
err.name, err.message);
@@ -435,68 +424,91 @@ done:
dbus_message_unref(message);
dbus_pending_call_cancel(req->call);
+ agent->request = NULL;
agent_request_free(req);
}
+static int pincode_request_new(struct agent_request *req, const char *device_path,
+ dbus_bool_t numeric)
+{
+ struct agent *agent = req->agent;
+
+ req->msg = dbus_message_new_method_call(agent->name, agent->path,
+ "org.bluez.Agent", "RequestPinCode");
+ if (req->msg == NULL) {
+ error("Couldn't allocate D-Bus message");
+ return -ENOMEM;
+ }
+
+ dbus_message_append_args(req->msg, DBUS_TYPE_OBJECT_PATH, &device_path,
+ DBUS_TYPE_INVALID);
+
+ if (dbus_connection_send_with_reply(connection, req->msg,
+ &req->call, REQUEST_TIMEOUT) == FALSE) {
+ error("D-Bus send failed");
+ return -EIO;
+ }
+
+ dbus_pending_call_set_notify(req->call, pincode_reply, req, NULL);
+ return 0;
+}
+
int agent_request_pincode(struct agent *agent, struct btd_device *device,
agent_pincode_cb cb, void *user_data)
{
struct agent_request *req;
const gchar *dev_path = device_get_path(device);
+ int err;
if (agent->request)
return -EBUSY;
req = agent_request_new(agent, AGENT_REQUEST_PINCODE, cb, user_data);
- req->call = pincode_request_new(agent, dev_path, FALSE);
- if (!req->call)
+ err = pincode_request_new(req, dev_path, FALSE);
+ if (err < 0)
goto failed;
- dbus_pending_call_set_notify(req->call, pincode_reply, req, NULL);
-
agent->request = req;
return 0;
failed:
g_free(req);
- return -1;
+ return err;
}
-static DBusPendingCall *confirm_mode_change_request_new(struct agent *agent,
- const char *mode)
+static int confirm_mode_change_request_new(struct agent_request *req,
+ const char *mode)
{
- DBusMessage *message;
- DBusPendingCall *call;
+ struct agent *agent = req->agent;
- message = dbus_message_new_method_call(agent->name, agent->path,
+ req->msg = dbus_message_new_method_call(agent->name, agent->path,
"org.bluez.Agent", "ConfirmModeChange");
- if (message == NULL) {
+ if (req->msg == NULL) {
error("Couldn't allocate D-Bus message");
- return NULL;
+ return -ENOMEM;
}
- dbus_message_append_args(message,
+ dbus_message_append_args(req->msg,
DBUS_TYPE_STRING, &mode,
DBUS_TYPE_INVALID);
- if (dbus_connection_send_with_reply(connection, message,
- &call, REQUEST_TIMEOUT) == FALSE) {
+ if (dbus_connection_send_with_reply(connection, req->msg,
+ &req->call, REQUEST_TIMEOUT) == FALSE) {
error("D-Bus send failed");
- dbus_message_unref(message);
- return NULL;
+ return -EIO;
}
- dbus_message_unref(message);
-
- return call;
+ dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL);
+ return 0;
}
int agent_confirm_mode_change(struct agent *agent, const char *new_mode,
agent_cb cb, void *user_data)
{
struct agent_request *req;
+ int err;
if (agent->request)
return -EBUSY;
@@ -507,46 +519,17 @@ int agent_confirm_mode_change(struct agent *agent, const char *new_mode,
req = agent_request_new(agent, AGENT_REQUEST_CONFIRM_MODE,
cb, user_data);
- req->call = confirm_mode_change_request_new(agent, new_mode);
- if (!req->call)
+ err = confirm_mode_change_request_new(req, new_mode);
+ if (err < 0)
goto failed;
- dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL);
-
agent->request = req;
return 0;
failed:
agent_request_free(req);
- return -1;
-}
-
-static DBusPendingCall *passkey_request_new(struct agent *agent,
- const char *device_path)
-{
- DBusMessage *message;
- DBusPendingCall *call;
-
- message = dbus_message_new_method_call(agent->name, agent->path,
- "org.bluez.Agent", "RequestPasskey");
- if (message == NULL) {
- error("Couldn't allocate D-Bus message");
- return NULL;
- }
-
- dbus_message_append_args(message, DBUS_TYPE_OBJECT_PATH, &device_path,
- DBUS_TYPE_INVALID);
-
- if (dbus_connection_send_with_reply(connection, message,
- &call, REQUEST_TIMEOUT) == FALSE) {
- error("D-Bus send failed");
- dbus_message_unref(message);
- return NULL;
- }
-
- dbus_message_unref(message);
- return call;
+ return err;
}
static void passkey_reply(DBusPendingCall *call, void *user_data)
@@ -564,6 +547,13 @@ static void passkey_reply(DBusPendingCall *call, void *user_data)
dbus_error_init(&err);
if (dbus_set_error_from_message(&err, message)) {
+ if ((g_str_equal(DBUS_ERROR_UNKNOWN_METHOD, err.name) ||
+ g_str_equal(DBUS_ERROR_NO_REPLY, err.name)) &&
+ request_fallback(req, passkey_reply) == 0) {
+ dbus_error_free(&err);
+ return;
+ }
+
error("Agent replied with an error: %s, %s",
err.name, err.message);
cb(agent, &err, 0, req->user_data);
@@ -588,14 +578,41 @@ done:
dbus_message_unref(message);
dbus_pending_call_cancel(req->call);
+ agent->request = NULL;
agent_request_free(req);
}
+static int passkey_request_new(struct agent_request *req,
+ const char *device_path)
+{
+ struct agent *agent = req->agent;
+
+ req->msg = dbus_message_new_method_call(agent->name, agent->path,
+ "org.bluez.Agent", "RequestPasskey");
+ if (req->msg == NULL) {
+ error("Couldn't allocate D-Bus message");
+ return -ENOMEM;
+ }
+
+ dbus_message_append_args(req->msg, DBUS_TYPE_OBJECT_PATH, &device_path,
+ DBUS_TYPE_INVALID);
+
+ if (dbus_connection_send_with_reply(connection, req->msg,
+ &req->call, REQUEST_TIMEOUT) == FALSE) {
+ error("D-Bus send failed");
+ return -EIO;
+ }
+
+ dbus_pending_call_set_notify(req->call, passkey_reply, req, NULL);
+ return 0;
+}
+
int agent_request_passkey(struct agent *agent, struct btd_device *device,
agent_passkey_cb cb, void *user_data)
{
struct agent_request *req;
const gchar *dev_path = device_get_path(device);
+ int err;
if (agent->request)
return -EBUSY;
@@ -605,50 +622,46 @@ int agent_request_passkey(struct agent *agent, struct btd_device *device,
req = agent_request_new(agent, AGENT_REQUEST_PASSKEY, cb, user_data);
- req->call = passkey_request_new(agent, dev_path);
- if (!req->call)
+ err = passkey_request_new(req, dev_path);
+ if (err < 0)
goto failed;
- dbus_pending_call_set_notify(req->call, passkey_reply, req, NULL);
-
agent->request = req;
return 0;
failed:
agent_request_free(req);
- return -1;
+ return err;
}
-static DBusPendingCall *confirmation_request_new(struct agent *agent,
- const char *device_path,
- uint32_t passkey)
+static int confirmation_request_new(struct agent_request *req,
+ const char *device_path,
+ uint32_t passkey)
{
- DBusMessage *message;
- DBusPendingCall *call;
+ struct agent *agent = req->agent;
- message = dbus_message_new_method_call(agent->name, agent->path,
+ req->msg = dbus_message_new_method_call(agent->name, agent->path,
"org.bluez.Agent", "RequestConfirmation");
- if (message == NULL) {
+ if (req->msg == NULL) {
error("Couldn't allocate D-Bus message");
- return NULL;
+ return -ENOMEM;
}
- dbus_message_append_args(message,
+ dbus_message_append_args(req->msg,
DBUS_TYPE_OBJECT_PATH, &device_path,
DBUS_TYPE_UINT32, &passkey,
DBUS_TYPE_INVALID);
- if (dbus_connection_send_with_reply(connection, message,
- &call, REQUEST_TIMEOUT) == FALSE) {
+ if (dbus_connection_send_with_reply(connection, req->msg,
+ &req->call, REQUEST_TIMEOUT) == FALSE) {
error("D-Bus send failed");
- dbus_message_unref(message);
- return NULL;
+ return -EIO;
}
- dbus_message_unref(message);
+ dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL);
- return call;
+ return 0;
}
int agent_request_confirmation(struct agent *agent, struct btd_device *device,
@@ -657,6 +670,7 @@ int agent_request_confirmation(struct agent *agent, struct btd_device *device,
{
struct agent_request *req;
const gchar *dev_path = device_get_path(device);
+ int err;
if (agent->request)
return -EBUSY;
@@ -667,19 +681,52 @@ int agent_request_confirmation(struct agent *agent, struct btd_device *device,
req = agent_request_new(agent, AGENT_REQUEST_CONFIRMATION, cb,
user_data);
- req->call = confirmation_request_new(agent, dev_path, passkey);
- if (!req->call)
+ err = confirmation_request_new(req, dev_path, passkey);
+ if (err < 0)
goto failed;
- dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL);
-
agent->request = req;
return 0;
failed:
agent_request_free(req);
- return -1;
+ return err;
+}
+
+static int request_fallback(struct agent_request *req,
+ DBusPendingCallNotifyFunction function)
+{
+ struct adapter *adapter = req->agent->adapter;
+ DBusMessage *msg;
+
+ if (req->agent == adapter->agent || adapter->agent == NULL)
+ return -EINVAL;
+
+ dbus_pending_call_cancel(req->call);
+
+ msg = dbus_message_copy(req->msg);
+
+ dbus_message_set_destination(msg, adapter->agent->name);
+ dbus_message_set_path(msg, adapter->agent->path);
+
+ if (dbus_connection_send_with_reply(connection, msg,
+ &req->call, REQUEST_TIMEOUT) == FALSE) {
+ error("D-Bus send failed");
+ dbus_message_unref(msg);
+ return -EIO;
+ }
+
+ req->agent->request = NULL;
+ req->agent = adapter->agent;
+ req->agent->request = req;
+
+ dbus_message_unref(req->msg);
+ req->msg = msg;
+
+ dbus_pending_call_set_notify(req->call, function, req, NULL);
+
+ return 0;
}
int agent_display_passkey(struct agent *agent, struct btd_device *device,
diff --git a/src/device.c b/src/device.c
index 4ef90803..ac578f2b 100644
--- a/src/device.c
+++ b/src/device.c
@@ -57,11 +57,11 @@
#include "device.h"
#include "dbus-common.h"
#include "dbus-hci.h"
-#include "dbus-service.h"
#include "error.h"
#include "glib-helper.h"
#include "agent.h"
#include "sdp-xml.h"
+#include "driver.h"
#define DEFAULT_XML_BUF_SIZE 1024
#define DISCONNECT_TIMER 2
@@ -101,8 +101,6 @@ struct browse_req {
gboolean browse;
};
-static GSList *drivers = NULL;
-
static uint16_t uuid_list[] = {
PUBLIC_BROWSE_GROUP,
HID_SVCLASS_ID,
@@ -620,13 +618,13 @@ sdp_record_t *get_record(sdp_list_t *recs, const char *uuid)
void device_probe_drivers(struct btd_device *device, GSList *uuids, sdp_list_t *recs)
{
- GSList *list;
+ GSList *list = btd_get_device_drivers();
const char **uuid;
int err;
debug("Probe drivers for %s", device->path);
- for (list = drivers; list; list = list->next) {
+ for (; list; list = list->next) {
struct btd_device_driver *driver = list->data;
GSList *records = NULL;
@@ -1085,23 +1083,3 @@ uint8_t device_get_auth(struct btd_device *device)
{
return device->auth;
}
-
-int btd_register_device_driver(struct btd_device_driver *driver)
-{
- const char **uuid;
-
- /* FIXME: hack to make hci to resolve service_req_auth symbol*/
- service_req_auth(NULL, NULL, NULL, NULL, NULL);
- drivers = g_slist_append(drivers, driver);
-
- for (uuid = driver->uuids; *uuid; uuid++) {
- debug("name %s uuid %s", driver->name, *uuid);
- }
-
- return 0;
-}
-
-void btd_unregister_device_driver(struct btd_device_driver *driver)
-{
- drivers = g_slist_remove(drivers, driver);
-}
diff --git a/src/device.h b/src/device.h
index 31480a66..c29d670b 100644
--- a/src/device.h
+++ b/src/device.h
@@ -42,17 +42,3 @@ void device_set_temporary(struct btd_device *device, gboolean temporary);
void device_set_cap(struct btd_device *device, uint8_t cap);
void device_set_auth(struct btd_device *device, uint8_t auth);
uint8_t device_get_auth(struct btd_device *device);
-
-#define BTD_UUIDS(args...) ((const char *[]) { args, NULL } )
-
-struct btd_device_driver {
- const char *name;
- const char **uuids;
- int (*probe) (struct btd_device_driver *driver,
- struct btd_device *device, GSList *records);
- void (*remove) (struct btd_device_driver *driver,
- struct btd_device *device);
-};
-
-int btd_register_device_driver(struct btd_device_driver *driver);
-void btd_unregister_device_driver(struct btd_device_driver *driver);
diff --git a/src/driver.c b/src/driver.c
new file mode 100644
index 00000000..5c47a250
--- /dev/null
+++ b/src/driver.c
@@ -0,0 +1,82 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2006-2007 Nokia Corporation
+ * 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 <bluetooth/bluetooth.h>
+
+#include <dbus/dbus.h>
+#include <glib.h>
+
+#include "logging.h"
+
+#include "driver.h"
+#include "dbus-service.h"
+
+static GSList *device_drivers = NULL;
+static GSList *adapter_drivers = NULL;
+
+int btd_register_device_driver(struct btd_device_driver *driver)
+{
+ const char **uuid;
+
+ /* FIXME: hack to make hci to resolve service_req_auth symbol*/
+ service_req_auth(NULL, NULL, NULL, NULL, NULL);
+ device_drivers = g_slist_append(device_drivers, driver);
+
+ for (uuid = driver->uuids; *uuid; uuid++) {
+ debug("name %s uuid %s", driver->name, *uuid);
+ }
+
+ return 0;
+}
+
+void btd_unregister_device_driver(struct btd_device_driver *driver)
+{
+ device_drivers = g_slist_remove(device_drivers, driver);
+}
+
+GSList *btd_get_device_drivers()
+{
+ return device_drivers;
+}
+
+int btd_register_adapter_driver(struct btd_adapter_driver *driver)
+{
+ adapter_drivers = g_slist_append(adapter_drivers, driver);
+
+ return 0;
+}
+
+void btd_unregister_adapter_driver(struct btd_adapter_driver *driver)
+{
+ adapter_drivers = g_slist_remove(adapter_drivers, driver);
+}
+
+GSList *btd_get_adapter_drivers()
+{
+ return adapter_drivers;
+}
diff --git a/src/driver.h b/src/driver.h
new file mode 100644
index 00000000..6ed56d53
--- /dev/null
+++ b/src/driver.h
@@ -0,0 +1,54 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2006-2007 Nokia Corporation
+ * 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
+ *
+ */
+
+#define BTD_UUIDS(args...) ((const char *[]) { args, NULL } )
+
+struct btd_device;
+
+struct btd_device_driver {
+ const char *name;
+ const char **uuids;
+ int (*probe) (struct btd_device_driver *driver,
+ struct btd_device *device, GSList *records);
+ void (*remove) (struct btd_device_driver *driver,
+ struct btd_device *device);
+};
+
+int btd_register_device_driver(struct btd_device_driver *driver);
+void btd_unregister_device_driver(struct btd_device_driver *driver);
+GSList *btd_get_device_drivers(void);
+
+struct btd_adapter;
+
+struct btd_adapter_driver {
+ const char *name;
+ int (*probe) (struct btd_adapter_driver *driver,
+ struct btd_adapter *adapter);
+ void (*remove) (struct btd_adapter_driver *driver,
+ struct btd_adapter *adapter);
+};
+
+int btd_register_adapter_driver(struct btd_adapter_driver *driver);
+void btd_unregister_adapter_driver(struct btd_adapter_driver *driver);
+GSList *btd_get_adapter_drivers(void);
diff --git a/src/manager.c b/src/manager.c
index cda45f4c..fc0c8738 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -59,7 +59,7 @@
#include "oui.h"
#include "agent.h"
#include "device.h"
-#include "glib-helper.h"
+#include "driver.h"
#include "manager.h"
@@ -443,14 +443,17 @@ static void manager_remove_adapter(struct adapter *adapter)
int manager_register_adapter(int id)
{
struct adapter *adapter = adapter_create(connection, id);
- const gchar *path;
+ GSList *l = btd_get_adapter_drivers();
if (!adapter)
return -1;
- path = adapter_get_path(adapter);
+ for (; l; l = l->next) {
+ struct btd_adapter_driver *driver = l->data;
- __probe_servers(path);
+ if (driver->probe)
+ driver->probe(driver, (struct btd_adapter *) adapter);
+ }
manager_add_adapter(adapter);
@@ -461,6 +464,7 @@ int manager_unregister_adapter(int id)
{
struct adapter *adapter;
const gchar *path;
+ GSList *l = btd_get_adapter_drivers();
adapter = manager_find_adapter_by_id(id);
if (!adapter)
@@ -470,7 +474,12 @@ int manager_unregister_adapter(int id)
info("Unregister path: %s", path);
- __remove_servers(path);
+ for (; l; l = l->next) {
+ struct btd_adapter_driver *driver = l->data;
+
+ if (driver->remove)
+ driver->remove(driver, (struct btd_adapter *) adapter);
+ }
adapter_stop(adapter);