summaryrefslogtreecommitdiff
path: root/plugins/dbusoob.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/dbusoob.c')
-rw-r--r--plugins/dbusoob.c234
1 files changed, 234 insertions, 0 deletions
diff --git a/plugins/dbusoob.c b/plugins/dbusoob.c
new file mode 100644
index 0000000..2c03780
--- /dev/null
+++ b/plugins/dbusoob.c
@@ -0,0 +1,234 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011 ST-Ericsson SA
+ *
+ * Author: Szymon Janc <szymon.janc@tieto.com> for ST-Ericsson
+ *
+ *
+ * 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 <errno.h>
+#include <gdbus.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/sdp.h>
+
+#include "plugin.h"
+#include "log.h"
+#include "adapter.h"
+#include "device.h"
+#include "manager.h"
+#include "dbus-common.h"
+#include "event.h"
+#include "error.h"
+#include "oob.h"
+
+#define OOB_INTERFACE "org.bluez.OutOfBand"
+
+struct oob_request {
+ struct btd_adapter *adapter;
+ DBusMessage *msg;
+};
+
+static GSList *oob_requests = NULL;
+static DBusConnection *connection = NULL;
+
+static gint oob_request_cmp(gconstpointer a, gconstpointer b)
+{
+ const struct oob_request *data = a;
+ const struct btd_adapter *adapter = b;
+
+ return data->adapter != adapter;
+}
+
+static struct oob_request *find_oob_request(struct btd_adapter *adapter)
+{
+ GSList *match;
+
+ match = g_slist_find_custom(oob_requests, adapter, oob_request_cmp);
+
+ if (match)
+ return match->data;
+
+ return NULL;
+}
+
+static void read_local_data_complete(struct btd_adapter *adapter, uint8_t *hash,
+ uint8_t *randomizer)
+{
+ struct DBusMessage *reply;
+ struct oob_request *oob_request;
+
+ oob_request = find_oob_request(adapter);
+ if (!oob_request)
+ return;
+
+ if (hash && randomizer)
+ reply = g_dbus_create_reply(oob_request->msg,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash, 16,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer, 16,
+ DBUS_TYPE_INVALID);
+ else
+ reply = btd_error_failed(oob_request->msg,
+ "Failed to read local OOB data.");
+
+ oob_requests = g_slist_remove(oob_requests, oob_request);
+ dbus_message_unref(oob_request->msg);
+ g_free(oob_request);
+
+ if (!reply) {
+ error("Couldn't allocate D-Bus message");
+ return;
+ }
+
+ if (!g_dbus_send_message(connection, reply))
+ error("D-Bus send failed");
+}
+
+static DBusMessage *read_local_data(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ struct btd_adapter *adapter = data;
+ struct oob_request *oob_request;
+
+ if (find_oob_request(adapter))
+ return btd_error_in_progress(msg);
+
+ if (btd_adapter_read_local_oob_data(adapter))
+ return btd_error_failed(msg, "Request failed.");
+
+ oob_request = g_new(struct oob_request, 1);
+ oob_request->adapter = adapter;
+ oob_requests = g_slist_append(oob_requests, oob_request);
+ oob_request->msg = dbus_message_ref(msg);
+
+ return NULL;
+}
+
+static DBusMessage *add_remote_data(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ struct btd_adapter *adapter = data;
+ uint8_t *hash, *randomizer;
+ int32_t hlen, rlen;
+ const char *addr;
+ bdaddr_t bdaddr;
+
+ if (!dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &addr,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash, &hlen,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer, &rlen,
+ DBUS_TYPE_INVALID))
+ return btd_error_invalid_args(msg);
+
+ if (hlen != 16 || rlen != 16 || bachk(addr))
+ return btd_error_invalid_args(msg);
+
+ str2ba(addr, &bdaddr);
+
+ if (btd_adapter_add_remote_oob_data(adapter, &bdaddr, hash, randomizer))
+ return btd_error_failed(msg, "Request failed");
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static DBusMessage *remove_remote_data(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ struct btd_adapter *adapter = data;
+ const char *addr;
+ bdaddr_t bdaddr;
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr,
+ DBUS_TYPE_INVALID))
+ return btd_error_invalid_args(msg);
+
+ if (bachk(addr))
+ return btd_error_invalid_args(msg);
+
+ str2ba(addr, &bdaddr);
+
+ if (btd_adapter_remove_remote_oob_data(adapter, &bdaddr))
+ return btd_error_failed(msg, "Request failed");
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static GDBusMethodTable oob_methods[] = {
+ {"AddRemoteData", "sayay", "", add_remote_data},
+ {"RemoveRemoteData", "s", "", remove_remote_data},
+ {"ReadLocalData", "", "ayay", read_local_data,
+ G_DBUS_METHOD_FLAG_ASYNC},
+ {}
+};
+
+static int oob_probe(struct btd_adapter *adapter)
+{
+ const char *path = adapter_get_path(adapter);
+
+ if (!g_dbus_register_interface(connection, path, OOB_INTERFACE,
+ oob_methods, NULL, NULL, adapter, NULL)) {
+ error("OOB interface init failed on path %s", path);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static void oob_remove(struct btd_adapter *adapter)
+{
+ read_local_data_complete(adapter, NULL, NULL);
+
+ g_dbus_unregister_interface(connection, adapter_get_path(adapter),
+ OOB_INTERFACE);
+}
+
+static struct btd_adapter_driver oob_driver = {
+ .name = "oob",
+ .probe = oob_probe,
+ .remove = oob_remove,
+};
+
+static int dbusoob_init(void)
+{
+ DBG("Setup dbusoob plugin");
+
+ connection = get_dbus_connection();
+
+ oob_register_cb(read_local_data_complete);
+
+ return btd_register_adapter_driver(&oob_driver);
+}
+
+static void dbusoob_exit(void)
+{
+ DBG("Cleanup dbusoob plugin");
+
+ manager_foreach_adapter((adapter_cb) oob_remove, NULL);
+
+ btd_unregister_adapter_driver(&oob_driver);
+}
+
+BLUETOOTH_PLUGIN_DEFINE(dbusoob, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+ dbusoob_init, dbusoob_exit)