* [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 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 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 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 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
* 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
* 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 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 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 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
* [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
* [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
* 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
* 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
* [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: 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
* Re: [PATCH BlueZ v2 01/10] android/ipc: Add initial code for audio IPC
From: Luiz Augusto von Dentz @ 2014-01-06 9:06 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <2688157.rF2s9RrCYM@athlon>
Hi Szymon,
On Sun, Jan 5, 2014 at 7:43 PM, Szymon Janc <szymon.janc@gmail.com> wrote:
> Hi Luiz,
>
> On Thursday 02 January 2014 13:58:25 Luiz Augusto von Dentz wrote:
>> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>>
>> This add initial code for listen and accept connections on the abstract
>> socket defined for the audio IPC.
>> ---
>> v2: Split audio IPC services for HAL services and fix invalid messages or
>> disconnections causing the daemon to exit. The audio HAL is independent of
>> bluetooth and should only affect A2DP service.
>
> What seems to be missing is some way to recover from Audio IPC error.
This has been discussed already with Lukasz, Audio HAL is a little bit
different than Bluetooth HAL because it does not seems to be able to
restart the service from the UI so the Audio IPC disconnecting are
probably due to crashes, we will indeed need a way to recover from
Audio IPC errors but it is not really a feature but more a error
recover which we can be done in a separate set.
Luiz Augusto von Dentz
^ permalink raw reply
* Re: [PATCH v4] Bluetooth: Add hci_h4p driver
From: Pavel Machek @ 2014-01-06 0:27 UTC (permalink / raw)
To: Marcel Holtmann, Pali Rohár,
Ивайло Димитров,
Gustavo F. Padovan, Johan Hedberg, linux-kernel,
linux-bluetooth@vger.kernel.org development, Ville Tervo
In-Reply-To: <20140105230155.GA2681@earth.universe>
> > > The drivers can still be initialized the old way using pdata quirks
> > > until all drivers are converted, but I think this driver can simply
> > > be prepared for DT directly:
> >
> > Well, normally DT support means a bit of argumentation and bikeshed
> > painting... I believe it would be better to get the driver in as-is
> > and then work on adding DT support.
>
> Maybe. Especially the UART reference may result in some discussion.
> But having the discussion early means its finished earlier :)
Well, merging the basic driver does not mean discussion can't start
early. If it is going to be complex, that's a very good reason to do
it in separate step. That is, have a working driver, then add device
tree support.
Thanks,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply
* Re: [PATCH v4] Bluetooth: Add hci_h4p driver
From: Sebastian Reichel @ 2014-01-05 23:01 UTC (permalink / raw)
To: Pavel Machek
Cc: Marcel Holtmann, Pali Rohár,
Ивайло Димитров,
Gustavo F. Padovan, Johan Hedberg, linux-kernel,
linux-bluetooth@vger.kernel.org development, Ville Tervo
In-Reply-To: <20140105223250.GB27517@amd.pavel.ucw.cz>
[-- Attachment #1: Type: text/plain, Size: 1328 bytes --]
On Sun, Jan 05, 2014 at 11:32:50PM +0100, Pavel Machek wrote:
> > > Changes from v3: Moved platform data into
> > > include/linux/platform_data/, something I missed before.
> >
> > As I wrote before Tony plans to remove the boardcode for all
> > OMAP boards including the Nokia N900 for 3.14, so you cannot
> > boot without DT from 3.14 onwards.
>
> Well, I believe it was agreed that DT should work for at least one
> version before platform support is removed.
https://git.kernel.org/cgit/linux/kernel/git/tmlind/linux-omap.git/tag/?id=omap-for-v3.14/omap3-board-removal-signed
There have been some discussion with RMK and iirc at the end
the plan still was to remove the boardcode for 3.14.
> > The drivers can still be initialized the old way using pdata quirks
> > until all drivers are converted, but I think this driver can simply
> > be prepared for DT directly:
>
> Well, normally DT support means a bit of argumentation and bikeshed
> painting... I believe it would be better to get the driver in as-is
> and then work on adding DT support.
Maybe. Especially the UART reference may result in some discussion.
But having the discussion early means its finished earlier :)
Assuming this is not merged for 3.14 there is quite some time for
the DT binding discussion ;)
-- Sebastian
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH v4] Bluetooth: Add hci_h4p driver
From: Pavel Machek @ 2014-01-05 22:32 UTC (permalink / raw)
To: Marcel Holtmann, Pali Rohár,
Ивайло Димитров,
Gustavo F. Padovan, Johan Hedberg, linux-kernel,
linux-bluetooth@vger.kernel.org development, Ville Tervo
In-Reply-To: <20140103010519.GA27678@earth.universe>
Hi!
> > Changes from v3: Moved platform data into
> > include/linux/platform_data/, something I missed before.
>
> As I wrote before Tony plans to remove the boardcode for all
> OMAP boards including the Nokia N900 for 3.14, so you cannot
> boot without DT from 3.14 onwards.
Well, I believe it was agreed that DT should work for at least one
version before platform support is removed.
> The drivers can still be initialized the old way using pdata quirks
> until all drivers are converted, but I think this driver can simply
> be prepared for DT directly:
Well, normally DT support means a bit of argumentation and bikeshed
painting... I believe it would be better to get the driver in as-is
and then work on adding DT support.
And yes, obviously it needs to be done.
Regards,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply
* Re: [PATCH BlueZ v2 01/10] android/ipc: Add initial code for audio IPC
From: Szymon Janc @ 2014-01-05 17:43 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1388663914-25003-1-git-send-email-luiz.dentz@gmail.com>
Hi Luiz,
On Thursday 02 January 2014 13:58:25 Luiz Augusto von Dentz wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> This add initial code for listen and accept connections on the abstract
> socket defined for the audio IPC.
> ---
> v2: Split audio IPC services for HAL services and fix invalid messages or
> disconnections causing the daemon to exit. The audio HAL is independent of
> bluetooth and should only affect A2DP service.
What seems to be missing is some way to recover from Audio IPC error.
>
> android/hal-msg.h | 1 +
> android/ipc.c | 78
> ++++++++++++++++++++++++++++++++++++++++++++++++++----- android/ipc.h |
> 3 +++
> 3 files changed, 76 insertions(+), 6 deletions(-)
>
> diff --git a/android/hal-msg.h b/android/hal-msg.h
> index c351501..b14eced 100644
> --- a/android/hal-msg.h
> +++ b/android/hal-msg.h
> @@ -24,6 +24,7 @@
> #define BLUEZ_HAL_MTU 1024
>
> static const char BLUEZ_HAL_SK_PATH[] = "\0bluez_hal_socket";
> +static const char BLUEZ_AUDIO_SK_PATH[] = "\0bluez_audio_socket";
>
> struct hal_hdr {
> uint8_t service_id;
> diff --git a/android/ipc.c b/android/ipc.c
> index 9e8ccc3..4c5a77e 100644
> --- a/android/ipc.c
> +++ b/android/ipc.c
> @@ -49,6 +49,7 @@ static struct service_handler services[HAL_SERVICE_ID_MAX
> + 1];
>
> static GIOChannel *cmd_io = NULL;
> static GIOChannel *notif_io = NULL;
> +static GIOChannel *audio_io = NULL;
>
> static void ipc_handle_msg(const void *buf, ssize_t len)
> {
> @@ -145,7 +146,8 @@ static gboolean notif_watch_cb(GIOChannel *io,
> GIOCondition cond, return FALSE;
> }
>
> -static GIOChannel *connect_hal(GIOFunc connect_cb)
> +static GIOChannel *ipc_connect(const char *path, size_t size,
> + GIOFunc connect_cb)
> {
> struct sockaddr_un addr;
> GIOCondition cond;
> @@ -167,11 +169,11 @@ static GIOChannel *connect_hal(GIOFunc connect_cb)
> memset(&addr, 0, sizeof(addr));
> addr.sun_family = AF_UNIX;
>
> - memcpy(addr.sun_path, BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH));
> + memcpy(addr.sun_path, path, size);
>
> if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
> - error("IPC: failed to connect HAL socket: %d (%s)", errno,
> - strerror(errno));
> + error("IPC: failed to connect HAL socket %s: %d (%s)", &path[1],
> + errno, strerror(errno));
> g_io_channel_unref(io);
> return NULL;
> }
> @@ -218,7 +220,8 @@ static gboolean cmd_connect_cb(GIOChannel *io,
> GIOCondition cond, return FALSE;
> }
>
> - notif_io = connect_hal(notif_connect_cb);
> + notif_io = ipc_connect(BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH),
> + notif_connect_cb);
> if (!notif_io)
> raise(SIGTERM);
>
> @@ -227,7 +230,8 @@ static gboolean cmd_connect_cb(GIOChannel *io,
> GIOCondition cond,
>
> void ipc_init(void)
> {
> - cmd_io = connect_hal(cmd_connect_cb);
> + cmd_io = ipc_connect(BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH),
> + cmd_connect_cb);
> if (!cmd_io)
> raise(SIGTERM);
> }
> @@ -338,3 +342,65 @@ void ipc_unregister(uint8_t service)
> services[service].handler = NULL;
> services[service].size = 0;
> }
> +
> +static gboolean audio_watch_cb(GIOChannel *io, GIOCondition cond,
> + gpointer user_data)
> +{
> + char buf[BLUEZ_HAL_MTU];
> + ssize_t ret;
> + int fd;
> +
> + if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
> + info("Audio IPC: command socket closed");
> + goto fail;
> + }
> +
> + fd = g_io_channel_unix_get_fd(io);
> +
> + ret = read(fd, buf, sizeof(buf));
> + if (ret < 0) {
> + error("Audio IPC: command read failed (%s)", strerror(errno));
> + goto fail;
> + }
> +
> + return TRUE;
> +
> +fail:
> + audio_ipc_cleanup();
> + return FALSE;
> +}
> +
> +static gboolean audio_connect_cb(GIOChannel *io, GIOCondition cond,
> + gpointer user_data)
> +{
> + DBG("");
> +
> + if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
> + error("Audio IPC: socket connect failed");
> + audio_ipc_cleanup();
> + return FALSE;
> + }
> +
> + cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
> +
> + g_io_add_watch(audio_io, cond, audio_watch_cb, NULL);
> +
> + info("Audio IPC: successfully connected");
> +
> + return FALSE;
> +}
> +
> +void audio_ipc_init(void)
> +{
> + audio_io = ipc_connect(BLUEZ_AUDIO_SK_PATH, sizeof(BLUEZ_AUDIO_SK_PATH),
> + audio_connect_cb);
> +}
> +
> +void audio_ipc_cleanup(void)
> +{
> + if (audio_io) {
> + g_io_channel_shutdown(audio_io, TRUE, NULL);
> + g_io_channel_unref(audio_io);
> + audio_io = NULL;
> + }
> +}
> diff --git a/android/ipc.h b/android/ipc.h
> index 6cd102b..8e92811 100644
> --- a/android/ipc.h
> +++ b/android/ipc.h
> @@ -37,3 +37,6 @@ void ipc_send_notif(uint8_t service_id, uint8_t opcode,
> uint16_t len, void ipc_register(uint8_t service, const struct ipc_handler
> *handlers, uint8_t size);
> void ipc_unregister(uint8_t service);
> +
> +void audio_ipc_init(void);
> +void audio_ipc_cleanup(void);
--
Szymon K. Janc
szymon.janc@gmail.com
^ permalink raw reply
* Re: A problem with "rfcomm bind" and wvdial
From: Gianluca Anzolin @ 2014-01-05 15:49 UTC (permalink / raw)
To: andrey.vihrov; +Cc: peter, marcel, gregkh, jslaby, linux-bluetooth
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.
In the past it worked because the carrier_raised() logic was open coded inside
the rfcomm code: it always waited for a successful or failed connection even
with a non-blocking tty.
But now the code uses the tty_port methods and won't wait for a successful
bluetooth connection on open().
But there is more: when wvdial terminates, it will set the CLOCAL flag for the
tty and this will result in the same behaviour described above, even without
setting the O_NONBLOCK flag. This will affect other users of the tty.
These two cases make clear that the use of carrier_raised() method was not that
fair after all: while that allowed us to remove some code we now have to work
around it to get the previous behaviour.
For example we could mask off the O_NONBLOCK flag before opening the port and
then restore it when the tty_port_open() is completed. We could do something
similar for the CLOCAL flag: always remove it in rfcomm_tty_set_termios().
The alternative is to remove the carrier_raised() method and wait for the BT
connection in rfcomm_dev_activate() like the old code did.
I'm CC-ing some people who know the code better than me to get a suggestion
on how to proceed.
Thank you,
Gianluca
^ permalink raw reply
* [PATCH 3/3] android/socket: Move logic from HAL to daemon in connect
From: Szymon Janc @ 2014-01-04 20:16 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1388866574-20158-1-git-send-email-szymon.janc@gmail.com>
This reduce logic in HAL to bare minimum e.g. no modifications in
library will be needed to add different socket type support.
Both bdaddr2str and btuuid2str handle NULL pointers so it is safe to
print debug unconditionally.
---
android/hal-sock.c | 16 ++++-------
android/socket.c | 81 ++++++++++++++++++++++++++++++++++++++----------------
2 files changed, 62 insertions(+), 35 deletions(-)
diff --git a/android/hal-sock.c b/android/hal-sock.c
index 47de63d..f62b7ef 100644
--- a/android/hal-sock.c
+++ b/android/hal-sock.c
@@ -61,30 +61,24 @@ static bt_status_t sock_connect(const bt_bdaddr_t *bdaddr, btsock_type_t type,
{
struct hal_cmd_sock_connect cmd;
- if ((!uuid && chan <= 0) || !bdaddr || !sock || !type) {
- error("Invalid params: bd_addr %s, uuid %s, chan %d, sock %p",
- bdaddr2str(bdaddr), btuuid2str(uuid), chan, sock);
+ if (!sock)
return BT_STATUS_PARM_INVALID;
- }
DBG("bdaddr %s uuid %s chan %d sock %p type %d flags 0x%02x",
bdaddr2str(bdaddr), btuuid2str(uuid), chan, sock, type, flags);
- if (type != BTSOCK_RFCOMM) {
- error("Socket type %u not supported", type);
- return BT_STATUS_UNSUPPORTED;
- }
-
memset(&cmd, 0, sizeof(cmd));
- cmd.flags = flags;
+ /* type match IPC type */
cmd.type = type;
+ cmd.flags = flags;
cmd.channel = chan;
if (uuid)
memcpy(cmd.uuid, uuid, sizeof(cmd.uuid));
- memcpy(cmd.bdaddr, bdaddr, sizeof(cmd.bdaddr));
+ if (bdaddr)
+ memcpy(cmd.bdaddr, bdaddr, sizeof(cmd.bdaddr));
return hal_ipc_cmd(HAL_SERVICE_ID_SOCK, HAL_OP_SOCK_CONNECT,
sizeof(cmd), &cmd, NULL, NULL, sock);
diff --git a/android/socket.c b/android/socket.c
index 98862cb..69b39ee 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -975,7 +975,7 @@ fail:
cleanup_rfsock(rfsock);
}
-static bool do_connect(struct rfcomm_sock *rfsock, int chan)
+static bool do_rfcomm_connect(struct rfcomm_sock *rfsock, int chan)
{
BtIOSecLevel sec_level = BT_IO_SEC_MEDIUM;
GIOChannel *io;
@@ -1056,58 +1056,91 @@ static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
DBG("Got RFCOMM channel %d", chan);
- if (do_connect(rfsock, chan))
+ if (do_rfcomm_connect(rfsock, chan))
return;
fail:
cleanup_rfsock(rfsock);
}
-static void handle_connect(const void *buf, uint16_t len)
+static uint8_t connect_rfcomm(const bdaddr_t *addr, int chan,
+ const uint8_t *uuid, uint8_t flags, int *hal_fd)
{
- const struct hal_cmd_sock_connect *cmd = buf;
struct rfcomm_sock *rfsock;
- uuid_t uuid;
- int hal_fd = -1;
+ uuid_t uu;
- DBG("");
+ if ((!memcmp(uuid, zero_uuid, sizeof(zero_uuid)) && chan <= 0) ||
+ !bacmp(addr, BDADDR_ANY)) {
+ error("Invalid rfcomm connect params");
+ return HAL_STATUS_INVALID;
+ }
- rfsock = create_rfsock(-1, &hal_fd);
+ rfsock = create_rfsock(-1, hal_fd);
if (!rfsock)
- goto failed;
+ return HAL_STATUS_FAILED;
- android2bdaddr(cmd->bdaddr, &rfsock->dst);
+ bacpy(&rfsock->dst, addr);
- if (!memcmp(cmd->uuid, zero_uuid, sizeof(zero_uuid))) {
- if (!do_connect(rfsock, cmd->channel))
+ if (!memcmp(uuid, zero_uuid, sizeof(zero_uuid))) {
+ if (!do_rfcomm_connect(rfsock, chan))
goto failed;
} else {
- memset(&uuid, 0, sizeof(uuid));
- uuid.type = SDP_UUID128;
- memcpy(&uuid.value.uuid128, cmd->uuid, sizeof(uint128_t));
+ memset(&uu, 0, sizeof(uu));
+ uu.type = SDP_UUID128;
+ memcpy(&uu.value.uuid128, uuid, sizeof(uint128_t));
- rfsock->profile = get_profile_by_uuid(cmd->uuid);
+ rfsock->profile = get_profile_by_uuid(uuid);
- if (bt_search_service(&adapter_addr, &rfsock->dst, &uuid,
+ if (bt_search_service(&adapter_addr, &rfsock->dst, &uu,
sdp_search_cb, rfsock, NULL) < 0) {
error("Failed to search SDP records");
goto failed;
}
}
+ return HAL_STATUS_SUCCESS;
+
+failed:
+ cleanup_rfsock(rfsock);
+ close(*hal_fd);
+ return HAL_STATUS_FAILED;
+}
+
+static void handle_connect(const void *buf, uint16_t len)
+{
+ const struct hal_cmd_sock_connect *cmd = buf;
+ bdaddr_t bdaddr;
+ uint8_t status;
+ int hal_fd;
+
+ DBG("");
+
+ android2bdaddr(cmd->bdaddr, &bdaddr);
+
+ switch (cmd->type) {
+ case HAL_SOCK_RFCOMM:
+ status = connect_rfcomm(&bdaddr, cmd->channel, cmd->uuid,
+ cmd->flags, &hal_fd);
+ break;
+ case HAL_SOCK_SCO:
+ case HAL_SOCK_L2CAP:
+ status = HAL_STATUS_UNSUPPORTED;
+ break;
+ default:
+ status = HAL_STATUS_INVALID;
+ break;
+ }
+
+ if (status != HAL_STATUS_SUCCESS)
+ goto failed;
+
ipc_send_rsp_full(HAL_SERVICE_ID_SOCK, HAL_OP_SOCK_CONNECT, 0, NULL,
hal_fd);
close(hal_fd);
return;
failed:
- ipc_send_rsp(HAL_SERVICE_ID_SOCK, HAL_OP_SOCK_CONNECT,
- HAL_STATUS_FAILED);
-
- if (rfsock)
- cleanup_rfsock(rfsock);
+ ipc_send_rsp(HAL_SERVICE_ID_SOCK, HAL_OP_SOCK_CONNECT, status);
- if (hal_fd >= 0)
- close(hal_fd);
}
static const struct ipc_handler cmd_handlers[] = {
--
1.8.5.2
^ permalink raw reply related
* [PATCH 2/3] android/socket: Move logic from HAL to daemon in listen
From: Szymon Janc @ 2014-01-04 20:16 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1388866574-20158-1-git-send-email-szymon.janc@gmail.com>
This reduce logic in HAL to bare minimum e.g. no modifications in
library will be needed to add different socket type support.
Both bdaddr2str and btuuid2str handle NULL pointers so it is safe to
print debug unconditionally.
---
android/hal-msg.h | 4 +++
android/hal-sock.c | 36 ++++++--------------------
android/socket.c | 74 +++++++++++++++++++++++++++++++++++++-----------------
3 files changed, 63 insertions(+), 51 deletions(-)
diff --git a/android/hal-msg.h b/android/hal-msg.h
index bbbb99c..ceaa3b2 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -231,6 +231,10 @@ struct hal_cmd_le_test_mode {
/* Bluetooth Socket HAL api */
+#define HAL_SOCK_RFCOMM 0x01
+#define HAL_SOCK_SCO 0x02
+#define HAL_SOCK_L2CAP 0x03
+
#define HAL_OP_SOCK_LISTEN 0x01
struct hal_cmd_sock_listen {
uint8_t type;
diff --git a/android/hal-sock.c b/android/hal-sock.c
index c39ca6a..47de63d 100644
--- a/android/hal-sock.c
+++ b/android/hal-sock.c
@@ -26,18 +26,23 @@
#include "hal-utils.h"
#include "hal.h"
-static bt_status_t sock_listen_rfcomm(const char *service_name,
+static bt_status_t sock_listen(btsock_type_t type, const char *service_name,
const uint8_t *uuid, int chan,
int *sock, int flags)
{
struct hal_cmd_sock_listen cmd;
- DBG("");
+ if (!sock)
+ return BT_STATUS_PARM_INVALID;
+
+ DBG("uuid %s chan %d sock %p type %d service_name %s flags 0x%02x",
+ btuuid2str(uuid), chan, sock, type, service_name, flags);
memset(&cmd, 0, sizeof(cmd));
+ /* type match IPC type */
+ cmd.type = type;
cmd.flags = flags;
- cmd.type = BTSOCK_RFCOMM;
cmd.channel = chan;
if (uuid)
@@ -50,31 +55,6 @@ static bt_status_t sock_listen_rfcomm(const char *service_name,
sizeof(cmd), &cmd, NULL, NULL, sock);
}
-static bt_status_t sock_listen(btsock_type_t type, const char *service_name,
- const uint8_t *uuid, int chan,
- int *sock, int flags)
-{
- if ((!uuid && chan <= 0) || !sock || !type) {
- error("Invalid params: uuid %s, chan %d, sock %p",
- btuuid2str(uuid), chan, sock);
- return BT_STATUS_PARM_INVALID;
- }
-
- DBG("uuid %s chan %d sock %p type %d service_name %s flags 0x%02x",
- btuuid2str(uuid), chan, sock, type, service_name, flags);
-
- switch (type) {
- case BTSOCK_RFCOMM:
- return sock_listen_rfcomm(service_name, uuid, chan, sock,
- flags);
- default:
- error("%s: Socket type %d not supported", __func__, type);
- break;
- }
-
- return BT_STATUS_UNSUPPORTED;
-}
-
static bt_status_t sock_connect(const bt_bdaddr_t *bdaddr, btsock_type_t type,
const uint8_t *uuid, int chan,
int *sock, int flags)
diff --git a/android/socket.c b/android/socket.c
index f68fbf0..98862cb 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -62,6 +62,8 @@
static bdaddr_t adapter_addr;
+static const uint8_t zero_uuid[16] = { 0 };
+
/* Simple list of RFCOMM server sockets */
GList *servers = NULL;
@@ -787,38 +789,40 @@ static void accept_cb(GIOChannel *io, GError *err, gpointer user_data)
rfsock_acc->rfcomm_watch);
}
-static void handle_listen(const void *buf, uint16_t len)
+static uint8_t rfcomm_listen(int chan, const uint8_t *name, const uint8_t *uuid,
+ uint8_t flags, int *hal_fd)
{
- const struct hal_cmd_sock_listen *cmd = buf;
const struct profile_info *profile;
struct rfcomm_sock *rfsock = NULL;
BtIOSecLevel sec_level;
GIOChannel *io, *io_stack;
GIOCondition cond;
GError *err = NULL;
- int hal_fd = -1;
- int chan;
guint id;
DBG("");
- profile = get_profile_by_uuid(cmd->uuid);
+ if (!memcmp(uuid, zero_uuid, sizeof(zero_uuid)) && chan <= 0) {
+ error("Invalid rfcomm listen params");
+ return HAL_STATUS_INVALID;
+ }
+
+ profile = get_profile_by_uuid(uuid);
if (!profile) {
- if (cmd->channel <= 0)
- goto failed;
+ if (chan <= 0)
+ return HAL_STATUS_INVALID;
- chan = cmd->channel;
sec_level = BT_IO_SEC_MEDIUM;
} else {
chan = profile->channel;
sec_level = profile->sec_level;
}
- DBG("rfcomm channel %d svc_name %s", chan, cmd->name);
+ DBG("rfcomm channel %d svc_name %s", chan, name);
- rfsock = create_rfsock(-1, &hal_fd);
+ rfsock = create_rfsock(-1, hal_fd);
if (!rfsock)
- goto failed;
+ return HAL_STATUS_FAILED;
io = bt_io_listen(accept_cb, NULL, rfsock, NULL, &err,
BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
@@ -847,31 +851,56 @@ static void handle_listen(const void *buf, uint16_t len)
rfsock->stack_watch = id;
DBG("real_sock %d fd %d hal_fd %d", rfsock->real_sock, rfsock->fd,
- hal_fd);
+ *hal_fd);
if (write(rfsock->fd, &chan, sizeof(chan)) != sizeof(chan)) {
error("Error sending RFCOMM channel");
goto failed;
}
- rfsock->service_handle = sdp_service_register(profile, cmd->name);
+ rfsock->service_handle = sdp_service_register(profile, name);
servers = g_list_append(servers, rfsock);
+ return HAL_STATUS_SUCCESS;
+
+failed:
+
+ cleanup_rfsock(rfsock);
+ close(*hal_fd);
+ return HAL_STATUS_FAILED;
+}
+
+static void handle_listen(const void *buf, uint16_t len)
+{
+ const struct hal_cmd_sock_listen *cmd = buf;
+ uint8_t status;
+ int hal_fd;
+
+ switch (cmd->type) {
+ case HAL_SOCK_RFCOMM:
+ status = rfcomm_listen(cmd->channel, cmd->name, cmd->uuid,
+ cmd->flags, &hal_fd);
+ break;
+ case HAL_SOCK_SCO:
+ case HAL_SOCK_L2CAP:
+ status = HAL_STATUS_UNSUPPORTED;
+ break;
+ default:
+ status = HAL_STATUS_INVALID;
+ break;
+ }
+
+ if (status != HAL_STATUS_SUCCESS)
+ goto failed;
+
ipc_send_rsp_full(HAL_SERVICE_ID_SOCK, HAL_OP_SOCK_LISTEN, 0, NULL,
hal_fd);
close(hal_fd);
- return;
+ return ;
failed:
- ipc_send_rsp(HAL_SERVICE_ID_SOCK, HAL_OP_SOCK_LISTEN,
- HAL_STATUS_FAILED);
-
- if (rfsock)
- cleanup_rfsock(rfsock);
-
- if (hal_fd >= 0)
- close(hal_fd);
+ ipc_send_rsp(HAL_SERVICE_ID_SOCK, HAL_OP_SOCK_LISTEN, status);
}
static bool sock_send_connect(struct rfcomm_sock *rfsock, bdaddr_t *bdaddr)
@@ -1036,7 +1065,6 @@ fail:
static void handle_connect(const void *buf, uint16_t len)
{
const struct hal_cmd_sock_connect *cmd = buf;
- static const uint8_t zero_uuid[16] = { 0 };
struct rfcomm_sock *rfsock;
uuid_t uuid;
int hal_fd = -1;
--
1.8.5.2
^ permalink raw reply related
* [PATCH 1/3] android/socket: Make channel int32_t in IPC specification
From: Szymon Janc @ 2014-01-04 20:16 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
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(-)
diff --git a/android/hal-msg.h b/android/hal-msg.h
index c351501..bbbb99c 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -233,20 +233,20 @@ struct hal_cmd_le_test_mode {
#define HAL_OP_SOCK_LISTEN 0x01
struct hal_cmd_sock_listen {
- uint8_t type;
- uint8_t name[256];
- uint8_t uuid[16];
- uint16_t channel;
- uint8_t flags;
+ uint8_t type;
+ uint8_t name[256];
+ uint8_t uuid[16];
+ int32_t channel;
+ uint8_t flags;
} __attribute__((packed));
#define HAL_OP_SOCK_CONNECT 0x02
struct hal_cmd_sock_connect {
- uint8_t bdaddr[6];
- uint8_t type;
- uint8_t uuid[16];
- uint16_t channel;
- uint8_t flags;
+ uint8_t bdaddr[6];
+ uint8_t type;
+ uint8_t uuid[16];
+ int32_t channel;
+ uint8_t flags;
} __attribute__((packed));
/* Bluetooth HID Host HAL API */
diff --git a/android/socket.c b/android/socket.c
index 11d64f8..f68fbf0 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -804,7 +804,7 @@ static void handle_listen(const void *buf, uint16_t len)
profile = get_profile_by_uuid(cmd->uuid);
if (!profile) {
- if (!cmd->channel)
+ if (cmd->channel <= 0)
goto failed;
chan = cmd->channel;
--
1.8.5.2
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox