Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH 5/5] Don't trigger the discovering when registering the client
From: Claudio Takahasi @ 2010-11-24  2:30 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1290565847-17382-1-git-send-email-claudio.takahasi@openbossa.org>

Discover All Primary Services should not be trigged by the attribute
client when a given device is registered. Discover services is now done
by the device entity.
---
 attrib/client.c |   47 +----------------------------------------------
 1 files changed, 1 insertions(+), 46 deletions(-)

diff --git a/attrib/client.c b/attrib/client.c
index a851a74..a8a4051 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -1322,16 +1322,8 @@ int attrib_client_register(struct btd_device *device, int psm)
 	struct btd_adapter *adapter = device_get_adapter(device);
 	const char *path = device_get_path(device);
 	struct gatt_service *gatt;
-	GError *gerr = NULL;
-	GIOChannel *io;
 	bdaddr_t sba, dba;
 
-	/*
-	 * Registering fake services/characteristics. The following
-	 * paths/interfaces shall be registered after discover primary
-	 * services only.
-	 */
-
 	adapter_get_address(adapter, &sba);
 	device_get_address(device, &dba);
 
@@ -1343,46 +1335,9 @@ int attrib_client_register(struct btd_device *device, int psm)
 	bacpy(&gatt->dba, &dba);
 	gatt->psm = psm;
 
-	if (load_primary_services(gatt)) {
+	if (load_primary_services(gatt))
 		DBG("Primary services loaded");
-		goto done;
-	}
-
-	if (psm < 0) {
-		io = bt_io_connect(BT_IO_L2CAP, connect_cb, gatt, NULL, &gerr,
-					BT_IO_OPT_SOURCE_BDADDR, &sba,
-					BT_IO_OPT_DEST_BDADDR, &dba,
-					BT_IO_OPT_CID, GATT_CID,
-					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
-					BT_IO_OPT_INVALID);
-
-			DBG("GATT over Low Energy");
-	} else {
-		io = bt_io_connect(BT_IO_L2CAP, connect_cb, gatt, NULL, &gerr,
-					BT_IO_OPT_SOURCE_BDADDR, &sba,
-					BT_IO_OPT_DEST_BDADDR, &dba,
-					BT_IO_OPT_PSM, psm,
-					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
-					BT_IO_OPT_INVALID);
-
-		DBG("GATT over Basic Rate");
-	}
-
-	if (!io) {
-		error("%s", gerr->message);
-		g_error_free(gerr);
-		gatt_service_free(gatt);
-		return -1;
-	}
-
-	gatt->attrib = g_attrib_new(io);
-	g_io_channel_unref(io);
 
-	g_attrib_set_destroy_function(gatt->attrib, attrib_destroy, gatt);
-	g_attrib_set_disconnect_function(gatt->attrib, attrib_disconnect,
-									gatt);
-
-done:
 	gatt_services = g_slist_append(gatt_services, gatt);
 
 	return 0;
-- 
1.7.3.2


^ permalink raw reply related

* [PATCH 4/5] Fix memory leak of sdp list in the attribute client
From: Claudio Takahasi @ 2010-11-24  2:30 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1290565847-17382-1-git-send-email-claudio.takahasi@openbossa.org>

---
 attrib/manager.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/attrib/manager.c b/attrib/manager.c
index 9b06c8c..f991f8e 100644
--- a/attrib/manager.c
+++ b/attrib/manager.c
@@ -44,15 +44,19 @@ static DBusConnection *connection;
 static int client_probe(struct btd_device *device, GSList *uuids)
 {
 	const sdp_record_t *rec;
-	sdp_list_t *list;
 	int psm = -1;
 
 	rec = btd_device_get_record(device, GATT_UUID);
 	if (rec) {
+		sdp_list_t *list;
 		if (sdp_get_access_protos(rec, &list) < 0)
 			return -1;
 
 		psm = sdp_get_proto_port(list, L2CAP_UUID);
+
+		sdp_list_foreach(list, (sdp_list_func_t) sdp_list_free, NULL);
+		sdp_list_free(list, NULL);
+
 		if (psm < 0)
 			return -1;
 	}
-- 
1.7.3.2


^ permalink raw reply related

* [PATCH 3/5] Return a D-Bus error if device_browse fails
From: Claudio Takahasi @ 2010-11-24  2:30 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1290565847-17382-1-git-send-email-claudio.takahasi@openbossa.org>

If Discover All Primary Services or SDP search fails, the CreateDevice
caller will not receive a response. Error reproducible when a Discover
All Primary Services is sent over a LE link and the kernel doesn't
address properly the connections in the channel ID 4.
---
 src/adapter.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 029bec8..6c3396c 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1696,6 +1696,7 @@ static DBusMessage *create_device(DBusConnection *conn,
 	struct remote_dev_info *dev, match;
 	const gchar *address;
 	gboolean le;
+	int err;
 
 	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address,
 						DBUS_TYPE_INVALID) == FALSE)
@@ -1722,7 +1723,9 @@ static DBusMessage *create_device(DBusConnection *conn,
 	if (!device)
 		return NULL;
 
-	device_browse(device, conn, msg, NULL, FALSE);
+	err = device_browse(device, conn, msg, NULL, FALSE);
+	if (err < 0)
+		return failed_strerror(msg, -err);
 
 	return NULL;
 }
-- 
1.7.3.2


^ permalink raw reply related

* [PATCH 2/5] Check the device type when creating the device
From: Claudio Takahasi @ 2010-11-24  2:30 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1290565847-17382-1-git-send-email-claudio.takahasi@openbossa.org>

For CreateDevice, if the remote device is LE capable, Discover All
Primary Services shall be issued instead of SDP queries. The logic
to define if the remote is LE capable shall be based on the result
of the interleaved discovery results. Meaning, the remote device
is classified as LE capable only if an advertising event from this
device was collected during the discovery.

Limitation: Advertising event data is not being considered yet to
infer the remote properties and CreateDevice needs to be called
during the discovery session.
---
 src/adapter.c |   25 +++++++++++++++++--------
 src/adapter.h |    3 ++-
 src/device.c  |    3 ++-
 src/device.h  |    5 +++--
 4 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 6b4a354..029bec8 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1199,15 +1199,15 @@ sdp_list_t *adapter_get_services(struct btd_adapter *adapter)
 }
 
 struct btd_device *adapter_create_device(DBusConnection *conn,
-						struct btd_adapter *adapter,
-						const char *address)
+					struct btd_adapter *adapter,
+					const char *address, gboolean le)
 {
 	struct btd_device *device;
 	const char *path;
 
 	DBG("%s", address);
 
-	device = device_create(conn, adapter, address);
+	device = device_create(conn, adapter, address, le);
 	if (!device)
 		return NULL;
 
@@ -1266,7 +1266,7 @@ struct btd_device *adapter_get_device(DBusConnection *conn,
 	if (device)
 		return device;
 
-	return adapter_create_device(conn, adapter, address);
+	return adapter_create_device(conn, adapter, address, FALSE);
 }
 
 static gboolean stop_scanning(gpointer user_data)
@@ -1693,7 +1693,9 @@ static DBusMessage *create_device(DBusConnection *conn,
 {
 	struct btd_adapter *adapter = data;
 	struct btd_device *device;
+	struct remote_dev_info *dev, match;
 	const gchar *address;
+	gboolean le;
 
 	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address,
 						DBUS_TYPE_INVALID) == FALSE)
@@ -1709,7 +1711,14 @@ static DBusMessage *create_device(DBusConnection *conn,
 
 	DBG("%s", address);
 
-	device = adapter_create_device(conn, adapter, address);
+	memset(&match, 0, sizeof(struct remote_dev_info));
+	str2ba(address, &match.bdaddr);
+	match.name_status = NAME_ANY;
+
+	dev = adapter_search_found_devices(adapter, &match);
+	le  = dev ? dev->le : FALSE;
+
+	device = adapter_create_device(conn, adapter, address, le);
 	if (!device)
 		return NULL;
 
@@ -2003,7 +2012,7 @@ static void create_stored_device_from_profiles(char *key, char *value,
 				key, (GCompareFunc) device_address_cmp))
 		return;
 
-	device = device_create(connection, adapter, key);
+	device = device_create(connection, adapter, key, FALSE);
 	if (!device)
 		return;
 
@@ -2026,7 +2035,7 @@ static void create_stored_device_from_linkkeys(char *key, char *value,
 					(GCompareFunc) device_address_cmp))
 		return;
 
-	device = device_create(connection, adapter, key);
+	device = device_create(connection, adapter, key, FALSE);
 	if (device) {
 		device_set_temporary(device, FALSE);
 		adapter->devices = g_slist_append(adapter->devices, device);
@@ -2043,7 +2052,7 @@ static void create_stored_device_from_blocked(char *key, char *value,
 				key, (GCompareFunc) device_address_cmp))
 		return;
 
-	device = device_create(connection, adapter, key);
+	device = device_create(connection, adapter, key, FALSE);
 	if (device) {
 		device_set_temporary(device, FALSE);
 		adapter->devices = g_slist_append(adapter->devices, device);
diff --git a/src/adapter.h b/src/adapter.h
index de6a6f5..4f5ccdb 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -109,7 +109,8 @@ void adapter_remove_device(DBusConnection *conn, struct btd_adapter *adapter,
 						struct btd_device *device,
 						gboolean remove_storage);
 struct btd_device *adapter_create_device(DBusConnection *conn,
-				struct btd_adapter *adapter, const char *address);
+					struct btd_adapter *adapter,
+					const char *address, gboolean le);
 
 int adapter_resolve_names(struct btd_adapter *adapter);
 
diff --git a/src/device.c b/src/device.c
index f236b29..1c119d5 100644
--- a/src/device.c
+++ b/src/device.c
@@ -965,7 +965,7 @@ void device_set_secmode3_conn(struct btd_device *device, gboolean enable)
 
 struct btd_device *device_create(DBusConnection *conn,
 					struct btd_adapter *adapter,
-					const gchar *address)
+					const gchar *address, gboolean le)
 {
 	gchar *address_up;
 	struct btd_device *device;
@@ -993,6 +993,7 @@ struct btd_device *device_create(DBusConnection *conn,
 
 	str2ba(address, &device->bdaddr);
 	device->adapter = adapter;
+	device->le = le;
 	adapter_get_address(adapter, &src);
 	ba2str(&src, srcaddr);
 	read_device_name(srcaddr, address, device->name);
diff --git a/src/device.h b/src/device.h
index b570bd1..a5b6273 100644
--- a/src/device.h
+++ b/src/device.h
@@ -34,8 +34,9 @@ typedef enum {
 	AUTH_TYPE_AUTO,
 } auth_type_t;
 
-struct btd_device *device_create(DBusConnection *conn, struct btd_adapter *adapter,
-				const gchar *address);
+struct btd_device *device_create(DBusConnection *conn,
+					struct btd_adapter *adapter,
+					const gchar *address, gboolean le);
 void device_set_name(struct btd_device *device, const char *name);
 void device_get_name(struct btd_device *device, char *name, size_t len);
 void device_remove(struct btd_device *device, gboolean remove_stored);
-- 
1.7.3.2


^ permalink raw reply related

* [PATCH 1/5] Implements primary service search when creating a device
From: Claudio Takahasi @ 2010-11-24  2:30 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

Discover primary services implemented inside the device entity to allow
proper integration of attribute plugin. Implements a single entry point
to the attribute plugin no matter the transport(BR/EDR or LE), the device
probe callback is called for both types.

Add a new function to discover all primary services without additional
calls to fetch the remaining primary services, sub-procedure iterations
is handled inside this function.

The next action are: clean the attribute client removing implicity service
and characteristics discovery, issue the Discover Primary Service based on
the remote properties and fetch the characteristic on demand.
---
 attrib/manager.c  |   27 +++-------
 src/device.c      |  106 +++++++++++++++++++++++++++++++-------
 src/glib-helper.c |  147 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/glib-helper.h |    5 ++
 4 files changed, 246 insertions(+), 39 deletions(-)

diff --git a/attrib/manager.c b/attrib/manager.c
index 9bd1774..9b06c8c 100644
--- a/attrib/manager.c
+++ b/attrib/manager.c
@@ -45,26 +45,17 @@ static int client_probe(struct btd_device *device, GSList *uuids)
 {
 	const sdp_record_t *rec;
 	sdp_list_t *list;
-	int psm;
-
-	/*
-	 * Entry point for BR/EDR GATT probe. LE scanning and primary service
-	 * search will be handled temporaly inside the gatt plugin. For the
-	 * final solution all LE operations should be moved to the "core",
-	 * otherwise it will not be possible serialize/schedule BR/EDR device
-	 * discovery and LE scanning.
-	 */
+	int psm = -1;
 
 	rec = btd_device_get_record(device, GATT_UUID);
-	if (!rec)
-		return -1;
-
-	if (sdp_get_access_protos(rec, &list) < 0)
-		return -1;
-
-	psm = sdp_get_proto_port(list, L2CAP_UUID);
-	if (psm < 0)
-		return -1;
+	if (rec) {
+		if (sdp_get_access_protos(rec, &list) < 0)
+			return -1;
+
+		psm = sdp_get_proto_port(list, L2CAP_UUID);
+		if (psm < 0)
+			return -1;
+	}
 
 	return attrib_client_register(device, psm);
 }
diff --git a/src/device.c b/src/device.c
index 7c421e3..f236b29 100644
--- a/src/device.c
+++ b/src/device.c
@@ -111,6 +111,7 @@ struct browse_req {
 
 struct btd_device {
 	bdaddr_t	bdaddr;
+	gboolean	le;
 	gchar		*path;
 	char		name[MAX_NAME_LENGTH + 1];
 	char		*alias;
@@ -215,7 +216,8 @@ static void browse_request_cancel(struct browse_req *req)
 
 	adapter_get_address(adapter, &src);
 
-	bt_cancel_discovery(&src, &device->bdaddr);
+	if (device->le == FALSE)
+		bt_cancel_discovery(&src, &device->bdaddr);
 
 	device->browse = NULL;
 	browse_request_free(req);
@@ -1557,29 +1559,67 @@ static void init_browse(struct browse_req *req, gboolean reverse)
 						l->data);
 }
 
-int device_browse(struct btd_device *device, DBusConnection *conn,
-			DBusMessage *msg, uuid_t *search, gboolean reverse)
+static void primary_cb(GSList *services, int err, gpointer user_data)
+{
+	struct browse_req *req = user_data;
+	struct btd_device *device = req->device;
+
+	if (err) {
+		error_failed_errno(req->conn, req->msg, -err);
+		goto done;
+	}
+
+	services_changed(req->device);
+	device_set_temporary(req->device, FALSE);
+	device_probe_drivers(req->device, services);
+
+	create_device_reply(req->device, req);
+
+done:
+	device->browse = NULL;
+	browse_request_free(req);
+}
+
+static struct browse_req *browse_primary(struct btd_device *device, int *err)
 {
 	struct btd_adapter *adapter = device->adapter;
 	struct browse_req *req;
 	bdaddr_t src;
-	uuid_t uuid;
-	bt_callback_t cb;
-	int err;
+	int ret;
 
-	if (device->browse)
-		return -EBUSY;
+	req = g_new0(struct browse_req, 1);
+	req->device = btd_device_ref(device);
 
 	adapter_get_address(adapter, &src);
 
-	req = g_new0(struct browse_req, 1);
+	ret = bt_discover_primary(&src, &device->bdaddr, -1, primary_cb, req,
+									NULL);
 
-	if (conn == NULL)
-		conn = get_dbus_connection();
+	if (ret < 0) {
+		browse_request_free(req);
+		if (err)
+			*err = ret;
 
-	req->conn = dbus_connection_ref(conn);
-	req->device = btd_device_ref(device);
+		return NULL;
+	}
+
+	return req;
+}
+
+static struct browse_req *browse_sdp(struct btd_device *device, uuid_t *search,
+						gboolean reverse, int *err)
+{
+	struct btd_adapter *adapter = device->adapter;
+	struct browse_req *req;
+	bt_callback_t cb;
+	bdaddr_t src;
+	uuid_t uuid;
+	int ret;
 
+	adapter_get_address(adapter, &src);
+
+	req = g_new0(struct browse_req, 1);
+	req->device = btd_device_ref(device);
 	if (search) {
 		memcpy(&uuid, search, sizeof(uuid_t));
 		cb = search_cb;
@@ -1589,6 +1629,39 @@ int device_browse(struct btd_device *device, DBusConnection *conn,
 		cb = browse_cb;
 	}
 
+	ret = bt_search_service(&src, &device->bdaddr, &uuid, cb, req, NULL);
+	if (ret < 0) {
+		browse_request_free(req);
+		if (err)
+			*err = ret;
+
+		return NULL;
+	}
+
+	return req;
+}
+
+int device_browse(struct btd_device *device, DBusConnection *conn,
+			DBusMessage *msg, uuid_t *search, gboolean reverse)
+{
+	struct browse_req *req;
+	int err = 0;
+
+	if (device->browse)
+		return -EBUSY;
+
+	if (device->le)
+		req = browse_primary(device, &err);
+	else
+		req = browse_sdp(device, search, reverse, &err);
+
+	if (req == NULL)
+		return err;
+
+	if (conn == NULL)
+		conn = get_dbus_connection();
+
+	req->conn = dbus_connection_ref(conn);
 	device->browse = req;
 
 	if (msg) {
@@ -1603,13 +1676,6 @@ int device_browse(struct btd_device *device, DBusConnection *conn,
 						req, NULL);
 	}
 
-	err = bt_search_service(&src, &device->bdaddr,
-				&uuid, cb, req, NULL);
-	if (err < 0) {
-		device->browse = NULL;
-		browse_request_free(req);
-	}
-
 	return err;
 }
 
diff --git a/src/glib-helper.c b/src/glib-helper.c
index 4941d99..f0689d5 100644
--- a/src/glib-helper.c
+++ b/src/glib-helper.c
@@ -42,12 +42,26 @@
 
 #include <glib.h>
 
-#include "glib-helper.h"
+#include "btio.h"
+#include "gattrib.h"
+#include "att.h"
+#include "gatt.h"
 #include "sdpd.h"
+#include "glib-helper.h"
 
 /* Number of seconds to keep a sdp_session_t in the cache */
 #define CACHE_TIMEOUT 2
 
+struct gattrib_context {
+	bdaddr_t src;
+	bdaddr_t dst;
+	GAttrib *attrib;
+	bt_primary_t cb;
+	bt_destroy_t destroy;
+	gpointer user_data;
+	GSList *uuids;
+};
+
 struct cached_sdp_session {
 	bdaddr_t src;
 	bdaddr_t dst;
@@ -57,6 +71,17 @@ struct cached_sdp_session {
 
 static GSList *cached_sdp_sessions = NULL;
 
+static void gattrib_context_free(struct gattrib_context *ctxt)
+{
+	if (ctxt->destroy)
+		ctxt->destroy(ctxt->user_data);
+
+	g_slist_foreach(ctxt->uuids, (GFunc) g_free, NULL);
+	g_slist_free(ctxt->uuids);
+	g_attrib_unref(ctxt->attrib);
+	g_free(ctxt);
+}
+
 static gboolean cached_session_expired(gpointer user_data)
 {
 	struct cached_sdp_session *cached = user_data;
@@ -118,6 +143,7 @@ struct search_context {
 	bdaddr_t		dst;
 	sdp_session_t		*session;
 	bt_callback_t		cb;
+	bt_primary_t		prim_cb;
 	bt_destroy_t		destroy;
 	gpointer		user_data;
 	uuid_t			uuid;
@@ -378,6 +404,125 @@ int bt_cancel_discovery(const bdaddr_t *src, const bdaddr_t *dst)
 	return 0;
 }
 
+static void primary_cb(guint8 status, const guint8 *pdu, guint16 plen,
+							gpointer user_data)
+{
+	struct gattrib_context *ctxt = user_data;
+	struct att_data_list *list;
+	unsigned int i, err;
+	uint16_t end;
+
+	if (status == ATT_ECODE_ATTR_NOT_FOUND) {
+		err = 0;
+		goto done;
+	}
+
+	if (status != 0) {
+		err = -EIO;
+		goto done;
+	}
+
+	list = dec_read_by_grp_resp(pdu, plen);
+	if (list == NULL) {
+		err = -EPROTO;
+		goto done;
+	}
+
+	for (i = 0, end = 0; i < list->num; i++) {
+		const uint8_t *data = list->data[i];
+		char *prim;
+		uuid_t u128, u16;
+
+		end = att_get_u16(&data[2]);
+
+		if (list->len == 6) {
+			sdp_uuid16_create(&u16,
+					att_get_u16(&data[4]));
+			sdp_uuid16_to_uuid128(&u128, &u16);
+
+		} else if (list->len == 20)
+			sdp_uuid128_create(&u128, &data[4]);
+		else
+			/* Skipping invalid data */
+			continue;
+
+		prim = bt_uuid2string(&u128);
+		ctxt->uuids = g_slist_append(ctxt->uuids, prim);
+	}
+
+	att_data_list_free(list);
+	err = 0;
+
+	if (end != 0xffff) {
+		gatt_discover_primary(ctxt->attrib, end + 1, 0xffff, NULL,
+							primary_cb, ctxt);
+		return;
+	}
+
+done:
+	ctxt->cb(ctxt->uuids, err, ctxt->user_data);
+	gattrib_context_free(ctxt);
+}
+
+static void connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
+{
+	struct gattrib_context *ctxt = user_data;
+
+	if (gerr) {
+		ctxt->cb(NULL, -EIO, ctxt->user_data);
+		gattrib_context_free(ctxt);
+		return;
+	}
+
+	gatt_discover_primary(ctxt->attrib, 0x0001, 0xffff, NULL, primary_cb,
+									ctxt);
+}
+
+int bt_discover_primary(const bdaddr_t *src, const bdaddr_t *dst, int psm,
+					bt_primary_t cb, void *user_data,
+					bt_destroy_t destroy)
+{
+	struct gattrib_context *ctxt;
+	GIOChannel *io;
+	GError *gerr = NULL;
+
+	ctxt = g_try_malloc0(sizeof(struct gattrib_context));
+	if (ctxt == NULL)
+		return -ENOMEM;
+
+	bacpy(&ctxt->src, src);
+	bacpy(&ctxt->dst, dst);
+	ctxt->user_data = user_data;
+	ctxt->cb = cb;
+	ctxt->destroy = destroy;
+
+	if (psm < 0)
+		io = bt_io_connect(BT_IO_L2CAP, connect_cb, ctxt, NULL, &gerr,
+				BT_IO_OPT_SOURCE_BDADDR, src,
+				BT_IO_OPT_DEST_BDADDR, dst,
+				BT_IO_OPT_CID, GATT_CID,
+				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+				BT_IO_OPT_INVALID);
+	else
+		io = bt_io_connect(BT_IO_L2CAP, connect_cb, ctxt, NULL, &gerr,
+				BT_IO_OPT_SOURCE_BDADDR, src,
+				BT_IO_OPT_DEST_BDADDR, dst,
+				BT_IO_OPT_PSM, psm,
+				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+				BT_IO_OPT_INVALID);
+
+	if (io == NULL) {
+		gattrib_context_free(ctxt);
+		return -EIO;
+	}
+
+	ctxt->attrib = g_attrib_new(io);
+
+	g_io_channel_unref(io);
+
+	return 0;
+}
+
 char *bt_uuid2string(uuid_t *uuid)
 {
 	gchar *str;
diff --git a/src/glib-helper.h b/src/glib-helper.h
index dfe4123..018ff92 100644
--- a/src/glib-helper.h
+++ b/src/glib-helper.h
@@ -22,6 +22,7 @@
  */
 
 typedef void (*bt_callback_t) (sdp_list_t *recs, int err, gpointer user_data);
+typedef void (*bt_primary_t) (GSList *l, int err, gpointer user_data);
 typedef void (*bt_destroy_t) (gpointer user_data);
 
 int bt_discover_services(const bdaddr_t *src, const bdaddr_t *dst,
@@ -32,6 +33,10 @@ int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst,
 			bt_destroy_t destroy);
 int bt_cancel_discovery(const bdaddr_t *src, const bdaddr_t *dst);
 
+int bt_discover_primary(const bdaddr_t *src, const bdaddr_t *dst, int psm,
+					bt_primary_t cb, void *user_data,
+					bt_destroy_t destroy);
+
 gchar *bt_uuid2string(uuid_t *uuid);
 uint16_t bt_name2class(const char *string);
 char *bt_name2string(const char *string);
-- 
1.7.3.2


^ permalink raw reply related

* Re: [RFC 12/20] Bluetooth: fix receiving L2CAP packets over LE
From: Vinicius Costa Gomes @ 2010-11-23 23:06 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: Vinicius Costa Gomes, linux-bluetooth
In-Reply-To: <20101123225558.GD11860@vigoh>

Hi Gustavo,

On 20:55 Tue 23 Nov     , Gustavo F. Padovan wrote:
> Hi Vinicius,
> 
> * Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2010-11-23 12:06:28 -0300]:
> 
> > As L2CAP packets coming over LE don't have any more encapsulation,
> > other than L2CAP, we are able to process them as soon as they arrive.
> > 
> > Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
> > ---
> >  net/bluetooth/l2cap.c |   17 +++++++++++++++--
> >  1 files changed, 15 insertions(+), 2 deletions(-)
> 
> So move this patch before the SMP changes in the patchset.

Will do.

> 
> -- 
> Gustavo F. Padovan
> http://profusion.mobi


Cheers,
-- 
Vinicius

^ permalink raw reply

* Re: [RFC 10/20] Bluetooth: Add server socket support for LE connection
From: Vinicius Costa Gomes @ 2010-11-23 23:04 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: Vinicius Costa Gomes, linux-bluetooth, Ville Tervo
In-Reply-To: <20101123225432.GC11860@vigoh>

On 20:54 Tue 23 Nov     , Gustavo F. Padovan wrote:
> * Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2010-11-23 12:06:26 -0300]:
> 
> > From: Ville Tervo <ville.tervo@nokia.com>
> > 
> > Add support for LE server sockets.
> > 
> > Signed-off-by: Ville Tervo <ville.tervo@nokia.com>
> > ---
> >  net/bluetooth/l2cap.c |    3 +--
> >  1 files changed, 1 insertions(+), 2 deletions(-)
> > 
> > diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
> > index 172bf93..e481d6b 100644
> > --- a/net/bluetooth/l2cap.c
> > +++ b/net/bluetooth/l2cap.c
> > @@ -1438,8 +1438,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
> >  	BT_DBG("");
> >  
> >  	/* Check if we have socket listening on cid */
> > -	parent = l2cap_get_sock_by_cid(BT_LISTEN, L2CAP_CID_LE_DATA,
> > -					conn->src);
> > +	parent = l2cap_get_sock_by_cid(BT_LISTEN, L2CAP_CID_LE_DATA, conn->src);
> 
> I didn't get this change, commit message tell about other stuff.

My mistake, this should have happened when I rebased these changes on top of
bluetooth-next.

> 
> -- 
> Gustavo F. Padovan
> http://profusion.mobi


Cheers,
-- 
Vinicius

^ permalink raw reply

* Re: [RFC 17/20] Bluetooth: Add support for using the crypto subsystem
From: Gustavo F. Padovan @ 2010-11-23 23:02 UTC (permalink / raw)
  To: Vinicius Costa Gomes; +Cc: linux-bluetooth
In-Reply-To: <1290524796-32246-18-git-send-email-vinicius.gomes@openbossa.org>

Hi Vinicius,

* Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2010-11-23 12:06:33 -0300]:

> This will allow using the crypto subsystem for encrypting data. As SMP
> (Security Manager Protocol) is implemented almost entirely on the host
> side and the crypto module already implements the needed methods
> (AES-128), it makes sense to use it.
> 
> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
> ---
>  include/net/bluetooth/hci_core.h |    2 ++
>  net/bluetooth/hci_core.c         |   10 ++++++++++
>  net/bluetooth/smp.c              |    1 -
>  3 files changed, 12 insertions(+), 1 deletions(-)
> 
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index e2d857a..ee5efa8 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -135,6 +135,8 @@ struct hci_dev {
>  	__u32			req_status;
>  	__u32			req_result;
>  
> +	struct crypto_blkcipher	*tfm;
> +
>  	struct inquiry_cache	inq_cache;
>  	struct hci_conn_hash	conn_hash;
>  	struct list_head	blacklist;
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 5750b80..0e98ffb 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -41,6 +41,7 @@
>  #include <linux/interrupt.h>
>  #include <linux/notifier.h>
>  #include <linux/rfkill.h>
> +#include <linux/crypto.h>
>  #include <net/sock.h>
>  
>  #include <asm/system.h>
> @@ -947,6 +948,13 @@ int hci_register_dev(struct hci_dev *hdev)
>  	if (!hdev->workqueue)
>  		goto nomem;
>  
> +	hdev->tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
> +	if (IS_ERR(hdev->tfm)) {
> +		BT_ERR("Failed to load transform for ecb(aes): %ld",
> +							PTR_ERR(hdev->tfm));
> +		goto nomem;
> +	}
> +
>  	hci_register_sysfs(hdev);
>  
>  	hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
> @@ -987,6 +995,8 @@ int hci_unregister_dev(struct hci_dev *hdev)
>  	for (i = 0; i < NUM_REASSEMBLY; i++)
>  		kfree_skb(hdev->reassembly[i]);
>  
> +	crypto_free_blkcipher(hdev->tfm);
> +
>  	hci_notify(hdev, HCI_DEV_UNREG);
>  
>  	if (hdev->rfkill) {
> diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> index 7997978..8e8be47 100644
> --- a/net/bluetooth/smp.c
> +++ b/net/bluetooth/smp.c
> @@ -227,7 +227,6 @@ static void smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb
>  	BT_DBG("");
>  
>  	if (conn->hcon->out) {
> -

Change not related to your patch here.

-- 
Gustavo F. Padovan
http://profusion.mobi

^ permalink raw reply

* Re: [RFC 12/20] Bluetooth: fix receiving L2CAP packets over LE
From: Gustavo F. Padovan @ 2010-11-23 22:55 UTC (permalink / raw)
  To: Vinicius Costa Gomes; +Cc: linux-bluetooth
In-Reply-To: <1290524796-32246-13-git-send-email-vinicius.gomes@openbossa.org>

Hi Vinicius,

* Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2010-11-23 12:06:28 -0300]:

> As L2CAP packets coming over LE don't have any more encapsulation,
> other than L2CAP, we are able to process them as soon as they arrive.
> 
> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
> ---
>  net/bluetooth/l2cap.c |   17 +++++++++++++++--
>  1 files changed, 15 insertions(+), 2 deletions(-)

So move this patch before the SMP changes in the patchset.

-- 
Gustavo F. Padovan
http://profusion.mobi

^ permalink raw reply

* Re: [RFC 10/20] Bluetooth: Add server socket support for LE connection
From: Gustavo F. Padovan @ 2010-11-23 22:54 UTC (permalink / raw)
  To: Vinicius Costa Gomes; +Cc: linux-bluetooth, Ville Tervo
In-Reply-To: <1290524796-32246-11-git-send-email-vinicius.gomes@openbossa.org>

* Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2010-11-23 12:06:26 -0300]:

> From: Ville Tervo <ville.tervo@nokia.com>
> 
> Add support for LE server sockets.
> 
> Signed-off-by: Ville Tervo <ville.tervo@nokia.com>
> ---
>  net/bluetooth/l2cap.c |    3 +--
>  1 files changed, 1 insertions(+), 2 deletions(-)
> 
> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
> index 172bf93..e481d6b 100644
> --- a/net/bluetooth/l2cap.c
> +++ b/net/bluetooth/l2cap.c
> @@ -1438,8 +1438,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
>  	BT_DBG("");
>  
>  	/* Check if we have socket listening on cid */
> -	parent = l2cap_get_sock_by_cid(BT_LISTEN, L2CAP_CID_LE_DATA,
> -					conn->src);
> +	parent = l2cap_get_sock_by_cid(BT_LISTEN, L2CAP_CID_LE_DATA, conn->src);

I didn't get this change, commit message tell about other stuff.

-- 
Gustavo F. Padovan
http://profusion.mobi

^ permalink raw reply

* Re: [RFC 09/20] Bluetooth: Fix locking balance in l2cap_le_conn_ready
From: Gustavo F. Padovan @ 2010-11-23 22:52 UTC (permalink / raw)
  To: Vinicius Costa Gomes; +Cc: linux-bluetooth, Ville Tervo
In-Reply-To: <1290524796-32246-10-git-send-email-vinicius.gomes@openbossa.org>

Hi Ville,

* Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2010-11-23 12:06:25 -0300]:

> From: Ville Tervo <ville.tervo@nokia.com>
> 
> Don't try to unlock sock if the lock was not held.
> 
> Signed-off-by: Ville Tervo <ville.tervo@nokia.com>
> ---
>  net/bluetooth/l2cap.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
> index 5894662..172bf93 100644
> --- a/net/bluetooth/l2cap.c
> +++ b/net/bluetooth/l2cap.c
> @@ -1441,7 +1441,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
>  	parent = l2cap_get_sock_by_cid(BT_LISTEN, L2CAP_CID_LE_DATA,
>  					conn->src);
>  	if (!parent)
> -		goto clean;
> +		return;

Why not merging this into patch 5/20?

-- 
Gustavo F. Padovan
http://profusion.mobi

^ permalink raw reply

* Re: [RFC 06/20] Bluetooth: Do not send disconn comand over LE links
From: Gustavo F. Padovan @ 2010-11-23 22:48 UTC (permalink / raw)
  To: Vinicius Costa Gomes; +Cc: linux-bluetooth, Ville Tervo
In-Reply-To: <1290524796-32246-7-git-send-email-vinicius.gomes@openbossa.org>

* Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2010-11-23 12:06:22 -0300]:

> From: Ville Tervo <ville.tervo@nokia.com>
> 
> l2cap over LE links can be disconnected without sending
> disconnect command first.
> 
> Signed-off-by: Ville Tervo <ville.tervo@nokia.com>
> ---
>  net/bluetooth/l2cap.c |   15 ++++++++++-----
>  1 files changed, 10 insertions(+), 5 deletions(-)
> 
> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
> index 0b583c4..5894662 100644
> --- a/net/bluetooth/l2cap.c
> +++ b/net/bluetooth/l2cap.c
> @@ -873,6 +873,8 @@ static void l2cap_sock_kill(struct sock *sk)
>  
>  static void __l2cap_sock_close(struct sock *sk, int reason)
>  {
> +	struct l2cap_conn *conn;
> +
>  	BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
>  
>  	switch (sk->sk_state) {
> @@ -882,8 +884,10 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
>  
>  	case BT_CONNECTED:
>  	case BT_CONFIG:
> -		if (sk->sk_type == SOCK_SEQPACKET ||
> -				sk->sk_type == SOCK_STREAM) {
> +		conn = l2cap_pi(sk)->conn;
> +		if ((sk->sk_type == SOCK_SEQPACKET ||
> +				sk->sk_type == SOCK_STREAM) &&
> +				conn->hcon->type != LE_LINK) {

Makes more senses check for conn->hcon->type == ACL_LINK.

>  			struct l2cap_conn *conn = l2cap_pi(sk)->conn;
>  
>  			l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
> @@ -893,9 +897,10 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
>  		break;
>  
>  	case BT_CONNECT2:
> -		if (sk->sk_type == SOCK_SEQPACKET ||
> -				sk->sk_type == SOCK_STREAM) {
> -			struct l2cap_conn *conn = l2cap_pi(sk)->conn;
> +		conn = l2cap_pi(sk)->conn;
> +		if ((sk->sk_type == SOCK_SEQPACKET ||
> +				sk->sk_type == SOCK_STREAM) &&
> +				conn->hcon->type != LE_LINK) {

Same here.

-- 
Gustavo F. Padovan
http://profusion.mobi

^ permalink raw reply

* Re: [PATCH 1/7] Add phonebook request
From: Luiz Augusto von Dentz @ 2010-11-23 21:07 UTC (permalink / raw)
  To: Dmitriy Paliy; +Cc: linux-bluetooth
In-Reply-To: <1290535889-17038-2-git-send-email-dmitriy.paliy@nokia.com>

Hi,

On Tue, Nov 23, 2010 at 8:11 PM, Dmitriy Paliy <dmitriy.paliy@nokia.com> wrote:
> Add phonebook request structure to phonebook-tracker and pointer to
> pending call in PBAP object.
> ---
>  plugins/pbap.c              |    1 +
>  plugins/phonebook-tracker.c |    4 ++++
>  2 files changed, 5 insertions(+), 0 deletions(-)
>
> diff --git a/plugins/pbap.c b/plugins/pbap.c
> index 1a7d001..3264e85 100644
> --- a/plugins/pbap.c
> +++ b/plugins/pbap.c
> @@ -147,6 +147,7 @@ struct pbap_session {
>  struct pbap_object {
>        GString *buffer;
>        struct pbap_session *session;
> +       void *request;
>  };
>
>  static const uint8_t PBAP_TARGET[TARGET_SIZE] = {
> diff --git a/plugins/phonebook-tracker.c b/plugins/phonebook-tracker.c
> index 20053f6..afe0f2f 100644
> --- a/plugins/phonebook-tracker.c
> +++ b/plugins/phonebook-tracker.c
> @@ -1035,6 +1035,10 @@ struct phonebook_index {
>        int index;
>  };
>
> +struct phonebook_req {
> +       DBusPendingCall *call;
> +};

No need to create a struct here, you can pass the call since there is
not other members.

-- 
Luiz Augusto von Dentz
Computer Engineer

^ permalink raw reply

* [PATCH 7/7] Code clean-up: lines longer 80 symbols removed
From: Dmitriy Paliy @ 2010-11-23 18:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Dmitriy Paliy
In-Reply-To: <1290535889-17038-1-git-send-email-dmitriy.paliy@nokia.com>

---
 plugins/pbap.c |   11 ++++++-----
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/plugins/pbap.c b/plugins/pbap.c
index 5137d07..40a5417 100644
--- a/plugins/pbap.c
+++ b/plugins/pbap.c
@@ -263,8 +263,8 @@ static void query_result(const char *buffer, size_t bufsize, int vcards,
 	if (!pbap->obj->buffer)
 		pbap->obj->buffer = g_string_new_len(buffer, bufsize);
 	else
-		pbap->obj->buffer = g_string_append_len(pbap->obj->buffer, buffer,
-								bufsize);
+		pbap->obj->buffer = g_string_append_len(pbap->obj->buffer,
+							buffer, bufsize);
 
 	obex_object_set_io_flags(pbap->obj, G_IO_IN, 0);
 }
@@ -423,11 +423,12 @@ static void cache_ready_notify(void *user_data)
 	for (; l && max; l = l->next, max--) {
 		const struct cache_entry *entry = l->data;
 
-		g_string_append_printf(pbap->obj->buffer, VCARD_LISTING_ELEMENT,
-						entry->handle, entry->name);
+		g_string_append_printf(pbap->obj->buffer,
+			VCARD_LISTING_ELEMENT, entry->handle, entry->name);
 	}
 
-	pbap->obj->buffer = g_string_append(pbap->obj->buffer, VCARD_LISTING_END);
+	pbap->obj->buffer = g_string_append(pbap->obj->buffer,
+							VCARD_LISTING_END);
 
 	g_slist_free(sorted);
 
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 6/7] Add update phonebook_create_cache
From: Dmitriy Paliy @ 2010-11-23 18:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Dmitriy Paliy
In-Reply-To: <1290535889-17038-1-git-send-email-dmitriy.paliy@nokia.com>

Add phonebook_create_cache updated function prototype to return void
pointer to backend specific request and error code. All backend
handlers updated accordingly (phonebook-tracker.c,
phonebook-dummy.c, and phonebook-ebook.c).

In PBAP vobject_list_open and vobject_vcard_open are updated to
store pointer to phonebook request. IRMC is not modified.

Phonebook request is created and stored dynamically only for tracker.
---
 plugins/pbap.c              |   18 +++++++++++++-----
 plugins/phonebook-dummy.c   |   16 ++++++++++------
 plugins/phonebook-ebook.c   |   20 ++++++++++++++------
 plugins/phonebook-tracker.c |   25 ++++++++++++++++++++-----
 plugins/phonebook.h         |    4 ++--
 5 files changed, 59 insertions(+), 24 deletions(-)

diff --git a/plugins/pbap.c b/plugins/pbap.c
index 2ce580b..5137d07 100644
--- a/plugins/pbap.c
+++ b/plugins/pbap.c
@@ -455,6 +455,13 @@ static void cache_entry_done(void *user_data)
 		return;
 	}
 
+	/*
+	 * If request to create cache succeeded, vobject and phonebook
+	 * request were created, then previous request has to be deleted,
+	 * even though there is no pending call anymore. In
+	 * phonebook_get_entry a new request will be created.
+	 */
+	phonebook_req_cancel(pbap->obj->request);
 	pbap->obj->request = phonebook_get_entry(pbap->folder, id,
 				pbap->params, query_result, pbap, &ret);
 	if (ret < 0)
@@ -759,6 +766,7 @@ static void *vobject_list_open(const char *name, int oflag, mode_t mode,
 {
 	struct pbap_session *pbap = context;
 	int ret;
+	void *request = NULL;
 
 	DBG("name %s context %p valid %d", name, context, pbap->cache.valid);
 
@@ -788,14 +796,14 @@ static void *vobject_list_open(const char *name, int oflag, mode_t mode,
 		goto done;
 	}
 
-	ret = phonebook_create_cache(name,
-		cache_entry_notify, cache_ready_notify, pbap);
+	request = phonebook_create_cache(name,
+		cache_entry_notify, cache_ready_notify, pbap, &ret);
 
 	if (ret < 0)
 		goto fail;
 
 done:
-	return vobject_create(pbap, NULL);
+	return vobject_create(pbap, request);
 
 fail:
 	if (err)
@@ -827,8 +835,8 @@ static void *vobject_vcard_open(const char *name, int oflag, mode_t mode,
 
 	if (pbap->cache.valid == FALSE) {
 		pbap->find_handle = handle;
-		ret = phonebook_create_cache(pbap->folder, cache_entry_notify,
-						cache_entry_done, pbap);
+		request = phonebook_create_cache(pbap->folder,
+			cache_entry_notify, cache_entry_done, pbap, &ret);
 		goto done;
 	}
 
diff --git a/plugins/phonebook-dummy.c b/plugins/phonebook-dummy.c
index 7a963b6..a269ea8 100644
--- a/plugins/phonebook-dummy.c
+++ b/plugins/phonebook-dummy.c
@@ -528,8 +528,8 @@ void *phonebook_get_entry(const char *folder, const char *id,
 	return NULL;
 }
 
-int phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
-		phonebook_cache_ready_cb ready_cb, void *user_data)
+void *phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
+		phonebook_cache_ready_cb ready_cb, void *user_data, int *err)
 {
 	struct cache_query *query;
 	char *foldername;
@@ -540,9 +540,10 @@ int phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
 	g_free(foldername);
 
 	if (dp == NULL) {
-		int err = errno;
-		DBG("opendir(): %s(%d)", strerror(err), err);
-		return -ENOENT;
+		DBG("opendir(): %s(%d)", strerror(errno), errno);
+		if (err)
+			*err = -ENOENT;
+		return NULL;
 	}
 
 	query = g_new0(struct cache_query, 1);
@@ -553,5 +554,8 @@ int phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
 
 	g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, create_cache, query,
 								query_free);
-	return 0;
+	if (err)
+		*err = 0;
+
+	return NULL;
 }
diff --git a/plugins/phonebook-ebook.c b/plugins/phonebook-ebook.c
index 2515bb0..5d7f624 100644
--- a/plugins/phonebook-ebook.c
+++ b/plugins/phonebook-ebook.c
@@ -459,15 +459,18 @@ void *phonebook_get_entry(const char *folder, const char *id,
 	return NULL;
 }
 
-int phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
-			phonebook_cache_ready_cb ready_cb, void *user_data)
+void *phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
+		phonebook_cache_ready_cb ready_cb, void *user_data, int *err)
 {
 	struct cache_query *data;
 	EBookQuery *query;
 	gboolean ret;
 
-	if (g_strcmp0("/telecom/pb", name) != 0)
-		return -ENOENT;
+	if (g_strcmp0("/telecom/pb", name) != 0) {
+		if (err)
+			*err = -ENOENT;
+		return NULL;
+	}
 
 	query = e_book_query_any_field_contains("");
 
@@ -480,8 +483,13 @@ int phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
 	e_book_query_unref(query);
 	if (ret != FALSE) {
 		g_free(data);
-		return -EFAULT;
+		if (err)
+			*err = -EFAULT;
+		return NULL;
 	}
 
-	return 0;
+	if (err)
+		*err = 0;
+
+	return NULL;
 }
diff --git a/plugins/phonebook-tracker.c b/plugins/phonebook-tracker.c
index ead583e..3577212 100644
--- a/plugins/phonebook-tracker.c
+++ b/plugins/phonebook-tracker.c
@@ -1907,22 +1907,37 @@ void *phonebook_get_entry(const char *folder, const char *id,
 	return req;
 }
 
-int phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
-			phonebook_cache_ready_cb ready_cb, void *user_data)
+void *phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
+		phonebook_cache_ready_cb ready_cb, void *user_data, int *err)
 {
 	struct cache_data *cache;
 	const char *query;
+	int ret;
+	struct phonebook_req *req;
 
 	DBG("name %s", name);
 
 	query = folder2query(name);
-	if (query == NULL)
-		return -ENOENT;
+	if (query == NULL) {
+		if (err)
+			*err = -ENOENT;
+		return NULL;
+	}
 
 	cache = g_new0(struct cache_data, 1);
 	cache->entry_cb = entry_cb;
 	cache->ready_cb = ready_cb;
 	cache->user_data = user_data;
 
-	return query_tracker(query, 7, add_to_cache, cache, NULL);
+	req = g_new0(struct phonebook_req, 1);
+
+	ret = query_tracker(query, 7, add_to_cache, cache, req);
+
+	if (ret < 0)
+		phonebook_req_cancel(req);
+
+	if (err)
+		*err = ret;
+
+	return req;
 }
diff --git a/plugins/phonebook.h b/plugins/phonebook.h
index 5342841..b6ae5a8 100644
--- a/plugins/phonebook.h
+++ b/plugins/phonebook.h
@@ -105,8 +105,8 @@ void *phonebook_get_entry(const char *folder, const char *id,
  * Cache will store only the necessary information required to reply to
  * PullvCardListing request and verify if a given contact belongs to the source.
  */
-int phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
-			phonebook_cache_ready_cb ready_cb, void *user_data);
+void *phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
+		phonebook_cache_ready_cb ready_cb, void *user_data, int *err);
 
 /* 
  * Function used to cancel pending request to backend and free resources
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 5/7] Add update phonebook_get_entry
From: Dmitriy Paliy @ 2010-11-23 18:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Dmitriy Paliy
In-Reply-To: <1290535889-17038-1-git-send-email-dmitriy.paliy@nokia.com>

Add phonebook_get_entry function prototype update to return void
pointer to backend specific request and error code. All backend
handlers updated accordingly (phonebook-tracker.c,
phonebook-dummy.c, and phonebook-ebook.c).

Phonebook request is created dynamically only for tracker,
therefore, removed appropriately when PBAP object is destroyed.

IRMC does not invoke phonebook_get_entry therefore is not changed.
---
 plugins/pbap.c              |   11 ++++++-----
 plugins/phonebook-dummy.c   |   18 +++++++++++-------
 plugins/phonebook-ebook.c   |   15 ++++++++++-----
 plugins/phonebook-tracker.c |   17 ++++++++++++-----
 plugins/phonebook.h         |    4 ++--
 5 files changed, 41 insertions(+), 24 deletions(-)

diff --git a/plugins/pbap.c b/plugins/pbap.c
index 0ceaf95..2ce580b 100644
--- a/plugins/pbap.c
+++ b/plugins/pbap.c
@@ -455,8 +455,8 @@ static void cache_entry_done(void *user_data)
 		return;
 	}
 
-	ret = phonebook_get_entry(pbap->folder, id, pbap->params,
-						query_result, pbap);
+	pbap->obj->request = phonebook_get_entry(pbap->folder, id,
+				pbap->params, query_result, pbap, &ret);
 	if (ret < 0)
 		obex_object_set_io_flags(pbap->obj, G_IO_ERR, ret);
 }
@@ -811,6 +811,7 @@ static void *vobject_vcard_open(const char *name, int oflag, mode_t mode,
 	const char *id;
 	uint32_t handle;
 	int ret;
+	void *request = NULL;
 
 	DBG("name %s context %p valid %d", name, context, pbap->cache.valid);
 
@@ -837,14 +838,14 @@ static void *vobject_vcard_open(const char *name, int oflag, mode_t mode,
 		goto fail;
 	}
 
-	ret = phonebook_get_entry(pbap->folder, id, pbap->params, query_result,
-									pbap);
+	request = phonebook_get_entry(pbap->folder, id, pbap->params,
+						query_result, pbap, &ret);
 
 done:
 	if (ret < 0)
 		goto fail;
 
-	return vobject_create(pbap, NULL);
+	return vobject_create(pbap, request);
 
 fail:
 	if (err)
diff --git a/plugins/phonebook-dummy.c b/plugins/phonebook-dummy.c
index d9a5a29..7a963b6 100644
--- a/plugins/phonebook-dummy.c
+++ b/plugins/phonebook-dummy.c
@@ -496,9 +496,9 @@ void *phonebook_pull(const char *name, const struct apparam_field *params,
 	return NULL;
 }
 
-int phonebook_get_entry(const char *folder, const char *id,
-					const struct apparam_field *params,
-					phonebook_cb cb, void *user_data)
+void *phonebook_get_entry(const char *folder, const char *id,
+			const struct apparam_field *params, phonebook_cb cb,
+			void *user_data, int *err)
 {
 	struct dummy_data *dummy;
 	char *filename;
@@ -508,9 +508,10 @@ int phonebook_get_entry(const char *folder, const char *id,
 
 	fd = open(filename, O_RDONLY);
 	if (fd < 0) {
-		int err = errno;
-		DBG("open(): %s(%d)", strerror(err), err);
-		return -ENOENT;
+		DBG("open(): %s(%d)", strerror(errno), errno);
+		if (err)
+			*err = -ENOENT;
+		return NULL;
 	}
 
 	dummy = g_new0(struct dummy_data, 1);
@@ -521,7 +522,10 @@ int phonebook_get_entry(const char *folder, const char *id,
 
 	g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, read_entry, dummy, dummy_free);
 
-	return 0;
+	if (err)
+		*err = 0;
+
+	return NULL;
 }
 
 int phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
diff --git a/plugins/phonebook-ebook.c b/plugins/phonebook-ebook.c
index 9097a0b..2515bb0 100644
--- a/plugins/phonebook-ebook.c
+++ b/plugins/phonebook-ebook.c
@@ -435,9 +435,9 @@ void *phonebook_pull(const char *name, const struct apparam_field *params,
 	return NULL;
 }
 
-int phonebook_get_entry(const char *folder, const char *id,
-					const struct apparam_field *params,
-					phonebook_cb cb, void *user_data)
+void *phonebook_get_entry(const char *folder, const char *id,
+				const struct apparam_field *params,
+				phonebook_cb cb, void *user_data, int *err)
 {
 	struct contacts_query *data;
 
@@ -448,10 +448,15 @@ int phonebook_get_entry(const char *folder, const char *id,
 
 	if (e_book_async_get_contact(ebook, id, ebook_entry_cb, data)) {
 		g_free(data);
-		return -ENOENT;
+		if (err)
+			*err = -ENOENT;
+		return NULL;
 	}
 
-	return 0;
+	if (err)
+		*err = 0;
+
+	return NULL;
 }
 
 int phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
diff --git a/plugins/phonebook-tracker.c b/plugins/phonebook-tracker.c
index bce60d6..ead583e 100644
--- a/plugins/phonebook-tracker.c
+++ b/plugins/phonebook-tracker.c
@@ -1868,13 +1868,14 @@ void *phonebook_pull(const char *name, const struct apparam_field *params,
 	return req;
 }
 
-int phonebook_get_entry(const char *folder, const char *id,
-					const struct apparam_field *params,
-					phonebook_cb cb, void *user_data)
+void *phonebook_get_entry(const char *folder, const char *id,
+				const struct apparam_field *params,
+				phonebook_cb cb, void *user_data, int *err)
 {
 	struct phonebook_data *data;
 	char *query;
 	int ret;
+	struct phonebook_req *req = g_new0(struct phonebook_req, 1);
 
 	DBG("folder %s id %s", folder, id);
 
@@ -1893,11 +1894,17 @@ int phonebook_get_entry(const char *folder, const char *id,
 								id, id, id);
 
 	ret = query_tracker(query, PULL_QUERY_COL_AMOUNT, pull_contacts, data,
-									NULL);
+									req);
 
 	g_free(query);
 
-	return ret;
+	if (ret < 0)
+		phonebook_req_cancel(req);
+
+	if (err)
+		*err = ret;
+
+	return req;
 }
 
 int phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
diff --git a/plugins/phonebook.h b/plugins/phonebook.h
index 951b370..5342841 100644
--- a/plugins/phonebook.h
+++ b/plugins/phonebook.h
@@ -95,9 +95,9 @@ void *phonebook_pull(const char *name, const struct apparam_field *params,
  * return only the content based on the application parameters requested
  * by the client.
  */
-int phonebook_get_entry(const char *folder, const char *id,
+void *phonebook_get_entry(const char *folder, const char *id,
 				const struct apparam_field *params,
-				phonebook_cb cb, void *user_data);
+				phonebook_cb cb, void *user_data, int *err);
 
 /*
  * PBAP core will keep the contacts cache per folder. SetPhoneBook or
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 4/7] Add update phonebook_pull
From: Dmitriy Paliy @ 2010-11-23 18:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Dmitriy Paliy
In-Reply-To: <1290535889-17038-1-git-send-email-dmitriy.paliy@nokia.com>

Add phonebook_pull function prototype is updated to return void
pointer to backend specific request and error code. All backend
handlers updated accordingly (phonebook-tracker.c,
phonebook-dummy.c, and phonebook-ebook.c).

Phonebook request is created dynamically only for tracker,
therefore, removed appropriately when PBAP object is destroyed,
or IRMC close method invoked.

query_tracker is updated to return pending call request.

IRMC is updated to handle pending request when phonebook is pulled.
---
 plugins/irmc.c              |   14 +++++++-------
 plugins/pbap.c              |   19 ++++++++++++++-----
 plugins/phonebook-dummy.c   |   21 ++++++++++++++++-----
 plugins/phonebook-ebook.c   |   13 ++++++++++---
 plugins/phonebook-tracker.c |   37 ++++++++++++++++++++++++++++---------
 plugins/phonebook.h         |    4 ++--
 6 files changed, 77 insertions(+), 31 deletions(-)

diff --git a/plugins/irmc.c b/plugins/irmc.c
index f7ad33b..4c11933 100644
--- a/plugins/irmc.c
+++ b/plugins/irmc.c
@@ -110,6 +110,7 @@ struct irmc_session {
 	char did[DID_LEN];
 	char manu[DID_LEN];
 	char model[DID_LEN];
+	void *request;
 };
 
 #define IRMC_TARGET_SIZE 9
@@ -210,11 +211,8 @@ static void *irmc_connect(struct obex_session *os, int *err)
 	param->maxlistcount = 0; /* to count the number of vcards... */
 	param->filter = 0x200085; /* UID TEL N VERSION */
 	irmc->params = param;
-	phonebook_pull("telecom/pb.vcf", irmc->params, phonebook_size_result,
-									irmc);
-
-	if (err)
-		*err = 0;
+	irmc->request = phonebook_pull("telecom/pb.vcf", irmc->params,
+					phonebook_size_result, irmc, err);
 
 	return irmc;
 }
@@ -298,8 +296,8 @@ static void *irmc_open_pb(const char *name, struct irmc_session *irmc,
 
 	if (!g_strcmp0(name, ".vcf")) {
 		/* how can we tell if the vcard count call already finished? */
-		ret = phonebook_pull("telecom/pb.vcf", irmc->params,
-							query_result, irmc);
+		irmc->request = phonebook_pull("telecom/pb.vcf", irmc->params,
+						query_result, irmc, &ret);
 		if (ret < 0) {
 			DBG("phonebook_pull failed...");
 			goto fail;
@@ -435,6 +433,8 @@ static int irmc_close(void *object)
 		irmc->buffer = NULL;
 	}
 
+	phonebook_req_cancel(irmc->request);
+
 	return 0;
 }
 
diff --git a/plugins/pbap.c b/plugins/pbap.c
index 3264e85..0ceaf95 100644
--- a/plugins/pbap.c
+++ b/plugins/pbap.c
@@ -698,13 +698,15 @@ static struct obex_service_driver pbap = {
 	.chkput = pbap_chkput
 };
 
-static struct pbap_object *vobject_create(struct pbap_session *pbap)
+static struct pbap_object *vobject_create(struct pbap_session *pbap,
+								void *request)
 {
 	struct pbap_object *obj;
 
 	obj = g_new0(struct pbap_object, 1);
 	obj->session = pbap;
 	pbap->obj = obj;
+	obj->request = request;
 
 	return obj;
 }
@@ -715,6 +717,7 @@ static void *vobject_pull_open(const char *name, int oflag, mode_t mode,
 	struct pbap_session *pbap = context;
 	phonebook_cb cb;
 	int ret;
+	void *request = NULL;
 
 	DBG("name %s context %p maxlistcount %d", name, context,
 						pbap->params->maxlistcount);
@@ -734,11 +737,15 @@ static void *vobject_pull_open(const char *name, int oflag, mode_t mode,
 	else
 		cb = query_result;
 
-	ret = phonebook_pull(name, pbap->params, cb, pbap);
+	request = phonebook_pull(name, pbap->params, cb, pbap, &ret);
+
 	if (ret < 0)
 		goto fail;
 
-	return vobject_create(pbap);
+	if (err)
+		*err = ret;
+
+	return vobject_create(pbap, request);
 
 fail:
 	if (err)
@@ -788,7 +795,7 @@ static void *vobject_list_open(const char *name, int oflag, mode_t mode,
 		goto fail;
 
 done:
-	return vobject_create(pbap);
+	return vobject_create(pbap, NULL);
 
 fail:
 	if (err)
@@ -837,7 +844,7 @@ done:
 	if (ret < 0)
 		goto fail;
 
-	return vobject_create(pbap);
+	return vobject_create(pbap, NULL);
 
 fail:
 	if (err)
@@ -913,6 +920,8 @@ static int vobject_close(void *object)
 	if (obj->buffer)
 		g_string_free(obj->buffer, TRUE);
 
+	phonebook_req_cancel(obj->request);
+
 	g_free(obj);
 
 	return 0;
diff --git a/plugins/phonebook-dummy.c b/plugins/phonebook-dummy.c
index 7c549fa..d9a5a29 100644
--- a/plugins/phonebook-dummy.c
+++ b/plugins/phonebook-dummy.c
@@ -447,8 +447,12 @@ done:
 	return relative;
 }
 
-int phonebook_pull(const char *name, const struct apparam_field *params,
-					phonebook_cb cb, void *user_data)
+void phonebook_req_cancel(void *request)
+{
+}
+
+void *phonebook_pull(const char *name, const struct apparam_field *params,
+				phonebook_cb cb, void *user_data, int *err)
 {
 	struct dummy_data *dummy;
 	char *filename, *folder;
@@ -463,14 +467,18 @@ int phonebook_pull(const char *name, const struct apparam_field *params,
 
 	if (!g_str_has_suffix(filename, ".vcf")) {
 		g_free(filename);
-		return -EBADR;
+		if (err)
+			*err = -EBADR;
+		return NULL;
 	}
 
 	folder = g_strndup(filename, strlen(filename) - 4);
 	g_free(filename);
 	if (!is_dir(folder)) {
 		g_free(folder);
-		return -ENOENT;
+		if (err)
+			*err = -ENOENT;
+		return NULL;
 	}
 
 	dummy = g_new0(struct dummy_data, 1);
@@ -482,7 +490,10 @@ int phonebook_pull(const char *name, const struct apparam_field *params,
 
 	g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, read_dir, dummy, dummy_free);
 
-	return 0;
+	if (err)
+		*err = 0;
+
+	return NULL;
 }
 
 int phonebook_get_entry(const char *folder, const char *id,
diff --git a/plugins/phonebook-ebook.c b/plugins/phonebook-ebook.c
index 073ff33..9097a0b 100644
--- a/plugins/phonebook-ebook.c
+++ b/plugins/phonebook-ebook.c
@@ -408,8 +408,12 @@ done:
 	return fullname;
 }
 
-int phonebook_pull(const char *name, const struct apparam_field *params,
-					phonebook_cb cb, void *user_data)
+void phonebook_req_cancel(void *request)
+{
+}
+
+void *phonebook_pull(const char *name, const struct apparam_field *params,
+				phonebook_cb cb, void *user_data, int *err)
 {
 	struct contacts_query *data;
 	EBookQuery *query;
@@ -425,7 +429,10 @@ int phonebook_pull(const char *name, const struct apparam_field *params,
 
 	e_book_query_unref(query);
 
-	return 0;
+	if (err)
+		*err = 0;
+
+	return NULL;
 }
 
 int phonebook_get_entry(const char *folder, const char *id,
diff --git a/plugins/phonebook-tracker.c b/plugins/phonebook-tracker.c
index 6ee5750..bce60d6 100644
--- a/plugins/phonebook-tracker.c
+++ b/plugins/phonebook-tracker.c
@@ -1203,7 +1203,8 @@ done:
 }
 
 static int query_tracker(const char *query, int num_fields,
-				reply_list_foreach_t callback, void *user_data)
+			reply_list_foreach_t callback, void *user_data,
+			struct phonebook_req *req)
 {
 	struct pending_reply *pending;
 	DBusPendingCall *call;
@@ -1232,9 +1233,11 @@ static int query_tracker(const char *query, int num_fields,
 	pending->num_fields = num_fields;
 
 	dbus_pending_call_set_notify(call, query_reply, pending, NULL);
-	dbus_pending_call_unref(call);
 	dbus_message_unref(msg);
 
+	if (req)
+		req->call = call;
+
 	return 0;
 }
 
@@ -1819,13 +1822,15 @@ void phonebook_req_cancel(void *request)
 	req = NULL;
 }
 
-int phonebook_pull(const char *name, const struct apparam_field *params,
-					phonebook_cb cb, void *user_data)
+void *phonebook_pull(const char *name, const struct apparam_field *params,
+				phonebook_cb cb, void *user_data, int *err)
 {
 	struct phonebook_data *data;
 	const char *query;
 	reply_list_foreach_t pull_cb;
 	int col_amount;
+	struct phonebook_req *req;
+	int ret;
 
 	DBG("name %s", name);
 
@@ -1839,15 +1844,28 @@ int phonebook_pull(const char *name, const struct apparam_field *params,
 		pull_cb = pull_contacts;
 	}
 
-	if (query == NULL)
-		return -ENOENT;
+	if (query == NULL) {
+		if (err)
+			*err = -ENOENT;
+		return NULL;
+	}
 
 	data = g_new0(struct phonebook_data, 1);
 	data->params = params;
 	data->user_data = user_data;
 	data->cb = cb;
 
-	return query_tracker(query, col_amount, pull_cb, data);
+	req = g_new0(struct phonebook_req, 1);
+	
+	ret = query_tracker(query, col_amount, pull_cb, data, req);
+
+	if (err)
+		*err = ret;
+
+	if (ret < 0)
+		phonebook_req_cancel(req);
+
+	return req;
 }
 
 int phonebook_get_entry(const char *folder, const char *id,
@@ -1874,7 +1892,8 @@ int phonebook_get_entry(const char *folder, const char *id,
 		query = g_strdup_printf(CONTACTS_OTHER_QUERY_FROM_URI,
 								id, id, id);
 
-	ret = query_tracker(query, PULL_QUERY_COL_AMOUNT, pull_contacts, data);
+	ret = query_tracker(query, PULL_QUERY_COL_AMOUNT, pull_contacts, data,
+									NULL);
 
 	g_free(query);
 
@@ -1898,5 +1917,5 @@ int phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
 	cache->ready_cb = ready_cb;
 	cache->user_data = user_data;
 
-	return query_tracker(query, 7, add_to_cache, cache);
+	return query_tracker(query, 7, add_to_cache, cache, NULL);
 }
diff --git a/plugins/phonebook.h b/plugins/phonebook.h
index 7ae5ccc..951b370 100644
--- a/plugins/phonebook.h
+++ b/plugins/phonebook.h
@@ -86,8 +86,8 @@ char *phonebook_set_folder(const char *current_folder,
  * entries of a given folder. The back-end MUST return only the content based
  * on the application parameters requested by the client.
  */
-int phonebook_pull(const char *name, const struct apparam_field *params,
-					phonebook_cb cb, void *user_data);
+void *phonebook_pull(const char *name, const struct apparam_field *params,
+				phonebook_cb cb, void *user_data, int *err);
 
 /*
  * Function used to retrieve a contact from the backend. Only contacts
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 3/7] Add phonebook_req_cancel to tracker
From: Dmitriy Paliy @ 2010-11-23 18:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Dmitriy Paliy
In-Reply-To: <1290535889-17038-1-git-send-email-dmitriy.paliy@nokia.com>

Add phonebook_req_cancel function to phonebook_tracker.c that cancels
pending request and deallocates memory of requst object.
---
 plugins/phonebook-tracker.c |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/plugins/phonebook-tracker.c b/plugins/phonebook-tracker.c
index afe0f2f..6ee5750 100644
--- a/plugins/phonebook-tracker.c
+++ b/plugins/phonebook-tracker.c
@@ -1803,6 +1803,22 @@ done:
 	return path;
 }
 
+void phonebook_req_cancel(void *request)
+{
+	struct phonebook_req *req = request;
+
+	if (!req)
+		return;
+
+	if (req->call) {
+		dbus_pending_call_cancel(req->call);
+		dbus_pending_call_unref(req->call);
+	}
+
+	g_free(req);
+	req = NULL;
+}
+
 int phonebook_pull(const char *name, const struct apparam_field *params,
 					phonebook_cb cb, void *user_data)
 {
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 2/7] Add phonebook_req_cancel prototype
From: Dmitriy Paliy @ 2010-11-23 18:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Dmitriy Paliy
In-Reply-To: <1290535889-17038-1-git-send-email-dmitriy.paliy@nokia.com>

Add phonebook_req_cancel function prototype to cancel pending request
to backend.
---
 plugins/phonebook.h |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/plugins/phonebook.h b/plugins/phonebook.h
index d7cfa46..7ae5ccc 100644
--- a/plugins/phonebook.h
+++ b/plugins/phonebook.h
@@ -107,3 +107,9 @@ int phonebook_get_entry(const char *folder, const char *id,
  */
 int phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
 			phonebook_cache_ready_cb ready_cb, void *user_data);
+
+/* 
+ * Function used to cancel pending request to backend and free resources
+ * allocated for phonebook request structure.
+ */
+void phonebook_req_cancel(void *request);
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 1/7] Add phonebook request
From: Dmitriy Paliy @ 2010-11-23 18:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Dmitriy Paliy
In-Reply-To: <1290535889-17038-1-git-send-email-dmitriy.paliy@nokia.com>

Add phonebook request structure to phonebook-tracker and pointer to
pending call in PBAP object.
---
 plugins/pbap.c              |    1 +
 plugins/phonebook-tracker.c |    4 ++++
 2 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/plugins/pbap.c b/plugins/pbap.c
index 1a7d001..3264e85 100644
--- a/plugins/pbap.c
+++ b/plugins/pbap.c
@@ -147,6 +147,7 @@ struct pbap_session {
 struct pbap_object {
 	GString *buffer;
 	struct pbap_session *session;
+	void *request;
 };
 
 static const uint8_t PBAP_TARGET[TARGET_SIZE] = {
diff --git a/plugins/phonebook-tracker.c b/plugins/phonebook-tracker.c
index 20053f6..afe0f2f 100644
--- a/plugins/phonebook-tracker.c
+++ b/plugins/phonebook-tracker.c
@@ -1035,6 +1035,10 @@ struct phonebook_index {
 	int index;
 };
 
+struct phonebook_req {
+	DBusPendingCall *call;
+};
+
 static DBusConnection *connection = NULL;
 
 static const char *name2query(const char *name)
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 0/7] Cancel pending phonebook request
From: Dmitriy Paliy @ 2010-11-23 18:11 UTC (permalink / raw)
  To: linux-bluetooth

Hi,

In this patch, pending request to backend is calceled when OBEX
object is destroyed. Such prevents situations of response on
query arriving to destroyed object, e.g. OBEX session is closed
in the middle of query to tracker.

Such required some changes in phonebook API. More specifcally,
changes in API affect phonebook_pull, phonebook_get_entry, and 
phonebook_create_cache functions. phonebook_req_cancel is added
to cancel pending request and deallocate resources respective to
it.

Phonebook request structure is specific to each backend and
created dinamically only for tracker. Therefore phonebook-dummy
and phonebook-ebook methods always return NULL instead of pending
request.

For PBAP, the object holds pointer to pending call. In IRMC, it 
is session where the pointer is stored and pending call canceled 
when closing OBEX object, and valid for phonebook_pull only.

BR,
Dmitriy


^ permalink raw reply

* Re: [RFC 02/20] Bluetooth: Add LE connect support
From: Gustavo F. Padovan @ 2010-11-23 17:57 UTC (permalink / raw)
  To: Vinicius Costa Gomes; +Cc: linux-bluetooth, Ville Tervo
In-Reply-To: <1290524796-32246-3-git-send-email-vinicius.gomes@openbossa.org>

Hi Ville,

* Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2010-11-23 12:06:18 -0300]:

> From: Ville Tervo <ville.tervo@nokia.com>
> 
> Bluetooth V4.0 adds support for Low Energy (LE)
> connections. Specification introduses new set
> of hci commands to control LE connection.
> This patch adds logic to create, cancel and
> disconnect LE connections
> 
> Signed-off-by: Ville Tervo <ville.tervo@nokia.com>

I remember Marcel acked some of these patches. Why the ack is not here?
It makes life easier if you tell who is acking your patch already.

-- 
Gustavo F. Padovan
http://profusion.mobi

^ permalink raw reply

* Re: sdptool hanging remote
From: Vinicius Costa Gomes @ 2010-11-23 17:51 UTC (permalink / raw)
  To: Grahame Jordan; +Cc: linux-bluetooth
In-Reply-To: <4CEB532F.1070804@theforce.com.au>

On 16:37 Tue 23 Nov     , Grahame Jordan wrote:
> Hi,
> 
> I am using bluez-4.77 on a Gumstix Verdex kernel 2.4.32 patch 21
> 
> When I run:
> sdptool records 00:80:37:2F:06:08"
> from the Workstation Ubuntu 10.04 Bluez-4.6? to the Gumstix the Gumstix 
> hangs.
> It does not hang completely but is very busy. It hangs for about 20 
> seconds and then releases for about 1 second
> before it locks up again.

I couldn't find anything that could solve this kind of problem in the logs
between 4.6 and the git head. But anyway, could you give a try to 4.80, or
better yet, the git head[1]? and see if the problem still happens?

> 
> I have tried this on several different Gumstix with the same issue.
> 
> Changing workstations from Ubuntu 10.04 to Ubuntu 8.04 does make a 
> difference.
>  From Ubuntu 8.04 there seems to be no problem. blue-utils 3.26?
> 

A really helpful piece of information that you could provide is the hcidump[2]
logs of both cases, just be sure to give hcidump the options "-V" (verbose
output) and "-t" (timestamps, to see where the hang happens). 

> Appreciate help
> 
> 
> Thanks
> 
> Grahame Jordan
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


Cheers,
-- 
Vinicius

[1] http://git.kernel.org/?p=bluetooth/bluez.git;a=summary

[2] http://git.kernel.org/?p=bluetooth/bluez-hcidump.git;a=summary

^ permalink raw reply

* [RFC 20/20] Bluetooth: Add support for resuming socket when SMP is finished
From: Vinicius Costa Gomes @ 2010-11-23 15:06 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1290524796-32246-1-git-send-email-vinicius.gomes@openbossa.org>

This adds support for resuming the user space traffic when SMP
negotiation is complete.

Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
---
 include/net/bluetooth/l2cap.h |    1 +
 net/bluetooth/l2cap_core.c    |   86 +++++++++++++++++++++++++++--------------
 2 files changed, 58 insertions(+), 29 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 1d0555f..196ad4e 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -433,5 +433,6 @@ static inline int l2cap_tx_window_full(struct sock *sk)
 #define __is_sar_start(ctrl) ((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START
 
 void l2cap_load(void);
+void l2cap_le_do_start(struct l2cap_conn *conn);
 
 #endif /* __L2CAP_H */
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 24719d3..df5402b 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -624,6 +624,31 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
 	}
 }
 
+static void l2cap_chan_ready(struct sock *sk)
+{
+	struct sock *parent = bt_sk(sk)->parent;
+
+	BT_DBG("sk %p, parent %p", sk, parent);
+
+	l2cap_pi(sk)->conf_state = 0;
+	l2cap_sock_clear_timer(sk);
+
+	if (!parent) {
+		/* Outgoing channel.
+		 * Wake up socket sleeping on connect.
+		 */
+		sk->sk_state = BT_CONNECTED;
+		sk->sk_state_change(sk);
+	} else {
+		/* Incoming channel.
+		 * Wake up socket sleeping on accept.
+		 */
+		parent->sk_state = BT_CONNECTED;
+		sk->sk_state_change(sk);
+		parent->sk_data_ready(parent, 0);
+	}
+}
+
 static void l2cap_conn_ready(struct l2cap_conn *conn)
 {
 	struct l2cap_chan_list *l = &conn->chan_list;
@@ -640,14 +665,10 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
 		bh_lock_sock(sk);
 
 		if (conn->hcon->type == LE_LINK) {
-			l2cap_sock_clear_timer(sk);
-			sk->sk_state = BT_CONNECTED;
-			sk->sk_state_change(sk);
 			if (smp_conn_security(conn, l2cap_pi(sk)->sec_level))
-				BT_DBG("Insufficient security");
-		}
+				l2cap_chan_ready(sk);
 
-		if (sk->sk_type != SOCK_SEQPACKET &&
+		} else if (sk->sk_type != SOCK_SEQPACKET &&
 				sk->sk_type != SOCK_STREAM) {
 			l2cap_sock_clear_timer(sk);
 			sk->sk_state = BT_CONNECTED;
@@ -692,6 +713,7 @@ static void l2cap_info_timeout(unsigned long arg)
 static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
 {
 	struct l2cap_conn *conn = hcon->l2cap_data;
+	struct hci_dev *hdev = hcon->hdev;
 
 	if (conn || status)
 		return conn;
@@ -705,10 +727,10 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
 
 	BT_DBG("hcon %p conn %p", hcon, conn);
 
-	if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
-		conn->mtu = hcon->hdev->le_mtu;
+	if (hdev->le_mtu && hcon->type == LE_LINK)
+		conn->mtu = hdev->le_mtu;
 	else
-		conn->mtu = hcon->hdev->acl_mtu;
+		conn->mtu = hdev->acl_mtu;
 
 	conn->src = &hcon->hdev->bdaddr;
 	conn->dst = &hcon->dst;
@@ -1199,7 +1221,7 @@ static int l2cap_do_connect(struct sock *sk)
 				sk->sk_type != SOCK_STREAM) {
 			l2cap_sock_clear_timer(sk);
 			sk->sk_state = BT_CONNECTED;
-		} else
+		} else if (hcon->type != LE_LINK)
 			l2cap_do_start(sk);
 	}
 
@@ -1467,9 +1489,6 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 
 	l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
 
-	sk->sk_state = BT_CONNECTED;
-	parent->sk_data_ready(parent, 0);
-
 	write_unlock_bh(&list->lock);
 
 clean:
@@ -2409,27 +2428,32 @@ static int l2cap_sock_release(struct socket *sock)
 	return err;
 }
 
-static void l2cap_chan_ready(struct sock *sk)
+void l2cap_le_do_start(struct l2cap_conn *conn)
 {
-	struct sock *parent = bt_sk(sk)->parent;
+	struct l2cap_chan_list *l = &conn->chan_list;
+	struct sock *sk;
 
-	BT_DBG("sk %p, parent %p", sk, parent);
+	read_lock(&l->lock);
 
-	l2cap_pi(sk)->conf_state = 0;
-	l2cap_sock_clear_timer(sk);
+	for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
+		bh_lock_sock(sk);
 
-	if (!parent) {
-		/* Outgoing channel.
-		 * Wake up socket sleeping on connect.
-		 */
-		sk->sk_state = BT_CONNECTED;
-		sk->sk_state_change(sk);
-	} else {
-		/* Incoming channel.
-		 * Wake up socket sleeping on accept.
-		 */
-		parent->sk_data_ready(parent, 0);
+		if (l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA) {
+			struct sock *parent = bt_sk(sk)->parent;
+
+			l2cap_sock_clear_timer(sk);
+
+			if (parent)
+				parent->sk_data_ready(parent, 0);
+
+			sk->sk_state = BT_CONNECTED;
+			sk->sk_state_change(sk);
+		}
+
+		bh_unlock_sock(sk);
 	}
+
+	read_unlock(&l->lock);
 }
 
 /* Copy frame to all raw sockets on that connection */
@@ -4742,6 +4766,10 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
 
 	BT_DBG("conn %p", conn);
 
+	if (hcon->type == LE_LINK)
+		if (encrypt)
+			l2cap_le_do_start(conn);
+
 	read_lock(&l->lock);
 
 	for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
-- 
1.7.3.2


^ permalink raw reply related

* [RFC 19/20] Bluetooth: Add support for LE Start Encryption
From: Vinicius Costa Gomes @ 2010-11-23 15:06 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1290524796-32246-1-git-send-email-vinicius.gomes@openbossa.org>

This adds support for starting SMP Phase 2 Encryption, when the initial
SMP negotiation is successful. This adds the LE Start Encryption and LE
Long Term Key Request commands and related events.

Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
---
 include/net/bluetooth/hci.h      |   34 +++++++++++++++++++
 include/net/bluetooth/hci_core.h |    5 +++
 net/bluetooth/hci_conn.c         |   47 ++++++++++++++++++++++++++
 net/bluetooth/hci_event.c        |   67 ++++++++++++++++++++++++++++++++++++++
 net/bluetooth/smp.c              |   10 +++++-
 5 files changed, 162 insertions(+), 1 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 2103731..036fdae 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -626,6 +626,33 @@ struct hci_cp_le_create_conn {
 
 #define HCI_OP_LE_CREATE_CONN_CANCEL	0x200e
 
+#define HCI_OP_LE_START_ENC		0x2019
+struct hci_cp_le_start_enc {
+	__le16	handle;
+	__u8	rand[8];
+	__le16	ediv;
+	__u8	ltk[16];
+} __packed;
+
+#define HCI_OP_LE_LTK_REPLY		0x201a
+struct hci_cp_le_ltk_reply {
+	__le16	handle;
+	__u8	ltk[16];
+} __packed;
+struct hci_rp_le_ltk_reply {
+	__u8	status;
+	__le16	handle;
+} __packed;
+
+#define HCI_OP_LE_LTK_NEG_REPLY		0x201b
+struct hci_cp_le_ltk_neg_reply {
+	__le16	handle;
+} __packed;
+struct hci_rp_le_ltk_neg_reply {
+	__u8	status;
+	__le16	handle;
+} __packed;
+
 /* ---- HCI Events ---- */
 #define HCI_EV_INQUIRY_COMPLETE		0x01
 
@@ -897,6 +924,13 @@ struct hci_ev_le_conn_complete {
 	__u8     clk_accurancy;
 } __packed;
 
+#define HCI_EV_LE_LTK_REQ		0x05
+struct hci_ev_le_ltk_req {
+	__le16	handle;
+	__u8	random[8];
+	__le16	ediv;
+} __packed;
+
 /* Internal events generated by Bluetooth stack */
 #define HCI_EV_STACK_INTERNAL	0xfd
 struct hci_ev_stack_internal {
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index ee5efa8..cfbe56c 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -192,6 +192,7 @@ struct hci_conn {
 	__u8             sec_level;
 	__u8             power_save;
 	__u16            disc_timeout;
+	__u8		 ltk[16];
 	unsigned long	 pend;
 
 	unsigned int	 sent;
@@ -713,4 +714,8 @@ struct hci_sec_filter {
 
 void hci_req_complete(struct hci_dev *hdev, int result);
 
+void hci_le_start_enc(struct hci_conn *conn, u8 ltk[16]);
+void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16]);
+void hci_le_ltk_neg_reply(struct hci_conn *conn);
+
 #endif /* __HCI_CORE_H */
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index d9a31b6..674829d 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -182,6 +182,53 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
 	hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
 }
 
+void hci_le_start_enc(struct hci_conn *conn, u8 ltk[16])
+{
+	struct hci_dev *hdev = conn->hdev;
+	struct hci_cp_le_start_enc cp;
+
+	BT_DBG("%p", conn);
+
+	memset(&cp, 0, sizeof(cp));
+
+	cp.handle = cpu_to_le16(conn->handle);
+	memcpy(cp.ltk, ltk, 16);
+
+	hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
+}
+EXPORT_SYMBOL(hci_le_start_enc);
+
+void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16])
+{
+	struct hci_dev *hdev = conn->hdev;
+	struct hci_cp_le_ltk_reply cp;
+
+	BT_DBG("%p", conn);
+
+	memset(&cp, 0, sizeof(cp));
+
+	cp.handle = cpu_to_le16(conn->handle);
+	memcpy(&cp.ltk, ltk, sizeof(ltk));
+
+	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
+}
+EXPORT_SYMBOL(hci_le_ltk_reply);
+
+void hci_le_ltk_neg_reply(struct hci_conn *conn)
+{
+	struct hci_dev *hdev = conn->hdev;
+	struct hci_cp_le_ltk_neg_reply cp;
+
+	BT_DBG("%p", conn);
+
+	memset(&cp, 0, sizeof(cp));
+
+	cp.handle = cpu_to_le16(conn->handle);
+
+	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(cp), &cp);
+}
+EXPORT_SYMBOL(hci_le_ltk_neg_reply);
+
 /* Device _must_ be locked */
 void hci_sco_setup(struct hci_conn *conn, __u8 status)
 {
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index df6eaa1..57560fb 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -559,6 +559,30 @@ static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
 	hci_req_complete(hdev, rp->status);
 }
 
+static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
+
+	BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+	if (rp->status)
+		return;
+
+	hci_req_complete(hdev, rp->status);
+}
+
+static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
+
+	BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+	if (rp->status)
+		return;
+
+	hci_req_complete(hdev, rp->status);
+}
+
 static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
 {
 	BT_DBG("%s status 0x%x", hdev->name, status);
@@ -920,6 +944,11 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
 	hci_dev_unlock(hdev);
 }
 
