Linux bluetooth development
 help / color / mirror / Atom feed
* Re: A problem with "rfcomm bind" and wvdial
From: Gianluca Anzolin @ 2014-01-06 11:33 UTC (permalink / raw)
  To: andrey.vihrov; +Cc: peter, marcel, gregkh, jslaby, linux-bluetooth
In-Reply-To: <20140105154942.GA12621@sottospazio.it>

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

On Sun, Jan 05, 2014 at 04:49:42PM +0100, Gianluca Anzolin wrote:
> Hello,
> 
> I looked at your problem this afternoon and I think I know what's happening:
> wvdial is opening the port with the flag O_NONBLOCK. As expected the rfcomm
> code returns immediately instead of waiting for the BT connection to come
> up. Then wvdial sends the AT commands and the writes fail.

Hi,

could you please test the attached patch?

If it works and people are ok with it I'll submit it along with the other fixes
I already sent to the list.

Thank you,
Gianluca

[-- Attachment #2: 0001-rfcomm-always-wait-for-a-bt-connection-on-open.patch --]
[-- Type: text/x-diff, Size: 5303 bytes --]

>From 2da1095aceb22bc323ceb9e1a4f43d92ebe5c2b6 Mon Sep 17 00:00:00 2001
From: Gianluca Anzolin <gianluca@sottospazio.it>
Date: Mon, 6 Jan 2014 12:19:51 +0100
Subject: [PATCH] rfcomm: always wait for a bt connection on open()

This patch fixes a regression introduced with the recent rfcomm tty
rework.

The current code uses the carrier_raised() method to wait for the
bluetooth connection when a process opens the tty. However processes may
open the port with the O_NONBLOCK flag or set the CLOCAL termios flag.

In those cases the open() syscall returns immediately without waiting
for the bluetooth connection to complete. This behaviour confuses
userspace which expects a working bluetooth connection.

The patch removes the carries_raised() method and restores the previous
working behaviour by waiting for the connection in rfcomm_dev_activate().

Signed-off-by: Gianluca Anzolin <gianluca@sottospazio.it>
Reported-by: Andrey Vihrov <andrey.vihrov@gmail.com>
---
 net/bluetooth/rfcomm/tty.c | 79 ++++++++++++++++++++++++++++------------------
 1 file changed, 49 insertions(+), 30 deletions(-)

diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 84fcf9f..e9683bb 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -58,6 +58,7 @@ struct rfcomm_dev {
 	uint			modem_status;
 
 	struct rfcomm_dlc	*dlc;
+	wait_queue_head_t       conn_wait;
 
 	struct device		*tty_dev;
 
@@ -103,20 +104,57 @@ static void rfcomm_dev_destruct(struct tty_port *port)
 	module_put(THIS_MODULE);
 }
 
-/* device-specific initialization: open the dlc */
-static int rfcomm_dev_activate(struct tty_port *port, struct tty_struct *tty)
+static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
 {
-	struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port);
+	struct hci_dev *hdev;
+	struct hci_conn *conn;
+
+	hdev = hci_get_route(&dev->dst, &dev->src);
+	if (!hdev)
+		return NULL;
+
+	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst);
+
+	hci_dev_put(hdev);
 
-	return rfcomm_dlc_open(dev->dlc, &dev->src, &dev->dst, dev->channel);
+	return conn ? &conn->dev : NULL;
 }
 
-/* we block the open until the dlc->state becomes BT_CONNECTED */
-static int rfcomm_dev_carrier_raised(struct tty_port *port)
+/* device-specific initialization: open the dlc */
+static int rfcomm_dev_activate(struct tty_port *port, struct tty_struct *tty)
 {
 	struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port);
+	DEFINE_WAIT(wait);
+	int err;
 
-	return (dev->dlc->state == BT_CONNECTED);
+	err = rfcomm_dlc_open(dev->dlc, &dev->src, &dev->dst, dev->channel);
+	if (err)
+		return err;
+
+	while (1) {
+		prepare_to_wait(&dev->conn_wait, &wait, TASK_INTERRUPTIBLE);
+
+		if (dev->dlc->state == BT_CLOSED) {
+			err = -dev->err;
+			break;
+		} else if (dev->dlc->state == BT_CONNECTED)
+			break;
+		else if (signal_pending(current)) {
+			err = -ERESTARTSYS;
+			break;
+		}
+
+		tty_unlock(tty);
+		schedule();
+		tty_lock(tty);
+	}
+	finish_wait(&dev->conn_wait, &wait);
+
+	if (!err)
+		device_move(dev->tty_dev, rfcomm_get_device(dev),
+			    DPM_ORDER_DEV_AFTER_PARENT);
+
+	return err;
 }
 
 /* device-specific cleanup: close the dlc */
@@ -135,7 +173,6 @@ static const struct tty_port_operations rfcomm_port_ops = {
 	.destruct = rfcomm_dev_destruct,
 	.activate = rfcomm_dev_activate,
 	.shutdown = rfcomm_dev_shutdown,
-	.carrier_raised = rfcomm_dev_carrier_raised,
 };
 
 static struct rfcomm_dev *__rfcomm_dev_get(int id)
@@ -169,22 +206,6 @@ static struct rfcomm_dev *rfcomm_dev_get(int id)
 	return dev;
 }
 
-static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
-{
-	struct hci_dev *hdev;
-	struct hci_conn *conn;
-
-	hdev = hci_get_route(&dev->dst, &dev->src);
-	if (!hdev)
-		return NULL;
-
-	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst);
-
-	hci_dev_put(hdev);
-
-	return conn ? &conn->dev : NULL;
-}
-
 static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf)
 {
 	struct rfcomm_dev *dev = dev_get_drvdata(tty_dev);
@@ -258,6 +279,7 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
 
 	tty_port_init(&dev->port);
 	dev->port.ops = &rfcomm_port_ops;
+	init_waitqueue_head(&dev->conn_wait);
 
 	skb_queue_head_init(&dev->pending);
 
@@ -575,12 +597,9 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
 	BT_DBG("dlc %p dev %p err %d", dlc, dev, err);
 
 	dev->err = err;
-	if (dlc->state == BT_CONNECTED) {
-		device_move(dev->tty_dev, rfcomm_get_device(dev),
-			    DPM_ORDER_DEV_AFTER_PARENT);
+	wake_up_interruptible(&dev->conn_wait);
 
-		wake_up_interruptible(&dev->port.open_wait);
-	} else if (dlc->state == BT_CLOSED)
+	if (dlc->state == BT_CLOSED)
 		tty_port_tty_hangup(&dev->port, false);
 }
 
@@ -1096,7 +1115,7 @@ int __init rfcomm_init_ttys(void)
 	rfcomm_tty_driver->subtype	= SERIAL_TYPE_NORMAL;
 	rfcomm_tty_driver->flags	= TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
 	rfcomm_tty_driver->init_termios	= tty_std_termios;
-	rfcomm_tty_driver->init_termios.c_cflag	= B9600 | CS8 | CREAD | HUPCL;
+	rfcomm_tty_driver->init_termios.c_cflag	= B9600 | CS8 | CREAD | HUPCL | CLOCAL;
 	rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON;
 	tty_set_operations(rfcomm_tty_driver, &rfcomm_ops);
 
-- 
1.8.5.2


^ permalink raw reply related

* [PATCH] unit: Fix test failures with glib 2.39.0
From: Colin Watson @ 2014-01-06 12:07 UTC (permalink / raw)
  To: linux-bluetooth

glib 2.39.0 made this change:

   - g_source_remove() will now throw a critical in the case that you
     try to remove a non-existent source.  We expect that there is some
     code in the wild that will fall afoul of this new critical but
     considering that we now reuse source IDs, this code is already
     broken and should probably be fixed.

This patch fixes the test suite to keep better track of whether sources have
already been removed and avoid double-removals.
---
 unit/test-avdtp.c          |  8 ++++++--
 unit/test-gobex-transfer.c |  6 ++++--
 unit/test-gobex.c          | 13 ++++++++-----
 unit/util.c                |  1 +
 unit/util.h                |  1 +
 5 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/unit/test-avdtp.c b/unit/test-avdtp.c
index 66c45f3..6e51313 100644
--- a/unit/test-avdtp.c
+++ b/unit/test-avdtp.c
@@ -143,6 +143,7 @@ static gboolean send_pdu(gpointer user_data)
 	if (pdu->fragmented)
 		return send_pdu(user_data);
 
+	context->process = 0;
 	return FALSE;
 }
 
@@ -178,8 +179,10 @@ static gboolean test_handler(GIOChannel *channel, GIOCondition cond,
 
 	pdu = &context->data->pdu_list[context->pdu_offset++];
 
-	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
+	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
+		context->source = 0;
 		return FALSE;
+	}
 
 	fd = g_io_channel_unix_get_fd(channel);
 
