10a708f8fSGustavo F. Padovan /* 20a708f8fSGustavo F. Padovan BlueZ - Bluetooth protocol stack for Linux 30a708f8fSGustavo F. Padovan Copyright (C) 2000-2001 Qualcomm Incorporated 40a708f8fSGustavo F. Padovan Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org> 50a708f8fSGustavo F. Padovan Copyright (C) 2010 Google Inc. 60a708f8fSGustavo F. Padovan 70a708f8fSGustavo F. Padovan Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> 80a708f8fSGustavo F. Padovan 90a708f8fSGustavo F. Padovan This program is free software; you can redistribute it and/or modify 100a708f8fSGustavo F. Padovan it under the terms of the GNU General Public License version 2 as 110a708f8fSGustavo F. Padovan published by the Free Software Foundation; 120a708f8fSGustavo F. Padovan 130a708f8fSGustavo F. Padovan THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 140a708f8fSGustavo F. Padovan OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 150a708f8fSGustavo F. Padovan FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 160a708f8fSGustavo F. Padovan IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 170a708f8fSGustavo F. Padovan CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 180a708f8fSGustavo F. Padovan WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 190a708f8fSGustavo F. Padovan ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 200a708f8fSGustavo F. Padovan OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 210a708f8fSGustavo F. Padovan 220a708f8fSGustavo F. Padovan ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 230a708f8fSGustavo F. Padovan COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 240a708f8fSGustavo F. Padovan SOFTWARE IS DISCLAIMED. 250a708f8fSGustavo F. Padovan */ 260a708f8fSGustavo F. Padovan 27bb58f747SGustavo F. Padovan /* Bluetooth L2CAP core. */ 280a708f8fSGustavo F. Padovan 290a708f8fSGustavo F. Padovan #include <linux/module.h> 300a708f8fSGustavo F. Padovan 310a708f8fSGustavo F. Padovan #include <linux/types.h> 320a708f8fSGustavo F. Padovan #include <linux/capability.h> 330a708f8fSGustavo F. Padovan #include <linux/errno.h> 340a708f8fSGustavo F. Padovan #include <linux/kernel.h> 350a708f8fSGustavo F. Padovan #include <linux/sched.h> 360a708f8fSGustavo F. Padovan #include <linux/slab.h> 370a708f8fSGustavo F. Padovan #include <linux/poll.h> 380a708f8fSGustavo F. Padovan #include <linux/fcntl.h> 390a708f8fSGustavo F. Padovan #include <linux/init.h> 400a708f8fSGustavo F. Padovan #include <linux/interrupt.h> 410a708f8fSGustavo F. Padovan #include <linux/socket.h> 420a708f8fSGustavo F. Padovan #include <linux/skbuff.h> 430a708f8fSGustavo F. Padovan #include <linux/list.h> 440a708f8fSGustavo F. Padovan #include <linux/device.h> 450a708f8fSGustavo F. Padovan #include <linux/debugfs.h> 460a708f8fSGustavo F. Padovan #include <linux/seq_file.h> 470a708f8fSGustavo F. Padovan #include <linux/uaccess.h> 480a708f8fSGustavo F. Padovan #include <linux/crc16.h> 490a708f8fSGustavo F. Padovan #include <net/sock.h> 500a708f8fSGustavo F. Padovan 510a708f8fSGustavo F. Padovan #include <asm/system.h> 520a708f8fSGustavo F. Padovan #include <asm/unaligned.h> 530a708f8fSGustavo F. Padovan 540a708f8fSGustavo F. Padovan #include <net/bluetooth/bluetooth.h> 550a708f8fSGustavo F. Padovan #include <net/bluetooth/hci_core.h> 560a708f8fSGustavo F. Padovan #include <net/bluetooth/l2cap.h> 57b501d6a1SAnderson Briglia #include <net/bluetooth/smp.h> 580a708f8fSGustavo F. Padovan 59bb58f747SGustavo F. Padovan int disable_ertm; 60a5fd6f30SAndrei Emeltchenko int enable_hs; 610a708f8fSGustavo F. Padovan 620a708f8fSGustavo F. Padovan static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; 630a708f8fSGustavo F. Padovan static u8 l2cap_fixed_chan[8] = { 0x02, }; 640a708f8fSGustavo F. Padovan 65b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list); 66b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock); 670a708f8fSGustavo F. Padovan 680a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 690a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data); 704519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 714519de9aSGustavo F. Padovan void *data); 72710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); 734519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, 744519de9aSGustavo F. Padovan struct l2cap_chan *chan, int err); 750a708f8fSGustavo F. Padovan 760a708f8fSGustavo F. Padovan static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb); 770a708f8fSGustavo F. Padovan 780a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */ 7971ba0e56SGustavo F. Padovan 8071ba0e56SGustavo F. Padovan static inline void chan_hold(struct l2cap_chan *c) 8171ba0e56SGustavo F. Padovan { 8271ba0e56SGustavo F. Padovan atomic_inc(&c->refcnt); 8371ba0e56SGustavo F. Padovan } 8471ba0e56SGustavo F. Padovan 8571ba0e56SGustavo F. Padovan static inline void chan_put(struct l2cap_chan *c) 8671ba0e56SGustavo F. Padovan { 8771ba0e56SGustavo F. Padovan if (atomic_dec_and_test(&c->refcnt)) 8871ba0e56SGustavo F. Padovan kfree(c); 8971ba0e56SGustavo F. Padovan } 9071ba0e56SGustavo F. Padovan 91baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid) 920a708f8fSGustavo F. Padovan { 9348454079SGustavo F. Padovan struct l2cap_chan *c; 94baa7e1faSGustavo F. Padovan 95baa7e1faSGustavo F. Padovan list_for_each_entry(c, &conn->chan_l, list) { 96fe4128e0SGustavo F. Padovan if (c->dcid == cid) 9748454079SGustavo F. Padovan return c; 980a708f8fSGustavo F. Padovan } 99baa7e1faSGustavo F. Padovan return NULL; 100baa7e1faSGustavo F. Padovan 101baa7e1faSGustavo F. Padovan } 1020a708f8fSGustavo F. Padovan 103baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) 1040a708f8fSGustavo F. Padovan { 10548454079SGustavo F. Padovan struct l2cap_chan *c; 106baa7e1faSGustavo F. Padovan 107baa7e1faSGustavo F. Padovan list_for_each_entry(c, &conn->chan_l, list) { 108fe4128e0SGustavo F. Padovan if (c->scid == cid) 10948454079SGustavo F. Padovan return c; 1100a708f8fSGustavo F. Padovan } 111baa7e1faSGustavo F. Padovan return NULL; 112baa7e1faSGustavo F. Padovan } 1130a708f8fSGustavo F. Padovan 1140a708f8fSGustavo F. Padovan /* Find channel with given SCID. 1150a708f8fSGustavo F. Padovan * Returns locked socket */ 116baa7e1faSGustavo F. Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) 1170a708f8fSGustavo F. Padovan { 11848454079SGustavo F. Padovan struct l2cap_chan *c; 119baa7e1faSGustavo F. Padovan 120baa7e1faSGustavo F. Padovan read_lock(&conn->chan_lock); 121baa7e1faSGustavo F. Padovan c = __l2cap_get_chan_by_scid(conn, cid); 12248454079SGustavo F. Padovan if (c) 12348454079SGustavo F. Padovan bh_lock_sock(c->sk); 124baa7e1faSGustavo F. Padovan read_unlock(&conn->chan_lock); 12548454079SGustavo F. Padovan return c; 1260a708f8fSGustavo F. Padovan } 1270a708f8fSGustavo F. Padovan 128baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident) 1290a708f8fSGustavo F. Padovan { 13048454079SGustavo F. Padovan struct l2cap_chan *c; 131baa7e1faSGustavo F. Padovan 132baa7e1faSGustavo F. Padovan list_for_each_entry(c, &conn->chan_l, list) { 133fc7f8a7eSGustavo F. Padovan if (c->ident == ident) 13448454079SGustavo F. Padovan return c; 1350a708f8fSGustavo F. Padovan } 136baa7e1faSGustavo F. Padovan return NULL; 137baa7e1faSGustavo F. Padovan } 1380a708f8fSGustavo F. Padovan 139baa7e1faSGustavo F. Padovan static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident) 1400a708f8fSGustavo F. Padovan { 14148454079SGustavo F. Padovan struct l2cap_chan *c; 142baa7e1faSGustavo F. Padovan 143baa7e1faSGustavo F. Padovan read_lock(&conn->chan_lock); 144baa7e1faSGustavo F. Padovan c = __l2cap_get_chan_by_ident(conn, ident); 14548454079SGustavo F. Padovan if (c) 14648454079SGustavo F. Padovan bh_lock_sock(c->sk); 147baa7e1faSGustavo F. Padovan read_unlock(&conn->chan_lock); 14848454079SGustavo F. Padovan return c; 1490a708f8fSGustavo F. Padovan } 1500a708f8fSGustavo F. Padovan 15123691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src) 1529e4425ffSGustavo F. Padovan { 15323691d75SGustavo F. Padovan struct l2cap_chan *c; 1549e4425ffSGustavo F. Padovan 15523691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 15623691d75SGustavo F. Padovan if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src)) 1579e4425ffSGustavo F. Padovan goto found; 1589e4425ffSGustavo F. Padovan } 1599e4425ffSGustavo F. Padovan 16023691d75SGustavo F. Padovan c = NULL; 1619e4425ffSGustavo F. Padovan found: 16223691d75SGustavo F. Padovan return c; 1639e4425ffSGustavo F. Padovan } 1649e4425ffSGustavo F. Padovan 1659e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) 1669e4425ffSGustavo F. Padovan { 16773b2ec18SGustavo F. Padovan int err; 16873b2ec18SGustavo F. Padovan 16923691d75SGustavo F. Padovan write_lock_bh(&chan_list_lock); 1709e4425ffSGustavo F. Padovan 17123691d75SGustavo F. Padovan if (psm && __l2cap_global_chan_by_addr(psm, src)) { 17273b2ec18SGustavo F. Padovan err = -EADDRINUSE; 17373b2ec18SGustavo F. Padovan goto done; 1749e4425ffSGustavo F. Padovan } 1759e4425ffSGustavo F. Padovan 17673b2ec18SGustavo F. Padovan if (psm) { 1779e4425ffSGustavo F. Padovan chan->psm = psm; 1789e4425ffSGustavo F. Padovan chan->sport = psm; 17973b2ec18SGustavo F. Padovan err = 0; 18073b2ec18SGustavo F. Padovan } else { 18173b2ec18SGustavo F. Padovan u16 p; 1829e4425ffSGustavo F. Padovan 18373b2ec18SGustavo F. Padovan err = -EINVAL; 18473b2ec18SGustavo F. Padovan for (p = 0x1001; p < 0x1100; p += 2) 18523691d75SGustavo F. Padovan if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) { 18673b2ec18SGustavo F. Padovan chan->psm = cpu_to_le16(p); 18773b2ec18SGustavo F. Padovan chan->sport = cpu_to_le16(p); 18873b2ec18SGustavo F. Padovan err = 0; 18973b2ec18SGustavo F. Padovan break; 19073b2ec18SGustavo F. Padovan } 19173b2ec18SGustavo F. Padovan } 19273b2ec18SGustavo F. Padovan 19373b2ec18SGustavo F. Padovan done: 19423691d75SGustavo F. Padovan write_unlock_bh(&chan_list_lock); 19573b2ec18SGustavo F. Padovan return err; 1969e4425ffSGustavo F. Padovan } 1979e4425ffSGustavo F. Padovan 1989e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) 1999e4425ffSGustavo F. Padovan { 20023691d75SGustavo F. Padovan write_lock_bh(&chan_list_lock); 2019e4425ffSGustavo F. Padovan 2029e4425ffSGustavo F. Padovan chan->scid = scid; 2039e4425ffSGustavo F. Padovan 20423691d75SGustavo F. Padovan write_unlock_bh(&chan_list_lock); 2059e4425ffSGustavo F. Padovan 2069e4425ffSGustavo F. Padovan return 0; 2079e4425ffSGustavo F. Padovan } 2089e4425ffSGustavo F. Padovan 209baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn) 2100a708f8fSGustavo F. Padovan { 2110a708f8fSGustavo F. Padovan u16 cid = L2CAP_CID_DYN_START; 2120a708f8fSGustavo F. Padovan 2130a708f8fSGustavo F. Padovan for (; cid < L2CAP_CID_DYN_END; cid++) { 214baa7e1faSGustavo F. Padovan if (!__l2cap_get_chan_by_scid(conn, cid)) 2150a708f8fSGustavo F. Padovan return cid; 2160a708f8fSGustavo F. Padovan } 2170a708f8fSGustavo F. Padovan 2180a708f8fSGustavo F. Padovan return 0; 2190a708f8fSGustavo F. Padovan } 2200a708f8fSGustavo F. Padovan 221c9b66675SGustavo F. Padovan static void l2cap_set_timer(struct l2cap_chan *chan, struct timer_list *timer, long timeout) 222ab07801dSGustavo F. Padovan { 223457f4850SAndrei Emeltchenko BT_DBG("chan %p state %d timeout %ld", chan, chan->state, timeout); 22489bc500eSGustavo F. Padovan 225942ecc9cSMat Martineau if (!mod_timer(timer, jiffies + msecs_to_jiffies(timeout))) 22671ba0e56SGustavo F. Padovan chan_hold(chan); 227ab07801dSGustavo F. Padovan } 228ab07801dSGustavo F. Padovan 229c9b66675SGustavo F. Padovan static void l2cap_clear_timer(struct l2cap_chan *chan, struct timer_list *timer) 230ab07801dSGustavo F. Padovan { 23189bc500eSGustavo F. Padovan BT_DBG("chan %p state %d", chan, chan->state); 232ab07801dSGustavo F. Padovan 233c9b66675SGustavo F. Padovan if (timer_pending(timer) && del_timer(timer)) 23471ba0e56SGustavo F. Padovan chan_put(chan); 235ab07801dSGustavo F. Padovan } 236ab07801dSGustavo F. Padovan 23789bc500eSGustavo F. Padovan static void l2cap_state_change(struct l2cap_chan *chan, int state) 23889bc500eSGustavo F. Padovan { 23989bc500eSGustavo F. Padovan chan->state = state; 24089bc500eSGustavo F. Padovan chan->ops->state_change(chan->data, state); 24189bc500eSGustavo F. Padovan } 24289bc500eSGustavo F. Padovan 243ab07801dSGustavo F. Padovan static void l2cap_chan_timeout(unsigned long arg) 244ab07801dSGustavo F. Padovan { 245ab07801dSGustavo F. Padovan struct l2cap_chan *chan = (struct l2cap_chan *) arg; 246ab07801dSGustavo F. Padovan struct sock *sk = chan->sk; 247ab07801dSGustavo F. Padovan int reason; 248ab07801dSGustavo F. Padovan 24989bc500eSGustavo F. Padovan BT_DBG("chan %p state %d", chan, chan->state); 250ab07801dSGustavo F. Padovan 251ab07801dSGustavo F. Padovan bh_lock_sock(sk); 252ab07801dSGustavo F. Padovan 253ab07801dSGustavo F. Padovan if (sock_owned_by_user(sk)) { 254ab07801dSGustavo F. Padovan /* sk is owned by user. Try again later */ 255c9b66675SGustavo F. Padovan __set_chan_timer(chan, HZ / 5); 256ab07801dSGustavo F. Padovan bh_unlock_sock(sk); 25771ba0e56SGustavo F. Padovan chan_put(chan); 258ab07801dSGustavo F. Padovan return; 259ab07801dSGustavo F. Padovan } 260ab07801dSGustavo F. Padovan 26189bc500eSGustavo F. Padovan if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) 262ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 26389bc500eSGustavo F. Padovan else if (chan->state == BT_CONNECT && 264ab07801dSGustavo F. Padovan chan->sec_level != BT_SECURITY_SDP) 265ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 266ab07801dSGustavo F. Padovan else 267ab07801dSGustavo F. Padovan reason = ETIMEDOUT; 268ab07801dSGustavo F. Padovan 2690f852724SGustavo F. Padovan l2cap_chan_close(chan, reason); 270ab07801dSGustavo F. Padovan 271ab07801dSGustavo F. Padovan bh_unlock_sock(sk); 272ab07801dSGustavo F. Padovan 273ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 27471ba0e56SGustavo F. Padovan chan_put(chan); 275ab07801dSGustavo F. Padovan } 276ab07801dSGustavo F. Padovan 27723691d75SGustavo F. Padovan struct l2cap_chan *l2cap_chan_create(struct sock *sk) 2780a708f8fSGustavo F. Padovan { 27948454079SGustavo F. Padovan struct l2cap_chan *chan; 2800a708f8fSGustavo F. Padovan 28148454079SGustavo F. Padovan chan = kzalloc(sizeof(*chan), GFP_ATOMIC); 28248454079SGustavo F. Padovan if (!chan) 28348454079SGustavo F. Padovan return NULL; 2840a708f8fSGustavo F. Padovan 28548454079SGustavo F. Padovan chan->sk = sk; 28648454079SGustavo F. Padovan 28723691d75SGustavo F. Padovan write_lock_bh(&chan_list_lock); 28823691d75SGustavo F. Padovan list_add(&chan->global_l, &chan_list); 28923691d75SGustavo F. Padovan write_unlock_bh(&chan_list_lock); 29023691d75SGustavo F. Padovan 291ab07801dSGustavo F. Padovan setup_timer(&chan->chan_timer, l2cap_chan_timeout, (unsigned long) chan); 292ab07801dSGustavo F. Padovan 29389bc500eSGustavo F. Padovan chan->state = BT_OPEN; 29489bc500eSGustavo F. Padovan 29571ba0e56SGustavo F. Padovan atomic_set(&chan->refcnt, 1); 29671ba0e56SGustavo F. Padovan 29748454079SGustavo F. Padovan return chan; 2980a708f8fSGustavo F. Padovan } 2990a708f8fSGustavo F. Padovan 30023691d75SGustavo F. Padovan void l2cap_chan_destroy(struct l2cap_chan *chan) 3016ff5abbfSGustavo F. Padovan { 30223691d75SGustavo F. Padovan write_lock_bh(&chan_list_lock); 30323691d75SGustavo F. Padovan list_del(&chan->global_l); 30423691d75SGustavo F. Padovan write_unlock_bh(&chan_list_lock); 30523691d75SGustavo F. Padovan 30671ba0e56SGustavo F. Padovan chan_put(chan); 3076ff5abbfSGustavo F. Padovan } 3086ff5abbfSGustavo F. Padovan 30948454079SGustavo F. Padovan static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 3100a708f8fSGustavo F. Padovan { 3110a708f8fSGustavo F. Padovan BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, 312fe4128e0SGustavo F. Padovan chan->psm, chan->dcid); 3130a708f8fSGustavo F. Padovan 3140a708f8fSGustavo F. Padovan conn->disc_reason = 0x13; 3150a708f8fSGustavo F. Padovan 3168c1d787bSGustavo F. Padovan chan->conn = conn; 3170a708f8fSGustavo F. Padovan 318715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) { 319b62f328bSVille Tervo if (conn->hcon->type == LE_LINK) { 320b62f328bSVille Tervo /* LE connection */ 3210c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_LE_DEFAULT_MTU; 322fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_LE_DATA; 323fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_LE_DATA; 324b62f328bSVille Tervo } else { 3250a708f8fSGustavo F. Padovan /* Alloc CID for connection-oriented socket */ 326fe4128e0SGustavo F. Padovan chan->scid = l2cap_alloc_cid(conn); 3270c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 328b62f328bSVille Tervo } 329715ec005SGustavo F. Padovan } else if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { 3300a708f8fSGustavo F. Padovan /* Connectionless socket */ 331fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_CONN_LESS; 332fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_CONN_LESS; 3330c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 3340a708f8fSGustavo F. Padovan } else { 3350a708f8fSGustavo F. Padovan /* Raw socket can send/recv signalling messages only */ 336fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_SIGNALING; 337fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_SIGNALING; 3380c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 3390a708f8fSGustavo F. Padovan } 3400a708f8fSGustavo F. Padovan 3418f7975b1SAndrei Emeltchenko chan->local_id = L2CAP_BESTEFFORT_ID; 3428f7975b1SAndrei Emeltchenko chan->local_stype = L2CAP_SERV_BESTEFFORT; 3438f7975b1SAndrei Emeltchenko chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE; 3448f7975b1SAndrei Emeltchenko chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME; 3458f7975b1SAndrei Emeltchenko chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT; 3468f7975b1SAndrei Emeltchenko chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO; 3478f7975b1SAndrei Emeltchenko 34871ba0e56SGustavo F. Padovan chan_hold(chan); 349baa7e1faSGustavo F. Padovan 350baa7e1faSGustavo F. Padovan list_add(&chan->list, &conn->chan_l); 3510a708f8fSGustavo F. Padovan } 3520a708f8fSGustavo F. Padovan 3530a708f8fSGustavo F. Padovan /* Delete channel. 3540a708f8fSGustavo F. Padovan * Must be called on the locked socket. */ 3554519de9aSGustavo F. Padovan static void l2cap_chan_del(struct l2cap_chan *chan, int err) 3560a708f8fSGustavo F. Padovan { 35748454079SGustavo F. Padovan struct sock *sk = chan->sk; 3588c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 3590a708f8fSGustavo F. Padovan struct sock *parent = bt_sk(sk)->parent; 3600a708f8fSGustavo F. Padovan 361c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 3620a708f8fSGustavo F. Padovan 36349208c9cSGustavo F. Padovan BT_DBG("chan %p, conn %p, err %d", chan, conn, err); 3640a708f8fSGustavo F. Padovan 3650a708f8fSGustavo F. Padovan if (conn) { 366baa7e1faSGustavo F. Padovan /* Delete from channel list */ 367baa7e1faSGustavo F. Padovan write_lock_bh(&conn->chan_lock); 368baa7e1faSGustavo F. Padovan list_del(&chan->list); 369baa7e1faSGustavo F. Padovan write_unlock_bh(&conn->chan_lock); 37071ba0e56SGustavo F. Padovan chan_put(chan); 371baa7e1faSGustavo F. Padovan 3728c1d787bSGustavo F. Padovan chan->conn = NULL; 3730a708f8fSGustavo F. Padovan hci_conn_put(conn->hcon); 3740a708f8fSGustavo F. Padovan } 3750a708f8fSGustavo F. Padovan 37689bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CLOSED); 3770a708f8fSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 3780a708f8fSGustavo F. Padovan 3790a708f8fSGustavo F. Padovan if (err) 3800a708f8fSGustavo F. Padovan sk->sk_err = err; 3810a708f8fSGustavo F. Padovan 3820a708f8fSGustavo F. Padovan if (parent) { 3830a708f8fSGustavo F. Padovan bt_accept_unlink(sk); 3840a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 3850a708f8fSGustavo F. Padovan } else 3860a708f8fSGustavo F. Padovan sk->sk_state_change(sk); 3870a708f8fSGustavo F. Padovan 388c1360a1cSGustavo F. Padovan if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) && 389c1360a1cSGustavo F. Padovan test_bit(CONF_INPUT_DONE, &chan->conf_state))) 3906ff5abbfSGustavo F. Padovan return; 3912ead70b8SGustavo F. Padovan 39258d35f87SGustavo F. Padovan skb_queue_purge(&chan->tx_q); 3930a708f8fSGustavo F. Padovan 3940c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_ERTM) { 3950a708f8fSGustavo F. Padovan struct srej_list *l, *tmp; 3960a708f8fSGustavo F. Padovan 3971a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 3981a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 3991a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 4000a708f8fSGustavo F. Padovan 401f1c6775bSGustavo F. Padovan skb_queue_purge(&chan->srej_q); 4020a708f8fSGustavo F. Padovan 40339d5a3eeSGustavo F. Padovan list_for_each_entry_safe(l, tmp, &chan->srej_l, list) { 4040a708f8fSGustavo F. Padovan list_del(&l->list); 4050a708f8fSGustavo F. Padovan kfree(l); 4060a708f8fSGustavo F. Padovan } 4070a708f8fSGustavo F. Padovan } 4080a708f8fSGustavo F. Padovan } 4090a708f8fSGustavo F. Padovan 4104519de9aSGustavo F. Padovan static void l2cap_chan_cleanup_listen(struct sock *parent) 4114519de9aSGustavo F. Padovan { 4124519de9aSGustavo F. Padovan struct sock *sk; 4134519de9aSGustavo F. Padovan 4144519de9aSGustavo F. Padovan BT_DBG("parent %p", parent); 4154519de9aSGustavo F. Padovan 4164519de9aSGustavo F. Padovan /* Close not yet accepted channels */ 4170f852724SGustavo F. Padovan while ((sk = bt_accept_dequeue(parent, NULL))) { 418ba3bd0eeSGustavo F. Padovan struct l2cap_chan *chan = l2cap_pi(sk)->chan; 419c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 4200f852724SGustavo F. Padovan lock_sock(sk); 421ba3bd0eeSGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 4220f852724SGustavo F. Padovan release_sock(sk); 423ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 4240f852724SGustavo F. Padovan } 4254519de9aSGustavo F. Padovan } 4264519de9aSGustavo F. Padovan 4270f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason) 4284519de9aSGustavo F. Padovan { 4294519de9aSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 4304519de9aSGustavo F. Padovan struct sock *sk = chan->sk; 4314519de9aSGustavo F. Padovan 43289bc500eSGustavo F. Padovan BT_DBG("chan %p state %d socket %p", chan, chan->state, sk->sk_socket); 4334519de9aSGustavo F. Padovan 43489bc500eSGustavo F. Padovan switch (chan->state) { 4354519de9aSGustavo F. Padovan case BT_LISTEN: 4364519de9aSGustavo F. Padovan l2cap_chan_cleanup_listen(sk); 43789bc500eSGustavo F. Padovan 43889bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CLOSED); 43989bc500eSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 4404519de9aSGustavo F. Padovan break; 4414519de9aSGustavo F. Padovan 4424519de9aSGustavo F. Padovan case BT_CONNECTED: 4434519de9aSGustavo F. Padovan case BT_CONFIG: 444715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && 4454519de9aSGustavo F. Padovan conn->hcon->type == ACL_LINK) { 446c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 447c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 4484519de9aSGustavo F. Padovan l2cap_send_disconn_req(conn, chan, reason); 4494519de9aSGustavo F. Padovan } else 4504519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 4514519de9aSGustavo F. Padovan break; 4524519de9aSGustavo F. Padovan 4534519de9aSGustavo F. Padovan case BT_CONNECT2: 454715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && 4554519de9aSGustavo F. Padovan conn->hcon->type == ACL_LINK) { 4564519de9aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 4574519de9aSGustavo F. Padovan __u16 result; 4584519de9aSGustavo F. Padovan 4594519de9aSGustavo F. Padovan if (bt_sk(sk)->defer_setup) 4604519de9aSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 4614519de9aSGustavo F. Padovan else 4624519de9aSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 46389bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_DISCONN); 4644519de9aSGustavo F. Padovan 4654519de9aSGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 4664519de9aSGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 4674519de9aSGustavo F. Padovan rsp.result = cpu_to_le16(result); 4684519de9aSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 4694519de9aSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 4704519de9aSGustavo F. Padovan sizeof(rsp), &rsp); 4714519de9aSGustavo F. Padovan } 4724519de9aSGustavo F. Padovan 4734519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 4744519de9aSGustavo F. Padovan break; 4754519de9aSGustavo F. Padovan 4764519de9aSGustavo F. Padovan case BT_CONNECT: 4774519de9aSGustavo F. Padovan case BT_DISCONN: 4784519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 4794519de9aSGustavo F. Padovan break; 4804519de9aSGustavo F. Padovan 4814519de9aSGustavo F. Padovan default: 4824519de9aSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 4834519de9aSGustavo F. Padovan break; 4844519de9aSGustavo F. Padovan } 4854519de9aSGustavo F. Padovan } 4864519de9aSGustavo F. Padovan 4874343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) 4880a708f8fSGustavo F. Padovan { 489715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_RAW) { 4904343478fSGustavo F. Padovan switch (chan->sec_level) { 4910a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 4920a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING_MITM; 4930a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 4940a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING; 4950a708f8fSGustavo F. Padovan default: 4960a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 4970a708f8fSGustavo F. Padovan } 498fe4128e0SGustavo F. Padovan } else if (chan->psm == cpu_to_le16(0x0001)) { 4994343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_LOW) 5004343478fSGustavo F. Padovan chan->sec_level = BT_SECURITY_SDP; 5010a708f8fSGustavo F. Padovan 5024343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_HIGH) 5030a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING_MITM; 5040a708f8fSGustavo F. Padovan else 5050a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 5060a708f8fSGustavo F. Padovan } else { 5074343478fSGustavo F. Padovan switch (chan->sec_level) { 5080a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 5090a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING_MITM; 5100a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 5110a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING; 5120a708f8fSGustavo F. Padovan default: 5130a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 5140a708f8fSGustavo F. Padovan } 5150a708f8fSGustavo F. Padovan } 5160a708f8fSGustavo F. Padovan } 5170a708f8fSGustavo F. Padovan 5180a708f8fSGustavo F. Padovan /* Service level security */ 5194343478fSGustavo F. Padovan static inline int l2cap_check_security(struct l2cap_chan *chan) 5200a708f8fSGustavo F. Padovan { 5218c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 5220a708f8fSGustavo F. Padovan __u8 auth_type; 5230a708f8fSGustavo F. Padovan 5244343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 5250a708f8fSGustavo F. Padovan 5264343478fSGustavo F. Padovan return hci_conn_security(conn->hcon, chan->sec_level, auth_type); 5270a708f8fSGustavo F. Padovan } 5280a708f8fSGustavo F. Padovan 529b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn) 5300a708f8fSGustavo F. Padovan { 5310a708f8fSGustavo F. Padovan u8 id; 5320a708f8fSGustavo F. Padovan 5330a708f8fSGustavo F. Padovan /* Get next available identificator. 5340a708f8fSGustavo F. Padovan * 1 - 128 are used by kernel. 5350a708f8fSGustavo F. Padovan * 129 - 199 are reserved. 5360a708f8fSGustavo F. Padovan * 200 - 254 are used by utilities like l2ping, etc. 5370a708f8fSGustavo F. Padovan */ 5380a708f8fSGustavo F. Padovan 5390a708f8fSGustavo F. Padovan spin_lock_bh(&conn->lock); 5400a708f8fSGustavo F. Padovan 5410a708f8fSGustavo F. Padovan if (++conn->tx_ident > 128) 5420a708f8fSGustavo F. Padovan conn->tx_ident = 1; 5430a708f8fSGustavo F. Padovan 5440a708f8fSGustavo F. Padovan id = conn->tx_ident; 5450a708f8fSGustavo F. Padovan 5460a708f8fSGustavo F. Padovan spin_unlock_bh(&conn->lock); 5470a708f8fSGustavo F. Padovan 5480a708f8fSGustavo F. Padovan return id; 5490a708f8fSGustavo F. Padovan } 5500a708f8fSGustavo F. Padovan 5514519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) 5520a708f8fSGustavo F. Padovan { 5530a708f8fSGustavo F. Padovan struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); 5540a708f8fSGustavo F. Padovan u8 flags; 5550a708f8fSGustavo F. Padovan 5560a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x", code); 5570a708f8fSGustavo F. Padovan 5580a708f8fSGustavo F. Padovan if (!skb) 5590a708f8fSGustavo F. Padovan return; 5600a708f8fSGustavo F. Padovan 5610a708f8fSGustavo F. Padovan if (lmp_no_flush_capable(conn->hcon->hdev)) 5620a708f8fSGustavo F. Padovan flags = ACL_START_NO_FLUSH; 5630a708f8fSGustavo F. Padovan else 5640a708f8fSGustavo F. Padovan flags = ACL_START; 5650a708f8fSGustavo F. Padovan 56614b12d0bSJaikumar Ganesh bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON; 5675e59b791SLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 56814b12d0bSJaikumar Ganesh 569*73d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, flags); 570*73d80debSLuiz Augusto von Dentz } 571*73d80debSLuiz Augusto von Dentz 572*73d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) 573*73d80debSLuiz Augusto von Dentz { 574*73d80debSLuiz Augusto von Dentz struct hci_conn *hcon = chan->conn->hcon; 575*73d80debSLuiz Augusto von Dentz u16 flags; 576*73d80debSLuiz Augusto von Dentz 577*73d80debSLuiz Augusto von Dentz BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, 578*73d80debSLuiz Augusto von Dentz skb->priority); 579*73d80debSLuiz Augusto von Dentz 580*73d80debSLuiz Augusto von Dentz if (!test_bit(FLAG_FLUSHABLE, &chan->flags) && 581*73d80debSLuiz Augusto von Dentz lmp_no_flush_capable(hcon->hdev)) 582*73d80debSLuiz Augusto von Dentz flags = ACL_START_NO_FLUSH; 583*73d80debSLuiz Augusto von Dentz else 584*73d80debSLuiz Augusto von Dentz flags = ACL_START; 585*73d80debSLuiz Augusto von Dentz 586*73d80debSLuiz Augusto von Dentz bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); 587*73d80debSLuiz Augusto von Dentz hci_send_acl(chan->conn->hchan, skb, flags); 5880a708f8fSGustavo F. Padovan } 5890a708f8fSGustavo F. Padovan 59088843ab0SAndrei Emeltchenko static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control) 5910a708f8fSGustavo F. Padovan { 5920a708f8fSGustavo F. Padovan struct sk_buff *skb; 5930a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 5948c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 595e4ca6d98SAndrei Emeltchenko int count, hlen; 5960a708f8fSGustavo F. Padovan 59789bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 5980a708f8fSGustavo F. Padovan return; 5990a708f8fSGustavo F. Padovan 600e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 601e4ca6d98SAndrei Emeltchenko hlen = L2CAP_EXT_HDR_SIZE; 602e4ca6d98SAndrei Emeltchenko else 603e4ca6d98SAndrei Emeltchenko hlen = L2CAP_ENH_HDR_SIZE; 604e4ca6d98SAndrei Emeltchenko 60547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 60603a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 6070a708f8fSGustavo F. Padovan 60888843ab0SAndrei Emeltchenko BT_DBG("chan %p, control 0x%8.8x", chan, control); 6090a708f8fSGustavo F. Padovan 6100a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, hlen); 611793c2f1cSAndrei Emeltchenko 612793c2f1cSAndrei Emeltchenko control |= __set_sframe(chan); 6130a708f8fSGustavo F. Padovan 614e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 61503f6715dSAndrei Emeltchenko control |= __set_ctrl_final(chan); 6160a708f8fSGustavo F. Padovan 617e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state)) 618e3781735SAndrei Emeltchenko control |= __set_ctrl_poll(chan); 6190a708f8fSGustavo F. Padovan 6200a708f8fSGustavo F. Padovan skb = bt_skb_alloc(count, GFP_ATOMIC); 6210a708f8fSGustavo F. Padovan if (!skb) 6220a708f8fSGustavo F. Padovan return; 6230a708f8fSGustavo F. Padovan 6240a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 6250a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); 626fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 62788843ab0SAndrei Emeltchenko 62888843ab0SAndrei Emeltchenko __put_control(chan, control, skb_put(skb, __ctrl_size(chan))); 6290a708f8fSGustavo F. Padovan 63047d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 63103a51213SAndrei Emeltchenko u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE); 63203a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 6330a708f8fSGustavo F. Padovan } 6340a708f8fSGustavo F. Padovan 635*73d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 636*73d80debSLuiz Augusto von Dentz l2cap_do_send(chan, skb); 6370a708f8fSGustavo F. Padovan } 6380a708f8fSGustavo F. Padovan 63988843ab0SAndrei Emeltchenko static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control) 6400a708f8fSGustavo F. Padovan { 641e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 642ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); 643e2ab4353SGustavo F. Padovan set_bit(CONN_RNR_SENT, &chan->conn_state); 6440a708f8fSGustavo F. Padovan } else 645ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 6460a708f8fSGustavo F. Padovan 6470b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 6480a708f8fSGustavo F. Padovan 649525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 6500a708f8fSGustavo F. Padovan } 6510a708f8fSGustavo F. Padovan 652b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) 6530a708f8fSGustavo F. Padovan { 654c1360a1cSGustavo F. Padovan return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); 6550a708f8fSGustavo F. Padovan } 6560a708f8fSGustavo F. Padovan 657fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan) 6580a708f8fSGustavo F. Padovan { 6598c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 6600a708f8fSGustavo F. Padovan 6610a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { 6620a708f8fSGustavo F. Padovan if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) 6630a708f8fSGustavo F. Padovan return; 6640a708f8fSGustavo F. Padovan 6654343478fSGustavo F. Padovan if (l2cap_check_security(chan) && 6664343478fSGustavo F. Padovan __l2cap_no_conn_pending(chan)) { 6670a708f8fSGustavo F. Padovan struct l2cap_conn_req req; 668fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 669fe4128e0SGustavo F. Padovan req.psm = chan->psm; 6700a708f8fSGustavo F. Padovan 671fc7f8a7eSGustavo F. Padovan chan->ident = l2cap_get_ident(conn); 672c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 6730a708f8fSGustavo F. Padovan 674fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, 675fc7f8a7eSGustavo F. Padovan sizeof(req), &req); 6760a708f8fSGustavo F. Padovan } 6770a708f8fSGustavo F. Padovan } else { 6780a708f8fSGustavo F. Padovan struct l2cap_info_req req; 6790a708f8fSGustavo F. Padovan req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 6800a708f8fSGustavo F. Padovan 6810a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 6820a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 6830a708f8fSGustavo F. Padovan 6840a708f8fSGustavo F. Padovan mod_timer(&conn->info_timer, jiffies + 6850a708f8fSGustavo F. Padovan msecs_to_jiffies(L2CAP_INFO_TIMEOUT)); 6860a708f8fSGustavo F. Padovan 6870a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 6880a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 6890a708f8fSGustavo F. Padovan } 6900a708f8fSGustavo F. Padovan } 6910a708f8fSGustavo F. Padovan 6920a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) 6930a708f8fSGustavo F. Padovan { 6940a708f8fSGustavo F. Padovan u32 local_feat_mask = l2cap_feat_mask; 6950a708f8fSGustavo F. Padovan if (!disable_ertm) 6960a708f8fSGustavo F. Padovan local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING; 6970a708f8fSGustavo F. Padovan 6980a708f8fSGustavo F. Padovan switch (mode) { 6990a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 7000a708f8fSGustavo F. Padovan return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask; 7010a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 7020a708f8fSGustavo F. Padovan return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask; 7030a708f8fSGustavo F. Padovan default: 7040a708f8fSGustavo F. Padovan return 0x00; 7050a708f8fSGustavo F. Padovan } 7060a708f8fSGustavo F. Padovan } 7070a708f8fSGustavo F. Padovan 7084519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err) 7090a708f8fSGustavo F. Padovan { 710e92c8e70SGustavo F. Padovan struct sock *sk; 7110a708f8fSGustavo F. Padovan struct l2cap_disconn_req req; 7120a708f8fSGustavo F. Padovan 7130a708f8fSGustavo F. Padovan if (!conn) 7140a708f8fSGustavo F. Padovan return; 7150a708f8fSGustavo F. Padovan 716e92c8e70SGustavo F. Padovan sk = chan->sk; 717e92c8e70SGustavo F. Padovan 7180c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_ERTM) { 7191a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 7201a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 7211a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 7220a708f8fSGustavo F. Padovan } 7230a708f8fSGustavo F. Padovan 724fe4128e0SGustavo F. Padovan req.dcid = cpu_to_le16(chan->dcid); 725fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 7260a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 7270a708f8fSGustavo F. Padovan L2CAP_DISCONN_REQ, sizeof(req), &req); 7280a708f8fSGustavo F. Padovan 72989bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_DISCONN); 7300a708f8fSGustavo F. Padovan sk->sk_err = err; 7310a708f8fSGustavo F. Padovan } 7320a708f8fSGustavo F. Padovan 7330a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */ 7340a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn) 7350a708f8fSGustavo F. Padovan { 736820ffdb3SGustavo F. Padovan struct l2cap_chan *chan, *tmp; 7370a708f8fSGustavo F. Padovan 7380a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 7390a708f8fSGustavo F. Padovan 740baa7e1faSGustavo F. Padovan read_lock(&conn->chan_lock); 7410a708f8fSGustavo F. Padovan 742820ffdb3SGustavo F. Padovan list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 74348454079SGustavo F. Padovan struct sock *sk = chan->sk; 744baa7e1faSGustavo F. Padovan 7450a708f8fSGustavo F. Padovan bh_lock_sock(sk); 7460a708f8fSGustavo F. Padovan 747715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 7480a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 7490a708f8fSGustavo F. Padovan continue; 7500a708f8fSGustavo F. Padovan } 7510a708f8fSGustavo F. Padovan 75289bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 7530a708f8fSGustavo F. Padovan struct l2cap_conn_req req; 7540a708f8fSGustavo F. Padovan 7554343478fSGustavo F. Padovan if (!l2cap_check_security(chan) || 756b4450035SGustavo F. Padovan !__l2cap_no_conn_pending(chan)) { 7570a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 7580a708f8fSGustavo F. Padovan continue; 7590a708f8fSGustavo F. Padovan } 7600a708f8fSGustavo F. Padovan 761c1360a1cSGustavo F. Padovan if (!l2cap_mode_supported(chan->mode, conn->feat_mask) 762c1360a1cSGustavo F. Padovan && test_bit(CONF_STATE2_DEVICE, 763c1360a1cSGustavo F. Padovan &chan->conf_state)) { 7640f852724SGustavo F. Padovan /* l2cap_chan_close() calls list_del(chan) 765820ffdb3SGustavo F. Padovan * so release the lock */ 7662461daacSGustavo F. Padovan read_unlock(&conn->chan_lock); 7670f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 7682461daacSGustavo F. Padovan read_lock(&conn->chan_lock); 7690a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 7700a708f8fSGustavo F. Padovan continue; 7710a708f8fSGustavo F. Padovan } 7720a708f8fSGustavo F. Padovan 773fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 774fe4128e0SGustavo F. Padovan req.psm = chan->psm; 7750a708f8fSGustavo F. Padovan 776fc7f8a7eSGustavo F. Padovan chan->ident = l2cap_get_ident(conn); 777c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 7780a708f8fSGustavo F. Padovan 779fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, 780fc7f8a7eSGustavo F. Padovan sizeof(req), &req); 7810a708f8fSGustavo F. Padovan 78289bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 7830a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 7840a708f8fSGustavo F. Padovan char buf[128]; 785fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 786fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 7870a708f8fSGustavo F. Padovan 7884343478fSGustavo F. Padovan if (l2cap_check_security(chan)) { 7890a708f8fSGustavo F. Padovan if (bt_sk(sk)->defer_setup) { 7900a708f8fSGustavo F. Padovan struct sock *parent = bt_sk(sk)->parent; 7910a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_PEND); 7920a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND); 79305e9a2f6SIlia Kolomisnky if (parent) 7940a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 7950a708f8fSGustavo F. Padovan 7960a708f8fSGustavo F. Padovan } else { 79789bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 7980a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 7990a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 8000a708f8fSGustavo F. Padovan } 8010a708f8fSGustavo F. Padovan } else { 8020a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_PEND); 8030a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND); 8040a708f8fSGustavo F. Padovan } 8050a708f8fSGustavo F. Padovan 806fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 807fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 8080a708f8fSGustavo F. Padovan 809c1360a1cSGustavo F. Padovan if (test_bit(CONF_REQ_SENT, &chan->conf_state) || 8100a708f8fSGustavo F. Padovan rsp.result != L2CAP_CR_SUCCESS) { 8110a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 8120a708f8fSGustavo F. Padovan continue; 8130a708f8fSGustavo F. Padovan } 8140a708f8fSGustavo F. Padovan 815c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 8160a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 81773ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 81873ffa904SGustavo F. Padovan chan->num_conf_req++; 8190a708f8fSGustavo F. Padovan } 8200a708f8fSGustavo F. Padovan 8210a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 8220a708f8fSGustavo F. Padovan } 8230a708f8fSGustavo F. Padovan 824baa7e1faSGustavo F. Padovan read_unlock(&conn->chan_lock); 8250a708f8fSGustavo F. Padovan } 8260a708f8fSGustavo F. Padovan 827b62f328bSVille Tervo /* Find socket with cid and source bdaddr. 828b62f328bSVille Tervo * Returns closest match, locked. 829b62f328bSVille Tervo */ 83023691d75SGustavo F. Padovan static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src) 831b62f328bSVille Tervo { 83223691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 833b62f328bSVille Tervo 83423691d75SGustavo F. Padovan read_lock(&chan_list_lock); 835b62f328bSVille Tervo 83623691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 83723691d75SGustavo F. Padovan struct sock *sk = c->sk; 838fe4128e0SGustavo F. Padovan 83989bc500eSGustavo F. Padovan if (state && c->state != state) 840b62f328bSVille Tervo continue; 841b62f328bSVille Tervo 84223691d75SGustavo F. Padovan if (c->scid == cid) { 843b62f328bSVille Tervo /* Exact match. */ 84423691d75SGustavo F. Padovan if (!bacmp(&bt_sk(sk)->src, src)) { 84523691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 84623691d75SGustavo F. Padovan return c; 84723691d75SGustavo F. Padovan } 848b62f328bSVille Tervo 849b62f328bSVille Tervo /* Closest match */ 850b62f328bSVille Tervo if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) 85123691d75SGustavo F. Padovan c1 = c; 852b62f328bSVille Tervo } 853b62f328bSVille Tervo } 854280f294fSGustavo F. Padovan 85523691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 856b62f328bSVille Tervo 85723691d75SGustavo F. Padovan return c1; 858b62f328bSVille Tervo } 859b62f328bSVille Tervo 860b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn) 861b62f328bSVille Tervo { 862c916fbe4SGustavo F. Padovan struct sock *parent, *sk; 86323691d75SGustavo F. Padovan struct l2cap_chan *chan, *pchan; 864b62f328bSVille Tervo 865b62f328bSVille Tervo BT_DBG(""); 866b62f328bSVille Tervo 867b62f328bSVille Tervo /* Check if we have socket listening on cid */ 86823691d75SGustavo F. Padovan pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA, 869b62f328bSVille Tervo conn->src); 87023691d75SGustavo F. Padovan if (!pchan) 871b62f328bSVille Tervo return; 872b62f328bSVille Tervo 87323691d75SGustavo F. Padovan parent = pchan->sk; 87423691d75SGustavo F. Padovan 87562f3a2cfSGustavo F. Padovan bh_lock_sock(parent); 87662f3a2cfSGustavo F. Padovan 877b62f328bSVille Tervo /* Check for backlog size */ 878b62f328bSVille Tervo if (sk_acceptq_is_full(parent)) { 879b62f328bSVille Tervo BT_DBG("backlog full %d", parent->sk_ack_backlog); 880b62f328bSVille Tervo goto clean; 881b62f328bSVille Tervo } 882b62f328bSVille Tervo 88380808e43SGustavo F. Padovan chan = pchan->ops->new_connection(pchan->data); 88480808e43SGustavo F. Padovan if (!chan) 885b62f328bSVille Tervo goto clean; 886b62f328bSVille Tervo 88780808e43SGustavo F. Padovan sk = chan->sk; 8885d41ce1dSGustavo F. Padovan 889baa7e1faSGustavo F. Padovan write_lock_bh(&conn->chan_lock); 890b62f328bSVille Tervo 891b62f328bSVille Tervo hci_conn_hold(conn->hcon); 892b62f328bSVille Tervo 893b62f328bSVille Tervo bacpy(&bt_sk(sk)->src, conn->src); 894b62f328bSVille Tervo bacpy(&bt_sk(sk)->dst, conn->dst); 895b62f328bSVille Tervo 896d1010240SGustavo F. Padovan bt_accept_enqueue(parent, sk); 897d1010240SGustavo F. Padovan 89848454079SGustavo F. Padovan __l2cap_chan_add(conn, chan); 89948454079SGustavo F. Padovan 900c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 901b62f328bSVille Tervo 90289bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECTED); 903b62f328bSVille Tervo parent->sk_data_ready(parent, 0); 904b62f328bSVille Tervo 905baa7e1faSGustavo F. Padovan write_unlock_bh(&conn->chan_lock); 906b62f328bSVille Tervo 907b62f328bSVille Tervo clean: 908b62f328bSVille Tervo bh_unlock_sock(parent); 909b62f328bSVille Tervo } 910b62f328bSVille Tervo 911f1cb9af5SVinicius Costa Gomes static void l2cap_chan_ready(struct sock *sk) 912f1cb9af5SVinicius Costa Gomes { 913f1cb9af5SVinicius Costa Gomes struct l2cap_chan *chan = l2cap_pi(sk)->chan; 914f1cb9af5SVinicius Costa Gomes struct sock *parent = bt_sk(sk)->parent; 915f1cb9af5SVinicius Costa Gomes 916f1cb9af5SVinicius Costa Gomes BT_DBG("sk %p, parent %p", sk, parent); 917f1cb9af5SVinicius Costa Gomes 918f1cb9af5SVinicius Costa Gomes chan->conf_state = 0; 919f1cb9af5SVinicius Costa Gomes __clear_chan_timer(chan); 920f1cb9af5SVinicius Costa Gomes 92143f3dc41SVinicius Costa Gomes l2cap_state_change(chan, BT_CONNECTED); 922f1cb9af5SVinicius Costa Gomes sk->sk_state_change(sk); 923f1cb9af5SVinicius Costa Gomes 924f1cb9af5SVinicius Costa Gomes if (parent) 925f1cb9af5SVinicius Costa Gomes parent->sk_data_ready(parent, 0); 926f1cb9af5SVinicius Costa Gomes } 927f1cb9af5SVinicius Costa Gomes 9280a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn) 9290a708f8fSGustavo F. Padovan { 93048454079SGustavo F. Padovan struct l2cap_chan *chan; 9310a708f8fSGustavo F. Padovan 9320a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 9330a708f8fSGustavo F. Padovan 934b62f328bSVille Tervo if (!conn->hcon->out && conn->hcon->type == LE_LINK) 935b62f328bSVille Tervo l2cap_le_conn_ready(conn); 936b62f328bSVille Tervo 937160dc6acSVinicius Costa Gomes if (conn->hcon->out && conn->hcon->type == LE_LINK) 938160dc6acSVinicius Costa Gomes smp_conn_security(conn, conn->hcon->pending_sec_level); 939160dc6acSVinicius Costa Gomes 940baa7e1faSGustavo F. Padovan read_lock(&conn->chan_lock); 9410a708f8fSGustavo F. Padovan 942baa7e1faSGustavo F. Padovan list_for_each_entry(chan, &conn->chan_l, list) { 94348454079SGustavo F. Padovan struct sock *sk = chan->sk; 944baa7e1faSGustavo F. Padovan 9450a708f8fSGustavo F. Padovan bh_lock_sock(sk); 9460a708f8fSGustavo F. Padovan 94763128451SVinicius Costa Gomes if (conn->hcon->type == LE_LINK) { 948b501d6a1SAnderson Briglia if (smp_conn_security(conn, chan->sec_level)) 949f1cb9af5SVinicius Costa Gomes l2cap_chan_ready(sk); 950acd7d370SVille Tervo 95163128451SVinicius Costa Gomes } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 952c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 95389bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECTED); 9540a708f8fSGustavo F. Padovan sk->sk_state_change(sk); 955b501d6a1SAnderson Briglia 95689bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT) 957fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 9580a708f8fSGustavo F. Padovan 9590a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 9600a708f8fSGustavo F. Padovan } 9610a708f8fSGustavo F. Padovan 962baa7e1faSGustavo F. Padovan read_unlock(&conn->chan_lock); 9630a708f8fSGustavo F. Padovan } 9640a708f8fSGustavo F. Padovan 9650a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */ 9660a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) 9670a708f8fSGustavo F. Padovan { 96848454079SGustavo F. Padovan struct l2cap_chan *chan; 9690a708f8fSGustavo F. Padovan 9700a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 9710a708f8fSGustavo F. Padovan 972baa7e1faSGustavo F. Padovan read_lock(&conn->chan_lock); 9730a708f8fSGustavo F. Padovan 974baa7e1faSGustavo F. Padovan list_for_each_entry(chan, &conn->chan_l, list) { 97548454079SGustavo F. Padovan struct sock *sk = chan->sk; 976baa7e1faSGustavo F. Padovan 977ecf61bdbSAndrei Emeltchenko if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) 9780a708f8fSGustavo F. Padovan sk->sk_err = err; 9790a708f8fSGustavo F. Padovan } 9800a708f8fSGustavo F. Padovan 981baa7e1faSGustavo F. Padovan read_unlock(&conn->chan_lock); 9820a708f8fSGustavo F. Padovan } 9830a708f8fSGustavo F. Padovan 9840a708f8fSGustavo F. Padovan static void l2cap_info_timeout(unsigned long arg) 9850a708f8fSGustavo F. Padovan { 9860a708f8fSGustavo F. Padovan struct l2cap_conn *conn = (void *) arg; 9870a708f8fSGustavo F. Padovan 9880a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 9890a708f8fSGustavo F. Padovan conn->info_ident = 0; 9900a708f8fSGustavo F. Padovan 9910a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 9920a708f8fSGustavo F. Padovan } 9930a708f8fSGustavo F. Padovan 9945d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err) 9955d3de7dfSVinicius Costa Gomes { 9965d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 9975d3de7dfSVinicius Costa Gomes struct l2cap_chan *chan, *l; 9985d3de7dfSVinicius Costa Gomes struct sock *sk; 9995d3de7dfSVinicius Costa Gomes 10005d3de7dfSVinicius Costa Gomes if (!conn) 10015d3de7dfSVinicius Costa Gomes return; 10025d3de7dfSVinicius Costa Gomes 10035d3de7dfSVinicius Costa Gomes BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); 10045d3de7dfSVinicius Costa Gomes 10055d3de7dfSVinicius Costa Gomes kfree_skb(conn->rx_skb); 10065d3de7dfSVinicius Costa Gomes 10075d3de7dfSVinicius Costa Gomes /* Kill channels */ 10085d3de7dfSVinicius Costa Gomes list_for_each_entry_safe(chan, l, &conn->chan_l, list) { 10095d3de7dfSVinicius Costa Gomes sk = chan->sk; 10105d3de7dfSVinicius Costa Gomes bh_lock_sock(sk); 10115d3de7dfSVinicius Costa Gomes l2cap_chan_del(chan, err); 10125d3de7dfSVinicius Costa Gomes bh_unlock_sock(sk); 10135d3de7dfSVinicius Costa Gomes chan->ops->close(chan->data); 10145d3de7dfSVinicius Costa Gomes } 10155d3de7dfSVinicius Costa Gomes 1016*73d80debSLuiz Augusto von Dentz hci_chan_del(conn->hchan); 1017*73d80debSLuiz Augusto von Dentz 10185d3de7dfSVinicius Costa Gomes if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 10195d3de7dfSVinicius Costa Gomes del_timer_sync(&conn->info_timer); 10205d3de7dfSVinicius Costa Gomes 1021d26a2345SVinicius Costa Gomes if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) { 10225d3de7dfSVinicius Costa Gomes del_timer(&conn->security_timer); 10238aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 1024d26a2345SVinicius Costa Gomes } 10255d3de7dfSVinicius Costa Gomes 10265d3de7dfSVinicius Costa Gomes hcon->l2cap_data = NULL; 10275d3de7dfSVinicius Costa Gomes kfree(conn); 10285d3de7dfSVinicius Costa Gomes } 10295d3de7dfSVinicius Costa Gomes 10305d3de7dfSVinicius Costa Gomes static void security_timeout(unsigned long arg) 10315d3de7dfSVinicius Costa Gomes { 10325d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = (void *) arg; 10335d3de7dfSVinicius Costa Gomes 10345d3de7dfSVinicius Costa Gomes l2cap_conn_del(conn->hcon, ETIMEDOUT); 10355d3de7dfSVinicius Costa Gomes } 10365d3de7dfSVinicius Costa Gomes 10370a708f8fSGustavo F. Padovan static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) 10380a708f8fSGustavo F. Padovan { 10390a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 1040*73d80debSLuiz Augusto von Dentz struct hci_chan *hchan; 10410a708f8fSGustavo F. Padovan 10420a708f8fSGustavo F. Padovan if (conn || status) 10430a708f8fSGustavo F. Padovan return conn; 10440a708f8fSGustavo F. Padovan 1045*73d80debSLuiz Augusto von Dentz hchan = hci_chan_create(hcon); 1046*73d80debSLuiz Augusto von Dentz if (!hchan) 10470a708f8fSGustavo F. Padovan return NULL; 10480a708f8fSGustavo F. Padovan 1049*73d80debSLuiz Augusto von Dentz conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC); 1050*73d80debSLuiz Augusto von Dentz if (!conn) { 1051*73d80debSLuiz Augusto von Dentz hci_chan_del(hchan); 1052*73d80debSLuiz Augusto von Dentz return NULL; 1053*73d80debSLuiz Augusto von Dentz } 1054*73d80debSLuiz Augusto von Dentz 10550a708f8fSGustavo F. Padovan hcon->l2cap_data = conn; 10560a708f8fSGustavo F. Padovan conn->hcon = hcon; 1057*73d80debSLuiz Augusto von Dentz conn->hchan = hchan; 10580a708f8fSGustavo F. Padovan 1059*73d80debSLuiz Augusto von Dentz BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); 10600a708f8fSGustavo F. Padovan 1061acd7d370SVille Tervo if (hcon->hdev->le_mtu && hcon->type == LE_LINK) 1062acd7d370SVille Tervo conn->mtu = hcon->hdev->le_mtu; 1063acd7d370SVille Tervo else 10640a708f8fSGustavo F. Padovan conn->mtu = hcon->hdev->acl_mtu; 1065acd7d370SVille Tervo 10660a708f8fSGustavo F. Padovan conn->src = &hcon->hdev->bdaddr; 10670a708f8fSGustavo F. Padovan conn->dst = &hcon->dst; 10680a708f8fSGustavo F. Padovan 10690a708f8fSGustavo F. Padovan conn->feat_mask = 0; 10700a708f8fSGustavo F. Padovan 10710a708f8fSGustavo F. Padovan spin_lock_init(&conn->lock); 1072baa7e1faSGustavo F. Padovan rwlock_init(&conn->chan_lock); 1073baa7e1faSGustavo F. Padovan 1074baa7e1faSGustavo F. Padovan INIT_LIST_HEAD(&conn->chan_l); 10750a708f8fSGustavo F. Padovan 10765d3de7dfSVinicius Costa Gomes if (hcon->type == LE_LINK) 10775d3de7dfSVinicius Costa Gomes setup_timer(&conn->security_timer, security_timeout, 10785d3de7dfSVinicius Costa Gomes (unsigned long) conn); 10795d3de7dfSVinicius Costa Gomes else 10800a708f8fSGustavo F. Padovan setup_timer(&conn->info_timer, l2cap_info_timeout, 10810a708f8fSGustavo F. Padovan (unsigned long) conn); 10820a708f8fSGustavo F. Padovan 10830a708f8fSGustavo F. Padovan conn->disc_reason = 0x13; 10840a708f8fSGustavo F. Padovan 10850a708f8fSGustavo F. Padovan return conn; 10860a708f8fSGustavo F. Padovan } 10870a708f8fSGustavo F. Padovan 108848454079SGustavo F. Padovan static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 10890a708f8fSGustavo F. Padovan { 1090baa7e1faSGustavo F. Padovan write_lock_bh(&conn->chan_lock); 109148454079SGustavo F. Padovan __l2cap_chan_add(conn, chan); 1092baa7e1faSGustavo F. Padovan write_unlock_bh(&conn->chan_lock); 10930a708f8fSGustavo F. Padovan } 10940a708f8fSGustavo F. Padovan 10950a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */ 10960a708f8fSGustavo F. Padovan 10970a708f8fSGustavo F. Padovan /* Find socket with psm and source bdaddr. 10980a708f8fSGustavo F. Padovan * Returns closest match. 10990a708f8fSGustavo F. Padovan */ 110023691d75SGustavo F. Padovan static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src) 11010a708f8fSGustavo F. Padovan { 110223691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 11030a708f8fSGustavo F. Padovan 110423691d75SGustavo F. Padovan read_lock(&chan_list_lock); 11050a708f8fSGustavo F. Padovan 110623691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 110723691d75SGustavo F. Padovan struct sock *sk = c->sk; 1108fe4128e0SGustavo F. Padovan 110989bc500eSGustavo F. Padovan if (state && c->state != state) 11100a708f8fSGustavo F. Padovan continue; 11110a708f8fSGustavo F. Padovan 111223691d75SGustavo F. Padovan if (c->psm == psm) { 11130a708f8fSGustavo F. Padovan /* Exact match. */ 111423691d75SGustavo F. Padovan if (!bacmp(&bt_sk(sk)->src, src)) { 1115a7567b20SJohannes Berg read_unlock(&chan_list_lock); 111623691d75SGustavo F. Padovan return c; 111723691d75SGustavo F. Padovan } 11180a708f8fSGustavo F. Padovan 11190a708f8fSGustavo F. Padovan /* Closest match */ 11200a708f8fSGustavo F. Padovan if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) 112123691d75SGustavo F. Padovan c1 = c; 11220a708f8fSGustavo F. Padovan } 11230a708f8fSGustavo F. Padovan } 11240a708f8fSGustavo F. Padovan 112523691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 11260a708f8fSGustavo F. Padovan 112723691d75SGustavo F. Padovan return c1; 11280a708f8fSGustavo F. Padovan } 11290a708f8fSGustavo F. Padovan 113077a74c7eSGustavo F. Padovan int l2cap_chan_connect(struct l2cap_chan *chan) 11310a708f8fSGustavo F. Padovan { 11325d41ce1dSGustavo F. Padovan struct sock *sk = chan->sk; 11330a708f8fSGustavo F. Padovan bdaddr_t *src = &bt_sk(sk)->src; 11340a708f8fSGustavo F. Padovan bdaddr_t *dst = &bt_sk(sk)->dst; 11350a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 11360a708f8fSGustavo F. Padovan struct hci_conn *hcon; 11370a708f8fSGustavo F. Padovan struct hci_dev *hdev; 11380a708f8fSGustavo F. Padovan __u8 auth_type; 11390a708f8fSGustavo F. Padovan int err; 11400a708f8fSGustavo F. Padovan 11410a708f8fSGustavo F. Padovan BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), 1142fe4128e0SGustavo F. Padovan chan->psm); 11430a708f8fSGustavo F. Padovan 11440a708f8fSGustavo F. Padovan hdev = hci_get_route(dst, src); 11450a708f8fSGustavo F. Padovan if (!hdev) 11460a708f8fSGustavo F. Padovan return -EHOSTUNREACH; 11470a708f8fSGustavo F. Padovan 11480a708f8fSGustavo F. Padovan hci_dev_lock_bh(hdev); 11490a708f8fSGustavo F. Padovan 11504343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 11510a708f8fSGustavo F. Padovan 1152fe4128e0SGustavo F. Padovan if (chan->dcid == L2CAP_CID_LE_DATA) 1153acd7d370SVille Tervo hcon = hci_connect(hdev, LE_LINK, dst, 11544343478fSGustavo F. Padovan chan->sec_level, auth_type); 1155acd7d370SVille Tervo else 11560a708f8fSGustavo F. Padovan hcon = hci_connect(hdev, ACL_LINK, dst, 11574343478fSGustavo F. Padovan chan->sec_level, auth_type); 1158acd7d370SVille Tervo 115930e76272SVille Tervo if (IS_ERR(hcon)) { 116030e76272SVille Tervo err = PTR_ERR(hcon); 11610a708f8fSGustavo F. Padovan goto done; 116230e76272SVille Tervo } 11630a708f8fSGustavo F. Padovan 11640a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, 0); 11650a708f8fSGustavo F. Padovan if (!conn) { 11660a708f8fSGustavo F. Padovan hci_conn_put(hcon); 116730e76272SVille Tervo err = -ENOMEM; 11680a708f8fSGustavo F. Padovan goto done; 11690a708f8fSGustavo F. Padovan } 11700a708f8fSGustavo F. Padovan 11710a708f8fSGustavo F. Padovan /* Update source addr of the socket */ 11720a708f8fSGustavo F. Padovan bacpy(src, conn->src); 11730a708f8fSGustavo F. Padovan 117448454079SGustavo F. Padovan l2cap_chan_add(conn, chan); 117548454079SGustavo F. Padovan 117689bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECT); 1177c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 11780a708f8fSGustavo F. Padovan 11790a708f8fSGustavo F. Padovan if (hcon->state == BT_CONNECTED) { 1180715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1181c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 11824343478fSGustavo F. Padovan if (l2cap_check_security(chan)) 118389bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECTED); 11840a708f8fSGustavo F. Padovan } else 1185fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 11860a708f8fSGustavo F. Padovan } 11870a708f8fSGustavo F. Padovan 118830e76272SVille Tervo err = 0; 118930e76272SVille Tervo 11900a708f8fSGustavo F. Padovan done: 11910a708f8fSGustavo F. Padovan hci_dev_unlock_bh(hdev); 11920a708f8fSGustavo F. Padovan hci_dev_put(hdev); 11930a708f8fSGustavo F. Padovan return err; 11940a708f8fSGustavo F. Padovan } 11950a708f8fSGustavo F. Padovan 1196dcba0dbaSGustavo F. Padovan int __l2cap_wait_ack(struct sock *sk) 11970a708f8fSGustavo F. Padovan { 11988c1d787bSGustavo F. Padovan struct l2cap_chan *chan = l2cap_pi(sk)->chan; 11990a708f8fSGustavo F. Padovan DECLARE_WAITQUEUE(wait, current); 12000a708f8fSGustavo F. Padovan int err = 0; 12010a708f8fSGustavo F. Padovan int timeo = HZ/5; 12020a708f8fSGustavo F. Padovan 12030a708f8fSGustavo F. Padovan add_wait_queue(sk_sleep(sk), &wait); 12040a708f8fSGustavo F. Padovan set_current_state(TASK_INTERRUPTIBLE); 1205a71a0cf4SPeter Hurley while (chan->unacked_frames > 0 && chan->conn) { 12060a708f8fSGustavo F. Padovan if (!timeo) 12070a708f8fSGustavo F. Padovan timeo = HZ/5; 12080a708f8fSGustavo F. Padovan 12090a708f8fSGustavo F. Padovan if (signal_pending(current)) { 12100a708f8fSGustavo F. Padovan err = sock_intr_errno(timeo); 12110a708f8fSGustavo F. Padovan break; 12120a708f8fSGustavo F. Padovan } 12130a708f8fSGustavo F. Padovan 12140a708f8fSGustavo F. Padovan release_sock(sk); 12150a708f8fSGustavo F. Padovan timeo = schedule_timeout(timeo); 12160a708f8fSGustavo F. Padovan lock_sock(sk); 1217a71a0cf4SPeter Hurley set_current_state(TASK_INTERRUPTIBLE); 12180a708f8fSGustavo F. Padovan 12190a708f8fSGustavo F. Padovan err = sock_error(sk); 12200a708f8fSGustavo F. Padovan if (err) 12210a708f8fSGustavo F. Padovan break; 12220a708f8fSGustavo F. Padovan } 12230a708f8fSGustavo F. Padovan set_current_state(TASK_RUNNING); 12240a708f8fSGustavo F. Padovan remove_wait_queue(sk_sleep(sk), &wait); 12250a708f8fSGustavo F. Padovan return err; 12260a708f8fSGustavo F. Padovan } 12270a708f8fSGustavo F. Padovan 12280a708f8fSGustavo F. Padovan static void l2cap_monitor_timeout(unsigned long arg) 12290a708f8fSGustavo F. Padovan { 1230525cd185SGustavo F. Padovan struct l2cap_chan *chan = (void *) arg; 1231525cd185SGustavo F. Padovan struct sock *sk = chan->sk; 12320a708f8fSGustavo F. Padovan 1233525cd185SGustavo F. Padovan BT_DBG("chan %p", chan); 12340a708f8fSGustavo F. Padovan 12350a708f8fSGustavo F. Padovan bh_lock_sock(sk); 12362c03a7a4SGustavo F. Padovan if (chan->retry_count >= chan->remote_max_tx) { 12378c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); 12380a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 12390a708f8fSGustavo F. Padovan return; 12400a708f8fSGustavo F. Padovan } 12410a708f8fSGustavo F. Padovan 12426a026610SGustavo F. Padovan chan->retry_count++; 12431a09bcb9SGustavo F. Padovan __set_monitor_timer(chan); 12440a708f8fSGustavo F. Padovan 1245525cd185SGustavo F. Padovan l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); 12460a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 12470a708f8fSGustavo F. Padovan } 12480a708f8fSGustavo F. Padovan 12490a708f8fSGustavo F. Padovan static void l2cap_retrans_timeout(unsigned long arg) 12500a708f8fSGustavo F. Padovan { 1251525cd185SGustavo F. Padovan struct l2cap_chan *chan = (void *) arg; 1252525cd185SGustavo F. Padovan struct sock *sk = chan->sk; 12530a708f8fSGustavo F. Padovan 125449208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 12550a708f8fSGustavo F. Padovan 12560a708f8fSGustavo F. Padovan bh_lock_sock(sk); 12576a026610SGustavo F. Padovan chan->retry_count = 1; 12581a09bcb9SGustavo F. Padovan __set_monitor_timer(chan); 12590a708f8fSGustavo F. Padovan 1260e2ab4353SGustavo F. Padovan set_bit(CONN_WAIT_F, &chan->conn_state); 12610a708f8fSGustavo F. Padovan 1262525cd185SGustavo F. Padovan l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); 12630a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 12640a708f8fSGustavo F. Padovan } 12650a708f8fSGustavo F. Padovan 126642e5c802SGustavo F. Padovan static void l2cap_drop_acked_frames(struct l2cap_chan *chan) 12670a708f8fSGustavo F. Padovan { 12680a708f8fSGustavo F. Padovan struct sk_buff *skb; 12690a708f8fSGustavo F. Padovan 127058d35f87SGustavo F. Padovan while ((skb = skb_peek(&chan->tx_q)) && 12716a026610SGustavo F. Padovan chan->unacked_frames) { 127242e5c802SGustavo F. Padovan if (bt_cb(skb)->tx_seq == chan->expected_ack_seq) 12730a708f8fSGustavo F. Padovan break; 12740a708f8fSGustavo F. Padovan 127558d35f87SGustavo F. Padovan skb = skb_dequeue(&chan->tx_q); 12760a708f8fSGustavo F. Padovan kfree_skb(skb); 12770a708f8fSGustavo F. Padovan 12786a026610SGustavo F. Padovan chan->unacked_frames--; 12790a708f8fSGustavo F. Padovan } 12800a708f8fSGustavo F. Padovan 12816a026610SGustavo F. Padovan if (!chan->unacked_frames) 12821a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 12830a708f8fSGustavo F. Padovan } 12840a708f8fSGustavo F. Padovan 128567c9e840SSzymon Janc static void l2cap_streaming_send(struct l2cap_chan *chan) 12860a708f8fSGustavo F. Padovan { 12870a708f8fSGustavo F. Padovan struct sk_buff *skb; 128888843ab0SAndrei Emeltchenko u32 control; 128988843ab0SAndrei Emeltchenko u16 fcs; 12900a708f8fSGustavo F. Padovan 129158d35f87SGustavo F. Padovan while ((skb = skb_dequeue(&chan->tx_q))) { 129288843ab0SAndrei Emeltchenko control = __get_control(chan, skb->data + L2CAP_HDR_SIZE); 1293fb45de7dSAndrei Emeltchenko control |= __set_txseq(chan, chan->next_tx_seq); 129488843ab0SAndrei Emeltchenko __put_control(chan, control, skb->data + L2CAP_HDR_SIZE); 12950a708f8fSGustavo F. Padovan 129647d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 129703a51213SAndrei Emeltchenko fcs = crc16(0, (u8 *)skb->data, 129803a51213SAndrei Emeltchenko skb->len - L2CAP_FCS_SIZE); 129903a51213SAndrei Emeltchenko put_unaligned_le16(fcs, 130003a51213SAndrei Emeltchenko skb->data + skb->len - L2CAP_FCS_SIZE); 13010a708f8fSGustavo F. Padovan } 13020a708f8fSGustavo F. Padovan 13034343478fSGustavo F. Padovan l2cap_do_send(chan, skb); 13040a708f8fSGustavo F. Padovan 1305836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 13060a708f8fSGustavo F. Padovan } 13070a708f8fSGustavo F. Padovan } 13080a708f8fSGustavo F. Padovan 1309fb45de7dSAndrei Emeltchenko static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq) 13100a708f8fSGustavo F. Padovan { 13110a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 131288843ab0SAndrei Emeltchenko u16 fcs; 131388843ab0SAndrei Emeltchenko u32 control; 13140a708f8fSGustavo F. Padovan 131558d35f87SGustavo F. Padovan skb = skb_peek(&chan->tx_q); 13160a708f8fSGustavo F. Padovan if (!skb) 13170a708f8fSGustavo F. Padovan return; 13180a708f8fSGustavo F. Padovan 13190a708f8fSGustavo F. Padovan do { 13200a708f8fSGustavo F. Padovan if (bt_cb(skb)->tx_seq == tx_seq) 13210a708f8fSGustavo F. Padovan break; 13220a708f8fSGustavo F. Padovan 132358d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 13240a708f8fSGustavo F. Padovan return; 13250a708f8fSGustavo F. Padovan 132658d35f87SGustavo F. Padovan } while ((skb = skb_queue_next(&chan->tx_q, skb))); 13270a708f8fSGustavo F. Padovan 13282c03a7a4SGustavo F. Padovan if (chan->remote_max_tx && 13292c03a7a4SGustavo F. Padovan bt_cb(skb)->retries == chan->remote_max_tx) { 13308c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); 13310a708f8fSGustavo F. Padovan return; 13320a708f8fSGustavo F. Padovan } 13330a708f8fSGustavo F. Padovan 13340a708f8fSGustavo F. Padovan tx_skb = skb_clone(skb, GFP_ATOMIC); 13350a708f8fSGustavo F. Padovan bt_cb(skb)->retries++; 133688843ab0SAndrei Emeltchenko 133788843ab0SAndrei Emeltchenko control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE); 13387e0ef6eeSAndrei Emeltchenko control &= __get_sar_mask(chan); 13390a708f8fSGustavo F. Padovan 1340e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 134103f6715dSAndrei Emeltchenko control |= __set_ctrl_final(chan); 13420a708f8fSGustavo F. Padovan 13430b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 1344fb45de7dSAndrei Emeltchenko control |= __set_txseq(chan, tx_seq); 13450a708f8fSGustavo F. Padovan 134688843ab0SAndrei Emeltchenko __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE); 13470a708f8fSGustavo F. Padovan 134847d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 134903a51213SAndrei Emeltchenko fcs = crc16(0, (u8 *)tx_skb->data, 135003a51213SAndrei Emeltchenko tx_skb->len - L2CAP_FCS_SIZE); 135103a51213SAndrei Emeltchenko put_unaligned_le16(fcs, 135203a51213SAndrei Emeltchenko tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE); 13530a708f8fSGustavo F. Padovan } 13540a708f8fSGustavo F. Padovan 13554343478fSGustavo F. Padovan l2cap_do_send(chan, tx_skb); 13560a708f8fSGustavo F. Padovan } 13570a708f8fSGustavo F. Padovan 135867c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan) 13590a708f8fSGustavo F. Padovan { 13600a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 136188843ab0SAndrei Emeltchenko u16 fcs; 136288843ab0SAndrei Emeltchenko u32 control; 13630a708f8fSGustavo F. Padovan int nsent = 0; 13640a708f8fSGustavo F. Padovan 136589bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 13660a708f8fSGustavo F. Padovan return -ENOTCONN; 13670a708f8fSGustavo F. Padovan 136858d35f87SGustavo F. Padovan while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) { 13690a708f8fSGustavo F. Padovan 13702c03a7a4SGustavo F. Padovan if (chan->remote_max_tx && 13712c03a7a4SGustavo F. Padovan bt_cb(skb)->retries == chan->remote_max_tx) { 13728c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); 13730a708f8fSGustavo F. Padovan break; 13740a708f8fSGustavo F. Padovan } 13750a708f8fSGustavo F. Padovan 13760a708f8fSGustavo F. Padovan tx_skb = skb_clone(skb, GFP_ATOMIC); 13770a708f8fSGustavo F. Padovan 13780a708f8fSGustavo F. Padovan bt_cb(skb)->retries++; 13790a708f8fSGustavo F. Padovan 138088843ab0SAndrei Emeltchenko control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE); 13817e0ef6eeSAndrei Emeltchenko control &= __get_sar_mask(chan); 13820a708f8fSGustavo F. Padovan 1383e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 138403f6715dSAndrei Emeltchenko control |= __set_ctrl_final(chan); 1385e2ab4353SGustavo F. Padovan 13860b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 1387fb45de7dSAndrei Emeltchenko control |= __set_txseq(chan, chan->next_tx_seq); 13880a708f8fSGustavo F. Padovan 138988843ab0SAndrei Emeltchenko __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE); 13900a708f8fSGustavo F. Padovan 139147d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 139203a51213SAndrei Emeltchenko fcs = crc16(0, (u8 *)skb->data, 139303a51213SAndrei Emeltchenko tx_skb->len - L2CAP_FCS_SIZE); 139403a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb->data + 139503a51213SAndrei Emeltchenko tx_skb->len - L2CAP_FCS_SIZE); 13960a708f8fSGustavo F. Padovan } 13970a708f8fSGustavo F. Padovan 13984343478fSGustavo F. Padovan l2cap_do_send(chan, tx_skb); 13990a708f8fSGustavo F. Padovan 14001a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 14010a708f8fSGustavo F. Padovan 140242e5c802SGustavo F. Padovan bt_cb(skb)->tx_seq = chan->next_tx_seq; 1403836be934SAndrei Emeltchenko 1404836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 14050a708f8fSGustavo F. Padovan 140623e9fde2SSuraj Sumangala if (bt_cb(skb)->retries == 1) 14076a026610SGustavo F. Padovan chan->unacked_frames++; 140823e9fde2SSuraj Sumangala 14096a026610SGustavo F. Padovan chan->frames_sent++; 14100a708f8fSGustavo F. Padovan 141158d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 141258d35f87SGustavo F. Padovan chan->tx_send_head = NULL; 14130a708f8fSGustavo F. Padovan else 141458d35f87SGustavo F. Padovan chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); 14150a708f8fSGustavo F. Padovan 14160a708f8fSGustavo F. Padovan nsent++; 14170a708f8fSGustavo F. Padovan } 14180a708f8fSGustavo F. Padovan 14190a708f8fSGustavo F. Padovan return nsent; 14200a708f8fSGustavo F. Padovan } 14210a708f8fSGustavo F. Padovan 1422525cd185SGustavo F. Padovan static int l2cap_retransmit_frames(struct l2cap_chan *chan) 14230a708f8fSGustavo F. Padovan { 14240a708f8fSGustavo F. Padovan int ret; 14250a708f8fSGustavo F. Padovan 142658d35f87SGustavo F. Padovan if (!skb_queue_empty(&chan->tx_q)) 142758d35f87SGustavo F. Padovan chan->tx_send_head = chan->tx_q.next; 14280a708f8fSGustavo F. Padovan 142942e5c802SGustavo F. Padovan chan->next_tx_seq = chan->expected_ack_seq; 1430525cd185SGustavo F. Padovan ret = l2cap_ertm_send(chan); 14310a708f8fSGustavo F. Padovan return ret; 14320a708f8fSGustavo F. Padovan } 14330a708f8fSGustavo F. Padovan 1434525cd185SGustavo F. Padovan static void l2cap_send_ack(struct l2cap_chan *chan) 14350a708f8fSGustavo F. Padovan { 143688843ab0SAndrei Emeltchenko u32 control = 0; 14370a708f8fSGustavo F. Padovan 14380b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 14390a708f8fSGustavo F. Padovan 1440e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 1441ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); 1442e2ab4353SGustavo F. Padovan set_bit(CONN_RNR_SENT, &chan->conn_state); 1443525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 14440a708f8fSGustavo F. Padovan return; 14450a708f8fSGustavo F. Padovan } 14460a708f8fSGustavo F. Padovan 1447525cd185SGustavo F. Padovan if (l2cap_ertm_send(chan) > 0) 14480a708f8fSGustavo F. Padovan return; 14490a708f8fSGustavo F. Padovan 1450ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 1451525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 14520a708f8fSGustavo F. Padovan } 14530a708f8fSGustavo F. Padovan 1454525cd185SGustavo F. Padovan static void l2cap_send_srejtail(struct l2cap_chan *chan) 14550a708f8fSGustavo F. Padovan { 14560a708f8fSGustavo F. Padovan struct srej_list *tail; 145788843ab0SAndrei Emeltchenko u32 control; 14580a708f8fSGustavo F. Padovan 1459ab784b73SAndrei Emeltchenko control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ); 146003f6715dSAndrei Emeltchenko control |= __set_ctrl_final(chan); 14610a708f8fSGustavo F. Padovan 146239d5a3eeSGustavo F. Padovan tail = list_entry((&chan->srej_l)->prev, struct srej_list, list); 14630b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, tail->tx_seq); 14640a708f8fSGustavo F. Padovan 1465525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 14660a708f8fSGustavo F. Padovan } 14670a708f8fSGustavo F. Padovan 14680a708f8fSGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb) 14690a708f8fSGustavo F. Padovan { 14708c1d787bSGustavo F. Padovan struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn; 14710a708f8fSGustavo F. Padovan struct sk_buff **frag; 14720a708f8fSGustavo F. Padovan int err, sent = 0; 14730a708f8fSGustavo F. Padovan 14740a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) 14750a708f8fSGustavo F. Padovan return -EFAULT; 14760a708f8fSGustavo F. Padovan 14770a708f8fSGustavo F. Padovan sent += count; 14780a708f8fSGustavo F. Padovan len -= count; 14790a708f8fSGustavo F. Padovan 14800a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 14810a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 14820a708f8fSGustavo F. Padovan while (len) { 14830a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 14840a708f8fSGustavo F. Padovan 14850a708f8fSGustavo F. Padovan *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err); 14860a708f8fSGustavo F. Padovan if (!*frag) 14870a708f8fSGustavo F. Padovan return err; 14880a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) 14890a708f8fSGustavo F. Padovan return -EFAULT; 14900a708f8fSGustavo F. Padovan 14915e59b791SLuiz Augusto von Dentz (*frag)->priority = skb->priority; 14925e59b791SLuiz Augusto von Dentz 14930a708f8fSGustavo F. Padovan sent += count; 14940a708f8fSGustavo F. Padovan len -= count; 14950a708f8fSGustavo F. Padovan 14960a708f8fSGustavo F. Padovan frag = &(*frag)->next; 14970a708f8fSGustavo F. Padovan } 14980a708f8fSGustavo F. Padovan 14990a708f8fSGustavo F. Padovan return sent; 15000a708f8fSGustavo F. Padovan } 15010a708f8fSGustavo F. Padovan 15025e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, 15035e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 15045e59b791SLuiz Augusto von Dentz u32 priority) 15050a708f8fSGustavo F. Padovan { 1506fe4128e0SGustavo F. Padovan struct sock *sk = chan->sk; 15078c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 15080a708f8fSGustavo F. Padovan struct sk_buff *skb; 150903a51213SAndrei Emeltchenko int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; 15100a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 15110a708f8fSGustavo F. Padovan 15125e59b791SLuiz Augusto von Dentz BT_DBG("sk %p len %d priority %u", sk, (int)len, priority); 15130a708f8fSGustavo F. Padovan 15140a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 15150a708f8fSGustavo F. Padovan skb = bt_skb_send_alloc(sk, count + hlen, 15160a708f8fSGustavo F. Padovan msg->msg_flags & MSG_DONTWAIT, &err); 15170a708f8fSGustavo F. Padovan if (!skb) 15180a708f8fSGustavo F. Padovan return ERR_PTR(err); 15190a708f8fSGustavo F. Padovan 15205e59b791SLuiz Augusto von Dentz skb->priority = priority; 15215e59b791SLuiz Augusto von Dentz 15220a708f8fSGustavo F. Padovan /* Create L2CAP header */ 15230a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 1524fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 15250a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 1526fe4128e0SGustavo F. Padovan put_unaligned_le16(chan->psm, skb_put(skb, 2)); 15270a708f8fSGustavo F. Padovan 15280a708f8fSGustavo F. Padovan err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb); 15290a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 15300a708f8fSGustavo F. Padovan kfree_skb(skb); 15310a708f8fSGustavo F. Padovan return ERR_PTR(err); 15320a708f8fSGustavo F. Padovan } 15330a708f8fSGustavo F. Padovan return skb; 15340a708f8fSGustavo F. Padovan } 15350a708f8fSGustavo F. Padovan 15365e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, 15375e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 15385e59b791SLuiz Augusto von Dentz u32 priority) 15390a708f8fSGustavo F. Padovan { 1540fe4128e0SGustavo F. Padovan struct sock *sk = chan->sk; 15418c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 15420a708f8fSGustavo F. Padovan struct sk_buff *skb; 15430a708f8fSGustavo F. Padovan int err, count, hlen = L2CAP_HDR_SIZE; 15440a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 15450a708f8fSGustavo F. Padovan 15460a708f8fSGustavo F. Padovan BT_DBG("sk %p len %d", sk, (int)len); 15470a708f8fSGustavo F. Padovan 15480a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 15490a708f8fSGustavo F. Padovan skb = bt_skb_send_alloc(sk, count + hlen, 15500a708f8fSGustavo F. Padovan msg->msg_flags & MSG_DONTWAIT, &err); 15510a708f8fSGustavo F. Padovan if (!skb) 15520a708f8fSGustavo F. Padovan return ERR_PTR(err); 15530a708f8fSGustavo F. Padovan 15545e59b791SLuiz Augusto von Dentz skb->priority = priority; 15555e59b791SLuiz Augusto von Dentz 15560a708f8fSGustavo F. Padovan /* Create L2CAP header */ 15570a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 1558fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 15590a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 15600a708f8fSGustavo F. Padovan 15610a708f8fSGustavo F. Padovan err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb); 15620a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 15630a708f8fSGustavo F. Padovan kfree_skb(skb); 15640a708f8fSGustavo F. Padovan return ERR_PTR(err); 15650a708f8fSGustavo F. Padovan } 15660a708f8fSGustavo F. Padovan return skb; 15670a708f8fSGustavo F. Padovan } 15680a708f8fSGustavo F. Padovan 1569ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, 1570ab0ff76dSLuiz Augusto von Dentz struct msghdr *msg, size_t len, 157188843ab0SAndrei Emeltchenko u32 control, u16 sdulen) 15720a708f8fSGustavo F. Padovan { 157347d1ec61SGustavo F. Padovan struct sock *sk = chan->sk; 15748c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 15750a708f8fSGustavo F. Padovan struct sk_buff *skb; 1576e4ca6d98SAndrei Emeltchenko int err, count, hlen; 15770a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 15780a708f8fSGustavo F. Padovan 15790a708f8fSGustavo F. Padovan BT_DBG("sk %p len %d", sk, (int)len); 15800a708f8fSGustavo F. Padovan 15810a708f8fSGustavo F. Padovan if (!conn) 15820a708f8fSGustavo F. Padovan return ERR_PTR(-ENOTCONN); 15830a708f8fSGustavo F. Padovan 1584e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1585e4ca6d98SAndrei Emeltchenko hlen = L2CAP_EXT_HDR_SIZE; 1586e4ca6d98SAndrei Emeltchenko else 1587e4ca6d98SAndrei Emeltchenko hlen = L2CAP_ENH_HDR_SIZE; 1588e4ca6d98SAndrei Emeltchenko 15890a708f8fSGustavo F. Padovan if (sdulen) 159003a51213SAndrei Emeltchenko hlen += L2CAP_SDULEN_SIZE; 15910a708f8fSGustavo F. Padovan 159247d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 159303a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 15940a708f8fSGustavo F. Padovan 15950a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 15960a708f8fSGustavo F. Padovan skb = bt_skb_send_alloc(sk, count + hlen, 15970a708f8fSGustavo F. Padovan msg->msg_flags & MSG_DONTWAIT, &err); 15980a708f8fSGustavo F. Padovan if (!skb) 15990a708f8fSGustavo F. Padovan return ERR_PTR(err); 16000a708f8fSGustavo F. Padovan 16010a708f8fSGustavo F. Padovan /* Create L2CAP header */ 16020a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 1603fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 16040a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 160588843ab0SAndrei Emeltchenko 160688843ab0SAndrei Emeltchenko __put_control(chan, control, skb_put(skb, __ctrl_size(chan))); 160788843ab0SAndrei Emeltchenko 16080a708f8fSGustavo F. Padovan if (sdulen) 160903a51213SAndrei Emeltchenko put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 16100a708f8fSGustavo F. Padovan 16110a708f8fSGustavo F. Padovan err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb); 16120a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 16130a708f8fSGustavo F. Padovan kfree_skb(skb); 16140a708f8fSGustavo F. Padovan return ERR_PTR(err); 16150a708f8fSGustavo F. Padovan } 16160a708f8fSGustavo F. Padovan 161747d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 161803a51213SAndrei Emeltchenko put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE)); 16190a708f8fSGustavo F. Padovan 16200a708f8fSGustavo F. Padovan bt_cb(skb)->retries = 0; 16210a708f8fSGustavo F. Padovan return skb; 16220a708f8fSGustavo F. Padovan } 16230a708f8fSGustavo F. Padovan 162467c9e840SSzymon Janc static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) 16250a708f8fSGustavo F. Padovan { 16260a708f8fSGustavo F. Padovan struct sk_buff *skb; 16270a708f8fSGustavo F. Padovan struct sk_buff_head sar_queue; 162888843ab0SAndrei Emeltchenko u32 control; 16290a708f8fSGustavo F. Padovan size_t size = 0; 16300a708f8fSGustavo F. Padovan 16310a708f8fSGustavo F. Padovan skb_queue_head_init(&sar_queue); 16327e0ef6eeSAndrei Emeltchenko control = __set_ctrl_sar(chan, L2CAP_SAR_START); 163347d1ec61SGustavo F. Padovan skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len); 16340a708f8fSGustavo F. Padovan if (IS_ERR(skb)) 16350a708f8fSGustavo F. Padovan return PTR_ERR(skb); 16360a708f8fSGustavo F. Padovan 16370a708f8fSGustavo F. Padovan __skb_queue_tail(&sar_queue, skb); 16382c03a7a4SGustavo F. Padovan len -= chan->remote_mps; 16392c03a7a4SGustavo F. Padovan size += chan->remote_mps; 16400a708f8fSGustavo F. Padovan 16410a708f8fSGustavo F. Padovan while (len > 0) { 16420a708f8fSGustavo F. Padovan size_t buflen; 16430a708f8fSGustavo F. Padovan 16442c03a7a4SGustavo F. Padovan if (len > chan->remote_mps) { 16457e0ef6eeSAndrei Emeltchenko control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE); 16462c03a7a4SGustavo F. Padovan buflen = chan->remote_mps; 16470a708f8fSGustavo F. Padovan } else { 16487e0ef6eeSAndrei Emeltchenko control = __set_ctrl_sar(chan, L2CAP_SAR_END); 16490a708f8fSGustavo F. Padovan buflen = len; 16500a708f8fSGustavo F. Padovan } 16510a708f8fSGustavo F. Padovan 165247d1ec61SGustavo F. Padovan skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0); 16530a708f8fSGustavo F. Padovan if (IS_ERR(skb)) { 16540a708f8fSGustavo F. Padovan skb_queue_purge(&sar_queue); 16550a708f8fSGustavo F. Padovan return PTR_ERR(skb); 16560a708f8fSGustavo F. Padovan } 16570a708f8fSGustavo F. Padovan 16580a708f8fSGustavo F. Padovan __skb_queue_tail(&sar_queue, skb); 16590a708f8fSGustavo F. Padovan len -= buflen; 16600a708f8fSGustavo F. Padovan size += buflen; 16610a708f8fSGustavo F. Padovan } 166258d35f87SGustavo F. Padovan skb_queue_splice_tail(&sar_queue, &chan->tx_q); 166358d35f87SGustavo F. Padovan if (chan->tx_send_head == NULL) 166458d35f87SGustavo F. Padovan chan->tx_send_head = sar_queue.next; 16650a708f8fSGustavo F. Padovan 16660a708f8fSGustavo F. Padovan return size; 16670a708f8fSGustavo F. Padovan } 16680a708f8fSGustavo F. Padovan 16695e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, 16705e59b791SLuiz Augusto von Dentz u32 priority) 16719a91a04aSGustavo F. Padovan { 16729a91a04aSGustavo F. Padovan struct sk_buff *skb; 167388843ab0SAndrei Emeltchenko u32 control; 16749a91a04aSGustavo F. Padovan int err; 16759a91a04aSGustavo F. Padovan 16769a91a04aSGustavo F. Padovan /* Connectionless channel */ 1677715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { 16785e59b791SLuiz Augusto von Dentz skb = l2cap_create_connless_pdu(chan, msg, len, priority); 16799a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 16809a91a04aSGustavo F. Padovan return PTR_ERR(skb); 16819a91a04aSGustavo F. Padovan 16829a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 16839a91a04aSGustavo F. Padovan return len; 16849a91a04aSGustavo F. Padovan } 16859a91a04aSGustavo F. Padovan 16869a91a04aSGustavo F. Padovan switch (chan->mode) { 16879a91a04aSGustavo F. Padovan case L2CAP_MODE_BASIC: 16889a91a04aSGustavo F. Padovan /* Check outgoing MTU */ 16899a91a04aSGustavo F. Padovan if (len > chan->omtu) 16909a91a04aSGustavo F. Padovan return -EMSGSIZE; 16919a91a04aSGustavo F. Padovan 16929a91a04aSGustavo F. Padovan /* Create a basic PDU */ 16935e59b791SLuiz Augusto von Dentz skb = l2cap_create_basic_pdu(chan, msg, len, priority); 16949a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 16959a91a04aSGustavo F. Padovan return PTR_ERR(skb); 16969a91a04aSGustavo F. Padovan 16979a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 16989a91a04aSGustavo F. Padovan err = len; 16999a91a04aSGustavo F. Padovan break; 17009a91a04aSGustavo F. Padovan 17019a91a04aSGustavo F. Padovan case L2CAP_MODE_ERTM: 17029a91a04aSGustavo F. Padovan case L2CAP_MODE_STREAMING: 17039a91a04aSGustavo F. Padovan /* Entire SDU fits into one PDU */ 17049a91a04aSGustavo F. Padovan if (len <= chan->remote_mps) { 17057e0ef6eeSAndrei Emeltchenko control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED); 17069a91a04aSGustavo F. Padovan skb = l2cap_create_iframe_pdu(chan, msg, len, control, 17079a91a04aSGustavo F. Padovan 0); 17089a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 17099a91a04aSGustavo F. Padovan return PTR_ERR(skb); 17109a91a04aSGustavo F. Padovan 17119a91a04aSGustavo F. Padovan __skb_queue_tail(&chan->tx_q, skb); 17129a91a04aSGustavo F. Padovan 17139a91a04aSGustavo F. Padovan if (chan->tx_send_head == NULL) 17149a91a04aSGustavo F. Padovan chan->tx_send_head = skb; 17159a91a04aSGustavo F. Padovan 17169a91a04aSGustavo F. Padovan } else { 17179a91a04aSGustavo F. Padovan /* Segment SDU into multiples PDUs */ 17189a91a04aSGustavo F. Padovan err = l2cap_sar_segment_sdu(chan, msg, len); 17199a91a04aSGustavo F. Padovan if (err < 0) 17209a91a04aSGustavo F. Padovan return err; 17219a91a04aSGustavo F. Padovan } 17229a91a04aSGustavo F. Padovan 17239a91a04aSGustavo F. Padovan if (chan->mode == L2CAP_MODE_STREAMING) { 17249a91a04aSGustavo F. Padovan l2cap_streaming_send(chan); 17259a91a04aSGustavo F. Padovan err = len; 17269a91a04aSGustavo F. Padovan break; 17279a91a04aSGustavo F. Padovan } 17289a91a04aSGustavo F. Padovan 1729e2ab4353SGustavo F. Padovan if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 1730e2ab4353SGustavo F. Padovan test_bit(CONN_WAIT_F, &chan->conn_state)) { 17319a91a04aSGustavo F. Padovan err = len; 17329a91a04aSGustavo F. Padovan break; 17339a91a04aSGustavo F. Padovan } 17349a91a04aSGustavo F. Padovan 17359a91a04aSGustavo F. Padovan err = l2cap_ertm_send(chan); 17369a91a04aSGustavo F. Padovan if (err >= 0) 17379a91a04aSGustavo F. Padovan err = len; 17389a91a04aSGustavo F. Padovan 17399a91a04aSGustavo F. Padovan break; 17409a91a04aSGustavo F. Padovan 17419a91a04aSGustavo F. Padovan default: 17429a91a04aSGustavo F. Padovan BT_DBG("bad state %1.1x", chan->mode); 17439a91a04aSGustavo F. Padovan err = -EBADFD; 17449a91a04aSGustavo F. Padovan } 17459a91a04aSGustavo F. Padovan 17469a91a04aSGustavo F. Padovan return err; 17479a91a04aSGustavo F. Padovan } 17489a91a04aSGustavo F. Padovan 17490a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */ 17500a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 17510a708f8fSGustavo F. Padovan { 17520a708f8fSGustavo F. Padovan struct sk_buff *nskb; 175348454079SGustavo F. Padovan struct l2cap_chan *chan; 17540a708f8fSGustavo F. Padovan 17550a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 17560a708f8fSGustavo F. Padovan 1757baa7e1faSGustavo F. Padovan read_lock(&conn->chan_lock); 1758baa7e1faSGustavo F. Padovan list_for_each_entry(chan, &conn->chan_l, list) { 175948454079SGustavo F. Padovan struct sock *sk = chan->sk; 1760715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW) 17610a708f8fSGustavo F. Padovan continue; 17620a708f8fSGustavo F. Padovan 17630a708f8fSGustavo F. Padovan /* Don't send frame to the socket it came from */ 17640a708f8fSGustavo F. Padovan if (skb->sk == sk) 17650a708f8fSGustavo F. Padovan continue; 17660a708f8fSGustavo F. Padovan nskb = skb_clone(skb, GFP_ATOMIC); 17670a708f8fSGustavo F. Padovan if (!nskb) 17680a708f8fSGustavo F. Padovan continue; 17690a708f8fSGustavo F. Padovan 177023070494SGustavo F. Padovan if (chan->ops->recv(chan->data, nskb)) 17710a708f8fSGustavo F. Padovan kfree_skb(nskb); 17720a708f8fSGustavo F. Padovan } 1773baa7e1faSGustavo F. Padovan read_unlock(&conn->chan_lock); 17740a708f8fSGustavo F. Padovan } 17750a708f8fSGustavo F. Padovan 17760a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */ 17770a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 17780a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data) 17790a708f8fSGustavo F. Padovan { 17800a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag; 17810a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd; 17820a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 17830a708f8fSGustavo F. Padovan int len, count; 17840a708f8fSGustavo F. Padovan 17850a708f8fSGustavo F. Padovan BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d", 17860a708f8fSGustavo F. Padovan conn, code, ident, dlen); 17870a708f8fSGustavo F. Padovan 17880a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; 17890a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 17900a708f8fSGustavo F. Padovan 17910a708f8fSGustavo F. Padovan skb = bt_skb_alloc(count, GFP_ATOMIC); 17920a708f8fSGustavo F. Padovan if (!skb) 17930a708f8fSGustavo F. Padovan return NULL; 17940a708f8fSGustavo F. Padovan 17950a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 17960a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); 17973300d9a9SClaudio Takahasi 17983300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 17993300d9a9SClaudio Takahasi lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING); 18003300d9a9SClaudio Takahasi else 18010a708f8fSGustavo F. Padovan lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING); 18020a708f8fSGustavo F. Padovan 18030a708f8fSGustavo F. Padovan cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); 18040a708f8fSGustavo F. Padovan cmd->code = code; 18050a708f8fSGustavo F. Padovan cmd->ident = ident; 18060a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen); 18070a708f8fSGustavo F. Padovan 18080a708f8fSGustavo F. Padovan if (dlen) { 18090a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE; 18100a708f8fSGustavo F. Padovan memcpy(skb_put(skb, count), data, count); 18110a708f8fSGustavo F. Padovan data += count; 18120a708f8fSGustavo F. Padovan } 18130a708f8fSGustavo F. Padovan 18140a708f8fSGustavo F. Padovan len -= skb->len; 18150a708f8fSGustavo F. Padovan 18160a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 18170a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 18180a708f8fSGustavo F. Padovan while (len) { 18190a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 18200a708f8fSGustavo F. Padovan 18210a708f8fSGustavo F. Padovan *frag = bt_skb_alloc(count, GFP_ATOMIC); 18220a708f8fSGustavo F. Padovan if (!*frag) 18230a708f8fSGustavo F. Padovan goto fail; 18240a708f8fSGustavo F. Padovan 18250a708f8fSGustavo F. Padovan memcpy(skb_put(*frag, count), data, count); 18260a708f8fSGustavo F. Padovan 18270a708f8fSGustavo F. Padovan len -= count; 18280a708f8fSGustavo F. Padovan data += count; 18290a708f8fSGustavo F. Padovan 18300a708f8fSGustavo F. Padovan frag = &(*frag)->next; 18310a708f8fSGustavo F. Padovan } 18320a708f8fSGustavo F. Padovan 18330a708f8fSGustavo F. Padovan return skb; 18340a708f8fSGustavo F. Padovan 18350a708f8fSGustavo F. Padovan fail: 18360a708f8fSGustavo F. Padovan kfree_skb(skb); 18370a708f8fSGustavo F. Padovan return NULL; 18380a708f8fSGustavo F. Padovan } 18390a708f8fSGustavo F. Padovan 18400a708f8fSGustavo F. Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val) 18410a708f8fSGustavo F. Padovan { 18420a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 18430a708f8fSGustavo F. Padovan int len; 18440a708f8fSGustavo F. Padovan 18450a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len; 18460a708f8fSGustavo F. Padovan *ptr += len; 18470a708f8fSGustavo F. Padovan 18480a708f8fSGustavo F. Padovan *type = opt->type; 18490a708f8fSGustavo F. Padovan *olen = opt->len; 18500a708f8fSGustavo F. Padovan 18510a708f8fSGustavo F. Padovan switch (opt->len) { 18520a708f8fSGustavo F. Padovan case 1: 18530a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val); 18540a708f8fSGustavo F. Padovan break; 18550a708f8fSGustavo F. Padovan 18560a708f8fSGustavo F. Padovan case 2: 18570a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val); 18580a708f8fSGustavo F. Padovan break; 18590a708f8fSGustavo F. Padovan 18600a708f8fSGustavo F. Padovan case 4: 18610a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val); 18620a708f8fSGustavo F. Padovan break; 18630a708f8fSGustavo F. Padovan 18640a708f8fSGustavo F. Padovan default: 18650a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val; 18660a708f8fSGustavo F. Padovan break; 18670a708f8fSGustavo F. Padovan } 18680a708f8fSGustavo F. Padovan 18690a708f8fSGustavo F. Padovan BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val); 18700a708f8fSGustavo F. Padovan return len; 18710a708f8fSGustavo F. Padovan } 18720a708f8fSGustavo F. Padovan 18730a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) 18740a708f8fSGustavo F. Padovan { 18750a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 18760a708f8fSGustavo F. Padovan 18770a708f8fSGustavo F. Padovan BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val); 18780a708f8fSGustavo F. Padovan 18790a708f8fSGustavo F. Padovan opt->type = type; 18800a708f8fSGustavo F. Padovan opt->len = len; 18810a708f8fSGustavo F. Padovan 18820a708f8fSGustavo F. Padovan switch (len) { 18830a708f8fSGustavo F. Padovan case 1: 18840a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val; 18850a708f8fSGustavo F. Padovan break; 18860a708f8fSGustavo F. Padovan 18870a708f8fSGustavo F. Padovan case 2: 18880a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val); 18890a708f8fSGustavo F. Padovan break; 18900a708f8fSGustavo F. Padovan 18910a708f8fSGustavo F. Padovan case 4: 18920a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val); 18930a708f8fSGustavo F. Padovan break; 18940a708f8fSGustavo F. Padovan 18950a708f8fSGustavo F. Padovan default: 18960a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len); 18970a708f8fSGustavo F. Padovan break; 18980a708f8fSGustavo F. Padovan } 18990a708f8fSGustavo F. Padovan 19000a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len; 19010a708f8fSGustavo F. Padovan } 19020a708f8fSGustavo F. Padovan 1903f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) 1904f89cef09SAndrei Emeltchenko { 1905f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs; 1906f89cef09SAndrei Emeltchenko 1907f89cef09SAndrei Emeltchenko switch(chan->mode) { 1908f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM: 1909f89cef09SAndrei Emeltchenko efs.id = chan->local_id; 1910f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype; 1911f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 1912f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 1913f89cef09SAndrei Emeltchenko efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); 1914f89cef09SAndrei Emeltchenko efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO); 1915f89cef09SAndrei Emeltchenko break; 1916f89cef09SAndrei Emeltchenko 1917f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING: 1918f89cef09SAndrei Emeltchenko efs.id = 1; 1919f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT; 1920f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 1921f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 1922f89cef09SAndrei Emeltchenko efs.acc_lat = 0; 1923f89cef09SAndrei Emeltchenko efs.flush_to = 0; 1924f89cef09SAndrei Emeltchenko break; 1925f89cef09SAndrei Emeltchenko 1926f89cef09SAndrei Emeltchenko default: 1927f89cef09SAndrei Emeltchenko return; 1928f89cef09SAndrei Emeltchenko } 1929f89cef09SAndrei Emeltchenko 1930f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), 1931f89cef09SAndrei Emeltchenko (unsigned long) &efs); 1932f89cef09SAndrei Emeltchenko } 1933f89cef09SAndrei Emeltchenko 19340a708f8fSGustavo F. Padovan static void l2cap_ack_timeout(unsigned long arg) 19350a708f8fSGustavo F. Padovan { 1936525cd185SGustavo F. Padovan struct l2cap_chan *chan = (void *) arg; 19370a708f8fSGustavo F. Padovan 1938525cd185SGustavo F. Padovan bh_lock_sock(chan->sk); 1939525cd185SGustavo F. Padovan l2cap_send_ack(chan); 1940525cd185SGustavo F. Padovan bh_unlock_sock(chan->sk); 19410a708f8fSGustavo F. Padovan } 19420a708f8fSGustavo F. Padovan 1943525cd185SGustavo F. Padovan static inline void l2cap_ertm_init(struct l2cap_chan *chan) 19440a708f8fSGustavo F. Padovan { 1945525cd185SGustavo F. Padovan struct sock *sk = chan->sk; 1946525cd185SGustavo F. Padovan 194742e5c802SGustavo F. Padovan chan->expected_ack_seq = 0; 19486a026610SGustavo F. Padovan chan->unacked_frames = 0; 194942e5c802SGustavo F. Padovan chan->buffer_seq = 0; 19506a026610SGustavo F. Padovan chan->num_acked = 0; 19516a026610SGustavo F. Padovan chan->frames_sent = 0; 19520a708f8fSGustavo F. Padovan 1953e92c8e70SGustavo F. Padovan setup_timer(&chan->retrans_timer, l2cap_retrans_timeout, 1954e92c8e70SGustavo F. Padovan (unsigned long) chan); 1955e92c8e70SGustavo F. Padovan setup_timer(&chan->monitor_timer, l2cap_monitor_timeout, 1956e92c8e70SGustavo F. Padovan (unsigned long) chan); 1957e92c8e70SGustavo F. Padovan setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan); 19580a708f8fSGustavo F. Padovan 1959f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q); 19600a708f8fSGustavo F. Padovan 196139d5a3eeSGustavo F. Padovan INIT_LIST_HEAD(&chan->srej_l); 196239d5a3eeSGustavo F. Padovan 19630a708f8fSGustavo F. Padovan 19640a708f8fSGustavo F. Padovan sk->sk_backlog_rcv = l2cap_ertm_data_rcv; 19650a708f8fSGustavo F. Padovan } 19660a708f8fSGustavo F. Padovan 19670a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) 19680a708f8fSGustavo F. Padovan { 19690a708f8fSGustavo F. Padovan switch (mode) { 19700a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 19710a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 19720a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask)) 19730a708f8fSGustavo F. Padovan return mode; 19740a708f8fSGustavo F. Padovan /* fall through */ 19750a708f8fSGustavo F. Padovan default: 19760a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC; 19770a708f8fSGustavo F. Padovan } 19780a708f8fSGustavo F. Padovan } 19790a708f8fSGustavo F. Padovan 19806327eb98SAndrei Emeltchenko static inline bool __l2cap_ews_supported(struct l2cap_chan *chan) 19816327eb98SAndrei Emeltchenko { 19826327eb98SAndrei Emeltchenko return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW; 19836327eb98SAndrei Emeltchenko } 19846327eb98SAndrei Emeltchenko 1985f89cef09SAndrei Emeltchenko static inline bool __l2cap_efs_supported(struct l2cap_chan *chan) 1986f89cef09SAndrei Emeltchenko { 1987f89cef09SAndrei Emeltchenko return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW; 1988f89cef09SAndrei Emeltchenko } 1989f89cef09SAndrei Emeltchenko 19906327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan) 19916327eb98SAndrei Emeltchenko { 19926327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && 1993836be934SAndrei Emeltchenko __l2cap_ews_supported(chan)) { 19946327eb98SAndrei Emeltchenko /* use extended control field */ 19956327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 1996836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 1997836be934SAndrei Emeltchenko } else { 19986327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win, 19996327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 2000836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 2001836be934SAndrei Emeltchenko } 20026327eb98SAndrei Emeltchenko } 20036327eb98SAndrei Emeltchenko 2004710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) 20050a708f8fSGustavo F. Padovan { 20060a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 20070c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode }; 20080a708f8fSGustavo F. Padovan void *ptr = req->data; 2009c8f79162SAndrei Emeltchenko u16 size; 20100a708f8fSGustavo F. Padovan 201149208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 20120a708f8fSGustavo F. Padovan 201373ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp) 20140a708f8fSGustavo F. Padovan goto done; 20150a708f8fSGustavo F. Padovan 20160c1bc5c6SGustavo F. Padovan switch (chan->mode) { 20170a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 20180a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 2019c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) 20200a708f8fSGustavo F. Padovan break; 20210a708f8fSGustavo F. Padovan 2022f89cef09SAndrei Emeltchenko if (__l2cap_efs_supported(chan)) 2023f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 2024f89cef09SAndrei Emeltchenko 20250a708f8fSGustavo F. Padovan /* fall through */ 20260a708f8fSGustavo F. Padovan default: 20278c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); 20280a708f8fSGustavo F. Padovan break; 20290a708f8fSGustavo F. Padovan } 20300a708f8fSGustavo F. Padovan 20310a708f8fSGustavo F. Padovan done: 20320c1bc5c6SGustavo F. Padovan if (chan->imtu != L2CAP_DEFAULT_MTU) 20330c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 20340a708f8fSGustavo F. Padovan 20350c1bc5c6SGustavo F. Padovan switch (chan->mode) { 20360a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 20378c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && 20388c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) 20390a708f8fSGustavo F. Padovan break; 20400a708f8fSGustavo F. Padovan 20410a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC; 20420a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 20430a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 20440a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 20450a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 20460a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0; 20470a708f8fSGustavo F. Padovan 20480a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 20490a708f8fSGustavo F. Padovan (unsigned long) &rfc); 20500a708f8fSGustavo F. Padovan break; 20510a708f8fSGustavo F. Padovan 20520a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 20530a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM; 205447d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx; 20550a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 20560a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 2057c8f79162SAndrei Emeltchenko 2058c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 2059c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2060c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2061c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2062c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 20630a708f8fSGustavo F. Padovan 20646327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan); 20656327eb98SAndrei Emeltchenko 20666327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win, 20676327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 20686327eb98SAndrei Emeltchenko 20690a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 20700a708f8fSGustavo F. Padovan (unsigned long) &rfc); 20710a708f8fSGustavo F. Padovan 2072f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 2073f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 2074f89cef09SAndrei Emeltchenko 20758c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) 20760a708f8fSGustavo F. Padovan break; 20770a708f8fSGustavo F. Padovan 207847d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 2079c1360a1cSGustavo F. Padovan test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { 208047d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 208147d1ec61SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); 20820a708f8fSGustavo F. Padovan } 20836327eb98SAndrei Emeltchenko 20846327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 20856327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 20866327eb98SAndrei Emeltchenko chan->tx_win); 20870a708f8fSGustavo F. Padovan break; 20880a708f8fSGustavo F. Padovan 20890a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 20900a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING; 20910a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 20920a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 20930a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 20940a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 2095c8f79162SAndrei Emeltchenko 2096c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 2097c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2098c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2099c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2100c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 21010a708f8fSGustavo F. Padovan 21020a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 21030a708f8fSGustavo F. Padovan (unsigned long) &rfc); 21040a708f8fSGustavo F. Padovan 2105f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 2106f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 2107f89cef09SAndrei Emeltchenko 21088c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) 21090a708f8fSGustavo F. Padovan break; 21100a708f8fSGustavo F. Padovan 211147d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 2112c1360a1cSGustavo F. Padovan test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { 211347d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 211447d1ec61SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); 21150a708f8fSGustavo F. Padovan } 21160a708f8fSGustavo F. Padovan break; 21170a708f8fSGustavo F. Padovan } 21180a708f8fSGustavo F. Padovan 2119fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 21200a708f8fSGustavo F. Padovan req->flags = cpu_to_le16(0); 21210a708f8fSGustavo F. Padovan 21220a708f8fSGustavo F. Padovan return ptr - data; 21230a708f8fSGustavo F. Padovan } 21240a708f8fSGustavo F. Padovan 212573ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) 21260a708f8fSGustavo F. Padovan { 21270a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 21280a708f8fSGustavo F. Padovan void *ptr = rsp->data; 212973ffa904SGustavo F. Padovan void *req = chan->conf_req; 213073ffa904SGustavo F. Padovan int len = chan->conf_len; 21310a708f8fSGustavo F. Padovan int type, hint, olen; 21320a708f8fSGustavo F. Padovan unsigned long val; 21330a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 213442dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs; 213542dceae2SAndrei Emeltchenko u8 remote_efs = 0; 21360a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU; 21370a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS; 2138c8f79162SAndrei Emeltchenko u16 size; 21390a708f8fSGustavo F. Padovan 214073ffa904SGustavo F. Padovan BT_DBG("chan %p", chan); 21410a708f8fSGustavo F. Padovan 21420a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 21430a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val); 21440a708f8fSGustavo F. Padovan 21450a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT; 21460a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK; 21470a708f8fSGustavo F. Padovan 21480a708f8fSGustavo F. Padovan switch (type) { 21490a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 21500a708f8fSGustavo F. Padovan mtu = val; 21510a708f8fSGustavo F. Padovan break; 21520a708f8fSGustavo F. Padovan 21530a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 21540c1bc5c6SGustavo F. Padovan chan->flush_to = val; 21550a708f8fSGustavo F. Padovan break; 21560a708f8fSGustavo F. Padovan 21570a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS: 21580a708f8fSGustavo F. Padovan break; 21590a708f8fSGustavo F. Padovan 21600a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 21610a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 21620a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen); 21630a708f8fSGustavo F. Padovan break; 21640a708f8fSGustavo F. Padovan 21650a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS: 21660a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE) 2167c1360a1cSGustavo F. Padovan set_bit(CONF_NO_FCS_RECV, &chan->conf_state); 216842dceae2SAndrei Emeltchenko break; 21690a708f8fSGustavo F. Padovan 217042dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS: 217142dceae2SAndrei Emeltchenko remote_efs = 1; 217242dceae2SAndrei Emeltchenko if (olen == sizeof(efs)) 217342dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen); 21740a708f8fSGustavo F. Padovan break; 21750a708f8fSGustavo F. Padovan 21766327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 21776327eb98SAndrei Emeltchenko if (!enable_hs) 21786327eb98SAndrei Emeltchenko return -ECONNREFUSED; 21796327eb98SAndrei Emeltchenko 21806327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 21816327eb98SAndrei Emeltchenko set_bit(CONF_EWS_RECV, &chan->conf_state); 2182836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 21836327eb98SAndrei Emeltchenko chan->remote_tx_win = val; 21846327eb98SAndrei Emeltchenko break; 21856327eb98SAndrei Emeltchenko 21860a708f8fSGustavo F. Padovan default: 21870a708f8fSGustavo F. Padovan if (hint) 21880a708f8fSGustavo F. Padovan break; 21890a708f8fSGustavo F. Padovan 21900a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN; 21910a708f8fSGustavo F. Padovan *((u8 *) ptr++) = type; 21920a708f8fSGustavo F. Padovan break; 21930a708f8fSGustavo F. Padovan } 21940a708f8fSGustavo F. Padovan } 21950a708f8fSGustavo F. Padovan 219673ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1) 21970a708f8fSGustavo F. Padovan goto done; 21980a708f8fSGustavo F. Padovan 21990c1bc5c6SGustavo F. Padovan switch (chan->mode) { 22000a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 22010a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 2202c1360a1cSGustavo F. Padovan if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { 22030c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, 22048c1d787bSGustavo F. Padovan chan->conn->feat_mask); 22050a708f8fSGustavo F. Padovan break; 22060a708f8fSGustavo F. Padovan } 22070a708f8fSGustavo F. Padovan 220842dceae2SAndrei Emeltchenko if (remote_efs) { 220942dceae2SAndrei Emeltchenko if (__l2cap_efs_supported(chan)) 221042dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 221142dceae2SAndrei Emeltchenko else 221242dceae2SAndrei Emeltchenko return -ECONNREFUSED; 221342dceae2SAndrei Emeltchenko } 221442dceae2SAndrei Emeltchenko 22150c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) 22160a708f8fSGustavo F. Padovan return -ECONNREFUSED; 22170a708f8fSGustavo F. Padovan 22180a708f8fSGustavo F. Padovan break; 22190a708f8fSGustavo F. Padovan } 22200a708f8fSGustavo F. Padovan 22210a708f8fSGustavo F. Padovan done: 22220c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) { 22230a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 22240c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 22250a708f8fSGustavo F. Padovan 222673ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1) 22270a708f8fSGustavo F. Padovan return -ECONNREFUSED; 22280a708f8fSGustavo F. Padovan 22290a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 22300a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 22310a708f8fSGustavo F. Padovan } 22320a708f8fSGustavo F. Padovan 22330a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) { 22340a708f8fSGustavo F. Padovan /* Configure output options and let the other side know 22350a708f8fSGustavo F. Padovan * which ones we don't like. */ 22360a708f8fSGustavo F. Padovan 22370a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU) 22380a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 22390a708f8fSGustavo F. Padovan else { 22400c1bc5c6SGustavo F. Padovan chan->omtu = mtu; 2241c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state); 22420a708f8fSGustavo F. Padovan } 22430c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); 22440a708f8fSGustavo F. Padovan 224542dceae2SAndrei Emeltchenko if (remote_efs) { 224642dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 224742dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 224842dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) { 224942dceae2SAndrei Emeltchenko 225042dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT; 225142dceae2SAndrei Emeltchenko 225242dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1) 225342dceae2SAndrei Emeltchenko return -ECONNREFUSED; 225442dceae2SAndrei Emeltchenko 225542dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 225642dceae2SAndrei Emeltchenko sizeof(efs), 225742dceae2SAndrei Emeltchenko (unsigned long) &efs); 22580e8b207eSAndrei Emeltchenko } else { 22593e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */ 22600e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING; 22610e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 226242dceae2SAndrei Emeltchenko } 226342dceae2SAndrei Emeltchenko } 226442dceae2SAndrei Emeltchenko 22650a708f8fSGustavo F. Padovan switch (rfc.mode) { 22660a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 226747d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 2268c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 22690a708f8fSGustavo F. Padovan break; 22700a708f8fSGustavo F. Padovan 22710a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 22726327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state)) 22732c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size; 22746327eb98SAndrei Emeltchenko else 22756327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; 22766327eb98SAndrei Emeltchenko 22772c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit; 22780a708f8fSGustavo F. Padovan 2279c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 2280c8f79162SAndrei Emeltchenko chan->conn->mtu - 2281c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2282c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2283c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2284c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 2285c8f79162SAndrei Emeltchenko chan->remote_mps = size; 22860a708f8fSGustavo F. Padovan 22870a708f8fSGustavo F. Padovan rfc.retrans_timeout = 22880a708f8fSGustavo F. Padovan le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO); 22890a708f8fSGustavo F. Padovan rfc.monitor_timeout = 22900a708f8fSGustavo F. Padovan le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO); 22910a708f8fSGustavo F. Padovan 2292c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 22930a708f8fSGustavo F. Padovan 22940a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 22950a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 22960a708f8fSGustavo F. Padovan 229742dceae2SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 229842dceae2SAndrei Emeltchenko chan->remote_id = efs.id; 229942dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype; 230042dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu); 230142dceae2SAndrei Emeltchenko chan->remote_flush_to = 230242dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to); 230342dceae2SAndrei Emeltchenko chan->remote_acc_lat = 230442dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat); 230542dceae2SAndrei Emeltchenko chan->remote_sdu_itime = 230642dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 230742dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 230842dceae2SAndrei Emeltchenko sizeof(efs), (unsigned long) &efs); 230942dceae2SAndrei Emeltchenko } 23100a708f8fSGustavo F. Padovan break; 23110a708f8fSGustavo F. Padovan 23120a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 2313c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 2314c8f79162SAndrei Emeltchenko chan->conn->mtu - 2315c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2316c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2317c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2318c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 2319c8f79162SAndrei Emeltchenko chan->remote_mps = size; 23200a708f8fSGustavo F. Padovan 2321c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 23220a708f8fSGustavo F. Padovan 23230a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 23240a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 23250a708f8fSGustavo F. Padovan 23260a708f8fSGustavo F. Padovan break; 23270a708f8fSGustavo F. Padovan 23280a708f8fSGustavo F. Padovan default: 23290a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 23300a708f8fSGustavo F. Padovan 23310a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc)); 23320c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 23330a708f8fSGustavo F. Padovan } 23340a708f8fSGustavo F. Padovan 23350a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) 2336c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 23370a708f8fSGustavo F. Padovan } 2338fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 23390a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 23400a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(0x0000); 23410a708f8fSGustavo F. Padovan 23420a708f8fSGustavo F. Padovan return ptr - data; 23430a708f8fSGustavo F. Padovan } 23440a708f8fSGustavo F. Padovan 2345b4450035SGustavo F. Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result) 23460a708f8fSGustavo F. Padovan { 23470a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 23480a708f8fSGustavo F. Padovan void *ptr = req->data; 23490a708f8fSGustavo F. Padovan int type, olen; 23500a708f8fSGustavo F. Padovan unsigned long val; 23510a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc; 23520a708f8fSGustavo F. Padovan 2353fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); 23540a708f8fSGustavo F. Padovan 23550a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 23560a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 23570a708f8fSGustavo F. Padovan 23580a708f8fSGustavo F. Padovan switch (type) { 23590a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 23600a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) { 23610a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT; 23620c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU; 23630a708f8fSGustavo F. Padovan } else 23640c1bc5c6SGustavo F. Padovan chan->imtu = val; 23650c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 23660a708f8fSGustavo F. Padovan break; 23670a708f8fSGustavo F. Padovan 23680a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 23690c1bc5c6SGustavo F. Padovan chan->flush_to = val; 23700a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 23710c1bc5c6SGustavo F. Padovan 2, chan->flush_to); 23720a708f8fSGustavo F. Padovan break; 23730a708f8fSGustavo F. Padovan 23740a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 23750a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 23760a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 23770a708f8fSGustavo F. Padovan 2378c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && 23790c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode) 23800a708f8fSGustavo F. Padovan return -ECONNREFUSED; 23810a708f8fSGustavo F. Padovan 238247d1ec61SGustavo F. Padovan chan->fcs = 0; 23830a708f8fSGustavo F. Padovan 23840a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 23850a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 23860a708f8fSGustavo F. Padovan break; 23876327eb98SAndrei Emeltchenko 23886327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 23896327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, val, 23906327eb98SAndrei Emeltchenko L2CAP_DEFAULT_EXT_WINDOW); 23913e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 23923e6b3b95SGustavo F. Padovan chan->tx_win); 23936327eb98SAndrei Emeltchenko break; 23940a708f8fSGustavo F. Padovan } 23950a708f8fSGustavo F. Padovan } 23960a708f8fSGustavo F. Padovan 23970c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) 23980a708f8fSGustavo F. Padovan return -ECONNREFUSED; 23990a708f8fSGustavo F. Padovan 24000c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode; 24010a708f8fSGustavo F. Padovan 24020e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) { 24030a708f8fSGustavo F. Padovan switch (rfc.mode) { 24040a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 240547d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 240647d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 240747d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 24080a708f8fSGustavo F. Padovan break; 24090a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 241047d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 24110a708f8fSGustavo F. Padovan } 24120a708f8fSGustavo F. Padovan } 24130a708f8fSGustavo F. Padovan 2414fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 24150a708f8fSGustavo F. Padovan req->flags = cpu_to_le16(0x0000); 24160a708f8fSGustavo F. Padovan 24170a708f8fSGustavo F. Padovan return ptr - data; 24180a708f8fSGustavo F. Padovan } 24190a708f8fSGustavo F. Padovan 2420fe4128e0SGustavo F. Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags) 24210a708f8fSGustavo F. Padovan { 24220a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 24230a708f8fSGustavo F. Padovan void *ptr = rsp->data; 24240a708f8fSGustavo F. Padovan 2425fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan); 24260a708f8fSGustavo F. Padovan 2427fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 24280a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 24290a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags); 24300a708f8fSGustavo F. Padovan 24310a708f8fSGustavo F. Padovan return ptr - data; 24320a708f8fSGustavo F. Padovan } 24330a708f8fSGustavo F. Padovan 24348c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) 2435710f9b0aSGustavo F. Padovan { 2436710f9b0aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 24378c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 2438710f9b0aSGustavo F. Padovan u8 buf[128]; 2439710f9b0aSGustavo F. Padovan 2440fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 2441fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 2442710f9b0aSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 2443710f9b0aSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 2444710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, 2445710f9b0aSGustavo F. Padovan L2CAP_CONN_RSP, sizeof(rsp), &rsp); 2446710f9b0aSGustavo F. Padovan 2447c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 2448710f9b0aSGustavo F. Padovan return; 2449710f9b0aSGustavo F. Padovan 2450710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 2451710f9b0aSGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 2452710f9b0aSGustavo F. Padovan chan->num_conf_req++; 2453710f9b0aSGustavo F. Padovan } 2454710f9b0aSGustavo F. Padovan 245547d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) 24560a708f8fSGustavo F. Padovan { 24570a708f8fSGustavo F. Padovan int type, olen; 24580a708f8fSGustavo F. Padovan unsigned long val; 24590a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc; 24600a708f8fSGustavo F. Padovan 246147d1ec61SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); 24620a708f8fSGustavo F. Padovan 24630c1bc5c6SGustavo F. Padovan if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) 24640a708f8fSGustavo F. Padovan return; 24650a708f8fSGustavo F. Padovan 24660a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 24670a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 24680a708f8fSGustavo F. Padovan 24690a708f8fSGustavo F. Padovan switch (type) { 24700a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 24710a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 24720a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 24730a708f8fSGustavo F. Padovan goto done; 24740a708f8fSGustavo F. Padovan } 24750a708f8fSGustavo F. Padovan } 24760a708f8fSGustavo F. Padovan 24770a708f8fSGustavo F. Padovan done: 24780a708f8fSGustavo F. Padovan switch (rfc.mode) { 24790a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 248047d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 248147d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 248247d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 24830a708f8fSGustavo F. Padovan break; 24840a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 248547d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 24860a708f8fSGustavo F. Padovan } 24870a708f8fSGustavo F. Padovan } 24880a708f8fSGustavo F. Padovan 24890a708f8fSGustavo F. Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 24900a708f8fSGustavo F. Padovan { 2491e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 24920a708f8fSGustavo F. Padovan 2493e2fd318eSIlia Kolomisnky if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) 24940a708f8fSGustavo F. Padovan return 0; 24950a708f8fSGustavo F. Padovan 24960a708f8fSGustavo F. Padovan if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && 24970a708f8fSGustavo F. Padovan cmd->ident == conn->info_ident) { 24980a708f8fSGustavo F. Padovan del_timer(&conn->info_timer); 24990a708f8fSGustavo F. Padovan 25000a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 25010a708f8fSGustavo F. Padovan conn->info_ident = 0; 25020a708f8fSGustavo F. Padovan 25030a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 25040a708f8fSGustavo F. Padovan } 25050a708f8fSGustavo F. Padovan 25060a708f8fSGustavo F. Padovan return 0; 25070a708f8fSGustavo F. Padovan } 25080a708f8fSGustavo F. Padovan 25090a708f8fSGustavo F. Padovan static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 25100a708f8fSGustavo F. Padovan { 25110a708f8fSGustavo F. Padovan struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 25120a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 251323691d75SGustavo F. Padovan struct l2cap_chan *chan = NULL, *pchan; 25140a708f8fSGustavo F. Padovan struct sock *parent, *sk = NULL; 25150a708f8fSGustavo F. Padovan int result, status = L2CAP_CS_NO_INFO; 25160a708f8fSGustavo F. Padovan 25170a708f8fSGustavo F. Padovan u16 dcid = 0, scid = __le16_to_cpu(req->scid); 25180a708f8fSGustavo F. Padovan __le16 psm = req->psm; 25190a708f8fSGustavo F. Padovan 25200a708f8fSGustavo F. Padovan BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid); 25210a708f8fSGustavo F. Padovan 25220a708f8fSGustavo F. Padovan /* Check if we have socket listening on psm */ 252323691d75SGustavo F. Padovan pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src); 252423691d75SGustavo F. Padovan if (!pchan) { 25250a708f8fSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 25260a708f8fSGustavo F. Padovan goto sendresp; 25270a708f8fSGustavo F. Padovan } 25280a708f8fSGustavo F. Padovan 252923691d75SGustavo F. Padovan parent = pchan->sk; 253023691d75SGustavo F. Padovan 25310a708f8fSGustavo F. Padovan bh_lock_sock(parent); 25320a708f8fSGustavo F. Padovan 25330a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */ 25340a708f8fSGustavo F. Padovan if (psm != cpu_to_le16(0x0001) && 25350a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) { 25360a708f8fSGustavo F. Padovan conn->disc_reason = 0x05; 25370a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 25380a708f8fSGustavo F. Padovan goto response; 25390a708f8fSGustavo F. Padovan } 25400a708f8fSGustavo F. Padovan 25410a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM; 25420a708f8fSGustavo F. Padovan 25430a708f8fSGustavo F. Padovan /* Check for backlog size */ 25440a708f8fSGustavo F. Padovan if (sk_acceptq_is_full(parent)) { 25450a708f8fSGustavo F. Padovan BT_DBG("backlog full %d", parent->sk_ack_backlog); 25460a708f8fSGustavo F. Padovan goto response; 25470a708f8fSGustavo F. Padovan } 25480a708f8fSGustavo F. Padovan 254980808e43SGustavo F. Padovan chan = pchan->ops->new_connection(pchan->data); 255080808e43SGustavo F. Padovan if (!chan) 25510a708f8fSGustavo F. Padovan goto response; 25520a708f8fSGustavo F. Padovan 255380808e43SGustavo F. Padovan sk = chan->sk; 255480808e43SGustavo F. Padovan 2555baa7e1faSGustavo F. Padovan write_lock_bh(&conn->chan_lock); 25560a708f8fSGustavo F. Padovan 25570a708f8fSGustavo F. Padovan /* Check if we already have channel with that dcid */ 2558baa7e1faSGustavo F. Padovan if (__l2cap_get_chan_by_dcid(conn, scid)) { 2559baa7e1faSGustavo F. Padovan write_unlock_bh(&conn->chan_lock); 25600a708f8fSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 2561ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 25620a708f8fSGustavo F. Padovan goto response; 25630a708f8fSGustavo F. Padovan } 25640a708f8fSGustavo F. Padovan 25650a708f8fSGustavo F. Padovan hci_conn_hold(conn->hcon); 25660a708f8fSGustavo F. Padovan 25670a708f8fSGustavo F. Padovan bacpy(&bt_sk(sk)->src, conn->src); 25680a708f8fSGustavo F. Padovan bacpy(&bt_sk(sk)->dst, conn->dst); 2569fe4128e0SGustavo F. Padovan chan->psm = psm; 2570fe4128e0SGustavo F. Padovan chan->dcid = scid; 25710a708f8fSGustavo F. Padovan 2572d1010240SGustavo F. Padovan bt_accept_enqueue(parent, sk); 2573d1010240SGustavo F. Padovan 257448454079SGustavo F. Padovan __l2cap_chan_add(conn, chan); 257548454079SGustavo F. Padovan 2576fe4128e0SGustavo F. Padovan dcid = chan->scid; 25770a708f8fSGustavo F. Padovan 2578c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 25790a708f8fSGustavo F. Padovan 2580fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident; 25810a708f8fSGustavo F. Padovan 25820a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { 25834343478fSGustavo F. Padovan if (l2cap_check_security(chan)) { 25840a708f8fSGustavo F. Padovan if (bt_sk(sk)->defer_setup) { 258589bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECT2); 25860a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 25870a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND; 25880a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 25890a708f8fSGustavo F. Padovan } else { 259089bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 25910a708f8fSGustavo F. Padovan result = L2CAP_CR_SUCCESS; 25920a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 25930a708f8fSGustavo F. Padovan } 25940a708f8fSGustavo F. Padovan } else { 259589bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECT2); 25960a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 25970a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND; 25980a708f8fSGustavo F. Padovan } 25990a708f8fSGustavo F. Padovan } else { 260089bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECT2); 26010a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 26020a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 26030a708f8fSGustavo F. Padovan } 26040a708f8fSGustavo F. Padovan 2605baa7e1faSGustavo F. Padovan write_unlock_bh(&conn->chan_lock); 26060a708f8fSGustavo F. Padovan 26070a708f8fSGustavo F. Padovan response: 26080a708f8fSGustavo F. Padovan bh_unlock_sock(parent); 26090a708f8fSGustavo F. Padovan 26100a708f8fSGustavo F. Padovan sendresp: 26110a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid); 26120a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid); 26130a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result); 26140a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status); 26150a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); 26160a708f8fSGustavo F. Padovan 26170a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { 26180a708f8fSGustavo F. Padovan struct l2cap_info_req info; 26190a708f8fSGustavo F. Padovan info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 26200a708f8fSGustavo F. Padovan 26210a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 26220a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 26230a708f8fSGustavo F. Padovan 26240a708f8fSGustavo F. Padovan mod_timer(&conn->info_timer, jiffies + 26250a708f8fSGustavo F. Padovan msecs_to_jiffies(L2CAP_INFO_TIMEOUT)); 26260a708f8fSGustavo F. Padovan 26270a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 26280a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(info), &info); 26290a708f8fSGustavo F. Padovan } 26300a708f8fSGustavo F. Padovan 2631c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && 26320a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) { 26330a708f8fSGustavo F. Padovan u8 buf[128]; 2634c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 26350a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 263673ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 263773ffa904SGustavo F. Padovan chan->num_conf_req++; 26380a708f8fSGustavo F. Padovan } 26390a708f8fSGustavo F. Padovan 26400a708f8fSGustavo F. Padovan return 0; 26410a708f8fSGustavo F. Padovan } 26420a708f8fSGustavo F. Padovan 26430a708f8fSGustavo F. Padovan static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 26440a708f8fSGustavo F. Padovan { 26450a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; 26460a708f8fSGustavo F. Padovan u16 scid, dcid, result, status; 264748454079SGustavo F. Padovan struct l2cap_chan *chan; 26480a708f8fSGustavo F. Padovan struct sock *sk; 26490a708f8fSGustavo F. Padovan u8 req[128]; 26500a708f8fSGustavo F. Padovan 26510a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 26520a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 26530a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 26540a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status); 26550a708f8fSGustavo F. Padovan 26560a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status); 26570a708f8fSGustavo F. Padovan 26580a708f8fSGustavo F. Padovan if (scid) { 2659baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 266048454079SGustavo F. Padovan if (!chan) 26610a708f8fSGustavo F. Padovan return -EFAULT; 26620a708f8fSGustavo F. Padovan } else { 2663baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_ident(conn, cmd->ident); 266448454079SGustavo F. Padovan if (!chan) 26650a708f8fSGustavo F. Padovan return -EFAULT; 26660a708f8fSGustavo F. Padovan } 26670a708f8fSGustavo F. Padovan 266848454079SGustavo F. Padovan sk = chan->sk; 266948454079SGustavo F. Padovan 26700a708f8fSGustavo F. Padovan switch (result) { 26710a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS: 267289bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 2673fc7f8a7eSGustavo F. Padovan chan->ident = 0; 2674fe4128e0SGustavo F. Padovan chan->dcid = dcid; 2675c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state); 26760a708f8fSGustavo F. Padovan 2677c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 26780a708f8fSGustavo F. Padovan break; 26790a708f8fSGustavo F. Padovan 26800a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 268173ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, req), req); 268273ffa904SGustavo F. Padovan chan->num_conf_req++; 26830a708f8fSGustavo F. Padovan break; 26840a708f8fSGustavo F. Padovan 26850a708f8fSGustavo F. Padovan case L2CAP_CR_PEND: 2686c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 26870a708f8fSGustavo F. Padovan break; 26880a708f8fSGustavo F. Padovan 26890a708f8fSGustavo F. Padovan default: 26900a708f8fSGustavo F. Padovan /* don't delete l2cap channel if sk is owned by user */ 26910a708f8fSGustavo F. Padovan if (sock_owned_by_user(sk)) { 269289bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_DISCONN); 2693c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 2694c9b66675SGustavo F. Padovan __set_chan_timer(chan, HZ / 5); 26950a708f8fSGustavo F. Padovan break; 26960a708f8fSGustavo F. Padovan } 26970a708f8fSGustavo F. Padovan 269848454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED); 26990a708f8fSGustavo F. Padovan break; 27000a708f8fSGustavo F. Padovan } 27010a708f8fSGustavo F. Padovan 27020a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 27030a708f8fSGustavo F. Padovan return 0; 27040a708f8fSGustavo F. Padovan } 27050a708f8fSGustavo F. Padovan 270647d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan) 27070a708f8fSGustavo F. Padovan { 27080a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both 27090a708f8fSGustavo F. Padovan * sides request it. 27100a708f8fSGustavo F. Padovan */ 27110c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) 271247d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 2713c1360a1cSGustavo F. Padovan else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) 271447d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16; 27150a708f8fSGustavo F. Padovan } 27160a708f8fSGustavo F. Padovan 27170a708f8fSGustavo F. Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 27180a708f8fSGustavo F. Padovan { 27190a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; 27200a708f8fSGustavo F. Padovan u16 dcid, flags; 27210a708f8fSGustavo F. Padovan u8 rsp[64]; 272248454079SGustavo F. Padovan struct l2cap_chan *chan; 27230a708f8fSGustavo F. Padovan struct sock *sk; 27240a708f8fSGustavo F. Padovan int len; 27250a708f8fSGustavo F. Padovan 27260a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 27270a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags); 27280a708f8fSGustavo F. Padovan 27290a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); 27300a708f8fSGustavo F. Padovan 2731baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid); 273248454079SGustavo F. Padovan if (!chan) 27330a708f8fSGustavo F. Padovan return -ENOENT; 27340a708f8fSGustavo F. Padovan 273548454079SGustavo F. Padovan sk = chan->sk; 273648454079SGustavo F. Padovan 2737033b1142SDavid S. Miller if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { 2738e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_cid rej; 27390a708f8fSGustavo F. Padovan 2740e2fd318eSIlia Kolomisnky rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID); 2741e2fd318eSIlia Kolomisnky rej.scid = cpu_to_le16(chan->scid); 2742e2fd318eSIlia Kolomisnky rej.dcid = cpu_to_le16(chan->dcid); 2743e2fd318eSIlia Kolomisnky 27440a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 27450a708f8fSGustavo F. Padovan sizeof(rej), &rej); 27460a708f8fSGustavo F. Padovan goto unlock; 27470a708f8fSGustavo F. Padovan } 27480a708f8fSGustavo F. Padovan 27490a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */ 27500a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req); 27517ac28817SDan Rosenberg if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) { 27520a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 2753fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 27540a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp); 27550a708f8fSGustavo F. Padovan goto unlock; 27560a708f8fSGustavo F. Padovan } 27570a708f8fSGustavo F. Padovan 27580a708f8fSGustavo F. Padovan /* Store config. */ 275973ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len); 276073ffa904SGustavo F. Padovan chan->conf_len += len; 27610a708f8fSGustavo F. Padovan 27620a708f8fSGustavo F. Padovan if (flags & 0x0001) { 27630a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */ 27640a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 2765fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 27660a708f8fSGustavo F. Padovan L2CAP_CONF_SUCCESS, 0x0001), rsp); 27670a708f8fSGustavo F. Padovan goto unlock; 27680a708f8fSGustavo F. Padovan } 27690a708f8fSGustavo F. Padovan 27700a708f8fSGustavo F. Padovan /* Complete config. */ 277173ffa904SGustavo F. Padovan len = l2cap_parse_conf_req(chan, rsp); 27720a708f8fSGustavo F. Padovan if (len < 0) { 2773e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 27740a708f8fSGustavo F. Padovan goto unlock; 27750a708f8fSGustavo F. Padovan } 27760a708f8fSGustavo F. Padovan 27770a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); 277873ffa904SGustavo F. Padovan chan->num_conf_rsp++; 27790a708f8fSGustavo F. Padovan 27800a708f8fSGustavo F. Padovan /* Reset config buffer. */ 278173ffa904SGustavo F. Padovan chan->conf_len = 0; 27820a708f8fSGustavo F. Padovan 2783c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) 27840a708f8fSGustavo F. Padovan goto unlock; 27850a708f8fSGustavo F. Padovan 2786c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 278747d1ec61SGustavo F. Padovan set_default_fcs(chan); 27880a708f8fSGustavo F. Padovan 278989bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECTED); 27900a708f8fSGustavo F. Padovan 279142e5c802SGustavo F. Padovan chan->next_tx_seq = 0; 279242e5c802SGustavo F. Padovan chan->expected_tx_seq = 0; 279358d35f87SGustavo F. Padovan skb_queue_head_init(&chan->tx_q); 27940c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_ERTM) 2795525cd185SGustavo F. Padovan l2cap_ertm_init(chan); 27960a708f8fSGustavo F. Padovan 27970a708f8fSGustavo F. Padovan l2cap_chan_ready(sk); 27980a708f8fSGustavo F. Padovan goto unlock; 27990a708f8fSGustavo F. Padovan } 28000a708f8fSGustavo F. Padovan 2801c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { 28020a708f8fSGustavo F. Padovan u8 buf[64]; 28030a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 280473ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 280573ffa904SGustavo F. Padovan chan->num_conf_req++; 28060a708f8fSGustavo F. Padovan } 28070a708f8fSGustavo F. Padovan 28080e8b207eSAndrei Emeltchenko /* Got Conf Rsp PENDING from remote side and asume we sent 28090e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */ 28100e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && 28110e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 28120e8b207eSAndrei Emeltchenko 28130e8b207eSAndrei Emeltchenko /* check compatibility */ 28140e8b207eSAndrei Emeltchenko 28150e8b207eSAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 28160e8b207eSAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 28170e8b207eSAndrei Emeltchenko 28180e8b207eSAndrei Emeltchenko l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 28190e8b207eSAndrei Emeltchenko l2cap_build_conf_rsp(chan, rsp, 28200e8b207eSAndrei Emeltchenko L2CAP_CONF_SUCCESS, 0x0000), rsp); 28210e8b207eSAndrei Emeltchenko } 28220e8b207eSAndrei Emeltchenko 28230a708f8fSGustavo F. Padovan unlock: 28240a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 28250a708f8fSGustavo F. Padovan return 0; 28260a708f8fSGustavo F. Padovan } 28270a708f8fSGustavo F. Padovan 28280a708f8fSGustavo F. Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 28290a708f8fSGustavo F. Padovan { 28300a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; 28310a708f8fSGustavo F. Padovan u16 scid, flags, result; 283248454079SGustavo F. Padovan struct l2cap_chan *chan; 28330a708f8fSGustavo F. Padovan struct sock *sk; 28340a708f8fSGustavo F. Padovan int len = cmd->len - sizeof(*rsp); 28350a708f8fSGustavo F. Padovan 28360a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 28370a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags); 28380a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 28390a708f8fSGustavo F. Padovan 28400a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x", 28410a708f8fSGustavo F. Padovan scid, flags, result); 28420a708f8fSGustavo F. Padovan 2843baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 284448454079SGustavo F. Padovan if (!chan) 28450a708f8fSGustavo F. Padovan return 0; 28460a708f8fSGustavo F. Padovan 284748454079SGustavo F. Padovan sk = chan->sk; 284848454079SGustavo F. Padovan 28490a708f8fSGustavo F. Padovan switch (result) { 28500a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS: 285147d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len); 28520e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state); 28530a708f8fSGustavo F. Padovan break; 28540a708f8fSGustavo F. Padovan 28550e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING: 28560e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state); 28570e8b207eSAndrei Emeltchenko 28580e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 28590e8b207eSAndrei Emeltchenko char buf[64]; 28600e8b207eSAndrei Emeltchenko 28610e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len, 28620e8b207eSAndrei Emeltchenko buf, &result); 28630e8b207eSAndrei Emeltchenko if (len < 0) { 28640e8b207eSAndrei Emeltchenko l2cap_send_disconn_req(conn, chan, ECONNRESET); 28650e8b207eSAndrei Emeltchenko goto done; 28660e8b207eSAndrei Emeltchenko } 28670e8b207eSAndrei Emeltchenko 28680e8b207eSAndrei Emeltchenko /* check compatibility */ 28690e8b207eSAndrei Emeltchenko 28700e8b207eSAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 28710e8b207eSAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 28720e8b207eSAndrei Emeltchenko 28730e8b207eSAndrei Emeltchenko l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 28740e8b207eSAndrei Emeltchenko l2cap_build_conf_rsp(chan, buf, 28750e8b207eSAndrei Emeltchenko L2CAP_CONF_SUCCESS, 0x0000), buf); 28760e8b207eSAndrei Emeltchenko } 28770e8b207eSAndrei Emeltchenko goto done; 28780e8b207eSAndrei Emeltchenko 28790a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT: 288073ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { 28810a708f8fSGustavo F. Padovan char req[64]; 28820a708f8fSGustavo F. Padovan 28830a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { 2884e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 28850a708f8fSGustavo F. Padovan goto done; 28860a708f8fSGustavo F. Padovan } 28870a708f8fSGustavo F. Padovan 28880a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */ 28890a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS; 2890b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len, 2891b4450035SGustavo F. Padovan req, &result); 28920a708f8fSGustavo F. Padovan if (len < 0) { 2893e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 28940a708f8fSGustavo F. Padovan goto done; 28950a708f8fSGustavo F. Padovan } 28960a708f8fSGustavo F. Padovan 28970a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 28980a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req); 289973ffa904SGustavo F. Padovan chan->num_conf_req++; 29000a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS) 29010a708f8fSGustavo F. Padovan goto done; 29020a708f8fSGustavo F. Padovan break; 29030a708f8fSGustavo F. Padovan } 29040a708f8fSGustavo F. Padovan 29050a708f8fSGustavo F. Padovan default: 29060a708f8fSGustavo F. Padovan sk->sk_err = ECONNRESET; 2907c9b66675SGustavo F. Padovan __set_chan_timer(chan, HZ * 5); 2908e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 29090a708f8fSGustavo F. Padovan goto done; 29100a708f8fSGustavo F. Padovan } 29110a708f8fSGustavo F. Padovan 29120a708f8fSGustavo F. Padovan if (flags & 0x01) 29130a708f8fSGustavo F. Padovan goto done; 29140a708f8fSGustavo F. Padovan 2915c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state); 29160a708f8fSGustavo F. Padovan 2917c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { 291847d1ec61SGustavo F. Padovan set_default_fcs(chan); 29190a708f8fSGustavo F. Padovan 292089bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECTED); 292142e5c802SGustavo F. Padovan chan->next_tx_seq = 0; 292242e5c802SGustavo F. Padovan chan->expected_tx_seq = 0; 292358d35f87SGustavo F. Padovan skb_queue_head_init(&chan->tx_q); 29240c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_ERTM) 2925525cd185SGustavo F. Padovan l2cap_ertm_init(chan); 29260a708f8fSGustavo F. Padovan 29270a708f8fSGustavo F. Padovan l2cap_chan_ready(sk); 29280a708f8fSGustavo F. Padovan } 29290a708f8fSGustavo F. Padovan 29300a708f8fSGustavo F. Padovan done: 29310a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 29320a708f8fSGustavo F. Padovan return 0; 29330a708f8fSGustavo F. Padovan } 29340a708f8fSGustavo F. Padovan 29350a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 29360a708f8fSGustavo F. Padovan { 29370a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; 29380a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp; 29390a708f8fSGustavo F. Padovan u16 dcid, scid; 294048454079SGustavo F. Padovan struct l2cap_chan *chan; 29410a708f8fSGustavo F. Padovan struct sock *sk; 29420a708f8fSGustavo F. Padovan 29430a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid); 29440a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 29450a708f8fSGustavo F. Padovan 29460a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); 29470a708f8fSGustavo F. Padovan 2948baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid); 294948454079SGustavo F. Padovan if (!chan) 29500a708f8fSGustavo F. Padovan return 0; 29510a708f8fSGustavo F. Padovan 295248454079SGustavo F. Padovan sk = chan->sk; 295348454079SGustavo F. Padovan 2954fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 2955fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 29560a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); 29570a708f8fSGustavo F. Padovan 29580a708f8fSGustavo F. Padovan sk->sk_shutdown = SHUTDOWN_MASK; 29590a708f8fSGustavo F. Padovan 29600a708f8fSGustavo F. Padovan /* don't delete l2cap channel if sk is owned by user */ 29610a708f8fSGustavo F. Padovan if (sock_owned_by_user(sk)) { 296289bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_DISCONN); 2963c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 2964c9b66675SGustavo F. Padovan __set_chan_timer(chan, HZ / 5); 29650a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 29660a708f8fSGustavo F. Padovan return 0; 29670a708f8fSGustavo F. Padovan } 29680a708f8fSGustavo F. Padovan 296948454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET); 29700a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 29710a708f8fSGustavo F. Padovan 2972ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 29730a708f8fSGustavo F. Padovan return 0; 29740a708f8fSGustavo F. Padovan } 29750a708f8fSGustavo F. Padovan 29760a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 29770a708f8fSGustavo F. Padovan { 29780a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; 29790a708f8fSGustavo F. Padovan u16 dcid, scid; 298048454079SGustavo F. Padovan struct l2cap_chan *chan; 29810a708f8fSGustavo F. Padovan struct sock *sk; 29820a708f8fSGustavo F. Padovan 29830a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 29840a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 29850a708f8fSGustavo F. Padovan 29860a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); 29870a708f8fSGustavo F. Padovan 2988baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 298948454079SGustavo F. Padovan if (!chan) 29900a708f8fSGustavo F. Padovan return 0; 29910a708f8fSGustavo F. Padovan 299248454079SGustavo F. Padovan sk = chan->sk; 299348454079SGustavo F. Padovan 29940a708f8fSGustavo F. Padovan /* don't delete l2cap channel if sk is owned by user */ 29950a708f8fSGustavo F. Padovan if (sock_owned_by_user(sk)) { 299689bc500eSGustavo F. Padovan l2cap_state_change(chan,BT_DISCONN); 2997c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 2998c9b66675SGustavo F. Padovan __set_chan_timer(chan, HZ / 5); 29990a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 30000a708f8fSGustavo F. Padovan return 0; 30010a708f8fSGustavo F. Padovan } 30020a708f8fSGustavo F. Padovan 300348454079SGustavo F. Padovan l2cap_chan_del(chan, 0); 30040a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 30050a708f8fSGustavo F. Padovan 3006ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 30070a708f8fSGustavo F. Padovan return 0; 30080a708f8fSGustavo F. Padovan } 30090a708f8fSGustavo F. Padovan 30100a708f8fSGustavo F. Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 30110a708f8fSGustavo F. Padovan { 30120a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data; 30130a708f8fSGustavo F. Padovan u16 type; 30140a708f8fSGustavo F. Padovan 30150a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type); 30160a708f8fSGustavo F. Padovan 30170a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type); 30180a708f8fSGustavo F. Padovan 30190a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) { 30200a708f8fSGustavo F. Padovan u8 buf[8]; 30210a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask; 30220a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 30230a708f8fSGustavo F. Padovan rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 30240a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 30250a708f8fSGustavo F. Padovan if (!disable_ertm) 30260a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING 30270a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS; 3028a5fd6f30SAndrei Emeltchenko if (enable_hs) 30296327eb98SAndrei Emeltchenko feat_mask |= L2CAP_FEAT_EXT_FLOW 30306327eb98SAndrei Emeltchenko | L2CAP_FEAT_EXT_WINDOW; 3031a5fd6f30SAndrei Emeltchenko 30320a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data); 30330a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 30340a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(buf), buf); 30350a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) { 30360a708f8fSGustavo F. Padovan u8 buf[12]; 30370a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 30380a708f8fSGustavo F. Padovan rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 30390a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 3040c6337ea6SAndrei Emeltchenko memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); 30410a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 30420a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(buf), buf); 30430a708f8fSGustavo F. Padovan } else { 30440a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp; 30450a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type); 30460a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP); 30470a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 30480a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(rsp), &rsp); 30490a708f8fSGustavo F. Padovan } 30500a708f8fSGustavo F. Padovan 30510a708f8fSGustavo F. Padovan return 0; 30520a708f8fSGustavo F. Padovan } 30530a708f8fSGustavo F. Padovan 30540a708f8fSGustavo F. Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 30550a708f8fSGustavo F. Padovan { 30560a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; 30570a708f8fSGustavo F. Padovan u16 type, result; 30580a708f8fSGustavo F. Padovan 30590a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type); 30600a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 30610a708f8fSGustavo F. Padovan 30620a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); 30630a708f8fSGustavo F. Padovan 3064e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */ 3065e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident || 3066e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 3067e90165beSAndrei Emeltchenko return 0; 3068e90165beSAndrei Emeltchenko 30690a708f8fSGustavo F. Padovan del_timer(&conn->info_timer); 30700a708f8fSGustavo F. Padovan 30710a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) { 30720a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 30730a708f8fSGustavo F. Padovan conn->info_ident = 0; 30740a708f8fSGustavo F. Padovan 30750a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 30760a708f8fSGustavo F. Padovan 30770a708f8fSGustavo F. Padovan return 0; 30780a708f8fSGustavo F. Padovan } 30790a708f8fSGustavo F. Padovan 30800a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) { 30810a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data); 30820a708f8fSGustavo F. Padovan 30830a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { 30840a708f8fSGustavo F. Padovan struct l2cap_info_req req; 30850a708f8fSGustavo F. Padovan req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 30860a708f8fSGustavo F. Padovan 30870a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 30880a708f8fSGustavo F. Padovan 30890a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 30900a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 30910a708f8fSGustavo F. Padovan } else { 30920a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 30930a708f8fSGustavo F. Padovan conn->info_ident = 0; 30940a708f8fSGustavo F. Padovan 30950a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 30960a708f8fSGustavo F. Padovan } 30970a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) { 30980a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 30990a708f8fSGustavo F. Padovan conn->info_ident = 0; 31000a708f8fSGustavo F. Padovan 31010a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 31020a708f8fSGustavo F. Padovan } 31030a708f8fSGustavo F. Padovan 31040a708f8fSGustavo F. Padovan return 0; 31050a708f8fSGustavo F. Padovan } 31060a708f8fSGustavo F. Padovan 3107e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency, 3108de73115aSClaudio Takahasi u16 to_multiplier) 3109de73115aSClaudio Takahasi { 3110de73115aSClaudio Takahasi u16 max_latency; 3111de73115aSClaudio Takahasi 3112de73115aSClaudio Takahasi if (min > max || min < 6 || max > 3200) 3113de73115aSClaudio Takahasi return -EINVAL; 3114de73115aSClaudio Takahasi 3115de73115aSClaudio Takahasi if (to_multiplier < 10 || to_multiplier > 3200) 3116de73115aSClaudio Takahasi return -EINVAL; 3117de73115aSClaudio Takahasi 3118de73115aSClaudio Takahasi if (max >= to_multiplier * 8) 3119de73115aSClaudio Takahasi return -EINVAL; 3120de73115aSClaudio Takahasi 3121de73115aSClaudio Takahasi max_latency = (to_multiplier * 8 / max) - 1; 3122de73115aSClaudio Takahasi if (latency > 499 || latency > max_latency) 3123de73115aSClaudio Takahasi return -EINVAL; 3124de73115aSClaudio Takahasi 3125de73115aSClaudio Takahasi return 0; 3126de73115aSClaudio Takahasi } 3127de73115aSClaudio Takahasi 3128de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, 3129de73115aSClaudio Takahasi struct l2cap_cmd_hdr *cmd, u8 *data) 3130de73115aSClaudio Takahasi { 3131de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon; 3132de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req; 3133de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp; 3134de73115aSClaudio Takahasi u16 min, max, latency, to_multiplier, cmd_len; 31352ce603ebSClaudio Takahasi int err; 3136de73115aSClaudio Takahasi 3137de73115aSClaudio Takahasi if (!(hcon->link_mode & HCI_LM_MASTER)) 3138de73115aSClaudio Takahasi return -EINVAL; 3139de73115aSClaudio Takahasi 3140de73115aSClaudio Takahasi cmd_len = __le16_to_cpu(cmd->len); 3141de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) 3142de73115aSClaudio Takahasi return -EPROTO; 3143de73115aSClaudio Takahasi 3144de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data; 3145de73115aSClaudio Takahasi min = __le16_to_cpu(req->min); 3146de73115aSClaudio Takahasi max = __le16_to_cpu(req->max); 3147de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency); 3148de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier); 3149de73115aSClaudio Takahasi 3150de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", 3151de73115aSClaudio Takahasi min, max, latency, to_multiplier); 3152de73115aSClaudio Takahasi 3153de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp)); 31542ce603ebSClaudio Takahasi 31552ce603ebSClaudio Takahasi err = l2cap_check_conn_param(min, max, latency, to_multiplier); 31562ce603ebSClaudio Takahasi if (err) 3157de73115aSClaudio Takahasi rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); 3158de73115aSClaudio Takahasi else 3159de73115aSClaudio Takahasi rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); 3160de73115aSClaudio Takahasi 3161de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, 3162de73115aSClaudio Takahasi sizeof(rsp), &rsp); 3163de73115aSClaudio Takahasi 31642ce603ebSClaudio Takahasi if (!err) 31652ce603ebSClaudio Takahasi hci_le_conn_update(hcon, min, max, latency, to_multiplier); 31662ce603ebSClaudio Takahasi 3167de73115aSClaudio Takahasi return 0; 3168de73115aSClaudio Takahasi } 3169de73115aSClaudio Takahasi 31703300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, 31713300d9a9SClaudio Takahasi struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 31723300d9a9SClaudio Takahasi { 31733300d9a9SClaudio Takahasi int err = 0; 31743300d9a9SClaudio Takahasi 31753300d9a9SClaudio Takahasi switch (cmd->code) { 31763300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 31773300d9a9SClaudio Takahasi l2cap_command_rej(conn, cmd, data); 31783300d9a9SClaudio Takahasi break; 31793300d9a9SClaudio Takahasi 31803300d9a9SClaudio Takahasi case L2CAP_CONN_REQ: 31813300d9a9SClaudio Takahasi err = l2cap_connect_req(conn, cmd, data); 31823300d9a9SClaudio Takahasi break; 31833300d9a9SClaudio Takahasi 31843300d9a9SClaudio Takahasi case L2CAP_CONN_RSP: 31853300d9a9SClaudio Takahasi err = l2cap_connect_rsp(conn, cmd, data); 31863300d9a9SClaudio Takahasi break; 31873300d9a9SClaudio Takahasi 31883300d9a9SClaudio Takahasi case L2CAP_CONF_REQ: 31893300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data); 31903300d9a9SClaudio Takahasi break; 31913300d9a9SClaudio Takahasi 31923300d9a9SClaudio Takahasi case L2CAP_CONF_RSP: 31933300d9a9SClaudio Takahasi err = l2cap_config_rsp(conn, cmd, data); 31943300d9a9SClaudio Takahasi break; 31953300d9a9SClaudio Takahasi 31963300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ: 31973300d9a9SClaudio Takahasi err = l2cap_disconnect_req(conn, cmd, data); 31983300d9a9SClaudio Takahasi break; 31993300d9a9SClaudio Takahasi 32003300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP: 32013300d9a9SClaudio Takahasi err = l2cap_disconnect_rsp(conn, cmd, data); 32023300d9a9SClaudio Takahasi break; 32033300d9a9SClaudio Takahasi 32043300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ: 32053300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data); 32063300d9a9SClaudio Takahasi break; 32073300d9a9SClaudio Takahasi 32083300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP: 32093300d9a9SClaudio Takahasi break; 32103300d9a9SClaudio Takahasi 32113300d9a9SClaudio Takahasi case L2CAP_INFO_REQ: 32123300d9a9SClaudio Takahasi err = l2cap_information_req(conn, cmd, data); 32133300d9a9SClaudio Takahasi break; 32143300d9a9SClaudio Takahasi 32153300d9a9SClaudio Takahasi case L2CAP_INFO_RSP: 32163300d9a9SClaudio Takahasi err = l2cap_information_rsp(conn, cmd, data); 32173300d9a9SClaudio Takahasi break; 32183300d9a9SClaudio Takahasi 32193300d9a9SClaudio Takahasi default: 32203300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code); 32213300d9a9SClaudio Takahasi err = -EINVAL; 32223300d9a9SClaudio Takahasi break; 32233300d9a9SClaudio Takahasi } 32243300d9a9SClaudio Takahasi 32253300d9a9SClaudio Takahasi return err; 32263300d9a9SClaudio Takahasi } 32273300d9a9SClaudio Takahasi 32283300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, 32293300d9a9SClaudio Takahasi struct l2cap_cmd_hdr *cmd, u8 *data) 32303300d9a9SClaudio Takahasi { 32313300d9a9SClaudio Takahasi switch (cmd->code) { 32323300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 32333300d9a9SClaudio Takahasi return 0; 32343300d9a9SClaudio Takahasi 32353300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ: 3236de73115aSClaudio Takahasi return l2cap_conn_param_update_req(conn, cmd, data); 32373300d9a9SClaudio Takahasi 32383300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP: 32393300d9a9SClaudio Takahasi return 0; 32403300d9a9SClaudio Takahasi 32413300d9a9SClaudio Takahasi default: 32423300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code); 32433300d9a9SClaudio Takahasi return -EINVAL; 32443300d9a9SClaudio Takahasi } 32453300d9a9SClaudio Takahasi } 32463300d9a9SClaudio Takahasi 32473300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn, 32483300d9a9SClaudio Takahasi struct sk_buff *skb) 32490a708f8fSGustavo F. Padovan { 32500a708f8fSGustavo F. Padovan u8 *data = skb->data; 32510a708f8fSGustavo F. Padovan int len = skb->len; 32520a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr cmd; 32533300d9a9SClaudio Takahasi int err; 32540a708f8fSGustavo F. Padovan 32550a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb); 32560a708f8fSGustavo F. Padovan 32570a708f8fSGustavo F. Padovan while (len >= L2CAP_CMD_HDR_SIZE) { 32580a708f8fSGustavo F. Padovan u16 cmd_len; 32590a708f8fSGustavo F. Padovan memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); 32600a708f8fSGustavo F. Padovan data += L2CAP_CMD_HDR_SIZE; 32610a708f8fSGustavo F. Padovan len -= L2CAP_CMD_HDR_SIZE; 32620a708f8fSGustavo F. Padovan 32630a708f8fSGustavo F. Padovan cmd_len = le16_to_cpu(cmd.len); 32640a708f8fSGustavo F. Padovan 32650a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident); 32660a708f8fSGustavo F. Padovan 32670a708f8fSGustavo F. Padovan if (cmd_len > len || !cmd.ident) { 32680a708f8fSGustavo F. Padovan BT_DBG("corrupted command"); 32690a708f8fSGustavo F. Padovan break; 32700a708f8fSGustavo F. Padovan } 32710a708f8fSGustavo F. Padovan 32723300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 32733300d9a9SClaudio Takahasi err = l2cap_le_sig_cmd(conn, &cmd, data); 32743300d9a9SClaudio Takahasi else 32753300d9a9SClaudio Takahasi err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data); 32760a708f8fSGustavo F. Padovan 32770a708f8fSGustavo F. Padovan if (err) { 3278e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk rej; 32792c6d1a2eSGustavo F. Padovan 32802c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err); 32810a708f8fSGustavo F. Padovan 32820a708f8fSGustavo F. Padovan /* FIXME: Map err to a valid reason */ 3283e2fd318eSIlia Kolomisnky rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 32840a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); 32850a708f8fSGustavo F. Padovan } 32860a708f8fSGustavo F. Padovan 32870a708f8fSGustavo F. Padovan data += cmd_len; 32880a708f8fSGustavo F. Padovan len -= cmd_len; 32890a708f8fSGustavo F. Padovan } 32900a708f8fSGustavo F. Padovan 32910a708f8fSGustavo F. Padovan kfree_skb(skb); 32920a708f8fSGustavo F. Padovan } 32930a708f8fSGustavo F. Padovan 329447d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) 32950a708f8fSGustavo F. Padovan { 32960a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs; 3297e4ca6d98SAndrei Emeltchenko int hdr_size; 3298e4ca6d98SAndrei Emeltchenko 3299e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 3300e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE; 3301e4ca6d98SAndrei Emeltchenko else 3302e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE; 33030a708f8fSGustavo F. Padovan 330447d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 330503a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE); 33060a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len); 33070a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); 33080a708f8fSGustavo F. Padovan 33090a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs) 33100a708f8fSGustavo F. Padovan return -EBADMSG; 33110a708f8fSGustavo F. Padovan } 33120a708f8fSGustavo F. Padovan return 0; 33130a708f8fSGustavo F. Padovan } 33140a708f8fSGustavo F. Padovan 3315525cd185SGustavo F. Padovan static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) 33160a708f8fSGustavo F. Padovan { 331788843ab0SAndrei Emeltchenko u32 control = 0; 33180a708f8fSGustavo F. Padovan 33196a026610SGustavo F. Padovan chan->frames_sent = 0; 33200a708f8fSGustavo F. Padovan 33210b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 33220a708f8fSGustavo F. Padovan 3323e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 3324ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); 3325525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 3326e2ab4353SGustavo F. Padovan set_bit(CONN_RNR_SENT, &chan->conn_state); 33270a708f8fSGustavo F. Padovan } 33280a708f8fSGustavo F. Padovan 3329e2ab4353SGustavo F. Padovan if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 3330525cd185SGustavo F. Padovan l2cap_retransmit_frames(chan); 33310a708f8fSGustavo F. Padovan 3332525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 33330a708f8fSGustavo F. Padovan 3334e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 33356a026610SGustavo F. Padovan chan->frames_sent == 0) { 3336ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 3337525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 33380a708f8fSGustavo F. Padovan } 33390a708f8fSGustavo F. Padovan } 33400a708f8fSGustavo F. Padovan 3341fb45de7dSAndrei Emeltchenko static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u16 tx_seq, u8 sar) 33420a708f8fSGustavo F. Padovan { 33430a708f8fSGustavo F. Padovan struct sk_buff *next_skb; 33440a708f8fSGustavo F. Padovan int tx_seq_offset, next_tx_seq_offset; 33450a708f8fSGustavo F. Padovan 33460a708f8fSGustavo F. Padovan bt_cb(skb)->tx_seq = tx_seq; 33470a708f8fSGustavo F. Padovan bt_cb(skb)->sar = sar; 33480a708f8fSGustavo F. Padovan 3349f1c6775bSGustavo F. Padovan next_skb = skb_peek(&chan->srej_q); 33500a708f8fSGustavo F. Padovan if (!next_skb) { 3351f1c6775bSGustavo F. Padovan __skb_queue_tail(&chan->srej_q, skb); 33520a708f8fSGustavo F. Padovan return 0; 33530a708f8fSGustavo F. Padovan } 33540a708f8fSGustavo F. Padovan 3355836be934SAndrei Emeltchenko tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq); 33560a708f8fSGustavo F. Padovan 33570a708f8fSGustavo F. Padovan do { 33580a708f8fSGustavo F. Padovan if (bt_cb(next_skb)->tx_seq == tx_seq) 33590a708f8fSGustavo F. Padovan return -EINVAL; 33600a708f8fSGustavo F. Padovan 3361836be934SAndrei Emeltchenko next_tx_seq_offset = __seq_offset(chan, 3362836be934SAndrei Emeltchenko bt_cb(next_skb)->tx_seq, chan->buffer_seq); 33630a708f8fSGustavo F. Padovan 33640a708f8fSGustavo F. Padovan if (next_tx_seq_offset > tx_seq_offset) { 3365f1c6775bSGustavo F. Padovan __skb_queue_before(&chan->srej_q, next_skb, skb); 33660a708f8fSGustavo F. Padovan return 0; 33670a708f8fSGustavo F. Padovan } 33680a708f8fSGustavo F. Padovan 3369f1c6775bSGustavo F. Padovan if (skb_queue_is_last(&chan->srej_q, next_skb)) 33700a708f8fSGustavo F. Padovan break; 33710a708f8fSGustavo F. Padovan 3372f1c6775bSGustavo F. Padovan } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb))); 33730a708f8fSGustavo F. Padovan 3374f1c6775bSGustavo F. Padovan __skb_queue_tail(&chan->srej_q, skb); 33750a708f8fSGustavo F. Padovan 33760a708f8fSGustavo F. Padovan return 0; 33770a708f8fSGustavo F. Padovan } 33780a708f8fSGustavo F. Padovan 337984084a31SMat Martineau static void append_skb_frag(struct sk_buff *skb, 338084084a31SMat Martineau struct sk_buff *new_frag, struct sk_buff **last_frag) 33810a708f8fSGustavo F. Padovan { 338284084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments 338384084a31SMat Martineau * skb->data_len reflects only data in fragments 338484084a31SMat Martineau */ 338584084a31SMat Martineau if (!skb_has_frag_list(skb)) 338684084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag; 338784084a31SMat Martineau 338884084a31SMat Martineau new_frag->next = NULL; 338984084a31SMat Martineau 339084084a31SMat Martineau (*last_frag)->next = new_frag; 339184084a31SMat Martineau *last_frag = new_frag; 339284084a31SMat Martineau 339384084a31SMat Martineau skb->len += new_frag->len; 339484084a31SMat Martineau skb->data_len += new_frag->len; 339584084a31SMat Martineau skb->truesize += new_frag->truesize; 339684084a31SMat Martineau } 339784084a31SMat Martineau 339888843ab0SAndrei Emeltchenko static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control) 339984084a31SMat Martineau { 340084084a31SMat Martineau int err = -EINVAL; 34010a708f8fSGustavo F. Padovan 34027e0ef6eeSAndrei Emeltchenko switch (__get_ctrl_sar(chan, control)) { 34037e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED: 340484084a31SMat Martineau if (chan->sdu) 340584084a31SMat Martineau break; 34060a708f8fSGustavo F. Padovan 340784084a31SMat Martineau err = chan->ops->recv(chan->data, skb); 340884084a31SMat Martineau break; 34090a708f8fSGustavo F. Padovan 34107e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START: 341184084a31SMat Martineau if (chan->sdu) 341284084a31SMat Martineau break; 34130a708f8fSGustavo F. Padovan 34146f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data); 341503a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE); 34160a708f8fSGustavo F. Padovan 341784084a31SMat Martineau if (chan->sdu_len > chan->imtu) { 341884084a31SMat Martineau err = -EMSGSIZE; 341984084a31SMat Martineau break; 342084084a31SMat Martineau } 34210a708f8fSGustavo F. Padovan 342284084a31SMat Martineau if (skb->len >= chan->sdu_len) 342384084a31SMat Martineau break; 342484084a31SMat Martineau 342584084a31SMat Martineau chan->sdu = skb; 342684084a31SMat Martineau chan->sdu_last_frag = skb; 342784084a31SMat Martineau 342884084a31SMat Martineau skb = NULL; 342984084a31SMat Martineau err = 0; 34300a708f8fSGustavo F. Padovan break; 34310a708f8fSGustavo F. Padovan 34327e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE: 34336f61fd47SGustavo F. Padovan if (!chan->sdu) 343484084a31SMat Martineau break; 34350a708f8fSGustavo F. Padovan 343684084a31SMat Martineau append_skb_frag(chan->sdu, skb, 343784084a31SMat Martineau &chan->sdu_last_frag); 343884084a31SMat Martineau skb = NULL; 34390a708f8fSGustavo F. Padovan 344084084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len) 344184084a31SMat Martineau break; 34420a708f8fSGustavo F. Padovan 344384084a31SMat Martineau err = 0; 34440a708f8fSGustavo F. Padovan break; 34450a708f8fSGustavo F. Padovan 34467e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END: 34476f61fd47SGustavo F. Padovan if (!chan->sdu) 344884084a31SMat Martineau break; 34490a708f8fSGustavo F. Padovan 345084084a31SMat Martineau append_skb_frag(chan->sdu, skb, 345184084a31SMat Martineau &chan->sdu_last_frag); 345284084a31SMat Martineau skb = NULL; 34530a708f8fSGustavo F. Padovan 345484084a31SMat Martineau if (chan->sdu->len != chan->sdu_len) 345584084a31SMat Martineau break; 34560a708f8fSGustavo F. Padovan 345784084a31SMat Martineau err = chan->ops->recv(chan->data, chan->sdu); 34580a708f8fSGustavo F. Padovan 345984084a31SMat Martineau if (!err) { 346084084a31SMat Martineau /* Reassembly complete */ 346184084a31SMat Martineau chan->sdu = NULL; 346284084a31SMat Martineau chan->sdu_last_frag = NULL; 346384084a31SMat Martineau chan->sdu_len = 0; 34640a708f8fSGustavo F. Padovan } 34650a708f8fSGustavo F. Padovan break; 34660a708f8fSGustavo F. Padovan } 34670a708f8fSGustavo F. Padovan 346884084a31SMat Martineau if (err) { 34690a708f8fSGustavo F. Padovan kfree_skb(skb); 34706f61fd47SGustavo F. Padovan kfree_skb(chan->sdu); 34716f61fd47SGustavo F. Padovan chan->sdu = NULL; 347284084a31SMat Martineau chan->sdu_last_frag = NULL; 347384084a31SMat Martineau chan->sdu_len = 0; 347484084a31SMat Martineau } 34750a708f8fSGustavo F. Padovan 347684084a31SMat Martineau return err; 34770a708f8fSGustavo F. Padovan } 34780a708f8fSGustavo F. Padovan 347926f880d2SMat Martineau static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan) 34800a708f8fSGustavo F. Padovan { 348188843ab0SAndrei Emeltchenko u32 control; 34820a708f8fSGustavo F. Padovan 348326f880d2SMat Martineau BT_DBG("chan %p, Enter local busy", chan); 348426f880d2SMat Martineau 348526f880d2SMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 348626f880d2SMat Martineau 34870b209faeSAndrei Emeltchenko control = __set_reqseq(chan, chan->buffer_seq); 3488ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); 348926f880d2SMat Martineau l2cap_send_sframe(chan, control); 349026f880d2SMat Martineau 349126f880d2SMat Martineau set_bit(CONN_RNR_SENT, &chan->conn_state); 349226f880d2SMat Martineau 349326f880d2SMat Martineau __clear_ack_timer(chan); 34940a708f8fSGustavo F. Padovan } 34950a708f8fSGustavo F. Padovan 349626f880d2SMat Martineau static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan) 349726f880d2SMat Martineau { 349888843ab0SAndrei Emeltchenko u32 control; 34990a708f8fSGustavo F. Padovan 3500e2ab4353SGustavo F. Padovan if (!test_bit(CONN_RNR_SENT, &chan->conn_state)) 35010a708f8fSGustavo F. Padovan goto done; 35020a708f8fSGustavo F. Padovan 35030b209faeSAndrei Emeltchenko control = __set_reqseq(chan, chan->buffer_seq); 3504e3781735SAndrei Emeltchenko control |= __set_ctrl_poll(chan); 3505ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 3506525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 35076a026610SGustavo F. Padovan chan->retry_count = 1; 35080a708f8fSGustavo F. Padovan 35091a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 35101a09bcb9SGustavo F. Padovan __set_monitor_timer(chan); 35110a708f8fSGustavo F. Padovan 3512e2ab4353SGustavo F. Padovan set_bit(CONN_WAIT_F, &chan->conn_state); 35130a708f8fSGustavo F. Padovan 35140a708f8fSGustavo F. Padovan done: 3515e2ab4353SGustavo F. Padovan clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 3516e2ab4353SGustavo F. Padovan clear_bit(CONN_RNR_SENT, &chan->conn_state); 35170a708f8fSGustavo F. Padovan 351849208c9cSGustavo F. Padovan BT_DBG("chan %p, Exit local busy", chan); 35190a708f8fSGustavo F. Padovan } 35200a708f8fSGustavo F. Padovan 3521e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 35220a708f8fSGustavo F. Padovan { 3523e328140fSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) { 3524e328140fSMat Martineau if (busy) 352526f880d2SMat Martineau l2cap_ertm_enter_local_busy(chan); 3526e328140fSMat Martineau else 3527e328140fSMat Martineau l2cap_ertm_exit_local_busy(chan); 35280a708f8fSGustavo F. Padovan } 35290a708f8fSGustavo F. Padovan } 35300a708f8fSGustavo F. Padovan 3531fb45de7dSAndrei Emeltchenko static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq) 35320a708f8fSGustavo F. Padovan { 35330a708f8fSGustavo F. Padovan struct sk_buff *skb; 353488843ab0SAndrei Emeltchenko u32 control; 35350a708f8fSGustavo F. Padovan 3536e328140fSMat Martineau while ((skb = skb_peek(&chan->srej_q)) && 3537e328140fSMat Martineau !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 3538e328140fSMat Martineau int err; 3539e328140fSMat Martineau 35400a708f8fSGustavo F. Padovan if (bt_cb(skb)->tx_seq != tx_seq) 35410a708f8fSGustavo F. Padovan break; 35420a708f8fSGustavo F. Padovan 3543f1c6775bSGustavo F. Padovan skb = skb_dequeue(&chan->srej_q); 35447e0ef6eeSAndrei Emeltchenko control = __set_ctrl_sar(chan, bt_cb(skb)->sar); 354584084a31SMat Martineau err = l2cap_reassemble_sdu(chan, skb, control); 3546e328140fSMat Martineau 3547e328140fSMat Martineau if (err < 0) { 3548e328140fSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 3549e328140fSMat Martineau break; 3550e328140fSMat Martineau } 3551e328140fSMat Martineau 3552836be934SAndrei Emeltchenko chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej); 3553836be934SAndrei Emeltchenko tx_seq = __next_seq(chan, tx_seq); 35540a708f8fSGustavo F. Padovan } 35550a708f8fSGustavo F. Padovan } 35560a708f8fSGustavo F. Padovan 3557fb45de7dSAndrei Emeltchenko static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq) 35580a708f8fSGustavo F. Padovan { 35590a708f8fSGustavo F. Padovan struct srej_list *l, *tmp; 356088843ab0SAndrei Emeltchenko u32 control; 35610a708f8fSGustavo F. Padovan 356239d5a3eeSGustavo F. Padovan list_for_each_entry_safe(l, tmp, &chan->srej_l, list) { 35630a708f8fSGustavo F. Padovan if (l->tx_seq == tx_seq) { 35640a708f8fSGustavo F. Padovan list_del(&l->list); 35650a708f8fSGustavo F. Padovan kfree(l); 35660a708f8fSGustavo F. Padovan return; 35670a708f8fSGustavo F. Padovan } 3568ab784b73SAndrei Emeltchenko control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ); 35690b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, l->tx_seq); 3570525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 35710a708f8fSGustavo F. Padovan list_del(&l->list); 357239d5a3eeSGustavo F. Padovan list_add_tail(&l->list, &chan->srej_l); 35730a708f8fSGustavo F. Padovan } 35740a708f8fSGustavo F. Padovan } 35750a708f8fSGustavo F. Padovan 3576fb45de7dSAndrei Emeltchenko static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq) 35770a708f8fSGustavo F. Padovan { 35780a708f8fSGustavo F. Padovan struct srej_list *new; 357988843ab0SAndrei Emeltchenko u32 control; 35800a708f8fSGustavo F. Padovan 358142e5c802SGustavo F. Padovan while (tx_seq != chan->expected_tx_seq) { 3582ab784b73SAndrei Emeltchenko control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ); 35830b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->expected_tx_seq); 3584525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 35850a708f8fSGustavo F. Padovan 35860a708f8fSGustavo F. Padovan new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); 358742e5c802SGustavo F. Padovan new->tx_seq = chan->expected_tx_seq; 3588836be934SAndrei Emeltchenko 3589836be934SAndrei Emeltchenko chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); 3590836be934SAndrei Emeltchenko 359139d5a3eeSGustavo F. Padovan list_add_tail(&new->list, &chan->srej_l); 35920a708f8fSGustavo F. Padovan } 3593836be934SAndrei Emeltchenko 3594836be934SAndrei Emeltchenko chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); 35950a708f8fSGustavo F. Padovan } 35960a708f8fSGustavo F. Padovan 359788843ab0SAndrei Emeltchenko static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb) 35980a708f8fSGustavo F. Padovan { 3599fb45de7dSAndrei Emeltchenko u16 tx_seq = __get_txseq(chan, rx_control); 36000b209faeSAndrei Emeltchenko u16 req_seq = __get_reqseq(chan, rx_control); 36017e0ef6eeSAndrei Emeltchenko u8 sar = __get_ctrl_sar(chan, rx_control); 36020a708f8fSGustavo F. Padovan int tx_seq_offset, expected_tx_seq_offset; 360347d1ec61SGustavo F. Padovan int num_to_ack = (chan->tx_win/6) + 1; 36040a708f8fSGustavo F. Padovan int err = 0; 36050a708f8fSGustavo F. Padovan 360688843ab0SAndrei Emeltchenko BT_DBG("chan %p len %d tx_seq %d rx_control 0x%8.8x", chan, skb->len, 3607525cd185SGustavo F. Padovan tx_seq, rx_control); 36080a708f8fSGustavo F. Padovan 360903f6715dSAndrei Emeltchenko if (__is_ctrl_final(chan, rx_control) && 3610e2ab4353SGustavo F. Padovan test_bit(CONN_WAIT_F, &chan->conn_state)) { 36111a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 36126a026610SGustavo F. Padovan if (chan->unacked_frames > 0) 36131a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 3614e2ab4353SGustavo F. Padovan clear_bit(CONN_WAIT_F, &chan->conn_state); 36150a708f8fSGustavo F. Padovan } 36160a708f8fSGustavo F. Padovan 361742e5c802SGustavo F. Padovan chan->expected_ack_seq = req_seq; 361842e5c802SGustavo F. Padovan l2cap_drop_acked_frames(chan); 36190a708f8fSGustavo F. Padovan 3620836be934SAndrei Emeltchenko tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq); 36210a708f8fSGustavo F. Padovan 36220a708f8fSGustavo F. Padovan /* invalid tx_seq */ 362347d1ec61SGustavo F. Padovan if (tx_seq_offset >= chan->tx_win) { 36248c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 36250a708f8fSGustavo F. Padovan goto drop; 36260a708f8fSGustavo F. Padovan } 36270a708f8fSGustavo F. Padovan 3628e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 36290a708f8fSGustavo F. Padovan goto drop; 36300a708f8fSGustavo F. Padovan 363102f1b641SMat Martineau if (tx_seq == chan->expected_tx_seq) 363202f1b641SMat Martineau goto expected; 363302f1b641SMat Martineau 3634e2ab4353SGustavo F. Padovan if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) { 36350a708f8fSGustavo F. Padovan struct srej_list *first; 36360a708f8fSGustavo F. Padovan 363739d5a3eeSGustavo F. Padovan first = list_first_entry(&chan->srej_l, 36380a708f8fSGustavo F. Padovan struct srej_list, list); 36390a708f8fSGustavo F. Padovan if (tx_seq == first->tx_seq) { 364042e5c802SGustavo F. Padovan l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); 3641525cd185SGustavo F. Padovan l2cap_check_srej_gap(chan, tx_seq); 36420a708f8fSGustavo F. Padovan 36430a708f8fSGustavo F. Padovan list_del(&first->list); 36440a708f8fSGustavo F. Padovan kfree(first); 36450a708f8fSGustavo F. Padovan 364639d5a3eeSGustavo F. Padovan if (list_empty(&chan->srej_l)) { 364742e5c802SGustavo F. Padovan chan->buffer_seq = chan->buffer_seq_srej; 3648e2ab4353SGustavo F. Padovan clear_bit(CONN_SREJ_SENT, &chan->conn_state); 3649525cd185SGustavo F. Padovan l2cap_send_ack(chan); 365049208c9cSGustavo F. Padovan BT_DBG("chan %p, Exit SREJ_SENT", chan); 36510a708f8fSGustavo F. Padovan } 36520a708f8fSGustavo F. Padovan } else { 36530a708f8fSGustavo F. Padovan struct srej_list *l; 36540a708f8fSGustavo F. Padovan 36550a708f8fSGustavo F. Padovan /* duplicated tx_seq */ 365642e5c802SGustavo F. Padovan if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0) 36570a708f8fSGustavo F. Padovan goto drop; 36580a708f8fSGustavo F. Padovan 365939d5a3eeSGustavo F. Padovan list_for_each_entry(l, &chan->srej_l, list) { 36600a708f8fSGustavo F. Padovan if (l->tx_seq == tx_seq) { 3661525cd185SGustavo F. Padovan l2cap_resend_srejframe(chan, tx_seq); 36620a708f8fSGustavo F. Padovan return 0; 36630a708f8fSGustavo F. Padovan } 36640a708f8fSGustavo F. Padovan } 3665525cd185SGustavo F. Padovan l2cap_send_srejframe(chan, tx_seq); 36660a708f8fSGustavo F. Padovan } 36670a708f8fSGustavo F. Padovan } else { 3668836be934SAndrei Emeltchenko expected_tx_seq_offset = __seq_offset(chan, 3669836be934SAndrei Emeltchenko chan->expected_tx_seq, chan->buffer_seq); 36700a708f8fSGustavo F. Padovan 36710a708f8fSGustavo F. Padovan /* duplicated tx_seq */ 36720a708f8fSGustavo F. Padovan if (tx_seq_offset < expected_tx_seq_offset) 36730a708f8fSGustavo F. Padovan goto drop; 36740a708f8fSGustavo F. Padovan 3675e2ab4353SGustavo F. Padovan set_bit(CONN_SREJ_SENT, &chan->conn_state); 36760a708f8fSGustavo F. Padovan 367749208c9cSGustavo F. Padovan BT_DBG("chan %p, Enter SREJ", chan); 36780a708f8fSGustavo F. Padovan 367939d5a3eeSGustavo F. Padovan INIT_LIST_HEAD(&chan->srej_l); 368042e5c802SGustavo F. Padovan chan->buffer_seq_srej = chan->buffer_seq; 36810a708f8fSGustavo F. Padovan 3682f1c6775bSGustavo F. Padovan __skb_queue_head_init(&chan->srej_q); 368342e5c802SGustavo F. Padovan l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); 36840a708f8fSGustavo F. Padovan 3685e2ab4353SGustavo F. Padovan set_bit(CONN_SEND_PBIT, &chan->conn_state); 36860a708f8fSGustavo F. Padovan 3687525cd185SGustavo F. Padovan l2cap_send_srejframe(chan, tx_seq); 36880a708f8fSGustavo F. Padovan 36891a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 36900a708f8fSGustavo F. Padovan } 36910a708f8fSGustavo F. Padovan return 0; 36920a708f8fSGustavo F. Padovan 36930a708f8fSGustavo F. Padovan expected: 3694836be934SAndrei Emeltchenko chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); 36950a708f8fSGustavo F. Padovan 3696e2ab4353SGustavo F. Padovan if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) { 36970a708f8fSGustavo F. Padovan bt_cb(skb)->tx_seq = tx_seq; 36980a708f8fSGustavo F. Padovan bt_cb(skb)->sar = sar; 3699f1c6775bSGustavo F. Padovan __skb_queue_tail(&chan->srej_q, skb); 37000a708f8fSGustavo F. Padovan return 0; 37010a708f8fSGustavo F. Padovan } 37020a708f8fSGustavo F. Padovan 370384084a31SMat Martineau err = l2cap_reassemble_sdu(chan, skb, rx_control); 3704836be934SAndrei Emeltchenko chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 3705836be934SAndrei Emeltchenko 3706e328140fSMat Martineau if (err < 0) { 3707e328140fSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 3708e328140fSMat Martineau return err; 3709e328140fSMat Martineau } 37100a708f8fSGustavo F. Padovan 371103f6715dSAndrei Emeltchenko if (__is_ctrl_final(chan, rx_control)) { 3712e2ab4353SGustavo F. Padovan if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 3713525cd185SGustavo F. Padovan l2cap_retransmit_frames(chan); 37140a708f8fSGustavo F. Padovan } 37150a708f8fSGustavo F. Padovan 37161a09bcb9SGustavo F. Padovan __set_ack_timer(chan); 37170a708f8fSGustavo F. Padovan 37186a026610SGustavo F. Padovan chan->num_acked = (chan->num_acked + 1) % num_to_ack; 37196a026610SGustavo F. Padovan if (chan->num_acked == num_to_ack - 1) 3720525cd185SGustavo F. Padovan l2cap_send_ack(chan); 37210a708f8fSGustavo F. Padovan 37220a708f8fSGustavo F. Padovan return 0; 37230a708f8fSGustavo F. Padovan 37240a708f8fSGustavo F. Padovan drop: 37250a708f8fSGustavo F. Padovan kfree_skb(skb); 37260a708f8fSGustavo F. Padovan return 0; 37270a708f8fSGustavo F. Padovan } 37280a708f8fSGustavo F. Padovan 372988843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control) 37300a708f8fSGustavo F. Padovan { 373188843ab0SAndrei Emeltchenko BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, 37320b209faeSAndrei Emeltchenko __get_reqseq(chan, rx_control), rx_control); 37330a708f8fSGustavo F. Padovan 37340b209faeSAndrei Emeltchenko chan->expected_ack_seq = __get_reqseq(chan, rx_control); 373542e5c802SGustavo F. Padovan l2cap_drop_acked_frames(chan); 37360a708f8fSGustavo F. Padovan 3737e3781735SAndrei Emeltchenko if (__is_ctrl_poll(chan, rx_control)) { 3738e2ab4353SGustavo F. Padovan set_bit(CONN_SEND_FBIT, &chan->conn_state); 3739e2ab4353SGustavo F. Padovan if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) { 3740e2ab4353SGustavo F. Padovan if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 37416a026610SGustavo F. Padovan (chan->unacked_frames > 0)) 37421a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 37430a708f8fSGustavo F. Padovan 3744e2ab4353SGustavo F. Padovan clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 3745525cd185SGustavo F. Padovan l2cap_send_srejtail(chan); 37460a708f8fSGustavo F. Padovan } else { 3747525cd185SGustavo F. Padovan l2cap_send_i_or_rr_or_rnr(chan); 37480a708f8fSGustavo F. Padovan } 37490a708f8fSGustavo F. Padovan 375003f6715dSAndrei Emeltchenko } else if (__is_ctrl_final(chan, rx_control)) { 3751e2ab4353SGustavo F. Padovan clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 37520a708f8fSGustavo F. Padovan 3753e2ab4353SGustavo F. Padovan if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 3754525cd185SGustavo F. Padovan l2cap_retransmit_frames(chan); 37550a708f8fSGustavo F. Padovan 37560a708f8fSGustavo F. Padovan } else { 3757e2ab4353SGustavo F. Padovan if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 37586a026610SGustavo F. Padovan (chan->unacked_frames > 0)) 37591a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 37600a708f8fSGustavo F. Padovan 3761e2ab4353SGustavo F. Padovan clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 3762e2ab4353SGustavo F. Padovan if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) 3763525cd185SGustavo F. Padovan l2cap_send_ack(chan); 37640a708f8fSGustavo F. Padovan else 3765525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 37660a708f8fSGustavo F. Padovan } 37670a708f8fSGustavo F. Padovan } 37680a708f8fSGustavo F. Padovan 376988843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control) 37700a708f8fSGustavo F. Padovan { 37710b209faeSAndrei Emeltchenko u16 tx_seq = __get_reqseq(chan, rx_control); 37720a708f8fSGustavo F. Padovan 377388843ab0SAndrei Emeltchenko BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control); 37740a708f8fSGustavo F. Padovan 3775e2ab4353SGustavo F. Padovan clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 37760a708f8fSGustavo F. Padovan 377742e5c802SGustavo F. Padovan chan->expected_ack_seq = tx_seq; 377842e5c802SGustavo F. Padovan l2cap_drop_acked_frames(chan); 37790a708f8fSGustavo F. Padovan 378003f6715dSAndrei Emeltchenko if (__is_ctrl_final(chan, rx_control)) { 3781e2ab4353SGustavo F. Padovan if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 3782525cd185SGustavo F. Padovan l2cap_retransmit_frames(chan); 37830a708f8fSGustavo F. Padovan } else { 3784525cd185SGustavo F. Padovan l2cap_retransmit_frames(chan); 37850a708f8fSGustavo F. Padovan 3786e2ab4353SGustavo F. Padovan if (test_bit(CONN_WAIT_F, &chan->conn_state)) 3787e2ab4353SGustavo F. Padovan set_bit(CONN_REJ_ACT, &chan->conn_state); 37880a708f8fSGustavo F. Padovan } 37890a708f8fSGustavo F. Padovan } 379088843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control) 37910a708f8fSGustavo F. Padovan { 37920b209faeSAndrei Emeltchenko u16 tx_seq = __get_reqseq(chan, rx_control); 37930a708f8fSGustavo F. Padovan 379488843ab0SAndrei Emeltchenko BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control); 37950a708f8fSGustavo F. Padovan 3796e2ab4353SGustavo F. Padovan clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 37970a708f8fSGustavo F. Padovan 3798e3781735SAndrei Emeltchenko if (__is_ctrl_poll(chan, rx_control)) { 379942e5c802SGustavo F. Padovan chan->expected_ack_seq = tx_seq; 380042e5c802SGustavo F. Padovan l2cap_drop_acked_frames(chan); 38010a708f8fSGustavo F. Padovan 3802e2ab4353SGustavo F. Padovan set_bit(CONN_SEND_FBIT, &chan->conn_state); 3803525cd185SGustavo F. Padovan l2cap_retransmit_one_frame(chan, tx_seq); 38040a708f8fSGustavo F. Padovan 3805525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 38060a708f8fSGustavo F. Padovan 3807e2ab4353SGustavo F. Padovan if (test_bit(CONN_WAIT_F, &chan->conn_state)) { 38086a026610SGustavo F. Padovan chan->srej_save_reqseq = tx_seq; 3809e2ab4353SGustavo F. Padovan set_bit(CONN_SREJ_ACT, &chan->conn_state); 38100a708f8fSGustavo F. Padovan } 381103f6715dSAndrei Emeltchenko } else if (__is_ctrl_final(chan, rx_control)) { 3812e2ab4353SGustavo F. Padovan if (test_bit(CONN_SREJ_ACT, &chan->conn_state) && 38136a026610SGustavo F. Padovan chan->srej_save_reqseq == tx_seq) 3814e2ab4353SGustavo F. Padovan clear_bit(CONN_SREJ_ACT, &chan->conn_state); 38150a708f8fSGustavo F. Padovan else 3816525cd185SGustavo F. Padovan l2cap_retransmit_one_frame(chan, tx_seq); 38170a708f8fSGustavo F. Padovan } else { 3818525cd185SGustavo F. Padovan l2cap_retransmit_one_frame(chan, tx_seq); 3819e2ab4353SGustavo F. Padovan if (test_bit(CONN_WAIT_F, &chan->conn_state)) { 38206a026610SGustavo F. Padovan chan->srej_save_reqseq = tx_seq; 3821e2ab4353SGustavo F. Padovan set_bit(CONN_SREJ_ACT, &chan->conn_state); 38220a708f8fSGustavo F. Padovan } 38230a708f8fSGustavo F. Padovan } 38240a708f8fSGustavo F. Padovan } 38250a708f8fSGustavo F. Padovan 382688843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control) 38270a708f8fSGustavo F. Padovan { 38280b209faeSAndrei Emeltchenko u16 tx_seq = __get_reqseq(chan, rx_control); 38290a708f8fSGustavo F. Padovan 383088843ab0SAndrei Emeltchenko BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control); 38310a708f8fSGustavo F. Padovan 3832e2ab4353SGustavo F. Padovan set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 383342e5c802SGustavo F. Padovan chan->expected_ack_seq = tx_seq; 383442e5c802SGustavo F. Padovan l2cap_drop_acked_frames(chan); 38350a708f8fSGustavo F. Padovan 3836e3781735SAndrei Emeltchenko if (__is_ctrl_poll(chan, rx_control)) 3837e2ab4353SGustavo F. Padovan set_bit(CONN_SEND_FBIT, &chan->conn_state); 38380a708f8fSGustavo F. Padovan 3839e2ab4353SGustavo F. Padovan if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) { 38401a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 3841e3781735SAndrei Emeltchenko if (__is_ctrl_poll(chan, rx_control)) 3842525cd185SGustavo F. Padovan l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL); 38430a708f8fSGustavo F. Padovan return; 38440a708f8fSGustavo F. Padovan } 38450a708f8fSGustavo F. Padovan 3846e3781735SAndrei Emeltchenko if (__is_ctrl_poll(chan, rx_control)) { 3847525cd185SGustavo F. Padovan l2cap_send_srejtail(chan); 3848ab784b73SAndrei Emeltchenko } else { 3849ab784b73SAndrei Emeltchenko rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR); 3850ab784b73SAndrei Emeltchenko l2cap_send_sframe(chan, rx_control); 3851ab784b73SAndrei Emeltchenko } 38520a708f8fSGustavo F. Padovan } 38530a708f8fSGustavo F. Padovan 385488843ab0SAndrei Emeltchenko static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb) 38550a708f8fSGustavo F. Padovan { 385688843ab0SAndrei Emeltchenko BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len); 38570a708f8fSGustavo F. Padovan 385803f6715dSAndrei Emeltchenko if (__is_ctrl_final(chan, rx_control) && 3859e2ab4353SGustavo F. Padovan test_bit(CONN_WAIT_F, &chan->conn_state)) { 38601a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 38616a026610SGustavo F. Padovan if (chan->unacked_frames > 0) 38621a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 3863e2ab4353SGustavo F. Padovan clear_bit(CONN_WAIT_F, &chan->conn_state); 38640a708f8fSGustavo F. Padovan } 38650a708f8fSGustavo F. Padovan 3866ab784b73SAndrei Emeltchenko switch (__get_ctrl_super(chan, rx_control)) { 3867ab784b73SAndrei Emeltchenko case L2CAP_SUPER_RR: 3868525cd185SGustavo F. Padovan l2cap_data_channel_rrframe(chan, rx_control); 38690a708f8fSGustavo F. Padovan break; 38700a708f8fSGustavo F. Padovan 3871ab784b73SAndrei Emeltchenko case L2CAP_SUPER_REJ: 3872525cd185SGustavo F. Padovan l2cap_data_channel_rejframe(chan, rx_control); 38730a708f8fSGustavo F. Padovan break; 38740a708f8fSGustavo F. Padovan 3875ab784b73SAndrei Emeltchenko case L2CAP_SUPER_SREJ: 3876525cd185SGustavo F. Padovan l2cap_data_channel_srejframe(chan, rx_control); 38770a708f8fSGustavo F. Padovan break; 38780a708f8fSGustavo F. Padovan 3879ab784b73SAndrei Emeltchenko case L2CAP_SUPER_RNR: 3880525cd185SGustavo F. Padovan l2cap_data_channel_rnrframe(chan, rx_control); 38810a708f8fSGustavo F. Padovan break; 38820a708f8fSGustavo F. Padovan } 38830a708f8fSGustavo F. Padovan 38840a708f8fSGustavo F. Padovan kfree_skb(skb); 38850a708f8fSGustavo F. Padovan return 0; 38860a708f8fSGustavo F. Padovan } 38870a708f8fSGustavo F. Padovan 38880a708f8fSGustavo F. Padovan static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) 38890a708f8fSGustavo F. Padovan { 3890525cd185SGustavo F. Padovan struct l2cap_chan *chan = l2cap_pi(sk)->chan; 389188843ab0SAndrei Emeltchenko u32 control; 38920b209faeSAndrei Emeltchenko u16 req_seq; 38930a708f8fSGustavo F. Padovan int len, next_tx_seq_offset, req_seq_offset; 38940a708f8fSGustavo F. Padovan 389588843ab0SAndrei Emeltchenko control = __get_control(chan, skb->data); 389688843ab0SAndrei Emeltchenko skb_pull(skb, __ctrl_size(chan)); 38970a708f8fSGustavo F. Padovan len = skb->len; 38980a708f8fSGustavo F. Padovan 38990a708f8fSGustavo F. Padovan /* 39000a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here. 39010a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery 39020a708f8fSGustavo F. Padovan * procedures and ask retransmission. 39030a708f8fSGustavo F. Padovan */ 390447d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 39050a708f8fSGustavo F. Padovan goto drop; 39060a708f8fSGustavo F. Padovan 3907793c2f1cSAndrei Emeltchenko if (__is_sar_start(chan, control) && !__is_sframe(chan, control)) 390803a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 39090a708f8fSGustavo F. Padovan 391047d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 391103a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 39120a708f8fSGustavo F. Padovan 391347d1ec61SGustavo F. Padovan if (len > chan->mps) { 39148c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 39150a708f8fSGustavo F. Padovan goto drop; 39160a708f8fSGustavo F. Padovan } 39170a708f8fSGustavo F. Padovan 39180b209faeSAndrei Emeltchenko req_seq = __get_reqseq(chan, control); 39190a708f8fSGustavo F. Padovan 3920836be934SAndrei Emeltchenko req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq); 3921836be934SAndrei Emeltchenko 3922836be934SAndrei Emeltchenko next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq, 3923836be934SAndrei Emeltchenko chan->expected_ack_seq); 39240a708f8fSGustavo F. Padovan 39250a708f8fSGustavo F. Padovan /* check for invalid req-seq */ 39260a708f8fSGustavo F. Padovan if (req_seq_offset > next_tx_seq_offset) { 39278c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 39280a708f8fSGustavo F. Padovan goto drop; 39290a708f8fSGustavo F. Padovan } 39300a708f8fSGustavo F. Padovan 3931793c2f1cSAndrei Emeltchenko if (!__is_sframe(chan, control)) { 39320a708f8fSGustavo F. Padovan if (len < 0) { 39338c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 39340a708f8fSGustavo F. Padovan goto drop; 39350a708f8fSGustavo F. Padovan } 39360a708f8fSGustavo F. Padovan 3937525cd185SGustavo F. Padovan l2cap_data_channel_iframe(chan, control, skb); 39380a708f8fSGustavo F. Padovan } else { 39390a708f8fSGustavo F. Padovan if (len != 0) { 39400a708f8fSGustavo F. Padovan BT_ERR("%d", len); 39418c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 39420a708f8fSGustavo F. Padovan goto drop; 39430a708f8fSGustavo F. Padovan } 39440a708f8fSGustavo F. Padovan 3945525cd185SGustavo F. Padovan l2cap_data_channel_sframe(chan, control, skb); 39460a708f8fSGustavo F. Padovan } 39470a708f8fSGustavo F. Padovan 39480a708f8fSGustavo F. Padovan return 0; 39490a708f8fSGustavo F. Padovan 39500a708f8fSGustavo F. Padovan drop: 39510a708f8fSGustavo F. Padovan kfree_skb(skb); 39520a708f8fSGustavo F. Padovan return 0; 39530a708f8fSGustavo F. Padovan } 39540a708f8fSGustavo F. Padovan 39550a708f8fSGustavo F. Padovan static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb) 39560a708f8fSGustavo F. Padovan { 395748454079SGustavo F. Padovan struct l2cap_chan *chan; 3958bf734843SDavid S. Miller struct sock *sk = NULL; 395988843ab0SAndrei Emeltchenko u32 control; 3960fb45de7dSAndrei Emeltchenko u16 tx_seq; 39610a708f8fSGustavo F. Padovan int len; 39620a708f8fSGustavo F. Padovan 3963baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 396448454079SGustavo F. Padovan if (!chan) { 39650a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid); 39660a708f8fSGustavo F. Padovan goto drop; 39670a708f8fSGustavo F. Padovan } 39680a708f8fSGustavo F. Padovan 396948454079SGustavo F. Padovan sk = chan->sk; 39700a708f8fSGustavo F. Padovan 397149208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len); 39720a708f8fSGustavo F. Padovan 397389bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 39740a708f8fSGustavo F. Padovan goto drop; 39750a708f8fSGustavo F. Padovan 39760c1bc5c6SGustavo F. Padovan switch (chan->mode) { 39770a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 39780a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here 39790a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable. 39800a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't 39810a708f8fSGustavo F. Padovan * provide flow control mechanism. */ 39820a708f8fSGustavo F. Padovan 39830c1bc5c6SGustavo F. Padovan if (chan->imtu < skb->len) 39840a708f8fSGustavo F. Padovan goto drop; 39850a708f8fSGustavo F. Padovan 398623070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 39870a708f8fSGustavo F. Padovan goto done; 39880a708f8fSGustavo F. Padovan break; 39890a708f8fSGustavo F. Padovan 39900a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 39910a708f8fSGustavo F. Padovan if (!sock_owned_by_user(sk)) { 39920a708f8fSGustavo F. Padovan l2cap_ertm_data_rcv(sk, skb); 39930a708f8fSGustavo F. Padovan } else { 39940a708f8fSGustavo F. Padovan if (sk_add_backlog(sk, skb)) 39950a708f8fSGustavo F. Padovan goto drop; 39960a708f8fSGustavo F. Padovan } 39970a708f8fSGustavo F. Padovan 39980a708f8fSGustavo F. Padovan goto done; 39990a708f8fSGustavo F. Padovan 40000a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 400188843ab0SAndrei Emeltchenko control = __get_control(chan, skb->data); 400288843ab0SAndrei Emeltchenko skb_pull(skb, __ctrl_size(chan)); 40030a708f8fSGustavo F. Padovan len = skb->len; 40040a708f8fSGustavo F. Padovan 400547d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 40060a708f8fSGustavo F. Padovan goto drop; 40070a708f8fSGustavo F. Padovan 40087e0ef6eeSAndrei Emeltchenko if (__is_sar_start(chan, control)) 400903a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 40100a708f8fSGustavo F. Padovan 401147d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 401203a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 40130a708f8fSGustavo F. Padovan 4014793c2f1cSAndrei Emeltchenko if (len > chan->mps || len < 0 || __is_sframe(chan, control)) 40150a708f8fSGustavo F. Padovan goto drop; 40160a708f8fSGustavo F. Padovan 4017fb45de7dSAndrei Emeltchenko tx_seq = __get_txseq(chan, control); 40180a708f8fSGustavo F. Padovan 401984084a31SMat Martineau if (chan->expected_tx_seq != tx_seq) { 402084084a31SMat Martineau /* Frame(s) missing - must discard partial SDU */ 402184084a31SMat Martineau kfree_skb(chan->sdu); 402284084a31SMat Martineau chan->sdu = NULL; 402384084a31SMat Martineau chan->sdu_last_frag = NULL; 402484084a31SMat Martineau chan->sdu_len = 0; 402584084a31SMat Martineau 402684084a31SMat Martineau /* TODO: Notify userland of missing data */ 402784084a31SMat Martineau } 402884084a31SMat Martineau 4029836be934SAndrei Emeltchenko chan->expected_tx_seq = __next_seq(chan, tx_seq); 40300a708f8fSGustavo F. Padovan 403184084a31SMat Martineau if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE) 403284084a31SMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 40330a708f8fSGustavo F. Padovan 40340a708f8fSGustavo F. Padovan goto done; 40350a708f8fSGustavo F. Padovan 40360a708f8fSGustavo F. Padovan default: 40370c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); 40380a708f8fSGustavo F. Padovan break; 40390a708f8fSGustavo F. Padovan } 40400a708f8fSGustavo F. Padovan 40410a708f8fSGustavo F. Padovan drop: 40420a708f8fSGustavo F. Padovan kfree_skb(skb); 40430a708f8fSGustavo F. Padovan 40440a708f8fSGustavo F. Padovan done: 40450a708f8fSGustavo F. Padovan if (sk) 40460a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 40470a708f8fSGustavo F. Padovan 40480a708f8fSGustavo F. Padovan return 0; 40490a708f8fSGustavo F. Padovan } 40500a708f8fSGustavo F. Padovan 40510a708f8fSGustavo F. Padovan static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb) 40520a708f8fSGustavo F. Padovan { 40536dcae1eaSDavid S. Miller struct sock *sk = NULL; 405423691d75SGustavo F. Padovan struct l2cap_chan *chan; 40550a708f8fSGustavo F. Padovan 405623691d75SGustavo F. Padovan chan = l2cap_global_chan_by_psm(0, psm, conn->src); 405723691d75SGustavo F. Padovan if (!chan) 40580a708f8fSGustavo F. Padovan goto drop; 40590a708f8fSGustavo F. Padovan 406023691d75SGustavo F. Padovan sk = chan->sk; 406123691d75SGustavo F. Padovan 40620a708f8fSGustavo F. Padovan bh_lock_sock(sk); 40630a708f8fSGustavo F. Padovan 40640a708f8fSGustavo F. Padovan BT_DBG("sk %p, len %d", sk, skb->len); 40650a708f8fSGustavo F. Padovan 406689bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 40670a708f8fSGustavo F. Padovan goto drop; 40680a708f8fSGustavo F. Padovan 4069e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 40700a708f8fSGustavo F. Padovan goto drop; 40710a708f8fSGustavo F. Padovan 407223070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 40730a708f8fSGustavo F. Padovan goto done; 40740a708f8fSGustavo F. Padovan 40750a708f8fSGustavo F. Padovan drop: 40760a708f8fSGustavo F. Padovan kfree_skb(skb); 40770a708f8fSGustavo F. Padovan 40780a708f8fSGustavo F. Padovan done: 40790a708f8fSGustavo F. Padovan if (sk) 40800a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 40810a708f8fSGustavo F. Padovan return 0; 40820a708f8fSGustavo F. Padovan } 40830a708f8fSGustavo F. Padovan 40849f69bda6SGustavo F. Padovan static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb) 40859f69bda6SGustavo F. Padovan { 40866dcae1eaSDavid S. Miller struct sock *sk = NULL; 408723691d75SGustavo F. Padovan struct l2cap_chan *chan; 40889f69bda6SGustavo F. Padovan 408923691d75SGustavo F. Padovan chan = l2cap_global_chan_by_scid(0, cid, conn->src); 409023691d75SGustavo F. Padovan if (!chan) 40919f69bda6SGustavo F. Padovan goto drop; 40929f69bda6SGustavo F. Padovan 409323691d75SGustavo F. Padovan sk = chan->sk; 409423691d75SGustavo F. Padovan 40959f69bda6SGustavo F. Padovan bh_lock_sock(sk); 40969f69bda6SGustavo F. Padovan 40979f69bda6SGustavo F. Padovan BT_DBG("sk %p, len %d", sk, skb->len); 40989f69bda6SGustavo F. Padovan 409989bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 41009f69bda6SGustavo F. Padovan goto drop; 41019f69bda6SGustavo F. Padovan 4102e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 41039f69bda6SGustavo F. Padovan goto drop; 41049f69bda6SGustavo F. Padovan 410523070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 41069f69bda6SGustavo F. Padovan goto done; 41079f69bda6SGustavo F. Padovan 41089f69bda6SGustavo F. Padovan drop: 41099f69bda6SGustavo F. Padovan kfree_skb(skb); 41109f69bda6SGustavo F. Padovan 41119f69bda6SGustavo F. Padovan done: 41129f69bda6SGustavo F. Padovan if (sk) 41139f69bda6SGustavo F. Padovan bh_unlock_sock(sk); 41149f69bda6SGustavo F. Padovan return 0; 41159f69bda6SGustavo F. Padovan } 41169f69bda6SGustavo F. Padovan 41170a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) 41180a708f8fSGustavo F. Padovan { 41190a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data; 41200a708f8fSGustavo F. Padovan u16 cid, len; 41210a708f8fSGustavo F. Padovan __le16 psm; 41220a708f8fSGustavo F. Padovan 41230a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE); 41240a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid); 41250a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len); 41260a708f8fSGustavo F. Padovan 41270a708f8fSGustavo F. Padovan if (len != skb->len) { 41280a708f8fSGustavo F. Padovan kfree_skb(skb); 41290a708f8fSGustavo F. Padovan return; 41300a708f8fSGustavo F. Padovan } 41310a708f8fSGustavo F. Padovan 41320a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid); 41330a708f8fSGustavo F. Padovan 41340a708f8fSGustavo F. Padovan switch (cid) { 41353300d9a9SClaudio Takahasi case L2CAP_CID_LE_SIGNALING: 41360a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING: 41370a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb); 41380a708f8fSGustavo F. Padovan break; 41390a708f8fSGustavo F. Padovan 41400a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS: 41410a708f8fSGustavo F. Padovan psm = get_unaligned_le16(skb->data); 41420a708f8fSGustavo F. Padovan skb_pull(skb, 2); 41430a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb); 41440a708f8fSGustavo F. Padovan break; 41450a708f8fSGustavo F. Padovan 41469f69bda6SGustavo F. Padovan case L2CAP_CID_LE_DATA: 41479f69bda6SGustavo F. Padovan l2cap_att_channel(conn, cid, skb); 41489f69bda6SGustavo F. Padovan break; 41499f69bda6SGustavo F. Padovan 4150b501d6a1SAnderson Briglia case L2CAP_CID_SMP: 4151b501d6a1SAnderson Briglia if (smp_sig_channel(conn, skb)) 4152b501d6a1SAnderson Briglia l2cap_conn_del(conn->hcon, EACCES); 4153b501d6a1SAnderson Briglia break; 4154b501d6a1SAnderson Briglia 41550a708f8fSGustavo F. Padovan default: 41560a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb); 41570a708f8fSGustavo F. Padovan break; 41580a708f8fSGustavo F. Padovan } 41590a708f8fSGustavo F. Padovan } 41600a708f8fSGustavo F. Padovan 41610a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */ 41620a708f8fSGustavo F. Padovan 41630a708f8fSGustavo F. Padovan static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) 41640a708f8fSGustavo F. Padovan { 41650a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0; 416623691d75SGustavo F. Padovan struct l2cap_chan *c; 41670a708f8fSGustavo F. Padovan 41680a708f8fSGustavo F. Padovan if (type != ACL_LINK) 41690a708f8fSGustavo F. Padovan return -EINVAL; 41700a708f8fSGustavo F. Padovan 41710a708f8fSGustavo F. Padovan BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); 41720a708f8fSGustavo F. Padovan 41730a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */ 417423691d75SGustavo F. Padovan read_lock(&chan_list_lock); 417523691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 417623691d75SGustavo F. Padovan struct sock *sk = c->sk; 41774343478fSGustavo F. Padovan 417889bc500eSGustavo F. Padovan if (c->state != BT_LISTEN) 41790a708f8fSGustavo F. Padovan continue; 41800a708f8fSGustavo F. Padovan 41810a708f8fSGustavo F. Padovan if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { 41820a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT; 418343bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 41840a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER; 41850a708f8fSGustavo F. Padovan exact++; 41860a708f8fSGustavo F. Padovan } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { 41870a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT; 418843bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 41890a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER; 41900a708f8fSGustavo F. Padovan } 41910a708f8fSGustavo F. Padovan } 419223691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 41930a708f8fSGustavo F. Padovan 41940a708f8fSGustavo F. Padovan return exact ? lm1 : lm2; 41950a708f8fSGustavo F. Padovan } 41960a708f8fSGustavo F. Padovan 41970a708f8fSGustavo F. Padovan static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) 41980a708f8fSGustavo F. Padovan { 41990a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 42000a708f8fSGustavo F. Padovan 42010a708f8fSGustavo F. Padovan BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); 42020a708f8fSGustavo F. Padovan 4203acd7d370SVille Tervo if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK)) 42040a708f8fSGustavo F. Padovan return -EINVAL; 42050a708f8fSGustavo F. Padovan 42060a708f8fSGustavo F. Padovan if (!status) { 42070a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, status); 42080a708f8fSGustavo F. Padovan if (conn) 42090a708f8fSGustavo F. Padovan l2cap_conn_ready(conn); 42100a708f8fSGustavo F. Padovan } else 4211e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status)); 42120a708f8fSGustavo F. Padovan 42130a708f8fSGustavo F. Padovan return 0; 42140a708f8fSGustavo F. Padovan } 42150a708f8fSGustavo F. Padovan 42160a708f8fSGustavo F. Padovan static int l2cap_disconn_ind(struct hci_conn *hcon) 42170a708f8fSGustavo F. Padovan { 42180a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 42190a708f8fSGustavo F. Padovan 42200a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon); 42210a708f8fSGustavo F. Padovan 4222b5694506SGustavo F. Padovan if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn) 42230a708f8fSGustavo F. Padovan return 0x13; 42240a708f8fSGustavo F. Padovan 42250a708f8fSGustavo F. Padovan return conn->disc_reason; 42260a708f8fSGustavo F. Padovan } 42270a708f8fSGustavo F. Padovan 42280a708f8fSGustavo F. Padovan static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) 42290a708f8fSGustavo F. Padovan { 42300a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason); 42310a708f8fSGustavo F. Padovan 4232acd7d370SVille Tervo if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK)) 42330a708f8fSGustavo F. Padovan return -EINVAL; 42340a708f8fSGustavo F. Padovan 4235e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason)); 42360a708f8fSGustavo F. Padovan 42370a708f8fSGustavo F. Padovan return 0; 42380a708f8fSGustavo F. Padovan } 42390a708f8fSGustavo F. Padovan 42404343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) 42410a708f8fSGustavo F. Padovan { 4242715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 42430a708f8fSGustavo F. Padovan return; 42440a708f8fSGustavo F. Padovan 42450a708f8fSGustavo F. Padovan if (encrypt == 0x00) { 42464343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) { 4247c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 4248c9b66675SGustavo F. Padovan __set_chan_timer(chan, HZ * 5); 42494343478fSGustavo F. Padovan } else if (chan->sec_level == BT_SECURITY_HIGH) 42500f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED); 42510a708f8fSGustavo F. Padovan } else { 42524343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) 4253c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 42540a708f8fSGustavo F. Padovan } 42550a708f8fSGustavo F. Padovan } 42560a708f8fSGustavo F. Padovan 42570a708f8fSGustavo F. Padovan static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) 42580a708f8fSGustavo F. Padovan { 42590a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 426048454079SGustavo F. Padovan struct l2cap_chan *chan; 42610a708f8fSGustavo F. Padovan 42620a708f8fSGustavo F. Padovan if (!conn) 42630a708f8fSGustavo F. Padovan return 0; 42640a708f8fSGustavo F. Padovan 42650a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 42660a708f8fSGustavo F. Padovan 4267160dc6acSVinicius Costa Gomes if (hcon->type == LE_LINK) { 4268160dc6acSVinicius Costa Gomes smp_distribute_keys(conn, 0); 4269160dc6acSVinicius Costa Gomes del_timer(&conn->security_timer); 4270160dc6acSVinicius Costa Gomes } 4271160dc6acSVinicius Costa Gomes 4272baa7e1faSGustavo F. Padovan read_lock(&conn->chan_lock); 42730a708f8fSGustavo F. Padovan 4274baa7e1faSGustavo F. Padovan list_for_each_entry(chan, &conn->chan_l, list) { 427548454079SGustavo F. Padovan struct sock *sk = chan->sk; 4276baa7e1faSGustavo F. Padovan 42770a708f8fSGustavo F. Padovan bh_lock_sock(sk); 42780a708f8fSGustavo F. Padovan 4279f1cb9af5SVinicius Costa Gomes BT_DBG("chan->scid %d", chan->scid); 4280f1cb9af5SVinicius Costa Gomes 4281f1cb9af5SVinicius Costa Gomes if (chan->scid == L2CAP_CID_LE_DATA) { 4282f1cb9af5SVinicius Costa Gomes if (!status && encrypt) { 4283f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level; 4284f1cb9af5SVinicius Costa Gomes l2cap_chan_ready(sk); 4285f1cb9af5SVinicius Costa Gomes } 4286f1cb9af5SVinicius Costa Gomes 4287f1cb9af5SVinicius Costa Gomes bh_unlock_sock(sk); 4288f1cb9af5SVinicius Costa Gomes continue; 4289f1cb9af5SVinicius Costa Gomes } 4290f1cb9af5SVinicius Costa Gomes 4291c1360a1cSGustavo F. Padovan if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) { 42920a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 42930a708f8fSGustavo F. Padovan continue; 42940a708f8fSGustavo F. Padovan } 42950a708f8fSGustavo F. Padovan 429689bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED || 429789bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) { 42984343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt); 42990a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 43000a708f8fSGustavo F. Padovan continue; 43010a708f8fSGustavo F. Padovan } 43020a708f8fSGustavo F. Padovan 430389bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 43040a708f8fSGustavo F. Padovan if (!status) { 43050a708f8fSGustavo F. Padovan struct l2cap_conn_req req; 4306fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 4307fe4128e0SGustavo F. Padovan req.psm = chan->psm; 43080a708f8fSGustavo F. Padovan 4309fc7f8a7eSGustavo F. Padovan chan->ident = l2cap_get_ident(conn); 4310c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 43110a708f8fSGustavo F. Padovan 4312fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, 43130a708f8fSGustavo F. Padovan L2CAP_CONN_REQ, sizeof(req), &req); 43140a708f8fSGustavo F. Padovan } else { 4315c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 4316c9b66675SGustavo F. Padovan __set_chan_timer(chan, HZ / 10); 43170a708f8fSGustavo F. Padovan } 431889bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 43190a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 4320df3c3931SJohan Hedberg __u16 res, stat; 43210a708f8fSGustavo F. Padovan 43220a708f8fSGustavo F. Padovan if (!status) { 4323df3c3931SJohan Hedberg if (bt_sk(sk)->defer_setup) { 4324df3c3931SJohan Hedberg struct sock *parent = bt_sk(sk)->parent; 4325df3c3931SJohan Hedberg res = L2CAP_CR_PEND; 4326df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND; 432705e9a2f6SIlia Kolomisnky if (parent) 4328df3c3931SJohan Hedberg parent->sk_data_ready(parent, 0); 4329df3c3931SJohan Hedberg } else { 433089bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 4331df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS; 4332df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 4333df3c3931SJohan Hedberg } 43340a708f8fSGustavo F. Padovan } else { 433589bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_DISCONN); 4336c9b66675SGustavo F. Padovan __set_chan_timer(chan, HZ / 10); 4337df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK; 4338df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 43390a708f8fSGustavo F. Padovan } 43400a708f8fSGustavo F. Padovan 4341fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 4342fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 4343df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res); 4344df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat); 4345fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 4346fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 43470a708f8fSGustavo F. Padovan } 43480a708f8fSGustavo F. Padovan 43490a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 43500a708f8fSGustavo F. Padovan } 43510a708f8fSGustavo F. Padovan 4352baa7e1faSGustavo F. Padovan read_unlock(&conn->chan_lock); 43530a708f8fSGustavo F. Padovan 43540a708f8fSGustavo F. Padovan return 0; 43550a708f8fSGustavo F. Padovan } 43560a708f8fSGustavo F. Padovan 43570a708f8fSGustavo F. Padovan static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) 43580a708f8fSGustavo F. Padovan { 43590a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 43600a708f8fSGustavo F. Padovan 43610a708f8fSGustavo F. Padovan if (!conn) 43620a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, 0); 43630a708f8fSGustavo F. Padovan 43640a708f8fSGustavo F. Padovan if (!conn) 43650a708f8fSGustavo F. Padovan goto drop; 43660a708f8fSGustavo F. Padovan 43670a708f8fSGustavo F. Padovan BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); 43680a708f8fSGustavo F. Padovan 43690a708f8fSGustavo F. Padovan if (!(flags & ACL_CONT)) { 43700a708f8fSGustavo F. Padovan struct l2cap_hdr *hdr; 437148454079SGustavo F. Padovan struct l2cap_chan *chan; 43720a708f8fSGustavo F. Padovan u16 cid; 43730a708f8fSGustavo F. Padovan int len; 43740a708f8fSGustavo F. Padovan 43750a708f8fSGustavo F. Padovan if (conn->rx_len) { 43760a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len); 43770a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 43780a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 43790a708f8fSGustavo F. Padovan conn->rx_len = 0; 43800a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 43810a708f8fSGustavo F. Padovan } 43820a708f8fSGustavo F. Padovan 43830a708f8fSGustavo F. Padovan /* Start fragment always begin with Basic L2CAP header */ 43840a708f8fSGustavo F. Padovan if (skb->len < L2CAP_HDR_SIZE) { 43850a708f8fSGustavo F. Padovan BT_ERR("Frame is too short (len %d)", skb->len); 43860a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 43870a708f8fSGustavo F. Padovan goto drop; 43880a708f8fSGustavo F. Padovan } 43890a708f8fSGustavo F. Padovan 43900a708f8fSGustavo F. Padovan hdr = (struct l2cap_hdr *) skb->data; 43910a708f8fSGustavo F. Padovan len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; 43920a708f8fSGustavo F. Padovan cid = __le16_to_cpu(hdr->cid); 43930a708f8fSGustavo F. Padovan 43940a708f8fSGustavo F. Padovan if (len == skb->len) { 43950a708f8fSGustavo F. Padovan /* Complete frame received */ 43960a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb); 43970a708f8fSGustavo F. Padovan return 0; 43980a708f8fSGustavo F. Padovan } 43990a708f8fSGustavo F. Padovan 44000a708f8fSGustavo F. Padovan BT_DBG("Start: total len %d, frag len %d", len, skb->len); 44010a708f8fSGustavo F. Padovan 44020a708f8fSGustavo F. Padovan if (skb->len > len) { 44030a708f8fSGustavo F. Padovan BT_ERR("Frame is too long (len %d, expected len %d)", 44040a708f8fSGustavo F. Padovan skb->len, len); 44050a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 44060a708f8fSGustavo F. Padovan goto drop; 44070a708f8fSGustavo F. Padovan } 44080a708f8fSGustavo F. Padovan 4409baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 44100a708f8fSGustavo F. Padovan 441148454079SGustavo F. Padovan if (chan && chan->sk) { 441248454079SGustavo F. Padovan struct sock *sk = chan->sk; 441348454079SGustavo F. Padovan 44140c1bc5c6SGustavo F. Padovan if (chan->imtu < len - L2CAP_HDR_SIZE) { 441548454079SGustavo F. Padovan BT_ERR("Frame exceeding recv MTU (len %d, " 441648454079SGustavo F. Padovan "MTU %d)", len, 44170c1bc5c6SGustavo F. Padovan chan->imtu); 44180a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 44190a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 44200a708f8fSGustavo F. Padovan goto drop; 44210a708f8fSGustavo F. Padovan } 44220a708f8fSGustavo F. Padovan bh_unlock_sock(sk); 442348454079SGustavo F. Padovan } 44240a708f8fSGustavo F. Padovan 44250a708f8fSGustavo F. Padovan /* Allocate skb for the complete frame (with header) */ 44260a708f8fSGustavo F. Padovan conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC); 44270a708f8fSGustavo F. Padovan if (!conn->rx_skb) 44280a708f8fSGustavo F. Padovan goto drop; 44290a708f8fSGustavo F. Padovan 44300a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 44310a708f8fSGustavo F. Padovan skb->len); 44320a708f8fSGustavo F. Padovan conn->rx_len = len - skb->len; 44330a708f8fSGustavo F. Padovan } else { 44340a708f8fSGustavo F. Padovan BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); 44350a708f8fSGustavo F. Padovan 44360a708f8fSGustavo F. Padovan if (!conn->rx_len) { 44370a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len); 44380a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 44390a708f8fSGustavo F. Padovan goto drop; 44400a708f8fSGustavo F. Padovan } 44410a708f8fSGustavo F. Padovan 44420a708f8fSGustavo F. Padovan if (skb->len > conn->rx_len) { 44430a708f8fSGustavo F. Padovan BT_ERR("Fragment is too long (len %d, expected %d)", 44440a708f8fSGustavo F. Padovan skb->len, conn->rx_len); 44450a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 44460a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 44470a708f8fSGustavo F. Padovan conn->rx_len = 0; 44480a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 44490a708f8fSGustavo F. Padovan goto drop; 44500a708f8fSGustavo F. Padovan } 44510a708f8fSGustavo F. Padovan 44520a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 44530a708f8fSGustavo F. Padovan skb->len); 44540a708f8fSGustavo F. Padovan conn->rx_len -= skb->len; 44550a708f8fSGustavo F. Padovan 44560a708f8fSGustavo F. Padovan if (!conn->rx_len) { 44570a708f8fSGustavo F. Padovan /* Complete frame received */ 44580a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, conn->rx_skb); 44590a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 44600a708f8fSGustavo F. Padovan } 44610a708f8fSGustavo F. Padovan } 44620a708f8fSGustavo F. Padovan 44630a708f8fSGustavo F. Padovan drop: 44640a708f8fSGustavo F. Padovan kfree_skb(skb); 44650a708f8fSGustavo F. Padovan return 0; 44660a708f8fSGustavo F. Padovan } 44670a708f8fSGustavo F. Padovan 44680a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p) 44690a708f8fSGustavo F. Padovan { 447023691d75SGustavo F. Padovan struct l2cap_chan *c; 44710a708f8fSGustavo F. Padovan 447223691d75SGustavo F. Padovan read_lock_bh(&chan_list_lock); 44730a708f8fSGustavo F. Padovan 447423691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 447523691d75SGustavo F. Padovan struct sock *sk = c->sk; 44760a708f8fSGustavo F. Padovan 4477903d343eSGustavo F. Padovan seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", 44780a708f8fSGustavo F. Padovan batostr(&bt_sk(sk)->src), 44790a708f8fSGustavo F. Padovan batostr(&bt_sk(sk)->dst), 448089bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm), 448123691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu, 448223691d75SGustavo F. Padovan c->sec_level, c->mode); 44830a708f8fSGustavo F. Padovan } 44840a708f8fSGustavo F. Padovan 448523691d75SGustavo F. Padovan read_unlock_bh(&chan_list_lock); 44860a708f8fSGustavo F. Padovan 44870a708f8fSGustavo F. Padovan return 0; 44880a708f8fSGustavo F. Padovan } 44890a708f8fSGustavo F. Padovan 44900a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file) 44910a708f8fSGustavo F. Padovan { 44920a708f8fSGustavo F. Padovan return single_open(file, l2cap_debugfs_show, inode->i_private); 44930a708f8fSGustavo F. Padovan } 44940a708f8fSGustavo F. Padovan 44950a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = { 44960a708f8fSGustavo F. Padovan .open = l2cap_debugfs_open, 44970a708f8fSGustavo F. Padovan .read = seq_read, 44980a708f8fSGustavo F. Padovan .llseek = seq_lseek, 44990a708f8fSGustavo F. Padovan .release = single_release, 45000a708f8fSGustavo F. Padovan }; 45010a708f8fSGustavo F. Padovan 45020a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs; 45030a708f8fSGustavo F. Padovan 45040a708f8fSGustavo F. Padovan static struct hci_proto l2cap_hci_proto = { 45050a708f8fSGustavo F. Padovan .name = "L2CAP", 45060a708f8fSGustavo F. Padovan .id = HCI_PROTO_L2CAP, 45070a708f8fSGustavo F. Padovan .connect_ind = l2cap_connect_ind, 45080a708f8fSGustavo F. Padovan .connect_cfm = l2cap_connect_cfm, 45090a708f8fSGustavo F. Padovan .disconn_ind = l2cap_disconn_ind, 45100a708f8fSGustavo F. Padovan .disconn_cfm = l2cap_disconn_cfm, 45110a708f8fSGustavo F. Padovan .security_cfm = l2cap_security_cfm, 45120a708f8fSGustavo F. Padovan .recv_acldata = l2cap_recv_acldata 45130a708f8fSGustavo F. Padovan }; 45140a708f8fSGustavo F. Padovan 451564274518SGustavo F. Padovan int __init l2cap_init(void) 45160a708f8fSGustavo F. Padovan { 45170a708f8fSGustavo F. Padovan int err; 45180a708f8fSGustavo F. Padovan 4519bb58f747SGustavo F. Padovan err = l2cap_init_sockets(); 45200a708f8fSGustavo F. Padovan if (err < 0) 45210a708f8fSGustavo F. Padovan return err; 45220a708f8fSGustavo F. Padovan 45230a708f8fSGustavo F. Padovan err = hci_register_proto(&l2cap_hci_proto); 45240a708f8fSGustavo F. Padovan if (err < 0) { 45250a708f8fSGustavo F. Padovan BT_ERR("L2CAP protocol registration failed"); 45260a708f8fSGustavo F. Padovan bt_sock_unregister(BTPROTO_L2CAP); 45270a708f8fSGustavo F. Padovan goto error; 45280a708f8fSGustavo F. Padovan } 45290a708f8fSGustavo F. Padovan 45300a708f8fSGustavo F. Padovan if (bt_debugfs) { 45310a708f8fSGustavo F. Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, 45320a708f8fSGustavo F. Padovan bt_debugfs, NULL, &l2cap_debugfs_fops); 45330a708f8fSGustavo F. Padovan if (!l2cap_debugfs) 45340a708f8fSGustavo F. Padovan BT_ERR("Failed to create L2CAP debug file"); 45350a708f8fSGustavo F. Padovan } 45360a708f8fSGustavo F. Padovan 45370a708f8fSGustavo F. Padovan return 0; 45380a708f8fSGustavo F. Padovan 45390a708f8fSGustavo F. Padovan error: 4540bb58f747SGustavo F. Padovan l2cap_cleanup_sockets(); 45410a708f8fSGustavo F. Padovan return err; 45420a708f8fSGustavo F. Padovan } 45430a708f8fSGustavo F. Padovan 454464274518SGustavo F. Padovan void l2cap_exit(void) 45450a708f8fSGustavo F. Padovan { 45460a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs); 45470a708f8fSGustavo F. Padovan 45480a708f8fSGustavo F. Padovan if (hci_unregister_proto(&l2cap_hci_proto) < 0) 45490a708f8fSGustavo F. Padovan BT_ERR("L2CAP protocol unregistration failed"); 45500a708f8fSGustavo F. Padovan 4551bb58f747SGustavo F. Padovan l2cap_cleanup_sockets(); 45520a708f8fSGustavo F. Padovan } 45530a708f8fSGustavo F. Padovan 45540a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644); 45550a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); 4556a5fd6f30SAndrei Emeltchenko 4557a5fd6f30SAndrei Emeltchenko module_param(enable_hs, bool, 0644); 4558a5fd6f30SAndrei Emeltchenko MODULE_PARM_DESC(enable_hs, "Enable High Speed"); 4559