Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH_v4 7/7] bnep: Refactored bnep server apis for bridge addition and deletion
From: Ravi kumar Veeramally @ 2013-12-18 14:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1387378396-6259-1-git-send-email-ravikumar.veeramally@linux.intel.com>

To simplify bnep server realted bridge creation and deletion calls
provided extra apis and moved existing apis to static.
---
 profiles/network/bnep.c   | 50 +++++++++++++++++++++++++++++++++++++++++------
 profiles/network/bnep.h   |  9 +++------
 profiles/network/server.c | 37 +++--------------------------------
 3 files changed, 50 insertions(+), 46 deletions(-)

diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index b7c3835..90728d3 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -151,7 +151,7 @@ int bnep_cleanup(void)
 	return 0;
 }
 
-int bnep_conndel(const bdaddr_t *dst)
+static int bnep_conndel(const bdaddr_t *dst)
 {
 	struct bnep_conndel_req req;
 
@@ -167,7 +167,7 @@ int bnep_conndel(const bdaddr_t *dst)
 	return 0;
 }
 
-int bnep_connadd(int sk, uint16_t role, char *dev)
+static int bnep_connadd(int sk, uint16_t role, char *dev)
 {
 	struct bnep_connadd_req req;
 
@@ -187,7 +187,7 @@ int bnep_connadd(int sk, uint16_t role, char *dev)
 	return 0;
 }
 
-int bnep_if_up(const char *devname)
+static int bnep_if_up(const char *devname)
 {
 	struct ifreq ifr;
 	int sk, err;
@@ -212,7 +212,7 @@ int bnep_if_up(const char *devname)
 	return 0;
 }
 
-int bnep_if_down(const char *devname)
+static int bnep_if_down(const char *devname)
 {
 	struct ifreq ifr;
 	int sk, err;
@@ -455,7 +455,7 @@ guint bnep_set_watchdog(struct bnep *b, GIOFunc watchdog, void *data)
 	return ret;
 }
 
-int bnep_add_to_bridge(const char *devname, const char *bridge)
+static int bnep_add_to_bridge(const char *devname, const char *bridge)
 {
 	int ifindex;
 	struct ifreq ifr;
@@ -486,7 +486,7 @@ int bnep_add_to_bridge(const char *devname, const char *bridge)
 	return 0;
 }
 
-int bnep_del_from_bridge(const char *devname, const char *bridge)
+static int bnep_del_from_bridge(const char *devname, const char *bridge)
 {
 	int ifindex = if_nametoindex(devname);
 	struct ifreq ifr;
@@ -592,3 +592,41 @@ uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req, uint16_t *dst,
 
 	return BNEP_SUCCESS;
 }
+
+int bnep_server_add(int sk, uint16_t dst, char *bridge, char *iface,
+						const bdaddr_t *addr)
+{
+	if (!bridge || !bridge || !iface || !addr)
+		return -EINVAL;
+
+	if (bnep_connadd(sk, dst, iface) < 0) {
+		error("Can't add connection to the bridge %s: %s(%d)",
+						bridge, strerror(errno), errno);
+		return -errno;
+	}
+
+	if (bnep_add_to_bridge(iface, bridge) < 0) {
+		error("Can't add %s to the bridge %s: %s(%d)",
+					iface, bridge, strerror(errno), errno);
+		bnep_conndel(addr);
+		return -errno;
+	}
+
+	if (bnep_if_up(iface) < 0) {
+		error("Can't up the interface %s: %s(%d)",
+						iface, strerror(errno), errno);
+		return -errno;
+	}
+
+	return 0;
+}
+
+void bnep_server_delete(char *bridge, char *iface, const bdaddr_t *addr)
+{
+	if (!bridge || !iface || !addr)
+		return;
+
+	bnep_del_from_bridge(iface, bridge);
+	bnep_if_down(iface);
+	bnep_conndel(addr);
+}
diff --git a/profiles/network/bnep.h b/profiles/network/bnep.h
index 46199df..3447f6e 100644
--- a/profiles/network/bnep.h
+++ b/profiles/network/bnep.h
@@ -32,12 +32,6 @@ const char *bnep_name(uint16_t id);
 
 struct bnep *bnep_new(int sk, uint16_t local_role, uint16_t remote_role);
 void bnep_free(struct bnep *b);
-int bnep_connadd(int sk, uint16_t role, char *dev);
-int bnep_conndel(const bdaddr_t *dst);
-int bnep_if_up(const char *devname);
-int bnep_if_down(const char *devname);
-int bnep_add_to_bridge(const char *devname, const char *bridge);
-int bnep_del_from_bridge(const char *devname, const char *bridge);
 
 typedef void (*bnep_connect_cb) (char *iface, int err, void *data);
 int bnep_connect(struct bnep *b, bnep_connect_cb conn_cb, void *data);
@@ -48,3 +42,6 @@ ssize_t bnep_send_ctrl_rsp(int sk, uint8_t type, uint8_t ctrl, uint16_t resp);
 uint16_t bnep_setup_chk(uint16_t dst_role, uint16_t src_role);
 uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req, uint16_t *dst,
 								uint16_t *src);
+int bnep_server_add(int sk, uint16_t dst, char *bridge, char *iface,
+							const bdaddr_t *addr);
+void bnep_server_delete(char *bridge, char *iface, const bdaddr_t *addr);
diff --git a/profiles/network/server.c b/profiles/network/server.c
index 73741ec..7cb5a1e 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -251,35 +251,6 @@ static sdp_record_t *server_record_new(const char *name, uint16_t id)
 	return record;
 }
 
-static int server_connadd(struct network_server *ns,
-				struct network_session *session,
-				uint16_t dst_role)
-{
-	char devname[16];
-	int err, nsk;
-
-	nsk = g_io_channel_unix_get_fd(session->io);
-	err = bnep_connadd(nsk, dst_role, devname);
-	if (err < 0)
-		return err;
-
-	info("Added new connection: %s", devname);
-
-	if (bnep_add_to_bridge(devname, ns->bridge) < 0) {
-		error("Can't add %s to the bridge %s: %s(%d)",
-				devname, ns->bridge, strerror(errno), errno);
-		return -EPERM;
-	}
-
-	bnep_if_up(devname);
-
-	strncpy(session->dev, devname, sizeof(devname));
-
-	ns->sessions = g_slist_append(ns->sessions, session);
-
-	return 0;
-}
-
 static void session_free(void *data)
 {
 	struct network_session *session = data;
@@ -377,7 +348,8 @@ static gboolean bnep_setup(GIOChannel *chan,
 		goto reply;
 	}
 
-	if (server_connadd(ns, na->setup, dst_role) < 0)
+	if (bnep_server_add(sk, dst_role, ns->bridge, na->setup->dev,
+							&na->setup->dst) < 0)
 		goto reply;
 
 	na->setup = NULL;
@@ -524,10 +496,7 @@ static void server_remove_sessions(struct network_server *ns)
 		if (*session->dev == '\0')
 			continue;
 
-		bnep_del_from_bridge(session->dev, ns->bridge);
-		bnep_if_down(session->dev);
-
-		bnep_conndel(&session->dst);
+		bnep_server_delete(ns->bridge, session->dev, &session->dst);
 	}
 
 	g_slist_free_full(ns->sessions, session_free);
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v4 6/7] bnep: Refactored bnep connect and disconnect calls
From: Ravi kumar Veeramally @ 2013-12-18 14:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1387378396-6259-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Refactored bnep connect and disconnect calls to simplify and
keeping bnep related functionality behind curtains.
Provided bnep struct globally. bnep_connect calls takes
care of bnep_setup until interface up then connect callback
will be called. Provided bnep_set_watchdog. When interface is
up then only set watchdog. bnep_disconnect should be called
only when iface is up/connected.
---
 android/pan.c                 | 50 ++++++++++++------------
 profiles/network/bnep.c       | 91 +++++++++++++++++++++++++++----------------
 profiles/network/bnep.h       |  8 ++--
 profiles/network/connection.c | 42 +++++++++++++-------
 4 files changed, 114 insertions(+), 77 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index f64b09a..85b1855 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -55,6 +55,7 @@ struct pan_device {
 	uint8_t		role;
 	GIOChannel	*io;
 	guint		watch;
+	struct bnep	*bnep_conn;
 };
 
 static int device_cmp(gconstpointer s, gconstpointer user_data)
@@ -67,6 +68,8 @@ static int device_cmp(gconstpointer s, gconstpointer user_data)
 
 static void pan_device_free(struct pan_device *dev)
 {
+	DBG("");
+
 	if (dev->watch > 0) {
 		g_source_remove(dev->watch);
 		dev->watch = 0;
@@ -77,6 +80,7 @@ static void pan_device_free(struct pan_device *dev)
 		dev->io = NULL;
 	}
 
+	bnep_free(dev->bnep_conn);
 	devices = g_slist_remove(devices, dev);
 	g_free(dev);
 
@@ -92,7 +96,6 @@ static void bt_pan_notify_conn_state(struct pan_device *dev, uint8_t state)
 	if (dev->conn_state == state)
 		return;
 
-	dev->conn_state = state;
 	ba2str(&dev->dst, addr);
 	DBG("device %s state %u", addr, state);
 
@@ -104,8 +107,16 @@ static void bt_pan_notify_conn_state(struct pan_device *dev, uint8_t state)
 
 	ipc_send_notif(HAL_SERVICE_ID_PAN, HAL_EV_PAN_CONN_STATE, sizeof(ev),
 									&ev);
-	if (dev->conn_state == HAL_PAN_STATE_DISCONNECTED)
-		pan_device_free(dev);
+
+	if (dev->conn_state == HAL_PAN_STATE_CONNECTED)
+		bnep_disconnect(dev->bnep_conn);
+
+	dev->conn_state = state;
+
+	if (state != HAL_PAN_STATE_DISCONNECTED)
+		return;
+
+	pan_device_free(dev);
 }
 
 static void bt_pan_notify_ctrl_state(struct pan_device *dev, uint8_t state)
@@ -131,14 +142,12 @@ static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
 
 	DBG("%s disconnected", dev->iface);
 
-	bnep_if_down(dev->iface);
-	bnep_conndel(&dev->dst);
 	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
 
 	return FALSE;
 }
 
-static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data)
+static void bnep_conn_cb(char *iface, int err, void *data)
 {
 	struct pan_device *dev = data;
 
@@ -146,28 +155,22 @@ static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data)
 
 	if (err < 0) {
 		error("bnep connect req failed: %s", strerror(-err));
-		bnep_conndel(&dev->dst);
 		bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
 		return;
 	}
 
-	memcpy(dev->iface, iface, sizeof(dev->iface));
-
-	DBG("%s connected", dev->iface);
+	DBG("%s connected", iface);
 
+	memcpy(dev->iface, iface, sizeof(dev->iface));
 	bt_pan_notify_ctrl_state(dev, HAL_PAN_CTRL_ENABLED);
 	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTED);
-
-	dev->watch = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
-							bnep_watchdog_cb, dev);
-	g_io_channel_unref(dev->io);
-	dev->io = NULL;
+	dev->watch = bnep_set_watchdog(dev->bnep_conn, bnep_watchdog_cb, dev);
 }
 
 static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
 {
 	struct pan_device *dev = data;
-	uint16_t src, dst;
+	uint16_t l_role, r_role;
 	int perr, sk;
 
 	DBG("");
@@ -177,11 +180,13 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
 		goto fail;
 	}
 
-	src = (local_role == HAL_PAN_ROLE_NAP) ? BNEP_SVC_NAP : BNEP_SVC_PANU;
-	dst = (dev->role == HAL_PAN_ROLE_NAP) ? BNEP_SVC_NAP : BNEP_SVC_PANU;
-	sk = g_io_channel_unix_get_fd(dev->io);
+	l_role = (local_role == HAL_PAN_ROLE_NAP) ? BNEP_SVC_NAP :
+								BNEP_SVC_PANU;
+	r_role = (dev->role == HAL_PAN_ROLE_NAP) ? BNEP_SVC_NAP : BNEP_SVC_PANU;
 
-	perr = bnep_connect(sk, src, dst, bnep_conn_cb, dev);
+	sk = g_io_channel_unix_get_fd(dev->io);
+	dev->bnep_conn = bnep_new(sk, l_role, r_role);
+	perr = bnep_connect(dev->bnep_conn, bnep_conn_cb, dev);
 	if (perr < 0) {
 		error("bnep connect req failed: %s", strerror(-perr));
 		goto fail;
@@ -286,11 +291,6 @@ static void bt_pan_disconnect(const void *buf, uint16_t len)
 	if (dev->io)
 		g_io_channel_shutdown(dev->io, TRUE, NULL);
 
-	if (dev->conn_state == HAL_PAN_STATE_CONNECTED) {
-		bnep_if_down(dev->iface);
-		bnep_conndel(&dst);
-	}
-
 	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTING);
 	status = HAL_STATUS_SUCCESS;
 
diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index f3ed63b..b7c3835 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -39,6 +39,7 @@
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/l2cap.h>
 #include <bluetooth/bnep.h>
+#include <btio/btio.h>
 
 #include <glib.h>
 
@@ -71,25 +72,15 @@ struct bnep {
 	GIOChannel	*io;
 	uint16_t	src;
 	uint16_t	dst;
+	bdaddr_t	dst_addr;
+	char	iface[16];
 	guint	attempts;
 	guint	setup_to;
 	void	*data;
 	bnep_connect_cb	conn_cb;
+	guint watch;
 };
 
-static void free_bnep_connect(struct bnep *b)
-{
-	if (!b)
-		return;
-
-	if (b->io) {
-		g_io_channel_unref(b->io);
-		b->io = NULL;
-	}
-
-	g_free(b);
-}
-
 uint16_t bnep_service_id(const char *svc)
 {
 	int i;
@@ -278,12 +269,11 @@ static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
 	struct bnep_control_rsp *rsp;
 	struct timeval timeo;
 	char pkt[BNEP_MTU];
-	char iface[16];
 	ssize_t r;
 	int sk;
 
 	if (cond & G_IO_NVAL)
-		goto failed;
+		return FALSE;
 
 	if (b->setup_to > 0) {
 		g_source_remove(b->setup_to);
@@ -335,24 +325,23 @@ static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
 	setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));
 
 	sk = g_io_channel_unix_get_fd(b->io);
-	if (bnep_connadd(sk, b->src, iface)) {
+	if (bnep_connadd(sk, b->src, b->iface)) {
 		error("bnep conn could not be added");
 		goto failed;
 	}
 
-	if (bnep_if_up(iface)) {
-		error("could not up %s", iface);
+	if (bnep_if_up(b->iface)) {
+		error("could not up %s", b->iface);
+		bnep_conndel(&b->dst_addr);
 		goto failed;
 	}
 
-	b->conn_cb(chan, iface, 0, b->data);
-	free_bnep_connect(b);
+	b->conn_cb(b->iface, 0, b->data);
 
 	return FALSE;
 
 failed:
-	b->conn_cb(NULL, NULL, -EIO, b->data);
-	free_bnep_connect(b);
+	b->conn_cb(NULL, -EIO, b->data);
 
 	return FALSE;
 }
@@ -396,40 +385,76 @@ static gboolean bnep_conn_req_to(gpointer user_data)
 			return TRUE;
 	}
 
-	b->conn_cb(NULL, NULL, -ETIMEDOUT, b->data);
-	free_bnep_connect(b);
+	b->conn_cb(NULL, -ETIMEDOUT, b->data);
 
 	return FALSE;
 }
 
-int bnep_connect(int sk, uint16_t src, uint16_t dst, bnep_connect_cb conn_cb,
-								void *data)
+int bnep_connect(struct bnep *b, bnep_connect_cb conn_cb, void *data)
 {
-	struct bnep *b;
+	GError *gerr = NULL;
 	int err;
 
-	if (!conn_cb)
+	if (!b || !conn_cb)
 		return -EINVAL;
 
-	b = g_new0(struct bnep, 1);
-	b->io = g_io_channel_unix_new(sk);
 	b->attempts = 0;
-	b->src = src;
-	b->dst = dst;
 	b->conn_cb = conn_cb;
 	b->data = data;
 
+	bt_io_get(b->io, &gerr, BT_IO_OPT_DEST_BDADDR, &b->dst_addr,
+							BT_IO_OPT_INVALID);
+	if (gerr) {
+		error("%s", gerr->message);
+		g_error_free(gerr);
+		return -EINVAL;
+	}
+
 	err = bnep_setup_conn_req(b);
 	if (err < 0)
 		return err;
 
 	b->setup_to = g_timeout_add_seconds(CON_SETUP_TO,
 							bnep_conn_req_to, b);
-	g_io_add_watch(b->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+	b->watch = g_io_add_watch(b->io,
+				G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
 							bnep_setup_cb, b);
 	return 0;
 }
 
+void bnep_disconnect(struct bnep *b)
+{
+	if (!b)
+		return;
+
+	if (b->io) {
+		g_io_channel_unref(b->io);
+		b->io = NULL;
+	}
+
+	if (b->watch) {
+		g_source_remove(b->watch);
+		b->watch = 0;
+	}
+
+	bnep_if_down(b->iface);
+	bnep_conndel(&b->dst_addr);
+}
+
+guint bnep_set_watchdog(struct bnep *b, GIOFunc watchdog, void *data)
+{
+	guint ret = 0;
+
+	if (!b)
+		return ret;
+
+	if (b->io)
+		ret = g_io_add_watch(b->io, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+								watchdog, data);
+
+	return ret;
+}
+
 int bnep_add_to_bridge(const char *devname, const char *bridge)
 {
 	int ifindex;
diff --git a/profiles/network/bnep.h b/profiles/network/bnep.h
index 091a7f2..46199df 100644
--- a/profiles/network/bnep.h
+++ b/profiles/network/bnep.h
@@ -39,10 +39,10 @@ int bnep_if_down(const char *devname);
 int bnep_add_to_bridge(const char *devname, const char *bridge);
 int bnep_del_from_bridge(const char *devname, const char *bridge);
 
-typedef void (*bnep_connect_cb) (GIOChannel *chan, char *iface, int err,
-								void *data);
-int bnep_connect(int sk, uint16_t src, uint16_t dst, bnep_connect_cb conn_cb,
-								void *data);
+typedef void (*bnep_connect_cb) (char *iface, int err, void *data);
+int bnep_connect(struct bnep *b, bnep_connect_cb conn_cb, void *data);
+guint bnep_set_watchdog(struct bnep *b, GIOFunc watchdog, void *data);
+void bnep_disconnect(struct bnep *b);
 
 ssize_t bnep_send_ctrl_rsp(int sk, uint8_t type, uint8_t ctrl, uint16_t resp);
 uint16_t bnep_setup_chk(uint16_t dst_role, uint16_t src_role);
diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index fb3e1ce..f1a44e9 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -72,6 +72,8 @@ struct network_conn {
 	guint		dc_id;
 	struct network_peer *peer;
 	DBusMessage	*connect;
+	struct bnep	*bnep_conn;
+	guint		watch;
 };
 
 static GSList *peers = NULL;
@@ -126,11 +128,19 @@ static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
 
 	info("%s disconnected", nc->dev);
 
-	bnep_if_down(nc->dev);
 	nc->state = DISCONNECTED;
 	memset(nc->dev, 0, sizeof(nc->dev));
 	strcpy(nc->dev, "bnep%d");
 
+	bnep_free(nc->bnep_conn);
+	nc->bnep_conn = NULL;
+
+	if (nc->io) {
+		g_io_channel_shutdown(nc->io, TRUE, NULL);
+		g_io_channel_unref(nc->io);
+		nc->io = NULL;
+	}
+
 	return FALSE;
 }
 
@@ -158,9 +168,17 @@ static void cancel_connection(struct network_conn *nc, int err)
 	if (nc->connect)
 		local_connect_cb(nc, err);
 
-	g_io_channel_shutdown(nc->io, TRUE, NULL);
-	g_io_channel_unref(nc->io);
-	nc->io = NULL;
+	if (nc->io) {
+		g_io_channel_shutdown(nc->io, TRUE, NULL);
+		g_io_channel_unref(nc->io);
+		nc->io = NULL;
+	}
+
+	if (nc->state == CONNECTED)
+		bnep_disconnect(nc->bnep_conn);
+
+	bnep_free(nc->bnep_conn);
+	nc->bnep_conn = NULL;
 
 	nc->state = DISCONNECTED;
 }
@@ -169,11 +187,7 @@ static void connection_destroy(DBusConnection *conn, void *user_data)
 {
 	struct network_conn *nc = user_data;
 
-	if (nc->state == CONNECTED) {
-		bnep_if_down(nc->dev);
-		bnep_conndel(device_get_address(nc->peer->device));
-	} else if (nc->io)
-		cancel_connection(nc, -EIO);
+	cancel_connection(nc, -EIO);
 }
 
 static void disconnect_cb(struct btd_device *device, gboolean removal,
@@ -186,7 +200,7 @@ static void disconnect_cb(struct btd_device *device, gboolean removal,
 	connection_destroy(NULL, user_data);
 }
 
-static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data)
+static void bnep_conn_cb(char *iface, int err, void *data)
 {
 	struct network_conn *nc = data;
 	const char *path;
@@ -220,10 +234,7 @@ static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data)
 	nc->state = CONNECTED;
 	nc->dc_id = device_add_disconnect_watch(nc->peer->device, disconnect_cb,
 								nc, NULL);