@@ -258,7 +261,8 @@ static void execute_context(struct context *context)
 {
 	g_main_loop_run(context->main_loop);
 
-	g_source_remove(context->source);
+	if (context->source > 0)
+		g_source_remove(context->source);
 	avdtp_unref(context->session);
 
 	g_main_loop_unref(context->main_loop);
diff --git a/unit/test-gobex-transfer.c b/unit/test-gobex-transfer.c
index ef05047..128a467 100644
--- a/unit/test-gobex-transfer.c
+++ b/unit/test-gobex-transfer.c
@@ -1805,7 +1805,8 @@ static void test_conn_rsp(void)
 
 	g_source_remove(timer_id);
 	g_io_channel_unref(io);
-	g_source_remove(io_id);
+	if (!d.io_completed)
+		g_source_remove(io_id);
 	g_obex_unref(obex);
 
 	g_assert_no_error(d.err);
@@ -2060,7 +2061,8 @@ static void test_conn_get_wrg_rsp(void)
 
 	g_source_remove(timer_id);
 	g_io_channel_unref(io);
-	g_source_remove(io_id);
+	if (!d.io_completed)
+		g_source_remove(io_id);
 	g_obex_unref(obex);
 
 	g_assert_no_error(d.err);
diff --git a/unit/test-gobex.c b/unit/test-gobex.c
index 66307c2..ded83dd 100644
--- a/unit/test-gobex.c
+++ b/unit/test-gobex.c
@@ -235,7 +235,7 @@ static void send_req(GObexPacket *req, GObexResponseFunc rsp_func,
 	GError *gerr = NULL;
 	GIOChannel *io;
 	GIOCondition cond;
-	guint io_id, timer_id, test_time;
+	guint timer_id, test_time;
 	GObex *obex;
 
 	create_endpoints(&obex, &io, transport_type);
@@ -244,7 +244,7 @@ static void send_req(GObexPacket *req, GObexResponseFunc rsp_func,
 	g_assert_no_error(gerr);
 
 	cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
-	io_id = g_io_add_watch(io, cond, send_rsp_func, &gerr);
+	g_io_add_watch(io, cond, send_rsp_func, &gerr);
 
 	mainloop = g_main_loop_new(NULL, FALSE);
 
@@ -262,7 +262,6 @@ static void send_req(GObexPacket *req, GObexResponseFunc rsp_func,
 
 	g_source_remove(timer_id);
 	g_io_channel_unref(io);
-	g_source_remove(io_id);
 	g_obex_unref(obex);
 
 	g_assert_no_error(gerr);
@@ -466,6 +465,7 @@ struct rcv_buf_info {
 	GError *err;
 	const guint8 *buf;
 	gsize len;
+	gboolean completed;
 };
 
 static gboolean rcv_data(GIOChannel *io, GIOCondition cond, gpointer user_data)
@@ -505,6 +505,7 @@ static gboolean rcv_data(GIOChannel *io, GIOCondition cond, gpointer user_data)
 
 done:
 	g_main_loop_quit(mainloop);
+	r->completed = TRUE;
 	return FALSE;
 }
 
@@ -546,7 +547,8 @@ static void test_send_connect(int transport_type)
 
 	g_source_remove(timer_id);
 	g_io_channel_unref(io);
-	g_source_remove(io_id);
+	if (!r.completed)
+		g_source_remove(io_id);
 	g_obex_unref(obex);
 
 	g_assert_no_error(r.err);
@@ -661,7 +663,8 @@ static void test_send_on_demand(int transport_type, GObexDataProducer func)
 
 	g_source_remove(timer_id);
 	g_io_channel_unref(io);
-	g_source_remove(io_id);
+	if (!r.completed)
+		g_source_remove(io_id);
 	g_obex_unref(obex);
 
 	g_assert_no_error(r.err);
diff --git a/unit/util.c b/unit/util.c
index c76acdf..71fe7ca 100644
--- a/unit/util.c
+++ b/unit/util.c
@@ -193,5 +193,6 @@ send:
 
 failed:
 	g_main_loop_quit(d->mainloop);
+	d->io_completed = TRUE;
 	return FALSE;
 }
diff --git a/unit/util.h b/unit/util.h
index 752ce61..96528a6 100644
--- a/unit/util.h
+++ b/unit/util.h
@@ -41,6 +41,7 @@ struct test_data {
 	guint id;
 	gsize total;
 	GMainLoop *mainloop;
+	gboolean io_completed;
 };
 
 #define TEST_ERROR test_error_quark()
-- 
1.8.5.2

^ permalink raw reply related

* Re: [RFC v5 00/14] LE auto connection and connection parameters
From: Andre Guedes @ 2014-01-06 13:24 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1387540675-2466-1-git-send-email-andre.guedes@openbossa.org>

Ping.

On Fri, 2013-12-20 at 08:57 -0300, Andre Guedes wrote:
> Hi all,
> 
> This patch set is pretty much the same of previous one, except it implements
> a different approach to handle discovery and LE connection (as discussed on
> "[RFC v4 05/12] Bluetooth: Stop scanning on LE connection").
> 
> Regards,
> 
> Andre
> 
> 
> Andre Guedes (14):
>   Bluetooth: Save connection interval parameters in hci_conn
>   Bluetooth: Group list_head fields from strcut hci_dev together
>   Bluetooth: Introduce connection parameters list
>   Bluetooth: Use connection parameters if any
>   Bluetooth: Introduce fail_conn_attempt() helper
>   Bluetooth: Stop scanning on LE connection
>   Bluetooth: Remove unused function
>   Bluetooth: Introduce hdev->pend_le_conn list
>   Bluetooth: Introduce LE auto connection infrastructure
>   Bluetooth: Re-enable background scan in case of error
>   Bluetooth: Temporarily stop background scanning on discovery
>   Bluetooth: Auto connection and power on
>   Bleutooth: Add support for auto connect options
>   Bluetooth: Add le_auto_conn file on debugfs
> 
>  include/net/bluetooth/hci.h      |   1 +
>  include/net/bluetooth/hci_core.h |  43 +++++-
>  net/bluetooth/hci_conn.c         | 111 +++++++++++---
>  net/bluetooth/hci_core.c         | 318 +++++++++++++++++++++++++++++++++++++++
>  net/bluetooth/hci_event.c        |  60 ++++++++
>  net/bluetooth/mgmt.c             |  25 ++-
>  6 files changed, 530 insertions(+), 28 deletions(-)
> 



^ permalink raw reply

* Re: A problem with "rfcomm bind" and wvdial
From: Andrey Vihrov @ 2014-01-06 16:06 UTC (permalink / raw)
  To: Gianluca Anzolin; +Cc: peter, marcel, gregkh, jslaby, linux-bluetooth
In-Reply-To: <20140106113353.GA21381@sottospazio.it>

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

Hello,

Thanks for the update. I applied the patch to the bluetooth-next
kernel and it seems to work as expected. I ran wvdial several times in a
row, and it was able to connect every time.

> On Sun, Jan 05, 2014 at 04:49:42PM +0100, Gianluca Anzolin wrote:
> > Hello,
> > 
> > I looked at your problem this afternoon and I think I know what's happening:
> > wvdial is opening the port with the flag O_NONBLOCK. As expected the rfcomm
> > code returns immediately instead of waiting for the BT connection to come
> > up. Then wvdial sends the AT commands and the writes fail.
> 
> Hi,
> 
> could you please test the attached patch?
> 
> If it works and people are ok with it I'll submit it along with the other fixes
> I already sent to the list.
> 
> Thank you,
> Gianluca

-- 
Andrey Vihrov <andrey.vihrov@gmail.com>


[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply

* [PATCH 1/2] Bluetooth: Fix NULL pointer dereference when disconnecting
From: johan.hedberg @ 2014-01-06 16:27 UTC (permalink / raw)
  To: linux-bluetooth

From: Johan Hedberg <johan.hedberg@intel.com>

When disconnecting it is possible that the l2cap_conn pointer is already
NULL when bt_6lowpan_del_conn() is entered. Looking at l2cap_conn_del
also verifies this as there's a NULL check there too. This patch adds
the missing NULL check without which the following bug may occur:

BUG: unable to handle kernel NULL pointer dereference at   (null)
IP: [<c131e9c7>] bt_6lowpan_del_conn+0x19/0x12a
*pde = 00000000
Oops: 0000 [#1] SMP
CPU: 1 PID: 52 Comm: kworker/u5:1 Not tainted 3.12.0+ #196
Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
Workqueue: hci0 hci_rx_work
task: f6259b00 ti: f48c0000 task.ti: f48c0000
EIP: 0060:[<c131e9c7>] EFLAGS: 00010282 CPU: 1
EIP is at bt_6lowpan_del_conn+0x19/0x12a
EAX: 00000000 EBX: ef094e10 ECX: 00000000 EDX: 00000016
ESI: 00000000 EDI: f48c1e60 EBP: f48c1e50 ESP: f48c1e34
 DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
CR0: 8005003b CR2: 00000000 CR3: 30c65000 CR4: 00000690
Stack:
 f4d38000 00000000 f4d38000 00000002 ef094e10 00000016 f48c1e60 f48c1e70
 c1316bed f48c1e84 c1316bed 00000000 00000001 ef094e10 f48c1e84 f48c1ed0
 c1303cc6 c1303c7b f31f331a c1303cc6 f6e7d1c0 f3f8ea16 f3f8f380 f4d38008
Call Trace:
 [<c1316bed>] l2cap_disconn_cfm+0x3f/0x5b
 [<c1316bed>] ? l2cap_disconn_cfm+0x3f/0x5b
 [<c1303cc6>] hci_event_packet+0x645/0x2117
 [<c1303c7b>] ? hci_event_packet+0x5fa/0x2117
 [<c1303cc6>] ? hci_event_packet+0x645/0x2117
 [<c12681bd>] ? __kfree_skb+0x65/0x68
 [<c12681eb>] ? kfree_skb+0x2b/0x2e
 [<c130d3fb>] ? hci_send_to_sock+0x18d/0x199
 [<c12fa327>] hci_rx_work+0xf9/0x295
 [<c12fa327>] ? hci_rx_work+0xf9/0x295
 [<c1036d25>] process_one_work+0x128/0x1df
 [<c1346a39>] ? _raw_spin_unlock_irq+0x8/0x12
 [<c1036d25>] ? process_one_work+0x128/0x1df
 [<c103713a>] worker_thread+0x127/0x1c4
 [<c1037013>] ? rescuer_thread+0x216/0x216
 [<c103aec6>] kthread+0x88/0x8d
 [<c1040000>] ? task_rq_lock+0x37/0x6e
 [<c13474b7>] ret_from_kernel_thread+0x1b/0x28
 [<c103ae3e>] ? __kthread_parkme+0x50/0x50
Code: 05 b8 f4 ff ff ff 8d 65 f4 5b 5e 5f 5d 8d 67 f8 5f c3 57 8d 7c 24 08 83 e4 f8 ff 77 fc 55 89 e5 57 56f
EIP: [<c131e9c7>] bt_6lowpan_del_conn+0x19/0x12a SS:ESP 0068:f48c1e34
CR2: 0000000000000000

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 net/bluetooth/6lowpan.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index d84a3776095e..5f0b11d94d95 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -785,7 +785,7 @@ int bt_6lowpan_del_conn(struct l2cap_conn *conn)
 	unsigned long flags;
 	bool last = false;
 
-	if (!is_bt_6lowpan(conn->hcon))
+	if (!conn || !is_bt_6lowpan(conn->hcon))
 		return 0;
 
 	write_lock_irqsave(&devices_lock, flags);
-- 
1.8.4.2


^ permalink raw reply related

* [PATCH 2/2] Bluetooth: Default to no security with L2CAP RAW sockets
From: johan.hedberg @ 2014-01-06 16:27 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389025622-13891-1-git-send-email-johan.hedberg@gmail.com>

From: Johan Hedberg <johan.hedberg@intel.com>

L2CAP RAW sockets can be used for things which do not involve
establishing actual connection oriented L2CAP channels. One example of
such usage is the l2ping tool. The default security level for L2CAP
sockets is LOW, which implies that for SSP based connection
authentication is still requested (although with no MITM requirement),
which is not what we want (or need) for things like l2ping. Therefore,
default to one lower level, i.e. BT_SECURITY_SDP, for L2CAP RAW sockets
in order not to trigger unwanted authentication requests.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 net/bluetooth/l2cap_sock.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index e7806e6d282c..20ef748b2906 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -147,6 +147,9 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 		    __le16_to_cpu(la.l2_psm) == L2CAP_PSM_RFCOMM)
 			chan->sec_level = BT_SECURITY_SDP;
 		break;
+	case L2CAP_CHAN_RAW:
+		chan->sec_level = BT_SECURITY_SDP;
+		break;
 	}
 
 	bacpy(&chan->src, &la.l2_bdaddr);
-- 
1.8.4.2


^ permalink raw reply related

* Re: [PATCH 1/2] Bluetooth: Fix NULL pointer dereference when disconnecting
From: Marcel Holtmann @ 2014-01-06 17:27 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1389025622-13891-1-git-send-email-johan.hedberg@gmail.com>

Hi Johan,

> When disconnecting it is possible that the l2cap_conn pointer is already
> NULL when bt_6lowpan_del_conn() is entered. Looking at l2cap_conn_del
> also verifies this as there's a NULL check there too. This patch adds
> the missing NULL check without which the following bug may occur:
> 
> BUG: unable to handle kernel NULL pointer dereference at   (null)
> IP: [<c131e9c7>] bt_6lowpan_del_conn+0x19/0x12a
> *pde = 00000000
> Oops: 0000 [#1] SMP
> CPU: 1 PID: 52 Comm: kworker/u5:1 Not tainted 3.12.0+ #196
> Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
> Workqueue: hci0 hci_rx_work
> task: f6259b00 ti: f48c0000 task.ti: f48c0000
> EIP: 0060:[<c131e9c7>] EFLAGS: 00010282 CPU: 1
> EIP is at bt_6lowpan_del_conn+0x19/0x12a
> EAX: 00000000 EBX: ef094e10 ECX: 00000000 EDX: 00000016
> ESI: 00000000 EDI: f48c1e60 EBP: f48c1e50 ESP: f48c1e34
> DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
> CR0: 8005003b CR2: 00000000 CR3: 30c65000 CR4: 00000690
> Stack:
> f4d38000 00000000 f4d38000 00000002 ef094e10 00000016 f48c1e60 f48c1e70
> c1316bed f48c1e84 c1316bed 00000000 00000001 ef094e10 f48c1e84 f48c1ed0
> c1303cc6 c1303c7b f31f331a c1303cc6 f6e7d1c0 f3f8ea16 f3f8f380 f4d38008
> Call Trace:
> [<c1316bed>] l2cap_disconn_cfm+0x3f/0x5b
> [<c1316bed>] ? l2cap_disconn_cfm+0x3f/0x5b
> [<c1303cc6>] hci_event_packet+0x645/0x2117
> [<c1303c7b>] ? hci_event_packet+0x5fa/0x2117
> [<c1303cc6>] ? hci_event_packet+0x645/0x2117
> [<c12681bd>] ? __kfree_skb+0x65/0x68
> [<c12681eb>] ? kfree_skb+0x2b/0x2e
> [<c130d3fb>] ? hci_send_to_sock+0x18d/0x199
> [<c12fa327>] hci_rx_work+0xf9/0x295
> [<c12fa327>] ? hci_rx_work+0xf9/0x295
> [<c1036d25>] process_one_work+0x128/0x1df
> [<c1346a39>] ? _raw_spin_unlock_irq+0x8/0x12
> [<c1036d25>] ? process_one_work+0x128/0x1df
> [<c103713a>] worker_thread+0x127/0x1c4
> [<c1037013>] ? rescuer_thread+0x216/0x216
> [<c103aec6>] kthread+0x88/0x8d
> [<c1040000>] ? task_rq_lock+0x37/0x6e
> [<c13474b7>] ret_from_kernel_thread+0x1b/0x28
> [<c103ae3e>] ? __kthread_parkme+0x50/0x50
> Code: 05 b8 f4 ff ff ff 8d 65 f4 5b 5e 5f 5d 8d 67 f8 5f c3 57 8d 7c 24 08 83 e4 f8 ff 77 fc 55 89 e5 57 56f
> EIP: [<c131e9c7>] bt_6lowpan_del_conn+0x19/0x12a SS:ESP 0068:f48c1e34
> CR2: 0000000000000000
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> net/bluetooth/6lowpan.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)

patch has been applied to bluetooth-next tree.

Regards

Marcel


^ permalink raw reply

* Re: [PATCH 2/2] Bluetooth: Default to no security with L2CAP RAW sockets
From: Marcel Holtmann @ 2014-01-06 17:28 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1389025622-13891-2-git-send-email-johan.hedberg@gmail.com>

Hi Johan,

> L2CAP RAW sockets can be used for things which do not involve
> establishing actual connection oriented L2CAP channels. One example of
> such usage is the l2ping tool. The default security level for L2CAP
> sockets is LOW, which implies that for SSP based connection
> authentication is still requested (although with no MITM requirement),
> which is not what we want (or need) for things like l2ping. Therefore,
> default to one lower level, i.e. BT_SECURITY_SDP, for L2CAP RAW sockets
> in order not to trigger unwanted authentication requests.
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> net/bluetooth/l2cap_sock.c | 3 +++
> 1 file changed, 3 insertions(+)

patch has been applied to bluetooth-next tree.

Regards

Marcel


^ permalink raw reply

* Re: [PATCH 0/2] Regression fixes for rfcomm/tty.c
From: Marcel Holtmann @ 2014-01-06 17:35 UTC (permalink / raw)
  To: Gianluca Anzolin
  Cc: Gustavo F. Padovan, peter,
	linux-bluetooth@vger.kernel.org development, Greg KH, jslaby,
	stable
In-Reply-To: <1388853038-6917-1-git-send-email-gianluca@sottospazio.it>

Hi Gianluca,

> The following two patches fix a couple of regressions introduced with
> the rfcomm tty_port conversion.
> 
> The first patch restores the expected behaviour of the rfcomm port when
> it's created with the flag RFCOMM_RELEASE_ONHUP.
> 
> The second patch fixes a bug that affect userspace (ModemManager) when
> the port is created with the flag RFCOMM_REUSE_DLC.
> 
> Gianluca Anzolin (2):
>  rfcomm: release the port when the last user closes the tty
>  rfcomm: move the device under its parent if already connected
> 
> net/bluetooth/rfcomm/tty.c | 68 ++++++++++++++++++++++++++--------------------
> 1 file changed, 39 insertions(+), 29 deletions(-)

I applied both patches to bluetooth-next to expose them wider testing. I like to have them go through bluetooth-next first before we push them back into -stable.

Regards

Marcel


^ permalink raw reply

* Re: [PATCH 0/2] Regression fixes for rfcomm/tty.c
From: Gianluca Anzolin @ 2014-01-06 17:42 UTC (permalink / raw)
  To: Marcel Holtmann
  Cc: Gustavo F. Padovan, peter,
	linux-bluetooth@vger.kernel.org development, Greg KH, jslaby,
	stable
In-Reply-To: <D4D6DA93-0C44-4F35-AD45-9EDE4775B052@holtmann.org>

On Mon, Jan 06, 2014 at 09:35:18AM -0800, Marcel Holtmann wrote:
> Hi Gianluca,
> 
> I applied both patches to bluetooth-next to expose them wider testing. I like to have them go through bluetooth-next first before we push them back into -stable.
> 
> Regards
> 
> Marcel
> 

Thank you for the reply, however there is another regression and the fix would
make the second patch unnecessary.

Would it be better if I resend a second iteration of patches? There would be 4
patches, two fixes and two which move code around.

^ permalink raw reply

* Re: [PATCH 0/2] Regression fixes for rfcomm/tty.c
From: Marcel Holtmann @ 2014-01-06 18:19 UTC (permalink / raw)
  To: Gianluca Anzolin
  Cc: Gustavo F. Padovan, peter,
	linux-bluetooth@vger.kernel.org development, Greg KH, jslaby,
	stable
In-Reply-To: <20140106174234.GA23339@sottospazio.it>

Hi Gianluca,

>> I applied both patches to bluetooth-next to expose them wider testing. I like to have them go through bluetooth-next first before we push them back into -stable.
>> 
>> Regards
>> 
>> Marcel
>> 
> 
> Thank you for the reply, however there is another regression and the fix would
> make the second patch unnecessary.
> 
> Would it be better if I resend a second iteration of patches? There would be 4
> patches, two fixes and two which move code around.

send it and I will have a look.

Regards

Marcel


^ permalink raw reply

* [PATCH 1/3] tools/rfcomm-tester: Initial version of rfcomm-tester
From: Marcin Kraglak @ 2014-01-06 18:42 UTC (permalink / raw)
  To: linux-bluetooth

Add rfcomm-tester to tree.
---
 .gitignore            |  1 +
 Makefile.tools        |  6 +++++-
 tools/rfcomm-tester.c | 36 ++++++++++++++++++++++++++++++++++++
 3 files changed, 42 insertions(+), 1 deletion(-)
 create mode 100644 tools/rfcomm-tester.c

diff --git a/.gitignore b/.gitignore
index 3e0641d..4ac216d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -81,6 +81,7 @@ unit/test-mgmt
 tools/mgmt-tester
 tools/smp-tester
 tools/gap-tester
+tools/rfcomm-tester
 tools/btattach
 tools/btmgmt
 tools/btsnoop
diff --git a/Makefile.tools b/Makefile.tools
index 1f61d15..ec3c71b 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -36,7 +36,7 @@ if EXPERIMENTAL
 noinst_PROGRAMS += emulator/btvirt emulator/b1ee tools/3dsp \
 					tools/mgmt-tester tools/gap-tester \
 					tools/l2cap-tester tools/sco-tester \
-					tools/smp-tester
+					tools/smp-tester tools/rfcomm-tester
 
 emulator_btvirt_SOURCES = emulator/main.c monitor/bt.h \
 					monitor/mainloop.h monitor/mainloop.c \
@@ -73,6 +73,10 @@ tools_l2cap_tester_SOURCES = tools/l2cap-tester.c monitor/bt.h \
 				src/shared/tester.h src/shared/tester.c
 tools_l2cap_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
+tools_rfcomm_tester_SOURCES = tools/rfcomm-tester.c src/shared/tester.h \
+				src/shared/tester.c
+tools_rfcomm_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
+
 tools_smp_tester_SOURCES = tools/smp-tester.c monitor/bt.h \
 				emulator/btdev.h emulator/btdev.c \
 				emulator/bthost.h emulator/bthost.c \
diff --git a/tools/rfcomm-tester.c b/tools/rfcomm-tester.c
new file mode 100644
index 0000000..194e2e6
--- /dev/null
+++ b/tools/rfcomm-tester.c
@@ -0,0 +1,36 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2013  Intel Corporation. All rights reserved.
+ *
+ *
+ *  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
+
+#include <glib.h>
+#include "src/shared/tester.h"
+
+int main(int argc, char *argv[])
+{
+	tester_init(&argc, &argv);
+
+	return tester_run();
+}
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH 2/3] tools/rfcomm-tester: Add basic rfcomm test case
From: Marcin Kraglak @ 2014-01-06 18:42 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389033760-16764-1-git-send-email-marcin.kraglak@tieto.com>

This test case verifies creating rfcomm socket.
---
 Makefile.tools        |   9 +-
 tools/rfcomm-tester.c | 257 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 264 insertions(+), 2 deletions(-)

diff --git a/Makefile.tools b/Makefile.tools
index ec3c71b..9a0841f 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -73,8 +73,13 @@ tools_l2cap_tester_SOURCES = tools/l2cap-tester.c monitor/bt.h \
 				src/shared/tester.h src/shared/tester.c
 tools_l2cap_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
-tools_rfcomm_tester_SOURCES = tools/rfcomm-tester.c src/shared/tester.h \
-				src/shared/tester.c
+tools_rfcomm_tester_SOURCES = tools/rfcomm-tester.c monitor/bt.h \
+				emulator/btdev.h emulator/btdev.c \
+				emulator/bthost.h emulator/bthost.c \
+				src/shared/util.h src/shared/util.c \
+				src/shared/mgmt.h src/shared/mgmt.c \
+				src/shared/hciemu.h src/shared/hciemu.c \
+				src/shared/tester.h src/shared/tester.c
 tools_rfcomm_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
 tools_smp_tester_SOURCES = tools/smp-tester.c monitor/bt.h \
diff --git a/tools/rfcomm-tester.c b/tools/rfcomm-tester.c
index 194e2e6..af87f75 100644
--- a/tools/rfcomm-tester.c
+++ b/tools/rfcomm-tester.c
@@ -25,12 +25,269 @@
 #include <config.h>
 #endif
 
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdbool.h>
+
 #include <glib.h>
+
+#include "lib/bluetooth.h"
+#include "lib/mgmt.h"
+
+#include "monitor/bt.h"
+#include "emulator/bthost.h"
+
 #include "src/shared/tester.h"
+#include "src/shared/mgmt.h"
+#include "src/shared/hciemu.h"
+
+struct test_data {
+	struct mgmt *mgmt;
+	uint16_t mgmt_index;
+	struct hciemu *hciemu;
+	enum hciemu_type hciemu_type;
+	const void *test_data;
+};
+
+static void mgmt_debug(const char *str, void *user_data)
+{
+	const char *prefix = user_data;
+
+	tester_print("%s%s", prefix, str);
+}
+
+static void read_info_callback(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct test_data *data = tester_get_data();
+	const struct mgmt_rp_read_info *rp = param;
+	char addr[18];
+	uint16_t manufacturer;
+	uint32_t supported_settings, current_settings;
+
+	tester_print("Read Info callback");
+	tester_print("  Status: 0x%02x", status);
+
+	if (status || !param) {
+		tester_pre_setup_failed();
+		return;
+	}
+
+	ba2str(&rp->bdaddr, addr);
+	manufacturer = btohs(rp->manufacturer);
+	supported_settings = btohl(rp->supported_settings);
+	current_settings = btohl(rp->current_settings);
+
+	tester_print("  Address: %s", addr);
+	tester_print("  Version: 0x%02x", rp->version);
+	tester_print("  Manufacturer: 0x%04x", manufacturer);
+	tester_print("  Supported settings: 0x%08x", supported_settings);
+	tester_print("  Current settings: 0x%08x", current_settings);
+	tester_print("  Class: 0x%02x%02x%02x",
+			rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]);
+	tester_print("  Name: %s", rp->name);
+	tester_print("  Short name: %s", rp->short_name);
+
+	if (strcmp(hciemu_get_address(data->hciemu), addr)) {
+		tester_pre_setup_failed();
+		return;
+	}
+
+	tester_pre_setup_complete();
+}
+
+static void index_added_callback(uint16_t index, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct test_data *data = tester_get_data();
+
+	tester_print("Index Added callback");
+	tester_print("  Index: 0x%04x", index);
+
+	data->mgmt_index = index;
+
+	mgmt_send(data->mgmt, MGMT_OP_READ_INFO, data->mgmt_index, 0, NULL,
+					read_info_callback, NULL, NULL);
+}
+
+static void index_removed_callback(uint16_t index, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct test_data *data = tester_get_data();
+
+	tester_print("Index Removed callback");
+	tester_print("  Index: 0x%04x", index);
+
+	if (index != data->mgmt_index)
+		return;
+
+	mgmt_unregister_index(data->mgmt, data->mgmt_index);
+
+	mgmt_unref(data->mgmt);
+	data->mgmt = NULL;
+
+	tester_post_teardown_complete();
+}
+
+static void read_index_list_callback(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct test_data *data = tester_get_data();
+
+	tester_print("Read Index List callback");
+	tester_print("  Status: 0x%02x", status);
+
+	if (status || !param) {
+		tester_pre_setup_failed();
+		return;
+	}
+
+	mgmt_register(data->mgmt, MGMT_EV_INDEX_ADDED, MGMT_INDEX_NONE,
+					index_added_callback, NULL, NULL);
+
+	mgmt_register(data->mgmt, MGMT_EV_INDEX_REMOVED, MGMT_INDEX_NONE,
+					index_removed_callback, NULL, NULL);
+
+	data->hciemu = hciemu_new(data->hciemu_type);
+	if (!data->hciemu) {
+		tester_warn("Failed to setup HCI emulation");
+		tester_pre_setup_failed();
+	}
+
+	tester_print("New hciemu instance created");
+}
+
+static void test_pre_setup(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+
+	data->mgmt = mgmt_new_default();
+	if (!data->mgmt) {
+		tester_warn("Failed to setup management interface");
+		tester_pre_setup_failed();
+		return;
+	}
+
+	if (tester_use_debug())
+		mgmt_set_debug(data->mgmt, mgmt_debug, "mgmt: ", NULL);
+
+	mgmt_send(data->mgmt, MGMT_OP_READ_INDEX_LIST, MGMT_INDEX_NONE, 0, NULL,
+					read_index_list_callback, NULL, NULL);
+}
+
+static void test_post_teardown(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+
+	hciemu_unref(data->hciemu);
+	data->hciemu = NULL;
+}
+
+static void test_data_free(void *test_data)
+{
+	struct test_data *data = test_data;
+
+	free(data);
+}
+
+static void client_connectable_complete(uint16_t opcode, uint8_t status,
+					const void *param, uint8_t len,
+					void *user_data)
+{
+	switch (opcode) {
+	case BT_HCI_CMD_WRITE_SCAN_ENABLE:
+	case BT_HCI_CMD_LE_SET_ADV_ENABLE:
+		break;
+	default:
+		return;
+	}
+
+	tester_print("Client set connectable status 0x%02x", status);
+
+	if (status)
+		tester_setup_failed();
+	else
+		tester_setup_complete();
+}
+
+static void setup_powered_client_callback(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct test_data *data = tester_get_data();
+	struct bthost *bthost;
+
+	if (status != MGMT_STATUS_SUCCESS) {
+		tester_setup_failed();
+		return;
+	}
+
+	tester_print("Controller powered on");
+
+	bthost = hciemu_client_get_host(data->hciemu);
+	bthost_set_cmd_complete_cb(bthost, client_connectable_complete, data);
+	if (data->hciemu_type == HCIEMU_TYPE_LE)
+		bthost_set_adv_enable(bthost, 0x01);
+	else
+		bthost_write_scan_enable(bthost, 0x03);
+}
+
+static void setup_powered_client(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+	unsigned char param[] = { 0x01 };
+
+	tester_print("Powering on controller");
+
+	if (data->hciemu_type == HCIEMU_TYPE_BREDR)
+		mgmt_send(data->mgmt, MGMT_OP_SET_SSP, data->mgmt_index,
+				sizeof(param), param, NULL, NULL, NULL);
+	else
+		mgmt_send(data->mgmt, MGMT_OP_SET_LE, data->mgmt_index,
+				sizeof(param), param, NULL, NULL, NULL);
+
+	mgmt_send(data->mgmt, MGMT_OP_SET_POWERED, data->mgmt_index,
+			sizeof(param), param, setup_powered_client_callback,
+			NULL, NULL);
+}
+
+static void test_basic(const void *test_data)
+{
+	int sk;
+
+	sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+	if (sk < 0) {
+		tester_warn("Can't create socket: %s (%d)", strerror(errno),
+									errno);
+		tester_test_failed();
+		return;
+	}
+
+	close(sk);
+
+	tester_test_passed();
+}
+
+#define test_rfcomm_bredr(name, data, setup, func) \
+	do { \
+		struct test_data *user; \
+		user = malloc(sizeof(struct test_data)); \
+		if (!user) \
+			break; \
+		user->hciemu_type = HCIEMU_TYPE_BREDR; \
+		user->test_data = data; \
+		tester_add_full(name, data, \
+				test_pre_setup, setup, func, NULL, \
+				test_post_teardown, 2, user, test_data_free); \
+	} while (0)
 
 int main(int argc, char *argv[])
 {
 	tester_init(&argc, &argv);
 
+	test_rfcomm_bredr("Basic RFCOMM Socket - Success", NULL,
+					setup_powered_client, test_basic);
+
 	return tester_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH 3/3] emulator/bthost: Add initial rfcomm handling
