All of lore.kernel.org
 help / color / mirror / Atom feed
* Sniff mode patch V2
@ 2008-09-14 20:08 Fabien Chevalier
  0 siblings, 0 replies; only message in thread
From: Fabien Chevalier @ 2008-09-14 20:08 UTC (permalink / raw)
  To: linux-bluetooth

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

Hi Marcel,

I spend most of the day reworking the sniff mode patch.
I implemented both L2CAP and RFCOMM, and tested those two. They both
seem to work.
The layering violation is gone.
The setting is propagated from a server socket to its children.

I think i've seen the end of your first round of comments ;-)

Could you please review this patch and tell me what needs fixing ?

Regards,

Fabien



[-- Attachment #2: 0001-Sniff-mode-fixes-V2.patch --]
[-- Type: text/x-patch, Size: 12311 bytes --]

>>From 1252afa5d458cd4782ee767ff1e487a6ce56c964 Mon Sep 17 00:00:00 2001
From: Fabien Chevalier <fabchevalier@free.fr>
Date: Sun, 14 Sep 2008 20:52:08 +0200
Subject: [PATCH] Sniff mode fixes V2.

* Introduces L2CAP_FORCE_ACTIVE_MODE and RFCOMM_FORCE_ACTIVE_MODE.
* Support for RFCOMM and L2CAP.
* Setting is now inherited on child sockets created through accept()
---
 include/net/bluetooth/hci_core.h |    3 ++-
 include/net/bluetooth/l2cap.h    |    5 +++++
 include/net/bluetooth/rfcomm.h   |    3 +++
 net/bluetooth/hci_conn.c         |    6 +++++-
 net/bluetooth/hci_core.c         |    4 +++-
 net/bluetooth/l2cap.c            |   38 ++++++++++++++++++++++++++++++++------
 net/bluetooth/rfcomm/core.c      |   13 +++++++++----
 net/bluetooth/rfcomm/sock.c      |   32 ++++++++++++++++++++++++++++++--
 8 files changed, 89 insertions(+), 15 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 46a43b7..95f113e 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -170,6 +170,7 @@ struct hci_conn {
 	__u32		 link_mode;
 	__u8             auth_type;
 	__u8             power_save;
+	__u8             force_active_mode;
 	unsigned long	 pend;
 
 	unsigned int	 sent;
@@ -631,7 +632,7 @@ int hci_register_notifier(struct notifier_block *nb);
 int hci_unregister_notifier(struct notifier_block *nb);
 
 int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param);
-int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
+int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, int force_active_mode, __u16 flags);
 int hci_send_sco(struct hci_conn *conn, struct sk_buff *skb);
 
 void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 73e115b..d13f586 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -62,6 +62,8 @@ struct l2cap_conninfo {
 #define L2CAP_LM_RELIABLE	0x0010
 #define L2CAP_LM_SECURE		0x0020
 
+#define L2CAP_FORCE_ACTIVE_MODE	0x04
+
 /* L2CAP command codes */
 #define L2CAP_COMMAND_REJ 0x01
 #define L2CAP_CONN_REQ    0x02
@@ -210,6 +212,8 @@ struct l2cap_conn {
 	__u8		info_state;
 	__u8		info_ident;
 
+	int		force_active_mode;
+
 	struct timer_list info_timer;
 
 	spinlock_t	lock;
@@ -239,6 +243,7 @@ struct l2cap_pinfo {
 	__u16		flush_to;
 
 	__u32		link_mode;
+	int		force_active_mode;
 
 	__u8		conf_req[64];
 	__u8		conf_len;
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index 4dc8d92..61bf1cf 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -185,6 +185,7 @@ struct rfcomm_dlc {
 	u8            out;
 
 	u32           link_mode;
+	int           force_active_mode;
 
 	uint          mtu;
 	uint          cfc;
@@ -298,6 +299,8 @@ struct rfcomm_conninfo {
 #define RFCOMM_LM_RELIABLE	0x0010
 #define RFCOMM_LM_SECURE	0x0020
 
+#define RFCOMM_FORCE_ACTIVE_MODE	0x04
+
 #define rfcomm_pi(sk) ((struct rfcomm_pinfo *) sk)
 
 struct rfcomm_pinfo {
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index b700242..a7feebd 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -214,6 +214,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
 	conn->state = BT_OPEN;
 
 	conn->power_save = 1;
+	conn->force_active_mode = 0;
 
 	switch (type) {
 	case ACL_LINK:
@@ -479,9 +480,12 @@ void hci_conn_enter_active_mode(struct hci_conn *conn)
 	if (test_bit(HCI_RAW, &hdev->flags))
 		return;
 
-	if (conn->mode != HCI_CM_SNIFF || !conn->power_save)
+	if (conn->mode != HCI_CM_SNIFF)
 		goto timer;
 
+	if (!conn->power_save && !conn->force_active_mode)
+ 		goto timer;
+ 		
 	if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
 		struct hci_cp_exit_sniff_mode cp;
 		cp.handle = cpu_to_le16(conn->handle);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index f5b21cb..ec4b1ff 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1193,7 +1193,7 @@ static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags)
 	hdr->dlen   = cpu_to_le16(len);
 }
 
-int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)
+int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, int force_active_mode, __u16 flags)
 {
 	struct hci_dev *hdev = conn->hdev;
 	struct sk_buff *list;
@@ -1234,6 +1234,8 @@ int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)
 		spin_unlock_bh(&conn->data_q.lock);
 	}
 
+	conn->force_active_mode = force_active_mode;
+
 	hci_sched_tx(hdev);
 	return 0;
 }
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 9610a9c..7d422e9 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -304,12 +304,12 @@ static inline int l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16
 {
 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
 
-	BT_DBG("code 0x%2.2x", code);
+	BT_DBG("code 0x%2.2x active_mode %d ", code, conn->force_active_mode);
 
 	if (!skb)
 		return -ENOMEM;
 
-	return hci_send_acl(conn->hcon, skb, 0);
+	return hci_send_acl(conn->hcon, skb, conn->force_active_mode, 0);
 }
 
 static void l2cap_do_start(struct sock *sk)
@@ -661,10 +661,13 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
 		pi->imtu = l2cap_pi(parent)->imtu;
 		pi->omtu = l2cap_pi(parent)->omtu;
 		pi->link_mode = l2cap_pi(parent)->link_mode;
+		pi->force_active_mode = 
+			l2cap_pi(parent)->force_active_mode;
 	} else {
 		pi->imtu = L2CAP_DEFAULT_MTU;
 		pi->omtu = 0;
 		pi->link_mode = 0;
+		pi->force_active_mode = 0;
 	}
 
 	/* Default config options */
@@ -818,6 +821,8 @@ static int l2cap_do_connect(struct sock *sk)
 
 	/* Update source addr of the socket */
 	bacpy(src, conn->src);
+	
+	conn->force_active_mode = l2cap_pi(sk)->force_active_mode;
 
 	l2cap_chan_add(conn, sk, NULL);
 
@@ -1021,7 +1026,7 @@ static inline int l2cap_do_send(struct sock *sk, struct msghdr *msg, int len)
 	int err, hlen, count, sent=0;
 	struct l2cap_hdr *lh;
 
-	BT_DBG("sk %p len %d", sk, len);
+	BT_DBG("sk %p len %d active_mode %d", sk, len, conn->force_active_mode);
 
 	/* First fragment (with L2CAP header) */
 	if (sk->sk_type == SOCK_DGRAM)
@@ -1072,7 +1077,7 @@ static inline int l2cap_do_send(struct sock *sk, struct msghdr *msg, int len)
 		frag = &(*frag)->next;
 	}
 
-	if ((err = hci_send_acl(conn->hcon, skb, 0)) < 0)
+	if ((err = hci_send_acl(conn->hcon, skb, l2cap_pi(sk)->force_active_mode, 0)) < 0)
 		goto fail;
 
 	return sent;
@@ -1148,6 +1153,20 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
 		l2cap_pi(sk)->link_mode = opt;
 		break;
 
+	case L2CAP_FORCE_ACTIVE_MODE:
+		if (get_user(opt, (u32 __user *) optval)) {
+			err = -EFAULT;
+			break;
+		}
+
+		l2cap_pi(sk)->force_active_mode = opt;
+
+		if (sk->sk_state == BT_CONNECTED) {
+			l2cap_pi(sk)->conn->force_active_mode = opt;
+		}
+
+		break;
+
 	default:
 		err = -ENOPROTOOPT;
 		break;
@@ -1204,6 +1223,12 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
 
 		break;
 
+	case L2CAP_FORCE_ACTIVE_MODE:
+		if (put_user(l2cap_pi(sk)->force_active_mode,
+				 (u32 __user *) optval))
+			err = -EFAULT;
+		break;
+
 	default:
 		err = -ENOPROTOOPT;
 		break;
@@ -2429,10 +2454,11 @@ static ssize_t l2cap_sysfs_show(struct class *dev, char *buf)
 	sk_for_each(sk, node, &l2cap_sk_list.head) {
 		struct l2cap_pinfo *pi = l2cap_pi(sk);
 
-		str += sprintf(str, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d 0x%x\n",
+		str += sprintf(str, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d 0x%x %d\n",
 				batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
 				sk->sk_state, btohs(pi->psm), pi->scid, pi->dcid,
-				pi->imtu, pi->omtu, pi->link_mode);
+				pi->imtu, pi->omtu, pi->link_mode,
+				pi->force_active_mode);
 	}
 
 	read_unlock_bh(&l2cap_sk_list.lock);
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index ba537fa..888b431 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -80,7 +80,7 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr);
 
 static void rfcomm_process_connect(struct rfcomm_session *s);
 
-static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int *err);
+static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int force_active_mode, int *err);
 static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst);
 static void rfcomm_session_del(struct rfcomm_session *s);
 
@@ -367,7 +367,7 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
 
 	s = rfcomm_session_get(src, dst);
 	if (!s) {
-		s = rfcomm_session_create(src, dst, &err);
+		s = rfcomm_session_create(src, dst, d->force_active_mode, &err);
 		if (!s)
 			return err;
 	}
@@ -625,19 +625,24 @@ static void rfcomm_session_close(struct rfcomm_session *s, int err)
 	rfcomm_session_put(s);
 }
 
-static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int *err)
+static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int force_active_mode, int *err)
 {
 	struct rfcomm_session *s = NULL;
 	struct sockaddr_l2 addr;
 	struct socket *sock;
 	struct sock *sk;
 
-	BT_DBG("%s %s", batostr(src), batostr(dst));
+	BT_DBG("%s %s %d", batostr(src), batostr(dst), force_active_mode);
 
 	*err = rfcomm_l2sock_create(&sock);
 	if (*err < 0)
 		return NULL;
 
+	*err = kernel_setsockopt(sock, SOL_BLUETOOTH, L2CAP_FORCE_ACTIVE_MODE,
+		(void *) &force_active_mode, sizeof(force_active_mode));
+	if (*err < 0)
+		goto failed;
+
 	bacpy(&addr.l2_bdaddr, src);
 	addr.l2_family = AF_BLUETOOTH;
 	addr.l2_psm    = 0;
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 8a972b6..f6a48e5 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -267,8 +267,11 @@ static void rfcomm_sock_init(struct sock *sk, struct sock *parent)
 	if (parent) {
 		sk->sk_type = parent->sk_type;
 		pi->link_mode = rfcomm_pi(parent)->link_mode;
+		pi->dlc->force_active_mode = 
+			rfcomm_pi(parent)->dlc->force_active_mode;
 	} else {
 		pi->link_mode = 0;
+		pi->dlc->force_active_mode = 0;
 	}
 
 	pi->dlc->link_mode = pi->link_mode;
@@ -735,6 +738,15 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c
 		rfcomm_pi(sk)->link_mode = opt;
 		break;
 
+	case RFCOMM_FORCE_ACTIVE_MODE:
+		if (get_user(opt, (u32 __user *) optval)) {
+			err = -EFAULT;
+			break;
+		}
+
+		rfcomm_pi(sk)->dlc->force_active_mode = opt;
+		break;
+
 	default:
 		err = -ENOPROTOOPT;
 		break;
@@ -781,6 +793,12 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c
 
 		break;
 
+	case RFCOMM_FORCE_ACTIVE_MODE:
+		if (put_user(rfcomm_pi(sk)->dlc->force_active_mode,
+				 (u32 __user *) optval))
+			err = -EFAULT;
+		break;
+
 	default:
 		err = -ENOPROTOOPT;
 		break;
@@ -859,6 +877,8 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
 	struct sock *sk, *parent;
 	bdaddr_t src, dst;
 	int result = 0;
+	int err;
+	int force_active_mode;
 
 	BT_DBG("session %p channel %d", s, channel);
 
@@ -869,6 +889,13 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
 	if (!parent)
 		return 0;
 
+	/* Propagate setting to children */
+	force_active_mode = rfcomm_pi(parent)->dlc->force_active_mode;
+	err = kernel_setsockopt(s->sock, SOL_BLUETOOTH, L2CAP_FORCE_ACTIVE_MODE,
+		(void *) &force_active_mode, sizeof(force_active_mode));
+	if (err < 0)
+		goto done;
+
 	/* Check for backlog size */
 	if (sk_acceptq_is_full(parent)) {
 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
@@ -905,9 +932,10 @@ static ssize_t rfcomm_sock_sysfs_show(struct class *dev, char *buf)
 	read_lock_bh(&rfcomm_sk_list.lock);
 
 	sk_for_each(sk, node, &rfcomm_sk_list.head) {
-		str += sprintf(str, "%s %s %d %d\n",
+		str += sprintf(str, "%s %s %d %d %d\n",
 				batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
-				sk->sk_state, rfcomm_pi(sk)->channel);
+				sk->sk_state, rfcomm_pi(sk)->channel, 
+				rfcomm_pi(sk)->dlc->force_active_mode);
 	}
 
 	read_unlock_bh(&rfcomm_sk_list.lock);
-- 
1.5.6.5




^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2008-09-14 20:08 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-14 20:08 Sniff mode patch V2 Fabien Chevalier

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.