summaryrefslogtreecommitdiffstats
path: root/btio
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2011-04-21 10:15:04 +0300
committerMarcel Holtmann <marcel@holtmann.org>2011-05-27 10:13:32 -0700
commit478e0ec81a2d0d7e4d5fa284d11b9ff74bc7822e (patch)
treea97e29fa7256b41750c36bdfaebb7fa0eb97f9f3 /btio
parent8a7725492158edf6442f857cb529a68f47821785 (diff)
downloadofono-478e0ec81a2d0d7e4d5fa284d11b9ff74bc7822e.tar.bz2
btio: Add BT_FLUSHABLE support to BtIO
This patch adds support for the BT_FLUSHABLE L2CAP socket option through BtIO. This can be used to mark data from specific L2CAP sockets to have the flushable flag set in their corresponding ACL packets.
Diffstat (limited to 'btio')
-rw-r--r--btio/btio.c58
-rw-r--r--btio/btio.h1
2 files changed, 54 insertions, 5 deletions
diff --git a/btio/btio.c b/btio/btio.c
index 3f5b69ad..6d71b90f 100644
--- a/btio/btio.c
+++ b/btio/btio.c
@@ -59,6 +59,7 @@ struct set_opts {
uint16_t omtu;
int master;
uint8_t mode;
+ int flushable;
};
struct connect {
@@ -485,8 +486,20 @@ static gboolean get_sec_level(int sock, BtIOType type, int *level,
return TRUE;
}
-static gboolean l2cap_set(int sock, int sec_level, uint16_t imtu, uint16_t omtu,
- uint8_t mode, int master, GError **err)
+static int l2cap_set_flushable(int sock, gboolean flushable)
+{
+ int f;
+
+ f = flushable;
+ if (setsockopt(sock, SOL_BLUETOOTH, BT_FLUSHABLE, &f, sizeof(f)) < 0)
+ return -errno;
+
+ return 0;
+}
+
+static gboolean l2cap_set(int sock, int sec_level, uint16_t imtu,
+ uint16_t omtu, uint8_t mode, int master,
+ int flushable, GError **err)
{
if (imtu || omtu || mode) {
struct l2cap_options l2o;
@@ -519,6 +532,11 @@ static gboolean l2cap_set(int sock, int sec_level, uint16_t imtu, uint16_t omtu,
return FALSE;
}
+ if (flushable >= 0 && l2cap_set_flushable(sock, flushable) < 0) {
+ ERROR_FAILED(err, "l2cap_set_flushable", errno);
+ return FALSE;
+ }
+
if (sec_level && !set_sec_level(sock, BT_IO_L2CAP, sec_level, err))
return FALSE;
@@ -643,6 +661,7 @@ static gboolean parse_set_opts(struct set_opts *opts, GError **err,
opts->master = -1;
opts->sec_level = BT_IO_SEC_MEDIUM;
opts->mode = L2CAP_MODE_BASIC;
+ opts->flushable = -1;
while (opt != BT_IO_OPT_INVALID) {
switch (opt) {
@@ -698,6 +717,9 @@ static gboolean parse_set_opts(struct set_opts *opts, GError **err,
case BT_IO_OPT_MODE:
opts->mode = va_arg(args, int);
break;
+ case BT_IO_OPT_FLUSHABLE:
+ opts->flushable = va_arg(args, gboolean);
+ break;
default:
g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
"Unknown option %d", opt);
@@ -750,6 +772,24 @@ static int l2cap_get_info(int sock, uint16_t *handle, uint8_t *dev_class)
return 0;
}
+static int l2cap_get_flushable(int sock, gboolean *flushable)
+{
+ int f;
+ socklen_t len;
+
+ f = 0;
+ len = sizeof(f);
+ if (getsockopt(sock, SOL_BLUETOOTH, BT_FLUSHABLE, &f, &len) < 0)
+ return -errno;
+
+ if (f)
+ *flushable = TRUE;
+ else
+ *flushable = FALSE;
+
+ return 0;
+}
+
static gboolean l2cap_get(int sock, GError **err, BtIOOption opt1,
va_list args)
{
@@ -760,6 +800,7 @@ static gboolean l2cap_get(int sock, GError **err, BtIOOption opt1,
uint8_t dev_class[3];
uint16_t handle;
socklen_t len;
+ gboolean flushable;
len = sizeof(l2o);
memset(&l2o, 0, len);
@@ -842,6 +883,13 @@ static gboolean l2cap_get(int sock, GError **err, BtIOOption opt1,
case BT_IO_OPT_MODE:
*(va_arg(args, uint8_t *)) = l2o.mode;
break;
+ case BT_IO_OPT_FLUSHABLE:
+ if (l2cap_get_flushable(sock, &flushable) < 0) {
+ ERROR_FAILED(err, "get_flushable", errno);
+ return FALSE;
+ }
+ *(va_arg(args, gboolean *)) = flushable;
+ break;
default:
g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
"Unknown option %d", opt);
@@ -1115,7 +1163,7 @@ gboolean bt_io_set(GIOChannel *io, BtIOType type, GError **err,
case BT_IO_L2RAW:
case BT_IO_L2CAP:
return l2cap_set(sock, opts.sec_level, opts.imtu, opts.omtu,
- opts.mode, opts.master, err);
+ opts.mode, opts.master, opts.flushable, err);
case BT_IO_RFCOMM:
return rfcomm_set(sock, opts.sec_level, opts.master, err);
case BT_IO_SCO:
@@ -1156,7 +1204,7 @@ static GIOChannel *create_io(BtIOType type, gboolean server,
if (l2cap_bind(sock, &opts->src, server ? opts->psm : 0,
opts->cid, err) < 0)
goto failed;
- if (!l2cap_set(sock, opts->sec_level, 0, 0, 0, -1, err))
+ if (!l2cap_set(sock, opts->sec_level, 0, 0, 0, -1, -1, err))
goto failed;
break;
case BT_IO_L2CAP:
@@ -1169,7 +1217,7 @@ static GIOChannel *create_io(BtIOType type, gboolean server,
opts->cid, err) < 0)
goto failed;
if (!l2cap_set(sock, opts->sec_level, opts->imtu, opts->omtu,
- opts->mode, opts->master, err))
+ opts->mode, opts->master, opts->flushable, err))
goto failed;
break;
case BT_IO_RFCOMM:
diff --git a/btio/btio.h b/btio/btio.h
index 53e8eaa9..c6b736f0 100644
--- a/btio/btio.h
+++ b/btio/btio.h
@@ -64,6 +64,7 @@ typedef enum {
BT_IO_OPT_HANDLE,
BT_IO_OPT_CLASS,
BT_IO_OPT_MODE,
+ BT_IO_OPT_FLUSHABLE,
} BtIOOption;
typedef enum {