From: Marcin Kraglak @ 2014-01-06 18:42 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389033760-16764-1-git-send-email-marcin.kraglak@tieto.com>

This is initial rfcomm handling in bthost. It also adds
rfcomm.h to monitor directory
---
 emulator/bthost.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 monitor/rfcomm.h  | 53 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 119 insertions(+), 1 deletion(-)
 create mode 100644 monitor/rfcomm.h

diff --git a/emulator/bthost.c b/emulator/bthost.c
index 83bfdee..e142038 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -36,6 +36,7 @@
 #include "bluetooth/bluetooth.h"
 
 #include "monitor/bt.h"
+#include "monitor/rfcomm.h"
 #include "bthost.h"
 
 /* ACL handle and flags pack/unpack */
@@ -1173,6 +1174,64 @@ static struct cid_hook *find_cid_hook(struct btconn *conn, uint16_t cid)
 	return NULL;
 }
 
+static void rfcomm_sabm_recv(struct bthost *bthost, struct btconn *conn,
+				struct l2conn *l2conn, const void *data,
+				uint16_t len)
+{
+}
+
+static void rfcomm_disc_recv(struct bthost *bthost, struct btconn *conn,
+				struct l2conn *l2conn, const void *data,
+				uint16_t len)
+{
+}
+
+static void rfcomm_ua_recv(struct bthost *bthost, struct btconn *conn,
+				struct l2conn *l2conn, const void *data,
+				uint16_t len)
+{
+}
+
+static void rfcomm_dm_recv(struct bthost *bthost, struct btconn *conn,
+				struct l2conn *l2conn, const void *data,
+				uint16_t len)
+{
+}
+
+static void rfcomm_uih_recv(struct bthost *bthost, struct btconn *conn,
+				struct l2conn *l2conn, const void *data,
+				uint16_t len)
+{
+}
+
+static void process_rfcomm(struct bthost *bthost, struct btconn *conn,
+				struct l2conn *l2conn, const void *data,
+				uint16_t len)
+{
+	const struct rfcomm_hdr *hdr = data;
+
+	switch (GET_TYPE(hdr->control)) {
+	case RFCOMM_SABM:
+		rfcomm_sabm_recv(bthost, conn, l2conn, data, len);
+		break;
+	case RFCOMM_DISC:
+		rfcomm_disc_recv(bthost, conn, l2conn, data, len);
+		break;
+	case RFCOMM_UA:
+		rfcomm_ua_recv(bthost, conn, l2conn, data, len);
+		break;
+	case RFCOMM_DM:
+		rfcomm_dm_recv(bthost, conn, l2conn, data, len);
+		break;
+	case RFCOMM_UIH:
+		rfcomm_uih_recv(bthost, conn, l2conn, data, len);
+		break;
+	default:
+		printf("Unknown frame type\n");
+		break;
+	}
+}
+
 static void process_acl(struct bthost *bthost, const void *data, uint16_t len)
 {
 	const struct bt_hci_acl_hdr *acl_hdr = data;
@@ -1180,6 +1239,7 @@ static void process_acl(struct bthost *bthost, const void *data, uint16_t len)
 	uint16_t handle, cid, acl_len, l2_len;
 	struct cid_hook *hook;
 	struct btconn *conn;
+	struct l2conn *l2conn;
 	const void *l2_data;
 
 	if (len < sizeof(*acl_hdr) + sizeof(*l2_hdr))
@@ -1218,7 +1278,12 @@ static void process_acl(struct bthost *bthost, const void *data, uint16_t len)
 		l2cap_le_sig(bthost, conn, l2_data, l2_len);
 		break;
 	default:
-		printf("Packet for unknown CID 0x%04x (%u)\n", cid, cid);
+		l2conn = btconn_find_l2cap_conn_by_scid(conn, cid);
+		if (l2conn->psm == 0x0003)
+			process_rfcomm(bthost, conn, l2conn, l2_data, l2_len);
+		else
+			printf("Packet for unknown CID 0x%04x (%u)\n", cid,
+									cid);
 		break;
 	}
 }
diff --git a/monitor/rfcomm.h b/monitor/rfcomm.h
new file mode 100644
index 0000000..a8266e7
--- /dev/null
+++ b/monitor/rfcomm.h
@@ -0,0 +1,53 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2013 Intel Corporation
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#define RFCOMM_SABM    0x2f
+#define RFCOMM_DISC    0x43
+#define RFCOMM_UA      0x63
+#define RFCOMM_DM      0x0f
+#define RFCOMM_UIH     0xef
+
+#define GET_TYPE(control)      ((control & 0xef))
+#define GET_DLCI(address)      ((address & 0xfc) >> 2)
+#define GET_CHANNEL(address)   ((address & 0xf8) >> 3)
+#define GET_DIR(address)       ((address & 0x04) >> 2)
+
+#define TEST_EA(length)      ((length & 0x01))
+
+#define ADDR(cr, dlci) (((dlci & 0x3f) << 2) | (cr << 1) | 0x01)
+#define CTRL(type, pf) (((type & 0xef) | (pf << 4)))
+#define LEN8(len)       (((len) << 1) | 1)
+#define LEN16(len)      ((len) << 1)
+
+struct rfcomm_hdr {
+	uint8_t address_field;
+	uint8_t control;
+	uint8_t length;
+} __attribute__((packed));
+
+struct rfcomm_cmd {
+	uint8_t address_field;
+	uint8_t control;
+	uint8_t length;
+	uint8_t fcs;
+} __attribute__((packed));
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH v2 0/4] Regression fixes for rfcomm/tty.c
From: Gianluca Anzolin @ 2014-01-06 18:43 UTC (permalink / raw)
  To: gustavo
  Cc: peter, marcel, linux-bluetooth, gregkh, jslaby, stable,
	Gianluca Anzolin