-	g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
-							bnep_watchdog_cb, nc);
-	g_io_channel_unref(nc->io);
-	nc->io = NULL;
+	nc->watch = bnep_set_watchdog(nc->bnep_conn, bnep_watchdog_cb, nc);
 
 	return;
 
@@ -242,7 +253,8 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
 	}
 
 	sk = g_io_channel_unix_get_fd(nc->io);
-	perr = bnep_connect(sk, BNEP_SVC_PANU, nc->id, bnep_conn_cb, nc);
+	nc->bnep_conn = bnep_new(sk, BNEP_SVC_PANU, nc->id);
+	perr = bnep_connect(nc->bnep_conn, bnep_conn_cb, nc);
 	if (perr < 0) {
 		error("bnep connect(): %s (%d)", strerror(-perr), -perr);
 		goto failed;
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v4 5/7] bnep: Add bnep_new and bnep_free api's
From: Ravi kumar Veeramally @ 2013-12-18 14:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1387378396-6259-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Refacoring connect and disconnect mechanisms. It would be more
convinient for caller to maintain just bnep connection reference
and delete whenever it is not required.
---
 profiles/network/bnep.c | 25 +++++++++++++++++++++++++
 profiles/network/bnep.h |  4 ++++
 2 files changed, 29 insertions(+)

diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index 02e2647..f3ed63b 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -246,6 +246,31 @@ int bnep_if_down(const char *devname)
 	return 0;
 }
 
+struct bnep *bnep_new(int sk, uint16_t local_role, uint16_t remote_role)
+{
+	struct bnep *b;
+
+	b = g_new0(struct bnep, 1);
+	b->io = g_io_channel_unix_new(sk);
+	b->src = local_role;
+	b->dst = remote_role;
+
+	return b;
+}
+
+void bnep_free(struct bnep *b)
+{
+	if (!b)
+		return;
+
+	if (b->io) {
+		g_io_channel_unref(b->io);
+		b->io = NULL;
+	}
+
+	g_free(b);
+}
+
 static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
 								gpointer data)
 {
diff --git a/profiles/network/bnep.h b/profiles/network/bnep.h
index dd22c40..091a7f2 100644
--- a/profiles/network/bnep.h
+++ b/profiles/network/bnep.h
@@ -21,6 +21,8 @@
  *
  */
 
+struct bnep;
+
 int bnep_init(void);
 int bnep_cleanup(void);
 
@@ -28,6 +30,8 @@ uint16_t bnep_service_id(const char *svc);
 const char *bnep_uuid(uint16_t id);
 const char *bnep_name(uint16_t id);
 
+struct bnep *bnep_new(int sk, uint16_t local_role, uint16_t remote_role);
+void bnep_free(struct bnep *b);
 int bnep_connadd(int sk, uint16_t role, char *dev);
 int bnep_conndel(const bdaddr_t *dst);
 int bnep_if_up(const char *devname);
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v4 4/7] bnep: Rename struct bnep_conn to struct bnep for better readability
From: Ravi kumar Veeramally @ 2013-12-18 14:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1387378396-6259-1-git-send-email-ravikumar.veeramally@linux.intel.com>

---
 profiles/network/bnep.c | 80 ++++++++++++++++++++++++-------------------------
 1 file changed, 40 insertions(+), 40 deletions(-)

diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index 08037e6..02e2647 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -67,7 +67,7 @@ struct __service_16 {
 	uint16_t src;
 } __attribute__ ((packed));
 
-struct bnep_conn {
+struct bnep {
 	GIOChannel	*io;
 	uint16_t	src;
 	uint16_t	dst;
@@ -77,17 +77,17 @@ struct bnep_conn {
 	bnep_connect_cb	conn_cb;
 };
 
-static void free_bnep_connect(struct bnep_conn *bc)
+static void free_bnep_connect(struct bnep *b)
 {
-	if (!bc)
+	if (!b)
 		return;
 
-	if (bc->io) {
-		g_io_channel_unref(bc->io);
-		bc->io = NULL;
+	if (b->io) {
+		g_io_channel_unref(b->io);
+		b->io = NULL;
 	}
 
-	g_free(bc);
+	g_free(b);
 }
 
 uint16_t bnep_service_id(const char *svc)
@@ -249,7 +249,7 @@ int bnep_if_down(const char *devname)
 static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
 								gpointer data)
 {
-	struct bnep_conn *bc = data;
+	struct bnep *b = data;
 	struct bnep_control_rsp *rsp;
 	struct timeval timeo;
 	char pkt[BNEP_MTU];
@@ -260,9 +260,9 @@ static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
 	if (cond & G_IO_NVAL)
 		goto failed;
 
-	if (bc->setup_to > 0) {
-		g_source_remove(bc->setup_to);
-		bc->setup_to = 0;
+	if (b->setup_to > 0) {
+		g_source_remove(b->setup_to);
+		b->setup_to = 0;
 	}
 
 	if (cond & (G_IO_HUP | G_IO_ERR)) {
@@ -309,8 +309,8 @@ static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
 	timeo.tv_sec = 0;
 	setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));
 
-	sk = g_io_channel_unix_get_fd(bc->io);
-	if (bnep_connadd(sk, bc->src, iface)) {
+	sk = g_io_channel_unix_get_fd(b->io);
+	if (bnep_connadd(sk, b->src, iface)) {
 		error("bnep conn could not be added");
 		goto failed;
 	}
@@ -320,19 +320,19 @@ static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
 		goto failed;
 	}
 
-	bc->conn_cb(chan, iface, 0, bc->data);
-	free_bnep_connect(bc);
+	b->conn_cb(chan, iface, 0, b->data);
+	free_bnep_connect(b);
 
 	return FALSE;
 
 failed:
-	bc->conn_cb(NULL, NULL, -EIO, bc->data);
-	free_bnep_connect(bc);
+	b->conn_cb(NULL, NULL, -EIO, b->data);
+	free_bnep_connect(b);
 
 	return FALSE;
 }
 
-static int bnep_setup_conn_req(struct bnep_conn *bc)
+static int bnep_setup_conn_req(struct bnep *b)
 {
 	struct bnep_setup_conn_req *req;
 	struct __service_16 *s;
@@ -345,34 +345,34 @@ static int bnep_setup_conn_req(struct bnep_conn *bc)
 	req->ctrl = BNEP_SETUP_CONN_REQ;
 	req->uuid_size = 2;     /* 16bit UUID */
 	s = (void *) req->service;
-	s->src = htons(bc->src);
-	s->dst = htons(bc->dst);
+	s->src = htons(b->src);
+	s->dst = htons(b->dst);
 
-	fd = g_io_channel_unix_get_fd(bc->io);
+	fd = g_io_channel_unix_get_fd(b->io);
 	if (write(fd, pkt, sizeof(*req) + sizeof(*s)) < 0) {
 		error("bnep connection req send failed: %s", strerror(errno));
 		return -errno;
 	}
 
-	bc->attempts++;
+	b->attempts++;
 
 	return 0;
 }
 
 static gboolean bnep_conn_req_to(gpointer user_data)
 {
-	struct bnep_conn *bc = user_data;
+	struct bnep *b = user_data;
 
-	if (bc->attempts == CON_SETUP_RETRIES) {
+	if (b->attempts == CON_SETUP_RETRIES) {
 		error("Too many bnep connection attempts");
 	} else {
 		error("bnep connection setup TO, retrying...");
-		if (bnep_setup_conn_req(bc) == 0)
+		if (bnep_setup_conn_req(b) == 0)
 			return TRUE;
 	}
 
-	bc->conn_cb(NULL, NULL, -ETIMEDOUT, bc->data);
-	free_bnep_connect(bc);
+	b->conn_cb(NULL, NULL, -ETIMEDOUT, b->data);
+	free_bnep_connect(b);
 
 	return FALSE;
 }
@@ -380,28 +380,28 @@ static gboolean bnep_conn_req_to(gpointer user_data)
 int bnep_connect(int sk, uint16_t src, uint16_t dst, bnep_connect_cb conn_cb,
 								void *data)
 {
-	struct bnep_conn *bc;
+	struct bnep *b;
 	int err;
 
 	if (!conn_cb)
 		return -EINVAL;
 
-	bc = g_new0(struct bnep_conn, 1);
-	bc->io = g_io_channel_unix_new(sk);
-	bc->attempts = 0;
-	bc->src = src;
-	bc->dst = dst;
-	bc->conn_cb = conn_cb;
-	bc->data = data;
+	b = g_new0(struct bnep, 1);
+	b->io = g_io_channel_unix_new(sk);
+	b->attempts = 0;
+	b->src = src;
+	b->dst = dst;
+	b->conn_cb = conn_cb;
+	b->data = data;
 
-	err = bnep_setup_conn_req(bc);
+	err = bnep_setup_conn_req(b);
 	if (err < 0)
 		return err;
 
-	bc->setup_to = g_timeout_add_seconds(CON_SETUP_TO,
-							bnep_conn_req_to, bc);
-	g_io_add_watch(bc->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
-							bnep_setup_cb, bc);
+	b->setup_to = g_timeout_add_seconds(CON_SETUP_TO,
+							bnep_conn_req_to, b);
+	g_io_add_watch(b->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+							bnep_setup_cb, b);
 	return 0;
 }
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v4 3/7] android/pan: shutdown io channel on disconnect call
From: Ravi kumar Veeramally @ 2013-12-18 14:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1387378396-6259-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Shutdown io channel and send DISCONNECTING notification and send
DISCONNECTED notification and free the device on callback.
---
 android/pan.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index b83f534..f64b09a 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -269,7 +269,7 @@ static void bt_pan_disconnect(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_pan_disconnect *cmd = buf;
 	struct pan_device *dev;
-	uint8_t status;
+	uint8_t status = HAL_STATUS_FAILED;
 	GSList *l;
 	bdaddr_t dst;
 
@@ -278,20 +278,20 @@ static void bt_pan_disconnect(const void *buf, uint16_t len)
 	android2bdaddr(&cmd->bdaddr, &dst);
 
 	l = g_slist_find_custom(devices, &dst, device_cmp);
-	if (!l) {
-		status = HAL_STATUS_FAILED;
+	if (!l)
 		goto failed;
-	}
 
 	dev = l->data;
-	if (dev->watch) {
-		g_source_remove(dev->watch);
-		dev->watch = 0;
+
+	if (dev->io)
+		g_io_channel_shutdown(dev->io, TRUE, NULL);
+
+	if (dev->conn_state == HAL_PAN_STATE_CONNECTED) {
+		bnep_if_down(dev->iface);
+		bnep_conndel(&dst);
 	}
 
-	bnep_if_down(dev->iface);
-	bnep_conndel(&dst);
-	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTING);
 	status = HAL_STATUS_SUCCESS;
 
 failed:
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v4 2/7] android/pan: Change local_role to NONE only when device list is empty
From: Ravi kumar Veeramally @ 2013-12-18 14:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1387378396-6259-1-git-send-email-ravikumar.veeramally@linux.intel.com>

---
 android/pan.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index 2bbba9e..b83f534 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -67,8 +67,6 @@ static int device_cmp(gconstpointer s, gconstpointer user_data)
 
 static void pan_device_free(struct pan_device *dev)
 {
-	local_role = HAL_PAN_ROLE_NONE;
-
 	if (dev->watch > 0) {
 		g_source_remove(dev->watch);
 		dev->watch = 0;
@@ -81,6 +79,9 @@ static void pan_device_free(struct pan_device *dev)
 
 	devices = g_slist_remove(devices, dev);
 	g_free(dev);
+
+	if (g_slist_length(devices) == 0)
+		local_role = HAL_PAN_ROLE_NONE;
 }
 
 static void bt_pan_notify_conn_state(struct pan_device *dev, uint8_t state)
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v4 1/7] android/pan: Free device after sending diconnected notification
From: Ravi kumar Veeramally @ 2013-12-18 14:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

---
 android/pan.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index e410f54..2bbba9e 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -103,6 +103,8 @@ static void bt_pan_notify_conn_state(struct pan_device *dev, uint8_t state)
 
 	ipc_send_notif(HAL_SERVICE_ID_PAN, HAL_EV_PAN_CONN_STATE, sizeof(ev),
 									&ev);
+	if (dev->conn_state == HAL_PAN_STATE_DISCONNECTED)
+		pan_device_free(dev);
 }
 
 static void bt_pan_notify_ctrl_state(struct pan_device *dev, uint8_t state)
@@ -131,7 +133,6 @@ static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
 	bnep_if_down(dev->iface);
 	bnep_conndel(&dev->dst);
 	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
-	pan_device_free(dev);
 
 	return FALSE;
 }
