From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
To: linux-bluetooth@vger.kernel.org
Subject: [PATCH v5 3/3] Bluetooth: Add BT_MODE socket option
Date: Mon, 23 Mar 2020 13:34:58 -0700 [thread overview]
Message-ID: <20200323203458.24733-4-luiz.dentz@gmail.com> (raw)
In-Reply-To: <20200323203458.24733-1-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This adds BT_MODE socket option which can be used to set L2CAP modes,
including modes only supported over LE which were not supported using
the L2CAP_OPTIONS.
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
include/net/bluetooth/bluetooth.h | 8 ++
include/net/bluetooth/l2cap.h | 6 ++
net/bluetooth/l2cap_sock.c | 124 ++++++++++++++++++++++++++++++
3 files changed, 138 insertions(+)
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 1576353a2773..3fa7b1e3c5d9 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -139,6 +139,14 @@ struct bt_voice {
#define BT_PHY_LE_CODED_TX 0x00002000
#define BT_PHY_LE_CODED_RX 0x00004000
+#define BT_MODE 15
+
+#define BT_MODE_BASIC 0x00
+#define BT_MODE_ERTM 0x01
+#define BT_MODE_STREAMING 0x02
+#define BT_MODE_LE_FLOWCTL 0x03
+#define BT_MODE_EXT_FLOWCTL 0x04
+
__printf(1, 2)
void bt_info(const char *fmt, ...);
__printf(1, 2)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index dada14d0622c..56f727ba23bd 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -720,9 +720,15 @@ struct l2cap_user {
/* ----- L2CAP socket info ----- */
#define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
+#define L2CAP_PI_OPTION_UNSET 0x00
+#define L2CAP_PI_OPTION_LEGACY 0x01
+#define L2CAP_PI_OPTION_BT_MODE 0x02
+
struct l2cap_pinfo {
struct bt_sock bt;
struct l2cap_chan *chan;
+ u8 option;
+ u8 bt_mode;
struct sk_buff *rx_busy_skb;
};
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 117ba20ea194..0a57101fe273 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -424,6 +424,14 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
break;
}
+ /* Check if BT_MODE was used which is not compatible with
+ * L2CAP_OPTIONS.
+ */
+ if (l2cap_pi(sk)->option == L2CAP_PI_OPTION_BT_MODE) {
+ err = -EINVAL;
+ break;
+ }
+
memset(&opts, 0, sizeof(opts));
opts.imtu = chan->imtu;
opts.omtu = chan->omtu;
@@ -624,6 +632,29 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
err = -EFAULT;
break;
+ case BT_MODE:
+ if (!enable_ecred) {
+ err = -ENOPROTOOPT;
+ break;
+ }
+
+ if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
+ err = -EINVAL;
+ break;
+ }
+
+ /* Check if L2CAP_OPTIONS was used which is not compatible with
+ * BT_MODE.
+ */
+ if (l2cap_pi(sk)->option == L2CAP_PI_OPTION_LEGACY) {
+ err = -EINVAL;
+ break;
+ }
+
+ if (put_user(l2cap_pi(sk)->bt_mode, (u8 __user *) optval))
+ err = -EFAULT;
+ break;
+
default:
err = -ENOPROTOOPT;
break;
@@ -674,6 +705,14 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
break;
}
+ /* Check if BT_MODE was used which is not compatible with
+ * L2CAP_OPTIONS.
+ */
+ if (l2cap_pi(sk)->option == L2CAP_PI_OPTION_BT_MODE) {
+ err = -EINVAL;
+ break;
+ }
+
opts.imtu = chan->imtu;
opts.omtu = chan->omtu;
opts.flush_to = chan->flush_to;
@@ -715,6 +754,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
break;
}
+ l2cap_pi(sk)->option = L2CAP_PI_OPTION_LEGACY;
+
BT_DBG("mode 0x%2.2x", chan->mode);
chan->imtu = opts.imtu;
@@ -763,6 +804,45 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
return err;
}
+static int l2cap_set_mode(struct l2cap_chan *chan, u8 mode)
+{
+ switch (mode) {
+ case BT_MODE_BASIC:
+ if (bdaddr_type_is_le(chan->src_type))
+ return -EINVAL;
+ mode = L2CAP_MODE_BASIC;
+ clear_bit(CONF_STATE2_DEVICE, &chan->conf_state);
+ break;
+ case BT_MODE_ERTM:
+ if (!disable_ertm || bdaddr_type_is_le(chan->src_type))
+ return -EINVAL;
+ mode = L2CAP_MODE_ERTM;
+ break;
+ case BT_MODE_STREAMING:
+ if (!disable_ertm || bdaddr_type_is_le(chan->src_type))
+ return -EINVAL;
+ mode = L2CAP_MODE_STREAMING;
+ break;
+ case BT_MODE_LE_FLOWCTL:
+ if (!bdaddr_type_is_le(chan->src_type))
+ return -EINVAL;
+ mode = L2CAP_MODE_LE_FLOWCTL;
+ break;
+ case BT_MODE_EXT_FLOWCTL:
+ /* TODO: Add support for ECRED PDUs to BR/EDR */
+ if (!bdaddr_type_is_le(chan->src_type))
+ return -EINVAL;
+ mode = L2CAP_MODE_EXT_FLOWCTL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ chan->mode = mode;
+
+ return 0;
+}
+
static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
char __user *optval, unsigned int optlen)
{
@@ -968,6 +1048,50 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break;
+ case BT_MODE:
+ if (!enable_ecred) {
+ err = -ENOPROTOOPT;
+ break;
+ }
+
+ BT_DBG("sk->sk_state %u", sk->sk_state);
+
+ if (sk->sk_state != BT_BOUND) {
+ err = -EINVAL;
+ break;
+ }
+
+ if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
+ err = -EINVAL;
+ break;
+ }
+
+ /* Check if L2CAP_OPTIONS was used which is not compatible with
+ * BT_MODE.
+ */
+ if (l2cap_pi(sk)->option == L2CAP_PI_OPTION_LEGACY) {
+ err = -EINVAL;
+ break;
+ }
+
+ if (get_user(opt, (u8 __user *) optval)) {
+ err = -EFAULT;
+ break;
+ }
+
+ BT_DBG("opt %u", opt);
+
+ err = l2cap_set_mode(chan, opt);
+ if (err)
+ break;
+
+ l2cap_pi(sk)->option = L2CAP_PI_OPTION_BT_MODE;
+ l2cap_pi(sk)->bt_mode = opt;
+
+ BT_DBG("mode 0x%2.2x", chan->mode);
+
+ break;
+
default:
err = -ENOPROTOOPT;
break;
--
2.21.1
next prev parent reply other threads:[~2020-03-23 20:35 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-03-23 20:34 [PATCH v5 0/3] Enable use of L2CAP_MODE_EXT_FLOWCTL Luiz Augusto von Dentz
2020-03-23 20:34 ` [PATCH v5 1/3] Bluetooth: L2CAP: Add get_peer_pid callback Luiz Augusto von Dentz
2020-03-24 8:48 ` Marcel Holtmann
2020-03-23 20:34 ` [PATCH v5 2/3] Bluetooth: L2CAP: Use DEFER_SETUP to group ECRED connections Luiz Augusto von Dentz
2020-03-24 8:47 ` Marcel Holtmann
2020-03-24 23:10 ` Luiz Augusto von Dentz
2020-03-23 20:34 ` Luiz Augusto von Dentz [this message]
2020-03-24 8:44 ` [PATCH v5 3/3] Bluetooth: Add BT_MODE socket option Marcel Holtmann
2020-03-24 16:56 ` Luiz Augusto von Dentz
2020-03-24 18:37 ` Marcel Holtmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200323203458.24733-4-luiz.dentz@gmail.com \
--to=luiz.dentz@gmail.com \
--cc=linux-bluetooth@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox