Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH 5/5] device: Retrieve device pnp ids from storage
From: Frédéric Danis @ 2012-11-21 13:49 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1353505791-21134-1-git-send-email-frederic.danis@linux.intel.com>

When device pnp ids are updated, save them and emit property
changed signals.
---
 src/device.c |   51 ++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 34 insertions(+), 17 deletions(-)

diff --git a/src/device.c b/src/device.c
index d4a553d..4559674 100644
--- a/src/device.c
+++ b/src/device.c
@@ -236,6 +236,17 @@ static gboolean store_device_info_cb(gpointer user_data)
 	g_key_file_set_boolean(key_file, "General", "Blocked",
 							device->blocked);
 
+	if (device->vendor_src) {
+		g_key_file_set_integer(key_file, "DeviceID", "Source",
+					device->vendor_src);
+		g_key_file_set_integer(key_file, "DeviceID", "Vendor",
+					device->vendor);
+		g_key_file_set_integer(key_file, "DeviceID", "Product",
+					device->product);
+		g_key_file_set_integer(key_file, "DeviceID", "Version",
+					device->version);
+	}
+
 	ba2str(adapter_get_address(device->adapter), adapter_addr);
 	ba2str(&device->bdaddr, device_addr);
 	snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", adapter_addr,
@@ -1766,6 +1777,7 @@ static void load_info(struct btd_device *device, const gchar *local,
 	char *str;
 	gboolean store_needed = FALSE;
 	gboolean blocked;
+	int source, vendor, product, version;
 
 	snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", local, peer);
 	filename[PATH_MAX] = '\0';
@@ -1811,6 +1823,24 @@ static void load_info(struct btd_device *device, const gchar *local,
 	if (blocked)
 		device_block(device, FALSE);
 
+	/* Load device id */
+	source = g_key_file_get_integer(key_file, "DeviceID", "Source", NULL);
+	if (source) {
+		device_set_vendor_src(device, source);
+
+		vendor = g_key_file_get_integer(key_file, "DeviceID",
+							"Vendor", NULL);
+		device_set_vendor(device, vendor);
+
+		product = g_key_file_get_integer(key_file, "DeviceID",
+							"Product", NULL);
+		device_set_product(device, product);
+
+		version = g_key_file_get_integer(key_file, "DeviceID",
+							"Version", NULL);
+		device_set_version(device, version);
+	}
+
 	if (store_needed)
 		store_device_info(device);
 
@@ -1825,7 +1855,6 @@ struct btd_device *device_create(struct btd_adapter *adapter,
 	const gchar *adapter_path = adapter_get_path(adapter);
 	const bdaddr_t *src;
 	char srcaddr[18];
-	uint16_t vendor, product, version;
 
 	device = g_try_malloc0(sizeof(struct btd_device));
 	if (device == NULL)
@@ -1867,13 +1896,6 @@ struct btd_device *device_create(struct btd_adapter *adapter,
 		device_set_bonded(device, TRUE);
 	}
 
-	if (read_device_id(srcaddr, address, bdaddr_type, NULL, &vendor,
-						&product, &version) == 0) {
-		device_set_vendor(device, vendor);
-		device_set_product(device, product);
-		device_set_version(device, version);
-	}
-
 	return btd_device_ref(device);
 }
 
@@ -2320,22 +2342,15 @@ static void update_bredr_services(struct browse_req *req, sdp_list_t *recs)
 			pdlist = sdp_data_get(rec, SDP_ATTR_VENDOR_ID);
 			vendor = pdlist ? pdlist->val.uint16 : 0x0000;
 
-			device_set_vendor(device, vendor);
-
 			pdlist = sdp_data_get(rec, SDP_ATTR_PRODUCT_ID);
 			product = pdlist ? pdlist->val.uint16 : 0x0000;
 
-			device_set_product(device, product);
-
 			pdlist = sdp_data_get(rec, SDP_ATTR_VERSION);
 			version = pdlist ? pdlist->val.uint16 : 0x0000;
 
-			device_set_version(device, version);
-
 			if (source || vendor || product || version)
-				store_device_id(srcaddr, dstaddr,
-						device->bdaddr_type, source,
-						vendor, product, version);
+				device_set_pnpid(device, source, vendor,
+							product, version);
 		}
 
 		/* Check for duplicates */
@@ -4094,4 +4109,6 @@ void device_set_pnpid(struct btd_device *device, uint8_t vendor_id_src,
 	device_set_vendor_src(device, vendor_id_src);
 	device_set_product(device, product_id);
 	device_set_version(device, product_ver);
+
+	store_device_info(device);
 }
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 4/5] adapter: Convert storage did file
From: Frédéric Danis @ 2012-11-21 13:49 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1353505791-21134-1-git-send-email-frederic.danis@linux.intel.com>

---
 src/adapter.c |   42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index 3dafacb..0d1dfea 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2548,6 +2548,45 @@ static void convert_blocked_entry(GKeyFile *key_file, void *value)
 	g_key_file_set_boolean(key_file, "General", "Blocked", TRUE);
 }
 
+static void convert_did_entry(GKeyFile *key_file, void *value)
+{
+	char *vendor_str, *product_str, *version_str;
+	uint16_t val;
+
+	vendor_str = strchr(value, ' ');
+	if (!vendor_str)
+		return;
+
+	*(vendor_str++) = 0;
+
+	if (g_str_equal(value, "FFFF"))
+		return;
+
+	product_str = strchr(vendor_str, ' ');
+	if (!product_str)
+		return;
+
+	*(product_str++) = 0;
+
+	version_str = strchr(product_str, ' ');
+	if (!version_str)
+		return;
+
+	*(version_str++) = 0;
+
+	val = (uint16_t) strtol(value, NULL, 16);
+	g_key_file_set_integer(key_file, "DeviceID", "Source", val);
+
+	val = (uint16_t) strtol(vendor_str, NULL, 16);
+	g_key_file_set_integer(key_file, "DeviceID", "Vendor", val);
+
+	val = (uint16_t) strtol(product_str, NULL, 16);
+	g_key_file_set_integer(key_file, "DeviceID", "Product", val);
+
+	val = (uint16_t) strtol(version_str, NULL, 16);
+	g_key_file_set_integer(key_file, "DeviceID", "Version", val);
+}
+
 static void convert_entry(char *key, char *value, void *user_data)
 {
 	struct device_converter *converter = user_data;
@@ -2633,6 +2672,9 @@ static void convert_device_storage(struct btd_adapter *adapter)
 
 	/* Convert blocked */
 	convert_file("blocked", address, convert_blocked_entry);
+
+	/* Convert device ids */
+	convert_file("did", address, convert_did_entry);
 }
 
 static void convert_config(struct btd_adapter *adapter, const char *filename,
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 3/5] device: Retrieve device blocked from storage
From: Frédéric Danis @ 2012-11-21 13:49 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1353505791-21134-1-git-send-email-frederic.danis@linux.intel.com>

---
 src/device.c |   22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/src/device.c b/src/device.c
index 915b0f8..d4a553d 100644
--- a/src/device.c
+++ b/src/device.c
@@ -233,6 +233,9 @@ static gboolean store_device_info_cb(gpointer user_data)
 	g_key_file_set_boolean(key_file, "General", "Trusted",
 							device->trusted);
 
+	g_key_file_set_boolean(key_file, "General", "Blocked",
+							device->blocked);
+
 	ba2str(adapter_get_address(device->adapter), adapter_addr);
 	ba2str(&device->bdaddr, device_addr);
 	snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", adapter_addr,
@@ -920,10 +923,7 @@ int device_block(struct btd_device *device, gboolean update_only)
 
 	device->blocked = TRUE;
 
