Linux bluetooth development
 help / color / mirror / Atom feed
* [bluetooth-next 11/16] Bluetooth: move l2cap_sock_recvmsg() to l2cap_sock.c
From: Gustavo F. Padovan @ 2011-02-04  6:01 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1296799318-5517-11-git-send-email-padovan@profusion.mobi>

It causes the move of the declaration of 3 functions to l2cap.h:
l2cap_get_ident(), l2cap_send_cmd(), l2cap_build_conf_req()

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
 include/net/bluetooth/l2cap.h |    5 +++-
 net/bluetooth/l2cap_core.c    |   49 ++--------------------------------------
 net/bluetooth/l2cap_sock.c    |   42 +++++++++++++++++++++++++++++++++++
 3 files changed, 49 insertions(+), 47 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index b5ebf87..336b2af7 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -431,6 +431,10 @@ extern struct bt_sock_list l2cap_sk_list;
 int l2cap_init_sockets(void);
 void l2cap_cleanup_sockets(void);
 
+u8 l2cap_get_ident(struct l2cap_conn *conn);
+void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data);
+int l2cap_build_conf_req(struct sock *sk, void *data);
+
 void l2cap_sock_set_timer(struct sock *sk, long timeout);
 void __l2cap_sock_close(struct sock *sk, int reason);
 void l2cap_sock_kill(struct sock *sk);
@@ -440,7 +444,6 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
 int l2cap_do_connect(struct sock *sk);
 
 int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len);
-int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags);
 int l2cap_sock_shutdown(struct socket *sock, int how);
 
 
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 2d141fc..8184d54 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -72,7 +72,6 @@ static void l2cap_busy_work(struct work_struct *work);
 
 static void l2cap_sock_close(struct sock *sk);
 
-static int l2cap_build_conf_req(struct sock *sk, void *data);
 static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
 				u8 code, u8 ident, u16 dlen, void *data);
 
@@ -311,7 +310,7 @@ static inline int l2cap_check_security(struct sock *sk)
 								auth_type);
 }
 
-static inline u8 l2cap_get_ident(struct l2cap_conn *conn)
+u8 l2cap_get_ident(struct l2cap_conn *conn)
 {
 	u8 id;
 
@@ -333,7 +332,7 @@ static inline u8 l2cap_get_ident(struct l2cap_conn *conn)
 	return id;
 }
 
-static inline void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
+void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
 {
 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
 	u8 flags;
@@ -1468,48 +1467,6 @@ done:
 	return err;
 }
 
-int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags)
-{
-	struct sock *sk = sock->sk;
-
-	lock_sock(sk);
-
-	if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
-		struct l2cap_conn_rsp rsp;
-		struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-		u8 buf[128];
-
-		sk->sk_state = BT_CONFIG;
-
-		rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
-		rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
-		rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
-		rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
-		l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident,
-					L2CAP_CONN_RSP, sizeof(rsp), &rsp);
-
-		if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) {
-			release_sock(sk);
-			return 0;
-		}
-
-		l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
-		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-				l2cap_build_conf_req(sk, buf), buf);
-		l2cap_pi(sk)->num_conf_req++;
-
-		release_sock(sk);
-		return 0;
-	}
-
-	release_sock(sk);
-
-	if (sock->type == SOCK_STREAM)
-		return bt_sock_stream_recvmsg(iocb, sock, msg, len, flags);
-
-	return bt_sock_recvmsg(iocb, sock, msg, len, flags);
-}
-
 int l2cap_sock_shutdown(struct socket *sock, int how)
 {
 	struct sock *sk = sock->sk;
@@ -1759,7 +1716,7 @@ static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
 	}
 }
 
-static int l2cap_build_conf_req(struct sock *sk, void *data)
+int l2cap_build_conf_req(struct sock *sk, void *data)
 {
 	struct l2cap_pinfo *pi = l2cap_pi(sk);
 	struct l2cap_conf_req *req = data;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index e2f14f1..fa2bc5d 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -681,6 +681,48 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
 	return err;
 }
 
+static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags)
+{
+	struct sock *sk = sock->sk;
+
+	lock_sock(sk);
+
+	if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
+		struct l2cap_conn_rsp rsp;
+		struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+		u8 buf[128];
+
+		sk->sk_state = BT_CONFIG;
+
+		rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
+		rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
+		rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
+		rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
+		l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident,
+					L2CAP_CONN_RSP, sizeof(rsp), &rsp);
+
+		if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) {
+			release_sock(sk);
+			return 0;
+		}
+
+		l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
+		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
+				l2cap_build_conf_req(sk, buf), buf);
+		l2cap_pi(sk)->num_conf_req++;
+
+		release_sock(sk);
+		return 0;
+	}
+
+	release_sock(sk);
+
+	if (sock->type == SOCK_STREAM)
+		return bt_sock_stream_recvmsg(iocb, sock, msg, len, flags);
+
+	return bt_sock_recvmsg(iocb, sock, msg, len, flags);
+}
+
 static int l2cap_sock_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
-- 
1.7.4.rc3


^ permalink raw reply related

* [bluetooth-next 10/16] Bluetooth: move l2cap_sock_connect() to l2cap_sock.c
From: Gustavo F. Padovan @ 2011-02-04  6:01 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1296799318-5517-10-git-send-email-padovan@profusion.mobi>

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
 include/net/bluetooth/l2cap.h |    2 +-
 net/bluetooth/l2cap_core.c    |   87 +----------------------------------------
 net/bluetooth/l2cap_sock.c    |   85 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 87 insertions(+), 87 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 1905aad..b5ebf87 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -437,8 +437,8 @@ void l2cap_sock_kill(struct sock *sk);
 void l2cap_sock_init(struct sock *sk, struct sock *parent);
 struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
 							int proto, gfp_t prio);
+int l2cap_do_connect(struct sock *sk);
 
-int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags);
 int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len);
 int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags);
 int l2cap_sock_shutdown(struct socket *sock, int how);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 34fc6b4..2d141fc 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -847,7 +847,7 @@ static void l2cap_sock_close(struct sock *sk)
 	l2cap_sock_kill(sk);
 }
 
-static int l2cap_do_connect(struct sock *sk)
+int l2cap_do_connect(struct sock *sk)
 {
 	bdaddr_t *src = &bt_sk(sk)->src;
 	bdaddr_t *dst = &bt_sk(sk)->dst;
@@ -907,91 +907,6 @@ done:
 	return err;
 }
 
-int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
-{
-	struct sock *sk = sock->sk;
-	struct sockaddr_l2 la;
-	int len, err = 0;
-
-	BT_DBG("sk %p", sk);
-
-	if (!addr || alen < sizeof(addr->sa_family) ||
-	    addr->sa_family != AF_BLUETOOTH)
-		return -EINVAL;
-
-	memset(&la, 0, sizeof(la));
-	len = min_t(unsigned int, sizeof(la), alen);
-	memcpy(&la, addr, len);
-
-	if (la.l2_cid)
-		return -EINVAL;
-
-	lock_sock(sk);
-
-	if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM)
-			&& !la.l2_psm) {
-		err = -EINVAL;
-		goto done;
-	}
-
-	switch (l2cap_pi(sk)->mode) {
-	case L2CAP_MODE_BASIC:
-		break;
-	case L2CAP_MODE_ERTM:
-	case L2CAP_MODE_STREAMING:
-		if (!disable_ertm)
-			break;
-		/* fall through */
-	default:
-		err = -ENOTSUPP;
-		goto done;
-	}
-
-	switch (sk->sk_state) {
-	case BT_CONNECT:
-	case BT_CONNECT2:
-	case BT_CONFIG:
-		/* Already connecting */
-		goto wait;
-
-	case BT_CONNECTED:
-		/* Already connected */
-		err = -EISCONN;
-		goto done;
-
-	case BT_OPEN:
-	case BT_BOUND:
-		/* Can connect */
-		break;
-
-	default:
-		err = -EBADFD;
-		goto done;
-	}
-
-	/* PSM must be odd and lsb of upper byte must be 0 */
-	if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 &&
-		sk->sk_type != SOCK_RAW) {
-		err = -EINVAL;
-		goto done;
-	}
-
-	/* Set destination address and psm */
-	bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
-	l2cap_pi(sk)->psm = la.l2_psm;
-
-	err = l2cap_do_connect(sk);
-	if (err)
-		goto done;
-
-wait:
-	err = bt_sock_wait_state(sk, BT_CONNECTED,
-			sock_sndtimeo(sk, flags & O_NONBLOCK));
-done:
-	release_sock(sk);
-	return err;
-}
-
 static int __l2cap_wait_ack(struct sock *sk)
 {
 	DECLARE_WAITQUEUE(wait, current);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index b7d5ae9..e2f14f1 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -139,6 +139,91 @@ done:
 	return err;
 }
 
+static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
+{
+	struct sock *sk = sock->sk;
+	struct sockaddr_l2 la;
+	int len, err = 0;
+
+	BT_DBG("sk %p", sk);
+
+	if (!addr || alen < sizeof(addr->sa_family) ||
+	    addr->sa_family != AF_BLUETOOTH)
+		return -EINVAL;
+
+	memset(&la, 0, sizeof(la));
+	len = min_t(unsigned int, sizeof(la), alen);
+	memcpy(&la, addr, len);
+
+	if (la.l2_cid)
+		return -EINVAL;
+
+	lock_sock(sk);
+
+	if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM)
+			&& !la.l2_psm) {
+		err = -EINVAL;
+		goto done;
+	}
+
+	switch (l2cap_pi(sk)->mode) {
+	case L2CAP_MODE_BASIC:
+		break;
+	case L2CAP_MODE_ERTM:
+	case L2CAP_MODE_STREAMING:
+		if (!disable_ertm)
+			break;
+		/* fall through */
+	default:
+		err = -ENOTSUPP;
+		goto done;
+	}
+
+	switch (sk->sk_state) {
+	case BT_CONNECT:
+	case BT_CONNECT2:
+	case BT_CONFIG:
+		/* Already connecting */
+		goto wait;
+
+	case BT_CONNECTED:
+		/* Already connected */
+		err = -EISCONN;
+		goto done;
+
+	case BT_OPEN:
+	case BT_BOUND:
+		/* Can connect */
+		break;
+
+	default:
+		err = -EBADFD;
+		goto done;
+	}
+
+	/* PSM must be odd and lsb of upper byte must be 0 */
+	if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 &&
+		sk->sk_type != SOCK_RAW) {
+		err = -EINVAL;
+		goto done;
+	}
+
+	/* Set destination address and psm */
+	bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
+	l2cap_pi(sk)->psm = la.l2_psm;
+
+	err = l2cap_do_connect(sk);
+	if (err)
+		goto done;
+
+wait:
+	err = bt_sock_wait_state(sk, BT_CONNECTED,
+			sock_sndtimeo(sk, flags & O_NONBLOCK));
+done:
+	release_sock(sk);
+	return err;
+}
+
 static int l2cap_sock_listen(struct socket *sock, int backlog)
 {
 	struct sock *sk = sock->sk;
-- 
1.7.4.rc3


^ permalink raw reply related

* [bluetooth-next 09/16] Bluetooth: move l2cap_sock_getsockopt() to l2cap_sock.c
From: Gustavo F. Padovan @ 2011-02-04  6:01 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1296799318-5517-9-git-send-email-padovan@profusion.mobi>

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
 include/net/bluetooth/l2cap.h |    1 -
 net/bluetooth/l2cap_core.c    |  145 -----------------------------------------
 net/bluetooth/l2cap_sock.c    |  145 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 145 insertions(+), 146 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 901ecbe..1905aad 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -442,7 +442,6 @@ int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int
 int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len);
 int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags);
 int l2cap_sock_shutdown(struct socket *sock, int how);
-int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen);
 
 
 void l2cap_load(void);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 26ec2b8..34fc6b4 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1595,151 +1595,6 @@ int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m
 	return bt_sock_recvmsg(iocb, sock, msg, len, flags);
 }
 
-static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
-{
-	struct sock *sk = sock->sk;
-	struct l2cap_options opts;
-	struct l2cap_conninfo cinfo;
-	int len, err = 0;
-	u32 opt;
-
-	BT_DBG("sk %p", sk);
-
-	if (get_user(len, optlen))
-		return -EFAULT;
-
-	lock_sock(sk);
-
-	switch (optname) {
-	case L2CAP_OPTIONS:
-		opts.imtu     = l2cap_pi(sk)->imtu;
-		opts.omtu     = l2cap_pi(sk)->omtu;
-		opts.flush_to = l2cap_pi(sk)->flush_to;
-		opts.mode     = l2cap_pi(sk)->mode;
-		opts.fcs      = l2cap_pi(sk)->fcs;
-		opts.max_tx   = l2cap_pi(sk)->max_tx;
-		opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
-
-		len = min_t(unsigned int, len, sizeof(opts));
-		if (copy_to_user(optval, (char *) &opts, len))
-			err = -EFAULT;
-
-		break;
-
-	case L2CAP_LM:
-		switch (l2cap_pi(sk)->sec_level) {
-		case BT_SECURITY_LOW:
-			opt = L2CAP_LM_AUTH;
-			break;
-		case BT_SECURITY_MEDIUM:
-			opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT;
-			break;
-		case BT_SECURITY_HIGH:
-			opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
-							L2CAP_LM_SECURE;
-			break;
-		default:
-			opt = 0;
-			break;
-		}
-
-		if (l2cap_pi(sk)->role_switch)
-			opt |= L2CAP_LM_MASTER;
-
-		if (l2cap_pi(sk)->force_reliable)
-			opt |= L2CAP_LM_RELIABLE;
-
-		if (put_user(opt, (u32 __user *) optval))
-			err = -EFAULT;
-		break;
-
-	case L2CAP_CONNINFO:
-		if (sk->sk_state != BT_CONNECTED &&
-					!(sk->sk_state == BT_CONNECT2 &&
-						bt_sk(sk)->defer_setup)) {
-			err = -ENOTCONN;
-			break;
-		}
-
-		cinfo.hci_handle = l2cap_pi(sk)->conn->hcon->handle;
-		memcpy(cinfo.dev_class, l2cap_pi(sk)->conn->hcon->dev_class, 3);
-
-		len = min_t(unsigned int, len, sizeof(cinfo));
-		if (copy_to_user(optval, (char *) &cinfo, len))
-			err = -EFAULT;
-
-		break;
-
-	default:
-		err = -ENOPROTOOPT;
-		break;
-	}
-
-	release_sock(sk);
-	return err;
-}
-
-int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
-{
-	struct sock *sk = sock->sk;
-	struct bt_security sec;
-	int len, err = 0;
-
-	BT_DBG("sk %p", sk);
-
-	if (level == SOL_L2CAP)
-		return l2cap_sock_getsockopt_old(sock, optname, optval, optlen);
-
-	if (level != SOL_BLUETOOTH)
-		return -ENOPROTOOPT;
-
-	if (get_user(len, optlen))
-		return -EFAULT;
-
-	lock_sock(sk);
-
-	switch (optname) {
-	case BT_SECURITY:
-		if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
-				&& sk->sk_type != SOCK_RAW) {
-			err = -EINVAL;
-			break;
-		}
-
-		sec.level = l2cap_pi(sk)->sec_level;
-
-		len = min_t(unsigned int, len, sizeof(sec));
-		if (copy_to_user(optval, (char *) &sec, len))
-			err = -EFAULT;
-
-		break;
-
-	case BT_DEFER_SETUP:
-		if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
-			err = -EINVAL;
-			break;
-		}
-
-		if (put_user(bt_sk(sk)->defer_setup, (u32 __user *) optval))
-			err = -EFAULT;
-
-		break;
-
-	case BT_FLUSHABLE:
-		if (put_user(l2cap_pi(sk)->flushable, (u32 __user *) optval))
-			err = -EFAULT;
-
-		break;
-
-	default:
-		err = -ENOPROTOOPT;
-		break;
-	}
-
-	release_sock(sk);
-	return err;
-}
-
 int l2cap_sock_shutdown(struct socket *sock, int how)
 {
 	struct sock *sk = sock->sk;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 1bbe8a0..b7d5ae9 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -277,6 +277,151 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
 	return 0;
 }
 
+static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
+{
+	struct sock *sk = sock->sk;
+	struct l2cap_options opts;
+	struct l2cap_conninfo cinfo;
+	int len, err = 0;
+	u32 opt;
+
+	BT_DBG("sk %p", sk);
+
+	if (get_user(len, optlen))
+		return -EFAULT;
+
+	lock_sock(sk);
+
+	switch (optname) {
+	case L2CAP_OPTIONS:
+		opts.imtu     = l2cap_pi(sk)->imtu;
+		opts.omtu     = l2cap_pi(sk)->omtu;
+		opts.flush_to = l2cap_pi(sk)->flush_to;
+		opts.mode     = l2cap_pi(sk)->mode;
+		opts.fcs      = l2cap_pi(sk)->fcs;
+		opts.max_tx   = l2cap_pi(sk)->max_tx;
+		opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
+
+		len = min_t(unsigned int, len, sizeof(opts));
+		if (copy_to_user(optval, (char *) &opts, len))
+			err = -EFAULT;
+
+		break;
+
+	case L2CAP_LM:
+		switch (l2cap_pi(sk)->sec_level) {
+		case BT_SECURITY_LOW:
+			opt = L2CAP_LM_AUTH;
+			break;
+		case BT_SECURITY_MEDIUM:
+			opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT;
+			break;
+		case BT_SECURITY_HIGH:
+			opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
+							L2CAP_LM_SECURE;
+			break;
+		default:
+			opt = 0;
+			break;
+		}
+
+		if (l2cap_pi(sk)->role_switch)
+			opt |= L2CAP_LM_MASTER;
+
+		if (l2cap_pi(sk)->force_reliable)
+			opt |= L2CAP_LM_RELIABLE;
+
+		if (put_user(opt, (u32 __user *) optval))
+			err = -EFAULT;
+		break;
+
+	case L2CAP_CONNINFO:
+		if (sk->sk_state != BT_CONNECTED &&
+					!(sk->sk_state == BT_CONNECT2 &&
+						bt_sk(sk)->defer_setup)) {
+			err = -ENOTCONN;
+			break;
+		}
+
+		cinfo.hci_handle = l2cap_pi(sk)->conn->hcon->handle;
+		memcpy(cinfo.dev_class, l2cap_pi(sk)->conn->hcon->dev_class, 3);
+
+		len = min_t(unsigned int, len, sizeof(cinfo));
+		if (copy_to_user(optval, (char *) &cinfo, len))
+			err = -EFAULT;
+
+		break;
+
+	default:
+		err = -ENOPROTOOPT;
+		break;
+	}
+
+	release_sock(sk);
+	return err;
+}
+
+static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
+{
+	struct sock *sk = sock->sk;
+	struct bt_security sec;
+	int len, err = 0;
+
+	BT_DBG("sk %p", sk);
+
+	if (level == SOL_L2CAP)
+		return l2cap_sock_getsockopt_old(sock, optname, optval, optlen);
+
+	if (level != SOL_BLUETOOTH)
+		return -ENOPROTOOPT;
+
+	if (get_user(len, optlen))
+		return -EFAULT;
+
+	lock_sock(sk);
+
+	switch (optname) {
+	case BT_SECURITY:
+		if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
+				&& sk->sk_type != SOCK_RAW) {
+			err = -EINVAL;
+			break;
+		}
+
+		sec.level = l2cap_pi(sk)->sec_level;
+
+		len = min_t(unsigned int, len, sizeof(sec));
+		if (copy_to_user(optval, (char *) &sec, len))
+			err = -EFAULT;
+
+		break;
+
+	case BT_DEFER_SETUP:
+		if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
+			err = -EINVAL;
+			break;
+		}
+
+		if (put_user(bt_sk(sk)->defer_setup, (u32 __user *) optval))
+			err = -EFAULT;
+
+		break;
+
+	case BT_FLUSHABLE:
+		if (put_user(l2cap_pi(sk)->flushable, (u32 __user *) optval))
+			err = -EFAULT;
+
+		break;
+
+	default:
+		err = -ENOPROTOOPT;
+		break;
+	}
+
+	release_sock(sk);
+	return err;
+}
+
 static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
 {
 	struct sock *sk = sock->sk;
-- 
1.7.4.rc3


^ permalink raw reply related

* [bluetooth-next 08/16] Bluetooth: move l2cap_sock_setsockopt() to l2cap_sock.c
From: Gustavo F. Padovan @ 2011-02-04  6:01 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1296799318-5517-8-git-send-email-padovan@profusion.mobi>

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
 include/net/bluetooth/l2cap.h |    1 -
 net/bluetooth/l2cap_core.c    |  174 ----------------------------------------
 net/bluetooth/l2cap_sock.c    |  175 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 175 insertions(+), 175 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 0d0c180..901ecbe 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -442,7 +442,6 @@ int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int
 int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len);
 int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags);
 int l2cap_sock_shutdown(struct socket *sock, int how);
-int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen);
 int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen);
 
 
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 6d0d81d..26ec2b8 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1595,180 +1595,6 @@ int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m
 	return bt_sock_recvmsg(iocb, sock, msg, len, flags);
 }
 
-static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
-{
-	struct sock *sk = sock->sk;
-	struct l2cap_options opts;
-	int len, err = 0;
-	u32 opt;
-
-	BT_DBG("sk %p", sk);
-
-	lock_sock(sk);
-
-	switch (optname) {
-	case L2CAP_OPTIONS:
-		if (sk->sk_state == BT_CONNECTED) {
-			err = -EINVAL;
-			break;
-		}
-
-		opts.imtu     = l2cap_pi(sk)->imtu;
-		opts.omtu     = l2cap_pi(sk)->omtu;
-		opts.flush_to = l2cap_pi(sk)->flush_to;
-		opts.mode     = l2cap_pi(sk)->mode;
-		opts.fcs      = l2cap_pi(sk)->fcs;
-		opts.max_tx   = l2cap_pi(sk)->max_tx;
-		opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
-
-		len = min_t(unsigned int, sizeof(opts), optlen);
-		if (copy_from_user((char *) &opts, optval, len)) {
-			err = -EFAULT;
-			break;
-		}
-
-		if (opts.txwin_size > L2CAP_DEFAULT_TX_WINDOW) {
-			err = -EINVAL;
-			break;
-		}
-
-		l2cap_pi(sk)->mode = opts.mode;
-		switch (l2cap_pi(sk)->mode) {
-		case L2CAP_MODE_BASIC:
-			l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
-			break;
-		case L2CAP_MODE_ERTM:
-		case L2CAP_MODE_STREAMING:
-			if (!disable_ertm)
-				break;
-			/* fall through */
-		default:
-			err = -EINVAL;
-			break;
-		}
-
-		l2cap_pi(sk)->imtu = opts.imtu;
-		l2cap_pi(sk)->omtu = opts.omtu;
-		l2cap_pi(sk)->fcs  = opts.fcs;
-		l2cap_pi(sk)->max_tx = opts.max_tx;
-		l2cap_pi(sk)->tx_win = (__u8)opts.txwin_size;
-		break;
-
-	case L2CAP_LM:
-		if (get_user(opt, (u32 __user *) optval)) {
-			err = -EFAULT;
-			break;
-		}
-
-		if (opt & L2CAP_LM_AUTH)
-			l2cap_pi(sk)->sec_level = BT_SECURITY_LOW;
-		if (opt & L2CAP_LM_ENCRYPT)
-			l2cap_pi(sk)->sec_level = BT_SECURITY_MEDIUM;
-		if (opt & L2CAP_LM_SECURE)
-			l2cap_pi(sk)->sec_level = BT_SECURITY_HIGH;
-
-		l2cap_pi(sk)->role_switch    = (opt & L2CAP_LM_MASTER);
-		l2cap_pi(sk)->force_reliable = (opt & L2CAP_LM_RELIABLE);
-		break;
-
-	default:
-		err = -ENOPROTOOPT;
-		break;
-	}
-
-	release_sock(sk);
-	return err;
-}
-
-int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
-{
-	struct sock *sk = sock->sk;
-	struct bt_security sec;
-	int len, err = 0;
-	u32 opt;
-
-	BT_DBG("sk %p", sk);
-
-	if (level == SOL_L2CAP)
-		return l2cap_sock_setsockopt_old(sock, optname, optval, optlen);
-
-	if (level != SOL_BLUETOOTH)
-		return -ENOPROTOOPT;
-
-	lock_sock(sk);
-
-	switch (optname) {
-	case BT_SECURITY:
-		if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
-				&& sk->sk_type != SOCK_RAW) {
-			err = -EINVAL;
-			break;
-		}
-
-		sec.level = BT_SECURITY_LOW;
-
-		len = min_t(unsigned int, sizeof(sec), optlen);
-		if (copy_from_user((char *) &sec, optval, len)) {
-			err = -EFAULT;
-			break;
-		}
-
-		if (sec.level < BT_SECURITY_LOW ||
-					sec.level > BT_SECURITY_HIGH) {
-			err = -EINVAL;
-			break;
-		}
-
-		l2cap_pi(sk)->sec_level = sec.level;
-		break;
-
-	case BT_DEFER_SETUP:
-		if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
-			err = -EINVAL;
-			break;
-		}
-
-		if (get_user(opt, (u32 __user *) optval)) {
-			err = -EFAULT;
-			break;
-		}
-
-		bt_sk(sk)->defer_setup = opt;
-		break;
-
-	case BT_FLUSHABLE:
-		if (get_user(opt, (u32 __user *) optval)) {
-			err = -EFAULT;
-			break;
-		}
-
-		if (opt > BT_FLUSHABLE_ON) {
-			err = -EINVAL;
-			break;
-		}
-
-		if (opt == BT_FLUSHABLE_OFF) {
-			struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-			/* proceed futher only when we have l2cap_conn and
-			   No Flush support in the LM */
-			if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) {
-				err = -EINVAL;
-				break;
-			}
-		}
-
-		l2cap_pi(sk)->flushable = opt;
-		break;
-
-	default:
-		err = -ENOPROTOOPT;
-		break;
-	}
-
-	release_sock(sk);
-	return err;
-}
-
 static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
 {
 	struct sock *sk = sock->sk;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 4c13f8b..1bbe8a0 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -27,6 +27,7 @@
 /* Bluetooth L2CAP sockets. */
 
 #include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
 
 static void l2cap_sock_timeout(unsigned long arg)
@@ -276,6 +277,180 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
 	return 0;
 }
 
+static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
+{
+	struct sock *sk = sock->sk;
+	struct l2cap_options opts;
+	int len, err = 0;
+	u32 opt;
+
+	BT_DBG("sk %p", sk);
+
+	lock_sock(sk);
+
+	switch (optname) {
+	case L2CAP_OPTIONS:
+		if (sk->sk_state == BT_CONNECTED) {
+			err = -EINVAL;
+			break;
+		}
+
+		opts.imtu     = l2cap_pi(sk)->imtu;
+		opts.omtu     = l2cap_pi(sk)->omtu;
+		opts.flush_to = l2cap_pi(sk)->flush_to;
+		opts.mode     = l2cap_pi(sk)->mode;
+		opts.fcs      = l2cap_pi(sk)->fcs;
+		opts.max_tx   = l2cap_pi(sk)->max_tx;
+		opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
+
+		len = min_t(unsigned int, sizeof(opts), optlen);
+		if (copy_from_user((char *) &opts, optval, len)) {
+			err = -EFAULT;
+			break;
+		}
+
+		if (opts.txwin_size > L2CAP_DEFAULT_TX_WINDOW) {
+			err = -EINVAL;
+			break;
+		}
+
+		l2cap_pi(sk)->mode = opts.mode;
+		switch (l2cap_pi(sk)->mode) {
+		case L2CAP_MODE_BASIC:
+			l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
+			break;
+		case L2CAP_MODE_ERTM:
+		case L2CAP_MODE_STREAMING:
+			if (!disable_ertm)
+				break;
+			/* fall through */
+		default:
+			err = -EINVAL;
+			break;
+		}
+
+		l2cap_pi(sk)->imtu = opts.imtu;
+		l2cap_pi(sk)->omtu = opts.omtu;
+		l2cap_pi(sk)->fcs  = opts.fcs;
+		l2cap_pi(sk)->max_tx = opts.max_tx;
+		l2cap_pi(sk)->tx_win = (__u8)opts.txwin_size;
+		break;
+
+	case L2CAP_LM:
+		if (get_user(opt, (u32 __user *) optval)) {
+			err = -EFAULT;
+			break;
+		}
+
+		if (opt & L2CAP_LM_AUTH)
+			l2cap_pi(sk)->sec_level = BT_SECURITY_LOW;
+		if (opt & L2CAP_LM_ENCRYPT)
+			l2cap_pi(sk)->sec_level = BT_SECURITY_MEDIUM;
+		if (opt & L2CAP_LM_SECURE)
+			l2cap_pi(sk)->sec_level = BT_SECURITY_HIGH;
+
+		l2cap_pi(sk)->role_switch    = (opt & L2CAP_LM_MASTER);
+		l2cap_pi(sk)->force_reliable = (opt & L2CAP_LM_RELIABLE);
+		break;
+
+	default:
+		err = -ENOPROTOOPT;
+		break;
+	}
+
+	release_sock(sk);
+	return err;
+}
+
+static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
+{
+	struct sock *sk = sock->sk;
+	struct bt_security sec;
+	int len, err = 0;
+	u32 opt;
+
+	BT_DBG("sk %p", sk);
+
+	if (level == SOL_L2CAP)
+		return l2cap_sock_setsockopt_old(sock, optname, optval, optlen);
+
+	if (level != SOL_BLUETOOTH)
+		return -ENOPROTOOPT;
+
+	lock_sock(sk);
+
+	switch (optname) {
+	case BT_SECURITY:
+		if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
+				&& sk->sk_type != SOCK_RAW) {
+			err = -EINVAL;
+			break;
+		}
+
+		sec.level = BT_SECURITY_LOW;
+
+		len = min_t(unsigned int, sizeof(sec), optlen);
+		if (copy_from_user((char *) &sec, optval, len)) {
+			err = -EFAULT;
+			break;
+		}
+
+		if (sec.level < BT_SECURITY_LOW ||
+					sec.level > BT_SECURITY_HIGH) {
+			err = -EINVAL;
+			break;
+		}
+
+		l2cap_pi(sk)->sec_level = sec.level;
+		break;
+
+	case BT_DEFER_SETUP:
+		if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
+			err = -EINVAL;
+			break;
+		}
+
+		if (get_user(opt, (u32 __user *) optval)) {
+			err = -EFAULT;
+			break;
+		}
+
+		bt_sk(sk)->defer_setup = opt;
+		break;
+
+	case BT_FLUSHABLE:
+		if (get_user(opt, (u32 __user *) optval)) {
+			err = -EFAULT;
+			break;
+		}
+
+		if (opt > BT_FLUSHABLE_ON) {
+			err = -EINVAL;
+			break;
+		}
+
+		if (opt == BT_FLUSHABLE_OFF) {
+			struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+			/* proceed futher only when we have l2cap_conn and
+			   No Flush support in the LM */
+			if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) {
+				err = -EINVAL;
+				break;
+			}
+		}
+
+		l2cap_pi(sk)->flushable = opt;
+		break;
+
+	default:
+		err = -ENOPROTOOPT;
+		break;
+	}
+
+	release_sock(sk);
+	return err;
+}
+
 static int l2cap_sock_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
-- 
1.7.4.rc3


^ permalink raw reply related

* [bluetooth-next 07/16] Bluetooth: move l2cap_sock_getname() to l2cap_sock.c
From: Gustavo F. Padovan @ 2011-02-04  6:01 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1296799318-5517-7-git-send-email-padovan@profusion.mobi>

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
 include/net/bluetooth/l2cap.h |    1 -
 net/bluetooth/l2cap_core.c    |   23 -----------------------
 net/bluetooth/l2cap_sock.c    |   23 +++++++++++++++++++++++
 3 files changed, 23 insertions(+), 24 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 7921b6b..0d0c180 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -439,7 +439,6 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
 							int proto, gfp_t prio);
 
 int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags);
-int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer);
 int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len);
 int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags);
 int l2cap_sock_shutdown(struct socket *sock, int how);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 32a615a..6d0d81d 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -992,29 +992,6 @@ done:
 	return err;
 }
 
-int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
-{
-	struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
-	struct sock *sk = sock->sk;
-
-	BT_DBG("sock %p, sk %p", sock, sk);
-
-	addr->sa_family = AF_BLUETOOTH;
-	*len = sizeof(struct sockaddr_l2);
-
-	if (peer) {
-		la->l2_psm = l2cap_pi(sk)->psm;
-		bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst);
-		la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid);
-	} else {
-		la->l2_psm = l2cap_pi(sk)->sport;
-		bacpy(&la->l2_bdaddr, &bt_sk(sk)->src);
-		la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid);
-	}
-
-	return 0;
-}
-
 static int __l2cap_wait_ack(struct sock *sk)
 {
 	DECLARE_WAITQUEUE(wait, current);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index b19a386..4c13f8b 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -253,6 +253,29 @@ done:
 	return err;
 }
 
+static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
+{
+	struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
+	struct sock *sk = sock->sk;
+
+	BT_DBG("sock %p, sk %p", sock, sk);
+
+	addr->sa_family = AF_BLUETOOTH;
+	*len = sizeof(struct sockaddr_l2);
+
+	if (peer) {
+		la->l2_psm = l2cap_pi(sk)->psm;
+		bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst);
+		la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid);
+	} else {
+		la->l2_psm = l2cap_pi(sk)->sport;
+		bacpy(&la->l2_bdaddr, &bt_sk(sk)->src);
+		la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid);
+	}
+
+	return 0;
+}
+
 static int l2cap_sock_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
-- 
1.7.4.rc3


^ permalink raw reply related

* [bluetooth-next 06/16] Bluetooth: move l2cap_sock_accept() to l2cap_sock.c
From: Gustavo F. Padovan @ 2011-02-04  6:01 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1296799318-5517-6-git-send-email-padovan@profusion.mobi>

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
 include/net/bluetooth/l2cap.h |    1 -
 net/bluetooth/l2cap_core.c    |   56 -----------------------------------------
 net/bluetooth/l2cap_sock.c    |   56 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 56 insertions(+), 57 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 3ca4fe3..7921b6b 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -439,7 +439,6 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
 							int proto, gfp_t prio);
 
 int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags);
-int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags);
 int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer);
 int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len);
 int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index c4a90c5..32a615a 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -992,62 +992,6 @@ done:
 	return err;
 }
 
-int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	struct sock *sk = sock->sk, *nsk;
-	long timeo;
-	int err = 0;
-
-	lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
-
-	if (sk->sk_state != BT_LISTEN) {
-		err = -EBADFD;
-		goto done;
-	}
-
-	timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
-
-	BT_DBG("sk %p timeo %ld", sk, timeo);
-
-	/* Wait for an incoming connection. (wake-one). */
-	add_wait_queue_exclusive(sk_sleep(sk), &wait);
-	while (!(nsk = bt_accept_dequeue(sk, newsock))) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (!timeo) {
-			err = -EAGAIN;
-			break;
-		}
-
-		release_sock(sk);
-		timeo = schedule_timeout(timeo);
-		lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
-
-		if (sk->sk_state != BT_LISTEN) {
-			err = -EBADFD;
-			break;
-		}
-
-		if (signal_pending(current)) {
-			err = sock_intr_errno(timeo);
-			break;
-		}
-	}
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(sk_sleep(sk), &wait);
-
-	if (err)
-		goto done;
-
-	newsock->state = SS_CONNECTED;
-
-	BT_DBG("new socket %p", nsk);
-
-done:
-	release_sock(sk);
-	return err;
-}
-
 int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
 {
 	struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index ef9a60f..b19a386 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -197,6 +197,62 @@ done:
 	return err;
 }
 
+static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	struct sock *sk = sock->sk, *nsk;
+	long timeo;
+	int err = 0;
+
+	lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
+
+	if (sk->sk_state != BT_LISTEN) {
+		err = -EBADFD;
+		goto done;
+	}
+
+	timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
+
+	BT_DBG("sk %p timeo %ld", sk, timeo);
+
+	/* Wait for an incoming connection. (wake-one). */
+	add_wait_queue_exclusive(sk_sleep(sk), &wait);
+	while (!(nsk = bt_accept_dequeue(sk, newsock))) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (!timeo) {
+			err = -EAGAIN;
+			break;
+		}
+
+		release_sock(sk);
+		timeo = schedule_timeout(timeo);
+		lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
+
+		if (sk->sk_state != BT_LISTEN) {
+			err = -EBADFD;
+			break;
+		}
+
+		if (signal_pending(current)) {
+			err = sock_intr_errno(timeo);
+			break;
+		}
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(sk_sleep(sk), &wait);
+
+	if (err)
+		goto done;
+
+	newsock->state = SS_CONNECTED;
+
+	BT_DBG("new socket %p", nsk);
+
+done:
+	release_sock(sk);
+	return err;
+}
+
 static int l2cap_sock_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
-- 
1.7.4.rc3


^ permalink raw reply related

* [bluetooth-next 05/16] Bluetooth: move l2cap_sock_bind()/listen() to l2cap_sock.c
From: Gustavo F. Padovan @ 2011-02-04  6:01 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1296799318-5517-5-git-send-email-padovan@profusion.mobi>

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
 include/net/bluetooth/l2cap.h |    2 -
 net/bluetooth/l2cap_core.c    |  134 ----------------------------------------
 net/bluetooth/l2cap_sock.c    |  135 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 135 insertions(+), 136 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index d0baf41..3ca4fe3 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -438,9 +438,7 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent);
 struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
 							int proto, gfp_t prio);
 
-int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen);
 int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags);
-int l2cap_sock_listen(struct socket *sock, int backlog);
 int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags);
 int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer);
 int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index fd2b940..c4a90c5 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -722,17 +722,6 @@ static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, stru
 }
 
 /* ---- Socket interface ---- */
-static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
-{
-	struct sock *sk;
-	struct hlist_node *node;
-	sk_for_each(sk, node, &l2cap_sk_list.head)
-		if (l2cap_pi(sk)->sport == psm && !bacmp(&bt_sk(sk)->src, src))
-			goto found;
-	sk = NULL;
-found:
-	return sk;
-}
 
 /* Find socket with psm and source bdaddr.
  * Returns closest match.
@@ -858,70 +847,6 @@ static void l2cap_sock_close(struct sock *sk)
 	l2cap_sock_kill(sk);
 }
 
-int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
-{
-	struct sock *sk = sock->sk;
-	struct sockaddr_l2 la;
-	int len, err = 0;
-
-	BT_DBG("sk %p", sk);
-
-	if (!addr || addr->sa_family != AF_BLUETOOTH)
-		return -EINVAL;
-
-	memset(&la, 0, sizeof(la));
-	len = min_t(unsigned int, sizeof(la), alen);
-	memcpy(&la, addr, len);
-
-	if (la.l2_cid)
-		return -EINVAL;
-
-	lock_sock(sk);
-
-	if (sk->sk_state != BT_OPEN) {
-		err = -EBADFD;
-		goto done;
-	}
-
-	if (la.l2_psm) {
-		__u16 psm = __le16_to_cpu(la.l2_psm);
-
-		/* PSM must be odd and lsb of upper byte must be 0 */
-		if ((psm & 0x0101) != 0x0001) {
-			err = -EINVAL;
-			goto done;
-		}
-
-		/* Restrict usage of well-known PSMs */
-		if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) {
-			err = -EACCES;
-			goto done;
-		}
-	}
-
-	write_lock_bh(&l2cap_sk_list.lock);
-
-	if (la.l2_psm && __l2cap_get_sock_by_addr(la.l2_psm, &la.l2_bdaddr)) {
-		err = -EADDRINUSE;
-	} else {
-		/* Save source address */
-		bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
-		l2cap_pi(sk)->psm   = la.l2_psm;
-		l2cap_pi(sk)->sport = la.l2_psm;
-		sk->sk_state = BT_BOUND;
-
-		if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
-					__le16_to_cpu(la.l2_psm) == 0x0003)
-			l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
-	}
-
-	write_unlock_bh(&l2cap_sk_list.lock);
-
-done:
-	release_sock(sk);
-	return err;
-}
-
 static int l2cap_do_connect(struct sock *sk)
 {
 	bdaddr_t *src = &bt_sk(sk)->src;
@@ -1067,65 +992,6 @@ done:
 	return err;
 }
 
-int l2cap_sock_listen(struct socket *sock, int backlog)
-{
-	struct sock *sk = sock->sk;
-	int err = 0;
-
-	BT_DBG("sk %p backlog %d", sk, backlog);
-
-	lock_sock(sk);
-
-	if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM)
-			|| sk->sk_state != BT_BOUND) {
-		err = -EBADFD;
-		goto done;
-	}
-
-	switch (l2cap_pi(sk)->mode) {
-	case L2CAP_MODE_BASIC:
-		break;
-	case L2CAP_MODE_ERTM:
-	case L2CAP_MODE_STREAMING:
-		if (!disable_ertm)
-			break;
-		/* fall through */
-	default:
-		err = -ENOTSUPP;
-		goto done;
-	}
-
-	if (!l2cap_pi(sk)->psm) {
-		bdaddr_t *src = &bt_sk(sk)->src;
-		u16 psm;
-
-		err = -EINVAL;
-
-		write_lock_bh(&l2cap_sk_list.lock);
-
-		for (psm = 0x1001; psm < 0x1100; psm += 2)
-			if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) {
-				l2cap_pi(sk)->psm   = cpu_to_le16(psm);
-				l2cap_pi(sk)->sport = cpu_to_le16(psm);
-				err = 0;
-				break;
-			}
-
-		write_unlock_bh(&l2cap_sk_list.lock);
-
-		if (err < 0)
-			goto done;
-	}
-
-	sk->sk_max_ack_backlog = backlog;
-	sk->sk_ack_backlog = 0;
-	sk->sk_state = BT_LISTEN;
-
-done:
-	release_sock(sk);
-	return err;
-}
-
 int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags)
 {
 	DECLARE_WAITQUEUE(wait, current);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 20efd24..ef9a60f 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -62,6 +62,141 @@ static void l2cap_sock_timeout(unsigned long arg)
 	sock_put(sk);
 }
 
+static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
+{
+	struct sock *sk;
+	struct hlist_node *node;
+	sk_for_each(sk, node, &l2cap_sk_list.head)
+		if (l2cap_pi(sk)->sport == psm && !bacmp(&bt_sk(sk)->src, src))
+			goto found;
+	sk = NULL;
+found:
+	return sk;
+}
+
+static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
+{
+	struct sock *sk = sock->sk;
+	struct sockaddr_l2 la;
+	int len, err = 0;
+
+	BT_DBG("sk %p", sk);
+
+	if (!addr || addr->sa_family != AF_BLUETOOTH)
+		return -EINVAL;
+
+	memset(&la, 0, sizeof(la));
+	len = min_t(unsigned int, sizeof(la), alen);
+	memcpy(&la, addr, len);
+
+	if (la.l2_cid)
+		return -EINVAL;
+
+	lock_sock(sk);
+
+	if (sk->sk_state != BT_OPEN) {
+		err = -EBADFD;
+		goto done;
+	}
+
+	if (la.l2_psm) {
+		__u16 psm = __le16_to_cpu(la.l2_psm);
+
+		/* PSM must be odd and lsb of upper byte must be 0 */
+		if ((psm & 0x0101) != 0x0001) {
+			err = -EINVAL;
+			goto done;
+		}
+
+		/* Restrict usage of well-known PSMs */
+		if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) {
+			err = -EACCES;
+			goto done;
+		}
+	}
+
+	write_lock_bh(&l2cap_sk_list.lock);
+
+	if (la.l2_psm && __l2cap_get_sock_by_addr(la.l2_psm, &la.l2_bdaddr)) {
+		err = -EADDRINUSE;
+	} else {
+		/* Save source address */
+		bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
+		l2cap_pi(sk)->psm   = la.l2_psm;
+		l2cap_pi(sk)->sport = la.l2_psm;
+		sk->sk_state = BT_BOUND;
+
+		if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
+					__le16_to_cpu(la.l2_psm) == 0x0003)
+			l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
+	}
+
+	write_unlock_bh(&l2cap_sk_list.lock);
+
+done:
+	release_sock(sk);
+	return err;
+}
+
+static int l2cap_sock_listen(struct socket *sock, int backlog)
+{
+	struct sock *sk = sock->sk;
+	int err = 0;
+
+	BT_DBG("sk %p backlog %d", sk, backlog);
+
+	lock_sock(sk);
+
+	if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM)
+			|| sk->sk_state != BT_BOUND) {
+		err = -EBADFD;
+		goto done;
+	}
+
+	switch (l2cap_pi(sk)->mode) {
+	case L2CAP_MODE_BASIC:
+		break;
+	case L2CAP_MODE_ERTM:
+	case L2CAP_MODE_STREAMING:
+		if (!disable_ertm)
+			break;
+		/* fall through */
+	default:
+		err = -ENOTSUPP;
+		goto done;
+	}
+
+	if (!l2cap_pi(sk)->psm) {
+		bdaddr_t *src = &bt_sk(sk)->src;
+		u16 psm;
+
+		err = -EINVAL;
+
+		write_lock_bh(&l2cap_sk_list.lock);
+
+		for (psm = 0x1001; psm < 0x1100; psm += 2)
+			if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) {
+				l2cap_pi(sk)->psm   = cpu_to_le16(psm);
+				l2cap_pi(sk)->sport = cpu_to_le16(psm);
+				err = 0;
+				break;
+			}
+
+		write_unlock_bh(&l2cap_sk_list.lock);
+
+		if (err < 0)
+			goto done;
+	}
+
+	sk->sk_max_ack_backlog = backlog;
+	sk->sk_ack_backlog = 0;
+	sk->sk_state = BT_LISTEN;
+
+done:
+	release_sock(sk);
+	return err;
+}
+
 static int l2cap_sock_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
-- 
1.7.4.rc3


^ permalink raw reply related

* [bluetooth-next 04/16] Bluetooth: move l2cap_sock_release() to l2cap_sock.c
From: Gustavo F. Padovan @ 2011-02-04  6:01 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1296799318-5517-4-git-send-email-padovan@profusion.mobi>

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
 include/net/bluetooth/l2cap.h |    1 -
 net/bluetooth/l2cap_core.c    |   17 -----------------
 net/bluetooth/l2cap_sock.c    |   17 +++++++++++++++++
 3 files changed, 17 insertions(+), 18 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 533bef5..d0baf41 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -438,7 +438,6 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent);
 struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
 							int proto, gfp_t prio);
 
-int l2cap_sock_release(struct socket *sock);
 int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen);
 int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags);
 int l2cap_sock_listen(struct socket *sock, int backlog);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index d11bcf2..fd2b940 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -2158,23 +2158,6 @@ int l2cap_sock_shutdown(struct socket *sock, int how)
 	return err;
 }
 
-int l2cap_sock_release(struct socket *sock)
-{
-	struct sock *sk = sock->sk;
-	int err;
-
-	BT_DBG("sock %p, sk %p", sock, sk);
-
-	if (!sk)
-		return 0;
-
-	err = l2cap_sock_shutdown(sock, 2);
-
-	sock_orphan(sk);
-	l2cap_sock_kill(sk);
-	return err;
-}
-
 static void l2cap_chan_ready(struct sock *sk)
 {
 	struct sock *parent = bt_sk(sk)->parent;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index c1455f7..20efd24 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -62,6 +62,23 @@ static void l2cap_sock_timeout(unsigned long arg)
 	sock_put(sk);
 }
 
+static int l2cap_sock_release(struct socket *sock)
+{
+	struct sock *sk = sock->sk;
+	int err;
+
+	BT_DBG("sock %p, sk %p", sock, sk);
+
+	if (!sk)
+		return 0;
+
+	err = l2cap_sock_shutdown(sock, 2);
+
+	sock_orphan(sk);
+	l2cap_sock_kill(sk);
+	return err;
+}
+
 static void l2cap_sock_destruct(struct sock *sk)
 {
 	BT_DBG("sk %p", sk);
-- 
1.7.4.rc3


^ permalink raw reply related

* [bluetooth-next 03/16] Bluetooth: move l2cap_sock_ops to l2cap_sock.c
From: Gustavo F. Padovan @ 2011-02-04  6:01 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1296799318-5517-3-git-send-email-padovan@profusion.mobi>

First step to move all l2cap_sock_ops function to l2cap_sock.c

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
 include/net/bluetooth/l2cap.h |   12 +++++++++++
 net/bluetooth/l2cap_core.c    |   42 ++++++++++------------------------------
 net/bluetooth/l2cap_sock.c    |   21 +++++++++++++++++++-
 3 files changed, 43 insertions(+), 32 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index fce5274..533bef5 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -438,6 +438,18 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent);
 struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
 							int proto, gfp_t prio);
 
+int l2cap_sock_release(struct socket *sock);
+int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen);
+int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags);
+int l2cap_sock_listen(struct socket *sock, int backlog);
+int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags);
+int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer);
+int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len);
+int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags);
+int l2cap_sock_shutdown(struct socket *sock, int how);
+int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen);
+int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen);
+
 
 void l2cap_load(void);
 
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 53f9ebd..d11bcf2 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -858,7 +858,7 @@ static void l2cap_sock_close(struct sock *sk)
 	l2cap_sock_kill(sk);
 }
 
-static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
+int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_l2 la;
@@ -982,7 +982,7 @@ done:
 	return err;
 }
 
-static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
+int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_l2 la;
@@ -1067,7 +1067,7 @@ done:
 	return err;
 }
 
-static int l2cap_sock_listen(struct socket *sock, int backlog)
+int l2cap_sock_listen(struct socket *sock, int backlog)
 {
 	struct sock *sk = sock->sk;
 	int err = 0;
@@ -1126,7 +1126,7 @@ done:
 	return err;
 }
 
-static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags)
+int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags)
 {
 	DECLARE_WAITQUEUE(wait, current);
 	struct sock *sk = sock->sk, *nsk;
@@ -1182,7 +1182,7 @@ done:
 	return err;
 }
 
-static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
+int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
 {
 	struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
 	struct sock *sk = sock->sk;
@@ -1664,7 +1664,7 @@ static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, siz
 	return size;
 }
 
-static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
+int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
 {
 	struct sock *sk = sock->sk;
 	struct l2cap_pinfo *pi = l2cap_pi(sk);
@@ -1766,7 +1766,7 @@ done:
 	return err;
 }
 
-static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags)
+int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags)
 {
 	struct sock *sk = sock->sk;
 
@@ -1893,7 +1893,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
 	return err;
 }
 
-static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
+int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
 {
 	struct sock *sk = sock->sk;
 	struct bt_security sec;
@@ -2066,7 +2066,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
 	return err;
 }
 
-static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
+int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
 {
 	struct sock *sk = sock->sk;
 	struct bt_security sec;
@@ -2127,7 +2127,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
 	return err;
 }
 
-static int l2cap_sock_shutdown(struct socket *sock, int how)
+int l2cap_sock_shutdown(struct socket *sock, int how)
 {
 	struct sock *sk = sock->sk;
 	int err = 0;
@@ -2158,7 +2158,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
 	return err;
 }
 
-static int l2cap_sock_release(struct socket *sock)
+int l2cap_sock_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
 	int err;