+static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
+{
+	BT_DBG("%s status 0x%x", hdev->name, status);
+}
+
 static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	__u8 status = *((__u8 *) skb->data);
@@ -1440,6 +1469,14 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
 		hci_cc_le_read_buffer_size(hdev, skb);
 		break;
 
+	case HCI_OP_LE_LTK_REPLY:
+		hci_cc_le_ltk_reply(hdev, skb);
+		break;
+
+	case HCI_OP_LE_LTK_NEG_REPLY:
+		hci_cc_le_ltk_neg_reply(hdev, skb);
+		break;
+
 	default:
 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
 		break;
@@ -1510,6 +1547,10 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_cs_le_create_conn(hdev, ev->status);
 		break;
 
+	case HCI_OP_LE_START_ENC:
+		hci_cs_le_start_enc(hdev, ev->status);
+		break;
+
 	default:
 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
 		break;
@@ -2013,6 +2054,28 @@ unlock:
 	hci_dev_unlock(hdev);
 }
 
+static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
+						struct sk_buff *skb)
+{
+	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
+	struct hci_cp_le_ltk_reply cp;
+	struct hci_conn *conn;
+
+	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
+
+	hci_dev_lock(hdev);
+
+	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
+
+	memset(&cp, 0, sizeof(cp));
+	cp.handle = cpu_to_le16(conn->handle);
+	memcpy(cp.ltk, conn->ltk, sizeof(conn->ltk));
+
+	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
+
+	hci_dev_unlock(hdev);
+}
+
 static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
