* Re: [PATCH 1/4] android/pan: Register Network Access Point
From: Johan Hedberg @ 2014-01-07 8:59 UTC (permalink / raw)
To: Ravi kumar Veeramally; +Cc: linux-bluetooth
In-Reply-To: <1389043592-5616-2-git-send-email-ravikumar.veeramally@linux.intel.com>
Hi Ravi,
On Mon, Jan 06, 2014, Ravi kumar Veeramally wrote:
> Register NAP server and adds bnep bridge. Removes bridge
> on destroy call. Bridge mechanism is needed when device acting
> as a server and listen for incoming connections.
> ---
> android/pan.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 112 insertions(+), 4 deletions(-)
>
> diff --git a/android/pan.c b/android/pan.c
> index 38e353d..93f712f 100644
> --- a/android/pan.c
> +++ b/android/pan.c
> @@ -28,6 +28,11 @@
> #include <unistd.h>
> #include <fcntl.h>
> #include <glib.h>
> +#include <sys/ioctl.h>
> +#include <sys/socket.h>
> +#include <sys/wait.h>
> +#include <net/if.h>
> +#include <linux/sockios.h>
>
> #include "btio/btio.h"
> #include "lib/bluetooth.h"
> @@ -49,7 +54,7 @@
> static bdaddr_t adapter_addr;
> GSList *devices = NULL;
> uint8_t local_role = HAL_PAN_ROLE_NONE;
> -static uint32_t record_id = 0;
> +char bridge[5] = "bnep\0";
This last line raises several questions. Firstly, C-strings have an
implicit nul-character at the end so no need to explicitly try to add
one there. You also don't need to have an explicit size between the
square brackets since this is automatically calculated if you do
initialization upon declaration. Why isn't this static? Why isn't it
const? Would a simple define make more sense instead of a dedicated
variable?
Johan
^ permalink raw reply
* Re: [PATCH] btmon: Fix compiler warnings
From: Johan Hedberg @ 2014-01-07 8:43 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1389081946-28347-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei,
On Tue, Jan 07, 2014, Andrei Emeltchenko wrote:
> When building for Android this fixes following warnings:
> ...
> monitor/ellisys.c: In function 'ellisys_inject_hci':
> monitor/ellisys.c:159:2: warning: implicit declaration of function 'writev'
> [-Wimplicit-function-declaration]
> ...
> ---
> monitor/ellisys.c | 1 +
> 1 file changed, 1 insertion(+)
Applied. Thanks.
Johan
^ permalink raw reply
* [PATCH] btmon: Fix compiler warnings
From: Andrei Emeltchenko @ 2014-01-07 8:05 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
When building for Android this fixes following warnings:
...
monitor/ellisys.c: In function 'ellisys_inject_hci':
monitor/ellisys.c:159:2: warning: implicit declaration of function 'writev'
[-Wimplicit-function-declaration]
...
---
monitor/ellisys.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/monitor/ellisys.c b/monitor/ellisys.c
index d21c164..dae690f 100644
--- a/monitor/ellisys.c
+++ b/monitor/ellisys.c
@@ -32,6 +32,7 @@
#include <time.h>
#include <sys/time.h>
#include <sys/socket.h>
+#include <sys/uio.h>
#include <netdb.h>
#include <arpa/inet.h>
--
1.8.3.2
^ permalink raw reply related
* Re: [PATCH v3 0/4] Regression fixes for rfcomm/tty.c
From: Marcel Holtmann @ 2014-01-06 21:57 UTC (permalink / raw)
To: Gianluca Anzolin
Cc: Gustavo F. Padovan, peter,
linux-bluetooth@vger.kernel.org development, Greg KH, jslaby,
stable
In-Reply-To: <1389039834-24491-1-git-send-email-gianluca@sottospazio.it>
Hi Gianluca,
> 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 v2:
> * Fix the style of if statements in rfcomm_dev_activate().
>
> 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 | 103 +++++++++++++++++++++++++++++----------------
> 1 file changed, 66 insertions(+), 37 deletions(-)
all 4 patches have been applied to bluetooth-next tree.
Regards
Marcel
^ permalink raw reply
* [PATCH 4/4] android/pan: Remove connected PAN devices on profile unregister call
From: Ravi kumar Veeramally @ 2014-01-06 21:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1389043592-5616-1-git-send-email-ravikumar.veeramally@linux.intel.com>
---
android/pan.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/android/pan.c b/android/pan.c
index 499702f..b482d55 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -763,10 +763,20 @@ bool bt_pan_register(const bdaddr_t *addr)
return true;
}
+static void pan_device_disconnected(gpointer data, gpointer user_data)
+{
+ struct pan_device *dev = data;
+
+ bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+}
+
void bt_pan_unregister(void)
{
DBG("");
+ g_slist_foreach(devices, pan_device_disconnected, NULL);
+ devices = NULL;
+
bnep_cleanup();
ipc_unregister(HAL_SERVICE_ID_PAN);
--
1.8.3.2
^ permalink raw reply related
* [PATCH 3/4] android/pan: Implement PAN enable HAL api at daemon side
From: Ravi kumar Veeramally @ 2014-01-06 21:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1389043592-5616-1-git-send-email-ravikumar.veeramally@linux.intel.com>
---
android/pan.c | 32 ++++++++++++++++++++++++++------
1 file changed, 26 insertions(+), 6 deletions(-)
diff --git a/android/pan.c b/android/pan.c
index 87753a0..499702f 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -588,18 +588,38 @@ static void bt_pan_enable(const void *buf, uint16_t len)
{
const struct hal_cmd_pan_enable *cmd = buf;
uint8_t status;
+ int err;
+
+ DBG("");
+
+ if (local_role == cmd->local_role) {
+ status = HAL_STATUS_SUCCESS;
+ goto reply;
+ }
+
+ /* destroy existing server */
+ destroy_nap_device();
switch (cmd->local_role) {
case HAL_PAN_ROLE_PANU:
- case HAL_PAN_ROLE_NAP:
- DBG("Not Implemented");
- status = HAL_STATUS_FAILED;
- break;
- default:
status = HAL_STATUS_UNSUPPORTED;
- break;
+ goto reply;
+ case HAL_PAN_ROLE_NONE:
+ status = HAL_STATUS_SUCCESS;
+ goto reply;
+ }
+
+ local_role = cmd->local_role;
+ err = register_nap_server();
+ if (err < 0) {
+ status = HAL_STATUS_FAILED;
+ destroy_nap_device();
+ goto reply;
}
+ status = HAL_STATUS_SUCCESS;
+
+reply:
ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_ENABLE, status);
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH 2/4] android/pan: Listen for incoming connections and accept in NAP role
From: Ravi kumar Veeramally @ 2014-01-06 21:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1389043592-5616-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Listen for incoming connections and accept it. Create bnep interface
add it to bridge and notify control and connection state information
through HAL. Remove the device on disconnect request. If android
settings UI does not have bluetooth tethering enabled it immediately
sends disconnect signal.
---
android/pan.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 189 insertions(+), 2 deletions(-)
diff --git a/android/pan.c b/android/pan.c
index 93f712f..87753a0 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -63,12 +63,17 @@ struct pan_device {
uint8_t role;
GIOChannel *io;
struct bnep *session;
+ guint watch;
};
static struct {
uint32_t record_id;
+ guint watch;
+ GIOChannel *io;
} nap_dev = {
.record_id = 0,
+ .watch = 0,
+ .io = NULL,
};
static int device_cmp(gconstpointer s, gconstpointer user_data)
@@ -81,13 +86,21 @@ static int device_cmp(gconstpointer s, gconstpointer user_data)
static void pan_device_free(struct pan_device *dev)
{
+ if (dev->watch > 0) {
+ bnep_server_delete(bridge, dev->iface, &dev->dst);
+ g_source_remove(dev->watch);
+ dev->watch = 0;
+ }
+
if (dev->io) {
g_io_channel_shutdown(dev->io, FALSE, NULL);
g_io_channel_unref(dev->io);
dev->io = NULL;
}
- bnep_free(dev->session);
+ if (dev->session)
+ bnep_free(dev->session);
+
devices = g_slist_remove(devices, dev);
g_free(dev);
@@ -298,7 +311,7 @@ static void bt_pan_disconnect(const void *buf, uint16_t len)
dev = l->data;
- if (dev->conn_state == HAL_PAN_STATE_CONNECTED)
+ if (dev->conn_state == HAL_PAN_STATE_CONNECTED && dev->session)
bnep_disconnect(dev->session);
bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
@@ -308,6 +321,153 @@ failed:
ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_DISCONNECT, status);
}
+static gboolean nap_watchdog_cb(GIOChannel *chan, GIOCondition cond,
+ gpointer user_data)
+{
+ struct pan_device *dev = user_data;
+
+ DBG("disconnected");
+
+ bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+
+ return FALSE;
+}
+static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
+ gpointer user_data)
+{
+ struct pan_device *dev = user_data;
+ uint8_t packet[BNEP_MTU];
+ struct bnep_setup_conn_req *req = (void *) packet;
+ uint16_t src_role, dst_role, rsp = BNEP_CONN_NOT_ALLOWED;
+ int sk, n;
+
+ if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
+ error("Hangup or error or inval on BNEP socket");
+ return FALSE;
+ }
+
+ sk = g_io_channel_unix_get_fd(chan);
+
+ /* Reading BNEP_SETUP_CONNECTION_REQUEST_MSG */
+ n = read(sk, packet, sizeof(packet));
+ if (n < 0) {
+ error("read(): %s(%d)", strerror(errno), errno);
+ goto failed;
+ }
+
+ /* Highest known control command id BNEP_FILTER_MULT_ADDR_RSP 0x06 */
+ if (req->type == BNEP_CONTROL &&
+ req->ctrl > BNEP_FILTER_MULT_ADDR_RSP) {
+ error("cmd not understood");
+ bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_CMD_NOT_UNDERSTOOD,
+ req->ctrl);
+ goto failed;
+ }
+
+ if (req->type != BNEP_CONTROL || req->ctrl != BNEP_SETUP_CONN_REQ) {
+ error("cmd is not BNEP_SETUP_CONN_REQ %02X %02X", req->type,
+ req->ctrl);
+ goto failed;
+ }
+
+ rsp = bnep_setup_decode(req, &dst_role, &src_role);
+ if (rsp) {
+ error("bnep_setup_decode failed");
+ goto failed;
+ }
+
+ rsp = bnep_setup_chk(dst_role, src_role);
+ if (rsp) {
+ error("benp_setup_chk failed");
+ goto failed;
+ }
+
+ if (bnep_server_add(sk, dst_role, bridge, dev->iface, &dev->dst) < 0) {
+ error("server_connadd failed");
+ rsp = BNEP_CONN_NOT_ALLOWED;
+ goto failed;
+ }
+
+ rsp = BNEP_SUCCESS;
+ bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_SETUP_CONN_RSP, rsp);
+
+ dev->watch = g_io_add_watch(chan, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ nap_watchdog_cb, dev);
+ g_io_channel_unref(dev->io);
+ dev->io = NULL;
+
+ bt_pan_notify_ctrl_state(dev, HAL_PAN_CTRL_ENABLED);
+ bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTED);
+
+ return FALSE;
+
+failed:
+ bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_SETUP_CONN_RSP, rsp);
+ pan_device_free(dev);
+
+ return FALSE;
+}
+
+static void nap_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
+{
+ struct pan_device *dev = user_data;
+
+ DBG("");
+
+ if (err) {
+ error("%s", err->message);
+ bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+ return;
+ }
+
+ g_io_channel_set_close_on_unref(chan, TRUE);
+ dev->watch = g_io_add_watch(chan,
+ G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ nap_setup_cb, dev);
+}
+
+static void nap_confirm_cb(GIOChannel *chan, gpointer data)
+{
+ struct pan_device *dev = NULL;
+ bdaddr_t dst;
+ char address[18];
+ GError *err = NULL;
+
+ DBG("");
+
+ bt_io_get(chan, &err, BT_IO_OPT_DEST_BDADDR, &dst,
+ BT_IO_OPT_DEST, address, BT_IO_OPT_INVALID);
+ if (err) {
+ error("%s", err->message);
+ g_error_free(err);
+ goto failed;
+ }
+
+ DBG("incoming connect request from %s", address);
+ dev = g_new0(struct pan_device, 1);
+ bacpy(&dev->dst, &dst);
+ local_role = HAL_PAN_ROLE_NAP;
+ dev->role = HAL_PAN_ROLE_PANU;
+
+ dev->io = g_io_channel_ref(chan);
+ g_io_channel_set_close_on_unref(dev->io, TRUE);
+
+ if (!bt_io_accept(dev->io, nap_connect_cb, dev, NULL, &err)) {
+ error("bt_io_accept: %s", err->message);
+ g_error_free(err);
+ goto failed;
+ }
+
+ devices = g_slist_append(devices, dev);
+ bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTING);
+
+ return;
+
+failed:
+ g_free(dev);
+ bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+}
+
static int set_forward_delay(void)
{
FILE *f;
@@ -382,10 +542,22 @@ static void destroy_nap_device(void)
nap_remove_bridge();
nap_dev.record_id = 0;
+
+ if (nap_dev.watch > 0) {
+ g_source_remove(nap_dev.watch);
+ nap_dev.watch = 0;
+ }
+
+ if (nap_dev.io) {
+ g_io_channel_shutdown(nap_dev.io, FALSE, NULL);
+ g_io_channel_unref(nap_dev.io);
+ nap_dev.io = NULL;
+ }
}
static int register_nap_server(void)
{
+ GError *gerr;
int err;
DBG("");
@@ -394,6 +566,21 @@ static int register_nap_server(void)
if (err < 0)
return err;
+ nap_dev.io = bt_io_listen(NULL, nap_confirm_cb, NULL, NULL, &gerr,
+ BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+ BT_IO_OPT_PSM, BNEP_PSM,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+ BT_IO_OPT_OMTU, BNEP_MTU,
+ BT_IO_OPT_IMTU, BNEP_MTU,
+ BT_IO_OPT_INVALID);
+
+ if (!nap_dev.io) {
+ destroy_nap_device();
+ error("%s", gerr->message);
+ g_error_free(gerr);
+ return -EINVAL;
+ }
+
return 0;
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH 1/4] android/pan: Register Network Access Point
From: Ravi kumar Veeramally @ 2014-01-06 21:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1389043592-5616-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Register NAP server and adds bnep bridge. Removes bridge
on destroy call. Bridge mechanism is needed when device acting
as a server and listen for incoming connections.
---
android/pan.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 112 insertions(+), 4 deletions(-)
diff --git a/android/pan.c b/android/pan.c
index 38e353d..93f712f 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -28,6 +28,11 @@
#include <unistd.h>
#include <fcntl.h>
#include <glib.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <net/if.h>
+#include <linux/sockios.h>
#include "btio/btio.h"
#include "lib/bluetooth.h"
@@ -49,7 +54,7 @@
static bdaddr_t adapter_addr;
GSList *devices = NULL;
uint8_t local_role = HAL_PAN_ROLE_NONE;
-static uint32_t record_id = 0;
+char bridge[5] = "bnep\0";
struct pan_device {
char iface[16];
@@ -60,6 +65,12 @@ struct pan_device {
struct bnep *session;
};
+static struct {
+ uint32_t record_id;
+} nap_dev = {
+ .record_id = 0,
+};
+
static int device_cmp(gconstpointer s, gconstpointer user_data)
{
const struct pan_device *dev = s;
@@ -297,6 +308,95 @@ failed:
ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_DISCONNECT, status);
}
+static int set_forward_delay(void)
+{
+ FILE *f;
+ char *path;
+
+ path = g_strdup_printf("/sys/class/net/%s/bridge/forward_delay",
+ bridge);
+ if (!path)
+ return -ENOMEM;
+
+ f = fopen(path, "r+");
+ g_free(path);
+ if (!f)
+ return -errno;
+
+ fprintf(f, "%d", 0);
+ fclose(f);
+
+ return 0;
+}
+
+static int nap_create_bridge(void)
+{
+ int sk, err;
+
+ DBG(" %s", bridge);
+
+ sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ if (sk < 0)
+ return -EOPNOTSUPP;
+
+ if (ioctl(sk, SIOCBRADDBR, bridge) == -1) {
+ err = -errno;
+ if (err != -EEXIST) {
+ close(sk);
+ return -EOPNOTSUPP;
+ }
+ }
+
+ err = set_forward_delay();
+ if (err < 0)
+ ioctl(sk, SIOCBRDELBR, bridge);
+
+ close(sk);
+
+ return err;
+}
+
+static int nap_remove_bridge(void)
+{
+ int sk, err;
+
+ DBG(" %s", bridge);
+
+ sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ if (sk < 0)
+ return -EOPNOTSUPP;
+
+ err = ioctl(sk, SIOCBRDELBR, bridge);
+ close(sk);
+
+ if (err < 0)
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+static void destroy_nap_device(void)
+{
+ DBG("");
+
+ nap_remove_bridge();
+
+ nap_dev.record_id = 0;
+}
+
+static int register_nap_server(void)
+{
+ int err;
+
+ DBG("");
+
+ err = nap_create_bridge();
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
static void bt_pan_enable(const void *buf, uint16_t len)
{
const struct hal_cmd_pan_enable *cmd = buf;
@@ -441,7 +541,15 @@ bool bt_pan_register(const bdaddr_t *addr)
return false;
}
- record_id = rec->handle;
+ err = register_nap_server();
+ if (err < 0) {
+ bt_adapter_remove_record(rec->handle);
+ sdp_record_free(rec);
+ bnep_cleanup();
+ return false;
+ }
+
+ nap_dev.record_id = rec->handle;
ipc_register(HAL_SERVICE_ID_PAN, cmd_handlers,
G_N_ELEMENTS(cmd_handlers));
@@ -455,6 +563,6 @@ void bt_pan_unregister(void)
bnep_cleanup();
ipc_unregister(HAL_SERVICE_ID_PAN);
- bt_adapter_remove_record(record_id);
- record_id = 0;
+ bt_adapter_remove_record(nap_dev.record_id);
+ destroy_nap_device();
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH 0/4] Add support for NAP role
From: Ravi kumar Veeramally @ 2014-01-06 21:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
This patch set add support for NAP role. It register NAP server and create
bnep bridge and listen for incoming connections from client devices.
On incoming connection request it accepts connection, creates bnep interface
and notifies control state and connection state infromation. Removes device
on disconnect request. Android related changes are required to enable this
role. Patches sent to respective ML.
Ravi kumar Veeramally (4):
android/pan: Register Network Access Point
android/pan: Listen for incoming connections and accept in NAP role
android/pan: Implement PAN enable HAL api at daemon side
android/pan: Remove connected PAN devices on profile unregister call
android/pan.c | 349 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 337 insertions(+), 12 deletions(-)
--
1.8.3.2
^ permalink raw reply
* [PATCH v3 4/4] rfcomm: remove rfcomm_carrier_raised()
From: Gianluca Anzolin @ 2014-01-06 20:23 UTC (permalink / raw)
To: gustavo
Cc: peter, marcel, linux-bluetooth, gregkh, jslaby, stable,
Gianluca Anzolin
In-Reply-To: <1389039834-24491-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 aeabade..f9c0980a 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -160,14 +160,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
* [PATCH v3 3/4] rfcomm: always wait for a bt connection on open()
From: Gianluca Anzolin @ 2014-01-06 20:23 UTC (permalink / raw)
To: gustavo
Cc: peter, marcel, linux-bluetooth, gregkh, jslaby, stable,
Gianluca Anzolin
In-Reply-To: <1389039834-24491-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 | 46 ++++++++++++++++++++++++++++++++++++++--------
1 file changed, 38 insertions(+), 8 deletions(-)
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 32ef9f9..aeabade 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,40 @@ 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);
- return rfcomm_dlc_open(dev->dlc, &dev->src, &dev->dst, dev->channel);
+ if (dev->dlc->state == BT_CLOSED) {
+ err = -dev->err;
+ break;
+ }
+
+ if (dev->dlc->state == BT_CONNECTED)
+ break;
+
+ 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;
}
/* we block the open until the dlc->state becomes BT_CONNECTED */
@@ -151,7 +184,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 +290,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 +609,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 +1133,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 v3 2/4] rfcomm: move rfcomm_get_device() before rfcomm_dev_activate()
From: Gianluca Anzolin @ 2014-01-06 20:23 UTC (permalink / raw)
To: gustavo
Cc: peter, marcel, linux-bluetooth, gregkh, jslaby, stable,
Gianluca Anzolin
In-Reply-To: <1389039834-24491-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 v3 1/4] rfcomm: release the port when the last user closes the tty
From: Gianluca Anzolin @ 2014-01-06 20:23 UTC (permalink / raw)
To: gustavo
Cc: peter, marcel, linux-bluetooth, gregkh, jslaby, stable,
Gianluca Anzolin
In-Reply-To: <1389039834-24491-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 v3 0/4] Regression fixes for rfcomm/tty.c
From: Gianluca Anzolin @ 2014-01-06 20:23 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 v2:
* Fix the style of if statements in rfcomm_dev_activate().
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 | 103 +++++++++++++++++++++++++++++----------------
1 file changed, 66 insertions(+), 37 deletions(-)
--
1.8.5.2
^ permalink raw reply
* Re: [PATCH v2 3/4] rfcomm: always wait for a bt connection on open()
From: Gianluca Anzolin @ 2014-01-06 19:37 UTC (permalink / raw)
To: Marcel Holtmann
Cc: Gustavo F. Padovan, peter,
linux-bluetooth@vger.kernel.org development, Greg KH, jslaby,
stable
In-Reply-To: <4321EF0E-97F4-4236-B763-0D0213BE97A8@holtmann.org>
On Mon, Jan 06, 2014 at 11:17:06AM -0800, Marcel Holtmann wrote:
> 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;
> }
I'll change the code.
> > - 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?
Yes, I removed it before because I relied on the carrier_raised() tty_port
method. But it turned out it wasn't a good idea because some code (wvdial
for example) set that flag on exit, leaving a non-working tty for subsequent
open() calls.
Now I restored the original flags, even if CLOCAL is actually ignored by the
code.
I will shortly send a third iteration with the fixed if statements.
Thanks,
Gianluca
> > rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON;
> > tty_set_operations(rfcomm_tty_driver, &rfcomm_ops);
>
> Regards
>
> Marcel
>
^ 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
* 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 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 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 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 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
* [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
* [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 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 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
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