@@ -4714,26 +4714,6 @@ static const struct file_operations l2cap_debugfs_fops = {
 
 static struct dentry *l2cap_debugfs;
 
-const struct proto_ops l2cap_sock_ops = {
-	.family		= PF_BLUETOOTH,
-	.owner		= THIS_MODULE,
-	.release	= l2cap_sock_release,
-	.bind		= l2cap_sock_bind,
-	.connect	= l2cap_sock_connect,
-	.listen		= l2cap_sock_listen,
-	.accept		= l2cap_sock_accept,
-	.getname	= l2cap_sock_getname,
-	.sendmsg	= l2cap_sock_sendmsg,
-	.recvmsg	= l2cap_sock_recvmsg,
-	.poll		= bt_sock_poll,
-	.ioctl		= bt_sock_ioctl,
-	.mmap		= sock_no_mmap,
-	.socketpair	= sock_no_socketpair,
-	.shutdown	= l2cap_sock_shutdown,
-	.setsockopt	= l2cap_sock_setsockopt,
-	.getsockopt	= l2cap_sock_getsockopt
-};
-
 static struct hci_proto l2cap_hci_proto = {
 	.name		= "L2CAP",
 	.id		= HCI_PROTO_L2CAP,
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 6ea1894..c1455f7 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -62,7 +62,6 @@ static void l2cap_sock_timeout(unsigned long arg)
 	sock_put(sk);
 }
 
-
 static void l2cap_sock_destruct(struct sock *sk)
 {
 	BT_DBG("sk %p", sk);
@@ -176,6 +175,26 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
 	return 0;
 }
 
+const struct proto_ops l2cap_sock_ops = {
+	.family		= PF_BLUETOOTH,
+	.owner		= THIS_MODULE,
+	.release	= l2cap_sock_release,
+	.bind		= l2cap_sock_bind,
+	.connect	= l2cap_sock_connect,
+	.listen		= l2cap_sock_listen,
+	.accept		= l2cap_sock_accept,
+	.getname	= l2cap_sock_getname,
+	.sendmsg	= l2cap_sock_sendmsg,
+	.recvmsg	= l2cap_sock_recvmsg,
+	.poll		= bt_sock_poll,
+	.ioctl		= bt_sock_ioctl,
+	.mmap		= sock_no_mmap,
+	.socketpair	= sock_no_socketpair,
+	.shutdown	= l2cap_sock_shutdown,
+	.setsockopt	= l2cap_sock_setsockopt,
+	.getsockopt	= l2cap_sock_getsockopt
+};
+
 static const struct net_proto_family l2cap_sock_family_ops = {
 	.family	= PF_BLUETOOTH,
 	.owner	= THIS_MODULE,
-- 
1.7.4.rc3


^ permalink raw reply related

* [bluetooth-next 02/16] Bluetooth: Initial work for L2CAP split.
From: Gustavo F. Padovan @ 2011-02-04  6:01 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1296799318-5517-2-git-send-email-padovan@profusion.mobi>

This patch tries to do the minimal to move l2cap_sock_create() and its
dependencies to l2cap_sock.c. It create a API to initialize and cleanup
the L2CAP sockets from l2cap_core.c through l2cap_init_sockets() and
l2cap_cleanup_sockets().

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
 include/net/bluetooth/l2cap.h |   15 +++
 net/bluetooth/Makefile        |    2 +-
 net/bluetooth/l2cap_core.c    |  187 ++----------------------------------
 net/bluetooth/l2cap_sock.c    |  213 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 240 insertions(+), 177 deletions(-)
 create mode 100644 net/bluetooth/l2cap_sock.c

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 7f88a87..fce5274 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -424,6 +424,21 @@ static inline int l2cap_tx_window_full(struct sock *sk)
 #define __is_sframe(ctrl)	((ctrl) & L2CAP_CTRL_FRAME_TYPE)
 #define __is_sar_start(ctrl)	(((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START)
 
+extern int disable_ertm;
+extern const struct proto_ops l2cap_sock_ops;
+extern struct bt_sock_list l2cap_sk_list;
+
+int l2cap_init_sockets(void);
+void l2cap_cleanup_sockets(void);
+
+void l2cap_sock_set_timer(struct sock *sk, long timeout);
+void __l2cap_sock_close(struct sock *sk, int reason);
+void l2cap_sock_kill(struct sock *sk);
+void l2cap_sock_init(struct sock *sk, struct sock *parent);
+struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
+							int proto, gfp_t prio);
+
+
 void l2cap_load(void);
 
 #endif /* __L2CAP_H */
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
index bf2945e..339b429 100644
--- a/net/bluetooth/Makefile
+++ b/net/bluetooth/Makefile
@@ -11,4 +11,4 @@ obj-$(CONFIG_BT_CMTP)	+= cmtp/
 obj-$(CONFIG_BT_HIDP)	+= hidp/
 
 bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o hci_sock.o hci_sysfs.o lib.o
-l2cap-y := l2cap_core.o
+l2cap-y := l2cap_core.o l2cap_sock.o
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 1761558..53f9ebd 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -24,7 +24,7 @@
    SOFTWARE IS DISCLAIMED.
 */
 
-/* Bluetooth L2CAP core and sockets. */
+/* Bluetooth L2CAP core. */
 
 #include <linux/module.h>
 
@@ -57,24 +57,20 @@
 
 #define VERSION "2.15"
 
-static int disable_ertm;
+int disable_ertm;
 
 static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
 static u8 l2cap_fixed_chan[8] = { 0x02, };
 
-static const struct proto_ops l2cap_sock_ops;
-
 static struct workqueue_struct *_busy_wq;
 
-static struct bt_sock_list l2cap_sk_list = {
+struct bt_sock_list l2cap_sk_list = {
 	.lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
 };
 
 static void l2cap_busy_work(struct work_struct *work);
 
-static void __l2cap_sock_close(struct sock *sk, int reason);
 static void l2cap_sock_close(struct sock *sk);
-static void l2cap_sock_kill(struct sock *sk);
 
 static int l2cap_build_conf_req(struct sock *sk, void *data);
 static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
@@ -83,7 +79,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
 static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
 
 /* ---- L2CAP timers ---- */
-static void l2cap_sock_set_timer(struct sock *sk, long timeout)
+void l2cap_sock_set_timer(struct sock *sk, long timeout)
 {
 	BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
 	sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
@@ -95,39 +91,6 @@ static void l2cap_sock_clear_timer(struct sock *sk)
 	sk_stop_timer(sk, &sk->sk_timer);
 }
 
-static void l2cap_sock_timeout(unsigned long arg)
-{
-	struct sock *sk = (struct sock *) arg;
-	int reason;
-
-	BT_DBG("sock %p state %d", sk, sk->sk_state);
-
-	bh_lock_sock(sk);
-
-	if (sock_owned_by_user(sk)) {
-		/* sk is owned by user. Try again later */
-		l2cap_sock_set_timer(sk, HZ / 5);
-		bh_unlock_sock(sk);
-		sock_put(sk);
-		return;
-	}
-
-	if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
-		reason = ECONNREFUSED;
-	else if (sk->sk_state == BT_CONNECT &&
-				l2cap_pi(sk)->sec_level != BT_SECURITY_SDP)
-		reason = ECONNREFUSED;
-	else
-		reason = ETIMEDOUT;
-
-	__l2cap_sock_close(sk, reason);
-
-	bh_unlock_sock(sk);
-
-	l2cap_sock_kill(sk);
-	sock_put(sk);
-}
-
 /* ---- L2CAP channels ---- */
 static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
 {
@@ -801,14 +764,6 @@ static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
 	return node ? sk : sk1;
 }
 
-static void l2cap_sock_destruct(struct sock *sk)
-{
-	BT_DBG("sk %p", sk);
-
-	skb_queue_purge(&sk->sk_receive_queue);
-	skb_queue_purge(&sk->sk_write_queue);
-}
-
 static void l2cap_sock_cleanup_listen(struct sock *parent)
 {
 	struct sock *sk;
@@ -826,7 +781,7 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)
 /* Kill socket (only if zapped and orphan)
  * Must be called on unlocked socket.
  */
-static void l2cap_sock_kill(struct sock *sk)
+void l2cap_sock_kill(struct sock *sk)
 {
 	if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
 		return;
@@ -839,7 +794,7 @@ static void l2cap_sock_kill(struct sock *sk)
 	sock_put(sk);
 }
 
-static void __l2cap_sock_close(struct sock *sk, int reason)
+void __l2cap_sock_close(struct sock *sk, int reason)
 {
 	BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
 
@@ -903,111 +858,6 @@ static void l2cap_sock_close(struct sock *sk)
 	l2cap_sock_kill(sk);
 }
 
-static void l2cap_sock_init(struct sock *sk, struct sock *parent)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-
-	BT_DBG("sk %p", sk);
-
-	if (parent) {
-		sk->sk_type = parent->sk_type;
-		bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup;
-
-		pi->imtu = l2cap_pi(parent)->imtu;
-		pi->omtu = l2cap_pi(parent)->omtu;
-		pi->conf_state = l2cap_pi(parent)->conf_state;
-		pi->mode = l2cap_pi(parent)->mode;
-		pi->fcs  = l2cap_pi(parent)->fcs;
-		pi->max_tx = l2cap_pi(parent)->max_tx;
-		pi->tx_win = l2cap_pi(parent)->tx_win;
-		pi->sec_level = l2cap_pi(parent)->sec_level;
-		pi->role_switch = l2cap_pi(parent)->role_switch;
-		pi->force_reliable = l2cap_pi(parent)->force_reliable;
-		pi->flushable = l2cap_pi(parent)->flushable;
-	} else {
-		pi->imtu = L2CAP_DEFAULT_MTU;
-		pi->omtu = 0;
-		if (!disable_ertm && sk->sk_type == SOCK_STREAM) {
-			pi->mode = L2CAP_MODE_ERTM;
-			pi->conf_state |= L2CAP_CONF_STATE2_DEVICE;
-		} else {
-			pi->mode = L2CAP_MODE_BASIC;
-		}
-		pi->max_tx = L2CAP_DEFAULT_MAX_TX;
-		pi->fcs  = L2CAP_FCS_CRC16;
-		pi->tx_win = L2CAP_DEFAULT_TX_WINDOW;
-		pi->sec_level = BT_SECURITY_LOW;
-		pi->role_switch = 0;
-		pi->force_reliable = 0;
-		pi->flushable = BT_FLUSHABLE_OFF;
-	}
-
-	/* Default config options */
-	pi->conf_len = 0;
-	pi->flush_to = L2CAP_DEFAULT_FLUSH_TO;
-	skb_queue_head_init(TX_QUEUE(sk));
-	skb_queue_head_init(SREJ_QUEUE(sk));
-	skb_queue_head_init(BUSY_QUEUE(sk));
-	INIT_LIST_HEAD(SREJ_LIST(sk));
-}
-
-static struct proto l2cap_proto = {
-	.name		= "L2CAP",
-	.owner		= THIS_MODULE,
-	.obj_size	= sizeof(struct l2cap_pinfo)
-};
-
-static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
-{
-	struct sock *sk;
-
-	sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto);
-	if (!sk)
-		return NULL;
-
-	sock_init_data(sock, sk);
-	INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
-
-	sk->sk_destruct = l2cap_sock_destruct;
-	sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT);
-
-	sock_reset_flag(sk, SOCK_ZAPPED);
-
-	sk->sk_protocol = proto;
-	sk->sk_state = BT_OPEN;
-
-	setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk);
-
-	bt_sock_link(&l2cap_sk_list, sk);
-	return sk;
-}
-
-static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
-			     int kern)
-{
-	struct sock *sk;
-
-	BT_DBG("sock %p", sock);
-
-	sock->state = SS_UNCONNECTED;
-
-	if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM &&
-			sock->type != SOCK_DGRAM && sock->type != SOCK_RAW)
-		return -ESOCKTNOSUPPORT;
-
-	if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
-		return -EPERM;
-
-	sock->ops = &l2cap_sock_ops;
-
-	sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC);
-	if (!sk)
-		return -ENOMEM;
-
-	l2cap_sock_init(sk, NULL);
-	return 0;
-}
-
 static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 {
 	struct sock *sk = sock->sk;
@@ -4864,7 +4714,7 @@ static const struct file_operations l2cap_debugfs_fops = {
 
 static struct dentry *l2cap_debugfs;
 
-static const struct proto_ops l2cap_sock_ops = {
+const struct proto_ops l2cap_sock_ops = {
 	.family		= PF_BLUETOOTH,
 	.owner		= THIS_MODULE,
 	.release	= l2cap_sock_release,
@@ -4884,12 +4734,6 @@ static const struct proto_ops l2cap_sock_ops = {
 	.getsockopt	= l2cap_sock_getsockopt
 };
 
-static const struct net_proto_family l2cap_sock_family_ops = {
-	.family	= PF_BLUETOOTH,
-	.owner	= THIS_MODULE,
-	.create	= l2cap_sock_create,
-};
-
 static struct hci_proto l2cap_hci_proto = {
 	.name		= "L2CAP",
 	.id		= HCI_PROTO_L2CAP,
@@ -4905,19 +4749,13 @@ static int __init l2cap_init(void)
 {
 	int err;
 
-	err = proto_register(&l2cap_proto, 0);
+	err = l2cap_init_sockets();
 	if (err < 0)
 		return err;
 
 	_busy_wq = create_singlethread_workqueue("l2cap");
 	if (!_busy_wq) {
-		proto_unregister(&l2cap_proto);
-		return -ENOMEM;
-	}
-
-	err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
-	if (err < 0) {
-		BT_ERR("L2CAP socket registration failed");
+		err = -ENOMEM;
 		goto error;
 	}
 
@@ -4942,7 +4780,7 @@ static int __init l2cap_init(void)
 
 error:
 	destroy_workqueue(_busy_wq);
-	proto_unregister(&l2cap_proto);
+	l2cap_cleanup_sockets();
 	return err;
 }
 
@@ -4953,13 +4791,10 @@ static void __exit l2cap_exit(void)
 	flush_workqueue(_busy_wq);
 	destroy_workqueue(_busy_wq);
 
-	if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
-		BT_ERR("L2CAP socket unregistration failed");
-
 	if (hci_unregister_proto(&l2cap_hci_proto) < 0)
 		BT_ERR("L2CAP protocol unregistration failed");
 
-	proto_unregister(&l2cap_proto);
+	l2cap_cleanup_sockets();
 }
 
 void l2cap_load(void)
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
new file mode 100644
index 0000000..6ea1894
--- /dev/null
+++ b/net/bluetooth/l2cap_sock.c
@@ -0,0 +1,213 @@
+/*
+   BlueZ - Bluetooth protocol stack for Linux
+   Copyright (C) 2000-2001 Qualcomm Incorporated
+   Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
+   Copyright (C) 2010 Google Inc.
+
+   Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2 as
+   published by the Free Software Foundation;
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+   SOFTWARE IS DISCLAIMED.
+*/
+
+/* Bluetooth L2CAP sockets. */
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/l2cap.h>
+
+static void l2cap_sock_timeout(unsigned long arg)
+{
+	struct sock *sk = (struct sock *) arg;
+	int reason;
+
+	BT_DBG("sock %p state %d", sk, sk->sk_state);
+
+	bh_lock_sock(sk);
+
+	if (sock_owned_by_user(sk)) {
+		/* sk is owned by user. Try again later */
+		l2cap_sock_set_timer(sk, HZ / 5);
+		bh_unlock_sock(sk);
+		sock_put(sk);
+		return;
+	}
+
+	if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
+		reason = ECONNREFUSED;
+	else if (sk->sk_state == BT_CONNECT &&
+				l2cap_pi(sk)->sec_level != BT_SECURITY_SDP)
+		reason = ECONNREFUSED;
+	else
+		reason = ETIMEDOUT;
+
+	__l2cap_sock_close(sk, reason);
+
+	bh_unlock_sock(sk);
+
+	l2cap_sock_kill(sk);
+	sock_put(sk);
+}
+
+
+static void l2cap_sock_destruct(struct sock *sk)
+{
+	BT_DBG("sk %p", sk);
+
+	skb_queue_purge(&sk->sk_receive_queue);
+	skb_queue_purge(&sk->sk_write_queue);
+}
+
+void l2cap_sock_init(struct sock *sk, struct sock *parent)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+
+	BT_DBG("sk %p", sk);
+
+	if (parent) {
+		sk->sk_type = parent->sk_type;
+		bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup;
+
+		pi->imtu = l2cap_pi(parent)->imtu;
+		pi->omtu = l2cap_pi(parent)->omtu;
+		pi->conf_state = l2cap_pi(parent)->conf_state;
+		pi->mode = l2cap_pi(parent)->mode;
+		pi->fcs  = l2cap_pi(parent)->fcs;
+		pi->max_tx = l2cap_pi(parent)->max_tx;
+		pi->tx_win = l2cap_pi(parent)->tx_win;
+		pi->sec_level = l2cap_pi(parent)->sec_level;
+		pi->role_switch = l2cap_pi(parent)->role_switch;
+		pi->force_reliable = l2cap_pi(parent)->force_reliable;
+		pi->flushable = l2cap_pi(parent)->flushable;
+	} else {
+		pi->imtu = L2CAP_DEFAULT_MTU;
+		pi->omtu = 0;
+		if (!disable_ertm && sk->sk_type == SOCK_STREAM) {
+			pi->mode = L2CAP_MODE_ERTM;
+			pi->conf_state |= L2CAP_CONF_STATE2_DEVICE;
+		} else {
+			pi->mode = L2CAP_MODE_BASIC;
+		}
+		pi->max_tx = L2CAP_DEFAULT_MAX_TX;
+		pi->fcs  = L2CAP_FCS_CRC16;
+		pi->tx_win = L2CAP_DEFAULT_TX_WINDOW;
+		pi->sec_level = BT_SECURITY_LOW;
+		pi->role_switch = 0;
+		pi->force_reliable = 0;
+		pi->flushable = BT_FLUSHABLE_OFF;
+	}
+
+	/* Default config options */
+	pi->conf_len = 0;
+	pi->flush_to = L2CAP_DEFAULT_FLUSH_TO;
+	skb_queue_head_init(TX_QUEUE(sk));
+	skb_queue_head_init(SREJ_QUEUE(sk));
+	skb_queue_head_init(BUSY_QUEUE(sk));
+	INIT_LIST_HEAD(SREJ_LIST(sk));
+}
+
+static struct proto l2cap_proto = {
+	.name		= "L2CAP",
+	.owner		= THIS_MODULE,
+	.obj_size	= sizeof(struct l2cap_pinfo)
+};
+
+struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
+{
+	struct sock *sk;
+
+	sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto);
+	if (!sk)
+		return NULL;
+
+	sock_init_data(sock, sk);
+	INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
+
+	sk->sk_destruct = l2cap_sock_destruct;
+	sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT);
+
+	sock_reset_flag(sk, SOCK_ZAPPED);
+
+	sk->sk_protocol = proto;
+	sk->sk_state = BT_OPEN;
+
+	setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk);
+
+	bt_sock_link(&l2cap_sk_list, sk);
+	return sk;
+}
+
+static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
+			     int kern)
+{
+	struct sock *sk;
+
+	BT_DBG("sock %p", sock);
+
+	sock->state = SS_UNCONNECTED;
+
+	if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM &&
+			sock->type != SOCK_DGRAM && sock->type != SOCK_RAW)
+		return -ESOCKTNOSUPPORT;
+
+	if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
+		return -EPERM;
+
+	sock->ops = &l2cap_sock_ops;
+
+	sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC);
+	if (!sk)
+		return -ENOMEM;
+
+	l2cap_sock_init(sk, NULL);
+	return 0;
+}
+
+static const struct net_proto_family l2cap_sock_family_ops = {
+	.family	= PF_BLUETOOTH,
+	.owner	= THIS_MODULE,
+	.create	= l2cap_sock_create,
+};
+
+int __init l2cap_init_sockets(void)
+{
+       int err;
+
+       err = proto_register(&l2cap_proto, 0);
+       if (err < 0)
+               return err;
+
+       err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
+       if (err < 0)
+               goto error;
+
+       BT_INFO("L2CAP socket layer initialized");
+
+       return 0;
+
+error:
+       BT_ERR("L2CAP socket registration failed");
+       proto_unregister(&l2cap_proto);
+       return err;
+}
+
+void l2cap_cleanup_sockets(void)
+{
+       if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
+               BT_ERR("L2CAP socket unregistration failed");
+
+       proto_unregister(&l2cap_proto);
+}
-- 
1.7.4.rc3


^ permalink raw reply related

* [bluetooth-next 00/16] l2cap.c split
From: Gustavo F. Padovan @ 2011-02-04  6:01 UTC (permalink / raw)
  To: linux-bluetooth

Here is the first real split of l2cap.c file. That file was getting so big that
we really need to split it in two or more. By now we have two file:
l2cap_sock.c and l2cap_core.c. In l2cap_sock.c we have all functions that deals
with sockets, in l2cap_core.c the rest.

Side efects are that I had to move the declaration of many functions to l2cap.h
along the l2cap socket list.

There are more steps on this, but this is surely a big one.

Gustavo F. Padovan (16):
  Bluetooth: Rename l2cap.c to l2cap_core.c
  Bluetooth: Initial work for L2CAP split.
  Bluetooth: move l2cap_sock_ops to l2cap_sock.c
  Bluetooth: move l2cap_sock_release() to l2cap_sock.c
  Bluetooth: move l2cap_sock_bind()/listen() to l2cap_sock.c
  Bluetooth: move l2cap_sock_accept() to l2cap_sock.c
  Bluetooth: move l2cap_sock_getname() to l2cap_sock.c
  Bluetooth: move l2cap_sock_setsockopt() to l2cap_sock.c
  Bluetooth: move l2cap_sock_getsockopt() to l2cap_sock.c
  Bluetooth: move l2cap_sock_connect() to l2cap_sock.c
  Bluetooth: move l2cap_sock_recvmsg() to l2cap_sock.c
  Bluetooth: move l2cap_sock_shutdown() to l2cap_sock.c
  Bluetooth: move l2cap_sock_sendmsg() to l2cap_sock.c
  Bluetooth: move L2CAP sock timers function to l2cap_sock.c
  Bluetooth: move l2cap_sock_kill() to l2cap_sock.c
  Bluetooth: move __l2cap_sock_close() to l2cap_sock.c

 include/net/bluetooth/l2cap.h |   31 +
 net/bluetooth/Makefile        |    1 +
 net/bluetooth/l2cap.c         | 4983 -----------------------------------------
 net/bluetooth/l2cap_core.c    | 3879 ++++++++++++++++++++++++++++++++
 net/bluetooth/l2cap_sock.c    | 1150 ++++++++++
 5 files changed, 5061 insertions(+), 4983 deletions(-)
 delete mode 100644 net/bluetooth/l2cap.c
 create mode 100644 net/bluetooth/l2cap_core.c
 create mode 100644 net/bluetooth/l2cap_sock.c

-- 
1.7.4.rc3


^ permalink raw reply

* Re: [PATCH] Changing required GLIB version in acinclude.m4
From: Johan Hedberg @ 2011-02-04  5:01 UTC (permalink / raw)
  To: Gustavo F. Padovan
  Cc: Luiz Augusto von Dentz, ankushbansal89, linux-bluetooth
In-Reply-To: <20110203200440.GD2168@joana>

Hi,

On Thu, Feb 03, 2011, Gustavo F. Padovan wrote:
> > Can you provide more details why this is needed, is there any new
> > function we are using which requires 2.16?
> 
> It is g_strcmp0(), but it should be a good idea add this info to the commit
> message.

I went ahead and added this to the patch. It has now been pushed
upstream.

Johan

^ permalink raw reply

* Re: [PATCH] Fix refcount in btd_adapter_any_request_path()
From: Johan Hedberg @ 2011-02-04  4:58 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: linux-bluetooth
In-Reply-To: <1296792331-467-1-git-send-email-anderson.lizardo@openbossa.org>

Hi Lizardo,

On Fri, Feb 04, 2011, Anderson Lizardo wrote:
> adapter_any_refcount was not being incremented when a pointer to
> allocated buffer was returned.
> ---
>  src/adapter.c |    3 +--
>  1 files changed, 1 insertions(+), 2 deletions(-)
> 
> diff --git a/src/adapter.c b/src/adapter.c
> index 08098a5..3e609c1 100644
> --- a/src/adapter.c
> +++ b/src/adapter.c
> @@ -3428,11 +3428,10 @@ const char *adapter_any_get_path(void)
>  
>  const char *btd_adapter_any_request_path(void)
>  {
> -	if (adapter_any_refcount > 0)
> +	if (adapter_any_refcount++ > 0)
>  		return adapter_any_path;
>  
>  	adapter_any_path = g_strdup_printf("%s/any", manager_get_base_path());
> -	adapter_any_refcount++;
>  
>  	return adapter_any_path;
>  }