@@ -146,7 +147,6 @@ static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data)
 		error("bnep connect req failed: %s", strerror(-err));
 		bnep_conndel(&dev->dst);
 		bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
-		pan_device_free(dev);
 		return;
 	}
 
@@ -190,7 +190,6 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
 
 fail:
 	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
-	pan_device_free(dev);
 }
 
 static void bt_pan_connect(const void *buf, uint16_t len)
@@ -284,7 +283,6 @@ static void bt_pan_disconnect(const void *buf, uint16_t len)
 	}
 
 	dev = l->data;
-
 	if (dev->watch) {
 		g_source_remove(dev->watch);
 		dev->watch = 0;
@@ -292,10 +290,7 @@ static void bt_pan_disconnect(const void *buf, uint16_t len)
 
 	bnep_if_down(dev->iface);
 	bnep_conndel(&dst);
-
 	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
-	pan_device_free(dev);
-
 	status = HAL_STATUS_SUCCESS;
 
 failed:
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH 3/3] android/tester: Test that connect call returns channel number
From: Andrei Emeltchenko @ 2013-12-18 14:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1387376336-17092-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

The test connects to emulated bthost and read channel number
---
 android/android-tester.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 117 insertions(+)

diff --git a/android/android-tester.c b/android/android-tester.c
index 55fa702..8a2861e 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -1080,6 +1080,27 @@ static void setup_socket_interface(const void *test_data)
 	tester_setup_complete();
 }
 
+static void setup_socket_interface_enabled(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+	const void *sock;
+	bt_status_t status;
+
+	setup(data);
+
+	sock = data->if_bluetooth->get_profile_interface(BT_PROFILE_SOCKETS_ID);
+	if (!sock) {
+		tester_setup_failed();
+		return;
+	}
+
+	data->if_sock = sock;
+
+	status = data->if_bluetooth->enable();
+	if (status != BT_STATUS_SUCCESS)
+		tester_setup_failed();
+}
+
 static void test_generic_listen(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
@@ -1148,6 +1169,97 @@ clean:
 		close(sock_fd);
 }
 
+static gboolean socket_chan_cb(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	int sock_fd = g_io_channel_unix_get_fd(io);
+	struct test_data *data = tester_get_data();
+	const struct socket_data *test = data->test_data;
+	int channel, len;
+
+	tester_print("%s", __func__);
+
+	if (cond & G_IO_HUP) {
+		tester_warn("Socket %d hang up", sock_fd);
+		goto failed;
+	}
+
+	if (cond & (G_IO_ERR | G_IO_NVAL)) {
+		tester_warn("Socket error: sock %d cond %d", sock_fd, cond);
+		goto failed;
+	}
+
+	if (test->test_channel) {
+		len = read(sock_fd, &channel, sizeof(channel));
+		if (len != sizeof(channel) || channel != test->channel)
+			goto failed;
+
+		tester_print("read correct channel: %d", channel);
+		tester_test_passed();
+		return FALSE;
+	}
+
+failed:
+	tester_test_failed();
+	return FALSE;
+}
+
+static void test_socket_real_connect(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+	const struct socket_data *test = data->test_data;
+	struct bthost *bthost = hciemu_client_get_host(data->hciemu);
+	const uint8_t *client_bdaddr;
+	bt_bdaddr_t emu_bdaddr;
+	bt_status_t status;
+	int sock_fd = -1;
+
+	client_bdaddr = hciemu_get_client_bdaddr(data->hciemu);
+	if (!client_bdaddr) {
+		tester_warn("No client bdaddr");
+		tester_test_failed();
+		return;
+	}
+
+	bdaddr2android((bdaddr_t *) client_bdaddr, &emu_bdaddr);
+
+	bthost_set_server_psm(bthost, 0x0003);
+
+	status = data->if_sock->connect(&emu_bdaddr, test->sock_type,
+					test->service_uuid, test->channel,
+					&sock_fd, test->flags);
+	if (status != test->expected_status) {
+		tester_test_failed();
+		goto clean;
+	}
+
+	/* Check that file descriptor is valid */
+	if (status == BT_STATUS_SUCCESS && fcntl(sock_fd, F_GETFD) == -1) {
+		tester_test_failed();
+		return;
+	}
+
+	tester_print("status %d sock_fd %d", status, sock_fd);
+
+	if (status == BT_STATUS_SUCCESS) {
+		GIOChannel *io;
+
+		io = g_io_channel_unix_new(sock_fd);
+		g_io_channel_set_close_on_unref(io, TRUE);
+
+		g_io_add_watch(io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				socket_chan_cb, NULL);
+
+		g_io_channel_unref(io);
+	}
+
+	return;
+
+clean:
+	if (sock_fd >= 0)
+		close(sock_fd);
+}
+
 #define test_bredrle(name, data, test_setup, test, test_teardown) \
 	do { \
 		struct test_data *user; \
@@ -1267,5 +1379,10 @@ int main(int argc, char *argv[])
 			&btsock_inv_param_bdaddr,
 			setup_socket_interface, test_generic_connect, teardown);
 
+	test_bredrle("Socket Connect - Check returned chan",
+			&btsock_success_check_chan,
+			setup_socket_interface_enabled,
+			test_socket_real_connect, teardown);
+
 	return tester_run();
 }
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH 2/3] android/socket: Connect directly to RFCOMM chan is uuid is zero
From: Andrei Emeltchenko @ 2013-12-18 14:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1387376336-17092-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Check uuid and connect to specified channel number directly.
---
 android/socket.c | 32 +++++++++++++++++++++++---------
 1 file changed, 23 insertions(+), 9 deletions(-)

diff --git a/android/socket.c b/android/socket.c
index 656222e..7bc5b0b 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -925,10 +925,17 @@ fail:
 	cleanup_rfsock(rfsock);
 }
 
