summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/l2cap_core.c13
-rw-r--r--net/bluetooth/l2cap_sock.c21
2 files changed, 31 insertions, 3 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 907fc174532..e260753184b 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -490,6 +490,13 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan)
set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
}
+void l2cap_le_flowctl_init(struct l2cap_chan *chan)
+{
+ chan->imtu = L2CAP_DEFAULT_MTU;
+ chan->omtu = L2CAP_LE_MIN_MTU;
+ chan->mode = L2CAP_MODE_LE_FLOWCTL;
+}
+
void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
{
BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
@@ -597,6 +604,9 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
case L2CAP_MODE_BASIC:
break;
+ case L2CAP_MODE_LE_FLOWCTL:
+ break;
+
case L2CAP_MODE_ERTM:
__clear_retrans_timer(chan);
__clear_monitor_timer(chan);
@@ -1849,6 +1859,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
switch (chan->mode) {
case L2CAP_MODE_BASIC:
+ case L2CAP_MODE_LE_FLOWCTL:
break;
case L2CAP_MODE_ERTM:
case L2CAP_MODE_STREAMING:
@@ -2530,6 +2541,7 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
switch (chan->mode) {
case L2CAP_MODE_BASIC:
+ case L2CAP_MODE_LE_FLOWCTL:
/* Check outgoing MTU */
if (len > chan->omtu)
return -EMSGSIZE;
@@ -6621,6 +6633,7 @@ static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
goto drop;
switch (chan->mode) {
+ case L2CAP_MODE_LE_FLOWCTL:
case L2CAP_MODE_BASIC:
/* If socket recv buffers overflows we drop data here
* which is *bad* because L2CAP has to be reliable.
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 5a1d0cb0b8d..485ca349fed 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -130,6 +130,9 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
bacpy(&chan->src, &la.l2_bdaddr);
chan->src_type = la.l2_bdaddr_type;
+ if (chan->psm && bdaddr_type_is_le(chan->src_type))
+ l2cap_le_flowctl_init(chan);
+
chan->state = BT_BOUND;
sk->sk_state = BT_BOUND;
@@ -200,6 +203,9 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr,
return -EINVAL;
}
+ if (chan->psm && bdaddr_type_is_le(chan->src_type))
+ l2cap_le_flowctl_init(chan);
+
err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid),
&la.l2_bdaddr, la.l2_bdaddr_type);
if (err)
@@ -237,6 +243,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
switch (chan->mode) {
case L2CAP_MODE_BASIC:
+ case L2CAP_MODE_LE_FLOWCTL:
break;
case L2CAP_MODE_ERTM:
case L2CAP_MODE_STREAMING:
@@ -588,6 +595,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
chan->mode = opts.mode;
switch (chan->mode) {
+ case L2CAP_MODE_LE_FLOWCTL:
+ break;
case L2CAP_MODE_BASIC:
clear_bit(CONF_STATE2_DEVICE, &chan->conf_state);
break;
@@ -862,10 +871,16 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
if (sk->sk_state == BT_CONNECT2 && test_bit(BT_SK_DEFER_SETUP,
&bt_sk(sk)->flags)) {
- sk->sk_state = BT_CONFIG;
- pi->chan->state = BT_CONFIG;
+ if (bdaddr_type_is_le(pi->chan->src_type)) {
+ sk->sk_state = BT_CONNECTED;
+ pi->chan->state = BT_CONNECTED;
+ __l2cap_le_connect_rsp_defer(pi->chan);
+ } else {
+ sk->sk_state = BT_CONFIG;
+ pi->chan->state = BT_CONFIG;
+ __l2cap_connect_rsp_defer(pi->chan);
+ }
- __l2cap_connect_rsp_defer(pi->chan);
err = 0;
goto done;
}