Nice catch. The patch has been pushed upstream. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH] rename: tools/main.c to tools/rfcomm.c
From: Johan Hedberg @ 2011-02-04  4:57 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: linux-bluetooth
In-Reply-To: <1296763379-13291-1-git-send-email-padovan@profusion.mobi>

Hi Gustavo,

On Thu, Feb 03, 2011, Gustavo F. Padovan wrote:
> ---
>  Makefile.tools |    2 +-
>  tools/main.c   |  849 --------------------------------------------------------
>  tools/rfcomm.c |  849 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 850 insertions(+), 850 deletions(-)
>  delete mode 100644 tools/main.c
>  create mode 100644 tools/rfcomm.c

The patch has been pushed upstream. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH] Fix invalid read after list concatenation
From: Johan Hedberg @ 2011-02-04  4:55 UTC (permalink / raw)
  To: Bruna Moreira; +Cc: linux-bluetooth
In-Reply-To: <1296758628-15202-1-git-send-email-bruna.moreira@openbossa.org>

Hi Bruna,

On Thu, Feb 03, 2011, Bruna Moreira wrote:
> g_slist_concat uses the items from second list directly so they should
> not be freed.
> ---
>  attrib/gatt.c |    1 -
>  1 files changed, 0 insertions(+), 1 deletions(-)

Pushed upstream. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH] Fix parameter type in att_put_u32
From: Johan Hedberg @ 2011-02-04  4:54 UTC (permalink / raw)
  To: Elvis Pfützenreuter; +Cc: linux-bluetooth
In-Reply-To: <1296740222-27174-1-git-send-email-epx@signove.com>

Hi Elvis,

On Thu, Feb 03, 2011, Elvis Pfützenreuter wrote:
> ---
>  attrib/att.h |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/attrib/att.h b/attrib/att.h
> index 1caa62a..7e81dc4 100644
> --- a/attrib/att.h
> +++ b/attrib/att.h
> @@ -180,7 +180,7 @@ static inline void att_put_u16(uint16_t src, void *dst)
>  	bt_put_unaligned(htobs(src), (uint16_t *) dst);
>  }
>  
> -static inline void att_put_u32(uint16_t src, void *dst)
> +static inline void att_put_u32(uint32_t src, void *dst)
>  {
>  	bt_put_unaligned(htobl(src), (uint32_t *) dst);
>  }

Pushed upstream. Thanks.

Johan

^ permalink raw reply

* [PATCH] Fix refcount in btd_adapter_any_request_path()
From: Anderson Lizardo @ 2011-02-04  4:05 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Lizardo

adapter_any_refcount was not being incremented when a pointer to
allocated buffer was returned.
---
 src/adapter.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 08098a5..3e609c1 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3428,11 +3428,10 @@ const char *adapter_any_get_path(void)
 
 const char *btd_adapter_any_request_path(void)
 {
-	if (adapter_any_refcount > 0)
+	if (adapter_any_refcount++ > 0)
 		return adapter_any_path;
 
 	adapter_any_path = g_strdup_printf("%s/any", manager_get_base_path());
-	adapter_any_refcount++;
 
 	return adapter_any_path;
 }
-- 
1.7.0.4


^ permalink raw reply related

* Re: [PATCH] Changing required GLIB version in acinclude.m4
From: Gustavo F. Padovan @ 2011-02-03 20:04 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: ankushbansal89, linux-bluetooth
In-Reply-To: <AANLkTi=DdZzYtadsTTOO6Y-R=8Sq7x+EX46g7UDYa-7m@mail.gmail.com>

Hi Luiz,

* Luiz Augusto von Dentz <luiz.dentz@gmail.com> [2011-02-03 10:46:08 +0200]:

> Hi,
> 
> On Wed, Feb 2, 2011 at 10:04 PM,  <ankushbansal89@gmail.com> wrote:
> > From: Ankush Bansal <ankushbansal89@gmail.com>
> >
> > ---
> >  acinclude.m4 |    4 ++--
> >  1 files changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/acinclude.m4 b/acinclude.m4
> > index ecf4b4b..9d3f6b2 100644
> > --- a/acinclude.m4
> > +++ b/acinclude.m4
> > @@ -108,8 +108,8 @@ AC_DEFUN([AC_PATH_DBUS], [
> >  ])
> >
> >  AC_DEFUN([AC_PATH_GLIB], [
> > -       PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.14, dummy=yes,
> > -                               AC_MSG_ERROR(GLib library version 2.14 or later is required))
> > +       PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes,
> > +                               AC_MSG_ERROR(GLib library version 2.16 or later is required))
> >        AC_SUBST(GLIB_CFLAGS)
> >        AC_SUBST(GLIB_LIBS)
> >  ])
> > --
> > 1.7.1
> 
> Can you provide more details why this is needed, is there any new
> function we are using which requires 2.16?

It is g_strcmp0(), but it should be a good idea add this info to the commit
message.

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

^ permalink raw reply

* [PATCH] rename: tools/main.c to tools/rfcomm.c
From: Gustavo F. Padovan @ 2011-02-03 20:02 UTC (permalink / raw)
  To: linux-bluetooth

---
 Makefile.tools |    2 +-
 tools/main.c   |  849 --------------------------------------------------------
 tools/rfcomm.c |  849 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 850 insertions(+), 850 deletions(-)
 delete mode 100644 tools/main.c
 create mode 100644 tools/rfcomm.c

diff --git a/Makefile.tools b/Makefile.tools
index 96c5915..9c43202 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -14,7 +14,7 @@ noinst_PROGRAMS += tools/avinfo tools/ppporc \
 
 tools/kword.c: tools/parser.h
 
-tools_rfcomm_SOURCES = tools/main.c tools/parser.y tools/lexer.l \
+tools_rfcomm_SOURCES = tools/rfcomm.c tools/parser.y tools/lexer.l \
 					tools/kword.h tools/kword.c
 EXTRA_tools_rfcomm_SOURCES = tools/parser.h tools/parser.c \
 							tools/lexer.c
diff --git a/tools/main.c b/tools/main.c
deleted file mode 100644
index 6800445..0000000
--- a/tools/main.c
+++ /dev/null
@@ -1,849 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <signal.h>
-#include <termios.h>
-#include <sys/poll.h>
-#include <sys/param.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/hci.h>
-#include <bluetooth/hci_lib.h>
-#include <bluetooth/rfcomm.h>
-
-#include "kword.h"
-
-#ifdef NEED_PPOLL
-#include "ppoll.h"
-#endif
-
-static char *rfcomm_config_file = NULL;
-static int rfcomm_raw_tty = 0;
-static int auth = 0;
-static int encryption = 0;
-static int secure = 0;
-static int master = 0;
-static int linger = 0;
-
-static char *rfcomm_state[] = {
-	"unknown",
-	"connected",
-	"clean",
-	"bound",
-	"listening",
-	"connecting",
-	"connecting",
-	"config",
-	"disconnecting",
-	"closed"
-};
-
-static volatile sig_atomic_t __io_canceled = 0;
-
-static void sig_hup(int sig)
-{
-	return;
-}
-
-static void sig_term(int sig)
-{
-	__io_canceled = 1;
-}
-
-static char *rfcomm_flagstostr(uint32_t flags)
-{
-	static char str[100];
-	str[0] = 0;
-
-	strcat(str, "[");
-
-	if (flags & (1 << RFCOMM_REUSE_DLC))
-		strcat(str, "reuse-dlc ");
-
-	if (flags & (1 << RFCOMM_RELEASE_ONHUP))
-		strcat(str, "release-on-hup ");
-
-	if (flags & (1 << RFCOMM_TTY_ATTACHED))
-		strcat(str, "tty-attached");
-
-	strcat(str, "]");
-	return str;
-}
-
-static void print_dev_info(struct rfcomm_dev_info *di)
-{
-	char src[18], dst[18], addr[40];
-
-	ba2str(&di->src, src); ba2str(&di->dst, dst);
-
-	if (bacmp(&di->src, BDADDR_ANY) == 0)
-		sprintf(addr, "%s", dst);
-	else
-		sprintf(addr, "%s -> %s", src, dst);
-
-	printf("rfcomm%d: %s channel %d %s %s\n",
-		di->id, addr, di->channel,
-		rfcomm_state[di->state],
-		di->flags ? rfcomm_flagstostr(di->flags) : "");
-}
-
-static void print_dev_list(int ctl, int flags)
-{
-	struct rfcomm_dev_list_req *dl;
-	struct rfcomm_dev_info *di;
-	int i;
-
-	dl = malloc(sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di));
-	if (!dl) {
-		perror("Can't allocate memory");
-		exit(1);
-	}
-
-	dl->dev_num = RFCOMM_MAX_DEV;
-	di = dl->dev_info;
-
-	if (ioctl(ctl, RFCOMMGETDEVLIST, (void *) dl) < 0) {
-		perror("Can't get device list");
-		free(dl);
-		exit(1);
-	}
-
-	for (i = 0; i < dl->dev_num; i++)
-		print_dev_info(di + i);
-	free(dl);
-}
-
-static int create_dev(int ctl, int dev, uint32_t flags, bdaddr_t *bdaddr, int argc, char **argv)
-{
-	struct rfcomm_dev_req req;
-	int err;
-
-	memset(&req, 0, sizeof(req));
-	req.dev_id = dev;
-	req.flags = flags;
-	bacpy(&req.src, bdaddr);
-
-	if (argc < 2) {
-		err = rfcomm_read_config(rfcomm_config_file);
-		if (err < 0) {
-			perror("Can't open RFCOMM config file");
-			return err;
-		}
-
-		bacpy(&req.dst, &rfcomm_opts[dev].bdaddr);
-		req.channel = rfcomm_opts[dev].channel;
-
-		if (bacmp(&req.dst, BDADDR_ANY) == 0) {
-			fprintf(stderr, "Can't find a config entry for rfcomm%d\n", dev);
-			return -EFAULT;
-		}
-	} else {
-		str2ba(argv[1], &req.dst);
-
-		if (argc > 2)
-			req.channel = atoi(argv[2]);
-		else
-			req.channel = 1;
-	}
-
-	err = ioctl(ctl, RFCOMMCREATEDEV, &req);
-	if (err == EOPNOTSUPP)
-		fprintf(stderr, "RFCOMM TTY support not available\n");
-	else if (err < 0)
-		perror("Can't create device");
-
-	return err;
-}
-
-static int create_all(int ctl)
-{
-	struct rfcomm_dev_req req;
-	int i, err;
-
-	err = rfcomm_read_config(rfcomm_config_file);
-	if (err < 0) {
-		perror("Can't open RFCOMM config file");
-		return err;
-	}
-
-	for (i = 0; i < RFCOMM_MAX_DEV; i++) {
-		if (!rfcomm_opts[i].bind)
-			continue;
-
-		memset(&req, 0, sizeof(req));
-		req.dev_id = i;
-		req.flags = 0;
-		bacpy(&req.src, BDADDR_ANY);
-		bacpy(&req.dst, &rfcomm_opts[i].bdaddr);
-		req.channel = rfcomm_opts[i].channel;
-
-		if (bacmp(&req.dst, BDADDR_ANY) != 0)
-			ioctl(ctl, RFCOMMCREATEDEV, &req);
-	}
-
-	return 0;
-}
-
-static int release_dev(int ctl, int dev, uint32_t flags)
-{
-	struct rfcomm_dev_req req;
-	int err;
-
-	memset(&req, 0, sizeof(req));
-	req.dev_id = dev;
-
-	err = ioctl(ctl, RFCOMMRELEASEDEV, &req);
-	if (err < 0)
-		perror("Can't release device");
-
-	return err;
-}
-
-static int release_all(int ctl)
-{
-	struct rfcomm_dev_list_req *dl;
-	struct rfcomm_dev_info *di;
-	int i;
-
-	dl = malloc(sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di));
-	if (!dl) {
-		perror("Can't allocate memory");
-		exit(1);
-	}
-
-	dl->dev_num = RFCOMM_MAX_DEV;
-	di = dl->dev_info;
-
-	if (ioctl(ctl, RFCOMMGETDEVLIST, (void *) dl) < 0) {
-		perror("Can't get device list");
-		free(dl);
-		exit(1);
-	}
-
-	for (i = 0; i < dl->dev_num; i++)
-		release_dev(ctl, (di + i)->id, 0);
-
-	free(dl);
-	return 0;
-}
-
-static void run_cmdline(struct pollfd *p, sigset_t* sigs, char *devname,
-			int argc, char **argv)
-{
-	int i;
-	pid_t pid;
-	char **cmdargv;
-
-	cmdargv = malloc((argc + 1) * sizeof(char*));
-	if (!cmdargv)
-		return;
-
-	for (i = 0; i < argc; i++)
-		cmdargv[i] = (strcmp(argv[i], "{}") == 0) ? devname : argv[i];
-	cmdargv[i] = NULL;
-
-	pid = fork();
-
-	switch (pid) {
-	case 0:
-		i = execvp(cmdargv[0], cmdargv);
-		fprintf(stderr, "Couldn't execute command %s (errno=%d:%s)\n",
-				cmdargv[0], errno, strerror(errno));
-		break;
-	case -1:
-		fprintf(stderr, "Couldn't fork to execute command %s\n",
-				cmdargv[0]);
-		break;
-	default:
-		while (1) {
-			int status;
-			pid_t child;
-			struct timespec ts;
-
-			child = waitpid(-1, &status, WNOHANG);
-			if (child == pid || (child < 0 && errno != EAGAIN))
-				break;
-
-			p->revents = 0;
-			ts.tv_sec  = 0;
-			ts.tv_nsec = 200;
-			if (ppoll(p, 1, &ts, sigs) || __io_canceled) {
-				kill(pid, SIGTERM);
-				waitpid(pid, &status, 0);
-				break;
-			}
-		}
-		break;
-	}
-
-	free(cmdargv);
-}
-
-static void cmd_connect(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
-{
-	struct sockaddr_rc laddr, raddr;
-	struct rfcomm_dev_req req;
-	struct termios ti;
-	struct sigaction sa;
-	struct pollfd p;
-	sigset_t sigs;
-	socklen_t alen;
-	char dst[18], devname[MAXPATHLEN];
-	int sk, fd, try = 30;
-
-	laddr.rc_family = AF_BLUETOOTH;
-	bacpy(&laddr.rc_bdaddr, bdaddr);
-	laddr.rc_channel = 0;
-
-	if (argc < 2) {
-		if (rfcomm_read_config(rfcomm_config_file) < 0) {
-			perror("Can't open RFCOMM config file");
-			return;
-		}
-
-		raddr.rc_family = AF_BLUETOOTH;
-		bacpy(&raddr.rc_bdaddr, &rfcomm_opts[dev].bdaddr);
-		raddr.rc_channel = rfcomm_opts[dev].channel;
-
-		if (bacmp(&raddr.rc_bdaddr, BDADDR_ANY) == 0) {
-			fprintf(stderr, "Can't find a config entry for rfcomm%d\n", dev);
-			return;
-		}
-	} else {
-		raddr.rc_family = AF_BLUETOOTH;
-		str2ba(argv[1], &raddr.rc_bdaddr);
-
-		if (argc > 2)
-			raddr.rc_channel = atoi(argv[2]);
-		else
-			raddr.rc_channel = 1;
-	}
-
-	sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
-	if (sk < 0) {
-		perror("Can't create RFCOMM socket");
-		return;
-	}
-
-	if (linger) {
-		struct linger l = { .l_onoff = 1, .l_linger = linger };
-
-		if (setsockopt(sk, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) < 0) {
-			perror("Can't set linger option");
-			return;
-		}
-	}
-
-	if (bind(sk, (struct sockaddr *) &laddr, sizeof(laddr)) < 0) {
-		perror("Can't bind RFCOMM socket");
-		close(sk);
-		return;
-	}
-
-	if (connect(sk, (struct sockaddr *) &raddr, sizeof(raddr)) < 0) {
-		perror("Can't connect RFCOMM socket");
-		close(sk);
-		return;
-	}
-
-	alen = sizeof(laddr);
-	if (getsockname(sk, (struct sockaddr *)&laddr, &alen) < 0) {
-		perror("Can't get RFCOMM socket name");
-		close(sk);
-		return;
-	}
-
-	memset(&req, 0, sizeof(req));
-	req.dev_id = dev;
-	req.flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP);
-
-	bacpy(&req.src, &laddr.rc_bdaddr);
-	bacpy(&req.dst, &raddr.rc_bdaddr);
-	req.channel = raddr.rc_channel;
-
-	dev = ioctl(sk, RFCOMMCREATEDEV, &req);
-	if (dev < 0) {
-		perror("Can't create RFCOMM TTY");
-		close(sk);
-		return;
-	}
-
-	snprintf(devname, MAXPATHLEN - 1, "/dev/rfcomm%d", dev);
-	while ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
-		if (errno == EACCES) {
-			perror("Can't open RFCOMM device");
-			goto release;
-		}
-
-		snprintf(devname, MAXPATHLEN - 1, "/dev/bluetooth/rfcomm/%d", dev);
-		if ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
-			if (try--) {
-				snprintf(devname, MAXPATHLEN - 1, "/dev/rfcomm%d", dev);
-				usleep(100 * 1000);
-				continue;
-			}
-			perror("Can't open RFCOMM device");
-			goto release;
-		}
-	}
-
-	if (rfcomm_raw_tty) {
-		tcflush(fd, TCIOFLUSH);
-
-		cfmakeraw(&ti);
-		tcsetattr(fd, TCSANOW, &ti);
-	}
-
-	close(sk);
-
-	ba2str(&req.dst, dst);
-	printf("Connected %s to %s on channel %d\n", devname, dst, req.channel);
-	printf("Press CTRL-C for hangup\n");
-
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_flags   = SA_NOCLDSTOP;
-	sa.sa_handler = SIG_IGN;
-	sigaction(SIGCHLD, &sa, NULL);
-	sigaction(SIGPIPE, &sa, NULL);
-
-	sa.sa_handler = sig_term;
-	sigaction(SIGTERM, &sa, NULL);
-	sigaction(SIGINT,  &sa, NULL);
-
-	sa.sa_handler = sig_hup;
-	sigaction(SIGHUP, &sa, NULL);
-
-	sigfillset(&sigs);
-	sigdelset(&sigs, SIGCHLD);
-	sigdelset(&sigs, SIGPIPE);
-	sigdelset(&sigs, SIGTERM);
-	sigdelset(&sigs, SIGINT);
-	sigdelset(&sigs, SIGHUP);
-
-	p.fd = fd;
-	p.events = POLLERR | POLLHUP;
-
-	while (!__io_canceled) {
-		p.revents = 0;
-		if (ppoll(&p, 1, NULL, &sigs) > 0)
-			break;
-	}
-
-	printf("Disconnected\n");
-
-	close(fd);
-	return;
-
-release:
-	memset(&req, 0, sizeof(req));
-	req.dev_id = dev;
-	req.flags = (1 << RFCOMM_HANGUP_NOW);
-	ioctl(ctl, RFCOMMRELEASEDEV, &req);
-
-	close(sk);
-}
-
-static void cmd_listen(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
-{
-	struct sockaddr_rc laddr, raddr;
-	struct rfcomm_dev_req req;
-	struct termios ti;
-	struct sigaction sa;
-	struct pollfd p;
-	sigset_t sigs;
-	socklen_t alen;
-	char dst[18], devname[MAXPATHLEN];
-	int sk, nsk, fd, lm, try = 30;
-
-	laddr.rc_family = AF_BLUETOOTH;
-	bacpy(&laddr.rc_bdaddr, bdaddr);
-	laddr.rc_channel = (argc < 2) ? 1 : atoi(argv[1]);
-
-	sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
-	if (sk < 0) {
-		perror("Can't create RFCOMM socket");
-		return;
-	}
-
-	lm = 0;
-	if (master)
-		lm |= RFCOMM_LM_MASTER;
-	if (auth)
-		lm |= RFCOMM_LM_AUTH;
-	if (encryption)
-		lm |= RFCOMM_LM_ENCRYPT;
-	if (secure)
-		lm |= RFCOMM_LM_SECURE;
-
-	if (lm && setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm)) < 0) {
-		perror("Can't set RFCOMM link mode");
-		close(sk);
-		return;
-	}
-
-	if (bind(sk, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) {
-		perror("Can't bind RFCOMM socket");
-		close(sk);
-		return;
-	}
-
-	printf("Waiting for connection on channel %d\n", laddr.rc_channel);
-
-	listen(sk, 10);
-
-	alen = sizeof(raddr);
-	nsk = accept(sk, (struct sockaddr *) &raddr, &alen);
-
-	alen = sizeof(laddr);
-	if (getsockname(nsk, (struct sockaddr *)&laddr, &alen) < 0) {
-		perror("Can't get RFCOMM socket name");
-		close(nsk);
-		return;
-	}
-
-	if (linger) {
-		struct linger l = { .l_onoff = 1, .l_linger = linger };
-
-		if (setsockopt(nsk, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) < 0) {
-			perror("Can't set linger option");
-			close(nsk);
-			return;
-		}
-	}
-
-	memset(&req, 0, sizeof(req));
-	req.dev_id = dev;
-	req.flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP);
-
-	bacpy(&req.src, &laddr.rc_bdaddr);
-	bacpy(&req.dst, &raddr.rc_bdaddr);
-	req.channel = raddr.rc_channel;
-
-	dev = ioctl(nsk, RFCOMMCREATEDEV, &req);
-	if (dev < 0) {
-		perror("Can't create RFCOMM TTY");
-		close(sk);
-		return;
-	}
-
-	snprintf(devname, MAXPATHLEN - 1, "/dev/rfcomm%d", dev);
-	while ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
-		if (errno == EACCES) {
-			perror("Can't open RFCOMM device");
-			goto release;
-		}
-
-		snprintf(devname, MAXPATHLEN - 1, "/dev/bluetooth/rfcomm/%d", dev);
-		if ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
-			if (try--) {
-				snprintf(devname, MAXPATHLEN - 1, "/dev/rfcomm%d", dev);
-				usleep(100 * 1000);
-				continue;
-			}
-			perror("Can't open RFCOMM device");
-			goto release;
-		}
-	}
-
-	if (rfcomm_raw_tty) {
-		tcflush(fd, TCIOFLUSH);
-
-		cfmakeraw(&ti);
-		tcsetattr(fd, TCSANOW, &ti);
-	}
-
-	close(sk);
-	close(nsk);
-
-	ba2str(&req.dst, dst);
-	printf("Connection from %s to %s\n", dst, devname);
-	printf("Press CTRL-C for hangup\n");
-
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_flags   = SA_NOCLDSTOP;
-	sa.sa_handler = SIG_IGN;
-	sigaction(SIGCHLD, &sa, NULL);
-	sigaction(SIGPIPE, &sa, NULL);
-
-	sa.sa_handler = sig_term;
-	sigaction(SIGTERM, &sa, NULL);
-	sigaction(SIGINT,  &sa, NULL);
-
-	sa.sa_handler = sig_hup;
-	sigaction(SIGHUP, &sa, NULL);
-
-	sigfillset(&sigs);
-	sigdelset(&sigs, SIGCHLD);
-	sigdelset(&sigs, SIGPIPE);
-	sigdelset(&sigs, SIGTERM);
-	sigdelset(&sigs, SIGINT);
-	sigdelset(&sigs, SIGHUP);
-
-	p.fd = fd;
-	p.events = POLLERR | POLLHUP;
-
-	if (argc <= 2) {
-		while (!__io_canceled) {
-			p.revents = 0;
-			if (ppoll(&p, 1, NULL, &sigs) > 0)
-				break;
-		}
-	} else
-		run_cmdline(&p, &sigs, devname, argc - 2, argv + 2);
-
-	sa.sa_handler = NULL;
-	sigaction(SIGTERM, &sa, NULL);
-	sigaction(SIGINT,  &sa, NULL);
-
-	printf("Disconnected\n");
-
-	close(fd);
-	return;
-
-release:
-	memset(&req, 0, sizeof(req));
-	req.dev_id = dev;
-	req.flags = (1 << RFCOMM_HANGUP_NOW);
-	ioctl(ctl, RFCOMMRELEASEDEV, &req);
-
-	close(sk);
-}
-
-static void cmd_watch(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
-{
-	while (!__io_canceled) {
-		cmd_listen(ctl, dev, bdaddr, argc, argv);
-		usleep(10000);
-	}
-}
-
-static void cmd_create(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
-{
-	if (strcmp(argv[0], "all") == 0)
-		create_all(ctl);
-	else
-		create_dev(ctl, dev, 0, bdaddr, argc, argv);
-}
-
-static void cmd_release(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
-{
-	if (strcmp(argv[0], "all") == 0)
-		release_all(ctl);
-	else
-		release_dev(ctl, dev, 0);
-}
-
-static void cmd_show(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
-{
-	if (strcmp(argv[0], "all") == 0)
-		print_dev_list(ctl, 0);
-	else {
-		struct rfcomm_dev_info di = { id: atoi(argv[0]) };
-		if (ioctl(ctl, RFCOMMGETDEVINFO, &di) < 0) {
-			perror("Get info failed");
-			exit(1);
-		}
-
-		print_dev_info(&di);
-	}
-}
-
-struct {
-	char *cmd;
-	char *alt;
-	void (*func)(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv);
-	char *opt;
-	char *doc;
-} command[] = {
-	{ "bind",    "create", cmd_create,  "<dev> <bdaddr> [channel]", "Bind device"    },
-	{ "release", "unbind", cmd_release, "<dev>",                    "Release device" },
-	{ "show",    "info",   cmd_show,    "<dev>",                    "Show device"    },
-	{ "connect", "conn",   cmd_connect, "<dev> <bdaddr> [channel]", "Connect device" },
-	{ "listen",  "server", cmd_listen,  "<dev> [channel [cmd]]",    "Listen"         },
-	{ "watch",   "watch",  cmd_watch,   "<dev> [channel [cmd]]",    "Watch"          },
-	{ NULL, NULL, NULL, 0, 0 }
-};
-
-static void usage(void)
-{
-	int i;
-
-	printf("RFCOMM configuration utility ver %s\n", VERSION);
-
-	printf("Usage:\n"
-		"\trfcomm [options] <command> <dev>\n"
-		"\n");
-
-	printf("Options:\n"
-		"\t-i [hciX|bdaddr]      Local HCI device or BD Address\n"
-		"\t-h, --help            Display help\n"
-		"\t-r, --raw             Switch TTY into raw mode\n"
-		"\t-A, --auth            Enable authentication\n"
-		"\t-E, --encrypt         Enable encryption\n"
-		"\t-S, --secure          Secure connection\n"
-		"\t-M, --master          Become the master of a piconet\n"
-		"\t-f, --config [file]   Specify alternate config file\n"
-		"\t-a                    Show all devices (default)\n"
-		"\n");
-
-	printf("Commands:\n");
-	for (i = 0; command[i].cmd; i++)
-		printf("\t%-8s %-24s\t%s\n",
-			command[i].cmd,
-			command[i].opt ? command[i].opt : " ",
-			command[i].doc);
-	printf("\n");
-}
-
-static struct option main_options[] = {
-	{ "help",	0, 0, 'h' },
-	{ "device",	1, 0, 'i' },
-	{ "config",	1, 0, 'f' },
-	{ "raw",	0, 0, 'r' },
-	{ "auth",	0, 0, 'A' },
-	{ "encrypt",	0, 0, 'E' },
-	{ "secure",	0, 0, 'S' },
-	{ "master",	0, 0, 'M' },
-	{ "linger",	1, 0, 'L' },
-	{ 0, 0, 0, 0 }
-};
-
-int main(int argc, char *argv[])
-{
-	bdaddr_t bdaddr;
-	int i, opt, ctl, dev_id, show_all = 0;
-
-	bacpy(&bdaddr, BDADDR_ANY);
-
-	while ((opt = getopt_long(argc, argv, "+i:f:rahAESML:", main_options, NULL)) != -1) {
-		switch(opt) {
-		case 'i':
-			if (strncmp(optarg, "hci", 3) == 0)
-				hci_devba(atoi(optarg + 3), &bdaddr);
-			else
-				str2ba(optarg, &bdaddr);
-			break;
-
-		case 'f':
-			rfcomm_config_file = strdup(optarg);
-			break;
-
-		case 'r':
-			rfcomm_raw_tty = 1;
-			break;
-
-		case 'a':
-			show_all = 1;
-			break;
-
-		case 'h':
-			usage();
-			exit(0);
-
-		case 'A':
-			auth = 1;
-			break;
-
-		case 'E':
-			encryption = 1;
-			break;
-
-		case 'S':
-			secure = 1;
-			break;
-
-		case 'M':
-			master = 1;
-			break;
-
-		case 'L':
-			linger = atoi(optarg);
-			break;
-
-		default:
-			exit(0);
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	if (argc < 2) {
-		if (argc != 0) {
-			usage();
-			exit(1);
-		} else
-			show_all = 1;
-	}
-
-	ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM);
-	if (ctl < 0) {
-		perror("Can't open RFCOMM control socket");
-		exit(1);
-	}
-
-	if (show_all) {
-		print_dev_list(ctl, 0);
-		close(ctl);
-		exit(0);
-	}
-
-	if (strncmp(argv[1], "/dev/rfcomm", 11) == 0)
-		dev_id = atoi(argv[1] + 11);
-	else if (strncmp(argv[1], "rfcomm", 6) == 0)
-		dev_id = atoi(argv[1] + 6);
-	else
-		dev_id = atoi(argv[1]);
-
-	for (i = 0; command[i].cmd; i++) {
-		if (strncmp(command[i].cmd, argv[0], 4) && strncmp(command[i].alt, argv[0], 4))
-			continue;
-		argc--;
-		argv++;
-		command[i].func(ctl, dev_id, &bdaddr, argc, argv);
-		close(ctl);
-		exit(0);
-	}
-
-	usage();
-
-	close(ctl);
-
-	return 0;
-}
diff --git a/tools/rfcomm.c b/tools/rfcomm.c
new file mode 100644
index 0000000..6800445
--- /dev/null
+++ b/tools/rfcomm.c
@@ -0,0 +1,849 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <signal.h>
+#include <termios.h>
+#include <sys/poll.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+#include <bluetooth/rfcomm.h>
+
+#include "kword.h"
+
+#ifdef NEED_PPOLL
+#include "ppoll.h"
+#endif
+
+static char *rfcomm_config_file = NULL;
+static int rfcomm_raw_tty = 0;
+static int auth = 0;
+static int encryption = 0;
+static int secure = 0;
+static int master = 0;
+static int linger = 0;
+
+static char *rfcomm_state[] = {
+	"unknown",
+	"connected",
+	"clean",
+	"bound",
+	"listening",
+	"connecting",
+	"connecting",
+	"config",
+	"disconnecting",
+	"closed"
+};
+
+static volatile sig_atomic_t __io_canceled = 0;
+
+static void sig_hup(int sig)
+{
+	return;
+}
+
+static void sig_term(int sig)
+{
+	__io_canceled = 1;
+}
+
+static char *rfcomm_flagstostr(uint32_t flags)
+{
+	static char str[100];
+	str[0] = 0;
+
+	strcat(str, "[");
+
+	if (flags & (1 << RFCOMM_REUSE_DLC))
+		strcat(str, "reuse-dlc ");
+
+	if (flags & (1 << RFCOMM_RELEASE_ONHUP))
+		strcat(str, "release-on-hup ");
+
+	if (flags & (1 << RFCOMM_TTY_ATTACHED))
+		strcat(str, "tty-attached");
+
+	strcat(str, "]");
+	return str;
+}
+
+static void print_dev_info(struct rfcomm_dev_info *di)
+{
+	char src[18], dst[18], addr[40];
+
+	ba2str(&di->src, src); ba2str(&di->dst, dst);
+
+	if (bacmp(&di->src, BDADDR_ANY) == 0)
+		sprintf(addr, "%s", dst);
+	else
+		sprintf(addr, "%s -> %s", src, dst);
+
+	printf("rfcomm%d: %s channel %d %s %s\n",
+		di->id, addr, di->channel,
+		rfcomm_state[di->state],
+		di->flags ? rfcomm_flagstostr(di->flags) : "");
+}
+
+static void print_dev_list(int ctl, int flags)
+{
+	struct rfcomm_dev_list_req *dl;
+	struct rfcomm_dev_info *di;
+	int i;
+
+	dl = malloc(sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di));
+	if (!dl) {
+		perror("Can't allocate memory");
+		exit(1);
+	}
+
+	dl->dev_num = RFCOMM_MAX_DEV;
+	di = dl->dev_info;
+
+	if (ioctl(ctl, RFCOMMGETDEVLIST, (void *) dl) < 0) {
+		perror("Can't get device list");
+		free(dl);
+		exit(1);
+	}
+
+	for (i = 0; i < dl->dev_num; i++)
+		print_dev_info(di + i);
+	free(dl);
+}
+
+static int create_dev(int ctl, int dev, uint32_t flags, bdaddr_t *bdaddr, int argc, char **argv)
+{
+	struct rfcomm_dev_req req;
+	int err;
+
+	memset(&req, 0, sizeof(req));
+	req.dev_id = dev;
+	req.flags = flags;
+	bacpy(&req.src, bdaddr);
+
+	if (argc < 2) {
+		err = rfcomm_read_config(rfcomm_config_file);
+		if (err < 0) {
+			perror("Can't open RFCOMM config file");
+			return err;
+		}
+
+		bacpy(&req.dst, &rfcomm_opts[dev].bdaddr);
+		req.channel = rfcomm_opts[dev].channel;
+
+		if (bacmp(&req.dst, BDADDR_ANY) == 0) {
+			fprintf(stderr, "Can't find a config entry for rfcomm%d\n", dev);
+			return -EFAULT;
+		}
+	} else {
+		str2ba(argv[1], &req.dst);
+
+		if (argc > 2)
+			req.channel = atoi(argv[2]);
+		else
+			req.channel = 1;
+	}
+
+	err = ioctl(ctl, RFCOMMCREATEDEV, &req);
+	if (err == EOPNOTSUPP)
+		fprintf(stderr, "RFCOMM TTY support not available\n");
+	else if (err < 0)
+		perror("Can't create device");
+
+	return err;
+}
+
+static int create_all(int ctl)
+{
+	struct rfcomm_dev_req req;
+	int i, err;
+
+	err = rfcomm_read_config(rfcomm_config_file);
+	if (err < 0) {
+		perror("Can't open RFCOMM config file");
+		return err;
+	}
+
+	for (i = 0; i < RFCOMM_MAX_DEV; i++) {
+		if (!rfcomm_opts[i].bind)
+			continue;
+
+		memset(&req, 0, sizeof(req));
+		req.dev_id = i;
+		req.flags = 0;
+		bacpy(&req.src, BDADDR_ANY);
+		bacpy(&req.dst, &rfcomm_opts[i].bdaddr);
+		req.channel = rfcomm_opts[i].channel;
+
+		if (bacmp(&req.dst, BDADDR_ANY) != 0)
+			ioctl(ctl, RFCOMMCREATEDEV, &req);
+	}
+
+	return 0;
+}
+
+static int release_dev(int ctl, int dev, uint32_t flags)
+{
+	struct rfcomm_dev_req req;
+	int err;
+
+	memset(&req, 0, sizeof(req));
+	req.dev_id = dev;
+
+	err = ioctl(ctl, RFCOMMRELEASEDEV, &req);
+	if (err < 0)
+		perror("Can't release device");
+
+	return err;
+}
+
+static int release_all(int ctl)
+{
+	struct rfcomm_dev_list_req *dl;
+	struct rfcomm_dev_info *di;
+	int i;
+
+	dl = malloc(sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di));
+	if (!dl) {
+		perror("Can't allocate memory");
+		exit(1);
+	}
+
+	dl->dev_num = RFCOMM_MAX_DEV;
+	di = dl->dev_info;
+
+	if (ioctl(ctl, RFCOMMGETDEVLIST, (void *) dl) < 0) {
+		perror("Can't get device list");
+		free(dl);
+		exit(1);
+	}
+
+	for (i = 0; i < dl->dev_num; i++)
+		release_dev(ctl, (di + i)->id, 0);
+
+	free(dl);
+	return 0;
+}
+
+static void run_cmdline(struct pollfd *p, sigset_t* sigs, char *devname,
+			int argc, char **argv)
+{
+	int i;
+	pid_t pid;
+	char **cmdargv;
+
+	cmdargv = malloc((argc + 1) * sizeof(char*));
+	if (!cmdargv)
+		return;
+
+	for (i = 0; i < argc; i++)
+		cmdargv[i] = (strcmp(argv[i], "{}") == 0) ? devname : argv[i];
+	cmdargv[i] = NULL;
+
+	pid = fork();
+
+	switch (pid) {
+	case 0:
+		i = execvp(cmdargv[0], cmdargv);
+		fprintf(stderr, "Couldn't execute command %s (errno=%d:%s)\n",
+				cmdargv[0], errno, strerror(errno));
+		break;
+	case -1:
+		fprintf(stderr, "Couldn't fork to execute command %s\n",
+				cmdargv[0]);
+		break;
+	default:
+		while (1) {
+			int status;
+			pid_t child;
+			struct timespec ts;
+
+			child = waitpid(-1, &status, WNOHANG);
+			if (child == pid || (child < 0 && errno != EAGAIN))
+				break;
+
+			p->revents = 0;
+			ts.tv_sec  = 0;
+			ts.tv_nsec = 200;
+			if (ppoll(p, 1, &ts, sigs) || __io_canceled) {
+				kill(pid, SIGTERM);
+				waitpid(pid, &status, 0);
+				break;
+			}
+		}
+		break;
+	}
+
+	free(cmdargv);
+}
+
+static void cmd_connect(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
+{
+	struct sockaddr_rc laddr, raddr;
+	struct rfcomm_dev_req req;
+	struct termios ti;
+	struct sigaction sa;
+	struct pollfd p;
+	sigset_t sigs;
+	socklen_t alen;
+	char dst[18], devname[MAXPATHLEN];
+	int sk, fd, try = 30;
+
+	laddr.rc_family = AF_BLUETOOTH;
+	bacpy(&laddr.rc_bdaddr, bdaddr);
+	laddr.rc_channel = 0;
+
+	if (argc < 2) {
+		if (rfcomm_read_config(rfcomm_config_file) < 0) {
+			perror("Can't open RFCOMM config file");
+			return;
+		}
+
+		raddr.rc_family = AF_BLUETOOTH;
+		bacpy(&raddr.rc_bdaddr, &rfcomm_opts[dev].bdaddr);
+		raddr.rc_channel = rfcomm_opts[dev].channel;
+
+		if (bacmp(&raddr.rc_bdaddr, BDADDR_ANY) == 0) {
+			fprintf(stderr, "Can't find a config entry for rfcomm%d\n", dev);
+			return;
+		}
+	} else {
+		raddr.rc_family = AF_BLUETOOTH;
+		str2ba(argv[1], &raddr.rc_bdaddr);
+
+		if (argc > 2)
+			raddr.rc_channel = atoi(argv[2]);
+		else
+			raddr.rc_channel = 1;
+	}
+
+	sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+	if (sk < 0) {
+		perror("Can't create RFCOMM socket");
+		return;
+	}
+
+	if (linger) {
+		struct linger l = { .l_onoff = 1, .l_linger = linger };
+
+		if (setsockopt(sk, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) < 0) {
+			perror("Can't set linger option");
+			return;
+		}
+	}
+
+	if (bind(sk, (struct sockaddr *) &laddr, sizeof(laddr)) < 0) {
+		perror("Can't bind RFCOMM socket");
+		close(sk);
+		return;
+	}
+
+	if (connect(sk, (struct sockaddr *) &raddr, sizeof(raddr)) < 0) {
+		perror("Can't connect RFCOMM socket");
+		close(sk);
+		return;
+	}
+
+	alen = sizeof(laddr);
+	if (getsockname(sk, (struct sockaddr *)&laddr, &alen) < 0) {
+		perror("Can't get RFCOMM socket name");
+		close(sk);
+		return;
+	}
+
+	memset(&req, 0, sizeof(req));
+	req.dev_id = dev;
+	req.flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP);
+
+	bacpy(&req.src, &laddr.rc_bdaddr);
+	bacpy(&req.dst, &raddr.rc_bdaddr);
+	req.channel = raddr.rc_channel;
+
+	dev = ioctl(sk, RFCOMMCREATEDEV, &req);
+	if (dev < 0) {
+		perror("Can't create RFCOMM TTY");
+		close(sk);
+		return;
+	}
+
+	snprintf(devname, MAXPATHLEN - 1, "/dev/rfcomm%d", dev);
+	while ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
+		if (errno == EACCES) {
+			perror("Can't open RFCOMM device");
+			goto release;
+		}
+
+		snprintf(devname, MAXPATHLEN - 1, "/dev/bluetooth/rfcomm/%d", dev);
+		if ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
+			if (try--) {
+				snprintf(devname, MAXPATHLEN - 1, "/dev/rfcomm%d", dev);
+				usleep(100 * 1000);
+				continue;
+			}
+			perror("Can't open RFCOMM device");
+			goto release;
+		}
+	}
+
+	if (rfcomm_raw_tty) {
+		tcflush(fd, TCIOFLUSH);
+
+		cfmakeraw(&ti);
+		tcsetattr(fd, TCSANOW, &ti);
+	}
+
+	close(sk);
+
+	ba2str(&req.dst, dst);
+	printf("Connected %s to %s on channel %d\n", devname, dst, req.channel);
+	printf("Press CTRL-C for hangup\n");
+
+	memset(&sa, 0, sizeof(sa));
+	sa.sa_flags   = SA_NOCLDSTOP;
+	sa.sa_handler = SIG_IGN;
+	sigaction(SIGCHLD, &sa, NULL);
+	sigaction(SIGPIPE, &sa, NULL);
+
+	sa.sa_handler = sig_term;
+	sigaction(SIGTERM, &sa, NULL);
+	sigaction(SIGINT,  &sa, NULL);
+
+	sa.sa_handler = sig_hup;
+	sigaction(SIGHUP, &sa, NULL);
+
+	sigfillset(&sigs);
+	sigdelset(&sigs, SIGCHLD);
+	sigdelset(&sigs, SIGPIPE);
+	sigdelset(&sigs, SIGTERM);
+	sigdelset(&sigs, SIGINT);
+	sigdelset(&sigs, SIGHUP);
+
+	p.fd = fd;
+	p.events = POLLERR | POLLHUP;
+
+	while (!__io_canceled) {
+		p.revents = 0;
+		if (ppoll(&p, 1, NULL, &sigs) > 0)
+			break;
+	}
+
+	printf("Disconnected\n");
+
+	close(fd);
+	return;
+
+release:
+	memset(&req, 0, sizeof(req));
+	req.dev_id = dev;
+	req.flags = (1 << RFCOMM_HANGUP_NOW);
+	ioctl(ctl, RFCOMMRELEASEDEV, &req);
+
+	close(sk);
+}
+
+static void cmd_listen(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
+{
+	struct sockaddr_rc laddr, raddr;
+	struct rfcomm_dev_req req;
+	struct termios ti;
+	struct sigaction sa;
+	struct pollfd p;
+	sigset_t sigs;
+	socklen_t alen;
+	char dst[18], devname[MAXPATHLEN];
+	int sk, nsk, fd, lm, try = 30;
+
+	laddr.rc_family = AF_BLUETOOTH;
+	bacpy(&laddr.rc_bdaddr, bdaddr);
+	laddr.rc_channel = (argc < 2) ? 1 : atoi(argv[1]);
+
+	sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+	if (sk < 0) {
+		perror("Can't create RFCOMM socket");
+		return;
+	}
+
+	lm = 0;
+	if (master)
+		lm |= RFCOMM_LM_MASTER;
+	if (auth)
+		lm |= RFCOMM_LM_AUTH;
+	if (encryption)
+		lm |= RFCOMM_LM_ENCRYPT;
+	if (secure)
+		lm |= RFCOMM_LM_SECURE;
+
+	if (lm && setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm)) < 0) {
+		perror("Can't set RFCOMM link mode");
+		close(sk);
+		return;
+	}
+
+	if (bind(sk, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) {
+		perror("Can't bind RFCOMM socket");
+		close(sk);
+		return;
+	}
+
+	printf("Waiting for connection on channel %d\n", laddr.rc_channel);
+
+	listen(sk, 10);
+
+	alen = sizeof(raddr);
+	nsk = accept(sk, (struct sockaddr *) &raddr, &alen);
+
+	alen = sizeof(laddr);
+	if (getsockname(nsk, (struct sockaddr *)&laddr, &alen) < 0) {
+		perror("Can't get RFCOMM socket name");
+		close(nsk);
+		return;
+	}
+
+	if (linger) {
+		struct linger l = { .l_onoff = 1, .l_linger = linger };
+
+		if (setsockopt(nsk, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) < 0) {
+			perror("Can't set linger option");
+			close(nsk);
+			return;
+		}
+	}
+
+	memset(&req, 0, sizeof(req));
+	req.dev_id = dev;
+	req.flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP);
+
+	bacpy(&req.src, &laddr.rc_bdaddr);
+	bacpy(&req.dst, &raddr.rc_bdaddr);
+	req.channel = raddr.rc_channel;
+
+	dev = ioctl(nsk, RFCOMMCREATEDEV, &req);
+	if (dev < 0) {
+		perror("Can't create RFCOMM TTY");
+		close(sk);
+		return;
+	}
+
+	snprintf(devname, MAXPATHLEN - 1, "/dev/rfcomm%d", dev);
+	while ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
+		if (errno == EACCES) {
+			perror("Can't open RFCOMM device");
+			goto release;
+		}
+
+		snprintf(devname, MAXPATHLEN - 1, "/dev/bluetooth/rfcomm/%d", dev);
+		if ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
+			if (try--) {
+				snprintf(devname, MAXPATHLEN - 1, "/dev/rfcomm%d", dev);
+				usleep(100 * 1000);
+				continue;
+			}
+			perror("Can't open RFCOMM device");
+			goto release;
+		}
+	}
+
+	if (rfcomm_raw_tty) {
+		tcflush(fd, TCIOFLUSH);
+
+		cfmakeraw(&ti);
+		tcsetattr(fd, TCSANOW, &ti);
+	}
+
+	close(sk);
+	close(nsk);
+
+	ba2str(&req.dst, dst);
+	printf("Connection from %s to %s\n", dst, devname);
+	printf("Press CTRL-C for hangup\n");
+
+	memset(&sa, 0, sizeof(sa));
+	sa.sa_flags   = SA_NOCLDSTOP;
+	sa.sa_handler = SIG_IGN;
+	sigaction(SIGCHLD, &sa, NULL);
+	sigaction(SIGPIPE, &sa, NULL);
+
+	sa.sa_handler = sig_term;
+	sigaction(SIGTERM, &sa, NULL);
+	sigaction(SIGINT,  &sa, NULL);
+
+	sa.sa_handler = sig_hup;
+	sigaction(SIGHUP, &sa, NULL);
+
+	sigfillset(&sigs);
+	sigdelset(&sigs, SIGCHLD);
+	sigdelset(&sigs, SIGPIPE);
+	sigdelset(&sigs, SIGTERM);
+	sigdelset(&sigs, SIGINT);
+	sigdelset(&sigs, SIGHUP);
+
+	p.fd = fd;
+	p.events = POLLERR | POLLHUP;
+
+	if (argc <= 2) {
+		while (!__io_canceled) {
+			p.revents = 0;
+			if (ppoll(&p, 1, NULL, &sigs) > 0)
+				break;
+		}
+	} else
+		run_cmdline(&p, &sigs, devname, argc - 2, argv + 2);
+
+	sa.sa_handler = NULL;
+	sigaction(SIGTERM, &sa, NULL);
+	sigaction(SIGINT,  &sa, NULL);
+
+	printf("Disconnected\n");
+
+	close(fd);
+	return;
+
+release:
+	memset(&req, 0, sizeof(req));
+	req.dev_id = dev;
+	req.flags = (1 << RFCOMM_HANGUP_NOW);
+	ioctl(ctl, RFCOMMRELEASEDEV, &req);
+
+	close(sk);
+}
+
+static void cmd_watch(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
+{
+	while (!__io_canceled) {
+		cmd_listen(ctl, dev, bdaddr, argc, argv);
+		usleep(10000);
+	}
+}
+
+static void cmd_create(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
+{
+	if (strcmp(argv[0], "all") == 0)
+		create_all(ctl);
+	else
+		create_dev(ctl, dev, 0, bdaddr, argc, argv);
+}
+
+static void cmd_release(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
+{
+	if (strcmp(argv[0], "all") == 0)
+		release_all(ctl);
+	else
+		release_dev(ctl, dev, 0);
+}
+
+static void cmd_show(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
+{
+	if (strcmp(argv[0], "all") == 0)
+		print_dev_list(ctl, 0);
+	else {
+		struct rfcomm_dev_info di = { id: atoi(argv[0]) };
+		if (ioctl(ctl, RFCOMMGETDEVINFO, &di) < 0) {
+			perror("Get info failed");
+			exit(1);
+		}
+
+		print_dev_info(&di);
+	}
+}
+
+struct {
+	char *cmd;
+	char *alt;
+	void (*func)(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv);
+	char *opt;
+	char *doc;
+} command[] = {
+	{ "bind",    "create", cmd_create,  "<dev> <bdaddr> [channel]", "Bind device"    },
+	{ "release", "unbind", cmd_release, "<dev>",                    "Release device" },
+	{ "show",    "info",   cmd_show,    "<dev>",                    "Show device"    },
+	{ "connect", "conn",   cmd_connect, "<dev> <bdaddr> [channel]", "Connect device" },
+	{ "listen",  "server", cmd_listen,  "<dev> [channel [cmd]]",    "Listen"         },
+	{ "watch",   "watch",  cmd_watch,   "<dev> [channel [cmd]]",    "Watch"          },
+	{ NULL, NULL, NULL, 0, 0 }
+};
+
+static void usage(void)
+{
+	int i;
+
+	printf("RFCOMM configuration utility ver %s\n", VERSION);
+
+	printf("Usage:\n"
+		"\trfcomm [options] <command> <dev>\n"
+		"\n");
+
+	printf("Options:\n"
+		"\t-i [hciX|bdaddr]      Local HCI device or BD Address\n"
+		"\t-h, --help            Display help\n"
+		"\t-r, --raw             Switch TTY into raw mode\n"
+		"\t-A, --auth            Enable authentication\n"
+		"\t-E, --encrypt         Enable encryption\n"
+		"\t-S, --secure          Secure connection\n"
+		"\t-M, --master          Become the master of a piconet\n"
+		"\t-f, --config [file]   Specify alternate config file\n"
+		"\t-a                    Show all devices (default)\n"
+		"\n");
+
+	printf("Commands:\n");
+	for (i = 0; command[i].cmd; i++)
+		printf("\t%-8s %-24s\t%s\n",
+			command[i].cmd,
+			command[i].opt ? command[i].opt : " ",
+			command[i].doc);
+	printf("\n");
+}
+
+static struct option main_options[] = {
+	{ "help",	0, 0, 'h' },
+	{ "device",	1, 0, 'i' },
+	{ "config",	1, 0, 'f' },
+	{ "raw",	0, 0, 'r' },
+	{ "auth",	0, 0, 'A' },
+	{ "encrypt",	0, 0, 'E' },
+	{ "secure",	0, 0, 'S' },
+	{ "master",	0, 0, 'M' },
+	{ "linger",	1, 0, 'L' },
+	{ 0, 0, 0, 0 }
+};
+
+int main(int argc, char *argv[])
+{
+	bdaddr_t bdaddr;
+	int i, opt, ctl, dev_id, show_all = 0;
+
+	bacpy(&bdaddr, BDADDR_ANY);
+
+	while ((opt = getopt_long(argc, argv, "+i:f:rahAESML:", main_options, NULL)) != -1) {
+		switch(opt) {
+		case 'i':
+			if (strncmp(optarg, "hci", 3) == 0)
+				hci_devba(atoi(optarg + 3), &bdaddr);
+			else
+				str2ba(optarg, &bdaddr);
+			break;
+
+		case 'f':
+			rfcomm_config_file = strdup(optarg);
+			break;
+
+		case 'r':
+			rfcomm_raw_tty = 1;
+			break;
+
+		case 'a':
+			show_all = 1;
+			break;
+
+		case 'h':
+			usage();
+			exit(0);
+
+		case 'A':
+			auth = 1;
+			break;
+
+		case 'E':
+			encryption = 1;
+			break;
+
+		case 'S':
+			secure = 1;
+			break;
+
+		case 'M':
+			master = 1;
+			break;
+
+		case 'L':
+			linger = atoi(optarg);
+			break;
+
+		default:
+			exit(0);
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+	optind = 0;
+
+	if (argc < 2) {
+		if (argc != 0) {
+			usage();
+			exit(1);
+		} else
+			show_all = 1;
+	}
+
+	ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM);
+	if (ctl < 0) {
+		perror("Can't open RFCOMM control socket");
+		exit(1);
+	}
+
+	if (show_all) {
+		print_dev_list(ctl, 0);
+		close(ctl);
+		exit(0);
+	}
+
+	if (strncmp(argv[1], "/dev/rfcomm", 11) == 0)
+		dev_id = atoi(argv[1] + 11);
+	else if (strncmp(argv[1], "rfcomm", 6) == 0)
+		dev_id = atoi(argv[1] + 6);
+	else
+		dev_id = atoi(argv[1]);
+
+	for (i = 0; command[i].cmd; i++) {
+		if (strncmp(command[i].cmd, argv[0], 4) && strncmp(command[i].alt, argv[0], 4))
+			continue;
+		argc--;
+		argv++;
+		command[i].func(ctl, dev_id, &bdaddr, argc, argv);
+		close(ctl);
+		exit(0);
+	}
+
+	usage();
+
+	close(ctl);
+
+	return 0;
+}
-- 
1.7.4.rc3


^ permalink raw reply related

* [PATCH] Fix invalid read after list concatenation
From: Bruna Moreira @ 2011-02-03 18:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Bruna Moreira

g_slist_concat uses the items from second list directly so they should
not be freed.
---
 attrib/gatt.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/attrib/gatt.c b/attrib/gatt.c
index f3b513e..20bb96f 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -121,7 +121,6 @@ static void primary_by_uuid_cb(guint8 status, const guint8 *ipdu,
 	dp->primaries = g_slist_concat(dp->primaries, ranges);
 
 	last = g_slist_last(ranges);
-	g_slist_free(ranges);
 	range = last->data;
 
 	if (range->end == 0xffff)
-- 
1.7.0.4


^ permalink raw reply related

* Re: [PATCH] linux-firmware: Remove ath3k-2.fw
From: Luis R. Rodriguez @ 2011-02-03 17:46 UTC (permalink / raw)
  To: Shanmugamkamatchi Balashanmugam
  Cc: David Woodhouse, linux-bluetooth@vger.kernel.org, Luis Rodriguez
In-Reply-To: <4D4A60E1.3080000@atheros.com>

On Thu, Feb 03, 2011 at 12:01:37AM -0800, Shanmugamkamatchi Balashanmugam wrote:
> On 2/3/2011 1:13 PM, David Woodhouse wrote:
> > On Fri, 2011-01-28 at 15:03 +0530, Bala Shanmugam wrote:
> >> ath3k-2.fw is obsolete and not use by Atheros chipsets
> >> anymore.
> > Are you telling me that there is no extant hardware, and no old kernels,
> > which would use this? It was added to the linux-firmware tree and
> > *never* used?
> >
> Yes David, no older kernel uses this firmware.
> We thought to have new firmware file for newer versions but
> our driver patch was not accepted and we decided to
> have single firmware for this chipset [ath3k-1.fw].
> 

To be clear, the patch for upstream to use that firmware was submitted IIRC but
never merged upstream... you merged the firmware first. By the time it came
time to push it again, I had asked WTF was in it, and asked for the patch to
get merged, but it was made clear by our team the APIs never changed so Marcel
suggested we just replace the firmware in linux-firmware instead of adding a
new firmware and patching the driver.

Apologies for any trouble.

  Luis

^ permalink raw reply

* [PATCH] Fix parameter type in att_put_u32
From: Elvis Pfützenreuter @ 2011-02-03 13:37 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: epx

---
 attrib/att.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/attrib/att.h b/attrib/att.h
index 1caa62a..7e81dc4 100644
--- a/attrib/att.h
+++ b/attrib/att.h
@@ -180,7 +180,7 @@ static inline void att_put_u16(uint16_t src, void *dst)
 	bt_put_unaligned(htobs(src), (uint16_t *) dst);
 }
 
-static inline void att_put_u32(uint16_t src, void *dst)
+static inline void att_put_u32(uint32_t src, void *dst)
 {
 	bt_put_unaligned(htobl(src), (uint32_t *) dst);
 }
-- 
1.7.1


^ permalink raw reply related

* Re: [PATCH 1/3 v4] Add libtracker-sparql to obexd dependencies
From: Johan Hedberg @ 2011-02-03 10:57 UTC (permalink / raw)
  To: Radoslaw Jablonski; +Cc: linux-bluetooth
In-Reply-To: <1296726203-22613-1-git-send-email-ext-jablonski.radoslaw@nokia.com>

Hi Radek,

On Thu, Feb 03, 2011, Radoslaw Jablonski wrote:
> In PBAP tracker is used only for reading and returns rather big
> parts of data, so using direct access libtracker-sparql is better
> solution than tracker D-Bus API(libtracker-sparql in most PBAP
> scenarios should be faster).
> ---
>  Makefile.am  |    4 +++-
>  configure.ac |    7 +++++++
>  2 files changed, 10 insertions(+), 1 deletions(-)

All three patches have been pushed upstream. Thanks.

Johan

^ permalink raw reply

* [PATCH 3/3 v4] Use libtracker-sparql in PBAP
From: Radoslaw Jablonski @ 2011-02-03  9:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Radoslaw Jablonski
In-Reply-To: <1296726203-22613-1-git-send-email-ext-jablonski.radoslaw@nokia.com>

Now direct tracker connection for transporting retrieved
parts of data is used, instead of D-Bus. This should result better
performance for PBAP requests.
Each part of results is now fetched from tracker asynchronously
and getting more results can be stopped in any moment -
GCancellable stored in phonebook_data is used for that purpose.
If processing of data has finished (or it was cancelled) then cleanup
of pending_reply is done in last invocation of
async_query_cursor_next_cb.
---
 plugins/phonebook-tracker.c |  262 ++++++++++++++++++++++---------------------
 1 files changed, 135 insertions(+), 127 deletions(-)

diff --git a/plugins/phonebook-tracker.c b/plugins/phonebook-tracker.c
index 3b61d6b..214961d 100644
--- a/plugins/phonebook-tracker.c
+++ b/plugins/phonebook-tracker.c
@@ -29,6 +29,7 @@
 #include <dbus/dbus.h>
 #include <openobex/obex.h>
 #include <openobex/obex_const.h>
+#include <libtracker-sparql/tracker-sparql.h>
 
 #include "log.h"
 #include "obex.h"
@@ -891,7 +892,7 @@
 	"} GROUP BY ?call ORDER BY DESC(nmo:receivedDate(?call)) "	\
 	"LIMIT 40"
 
-typedef void (*reply_list_foreach_t) (char **reply, int num_fields,
+typedef void (*reply_list_foreach_t) (const char **reply, int num_fields,
 							void *user_data);
 
 typedef void (*add_field_t) (struct phonebook_contact *contact,
@@ -918,7 +919,7 @@ struct phonebook_data {
 	phonebook_cache_ready_cb ready_cb;
 	phonebook_entry_cb entry_cb;
 	int newmissedcalls;
-	DBusPendingCall *call;
+	GCancellable *query_canc;
 };
 
 struct phonebook_index {
@@ -926,7 +927,7 @@ struct phonebook_index {
 	int index;
 };
 
-static DBusConnection *connection = NULL;
+static TrackerSparqlConnection *connection = NULL;
 
 static const char *name2query(const char *name)
 {
@@ -999,131 +1000,124 @@ static const char *folder2query(const char *folder)
 	return NULL;
 }
 
-static char **string_array_from_iter(DBusMessageIter iter, int array_len)
+static const char **string_array_from_cursor(TrackerSparqlCursor *cursor,
+								int array_len)
 {
-	DBusMessageIter sub;
-	char **result;
+	const char **result;
 	int i;
 
-	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
-		return NULL;
-
-	result = g_new0(char *, array_len);
+	result = g_new0(const char *, array_len);
 
-	dbus_message_iter_recurse(&iter, &sub);
+	for (i = 0; i < array_len; ++i) {
+		TrackerSparqlValueType type;
 
-	i = 0;
-	while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-		char *arg;
-
-		if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
-			g_free(result);
-			return NULL;
-		}
+		type = tracker_sparql_cursor_get_value_type(cursor, i);
 
-		dbus_message_iter_get_basic(&sub, &arg);
-
-		result[i] = arg;
-
-		i++;
-		dbus_message_iter_next(&sub);
+		if (type == TRACKER_SPARQL_VALUE_TYPE_BLANK_NODE ||
+				type == TRACKER_SPARQL_VALUE_TYPE_UNBOUND)
+			/* For null/unbound type filling result part with ""*/
+			result[i] = "";
+		else
+			/* Filling with string representation of content*/
+			result[i] = tracker_sparql_cursor_get_string(cursor, i,
+									NULL);
 	}
 
 	return result;
 }
 
-static void query_reply(DBusPendingCall *call, void *user_data)
+static void update_cancellable(struct phonebook_data *pdata,
+							GCancellable *canc)
 {
-	DBusMessage *reply = dbus_pending_call_steal_reply(call);
-	struct pending_reply *pending = user_data;
-	DBusMessageIter iter, element;
-	DBusError derr;
-	int err;
-
-	dbus_error_init(&derr);
-	if (dbus_set_error_from_message(&derr, reply)) {
-		error("Replied with an error: %s, %s", derr.name,
-							derr.message);
-		dbus_error_free(&derr);
-
-		err = -1;
-		goto done;
-	}
-
-	dbus_message_iter_init(reply, &iter);
-
-	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
-		error("SparqlQuery reply is not an array");
+	if (pdata->query_canc)
+		g_object_unref(pdata->query_canc);
 
-		err = -1;
-		goto done;
-	}
-
-	dbus_message_iter_recurse(&iter, &element);
-
-	err = 0;
-
-	while (dbus_message_iter_get_arg_type(&element) != DBUS_TYPE_INVALID) {
-		char **node;
-
-		if (dbus_message_iter_get_arg_type(&element) !=
-						DBUS_TYPE_ARRAY) {
-			error("element is not an array");
-			goto done;
-		}
-
-		node = string_array_from_iter(element, pending->num_fields);
-		pending->callback(node, pending->num_fields,
-							pending->user_data);
+	pdata->query_canc = canc;
+}
 
-		g_free(node);
+static void async_query_cursor_next_cb(GObject *source, GAsyncResult *result,
+							gpointer user_data)
+{
+	struct pending_reply *pending = user_data;
+	TrackerSparqlCursor *cursor = TRACKER_SPARQL_CURSOR(source);
+	GCancellable *cancellable;
+	GError *error = NULL;
+	gboolean success;
+	const char **node;
+
+	success = tracker_sparql_cursor_next_finish(
+						TRACKER_SPARQL_CURSOR(source),
+						result, &error);
+
+	if (!success) {
+		if (error) {
+			DBG("cursor_next error: %s", error->message);
+			g_error_free(error);
+		} else
+			/* When tracker_sparql_cursor_next_finish ends with
+			 * failure and no error is set, that means end of
+			 * results returned by query */
+			pending->callback(NULL, 0, pending->user_data);
 
-		dbus_message_iter_next(&element);
+		goto failed;
 	}
 
-done:
-	/* This is the last entry */
-	pending->callback(NULL, err, pending->user_data);
+	node = string_array_from_cursor(cursor, pending->num_fields);
+	pending->callback(node, pending->num_fields, pending->user_data);
+	g_free(node);
 
-	dbus_message_unref(reply);
 
-	/* pending data is freed in query_free_data after call is unreffed. */
-}
-
-static void query_free_data(void *user_data)
-{
-	struct pending_reply *pending = user_data;
-
-	if (!pending)
-		return;
+	/* getting next row from query results */
+	cancellable = g_cancellable_new();
+	update_cancellable(pending->user_data, cancellable);
+	tracker_sparql_cursor_next_async(cursor, cancellable,
+						async_query_cursor_next_cb,
+						pending);
+	return;
 
+failed:
+	g_object_unref(cursor);
 	g_free(pending);
 }
 
-static DBusPendingCall *query_tracker(const char *query, int num_fields,
-		reply_list_foreach_t callback, void *user_data, int *err)
+static void query_tracker(const char *query, int num_fields,
+				reply_list_foreach_t callback, void *user_data,
+				int *err)
 {
 	struct pending_reply *pending;
-	DBusPendingCall *call;
-	DBusMessage *msg;
+	GCancellable *cancellable;
+	TrackerSparqlCursor *cursor;
+	GError *error = NULL;
+
+	DBG("");
 
 	if (connection == NULL)
-		connection = obex_dbus_get_connection();
+		connection = tracker_sparql_connection_get_direct(
+								NULL, &error);
 
-	msg = dbus_message_new_method_call(TRACKER_SERVICE,
-			TRACKER_RESOURCES_PATH, TRACKER_RESOURCES_INTERFACE,
-								"SparqlQuery");
+	if (!connection) {
+		if (error) {
+			DBG("direct-connection error: %s", error->message);
+			g_error_free(error);
+		}
 
-	dbus_message_append_args(msg, DBUS_TYPE_STRING, &query,
-						DBUS_TYPE_INVALID);
+		goto failed;
+	}
 
-	if (dbus_connection_send_with_reply(connection, msg, &call,
-							-1) == FALSE) {
-		error("Could not send dbus message");
-		dbus_message_unref(msg);
-		if (err)
-			*err = -EPERM;
-		return NULL;
+	cancellable = g_cancellable_new();
+	update_cancellable(user_data, cancellable);
+	cursor = tracker_sparql_connection_query(connection, query,
+							cancellable, &error);
+
+	if (cursor == NULL) {
+		if (error) {
+			DBG("connection_query error: %s", error->message);
+			g_error_free(error);
+		}
+
+		g_object_unref(cancellable);
+
+		goto failed;
 	}
 
 	pending = g_new0(struct pending_reply, 1);
@@ -1131,14 +1125,21 @@ static DBusPendingCall *query_tracker(const char *query, int num_fields,
 	pending->user_data = user_data;
 	pending->num_fields = num_fields;
 
-	dbus_pending_call_set_notify(call, query_reply, pending,
-							query_free_data);
-	dbus_message_unref(msg);
+	/* Now asynchronously going through each row of results - callback
+	 * async_query_cursor_next_cb will be called ALWAYS, even if async
+	 * request was canceled */
+	tracker_sparql_cursor_next_async(cursor, cancellable,
+						async_query_cursor_next_cb,
+						pending);
 
 	if (err)
 		*err = 0;
 
-	return call;
+	return;
+
+failed:
+	if (err)
+		*err = -EPERM;
 }
 
 static char *iso8601_utc_to_localtime(const char *datetime)
@@ -1331,7 +1332,8 @@ static GString *gen_vcards(GSList *contacts,
 	return vcards;
 }
 
-static void pull_contacts_size(char **reply, int num_fields, void *user_data)
+static void pull_contacts_size(const char **reply, int num_fields,
+							void *user_data)
 {
 	struct phonebook_data *data = user_data;
 
@@ -1363,7 +1365,8 @@ static void add_affiliation(char **field, const char *value)
 	*field = g_strdup(value);
 }
 
-static void contact_init(struct phonebook_contact *contact, char **reply)
+static void contact_init(struct phonebook_contact *contact,
+							const char **reply)
 {
 
 	contact->fullname = g_strdup(reply[COL_FULL_NAME]);
@@ -1395,8 +1398,8 @@ static enum phonebook_number_type get_phone_type(const char *affilation)
 	return TEL_TYPE_OTHER;
 }
 
-static void add_aff_number(struct phonebook_contact *contact, char *pnumber,
-								char *aff_type)
+static void add_aff_number(struct phonebook_contact *contact,
+				const char *pnumber, const char *aff_type)
 {
 	char **num_parts;
 	char *type, *number;
@@ -1433,7 +1436,7 @@ failed:
 }
 
 static void contact_add_numbers(struct phonebook_contact *contact,
-								char **reply)
+							const char **reply)
 {
 	char **aff_numbers;
 	int i;
@@ -1459,8 +1462,8 @@ static enum phonebook_field_type get_field_type(const char *affilation)
 	return FIELD_TYPE_OTHER;
 }
 
-static void add_aff_field(struct phonebook_contact *contact, char *aff_email,
-						add_field_t add_field_cb)
+static void add_aff_field(struct phonebook_contact *contact,
+			const char *aff_email, add_field_t add_field_cb)
 {
 	char **email_parts;
 	char *type, *email;
@@ -1490,7 +1493,7 @@ failed:
 }
 
 static void contact_add_emails(struct phonebook_contact *contact,
-								char **reply)
+							const char **reply)
 {
 	char **aff_emails;
 	int i;
@@ -1506,7 +1509,7 @@ static void contact_add_emails(struct phonebook_contact *contact,
 }
 
 static void contact_add_addresses(struct phonebook_contact *contact,
-								char **reply)
+							const char **reply)
 {
 	char **aff_addr;
 	int i;
@@ -1522,7 +1525,8 @@ static void contact_add_addresses(struct phonebook_contact *contact,
 	g_strfreev(aff_addr);
 }
 
-static void contact_add_urls(struct phonebook_contact *contact, char **reply)
+static void contact_add_urls(struct phonebook_contact *contact,
+							const char **reply)
 {
 	char **aff_url;
 	int i;
@@ -1538,7 +1542,7 @@ static void contact_add_urls(struct phonebook_contact *contact, char **reply)
 }
 
 static void contact_add_organization(struct phonebook_contact *contact,
-								char **reply)
+							const char **reply)
 {
 	/* Adding fields connected by nco:hasAffiliation - they may be in
 	 * separate replies */
@@ -1548,7 +1552,7 @@ static void contact_add_organization(struct phonebook_contact *contact,
 	add_affiliation(&contact->role, reply[COL_ORG_ROLE]);
 }
 
-static void pull_contacts(char **reply, int num_fields, void *user_data)
+static void pull_contacts(const char **reply, int num_fields, void *user_data)
 {
 	struct phonebook_data *data = user_data;
 	const struct apparam_field *params = data->params;
@@ -1649,7 +1653,7 @@ fail:
 	 */
 }
 
-static void add_to_cache(char **reply, int num_fields, void *user_data)
+static void add_to_cache(const char **reply, int num_fields, void *user_data)
 {
 	struct phonebook_data *data = user_data;
 	char *formatted;
@@ -1699,6 +1703,9 @@ done:
 
 int phonebook_init(void)
 {
+	g_thread_init(NULL);
+	g_type_init();
+
 	return 0;
 }
 
@@ -1792,12 +1799,13 @@ void phonebook_req_finalize(void *request)
 	if (!data)
 		return;
 
-	if (!dbus_pending_call_get_completed(data->call))
-		dbus_pending_call_cancel(data->call);
-
-	dbus_pending_call_unref(data->call);
+	/* canceling asynchronous operation on tracker if any is active */
+	if (data->query_canc) {
+		g_cancellable_cancel(data->query_canc);
+		g_object_unref(data->query_canc);
+	}
 
-	/* freeing list of contacts used for generating vcards */
+	/* freeing contacts */
 	for (l = data->contacts; l; l = l->next) {
 		struct contact_data *c_data = l->data;
 
@@ -1828,7 +1836,8 @@ static void gstring_free_helper(gpointer data, gpointer user_data)
 	g_string_free(data, TRUE);
 }
 
-static void pull_newmissedcalls(char **reply, int num_fields, void *user_data)
+static void pull_newmissedcalls(const char **reply, int num_fields,
+							void *user_data)
 {
 	struct phonebook_data *data = user_data;
 	reply_list_foreach_t pull_cb;
@@ -1870,8 +1879,7 @@ done:
 		pull_cb = pull_contacts;
 	}
 
-	dbus_pending_call_unref(data->call);
-	data->call = query_tracker(query, col_amount, pull_cb, data, &err);
+	query_tracker(query, col_amount, pull_cb, data, &err);
 	if (err < 0)
 		data->cb(NULL, 0, err, 0, data->user_data);
 }
@@ -1910,7 +1918,7 @@ void *phonebook_pull(const char *name, const struct apparam_field *params,
 	data->params = params;
 	data->user_data = user_data;
 	data->cb = cb;
-	data->call = query_tracker(query, col_amount, pull_cb, data, err);
+	query_tracker(query, col_amount, pull_cb, data, err);
 
 	return data;
 }
@@ -1938,8 +1946,8 @@ void *phonebook_get_entry(const char *folder, const char *id,
 		query = g_strdup_printf(CONTACTS_OTHER_QUERY_FROM_URI,
 								id, id, id);
 
-	data->call = query_tracker(query, PULL_QUERY_COL_AMOUNT, pull_contacts,
-								data, err);
+	query_tracker(query, PULL_QUERY_COL_AMOUNT,
+						pull_contacts, data, err);
 
 	g_free(query);
 
@@ -1965,7 +1973,7 @@ void *phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
 	data->entry_cb = entry_cb;
 	data->ready_cb = ready_cb;
 	data->user_data = user_data;
-	data->call = query_tracker(query, 7, add_to_cache, data, err);
+	query_tracker(query, 7, add_to_cache, data, err);
 
 	return data;
 }
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 2/3 v4] Move freeing contacts data to phonebook_req_finalize
From: Radoslaw Jablonski @ 2011-02-03  9:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Radoslaw Jablonski
In-Reply-To: <1296726203-22613-1-git-send-email-ext-jablonski.radoslaw@nokia.com>

Previously data used for generating vcards was freed only in
gen_vcards body. This may result a memory leak, if fetching data
from tracker was cancelled in the middle of process and gen_vcards
wasn't called. Phonebook_req_finalize is better place for this
kind of cleanup.
---
 plugins/phonebook-tracker.c |   14 ++++++++++----
 1 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/plugins/phonebook-tracker.c b/plugins/phonebook-tracker.c
index e60cf74..3b61d6b 100644
--- a/plugins/phonebook-tracker.c
+++ b/plugins/phonebook-tracker.c
@@ -1326,10 +1326,6 @@ static GString *gen_vcards(GSList *contacts,
 		struct contact_data *c_data = l->data;
 		phonebook_add_contact(vcards, c_data->contact,
 					params->filter, params->format);
-
-		g_free(c_data->id);
-		phonebook_contact_free(c_data->contact);
-		g_free(c_data);
 	}
 
 	return vcards;
@@ -1789,6 +1785,7 @@ done:
 void phonebook_req_finalize(void *request)
 {
 	struct phonebook_data *data = request;
+	GSList *l;
 
 	DBG("");
 
@@ -1800,6 +1797,15 @@ void phonebook_req_finalize(void *request)
 
 	dbus_pending_call_unref(data->call);
 
+	/* freeing list of contacts used for generating vcards */
+	for (l = data->contacts; l; l = l->next) {
+		struct contact_data *c_data = l->data;
+
+		g_free(c_data->id);
+		phonebook_contact_free(c_data->contact);
+		g_free(c_data);
+	}
+
 	g_slist_free(data->contacts);
 	g_free(data);
 }
-- 
1.7.0.4


^ 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