-	err = write_blocked(adapter_get_address(device->adapter),
-				&device->bdaddr, device->bdaddr_type, TRUE);
-	if (err < 0)
-		error("write_blocked(): %s (%d)", strerror(-err), -err);
+	store_device_info(device);
 
 	device_set_temporary(device, FALSE);
 
@@ -950,10 +950,7 @@ int device_unblock(struct btd_device *device, gboolean silent,
 
 	device->blocked = FALSE;
 
-	err = write_blocked(adapter_get_address(device->adapter),
-				&device->bdaddr, device->bdaddr_type, FALSE);
-	if (err < 0)
-		error("write_blocked(): %s (%d)", strerror(-err), -err);
+	store_device_info(device);
 
 	if (!silent) {
 		g_dbus_emit_property_changed(btd_get_dbus_connection(),
@@ -1768,6 +1765,7 @@ static void load_info(struct btd_device *device, const gchar *local,
 	GKeyFile *key_file;
 	char *str;
 	gboolean store_needed = FALSE;
+	gboolean blocked;
 
 	snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", local, peer);
 	filename[PATH_MAX] = '\0';
@@ -1808,6 +1806,11 @@ static void load_info(struct btd_device *device, const gchar *local,
 	device->trusted = g_key_file_get_boolean(key_file, "General",
 							"Trusted", NULL);
 
+	/* Load device blocked */
+	blocked = g_key_file_get_boolean(key_file, "General", "Blocked", NULL);
+	if (blocked)
+		device_block(device, FALSE);
+
 	if (store_needed)
 		store_device_info(device);
 
@@ -1852,9 +1855,6 @@ struct btd_device *device_create(struct btd_adapter *adapter,
 
 	load_info(device, srcaddr, address);
 
-	if (read_blocked(src, &device->bdaddr, device->bdaddr_type))
-		device_block(device, FALSE);
-
 	if (read_link_key(src, &device->bdaddr, device->bdaddr_type, NULL,
 								NULL) == 0) {
 		device_set_paired(device, TRUE);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 2/5] adapter: Convert storage device blocked
From: Frédéric Danis @ 2012-11-21 13:49 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1353505791-21134-1-git-send-email-frederic.danis@linux.intel.com>

An entry exists in blocked file only when a device is blocked.
So, we do not need to check entry value and set device (entry key) as
blocked.
---
 src/adapter.c |    8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index 0f6a078..3dafacb 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2543,6 +2543,11 @@ static void convert_classes_entry(GKeyFile *key_file, void *value)
 	g_key_file_set_string(key_file, "General", "Class", value);
 }
 
+static void convert_blocked_entry(GKeyFile *key_file, void *value)
+{
+	g_key_file_set_boolean(key_file, "General", "Blocked", TRUE);
+}
+
 static void convert_entry(char *key, char *value, void *user_data)
 {
 	struct device_converter *converter = user_data;
@@ -2625,6 +2630,9 @@ static void convert_device_storage(struct btd_adapter *adapter)
 
 	/* Convert classes */
 	convert_file("classes", address, convert_classes_entry);
+
+	/* Convert blocked */
+	convert_file("blocked", address, convert_blocked_entry);
 }
 
 static void convert_config(struct btd_adapter *adapter, const char *filename,
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 1/5] doc: Update settings-storage.txt
From: Frédéric Danis @ 2012-11-21 13:49 UTC (permalink / raw)
  To: linux-bluetooth

Remote features are not available from user space,
so replace Features entry by SupportedTechnologies.

Device blocked should be saved in device info file.
---
 doc/settings-storage.txt |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/doc/settings-storage.txt b/doc/settings-storage.txt
index 1174d44..3fdcb03 100644
--- a/doc/settings-storage.txt
+++ b/doc/settings-storage.txt
@@ -139,13 +139,16 @@ Long term key) related to a remote device.
   Class			String		Device class in hexadecimal,
 					i.e. 0x000000
 
-  Features		String		Bluetooth device features in
-					hexadecimal, i.e. 0x0000000000000000
+  SupportedTechnologies	List of		List of technologies supported by
+			strings		device, separated by ";"
+					Technologies can be BR/EDR or LE
 
   AddressType		String		An address can be "static" or "public"
 
   Trusted		Boolean		True if the remote device is trusted
 
+  Blocked		Boolean		True if the remote device is blocked
+
   Profiles		List of		List of profiles advertised by remote,
 			strings		in 128-bits UUID format, separated by
 					";"
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH] Bluetooth:  Provide definitions for CSA2 audio commands
From: Michael Knudsen @ 2012-11-21 13:22 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michael Knudsen

---
 lib/hci.c |    9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/lib/hci.c b/lib/hci.c
index 66b2d5f..fd27f1a 100644
--- a/lib/hci.c
+++ b/lib/hci.c
@@ -590,6 +590,15 @@ static hci_map commands_map[] = {
 	{ "LE Test End",				230 },
 	{ "Reserved",					231 },
 
+	{ "Reserved",						232 },
+	{ "Reserved",						233 },
+	{ "Reserved",						234 },
+	{ "Enhanced Setup Synchronous Connection",		235 },
+	{ "Enhanced Accept Synchronous Connection Request",	236 },
+	{ "Read Local Supported Codecs",			237 },
+	{ "Reserved",						238 },
+	{ "Reserved",						239 },
+
 	{ NULL }
 };
 
-- 
1.7.9.5


^ permalink raw reply related

* Re: [PATCH BlueZ 1/6] core: Fix connection order of Device.Connect
From: Johan Hedberg @ 2012-11-21 12:37 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1353499818-10153-1-git-send-email-luiz.dentz@gmail.com>

Hi Luiz,

On Wed, Nov 21, 2012, Luiz Augusto von Dentz wrote:
> We should with higher priority first.
> ---
>  src/device.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

All patches in this set have been applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH v3] neard: Set device class in device object
From: Johan Hedberg @ 2012-11-21 12:34 UTC (permalink / raw)
  To: Frédéric Danis; +Cc: linux-bluetooth
In-Reply-To: <1353499163-18479-1-git-send-email-frederic.danis@linux.intel.com>

Hi Frederic,

On Wed, Nov 21, 2012, Frédéric Danis wrote:
> As soon as we have info related to a new device,
> device object will be created if it does not exist yet.
> 
> Change check_device() to use this device object and
> remove call to adapter_remove_device() in it.
> ---
>  plugins/neard.c |   32 +++++++++++++++-----------------
>  1 file changed, 15 insertions(+), 17 deletions(-)

Applied. Thanks.

Johan

^ permalink raw reply

* [PATCH BlueZ 6/6] control: Add profile .connect and .disconnect
From: Luiz Augusto von Dentz @ 2012-11-21 12:10 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1353499818-10153-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Add the connection and disconnection hooks to the avrcp btd_profile.
---
 profiles/audio/manager.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/profiles/audio/manager.c b/profiles/audio/manager.c
index dad46a9..714489a 100644
--- a/profiles/audio/manager.c
+++ b/profiles/audio/manager.c
@@ -318,6 +318,62 @@ static int a2dp_sink_disconnect(struct btd_device *dev,
 	return 0;
 }
 
+static int avrcp_control_connect(struct btd_device *dev,
+						struct btd_profile *profile,
+						btd_profile_cb cb)
+{
+	const gchar *path = device_get_path(dev);
+	struct audio_device *audio_dev;
+	struct profile_req *req;
+	int err;
+
+	DBG("path %s", path);
+
+	audio_dev = get_audio_dev(dev);
+	if (!audio_dev) {
+		DBG("unable to get a device object");
+		return -1;
+	}
+
+	req = new_profile_request(dev, profile, cb);
+
+	err = control_connect(audio_dev, profile_cb, req);
+	if (err < 0) {
+		g_free(req);
+		return err;
+	}
+
+	return 0;
+}
+
+static int avrcp_control_disconnect(struct btd_device *dev,
+						struct btd_profile *profile,
+						btd_profile_cb cb)
+{
+	const gchar *path = device_get_path(dev);
+	struct audio_device *audio_dev;
+	struct profile_req *req;
+	int err;
+
+	DBG("path %s", path);
+
+	audio_dev = get_audio_dev(dev);
+	if (!audio_dev) {
+		DBG("unable to get a device object");
+		return -1;
+	}
+
+	req = new_profile_request(dev, profile, cb);
+
+	err = control_disconnect(audio_dev, profile_cb, req);
+	if (err < 0) {
+		g_free(req);
+		return err;
+	}
+
+	return 0;
+}
+
 static struct audio_adapter *audio_adapter_ref(struct audio_adapter *adp)
 {
 	adp->ref++;
@@ -506,6 +562,10 @@ static struct btd_profile avrcp_profile = {
 	.device_probe	= avrcp_probe,
 	.device_remove	= audio_remove,
 
+	.auto_connect	= true,
+	.connect	= avrcp_control_connect,
+	.disconnect	= avrcp_control_disconnect,
+
 	.adapter_probe	= avrcp_server_probe,
 	.adapter_remove = avrcp_server_remove,
 };
-- 
1.7.11.7


^ permalink raw reply related

* [PATCH BlueZ 5/6] control: Expose internal connection API
From: Luiz Augusto von Dentz @ 2012-11-21 12:10 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1353499818-10153-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Separate the D-Bus code from the internal connection handling code,
exposing an internal API in case some internal codepath/plugin is
interested in using it.
---
 profiles/audio/control.c | 118 ++++++++++++++++++++++++++++++++++++-----------
 profiles/audio/control.h |   4 ++
 2 files changed, 96 insertions(+), 26 deletions(-)

diff --git a/profiles/audio/control.c b/profiles/audio/control.c
index 1620128..b2bfb0a 100644
--- a/profiles/audio/control.c
+++ b/profiles/audio/control.c
@@ -61,12 +61,28 @@
 
 static unsigned int avctp_id = 0;
 
+struct pending_request {
+	audio_device_cb cb;
+	void *data;
+	unsigned int id;
+};
+
 struct control {
 	struct avctp *session;
 	gboolean target;
-	DBusMessage *connect;
+	struct pending_request *connect;
 };
 
+static void pending_request_free(struct audio_device *dev,
+					struct pending_request *pending,
+					int err)
+{
+	if (pending->cb)
+		pending->cb(dev, err, pending->data);
+
+	g_free(pending);
+}
+
 static void state_changed(struct audio_device *dev, avctp_state_t old_state,
 				avctp_state_t new_state, void *user_data)
 {
@@ -79,11 +95,7 @@ static void state_changed(struct audio_device *dev, avctp_state_t old_state,
 		control->session = NULL;
 
 		if (control->connect) {
-			DBusMessage *reply = btd_error_failed(control->connect,
-							"Unable to connect");
-
-			g_dbus_send_message(btd_get_dbus_connection(), reply);
-			dbus_message_unref(control->connect);
+			pending_request_free(dev, control->connect, -EIO);
 			control->connect = NULL;
 		}
 
@@ -105,9 +117,7 @@ static void state_changed(struct audio_device *dev, avctp_state_t old_state,
 		break;
 	case AVCTP_STATE_CONNECTED:
 		if (control->connect) {
-			g_dbus_send_reply(conn, control->connect,
-							DBUS_TYPE_INVALID);
-			dbus_message_unref(control->connect);
+			pending_request_free(dev, control->connect, 0);
 			control->connect = NULL;
 		}
 
@@ -143,41 +153,97 @@ static DBusMessage *control_is_connected(DBusConnection *conn,
 	return reply;
 }
 
-static DBusMessage *control_connect(DBusConnection *conn, DBusMessage *msg,
-								void *data)
+int control_connect(struct audio_device *dev, audio_device_cb cb, void *data)
 {
-	struct audio_device *device = data;
-	struct control *control = device->control;
+	struct control *control = dev->control;
+	struct pending_request *pending;
 
 	if (control->session)
-		return btd_error_already_connected(msg);
+		return -EALREADY;
 
 	if (!control->target)
-		return btd_error_not_supported(msg);
+		return -ENOTSUP;
 
 	if (control->connect)
-		return btd_error_in_progress(msg);
+		return -EINPROGRESS;
 
-	control->session = avctp_connect(&device->src, &device->dst);
+	control->session = avctp_connect(&dev->src, &dev->dst);
 	if (!control->session)
-		return btd_error_failed(msg, "Unable to connect");
+		return -EIO;
 
-	control->connect = dbus_message_ref(msg);
+	pending = g_new0(struct pending_request, 1);
+	pending->cb = cb;
+	pending->data = data;
+	control->connect = pending;
 
-	return NULL;
+	return 0;
 }
 
-static DBusMessage *control_disconnect(DBusConnection *conn, DBusMessage *msg,
+static void generic_cb(struct audio_device *dev, int err, void *data)
+{
+	DBusMessage *msg = data;
+	DBusMessage *reply;
+
+	if (err < 0) {
+		reply = btd_error_failed(msg, strerror(-err));
+		g_dbus_send_message(btd_get_dbus_connection(), reply);
+		dbus_message_unref(msg);
+		return;
+	}
+
+	g_dbus_send_reply(btd_get_dbus_connection(), msg, DBUS_TYPE_INVALID);
+
+	dbus_message_unref(msg);
+}
+
+static DBusMessage *connect_control(DBusConnection *conn, DBusMessage *msg,
 								void *data)
 {
 	struct audio_device *device = data;
-	struct control *control = device->control;
+	int err;
+
+	err = control_connect(device, generic_cb, msg);
+	if (err < 0)
+		return btd_error_failed(msg, strerror(-err));
+
+	dbus_message_ref(msg);
+
+	return NULL;
+}
+
+int control_disconnect(struct audio_device *dev, audio_device_cb cb,
+								void *data)
+{
+	struct control *control = dev->control;
 
 	if (!control->session)
-		return btd_error_not_connected(msg);
+		return -ENOTCONN;
+
+	/* cancel pending connect */
+	if (control->connect) {
+		pending_request_free(dev, control->connect, -ECANCELED);
+		control->connect = NULL;
+	}
 
 	avctp_disconnect(control->session);
 
+	if (cb)
+		cb(dev, 0, data);
+
+	return 0;
+
+}
+
+static DBusMessage *disconnect_control(DBusConnection *conn, DBusMessage *msg,
+								void *data)
+{
+	struct audio_device *device = data;
+	int err;
+
+	err = control_disconnect(device, NULL, NULL);
+	if (err < 0)
+		return btd_error_failed(msg, strerror(-err));
+
 	return dbus_message_new_method_return(msg);
 }
 
@@ -259,8 +325,8 @@ static const GDBusMethodTable control_methods[] = {
 	{ GDBUS_DEPRECATED_METHOD("IsConnected",
 				NULL, GDBUS_ARGS({ "connected", "b" }),
 				control_is_connected) },
-	{ GDBUS_ASYNC_METHOD("Connect", NULL, NULL, control_connect) },
-	{ GDBUS_METHOD("Disconnect", NULL, NULL, control_disconnect) },
+	{ GDBUS_ASYNC_METHOD("Connect", NULL, NULL, connect_control) },
+	{ GDBUS_METHOD("Disconnect", NULL, NULL, disconnect_control) },
 	{ GDBUS_METHOD("Play", NULL, NULL, control_play) },
 	{ GDBUS_METHOD("Pause", NULL, NULL, control_pause) },
 	{ GDBUS_METHOD("Stop", NULL, NULL, control_stop) },
@@ -294,7 +360,7 @@ static void path_unregister(void *data)
 		avctp_disconnect(control->session);
 
 	if (control->connect)
-		dbus_message_unref(control->connect);
+		pending_request_free(dev, control->connect, -ECANCELED);
 
 	g_free(control);
 	dev->control = NULL;
diff --git a/profiles/audio/control.h b/profiles/audio/control.h
index 5f4f728..800a151 100644
--- a/profiles/audio/control.h
+++ b/profiles/audio/control.h
@@ -28,3 +28,7 @@ struct control *control_init(struct audio_device *dev, GSList *uuids);
 void control_update(struct control *control, GSList *uuids);
 void control_unregister(struct audio_device *dev);
 gboolean control_is_active(struct audio_device *dev);
+
+int control_connect(struct audio_device *dev, audio_device_cb cb, void *data);
+int control_disconnect(struct audio_device *dev, audio_device_cb cb,
+								void *data);
-- 
1.7.11.7


^ permalink raw reply related

* [PATCH BlueZ 4/6] sink: Add profile .connect and .disconnect
From: Luiz Augusto von Dentz @ 2012-11-21 12:10 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1353499818-10153-1-git-send-email-luiz.dentz@gmail.com>

From: Mikel Astiz <mikel.astiz@bmw-carit.de>

Add the connection and disconnection hooks to the a2dp_sink btd_profile.
---
 profiles/audio/manager.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/profiles/audio/manager.c b/profiles/audio/manager.c
index eaae018..dad46a9 100644
--- a/profiles/audio/manager.c
+++ b/profiles/audio/manager.c
@@ -262,6 +262,62 @@ static int a2dp_source_disconnect(struct btd_device *dev,
 	return 0;
 }
 
+static int a2dp_sink_connect(struct btd_device *dev,
+						struct btd_profile *profile,
+						btd_profile_cb cb)
+{
+	const gchar *path = device_get_path(dev);
+	struct audio_device *audio_dev;
+	struct profile_req *req;
+	int err;
+
+	DBG("path %s", path);
+
+	audio_dev = get_audio_dev(dev);
+	if (!audio_dev) {
+		DBG("unable to get a device object");
+		return -1;
+	}
+
+	req = new_profile_request(dev, profile, cb);
+
+	err = sink_connect(audio_dev, profile_cb, req);
+	if (err < 0) {
+		g_free(req);
+		return err;
+	}
+
+	return 0;
+}
+
+static int a2dp_sink_disconnect(struct btd_device *dev,
+						struct btd_profile *profile,
+						btd_profile_cb cb)
+{
+	const gchar *path = device_get_path(dev);
+	struct audio_device *audio_dev;
+	struct profile_req *req;
+	int err;
+
+	DBG("path %s", path);
+
+	audio_dev = get_audio_dev(dev);
+	if (!audio_dev) {
+		DBG("unable to get a device object");
+		return -1;
+	}
+
+	req = new_profile_request(dev, profile, cb);
+
+	err = sink_disconnect(audio_dev, FALSE, profile_cb, req);
+	if (err < 0) {
+		g_free(req);
+		return err;
+	}
+
+	return 0;
+}
+
 static struct audio_adapter *audio_adapter_ref(struct audio_adapter *adp)
 {
 	adp->ref++;
@@ -436,6 +492,10 @@ static struct btd_profile a2dp_sink_profile = {
 	.device_probe	= a2dp_sink_probe,
 	.device_remove	= audio_remove,
 
+	.auto_connect	= true,
+	.connect	= a2dp_sink_connect,
+	.disconnect	= a2dp_sink_disconnect,
+
 	.adapter_probe	= a2dp_sink_server_probe,
 };
 
-- 
1.7.11.7


^ permalink raw reply related

* [PATCH BlueZ 3/6] source: Add profile .connect and .disconnect
From: Luiz Augusto von Dentz @ 2012-11-21 12:10 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1353499818-10153-1-git-send-email-luiz.dentz@gmail.com>

From: Mikel Astiz <mikel.astiz@bmw-carit.de>

Add the connection and disconnection hooks to the a2dp_source
btd_profile.
---
 profiles/audio/manager.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)

diff --git a/profiles/audio/manager.c b/profiles/audio/manager.c
index 2f36efd..eaae018 100644
--- a/profiles/audio/manager.c
+++ b/profiles/audio/manager.c
@@ -74,6 +74,12 @@ struct audio_adapter {
 	gint ref;
 };
 
+struct profile_req {
+	struct btd_device	*device;
+	struct btd_profile	*profile;
+	btd_profile_cb		cb;
+};
+
 static gboolean auto_connect = TRUE;
 static int max_connected_headsets = 1;
 static GKeyFile *config = NULL;
@@ -176,6 +182,86 @@ static int avrcp_probe(struct btd_profile *p, struct btd_device *device,
 	return 0;
 }
 
+static struct profile_req *new_profile_request(struct btd_device *dev,
+						struct btd_profile *profile,
+						btd_profile_cb cb)
+{
+	struct profile_req *req;
+
+	req  = g_new0(struct profile_req, 1);
+	req->device = dev;
+	req->profile = profile;
+	req->cb = cb;
+
+	return req;
+}
+
+static void profile_cb(struct audio_device *dev, int err, void *data)
+{
+	struct profile_req *req = data;
+
+	if (req->cb)
+		req->cb(req->profile, req->device, err);
+
+	g_free(req);
+}
+
+static int a2dp_source_connect(struct btd_device *dev,
+						struct btd_profile *profile,
+						btd_profile_cb cb)
+{
+	const gchar *path = device_get_path(dev);
+	struct audio_device *audio_dev;
+	struct profile_req *req;
+	int err;
+
+	DBG("path %s", path);
+
+	audio_dev = get_audio_dev(dev);
+	if (!audio_dev) {
+		DBG("unable to get a device object");
+		return -1;
+	}
+
+	req = new_profile_request(dev, profile, cb);
+
+	err = source_connect(audio_dev, profile_cb, req);
+	if (err < 0) {
+		g_free(req);
+		return err;
+	}
+
+	return 0;
+}
+
+static int a2dp_source_disconnect(struct btd_device *dev,
+						struct btd_profile *profile,
+						btd_profile_cb cb)
+{
+	const gchar *path = device_get_path(dev);
+	struct audio_device *audio_dev;
+	struct profile_req *req;
+	int err;
+
+	DBG("path %s", path);
+
+	audio_dev = get_audio_dev(dev);
+	if (!audio_dev) {
+		DBG("unable to get a device object");
+		return -1;
+	}
+
+	req = new_profile_request(dev, profile, cb);
+
+	err = source_disconnect(audio_dev, FALSE, profile_cb, req);
+	if (err < 0) {
+		g_free(req);
+		return err;
+	}
+
+	return 0;
+}
+
 static struct audio_adapter *audio_adapter_ref(struct audio_adapter *adp)
 {
 	adp->ref++;
@@ -335,6 +421,10 @@ static struct btd_profile a2dp_source_profile = {
 	.device_probe	= a2dp_source_probe,
 	.device_remove	= audio_remove,
 
+	.auto_connect	= true,
+	.connect	= a2dp_source_connect,
+	.disconnect	= a2dp_source_disconnect,
+
 	.adapter_probe	= a2dp_source_server_probe,
 };
 
-- 
1.7.11.7


^ permalink raw reply related

* [PATCH BlueZ 2/6] audio: Split A2DP into two btd_profile
From: Luiz Augusto von Dentz @ 2012-11-21 12:10 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1353499818-10153-1-git-send-email-luiz.dentz@gmail.com>

From: Mikel Astiz <mikel.astiz@bmw-carit.de>

Merging the three audio profiles (AVDTP, A2DP sink and A2DP source)
into one was convenient in the past was doesn't fit very well the new
btd_profile approach. The split is also more consistent with other
existing profiles.
---
 profiles/audio/a2dp.c    | 80 +++++++++++++++++++++++------------------------
 profiles/audio/a2dp.h    |  3 +-
 profiles/audio/manager.c | 81 +++++++++++++++++++++++++++++++-----------------
 3 files changed, 92 insertions(+), 72 deletions(-)

diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
index 50c0f43..177f653 100644
--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
@@ -1166,63 +1166,59 @@ static struct a2dp_server *find_server(GSList *list, const bdaddr_t *src)
 	return NULL;
 }
 
-int a2dp_register(const bdaddr_t *src, GKeyFile *config)
+static struct a2dp_server *a2dp_server_register(const bdaddr_t *src,
+							GKeyFile *config)
 {
-	gboolean source = TRUE, sink = FALSE;
-	char *str;
-	GError *err = NULL;
 	struct a2dp_server *server;
+	int av_err;
 
-	if (!config)
-		goto proceed;
+	server = g_new0(struct a2dp_server, 1);
 
-	str = g_key_file_get_string(config, "General", "Enable", &err);
-
-	if (err) {
-		DBG("audio.conf: %s", err->message);
-		g_clear_error(&err);
-	} else {
-		if (strstr(str, "Sink"))
-			source = TRUE;
-		if (strstr(str, "Source"))
-			sink = TRUE;
-		g_free(str);
+	av_err = avdtp_init(src, config);
+	if (av_err < 0) {
+		DBG("AVDTP not registered");
+		g_free(server);
+		return NULL;
 	}
 
-	str = g_key_file_get_string(config, "General", "Disable", &err);
+	bacpy(&server->src, src);
+	servers = g_slist_append(servers, server);
 
-	if (err) {
-		DBG("audio.conf: %s", err->message);
-		g_clear_error(&err);
-	} else {
-		if (strstr(str, "Sink"))
-			source = FALSE;
-		if (strstr(str, "Source"))
-			sink = FALSE;
-		g_free(str);
-	}
+	return server;
+}
 
-proceed:
+int a2dp_source_register(const bdaddr_t *src, GKeyFile *config)
+{
+	struct a2dp_server *server;
 
 	server = find_server(servers, src);
-	if (!server) {
-		int av_err;
+	if (server != NULL)
+		goto done;
 
-		server = g_new0(struct a2dp_server, 1);
+	server = a2dp_server_register(src, config);
+	if (server == NULL)
+		return -EPROTONOSUPPORT;
 
-		av_err = avdtp_init(src, config);
-		if (av_err < 0) {
-			g_free(server);
-			return av_err;
-		}
+done:
+	server->source_enabled = TRUE;
 
-		bacpy(&server->src, src);
-		servers = g_slist_append(servers, server);
-	}
+	return 0;
+}
 
-	server->source_enabled = source;
+int a2dp_sink_register(const bdaddr_t *src, GKeyFile *config)
+{
+	struct a2dp_server *server;
 
-	server->sink_enabled = sink;
+	server = find_server(servers, src);
+	if (server != NULL)
+		goto done;
+
+	server = a2dp_server_register(src, config);
+	if (server == NULL)
+		return -EPROTONOSUPPORT;
+
+done:
+	server->sink_enabled = TRUE;
 
 	return 0;
 }
diff --git a/profiles/audio/a2dp.h b/profiles/audio/a2dp.h
index 736bc66..ded1060 100644
--- a/profiles/audio/a2dp.h
+++ b/profiles/audio/a2dp.h
@@ -64,7 +64,8 @@ typedef void (*a2dp_stream_cb_t) (struct avdtp *session,
 					struct avdtp_error *err,
 					void *user_data);
 
-int a2dp_register(const bdaddr_t *src, GKeyFile *config);
+int a2dp_source_register(const bdaddr_t *src, GKeyFile *config);
+int a2dp_sink_register(const bdaddr_t *src, GKeyFile *config);
 void a2dp_unregister(const bdaddr_t *src);
 
 struct a2dp_sep *a2dp_add_sep(const bdaddr_t *src, uint8_t type,
diff --git a/profiles/audio/manager.c b/profiles/audio/manager.c
index e453e26..2f36efd 100644
--- a/profiles/audio/manager.c
+++ b/profiles/audio/manager.c
@@ -122,7 +122,7 @@ static void audio_remove(struct btd_profile *p, struct btd_device *device)
 	audio_device_unregister(dev);
 }
 
-static int a2dp_probe(struct btd_profile *p, struct btd_device *device,
+static int a2dp_source_probe(struct btd_profile *p, struct btd_device *device,
 								GSList *uuids)
 {
 	struct audio_device *audio_dev;
@@ -133,13 +133,23 @@ static int a2dp_probe(struct btd_profile *p, struct btd_device *device,
 		return -1;
 	}
 
-	if (g_slist_find_custom(uuids, A2DP_SINK_UUID, bt_uuid_strcmp) &&
-						audio_dev->sink == NULL)
-		audio_dev->sink = sink_init(audio_dev);
+	audio_dev->source = source_init(audio_dev);
 
-	if (g_slist_find_custom(uuids, A2DP_SOURCE_UUID, bt_uuid_strcmp) &&
-						audio_dev->source == NULL)
-		audio_dev->source = source_init(audio_dev);
+	return 0;
+}
+
+static int a2dp_sink_probe(struct btd_profile *p, struct btd_device *device,
+								GSList *uuids)
+{
+	struct audio_device *audio_dev;
+
+	audio_dev = get_audio_dev(device);
+	if (!audio_dev) {
+		DBG("unable to get a device object");
+		return -1;
+	}
+
+	audio_dev->sink = sink_init(audio_dev);
 
 	return 0;
 }
@@ -213,12 +223,11 @@ static struct audio_adapter *audio_adapter_get(struct btd_adapter *adapter)
 	return adp;
 }
 
-static int a2dp_server_probe(struct btd_profile *p,
+static int a2dp_source_server_probe(struct btd_profile *p,
 						struct btd_adapter *adapter)
 {
 	struct audio_adapter *adp;
 	const gchar *path = adapter_get_path(adapter);
-	int err;
 
 	DBG("path %s", path);
 
@@ -226,14 +235,12 @@ static int a2dp_server_probe(struct btd_profile *p,
 	if (!adp)
 		return -EINVAL;
 
-	err = a2dp_register(adapter_get_address(adapter), config);
-	if (err < 0)
-		audio_adapter_unref(adp);
+	audio_adapter_unref(adp); /* Referenced by a2dp server */
 
-	return err;
+	return a2dp_source_register(adapter_get_address(adapter), config);
 }
 
-static void a2dp_server_remove(struct btd_profile *p,
+static int a2dp_sink_server_probe(struct btd_profile *p,
 						struct btd_adapter *adapter)
 {
 	struct audio_adapter *adp;
@@ -241,12 +248,13 @@ static void a2dp_server_remove(struct btd_profile *p,
 
 	DBG("path %s", path);
 
-	adp = find_adapter(adapters, adapter);
+	adp = audio_adapter_get(adapter);
 	if (!adp)
-		return;
+		return -EINVAL;
 
-	a2dp_unregister(adapter_get_address(adapter));
-	audio_adapter_unref(adp);
+	audio_adapter_unref(adp); /* Referenced by a2dp server */
+
+	return a2dp_sink_register(adapter_get_address(adapter), config);
 }
 
 static int avrcp_server_probe(struct btd_profile *p,
@@ -319,17 +327,26 @@ static void media_server_remove(struct btd_adapter *adapter)
 	audio_adapter_unref(adp);
 }
 
-static struct btd_profile a2dp_profile = {
-	.name		= "audio-a2dp",
+static struct btd_profile a2dp_source_profile = {
+	.name		= "audio-source",
 	.priority	= BTD_PROFILE_PRIORITY_MEDIUM,
 
-	.remote_uuids	= BTD_UUIDS(A2DP_SOURCE_UUID, A2DP_SINK_UUID,
-							ADVANCED_AUDIO_UUID),
-	.device_probe	= a2dp_probe,
+	.remote_uuids	= BTD_UUIDS(A2DP_SOURCE_UUID),
+	.device_probe	= a2dp_source_probe,
 	.device_remove	= audio_remove,
 
-	.adapter_probe	= a2dp_server_probe,
-	.adapter_remove = a2dp_server_remove,
+	.adapter_probe	= a2dp_source_server_probe,
+};
+
+static struct btd_profile a2dp_sink_profile = {
+	.name		= "audio-sink",
+	.priority	= BTD_PROFILE_PRIORITY_MEDIUM,
+
+	.remote_uuids	= BTD_UUIDS(A2DP_SINK_UUID),
+	.device_probe	= a2dp_sink_probe,
+	.device_remove	= audio_remove,
+
+	.adapter_probe	= a2dp_sink_server_probe,
 };
 
 static struct btd_profile avrcp_profile = {
@@ -402,8 +419,11 @@ int audio_manager_init(GKeyFile *conf)
 		max_connected_headsets = i;
 
 proceed:
-	if (enabled.source || enabled.sink)
-		btd_profile_register(&a2dp_profile);
+	if (enabled.source)
+		btd_profile_register(&a2dp_source_profile);
+
+	if (enabled.sink)
+		btd_profile_register(&a2dp_sink_profile);
 
 	if (enabled.control)
 		btd_profile_register(&avrcp_profile);
@@ -420,8 +440,11 @@ void audio_manager_exit(void)
 		config = NULL;
 	}
 
-	if (enabled.source || enabled.sink)
-		btd_profile_unregister(&a2dp_profile);
+	if (enabled.source)
+		btd_profile_unregister(&a2dp_source_profile);
+
+	if (enabled.sink)
+		btd_profile_unregister(&a2dp_sink_profile);
 
 	if (enabled.control)
 		btd_profile_unregister(&avrcp_profile);
-- 
1.7.11.7


^ permalink raw reply related

* [PATCH BlueZ 1/6] core: Fix connection order of Device.Connect
From: Luiz Augusto von Dentz @ 2012-11-21 12:10 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

We should with higher priority first.
---
 src/device.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/device.c b/src/device.c
index 0053098..fd29a7f 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1299,7 +1299,7 @@ static gint profile_prio_cmp(gconstpointer a, gconstpointer b)
 {
 	const struct btd_profile *p1 = a, *p2 = b;
 
-	return p1->priority - p2->priority;
+	return p2->priority - p1->priority;
 }
 
 static DBusMessage *connect_profiles(struct btd_device *dev, DBusMessage *msg,
-- 
1.7.11.7


^ permalink raw reply related

* [PATCH v3] neard: Set device class in device object
From: Frédéric Danis @ 2012-11-21 11:59 UTC (permalink / raw)
  To: linux-bluetooth

As soon as we have info related to a new device,
device object will be created if it does not exist yet.

Change check_device() to use this device object and
remove call to adapter_remove_device() in it.
---
 plugins/neard.c |   32 +++++++++++++++-----------------
 1 file changed, 15 insertions(+), 17 deletions(-)

diff --git a/plugins/neard.c b/plugins/neard.c
index 963c8e4..5c9e032 100644
--- a/plugins/neard.c
+++ b/plugins/neard.c
@@ -39,7 +39,6 @@
 #include "manager.h"
 #include "device.h"
 #include "eir.h"
-#include "storage.h"
 #include "agent.h"
 #include "hcid.h"
 #include "event.h"
@@ -260,28 +259,23 @@ static void bonding_complete(struct btd_adapter *adapter,
 		error("D-Bus send failed");
 }
 
-static int check_device(struct btd_adapter *adapter, const char *address)
+static int check_device(struct btd_device *device)
 {
-	struct btd_device *device;
-
-	device = adapter_find_device(adapter, address);
+	if (!device)
+		return -ENOENT;
 
 	/* If already paired */
-	if (device && device_is_paired(device)) {
+	if (device_is_paired(device)) {
 		DBG("already paired");
 		return 1;
 	}
 
 	/* Pairing in progress... */
-	if (device && device_is_bonding(device, NULL)) {
+	if (device_is_bonding(device, NULL)) {
 		DBG("pairing in progress");
 		return -EINPROGRESS;
 	}
 
-	/* If we have unpaired device hanging around, purge it */
-	if (device)
-		adapter_remove_device(adapter, device, TRUE);
-
 	return 0;
 }
 
@@ -291,6 +285,7 @@ static int process_eir(struct btd_adapter *adapter, uint8_t *eir, size_t size,
 {
 	struct eir_data eir_data;
 	char remote_address[18];
+	struct btd_device *device;
 	int ret;
 
 	DBG("size %zu", size);
@@ -304,7 +299,9 @@ static int process_eir(struct btd_adapter *adapter, uint8_t *eir, size_t size,
 
 	DBG("hci%u remote:%s", adapter_get_dev_id(adapter), remote_address);
 
-	ret = check_device (adapter, remote_address);
+	device = adapter_get_device(adapter, remote_address);
+
+	ret = check_device(device);
 	if (ret != 0) {
 		eir_data_free(&eir_data);
 		return ret;
@@ -312,8 +309,7 @@ static int process_eir(struct btd_adapter *adapter, uint8_t *eir, size_t size,
 
 	/* store OOB data */
 	if (eir_data.class != 0)
-		write_remote_class(adapter_get_address(adapter),
-					&eir_data.addr, eir_data.class);
+		device_set_class(device, eir_data.class);
 
 	/* TODO handle incomplete name? */
 	if (eir_data.name)
@@ -461,6 +457,7 @@ static int process_nokia_com_bt(struct btd_adapter *adapter, void *data,
 {
 	uint8_t *marker;
 	struct nokia_com_bt nokia;
+	struct btd_device *device;
 	int ret;
 	char remote_address[18];
 
@@ -499,7 +496,9 @@ static int process_nokia_com_bt(struct btd_adapter *adapter, void *data,
 	ba2str(&nokia.address, remote_address);
 	DBG("hci%u remote:%s", adapter_get_dev_id(adapter), remote_address);
 
-	ret = check_device(adapter, remote_address);
+	device = adapter_get_device(adapter, remote_address);
+
+	ret = check_device(device);
 	if (ret != 0) {
 		g_free(nokia.name);
 		return ret;
@@ -514,8 +513,7 @@ static int process_nokia_com_bt(struct btd_adapter *adapter, void *data,
 	}
 
 	if (nokia.cod != 0)
-		write_remote_class(adapter_get_address(adapter), remote,
-								nokia.cod);
+		device_set_class(device, nokia.cod);
 
 	if (nokia.pin_len > 0) {
 		/* TODO
-- 
1.7.9.5


^ permalink raw reply related

* Re: [PATCH] doc: Add HFP design document
From: Johan Hedberg @ 2012-11-21 11:05 UTC (permalink / raw)
  To: Frédéric Danis; +Cc: linux-bluetooth
In-Reply-To: <1353000939-16880-1-git-send-email-frederic.danis@linux.intel.com>

Hi Frederic,

On Thu, Nov 15, 2012, Frédéric Danis wrote:
> ---
>  Makefile.am                    |    2 +-
>  doc/audio-telephony-design.txt |  320 ++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 321 insertions(+), 1 deletion(-)
>  create mode 100644 doc/audio-telephony-design.txt

Applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH] gdbus: Remove not needed NULL pointer checks
From: Johan Hedberg @ 2012-11-21 10:38 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1353493263-18191-1-git-send-email-szymon.janc@tieto.com>

Hi Szymon,

On Wed, Nov 21, 2012, Szymon Janc wrote:
> g_strdup returns NULL if argument passed is NULL and there is no need
> to double check that.
> ---
>  gdbus/watch.c |    4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)

Applied. Thanks.

Johan

^ permalink raw reply

* [PATCH] gdbus: Remove not needed NULL pointer checks
From: Szymon Janc @ 2012-11-21 10:21 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

g_strdup returns NULL if argument passed is NULL and there is no need
to double check that.
---
 gdbus/watch.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gdbus/watch.c b/gdbus/watch.c
index 07feb61..1cd1211 100644
--- a/gdbus/watch.c
+++ b/gdbus/watch.c
@@ -240,8 +240,8 @@ proceed:
 	data = g_new0(struct filter_data, 1);
 
 	data->connection = dbus_connection_ref(connection);
-	data->name = name ? g_strdup(name) : NULL;
-	data->owner = owner ? g_strdup(owner) : NULL;
+	data->name = g_strdup(name);
+	data->owner = g_strdup(owner);
 	data->path = g_strdup(path);
 	data->interface = g_strdup(interface);
 	data->member = g_strdup(member);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v2 2/2] Bluetooth: Implement deferred sco socket setup
From: Frédéric Dalleau @ 2012-11-21  9:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1353491473-3789-1-git-send-email-frederic.dalleau@linux.intel.com>

In order to authenticate and configure an incoming SCO connection, the
BT_DEFER_SETUP option was added. This option is intended to defer reply
to Connect Request on SCO sockets.
When a connection is requested, the listening socket is unblocked but
the effective connection setup happens only on first recv. Any send
between accept and recv fails with -ENOTCONN.

Signed-off-by: Frédéric Dalleau <frederic.dalleau@linux.intel.com>
---
 include/net/bluetooth/hci_core.h |    9 ++++---
 net/bluetooth/hci_event.c        |   52 +++++++++++++++++++++++++++++++++++---
 net/bluetooth/sco.c              |   35 ++++++++++++++++++++++---
 3 files changed, 86 insertions(+), 10 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index ef5b85d..76891a9 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -376,7 +376,7 @@ extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt);
 extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb,
 			      u16 flags);
 
-extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
+extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags);
 extern void sco_connect_cfm(struct hci_conn *hcon, __u8 status);
 extern void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
 extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);
@@ -577,6 +577,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst);
 int hci_conn_del(struct hci_conn *conn);
 void hci_conn_hash_flush(struct hci_dev *hdev);
 void hci_conn_check_pending(struct hci_dev *hdev);
+void hci_conn_accept(struct hci_conn *conn, int mask);
 
 struct hci_chan *hci_chan_create(struct hci_conn *conn);
 void hci_chan_del(struct hci_chan *chan);
@@ -779,8 +780,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 #define lmp_host_le_br_capable(dev) ((dev)->host_features[0] & LMP_HOST_LE_BREDR)
 
 /* ----- HCI protocols ----- */
+#define HCI_PROTO_DEFER             0x01
+
 static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
-								__u8 type)
+					__u8 type, __u8 *flags)
 {
 	switch (type) {
 	case ACL_LINK:
@@ -788,7 +791,7 @@ static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
 
 	case SCO_LINK:
 	case ESCO_LINK:
-		return sco_connect_ind(hdev, bdaddr);
+		return sco_connect_ind(hdev, bdaddr, flags);
 
 	default:
 		BT_ERR("unknown link type %d", type);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 9f5c5f2..c3e16d8 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2047,15 +2047,53 @@ unlock:
 	hci_conn_check_pending(hdev);
 }
 
+void hci_conn_accept(struct hci_conn *conn, int mask)
+{
+	struct hci_dev *hdev = conn->hdev;
+
+	BT_DBG("conn %p", conn);
+
+	if (!lmp_esco_capable(hdev)) {
+		struct hci_cp_accept_conn_req cp;
+
+		conn->state = BT_CONFIG;
+		bacpy(&cp.bdaddr, &conn->dst);
+
+		if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
+			cp.role = 0x00; /* Become master */
+		else
+			cp.role = 0x01; /* Remain slave */
+
+		hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
+	} else /* lmp_esco_capable(hdev)) */ {
+		struct hci_cp_accept_sync_conn_req cp;
+
+		conn->state = BT_CONFIG;
+		bacpy(&cp.bdaddr, &conn->dst);
+		cp.pkt_type = cpu_to_le16(conn->pkt_type);
+
+		cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
+		cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
+		cp.max_latency    = __constant_cpu_to_le16(0xffff);
+		cp.content_format = cpu_to_le16(hdev->voice_setting);
+		cp.retrans_effort = 0xff;
+
+		hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
+			     sizeof(cp), &cp);
+	}
+}
+
 static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_ev_conn_request *ev = (void *) skb->data;
 	int mask = hdev->link_mode;
+	__u8 flags = 0;
 
 	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
 	       ev->link_type);
 
-	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
+	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
+				      &flags);
 
 	if ((mask & HCI_LM_ACCEPT) &&
 	    !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
@@ -2081,12 +2119,13 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		}
 
 		memcpy(conn->dev_class, ev->dev_class, 3);
-		conn->state = BT_CONNECT;
 
 		hci_dev_unlock(hdev);
 
-		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
+		if (ev->link_type == ACL_LINK ||
+		    (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
 			struct hci_cp_accept_conn_req cp;
+			conn->state = BT_CONNECT;
 
 			bacpy(&cp.bdaddr, &ev->bdaddr);
 
@@ -2097,8 +2136,9 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
 				     &cp);
-		} else {
+		} else if (!(flags & HCI_PROTO_DEFER)) {
 			struct hci_cp_accept_sync_conn_req cp;
+			conn->state = BT_CONNECT;
 
 			bacpy(&cp.bdaddr, &ev->bdaddr);
 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
@@ -2111,6 +2151,10 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
 				     sizeof(cp), &cp);
+		} else {
+			conn->state = BT_CONNECT2;
+			hci_proto_connect_cfm(conn, 0);
+			hci_conn_put(conn);
 		}
 	} else {
 		/* Connection rejected */
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index c6678f2..eea17cd 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -397,6 +397,7 @@ static void sco_sock_init(struct sock *sk, struct sock *parent)
 
 	if (parent) {
 		sk->sk_type = parent->sk_type;
+		bt_sk(sk)->flags = bt_sk(parent)->flags;
 		security_sk_clone(parent, sk);
 	}
 }
@@ -662,6 +663,28 @@ static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
 	return err;
 }
 
+static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
+			    struct msghdr *msg, size_t len, int flags)
+{
+	struct sock *sk = sock->sk;
+	struct sco_pinfo *pi = sco_pi(sk);
+
+	lock_sock(sk);
+
+	if (sk->sk_state == BT_CONNECT2 &&
+	    test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
+		hci_conn_accept(pi->conn->hcon, 0);
+		sk->sk_state = BT_CONFIG;
+
+		release_sock(sk);
+		return 0;
+	}
+
+	release_sock(sk);
+
+	return bt_sock_recvmsg(iocb, sock, msg, len, flags);
+}
+
 static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
 {
 	struct sock *sk = sock->sk;
@@ -906,7 +929,10 @@ static void sco_conn_ready(struct sco_conn *conn)
 		hci_conn_hold(conn->hcon);
 		__sco_chan_add(conn, sk, parent);
 
-		sk->sk_state = BT_CONNECTED;
+		if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
+			sk->sk_state = BT_CONNECT2;
+		else
+			sk->sk_state = BT_CONNECTED;
 
 		/* Wake up parent */
 		parent->sk_data_ready(parent, 1);
@@ -919,7 +945,7 @@ done:
 }
 
 /* ----- SCO interface with lower layer (HCI) ----- */
-int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
+int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
 {
 	struct sock *sk;
 	struct hlist_node *node;
@@ -936,6 +962,9 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
 		if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr) ||
 		    !bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
 			lm |= HCI_LM_ACCEPT;
+
+			if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))
+				*flags |= HCI_PROTO_DEFER;
 			break;
 		}
 	}
@@ -1024,7 +1053,7 @@ static const struct proto_ops sco_sock_ops = {
 	.accept		= sco_sock_accept,
 	.getname	= sco_sock_getname,
 	.sendmsg	= sco_sock_sendmsg,
-	.recvmsg	= bt_sock_recvmsg,
+	.recvmsg	= sco_sock_recvmsg,
 	.poll		= bt_sock_poll,
 	.ioctl		= bt_sock_ioctl,
 	.mmap		= sock_no_mmap,
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v2 1/2] Bluetooth: Add BT_DEFER_SETUP option to sco socket
From: Frédéric Dalleau @ 2012-11-21  9:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1353491473-3789-1-git-send-email-frederic.dalleau@linux.intel.com>

This option will set the BT_SK_DEFER_SETUP bit in socket flags.

Signed-off-by: Frédéric Dalleau <frederic.dalleau@linux.intel.com>
---
 net/bluetooth/sco.c |   32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 450cdcd..c6678f2 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -666,12 +666,31 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char
 {
 	struct sock *sk = sock->sk;
 	int err = 0;
+	u32 opt;
 
 	BT_DBG("sk %p", sk);
 
 	lock_sock(sk);
 
 	switch (optname) {
+
+	case BT_DEFER_SETUP:
+		if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
+			err = -EINVAL;
+			break;
+		}
+
+		if (get_user(opt, (u32 __user *) optval)) {
+			err = -EFAULT;
+			break;
+		}
+
+		if (opt)
+			set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
+		else
+			clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
+		break;
+
 	default:
 		err = -ENOPROTOOPT;
 		break;
@@ -753,6 +772,19 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char
 	lock_sock(sk);
 
 	switch (optname) {
+
+	case BT_DEFER_SETUP:
+		if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
+			err = -EINVAL;
+			break;
+		}
+
+		if (put_user(test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags),
+			     (u32 __user *) optval))
+			err = -EFAULT;
+
+		break;
+
 	default:
 		err = -ENOPROTOOPT;
 		break;
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v2 0/2] sco: BT_DEFER_SETUP for SCO sockets
From: Frédéric Dalleau @ 2012-11-21  9:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

Hi,

This patch implements BT_DEFER_SETUP option on SCO sockets. hci layer get some
changes since previous behavior was to accept all SCO connections.

How to test :
compile bluez (3fd3d5f or newer) with --enable-test and run:
$ btiotest -s -d -a 5
on another machine run:
$ btiotest -s <bdaddr>
Check result with btmon.

Best regards,
Frédéric


Frédéric Dalleau (2):
  Bluetooth: Add BT_DEFER_SETUP option to sco socket
  Bluetooth: Implement deferred sco socket setup

 include/net/bluetooth/hci_core.h |    9 +++--
 net/bluetooth/hci_event.c        |   52 ++++++++++++++++++++++++++---
 net/bluetooth/sco.c              |   67 ++++++++++++++++++++++++++++++++++++--
 3 files changed, 118 insertions(+), 10 deletions(-)

-- 
1.7.9.5


^ permalink raw reply

* Re: [PATCH 2/2] Bluetooth: Implement deferred sco socket setup
From: Frédéric Dalleau @ 2012-11-20 18:08 UTC (permalink / raw)
  To: Gustavo Padovan, linux-bluetooth
In-Reply-To: <20121120180114.GJ14006@joana>

Hi,

On 11/20/2012 07:01 PM, Gustavo Padovan wrote:
> * Frédéric Dalleau <frederic.dalleau@linux.intel.com> [2012-11-20 18:55:39 +0100]:
>
>> Hi Gustavo,
>>
>> I'm taking your remarks into account asap
>>
>> On 11/20/2012 06:37 PM, Gustavo Padovan wrote:
>>> Where do you set sk_state to BT_CONNECTED. Doesn't it need to be here?
>> The state is set to BT_CONNECTED in hci_sync_conn_complete_evt. ie when
>> the connection is effectively created.
>
> Are we both talking about the sk_state var? I failed to see how it is set to
> BT_CONNECTED.

Yes, hci_sync_conn_complete_evt > hci_proto_connect_cfm > sco_connect_cfm >

if there is no error, sco_conn_ready.
Since the socket is already created we get in first if branch.

Frédéric

^ permalink raw reply

* Re: [PATCH v2] Bluetooth: Remove OOB data if device was discovered in band
From: Gustavo Padovan @ 2012-11-20 18:04 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1353407934-17831-1-git-send-email-szymon.janc@tieto.com>

Hi Szymon,

* Szymon Janc <szymon.janc@tieto.com> [2012-11-20 11:38:54 +0100]:

> OOB authentication mechanism should be used only if pairing process
> has been activated by previous OOB information exchange (Core Spec
> 4.0 , vol. 1, Part A, 5.1.4.3). Stored OOB data for specific device
> should be removed if that device was discovered in band later on.
> 
> Signed-off-by: Szymon Janc <szymon.janc@tieto.com>
> ---
> V2:
> Move OOB data removal to hci_inquiry_cache_update to cover all inquiry
> events (ext/rssi) in one place.
> 
>  net/bluetooth/hci_core.c |    2 ++
>  1 file changed, 2 insertions(+)

patch has been applied to bluetooth-next. Thanks.

	Gustavo

^ permalink raw reply

* Re: [PATCH 2/2] Bluetooth: Implement deferred sco socket setup
From: Gustavo Padovan @ 2012-11-20 18:01 UTC (permalink / raw)
  To: Frédéric Dalleau; +Cc: linux-bluetooth
In-Reply-To: <50ABC41B.8030802@linux.intel.com>

* Frédéric Dalleau <frederic.dalleau@linux.intel.com> [2012-11-20 18:55:39 +0100]:

> Hi Gustavo,
> 
> I'm taking your remarks into account asap
> 
> On 11/20/2012 06:37 PM, Gustavo Padovan wrote:
> >Where do you set sk_state to BT_CONNECTED. Doesn't it need to be here?
> The state is set to BT_CONNECTED in hci_sync_conn_complete_evt. ie when
> the connection is effectively created.

Are we both talking about the sk_state var? I failed to see how it is set to
BT_CONNECTED.

	Gustavo

^ permalink raw reply

* Re: [RFC 4/4] Bluetooth: AMP: Set no FCS for incoming L2CAP chan
From: Gustavo Padovan @ 2012-11-20 17:56 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1353424582-26042-5-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

* Andrei Emeltchenko <Andrei.Emeltchenko.news@gmail.com> [2012-11-20 17:16:22 +0200]:

> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> 
> When receiving L2CAP Create Channel Request set the channel as
> L2CAP_FCS_NONE. Then in "L2CAP Config req" following field will
> be set: "FCS Option 0x00 (No FCS)". So by default High Speed
> channels have no FCS.
> 
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> ---
>  net/bluetooth/l2cap_core.c |    1 +
>  1 file changed, 1 insertion(+)

All 4 patches have been applied to bluetooth-next. Thanks.

	Gustavo

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox