summaryrefslogtreecommitdiff
path: root/btio
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2019-07-31 13:56:24 +0300
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2020-03-30 15:23:11 -0700
commitf2418bf97dec1454e958de864964b7792d525e50 (patch)
treeb25dbdd1739a4df64a86db10b63dd0e8602b4707 /btio
parentcbb39474cf4d398d73c908b2adfe117415a90318 (diff)
downloadbluez-f2418bf97dec1454e958de864964b7792d525e50.tar.gz
btio: Add mode to for Enhanced Credit Mode
This adds BT_IO_MODE_EXT_FLOWCTL which directly maps to BT_MODE_EXT_FLOWCTL.
Diffstat (limited to 'btio')
-rw-r--r--btio/btio.c59
-rw-r--r--btio/btio.h6
2 files changed, 56 insertions, 9 deletions
diff --git a/btio/btio.c b/btio/btio.c
index db37b99da..e7b4db16b 100644
--- a/btio/btio.c
+++ b/btio/btio.c
@@ -630,18 +630,34 @@ static gboolean set_le_imtu(int sock, uint16_t imtu, GError **err)
return TRUE;
}
+static gboolean set_le_mode(int sock, uint8_t mode, GError **err)
+{
+ if (setsockopt(sock, SOL_BLUETOOTH, BT_MODE, &mode,
+ sizeof(mode)) < 0) {
+ ERROR_FAILED(err, "setsockopt(BT_MODE)", errno);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static gboolean l2cap_set(int sock, uint8_t src_type, int sec_level,
uint16_t imtu, uint16_t omtu, uint8_t mode,
int master, int flushable, uint32_t priority,
GError **err)
{
if (imtu || omtu || mode) {
- gboolean ret;
+ gboolean ret = FALSE;
if (src_type == BDADDR_BREDR)
ret = set_l2opts(sock, imtu, omtu, mode, err);
- else
- ret = set_le_imtu(sock, imtu, err);
+ else {
+ if (imtu)
+ ret = set_le_imtu(sock, imtu, err);
+
+ if (ret && mode)
+ ret = set_le_mode(sock, mode, err);
+ }
if (!ret)
return ret;
@@ -980,6 +996,30 @@ static int get_phy(int sock, uint32_t *phy)
return 0;
}
+static int get_le_imtu(int sock, uint16_t *mtu)
+{
+ socklen_t len;
+
+ len = sizeof(*mtu);
+
+ if (getsockopt(sock, SOL_BLUETOOTH, BT_RCVMTU, mtu, &len) < 0)
+ return -errno;
+
+ return 0;
+}
+
+static int get_le_mode(int sock, uint8_t *mode)
+{
+ socklen_t len;
+
+ len = sizeof(*mode);
+
+ if (getsockopt(sock, SOL_BLUETOOTH, BT_MODE, mode, &len) < 0)
+ return -errno;
+
+ return 0;
+}
+
static gboolean l2cap_get(int sock, GError **err, BtIOOption opt1,
va_list args)
{
@@ -999,10 +1039,11 @@ static gboolean l2cap_get(int sock, GError **err, BtIOOption opt1,
memset(&l2o, 0, sizeof(l2o));
if (src.l2_bdaddr_type != BDADDR_BREDR) {
- len = sizeof(l2o.imtu);
- if (getsockopt(sock, SOL_BLUETOOTH, BT_RCVMTU,
- &l2o.imtu, &len) == 0)
+ if (get_le_imtu(sock, &l2o.imtu) == 0) {
+ /* Older kernels may not support BT_MODE */
+ get_le_mode(sock, &l2o.mode);
goto parse_opts;
+ }
/* Non-LE CoC enabled kernels will return one of these
* in which case we need to fall back to L2CAP_OPTIONS.
@@ -1644,6 +1685,12 @@ GIOChannel *bt_io_connect(BtIOConnect connect, gpointer user_data,
sock = g_io_channel_unix_get_fd(io);
+ /* Use DEFER_SETUP when connecting using Ext-Flowctl */
+ if (opts.mode == BT_IO_MODE_EXT_FLOWCTL && opts.defer) {
+ setsockopt(sock, SOL_BLUETOOTH, BT_DEFER_SETUP, &opts.defer,
+ sizeof(opts.defer));
+ }
+
switch (opts.type) {
case BT_IO_L2CAP:
err = l2cap_connect(sock, &opts.dst, opts.dst_type,
diff --git a/btio/btio.h b/btio/btio.h
index 41a017acb..23e0ef72b 100644
--- a/btio/btio.h
+++ b/btio/btio.h
@@ -68,10 +68,10 @@ typedef enum {
typedef enum {
BT_IO_MODE_BASIC = 0,
- BT_IO_MODE_RETRANS,
- BT_IO_MODE_FLOWCTL,
BT_IO_MODE_ERTM,
- BT_IO_MODE_STREAMING
+ BT_IO_MODE_STREAMING,
+ BT_IO_MODE_LE_FLOWCTL,
+ BT_IO_MODE_EXT_FLOWCTL
} BtIOMode;
typedef void (*BtIOConfirm)(GIOChannel *io, gpointer user_data);