+static bool is_empty(const uint8_t *uuid)
+{
+	static uint8_t zero_uuid[16];
+
+	return memcmp(uuid, zero_uuid, sizeof(zero_uuid)) == 0;
+}
+
 static void handle_connect(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_sock_connect *cmd = buf;
-	struct rfcomm_sock *rfsock;
+	struct rfcomm_sock *rfsock = NULL;
 	uuid_t uuid;
 	int hal_fd = -1;
 
@@ -940,17 +947,21 @@ static void handle_connect(const void *buf, uint16_t len)
 
 	android2bdaddr(cmd->bdaddr, &rfsock->dst);
 
-	memset(&uuid, 0, sizeof(uuid));
-	uuid.type = SDP_UUID128;
-	memcpy(&uuid.value.uuid128, cmd->uuid, sizeof(uint128_t));
+	if (is_empty(cmd->uuid)) {
+		if (!do_connect(rfsock, cmd->channel))
+			goto failed;
+	} else {
+		memset(&uuid, 0, sizeof(uuid));
+		uuid.type = SDP_UUID128;
+		memcpy(&uuid.value.uuid128, cmd->uuid, sizeof(uint128_t));
 
-	rfsock->profile = get_profile_by_uuid(cmd->uuid);
+		rfsock->profile = get_profile_by_uuid(cmd->uuid);
 
-	if (bt_search_service(&adapter_addr, &rfsock->dst, &uuid,
+		if (bt_search_service(&adapter_addr, &rfsock->dst, &uuid,
 					sdp_search_cb, rfsock, NULL) < 0) {
-		error("Failed to search SDP records");
-		cleanup_rfsock(rfsock);
-		goto failed;
+			error("Failed to search SDP records");
+			goto failed;
+		}
 	}
 
 	ipc_send_rsp_full(HAL_SERVICE_ID_SOCK, HAL_OP_SOCK_CONNECT, 0, NULL,
@@ -962,6 +973,9 @@ failed:
 	ipc_send_rsp(HAL_SERVICE_ID_SOCK, HAL_OP_SOCK_CONNECT,
 							HAL_STATUS_FAILED);
 
+	if (rfsock)
+		cleanup_rfsock(rfsock);
+
 	if (hal_fd >= 0)
 		close(hal_fd);
 }
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH 1/3] android/socket: Refactor connect to allow directly connect to rfcomm
From: Andrei Emeltchenko @ 2013-12-18 14:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1387376336-17092-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Since Socket HAL allows us to specify RFCOMM channel number and directly
connect refactor send function to allow connect directly is uuid is zero
and channel number is specified.
---
 android/socket.c | 71 +++++++++++++++++++++++++++++++-------------------------
 1 file changed, 39 insertions(+), 32 deletions(-)

diff --git a/android/socket.c b/android/socket.c
index cee4b6e..656222e 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -838,13 +838,47 @@ fail:
 	cleanup_rfsock(rfsock);
 }
 
-static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
+static bool do_connect(struct rfcomm_sock *rfsock, int chan)
 {
-	struct rfcomm_sock *rfsock = data;
 	BtIOSecLevel sec_level = BT_IO_SEC_MEDIUM;
+	GIOChannel *io;
 	GError *gerr = NULL;
+
+	if (rfsock->profile)
+		sec_level = rfsock->profile->sec_level;
+
+	io = bt_io_connect(connect_cb, rfsock, NULL, &gerr,
+				BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+				BT_IO_OPT_DEST_BDADDR, &rfsock->dst,
+				BT_IO_OPT_CHANNEL, chan,
+				BT_IO_OPT_SEC_LEVEL, sec_level,
+				BT_IO_OPT_INVALID);
+	if (!io) {
+		error("Failed connect: %s", gerr->message);
+		g_error_free(gerr);
+		return false;
+	}
+
+	g_io_channel_set_close_on_unref(io, FALSE);
+	g_io_channel_unref(io);
+
+	if (write(rfsock->fd, &chan, sizeof(chan)) != sizeof(chan)) {
+		error("Error sending RFCOMM channel");
+		return false;
+	}
+
+	rfsock->real_sock = g_io_channel_unix_get_fd(io);
+	rfsock_set_buffer(rfsock);
+	rfsock->channel = chan;
+	connections = g_list_append(connections, rfsock);
+
+	return true;
+}
+
+static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
+{
+	struct rfcomm_sock *rfsock = data;
 	sdp_list_t *list;
-	GIOChannel *io;
 	int chan;
 
 	DBG("");
@@ -885,36 +919,9 @@ static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
 
 	DBG("Got RFCOMM channel %d", chan);
 
-	if (rfsock->profile)
-		sec_level = rfsock->profile->sec_level;
-
-	io = bt_io_connect(connect_cb, rfsock, NULL, &gerr,
-				BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
-				BT_IO_OPT_DEST_BDADDR, &rfsock->dst,
-				BT_IO_OPT_CHANNEL, chan,
-				BT_IO_OPT_SEC_LEVEL, sec_level,
-				BT_IO_OPT_INVALID);
-	if (!io) {
-		error("Failed connect: %s", gerr->message);
-		g_error_free(gerr);
-		goto fail;
-	}
-
-	if (write(rfsock->fd, &chan, sizeof(chan)) != sizeof(chan)) {
-		error("Error sending RFCOMM channel");
-		goto fail;
-	}
-
-	rfsock->real_sock = g_io_channel_unix_get_fd(io);
-	rfsock_set_buffer(rfsock);
-	rfsock->channel = chan;
-	connections = g_list_append(connections, rfsock);
-
-	g_io_channel_unref(io);
-
-	return;
+	if (do_connect(rfsock, chan))
+		return;
 fail:
-	connections = g_list_remove(connections, rfsock);
 	cleanup_rfsock(rfsock);
 }
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH 0/3] Allow directly connect to RFCOMM channel
From: Andrei Emeltchenko @ 2013-12-18 14:18 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Since Android calls allows directly connect to specified channel numbers
refactor code which makes connect to function and reuse it from both
places. This allows to test connect without parsing SDP.

Andrei Emeltchenko (3):
  android/socket: Refactor connect to allow directly connect to rfcomm
  android/socket: Connect directly to RFCOMM chan is uuid is zero
  android/tester: Test that connect call returns channel number

 android/android-tester.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++
 android/socket.c         | 103 ++++++++++++++++++++++++-----------------
 2 files changed, 179 insertions(+), 41 deletions(-)

-- 
1.8.3.2


^ permalink raw reply

* [PATCH 4/4] android/bluetooth: Add support for restoring devices from storage
From: Szymon Janc @ 2013-12-18 14:05 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1387375558-17976-1-git-send-email-szymon.janc@tieto.com>

This adds support to restore bonded devices from storage (including
linkkeys).
---
 android/bluetooth.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 112 insertions(+), 1 deletion(-)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index dd16a54..c7fb95f 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -1576,6 +1576,117 @@ static void clear_uuids(void)
 					sizeof(cp), &cp, NULL, NULL, NULL);
 }
 
+static void create_device_from_info(GKeyFile *key_file, const char *peer)
+{
+	struct device *dev;
+	uint8_t type;
+	bdaddr_t bdaddr;
+	char **uuids;
+	char *str;
+
+	DBG("%s", peer);
+
+	type = g_key_file_get_integer(key_file, peer, "Type", NULL);
+
+	str2ba(peer, &bdaddr);
+	dev = create_device(&bdaddr, type);
+
+	dev->bond_state = HAL_BOND_STATE_BONDED;
+
+	str = g_key_file_get_string(key_file, peer, "Name", NULL);
+	if (str) {
+		g_free(dev->name);
+		dev->name = str;
+	}
+
+	str = g_key_file_get_string(key_file, peer, "FriendlyName", NULL);
+	if (str) {
+		g_free(dev->friendly_name);
+		dev->friendly_name = str;
+	}
+
+	dev->class = g_key_file_get_integer(key_file, peer, "Class", NULL);
+
+	uuids = g_key_file_get_string_list(key_file, peer, "Services", NULL,
+									NULL);
+	if (uuids) {
+		char **uuid;
+
+		for (uuid = uuids; *uuid; uuid++) {
+			uint8_t *u = g_malloc0(16);
+			int i;
+
+			for (i = 0; i < 16; i++)
+				sscanf((*uuid) + (i * 2), "%02hhX", &u[i]);
+
+			dev->uuids = g_slist_append(dev->uuids, u);
+		}
+
+		g_strfreev(uuids);
+	}
+}
+
+static struct mgmt_link_key_info *get_key_info(GKeyFile *key_file, const char *peer)
+{
+	struct mgmt_link_key_info *info = NULL;
+	char *str;
+	unsigned int i;
+
+	str = g_key_file_get_string(key_file, peer, "LinkKey", NULL);
+	if (!str || strlen(str) != 32)
+		goto failed;
+
+	info = g_new0(struct mgmt_link_key_info, 1);
+
+	str2ba(peer, &info->addr.bdaddr);
+
+	info->addr.type = g_key_file_get_integer(key_file, peer, "Type", NULL);
+
+	for (i = 0; i < sizeof(info->val); i++)
+		sscanf(str + (i * 2), "%02hhX", &info->val[i]);
+
+	info->type = g_key_file_get_integer(key_file, peer, "LinkKeyType",
+									NULL);
+	info->pin_len = g_key_file_get_integer(key_file, peer,
+						"LinkKeyPINLength", NULL);
+
+failed:
+	g_free(str);
+
+	return info;
+}
+
+static void load_devices_info(bt_bluetooth_ready cb)
+{
+	GKeyFile *key_file;
+	gchar **devs;
+	gsize len = 0;
+	unsigned int i;
+	GSList *keys = NULL;
+
+	key_file = g_key_file_new();
+
+	g_key_file_load_from_file(key_file, ANDROID_STORAGEDIR"/devices", 0,
+									NULL);
+
+	devs = g_key_file_get_groups(key_file, &len);
+
+	for (i = 0; i < len; i++) {
+		struct mgmt_link_key_info *key_info;
+
+		create_device_from_info(key_file, devs[i]);
+
+		key_info = get_key_info(key_file, devs[i]);
+		if (key_info)
+			keys = g_slist_prepend(keys, key_info);
+
+		/* TODO ltk */
+	}
+
+	load_link_keys(keys, cb);
+	g_slist_free_full(keys, g_free);
+}
+
 static void read_info_complete(uint8_t status, uint16_t length,
 					const void *param, void *user_data)
 {
@@ -1630,7 +1741,7 @@ static void read_info_complete(uint8_t status, uint16_t length,
 
 	clear_uuids();
 
-	load_link_keys(NULL, cb);
+	load_devices_info(cb);
 
 	set_io_capability();
 	set_device_id();
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH 3/4] android/bluetooth: Add support for storing link keys
From: Szymon Janc @ 2013-12-18 14:05 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1387375558-17976-1-git-send-email-szymon.janc@tieto.com>

When new linkkey event is received store linkkey in devices info file.
Stored info includes linkkey, linkkey type and pin length.
---
 android/bluetooth.c | 36 ++++++++++++++++++++++++++++++++----
 1 file changed, 32 insertions(+), 4 deletions(-)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index b8f078f..dd16a54 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -493,7 +493,35 @@ static void mgmt_dev_class_changed_event(uint16_t index, uint16_t length,
 static void store_link_key(const bdaddr_t *dst, const uint8_t *key,
 					uint8_t type, uint8_t pin_length)
 {
-	/* TODO store link key */
+	GKeyFile *key_file;
+	char key_str[33];
+	gsize length = 0;
+	char addr[18];
+	char *data;
+	int i;
+
+	key_file = g_key_file_new();
+
+	if (!g_key_file_load_from_file(key_file, ANDROID_STORAGEDIR"/devices",
+								0, NULL))
+		return;
+
+	ba2str(dst, addr);
+
+	DBG("%s type %u pin_len %u", addr, type, pin_length);
+
+	for (i = 0; i < 16; i++)
+		sprintf(key_str + (i * 2), "%2.2X", key[i]);
+
+	g_key_file_set_string(key_file, addr, "LinkKey", key_str);
+	g_key_file_set_integer(key_file, addr, "LinkKeyType", type);
+	g_key_file_set_integer(key_file, addr, "LinkKeyPINLength", pin_length);
+
+	data = g_key_file_to_data(key_file, &length, NULL);
+	g_file_set_contents(ANDROID_STORAGEDIR"/devices", data, length, NULL);
+	g_free(data);
+
+	g_key_file_free(key_file);
 }
 
 static void send_bond_state_change(const bdaddr_t *addr, uint8_t status,
@@ -720,6 +748,9 @@ static void new_link_key_callback(uint16_t index, uint16_t length,
 		return;
 	}
 
+	set_device_bond_state(&addr->bdaddr, HAL_STATUS_SUCCESS,
+							HAL_BOND_STATE_BONDED);
+
 	if (ev->store_hint) {
 		const struct mgmt_link_key_info *key = &ev->key;
 
@@ -727,9 +758,6 @@ static void new_link_key_callback(uint16_t index, uint16_t length,
 								key->pin_len);
 	}
 
-	set_device_bond_state(&addr->bdaddr, HAL_STATUS_SUCCESS,
-							HAL_BOND_STATE_BONDED);
-
 	browse_remote_sdp(&addr->bdaddr);
 }
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH 2/4] android/bluetooth: Add initial support for storing device info
From: Szymon Janc @ 2013-12-18 14:05 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1387375558-17976-1-git-send-email-szymon.janc@tieto.com>

This allows to store information about remote device. For now this is
stored only for bonded devices. Currently stored data includes devices
ddress, type, name, friendly name, class and uuids.
---
 android/bluetooth.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 68 insertions(+), 1 deletion(-)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index 114a466..b8f078f 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -196,6 +196,69 @@ static void load_adapter_config(void)
 	g_key_file_free(key_file);
 }
 
+static void store_device_info(struct device *dev)
+{
+	GKeyFile *key_file;
+	char addr[18];
+	gsize length = 0;
+	char **uuids = NULL;
+	char *str;
+
+	if (dev->bond_state != HAL_BOND_STATE_BONDED)
+		return;
+
+	ba2str(&dev->bdaddr, addr);
+
+	key_file = g_key_file_new();
+	g_key_file_load_from_file(key_file, ANDROID_STORAGEDIR"/devices", 0,
+									NULL);
+
+	g_key_file_set_integer(key_file, addr, "Type", dev->bdaddr_type);
+
+	g_key_file_set_string(key_file, addr, "Name", dev->name);
+
+	if (dev->friendly_name)
+		g_key_file_set_string(key_file, addr, "FriendlyName",
+							dev->friendly_name);
+	else
+		g_key_file_remove_key(key_file, addr, "FriendlyName", NULL);
+
+	if (dev->class)
+		g_key_file_set_integer(key_file, addr, "Class", dev->class);
+	else
+		g_key_file_remove_key(key_file, addr, "Class", NULL);
+
+	if (dev->uuids) {
+		GSList *l;
+		int i;
+
+		uuids = g_new0(char *, g_slist_length(dev->uuids) + 1);
+
+		for (i = 0, l = dev->uuids; l; l = g_slist_next(l), i++) {
+			int j;
+			uint8_t *u = l->data;
+			char *uuid_str = g_malloc0(33);
+
+			for (j = 0; j < 16; j++)
+				sprintf(uuid_str + (j * 2), "%2.2X", u[j]);
+
+			uuids[i] = uuid_str;
+		}
+
+		g_key_file_set_string_list(key_file, addr, "Services",
+						(const char **)uuids, i);
+	} else {
+		g_key_file_remove_key(key_file, addr, "Services", NULL);
+	}
+
+	str = g_key_file_to_data(key_file, &length, NULL);
+	g_file_set_contents(ANDROID_STORAGEDIR"/devices", str, length, NULL);
+	g_free(str);
+
+	g_key_file_free(key_file);
+	g_strfreev(uuids);
+}
+
 static int bdaddr_cmp(gconstpointer a, gconstpointer b)
 {
 	const bdaddr_t *bda = a;
@@ -458,6 +521,8 @@ static void set_device_bond_state(const bdaddr_t *addr, uint8_t status,
 	if (dev->bond_state != state) {
 		dev->bond_state = state;
 		send_bond_state_change(&dev->bdaddr, status, state);
+
+		store_device_info(dev);
 	}
 }
 
@@ -498,6 +563,8 @@ static void set_device_uuids(struct device *dev, GSList *uuids)
 	g_slist_free_full(dev->uuids, g_free);
 	dev->uuids = uuids;
 
+	store_device_info(dev);
+
 	send_device_uuids_notif(dev);
 }
 
@@ -2539,7 +2606,7 @@ static uint8_t set_device_friendly_name(struct device *dev, const uint8_t *val,
 	g_free(dev->friendly_name);
 	dev->friendly_name = g_strndup((const char *) val, len);
 
-	/* TODO store friendly name */
+	store_device_info(dev);
 
 	send_device_property(&dev->bdaddr, HAL_PROP_DEVICE_FRIENDLY_NAME,
 				strlen(dev->friendly_name), dev->friendly_name);
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH 1/4] android/bluetooth: Add initial support for permanent storage
From: Szymon Janc @ 2013-12-18 14:05 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1387375558-17976-1-git-send-email-szymon.janc@tieto.com>

This patch adds initial support for storing adapter configuration.
Currently stored data is address, name and discoverable timeout.

Since Android daemon storage format is to be simpler than Linux check
if correct adapter is used before going operational. This is
a precaution to avoid e.g. using linkkeys generated for different
controller.
---
 android/Android.mk  |  3 +-
 android/bluetooth.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 configure.ac        |  3 ++
 3 files changed, 95 insertions(+), 6 deletions(-)

diff --git a/android/Android.mk b/android/Android.mk
index ebc3219..2953a6e 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -8,7 +8,8 @@ pathmap_INCL += glib:external/bluetooth/glib
 
 # Specify common compiler flags
 BLUEZ_COMMON_CFLAGS := -DVERSION=\"$(BLUEZ_VERSION)\" \
-	-DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION)
+	-DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION) \
+	-DANDROID_STORAGEDIR=\"/data/misc/bluetooth\" \
 
 # Disable warnings enabled by Android but not enabled in autotools build
 BLUEZ_COMMON_CFLAGS += -Wno-pointer-arith -Wno-missing-field-initializers
diff --git a/android/bluetooth.c b/android/bluetooth.c
index 97d4aae..114a466 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -27,6 +27,10 @@
 
 #include <errno.h>
 #include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 
 #include <glib.h>
 
@@ -123,6 +127,75 @@ static GSList *devices = NULL;
 /* This list contains addresses which are asked for records */
 static GSList *browse_reqs;
 
+static void store_adapter_config(void)
+{
+	GKeyFile *key_file;
+	gsize length = 0;
+	char addr[18];
+	char *data;
+
+	key_file = g_key_file_new();
+
+	if (!g_key_file_load_from_file(key_file, ANDROID_STORAGEDIR"/settings",
+								0, NULL)) {
+		int fd = open(ANDROID_STORAGEDIR"/settings", O_CREAT, 0600);
+		if (fd < 0) {
+			error("Failed to create adapter config file: %d (%s)",
+							errno, strerror(errno));
+			return;
+		}
+
+		close(fd);
+	}
+
+	ba2str(&adapter.bdaddr, addr);
+
+	g_key_file_set_string(key_file, "General", "Address", addr);
+	g_key_file_set_string(key_file, "General", "Name", adapter.name);
+	g_key_file_set_integer(key_file, "General", "DiscoverableTimeout",
+						adapter.discoverable_timeout);
+
+	data = g_key_file_to_data(key_file, &length, NULL);
+
+	g_file_set_contents(ANDROID_STORAGEDIR"/settings", data, length, NULL);
+
+	g_free(data);
+	g_key_file_free(key_file);
+}
+
+static void load_adapter_config(void)
+{
+	GError *gerr = NULL;
+	GKeyFile *key_file;
+	char *str;
+
+	key_file = g_key_file_new();
+
+	g_key_file_load_from_file(key_file, ANDROID_STORAGEDIR"/settings", 0,
+									NULL);
+
+	str = g_key_file_get_string(key_file, "General", "Address", NULL);
+	if (!str) {
+		g_key_file_free(key_file);
+		return;
+	}
+
+	str2ba(str, &adapter.bdaddr);
+	g_free(str);
+
+	adapter.name = g_key_file_get_string(key_file, "General", "Name", NULL);
+
+	adapter.discoverable_timeout = g_key_file_get_integer(key_file,
+				"General", "DiscoverableTimeout", &gerr);
+	if (gerr) {
+		adapter.discoverable_timeout = DEFAULT_DISCOVERABLE_TIMEOUT;
+		g_error_free(gerr);
+		gerr = NULL;
+	}
+
+	g_key_file_free(key_file);
+}
+
 static int bdaddr_cmp(gconstpointer a, gconstpointer b)
 {
 	const bdaddr_t *bda = a;
@@ -215,6 +288,8 @@ static void adapter_set_name(const uint8_t *name)
 	g_free(adapter.name);
 	adapter.name = g_strdup((const char *) name);
 
+	store_adapter_config();
+
 	adapter_name_changed(name);
 }
 
@@ -1385,9 +1460,10 @@ static uint8_t set_adapter_discoverable_timeout(const void *buf, uint16_t len)
 	 * There is no need to use kernel feature for that.
 	 * Just need to store this value here */
 
-	/* TODO: This should be in some storage */
 	memcpy(&adapter.discoverable_timeout, timeout, sizeof(uint32_t));
 
+	store_adapter_config();
+
 	send_adapter_property(HAL_PROP_ADAPTER_DISC_TIMEOUT,
 					sizeof(adapter.discoverable_timeout),
 					&adapter.discoverable_timeout);
@@ -1434,17 +1510,26 @@ static void read_info_complete(uint8_t status, uint16_t length,
 		goto failed;
 	}
 
+	load_adapter_config();
+
+	if (!bacmp(&adapter.bdaddr, BDADDR_ANY)) {
+		bacpy(&adapter.bdaddr, &rp->bdaddr);
+		adapter.name = g_strdup((const char *) rp->name);
+		store_adapter_config();
+		set_adapter_name(rp->name, strlen((char *)rp->name));
+	} else if (bacmp(&adapter.bdaddr, &rp->bdaddr)) {
+		error("Bluetooth address mismatch");
+		err = -ENODEV;
+		goto failed;
+	}
+
 	/* Store adapter information */
-	bacpy(&adapter.bdaddr, &rp->bdaddr);
 	adapter.dev_class = rp->dev_class[0] | (rp->dev_class[1] << 8) |
 						(rp->dev_class[2] << 16);
-	adapter.name = g_strdup((const char *) rp->name);
 
 	supported_settings = btohs(rp->supported_settings);
 	adapter.current_settings = btohs(rp->current_settings);
 
-	/* TODO: Read discoverable timeout from storage here */
-
 	/* TODO: Register all event notification handlers */
 	register_mgmt_handlers();
 
