summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbhinav Kumar <abhinav.ku91@samsung.com>2015-02-19 09:45:59 +0530
committerAbhinav Kumar <abhinav.ku91@samsung.com>2015-02-19 09:45:59 +0530
commit7a63bb884b1e84ec510349114f0dfcea0506b0ac (patch)
treeda543cd7d57276321401b14ec2eec944626801a5
parentd88e507a339b9c982b172b555834cd831c54f050 (diff)
downloadbluez-7a63bb884b1e84ec510349114f0dfcea0506b0ac.tar.gz
bluez-7a63bb884b1e84ec510349114f0dfcea0506b0ac.tar.bz2
bluez-7a63bb884b1e84ec510349114f0dfcea0506b0ac.zip
Applied bluez patches present in Tizen branch. The following patches have been applied :
1> bluetooth player: add searchable value to show cmd 2> add property connected for input device 3> core/service: Add btd_service_get_version 4> core/profile: Add version information to btd_profile 5> core/service: Add btd_service_set_auto_connect 6> core/service: Add btd_service_get_auto_connect 7> core/device: Use service auto_connect flag 8> profiles: Add missing local_uuid 9> core/service: Add btd_service_set_blocked 10> core/service: Add btd_service_is_blocked 11> core/profile: Add authorization UUID information to btd_profile 12> core/device: Add device_is_service_blocked 13> core/adapter: Check if service is blocked before authorizing 14> plugins: Add initial code for service plugin 15> plugins/service: Add initial code 16> Fix bluetoothd core dumped if disable bt tethering 17> Fix Security Static Code Analysis 18> Add param fd into authorize service 19> Modify the param of authorize service 20> Fix the remaining Security Static Code Analysis 21> Fix the length of string 22> Fix the remaining Security Static Code Analysis Change-Id: I3191182d850b1252248de76d4bd8f70768230b93
-rw-r--r--Makefile.plugins8
-rw-r--r--client/agent.c7
-rw-r--r--configure.ac4
-rw-r--r--obexd/plugins/pbap.c2
-rw-r--r--plugins/service.c439
-rw-r--r--profiles/audio/a2dp.c8
-rw-r--r--profiles/audio/avctp.c4
-rw-r--r--profiles/audio/avdtp.c2
-rw-r--r--profiles/audio/avrcp.c8
-rw-r--r--profiles/health/hdp_manager.c6
-rw-r--r--profiles/input/device.c21
-rw-r--r--profiles/input/manager.c2
-rw-r--r--profiles/input/server.c2
-rw-r--r--profiles/network/manager.c6
-rw-r--r--profiles/network/server.c21
-rw-r--r--profiles/sap/server.c2
-rw-r--r--src/adapter.c17
-rw-r--r--src/adapter.h2
-rw-r--r--src/agent.c19
-rw-r--r--src/agent.h2
-rw-r--r--src/bluetooth.conf3
-rw-r--r--src/device.c34
-rw-r--r--src/device.h1
-rw-r--r--src/org.bluez.service2
-rw-r--r--src/profile.c4
-rw-r--r--src/profile.h2
-rw-r--r--src/service.c50
-rw-r--r--src/service.h5
-rw-r--r--tools/bluetooth-player.c1
-rw-r--r--tools/hciattach.c2
-rw-r--r--tools/hcitool.c23
31 files changed, 672 insertions, 37 deletions
diff --git a/Makefile.plugins b/Makefile.plugins
index ddcbd3ac..ce2d2e1c 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -142,3 +142,11 @@ plugins_sixaxis_la_LDFLAGS = $(AM_LDFLAGS) -module -avoid-version \
-no-undefined @UDEV_LIBS@
plugins_sixaxis_la_CFLAGS = $(AM_CFLAGS) -fvisibility=hidden @UDEV_CFLAGS@
endif
+
+if SERVICE
+plugin_LTLIBRARIES += plugins/service.la
+plugins_service_la_SOURCES = plugins/service.c
+plugins_service_la_LDFLAGS = $(AM_LDFLAGS) -module -avoid-version \
+ -no-undefined
+plugins_service_la_CFLAGS = $(AM_CFLAGS) -fvisibility=hidden
+endif
diff --git a/client/agent.c b/client/agent.c
index eeabd5b0..54c83fce 100644
--- a/client/agent.c
+++ b/client/agent.c
@@ -295,11 +295,13 @@ static DBusMessage *authorize_service(DBusConnection *conn,
{
const char *device, *uuid;
char *str;
+ int fd;
rl_printf("Authorize service\n");
dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &device,
- DBUS_TYPE_STRING, &uuid, DBUS_TYPE_INVALID);
+ DBUS_TYPE_STRING, &uuid,
+ DBUS_TYPE_UNIX_FD, &fd, DBUS_TYPE_INVALID);
str = g_strdup_printf("Authorize service %s (yes/no): ", uuid);
agent_prompt(str);
@@ -344,7 +346,8 @@ static const GDBusMethodTable methods[] = {
GDBUS_ARGS({ "device", "o" }),
NULL, request_authorization) },
{ GDBUS_ASYNC_METHOD("AuthorizeService",
- GDBUS_ARGS({ "device", "o" }, { "uuid", "s" }),
+ GDBUS_ARGS({ "device", "o" }, { "uuid", "s" },
+ {"fd", "h"}),
NULL, authorize_service) },
{ GDBUS_METHOD("Cancel", NULL, NULL, cancel_request) },
{ }
diff --git a/configure.ac b/configure.ac
index 8a4bae6d..18e4ddbb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -245,6 +245,10 @@ AC_ARG_ENABLE(sixaxis, AC_HELP_STRING([--enable-sixaxis],
AM_CONDITIONAL(SIXAXIS, test "${enable_sixaxis}" = "yes" &&
test "${enable_udev}" != "no")
+AC_ARG_ENABLE(service, AC_HELP_STRING([--enable-service],
+ [enable service plugin]), [enable_service=${enableval}])
+AM_CONDITIONAL(SERVICE, test "${enable_service}" = "yes")
+
if (test "${prefix}" = "NONE"); then
dnl no prefix and no localstatedir, so default to /var
if (test "$localstatedir" = '${prefix}/var'); then
diff --git a/obexd/plugins/pbap.c b/obexd/plugins/pbap.c
index 2008f365..d9e96437 100644
--- a/obexd/plugins/pbap.c
+++ b/obexd/plugins/pbap.c
@@ -460,7 +460,7 @@ static void cache_entry_done(void *user_data)
{
struct pbap_session *pbap = user_data;
const char *id;
- int ret;
+ int ret = 0;
DBG("");
diff --git a/plugins/service.c b/plugins/service.c
new file mode 100644
index 00000000..25111f6c
--- /dev/null
+++ b/plugins/service.c
@@ -0,0 +1,439 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2014 Intel Corporation.
+ *
+ *
+ * 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 <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <gdbus/gdbus.h>
+
+#include "lib/uuid.h"
+#include "src/plugin.h"
+#include "src/log.h"
+#include "src/dbus-common.h"
+#include "src/error.h"
+#include "src/adapter.h"
+#include "src/device.h"
+#include "src/service.h"
+#include "src/profile.h"
+
+#define SERVICE_INTERFACE "org.bluez.Service1"
+
+static unsigned int service_id = 0;
+static GSList *services = NULL;
+
+struct service_data {
+ struct btd_service *service;
+ char *path;
+ DBusMessage *connect;
+ DBusMessage *disconnect;
+};
+
+static struct service_data *find_data(struct btd_service *service)
+{
+ GSList *l;
+
+ for (l = services; l; l = l->next) {
+ struct service_data *data = l->data;
+
+ if (data->service == service)
+ return data;
+ }
+
+ return NULL;
+}
+
+static void data_free(void *user_data)
+{
+ struct service_data *data = user_data;
+
+ if (data->connect)
+ dbus_message_unref(data->connect);
+
+ if (data->disconnect)
+ dbus_message_unref(data->disconnect);
+
+ g_free(data->path);
+ g_free(data);
+}
+
+static void data_remove(struct service_data *data)
+{
+ services = g_slist_remove(services, data);
+ g_dbus_unregister_interface(btd_get_dbus_connection(), data->path,
+ SERVICE_INTERFACE);
+}
+
+static DBusMessage *service_disconnect(DBusConnection *conn, DBusMessage *msg,
+ void *user_data)
+{
+ struct service_data *data = user_data;
+ int err;
+
+ if (data->disconnect)
+ return btd_error_in_progress(msg);
+
+ data->disconnect = dbus_message_ref(msg);
+
+ err = btd_service_disconnect(data->service);
+ if (err == 0)
+ return NULL;
+
+ dbus_message_unref(data->disconnect);
+ data->disconnect = NULL;
+
+ return btd_error_failed(msg, strerror(-err));
+}
+
+static DBusMessage *service_connect(DBusConnection *conn, DBusMessage *msg,
+ void *user_data)
+{
+ struct service_data *data = user_data;
+ int err;
+
+ if (data->connect)
+ return btd_error_in_progress(msg);
+
+ err = btd_service_connect(data->service);
+ if (err < 0)
+ return btd_error_failed(msg, strerror(-err));
+
+ data->connect = dbus_message_ref(msg);
+
+ return NULL;
+}
+
+static const char *data_get_state(struct service_data *data)
+{
+ btd_service_state_t state = btd_service_get_state(data->service);
+ int err;
+
+ switch (state) {
+ case BTD_SERVICE_STATE_UNAVAILABLE:
+ return "unavailable";
+ case BTD_SERVICE_STATE_DISCONNECTED:
+ err = btd_service_get_error(data->service);
+ return err < 0 ? "error" : "disconnected";
+ case BTD_SERVICE_STATE_CONNECTING:
+ return "connecting";
+ case BTD_SERVICE_STATE_CONNECTED:
+ return "connected";
+ case BTD_SERVICE_STATE_DISCONNECTING:
+ return "disconnecting";
+ }
+
+ return "unknown";
+}
+
+static gboolean get_device(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct service_data *data = user_data;
+ struct btd_device *dev = btd_service_get_device(data->service);
+ const char *path = btd_device_get_path(dev);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
+
+ return TRUE;
+}
+
+static gboolean get_state(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct service_data *data = user_data;
+ const char *state;
+
+ state = data_get_state(data);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &state);
+
+ return TRUE;
+}
+
+static gboolean remote_uuid_exists(const GDBusPropertyTable *property,
+ void *user_data)
+{
+ struct service_data *data = user_data;
+ struct btd_profile *p = btd_service_get_profile(data->service);
+
+ return p->remote_uuid != NULL;
+}
+
+static gboolean get_remote_uuid(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct service_data *data = user_data;
+ struct btd_profile *p = btd_service_get_profile(data->service);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &p->remote_uuid);
+
+ return TRUE;
+}
+
+
+static gboolean local_uuid_exists(const GDBusPropertyTable *property,
+ void *user_data)
+{
+ struct service_data *data = user_data;
+ struct btd_profile *p = btd_service_get_profile(data->service);
+
+ return p->local_uuid != NULL;
+}
+
+static gboolean get_local_uuid(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct service_data *data = user_data;
+ struct btd_profile *p = btd_service_get_profile(data->service);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &p->local_uuid);
+
+ return TRUE;
+}
+
+static gboolean version_exists(const GDBusPropertyTable *property,
+ void *user_data)
+{
+ struct service_data *data = user_data;
+ uint16_t version = btd_service_get_version(data->service);
+
+ return version != 0x0000;
+}
+
+static gboolean get_version(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct service_data *data = user_data;
+ uint16_t version = btd_service_get_version(data->service);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &version);
+
+ return TRUE;
+}
+
+static gboolean get_auto_connect(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct service_data *data = user_data;
+ dbus_bool_t value = btd_service_get_auto_connect(data->service);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &value);
+
+ return TRUE;
+}
+
+static void set_auto_connect(const GDBusPropertyTable *property,
+ DBusMessageIter *value,
+ GDBusPendingPropertySet id,
+ void *user_data)
+{
+ struct service_data *data = user_data;
+ dbus_bool_t b;
+
+ if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_BOOLEAN) {
+ g_dbus_pending_property_error(id,
+ ERROR_INTERFACE ".InvalidArguments",
+ "Invalid arguments in method call");
+ return;
+ }
+
+ dbus_message_iter_get_basic(value, &b);
+
+ btd_service_set_auto_connect(data->service, b);
+
+ g_dbus_pending_property_success(id);
+}
+
+static gboolean get_blocked(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct service_data *data = user_data;
+ dbus_bool_t value = btd_service_is_blocked(data->service);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &value);
+
+ return TRUE;
+}
+
+static void set_blocked(const GDBusPropertyTable *property,
+ DBusMessageIter *value,
+ GDBusPendingPropertySet id,
+ void *user_data)
+{
+ struct service_data *data = user_data;
+ dbus_bool_t b;
+
+ if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_BOOLEAN) {
+ g_dbus_pending_property_error(id,
+ ERROR_INTERFACE ".InvalidArguments",
+ "Invalid arguments in method call");
+ return;
+ }
+
+ dbus_message_iter_get_basic(value, &b);
+
+ btd_service_set_blocked(data->service, b);
+
+ g_dbus_pending_property_success(id);
+}
+
+static const GDBusPropertyTable service_properties[] = {
+ { "Device", "o", get_device, NULL, NULL },
+ { "State", "s", get_state, NULL, NULL },
+ { "RemoteUUID", "s", get_remote_uuid, NULL, remote_uuid_exists },
+ { "LocalUUID", "s", get_local_uuid, NULL, local_uuid_exists },
+ { "Version", "q", get_version, NULL, version_exists },
+ { "AutoConnect", "b", get_auto_connect, set_auto_connect, NULL },
+ { "Blocked", "b", get_blocked, set_blocked, NULL },
+ { }
+};
+
+static const GDBusMethodTable service_methods[] = {
+ { GDBUS_ASYNC_METHOD("Disconnect", NULL, NULL, service_disconnect) },
+ { GDBUS_ASYNC_METHOD("Connect", NULL, NULL, service_connect) },
+ {}
+};
+
+static struct service_data *service_get_data(struct btd_service *service)
+{
+ struct btd_device *dev = btd_service_get_device(service);
+ struct btd_profile *p = btd_service_get_profile(service);
+ struct service_data *data;
+
+ data = find_data(service);
+ if (data != NULL)
+ return data;
+
+ data = g_new0(struct service_data, 1);
+ data->path = g_strdup_printf("%s/%s", btd_device_get_path(dev),
+ p->remote_uuid);
+ data->path = g_strdelimit(data->path, "-", '_');
+ data->service = service;
+ if (g_dbus_register_interface(btd_get_dbus_connection(),
+ data->path, SERVICE_INTERFACE,
+ service_methods, NULL,
+ service_properties, data,
+ data_free) == FALSE) {
+ error("Unable to register service interface for %s",
+ data->path);
+ data_free(data);
+ return NULL;
+ }
+
+ services = g_slist_prepend(services, data);
+
+ DBG("%s", data->path);
+
+ return data;
+}
+
+static void service_connected(struct service_data *data)
+{
+ DBusMessage *reply;
+
+ if (!data->connect)
+ return;
+
+ reply = dbus_message_new_method_return(data->connect);
+ g_dbus_send_message(btd_get_dbus_connection(), reply);
+ dbus_message_unref(data->connect);
+ data->connect = NULL;
+}
+
+static void service_disconnected(struct service_data *data)
+{
+ DBusMessage *reply;
+ int err;
+
+ if (data->disconnect) {
+ reply = dbus_message_new_method_return(data->disconnect);
+ g_dbus_send_message(btd_get_dbus_connection(), reply);
+ dbus_message_unref(data->disconnect);
+ data->connect = NULL;
+ }
+
+ if (!data->connect)
+ return;
+
+ err = btd_service_get_error(data->service);
+
+ reply = btd_error_failed(data->connect, strerror(-err));
+ g_dbus_send_message(btd_get_dbus_connection(), reply);
+ dbus_message_unref(data->connect);
+ data->connect = NULL;
+}
+
+static void service_cb(struct btd_service *service,
+ btd_service_state_t old_state,
+ btd_service_state_t new_state,
+ void *user_data)
+{
+ struct service_data *data;
+
+ data = service_get_data(service);
+ if (!data)
+ return;
+
+ switch (new_state) {
+ case BTD_SERVICE_STATE_UNAVAILABLE:
+ data_remove(data);
+ return;
+ case BTD_SERVICE_STATE_CONNECTED:
+ service_connected(data);
+ break;
+ case BTD_SERVICE_STATE_DISCONNECTED:
+ service_disconnected(data);
+ break;
+ default:
+ break;
+ }
+
+ g_dbus_emit_property_changed(btd_get_dbus_connection(), data->path,
+ SERVICE_INTERFACE, "State");
+}
+
+static int service_init(void)
+{
+ DBG("");
+
+ service_id = btd_service_add_state_cb(service_cb, NULL);
+
+ return 0;
+}
+
+static void service_exit(void)
+{
+ DBG("");
+
+ btd_service_remove_state_cb(service_id);
+
+ g_slist_free_full(services, data_free);
+}
+
+BLUETOOTH_PLUGIN_DEFINE(service, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+ service_init, service_exit)
diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
index 96416b5e..ffb482b9 100644
--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
@@ -2071,8 +2071,12 @@ static void media_server_remove(struct btd_adapter *adapter)
static struct btd_profile a2dp_source_profile = {
.name = "a2dp-source",
.priority = BTD_PROFILE_PRIORITY_MEDIUM,
+ .version = 0x0103,
.remote_uuid = A2DP_SOURCE_UUID,
+ .local_uuid = A2DP_SINK_UUID,
+ .auth_uuid = ADVANCED_AUDIO_UUID,
+
.device_probe = a2dp_source_probe,
.device_remove = a2dp_source_remove,
@@ -2087,8 +2091,12 @@ static struct btd_profile a2dp_source_profile = {
static struct btd_profile a2dp_sink_profile = {
.name = "a2dp-sink",
.priority = BTD_PROFILE_PRIORITY_MEDIUM,
+ .version = 0x0103,
.remote_uuid = A2DP_SINK_UUID,
+ .local_uuid = A2DP_SOURCE_UUID,
+ .auth_uuid = ADVANCED_AUDIO_UUID,
+
.device_probe = a2dp_sink_probe,
.device_remove = a2dp_sink_remove,
diff --git a/profiles/audio/avctp.c b/profiles/audio/avctp.c
index 36804001..4514d69e 100644
--- a/profiles/audio/avctp.c
+++ b/profiles/audio/avctp.c
@@ -1351,11 +1351,11 @@ static void avctp_control_confirm(struct avctp *session, GIOChannel *chan,
#ifdef __TIZEN_PATCH__
session->auth_id = btd_request_authorization(src, dst,
AVRCP_TARGET_UUID,
- auth_cb, session);
+ auth_cb, session, 0);
#else
session->auth_id = btd_request_authorization(src, dst,
AVRCP_REMOTE_UUID,
- auth_cb, session);
+ auth_cb, session, 0);
#endif
if (session->auth_id == 0)
goto drop;
diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c
index f6d810eb..ef6979e6 100644
--- a/profiles/audio/avdtp.c
+++ b/profiles/audio/avdtp.c
@@ -2722,7 +2722,7 @@ static void avdtp_confirm_cb(GIOChannel *chan, gpointer data)
session->auth_id = btd_request_authorization(&src, &dst,
ADVANCED_AUDIO_UUID,
- auth_cb, session);
+ auth_cb, session, 0);
if (session->auth_id == 0) {
avdtp_set_state(session, AVDTP_SESSION_STATE_DISCONNECTED);
goto drop;
diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index f2817b77..90fd5d5f 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -4031,8 +4031,12 @@ done:
static struct btd_profile avrcp_target_profile = {
.name = "audio-avrcp-target",
+ .version = 0x0105,
.remote_uuid = AVRCP_TARGET_UUID,
+ .local_uuid = AVRCP_REMOTE_UUID,
+ .auth_uuid = AVRCP_REMOTE_UUID,
+
.device_probe = avrcp_target_probe,
.device_remove = avrcp_target_remove,
@@ -4114,8 +4118,12 @@ done:
static struct btd_profile avrcp_controller_profile = {
.name = "avrcp-controller",
+ .version = 0x0104,
.remote_uuid = AVRCP_REMOTE_UUID,
+ .local_uuid = AVRCP_TARGET_UUID,
+ .auth_uuid = AVRCP_REMOTE_UUID,
+
.device_probe = avrcp_controller_probe,
.device_remove = avrcp_controller_remove,
diff --git a/profiles/health/hdp_manager.c b/profiles/health/hdp_manager.c
index 1882043b..95ee7ac9 100644
--- a/profiles/health/hdp_manager.c
+++ b/profiles/health/hdp_manager.c
@@ -70,7 +70,10 @@ static void hdp_driver_remove(struct btd_service *service)
static struct btd_profile hdp_source_profile = {
.name = "hdp-source",
+ .version = 0x0100,
+
.remote_uuid = HDP_SOURCE_UUID,
+ .local_uuid = HDP_SINK_UUID,
.device_probe = hdp_driver_probe,
.device_remove = hdp_driver_remove,
@@ -81,7 +84,10 @@ static struct btd_profile hdp_source_profile = {
static struct btd_profile hdp_sink_profile = {
.name = "hdp-sink",
+ .version = 0x0100,
+
.remote_uuid = HDP_SINK_UUID,
+ .local_uuid = HDP_SOURCE_UUID,
.device_probe = hdp_driver_probe,
.device_remove = hdp_driver_remove,
diff --git a/profiles/input/device.c b/profiles/input/device.c
index cfa5e231..277f8a59 100644
--- a/profiles/input/device.c
+++ b/profiles/input/device.c
@@ -1341,8 +1341,29 @@ static gboolean property_get_reconnect_mode(
return TRUE;
}
+static gboolean property_get_connected(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct input_device *idev = data;
+ dbus_bool_t connected;
+
+ if (idev->service == NULL)
+ return FALSE;
+
+ if (btd_service_get_state(idev->service)
+ == BTD_SERVICE_STATE_CONNECTED) {
+ connected = true;
+ } else
+ connected = false;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &connected);
+
+ return TRUE;
+}
+
static const GDBusPropertyTable input_properties[] = {
{ "ReconnectMode", "s", property_get_reconnect_mode },
+ { "Connected", "b", property_get_connected },
{ }
};
diff --git a/profiles/input/manager.c b/profiles/input/manager.c
index 9712d2c8..cfc9f6a1 100644
--- a/profiles/input/manager.c
+++ b/profiles/input/manager.c
@@ -57,6 +57,8 @@ static void hid_server_remove(struct btd_profile *p,
static struct btd_profile input_profile = {
.name = "input-hid",
+ .version = 0x0101,
+
.local_uuid = HID_UUID,
.remote_uuid = HID_UUID,
diff --git a/profiles/input/server.c b/profiles/input/server.c
index 50a9074e..95f7eeb1 100644
--- a/profiles/input/server.c
+++ b/profiles/input/server.c
@@ -270,7 +270,7 @@ static void confirm_event_cb(GIOChannel *chan, gpointer user_data)
bacpy(&server->confirm->dst, &dst);
ret = btd_request_authorization(&src, &dst, HID_UUID,
- auth_callback, server);
+ auth_callback, server, 0);
if (ret != 0)
return;
diff --git a/profiles/network/manager.c b/profiles/network/manager.c
index 0fe98a04..81b0ce05 100644
--- a/profiles/network/manager.c
+++ b/profiles/network/manager.c
@@ -135,8 +135,10 @@ static void nap_server_remove(struct btd_profile *p,
static struct btd_profile panu_profile = {
.name = "network-panu",
+ .version = 0x0100,
.local_uuid = NAP_UUID,
.remote_uuid = PANU_UUID,
+ .auth_uuid = BNEP_SVC_UUID,
.device_probe = connection_register,
.device_remove = connection_unregister,
.connect = connection_connect,
@@ -147,8 +149,10 @@ static struct btd_profile panu_profile = {
static struct btd_profile gn_profile = {
.name = "network-gn",
+ .version = 0x0100,
.local_uuid = PANU_UUID,
.remote_uuid = GN_UUID,
+ .auth_uuid = BNEP_SVC_UUID,
.device_probe = connection_register,
.device_remove = connection_unregister,
.connect = connection_connect,
@@ -159,8 +163,10 @@ static struct btd_profile gn_profile = {
static struct btd_profile nap_profile = {
.name = "network-nap",
+ .version = 0x0100,
.local_uuid = PANU_UUID,
.remote_uuid = NAP_UUID,
+ .auth_uuid = BNEP_SVC_UUID,
.device_probe = connection_register,
.device_remove = connection_unregister,
.connect = connection_connect,
diff --git a/profiles/network/server.c b/profiles/network/server.c
index b0103711..a1b41268 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -325,7 +325,7 @@ static gboolean server_disconnected_cb(GIOChannel *chan,
{
struct network_server *ns = NULL;
struct network_session *session = NULL;
- char address[20] = {0};
+ char address[24] = {0};
const char* paddr = address;
char *name_str = NULL;
@@ -373,7 +373,7 @@ static gboolean bnep_setup(GIOChannel *chan,
GIOCondition cond, gpointer user_data)
{
struct network_adapter *na = user_data;
- struct network_server *ns;
+ struct network_server *ns = NULL;
uint8_t packet[BNEP_MTU];
struct bnep_setup_conn_req *req = (void *) packet;
uint16_t src_role, dst_role, rsp = BNEP_CONN_NOT_ALLOWED;
@@ -564,7 +564,7 @@ static void confirm_event(GIOChannel *chan, gpointer user_data)
na->setup->io = g_io_channel_ref(chan);
ret = btd_request_authorization(&src, &dst, BNEP_SVC_UUID,
- auth_cb, na);
+ auth_cb, na, 0);
if (ret == 0) {
error("Refusing connect from %s", address);
setup_destroy(na);
@@ -611,11 +611,26 @@ static void server_remove_sessions(struct network_server *ns)
for (list = ns->sessions; list; list = list->next) {
struct network_session *session = list->data;
+ char address[24] = {0};
+ char *paddr = address;
+ const char *name_str = NULL;
if (*session->dev == '\0')
continue;
bnep_server_delete(ns->bridge, session->dev, &session->dst);
+
+ name_str = session->dev;
+ ba2str(&session->dst, paddr);
+
+ DBG("send peerdisconnected signal");
+
+ g_dbus_emit_signal(btd_get_dbus_connection(),
+ adapter_get_path(ns->na->adapter),
+ NETWORK_SERVER_INTERFACE, "PeerDisconnected",
+ DBUS_TYPE_STRING, &name_str,
+ DBUS_TYPE_STRING, &paddr,
+ DBUS_TYPE_INVALID);
}
#ifndef __TIZEN_PATCH__
diff --git a/profiles/sap/server.c b/profiles/sap/server.c
index 20c6cab7..683d6f2b 100644
--- a/profiles/sap/server.c
+++ b/profiles/sap/server.c
@@ -1253,7 +1253,7 @@ static void connect_confirm_cb(GIOChannel *io, gpointer data)
ba2str(&dst, dstaddr);
ret = btd_request_authorization(&src, &dst, SAP_UUID, connect_auth_cb,
- server);
+ server, 0);
if (ret == 0) {
error("Authorization failure");
sap_server_remove_conn(server);
diff --git a/src/adapter.c b/src/adapter.c
index d7815e80..0066c768 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -173,6 +173,7 @@ struct service_auth {
struct btd_device *device;
struct btd_adapter *adapter;
struct agent *agent; /* NULL for queued auths */
+ int fd;
};
struct btd_adapter_pin_cb_iter {
@@ -7266,6 +7267,11 @@ static gboolean process_auth_queue(gpointer user_data)
if (auth->svc_id > 0)
return FALSE;
+ if (device_is_service_blocked(device, auth->uuid)) {
+ auth->cb(&err, auth->user_data);
+ goto next;
+ }
+
/* The below patch should be removed after we provide the API
* to control autorization for the specific UUID.
*/
@@ -7288,7 +7294,7 @@ static gboolean process_auth_queue(gpointer user_data)
dev_path = device_get_path(device);
if (agent_authorize_service(auth->agent, dev_path, auth->uuid,
- agent_auth_cb, adapter, NULL) < 0) {
+ agent_auth_cb, adapter, NULL, auth->fd) < 0) {
auth->cb(&err, auth->user_data);
goto next;
}
@@ -7324,7 +7330,7 @@ static void svc_complete(struct btd_device *dev, int err, void *user_data)
static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
const char *uuid, service_auth_cb cb,
- void *user_data)
+ void *user_data, int fd)
{
struct service_auth *auth;
struct btd_device *device;
@@ -7348,6 +7354,7 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
auth->device = device;
auth->adapter = adapter;
auth->id = ++id;
+ auth->fd = fd;
auth->svc_id = device_wait_for_svc_complete(device, svc_complete, auth);
g_queue_push_tail(adapter->auths, auth);
@@ -7357,7 +7364,7 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
guint btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst,
const char *uuid, service_auth_cb cb,
- void *user_data)
+ void *user_data, int fd)
{
struct btd_adapter *adapter;
GSList *l;
@@ -7367,7 +7374,7 @@ guint btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst,
if (!adapter)
return 0;
- return adapter_authorize(adapter, dst, uuid, cb, user_data);
+ return adapter_authorize(adapter, dst, uuid, cb, user_data, fd);
}
for (l = adapters; l != NULL; l = g_slist_next(l)) {
@@ -7375,7 +7382,7 @@ guint btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst,
adapter = l->data;
- id = adapter_authorize(adapter, dst, uuid, cb, user_data);
+ id = adapter_authorize(adapter, dst, uuid, cb, user_data, fd);
if (id != 0)
return id;
}
diff --git a/src/adapter.h b/src/adapter.h
index 8cb3009e..0069c4b3 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -127,7 +127,7 @@ void adapter_remove_profile(struct btd_adapter *adapter, gpointer p);
int btd_register_adapter_driver(struct btd_adapter_driver *driver);
void btd_unregister_adapter_driver(struct btd_adapter_driver *driver);
guint btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst,
- const char *uuid, service_auth_cb cb, void *user_data);
+ const char *uuid, service_auth_cb cb, void *user_data, int fd);
int btd_cancel_authorization(guint id);
int btd_adapter_restore_powered(struct btd_adapter *adapter);
diff --git a/src/agent.c b/src/agent.c
index 73b2fdd8..bd88eb9a 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -383,8 +383,9 @@ done:
static int agent_call_authorize_service(struct agent_request *req,
const char *device_path,
- const char *uuid)
+ const char *uuid, const int fd)
{
+ DBusMessageIter iter, dict;
struct agent *agent = req->agent;
req->msg = dbus_message_new_method_call(agent->owner, agent->path,
@@ -394,10 +395,14 @@ static int agent_call_authorize_service(struct agent_request *req,
return -ENOMEM;
}
- dbus_message_append_args(req->msg,
- DBUS_TYPE_OBJECT_PATH, &device_path,
- DBUS_TYPE_STRING, &uuid,
- DBUS_TYPE_INVALID);
+ dbus_message_iter_init_append(req->msg, &iter);
+
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+ &device_path);
+
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &uuid);
+
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_UNIX_FD, &fd);
if (g_dbus_send_message_with_reply(btd_get_dbus_connection(),
req->msg, &req->call,
@@ -412,7 +417,7 @@ static int agent_call_authorize_service(struct agent_request *req,
int agent_authorize_service(struct agent *agent, const char *path,
const char *uuid, agent_cb cb,
- void *user_data, GDestroyNotify destroy)
+ void *user_data, GDestroyNotify destroy, int fd)
{
struct agent_request *req;
int err;
@@ -423,7 +428,7 @@ int agent_authorize_service(struct agent *agent, const char *path,
req = agent_request_new(agent, AGENT_REQUEST_AUTHORIZE_SERVICE, cb,
user_data, destroy);
- err = agent_call_authorize_service(req, path, uuid);
+ err = agent_call_authorize_service(req, path, uuid, fd);
if (err < 0) {
agent_request_free(req, FALSE);
return -ENOMEM;
diff --git a/src/agent.h b/src/agent.h
index 1e469203..dafee9c4 100644
--- a/src/agent.h
+++ b/src/agent.h
@@ -40,7 +40,7 @@ struct agent *agent_get(const char *owner);
int agent_authorize_service(struct agent *agent, const char *path,
const char *uuid, agent_cb cb,
- void *user_data, GDestroyNotify destroy);
+ void *user_data, GDestroyNotify destroy, int fd);
int agent_request_pincode(struct agent *agent, struct btd_device *device,
agent_pincode_cb cb, gboolean secure,
diff --git a/src/bluetooth.conf b/src/bluetooth.conf
index 70d9aa60..b575f787 100644
--- a/src/bluetooth.conf
+++ b/src/bluetooth.conf
@@ -8,6 +8,8 @@
<!-- ../system.conf have denied everything, so we just punch some holes -->
<policy user="root">
+ <allow own="org.bluez"/>
+ <allow send_destination="org.bluez"/>
<allow own="org.projectx.bluetooth"/>
<allow send_interface="org.projectx.bluetooth"/>
<allow send_destination="org.projectx.bluetooth"/>
@@ -38,6 +40,7 @@
<allow own="org.bluez.Profile1"/>
<allow send_interface="org.bluez.Profile1"/>
<allow send_destination="org.bluez.Profile1"/>
+ <allow send_interface="org.freedesktop.DBus.ObjectManager"/>
</policy>
<policy at_console="true">
diff --git a/src/device.c b/src/device.c
index f98e4a6e..9a4f5f2c 100644
--- a/src/device.c
+++ b/src/device.c
@@ -383,7 +383,7 @@ static GSList *find_service_with_gatt_handles(GSList *list,
static void update_technologies(GKeyFile *file, struct btd_device *dev)
{
- const char *list[2];
+ const char *list[2] = {NULL, NULL};
size_t len = 0;
if (dev->bredr)
@@ -810,6 +810,34 @@ gboolean device_is_trusted(struct btd_device *device)
return device->trusted;
}
+bool device_is_service_blocked(struct btd_device *device, const char *uuid)
+{
+ GSList *l;
+ bool block = false;
+
+ for (l = device->services; l; l = g_slist_next(l)) {
+ struct btd_service *service = l->data;
+ struct btd_profile *p = btd_service_get_profile(service);
+ const char *p_uuid;
+
+ p_uuid = p->auth_uuid ? p->auth_uuid : p->local_uuid;
+ if (!p_uuid)
+ continue;
+
+ if (strcasecmp(uuid, p_uuid))
+ continue;
+
+ if (!btd_service_is_blocked(service))
+ return false;
+
+ block = true;
+ }
+
+ /* Every service matching is blocked
+ */
+ return block;
+}
+
static gboolean dev_property_get_address(const GDBusPropertyTable *property,
DBusMessageIter *iter, void *data)
{
@@ -1811,6 +1839,10 @@ static GSList *create_pending_list(struct btd_device *dev, const char *uuid)
for (l = dev->services; l != NULL; l = g_slist_next(l)) {
service = l->data;
+
+ if (!btd_service_get_auto_connect(service))
+ continue;
+
p = btd_service_get_profile(service);
#ifdef __TIZEN_PATCH__
diff --git a/src/device.h b/src/device.h
index cc4ab4e6..383f268e 100644
--- a/src/device.h
+++ b/src/device.h
@@ -106,6 +106,7 @@ bool device_is_bonded(struct btd_device *device, uint8_t bdaddr_type);
gboolean device_is_trusted(struct btd_device *device);
void device_set_paired(struct btd_device *dev, uint8_t bdaddr_type);
void device_set_unpaired(struct btd_device *dev, uint8_t bdaddr_type);
+bool device_is_service_blocked(struct btd_device *device, const char *uuid);
void btd_device_set_temporary(struct btd_device *device, gboolean temporary);
void btd_device_set_trusted(struct btd_device *device, gboolean trusted);
void device_set_bonded(struct btd_device *device, uint8_t bdaddr_type);
diff --git a/src/org.bluez.service b/src/org.bluez.service
index dd7ae8f1..2a3b0575 100644
--- a/src/org.bluez.service
+++ b/src/org.bluez.service
@@ -2,4 +2,4 @@
Name=org.bluez
Exec=/bin/false
User=root
-SystemdService=dbus-org.bluez.service
+SystemdService=bluetooth.service
diff --git a/src/profile.c b/src/profile.c
index 46349208..0874ecba 100644
--- a/src/profile.c
+++ b/src/profile.c
@@ -1253,6 +1253,7 @@ static void ext_confirm(GIOChannel *io, gpointer user_data)
GError *gerr = NULL;
bdaddr_t src, dst;
char addr[18];
+ int fd;
bt_io_get(io, &gerr,
BT_IO_OPT_SOURCE_BDADDR, &src,
@@ -1272,8 +1273,9 @@ static void ext_confirm(GIOChannel *io, gpointer user_data)
if (conn == NULL)
return;
+ fd = g_io_channel_unix_get_fd(conn->io);
conn->auth_id = btd_request_authorization(&src, &dst, uuid, ext_auth,
- conn);
+ conn, fd);
if (conn->auth_id == 0) {
error("%s authorization failure", ext->name);
ext_io_destroy(conn);
diff --git a/src/profile.h b/src/profile.h
index f5a3ded0..254d85e9 100644
--- a/src/profile.h
+++ b/src/profile.h
@@ -30,9 +30,11 @@ struct btd_service;
struct btd_profile {
const char *name;
int priority;
+ uint16_t version;
const char *local_uuid;
const char *remote_uuid;
+ const char *auth_uuid;
bool auto_connect;
diff --git a/src/service.c b/src/service.c
index 28e71693..8ecb7d42 100644
--- a/src/service.c
+++ b/src/service.c
@@ -36,6 +36,8 @@
#include <errno.h>
#include <bluetooth/bluetooth.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
#include <glib.h>
@@ -55,6 +57,8 @@ struct btd_service {
int err;
uint16_t start_handle;
uint16_t end_handle;
+ bool auto_connect;
+ bool blocked;
};
struct service_state_callback {
@@ -146,6 +150,7 @@ struct btd_service *service_create(struct btd_device *device,
service->ref = 1;
service->device = device; /* Weak ref */
service->profile = profile;
+ service->auto_connect = profile->auto_connect;
service->state = BTD_SERVICE_STATE_UNAVAILABLE;
return service;
@@ -325,6 +330,51 @@ int btd_service_get_error(const struct btd_service *service)
return service->err;
}
+uint16_t btd_service_get_version(const struct btd_service *service)
+{
+ const sdp_record_t *rec;
+ sdp_list_t *list;
+ sdp_profile_desc_t *desc;
+ uint16_t version;
+
+ if (!service->profile->version)
+ return 0;
+
+ rec = btd_device_get_record(service->device,
+ service->profile->remote_uuid);
+ if (rec == NULL)
+ return 0;
+
+ if (sdp_get_profile_descs(rec, &list) < 0)
+ return 0;
+
+ desc = list->data;
+ version = desc->version;
+ sdp_list_free(list, free);
+
+ return MIN(version, service->profile->version);
+}
+
+void btd_service_set_auto_connect(struct btd_service *service, bool value)
+{
+ service->auto_connect = value;
+}
+
+bool btd_service_get_auto_connect(const struct btd_service *service)
+{
+ return service->auto_connect;
+}
+
+void btd_service_set_blocked(struct btd_service *service, bool value)
+{
+ service->blocked = value;
+}
+
+bool btd_service_is_blocked(const struct btd_service *service)
+{
+ return service->blocked;
+}
+
bool btd_service_get_gatt_handles(const struct btd_service *service,
uint16_t *start_handle,
uint16_t *end_handle)
diff --git a/src/service.h b/src/service.h
index 3a0db6ee..d092cc48 100644
--- a/src/service.h
+++ b/src/service.h
@@ -63,6 +63,11 @@ struct btd_device *btd_service_get_device(const struct btd_service *service);
struct btd_profile *btd_service_get_profile(const struct btd_service *service);
btd_service_state_t btd_service_get_state(const struct btd_service *service);
int btd_service_get_error(const struct btd_service *service);
+uint16_t btd_service_get_version(const struct btd_service *service);
+void btd_service_set_auto_connect(struct btd_service *service, bool value);
+bool btd_service_get_auto_connect(const struct btd_service *service);
+void btd_service_set_blocked(struct btd_service *service, bool value);
+bool btd_service_is_blocked(const struct btd_service *service);
bool btd_service_get_gatt_handles(const struct btd_service *service,
uint16_t *start_handle,
uint16_t *end_handle);
diff --git a/tools/bluetooth-player.c b/tools/bluetooth-player.c
index f10d9be5..f090e1b1 100644
--- a/tools/bluetooth-player.c
+++ b/tools/bluetooth-player.c
@@ -654,6 +654,7 @@ static void cmd_show(int argc, char *argv[])
rl_printf("Player %s\n", g_dbus_proxy_get_path(proxy));
print_property(proxy, "Name");
+ print_property(proxy, "Searchable");
print_property(proxy, "Repeat");
print_property(proxy, "Equalizer");
print_property(proxy, "Shuffle");
diff --git a/tools/hciattach.c b/tools/hciattach.c
index db11f9a9..3535faa7 100644
--- a/tools/hciattach.c
+++ b/tools/hciattach.c
@@ -1530,7 +1530,7 @@ int main(int argc, char *argv[])
dev[0] = 0;
if (!strchr(opt, '/'))
strcpy(dev, "/dev/");
- strcat(dev, opt);
+ strncat(dev, opt, PATH_MAX);
break;
case 1:
diff --git a/tools/hcitool.c b/tools/hcitool.c
index 648a0f7d..2c84dc7d 100644
--- a/tools/hcitool.c
+++ b/tools/hcitool.c
@@ -2404,7 +2404,9 @@ failed:
static int print_advertising_devices(int dd, uint8_t filter_type)
{
- unsigned char buf[HCI_MAX_EVENT_SIZE], *ptr;
+ unsigned char buf_array[HCI_MAX_EVENT_SIZE+1] = {0};
+ unsigned char *buf = buf_array;
+ unsigned char *ptr = NULL;
struct hci_filter nf, of;
struct sigaction sa;
socklen_t olen;
@@ -2431,11 +2433,14 @@ static int print_advertising_devices(int dd, uint8_t filter_type)
sigaction(SIGINT, &sa, NULL);
while (1) {
- evt_le_meta_event *meta;
- le_advertising_info *info;
- char addr[18];
+ evt_le_meta_event *meta = NULL;
+ le_advertising_info *info = NULL;
+ char addr_array[18];
+ char *addr = addr_array;
+
+ buf[HCI_MAX_EVENT_SIZE] = 0;
- while ((len = read(dd, buf, sizeof(buf))) < 0) {
+ while ((len = read(dd, buf, HCI_MAX_EVENT_SIZE)) < 0) {
if (errno == EINTR && signal_received == SIGINT) {
len = 0;
goto done;
@@ -2457,14 +2462,16 @@ static int print_advertising_devices(int dd, uint8_t filter_type)
/* Ignoring multiple reports */
info = (le_advertising_info *) (meta->data + 1);
if (check_report_filter(filter_type, info)) {
- char name[30];
+ char name_array[30];
+ char *name = name_array;
- memset(name, 0, sizeof(name));
+ memset(name, 0, 30);
ba2str(&info->bdaddr, addr);
eir_parse_name(info->data, info->length,
- name, sizeof(name) - 1);
+ name, 29);
+ name[29] = '\0';
printf("%s %s\n", addr, name);
}
}