@@ -2024,6 +2087,10 @@ static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_le_conn_complete_evt(hdev, skb);
 		break;
 
+	case HCI_EV_LE_LTK_REQ:
+		hci_le_ltk_request_evt(hdev, skb);
+		break;
+
 	default:
 		break;
 	}
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index a8d2e12..6cfd088 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -287,7 +287,8 @@ static void smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb
 
 static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
 {
-	struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
+	struct hci_conn *hcon = conn->hcon;
+	struct crypto_blkcipher *tfm = hcon->hdev->tfm;
 	int ret;
 	u8 k[16], key[16], res[16], random[16], confirm[16], buf[128];
 
@@ -295,6 +296,7 @@ static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
 	skb_pull(skb, 16);
 
 	memset(k, 0, sizeof(k));
+	memset(hcon->ltk, 0, sizeof(hcon->ltk));
 
 	if (conn->hcon->out)
 		ret = smp_c1(tfm, k, random, conn->preq, conn->pres, 0,
@@ -319,6 +321,10 @@ static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
 	if (conn->hcon->out) {
 		smp_s1(tfm, k, random, conn->prnd, key);
 
+		swap128(key, hcon->ltk);
+
+		hci_le_start_enc(conn->hcon, hcon->ltk);
+
 		hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
 
 		BT_DBG("key %s", buf);
@@ -331,6 +337,8 @@ static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
 
 		smp_s1(tfm, k, conn->prnd, random, key);
 
+		swap128(key, hcon->ltk);
+
 		hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
 
 		BT_DBG("key %s", buf);
-- 
1.7.3.2


^ permalink raw reply related


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