diff --git a/configure.ac b/configure.ac
index 18d0b55..5171c38 100644
--- a/configure.ac
+++ b/configure.ac
@@ -252,4 +252,7 @@ AC_ARG_ENABLE(android, AC_HELP_STRING([--enable-android],
 					[enable_android=${enableval}])
 AM_CONDITIONAL(ANDROID, test "${enable_android}" = "yes")
 
+AC_DEFINE_UNQUOTED(ANDROID_STORAGEDIR, "${storagedir}/android",
+			[Directory for the Android daemon storage files])
+
 AC_OUTPUT(Makefile src/bluetoothd.8 lib/bluez.pc)
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH 0/4] android: Permanent storage support
From: Szymon Janc @ 2013-12-18 14:05 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

V2:
 - no longer RFC
 - linkkeys and uuids stored as hexstrings without leading 0x
 - Android storage path changed to /data/misc/bluetooth

Szymon Janc (4):
  android/bluetooth: Add initial support for permanent storage
  android/bluetooth: Add initial support for storing device info
  android/bluetooth: Add support for storing link keys
  android/bluetooth: Add support for restoring devices from storage

 android/Android.mk  |   3 +-
 android/bluetooth.c | 313 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 configure.ac        |   3 +
 3 files changed, 307 insertions(+), 12 deletions(-)

-- 
1.8.3.2


^ permalink raw reply

* [PATCH v2 BlueZ] build: Add coverage support
From: Luiz Augusto von Dentz @ 2013-12-18 13:09 UTC (permalink / raw)
  To: linux-bluetooth

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

Coverage is enabled with --enable-maintainer-mode, 2 new targets are
added 'coverage' and 'clean-coverage', the first generate the reports
using lcov and depend on the second to cleanup previous generated
reports and .gcda files.
---
 .gitignore   |  4 ++++
 Makefile.am  | 18 ++++++++++++++++++
 acinclude.m4 |  4 ++++
 configure.ac |  4 ++++
 4 files changed, 30 insertions(+)

diff --git a/.gitignore b/.gitignore
index c570728..21dbe26 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,8 @@
 *.lo
 *.la
 *.so
+*.gcno
+*.gcda
 .deps
 .libs
 .dirstamp
@@ -27,7 +29,9 @@ stamp-h1
 autom4te.cache
 test-driver
 test-suite.log
+coverage.info
 
+coverage
 lib/bluez.pc
 lib/bluetooth
 src/builtin.h
diff --git a/Makefile.am b/Makefile.am
index 15cc149..7380e61 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -331,5 +331,23 @@ lib/bluetooth/%.h: lib/%.h
 	$(AM_V_at)$(MKDIR_P) lib/bluetooth
 	$(AM_V_GEN)$(LN_S) -f "$(abs_top_builddir)"/$< $@
 
+if MAINTAINER_MODE
+clean-coverage:
+	-find $(top_builddir) -name "*.gcda" -delete
+	@lcov --directory $(top_builddir) --zerocounters
+	$(RM) -r coverage $(top_builddir)/coverage.info
+
+coverage: clean-coverage check
+	@lcov --compat-libtool --directory $(top_builddir) --capture \
+				--output-file $(top_builddir)/coverage.info
+	$(AM_V_at)$(MKDIR_P) coverage
+	@genhtml -o coverage/ $(top_builddir)/coverage.info
+
+clean-local: clean-coverage
+	-find $(top_builddir) -name "*.gcno" -delete
+	$(RM) -r lib/bluetooth
+
+else
 clean-local:
 	$(RM) -r lib/bluetooth
+endif
diff --git a/acinclude.m4 b/acinclude.m4
index 2065852..afc7c6d 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -51,6 +51,10 @@ AC_DEFUN([MISC_FLAGS], [
 			misc_ldflags="$misc_ldflags -pie"
 		fi
 	])
+	if (test "$USE_MAINTAINER_MODE" = "yes"); then
+		misc_cflags="$misc_cflags --coverage"
+		misc_ldflags="$misc_ldflags --coverage"
+	fi
 	AC_SUBST([MISC_CFLAGS], $misc_cflags)
 	AC_SUBST([MISC_LDFLAGS], $misc_ldflags)
 ])
diff --git a/configure.ac b/configure.ac
index 18d0b55..4f36355 100644
--- a/configure.ac
+++ b/configure.ac
@@ -252,4 +252,8 @@ AC_ARG_ENABLE(android, AC_HELP_STRING([--enable-android],
 					[enable_android=${enableval}])
 AM_CONDITIONAL(ANDROID, test "${enable_android}" = "yes")
 
+if (test "$USE_MAINTAINER_MODE" = "yes"); then
+	AC_CHECK_PROG([LCOV], [lcov], [yes], AC_MSG_ERROR(lcov is required))
+fi
+
 AC_OUTPUT(Makefile src/bluetoothd.8 lib/bluez.pc)
-- 
1.8.3.1


^ permalink raw reply related

* Re: [PATCH BlueZ] android/AVDTP: Fix not removing start_timer source
From: Johan Hedberg @ 2013-12-18 12:54 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1387369783-28164-1-git-send-email-luiz.dentz@gmail.com>

Hi Luiz,

On Wed, Dec 18, 2013, Luiz Augusto von Dentz wrote:
> It is possible that stream->start_timer can be set on stream_free which
> should then should take care of remove it properly otherwise it can
> trigger which would very likely cause a crash.
> 
> Thanks to Hannu Mallat <hannu.mallat@jolla.com> for reporting it.
> ---
>  android/avdtp.c | 3 +++
>  1 file changed, 3 insertions(+)

Applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH 1/2] android/tester: Move Bluetooth HAL functions before socket HAL
From: Johan Hedberg @ 2013-12-18 12:53 UTC (permalink / raw)
  To: Grzegorz Kolodziejczyk; +Cc: linux-bluetooth
In-Reply-To: <1387367677-8099-1-git-send-email-grzegorz.kolodziejczyk@tieto.com>

Hi Grzegorz,

On Wed, Dec 18, 2013, Grzegorz Kolodziejczyk wrote:
> This patch move bluetooth HAL test functions before socket
> HAL functions. This make it more readable for future test cases growth.
> ---
>  android/android-tester.c | 272 +++++++++++++++++++++++------------------------
>  1 file changed, 136 insertions(+), 136 deletions(-)

Both patches have been applied. Thanks.

Johan

^ permalink raw reply

* pull request: bluetooth 2013-12-18
From: Gustavo Padovan @ 2013-12-18 12:52 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, linux-bluetooth, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1248 bytes --]

Hi John,

Two patches in this pull request. An important fix from Marcel in the
permission check for HCI User Channels, there was a extra check for
CAP_NET_RAW, and it was now removed. These channels should only require
CAP_NET_ADMIN. The other patch is a device id addition.

Please pull or let me know of any problems! Thanks.

        Gustavo

---
The following changes since commit eafbdde9c5629bea58df07275c5917eb42afbbe7:

  rtlwifi: rtl8192cu: Fix more pointer arithmetic errors (2013-11-15 14:29:33 -0500)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git for-upstream

for you to fetch changes up to 1bc5ad168f441f6f8bfd944288a5f7b4963ac1f6:

  Bluetooth: Fix HCI User Channel permission check in hci_sock_sendmsg (2013-12-17 13:47:27 +0200)

----------------------------------------------------------------
Marcel Holtmann (1):
      Bluetooth: Fix HCI User Channel permission check in hci_sock_sendmsg

Marco Piazza (1):
      Bluetooth: Add support for Toshiba Bluetooth device [0930:0220]

 drivers/bluetooth/ath3k.c |  2 ++
 drivers/bluetooth/btusb.c |  1 +
 net/bluetooth/hci_sock.c  | 26 ++++++++++++++++----------
 3 files changed, 19 insertions(+), 10 deletions(-)


