diff options
| author | Marcel Holtmann <marcel@holtmann.org> | 2004-11-17 13:21:33 +0100 |
|---|---|---|
| committer | Marcel Holtmann <linux-mh.adm@bkbits.net> | 2004-11-17 13:21:33 +0100 |
| commit | b01b5bbf311edcaf88b28e43db631851310012f6 (patch) | |
| tree | f5f76b7c4be5fbc112add8e094e1adfa7a0bc962 | |
| parent | 4227e3a886a778c3074fcb837c5d4647a417a177 (diff) | |
[Bluetooth] Check for L2CAP reliability
The L2CAP sockets can now set LM_RELIABLE flag and get notification
when a reliability problem with the ACL connection is detected. The
Bluetooth qualification tests require this functionality.
Signed-off-by: Maxim Krasnyansky <maxk@qualcomm.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
| -rw-r--r-- | net/bluetooth/l2cap.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 222184e6e5d4..498572901276 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1100,6 +1100,22 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) read_unlock(&l->lock); } +/* Notify sockets that we cannot guaranty reliability anymore */ +static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) +{ + struct l2cap_chan_list *l = &conn->chan_list; + struct sock *sk; + + BT_DBG("conn %p", conn); + + read_lock(&l->lock); + for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { + if (l2cap_pi(sk)->link_mode & L2CAP_LM_RELIABLE) + sk->sk_err = err; + } + read_unlock(&l->lock); +} + static void l2cap_chan_ready(struct sock *sk) { struct sock *parent = bt_sk(sk)->parent; @@ -2045,10 +2061,12 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl kfree_skb(conn->rx_skb); conn->rx_skb = NULL; conn->rx_len = 0; + l2cap_conn_unreliable(conn, ECOMM); } if (skb->len < 2) { BT_ERR("Frame is too short (len %d)", skb->len); + l2cap_conn_unreliable(conn, ECOMM); goto drop; } @@ -2066,6 +2084,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl if (skb->len > len) { BT_ERR("Frame is too long (len %d, expected len %d)", skb->len, len); + l2cap_conn_unreliable(conn, ECOMM); goto drop; } @@ -2080,6 +2099,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl if (!conn->rx_len) { BT_ERR("Unexpected continuation frame (len %d)", skb->len); + l2cap_conn_unreliable(conn, ECOMM); goto drop; } @@ -2089,6 +2109,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl kfree_skb(conn->rx_skb); conn->rx_skb = NULL; conn->rx_len = 0; + l2cap_conn_unreliable(conn, ECOMM); goto drop; } |
