--- /dev/null
+/*
+ *
+ * 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 TIZEN_FEATURE_BLUEZ_MODIFY
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include "gdbus/gdbus.h"
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/sdp.h>
+
+#include "src/plugin.h"
+#include "src/log.h"
+#include "src/dbus-common.h"
+#include "src/adapter.h"
+#include "src/device.h"
+#include "src/eir.h"
+#include "src/agent.h"
+#include "src/hcid.h"
+#include "src/error.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,
+ const uint8_t *hash192, const uint8_t *randomizer192,
+ const uint8_t *hash256, const uint8_t *randomizer256,
+ void *user_data)
+{
+ struct DBusMessage *reply;
+ struct oob_request *oob_request;
+
+ oob_request = find_oob_request(adapter);
+ if (!oob_request)
+ return;
+
+ if ((hash192 && randomizer192) || (hash256 && randomizer256))
+ reply = g_dbus_create_reply(oob_request->msg,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash192, 16,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer192, 16,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &hash256, hash256 ? 16 : 0,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &randomizer256, randomizer256 ? 16 : 0,
+ 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;
+ struct oob_handler *handler;
+
+ 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);
+
+ handler = g_new0(struct oob_handler, 1);
+ handler->read_local_cb = read_local_data_complete;
+
+ btd_adapter_set_oob_handler(oob_request->adapter, handler);
+
+ return NULL;
+}
+
+static DBusMessage *add_remote_data(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ struct btd_adapter *adapter = data;
+ const char *addr = NULL;
+ uint8_t *hash192 = NULL;
+ uint8_t *randomizer192 = NULL;
+ int32_t h192_len = 0;
+ int32_t r192_len = 0;
+ uint8_t *hash256 = NULL;
+ uint8_t *randomizer256 = NULL;
+ int32_t h256_len = 0;
+ int32_t r256_len = 0;
+ bdaddr_t bdaddr;
+ uint8_t addr_type = BDADDR_BREDR;
+ bool valid_len;
+
+ if (!dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &addr,
+ DBUS_TYPE_BYTE, &addr_type,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash192, &h192_len,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer192, &r192_len,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash256, &h256_len,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer256, &r256_len,
+ DBUS_TYPE_INVALID))
+ return btd_error_invalid_args(msg);
+
+ DBG("address type: %d", addr_type);
+
+ valid_len = (h192_len == 16 && r192_len == 16) ||
+ (h256_len == 16 && r256_len == 16);
+
+ if (!valid_len || bachk(addr))
+ return btd_error_invalid_args(msg);
+
+ str2ba(addr, &bdaddr);
+
+ if (btd_adapter_add_remote_oob_ext_data(adapter, &bdaddr, addr_type,
+ hash192, randomizer192,
+ hash256, randomizer256))
+ 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;
+ uint8_t addr_type = 0;
+
+ 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_ext_data(adapter, &bdaddr, addr_type))
+ return btd_error_failed(msg, "Request failed");
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static const GDBusMethodTable oob_methods[] = {
+ { GDBUS_METHOD("AddRemoteData",
+ GDBUS_ARGS({ "address", "s" },
+ { "address_type", "y" },
+ { "hash192", "ay" }, { "randomizer192", "ay" },
+ { "hash256", "ay" }, { "randomizer256", "ay" }),
+ NULL,
+ add_remote_data) },
+ { GDBUS_METHOD("RemoveRemoteData",
+ GDBUS_ARGS({ "address", "s" }), NULL,
+ remove_remote_data) },
+ { GDBUS_ASYNC_METHOD("ReadLocalData",
+ NULL, GDBUS_ARGS(
+ {"hash192", "ay" }, { "randomizer192", "ay" },
+ {"hash256", "ay" }, { "randomizer256", "ay" }),
+ read_local_data) },
+ { }
+};
+
+static int oob_probe(struct btd_adapter *adapter)
+{
+ const char *path = adapter_get_path(adapter);
+
+ DBG("dbusoob probe");
+ DBG("adapter path: %s", path);
+
+ 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, NULL, 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 = btd_get_dbus_connection();
+
+ return btd_register_adapter_driver(&oob_driver);
+}
+
+static void dbusoob_exit(void)
+{
+ DBG("Cleanup dbusoob plugin");
+
+ btd_unregister_adapter_driver(&oob_driver);
+}
+
+BLUETOOTH_PLUGIN_DEFINE(dbusoob, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+ dbusoob_init, dbusoob_exit)
+#endif