[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [RFC 0/4] android: Permanent storage support
From: Szymon Janc @ 2013-12-18 12:39 UTC (permalink / raw)
  To: Andrei Emeltchenko
  Cc: Marcel Holtmann, linux-bluetooth@vger.kernel.org development
In-Reply-To: <20131218123111.GE26311@aemeltch-MOBL1>

Hi Andrei,

> Hi Szymon,
> 
> On Wed, Dec 18, 2013 at 01:23:40PM +0100, Szymon Janc wrote:
> > Hi Marcel,
> > 
> > > Hi Szymon,
> > > 
> > > > This is first RFC for storage format for Android daemon.
> > > > 
> > > > Some highlights:
> > > > - storage is much simple in format than Linux daemon (no addresses in paths
> > > >  or filenames, only 1 adapter support etc)
> > > > - only info that requires persistency  over daemon lifetime from Framework
> > > >  perspective is stored
> > > > - settings file for adapter config
> > > > - devices file for remote device info (groups are remote devices addresses)
> > > > - Android storage path is /data/misc/bluez (I've decided to not use
> > > >  /data/misc/bluetooth to avoid any clashes as there still seems to be
> > > >  leftovers available in Android tree eg. there are still references to that
> > > >  directory in CTS testcases and init files of Android 4.4)
> > > 
> > > I would use /data/misc/bluetooth actually. Especially since the daemon is also called bluetoothd and not bluezd.
> > > 
> > > What is the impact on just using /data/misc/bluetooth and see if anything really breaks.
> > 
> > OK, this will require proper chown in device init.rc (as it is set to system/system
> > in system/core/rootdir/init.rc), but that would be needed for /data/misc/bluez path
> > anyway...
> 
> I wonder can we find place without need to add extra chown... like using
> Bluedroid configuration location?

I would avoid touching bluedroid configs (other than converting storage, but
this is future anyway). And anyone integrating BlueZ into product will need to
modify init.rc anyway so this is not that much of a problem.

-- 
BR
Szymon Janc

^ permalink raw reply

* Re: [RFC 0/4] android: Permanent storage support
From: Marcel Holtmann @ 2013-12-18 12:35 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1743761.bXhrtg3e4W@uw000953>

Hi Szymon,

>>> This is first RFC for storage format for Android daemon.
>>> 
>>> Some highlights:
>>> - storage is much simple in format than Linux daemon (no addresses in paths
>>> or filenames, only 1 adapter support etc)
>>> - only info that requires persistency  over daemon lifetime from Framework
>>> perspective is stored
>>> - settings file for adapter config
>>> - devices file for remote device info (groups are remote devices addresses)
>>> - Android storage path is /data/misc/bluez (I've decided to not use
>>> /data/misc/bluetooth to avoid any clashes as there still seems to be
>>> leftovers available in Android tree eg. there are still references to that
>>> directory in CTS testcases and init files of Android 4.4)
>> 
>> I would use /data/misc/bluetooth actually. Especially since the daemon is also called bluetoothd and not bluezd.
>> 
>> What is the impact on just using /data/misc/bluetooth and see if anything really breaks.
> 
> OK, this will require proper chown in device init.rc (as it is set to system/system
> in system/core/rootdir/init.rc), but that would be needed for /data/misc/bluez path
> anyway...
> 
>> 
>>> I'm not sure how to handle storage on Linux host so for now it is set to
>>> STORAGEDIR/android/ directory (if directory is missing it is not created
>>> by daemon).
>> 
>> That is actually fine. Works for me.
>> 
>>> Storage format is as following sample:
>>> 
>>> settings file:
>>> [General]
>>> Address=20:68:9D:3A:52:5E
>>> Name=BlueZ Android
>>> DiscoverableTimeout=0
>>> 
>>> devices file:
>>> [00:0D:3C:B1:C4:AC]
>>> Type=0
>>> Name=Nokia BH-503
>>> Class=2360324
>>> LinkKey=0x306A400930B0AE36D7AC45D8DC50F1A0
>> 
>> I would leave the 0x out of it. Just make it a hex encoded string.
> 
> OK.
> 
>> 
>>> LinkKeyType=0
>>> LinkKeyPINLength=4
>>> Services=0x0000110B00001000800000805F9B34FB;0x0000110C00001000800000805F9B34FB;0x0000110E00001000800000805F9B34FB;0x0000111E00001000800000805F9B34FB;0x0000110800001000800000805F9B34FB;
>> 
>> Lets store these as UUID strings. We convert between them anyway.
> 
> We actually don't use strings in Android daemon and keep UUIDs as 16bytes
> arrays (same format as HAL expects).
> So we would first need to convert to bt_uuid_t to be able to use lib/uuid.h
> uuid<->string helpers. We could also just add '-' where needed while converting
> array to hexstring if that really improves readability.

then just remove the 0x in front of it and store them the same way as the link keys.

>>> [00:1F:20:17:87:D7]
>>> Type=0
>>> Name=Bluetooth Laser Travel Mouse
>>> Class=9600
>>> LinkKey=0x3725CC552EAB8AB82D843BFEB14D2E47
>>> LinkKeyType=0
>>> LinkKeyPINLength=4
>>> Services=0x0000112400001000800000805F9B34FB;0x0000120000001000800000805F9B34FB;
>>> 
>>> [40:B0:FA:39:FF:B8]
>>> Type=0
>>> Name=Nexus 4
>>> Class=5898764
>>> LinkKey=0x1E201EE8E82E1E50682622077D372F20
>>> LinkKeyType=5
>>> LinkKeyPINLength=0
>>> Services=0x0000180100001000800000805F9B34FB;0x0000180000001000800000805F9B34FB;0x0000111200001000800000805F9B34FB;0x0000111F00001000800000805F9B34FB;0x0000110C00001000800000805F9B34FB;0x0000110A00001000800000805F9B34FB;0x0000110E00001000800000805F9B34FB;0x0000111600001000800000805F9B34FB;0x0000111500001000800000805F9B34FB;0x0000113200001000800000805F9B34FB;0x0000112F00001000800000805F9B34FB;0x0000110500001000800000805F9B34FB;
>>> 
>>> 
>>> Comments are welcome.
>> 
>> I think the only discussion we could have is if we want to store them as 1 file per remote device or all devices in one file. I am personally fine with this approach since it is a limited scope with Android anyway. Also upgrading to a more complex storage later is easily possible.
> 
> FWIW, we could also always keep g_key_file in memory and only write on update
> (to reduce reads). And that would be more complicated if we use multiple files.

Sure. That could be done as well.

Regards

Marcel


^ permalink raw reply

* Re: [RFC 0/4] android: Permanent storage support
From: Andrei Emeltchenko @ 2013-12-18 12:31 UTC (permalink / raw)
  To: Szymon Janc; +Cc: Marcel Holtmann, linux-bluetooth@vger.kernel.org development
In-Reply-To: <1743761.bXhrtg3e4W@uw000953>

Hi Szymon,

On Wed, Dec 18, 2013 at 01:23:40PM +0100, Szymon Janc wrote:
> Hi Marcel,
> 
> > Hi Szymon,
> > 
> > > This is first RFC for storage format for Android daemon.
> > > 
> > > Some highlights:
> > > - storage is much simple in format than Linux daemon (no addresses in paths
> > >  or filenames, only 1 adapter support etc)
> > > - only info that requires persistency  over daemon lifetime from Framework
> > >  perspective is stored
> > > - settings file for adapter config
> > > - devices file for remote device info (groups are remote devices addresses)
> > > - Android storage path is /data/misc/bluez (I've decided to not use
> > >  /data/misc/bluetooth to avoid any clashes as there still seems to be
> > >  leftovers available in Android tree eg. there are still references to that
> > >  directory in CTS testcases and init files of Android 4.4)
> > 
> > I would use /data/misc/bluetooth actually. Especially since the daemon is also called bluetoothd and not bluezd.
> > 
> > What is the impact on just using /data/misc/bluetooth and see if anything really breaks.
> 
> OK, this will require proper chown in device init.rc (as it is set to system/system
> in system/core/rootdir/init.rc), but that would be needed for /data/misc/bluez path
> anyway...

I wonder can we find place without need to add extra chown... like using
Bluedroid configuration location?

Best regards 
Andrei Emeltchenko 

^ permalink raw reply

* [PATCH BlueZ] android/AVDTP: Fix not removing start_timer source
From: Luiz Augusto von Dentz @ 2013-12-18 12:29 UTC (permalink / raw)
  To: linux-bluetooth

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

It is possible that stream->start_timer can be set on stream_free which
should then should take care of remove it properly otherwise it can
trigger which would very likely cause a crash.

Thanks to Hannu Mallat <hannu.mallat@jolla.com> for reporting it.
---
 android/avdtp.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/android/avdtp.c b/android/avdtp.c
index 5ae3afc..3a3380a 100644
--- a/android/avdtp.c
+++ b/android/avdtp.c
@@ -670,6 +670,9 @@ static void stream_free(void *data)
 	if (stream->timer)
 		g_source_remove(stream->timer);
 
+	if (stream->start_timer > 0)
+		g_source_remove(stream->start_timer);
+
 	if (stream->io)
 		close_stream(stream);
 
-- 
1.8.3.1


^ permalink raw reply related

* Re: [RFC 0/4] android: Permanent storage support
From: Szymon Janc @ 2013-12-18 12:23 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <3D8D935B-BE1E-4158-B2F5-8F49851A718C@holtmann.org>

Hi Marcel,

> Hi Szymon,
> 
> > This is first RFC for storage format for Android daemon.
> > 
> > Some highlights:
> > - storage is much simple in format than Linux daemon (no addresses in paths
> >  or filenames, only 1 adapter support etc)
> > - only info that requires persistency  over daemon lifetime from Framework
> >  perspective is stored
> > - settings file for adapter config
> > - devices file for remote device info (groups are remote devices addresses)
> > - Android storage path is /data/misc/bluez (I've decided to not use
> >  /data/misc/bluetooth to avoid any clashes as there still seems to be
> >  leftovers available in Android tree eg. there are still references to that
> >  directory in CTS testcases and init files of Android 4.4)
> 
> I would use /data/misc/bluetooth actually. Especially since the daemon is also called bluetoothd and not bluezd.
> 
> What is the impact on just using /data/misc/bluetooth and see if anything really breaks.

OK, this will require proper chown in device init.rc (as it is set to system/system
in system/core/rootdir/init.rc), but that would be needed for /data/misc/bluez path
anyway...

> 
> > I'm not sure how to handle storage on Linux host so for now it is set to
> > STORAGEDIR/android/ directory (if directory is missing it is not created
> > by daemon).
> 
> That is actually fine. Works for me.
> 
> > Storage format is as following sample:
> > 
> > settings file:
> > [General]
> > Address=20:68:9D:3A:52:5E
> > Name=BlueZ Android
> > DiscoverableTimeout=0
> > 
> > devices file:
> > [00:0D:3C:B1:C4:AC]
> > Type=0
> > Name=Nokia BH-503
> > Class=2360324
> > LinkKey=0x306A400930B0AE36D7AC45D8DC50F1A0
> 
> I would leave the 0x out of it. Just make it a hex encoded string.

OK.

> 
> > LinkKeyType=0
> > LinkKeyPINLength=4
> > Services=0x0000110B00001000800000805F9B34FB;0x0000110C00001000800000805F9B34FB;0x0000110E00001000800000805F9B34FB;0x0000111E00001000800000805F9B34FB;0x0000110800001000800000805F9B34FB;
> 
> Lets store these as UUID strings. We convert between them anyway.

We actually don't use strings in Android daemon and keep UUIDs as 16bytes
arrays (same format as HAL expects).
So we would first need to convert to bt_uuid_t to be able to use lib/uuid.h
uuid<->string helpers. We could also just add '-' where needed while converting
array to hexstring if that really improves readability.

> 
> > [00:1F:20:17:87:D7]
> > Type=0
> > Name=Bluetooth Laser Travel Mouse
> > Class=9600
> > LinkKey=0x3725CC552EAB8AB82D843BFEB14D2E47
> > LinkKeyType=0
> > LinkKeyPINLength=4
> > Services=0x0000112400001000800000805F9B34FB;0x0000120000001000800000805F9B34FB;
> > 
> > [40:B0:FA:39:FF:B8]
> > Type=0
> > Name=Nexus 4
> > Class=5898764
> > LinkKey=0x1E201EE8E82E1E50682622077D372F20
> > LinkKeyType=5
> > LinkKeyPINLength=0
> > Services=0x0000180100001000800000805F9B34FB;0x0000180000001000800000805F9B34FB;0x0000111200001000800000805F9B34FB;0x0000111F00001000800000805F9B34FB;0x0000110C00001000800000805F9B34FB;0x0000110A00001000800000805F9B34FB;0x0000110E00001000800000805F9B34FB;0x0000111600001000800000805F9B34FB;0x0000111500001000800000805F9B34FB;0x0000113200001000800000805F9B34FB;0x0000112F00001000800000805F9B34FB;0x0000110500001000800000805F9B34FB;
> > 
> > 
> > Comments are welcome.
> 
> I think the only discussion we could have is if we want to store them as 1 file per remote device or all devices in one file. I am personally fine with this approach since it is a limited scope with Android anyway. Also upgrading to a more complex storage later is easily possible.

FWIW, we could also always keep g_key_file in memory and only write on update
(to reduce reads). And that would be more complicated if we use multiple files.

-- 
BR
Szymon Janc

^ 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