Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH 1/2] list api docs alphabetically and one per line in EXTRA_DIST
From: Uwe Kleine-König @ 2010-08-06 14:18 UTC (permalink / raw)
  To: linux-bluetooth

This makes further changes to the list easier to review

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 Makefile.am |   17 ++++++++++++-----
 1 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 65d4312..4bb82fe 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -309,11 +309,18 @@ udevdir = $(libexecdir)/udev
 dist_udev_SCRIPTS = scripts/bluetooth_serial
 endif
 
-EXTRA_DIST += doc/manager-api.txt \
-		doc/adapter-api.txt doc/device-api.txt \
-		doc/service-api.txt doc/agent-api.txt doc/attribute-api.txt \
-		doc/serial-api.txt doc/network-api.txt \
-		doc/input-api.txt doc/audio-api.txt doc/control-api.txt
+EXTRA_DIST += \
+	      doc/adapter-api.txt \
+	      doc/agent-api.txt \
+	      doc/attribute-api.txt \
+	      doc/audio-api.txt \
+	      doc/control-api.txt \
+	      doc/device-api.txt \
+	      doc/input-api.txt \
+	      doc/manager-api.txt \
+	      doc/network-api.txt \
+	      doc/serial-api.txt \
+	      doc/service-api.txt \
 
 AM_YFLAGS = -d
 
-- 
1.7.1


^ permalink raw reply related

* Re: [PATCH 7/7] Add service UUIDs from EIR to device properties in "Device Found" signal.
From: Johan Hedberg @ 2010-08-06  7:58 UTC (permalink / raw)
  To: Inga Stotland, linux-bluetooth, marcel, rshaffer
In-Reply-To: <20100806075552.GA22150@jh-x301>

Hi,

On Fri, Aug 06, 2010, Johan Hedberg wrote:
> 		/* Bail out if field_len claims to reach beyond the EIR
> 		 * data end */
> 		if (len + field_len + 1 >= EIR_DATA_LENGTH)
> 			break;

Sorry, that should actually be > and not >= since it's fine if the end
of the field coincides with the end of EIR data.

Johan

^ permalink raw reply

* Re: [PATCH 7/7] Add service UUIDs from EIR to device properties in "Device Found" signal.
From: Johan Hedberg @ 2010-08-06  7:55 UTC (permalink / raw)
  To: Inga Stotland; +Cc: linux-bluetooth, marcel, rshaffer
In-Reply-To: <1281047801-4044-1-git-send-email-ingas@codeaurora.org>

Hi Inga,

On Thu, Aug 05, 2010, Inga Stotland wrote:
> +	while (len < EIR_DATA_LENGTH - 1) {
> +		uint8_t type = eir_data[1];
> +		uint8_t field_len = eir_data[0];
> +
> +		/* Check for the end of EIR */
> +		if (field_len == 0)
> +			break;

Shouldn't there also be another check here:

		/* Bail out if field_len claims to reach beyond the EIR
		 * data end */
		if (len + field_len + 1 >= EIR_DATA_LENGTH)
			break;

Johan

^ permalink raw reply

* [PATCH 9/9] Bluetooth: Use 3-DH5 payload size for default ERTM max PDU size.
From: Mat Martineau @ 2010-08-05 22:54 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, rshaffer, linux-arm-msm, Mat Martineau
In-Reply-To: <1281048867-32630-1-git-send-email-mathewm@codeaurora.org>

The previous value of 672 for L2CAP_DEFAULT_MAX_PDU_SIZE is based on
the default L2CAP MTU.  That default MTU is calculated from the size
of two DH5 packets, minus ACL and L2CAP b-frame header overhead.

ERTM is used with newer basebands that typically support larger 3-DH5
packets, and i-frames and s-frames have more header overhead.  With
clean RF conditions, basebands will typically attempt to use 1021-byte
3-DH5 packets for maximum throughput.  Adjusting for 2 bytes of ACL
headers plus 10 bytes of worst-case L2CAP headers yields 1009 bytes
of payload.

This PDU size imposes less overhead for header bytes and gives the
baseband the option to choose 3-DH5 packets, but is small enough for
ERTM traffic to interleave well with other L2CAP or SCO data.
672-byte payloads do not allow the most efficient over-the-air
packet choice, and cannot achieve maximum throughput over BR/EDR.

Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
---
 include/net/bluetooth/l2cap.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 16e412f..6c24144 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -35,7 +35,7 @@
 #define L2CAP_DEFAULT_MAX_TX		3
 #define L2CAP_DEFAULT_RETRANS_TO	2000    /* 2 seconds */
 #define L2CAP_DEFAULT_MONITOR_TO	12000   /* 12 seconds */
-#define L2CAP_DEFAULT_MAX_PDU_SIZE	672
+#define L2CAP_DEFAULT_MAX_PDU_SIZE	1009    /* Sized for 3-DH5 packet */
 #define L2CAP_DEFAULT_ACK_TO		200
 #define L2CAP_LOCAL_BUSY_TRIES		12
 
-- 
1.7.1

--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply related

* [PATCH 8/9] Bluetooth: Use a stream-oriented recvmsg with SOCK_STREAM L2CAP sockets.
From: Mat Martineau @ 2010-08-05 22:54 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, rshaffer, linux-arm-msm, Mat Martineau
In-Reply-To: <1281048867-32630-1-git-send-email-mathewm@codeaurora.org>

L2CAP ERTM sockets can be opened with the SOCK_STREAM socket type,
which is a mandatory request for ERTM mode.

However, these sockets still have SOCK_SEQPACKET read semantics when
bt_sock_recvmsg() is used to pull data from the receive queue.  If the
application is only reading part of a frame, then the unread portion
of the frame is discarded.  If the application requests more bytes
than are in the current frame, only the current frame's data is
returned.

This patch utilizes common code derived from RFCOMM's recvmsg()
function to make L2CAP SOCK_STREAM reads behave like RFCOMM reads (and
other SOCK_STREAM sockets in general).  The application may read one
byte at a time from the input stream and not lose any data, and may
also read across L2CAP frame boundaries.

Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
---
 net/bluetooth/l2cap.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 43e0eae..cd0e150 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1956,7 +1956,10 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms
 
 	release_sock(sk);
 
-	return bt_sock_recvmsg(iocb, sock, msg, len, flags);
+	if (sock->type == SOCK_STREAM)
+		return bt_sock_stream_recvmsg(iocb, sock, msg, len, flags);
+	else
+		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)
-- 
1.7.1

--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply related

* [PATCH 7/9] Bluetooth: Use common SOCK_STREAM receive code in RFCOMM.
From: Mat Martineau @ 2010-08-05 22:54 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, rshaffer, linux-arm-msm, Mat Martineau
In-Reply-To: <1281048867-32630-1-git-send-email-mathewm@codeaurora.org>

To reduce code duplication, have rfcomm_sock_recvmsg() call
bt_sock_stream_recvmsg().  The common bt_sock_stream_recvmsg()
code is nearly identical, with the RFCOMM-specific functionality
for deferred setup and connection unthrottling left in
rfcomm_sock_recvmsg().

Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
---
 net/bluetooth/rfcomm/sock.c |  104 +++----------------------------------------
 1 files changed, 6 insertions(+), 98 deletions(-)

diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 44a6232..4396f47 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -617,121 +617,29 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
 	return sent;
 }
 
-static long rfcomm_sock_data_wait(struct sock *sk, long timeo)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	add_wait_queue(sk_sleep(sk), &wait);
-	for (;;) {
-		set_current_state(TASK_INTERRUPTIBLE);
-
-		if (!skb_queue_empty(&sk->sk_receive_queue) ||
-		    sk->sk_err ||
-		    (sk->sk_shutdown & RCV_SHUTDOWN) ||
-		    signal_pending(current) ||
-		    !timeo)
-			break;
-
-		set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
-		release_sock(sk);
-		timeo = schedule_timeout(timeo);
-		lock_sock(sk);
-		clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
-	}
-
-	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(sk_sleep(sk), &wait);
-	return timeo;
-}
-
 static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 			       struct msghdr *msg, size_t size, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;
-	int err = 0;
-	size_t target, copied = 0;
-	long timeo;
+	int len;
 
 	if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
 		rfcomm_dlc_accept(d);
 		return 0;
 	}
 