The following patches fix three regressions introduced with the
rfcomm tty_port conversion.

The first patch restores the expected behaviour of the rfcomm port when
it's created with the flag RFCOMM_RELEASE_ONHUP.

The second patch moves rfcomm_get_device() and is preparatory for the
third patch.

The third patch fixes two regressions:
1) when the tty is opened with O_NONBLOCK or CLOCAL is set (fixes
   wvdial)
2) when the rfcomm device is created with the flag RFCOMM_REUSE_DLC
   (fixes ModemManager)

The fourth patch removes rfcomm_dev_carrier_raised().

Changes from v1:
  * Removed the device_move() fix which is now incorporated in a new patch.

Gianluca Anzolin (4):
  rfcomm: release the port when the last user closes the tty
  rfcomm: move rfcomm_get_device() before rfcomm_dev_activate()
  rfcomm: always wait for a bt connection on open()
  rfcomm: remove rfcomm_carrier_raised()

 net/bluetooth/rfcomm/tty.c | 100 ++++++++++++++++++++++++++++-----------------
 1 file changed, 63 insertions(+), 37 deletions(-)

-- 
1.8.5.2

^ permalink raw reply

* [PATCH v2 1/4] rfcomm: release the port when the last user closes the tty
From: Gianluca Anzolin @ 2014-01-06 18:43 UTC (permalink / raw)
  To: gustavo
  Cc: peter, marcel, linux-bluetooth, gregkh, jslaby, stable,
	Gianluca Anzolin
In-Reply-To: <1389033795-23895-1-git-send-email-gianluca@sottospazio.it>

This patch fixes a userspace regression introduced by the commit
29cd718b.

If the rfcomm device was created with the flag RFCOMM_RELEASE_ONHUP the
user space expects that the tty_port is released as soon as the last
process closes the tty.

The current code attempts to release the port in the function
rfcomm_dev_state_change(). However it won't get a reference to the
relevant tty to send a HUP: at that point the tty is already destroyed
and therefore NULL.

This patch fixes the regression by taking over the tty refcount in the
tty install method(). This way the tty_port is automatically released as
soon as the tty is destroyed.

As a consequence the check for RFCOMM_RELEASE_ONHUP flag in the hangup()
method is now redundant. Instead we have to be careful with the reference
counting in the rfcomm_release_dev() function.

Signed-off-by: Gianluca Anzolin <gianluca@sottospazio.it>
Reported-by: Alexander Holler <holler@ahsoftware.de>
---
 net/bluetooth/rfcomm/tty.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 84fcf9f..a535ef1 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -437,7 +437,8 @@ static int rfcomm_release_dev(void __user *arg)
 		tty_kref_put(tty);
 	}
 
-	if (!test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags))
+	if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags) &&
+	    !test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags))
 		tty_port_put(&dev->port);
 
 	tty_port_put(&dev->port);
@@ -670,10 +671,20 @@ static int rfcomm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
 
 	/* install the tty_port */
 	err = tty_port_install(&dev->port, driver, tty);
-	if (err)
+	if (err) {
 		rfcomm_tty_cleanup(tty);
+		return err;
+	}
 
-	return err;
+	/* take over the tty_port reference if the port was created with the
+	 * flag RFCOMM_RELEASE_ONHUP. This will force the release of the port
+	 * when the last process closes the tty. The behaviour is expected by
+	 * userspace.
+	 */
+	if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags))
+		tty_port_put(&dev->port);
+
+	return 0;
 }
 
 static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
@@ -1010,10 +1021,6 @@ static void rfcomm_tty_hangup(struct tty_struct *tty)
 	BT_DBG("tty %p dev %p", tty, dev);
 
 	tty_port_hangup(&dev->port);
-
-	if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags) &&
-	    !test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags))
-		tty_port_put(&dev->port);
 }
 
 static int rfcomm_tty_tiocmget(struct tty_struct *tty)
-- 
1.8.5.2

^ permalink raw reply related

* [PATCH v2 2/4] rfcomm: move rfcomm_get_device() before rfcomm_dev_activate()
From: Gianluca Anzolin @ 2014-01-06 18:43 UTC (permalink / raw)
  To: gustavo
  Cc: peter, marcel, linux-bluetooth, gregkh, jslaby, stable,
	Gianluca Anzolin
In-Reply-To: <1389033795-23895-1-git-send-email-gianluca@sottospazio.it>

This is a preparatory patch which moves the rfcomm_get_device()
definition before rfcomm_dev_activate() where it will be used.

Signed-off-by: Gianluca Anzolin <gianluca@sottospazio.it>
---
 net/bluetooth/rfcomm/tty.c | 32 ++++++++++++++++----------------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index a535ef1..32ef9f9 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -103,6 +103,22 @@ static void rfcomm_dev_destruct(struct tty_port *port)
 	module_put(THIS_MODULE);
 }
 
+static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
+{
+	struct hci_dev *hdev;
+	struct hci_conn *conn;
+
+	hdev = hci_get_route(&dev->dst, &dev->src);
+	if (!hdev)
+		return NULL;
+
+	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst);
+
+	hci_dev_put(hdev);
+
+	return conn ? &conn->dev : NULL;
+}
+
 /* device-specific initialization: open the dlc */
 static int rfcomm_dev_activate(struct tty_port *port, struct tty_struct *tty)
 {
@@ -169,22 +185,6 @@ static struct rfcomm_dev *rfcomm_dev_get(int id)
 	return dev;
 }
 
-static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
-{
-	struct hci_dev *hdev;
-	struct hci_conn *conn;
-
-	hdev = hci_get_route(&dev->dst, &dev->src);
-	if (!hdev)
-		return NULL;
-
-	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst);
-
-	hci_dev_put(hdev);
-
-	return conn ? &conn->dev : NULL;
-}
-
 static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf)
 {
 	struct rfcomm_dev *dev = dev_get_drvdata(tty_dev);
-- 
1.8.5.2

^ permalink raw reply related

* [PATCH v2 3/4] rfcomm: always wait for a bt connection on open()
From: Gianluca Anzolin @ 2014-01-06 18:43 UTC (permalink / raw)
  To: gustavo
  Cc: peter, marcel, linux-bluetooth, gregkh, jslaby, stable,
	Gianluca Anzolin
In-Reply-To: <1389033795-23895-1-git-send-email-gianluca@sottospazio.it>

This patch fixes two regressions introduced with the recent rfcomm tty
rework.

The current code uses the carrier_raised() method to wait for the
bluetooth connection when a process opens the tty.

However processes may open the port with the O_NONBLOCK flag or set the
CLOCAL termios flag: in these cases the open() syscall returns
immediately without waiting for the bluetooth connection to
complete.

This behaviour confuses userspace which expects an established bluetooth
connection.

The patch restores the old behaviour by waiting for the connection in
rfcomm_dev_activate() and removes carrier_raised() from the tty_port ops.

As a side effect the new code also fixes the case in which the rfcomm
tty device is created with the flag RFCOMM_REUSE_DLC: the old code
didn't call device_move() and ModemManager skipped the detection
probe. Now device_move() is always called inside rfcomm_dev_activate().

Signed-off-by: Gianluca Anzolin <gianluca@sottospazio.it>
Reported-by: Andrey Vihrov <andrey.vihrov@gmail.com>
Reported-by: Beson Chow <blc+bluez@mail.vanade.com>
---
 net/bluetooth/rfcomm/tty.c | 43 +++++++++++++++++++++++++++++++++++--------
 1 file changed, 35 insertions(+), 8 deletions(-)

diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 32ef9f9..65c0699 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -58,6 +58,7 @@ struct rfcomm_dev {
 	uint			modem_status;
 
 	struct rfcomm_dlc	*dlc;
+	wait_queue_head_t       conn_wait;
 
 	struct device		*tty_dev;
 
@@ -123,8 +124,37 @@ static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
 static int rfcomm_dev_activate(struct tty_port *port, struct tty_struct *tty)
 {
 	struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port);
+	DEFINE_WAIT(wait);
+	int err;
+
+	err = rfcomm_dlc_open(dev->dlc, &dev->src, &dev->dst, dev->channel);
+	if (err)
+		return err;
+
+	while (1) {
+		prepare_to_wait(&dev->conn_wait, &wait, TASK_INTERRUPTIBLE);
+
+		if (dev->dlc->state == BT_CLOSED) {
+			err = -dev->err;
+			break;
+		} else if (dev->dlc->state == BT_CONNECTED)
+			break;
+		else if (signal_pending(current)) {
+			err = -ERESTARTSYS;
+			break;
+		}
+
+		tty_unlock(tty);
+		schedule();
+		tty_lock(tty);
+	}
+	finish_wait(&dev->conn_wait, &wait);
 
-	return rfcomm_dlc_open(dev->dlc, &dev->src, &dev->dst, dev->channel);
+	if (!err)
+		device_move(dev->tty_dev, rfcomm_get_device(dev),
+			    DPM_ORDER_DEV_AFTER_PARENT);
+
+	return err;
 }
 
 /* we block the open until the dlc->state becomes BT_CONNECTED */
@@ -151,7 +181,6 @@ static const struct tty_port_operations rfcomm_port_ops = {
 	.destruct = rfcomm_dev_destruct,
 	.activate = rfcomm_dev_activate,
 	.shutdown = rfcomm_dev_shutdown,
-	.carrier_raised = rfcomm_dev_carrier_raised,
 };
 
 static struct rfcomm_dev *__rfcomm_dev_get(int id)
@@ -258,6 +287,7 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
 
 	tty_port_init(&dev->port);
 	dev->port.ops = &rfcomm_port_ops;
+	init_waitqueue_head(&dev->conn_wait);
 
 	skb_queue_head_init(&dev->pending);
 
@@ -576,12 +606,9 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
 	BT_DBG("dlc %p dev %p err %d", dlc, dev, err);
 
 	dev->err = err;
-	if (dlc->state == BT_CONNECTED) {
-		device_move(dev->tty_dev, rfcomm_get_device(dev),
-			    DPM_ORDER_DEV_AFTER_PARENT);
+	wake_up_interruptible(&dev->conn_wait);
 
-		wake_up_interruptible(&dev->port.open_wait);
-	} else if (dlc->state == BT_CLOSED)
+	if (dlc->state == BT_CLOSED)
 		tty_port_tty_hangup(&dev->port, false);
 }
 
@@ -1103,7 +1130,7 @@ int __init rfcomm_init_ttys(void)
 	rfcomm_tty_driver->subtype	= SERIAL_TYPE_NORMAL;
 	rfcomm_tty_driver->flags	= TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
 	rfcomm_tty_driver->init_termios	= tty_std_termios;
-	rfcomm_tty_driver->init_termios.c_cflag	= B9600 | CS8 | CREAD | HUPCL;
+	rfcomm_tty_driver->init_termios.c_cflag	= B9600 | CS8 | CREAD | HUPCL | CLOCAL;
 	rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON;
 	tty_set_operations(rfcomm_tty_driver, &rfcomm_ops);
 
-- 
1.8.5.2

^ permalink raw reply related

* [PATCH v2 4/4] rfcomm: remove rfcomm_carrier_raised()
From: Gianluca Anzolin @ 2014-01-06 18:43 UTC (permalink / raw)
  To: gustavo
  Cc: peter, marcel, linux-bluetooth, gregkh, jslaby, stable,
	Gianluca Anzolin
In-Reply-To: <1389033795-23895-1-git-send-email-gianluca@sottospazio.it>

Remove the rfcomm_carrier_raised() definition as that function isn't
used anymore.

Signed-off-by: Gianluca Anzolin <gianluca@sottospazio.it>
---
 net/bluetooth/rfcomm/tty.c | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 65c0699..6d96954 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -157,14 +157,6 @@ static int rfcomm_dev_activate(struct tty_port *port, struct tty_struct *tty)
 	return err;
 }
 
-/* we block the open until the dlc->state becomes BT_CONNECTED */
-static int rfcomm_dev_carrier_raised(struct tty_port *port)
-{
-	struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port);
-
-	return (dev->dlc->state == BT_CONNECTED);
-}
-
 /* device-specific cleanup: close the dlc */
 static void rfcomm_dev_shutdown(struct tty_port *port)
 {
-- 
1.8.5.2

^ permalink raw reply related

* Re: [PATCH v2 3/4] rfcomm: always wait for a bt connection on open()
From: Marcel Holtmann @ 2014-01-06 19:17 UTC (permalink / raw)
  To: Gianluca Anzolin
  Cc: Gustavo F. Padovan, peter,
	linux-bluetooth@vger.kernel.org development, Greg KH, jslaby,
	stable
In-Reply-To: <1389033795-23895-4-git-send-email-gianluca@sottospazio.it>

Hi Gianluca,

> This patch fixes two regressions introduced with the recent rfcomm tty
> rework.
> 
> The current code uses the carrier_raised() method to wait for the
> bluetooth connection when a process opens the tty.
> 
> However processes may open the port with the O_NONBLOCK flag or set the
> CLOCAL termios flag: in these cases the open() syscall returns
> immediately without waiting for the bluetooth connection to
> complete.
> 
> This behaviour confuses userspace which expects an established bluetooth
> connection.
> 
> The patch restores the old behaviour by waiting for the connection in
> rfcomm_dev_activate() and removes carrier_raised() from the tty_port ops.
> 
> As a side effect the new code also fixes the case in which the rfcomm
> tty device is created with the flag RFCOMM_REUSE_DLC: the old code
> didn't call device_move() and ModemManager skipped the detection
> probe. Now device_move() is always called inside rfcomm_dev_activate().
> 
> Signed-off-by: Gianluca Anzolin <gianluca@sottospazio.it>
> Reported-by: Andrey Vihrov <andrey.vihrov@gmail.com>
> Reported-by: Beson Chow <blc+bluez@mail.vanade.com>
> ---
> net/bluetooth/rfcomm/tty.c | 43 +++++++++++++++++++++++++++++++++++--------
> 1 file changed, 35 insertions(+), 8 deletions(-)
> 
> diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
> index 32ef9f9..65c0699 100644
> --- a/net/bluetooth/rfcomm/tty.c
> +++ b/net/bluetooth/rfcomm/tty.c
> @@ -58,6 +58,7 @@ struct rfcomm_dev {
> 	uint			modem_status;
> 
> 	struct rfcomm_dlc	*dlc;
> +	wait_queue_head_t       conn_wait;
> 
> 	struct device		*tty_dev;
> 
> @@ -123,8 +124,37 @@ static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
> static int rfcomm_dev_activate(struct tty_port *port, struct tty_struct *tty)
> {
> 	struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port);
> +	DEFINE_WAIT(wait);
> +	int err;
> +
> +	err = rfcomm_dlc_open(dev->dlc, &dev->src, &dev->dst, dev->channel);
> +	if (err)
> +		return err;
> +
> +	while (1) {
> +		prepare_to_wait(&dev->conn_wait, &wait, TASK_INTERRUPTIBLE);
> +
> +		if (dev->dlc->state == BT_CLOSED) {
> +			err = -dev->err;
> +			break;
> +		} else if (dev->dlc->state == BT_CONNECTED)
> +			break;
> +		else if (signal_pending(current)) {
> +			err = -ERESTARTSYS;
> +			break;
> +		}

don’t do an if-else-else if statement here. Just break.

	if (dev->dlc->state == BT_CLOSED) {
		..
		break;	
	}

	if (dev->dlc->state == BT_CONNECTED)
		break;

	if (signal_pending(..)) {
		..
		break;
	}

> +
> +		tty_unlock(tty);
> +		schedule();
> +		tty_lock(tty);
> +	}
> +	finish_wait(&dev->conn_wait, &wait);
> 
> -	return rfcomm_dlc_open(dev->dlc, &dev->src, &dev->dst, dev->channel);
> +	if (!err)
> +		device_move(dev->tty_dev, rfcomm_get_device(dev),
> +			    DPM_ORDER_DEV_AFTER_PARENT);
> +
> +	return err;
> }
> 
> /* we block the open until the dlc->state becomes BT_CONNECTED */
> @@ -151,7 +181,6 @@ static const struct tty_port_operations rfcomm_port_ops = {
> 	.destruct = rfcomm_dev_destruct,
> 	.activate = rfcomm_dev_activate,
> 	.shutdown = rfcomm_dev_shutdown,
> -	.carrier_raised = rfcomm_dev_carrier_raised,
> };
> 
> static struct rfcomm_dev *__rfcomm_dev_get(int id)
> @@ -258,6 +287,7 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
> 
> 	tty_port_init(&dev->port);
> 	dev->port.ops = &rfcomm_port_ops;
> +	init_waitqueue_head(&dev->conn_wait);
> 
> 	skb_queue_head_init(&dev->pending);
> 
> @@ -576,12 +606,9 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
> 	BT_DBG("dlc %p dev %p err %d", dlc, dev, err);
> 
> 	dev->err = err;
> -	if (dlc->state == BT_CONNECTED) {
> -		device_move(dev->tty_dev, rfcomm_get_device(dev),
> -			    DPM_ORDER_DEV_AFTER_PARENT);
> +	wake_up_interruptible(&dev->conn_wait);
> 
> -		wake_up_interruptible(&dev->port.open_wait);
> -	} else if (dlc->state == BT_CLOSED)
> +	if (dlc->state == BT_CLOSED)
> 		tty_port_tty_hangup(&dev->port, false);
> }
> 
> @@ -1103,7 +1130,7 @@ int __init rfcomm_init_ttys(void)
> 	rfcomm_tty_driver->subtype	= SERIAL_TYPE_NORMAL;
> 	rfcomm_tty_driver->flags	= TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
> 	rfcomm_tty_driver->init_termios	= tty_std_termios;
> -	rfcomm_tty_driver->init_termios.c_cflag	= B9600 | CS8 | CREAD | HUPCL;
> +	rfcomm_tty_driver->init_termios.c_cflag	= B9600 | CS8 | CREAD | HUPCL | CLOCAL;

Is adding CLOCAL by default intentional?

> 	rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON;
> 	tty_set_operations(rfcomm_tty_driver, &rfcomm_ops);

Regards

Marcel


^ permalink raw reply

* Re: [PATCH 3/3] emulator/bthost: Add initial rfcomm handling
From: Marcel Holtmann @ 2014-01-06 19:20 UTC (permalink / raw)
  To: Marcin Kraglak; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1389033760-16764-3-git-send-email-marcin.kraglak@tieto.com>

Hi Marcin,

> This is initial rfcomm handling in bthost. It also adds
> rfcomm.h to monitor directory
> ---
> emulator/bthost.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> monitor/rfcomm.h  | 53 +++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 119 insertions(+), 1 deletion(-)
> create mode 100644 monitor/rfcomm.h

split this out. I rather not intermix them if not needed.

> 
> diff --git a/emulator/bthost.c b/emulator/bthost.c
> index 83bfdee..e142038 100644
> --- a/emulator/bthost.c
> +++ b/emulator/bthost.c
> @@ -36,6 +36,7 @@
> #include "bluetooth/bluetooth.h"
> 
> #include "monitor/bt.h"
> +#include "monitor/rfcomm.h"
> #include "bthost.h"
> 
> /* ACL handle and flags pack/unpack */
> @@ -1173,6 +1174,64 @@ static struct cid_hook *find_cid_hook(struct btconn *conn, uint16_t cid)
> 	return NULL;
> }
> 
> +static void rfcomm_sabm_recv(struct bthost *bthost, struct btconn *conn,
> +				struct l2conn *l2conn, const void *data,
> +				uint16_t len)
> +{
> +}
> +
> +static void rfcomm_disc_recv(struct bthost *bthost, struct btconn *conn,
> +				struct l2conn *l2conn, const void *data,
> +				uint16_t len)
> +{
> +}
> +
> +static void rfcomm_ua_recv(struct bthost *bthost, struct btconn *conn,
> +				struct l2conn *l2conn, const void *data,
> +				uint16_t len)
> +{
> +}
> +
> +static void rfcomm_dm_recv(struct bthost *bthost, struct btconn *conn,
> +				struct l2conn *l2conn, const void *data,
> +				uint16_t len)
> +{
> +}
> +
> +static void rfcomm_uih_recv(struct bthost *bthost, struct btconn *conn,
> +				struct l2conn *l2conn, const void *data,
> +				uint16_t len)
> +{
> +}
> +
> +static void process_rfcomm(struct bthost *bthost, struct btconn *conn,
> +				struct l2conn *l2conn, const void *data,
> +				uint16_t len)
> +{
> +	const struct rfcomm_hdr *hdr = data;
> +
> +	switch (GET_TYPE(hdr->control)) {
> +	case RFCOMM_SABM:
> +		rfcomm_sabm_recv(bthost, conn, l2conn, data, len);
> +		break;
> +	case RFCOMM_DISC:
> +		rfcomm_disc_recv(bthost, conn, l2conn, data, len);
> +		break;
> +	case RFCOMM_UA:
> +		rfcomm_ua_recv(bthost, conn, l2conn, data, len);
> +		break;
> +	case RFCOMM_DM:
> +		rfcomm_dm_recv(bthost, conn, l2conn, data, len);
> +		break;
> +	case RFCOMM_UIH:
> +		rfcomm_uih_recv(bthost, conn, l2conn, data, len);
> +		break;
> +	default:
> +		printf("Unknown frame type\n");
> +		break;
> +	}
> +}
> +
> static void process_acl(struct bthost *bthost, const void *data, uint16_t len)
> {
> 	const struct bt_hci_acl_hdr *acl_hdr = data;
> @@ -1180,6 +1239,7 @@ static void process_acl(struct bthost *bthost, const void *data, uint16_t len)
> 	uint16_t handle, cid, acl_len, l2_len;
> 	struct cid_hook *hook;
> 	struct btconn *conn;
> +	struct l2conn *l2conn;
> 	const void *l2_data;
> 
> 	if (len < sizeof(*acl_hdr) + sizeof(*l2_hdr))
> @@ -1218,7 +1278,12 @@ static void process_acl(struct bthost *bthost, const void *data, uint16_t len)
> 		l2cap_le_sig(bthost, conn, l2_data, l2_len);
> 		break;
> 	default:
> -		printf("Packet for unknown CID 0x%04x (%u)\n", cid, cid);
> +		l2conn = btconn_find_l2cap_conn_by_scid(conn, cid);
> +		if (l2conn->psm == 0x0003)
> +			process_rfcomm(bthost, conn, l2conn, l2_data, l2_len);
> +		else
> +			printf("Packet for unknown CID 0x%04x (%u)\n", cid,
> +									cid);
> 		break;
> 	}
> }
> diff --git a/monitor/rfcomm.h b/monitor/rfcomm.h
> new file mode 100644
> index 0000000..a8266e7
> --- /dev/null
> +++ b/monitor/rfcomm.h
> @@ -0,0 +1,53 @@
> +/*
> + *
> + *  BlueZ - Bluetooth protocol stack for Linux
> + *
> + *  Copyright (C) 2013 Intel Corporation
> + *
> + *
> + *  This library is free software; you can redistribute it and/or
> + *  modify it under the terms of the GNU Lesser General Public
> + *  License as published by the Free Software Foundation; either
> + *  version 2.1 of the License, or (at your option) any later version.
> + *
> + *  This library 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
> + *  Lesser General Public License for more details.
> + *
> + *  You should have received a copy of the GNU Lesser General Public
> + *  License along with this library; if not, write to the Free Software
> + *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
> + *
> + */
> +
> +#define RFCOMM_SABM    0x2f
> +#define RFCOMM_DISC    0x43
> +#define RFCOMM_UA      0x63
> +#define RFCOMM_DM      0x0f
> +#define RFCOMM_UIH     0xef
> +
> +#define GET_TYPE(control)      ((control & 0xef))
> +#define GET_DLCI(address)      ((address & 0xfc) >> 2)
> +#define GET_CHANNEL(address)   ((address & 0xf8) >> 3)
> +#define GET_DIR(address)       ((address & 0x04) >> 2)

	((control) & 0xef)

and so on ..

You might also prefix these with RFCOMM_

> +
> +#define TEST_EA(length)      ((length & 0x01))
> +
> +#define ADDR(cr, dlci) (((dlci & 0x3f) << 2) | (cr << 1) | 0x01)
> +#define CTRL(type, pf) (((type & 0xef) | (pf << 4)))
> +#define LEN8(len)       (((len) << 1) | 1)
> +#define LEN16(len)      ((len) << 1)
> +
> +struct rfcomm_hdr {
> +	uint8_t address_field;

Just call it address;

> +	uint8_t control;
> +	uint8_t length;
> +} __attribute__((packed));
> +
> +struct rfcomm_cmd {
> +	uint8_t address_field;
> +	uint8_t control;
> +	uint8_t length;
> +	uint8_t fcs;
> +} __attribute__((packed));

Regards

Marcel


^ permalink raw reply

* Re: [PATCH BlueZ 00/12] Fixes detected by clang
From: Johan Hedberg @ 2014-01-06 19:23 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: linux-bluetooth
In-Reply-To: <1388800528-10699-1-git-send-email-anderson.lizardo@openbossa.org>

Hi Lizardo,

On Fri, Jan 03, 2014, Anderson Lizardo wrote:
> The patches on this set (except for the last patch) fix issues detected while
> building BlueZ with clang. Note that these fixes were only compile tested (I
> did run "make check" but it obviously does not cover code touched by these
> patches). For strncat/sprintf/sscanf related patches, I did some tests with
> sample code to make sure the changes worked as expected.
> 
> The last patch is a fix that I think should be inoffensive (unless there is
> some clever hack going on there that I could not see.)
> 
> BTW, I've been experimenting with Travis CI for automatically running
> build/unit tests for commits made on my personal development tree:
> https://travis-ci.org/lizardo/bluez-devel. Enabling builds with clang (along
> with gcc) was a one-line change to the configuration file. I plan in near
> future to also run functional tests (right now it just runs "make check" and
> "make distcheck")
> 
> Best Regards,
> Anderson Lizardo
> 
> Anderson Lizardo (12):
>   tools: Fix strncat() usage in hciconfig/hcitool
>   avrcp: Remove unnecessary "if (...)"
>   health: Fix struct mcap_csp "csp_req" field type
>   attrib: Fix sprintf() format specification
>   core: Fix sscanf() format specification
>   tools: Fix unaligned memory access on smp-tester
>   tools: Fix possible uninitialized variable in obexctl
>   android/client: Fix incorrect usage of bt_state_t2str()
>   android/client: Remove duplicate "const" specifier
>   android/client: Use memcpy() for getting CMSG_DATA()
>   android/client: Fix uninitialized "sock_fd" variable
>   android/system-emulator: Remove useless "static" qualifier
> 
>  android/client/if-bt.c      |  2 +-
>  android/client/if-hh.c      | 16 ++++++++--------
>  android/client/if-pan.c     |  8 ++++----
>  android/client/if-sock.c    |  8 +++-----
>  android/system-emulator.c   |  3 +--
>  profiles/audio/avrcp.c      |  2 +-
>  profiles/health/mcap_sync.c |  2 +-
>  src/adapter.c               | 12 ++++++------
>  src/attrib-server.c         |  2 +-
>  tools/hciconfig.c           | 21 ++++++++++++++-------
>  tools/hcitool.c             | 23 +++++++++++++++--------
>  tools/obexctl.c             |  6 ++----
>  tools/smp-tester.c          | 16 +++++++++++-----
>  13 files changed, 68 insertions(+), 53 deletions(-)

All patches have been applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH BlueZ 06/12] tools: Fix unaligned memory access on smp-tester
From: Johan Hedberg @ 2014-01-06 19:25 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: linux-bluetooth
In-Reply-To: <1388800528-10699-7-git-send-email-anderson.lizardo@openbossa.org>

Hi Lizardo,

On Fri, Jan 03, 2014, Anderson Lizardo wrote:
> Fixes clang errors like:
> 
> tools/smp-tester.c:263:11: error: cast from 'uint8_t *' (aka 'unsigned
> char *') to 'u128 *' increases required alignment from 1 to 8
> [-Werror,-Wcast-align]
> ---
>  tools/smp-tester.c | 16 +++++++++++-----
>  1 file changed, 11 insertions(+), 5 deletions(-)
> 
> diff --git a/tools/smp-tester.c b/tools/smp-tester.c
> index 685d379..20429a9 100644
> --- a/tools/smp-tester.c
> +++ b/tools/smp-tester.c
> @@ -233,10 +233,16 @@ typedef struct {
>  	uint64_t a, b;
>  } u128;
>  
> -static inline void u128_xor(u128 *r, const u128 *p, const u128 *q)
> +static inline void u128_xor(void *r, const void *p, const void *q)
>  {
> -	r->a = p->a ^ q->a;
> -	r->b = p->b ^ q->b;
> +	const u128 pp = bt_get_unaligned((const u128 *) p);
> +	const u128 qq = bt_get_unaligned((const u128 *) q);
> +	u128 rr;
> +
> +	rr.a = pp.a ^ qq.a;
> +	rr.b = pp.b ^ qq.b;
> +
> +	bt_put_unaligned(rr, (u128 *) r);
>  }

This code was essentially a direct copy of what the kernel side SMP
implementation does. Does this mean we have a problem on the kernel side
too? Could you send a patch for that (after confirming that we do have a
problem there too).

Johan

^ permalink raw reply

* Re: [PATCH 1/3] android/socket: Make channel int32_t in IPC specification
From: Johan Hedberg @ 2014-01-06 19:26 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1388866574-20158-1-git-send-email-szymon.janc@gmail.com>

Hi Szymon,

On Sat, Jan 04, 2014, Szymon Janc wrote:
> This match IPC type with type in socket HAL API. This allows to pass
> data directly from HAL library and will allow to reduce logic in it.
> ---
>  android/hal-msg.h | 20 ++++++++++----------
>  android/socket.c  |  2 +-
>  2 files changed, 11 insertions(+), 11 deletions(-)

All three patches have been applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH] unit: Fix test failures with glib 2.39.0
From: Johan Hedberg @ 2014-01-06 19:28 UTC (permalink / raw)
  To: Colin Watson; +Cc: linux-bluetooth
In-Reply-To: <20140106120700.GZ5883@riva.ucam.org>

Hi Colin,

On Mon, Jan 06, 2014, Colin Watson wrote:
> glib 2.39.0 made this change:
> 
>    - g_source_remove() will now throw a critical in the case that you
>      try to remove a non-existent source.  We expect that there is some
>      code in the wild that will fall afoul of this new critical but
>      considering that we now reuse source IDs, this code is already
>      broken and should probably be fixed.
> 
> This patch fixes the test suite to keep better track of whether sources have
> already been removed and avoid double-removals.
> ---
>  unit/test-avdtp.c          |  8 ++++++--
>  unit/test-gobex-transfer.c |  6 ++++--
>  unit/test-gobex.c          | 13 ++++++++-----
>  unit/util.c                |  1 +
>  unit/util.h                |  1 +
>  5 files changed, 20 insertions(+), 9 deletions(-)

Applied. Thanks.

Johan

^ permalink raw reply


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