-	if (flags & MSG_OOB)
-		return -EOPNOTSUPP;
-
-	msg->msg_namelen = 0;
-
-	BT_DBG("sk %p size %zu", sk, size);
+	len = bt_sock_stream_recvmsg(iocb, sock, msg, size, flags);
 
 	lock_sock(sk);
+	if (!(flags & MSG_PEEK) && len > 0)
+		atomic_sub(len, &sk->sk_rmem_alloc);
 
-	target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
-	timeo  = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
-
-	do {
-		struct sk_buff *skb;
-		int chunk;
-
-		skb = skb_dequeue(&sk->sk_receive_queue);
-		if (!skb) {
-			if (copied >= target)
-				break;
-
-			if ((err = sock_error(sk)) != 0)
-				break;
-			if (sk->sk_shutdown & RCV_SHUTDOWN)
-				break;
-
-			err = -EAGAIN;
-			if (!timeo)
-				break;
-
-			timeo = rfcomm_sock_data_wait(sk, timeo);
-
-			if (signal_pending(current)) {
-				err = sock_intr_errno(timeo);
-				goto out;
-			}
-			continue;
-		}
-
-		chunk = min_t(unsigned int, skb->len, size);
-		if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
-			skb_queue_head(&sk->sk_receive_queue, skb);
-			if (!copied)
-				copied = -EFAULT;
-			break;
-		}
-		copied += chunk;
-		size   -= chunk;
-
-		sock_recv_ts_and_drops(msg, sk, skb);
-
-		if (!(flags & MSG_PEEK)) {
-			atomic_sub(chunk, &sk->sk_rmem_alloc);
-
-			skb_pull(skb, chunk);
-			if (skb->len) {
-				skb_queue_head(&sk->sk_receive_queue, skb);
-				break;
-			}
-			kfree_skb(skb);
-
-		} else {
-			/* put message back and return */
-			skb_queue_head(&sk->sk_receive_queue, skb);
-			break;
-		}
-	} while (size);
-
-out:
 	if (atomic_read(&sk->sk_rmem_alloc) <= (sk->sk_rcvbuf >> 2))
 		rfcomm_dlc_unthrottle(rfcomm_pi(sk)->dlc);
-
 	release_sock(sk);
-	return copied ? : err;
+
+	return len;
 }
 
 static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
-- 
1.7.1

--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply related

* [PATCH 6/9] Bluetooth: Add common code for stream-oriented recvmsg()
From: Mat Martineau @ 2010-08-05 22:54 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, rshaffer, linux-arm-msm, Mat Martineau
In-Reply-To: <1281048867-32630-1-git-send-email-mathewm@codeaurora.org>

This commit adds a bt_sock_stream_recvmsg() function for use by any
Bluetooth code that uses SOCK_STREAM sockets.  This code is copied
from rfcomm_sock_recvmsg() with minimal modifications to remove
RFCOMM-specific functionality and improve readability.

L2CAP (with the SOCK_STREAM socket type) and RFCOMM have common needs
when it comes to reading data.  Proper stream read semantics require
that applications can read from a stream one byte at a time and not
lose any data.  The RFCOMM code already operated on and pulled data
from the underlying L2CAP socket, so very few changes were required to
make the code more generic for use with non-RFCOMM data over L2CAP.

Applications that need more awareness of L2CAP frame boundaries are
still free to use SOCK_SEQPACKET sockets, and may verify that they
connection did not fall back to basic mode by calling getsockopt().

Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
---
 include/net/bluetooth/bluetooth.h |    2 +
 net/bluetooth/af_bluetooth.c      |  109 +++++++++++++++++++++++++++++++++++++
 2 files changed, 111 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 27a902d..08b6c2a 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -126,6 +126,8 @@ int  bt_sock_unregister(int proto);
 void bt_sock_link(struct bt_sock_list *l, struct sock *s);
 void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
 int  bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags);
+int  bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
+			struct msghdr *msg, size_t len, int flags);
 uint bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait);
 int  bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
 int  bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo);
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 421c45b..77a26fe 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -265,6 +265,115 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 }
 EXPORT_SYMBOL(bt_sock_recvmsg);
 
+static long bt_sock_data_wait(struct sock *sk, long timeo)
+{
+	DECLARE_WAITQUEUE(wait, current);
+
+	add_wait_queue(sk_sleep(sk), &wait);
+	for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+
+		if (!skb_queue_empty(&sk->sk_receive_queue))
+			break;
+
+		if (sk->sk_err || (sk->sk_shutdown & RCV_SHUTDOWN))
+			break;
+
+		if (signal_pending(current) || !timeo)
+			break;
+
+		set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
+		release_sock(sk);
+		timeo = schedule_timeout(timeo);
+		lock_sock(sk);
+		clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
+	}
+
+	__set_current_state(TASK_RUNNING);
+	remove_wait_queue(sk_sleep(sk), &wait);
+	return timeo;
+}
+
+int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
+			       struct msghdr *msg, size_t size, int flags)
+{
+	struct sock *sk = sock->sk;
+	int err = 0;
+	size_t target, copied = 0;
+	long timeo;
+
+	if (flags & MSG_OOB)
+		return -EOPNOTSUPP;
+
+	msg->msg_namelen = 0;
+
+	BT_DBG("sk %p size %zu", sk, size);
+
+	lock_sock(sk);
+
+	target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
+	timeo  = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
+
+	do {
+		struct sk_buff *skb;
+		int chunk;
+
+		skb = skb_dequeue(&sk->sk_receive_queue);
+		if (!skb) {
+			if (copied >= target)
+				break;
+
+			if ((err = sock_error(sk)) != 0)
+				break;
+			if (sk->sk_shutdown & RCV_SHUTDOWN)
+				break;
+
+			err = -EAGAIN;
+			if (!timeo)
+				break;
+
+			timeo = bt_sock_data_wait(sk, timeo);
+
+			if (signal_pending(current)) {
+				err = sock_intr_errno(timeo);
+				goto out;
+			}
+			continue;
+		}
+
+		chunk = min_t(unsigned int, skb->len, size);
+		if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
+			skb_queue_head(&sk->sk_receive_queue, skb);
+			if (!copied)
+				copied = -EFAULT;
+			break;
+		}
+		copied += chunk;
+		size   -= chunk;
+
+		sock_recv_ts_and_drops(msg, sk, skb);
+
+		if (!(flags & MSG_PEEK)) {
+			skb_pull(skb, chunk);
+			if (skb->len) {
+				skb_queue_head(&sk->sk_receive_queue, skb);
+				break;
+			}
+			kfree_skb(skb);
+
+		} else {
+			/* put message back and return */
+			skb_queue_head(&sk->sk_receive_queue, skb);
+			break;
+		}
+	} while (size);
+
+out:
+	release_sock(sk);
+	return copied ? : err;
+}
+EXPORT_SYMBOL(bt_sock_stream_recvmsg);
+
 static inline unsigned int bt_accept_poll(struct sock *parent)
 {
 	struct list_head *p, *n;
-- 
1.7.1

--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply related

* [PATCH 5/9] Bluetooth: Fix incorrect setting of remote_tx_win for L2CAP ERTM.
From: Mat Martineau @ 2010-08-05 22:54 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, rshaffer, linux-arm-msm, Mat Martineau
In-Reply-To: <1281048867-32630-1-git-send-email-mathewm@codeaurora.org>

remote_tx_win is intended to be set on receipt of an L2CAP
configuration request.  The value is used to determine the size of the
transmit window on the remote side of an ERTM connection, so L2CAP
can stop sending frames when that remote window is full.

An incorrect remote_tx_win value will cause the stack to not fully
utilize the tx window (performance impact), or to overfill the remote
tx window (causing dropped frames or a disconnect).

This patch removes an extra setting of remote_tx_win when a
configuration response is received.  The transmit window has a
different meaning in a response - it is an informational value
less than or equal to the local tx_win.

Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
---
 net/bluetooth/l2cap.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 5541b56..43e0eae 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -2819,7 +2819,6 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data,
 	if (*result == L2CAP_CONF_SUCCESS) {
 		switch (rfc.mode) {
 		case L2CAP_MODE_ERTM:
-			pi->remote_tx_win   = rfc.txwin_size;
 			pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
 			pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
 			pi->mps    = le16_to_cpu(rfc.max_pdu_size);
@@ -2875,7 +2874,6 @@ static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
 done:
 	switch (rfc.mode) {
 	case L2CAP_MODE_ERTM:
-		pi->remote_tx_win   = rfc.txwin_size;
 		pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
 		pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
 		pi->mps    = le16_to_cpu(rfc.max_pdu_size);
-- 
1.7.1

--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply related

* [PATCH 4/9] Bluetooth: Fix endianness issue with L2CAP MPS configuration.
From: Mat Martineau @ 2010-08-05 22:54 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, rshaffer, linux-arm-msm, Mat Martineau
In-Reply-To: <1281048867-32630-1-git-send-email-mathewm@codeaurora.org>

Incoming configuration values must be converted to native CPU order
before use.  This fixes a bug where a little-endian MPS value is
compared to a native CPU value.  On big-endian processors, this
can cause ERTM and streaming mode segmentation to produce PDUs
that are larger than the remote stack is expecting, or that would
produce fragmented skbs that the current FCS code cannot handle.

Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
---
 net/bluetooth/l2cap.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 77ba106..5541b56 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -2717,8 +2717,9 @@ done:
 		case L2CAP_MODE_ERTM:
 			pi->remote_tx_win = rfc.txwin_size;
 			pi->remote_max_tx = rfc.max_transmit;
-			if (rfc.max_pdu_size > pi->conn->mtu - 10)
-				rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10);
+
+			if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
+				rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
 
 			pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
 
@@ -2735,8 +2736,8 @@ done:
 			break;
 
 		case L2CAP_MODE_STREAMING:
-			if (rfc.max_pdu_size > pi->conn->mtu - 10)
-				rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10);
+			if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
+				rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
 
 			pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
 
-- 
1.7.1

--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply related

* [PATCH 3/9] Bluetooth: Validate PSM values in calls to connect() and bind().
From: Mat Martineau @ 2010-08-05 22:54 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, rshaffer, linux-arm-msm, Mat Martineau
In-Reply-To: <1281048867-32630-1-git-send-email-mathewm@codeaurora.org>

Valid L2CAP PSMs are odd numbers, and the least significant bit of the
most significant byte must be 0.

Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
---
 net/bluetooth/l2cap.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index bc10be8..77ba106 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1008,6 +1008,12 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 		goto done;
 	}
 
+	/* If specified, PSM must be odd and lsb of upper byte must be 0 */
+	if (la.l2_psm && (__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001) {
+		err = -EINVAL;
+		goto done;
+	}
+
 	if (la.l2_psm && __le16_to_cpu(la.l2_psm) < 0x1001 &&
 				!capable(CAP_NET_BIND_SERVICE)) {
 		err = -EACCES;
@@ -1190,6 +1196,12 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
 		goto done;
 	}
 
+	/* PSM must be odd and lsb of upper byte must be 0 */
+	if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001) {
+		err = -EINVAL;
+		goto done;
+	}
+
 	/* Set destination address and psm */
 	bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
 	l2cap_pi(sk)->psm = la.l2_psm;
-- 
1.7.1

--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply related

* [PATCH 2/9] Bluetooth: Change default ERTM retransmit timeout.
From: Mat Martineau @ 2010-08-05 22:54 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, rshaffer, linux-arm-msm, Mat Martineau
In-Reply-To: <1281048867-32630-1-git-send-email-mathewm@codeaurora.org>

The L2CAP spec requires that the ERTM retransmit timeout be at least 2
seconds for BR/EDR connections.

Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
---
 include/net/bluetooth/l2cap.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 636724b..16e412f 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -33,7 +33,7 @@
 #define L2CAP_DEFAULT_FLUSH_TO		0xffff
 #define L2CAP_DEFAULT_TX_WINDOW		63
 #define L2CAP_DEFAULT_MAX_TX		3
-#define L2CAP_DEFAULT_RETRANS_TO	1000    /* 1 second */
+#define L2CAP_DEFAULT_RETRANS_TO	2000    /* 2 seconds */
 #define L2CAP_DEFAULT_MONITOR_TO	12000   /* 12 seconds */
 #define L2CAP_DEFAULT_MAX_PDU_SIZE	672
 #define L2CAP_DEFAULT_ACK_TO		200
-- 
1.7.1

--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply related

* [PATCH 1/9] Bluetooth: Only enable for L2CAP FCS for ERTM or streaming.
From: Mat Martineau @ 2010-08-05 22:54 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, rshaffer, linux-arm-msm, Mat Martineau
In-Reply-To: <1281048867-32630-1-git-send-email-mathewm@codeaurora.org>

This fixes a bug which caused the FCS setting to show L2CAP_FCS_CRC16
with L2CAP modes other than ERTM or streaming.  At present, this only
affects the FCS value shown with getsockopt() for basic mode.

Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
---
 net/bluetooth/l2cap.c |   16 ++++++++++++----
 1 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 3e3cd9d..bc10be8 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3072,6 +3072,16 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
 	return 0;
 }
 
+static inline int l2cap_fcs_needed(struct l2cap_pinfo *pi)
+{
+	if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
+		return 0;
+
+	/* FCS is enabled if one or both sides request it. */
+	return !(pi->conf_state & L2CAP_CONF_NO_FCS_RECV) ||
+		pi->fcs == L2CAP_FCS_CRC16;
+}
+
 static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
 {
 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
@@ -3136,8 +3146,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 		goto unlock;
 
 	if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
-		if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_NO_FCS_RECV) ||
-		    l2cap_pi(sk)->fcs != L2CAP_FCS_NONE)
+		if (l2cap_fcs_needed(l2cap_pi(sk)))
 			l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16;
 
 		sk->sk_state = BT_CONNECTED;
@@ -3226,8 +3235,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 	l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
 
 	if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
-		if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_NO_FCS_RECV) ||
-		    l2cap_pi(sk)->fcs != L2CAP_FCS_NONE)
+		if (l2cap_fcs_needed(l2cap_pi(sk)))
 			l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16;
 
 		sk->sk_state = BT_CONNECTED;
-- 
1.7.1

--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply related

* [PATCH v3 0/9] Bluetooth: L2CAP updates for PSM validation and ERTM
From: Mat Martineau @ 2010-08-05 22:54 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, rshaffer, linux-arm-msm

This is a collection of ERTM-related patches, including some L2CAP
configuration fixes and allowing partial-frame reads from L2CAP
SOCK_STREAM sockets.  PSM validation is also included, although that
is not restricted to ERTM.

--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum



^ permalink raw reply

* [PATCH 7/7] Add service UUIDs from EIR to device properties in "Device Found" signal.
From: Inga Stotland @ 2010-08-05 22:36 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: johan.hedberg, marcel, rshaffer, Inga Stotland
In-Reply-To: <20100805102513.GA7221@jh-x301>

---
 src/adapter.c  |  108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 src/adapter.h  |    4 +-
 src/dbus-hci.c |    6 ++--
 3 files changed, 110 insertions(+), 8 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index c142a4a..b2b5be8 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2749,8 +2749,102 @@ static void emit_device_found(const char *path, const char *address,
 	g_dbus_send_message(connection, signal);
 }
 
+static char **get_eir_uuids(uint8_t *eir_data, size_t *uuid_count)
+{
+	uint16_t len = 0;
+	char **uuids;
+	size_t total;
+	size_t uuid16_count = 0;
+	size_t uuid32_count = 0;
+	size_t uuid128_count = 0;
+	uint8_t *uuid16;
+	uint8_t *uuid32;
+	uint8_t *uuid128;
+	uuid_t service;
+	int i;
+
+	while (len < EIR_DATA_LENGTH - 1) {
+		uint8_t type = eir_data[1];
+		uint8_t field_len = eir_data[0];
+
+		/* Check for the end of EIR */
+		if (field_len == 0)
+			break;
+
+		switch (type) {
+		case EIR_UUID16_SOME:
+		case EIR_UUID16_ALL:
+			uuid16_count = field_len / 2;
+			uuid16 = &eir_data[2];
+			break;
+		case EIR_UUID32_SOME:
+		case EIR_UUID32_ALL:
+			uuid32_count = field_len / 4;
+			uuid32 = &eir_data[2];
+			break;
+		case EIR_UUID128_SOME:
+		case EIR_UUID128_ALL:
+			uuid128_count = field_len / 16;
+			uuid128 = &eir_data[2];
+			break;
+		}
+
+		len += field_len + 1;
+		eir_data += field_len + 1;
+	}
+
+	/* Bail out if got incorrect length */
+	if (len > EIR_DATA_LENGTH)
+		return NULL;
+
+	total = uuid16_count + uuid32_count + uuid128_count;
+	*uuid_count = total;
+
+	if (!total)
+		return NULL;
+
+	uuids = g_new0(char *, total + 1);
+
+	/* Generate uuids in SDP format (EIR data is Little Endian) */
+	service.type = SDP_UUID16;
+	for (i = 0; i < uuid16_count; i++) {
+		uint16_t val16 = uuid16[1];
+
+		val16 = (val16 << 8) + uuid16[0];
+		service.value.uuid16 = val16;
+		uuids[i] = bt_uuid2string(&service);
+		uuid16 += 2;
+	}
+
+	service.type = SDP_UUID32;
+	for (i = uuid16_count; i < uuid32_count + uuid16_count; i++) {
+		uint32_t val32 = uuid32[3];
+		int k;
+
+		for (k = 2; k >= 0; k--)
+			val32 = (val32 << 8) + uuid32[k];
+
+		service.value.uuid32 = val32;
+		uuids[i] = bt_uuid2string(&service);
+		uuid32 += 4;
+	}
+
+	service.type = SDP_UUID128;
+	for (i = uuid32_count + uuid16_count; i < total; i++) {
+		int k;
+
+		for (k = 0; k < 16; k++)
+			service.value.uuid128.data[k] = uuid128[16 - k - 1];
+
+		uuids[i] = bt_uuid2string(&service);
+		uuid128 += 16;
+	}
+
+	return uuids;
+}
+
 void adapter_emit_device_found(struct btd_adapter *adapter,
-				struct remote_dev_info *dev)
+				struct remote_dev_info *dev, uint8_t *eir_data)
 {
 	struct btd_device *device;
 	char peer_addr[18], local_addr[18];
@@ -2758,6 +2852,8 @@ void adapter_emit_device_found(struct btd_adapter *adapter,
 	dbus_bool_t paired = FALSE;
 	dbus_int16_t rssi = dev->rssi;
 	char *alias;
+	char **uuids = NULL;
+	size_t uuid_count = 0;
 
 	ba2str(&dev->bdaddr, peer_addr);
 	ba2str(&adapter->bdaddr, local_addr);
@@ -2777,6 +2873,10 @@ void adapter_emit_device_found(struct btd_adapter *adapter,
 	} else
 		alias = g_strdup(dev->alias);
 
+	/* Extract UUIDs from extended inquiry response if any*/
+	if (eir_data != NULL)
+		uuids = get_eir_uuids(eir_data, &uuid_count);
+
 	emit_device_found(adapter->path, paddr,
 			"Address", DBUS_TYPE_STRING, &paddr,
 			"Class", DBUS_TYPE_UINT32, &dev->class,
@@ -2786,15 +2886,17 @@ void adapter_emit_device_found(struct btd_adapter *adapter,
 			"Alias", DBUS_TYPE_STRING, &alias,
 			"LegacyPairing", DBUS_TYPE_BOOLEAN, &dev->legacy,
 			"Paired", DBUS_TYPE_BOOLEAN, &paired,
+			"UUIDs", DBUS_TYPE_ARRAY, &uuids, uuid_count,
 			NULL);
 
 	g_free(alias);
+	g_strfreev(uuids);
 }
 
 void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
 				int8_t rssi, uint32_t class, const char *name,
 				const char *alias, gboolean legacy,
-				name_status_t name_status)
+				name_status_t name_status, uint8_t *eir_data)
 {
 	struct remote_dev_info *dev, match;
 
@@ -2833,7 +2935,7 @@ done:
 	adapter->found_devices = g_slist_sort(adapter->found_devices,
 						(GCompareFunc) dev_rssi_cmp);
 
-	adapter_emit_device_found(adapter, dev);
+	adapter_emit_device_found(adapter, dev, eir_data);
 }
 
 int adapter_remove_found_device(struct btd_adapter *adapter, bdaddr_t *bdaddr)
diff --git a/src/adapter.h b/src/adapter.h
index 8226514..a7eca0e 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -113,10 +113,10 @@ struct remote_dev_info *adapter_search_found_devices(struct btd_adapter *adapter
 void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
 				int8_t rssi, uint32_t class, const char *name,
 				const char *alias, gboolean legacy,
-				name_status_t name_status);
+				name_status_t name_status, uint8_t *eir_data);
 int adapter_remove_found_device(struct btd_adapter *adapter, bdaddr_t *bdaddr);
 void adapter_emit_device_found(struct btd_adapter *adapter,
-				struct remote_dev_info *dev);
+				struct remote_dev_info *dev, uint8_t *eir_data);
 void adapter_update_oor_devices(struct btd_adapter *adapter);
 void adapter_mode_changed(struct btd_adapter *adapter, uint8_t scan_mode);
 void adapter_setname_complete(bdaddr_t *local, uint8_t status);
diff --git a/src/dbus-hci.c b/src/dbus-hci.c
index b83506f..6d27caa 100644
--- a/src/dbus-hci.c
+++ b/src/dbus-hci.c
@@ -515,7 +515,7 @@ void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
 	if (dev) {
 		adapter_update_found_devices(adapter, peer, rssi, class,
 						NULL, NULL, dev->legacy,
-						NAME_NOT_REQUIRED);
+						NAME_NOT_REQUIRED, data);
 		return;
 	}
 
@@ -566,7 +566,7 @@ void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
 
 	/* add in the list to track name sent/pending */
 	adapter_update_found_devices(adapter, peer, rssi, class, name, alias,
-					legacy, name_status);
+					legacy, name_status, data);
 
 	g_free(name);
 	g_free(alias);
@@ -642,7 +642,7 @@ void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_t status,
 	if (dev_info) {
 		g_free(dev_info->name);
 		dev_info->name = g_strdup(name);
-		adapter_emit_device_found(adapter, dev_info);
+		adapter_emit_device_found(adapter, dev_info, NULL);
 	}
 
 	if (device)
-- 
1.7.2

-- 
Inga Stotland
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply related

* Handling HID Connections for certain devices externally
From: Carl Önnheim @ 2010-08-05 22:15 UTC (permalink / raw)
  To: linux-bluetooth

Hi,

I am working on a project to integrate the Sony PS3 Remote to LIRC.
BlueZ supports the use of this device by translating key presses to
keyboard events. It is possible for me to read these translated keyboard
events to figure out what happens on the remote, but the application is
more stable if I can get hold of the raw data stream from the remote
directly. This ability would also allow for separate development for
other special devices that communicate as HID devices (e.g. the
WII-remotes).

I have not been able to get a hold of that datastream (except by
stopping bluez and then listening directly on the relevant PSM's, but
since bluez need to run for all other purposes that is not really an
option). So my question is:

1. Is there a possibility that I have missed for a separate user-space
program to "steal" the interrupt and control channels from BlueZ for a
specific HID Device?

2. If not, will you consider adding this possibility? I have
experimented with one option; the fake_hid functionality is extended so
that when a HID device connects it tries to connect to a unix socket
with a predefined name
(e.g. /var/run/bluez/fakehid_<vendor_id>_<product_id>). If a program
listens on that socket, the data channels will be passed over. If not,
bluez will continue as usual.

I have a patch that does this more or less ready to go, and I would be
happy to contribute further if I can. Other options can of course be
considered (e.g. exposing new DBus methods). But I wanted to check your
initial views before going into more details. You can see all details
about the project I am working on at
http://sourceforge.net/projects/sonyps3remote/.

The patch can be found in the svn tree there as well:
http://sonyps3remote.svn.sourceforge.net/viewvc/sonyps3remote/bluez/patches/bluez-4.69-sonyps3.diff.gz?view=log

Thanks in advance
//Carl


^ permalink raw reply

* Re: [PATCH 7/7] Add service UUIDs from EIR to device properties in "Device Found" signal.
From: ingas @ 2010-08-05 21:26 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth
In-Reply-To: <20100805102513.GA7221@jh-x301>

Hi Johan,

> I've pushed the six other patches upstream, but I'm still a bit
> concerned with this one.
>

Thanks :)

>
> Then, a more general concern about this function. It will receive data
> as input that any nearby device that's discoverable has declared in
> their EIR data. I.e. we need to be super strict about checking the
> validity of the data and not make any assumptions about the correctness
> of encoded field lengths etc. in order not to do buffer overflows. Have
> you taken this into account when designing the function? Looking at it
> it seems it might be possible to give it data that will cause some
> buffer overflows (by e.g. placing a uuid list at the very end of the EIR
> data with an invalid field length value).
>

I agree. Adding few more checks there. Will send a new patch today.

Inga


^ permalink raw reply

* Re: NoInputNoOutput and legacy pairing?
From: Manuel Naranjo @ 2010-08-05 20:58 UTC (permalink / raw)
  To: BlueZ
In-Reply-To: <20100805195314.GA13190@jh-x301>


>> >  I have a question regarding the NoInputNoOutput mode for registering
>> >  agents for BlueZ. What happens when there's a legacy pin request and
>> >  the mode is NoInputNoOutput? Will it fallback to standard pin code
>> >  pairing?
>>      
Great thanks. I know how to go on now.

BTW what happened to the wiki? This are the kind of things that would be 
easy to address by just looking at it.

^ permalink raw reply

* Re: NoInputNoOutput and legacy pairing?
From: Johan Hedberg @ 2010-08-05 19:53 UTC (permalink / raw)
  To: Manuel Naranjo; +Cc: BlueZ
In-Reply-To: <4C5B0884.2040805@aircable.net>

Hi Manuel,

On Thu, Aug 05, 2010, Manuel Naranjo wrote:
> I have a question regarding the NoInputNoOutput mode for registering
> agents for BlueZ. What happens when there's a legacy pin request and
> the mode is NoInputNoOutput? Will it fallback to standard pin code
> pairing?

Yes. The IO capability is only relevant for Secure Simple Pairing. It
doesn't matter what capability you give for legacy pairing since you'll
always get a pin request then.

Johan

^ permalink raw reply

* NoInputNoOutput and legacy pairing?
From: Manuel Naranjo @ 2010-08-05 18:52 UTC (permalink / raw)
  To: BlueZ

Hi guys,

I have a question regarding the NoInputNoOutput mode for registering 
agents for BlueZ. What happens when there's a legacy pin request and the 
mode is NoInputNoOutput? Will it fallback to standard pin code pairing?

My system is working in an environment where no screen or no keyboard is 
available so I can't pair with a random number. Thing is in some cases I 
still need to fallback to a hardcoded pin because some cellphones 
require it.

Manuel

^ permalink raw reply

* Re: [PATCH 5/9] Bluetooth: Fix incorrect setting of remote_tx_win for L2CAP ERTM.
From: Mat Martineau @ 2010-08-05 16:54 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: linux-bluetooth, marcel, rshaffer, linux-arm-msm
In-Reply-To: <20100805042013.GH7870@vigoh>


Gustavo -

On Thu, 5 Aug 2010, Gustavo F. Padovan wrote:

> Hi Mat,
>
> * Mat Martineau <mathewm@codeaurora.org> [2010-08-04 15:49:02 -0700]:
>
>> remote_tx_win is intended to be set on receipt of an L2CAP
>> configuration request.  The value is used to determine the size of the
>> transmit window on the remote side of an ERTM connection, so L2CAP
>> can stop sending frames when that remote window is full.
>>
>> An incorrect remote_tx_win value will cause the stack to not fully
>> utilize the tx window (performance impact), or to overfill the remote
>> tx window (causing dropped frames or a disconnect).
>>
>> This patch removes an extra setting of remote_tx_win when a
>> configuration response is received.  The transmit window has a
>> different meaning in a response - it is an informational value
>> less than or equal to the local tx_win.
>>
>> Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
>> ---
>>  net/bluetooth/l2cap.c |    1 -
>>  1 files changed, 0 insertions(+), 1 deletions(-)
>>
>> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
>> index 8cf9569..f0f3c7c 100644
>> --- a/net/bluetooth/l2cap.c
>> +++ b/net/bluetooth/l2cap.c
>> @@ -2808,7 +2808,6 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data,
>>  	if (*result == L2CAP_CONF_SUCCESS) {
>>  		switch (rfc.mode) {
>>  		case L2CAP_MODE_ERTM:
>> -			pi->remote_tx_win   = rfc.txwin_size;
>>  			pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
>>  			pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
>>  			pi->mps    = le16_to_cpu(rfc.max_pdu_size);
>
> I agree. But you may also want to remove the same check inside
> l2cap_conf_rfc_get()

I'll do that.

--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply

* Re: [PATCH 4/9] Bluetooth: Fix endianness issue with L2CAP MPS configuration.
From: Mat Martineau @ 2010-08-05 16:50 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: linux-bluetooth, marcel, rshaffer, linux-arm-msm
In-Reply-To: <20100805040018.GG7870@vigoh>


Gustavo -

On Thu, 5 Aug 2010, Gustavo F. Padovan wrote:

> Hi Mat,
>
> * Mat Martineau <mathewm@codeaurora.org> [2010-08-04 15:49:01 -0700]:
>
>> Incoming configuration values must be converted to native CPU order
>> before use.  This fixes a bug where a little-endian MPS value is
>> compared to a native CPU value.  On big-endian processors, this
>> can cause ERTM and streaming mode segmentation to produce PDUs
>> that are larger than the remote stack is expecting, or that would
>> produce fragmented skbs that the current FCS code cannot handle.
>>
>> Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
>> ---
>>  net/bluetooth/l2cap.c |    9 ++++-----
>>  1 files changed, 4 insertions(+), 5 deletions(-)
>>
>> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
>> index 920a53f..8cf9569 100644
>> --- a/net/bluetooth/l2cap.c
>> +++ b/net/bluetooth/l2cap.c
>> @@ -2708,10 +2708,10 @@ done:
>>  		case L2CAP_MODE_ERTM:
>>  			pi->remote_tx_win = rfc.txwin_size;
>>  			pi->remote_max_tx = rfc.max_transmit;
>> -			if (rfc.max_pdu_size > pi->conn->mtu - 10)
>> -				rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10);
>>
>>  			pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
>> +			if (pi->remote_mps > pi->conn->mtu - 10)
>> +				pi->remote_mps = pi->conn->mtu - 10;
>
>
> What happened with thte "rfc.max_pdu_size =" attribution. We have the
> send the value to through the RFC option.

You're right - I didn't see that the rfc struct was used for both the 
response and reply.

> So what I do propose here is:
>
> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
> index 0f34e12..11d4405 100644
> --- a/net/bluetooth/l2cap.c
> +++ b/net/bluetooth/l2cap.c
> @@ -2705,7 +2705,7 @@ done:
>                case L2CAP_MODE_ERTM:
>                        pi->remote_tx_win = rfc.txwin_size;
>                        pi->remote_max_tx = rfc.max_transmit;
> -                       if (rfc.max_pdu_size > pi->conn->mtu - 10)
> +                       if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
>                                rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10);
>
>                        pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);

Sure.  I'll change it to "cpu_to_le16(pi->conn->mtu - 10)" (even 
though they're functionally equivalent, it is definitely a conversion 
to le16).

> @@ -2723,7 +2723,7 @@ done:
>                        break;
>
>                case L2CAP_MODE_STREAMING:
> -                       if (rfc.max_pdu_size > pi->conn->mtu - 10)
> +                       if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
>                                rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10);

Same thing - cpu_to_le16() instead.

>                        pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
>
>
>
>>
>>  			rfc.retrans_timeout =
>>  				le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
>> @@ -2726,10 +2726,9 @@ done:
>>  			break;
>>
>>  		case L2CAP_MODE_STREAMING:
>> -			if (rfc.max_pdu_size > pi->conn->mtu - 10)
>> -				rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10);
>> -
>>  			pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
>> +			if (pi->remote_mps > pi->conn->mtu - 10)
>> +				pi->remote_mps = pi->conn->mtu - 10;
>>
>>  			pi->conf_state |= L2CAP_CONF_MODE_DONE;



--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply

* Re: [PATCH 1/9] Bluetooth: Only enable for L2CAP FCS for ERTM or streaming.
From: Mat Martineau @ 2010-08-05 16:27 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: linux-bluetooth, marcel, rshaffer, linux-arm-msm
In-Reply-To: <20100805033218.GE7870@vigoh>


Gustavo -

On Thu, 5 Aug 2010, Gustavo F. Padovan wrote:

> Hi Mat,
>
> * Mat Martineau <mathewm@codeaurora.org> [2010-08-04 15:48:58 -0700]:
>
>> This fixes a bug which caused the FCS setting to show L2CAP_FCS_CRC16
>> with L2CAP modes other than ERTM or streaming.  At present, this only
>> affects the FCS value shown with getsockopt() for basic mode.
>>
>> Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
>> ---
>>  net/bluetooth/l2cap.c |   17 +++++++++++++----
>>  1 files changed, 13 insertions(+), 4 deletions(-)
>>
>> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
>> index 9ba1e8e..a2706d9 100644
>> --- a/net/bluetooth/l2cap.c
>> +++ b/net/bluetooth/l2cap.c
>> @@ -3063,6 +3063,17 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
>>  	return 0;
>>  }
>>
>> +static inline int l2cap_fcs_needed(struct l2cap_pinfo *pi)
>> +{
>> +	if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
>> +		return 0;
>> +	else {
>> +		/* FCS is enabled if one or both sides request it. */
>> +		return !(pi->conf_state & L2CAP_CONF_NO_FCS_RECV) ||
>> +			pi->fcs == L2CAP_FCS_CRC16;
>> +	}
>
> Get ride of the else, just put the return !(pi->....

Ok.

> Also I would like to see the use case for the check for the ERTM and
> Streaming before merge this patch. ;)

I have a patch modifying l2cap_skbuff_fromiovec() that allows ERTM 
PDUs to be longer than the HCI MTU (some USB BT dongles only have a 
310 byte HCI MTU).  That function has to allocate space for the FCS in 
the final HCI continuation fragment, and therefore checks to see if 
FCS is enabled.  When I first did this, it was not obvious that 
pi->fcs could be L2CAP_FCS_CRC16 even when the FCS is not in use.

I hope you can agree that this patch makes the meaning of pi->fcs more 
intuitive, and eliminates the need to check both pi->fcs and pi->mode 
to really determine if the FCS is in use.  Depending on using pi->fcs 
only in ERTM code paths makes the code more fragile.

--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply

* Re: [PATCH 2/9] Bluetooth: Change default ERTM retransmit timeout.
From: Mat Martineau @ 2010-08-05 15:53 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: linux-bluetooth, marcel, rshaffer, linux-arm-msm
In-Reply-To: <20100805032903.GD7870@vigoh>


Hi Gustavo -

On Thu, 5 Aug 2010, Gustavo F. Padovan wrote:

> Hi Mat,
>
> * Mat Martineau <mathewm@codeaurora.org> [2010-08-04 15:48:59 -0700]:
>
>> The L2CAP spec requires that the ERTM retransmit timeout be at least 2
>> seconds for BR/EDR connections.
>>
>> Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
>> ---
>>  include/net/bluetooth/l2cap.h |    2 +-
>>  1 files changed, 1 insertions(+), 1 deletions(-)
>>
>> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
>> index 636724b..16e412f 100644
>> --- a/include/net/bluetooth/l2cap.h
>> +++ b/include/net/bluetooth/l2cap.h
>> @@ -33,7 +33,7 @@
>>  #define L2CAP_DEFAULT_FLUSH_TO		0xffff
>>  #define L2CAP_DEFAULT_TX_WINDOW		63
>>  #define L2CAP_DEFAULT_MAX_TX		3
>> -#define L2CAP_DEFAULT_RETRANS_TO	1000    /* 1 second */
>> +#define L2CAP_DEFAULT_RETRANS_TO	2000    /* 2 seconds */
>>  #define L2CAP_DEFAULT_MONITOR_TO	12000   /* 12 seconds */
>>  #define L2CAP_DEFAULT_MAX_PDU_SIZE	672
>>  #define L2CAP_DEFAULT_ACK_TO		200
>
> The spec says that a 2 seconds retransmission timeout shall be used
> after a move channel operation in a BR/EDR radio. (section 8.6.2.3)
> For a normal ACL connection the default value is 1 second(section
> 8.6.2.1), so I prefer to keep L2CAP_DEFAULT_RETRANS_TO set to 1000.

Section 8.6.2.1 reads:

"If a flush timeout does not exist on the BR/EDR link for the channel 
using Enhanced Retransmission mode, then the value for the 
Retransmission timeout shall be at least two seconds..."

That is followed by the rule for channels with a flush timeout, which 
requires the retrans timeout to be the larger of flushTO * 3 or 1 
second.  Since BlueZ does not configure the flush timeout for BR/EDR 
links, the 2 second rule applies.

I experienced interoperability problems with ERTM on the BM3 Bluetooth 
stack and the 1-second timeout - the one second timeout was not long 
enough to allow for all the transmit buffering in BlueZ (all frames to 
fill the TX window are immediately pushed to the HCI TX queue).  I'd 
like to discuss changing the way ERTM queues data to HCI, but that's a 
separate topic - maybe something to chat about in Boston.


Regards,

--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply

* Re: [PATCH][RFC] Fix SDP resolving segfault
From: Manuel Naranjo @ 2010-08-05 14:48 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: Johan Hedberg, BlueZ
In-Reply-To: <4C587AFF.7060402@aircable.net>

Luiz,

>> This looks like a different issue, at least it doesn't seems to crash
>> in the same point, so I assume the patch does fix something but
>> uncover another problem. But we have to find out where exactly is this
>> other problem because btd_device_unref doesn't seems to be the place,
>> can't you get any core dumps from the tests you did?
>>
>
> I agree it looks like it triggered another issue, I will try to get logs
> tomorrow.
>

Here's the call trace, unfortunately I don't have bluetoothd debug
messages, just this
	+  0 0x804e4ea (from 0x7e0dab)  watch_func():
/home/manuel/bluez/gdbus/mainloop.c:94
	+  1 0x804ea3b (from 0x7140dd)   dispatch_status():
/home/manuel/bluez/gdbus/mainloop.c:244
	+  2 0x804e49b (from 0x804ea7d)    queue_dispatch():
/home/manuel/bluez/gdbus/mainloop.c:87
	+  0 0x804e436 (from 0x7aa53c)  message_dispatch():
/home/manuel/bluez/gdbus/mainloop.c:73
	+  1 0x8050fa1 (from 0x716c8d)   message_filter():
/home/manuel/bluez/gdbus/watch.c:408
	+  1 0x804f506 (from 0x723f13)   generic_message():
/home/manuel/bluez/gdbus/object.c:236
	+  2 0x804f483 (from 0x804f549)    find_interface():
/home/manuel/bluez/gdbus/object.c:219
	+  2 0x80a4d46 (from 0x804f5cb)    adapter_start_discovery():
/home/manuel/bluez/src/adapter.c:1215
	+  3 0x80a354c (from 0x80a4da5)     find_session():
/home/manuel/bluez/src/adapter.c:621
	+  3 0x80a4cce (from 0x80a4dfa)     adapter_start_inquiry():
/home/manuel/bluez/src/adapter.c:1203
	+  4 0x80a2744 (from 0x80a4d0c)      pending_remote_name_cancel():
/home/manuel/bluez/src/adapter.c:263
	+  5 0x80a208d (from 0x80a27aa)       bacpy():
/home/manuel/bluez/./lib/bluetooth/bluetooth.h:132
	+  5 0x80a8b8e (from 0x80a27c3)       adapter_search_found_devices():
/home/manuel/bluez/src/adapter.c:2667
	+  4 0x808831a (from 0x80a4d29)      hciops_start_discovery():
/home/manuel/bluez/plugins/hciops.c:570
	+  3 0x80a2de5 (from 0x80a4e45)     create_session():
/home/manuel/bluez/src/adapter.c:425
	+  4 0x80514c7 (from 0x80a2ea9)      g_dbus_add_disconnect_watch():
/home/manuel/bluez/gdbus/watch.c:572
	+  5 0x80513cc (from 0x8051510)       g_dbus_add_service_watch():
/home/manuel/bluez/gdbus/watch.c:544
	+  6 0x8050753 (from 0x8051430)        filter_data_get():
/home/manuel/bluez/gdbus/watch.c:177
	+  7 0x80502a8 (from 0x80507a0)         filter_data_find():
/home/manuel/bluez/gdbus/watch.c:69
	+  7 0x80502a8 (from 0x8050803)         filter_data_find():
/home/manuel/bluez/gdbus/watch.c:69
	+  7 0x8050572 (from 0x80508a4)         add_match():
/home/manuel/bluez/gdbus/watch.c:134
	+  8 0x8050402 (from 0x80505cc)          format_rule():
/home/manuel/bluez/gdbus/watch.c:111
	+  8 0x804e8bd (from 0x729783)          add_timeout():
/home/manuel/bluez/gdbus/mainloop.c:207
	+  8 0x804ea3b (from 0x7140dd)          dispatch_status():
/home/manuel/bluez/gdbus/mainloop.c:244
	+  9 0x804e49b (from 0x804ea7d)           queue_dispatch():
/home/manuel/bluez/gdbus/mainloop.c:87
	+  8 0x804e96c (from 0x7296ff)          remove_timeout():
/home/manuel/bluez/gdbus/mainloop.c:227
	+  8 0x804e85f (from 0x729469)          timeout_handler_free():
/home/manuel/bluez/gdbus/mainloop.c:195
	+  6 0x8050af5 (from 0x8051470)        filter_data_add_callback():
/home/manuel/bluez/gdbus/watch.c:272
	+  4 0x8089ea8 (from 0x80a2ee4)      info(): /home/manuel/bluez/src/log.c:36
	+  4 0x80a2d65 (from 0x80a2eef)      session_ref():
/home/manuel/bluez/src/adapter.c:416
	+  5 0x8089f44 (from 0x80a2dc7)       btd_debug():
/home/manuel/bluez/src/log.c:58
	+  0 0x808c945 (from 0x7e0dab)  io_security_event():
/home/manuel/bluez/src/security.c:967
	+  1 0x808a32d (from 0x808caa9)   hci_test_bit():
/home/manuel/bluez/./lib/bluetooth/hci_lib.h:167
	+  1 0x808bc97 (from 0x808cb24)   cmd_complete():
/home/manuel/bluez/src/security.c:690
	+  2 0x808b951 (from 0x808bd70)    start_inquiry():
/home/manuel/bluez/src/security.c:570
	+  3 0x80a1a5d (from 0x808b9a0)     manager_find_adapter():
/home/manuel/bluez/src/manager.c:343
	+  4 0x80a1955 (from 0x7c947e)      adapter_cmp():
/home/manuel/bluez/src/manager.c:319
	+  5 0x80a89ca (from 0x80a198d)       adapter_get_address():
/home/manuel/bluez/src/adapter.c:2625
	+  6 0x80a208d (from 0x80a89f8)        bacpy():
/home/manuel/bluez/./lib/bluetooth/bluetooth.h:132
	+  5 0x80a1000 (from 0x80a199f)       bacmp():
/home/manuel/bluez/./lib/bluetooth/bluetooth.h:128
	+  3 0x80a8b15 (from 0x808b9ca)     adapter_get_state():
/home/manuel/bluez/src/adapter.c:2657
	+  3 0x80a995b (from 0x808b9d8)     adapter_has_discov_sessions():
/home/manuel/bluez/src/adapter.c:3021
	+  3 0x80a8a0d (from 0x808b9fc)     adapter_set_state():
/home/manuel/bluez/src/adapter.c:2630
	+  4 0x80b0b44 (from 0x80a8aeb)      emit_property_changed():
/home/manuel/bluez/src/dbus-common.c:266
	+  5 0x80b086d (from 0x80b0be0)       append_variant():
/home/manuel/bluez/src/dbus-common.c:195
	+  5 0x805005d (from 0x80b0bf2)       g_dbus_send_message():
/home/manuel/bluez/gdbus/object.c:615
	+  1 0x808a82f (from 0x808cdb4)   check_pending_hci_req():
/home/manuel/bluez/src/security.c:186
	+  0 0x808c945 (from 0x7e0dab)  io_security_event():
/home/manuel/bluez/src/security.c:967
	+  1 0x808a32d (from 0x808caa9)   hci_test_bit():
/home/manuel/bluez/./lib/bluetooth/hci_lib.h:167
	+  1 0x808bc30 (from 0x808cafa)   cmd_status():
/home/manuel/bluez/src/security.c:681
	+  1 0x808a82f (from 0x808cdb4)   check_pending_hci_req():
/home/manuel/bluez/src/security.c:186
	+  0 0x808c945 (from 0x7e0dab)  io_security_event():
/home/manuel/bluez/src/security.c:967
	+  1 0x808a32d (from 0x808caa9)   hci_test_bit():
/home/manuel/bluez/./lib/bluetooth/hci_lib.h:167
	+  1 0x808c6e1 (from 0x808cd1b)   disconn_complete():
/home/manuel/bluez/src/security.c:916
	+  2 0x80b2947 (from 0x808c734)    hcid_dbus_disconn_complete():
/home/manuel/bluez/src/dbus-hci.c:779
	+  3 0x80a1a5d (from 0x80b29a3)     manager_find_adapter():
/home/manuel/bluez/src/manager.c:343
	+  4 0x80a1955 (from 0x7c947e)      adapter_cmp():
/home/manuel/bluez/src/manager.c:319
	+  5 0x80a89ca (from 0x80a198d)       adapter_get_address():
/home/manuel/bluez/src/adapter.c:2625
	+  6 0x80a208d (from 0x80a89f8)        bacpy():
/home/manuel/bluez/./lib/bluetooth/bluetooth.h:132
	+  5 0x80a1000 (from 0x80a199f)       bacmp():
/home/manuel/bluez/./lib/bluetooth/bluetooth.h:128
	+  3 0x80a45fd (from 0x80b29d2)     adapter_find_connection():
/home/manuel/bluez/src/adapter.c:1025
	+  4 0x80ac5b0 (from 0x80a4644)      device_has_connection():
/home/manuel/bluez/src/device.c:934
	+  3 0x80a97f0 (from 0x80b2a2c)     adapter_remove_connection():
/home/manuel/bluez/src/adapter.c:2992
	+  4 0x80ac472 (from 0x80a9864)      device_remove_connection():
/home/manuel/bluez/src/device.c:908
	+  5 0x80ac306 (from 0x80ac58f)       device_set_connected():
/home/manuel/bluez/src/device.c:875
	+  6 0x80b0b44 (from 0x80ac353)        emit_property_changed():
/home/manuel/bluez/src/dbus-common.c:266
	+  7 0x80b086d (from 0x80b0be0)         append_variant():
/home/manuel/bluez/src/dbus-common.c:195
	+  7 0x805005d (from 0x80b0bf2)         g_dbus_send_message():
/home/manuel/bluez/gdbus/object.c:615
	+  4 0x80ae44a (from 0x80a9891)      device_get_address():
/home/manuel/bluez/src/device.c:1654
	+  5 0x80aa3e0 (from 0x80ae475)       bacpy():
/home/manuel/bluez/./lib/bluetooth/bluetooth.h:132
	+  4 0x808a77f (from 0x80a98a9)      hci_req_queue_remove():
/home/manuel/bluez/src/security.c:169
	+  4 0x80afe26 (from 0x80a98b4)      device_is_authenticating():
/home/manuel/bluez/src/device.c:2339
	+  4 0x80ae585 (from 0x80a98d6)      device_is_temporary():
/home/manuel/bluez/src/device.c:1683
	+  1 0x808a82f (from 0x808cdb4)   check_pending_hci_req():
/home/manuel/bluez/src/security.c:186
	+  0 0x8099459 (from 0x7e0dab)  connect_watch():
/home/manuel/bluez/src/glib-helper.c:257
	+  1 0x80ae001 (from 0x809963a)   browse_cb():
/home/manuel/bluez/src/device.c:1540

I think it keeps crashing the same way, when browse_cb gets called
user_data points to non valid data.

Manuel

^ permalink raw reply

* [PATCH] Fix not deleting stored keys when a new one is created
From: Luiz Augusto von Dentz @ 2010-08-05 13:58 UTC (permalink / raw)
  To: linux-bluetooth

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

When a new link key is created but it doesn't match any criteria to be
stored any previouly one should be removed from filesystem.

This can be reproduced by the following steps:

1. Pair devices normally so that a valid link key is stored
2. Remove link key on remote device
3. Attempt to do a rfcomm connection with security level higher than low

This can be triggered in some other ways but right now this is the
easiest since kernel will switch the authentication requirements in this
case, here is the hcidump output:

< HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9
  bdaddr xx:xx:xx:xx:xx:xx capability 0x01 oob 0x00 auth 0x00
  Capability: DisplayYesNo (OOB data not present)
  Authentication: No Bonding (No MITM Protection)
...
> HCI Event: Link Key Notification (0x18) plen 23
  bdaddr xx:xx:xx:xx:xx:xx key 26D32FBEF7B7CBD7923CA391A2DE600F type 4
  Type: Unauthenticated Combination Key
...
< HCI Command: Link Key Request Reply (0x01|0x000b) plen 22
  bdaddr xx:xx:xx:xx:xx:xx key 38E2BC10B26148FBC264E0DBA2535F1B
> HCI Event: Auth Complete (0x06) plen 3
  status 0x05 handle 1
Error: Authentication Failure

Note that the reason this is reproducible with a single rfcomm connection
might be a bug in kernel, but there is clearly a problem in the daemon
too since link keys doesn't match.

So link keys information should be available while connected even in
cases where bonding is not required, to fix this everytime there is a new
link key the old one is clear, to make sure this actually work with those
keys that are not stored persistently all keys are cached in memory so
they are always accessible via device object as long the object exists,
this changes should also enable the code path bellow:

	/* Don't use unauthenticated combination keys if MITM is
	 * required */
	if (type == 0x04 && req.type != 0xff && (req.type & 0x01))

and follow the recommendation of the simple pairing white paper which
says:

	"Bonding is defined as the connection process where the link key
	and connection information are stored in non-volatile memory.
	Thus bonding implies that the device’s link information is
	available after the current connection ceases. If the link key
	and current connection information are not stored, then the
	connection process uses “Pairing”"

Devices which link key is not permanently stored are currently being
marked as temporary so their information will be lost once the connection
ceases.
---
 src/dbus-hci.c |   23 +++++++++++------------
 src/device.c   |   31 ++++++++++++++++---------------
 src/device.h   |    5 +++--
 src/security.c |    5 ++---
 4 files changed, 32 insertions(+), 32 deletions(-)

diff --git a/src/dbus-hci.c b/src/dbus-hci.c
index b83506f..c8b2ad6 100644
--- a/src/dbus-hci.c
+++ b/src/dbus-hci.c
@@ -674,11 +674,12 @@ int hcid_dbus_link_key_notify(bdaddr_t *local, bdaddr_t *peer,
 	if (!get_adapter_and_device(local, peer, &adapter, &device, TRUE))
 		return -ENODEV;
 
+	/* Check if there is a key cached in memory */
+	device_get_key(device, NULL, &old_key_type);
+
 	new_key_type = key_type;
 
 	if (key_type == 0x06) {
-		if (device_get_debug_key(device, NULL))
-			old_key_type = 0x03;
 		if (old_key_type != 0xff)
 			new_key_type = old_key_type;
 		else
@@ -697,12 +698,11 @@ int hcid_dbus_link_key_notify(bdaddr_t *local, bdaddr_t *peer,
 	DBG("local auth 0x%02x and remote auth 0x%02x",
 					local_auth, remote_auth);
 
-	/* Clear any previous debug key */
-	device_set_debug_key(device, NULL);
+	/* Cache new link key */
+	device_set_key(device, key, new_key_type);
 
-	/* Store the link key only in runtime memory if it's a debug
-	 * key, else store the link key persistently if one of the
-	 * following is true:
+	/* Link key are ALWAYS stored in runtime memory, they are also stored
+	 * in filesystem persistently if one of the following is true:
 	 * 1. this is a legacy link key
 	 * 2. this is a changed combination key and there was a previously
 	 *    stored one
@@ -710,13 +710,12 @@ int hcid_dbus_link_key_notify(bdaddr_t *local, bdaddr_t *peer,
 	 * 4. the local side had dedicated bonding as a requirement
 	 * 5. the remote side is using dedicated bonding since in that case
 	 *    also the local requirements are set to dedicated bonding
-	 * If none of the above match only keep the link key around for
+	 * If none of the above match and only keep the link key around for
 	 * this connection and set the temporary flag for the device.
 	 */
-	if (new_key_type == 0x03) {
-		DBG("Storing debug key in runtime memory");
-		device_set_debug_key(device, key);
-	} else if (key_type < 0x03 ||
+	if (new_key_type == 0x03)
+		temporary = FALSE;
+	else if (key_type < 0x03 ||
 				(key_type == 0x06 && old_key_type != 0xff) ||
 				(local_auth > 0x01 && remote_auth > 0x01) ||
 				(local_auth == 0x02 || local_auth == 0x03) ||
diff --git a/src/device.c b/src/device.c
index 6af76d1..059aec3 100644
--- a/src/device.c
+++ b/src/device.c
@@ -143,8 +143,8 @@ struct btd_device {
 	gboolean	authorizing;
 	gint		ref;
 
-	gboolean	has_debug_key;
-	uint8_t		debug_key[16];
+	uint8_t		key[16];
+	uint8_t		key_type;
 };
 
 static uint16_t uuid_list[] = {
@@ -1024,7 +1024,8 @@ struct btd_device *device_create(DBusConnection *conn,
 
 	device->auth = 0xff;
 
-	if (read_link_key(&src, &device->bdaddr, NULL, NULL) == 0)
+	if (read_link_key(&src, &device->bdaddr, device->key,
+						&device->key_type) == 0)
 		device->paired = TRUE;
 
 	return btd_device_ref(device);
@@ -2399,26 +2400,26 @@ const sdp_record_t *btd_device_get_record(struct btd_device *device,
 	return find_record_in_list(device->tmp_records, uuid);
 }
 
-gboolean device_set_debug_key(struct btd_device *device, uint8_t *key)
+void device_set_key(struct btd_device *device, uint8_t *key, uint8_t type)
 {
-	if (key == NULL) {
-		device->has_debug_key = FALSE;
-		return TRUE;
-	}
-
-	memcpy(device->debug_key, key, 16);
-	device->has_debug_key = TRUE;
+	/* Clear any previous key */
+	if (device->paired)
+		device_remove_bonding(device);
 
-	return TRUE;
+	memcpy(device->key, key, 16);
+	device->key_type = type;
 }
 
-gboolean device_get_debug_key(struct btd_device *device, uint8_t *key)
+gboolean device_get_key(struct btd_device *device, uint8_t *key, uint8_t *type)
 {
-	if (!device->has_debug_key)
+	if (!device->paired)
 		return FALSE;
 
 	if (key != NULL)
-		memcpy(key, device->debug_key, 16);
+		memcpy(key, device->key, 16);
+
+	if (type != NULL)
+		*type = device->key_type;
 
 	return TRUE;
 }
diff --git a/src/device.h b/src/device.h
index 5f75e61..229bc9e 100644
--- a/src/device.h
+++ b/src/device.h
@@ -79,8 +79,9 @@ gboolean device_is_authenticating(struct btd_device *device);
 gboolean device_is_authorizing(struct btd_device *device);
 void device_set_authorizing(struct btd_device *device, gboolean auth);
 void device_set_renewed_key(struct btd_device *device, gboolean renewed);
-gboolean device_set_debug_key(struct btd_device *device, uint8_t *key);
-gboolean device_get_debug_key(struct btd_device *device, uint8_t *key);
+void device_set_key(struct btd_device *device, uint8_t *key, uint8_t type);
+gboolean device_get_key(struct btd_device *device, uint8_t *key,
+								uint8_t *type);
 void device_add_connection(struct btd_device *device, DBusConnection *conn,
 				uint16_t handle);
 void device_remove_connection(struct btd_device *device, DBusConnection *conn,
diff --git a/src/security.c b/src/security.c
index ca394e1..9d9e26f 100644
--- a/src/security.c
+++ b/src/security.c
@@ -329,9 +329,8 @@ static void link_key_request(int dev, bdaddr_t *sba, bdaddr_t *dba)
 
 	DBG("kernel auth requirements = 0x%02x", req.type);
 
-	if (main_opts.debug_keys && device && device_get_debug_key(device, key))
-		type = 0x03;
-	else if (read_link_key(sba, dba, key, &type) < 0 || type == 0x03) {
+	if (device_get_key(device, key, &type) == FALSE ||
+			(type == 0x03 && main_opts.debug_keys == FALSE)) {
 		/* Link key not found */
 		hci_send_cmd(dev, OGF_LINK_CTL, OCF_LINK_KEY_NEG_REPLY, 6, dba);
 		return;
-- 
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