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. 6590051deSGustavo F. Padovan Copyright (C) 2011 ProFUSION Embedded Systems 70a708f8fSGustavo F. Padovan 80a708f8fSGustavo F. Padovan Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> 90a708f8fSGustavo F. Padovan 100a708f8fSGustavo F. Padovan This program is free software; you can redistribute it and/or modify 110a708f8fSGustavo F. Padovan it under the terms of the GNU General Public License version 2 as 120a708f8fSGustavo F. Padovan published by the Free Software Foundation; 130a708f8fSGustavo F. Padovan 140a708f8fSGustavo F. Padovan THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 150a708f8fSGustavo F. Padovan OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 160a708f8fSGustavo F. Padovan FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 170a708f8fSGustavo F. Padovan IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 180a708f8fSGustavo F. Padovan CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 190a708f8fSGustavo F. Padovan WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 200a708f8fSGustavo F. Padovan ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 210a708f8fSGustavo F. Padovan OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 220a708f8fSGustavo F. Padovan 230a708f8fSGustavo F. Padovan ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 240a708f8fSGustavo F. Padovan COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 250a708f8fSGustavo F. Padovan SOFTWARE IS DISCLAIMED. 260a708f8fSGustavo F. Padovan */ 270a708f8fSGustavo F. Padovan 28bb58f747SGustavo F. Padovan /* Bluetooth L2CAP core. */ 290a708f8fSGustavo F. Padovan 300a708f8fSGustavo F. Padovan #include <linux/module.h> 310a708f8fSGustavo F. Padovan 320a708f8fSGustavo F. Padovan #include <linux/types.h> 330a708f8fSGustavo F. Padovan #include <linux/capability.h> 340a708f8fSGustavo F. Padovan #include <linux/errno.h> 350a708f8fSGustavo F. Padovan #include <linux/kernel.h> 360a708f8fSGustavo F. Padovan #include <linux/sched.h> 370a708f8fSGustavo F. Padovan #include <linux/slab.h> 380a708f8fSGustavo F. Padovan #include <linux/poll.h> 390a708f8fSGustavo F. Padovan #include <linux/fcntl.h> 400a708f8fSGustavo F. Padovan #include <linux/init.h> 410a708f8fSGustavo F. Padovan #include <linux/interrupt.h> 420a708f8fSGustavo F. Padovan #include <linux/socket.h> 430a708f8fSGustavo F. Padovan #include <linux/skbuff.h> 440a708f8fSGustavo F. Padovan #include <linux/list.h> 450a708f8fSGustavo F. Padovan #include <linux/device.h> 460a708f8fSGustavo F. Padovan #include <linux/debugfs.h> 470a708f8fSGustavo F. Padovan #include <linux/seq_file.h> 480a708f8fSGustavo F. Padovan #include <linux/uaccess.h> 490a708f8fSGustavo F. Padovan #include <linux/crc16.h> 500a708f8fSGustavo F. Padovan #include <net/sock.h> 510a708f8fSGustavo F. Padovan 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 59eb939922SRusty Russell bool disable_ertm; 600a708f8fSGustavo F. Padovan 610a708f8fSGustavo F. Padovan static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; 6250a147cdSMat Martineau static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, }; 630a708f8fSGustavo F. Padovan 64b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list); 65b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock); 660a708f8fSGustavo F. Padovan 670a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 680a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data); 694519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 704519de9aSGustavo F. Padovan void *data); 71710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); 724519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, 734519de9aSGustavo F. Padovan struct l2cap_chan *chan, int err); 740a708f8fSGustavo F. Padovan 750a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */ 7671ba0e56SGustavo F. Padovan 77baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid) 780a708f8fSGustavo F. Padovan { 793df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 80baa7e1faSGustavo F. Padovan 813df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 823df91ea2SAndrei Emeltchenko if (c->dcid == cid) 833df91ea2SAndrei Emeltchenko return c; 840a708f8fSGustavo F. Padovan } 853df91ea2SAndrei Emeltchenko return NULL; 86baa7e1faSGustavo F. Padovan } 870a708f8fSGustavo F. Padovan 88baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) 890a708f8fSGustavo F. Padovan { 903df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 91baa7e1faSGustavo F. Padovan 923df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 933df91ea2SAndrei Emeltchenko if (c->scid == cid) 943df91ea2SAndrei Emeltchenko return c; 950a708f8fSGustavo F. Padovan } 963df91ea2SAndrei Emeltchenko return NULL; 97baa7e1faSGustavo F. Padovan } 980a708f8fSGustavo F. Padovan 990a708f8fSGustavo F. Padovan /* Find channel with given SCID. 1000a708f8fSGustavo F. Padovan * Returns locked socket */ 101baa7e1faSGustavo F. Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) 1020a708f8fSGustavo F. Padovan { 10348454079SGustavo F. Padovan struct l2cap_chan *c; 104baa7e1faSGustavo F. Padovan 1053df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 106baa7e1faSGustavo F. Padovan c = __l2cap_get_chan_by_scid(conn, cid); 1073df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 1083df91ea2SAndrei Emeltchenko 10948454079SGustavo F. Padovan return c; 1100a708f8fSGustavo F. Padovan } 1110a708f8fSGustavo F. Padovan 112baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident) 1130a708f8fSGustavo F. Padovan { 1143df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 115baa7e1faSGustavo F. Padovan 1163df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 1173df91ea2SAndrei Emeltchenko if (c->ident == ident) 1183df91ea2SAndrei Emeltchenko return c; 1190a708f8fSGustavo F. Padovan } 1203df91ea2SAndrei Emeltchenko return NULL; 121baa7e1faSGustavo F. Padovan } 1220a708f8fSGustavo F. Padovan 123baa7e1faSGustavo F. Padovan static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident) 1240a708f8fSGustavo F. Padovan { 12548454079SGustavo F. Padovan struct l2cap_chan *c; 126baa7e1faSGustavo F. Padovan 1273df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 128baa7e1faSGustavo F. Padovan c = __l2cap_get_chan_by_ident(conn, ident); 1293df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 1303df91ea2SAndrei Emeltchenko 13148454079SGustavo F. Padovan return c; 1320a708f8fSGustavo F. Padovan } 1330a708f8fSGustavo F. Padovan 13423691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src) 1359e4425ffSGustavo F. Padovan { 13623691d75SGustavo F. Padovan struct l2cap_chan *c; 1379e4425ffSGustavo F. Padovan 13823691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 13923691d75SGustavo F. Padovan if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src)) 14023691d75SGustavo F. Padovan return c; 1419e4425ffSGustavo F. Padovan } 142250938cbSSzymon Janc return NULL; 143250938cbSSzymon Janc } 1449e4425ffSGustavo F. Padovan 1459e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) 1469e4425ffSGustavo F. Padovan { 14773b2ec18SGustavo F. Padovan int err; 14873b2ec18SGustavo F. Padovan 149333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 1509e4425ffSGustavo F. Padovan 15123691d75SGustavo F. Padovan if (psm && __l2cap_global_chan_by_addr(psm, src)) { 15273b2ec18SGustavo F. Padovan err = -EADDRINUSE; 15373b2ec18SGustavo F. Padovan goto done; 1549e4425ffSGustavo F. Padovan } 1559e4425ffSGustavo F. Padovan 15673b2ec18SGustavo F. Padovan if (psm) { 1579e4425ffSGustavo F. Padovan chan->psm = psm; 1589e4425ffSGustavo F. Padovan chan->sport = psm; 15973b2ec18SGustavo F. Padovan err = 0; 16073b2ec18SGustavo F. Padovan } else { 16173b2ec18SGustavo F. Padovan u16 p; 1629e4425ffSGustavo F. Padovan 16373b2ec18SGustavo F. Padovan err = -EINVAL; 16473b2ec18SGustavo F. Padovan for (p = 0x1001; p < 0x1100; p += 2) 16523691d75SGustavo F. Padovan if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) { 16673b2ec18SGustavo F. Padovan chan->psm = cpu_to_le16(p); 16773b2ec18SGustavo F. Padovan chan->sport = cpu_to_le16(p); 16873b2ec18SGustavo F. Padovan err = 0; 16973b2ec18SGustavo F. Padovan break; 17073b2ec18SGustavo F. Padovan } 17173b2ec18SGustavo F. Padovan } 17273b2ec18SGustavo F. Padovan 17373b2ec18SGustavo F. Padovan done: 174333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 17573b2ec18SGustavo F. Padovan return err; 1769e4425ffSGustavo F. Padovan } 1779e4425ffSGustavo F. Padovan 1789e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) 1799e4425ffSGustavo F. Padovan { 180333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 1819e4425ffSGustavo F. Padovan 1829e4425ffSGustavo F. Padovan chan->scid = scid; 1839e4425ffSGustavo F. Padovan 184333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 1859e4425ffSGustavo F. Padovan 1869e4425ffSGustavo F. Padovan return 0; 1879e4425ffSGustavo F. Padovan } 1889e4425ffSGustavo F. Padovan 189baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn) 1900a708f8fSGustavo F. Padovan { 1910a708f8fSGustavo F. Padovan u16 cid = L2CAP_CID_DYN_START; 1920a708f8fSGustavo F. Padovan 1930a708f8fSGustavo F. Padovan for (; cid < L2CAP_CID_DYN_END; cid++) { 194baa7e1faSGustavo F. Padovan if (!__l2cap_get_chan_by_scid(conn, cid)) 1950a708f8fSGustavo F. Padovan return cid; 1960a708f8fSGustavo F. Padovan } 1970a708f8fSGustavo F. Padovan 1980a708f8fSGustavo F. Padovan return 0; 1990a708f8fSGustavo F. Padovan } 2000a708f8fSGustavo F. Padovan 2010e587be7SAndrei Emeltchenko static void __l2cap_state_change(struct l2cap_chan *chan, int state) 20289bc500eSGustavo F. Padovan { 20342d2d87cSAndrei Emeltchenko BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state), 204badaaa00SGustavo F. Padovan state_to_string(state)); 205badaaa00SGustavo F. Padovan 20689bc500eSGustavo F. Padovan chan->state = state; 20789bc500eSGustavo F. Padovan chan->ops->state_change(chan->data, state); 20889bc500eSGustavo F. Padovan } 20989bc500eSGustavo F. Padovan 2100e587be7SAndrei Emeltchenko static void l2cap_state_change(struct l2cap_chan *chan, int state) 2110e587be7SAndrei Emeltchenko { 2120e587be7SAndrei Emeltchenko struct sock *sk = chan->sk; 2130e587be7SAndrei Emeltchenko 2140e587be7SAndrei Emeltchenko lock_sock(sk); 2150e587be7SAndrei Emeltchenko __l2cap_state_change(chan, state); 2160e587be7SAndrei Emeltchenko release_sock(sk); 2170e587be7SAndrei Emeltchenko } 2180e587be7SAndrei Emeltchenko 2192e0052e4SAndrei Emeltchenko static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err) 2202e0052e4SAndrei Emeltchenko { 2212e0052e4SAndrei Emeltchenko struct sock *sk = chan->sk; 2222e0052e4SAndrei Emeltchenko 2232e0052e4SAndrei Emeltchenko sk->sk_err = err; 2242e0052e4SAndrei Emeltchenko } 2252e0052e4SAndrei Emeltchenko 2262e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err) 2272e0052e4SAndrei Emeltchenko { 2282e0052e4SAndrei Emeltchenko struct sock *sk = chan->sk; 2292e0052e4SAndrei Emeltchenko 2302e0052e4SAndrei Emeltchenko lock_sock(sk); 2312e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 2322e0052e4SAndrei Emeltchenko release_sock(sk); 2332e0052e4SAndrei Emeltchenko } 2342e0052e4SAndrei Emeltchenko 235721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work) 236ab07801dSGustavo F. Padovan { 237721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 238721c4181SGustavo F. Padovan chan_timer.work); 2393df91ea2SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 240ab07801dSGustavo F. Padovan int reason; 241ab07801dSGustavo F. Padovan 242e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 243ab07801dSGustavo F. Padovan 2443df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 2456be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 246ab07801dSGustavo F. Padovan 24789bc500eSGustavo F. Padovan if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) 248ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 24989bc500eSGustavo F. Padovan else if (chan->state == BT_CONNECT && 250ab07801dSGustavo F. Padovan chan->sec_level != BT_SECURITY_SDP) 251ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 252ab07801dSGustavo F. Padovan else 253ab07801dSGustavo F. Padovan reason = ETIMEDOUT; 254ab07801dSGustavo F. Padovan 2550f852724SGustavo F. Padovan l2cap_chan_close(chan, reason); 256ab07801dSGustavo F. Padovan 2576be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 258ab07801dSGustavo F. Padovan 259ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 2603df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 2613df91ea2SAndrei Emeltchenko 262371fd835SUlisses Furquim l2cap_chan_put(chan); 263ab07801dSGustavo F. Padovan } 264ab07801dSGustavo F. Padovan 26523691d75SGustavo F. Padovan struct l2cap_chan *l2cap_chan_create(struct sock *sk) 2660a708f8fSGustavo F. Padovan { 26748454079SGustavo F. Padovan struct l2cap_chan *chan; 2680a708f8fSGustavo F. Padovan 26948454079SGustavo F. Padovan chan = kzalloc(sizeof(*chan), GFP_ATOMIC); 27048454079SGustavo F. Padovan if (!chan) 27148454079SGustavo F. Padovan return NULL; 2720a708f8fSGustavo F. Padovan 273c03b355eSAndrei Emeltchenko mutex_init(&chan->lock); 274c03b355eSAndrei Emeltchenko 27548454079SGustavo F. Padovan chan->sk = sk; 27648454079SGustavo F. Padovan 277333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 27823691d75SGustavo F. Padovan list_add(&chan->global_l, &chan_list); 279333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 28023691d75SGustavo F. Padovan 281721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout); 282ab07801dSGustavo F. Padovan 28389bc500eSGustavo F. Padovan chan->state = BT_OPEN; 28489bc500eSGustavo F. Padovan 28571ba0e56SGustavo F. Padovan atomic_set(&chan->refcnt, 1); 28671ba0e56SGustavo F. Padovan 287abc545b8SSzymon Janc BT_DBG("sk %p chan %p", sk, chan); 288abc545b8SSzymon Janc 28948454079SGustavo F. Padovan return chan; 2900a708f8fSGustavo F. Padovan } 2910a708f8fSGustavo F. Padovan 29223691d75SGustavo F. Padovan void l2cap_chan_destroy(struct l2cap_chan *chan) 2936ff5abbfSGustavo F. Padovan { 294333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 29523691d75SGustavo F. Padovan list_del(&chan->global_l); 296333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 29723691d75SGustavo F. Padovan 298371fd835SUlisses Furquim l2cap_chan_put(chan); 2996ff5abbfSGustavo F. Padovan } 3006ff5abbfSGustavo F. Padovan 301643162a8SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 3020a708f8fSGustavo F. Padovan { 3030a708f8fSGustavo F. Padovan BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, 304097db76cSAndrei Emeltchenko __le16_to_cpu(chan->psm), chan->dcid); 3050a708f8fSGustavo F. Padovan 3069f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 3070a708f8fSGustavo F. Padovan 3088c1d787bSGustavo F. Padovan chan->conn = conn; 3090a708f8fSGustavo F. Padovan 3105491120eSAndrei Emeltchenko switch (chan->chan_type) { 3115491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_ORIENTED: 312b62f328bSVille Tervo if (conn->hcon->type == LE_LINK) { 313b62f328bSVille Tervo /* LE connection */ 3140c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_LE_DEFAULT_MTU; 315fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_LE_DATA; 316fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_LE_DATA; 317b62f328bSVille Tervo } else { 3180a708f8fSGustavo F. Padovan /* Alloc CID for connection-oriented socket */ 319fe4128e0SGustavo F. Padovan chan->scid = l2cap_alloc_cid(conn); 3200c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 321b62f328bSVille Tervo } 3225491120eSAndrei Emeltchenko break; 3235491120eSAndrei Emeltchenko 3245491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_LESS: 3250a708f8fSGustavo F. Padovan /* Connectionless socket */ 326fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_CONN_LESS; 327fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_CONN_LESS; 3280c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 3295491120eSAndrei Emeltchenko break; 3305491120eSAndrei Emeltchenko 3315491120eSAndrei Emeltchenko default: 3320a708f8fSGustavo F. Padovan /* Raw socket can send/recv signalling messages only */ 333fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_SIGNALING; 334fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_SIGNALING; 3350c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 3360a708f8fSGustavo F. Padovan } 3370a708f8fSGustavo F. Padovan 3388f7975b1SAndrei Emeltchenko chan->local_id = L2CAP_BESTEFFORT_ID; 3398f7975b1SAndrei Emeltchenko chan->local_stype = L2CAP_SERV_BESTEFFORT; 3408f7975b1SAndrei Emeltchenko chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE; 3418f7975b1SAndrei Emeltchenko chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME; 3428f7975b1SAndrei Emeltchenko chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT; 3438f7975b1SAndrei Emeltchenko chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO; 3448f7975b1SAndrei Emeltchenko 345371fd835SUlisses Furquim l2cap_chan_hold(chan); 346baa7e1faSGustavo F. Padovan 3473df91ea2SAndrei Emeltchenko list_add(&chan->list, &conn->chan_l); 348643162a8SAndrei Emeltchenko } 349643162a8SAndrei Emeltchenko 350643162a8SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 351643162a8SAndrei Emeltchenko { 352643162a8SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 353643162a8SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 3543df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 3550a708f8fSGustavo F. Padovan } 3560a708f8fSGustavo F. Padovan 3574519de9aSGustavo F. Padovan static void l2cap_chan_del(struct l2cap_chan *chan, int err) 3580a708f8fSGustavo F. Padovan { 35948454079SGustavo F. Padovan struct sock *sk = chan->sk; 3608c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 3610a708f8fSGustavo F. Padovan struct sock *parent = bt_sk(sk)->parent; 3620a708f8fSGustavo F. Padovan 363c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 3640a708f8fSGustavo F. Padovan 36549208c9cSGustavo F. Padovan BT_DBG("chan %p, conn %p, err %d", chan, conn, err); 3660a708f8fSGustavo F. Padovan 3670a708f8fSGustavo F. Padovan if (conn) { 368baa7e1faSGustavo F. Padovan /* Delete from channel list */ 3693df91ea2SAndrei Emeltchenko list_del(&chan->list); 3703d57dc68SGustavo F. Padovan 371371fd835SUlisses Furquim l2cap_chan_put(chan); 372baa7e1faSGustavo F. Padovan 3738c1d787bSGustavo F. Padovan chan->conn = NULL; 3740a708f8fSGustavo F. Padovan hci_conn_put(conn->hcon); 3750a708f8fSGustavo F. Padovan } 3760a708f8fSGustavo F. Padovan 3776be36555SAndrei Emeltchenko lock_sock(sk); 3786be36555SAndrei Emeltchenko 3790e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CLOSED); 3800a708f8fSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 3810a708f8fSGustavo F. Padovan 3820a708f8fSGustavo F. Padovan if (err) 3832e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 3840a708f8fSGustavo F. Padovan 3850a708f8fSGustavo F. Padovan if (parent) { 3860a708f8fSGustavo F. Padovan bt_accept_unlink(sk); 3870a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 3880a708f8fSGustavo F. Padovan } else 3890a708f8fSGustavo F. Padovan sk->sk_state_change(sk); 3900a708f8fSGustavo F. Padovan 3916be36555SAndrei Emeltchenko release_sock(sk); 3926be36555SAndrei Emeltchenko 393c1360a1cSGustavo F. Padovan if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) && 394c1360a1cSGustavo F. Padovan test_bit(CONF_INPUT_DONE, &chan->conf_state))) 3956ff5abbfSGustavo F. Padovan return; 3962ead70b8SGustavo F. Padovan 39758d35f87SGustavo F. Padovan skb_queue_purge(&chan->tx_q); 3980a708f8fSGustavo F. Padovan 3990c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_ERTM) { 4000a708f8fSGustavo F. Padovan struct srej_list *l, *tmp; 4010a708f8fSGustavo F. Padovan 4021a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 4031a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 4041a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 4050a708f8fSGustavo F. Padovan 406f1c6775bSGustavo F. Padovan skb_queue_purge(&chan->srej_q); 4070a708f8fSGustavo F. Padovan 40839d5a3eeSGustavo F. Padovan list_for_each_entry_safe(l, tmp, &chan->srej_l, list) { 4090a708f8fSGustavo F. Padovan list_del(&l->list); 4100a708f8fSGustavo F. Padovan kfree(l); 4110a708f8fSGustavo F. Padovan } 4120a708f8fSGustavo F. Padovan } 4130a708f8fSGustavo F. Padovan } 4140a708f8fSGustavo F. Padovan 4154519de9aSGustavo F. Padovan static void l2cap_chan_cleanup_listen(struct sock *parent) 4164519de9aSGustavo F. Padovan { 4174519de9aSGustavo F. Padovan struct sock *sk; 4184519de9aSGustavo F. Padovan 4194519de9aSGustavo F. Padovan BT_DBG("parent %p", parent); 4204519de9aSGustavo F. Padovan 4214519de9aSGustavo F. Padovan /* Close not yet accepted channels */ 4220f852724SGustavo F. Padovan while ((sk = bt_accept_dequeue(parent, NULL))) { 423ba3bd0eeSGustavo F. Padovan struct l2cap_chan *chan = l2cap_pi(sk)->chan; 4243df91ea2SAndrei Emeltchenko 4256be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 426c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 427ba3bd0eeSGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 4286be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 4293df91ea2SAndrei Emeltchenko 430ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 4310f852724SGustavo F. Padovan } 4324519de9aSGustavo F. Padovan } 4334519de9aSGustavo F. Padovan 4340f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason) 4354519de9aSGustavo F. Padovan { 4364519de9aSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 4374519de9aSGustavo F. Padovan struct sock *sk = chan->sk; 4384519de9aSGustavo F. Padovan 439e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s sk %p", chan, 440e05dcc32SAndrei Emeltchenko state_to_string(chan->state), sk); 4414519de9aSGustavo F. Padovan 44289bc500eSGustavo F. Padovan switch (chan->state) { 4434519de9aSGustavo F. Padovan case BT_LISTEN: 4446be36555SAndrei Emeltchenko lock_sock(sk); 4454519de9aSGustavo F. Padovan l2cap_chan_cleanup_listen(sk); 44689bc500eSGustavo F. Padovan 4470e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CLOSED); 44889bc500eSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 4496be36555SAndrei Emeltchenko release_sock(sk); 4504519de9aSGustavo F. Padovan break; 4514519de9aSGustavo F. Padovan 4524519de9aSGustavo F. Padovan case BT_CONNECTED: 4534519de9aSGustavo F. Padovan case BT_CONFIG: 454715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && 4554519de9aSGustavo F. Padovan conn->hcon->type == ACL_LINK) { 456c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 457c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 4584519de9aSGustavo F. Padovan l2cap_send_disconn_req(conn, chan, reason); 4594519de9aSGustavo F. Padovan } else 4604519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 4614519de9aSGustavo F. Padovan break; 4624519de9aSGustavo F. Padovan 4634519de9aSGustavo F. Padovan case BT_CONNECT2: 464715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && 4654519de9aSGustavo F. Padovan conn->hcon->type == ACL_LINK) { 4664519de9aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 4674519de9aSGustavo F. Padovan __u16 result; 4684519de9aSGustavo F. Padovan 4694519de9aSGustavo F. Padovan if (bt_sk(sk)->defer_setup) 4704519de9aSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 4714519de9aSGustavo F. Padovan else 4724519de9aSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 47389bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_DISCONN); 4744519de9aSGustavo F. Padovan 4754519de9aSGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 4764519de9aSGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 4774519de9aSGustavo F. Padovan rsp.result = cpu_to_le16(result); 4784519de9aSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 4794519de9aSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 4804519de9aSGustavo F. Padovan sizeof(rsp), &rsp); 4814519de9aSGustavo F. Padovan } 4824519de9aSGustavo F. Padovan 4834519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 4844519de9aSGustavo F. Padovan break; 4854519de9aSGustavo F. Padovan 4864519de9aSGustavo F. Padovan case BT_CONNECT: 4874519de9aSGustavo F. Padovan case BT_DISCONN: 4884519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 4894519de9aSGustavo F. Padovan break; 4904519de9aSGustavo F. Padovan 4914519de9aSGustavo F. Padovan default: 4926be36555SAndrei Emeltchenko lock_sock(sk); 4934519de9aSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 4946be36555SAndrei Emeltchenko release_sock(sk); 4954519de9aSGustavo F. Padovan break; 4964519de9aSGustavo F. Padovan } 4974519de9aSGustavo F. Padovan } 4984519de9aSGustavo F. Padovan 4994343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) 5000a708f8fSGustavo F. Padovan { 501715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_RAW) { 5024343478fSGustavo F. Padovan switch (chan->sec_level) { 5030a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 5040a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING_MITM; 5050a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 5060a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING; 5070a708f8fSGustavo F. Padovan default: 5080a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 5090a708f8fSGustavo F. Padovan } 510fe4128e0SGustavo F. Padovan } else if (chan->psm == cpu_to_le16(0x0001)) { 5114343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_LOW) 5124343478fSGustavo F. Padovan chan->sec_level = BT_SECURITY_SDP; 5130a708f8fSGustavo F. Padovan 5144343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_HIGH) 5150a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING_MITM; 5160a708f8fSGustavo F. Padovan else 5170a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 5180a708f8fSGustavo F. Padovan } else { 5194343478fSGustavo F. Padovan switch (chan->sec_level) { 5200a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 5210a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING_MITM; 5220a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 5230a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING; 5240a708f8fSGustavo F. Padovan default: 5250a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 5260a708f8fSGustavo F. Padovan } 5270a708f8fSGustavo F. Padovan } 5280a708f8fSGustavo F. Padovan } 5290a708f8fSGustavo F. Padovan 5300a708f8fSGustavo F. Padovan /* Service level security */ 531d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan) 5320a708f8fSGustavo F. Padovan { 5338c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 5340a708f8fSGustavo F. Padovan __u8 auth_type; 5350a708f8fSGustavo F. Padovan 5364343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 5370a708f8fSGustavo F. Padovan 5384343478fSGustavo F. Padovan return hci_conn_security(conn->hcon, chan->sec_level, auth_type); 5390a708f8fSGustavo F. Padovan } 5400a708f8fSGustavo F. Padovan 541b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn) 5420a708f8fSGustavo F. Padovan { 5430a708f8fSGustavo F. Padovan u8 id; 5440a708f8fSGustavo F. Padovan 5450a708f8fSGustavo F. Padovan /* Get next available identificator. 5460a708f8fSGustavo F. Padovan * 1 - 128 are used by kernel. 5470a708f8fSGustavo F. Padovan * 129 - 199 are reserved. 5480a708f8fSGustavo F. Padovan * 200 - 254 are used by utilities like l2ping, etc. 5490a708f8fSGustavo F. Padovan */ 5500a708f8fSGustavo F. Padovan 551333055f2SGustavo F. Padovan spin_lock(&conn->lock); 5520a708f8fSGustavo F. Padovan 5530a708f8fSGustavo F. Padovan if (++conn->tx_ident > 128) 5540a708f8fSGustavo F. Padovan conn->tx_ident = 1; 5550a708f8fSGustavo F. Padovan 5560a708f8fSGustavo F. Padovan id = conn->tx_ident; 5570a708f8fSGustavo F. Padovan 558333055f2SGustavo F. Padovan spin_unlock(&conn->lock); 5590a708f8fSGustavo F. Padovan 5600a708f8fSGustavo F. Padovan return id; 5610a708f8fSGustavo F. Padovan } 5620a708f8fSGustavo F. Padovan 5634519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) 5640a708f8fSGustavo F. Padovan { 5650a708f8fSGustavo F. Padovan struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); 5660a708f8fSGustavo F. Padovan u8 flags; 5670a708f8fSGustavo F. Padovan 5680a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x", code); 5690a708f8fSGustavo F. Padovan 5700a708f8fSGustavo F. Padovan if (!skb) 5710a708f8fSGustavo F. Padovan return; 5720a708f8fSGustavo F. Padovan 5730a708f8fSGustavo F. Padovan if (lmp_no_flush_capable(conn->hcon->hdev)) 5740a708f8fSGustavo F. Padovan flags = ACL_START_NO_FLUSH; 5750a708f8fSGustavo F. Padovan else 5760a708f8fSGustavo F. Padovan flags = ACL_START; 5770a708f8fSGustavo F. Padovan 57814b12d0bSJaikumar Ganesh bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON; 5795e59b791SLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 58014b12d0bSJaikumar Ganesh 58173d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, flags); 5820a708f8fSGustavo F. Padovan } 5830a708f8fSGustavo F. Padovan 58473d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) 58573d80debSLuiz Augusto von Dentz { 58673d80debSLuiz Augusto von Dentz struct hci_conn *hcon = chan->conn->hcon; 58773d80debSLuiz Augusto von Dentz u16 flags; 58873d80debSLuiz Augusto von Dentz 58973d80debSLuiz Augusto von Dentz BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, 59073d80debSLuiz Augusto von Dentz skb->priority); 59173d80debSLuiz Augusto von Dentz 59273d80debSLuiz Augusto von Dentz if (!test_bit(FLAG_FLUSHABLE, &chan->flags) && 59373d80debSLuiz Augusto von Dentz lmp_no_flush_capable(hcon->hdev)) 59473d80debSLuiz Augusto von Dentz flags = ACL_START_NO_FLUSH; 59573d80debSLuiz Augusto von Dentz else 59673d80debSLuiz Augusto von Dentz flags = ACL_START; 59773d80debSLuiz Augusto von Dentz 59873d80debSLuiz Augusto von Dentz bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); 59973d80debSLuiz Augusto von Dentz hci_send_acl(chan->conn->hchan, skb, flags); 6000a708f8fSGustavo F. Padovan } 6010a708f8fSGustavo F. Padovan 60288843ab0SAndrei Emeltchenko static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control) 6030a708f8fSGustavo F. Padovan { 6040a708f8fSGustavo F. Padovan struct sk_buff *skb; 6050a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 6068c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 607e4ca6d98SAndrei Emeltchenko int count, hlen; 6080a708f8fSGustavo F. Padovan 60989bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 6100a708f8fSGustavo F. Padovan return; 6110a708f8fSGustavo F. Padovan 612e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 613e4ca6d98SAndrei Emeltchenko hlen = L2CAP_EXT_HDR_SIZE; 614e4ca6d98SAndrei Emeltchenko else 615e4ca6d98SAndrei Emeltchenko hlen = L2CAP_ENH_HDR_SIZE; 6160a708f8fSGustavo F. Padovan 6170a708f8fSGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 61803a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 6190a708f8fSGustavo F. Padovan 62088843ab0SAndrei Emeltchenko BT_DBG("chan %p, control 0x%8.8x", chan, control); 6210a708f8fSGustavo F. Padovan 6220a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, hlen); 623793c2f1cSAndrei Emeltchenko 624793c2f1cSAndrei Emeltchenko control |= __set_sframe(chan); 6250a708f8fSGustavo F. Padovan 626e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 62703f6715dSAndrei Emeltchenko control |= __set_ctrl_final(chan); 6280a708f8fSGustavo F. Padovan 629e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state)) 630e3781735SAndrei Emeltchenko control |= __set_ctrl_poll(chan); 6310a708f8fSGustavo F. Padovan 6320a708f8fSGustavo F. Padovan skb = bt_skb_alloc(count, GFP_ATOMIC); 6330a708f8fSGustavo F. Padovan if (!skb) 6340a708f8fSGustavo F. Padovan return; 6350a708f8fSGustavo F. Padovan 6360a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 6370a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); 638fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 63988843ab0SAndrei Emeltchenko 64088843ab0SAndrei Emeltchenko __put_control(chan, control, skb_put(skb, __ctrl_size(chan))); 6410a708f8fSGustavo F. Padovan 64247d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 64303a51213SAndrei Emeltchenko u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE); 64403a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 6450a708f8fSGustavo F. Padovan } 6460a708f8fSGustavo F. Padovan 64773d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 64873d80debSLuiz Augusto von Dentz l2cap_do_send(chan, skb); 6490a708f8fSGustavo F. Padovan } 6500a708f8fSGustavo F. Padovan 65188843ab0SAndrei Emeltchenko static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control) 6520a708f8fSGustavo F. Padovan { 653e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 654ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); 655e2ab4353SGustavo F. Padovan set_bit(CONN_RNR_SENT, &chan->conn_state); 6560a708f8fSGustavo F. Padovan } else 657ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 6580a708f8fSGustavo F. Padovan 6590b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 6600a708f8fSGustavo F. Padovan 661525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 6620a708f8fSGustavo F. Padovan } 6630a708f8fSGustavo F. Padovan 664b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) 6650a708f8fSGustavo F. Padovan { 666c1360a1cSGustavo F. Padovan return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); 6670a708f8fSGustavo F. Padovan } 6680a708f8fSGustavo F. Padovan 6699b27f350SAndrei Emeltchenko static void l2cap_send_conn_req(struct l2cap_chan *chan) 6709b27f350SAndrei Emeltchenko { 6719b27f350SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 6729b27f350SAndrei Emeltchenko struct l2cap_conn_req req; 6739b27f350SAndrei Emeltchenko 6749b27f350SAndrei Emeltchenko req.scid = cpu_to_le16(chan->scid); 6759b27f350SAndrei Emeltchenko req.psm = chan->psm; 6769b27f350SAndrei Emeltchenko 6779b27f350SAndrei Emeltchenko chan->ident = l2cap_get_ident(conn); 6789b27f350SAndrei Emeltchenko 6799b27f350SAndrei Emeltchenko set_bit(CONF_CONNECT_PEND, &chan->conf_state); 6809b27f350SAndrei Emeltchenko 6819b27f350SAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); 6829b27f350SAndrei Emeltchenko } 6839b27f350SAndrei Emeltchenko 684fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan) 6850a708f8fSGustavo F. Padovan { 6868c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 6870a708f8fSGustavo F. Padovan 6880a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { 6890a708f8fSGustavo F. Padovan if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) 6900a708f8fSGustavo F. Padovan return; 6910a708f8fSGustavo F. Padovan 692d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan) && 6939b27f350SAndrei Emeltchenko __l2cap_no_conn_pending(chan)) 6949b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 6950a708f8fSGustavo F. Padovan } else { 6960a708f8fSGustavo F. Padovan struct l2cap_info_req req; 6970a708f8fSGustavo F. Padovan req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 6980a708f8fSGustavo F. Padovan 6990a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 7000a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 7010a708f8fSGustavo F. Padovan 702ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 7030a708f8fSGustavo F. Padovan 7040a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 7050a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 7060a708f8fSGustavo F. Padovan } 7070a708f8fSGustavo F. Padovan } 7080a708f8fSGustavo F. Padovan 7090a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) 7100a708f8fSGustavo F. Padovan { 7110a708f8fSGustavo F. Padovan u32 local_feat_mask = l2cap_feat_mask; 7120a708f8fSGustavo F. Padovan if (!disable_ertm) 7130a708f8fSGustavo F. Padovan local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING; 7140a708f8fSGustavo F. Padovan 7150a708f8fSGustavo F. Padovan switch (mode) { 7160a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 7170a708f8fSGustavo F. Padovan return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask; 7180a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 7190a708f8fSGustavo F. Padovan return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask; 7200a708f8fSGustavo F. Padovan default: 7210a708f8fSGustavo F. Padovan return 0x00; 7220a708f8fSGustavo F. Padovan } 7230a708f8fSGustavo F. Padovan } 7240a708f8fSGustavo F. Padovan 7254519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err) 7260a708f8fSGustavo F. Padovan { 7276be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 7280a708f8fSGustavo F. Padovan struct l2cap_disconn_req req; 7290a708f8fSGustavo F. Padovan 7300a708f8fSGustavo F. Padovan if (!conn) 7310a708f8fSGustavo F. Padovan return; 7320a708f8fSGustavo F. Padovan 7330c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_ERTM) { 7341a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 7351a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 7361a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 7370a708f8fSGustavo F. Padovan } 7380a708f8fSGustavo F. Padovan 739fe4128e0SGustavo F. Padovan req.dcid = cpu_to_le16(chan->dcid); 740fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 7410a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 7420a708f8fSGustavo F. Padovan L2CAP_DISCONN_REQ, sizeof(req), &req); 7430a708f8fSGustavo F. Padovan 7446be36555SAndrei Emeltchenko lock_sock(sk); 7450e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_DISCONN); 7462e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 7476be36555SAndrei Emeltchenko release_sock(sk); 7480a708f8fSGustavo F. Padovan } 7490a708f8fSGustavo F. Padovan 7500a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */ 7510a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn) 7520a708f8fSGustavo F. Padovan { 7533df91ea2SAndrei Emeltchenko struct l2cap_chan *chan, *tmp; 7540a708f8fSGustavo F. Padovan 7550a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 7560a708f8fSGustavo F. Padovan 7573df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 7580a708f8fSGustavo F. Padovan 7593df91ea2SAndrei Emeltchenko list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 76048454079SGustavo F. Padovan struct sock *sk = chan->sk; 761baa7e1faSGustavo F. Padovan 7626be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 7630a708f8fSGustavo F. Padovan 764715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 7656be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 7660a708f8fSGustavo F. Padovan continue; 7670a708f8fSGustavo F. Padovan } 7680a708f8fSGustavo F. Padovan 76989bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 770d45fc423SGustavo F. Padovan if (!l2cap_chan_check_security(chan) || 771b4450035SGustavo F. Padovan !__l2cap_no_conn_pending(chan)) { 7726be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 7730a708f8fSGustavo F. Padovan continue; 7740a708f8fSGustavo F. Padovan } 7750a708f8fSGustavo F. Padovan 776c1360a1cSGustavo F. Padovan if (!l2cap_mode_supported(chan->mode, conn->feat_mask) 777c1360a1cSGustavo F. Padovan && test_bit(CONF_STATE2_DEVICE, 778c1360a1cSGustavo F. Padovan &chan->conf_state)) { 7790f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 7806be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 7810a708f8fSGustavo F. Padovan continue; 7820a708f8fSGustavo F. Padovan } 7830a708f8fSGustavo F. Padovan 7849b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 7850a708f8fSGustavo F. Padovan 78689bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 7870a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 7880a708f8fSGustavo F. Padovan char buf[128]; 789fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 790fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 7910a708f8fSGustavo F. Padovan 792d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 7936be36555SAndrei Emeltchenko lock_sock(sk); 7940a708f8fSGustavo F. Padovan if (bt_sk(sk)->defer_setup) { 7950a708f8fSGustavo F. Padovan struct sock *parent = bt_sk(sk)->parent; 7960a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_PEND); 7970a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND); 79805e9a2f6SIlia Kolomisnky if (parent) 7990a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 8000a708f8fSGustavo F. Padovan 8010a708f8fSGustavo F. Padovan } else { 8020e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 8030a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 8040a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 8050a708f8fSGustavo F. Padovan } 8066be36555SAndrei Emeltchenko release_sock(sk); 8070a708f8fSGustavo F. Padovan } else { 8080a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_PEND); 8090a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND); 8100a708f8fSGustavo F. Padovan } 8110a708f8fSGustavo F. Padovan 812fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 813fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 8140a708f8fSGustavo F. Padovan 815c1360a1cSGustavo F. Padovan if (test_bit(CONF_REQ_SENT, &chan->conf_state) || 8160a708f8fSGustavo F. Padovan rsp.result != L2CAP_CR_SUCCESS) { 8176be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 8180a708f8fSGustavo F. Padovan continue; 8190a708f8fSGustavo F. Padovan } 8200a708f8fSGustavo F. Padovan 821c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 8220a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 82373ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 82473ffa904SGustavo F. Padovan chan->num_conf_req++; 8250a708f8fSGustavo F. Padovan } 8260a708f8fSGustavo F. Padovan 8276be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 8280a708f8fSGustavo F. Padovan } 8290a708f8fSGustavo F. Padovan 8303df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 8310a708f8fSGustavo F. Padovan } 8320a708f8fSGustavo F. Padovan 833b62f328bSVille Tervo /* Find socket with cid and source bdaddr. 834b62f328bSVille Tervo * Returns closest match, locked. 835b62f328bSVille Tervo */ 83623691d75SGustavo F. Padovan static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src) 837b62f328bSVille Tervo { 83823691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 839b62f328bSVille Tervo 84023691d75SGustavo F. Padovan read_lock(&chan_list_lock); 841b62f328bSVille Tervo 84223691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 84323691d75SGustavo F. Padovan struct sock *sk = c->sk; 844fe4128e0SGustavo F. Padovan 84589bc500eSGustavo F. Padovan if (state && c->state != state) 846b62f328bSVille Tervo continue; 847b62f328bSVille Tervo 84823691d75SGustavo F. Padovan if (c->scid == cid) { 849b62f328bSVille Tervo /* Exact match. */ 85023691d75SGustavo F. Padovan if (!bacmp(&bt_sk(sk)->src, src)) { 85123691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 85223691d75SGustavo F. Padovan return c; 85323691d75SGustavo F. Padovan } 854b62f328bSVille Tervo 855b62f328bSVille Tervo /* Closest match */ 856b62f328bSVille Tervo if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) 85723691d75SGustavo F. Padovan c1 = c; 858b62f328bSVille Tervo } 859b62f328bSVille Tervo } 860280f294fSGustavo F. Padovan 86123691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 862b62f328bSVille Tervo 86323691d75SGustavo F. Padovan return c1; 864b62f328bSVille Tervo } 865b62f328bSVille Tervo 866b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn) 867b62f328bSVille Tervo { 868c916fbe4SGustavo F. Padovan struct sock *parent, *sk; 86923691d75SGustavo F. Padovan struct l2cap_chan *chan, *pchan; 870b62f328bSVille Tervo 871b62f328bSVille Tervo BT_DBG(""); 872b62f328bSVille Tervo 873b62f328bSVille Tervo /* Check if we have socket listening on cid */ 87423691d75SGustavo F. Padovan pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA, 875b62f328bSVille Tervo conn->src); 87623691d75SGustavo F. Padovan if (!pchan) 877b62f328bSVille Tervo return; 878b62f328bSVille Tervo 87923691d75SGustavo F. Padovan parent = pchan->sk; 88023691d75SGustavo F. Padovan 881aa2ac881SGustavo F. Padovan lock_sock(parent); 88262f3a2cfSGustavo F. Padovan 883b62f328bSVille Tervo /* Check for backlog size */ 884b62f328bSVille Tervo if (sk_acceptq_is_full(parent)) { 885b62f328bSVille Tervo BT_DBG("backlog full %d", parent->sk_ack_backlog); 886b62f328bSVille Tervo goto clean; 887b62f328bSVille Tervo } 888b62f328bSVille Tervo 88980808e43SGustavo F. Padovan chan = pchan->ops->new_connection(pchan->data); 89080808e43SGustavo F. Padovan if (!chan) 891b62f328bSVille Tervo goto clean; 892b62f328bSVille Tervo 89380808e43SGustavo F. Padovan sk = chan->sk; 8945d41ce1dSGustavo F. Padovan 895b62f328bSVille Tervo hci_conn_hold(conn->hcon); 896b62f328bSVille Tervo 897b62f328bSVille Tervo bacpy(&bt_sk(sk)->src, conn->src); 898b62f328bSVille Tervo bacpy(&bt_sk(sk)->dst, conn->dst); 899b62f328bSVille Tervo 900d1010240SGustavo F. Padovan bt_accept_enqueue(parent, sk); 901d1010240SGustavo F. Padovan 9023d57dc68SGustavo F. Padovan l2cap_chan_add(conn, chan); 90348454079SGustavo F. Padovan 904c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 905b62f328bSVille Tervo 9060e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECTED); 907b62f328bSVille Tervo parent->sk_data_ready(parent, 0); 908b62f328bSVille Tervo 909b62f328bSVille Tervo clean: 910aa2ac881SGustavo F. Padovan release_sock(parent); 911b62f328bSVille Tervo } 912b62f328bSVille Tervo 913cf4cd009SAndrei Emeltchenko static void l2cap_chan_ready(struct l2cap_chan *chan) 914f1cb9af5SVinicius Costa Gomes { 915cf4cd009SAndrei Emeltchenko struct sock *sk = chan->sk; 9166be36555SAndrei Emeltchenko struct sock *parent; 9176be36555SAndrei Emeltchenko 9186be36555SAndrei Emeltchenko lock_sock(sk); 9196be36555SAndrei Emeltchenko 9206be36555SAndrei Emeltchenko parent = bt_sk(sk)->parent; 921f1cb9af5SVinicius Costa Gomes 922f1cb9af5SVinicius Costa Gomes BT_DBG("sk %p, parent %p", sk, parent); 923f1cb9af5SVinicius Costa Gomes 924f1cb9af5SVinicius Costa Gomes chan->conf_state = 0; 925f1cb9af5SVinicius Costa Gomes __clear_chan_timer(chan); 926f1cb9af5SVinicius Costa Gomes 9270e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECTED); 928f1cb9af5SVinicius Costa Gomes sk->sk_state_change(sk); 929f1cb9af5SVinicius Costa Gomes 930f1cb9af5SVinicius Costa Gomes if (parent) 931f1cb9af5SVinicius Costa Gomes parent->sk_data_ready(parent, 0); 9326be36555SAndrei Emeltchenko 9336be36555SAndrei Emeltchenko release_sock(sk); 934f1cb9af5SVinicius Costa Gomes } 935f1cb9af5SVinicius Costa Gomes 9360a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn) 9370a708f8fSGustavo F. Padovan { 93848454079SGustavo F. Padovan struct l2cap_chan *chan; 9390a708f8fSGustavo F. Padovan 9400a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 9410a708f8fSGustavo F. Padovan 942b62f328bSVille Tervo if (!conn->hcon->out && conn->hcon->type == LE_LINK) 943b62f328bSVille Tervo l2cap_le_conn_ready(conn); 944b62f328bSVille Tervo 945160dc6acSVinicius Costa Gomes if (conn->hcon->out && conn->hcon->type == LE_LINK) 946160dc6acSVinicius Costa Gomes smp_conn_security(conn, conn->hcon->pending_sec_level); 947160dc6acSVinicius Costa Gomes 9483df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 9490a708f8fSGustavo F. Padovan 9503df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 951baa7e1faSGustavo F. Padovan 9526be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 9530a708f8fSGustavo F. Padovan 95463128451SVinicius Costa Gomes if (conn->hcon->type == LE_LINK) { 955b501d6a1SAnderson Briglia if (smp_conn_security(conn, chan->sec_level)) 956cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 957acd7d370SVille Tervo 95863128451SVinicius Costa Gomes } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 9596be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 960c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 9616be36555SAndrei Emeltchenko lock_sock(sk); 9620e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECTED); 9630a708f8fSGustavo F. Padovan sk->sk_state_change(sk); 9646be36555SAndrei Emeltchenko release_sock(sk); 965b501d6a1SAnderson Briglia 96689bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT) 967fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 9680a708f8fSGustavo F. Padovan 9696be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 9700a708f8fSGustavo F. Padovan } 9710a708f8fSGustavo F. Padovan 9723df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 9730a708f8fSGustavo F. Padovan } 9740a708f8fSGustavo F. Padovan 9750a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */ 9760a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) 9770a708f8fSGustavo F. Padovan { 97848454079SGustavo F. Padovan struct l2cap_chan *chan; 9790a708f8fSGustavo F. Padovan 9800a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 9810a708f8fSGustavo F. Padovan 9823df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 9830a708f8fSGustavo F. Padovan 9843df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 985ecf61bdbSAndrei Emeltchenko if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) 9862e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 9870a708f8fSGustavo F. Padovan } 9880a708f8fSGustavo F. Padovan 9893df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 9900a708f8fSGustavo F. Padovan } 9910a708f8fSGustavo F. Padovan 992f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work) 9930a708f8fSGustavo F. Padovan { 994f878fcadSGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 995030013d8SGustavo F. Padovan info_timer.work); 9960a708f8fSGustavo F. Padovan 9970a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 9980a708f8fSGustavo F. Padovan conn->info_ident = 0; 9990a708f8fSGustavo F. Padovan 10000a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 10010a708f8fSGustavo F. Padovan } 10020a708f8fSGustavo F. Padovan 10035d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err) 10045d3de7dfSVinicius Costa Gomes { 10055d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 10065d3de7dfSVinicius Costa Gomes struct l2cap_chan *chan, *l; 10075d3de7dfSVinicius Costa Gomes 10085d3de7dfSVinicius Costa Gomes if (!conn) 10095d3de7dfSVinicius Costa Gomes return; 10105d3de7dfSVinicius Costa Gomes 10115d3de7dfSVinicius Costa Gomes BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); 10125d3de7dfSVinicius Costa Gomes 10135d3de7dfSVinicius Costa Gomes kfree_skb(conn->rx_skb); 10145d3de7dfSVinicius Costa Gomes 10153df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 10163df91ea2SAndrei Emeltchenko 10175d3de7dfSVinicius Costa Gomes /* Kill channels */ 10185d3de7dfSVinicius Costa Gomes list_for_each_entry_safe(chan, l, &conn->chan_l, list) { 10196be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 10206be36555SAndrei Emeltchenko 10215d3de7dfSVinicius Costa Gomes l2cap_chan_del(chan, err); 10226be36555SAndrei Emeltchenko 10236be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10246be36555SAndrei Emeltchenko 10255d3de7dfSVinicius Costa Gomes chan->ops->close(chan->data); 10265d3de7dfSVinicius Costa Gomes } 10275d3de7dfSVinicius Costa Gomes 10283df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 10293df91ea2SAndrei Emeltchenko 103073d80debSLuiz Augusto von Dentz hci_chan_del(conn->hchan); 103173d80debSLuiz Augusto von Dentz 10325d3de7dfSVinicius Costa Gomes if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1033127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->info_timer); 10345d3de7dfSVinicius Costa Gomes 103551a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) { 1036127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->security_timer); 10378aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 1038d26a2345SVinicius Costa Gomes } 10395d3de7dfSVinicius Costa Gomes 10405d3de7dfSVinicius Costa Gomes hcon->l2cap_data = NULL; 10415d3de7dfSVinicius Costa Gomes kfree(conn); 10425d3de7dfSVinicius Costa Gomes } 10435d3de7dfSVinicius Costa Gomes 10446c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work) 10455d3de7dfSVinicius Costa Gomes { 10466c9d42a1SGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 10476c9d42a1SGustavo F. Padovan security_timer.work); 10485d3de7dfSVinicius Costa Gomes 10495d3de7dfSVinicius Costa Gomes l2cap_conn_del(conn->hcon, ETIMEDOUT); 10505d3de7dfSVinicius Costa Gomes } 10515d3de7dfSVinicius Costa Gomes 10520a708f8fSGustavo F. Padovan static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) 10530a708f8fSGustavo F. Padovan { 10540a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 105573d80debSLuiz Augusto von Dentz struct hci_chan *hchan; 10560a708f8fSGustavo F. Padovan 10570a708f8fSGustavo F. Padovan if (conn || status) 10580a708f8fSGustavo F. Padovan return conn; 10590a708f8fSGustavo F. Padovan 106073d80debSLuiz Augusto von Dentz hchan = hci_chan_create(hcon); 106173d80debSLuiz Augusto von Dentz if (!hchan) 10620a708f8fSGustavo F. Padovan return NULL; 10630a708f8fSGustavo F. Padovan 106473d80debSLuiz Augusto von Dentz conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC); 106573d80debSLuiz Augusto von Dentz if (!conn) { 106673d80debSLuiz Augusto von Dentz hci_chan_del(hchan); 106773d80debSLuiz Augusto von Dentz return NULL; 106873d80debSLuiz Augusto von Dentz } 106973d80debSLuiz Augusto von Dentz 10700a708f8fSGustavo F. Padovan hcon->l2cap_data = conn; 10710a708f8fSGustavo F. Padovan conn->hcon = hcon; 107273d80debSLuiz Augusto von Dentz conn->hchan = hchan; 10730a708f8fSGustavo F. Padovan 107473d80debSLuiz Augusto von Dentz BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); 10750a708f8fSGustavo F. Padovan 1076acd7d370SVille Tervo if (hcon->hdev->le_mtu && hcon->type == LE_LINK) 1077acd7d370SVille Tervo conn->mtu = hcon->hdev->le_mtu; 1078acd7d370SVille Tervo else 10790a708f8fSGustavo F. Padovan conn->mtu = hcon->hdev->acl_mtu; 1080acd7d370SVille Tervo 10810a708f8fSGustavo F. Padovan conn->src = &hcon->hdev->bdaddr; 10820a708f8fSGustavo F. Padovan conn->dst = &hcon->dst; 10830a708f8fSGustavo F. Padovan 10840a708f8fSGustavo F. Padovan conn->feat_mask = 0; 10850a708f8fSGustavo F. Padovan 10860a708f8fSGustavo F. Padovan spin_lock_init(&conn->lock); 10873df91ea2SAndrei Emeltchenko mutex_init(&conn->chan_lock); 1088baa7e1faSGustavo F. Padovan 1089baa7e1faSGustavo F. Padovan INIT_LIST_HEAD(&conn->chan_l); 10900a708f8fSGustavo F. Padovan 10915d3de7dfSVinicius Costa Gomes if (hcon->type == LE_LINK) 10926c9d42a1SGustavo F. Padovan INIT_DELAYED_WORK(&conn->security_timer, security_timeout); 10935d3de7dfSVinicius Costa Gomes else 1094030013d8SGustavo F. Padovan INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); 10950a708f8fSGustavo F. Padovan 10969f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 10970a708f8fSGustavo F. Padovan 10980a708f8fSGustavo F. Padovan return conn; 10990a708f8fSGustavo F. Padovan } 11000a708f8fSGustavo F. Padovan 11010a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */ 11020a708f8fSGustavo F. Padovan 11030a708f8fSGustavo F. Padovan /* Find socket with psm and source bdaddr. 11040a708f8fSGustavo F. Padovan * Returns closest match. 11050a708f8fSGustavo F. Padovan */ 110623691d75SGustavo F. Padovan static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src) 11070a708f8fSGustavo F. Padovan { 110823691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 11090a708f8fSGustavo F. Padovan 111023691d75SGustavo F. Padovan read_lock(&chan_list_lock); 11110a708f8fSGustavo F. Padovan 111223691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 111323691d75SGustavo F. Padovan struct sock *sk = c->sk; 1114fe4128e0SGustavo F. Padovan 111589bc500eSGustavo F. Padovan if (state && c->state != state) 11160a708f8fSGustavo F. Padovan continue; 11170a708f8fSGustavo F. Padovan 111823691d75SGustavo F. Padovan if (c->psm == psm) { 11190a708f8fSGustavo F. Padovan /* Exact match. */ 112023691d75SGustavo F. Padovan if (!bacmp(&bt_sk(sk)->src, src)) { 1121a7567b20SJohannes Berg read_unlock(&chan_list_lock); 112223691d75SGustavo F. Padovan return c; 112323691d75SGustavo F. Padovan } 11240a708f8fSGustavo F. Padovan 11250a708f8fSGustavo F. Padovan /* Closest match */ 11260a708f8fSGustavo F. Padovan if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) 112723691d75SGustavo F. Padovan c1 = c; 11280a708f8fSGustavo F. Padovan } 11290a708f8fSGustavo F. Padovan } 11300a708f8fSGustavo F. Padovan 113123691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 11320a708f8fSGustavo F. Padovan 113323691d75SGustavo F. Padovan return c1; 11340a708f8fSGustavo F. Padovan } 11350a708f8fSGustavo F. Padovan 1136cbe8fed4SJohan Hedberg int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst) 11370a708f8fSGustavo F. Padovan { 11385d41ce1dSGustavo F. Padovan struct sock *sk = chan->sk; 11390a708f8fSGustavo F. Padovan bdaddr_t *src = &bt_sk(sk)->src; 11400a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 11410a708f8fSGustavo F. Padovan struct hci_conn *hcon; 11420a708f8fSGustavo F. Padovan struct hci_dev *hdev; 11430a708f8fSGustavo F. Padovan __u8 auth_type; 11440a708f8fSGustavo F. Padovan int err; 11450a708f8fSGustavo F. Padovan 11460a708f8fSGustavo F. Padovan BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), 1147097db76cSAndrei Emeltchenko __le16_to_cpu(chan->psm)); 11480a708f8fSGustavo F. Padovan 11490a708f8fSGustavo F. Padovan hdev = hci_get_route(dst, src); 11500a708f8fSGustavo F. Padovan if (!hdev) 11510a708f8fSGustavo F. Padovan return -EHOSTUNREACH; 11520a708f8fSGustavo F. Padovan 115309fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 11540a708f8fSGustavo F. Padovan 11556be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 115603a00194SGustavo F. Padovan 115703a00194SGustavo F. Padovan /* PSM must be odd and lsb of upper byte must be 0 */ 115803a00194SGustavo F. Padovan if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid && 115903a00194SGustavo F. Padovan chan->chan_type != L2CAP_CHAN_RAW) { 116003a00194SGustavo F. Padovan err = -EINVAL; 116103a00194SGustavo F. Padovan goto done; 116203a00194SGustavo F. Padovan } 116303a00194SGustavo F. Padovan 116403a00194SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) { 116503a00194SGustavo F. Padovan err = -EINVAL; 116603a00194SGustavo F. Padovan goto done; 116703a00194SGustavo F. Padovan } 116803a00194SGustavo F. Padovan 116903a00194SGustavo F. Padovan switch (chan->mode) { 117003a00194SGustavo F. Padovan case L2CAP_MODE_BASIC: 117103a00194SGustavo F. Padovan break; 117203a00194SGustavo F. Padovan case L2CAP_MODE_ERTM: 117303a00194SGustavo F. Padovan case L2CAP_MODE_STREAMING: 117403a00194SGustavo F. Padovan if (!disable_ertm) 117503a00194SGustavo F. Padovan break; 117603a00194SGustavo F. Padovan /* fall through */ 117703a00194SGustavo F. Padovan default: 117803a00194SGustavo F. Padovan err = -ENOTSUPP; 117903a00194SGustavo F. Padovan goto done; 118003a00194SGustavo F. Padovan } 118103a00194SGustavo F. Padovan 11826be36555SAndrei Emeltchenko lock_sock(sk); 11836be36555SAndrei Emeltchenko 118403a00194SGustavo F. Padovan switch (sk->sk_state) { 118503a00194SGustavo F. Padovan case BT_CONNECT: 118603a00194SGustavo F. Padovan case BT_CONNECT2: 118703a00194SGustavo F. Padovan case BT_CONFIG: 118803a00194SGustavo F. Padovan /* Already connecting */ 118903a00194SGustavo F. Padovan err = 0; 11906be36555SAndrei Emeltchenko release_sock(sk); 119103a00194SGustavo F. Padovan goto done; 119203a00194SGustavo F. Padovan 119303a00194SGustavo F. Padovan case BT_CONNECTED: 119403a00194SGustavo F. Padovan /* Already connected */ 119503a00194SGustavo F. Padovan err = -EISCONN; 11966be36555SAndrei Emeltchenko release_sock(sk); 119703a00194SGustavo F. Padovan goto done; 119803a00194SGustavo F. Padovan 119903a00194SGustavo F. Padovan case BT_OPEN: 120003a00194SGustavo F. Padovan case BT_BOUND: 120103a00194SGustavo F. Padovan /* Can connect */ 120203a00194SGustavo F. Padovan break; 120303a00194SGustavo F. Padovan 120403a00194SGustavo F. Padovan default: 120503a00194SGustavo F. Padovan err = -EBADFD; 12066be36555SAndrei Emeltchenko release_sock(sk); 120703a00194SGustavo F. Padovan goto done; 120803a00194SGustavo F. Padovan } 120903a00194SGustavo F. Padovan 121003a00194SGustavo F. Padovan /* Set destination address and psm */ 12119219b2a0SGustavo F. Padovan bacpy(&bt_sk(sk)->dst, dst); 12126be36555SAndrei Emeltchenko 12136be36555SAndrei Emeltchenko release_sock(sk); 12146be36555SAndrei Emeltchenko 121503a00194SGustavo F. Padovan chan->psm = psm; 121603a00194SGustavo F. Padovan chan->dcid = cid; 12170a708f8fSGustavo F. Padovan 12184343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 12190a708f8fSGustavo F. Padovan 1220fe4128e0SGustavo F. Padovan if (chan->dcid == L2CAP_CID_LE_DATA) 1221acd7d370SVille Tervo hcon = hci_connect(hdev, LE_LINK, dst, 12224343478fSGustavo F. Padovan chan->sec_level, auth_type); 1223acd7d370SVille Tervo else 12240a708f8fSGustavo F. Padovan hcon = hci_connect(hdev, ACL_LINK, dst, 12254343478fSGustavo F. Padovan chan->sec_level, auth_type); 1226acd7d370SVille Tervo 122730e76272SVille Tervo if (IS_ERR(hcon)) { 122830e76272SVille Tervo err = PTR_ERR(hcon); 12290a708f8fSGustavo F. Padovan goto done; 123030e76272SVille Tervo } 12310a708f8fSGustavo F. Padovan 12320a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, 0); 12330a708f8fSGustavo F. Padovan if (!conn) { 12340a708f8fSGustavo F. Padovan hci_conn_put(hcon); 123530e76272SVille Tervo err = -ENOMEM; 12360a708f8fSGustavo F. Padovan goto done; 12370a708f8fSGustavo F. Padovan } 12380a708f8fSGustavo F. Padovan 12390a708f8fSGustavo F. Padovan /* Update source addr of the socket */ 12400a708f8fSGustavo F. Padovan bacpy(src, conn->src); 12410a708f8fSGustavo F. Padovan 12426be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 124348454079SGustavo F. Padovan l2cap_chan_add(conn, chan); 12446be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 124548454079SGustavo F. Padovan 12466be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECT); 1247c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 12480a708f8fSGustavo F. Padovan 12490a708f8fSGustavo F. Padovan if (hcon->state == BT_CONNECTED) { 1250715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1251c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 1252d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) 12536be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECTED); 12540a708f8fSGustavo F. Padovan } else 1255fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 12560a708f8fSGustavo F. Padovan } 12570a708f8fSGustavo F. Padovan 125830e76272SVille Tervo err = 0; 125930e76272SVille Tervo 12600a708f8fSGustavo F. Padovan done: 12616be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 126209fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 12630a708f8fSGustavo F. Padovan hci_dev_put(hdev); 12640a708f8fSGustavo F. Padovan return err; 12650a708f8fSGustavo F. Padovan } 12660a708f8fSGustavo F. Padovan 1267dcba0dbaSGustavo F. Padovan int __l2cap_wait_ack(struct sock *sk) 12680a708f8fSGustavo F. Padovan { 12698c1d787bSGustavo F. Padovan struct l2cap_chan *chan = l2cap_pi(sk)->chan; 12700a708f8fSGustavo F. Padovan DECLARE_WAITQUEUE(wait, current); 12710a708f8fSGustavo F. Padovan int err = 0; 12720a708f8fSGustavo F. Padovan int timeo = HZ/5; 12730a708f8fSGustavo F. Padovan 12740a708f8fSGustavo F. Padovan add_wait_queue(sk_sleep(sk), &wait); 12750a708f8fSGustavo F. Padovan set_current_state(TASK_INTERRUPTIBLE); 1276a71a0cf4SPeter Hurley while (chan->unacked_frames > 0 && chan->conn) { 12770a708f8fSGustavo F. Padovan if (!timeo) 12780a708f8fSGustavo F. Padovan timeo = HZ/5; 12790a708f8fSGustavo F. Padovan 12800a708f8fSGustavo F. Padovan if (signal_pending(current)) { 12810a708f8fSGustavo F. Padovan err = sock_intr_errno(timeo); 12820a708f8fSGustavo F. Padovan break; 12830a708f8fSGustavo F. Padovan } 12840a708f8fSGustavo F. Padovan 12850a708f8fSGustavo F. Padovan release_sock(sk); 12860a708f8fSGustavo F. Padovan timeo = schedule_timeout(timeo); 12870a708f8fSGustavo F. Padovan lock_sock(sk); 1288a71a0cf4SPeter Hurley set_current_state(TASK_INTERRUPTIBLE); 12890a708f8fSGustavo F. Padovan 12900a708f8fSGustavo F. Padovan err = sock_error(sk); 12910a708f8fSGustavo F. Padovan if (err) 12920a708f8fSGustavo F. Padovan break; 12930a708f8fSGustavo F. Padovan } 12940a708f8fSGustavo F. Padovan set_current_state(TASK_RUNNING); 12950a708f8fSGustavo F. Padovan remove_wait_queue(sk_sleep(sk), &wait); 12960a708f8fSGustavo F. Padovan return err; 12970a708f8fSGustavo F. Padovan } 12980a708f8fSGustavo F. Padovan 1299721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work) 13000a708f8fSGustavo F. Padovan { 1301721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1302721c4181SGustavo F. Padovan monitor_timer.work); 13030a708f8fSGustavo F. Padovan 1304525cd185SGustavo F. Padovan BT_DBG("chan %p", chan); 13050a708f8fSGustavo F. Padovan 13066be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 13076be36555SAndrei Emeltchenko 13082c03a7a4SGustavo F. Padovan if (chan->retry_count >= chan->remote_max_tx) { 13098c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); 13106be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13118d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 13120a708f8fSGustavo F. Padovan return; 13130a708f8fSGustavo F. Padovan } 13140a708f8fSGustavo F. Padovan 13156a026610SGustavo F. Padovan chan->retry_count++; 13161a09bcb9SGustavo F. Padovan __set_monitor_timer(chan); 13170a708f8fSGustavo F. Padovan 1318525cd185SGustavo F. Padovan l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); 13196be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13208d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 13210a708f8fSGustavo F. Padovan } 13220a708f8fSGustavo F. Padovan 1323721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work) 13240a708f8fSGustavo F. Padovan { 1325721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1326721c4181SGustavo F. Padovan retrans_timer.work); 13270a708f8fSGustavo F. Padovan 132849208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 13290a708f8fSGustavo F. Padovan 13306be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 13316be36555SAndrei Emeltchenko 13326a026610SGustavo F. Padovan chan->retry_count = 1; 13331a09bcb9SGustavo F. Padovan __set_monitor_timer(chan); 13340a708f8fSGustavo F. Padovan 1335e2ab4353SGustavo F. Padovan set_bit(CONN_WAIT_F, &chan->conn_state); 13360a708f8fSGustavo F. Padovan 1337525cd185SGustavo F. Padovan l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); 13386be36555SAndrei Emeltchenko 13396be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13408d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 13410a708f8fSGustavo F. Padovan } 13420a708f8fSGustavo F. Padovan 134342e5c802SGustavo F. Padovan static void l2cap_drop_acked_frames(struct l2cap_chan *chan) 13440a708f8fSGustavo F. Padovan { 13450a708f8fSGustavo F. Padovan struct sk_buff *skb; 13460a708f8fSGustavo F. Padovan 134758d35f87SGustavo F. Padovan while ((skb = skb_peek(&chan->tx_q)) && 13486a026610SGustavo F. Padovan chan->unacked_frames) { 134942e5c802SGustavo F. Padovan if (bt_cb(skb)->tx_seq == chan->expected_ack_seq) 13500a708f8fSGustavo F. Padovan break; 13510a708f8fSGustavo F. Padovan 135258d35f87SGustavo F. Padovan skb = skb_dequeue(&chan->tx_q); 13530a708f8fSGustavo F. Padovan kfree_skb(skb); 13540a708f8fSGustavo F. Padovan 13556a026610SGustavo F. Padovan chan->unacked_frames--; 13560a708f8fSGustavo F. Padovan } 13570a708f8fSGustavo F. Padovan 13586a026610SGustavo F. Padovan if (!chan->unacked_frames) 13591a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 13600a708f8fSGustavo F. Padovan } 13610a708f8fSGustavo F. Padovan 136267c9e840SSzymon Janc static void l2cap_streaming_send(struct l2cap_chan *chan) 13630a708f8fSGustavo F. Padovan { 13640a708f8fSGustavo F. Padovan struct sk_buff *skb; 136588843ab0SAndrei Emeltchenko u32 control; 136688843ab0SAndrei Emeltchenko u16 fcs; 13670a708f8fSGustavo F. Padovan 136858d35f87SGustavo F. Padovan while ((skb = skb_dequeue(&chan->tx_q))) { 136988843ab0SAndrei Emeltchenko control = __get_control(chan, skb->data + L2CAP_HDR_SIZE); 1370fb45de7dSAndrei Emeltchenko control |= __set_txseq(chan, chan->next_tx_seq); 137188843ab0SAndrei Emeltchenko __put_control(chan, control, skb->data + L2CAP_HDR_SIZE); 13720a708f8fSGustavo F. Padovan 137347d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 137403a51213SAndrei Emeltchenko fcs = crc16(0, (u8 *)skb->data, 137503a51213SAndrei Emeltchenko skb->len - L2CAP_FCS_SIZE); 137603a51213SAndrei Emeltchenko put_unaligned_le16(fcs, 137703a51213SAndrei Emeltchenko skb->data + skb->len - L2CAP_FCS_SIZE); 13780a708f8fSGustavo F. Padovan } 13790a708f8fSGustavo F. Padovan 13804343478fSGustavo F. Padovan l2cap_do_send(chan, skb); 13810a708f8fSGustavo F. Padovan 1382836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 13830a708f8fSGustavo F. Padovan } 13840a708f8fSGustavo F. Padovan } 13850a708f8fSGustavo F. Padovan 1386fb45de7dSAndrei Emeltchenko static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq) 13870a708f8fSGustavo F. Padovan { 13880a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 138988843ab0SAndrei Emeltchenko u16 fcs; 139088843ab0SAndrei Emeltchenko u32 control; 13910a708f8fSGustavo F. Padovan 139258d35f87SGustavo F. Padovan skb = skb_peek(&chan->tx_q); 13930a708f8fSGustavo F. Padovan if (!skb) 13940a708f8fSGustavo F. Padovan return; 13950a708f8fSGustavo F. Padovan 1396d1726b6dSSzymon Janc while (bt_cb(skb)->tx_seq != tx_seq) { 139758d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 13980a708f8fSGustavo F. Padovan return; 13990a708f8fSGustavo F. Padovan 1400d1726b6dSSzymon Janc skb = skb_queue_next(&chan->tx_q, skb); 1401d1726b6dSSzymon Janc } 14020a708f8fSGustavo F. Padovan 14032c03a7a4SGustavo F. Padovan if (chan->remote_max_tx && 14042c03a7a4SGustavo F. Padovan bt_cb(skb)->retries == chan->remote_max_tx) { 14058c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); 14060a708f8fSGustavo F. Padovan return; 14070a708f8fSGustavo F. Padovan } 14080a708f8fSGustavo F. Padovan 14090a708f8fSGustavo F. Padovan tx_skb = skb_clone(skb, GFP_ATOMIC); 14100a708f8fSGustavo F. Padovan bt_cb(skb)->retries++; 141188843ab0SAndrei Emeltchenko 141288843ab0SAndrei Emeltchenko control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE); 14137e0ef6eeSAndrei Emeltchenko control &= __get_sar_mask(chan); 14140a708f8fSGustavo F. Padovan 1415e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 141603f6715dSAndrei Emeltchenko control |= __set_ctrl_final(chan); 14170a708f8fSGustavo F. Padovan 14180b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 1419fb45de7dSAndrei Emeltchenko control |= __set_txseq(chan, tx_seq); 14200a708f8fSGustavo F. Padovan 142188843ab0SAndrei Emeltchenko __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE); 14220a708f8fSGustavo F. Padovan 142347d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 142403a51213SAndrei Emeltchenko fcs = crc16(0, (u8 *)tx_skb->data, 142503a51213SAndrei Emeltchenko tx_skb->len - L2CAP_FCS_SIZE); 142603a51213SAndrei Emeltchenko put_unaligned_le16(fcs, 142703a51213SAndrei Emeltchenko tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE); 14280a708f8fSGustavo F. Padovan } 14290a708f8fSGustavo F. Padovan 14304343478fSGustavo F. Padovan l2cap_do_send(chan, tx_skb); 14310a708f8fSGustavo F. Padovan } 14320a708f8fSGustavo F. Padovan 143367c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan) 14340a708f8fSGustavo F. Padovan { 14350a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 143688843ab0SAndrei Emeltchenko u16 fcs; 143788843ab0SAndrei Emeltchenko u32 control; 14380a708f8fSGustavo F. Padovan int nsent = 0; 14390a708f8fSGustavo F. Padovan 144089bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 14410a708f8fSGustavo F. Padovan return -ENOTCONN; 14420a708f8fSGustavo F. Padovan 144358d35f87SGustavo F. Padovan while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) { 14440a708f8fSGustavo F. Padovan 14452c03a7a4SGustavo F. Padovan if (chan->remote_max_tx && 14462c03a7a4SGustavo F. Padovan bt_cb(skb)->retries == chan->remote_max_tx) { 14478c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); 14480a708f8fSGustavo F. Padovan break; 14490a708f8fSGustavo F. Padovan } 14500a708f8fSGustavo F. Padovan 14510a708f8fSGustavo F. Padovan tx_skb = skb_clone(skb, GFP_ATOMIC); 14520a708f8fSGustavo F. Padovan 14530a708f8fSGustavo F. Padovan bt_cb(skb)->retries++; 14540a708f8fSGustavo F. Padovan 145588843ab0SAndrei Emeltchenko control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE); 14567e0ef6eeSAndrei Emeltchenko control &= __get_sar_mask(chan); 14570a708f8fSGustavo F. Padovan 1458e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 145903f6715dSAndrei Emeltchenko control |= __set_ctrl_final(chan); 1460e2ab4353SGustavo F. Padovan 14610b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 1462fb45de7dSAndrei Emeltchenko control |= __set_txseq(chan, chan->next_tx_seq); 14630a708f8fSGustavo F. Padovan 146488843ab0SAndrei Emeltchenko __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE); 14650a708f8fSGustavo F. Padovan 146647d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 146703a51213SAndrei Emeltchenko fcs = crc16(0, (u8 *)skb->data, 146803a51213SAndrei Emeltchenko tx_skb->len - L2CAP_FCS_SIZE); 146903a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb->data + 147003a51213SAndrei Emeltchenko tx_skb->len - L2CAP_FCS_SIZE); 14710a708f8fSGustavo F. Padovan } 14720a708f8fSGustavo F. Padovan 14734343478fSGustavo F. Padovan l2cap_do_send(chan, tx_skb); 14740a708f8fSGustavo F. Padovan 14751a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 14760a708f8fSGustavo F. Padovan 147742e5c802SGustavo F. Padovan bt_cb(skb)->tx_seq = chan->next_tx_seq; 1478836be934SAndrei Emeltchenko 1479836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 14800a708f8fSGustavo F. Padovan 14818ed7a0aeSSzymon Janc if (bt_cb(skb)->retries == 1) { 14826a026610SGustavo F. Padovan chan->unacked_frames++; 1483930fa4aeSSzymon Janc 1484930fa4aeSSzymon Janc if (!nsent++) 1485930fa4aeSSzymon Janc __clear_ack_timer(chan); 14868ed7a0aeSSzymon Janc } 148723e9fde2SSuraj Sumangala 14886a026610SGustavo F. Padovan chan->frames_sent++; 14890a708f8fSGustavo F. Padovan 149058d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 149158d35f87SGustavo F. Padovan chan->tx_send_head = NULL; 14920a708f8fSGustavo F. Padovan else 149358d35f87SGustavo F. Padovan chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); 14940a708f8fSGustavo F. Padovan } 14950a708f8fSGustavo F. Padovan 14960a708f8fSGustavo F. Padovan return nsent; 14970a708f8fSGustavo F. Padovan } 14980a708f8fSGustavo F. Padovan 1499525cd185SGustavo F. Padovan static int l2cap_retransmit_frames(struct l2cap_chan *chan) 15000a708f8fSGustavo F. Padovan { 15010a708f8fSGustavo F. Padovan int ret; 15020a708f8fSGustavo F. Padovan 150358d35f87SGustavo F. Padovan if (!skb_queue_empty(&chan->tx_q)) 150458d35f87SGustavo F. Padovan chan->tx_send_head = chan->tx_q.next; 15050a708f8fSGustavo F. Padovan 150642e5c802SGustavo F. Padovan chan->next_tx_seq = chan->expected_ack_seq; 1507525cd185SGustavo F. Padovan ret = l2cap_ertm_send(chan); 15080a708f8fSGustavo F. Padovan return ret; 15090a708f8fSGustavo F. Padovan } 15100a708f8fSGustavo F. Padovan 1511b17e73bbSSzymon Janc static void __l2cap_send_ack(struct l2cap_chan *chan) 15120a708f8fSGustavo F. Padovan { 151388843ab0SAndrei Emeltchenko u32 control = 0; 15140a708f8fSGustavo F. Padovan 15150b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 15160a708f8fSGustavo F. Padovan 1517e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 1518ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); 1519e2ab4353SGustavo F. Padovan set_bit(CONN_RNR_SENT, &chan->conn_state); 1520525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 15210a708f8fSGustavo F. Padovan return; 15220a708f8fSGustavo F. Padovan } 15230a708f8fSGustavo F. Padovan 1524525cd185SGustavo F. Padovan if (l2cap_ertm_send(chan) > 0) 15250a708f8fSGustavo F. Padovan return; 15260a708f8fSGustavo F. Padovan 1527ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 1528525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 15290a708f8fSGustavo F. Padovan } 15300a708f8fSGustavo F. Padovan 1531b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan) 1532b17e73bbSSzymon Janc { 1533b17e73bbSSzymon Janc __clear_ack_timer(chan); 1534b17e73bbSSzymon Janc __l2cap_send_ack(chan); 1535b17e73bbSSzymon Janc } 1536b17e73bbSSzymon Janc 1537525cd185SGustavo F. Padovan static void l2cap_send_srejtail(struct l2cap_chan *chan) 15380a708f8fSGustavo F. Padovan { 15390a708f8fSGustavo F. Padovan struct srej_list *tail; 154088843ab0SAndrei Emeltchenko u32 control; 15410a708f8fSGustavo F. Padovan 1542ab784b73SAndrei Emeltchenko control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ); 154303f6715dSAndrei Emeltchenko control |= __set_ctrl_final(chan); 15440a708f8fSGustavo F. Padovan 154539d5a3eeSGustavo F. Padovan tail = list_entry((&chan->srej_l)->prev, struct srej_list, list); 15460b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, tail->tx_seq); 15470a708f8fSGustavo F. Padovan 1548525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 15490a708f8fSGustavo F. Padovan } 15500a708f8fSGustavo F. Padovan 155104124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, 155204124681SGustavo F. Padovan struct msghdr *msg, int len, 155304124681SGustavo F. Padovan int count, struct sk_buff *skb) 15540a708f8fSGustavo F. Padovan { 15550952a57aSAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 15560a708f8fSGustavo F. Padovan struct sk_buff **frag; 15570a708f8fSGustavo F. Padovan int err, sent = 0; 15580a708f8fSGustavo F. Padovan 15590a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) 15600a708f8fSGustavo F. Padovan return -EFAULT; 15610a708f8fSGustavo F. Padovan 15620a708f8fSGustavo F. Padovan sent += count; 15630a708f8fSGustavo F. Padovan len -= count; 15640a708f8fSGustavo F. Padovan 15650a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 15660a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 15670a708f8fSGustavo F. Padovan while (len) { 15680a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 15690a708f8fSGustavo F. Padovan 15702f7719ceSAndrei Emeltchenko *frag = chan->ops->alloc_skb(chan, count, 157104124681SGustavo F. Padovan msg->msg_flags & MSG_DONTWAIT, 157204124681SGustavo F. Padovan &err); 15732f7719ceSAndrei Emeltchenko 15740a708f8fSGustavo F. Padovan if (!*frag) 15750a708f8fSGustavo F. Padovan return err; 15760a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) 15770a708f8fSGustavo F. Padovan return -EFAULT; 15780a708f8fSGustavo F. Padovan 15795e59b791SLuiz Augusto von Dentz (*frag)->priority = skb->priority; 15805e59b791SLuiz Augusto von Dentz 15810a708f8fSGustavo F. Padovan sent += count; 15820a708f8fSGustavo F. Padovan len -= count; 15830a708f8fSGustavo F. Padovan 15840a708f8fSGustavo F. Padovan frag = &(*frag)->next; 15850a708f8fSGustavo F. Padovan } 15860a708f8fSGustavo F. Padovan 15870a708f8fSGustavo F. Padovan return sent; 15880a708f8fSGustavo F. Padovan } 15890a708f8fSGustavo F. Padovan 15905e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, 15915e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 15925e59b791SLuiz Augusto von Dentz u32 priority) 15930a708f8fSGustavo F. Padovan { 15948c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 15950a708f8fSGustavo F. Padovan struct sk_buff *skb; 159603a51213SAndrei Emeltchenko int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; 15970a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 15980a708f8fSGustavo F. Padovan 15996d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d priority %u", chan, (int)len, priority); 16000a708f8fSGustavo F. Padovan 16010a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 16022f7719ceSAndrei Emeltchenko 16032f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 16040a708f8fSGustavo F. Padovan msg->msg_flags & MSG_DONTWAIT, &err); 16052f7719ceSAndrei Emeltchenko 16060a708f8fSGustavo F. Padovan if (!skb) 16070a708f8fSGustavo F. Padovan return ERR_PTR(err); 16080a708f8fSGustavo F. Padovan 16095e59b791SLuiz Augusto von Dentz skb->priority = priority; 16105e59b791SLuiz Augusto von Dentz 16110a708f8fSGustavo F. Padovan /* Create L2CAP header */ 16120a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 1613fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 16140a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 1615097db76cSAndrei Emeltchenko put_unaligned(chan->psm, skb_put(skb, 2)); 16160a708f8fSGustavo F. Padovan 16170952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 16180a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 16190a708f8fSGustavo F. Padovan kfree_skb(skb); 16200a708f8fSGustavo F. Padovan return ERR_PTR(err); 16210a708f8fSGustavo F. Padovan } 16220a708f8fSGustavo F. Padovan return skb; 16230a708f8fSGustavo F. Padovan } 16240a708f8fSGustavo F. Padovan 16255e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, 16265e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 16275e59b791SLuiz Augusto von Dentz u32 priority) 16280a708f8fSGustavo F. Padovan { 16298c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 16300a708f8fSGustavo F. Padovan struct sk_buff *skb; 16310a708f8fSGustavo F. Padovan int err, count, hlen = L2CAP_HDR_SIZE; 16320a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 16330a708f8fSGustavo F. Padovan 16346d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d", chan, (int)len); 16350a708f8fSGustavo F. Padovan 16360a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 16372f7719ceSAndrei Emeltchenko 16382f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 16390a708f8fSGustavo F. Padovan msg->msg_flags & MSG_DONTWAIT, &err); 16402f7719ceSAndrei Emeltchenko 16410a708f8fSGustavo F. Padovan if (!skb) 16420a708f8fSGustavo F. Padovan return ERR_PTR(err); 16430a708f8fSGustavo F. Padovan 16445e59b791SLuiz Augusto von Dentz skb->priority = priority; 16455e59b791SLuiz Augusto von Dentz 16460a708f8fSGustavo F. Padovan /* Create L2CAP header */ 16470a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 1648fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 16490a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 16500a708f8fSGustavo F. Padovan 16510952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 16520a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 16530a708f8fSGustavo F. Padovan kfree_skb(skb); 16540a708f8fSGustavo F. Padovan return ERR_PTR(err); 16550a708f8fSGustavo F. Padovan } 16560a708f8fSGustavo F. Padovan return skb; 16570a708f8fSGustavo F. Padovan } 16580a708f8fSGustavo F. Padovan 1659ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, 1660ab0ff76dSLuiz Augusto von Dentz struct msghdr *msg, size_t len, 166188843ab0SAndrei Emeltchenko u32 control, u16 sdulen) 16620a708f8fSGustavo F. Padovan { 16638c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 16640a708f8fSGustavo F. Padovan struct sk_buff *skb; 1665e4ca6d98SAndrei Emeltchenko int err, count, hlen; 16660a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 16670a708f8fSGustavo F. Padovan 16686d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d", chan, (int)len); 16690a708f8fSGustavo F. Padovan 16700a708f8fSGustavo F. Padovan if (!conn) 16710a708f8fSGustavo F. Padovan return ERR_PTR(-ENOTCONN); 16720a708f8fSGustavo F. Padovan 1673e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1674e4ca6d98SAndrei Emeltchenko hlen = L2CAP_EXT_HDR_SIZE; 1675e4ca6d98SAndrei Emeltchenko else 1676e4ca6d98SAndrei Emeltchenko hlen = L2CAP_ENH_HDR_SIZE; 1677e4ca6d98SAndrei Emeltchenko 16780a708f8fSGustavo F. Padovan if (sdulen) 167903a51213SAndrei Emeltchenko hlen += L2CAP_SDULEN_SIZE; 16800a708f8fSGustavo F. Padovan 168147d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 168203a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 16830a708f8fSGustavo F. Padovan 16840a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 16852f7719ceSAndrei Emeltchenko 16862f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 16870a708f8fSGustavo F. Padovan msg->msg_flags & MSG_DONTWAIT, &err); 16882f7719ceSAndrei Emeltchenko 16890a708f8fSGustavo F. Padovan if (!skb) 16900a708f8fSGustavo F. Padovan return ERR_PTR(err); 16910a708f8fSGustavo F. Padovan 16920a708f8fSGustavo F. Padovan /* Create L2CAP header */ 16930a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 1694fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 16950a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 169688843ab0SAndrei Emeltchenko 169788843ab0SAndrei Emeltchenko __put_control(chan, control, skb_put(skb, __ctrl_size(chan))); 169888843ab0SAndrei Emeltchenko 16990a708f8fSGustavo F. Padovan if (sdulen) 170003a51213SAndrei Emeltchenko put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 17010a708f8fSGustavo F. Padovan 17020952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 17030a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 17040a708f8fSGustavo F. Padovan kfree_skb(skb); 17050a708f8fSGustavo F. Padovan return ERR_PTR(err); 17060a708f8fSGustavo F. Padovan } 17070a708f8fSGustavo F. Padovan 170847d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 170903a51213SAndrei Emeltchenko put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE)); 17100a708f8fSGustavo F. Padovan 17110a708f8fSGustavo F. Padovan bt_cb(skb)->retries = 0; 17120a708f8fSGustavo F. Padovan return skb; 17130a708f8fSGustavo F. Padovan } 17140a708f8fSGustavo F. Padovan 171567c9e840SSzymon Janc static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) 17160a708f8fSGustavo F. Padovan { 17170a708f8fSGustavo F. Padovan struct sk_buff *skb; 17180a708f8fSGustavo F. Padovan struct sk_buff_head sar_queue; 171988843ab0SAndrei Emeltchenko u32 control; 17200a708f8fSGustavo F. Padovan size_t size = 0; 17210a708f8fSGustavo F. Padovan 17220a708f8fSGustavo F. Padovan skb_queue_head_init(&sar_queue); 17237e0ef6eeSAndrei Emeltchenko control = __set_ctrl_sar(chan, L2CAP_SAR_START); 172447d1ec61SGustavo F. Padovan skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len); 17250a708f8fSGustavo F. Padovan if (IS_ERR(skb)) 17260a708f8fSGustavo F. Padovan return PTR_ERR(skb); 17270a708f8fSGustavo F. Padovan 17280a708f8fSGustavo F. Padovan __skb_queue_tail(&sar_queue, skb); 17292c03a7a4SGustavo F. Padovan len -= chan->remote_mps; 17302c03a7a4SGustavo F. Padovan size += chan->remote_mps; 17310a708f8fSGustavo F. Padovan 17320a708f8fSGustavo F. Padovan while (len > 0) { 17330a708f8fSGustavo F. Padovan size_t buflen; 17340a708f8fSGustavo F. Padovan 17352c03a7a4SGustavo F. Padovan if (len > chan->remote_mps) { 17367e0ef6eeSAndrei Emeltchenko control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE); 17372c03a7a4SGustavo F. Padovan buflen = chan->remote_mps; 17380a708f8fSGustavo F. Padovan } else { 17397e0ef6eeSAndrei Emeltchenko control = __set_ctrl_sar(chan, L2CAP_SAR_END); 17400a708f8fSGustavo F. Padovan buflen = len; 17410a708f8fSGustavo F. Padovan } 17420a708f8fSGustavo F. Padovan 174347d1ec61SGustavo F. Padovan skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0); 17440a708f8fSGustavo F. Padovan if (IS_ERR(skb)) { 17450a708f8fSGustavo F. Padovan skb_queue_purge(&sar_queue); 17460a708f8fSGustavo F. Padovan return PTR_ERR(skb); 17470a708f8fSGustavo F. Padovan } 17480a708f8fSGustavo F. Padovan 17490a708f8fSGustavo F. Padovan __skb_queue_tail(&sar_queue, skb); 17500a708f8fSGustavo F. Padovan len -= buflen; 17510a708f8fSGustavo F. Padovan size += buflen; 17520a708f8fSGustavo F. Padovan } 175358d35f87SGustavo F. Padovan skb_queue_splice_tail(&sar_queue, &chan->tx_q); 175458d35f87SGustavo F. Padovan if (chan->tx_send_head == NULL) 175558d35f87SGustavo F. Padovan chan->tx_send_head = sar_queue.next; 17560a708f8fSGustavo F. Padovan 17570a708f8fSGustavo F. Padovan return size; 17580a708f8fSGustavo F. Padovan } 17590a708f8fSGustavo F. Padovan 17605e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, 17615e59b791SLuiz Augusto von Dentz u32 priority) 17629a91a04aSGustavo F. Padovan { 17639a91a04aSGustavo F. Padovan struct sk_buff *skb; 176488843ab0SAndrei Emeltchenko u32 control; 17659a91a04aSGustavo F. Padovan int err; 17669a91a04aSGustavo F. Padovan 17679a91a04aSGustavo F. Padovan /* Connectionless channel */ 1768715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { 17695e59b791SLuiz Augusto von Dentz skb = l2cap_create_connless_pdu(chan, msg, len, priority); 17709a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 17719a91a04aSGustavo F. Padovan return PTR_ERR(skb); 17729a91a04aSGustavo F. Padovan 17739a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 17749a91a04aSGustavo F. Padovan return len; 17759a91a04aSGustavo F. Padovan } 17769a91a04aSGustavo F. Padovan 17779a91a04aSGustavo F. Padovan switch (chan->mode) { 17789a91a04aSGustavo F. Padovan case L2CAP_MODE_BASIC: 17799a91a04aSGustavo F. Padovan /* Check outgoing MTU */ 17809a91a04aSGustavo F. Padovan if (len > chan->omtu) 17819a91a04aSGustavo F. Padovan return -EMSGSIZE; 17829a91a04aSGustavo F. Padovan 17839a91a04aSGustavo F. Padovan /* Create a basic PDU */ 17845e59b791SLuiz Augusto von Dentz skb = l2cap_create_basic_pdu(chan, msg, len, priority); 17859a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 17869a91a04aSGustavo F. Padovan return PTR_ERR(skb); 17879a91a04aSGustavo F. Padovan 17889a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 17899a91a04aSGustavo F. Padovan err = len; 17909a91a04aSGustavo F. Padovan break; 17919a91a04aSGustavo F. Padovan 17929a91a04aSGustavo F. Padovan case L2CAP_MODE_ERTM: 17939a91a04aSGustavo F. Padovan case L2CAP_MODE_STREAMING: 17949a91a04aSGustavo F. Padovan /* Entire SDU fits into one PDU */ 17959a91a04aSGustavo F. Padovan if (len <= chan->remote_mps) { 17967e0ef6eeSAndrei Emeltchenko control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED); 17979a91a04aSGustavo F. Padovan skb = l2cap_create_iframe_pdu(chan, msg, len, control, 17989a91a04aSGustavo F. Padovan 0); 17999a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 18009a91a04aSGustavo F. Padovan return PTR_ERR(skb); 18019a91a04aSGustavo F. Padovan 18029a91a04aSGustavo F. Padovan __skb_queue_tail(&chan->tx_q, skb); 18039a91a04aSGustavo F. Padovan 18049a91a04aSGustavo F. Padovan if (chan->tx_send_head == NULL) 18059a91a04aSGustavo F. Padovan chan->tx_send_head = skb; 18069a91a04aSGustavo F. Padovan 18079a91a04aSGustavo F. Padovan } else { 18089a91a04aSGustavo F. Padovan /* Segment SDU into multiples PDUs */ 18099a91a04aSGustavo F. Padovan err = l2cap_sar_segment_sdu(chan, msg, len); 18109a91a04aSGustavo F. Padovan if (err < 0) 18119a91a04aSGustavo F. Padovan return err; 18129a91a04aSGustavo F. Padovan } 18139a91a04aSGustavo F. Padovan 18149a91a04aSGustavo F. Padovan if (chan->mode == L2CAP_MODE_STREAMING) { 18159a91a04aSGustavo F. Padovan l2cap_streaming_send(chan); 18169a91a04aSGustavo F. Padovan err = len; 18179a91a04aSGustavo F. Padovan break; 18189a91a04aSGustavo F. Padovan } 18199a91a04aSGustavo F. Padovan 1820e2ab4353SGustavo F. Padovan if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 1821e2ab4353SGustavo F. Padovan test_bit(CONN_WAIT_F, &chan->conn_state)) { 18229a91a04aSGustavo F. Padovan err = len; 18239a91a04aSGustavo F. Padovan break; 18249a91a04aSGustavo F. Padovan } 18259a91a04aSGustavo F. Padovan 18269a91a04aSGustavo F. Padovan err = l2cap_ertm_send(chan); 18279a91a04aSGustavo F. Padovan if (err >= 0) 18289a91a04aSGustavo F. Padovan err = len; 18299a91a04aSGustavo F. Padovan 18309a91a04aSGustavo F. Padovan break; 18319a91a04aSGustavo F. Padovan 18329a91a04aSGustavo F. Padovan default: 18339a91a04aSGustavo F. Padovan BT_DBG("bad state %1.1x", chan->mode); 18349a91a04aSGustavo F. Padovan err = -EBADFD; 18359a91a04aSGustavo F. Padovan } 18369a91a04aSGustavo F. Padovan 18379a91a04aSGustavo F. Padovan return err; 18389a91a04aSGustavo F. Padovan } 18399a91a04aSGustavo F. Padovan 18400a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */ 18410a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 18420a708f8fSGustavo F. Padovan { 18430a708f8fSGustavo F. Padovan struct sk_buff *nskb; 184448454079SGustavo F. Padovan struct l2cap_chan *chan; 18450a708f8fSGustavo F. Padovan 18460a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 18470a708f8fSGustavo F. Padovan 18483df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 18493d57dc68SGustavo F. Padovan 18503df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 185148454079SGustavo F. Padovan struct sock *sk = chan->sk; 1852715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW) 18530a708f8fSGustavo F. Padovan continue; 18540a708f8fSGustavo F. Padovan 18550a708f8fSGustavo F. Padovan /* Don't send frame to the socket it came from */ 18560a708f8fSGustavo F. Padovan if (skb->sk == sk) 18570a708f8fSGustavo F. Padovan continue; 18580a708f8fSGustavo F. Padovan nskb = skb_clone(skb, GFP_ATOMIC); 18590a708f8fSGustavo F. Padovan if (!nskb) 18600a708f8fSGustavo F. Padovan continue; 18610a708f8fSGustavo F. Padovan 186223070494SGustavo F. Padovan if (chan->ops->recv(chan->data, nskb)) 18630a708f8fSGustavo F. Padovan kfree_skb(nskb); 18640a708f8fSGustavo F. Padovan } 18653d57dc68SGustavo F. Padovan 18663df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 18670a708f8fSGustavo F. Padovan } 18680a708f8fSGustavo F. Padovan 18690a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */ 18700a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 18710a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data) 18720a708f8fSGustavo F. Padovan { 18730a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag; 18740a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd; 18750a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 18760a708f8fSGustavo F. Padovan int len, count; 18770a708f8fSGustavo F. Padovan 18780a708f8fSGustavo F. Padovan BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d", 18790a708f8fSGustavo F. Padovan conn, code, ident, dlen); 18800a708f8fSGustavo F. Padovan 18810a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; 18820a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 18830a708f8fSGustavo F. Padovan 18840a708f8fSGustavo F. Padovan skb = bt_skb_alloc(count, GFP_ATOMIC); 18850a708f8fSGustavo F. Padovan if (!skb) 18860a708f8fSGustavo F. Padovan return NULL; 18870a708f8fSGustavo F. Padovan 18880a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 18890a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); 18903300d9a9SClaudio Takahasi 18913300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 18923300d9a9SClaudio Takahasi lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING); 18933300d9a9SClaudio Takahasi else 18940a708f8fSGustavo F. Padovan lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING); 18950a708f8fSGustavo F. Padovan 18960a708f8fSGustavo F. Padovan cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); 18970a708f8fSGustavo F. Padovan cmd->code = code; 18980a708f8fSGustavo F. Padovan cmd->ident = ident; 18990a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen); 19000a708f8fSGustavo F. Padovan 19010a708f8fSGustavo F. Padovan if (dlen) { 19020a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE; 19030a708f8fSGustavo F. Padovan memcpy(skb_put(skb, count), data, count); 19040a708f8fSGustavo F. Padovan data += count; 19050a708f8fSGustavo F. Padovan } 19060a708f8fSGustavo F. Padovan 19070a708f8fSGustavo F. Padovan len -= skb->len; 19080a708f8fSGustavo F. Padovan 19090a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 19100a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 19110a708f8fSGustavo F. Padovan while (len) { 19120a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 19130a708f8fSGustavo F. Padovan 19140a708f8fSGustavo F. Padovan *frag = bt_skb_alloc(count, GFP_ATOMIC); 19150a708f8fSGustavo F. Padovan if (!*frag) 19160a708f8fSGustavo F. Padovan goto fail; 19170a708f8fSGustavo F. Padovan 19180a708f8fSGustavo F. Padovan memcpy(skb_put(*frag, count), data, count); 19190a708f8fSGustavo F. Padovan 19200a708f8fSGustavo F. Padovan len -= count; 19210a708f8fSGustavo F. Padovan data += count; 19220a708f8fSGustavo F. Padovan 19230a708f8fSGustavo F. Padovan frag = &(*frag)->next; 19240a708f8fSGustavo F. Padovan } 19250a708f8fSGustavo F. Padovan 19260a708f8fSGustavo F. Padovan return skb; 19270a708f8fSGustavo F. Padovan 19280a708f8fSGustavo F. Padovan fail: 19290a708f8fSGustavo F. Padovan kfree_skb(skb); 19300a708f8fSGustavo F. Padovan return NULL; 19310a708f8fSGustavo F. Padovan } 19320a708f8fSGustavo F. Padovan 19330a708f8fSGustavo F. Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val) 19340a708f8fSGustavo F. Padovan { 19350a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 19360a708f8fSGustavo F. Padovan int len; 19370a708f8fSGustavo F. Padovan 19380a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len; 19390a708f8fSGustavo F. Padovan *ptr += len; 19400a708f8fSGustavo F. Padovan 19410a708f8fSGustavo F. Padovan *type = opt->type; 19420a708f8fSGustavo F. Padovan *olen = opt->len; 19430a708f8fSGustavo F. Padovan 19440a708f8fSGustavo F. Padovan switch (opt->len) { 19450a708f8fSGustavo F. Padovan case 1: 19460a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val); 19470a708f8fSGustavo F. Padovan break; 19480a708f8fSGustavo F. Padovan 19490a708f8fSGustavo F. Padovan case 2: 19500a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val); 19510a708f8fSGustavo F. Padovan break; 19520a708f8fSGustavo F. Padovan 19530a708f8fSGustavo F. Padovan case 4: 19540a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val); 19550a708f8fSGustavo F. Padovan break; 19560a708f8fSGustavo F. Padovan 19570a708f8fSGustavo F. Padovan default: 19580a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val; 19590a708f8fSGustavo F. Padovan break; 19600a708f8fSGustavo F. Padovan } 19610a708f8fSGustavo F. Padovan 19620a708f8fSGustavo F. Padovan BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val); 19630a708f8fSGustavo F. Padovan return len; 19640a708f8fSGustavo F. Padovan } 19650a708f8fSGustavo F. Padovan 19660a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) 19670a708f8fSGustavo F. Padovan { 19680a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 19690a708f8fSGustavo F. Padovan 19700a708f8fSGustavo F. Padovan BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val); 19710a708f8fSGustavo F. Padovan 19720a708f8fSGustavo F. Padovan opt->type = type; 19730a708f8fSGustavo F. Padovan opt->len = len; 19740a708f8fSGustavo F. Padovan 19750a708f8fSGustavo F. Padovan switch (len) { 19760a708f8fSGustavo F. Padovan case 1: 19770a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val; 19780a708f8fSGustavo F. Padovan break; 19790a708f8fSGustavo F. Padovan 19800a708f8fSGustavo F. Padovan case 2: 19810a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val); 19820a708f8fSGustavo F. Padovan break; 19830a708f8fSGustavo F. Padovan 19840a708f8fSGustavo F. Padovan case 4: 19850a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val); 19860a708f8fSGustavo F. Padovan break; 19870a708f8fSGustavo F. Padovan 19880a708f8fSGustavo F. Padovan default: 19890a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len); 19900a708f8fSGustavo F. Padovan break; 19910a708f8fSGustavo F. Padovan } 19920a708f8fSGustavo F. Padovan 19930a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len; 19940a708f8fSGustavo F. Padovan } 19950a708f8fSGustavo F. Padovan 1996f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) 1997f89cef09SAndrei Emeltchenko { 1998f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs; 1999f89cef09SAndrei Emeltchenko 2000f89cef09SAndrei Emeltchenko switch (chan->mode) { 2001f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM: 2002f89cef09SAndrei Emeltchenko efs.id = chan->local_id; 2003f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype; 2004f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 2005f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 2006f89cef09SAndrei Emeltchenko efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); 2007f89cef09SAndrei Emeltchenko efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO); 2008f89cef09SAndrei Emeltchenko break; 2009f89cef09SAndrei Emeltchenko 2010f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING: 2011f89cef09SAndrei Emeltchenko efs.id = 1; 2012f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT; 2013f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 2014f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 2015f89cef09SAndrei Emeltchenko efs.acc_lat = 0; 2016f89cef09SAndrei Emeltchenko efs.flush_to = 0; 2017f89cef09SAndrei Emeltchenko break; 2018f89cef09SAndrei Emeltchenko 2019f89cef09SAndrei Emeltchenko default: 2020f89cef09SAndrei Emeltchenko return; 2021f89cef09SAndrei Emeltchenko } 2022f89cef09SAndrei Emeltchenko 2023f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), 2024f89cef09SAndrei Emeltchenko (unsigned long) &efs); 2025f89cef09SAndrei Emeltchenko } 2026f89cef09SAndrei Emeltchenko 2027721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work) 20280a708f8fSGustavo F. Padovan { 2029721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 2030721c4181SGustavo F. Padovan ack_timer.work); 20310a708f8fSGustavo F. Padovan 20322fb9b3d4SGustavo F. Padovan BT_DBG("chan %p", chan); 20332fb9b3d4SGustavo F. Padovan 20346be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 20356be36555SAndrei Emeltchenko 2036b17e73bbSSzymon Janc __l2cap_send_ack(chan); 20376be36555SAndrei Emeltchenko 20386be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 203909bfb2eeSSzymon Janc 204009bfb2eeSSzymon Janc l2cap_chan_put(chan); 20410a708f8fSGustavo F. Padovan } 20420a708f8fSGustavo F. Padovan 2043525cd185SGustavo F. Padovan static inline void l2cap_ertm_init(struct l2cap_chan *chan) 20440a708f8fSGustavo F. Padovan { 204542e5c802SGustavo F. Padovan chan->expected_ack_seq = 0; 20466a026610SGustavo F. Padovan chan->unacked_frames = 0; 204742e5c802SGustavo F. Padovan chan->buffer_seq = 0; 20486a026610SGustavo F. Padovan chan->num_acked = 0; 20496a026610SGustavo F. Padovan chan->frames_sent = 0; 20500a708f8fSGustavo F. Padovan 2051721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout); 2052721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout); 2053721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout); 20540a708f8fSGustavo F. Padovan 2055f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q); 20560a708f8fSGustavo F. Padovan 205739d5a3eeSGustavo F. Padovan INIT_LIST_HEAD(&chan->srej_l); 20580a708f8fSGustavo F. Padovan } 20590a708f8fSGustavo F. Padovan 20600a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) 20610a708f8fSGustavo F. Padovan { 20620a708f8fSGustavo F. Padovan switch (mode) { 20630a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 20640a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 20650a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask)) 20660a708f8fSGustavo F. Padovan return mode; 20670a708f8fSGustavo F. Padovan /* fall through */ 20680a708f8fSGustavo F. Padovan default: 20690a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC; 20700a708f8fSGustavo F. Padovan } 20710a708f8fSGustavo F. Padovan } 20720a708f8fSGustavo F. Padovan 20736327eb98SAndrei Emeltchenko static inline bool __l2cap_ews_supported(struct l2cap_chan *chan) 20746327eb98SAndrei Emeltchenko { 20756327eb98SAndrei Emeltchenko return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW; 20766327eb98SAndrei Emeltchenko } 20776327eb98SAndrei Emeltchenko 2078f89cef09SAndrei Emeltchenko static inline bool __l2cap_efs_supported(struct l2cap_chan *chan) 2079f89cef09SAndrei Emeltchenko { 2080f89cef09SAndrei Emeltchenko return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW; 2081f89cef09SAndrei Emeltchenko } 2082f89cef09SAndrei Emeltchenko 20836327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan) 20846327eb98SAndrei Emeltchenko { 20856327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && 2086836be934SAndrei Emeltchenko __l2cap_ews_supported(chan)) { 20876327eb98SAndrei Emeltchenko /* use extended control field */ 20886327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 2089836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 2090836be934SAndrei Emeltchenko } else { 20916327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win, 20926327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 2093836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 2094836be934SAndrei Emeltchenko } 20956327eb98SAndrei Emeltchenko } 20966327eb98SAndrei Emeltchenko 2097710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) 20980a708f8fSGustavo F. Padovan { 20990a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 21000c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode }; 21010a708f8fSGustavo F. Padovan void *ptr = req->data; 2102c8f79162SAndrei Emeltchenko u16 size; 21030a708f8fSGustavo F. Padovan 210449208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 21050a708f8fSGustavo F. Padovan 210673ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp) 21070a708f8fSGustavo F. Padovan goto done; 21080a708f8fSGustavo F. Padovan 21090c1bc5c6SGustavo F. Padovan switch (chan->mode) { 21100a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 21110a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 2112c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) 21130a708f8fSGustavo F. Padovan break; 21140a708f8fSGustavo F. Padovan 2115f89cef09SAndrei Emeltchenko if (__l2cap_efs_supported(chan)) 2116f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 2117f89cef09SAndrei Emeltchenko 21180a708f8fSGustavo F. Padovan /* fall through */ 21190a708f8fSGustavo F. Padovan default: 21208c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); 21210a708f8fSGustavo F. Padovan break; 21220a708f8fSGustavo F. Padovan } 21230a708f8fSGustavo F. Padovan 21240a708f8fSGustavo F. Padovan done: 21250c1bc5c6SGustavo F. Padovan if (chan->imtu != L2CAP_DEFAULT_MTU) 21260c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 21270a708f8fSGustavo F. Padovan 21280c1bc5c6SGustavo F. Padovan switch (chan->mode) { 21290a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 21308c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && 21318c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) 21320a708f8fSGustavo F. Padovan break; 21330a708f8fSGustavo F. Padovan 21340a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC; 21350a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 21360a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 21370a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 21380a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 21390a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0; 21400a708f8fSGustavo F. Padovan 21410a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 21420a708f8fSGustavo F. Padovan (unsigned long) &rfc); 21430a708f8fSGustavo F. Padovan break; 21440a708f8fSGustavo F. Padovan 21450a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 21460a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM; 214747d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx; 21480a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 21490a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 2150c8f79162SAndrei Emeltchenko 2151c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 2152c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2153c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2154c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2155c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 21560a708f8fSGustavo F. Padovan 21576327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan); 21586327eb98SAndrei Emeltchenko 21596327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win, 21606327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 21610a708f8fSGustavo F. Padovan 21620a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 21630a708f8fSGustavo F. Padovan (unsigned long) &rfc); 21640a708f8fSGustavo F. Padovan 2165f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 2166f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 2167f89cef09SAndrei Emeltchenko 21688c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) 21690a708f8fSGustavo F. Padovan break; 21700a708f8fSGustavo F. Padovan 217147d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 2172c1360a1cSGustavo F. Padovan test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { 217347d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 217447d1ec61SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); 21750a708f8fSGustavo F. Padovan } 21766327eb98SAndrei Emeltchenko 21776327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 21786327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 21796327eb98SAndrei Emeltchenko chan->tx_win); 21800a708f8fSGustavo F. Padovan break; 21810a708f8fSGustavo F. Padovan 21820a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 21830a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING; 21840a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 21850a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 21860a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 21870a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 2188c8f79162SAndrei Emeltchenko 2189c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 2190c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2191c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2192c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2193c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 21940a708f8fSGustavo F. Padovan 21950a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 21960a708f8fSGustavo F. Padovan (unsigned long) &rfc); 21970a708f8fSGustavo F. Padovan 2198f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 2199f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 2200f89cef09SAndrei Emeltchenko 22018c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) 22020a708f8fSGustavo F. Padovan break; 22030a708f8fSGustavo F. Padovan 220447d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 2205c1360a1cSGustavo F. Padovan test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { 220647d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 220747d1ec61SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); 22080a708f8fSGustavo F. Padovan } 22090a708f8fSGustavo F. Padovan break; 22100a708f8fSGustavo F. Padovan } 22110a708f8fSGustavo F. Padovan 2212fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 22130a708f8fSGustavo F. Padovan req->flags = cpu_to_le16(0); 22140a708f8fSGustavo F. Padovan 22150a708f8fSGustavo F. Padovan return ptr - data; 22160a708f8fSGustavo F. Padovan } 22170a708f8fSGustavo F. Padovan 221873ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) 22190a708f8fSGustavo F. Padovan { 22200a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 22210a708f8fSGustavo F. Padovan void *ptr = rsp->data; 222273ffa904SGustavo F. Padovan void *req = chan->conf_req; 222373ffa904SGustavo F. Padovan int len = chan->conf_len; 22240a708f8fSGustavo F. Padovan int type, hint, olen; 22250a708f8fSGustavo F. Padovan unsigned long val; 22260a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 222742dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs; 222842dceae2SAndrei Emeltchenko u8 remote_efs = 0; 22290a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU; 22300a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS; 2231c8f79162SAndrei Emeltchenko u16 size; 22320a708f8fSGustavo F. Padovan 223373ffa904SGustavo F. Padovan BT_DBG("chan %p", chan); 22340a708f8fSGustavo F. Padovan 22350a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 22360a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val); 22370a708f8fSGustavo F. Padovan 22380a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT; 22390a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK; 22400a708f8fSGustavo F. Padovan 22410a708f8fSGustavo F. Padovan switch (type) { 22420a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 22430a708f8fSGustavo F. Padovan mtu = val; 22440a708f8fSGustavo F. Padovan break; 22450a708f8fSGustavo F. Padovan 22460a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 22470c1bc5c6SGustavo F. Padovan chan->flush_to = val; 22480a708f8fSGustavo F. Padovan break; 22490a708f8fSGustavo F. Padovan 22500a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS: 22510a708f8fSGustavo F. Padovan break; 22520a708f8fSGustavo F. Padovan 22530a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 22540a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 22550a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen); 22560a708f8fSGustavo F. Padovan break; 22570a708f8fSGustavo F. Padovan 22580a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS: 22590a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE) 2260c1360a1cSGustavo F. Padovan set_bit(CONF_NO_FCS_RECV, &chan->conf_state); 226142dceae2SAndrei Emeltchenko break; 22620a708f8fSGustavo F. Padovan 226342dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS: 226442dceae2SAndrei Emeltchenko remote_efs = 1; 226542dceae2SAndrei Emeltchenko if (olen == sizeof(efs)) 226642dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen); 22670a708f8fSGustavo F. Padovan break; 22680a708f8fSGustavo F. Padovan 22696327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 22706327eb98SAndrei Emeltchenko if (!enable_hs) 22716327eb98SAndrei Emeltchenko return -ECONNREFUSED; 22726327eb98SAndrei Emeltchenko 22736327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 22746327eb98SAndrei Emeltchenko set_bit(CONF_EWS_RECV, &chan->conf_state); 2275836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 22766327eb98SAndrei Emeltchenko chan->remote_tx_win = val; 22770a708f8fSGustavo F. Padovan break; 22780a708f8fSGustavo F. Padovan 22790a708f8fSGustavo F. Padovan default: 22800a708f8fSGustavo F. Padovan if (hint) 22810a708f8fSGustavo F. Padovan break; 22820a708f8fSGustavo F. Padovan 22830a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN; 22840a708f8fSGustavo F. Padovan *((u8 *) ptr++) = type; 22850a708f8fSGustavo F. Padovan break; 22860a708f8fSGustavo F. Padovan } 22870a708f8fSGustavo F. Padovan } 22880a708f8fSGustavo F. Padovan 228973ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1) 22900a708f8fSGustavo F. Padovan goto done; 22910a708f8fSGustavo F. Padovan 22920c1bc5c6SGustavo F. Padovan switch (chan->mode) { 22930a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 22940a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 2295c1360a1cSGustavo F. Padovan if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { 22960c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, 22978c1d787bSGustavo F. Padovan chan->conn->feat_mask); 22980a708f8fSGustavo F. Padovan break; 22990a708f8fSGustavo F. Padovan } 23000a708f8fSGustavo F. Padovan 230142dceae2SAndrei Emeltchenko if (remote_efs) { 230242dceae2SAndrei Emeltchenko if (__l2cap_efs_supported(chan)) 230342dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 230442dceae2SAndrei Emeltchenko else 230542dceae2SAndrei Emeltchenko return -ECONNREFUSED; 230642dceae2SAndrei Emeltchenko } 230742dceae2SAndrei Emeltchenko 23080c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) 23090a708f8fSGustavo F. Padovan return -ECONNREFUSED; 23100a708f8fSGustavo F. Padovan 23110a708f8fSGustavo F. Padovan break; 23120a708f8fSGustavo F. Padovan } 23130a708f8fSGustavo F. Padovan 23140a708f8fSGustavo F. Padovan done: 23150c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) { 23160a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 23170c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 23180a708f8fSGustavo F. Padovan 231973ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1) 23200a708f8fSGustavo F. Padovan return -ECONNREFUSED; 23210a708f8fSGustavo F. Padovan 23220a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 23230a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 23240a708f8fSGustavo F. Padovan } 23250a708f8fSGustavo F. Padovan 23260a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) { 23270a708f8fSGustavo F. Padovan /* Configure output options and let the other side know 23280a708f8fSGustavo F. Padovan * which ones we don't like. */ 23290a708f8fSGustavo F. Padovan 23300a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU) 23310a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 23320a708f8fSGustavo F. Padovan else { 23330c1bc5c6SGustavo F. Padovan chan->omtu = mtu; 2334c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state); 23350a708f8fSGustavo F. Padovan } 23360c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); 23370a708f8fSGustavo F. Padovan 233842dceae2SAndrei Emeltchenko if (remote_efs) { 233942dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 234042dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 234142dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) { 234242dceae2SAndrei Emeltchenko 234342dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT; 234442dceae2SAndrei Emeltchenko 234542dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1) 234642dceae2SAndrei Emeltchenko return -ECONNREFUSED; 234742dceae2SAndrei Emeltchenko 234842dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 234942dceae2SAndrei Emeltchenko sizeof(efs), 235042dceae2SAndrei Emeltchenko (unsigned long) &efs); 23510e8b207eSAndrei Emeltchenko } else { 23523e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */ 23530e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING; 23540e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 235542dceae2SAndrei Emeltchenko } 235642dceae2SAndrei Emeltchenko } 235742dceae2SAndrei Emeltchenko 23580a708f8fSGustavo F. Padovan switch (rfc.mode) { 23590a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 236047d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 2361c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 23620a708f8fSGustavo F. Padovan break; 23630a708f8fSGustavo F. Padovan 23640a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 23656327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state)) 23662c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size; 23676327eb98SAndrei Emeltchenko else 23686327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; 23696327eb98SAndrei Emeltchenko 23702c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit; 23710a708f8fSGustavo F. Padovan 2372c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 2373c8f79162SAndrei Emeltchenko chan->conn->mtu - 2374c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2375c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2376c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2377c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 2378c8f79162SAndrei Emeltchenko chan->remote_mps = size; 23790a708f8fSGustavo F. Padovan 23800a708f8fSGustavo F. Padovan rfc.retrans_timeout = 23810a708f8fSGustavo F. Padovan le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO); 23820a708f8fSGustavo F. Padovan rfc.monitor_timeout = 23830a708f8fSGustavo F. Padovan le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO); 23840a708f8fSGustavo F. Padovan 2385c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 23860a708f8fSGustavo F. Padovan 23870a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 23880a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 23890a708f8fSGustavo F. Padovan 239042dceae2SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 239142dceae2SAndrei Emeltchenko chan->remote_id = efs.id; 239242dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype; 239342dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu); 239442dceae2SAndrei Emeltchenko chan->remote_flush_to = 239542dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to); 239642dceae2SAndrei Emeltchenko chan->remote_acc_lat = 239742dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat); 239842dceae2SAndrei Emeltchenko chan->remote_sdu_itime = 239942dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 240042dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 240142dceae2SAndrei Emeltchenko sizeof(efs), (unsigned long) &efs); 240242dceae2SAndrei Emeltchenko } 24030a708f8fSGustavo F. Padovan break; 24040a708f8fSGustavo F. Padovan 24050a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 2406c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 2407c8f79162SAndrei Emeltchenko chan->conn->mtu - 2408c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2409c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2410c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2411c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 2412c8f79162SAndrei Emeltchenko chan->remote_mps = size; 24130a708f8fSGustavo F. Padovan 2414c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 24150a708f8fSGustavo F. Padovan 24160a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 24170a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 24180a708f8fSGustavo F. Padovan 24190a708f8fSGustavo F. Padovan break; 24200a708f8fSGustavo F. Padovan 24210a708f8fSGustavo F. Padovan default: 24220a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 24230a708f8fSGustavo F. Padovan 24240a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc)); 24250c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 24260a708f8fSGustavo F. Padovan } 24270a708f8fSGustavo F. Padovan 24280a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) 2429c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 24300a708f8fSGustavo F. Padovan } 2431fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 24320a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 24330a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(0x0000); 24340a708f8fSGustavo F. Padovan 24350a708f8fSGustavo F. Padovan return ptr - data; 24360a708f8fSGustavo F. Padovan } 24370a708f8fSGustavo F. Padovan 2438b4450035SGustavo F. Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result) 24390a708f8fSGustavo F. Padovan { 24400a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 24410a708f8fSGustavo F. Padovan void *ptr = req->data; 24420a708f8fSGustavo F. Padovan int type, olen; 24430a708f8fSGustavo F. Padovan unsigned long val; 244436e999a8SMat Martineau struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 244566af7aafSAndrei Emeltchenko struct l2cap_conf_efs efs; 24460a708f8fSGustavo F. Padovan 2447fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); 24480a708f8fSGustavo F. Padovan 24490a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 24500a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 24510a708f8fSGustavo F. Padovan 24520a708f8fSGustavo F. Padovan switch (type) { 24530a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 24540a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) { 24550a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT; 24560c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU; 24570a708f8fSGustavo F. Padovan } else 24580c1bc5c6SGustavo F. Padovan chan->imtu = val; 24590c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 24600a708f8fSGustavo F. Padovan break; 24610a708f8fSGustavo F. Padovan 24620a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 24630c1bc5c6SGustavo F. Padovan chan->flush_to = val; 24640a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 24650c1bc5c6SGustavo F. Padovan 2, chan->flush_to); 24660a708f8fSGustavo F. Padovan break; 24670a708f8fSGustavo F. Padovan 24680a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 24690a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 24700a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 24710a708f8fSGustavo F. Padovan 2472c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && 24730c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode) 24740a708f8fSGustavo F. Padovan return -ECONNREFUSED; 24750a708f8fSGustavo F. Padovan 247647d1ec61SGustavo F. Padovan chan->fcs = 0; 24770a708f8fSGustavo F. Padovan 24780a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 24790a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 24800a708f8fSGustavo F. Padovan break; 24816327eb98SAndrei Emeltchenko 24826327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 24836327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, val, 24846327eb98SAndrei Emeltchenko L2CAP_DEFAULT_EXT_WINDOW); 24853e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 24863e6b3b95SGustavo F. Padovan chan->tx_win); 24876327eb98SAndrei Emeltchenko break; 248866af7aafSAndrei Emeltchenko 248966af7aafSAndrei Emeltchenko case L2CAP_CONF_EFS: 249066af7aafSAndrei Emeltchenko if (olen == sizeof(efs)) 249166af7aafSAndrei Emeltchenko memcpy(&efs, (void *)val, olen); 249266af7aafSAndrei Emeltchenko 249366af7aafSAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 249466af7aafSAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 249566af7aafSAndrei Emeltchenko efs.stype != chan->local_stype) 249666af7aafSAndrei Emeltchenko return -ECONNREFUSED; 249766af7aafSAndrei Emeltchenko 249866af7aafSAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 249966af7aafSAndrei Emeltchenko sizeof(efs), (unsigned long) &efs); 250066af7aafSAndrei Emeltchenko break; 25010a708f8fSGustavo F. Padovan } 25020a708f8fSGustavo F. Padovan } 25030a708f8fSGustavo F. Padovan 25040c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) 25050a708f8fSGustavo F. Padovan return -ECONNREFUSED; 25060a708f8fSGustavo F. Padovan 25070c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode; 25080a708f8fSGustavo F. Padovan 25090e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) { 25100a708f8fSGustavo F. Padovan switch (rfc.mode) { 25110a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 251247d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 251347d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 251447d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 251566af7aafSAndrei Emeltchenko 251666af7aafSAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 251766af7aafSAndrei Emeltchenko chan->local_msdu = le16_to_cpu(efs.msdu); 251866af7aafSAndrei Emeltchenko chan->local_sdu_itime = 251966af7aafSAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 252066af7aafSAndrei Emeltchenko chan->local_acc_lat = le32_to_cpu(efs.acc_lat); 252166af7aafSAndrei Emeltchenko chan->local_flush_to = 252266af7aafSAndrei Emeltchenko le32_to_cpu(efs.flush_to); 252366af7aafSAndrei Emeltchenko } 25240a708f8fSGustavo F. Padovan break; 252566af7aafSAndrei Emeltchenko 25260a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 252747d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 25280a708f8fSGustavo F. Padovan } 25290a708f8fSGustavo F. Padovan } 25300a708f8fSGustavo F. Padovan 2531fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 25320a708f8fSGustavo F. Padovan req->flags = cpu_to_le16(0x0000); 25330a708f8fSGustavo F. Padovan 25340a708f8fSGustavo F. Padovan return ptr - data; 25350a708f8fSGustavo F. Padovan } 25360a708f8fSGustavo F. Padovan 2537fe4128e0SGustavo F. Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags) 25380a708f8fSGustavo F. Padovan { 25390a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 25400a708f8fSGustavo F. Padovan void *ptr = rsp->data; 25410a708f8fSGustavo F. Padovan 2542fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan); 25430a708f8fSGustavo F. Padovan 2544fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 25450a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 25460a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags); 25470a708f8fSGustavo F. Padovan 25480a708f8fSGustavo F. Padovan return ptr - data; 25490a708f8fSGustavo F. Padovan } 25500a708f8fSGustavo F. Padovan 25518c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) 2552710f9b0aSGustavo F. Padovan { 2553710f9b0aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 25548c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 2555710f9b0aSGustavo F. Padovan u8 buf[128]; 2556710f9b0aSGustavo F. Padovan 2557fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 2558fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 2559710f9b0aSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 2560710f9b0aSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 2561710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, 2562710f9b0aSGustavo F. Padovan L2CAP_CONN_RSP, sizeof(rsp), &rsp); 2563710f9b0aSGustavo F. Padovan 2564c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 2565710f9b0aSGustavo F. Padovan return; 2566710f9b0aSGustavo F. Padovan 2567710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 2568710f9b0aSGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 2569710f9b0aSGustavo F. Padovan chan->num_conf_req++; 2570710f9b0aSGustavo F. Padovan } 2571710f9b0aSGustavo F. Padovan 257247d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) 25730a708f8fSGustavo F. Padovan { 25740a708f8fSGustavo F. Padovan int type, olen; 25750a708f8fSGustavo F. Padovan unsigned long val; 25760a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc; 25770a708f8fSGustavo F. Padovan 257847d1ec61SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); 25790a708f8fSGustavo F. Padovan 25800c1bc5c6SGustavo F. Padovan if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) 25810a708f8fSGustavo F. Padovan return; 25820a708f8fSGustavo F. Padovan 25830a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 25840a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 25850a708f8fSGustavo F. Padovan 25860a708f8fSGustavo F. Padovan switch (type) { 25870a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 25880a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 25890a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 25900a708f8fSGustavo F. Padovan goto done; 25910a708f8fSGustavo F. Padovan } 25920a708f8fSGustavo F. Padovan } 25930a708f8fSGustavo F. Padovan 259436e999a8SMat Martineau /* Use sane default values in case a misbehaving remote device 259536e999a8SMat Martineau * did not send an RFC option. 259636e999a8SMat Martineau */ 259736e999a8SMat Martineau rfc.mode = chan->mode; 259836e999a8SMat Martineau rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 259936e999a8SMat Martineau rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 260036e999a8SMat Martineau rfc.max_pdu_size = cpu_to_le16(chan->imtu); 260136e999a8SMat Martineau 260236e999a8SMat Martineau BT_ERR("Expected RFC option was not found, using defaults"); 260336e999a8SMat Martineau 26040a708f8fSGustavo F. Padovan done: 26050a708f8fSGustavo F. Padovan switch (rfc.mode) { 26060a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 260747d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 260847d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 260947d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 26100a708f8fSGustavo F. Padovan break; 26110a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 261247d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 26130a708f8fSGustavo F. Padovan } 26140a708f8fSGustavo F. Padovan } 26150a708f8fSGustavo F. Padovan 26160a708f8fSGustavo F. Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 26170a708f8fSGustavo F. Padovan { 2618e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 26190a708f8fSGustavo F. Padovan 2620e2fd318eSIlia Kolomisnky if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) 26210a708f8fSGustavo F. Padovan return 0; 26220a708f8fSGustavo F. Padovan 26230a708f8fSGustavo F. Padovan if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && 26240a708f8fSGustavo F. Padovan cmd->ident == conn->info_ident) { 262517cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 26260a708f8fSGustavo F. Padovan 26270a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 26280a708f8fSGustavo F. Padovan conn->info_ident = 0; 26290a708f8fSGustavo F. Padovan 26300a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 26310a708f8fSGustavo F. Padovan } 26320a708f8fSGustavo F. Padovan 26330a708f8fSGustavo F. Padovan return 0; 26340a708f8fSGustavo F. Padovan } 26350a708f8fSGustavo F. Padovan 26360a708f8fSGustavo F. Padovan static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 26370a708f8fSGustavo F. Padovan { 26380a708f8fSGustavo F. Padovan struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 26390a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 264023691d75SGustavo F. Padovan struct l2cap_chan *chan = NULL, *pchan; 26410a708f8fSGustavo F. Padovan struct sock *parent, *sk = NULL; 26420a708f8fSGustavo F. Padovan int result, status = L2CAP_CS_NO_INFO; 26430a708f8fSGustavo F. Padovan 26440a708f8fSGustavo F. Padovan u16 dcid = 0, scid = __le16_to_cpu(req->scid); 26450a708f8fSGustavo F. Padovan __le16 psm = req->psm; 26460a708f8fSGustavo F. Padovan 2647097db76cSAndrei Emeltchenko BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); 26480a708f8fSGustavo F. Padovan 26490a708f8fSGustavo F. Padovan /* Check if we have socket listening on psm */ 265023691d75SGustavo F. Padovan pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src); 265123691d75SGustavo F. Padovan if (!pchan) { 26520a708f8fSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 26530a708f8fSGustavo F. Padovan goto sendresp; 26540a708f8fSGustavo F. Padovan } 26550a708f8fSGustavo F. Padovan 265623691d75SGustavo F. Padovan parent = pchan->sk; 265723691d75SGustavo F. Padovan 26583df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 2659aa2ac881SGustavo F. Padovan lock_sock(parent); 26600a708f8fSGustavo F. Padovan 26610a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */ 26620a708f8fSGustavo F. Padovan if (psm != cpu_to_le16(0x0001) && 26630a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) { 26649f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_AUTH_FAILURE; 26650a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 26660a708f8fSGustavo F. Padovan goto response; 26670a708f8fSGustavo F. Padovan } 26680a708f8fSGustavo F. Padovan 26690a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM; 26700a708f8fSGustavo F. Padovan 26710a708f8fSGustavo F. Padovan /* Check for backlog size */ 26720a708f8fSGustavo F. Padovan if (sk_acceptq_is_full(parent)) { 26730a708f8fSGustavo F. Padovan BT_DBG("backlog full %d", parent->sk_ack_backlog); 26740a708f8fSGustavo F. Padovan goto response; 26750a708f8fSGustavo F. Padovan } 26760a708f8fSGustavo F. Padovan 267780808e43SGustavo F. Padovan chan = pchan->ops->new_connection(pchan->data); 267880808e43SGustavo F. Padovan if (!chan) 26790a708f8fSGustavo F. Padovan goto response; 26800a708f8fSGustavo F. Padovan 268180808e43SGustavo F. Padovan sk = chan->sk; 268280808e43SGustavo F. Padovan 26830a708f8fSGustavo F. Padovan /* Check if we already have channel with that dcid */ 2684baa7e1faSGustavo F. Padovan if (__l2cap_get_chan_by_dcid(conn, scid)) { 26850a708f8fSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 2686ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 26870a708f8fSGustavo F. Padovan goto response; 26880a708f8fSGustavo F. Padovan } 26890a708f8fSGustavo F. Padovan 26900a708f8fSGustavo F. Padovan hci_conn_hold(conn->hcon); 26910a708f8fSGustavo F. Padovan 26920a708f8fSGustavo F. Padovan bacpy(&bt_sk(sk)->src, conn->src); 26930a708f8fSGustavo F. Padovan bacpy(&bt_sk(sk)->dst, conn->dst); 2694fe4128e0SGustavo F. Padovan chan->psm = psm; 2695fe4128e0SGustavo F. Padovan chan->dcid = scid; 26960a708f8fSGustavo F. Padovan 2697d1010240SGustavo F. Padovan bt_accept_enqueue(parent, sk); 2698d1010240SGustavo F. Padovan 26996be36555SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 270048454079SGustavo F. Padovan 2701fe4128e0SGustavo F. Padovan dcid = chan->scid; 27020a708f8fSGustavo F. Padovan 2703c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 27040a708f8fSGustavo F. Padovan 2705fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident; 27060a708f8fSGustavo F. Padovan 27070a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { 2708d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 27090a708f8fSGustavo F. Padovan if (bt_sk(sk)->defer_setup) { 27100e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 27110a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 27120a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND; 27130a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 27140a708f8fSGustavo F. Padovan } else { 27150e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 27160a708f8fSGustavo F. Padovan result = L2CAP_CR_SUCCESS; 27170a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 27180a708f8fSGustavo F. Padovan } 27190a708f8fSGustavo F. Padovan } else { 27200e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 27210a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 27220a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND; 27230a708f8fSGustavo F. Padovan } 27240a708f8fSGustavo F. Padovan } else { 27250e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 27260a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 27270a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 27280a708f8fSGustavo F. Padovan } 27290a708f8fSGustavo F. Padovan 27300a708f8fSGustavo F. Padovan response: 2731aa2ac881SGustavo F. Padovan release_sock(parent); 27323df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 27330a708f8fSGustavo F. Padovan 27340a708f8fSGustavo F. Padovan sendresp: 27350a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid); 27360a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid); 27370a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result); 27380a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status); 27390a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); 27400a708f8fSGustavo F. Padovan 27410a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { 27420a708f8fSGustavo F. Padovan struct l2cap_info_req info; 27430a708f8fSGustavo F. Padovan info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 27440a708f8fSGustavo F. Padovan 27450a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 27460a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 27470a708f8fSGustavo F. Padovan 2748ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 27490a708f8fSGustavo F. Padovan 27500a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 27510a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(info), &info); 27520a708f8fSGustavo F. Padovan } 27530a708f8fSGustavo F. Padovan 2754c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && 27550a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) { 27560a708f8fSGustavo F. Padovan u8 buf[128]; 2757c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 27580a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 275973ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 276073ffa904SGustavo F. Padovan chan->num_conf_req++; 27610a708f8fSGustavo F. Padovan } 27620a708f8fSGustavo F. Padovan 27630a708f8fSGustavo F. Padovan return 0; 27640a708f8fSGustavo F. Padovan } 27650a708f8fSGustavo F. Padovan 27660a708f8fSGustavo F. Padovan static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 27670a708f8fSGustavo F. Padovan { 27680a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; 27690a708f8fSGustavo F. Padovan u16 scid, dcid, result, status; 277048454079SGustavo F. Padovan struct l2cap_chan *chan; 27710a708f8fSGustavo F. Padovan u8 req[128]; 27723df91ea2SAndrei Emeltchenko int err; 27730a708f8fSGustavo F. Padovan 27740a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 27750a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 27760a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 27770a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status); 27780a708f8fSGustavo F. Padovan 27791b009c98SAndrei Emeltchenko BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", 27801b009c98SAndrei Emeltchenko dcid, scid, result, status); 27810a708f8fSGustavo F. Padovan 27823df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 27833df91ea2SAndrei Emeltchenko 27840a708f8fSGustavo F. Padovan if (scid) { 27853df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 27863df91ea2SAndrei Emeltchenko if (!chan) { 27873df91ea2SAndrei Emeltchenko err = -EFAULT; 27883df91ea2SAndrei Emeltchenko goto unlock; 27893df91ea2SAndrei Emeltchenko } 27900a708f8fSGustavo F. Padovan } else { 27913df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 27923df91ea2SAndrei Emeltchenko if (!chan) { 27933df91ea2SAndrei Emeltchenko err = -EFAULT; 27943df91ea2SAndrei Emeltchenko goto unlock; 27953df91ea2SAndrei Emeltchenko } 27960a708f8fSGustavo F. Padovan } 27970a708f8fSGustavo F. Padovan 27983df91ea2SAndrei Emeltchenko err = 0; 27993df91ea2SAndrei Emeltchenko 28006be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 280148454079SGustavo F. Padovan 28020a708f8fSGustavo F. Padovan switch (result) { 28030a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS: 280489bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 2805fc7f8a7eSGustavo F. Padovan chan->ident = 0; 2806fe4128e0SGustavo F. Padovan chan->dcid = dcid; 2807c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state); 28080a708f8fSGustavo F. Padovan 2809c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 28100a708f8fSGustavo F. Padovan break; 28110a708f8fSGustavo F. Padovan 28120a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 281373ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, req), req); 281473ffa904SGustavo F. Padovan chan->num_conf_req++; 28150a708f8fSGustavo F. Padovan break; 28160a708f8fSGustavo F. Padovan 28170a708f8fSGustavo F. Padovan case L2CAP_CR_PEND: 2818c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 28190a708f8fSGustavo F. Padovan break; 28200a708f8fSGustavo F. Padovan 28210a708f8fSGustavo F. Padovan default: 282248454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED); 28230a708f8fSGustavo F. Padovan break; 28240a708f8fSGustavo F. Padovan } 28250a708f8fSGustavo F. Padovan 28266be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 28273df91ea2SAndrei Emeltchenko 28283df91ea2SAndrei Emeltchenko unlock: 28293df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 28303df91ea2SAndrei Emeltchenko 28313df91ea2SAndrei Emeltchenko return err; 28320a708f8fSGustavo F. Padovan } 28330a708f8fSGustavo F. Padovan 283447d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan) 28350a708f8fSGustavo F. Padovan { 28360a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both 28370a708f8fSGustavo F. Padovan * sides request it. 28380a708f8fSGustavo F. Padovan */ 28390c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) 284047d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 2841c1360a1cSGustavo F. Padovan else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) 284247d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16; 28430a708f8fSGustavo F. Padovan } 28440a708f8fSGustavo F. Padovan 28450a708f8fSGustavo F. Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 28460a708f8fSGustavo F. Padovan { 28470a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; 28480a708f8fSGustavo F. Padovan u16 dcid, flags; 28490a708f8fSGustavo F. Padovan u8 rsp[64]; 285048454079SGustavo F. Padovan struct l2cap_chan *chan; 28510a708f8fSGustavo F. Padovan int len; 28520a708f8fSGustavo F. Padovan 28530a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 28540a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags); 28550a708f8fSGustavo F. Padovan 28560a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); 28570a708f8fSGustavo F. Padovan 2858baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid); 285948454079SGustavo F. Padovan if (!chan) 28600a708f8fSGustavo F. Padovan return -ENOENT; 28610a708f8fSGustavo F. Padovan 28626be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 286348454079SGustavo F. Padovan 2864033b1142SDavid S. Miller if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { 2865e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_cid rej; 28660a708f8fSGustavo F. Padovan 2867e2fd318eSIlia Kolomisnky rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID); 2868e2fd318eSIlia Kolomisnky rej.scid = cpu_to_le16(chan->scid); 2869e2fd318eSIlia Kolomisnky rej.dcid = cpu_to_le16(chan->dcid); 2870e2fd318eSIlia Kolomisnky 28710a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 28720a708f8fSGustavo F. Padovan sizeof(rej), &rej); 28730a708f8fSGustavo F. Padovan goto unlock; 28740a708f8fSGustavo F. Padovan } 28750a708f8fSGustavo F. Padovan 28760a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */ 28770a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req); 28787ac28817SDan Rosenberg if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) { 28790a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 2880fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 28810a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp); 28820a708f8fSGustavo F. Padovan goto unlock; 28830a708f8fSGustavo F. Padovan } 28840a708f8fSGustavo F. Padovan 28850a708f8fSGustavo F. Padovan /* Store config. */ 288673ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len); 288773ffa904SGustavo F. Padovan chan->conf_len += len; 28880a708f8fSGustavo F. Padovan 28890a708f8fSGustavo F. Padovan if (flags & 0x0001) { 28900a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */ 28910a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 2892fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 28930a708f8fSGustavo F. Padovan L2CAP_CONF_SUCCESS, 0x0001), rsp); 28940a708f8fSGustavo F. Padovan goto unlock; 28950a708f8fSGustavo F. Padovan } 28960a708f8fSGustavo F. Padovan 28970a708f8fSGustavo F. Padovan /* Complete config. */ 289873ffa904SGustavo F. Padovan len = l2cap_parse_conf_req(chan, rsp); 28990a708f8fSGustavo F. Padovan if (len < 0) { 2900e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 29010a708f8fSGustavo F. Padovan goto unlock; 29020a708f8fSGustavo F. Padovan } 29030a708f8fSGustavo F. Padovan 29040a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); 290573ffa904SGustavo F. Padovan chan->num_conf_rsp++; 29060a708f8fSGustavo F. Padovan 29070a708f8fSGustavo F. Padovan /* Reset config buffer. */ 290873ffa904SGustavo F. Padovan chan->conf_len = 0; 29090a708f8fSGustavo F. Padovan 2910c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) 29110a708f8fSGustavo F. Padovan goto unlock; 29120a708f8fSGustavo F. Padovan 2913c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 291447d1ec61SGustavo F. Padovan set_default_fcs(chan); 29150a708f8fSGustavo F. Padovan 291689bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECTED); 29170a708f8fSGustavo F. Padovan 291842e5c802SGustavo F. Padovan chan->next_tx_seq = 0; 291942e5c802SGustavo F. Padovan chan->expected_tx_seq = 0; 292058d35f87SGustavo F. Padovan skb_queue_head_init(&chan->tx_q); 29210c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_ERTM) 2922525cd185SGustavo F. Padovan l2cap_ertm_init(chan); 29230a708f8fSGustavo F. Padovan 2924cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 29250a708f8fSGustavo F. Padovan goto unlock; 29260a708f8fSGustavo F. Padovan } 29270a708f8fSGustavo F. Padovan 2928c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { 29290a708f8fSGustavo F. Padovan u8 buf[64]; 29300a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 293173ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 293273ffa904SGustavo F. Padovan chan->num_conf_req++; 29330a708f8fSGustavo F. Padovan } 29340a708f8fSGustavo F. Padovan 29350e8b207eSAndrei Emeltchenko /* Got Conf Rsp PENDING from remote side and asume we sent 29360e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */ 29370e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && 29380e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 29390e8b207eSAndrei Emeltchenko 29400e8b207eSAndrei Emeltchenko /* check compatibility */ 29410e8b207eSAndrei Emeltchenko 29420e8b207eSAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 29430e8b207eSAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 29440e8b207eSAndrei Emeltchenko 29450e8b207eSAndrei Emeltchenko l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 29460e8b207eSAndrei Emeltchenko l2cap_build_conf_rsp(chan, rsp, 29470e8b207eSAndrei Emeltchenko L2CAP_CONF_SUCCESS, 0x0000), rsp); 29480e8b207eSAndrei Emeltchenko } 29490e8b207eSAndrei Emeltchenko 29500a708f8fSGustavo F. Padovan unlock: 29516be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 29520a708f8fSGustavo F. Padovan return 0; 29530a708f8fSGustavo F. Padovan } 29540a708f8fSGustavo F. Padovan 29550a708f8fSGustavo F. Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 29560a708f8fSGustavo F. Padovan { 29570a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; 29580a708f8fSGustavo F. Padovan u16 scid, flags, result; 295948454079SGustavo F. Padovan struct l2cap_chan *chan; 296061386cbaSAndrei Emeltchenko int len = le16_to_cpu(cmd->len) - sizeof(*rsp); 29610a708f8fSGustavo F. Padovan 29620a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 29630a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags); 29640a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 29650a708f8fSGustavo F. Padovan 296661386cbaSAndrei Emeltchenko BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags, 296761386cbaSAndrei Emeltchenko result, len); 29680a708f8fSGustavo F. Padovan 2969baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 297048454079SGustavo F. Padovan if (!chan) 29710a708f8fSGustavo F. Padovan return 0; 29720a708f8fSGustavo F. Padovan 29736be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 297448454079SGustavo F. Padovan 29750a708f8fSGustavo F. Padovan switch (result) { 29760a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS: 297747d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len); 29780e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state); 29790a708f8fSGustavo F. Padovan break; 29800a708f8fSGustavo F. Padovan 29810e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING: 29820e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state); 29830e8b207eSAndrei Emeltchenko 29840e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 29850e8b207eSAndrei Emeltchenko char buf[64]; 29860e8b207eSAndrei Emeltchenko 29870e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len, 29880e8b207eSAndrei Emeltchenko buf, &result); 29890e8b207eSAndrei Emeltchenko if (len < 0) { 29900e8b207eSAndrei Emeltchenko l2cap_send_disconn_req(conn, chan, ECONNRESET); 29910e8b207eSAndrei Emeltchenko goto done; 29920e8b207eSAndrei Emeltchenko } 29930e8b207eSAndrei Emeltchenko 29940e8b207eSAndrei Emeltchenko /* check compatibility */ 29950e8b207eSAndrei Emeltchenko 29960e8b207eSAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 29970e8b207eSAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 29980e8b207eSAndrei Emeltchenko 29990e8b207eSAndrei Emeltchenko l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 30000e8b207eSAndrei Emeltchenko l2cap_build_conf_rsp(chan, buf, 30010e8b207eSAndrei Emeltchenko L2CAP_CONF_SUCCESS, 0x0000), buf); 30020e8b207eSAndrei Emeltchenko } 30030e8b207eSAndrei Emeltchenko goto done; 30040e8b207eSAndrei Emeltchenko 30050a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT: 300673ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { 30070a708f8fSGustavo F. Padovan char req[64]; 30080a708f8fSGustavo F. Padovan 30090a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { 3010e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 30110a708f8fSGustavo F. Padovan goto done; 30120a708f8fSGustavo F. Padovan } 30130a708f8fSGustavo F. Padovan 30140a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */ 30150a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS; 3016b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len, 3017b4450035SGustavo F. Padovan req, &result); 30180a708f8fSGustavo F. Padovan if (len < 0) { 3019e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 30200a708f8fSGustavo F. Padovan goto done; 30210a708f8fSGustavo F. Padovan } 30220a708f8fSGustavo F. Padovan 30230a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 30240a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req); 302573ffa904SGustavo F. Padovan chan->num_conf_req++; 30260a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS) 30270a708f8fSGustavo F. Padovan goto done; 30280a708f8fSGustavo F. Padovan break; 30290a708f8fSGustavo F. Padovan } 30300a708f8fSGustavo F. Padovan 30310a708f8fSGustavo F. Padovan default: 30326be36555SAndrei Emeltchenko l2cap_chan_set_err(chan, ECONNRESET); 30332e0052e4SAndrei Emeltchenko 3034ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); 3035e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 30360a708f8fSGustavo F. Padovan goto done; 30370a708f8fSGustavo F. Padovan } 30380a708f8fSGustavo F. Padovan 30390a708f8fSGustavo F. Padovan if (flags & 0x01) 30400a708f8fSGustavo F. Padovan goto done; 30410a708f8fSGustavo F. Padovan 3042c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state); 30430a708f8fSGustavo F. Padovan 3044c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { 304547d1ec61SGustavo F. Padovan set_default_fcs(chan); 30460a708f8fSGustavo F. Padovan 304789bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECTED); 304842e5c802SGustavo F. Padovan chan->next_tx_seq = 0; 304942e5c802SGustavo F. Padovan chan->expected_tx_seq = 0; 305058d35f87SGustavo F. Padovan skb_queue_head_init(&chan->tx_q); 30510c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_ERTM) 3052525cd185SGustavo F. Padovan l2cap_ertm_init(chan); 30530a708f8fSGustavo F. Padovan 3054cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 30550a708f8fSGustavo F. Padovan } 30560a708f8fSGustavo F. Padovan 30570a708f8fSGustavo F. Padovan done: 30586be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 30590a708f8fSGustavo F. Padovan return 0; 30600a708f8fSGustavo F. Padovan } 30610a708f8fSGustavo F. Padovan 30620a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 30630a708f8fSGustavo F. Padovan { 30640a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; 30650a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp; 30660a708f8fSGustavo F. Padovan u16 dcid, scid; 306748454079SGustavo F. Padovan struct l2cap_chan *chan; 30680a708f8fSGustavo F. Padovan struct sock *sk; 30690a708f8fSGustavo F. Padovan 30700a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid); 30710a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 30720a708f8fSGustavo F. Padovan 30730a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); 30740a708f8fSGustavo F. Padovan 30753df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 30763df91ea2SAndrei Emeltchenko 30773df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, dcid); 30783df91ea2SAndrei Emeltchenko if (!chan) { 30793df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 30800a708f8fSGustavo F. Padovan return 0; 30813df91ea2SAndrei Emeltchenko } 30820a708f8fSGustavo F. Padovan 30836be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 30846be36555SAndrei Emeltchenko 308548454079SGustavo F. Padovan sk = chan->sk; 308648454079SGustavo F. Padovan 3087fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3088fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 30890a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); 30900a708f8fSGustavo F. Padovan 30916be36555SAndrei Emeltchenko lock_sock(sk); 30920a708f8fSGustavo F. Padovan sk->sk_shutdown = SHUTDOWN_MASK; 30936be36555SAndrei Emeltchenko release_sock(sk); 30940a708f8fSGustavo F. Padovan 309548454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET); 30966be36555SAndrei Emeltchenko 30976be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 30980a708f8fSGustavo F. Padovan 3099ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 31003df91ea2SAndrei Emeltchenko 31013df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 31023df91ea2SAndrei Emeltchenko 31030a708f8fSGustavo F. Padovan return 0; 31040a708f8fSGustavo F. Padovan } 31050a708f8fSGustavo F. Padovan 31060a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 31070a708f8fSGustavo F. Padovan { 31080a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; 31090a708f8fSGustavo F. Padovan u16 dcid, scid; 311048454079SGustavo F. Padovan struct l2cap_chan *chan; 31110a708f8fSGustavo F. Padovan 31120a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 31130a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 31140a708f8fSGustavo F. Padovan 31150a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); 31160a708f8fSGustavo F. Padovan 31173df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 31183df91ea2SAndrei Emeltchenko 31193df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 31203df91ea2SAndrei Emeltchenko if (!chan) { 31213df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 31220a708f8fSGustavo F. Padovan return 0; 31233df91ea2SAndrei Emeltchenko } 31240a708f8fSGustavo F. Padovan 31256be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 312648454079SGustavo F. Padovan 312748454079SGustavo F. Padovan l2cap_chan_del(chan, 0); 31286be36555SAndrei Emeltchenko 31296be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 31300a708f8fSGustavo F. Padovan 3131ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 31323df91ea2SAndrei Emeltchenko 31333df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 31343df91ea2SAndrei Emeltchenko 31350a708f8fSGustavo F. Padovan return 0; 31360a708f8fSGustavo F. Padovan } 31370a708f8fSGustavo F. Padovan 31380a708f8fSGustavo F. Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 31390a708f8fSGustavo F. Padovan { 31400a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data; 31410a708f8fSGustavo F. Padovan u16 type; 31420a708f8fSGustavo F. Padovan 31430a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type); 31440a708f8fSGustavo F. Padovan 31450a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type); 31460a708f8fSGustavo F. Padovan 31470a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) { 31480a708f8fSGustavo F. Padovan u8 buf[8]; 31490a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask; 31500a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 31510a708f8fSGustavo F. Padovan rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 31520a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 31530a708f8fSGustavo F. Padovan if (!disable_ertm) 31540a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING 31550a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS; 3156a5fd6f30SAndrei Emeltchenko if (enable_hs) 31576327eb98SAndrei Emeltchenko feat_mask |= L2CAP_FEAT_EXT_FLOW 31586327eb98SAndrei Emeltchenko | L2CAP_FEAT_EXT_WINDOW; 3159a5fd6f30SAndrei Emeltchenko 31600a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data); 31610a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 31620a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(buf), buf); 31630a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) { 31640a708f8fSGustavo F. Padovan u8 buf[12]; 31650a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 316650a147cdSMat Martineau 316750a147cdSMat Martineau if (enable_hs) 316850a147cdSMat Martineau l2cap_fixed_chan[0] |= L2CAP_FC_A2MP; 316950a147cdSMat Martineau else 317050a147cdSMat Martineau l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP; 317150a147cdSMat Martineau 31720a708f8fSGustavo F. Padovan rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 31730a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 3174c6337ea6SAndrei Emeltchenko memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); 31750a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 31760a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(buf), buf); 31770a708f8fSGustavo F. Padovan } else { 31780a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp; 31790a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type); 31800a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP); 31810a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 31820a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(rsp), &rsp); 31830a708f8fSGustavo F. Padovan } 31840a708f8fSGustavo F. Padovan 31850a708f8fSGustavo F. Padovan return 0; 31860a708f8fSGustavo F. Padovan } 31870a708f8fSGustavo F. Padovan 31880a708f8fSGustavo F. Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 31890a708f8fSGustavo F. Padovan { 31900a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; 31910a708f8fSGustavo F. Padovan u16 type, result; 31920a708f8fSGustavo F. Padovan 31930a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type); 31940a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 31950a708f8fSGustavo F. Padovan 31960a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); 31970a708f8fSGustavo F. Padovan 3198e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */ 3199e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident || 3200e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 3201e90165beSAndrei Emeltchenko return 0; 3202e90165beSAndrei Emeltchenko 320317cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 32040a708f8fSGustavo F. Padovan 32050a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) { 32060a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 32070a708f8fSGustavo F. Padovan conn->info_ident = 0; 32080a708f8fSGustavo F. Padovan 32090a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 32100a708f8fSGustavo F. Padovan 32110a708f8fSGustavo F. Padovan return 0; 32120a708f8fSGustavo F. Padovan } 32130a708f8fSGustavo F. Padovan 3214978c93b9SAndrei Emeltchenko switch (type) { 3215978c93b9SAndrei Emeltchenko case L2CAP_IT_FEAT_MASK: 32160a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data); 32170a708f8fSGustavo F. Padovan 32180a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { 32190a708f8fSGustavo F. Padovan struct l2cap_info_req req; 32200a708f8fSGustavo F. Padovan req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 32210a708f8fSGustavo F. Padovan 32220a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 32230a708f8fSGustavo F. Padovan 32240a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 32250a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 32260a708f8fSGustavo F. Padovan } else { 32270a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 32280a708f8fSGustavo F. Padovan conn->info_ident = 0; 32290a708f8fSGustavo F. Padovan 32300a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 32310a708f8fSGustavo F. Padovan } 3232978c93b9SAndrei Emeltchenko break; 3233978c93b9SAndrei Emeltchenko 3234978c93b9SAndrei Emeltchenko case L2CAP_IT_FIXED_CHAN: 3235978c93b9SAndrei Emeltchenko conn->fixed_chan_mask = rsp->data[0]; 32360a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 32370a708f8fSGustavo F. Padovan conn->info_ident = 0; 32380a708f8fSGustavo F. Padovan 32390a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 3240978c93b9SAndrei Emeltchenko break; 32410a708f8fSGustavo F. Padovan } 32420a708f8fSGustavo F. Padovan 32430a708f8fSGustavo F. Padovan return 0; 32440a708f8fSGustavo F. Padovan } 32450a708f8fSGustavo F. Padovan 3246f94ff6ffSMat Martineau static inline int l2cap_create_channel_req(struct l2cap_conn *conn, 3247f94ff6ffSMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, 3248f94ff6ffSMat Martineau void *data) 3249f94ff6ffSMat Martineau { 3250f94ff6ffSMat Martineau struct l2cap_create_chan_req *req = data; 3251f94ff6ffSMat Martineau struct l2cap_create_chan_rsp rsp; 3252f94ff6ffSMat Martineau u16 psm, scid; 3253f94ff6ffSMat Martineau 3254f94ff6ffSMat Martineau if (cmd_len != sizeof(*req)) 3255f94ff6ffSMat Martineau return -EPROTO; 3256f94ff6ffSMat Martineau 3257f94ff6ffSMat Martineau if (!enable_hs) 3258f94ff6ffSMat Martineau return -EINVAL; 3259f94ff6ffSMat Martineau 3260f94ff6ffSMat Martineau psm = le16_to_cpu(req->psm); 3261f94ff6ffSMat Martineau scid = le16_to_cpu(req->scid); 3262f94ff6ffSMat Martineau 3263f94ff6ffSMat Martineau BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id); 3264f94ff6ffSMat Martineau 3265f94ff6ffSMat Martineau /* Placeholder: Always reject */ 3266f94ff6ffSMat Martineau rsp.dcid = 0; 3267f94ff6ffSMat Martineau rsp.scid = cpu_to_le16(scid); 3268f94ff6ffSMat Martineau rsp.result = L2CAP_CR_NO_MEM; 3269f94ff6ffSMat Martineau rsp.status = L2CAP_CS_NO_INFO; 3270f94ff6ffSMat Martineau 3271f94ff6ffSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, 3272f94ff6ffSMat Martineau sizeof(rsp), &rsp); 3273f94ff6ffSMat Martineau 3274f94ff6ffSMat Martineau return 0; 3275f94ff6ffSMat Martineau } 3276f94ff6ffSMat Martineau 3277f94ff6ffSMat Martineau static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn, 3278f94ff6ffSMat Martineau struct l2cap_cmd_hdr *cmd, void *data) 3279f94ff6ffSMat Martineau { 3280f94ff6ffSMat Martineau BT_DBG("conn %p", conn); 3281f94ff6ffSMat Martineau 3282f94ff6ffSMat Martineau return l2cap_connect_rsp(conn, cmd, data); 3283f94ff6ffSMat Martineau } 3284f94ff6ffSMat Martineau 32858d5a04a1SMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident, 32868d5a04a1SMat Martineau u16 icid, u16 result) 32878d5a04a1SMat Martineau { 32888d5a04a1SMat Martineau struct l2cap_move_chan_rsp rsp; 32898d5a04a1SMat Martineau 32908d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 32918d5a04a1SMat Martineau 32928d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 32938d5a04a1SMat Martineau rsp.result = cpu_to_le16(result); 32948d5a04a1SMat Martineau 32958d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp); 32968d5a04a1SMat Martineau } 32978d5a04a1SMat Martineau 32988d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn, 32998d5a04a1SMat Martineau struct l2cap_chan *chan, u16 icid, u16 result) 33008d5a04a1SMat Martineau { 33018d5a04a1SMat Martineau struct l2cap_move_chan_cfm cfm; 33028d5a04a1SMat Martineau u8 ident; 33038d5a04a1SMat Martineau 33048d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 33058d5a04a1SMat Martineau 33068d5a04a1SMat Martineau ident = l2cap_get_ident(conn); 33078d5a04a1SMat Martineau if (chan) 33088d5a04a1SMat Martineau chan->ident = ident; 33098d5a04a1SMat Martineau 33108d5a04a1SMat Martineau cfm.icid = cpu_to_le16(icid); 33118d5a04a1SMat Martineau cfm.result = cpu_to_le16(result); 33128d5a04a1SMat Martineau 33138d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm); 33148d5a04a1SMat Martineau } 33158d5a04a1SMat Martineau 33168d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, 33178d5a04a1SMat Martineau u16 icid) 33188d5a04a1SMat Martineau { 33198d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp rsp; 33208d5a04a1SMat Martineau 33218d5a04a1SMat Martineau BT_DBG("icid %d", icid); 33228d5a04a1SMat Martineau 33238d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 33248d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp); 33258d5a04a1SMat Martineau } 33268d5a04a1SMat Martineau 33278d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn, 33288d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 33298d5a04a1SMat Martineau { 33308d5a04a1SMat Martineau struct l2cap_move_chan_req *req = data; 33318d5a04a1SMat Martineau u16 icid = 0; 33328d5a04a1SMat Martineau u16 result = L2CAP_MR_NOT_ALLOWED; 33338d5a04a1SMat Martineau 33348d5a04a1SMat Martineau if (cmd_len != sizeof(*req)) 33358d5a04a1SMat Martineau return -EPROTO; 33368d5a04a1SMat Martineau 33378d5a04a1SMat Martineau icid = le16_to_cpu(req->icid); 33388d5a04a1SMat Martineau 33398d5a04a1SMat Martineau BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id); 33408d5a04a1SMat Martineau 33418d5a04a1SMat Martineau if (!enable_hs) 33428d5a04a1SMat Martineau return -EINVAL; 33438d5a04a1SMat Martineau 33448d5a04a1SMat Martineau /* Placeholder: Always refuse */ 33458d5a04a1SMat Martineau l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result); 33468d5a04a1SMat Martineau 33478d5a04a1SMat Martineau return 0; 33488d5a04a1SMat Martineau } 33498d5a04a1SMat Martineau 33508d5a04a1SMat Martineau static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn, 33518d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 33528d5a04a1SMat Martineau { 33538d5a04a1SMat Martineau struct l2cap_move_chan_rsp *rsp = data; 33548d5a04a1SMat Martineau u16 icid, result; 33558d5a04a1SMat Martineau 33568d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 33578d5a04a1SMat Martineau return -EPROTO; 33588d5a04a1SMat Martineau 33598d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 33608d5a04a1SMat Martineau result = le16_to_cpu(rsp->result); 33618d5a04a1SMat Martineau 33628d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 33638d5a04a1SMat Martineau 33648d5a04a1SMat Martineau /* Placeholder: Always unconfirmed */ 33658d5a04a1SMat Martineau l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED); 33668d5a04a1SMat Martineau 33678d5a04a1SMat Martineau return 0; 33688d5a04a1SMat Martineau } 33698d5a04a1SMat Martineau 33708d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn, 33718d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 33728d5a04a1SMat Martineau { 33738d5a04a1SMat Martineau struct l2cap_move_chan_cfm *cfm = data; 33748d5a04a1SMat Martineau u16 icid, result; 33758d5a04a1SMat Martineau 33768d5a04a1SMat Martineau if (cmd_len != sizeof(*cfm)) 33778d5a04a1SMat Martineau return -EPROTO; 33788d5a04a1SMat Martineau 33798d5a04a1SMat Martineau icid = le16_to_cpu(cfm->icid); 33808d5a04a1SMat Martineau result = le16_to_cpu(cfm->result); 33818d5a04a1SMat Martineau 33828d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 33838d5a04a1SMat Martineau 33848d5a04a1SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 33858d5a04a1SMat Martineau 33868d5a04a1SMat Martineau return 0; 33878d5a04a1SMat Martineau } 33888d5a04a1SMat Martineau 33898d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, 33908d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 33918d5a04a1SMat Martineau { 33928d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp *rsp = data; 33938d5a04a1SMat Martineau u16 icid; 33948d5a04a1SMat Martineau 33958d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 33968d5a04a1SMat Martineau return -EPROTO; 33978d5a04a1SMat Martineau 33988d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 33998d5a04a1SMat Martineau 34008d5a04a1SMat Martineau BT_DBG("icid %d", icid); 34018d5a04a1SMat Martineau 34028d5a04a1SMat Martineau return 0; 34038d5a04a1SMat Martineau } 34048d5a04a1SMat Martineau 3405e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency, 3406de73115aSClaudio Takahasi u16 to_multiplier) 3407de73115aSClaudio Takahasi { 3408de73115aSClaudio Takahasi u16 max_latency; 3409de73115aSClaudio Takahasi 3410de73115aSClaudio Takahasi if (min > max || min < 6 || max > 3200) 3411de73115aSClaudio Takahasi return -EINVAL; 3412de73115aSClaudio Takahasi 3413de73115aSClaudio Takahasi if (to_multiplier < 10 || to_multiplier > 3200) 3414de73115aSClaudio Takahasi return -EINVAL; 3415de73115aSClaudio Takahasi 3416de73115aSClaudio Takahasi if (max >= to_multiplier * 8) 3417de73115aSClaudio Takahasi return -EINVAL; 3418de73115aSClaudio Takahasi 3419de73115aSClaudio Takahasi max_latency = (to_multiplier * 8 / max) - 1; 3420de73115aSClaudio Takahasi if (latency > 499 || latency > max_latency) 3421de73115aSClaudio Takahasi return -EINVAL; 3422de73115aSClaudio Takahasi 3423de73115aSClaudio Takahasi return 0; 3424de73115aSClaudio Takahasi } 3425de73115aSClaudio Takahasi 3426de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, 3427de73115aSClaudio Takahasi struct l2cap_cmd_hdr *cmd, u8 *data) 3428de73115aSClaudio Takahasi { 3429de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon; 3430de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req; 3431de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp; 3432de73115aSClaudio Takahasi u16 min, max, latency, to_multiplier, cmd_len; 34332ce603ebSClaudio Takahasi int err; 3434de73115aSClaudio Takahasi 3435de73115aSClaudio Takahasi if (!(hcon->link_mode & HCI_LM_MASTER)) 3436de73115aSClaudio Takahasi return -EINVAL; 3437de73115aSClaudio Takahasi 3438de73115aSClaudio Takahasi cmd_len = __le16_to_cpu(cmd->len); 3439de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) 3440de73115aSClaudio Takahasi return -EPROTO; 3441de73115aSClaudio Takahasi 3442de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data; 3443de73115aSClaudio Takahasi min = __le16_to_cpu(req->min); 3444de73115aSClaudio Takahasi max = __le16_to_cpu(req->max); 3445de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency); 3446de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier); 3447de73115aSClaudio Takahasi 3448de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", 3449de73115aSClaudio Takahasi min, max, latency, to_multiplier); 3450de73115aSClaudio Takahasi 3451de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp)); 34522ce603ebSClaudio Takahasi 34532ce603ebSClaudio Takahasi err = l2cap_check_conn_param(min, max, latency, to_multiplier); 34542ce603ebSClaudio Takahasi if (err) 3455de73115aSClaudio Takahasi rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); 3456de73115aSClaudio Takahasi else 3457de73115aSClaudio Takahasi rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); 3458de73115aSClaudio Takahasi 3459de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, 3460de73115aSClaudio Takahasi sizeof(rsp), &rsp); 3461de73115aSClaudio Takahasi 34622ce603ebSClaudio Takahasi if (!err) 34632ce603ebSClaudio Takahasi hci_le_conn_update(hcon, min, max, latency, to_multiplier); 34642ce603ebSClaudio Takahasi 3465de73115aSClaudio Takahasi return 0; 3466de73115aSClaudio Takahasi } 3467de73115aSClaudio Takahasi 34683300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, 34693300d9a9SClaudio Takahasi struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 34703300d9a9SClaudio Takahasi { 34713300d9a9SClaudio Takahasi int err = 0; 34723300d9a9SClaudio Takahasi 34733300d9a9SClaudio Takahasi switch (cmd->code) { 34743300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 34753300d9a9SClaudio Takahasi l2cap_command_rej(conn, cmd, data); 34763300d9a9SClaudio Takahasi break; 34773300d9a9SClaudio Takahasi 34783300d9a9SClaudio Takahasi case L2CAP_CONN_REQ: 34793300d9a9SClaudio Takahasi err = l2cap_connect_req(conn, cmd, data); 34803300d9a9SClaudio Takahasi break; 34813300d9a9SClaudio Takahasi 34823300d9a9SClaudio Takahasi case L2CAP_CONN_RSP: 34833300d9a9SClaudio Takahasi err = l2cap_connect_rsp(conn, cmd, data); 34843300d9a9SClaudio Takahasi break; 34853300d9a9SClaudio Takahasi 34863300d9a9SClaudio Takahasi case L2CAP_CONF_REQ: 34873300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data); 34883300d9a9SClaudio Takahasi break; 34893300d9a9SClaudio Takahasi 34903300d9a9SClaudio Takahasi case L2CAP_CONF_RSP: 34913300d9a9SClaudio Takahasi err = l2cap_config_rsp(conn, cmd, data); 34923300d9a9SClaudio Takahasi break; 34933300d9a9SClaudio Takahasi 34943300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ: 34953300d9a9SClaudio Takahasi err = l2cap_disconnect_req(conn, cmd, data); 34963300d9a9SClaudio Takahasi break; 34973300d9a9SClaudio Takahasi 34983300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP: 34993300d9a9SClaudio Takahasi err = l2cap_disconnect_rsp(conn, cmd, data); 35003300d9a9SClaudio Takahasi break; 35013300d9a9SClaudio Takahasi 35023300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ: 35033300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data); 35043300d9a9SClaudio Takahasi break; 35053300d9a9SClaudio Takahasi 35063300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP: 35073300d9a9SClaudio Takahasi break; 35083300d9a9SClaudio Takahasi 35093300d9a9SClaudio Takahasi case L2CAP_INFO_REQ: 35103300d9a9SClaudio Takahasi err = l2cap_information_req(conn, cmd, data); 35113300d9a9SClaudio Takahasi break; 35123300d9a9SClaudio Takahasi 35133300d9a9SClaudio Takahasi case L2CAP_INFO_RSP: 35143300d9a9SClaudio Takahasi err = l2cap_information_rsp(conn, cmd, data); 35153300d9a9SClaudio Takahasi break; 35163300d9a9SClaudio Takahasi 3517f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_REQ: 3518f94ff6ffSMat Martineau err = l2cap_create_channel_req(conn, cmd, cmd_len, data); 3519f94ff6ffSMat Martineau break; 3520f94ff6ffSMat Martineau 3521f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_RSP: 3522f94ff6ffSMat Martineau err = l2cap_create_channel_rsp(conn, cmd, data); 3523f94ff6ffSMat Martineau break; 3524f94ff6ffSMat Martineau 35258d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_REQ: 35268d5a04a1SMat Martineau err = l2cap_move_channel_req(conn, cmd, cmd_len, data); 35278d5a04a1SMat Martineau break; 35288d5a04a1SMat Martineau 35298d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_RSP: 35308d5a04a1SMat Martineau err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data); 35318d5a04a1SMat Martineau break; 35328d5a04a1SMat Martineau 35338d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM: 35348d5a04a1SMat Martineau err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data); 35358d5a04a1SMat Martineau break; 35368d5a04a1SMat Martineau 35378d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM_RSP: 35388d5a04a1SMat Martineau err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data); 35398d5a04a1SMat Martineau break; 35408d5a04a1SMat Martineau 35413300d9a9SClaudio Takahasi default: 35423300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code); 35433300d9a9SClaudio Takahasi err = -EINVAL; 35443300d9a9SClaudio Takahasi break; 35453300d9a9SClaudio Takahasi } 35463300d9a9SClaudio Takahasi 35473300d9a9SClaudio Takahasi return err; 35483300d9a9SClaudio Takahasi } 35493300d9a9SClaudio Takahasi 35503300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, 35513300d9a9SClaudio Takahasi struct l2cap_cmd_hdr *cmd, u8 *data) 35523300d9a9SClaudio Takahasi { 35533300d9a9SClaudio Takahasi switch (cmd->code) { 35543300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 35553300d9a9SClaudio Takahasi return 0; 35563300d9a9SClaudio Takahasi 35573300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ: 3558de73115aSClaudio Takahasi return l2cap_conn_param_update_req(conn, cmd, data); 35593300d9a9SClaudio Takahasi 35603300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP: 35613300d9a9SClaudio Takahasi return 0; 35623300d9a9SClaudio Takahasi 35633300d9a9SClaudio Takahasi default: 35643300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code); 35653300d9a9SClaudio Takahasi return -EINVAL; 35663300d9a9SClaudio Takahasi } 35673300d9a9SClaudio Takahasi } 35683300d9a9SClaudio Takahasi 35693300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn, 35703300d9a9SClaudio Takahasi struct sk_buff *skb) 35710a708f8fSGustavo F. Padovan { 35720a708f8fSGustavo F. Padovan u8 *data = skb->data; 35730a708f8fSGustavo F. Padovan int len = skb->len; 35740a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr cmd; 35753300d9a9SClaudio Takahasi int err; 35760a708f8fSGustavo F. Padovan 35770a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb); 35780a708f8fSGustavo F. Padovan 35790a708f8fSGustavo F. Padovan while (len >= L2CAP_CMD_HDR_SIZE) { 35800a708f8fSGustavo F. Padovan u16 cmd_len; 35810a708f8fSGustavo F. Padovan memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); 35820a708f8fSGustavo F. Padovan data += L2CAP_CMD_HDR_SIZE; 35830a708f8fSGustavo F. Padovan len -= L2CAP_CMD_HDR_SIZE; 35840a708f8fSGustavo F. Padovan 35850a708f8fSGustavo F. Padovan cmd_len = le16_to_cpu(cmd.len); 35860a708f8fSGustavo F. Padovan 35870a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident); 35880a708f8fSGustavo F. Padovan 35890a708f8fSGustavo F. Padovan if (cmd_len > len || !cmd.ident) { 35900a708f8fSGustavo F. Padovan BT_DBG("corrupted command"); 35910a708f8fSGustavo F. Padovan break; 35920a708f8fSGustavo F. Padovan } 35930a708f8fSGustavo F. Padovan 35943300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 35953300d9a9SClaudio Takahasi err = l2cap_le_sig_cmd(conn, &cmd, data); 35963300d9a9SClaudio Takahasi else 35973300d9a9SClaudio Takahasi err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data); 35980a708f8fSGustavo F. Padovan 35990a708f8fSGustavo F. Padovan if (err) { 3600e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk rej; 36012c6d1a2eSGustavo F. Padovan 36022c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err); 36030a708f8fSGustavo F. Padovan 36040a708f8fSGustavo F. Padovan /* FIXME: Map err to a valid reason */ 3605e2fd318eSIlia Kolomisnky rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 36060a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); 36070a708f8fSGustavo F. Padovan } 36080a708f8fSGustavo F. Padovan 36090a708f8fSGustavo F. Padovan data += cmd_len; 36100a708f8fSGustavo F. Padovan len -= cmd_len; 36110a708f8fSGustavo F. Padovan } 36120a708f8fSGustavo F. Padovan 36130a708f8fSGustavo F. Padovan kfree_skb(skb); 36140a708f8fSGustavo F. Padovan } 36150a708f8fSGustavo F. Padovan 361647d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) 36170a708f8fSGustavo F. Padovan { 36180a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs; 3619e4ca6d98SAndrei Emeltchenko int hdr_size; 3620e4ca6d98SAndrei Emeltchenko 3621e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 3622e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE; 3623e4ca6d98SAndrei Emeltchenko else 3624e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE; 36250a708f8fSGustavo F. Padovan 362647d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 362703a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE); 36280a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len); 36290a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); 36300a708f8fSGustavo F. Padovan 36310a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs) 36320a708f8fSGustavo F. Padovan return -EBADMSG; 36330a708f8fSGustavo F. Padovan } 36340a708f8fSGustavo F. Padovan return 0; 36350a708f8fSGustavo F. Padovan } 36360a708f8fSGustavo F. Padovan 3637525cd185SGustavo F. Padovan static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) 36380a708f8fSGustavo F. Padovan { 363988843ab0SAndrei Emeltchenko u32 control = 0; 36400a708f8fSGustavo F. Padovan 36416a026610SGustavo F. Padovan chan->frames_sent = 0; 36420a708f8fSGustavo F. Padovan 36430b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 36440a708f8fSGustavo F. Padovan 3645e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 3646ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); 3647525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 3648e2ab4353SGustavo F. Padovan set_bit(CONN_RNR_SENT, &chan->conn_state); 36490a708f8fSGustavo F. Padovan } 36500a708f8fSGustavo F. Padovan 3651e2ab4353SGustavo F. Padovan if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 3652525cd185SGustavo F. Padovan l2cap_retransmit_frames(chan); 36530a708f8fSGustavo F. Padovan 3654525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 36550a708f8fSGustavo F. Padovan 3656e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 36576a026610SGustavo F. Padovan chan->frames_sent == 0) { 3658ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 3659525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 36600a708f8fSGustavo F. Padovan } 36610a708f8fSGustavo F. Padovan } 36620a708f8fSGustavo F. Padovan 3663fb45de7dSAndrei Emeltchenko static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u16 tx_seq, u8 sar) 36640a708f8fSGustavo F. Padovan { 36650a708f8fSGustavo F. Padovan struct sk_buff *next_skb; 36660a708f8fSGustavo F. Padovan int tx_seq_offset, next_tx_seq_offset; 36670a708f8fSGustavo F. Padovan 36680a708f8fSGustavo F. Padovan bt_cb(skb)->tx_seq = tx_seq; 36690a708f8fSGustavo F. Padovan bt_cb(skb)->sar = sar; 36700a708f8fSGustavo F. Padovan 3671f1c6775bSGustavo F. Padovan next_skb = skb_peek(&chan->srej_q); 36720a708f8fSGustavo F. Padovan 3673836be934SAndrei Emeltchenko tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq); 36740a708f8fSGustavo F. Padovan 3675039d9572SSzymon Janc while (next_skb) { 36760a708f8fSGustavo F. Padovan if (bt_cb(next_skb)->tx_seq == tx_seq) 36770a708f8fSGustavo F. Padovan return -EINVAL; 36780a708f8fSGustavo F. Padovan 3679836be934SAndrei Emeltchenko next_tx_seq_offset = __seq_offset(chan, 3680836be934SAndrei Emeltchenko bt_cb(next_skb)->tx_seq, chan->buffer_seq); 36810a708f8fSGustavo F. Padovan 36820a708f8fSGustavo F. Padovan if (next_tx_seq_offset > tx_seq_offset) { 3683f1c6775bSGustavo F. Padovan __skb_queue_before(&chan->srej_q, next_skb, skb); 36840a708f8fSGustavo F. Padovan return 0; 36850a708f8fSGustavo F. Padovan } 36860a708f8fSGustavo F. Padovan 3687f1c6775bSGustavo F. Padovan if (skb_queue_is_last(&chan->srej_q, next_skb)) 3688039d9572SSzymon Janc next_skb = NULL; 3689039d9572SSzymon Janc else 3690039d9572SSzymon Janc next_skb = skb_queue_next(&chan->srej_q, next_skb); 3691039d9572SSzymon Janc } 36920a708f8fSGustavo F. Padovan 3693f1c6775bSGustavo F. Padovan __skb_queue_tail(&chan->srej_q, skb); 36940a708f8fSGustavo F. Padovan 36950a708f8fSGustavo F. Padovan return 0; 36960a708f8fSGustavo F. Padovan } 36970a708f8fSGustavo F. Padovan 369884084a31SMat Martineau static void append_skb_frag(struct sk_buff *skb, 369984084a31SMat Martineau struct sk_buff *new_frag, struct sk_buff **last_frag) 37000a708f8fSGustavo F. Padovan { 370184084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments 370284084a31SMat Martineau * skb->data_len reflects only data in fragments 370384084a31SMat Martineau */ 370484084a31SMat Martineau if (!skb_has_frag_list(skb)) 370584084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag; 370684084a31SMat Martineau 370784084a31SMat Martineau new_frag->next = NULL; 370884084a31SMat Martineau 370984084a31SMat Martineau (*last_frag)->next = new_frag; 371084084a31SMat Martineau *last_frag = new_frag; 371184084a31SMat Martineau 371284084a31SMat Martineau skb->len += new_frag->len; 371384084a31SMat Martineau skb->data_len += new_frag->len; 371484084a31SMat Martineau skb->truesize += new_frag->truesize; 371584084a31SMat Martineau } 371684084a31SMat Martineau 371788843ab0SAndrei Emeltchenko static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control) 371884084a31SMat Martineau { 371984084a31SMat Martineau int err = -EINVAL; 37200a708f8fSGustavo F. Padovan 37217e0ef6eeSAndrei Emeltchenko switch (__get_ctrl_sar(chan, control)) { 37227e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED: 372384084a31SMat Martineau if (chan->sdu) 372484084a31SMat Martineau break; 37250a708f8fSGustavo F. Padovan 372684084a31SMat Martineau err = chan->ops->recv(chan->data, skb); 372784084a31SMat Martineau break; 37280a708f8fSGustavo F. Padovan 37297e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START: 373084084a31SMat Martineau if (chan->sdu) 373184084a31SMat Martineau break; 37320a708f8fSGustavo F. Padovan 37336f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data); 373403a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE); 37350a708f8fSGustavo F. Padovan 373684084a31SMat Martineau if (chan->sdu_len > chan->imtu) { 373784084a31SMat Martineau err = -EMSGSIZE; 373884084a31SMat Martineau break; 373984084a31SMat Martineau } 37400a708f8fSGustavo F. Padovan 374184084a31SMat Martineau if (skb->len >= chan->sdu_len) 374284084a31SMat Martineau break; 374384084a31SMat Martineau 374484084a31SMat Martineau chan->sdu = skb; 374584084a31SMat Martineau chan->sdu_last_frag = skb; 374684084a31SMat Martineau 374784084a31SMat Martineau skb = NULL; 374884084a31SMat Martineau err = 0; 37490a708f8fSGustavo F. Padovan break; 37500a708f8fSGustavo F. Padovan 37517e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE: 37526f61fd47SGustavo F. Padovan if (!chan->sdu) 375384084a31SMat Martineau break; 37540a708f8fSGustavo F. Padovan 375584084a31SMat Martineau append_skb_frag(chan->sdu, skb, 375684084a31SMat Martineau &chan->sdu_last_frag); 375784084a31SMat Martineau skb = NULL; 37580a708f8fSGustavo F. Padovan 375984084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len) 376084084a31SMat Martineau break; 37610a708f8fSGustavo F. Padovan 376284084a31SMat Martineau err = 0; 37630a708f8fSGustavo F. Padovan break; 37640a708f8fSGustavo F. Padovan 37657e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END: 37666f61fd47SGustavo F. Padovan if (!chan->sdu) 376784084a31SMat Martineau break; 37680a708f8fSGustavo F. Padovan 376984084a31SMat Martineau append_skb_frag(chan->sdu, skb, 377084084a31SMat Martineau &chan->sdu_last_frag); 377184084a31SMat Martineau skb = NULL; 37720a708f8fSGustavo F. Padovan 377384084a31SMat Martineau if (chan->sdu->len != chan->sdu_len) 377484084a31SMat Martineau break; 37750a708f8fSGustavo F. Padovan 377684084a31SMat Martineau err = chan->ops->recv(chan->data, chan->sdu); 37770a708f8fSGustavo F. Padovan 377884084a31SMat Martineau if (!err) { 377984084a31SMat Martineau /* Reassembly complete */ 378084084a31SMat Martineau chan->sdu = NULL; 378184084a31SMat Martineau chan->sdu_last_frag = NULL; 378284084a31SMat Martineau chan->sdu_len = 0; 37830a708f8fSGustavo F. Padovan } 37840a708f8fSGustavo F. Padovan break; 37850a708f8fSGustavo F. Padovan } 37860a708f8fSGustavo F. Padovan 378784084a31SMat Martineau if (err) { 37880a708f8fSGustavo F. Padovan kfree_skb(skb); 37896f61fd47SGustavo F. Padovan kfree_skb(chan->sdu); 37906f61fd47SGustavo F. Padovan chan->sdu = NULL; 379184084a31SMat Martineau chan->sdu_last_frag = NULL; 379284084a31SMat Martineau chan->sdu_len = 0; 379384084a31SMat Martineau } 37940a708f8fSGustavo F. Padovan 379584084a31SMat Martineau return err; 37960a708f8fSGustavo F. Padovan } 37970a708f8fSGustavo F. Padovan 379826f880d2SMat Martineau static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan) 37990a708f8fSGustavo F. Padovan { 380026f880d2SMat Martineau BT_DBG("chan %p, Enter local busy", chan); 380126f880d2SMat Martineau 380226f880d2SMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 380326f880d2SMat Martineau 380477f918bcSSzymon Janc __set_ack_timer(chan); 38050a708f8fSGustavo F. Padovan } 38060a708f8fSGustavo F. Padovan 380726f880d2SMat Martineau static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan) 380826f880d2SMat Martineau { 380988843ab0SAndrei Emeltchenko u32 control; 38100a708f8fSGustavo F. Padovan 3811e2ab4353SGustavo F. Padovan if (!test_bit(CONN_RNR_SENT, &chan->conn_state)) 38120a708f8fSGustavo F. Padovan goto done; 38130a708f8fSGustavo F. Padovan 38140b209faeSAndrei Emeltchenko control = __set_reqseq(chan, chan->buffer_seq); 3815e3781735SAndrei Emeltchenko control |= __set_ctrl_poll(chan); 3816ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 3817525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 38186a026610SGustavo F. Padovan chan->retry_count = 1; 38190a708f8fSGustavo F. Padovan 38201a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 38211a09bcb9SGustavo F. Padovan __set_monitor_timer(chan); 38220a708f8fSGustavo F. Padovan 3823e2ab4353SGustavo F. Padovan set_bit(CONN_WAIT_F, &chan->conn_state); 38240a708f8fSGustavo F. Padovan 38250a708f8fSGustavo F. Padovan done: 3826e2ab4353SGustavo F. Padovan clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 3827e2ab4353SGustavo F. Padovan clear_bit(CONN_RNR_SENT, &chan->conn_state); 38280a708f8fSGustavo F. Padovan 382949208c9cSGustavo F. Padovan BT_DBG("chan %p, Exit local busy", chan); 38300a708f8fSGustavo F. Padovan } 38310a708f8fSGustavo F. Padovan 3832e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 38330a708f8fSGustavo F. Padovan { 3834e328140fSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) { 3835e328140fSMat Martineau if (busy) 383626f880d2SMat Martineau l2cap_ertm_enter_local_busy(chan); 3837e328140fSMat Martineau else 3838e328140fSMat Martineau l2cap_ertm_exit_local_busy(chan); 38390a708f8fSGustavo F. Padovan } 38400a708f8fSGustavo F. Padovan } 38410a708f8fSGustavo F. Padovan 3842fb45de7dSAndrei Emeltchenko static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq) 38430a708f8fSGustavo F. Padovan { 38440a708f8fSGustavo F. Padovan struct sk_buff *skb; 384588843ab0SAndrei Emeltchenko u32 control; 38460a708f8fSGustavo F. Padovan 3847e328140fSMat Martineau while ((skb = skb_peek(&chan->srej_q)) && 3848e328140fSMat Martineau !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 3849e328140fSMat Martineau int err; 3850e328140fSMat Martineau 38510a708f8fSGustavo F. Padovan if (bt_cb(skb)->tx_seq != tx_seq) 38520a708f8fSGustavo F. Padovan break; 38530a708f8fSGustavo F. Padovan 3854f1c6775bSGustavo F. Padovan skb = skb_dequeue(&chan->srej_q); 38557e0ef6eeSAndrei Emeltchenko control = __set_ctrl_sar(chan, bt_cb(skb)->sar); 385684084a31SMat Martineau err = l2cap_reassemble_sdu(chan, skb, control); 3857e328140fSMat Martineau 3858e328140fSMat Martineau if (err < 0) { 3859e328140fSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 3860e328140fSMat Martineau break; 3861e328140fSMat Martineau } 3862e328140fSMat Martineau 3863836be934SAndrei Emeltchenko chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej); 3864836be934SAndrei Emeltchenko tx_seq = __next_seq(chan, tx_seq); 38650a708f8fSGustavo F. Padovan } 38660a708f8fSGustavo F. Padovan } 38670a708f8fSGustavo F. Padovan 3868fb45de7dSAndrei Emeltchenko static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq) 38690a708f8fSGustavo F. Padovan { 38700a708f8fSGustavo F. Padovan struct srej_list *l, *tmp; 387188843ab0SAndrei Emeltchenko u32 control; 38720a708f8fSGustavo F. Padovan 387339d5a3eeSGustavo F. Padovan list_for_each_entry_safe(l, tmp, &chan->srej_l, list) { 38740a708f8fSGustavo F. Padovan if (l->tx_seq == tx_seq) { 38750a708f8fSGustavo F. Padovan list_del(&l->list); 38760a708f8fSGustavo F. Padovan kfree(l); 38770a708f8fSGustavo F. Padovan return; 38780a708f8fSGustavo F. Padovan } 3879ab784b73SAndrei Emeltchenko control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ); 38800b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, l->tx_seq); 3881525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 38820a708f8fSGustavo F. Padovan list_del(&l->list); 388339d5a3eeSGustavo F. Padovan list_add_tail(&l->list, &chan->srej_l); 38840a708f8fSGustavo F. Padovan } 38850a708f8fSGustavo F. Padovan } 38860a708f8fSGustavo F. Padovan 3887aef89f21SSzymon Janc static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq) 38880a708f8fSGustavo F. Padovan { 38890a708f8fSGustavo F. Padovan struct srej_list *new; 389088843ab0SAndrei Emeltchenko u32 control; 38910a708f8fSGustavo F. Padovan 389242e5c802SGustavo F. Padovan while (tx_seq != chan->expected_tx_seq) { 3893ab784b73SAndrei Emeltchenko control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ); 38940b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->expected_tx_seq); 3895525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 38960a708f8fSGustavo F. Padovan 38970a708f8fSGustavo F. Padovan new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); 3898aef89f21SSzymon Janc if (!new) 3899aef89f21SSzymon Janc return -ENOMEM; 3900aef89f21SSzymon Janc 390142e5c802SGustavo F. Padovan new->tx_seq = chan->expected_tx_seq; 3902836be934SAndrei Emeltchenko 3903836be934SAndrei Emeltchenko chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); 3904836be934SAndrei Emeltchenko 390539d5a3eeSGustavo F. Padovan list_add_tail(&new->list, &chan->srej_l); 39060a708f8fSGustavo F. Padovan } 3907836be934SAndrei Emeltchenko 3908836be934SAndrei Emeltchenko chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); 3909aef89f21SSzymon Janc 3910aef89f21SSzymon Janc return 0; 39110a708f8fSGustavo F. Padovan } 39120a708f8fSGustavo F. Padovan 391388843ab0SAndrei Emeltchenko static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb) 39140a708f8fSGustavo F. Padovan { 3915fb45de7dSAndrei Emeltchenko u16 tx_seq = __get_txseq(chan, rx_control); 39160b209faeSAndrei Emeltchenko u16 req_seq = __get_reqseq(chan, rx_control); 39177e0ef6eeSAndrei Emeltchenko u8 sar = __get_ctrl_sar(chan, rx_control); 39180a708f8fSGustavo F. Padovan int tx_seq_offset, expected_tx_seq_offset; 391947d1ec61SGustavo F. Padovan int num_to_ack = (chan->tx_win/6) + 1; 39200a708f8fSGustavo F. Padovan int err = 0; 39210a708f8fSGustavo F. Padovan 392288843ab0SAndrei Emeltchenko BT_DBG("chan %p len %d tx_seq %d rx_control 0x%8.8x", chan, skb->len, 3923525cd185SGustavo F. Padovan tx_seq, rx_control); 39240a708f8fSGustavo F. Padovan 392503f6715dSAndrei Emeltchenko if (__is_ctrl_final(chan, rx_control) && 3926e2ab4353SGustavo F. Padovan test_bit(CONN_WAIT_F, &chan->conn_state)) { 39271a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 39286a026610SGustavo F. Padovan if (chan->unacked_frames > 0) 39291a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 3930e2ab4353SGustavo F. Padovan clear_bit(CONN_WAIT_F, &chan->conn_state); 39310a708f8fSGustavo F. Padovan } 39320a708f8fSGustavo F. Padovan 393342e5c802SGustavo F. Padovan chan->expected_ack_seq = req_seq; 393442e5c802SGustavo F. Padovan l2cap_drop_acked_frames(chan); 39350a708f8fSGustavo F. Padovan 3936836be934SAndrei Emeltchenko tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq); 39370a708f8fSGustavo F. Padovan 39380a708f8fSGustavo F. Padovan /* invalid tx_seq */ 393947d1ec61SGustavo F. Padovan if (tx_seq_offset >= chan->tx_win) { 39408c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 39410a708f8fSGustavo F. Padovan goto drop; 39420a708f8fSGustavo F. Padovan } 39430a708f8fSGustavo F. Padovan 394477f918bcSSzymon Janc if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 394577f918bcSSzymon Janc if (!test_bit(CONN_RNR_SENT, &chan->conn_state)) 394677f918bcSSzymon Janc l2cap_send_ack(chan); 39470a708f8fSGustavo F. Padovan goto drop; 394877f918bcSSzymon Janc } 39490a708f8fSGustavo F. Padovan 395002f1b641SMat Martineau if (tx_seq == chan->expected_tx_seq) 395102f1b641SMat Martineau goto expected; 395202f1b641SMat Martineau 3953e2ab4353SGustavo F. Padovan if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) { 39540a708f8fSGustavo F. Padovan struct srej_list *first; 39550a708f8fSGustavo F. Padovan 395639d5a3eeSGustavo F. Padovan first = list_first_entry(&chan->srej_l, 39570a708f8fSGustavo F. Padovan struct srej_list, list); 39580a708f8fSGustavo F. Padovan if (tx_seq == first->tx_seq) { 395942e5c802SGustavo F. Padovan l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); 3960525cd185SGustavo F. Padovan l2cap_check_srej_gap(chan, tx_seq); 39610a708f8fSGustavo F. Padovan 39620a708f8fSGustavo F. Padovan list_del(&first->list); 39630a708f8fSGustavo F. Padovan kfree(first); 39640a708f8fSGustavo F. Padovan 396539d5a3eeSGustavo F. Padovan if (list_empty(&chan->srej_l)) { 396642e5c802SGustavo F. Padovan chan->buffer_seq = chan->buffer_seq_srej; 3967e2ab4353SGustavo F. Padovan clear_bit(CONN_SREJ_SENT, &chan->conn_state); 3968525cd185SGustavo F. Padovan l2cap_send_ack(chan); 396949208c9cSGustavo F. Padovan BT_DBG("chan %p, Exit SREJ_SENT", chan); 39700a708f8fSGustavo F. Padovan } 39710a708f8fSGustavo F. Padovan } else { 39720a708f8fSGustavo F. Padovan struct srej_list *l; 39730a708f8fSGustavo F. Padovan 39740a708f8fSGustavo F. Padovan /* duplicated tx_seq */ 397542e5c802SGustavo F. Padovan if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0) 39760a708f8fSGustavo F. Padovan goto drop; 39770a708f8fSGustavo F. Padovan 397839d5a3eeSGustavo F. Padovan list_for_each_entry(l, &chan->srej_l, list) { 39790a708f8fSGustavo F. Padovan if (l->tx_seq == tx_seq) { 3980525cd185SGustavo F. Padovan l2cap_resend_srejframe(chan, tx_seq); 39810a708f8fSGustavo F. Padovan return 0; 39820a708f8fSGustavo F. Padovan } 39830a708f8fSGustavo F. Padovan } 3984aef89f21SSzymon Janc 3985aef89f21SSzymon Janc err = l2cap_send_srejframe(chan, tx_seq); 3986aef89f21SSzymon Janc if (err < 0) { 3987aef89f21SSzymon Janc l2cap_send_disconn_req(chan->conn, chan, -err); 3988aef89f21SSzymon Janc return err; 3989aef89f21SSzymon Janc } 39900a708f8fSGustavo F. Padovan } 39910a708f8fSGustavo F. Padovan } else { 3992836be934SAndrei Emeltchenko expected_tx_seq_offset = __seq_offset(chan, 3993836be934SAndrei Emeltchenko chan->expected_tx_seq, chan->buffer_seq); 39940a708f8fSGustavo F. Padovan 39950a708f8fSGustavo F. Padovan /* duplicated tx_seq */ 39960a708f8fSGustavo F. Padovan if (tx_seq_offset < expected_tx_seq_offset) 39970a708f8fSGustavo F. Padovan goto drop; 39980a708f8fSGustavo F. Padovan 3999e2ab4353SGustavo F. Padovan set_bit(CONN_SREJ_SENT, &chan->conn_state); 40000a708f8fSGustavo F. Padovan 400149208c9cSGustavo F. Padovan BT_DBG("chan %p, Enter SREJ", chan); 40020a708f8fSGustavo F. Padovan 400339d5a3eeSGustavo F. Padovan INIT_LIST_HEAD(&chan->srej_l); 400442e5c802SGustavo F. Padovan chan->buffer_seq_srej = chan->buffer_seq; 40050a708f8fSGustavo F. Padovan 4006f1c6775bSGustavo F. Padovan __skb_queue_head_init(&chan->srej_q); 400742e5c802SGustavo F. Padovan l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); 40080a708f8fSGustavo F. Padovan 40090ef3ef0fSSzymon Janc /* Set P-bit only if there are some I-frames to ack. */ 40100ef3ef0fSSzymon Janc if (__clear_ack_timer(chan)) 4011e2ab4353SGustavo F. Padovan set_bit(CONN_SEND_PBIT, &chan->conn_state); 40120a708f8fSGustavo F. Padovan 4013aef89f21SSzymon Janc err = l2cap_send_srejframe(chan, tx_seq); 4014aef89f21SSzymon Janc if (err < 0) { 4015aef89f21SSzymon Janc l2cap_send_disconn_req(chan->conn, chan, -err); 4016aef89f21SSzymon Janc return err; 4017aef89f21SSzymon Janc } 40180a708f8fSGustavo F. Padovan } 40190a708f8fSGustavo F. Padovan return 0; 40200a708f8fSGustavo F. Padovan 40210a708f8fSGustavo F. Padovan expected: 4022836be934SAndrei Emeltchenko chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); 40230a708f8fSGustavo F. Padovan 4024e2ab4353SGustavo F. Padovan if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) { 40250a708f8fSGustavo F. Padovan bt_cb(skb)->tx_seq = tx_seq; 40260a708f8fSGustavo F. Padovan bt_cb(skb)->sar = sar; 4027f1c6775bSGustavo F. Padovan __skb_queue_tail(&chan->srej_q, skb); 40280a708f8fSGustavo F. Padovan return 0; 40290a708f8fSGustavo F. Padovan } 40300a708f8fSGustavo F. Padovan 403184084a31SMat Martineau err = l2cap_reassemble_sdu(chan, skb, rx_control); 4032836be934SAndrei Emeltchenko chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 4033836be934SAndrei Emeltchenko 4034e328140fSMat Martineau if (err < 0) { 4035e328140fSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 4036e328140fSMat Martineau return err; 4037e328140fSMat Martineau } 40380a708f8fSGustavo F. Padovan 403903f6715dSAndrei Emeltchenko if (__is_ctrl_final(chan, rx_control)) { 4040e2ab4353SGustavo F. Padovan if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 4041525cd185SGustavo F. Padovan l2cap_retransmit_frames(chan); 40420a708f8fSGustavo F. Padovan } 40430a708f8fSGustavo F. Padovan 40440a708f8fSGustavo F. Padovan 40456a026610SGustavo F. Padovan chan->num_acked = (chan->num_acked + 1) % num_to_ack; 40466a026610SGustavo F. Padovan if (chan->num_acked == num_to_ack - 1) 4047525cd185SGustavo F. Padovan l2cap_send_ack(chan); 40484d611e4dSGustavo F. Padovan else 40494d611e4dSGustavo F. Padovan __set_ack_timer(chan); 40500a708f8fSGustavo F. Padovan 40510a708f8fSGustavo F. Padovan return 0; 40520a708f8fSGustavo F. Padovan 40530a708f8fSGustavo F. Padovan drop: 40540a708f8fSGustavo F. Padovan kfree_skb(skb); 40550a708f8fSGustavo F. Padovan return 0; 40560a708f8fSGustavo F. Padovan } 40570a708f8fSGustavo F. Padovan 405888843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control) 40590a708f8fSGustavo F. Padovan { 406088843ab0SAndrei Emeltchenko BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, 40610b209faeSAndrei Emeltchenko __get_reqseq(chan, rx_control), rx_control); 40620a708f8fSGustavo F. Padovan 40630b209faeSAndrei Emeltchenko chan->expected_ack_seq = __get_reqseq(chan, rx_control); 406442e5c802SGustavo F. Padovan l2cap_drop_acked_frames(chan); 40650a708f8fSGustavo F. Padovan 4066e3781735SAndrei Emeltchenko if (__is_ctrl_poll(chan, rx_control)) { 4067e2ab4353SGustavo F. Padovan set_bit(CONN_SEND_FBIT, &chan->conn_state); 4068e2ab4353SGustavo F. Padovan if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) { 4069e2ab4353SGustavo F. Padovan if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 40706a026610SGustavo F. Padovan (chan->unacked_frames > 0)) 40711a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 40720a708f8fSGustavo F. Padovan 4073e2ab4353SGustavo F. Padovan clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4074525cd185SGustavo F. Padovan l2cap_send_srejtail(chan); 40750a708f8fSGustavo F. Padovan } else { 4076525cd185SGustavo F. Padovan l2cap_send_i_or_rr_or_rnr(chan); 40770a708f8fSGustavo F. Padovan } 40780a708f8fSGustavo F. Padovan 407903f6715dSAndrei Emeltchenko } else if (__is_ctrl_final(chan, rx_control)) { 4080e2ab4353SGustavo F. Padovan clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 40810a708f8fSGustavo F. Padovan 4082e2ab4353SGustavo F. Padovan if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 4083525cd185SGustavo F. Padovan l2cap_retransmit_frames(chan); 40840a708f8fSGustavo F. Padovan 40850a708f8fSGustavo F. Padovan } else { 4086e2ab4353SGustavo F. Padovan if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 40876a026610SGustavo F. Padovan (chan->unacked_frames > 0)) 40881a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 40890a708f8fSGustavo F. Padovan 4090e2ab4353SGustavo F. Padovan clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4091e2ab4353SGustavo F. Padovan if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) 4092525cd185SGustavo F. Padovan l2cap_send_ack(chan); 40930a708f8fSGustavo F. Padovan else 4094525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 40950a708f8fSGustavo F. Padovan } 40960a708f8fSGustavo F. Padovan } 40970a708f8fSGustavo F. Padovan 409888843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control) 40990a708f8fSGustavo F. Padovan { 41000b209faeSAndrei Emeltchenko u16 tx_seq = __get_reqseq(chan, rx_control); 41010a708f8fSGustavo F. Padovan 410288843ab0SAndrei Emeltchenko BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control); 41030a708f8fSGustavo F. Padovan 4104e2ab4353SGustavo F. Padovan clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 41050a708f8fSGustavo F. Padovan 410642e5c802SGustavo F. Padovan chan->expected_ack_seq = tx_seq; 410742e5c802SGustavo F. Padovan l2cap_drop_acked_frames(chan); 41080a708f8fSGustavo F. Padovan 410903f6715dSAndrei Emeltchenko if (__is_ctrl_final(chan, rx_control)) { 4110e2ab4353SGustavo F. Padovan if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 4111525cd185SGustavo F. Padovan l2cap_retransmit_frames(chan); 41120a708f8fSGustavo F. Padovan } else { 4113525cd185SGustavo F. Padovan l2cap_retransmit_frames(chan); 41140a708f8fSGustavo F. Padovan 4115e2ab4353SGustavo F. Padovan if (test_bit(CONN_WAIT_F, &chan->conn_state)) 4116e2ab4353SGustavo F. Padovan set_bit(CONN_REJ_ACT, &chan->conn_state); 41170a708f8fSGustavo F. Padovan } 41180a708f8fSGustavo F. Padovan } 411988843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control) 41200a708f8fSGustavo F. Padovan { 41210b209faeSAndrei Emeltchenko u16 tx_seq = __get_reqseq(chan, rx_control); 41220a708f8fSGustavo F. Padovan 412388843ab0SAndrei Emeltchenko BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control); 41240a708f8fSGustavo F. Padovan 4125e2ab4353SGustavo F. Padovan clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 41260a708f8fSGustavo F. Padovan 4127e3781735SAndrei Emeltchenko if (__is_ctrl_poll(chan, rx_control)) { 412842e5c802SGustavo F. Padovan chan->expected_ack_seq = tx_seq; 412942e5c802SGustavo F. Padovan l2cap_drop_acked_frames(chan); 41300a708f8fSGustavo F. Padovan 4131e2ab4353SGustavo F. Padovan set_bit(CONN_SEND_FBIT, &chan->conn_state); 4132525cd185SGustavo F. Padovan l2cap_retransmit_one_frame(chan, tx_seq); 41330a708f8fSGustavo F. Padovan 4134525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 41350a708f8fSGustavo F. Padovan 4136e2ab4353SGustavo F. Padovan if (test_bit(CONN_WAIT_F, &chan->conn_state)) { 41376a026610SGustavo F. Padovan chan->srej_save_reqseq = tx_seq; 4138e2ab4353SGustavo F. Padovan set_bit(CONN_SREJ_ACT, &chan->conn_state); 41390a708f8fSGustavo F. Padovan } 414003f6715dSAndrei Emeltchenko } else if (__is_ctrl_final(chan, rx_control)) { 4141e2ab4353SGustavo F. Padovan if (test_bit(CONN_SREJ_ACT, &chan->conn_state) && 41426a026610SGustavo F. Padovan chan->srej_save_reqseq == tx_seq) 4143e2ab4353SGustavo F. Padovan clear_bit(CONN_SREJ_ACT, &chan->conn_state); 41440a708f8fSGustavo F. Padovan else 4145525cd185SGustavo F. Padovan l2cap_retransmit_one_frame(chan, tx_seq); 41460a708f8fSGustavo F. Padovan } else { 4147525cd185SGustavo F. Padovan l2cap_retransmit_one_frame(chan, tx_seq); 4148e2ab4353SGustavo F. Padovan if (test_bit(CONN_WAIT_F, &chan->conn_state)) { 41496a026610SGustavo F. Padovan chan->srej_save_reqseq = tx_seq; 4150e2ab4353SGustavo F. Padovan set_bit(CONN_SREJ_ACT, &chan->conn_state); 41510a708f8fSGustavo F. Padovan } 41520a708f8fSGustavo F. Padovan } 41530a708f8fSGustavo F. Padovan } 41540a708f8fSGustavo F. Padovan 415588843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control) 41560a708f8fSGustavo F. Padovan { 41570b209faeSAndrei Emeltchenko u16 tx_seq = __get_reqseq(chan, rx_control); 41580a708f8fSGustavo F. Padovan 415988843ab0SAndrei Emeltchenko BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control); 41600a708f8fSGustavo F. Padovan 4161e2ab4353SGustavo F. Padovan set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 416242e5c802SGustavo F. Padovan chan->expected_ack_seq = tx_seq; 416342e5c802SGustavo F. Padovan l2cap_drop_acked_frames(chan); 41640a708f8fSGustavo F. Padovan 4165e3781735SAndrei Emeltchenko if (__is_ctrl_poll(chan, rx_control)) 4166e2ab4353SGustavo F. Padovan set_bit(CONN_SEND_FBIT, &chan->conn_state); 41670a708f8fSGustavo F. Padovan 4168e2ab4353SGustavo F. Padovan if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) { 41691a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 4170e3781735SAndrei Emeltchenko if (__is_ctrl_poll(chan, rx_control)) 4171525cd185SGustavo F. Padovan l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL); 41720a708f8fSGustavo F. Padovan return; 41730a708f8fSGustavo F. Padovan } 41740a708f8fSGustavo F. Padovan 4175e3781735SAndrei Emeltchenko if (__is_ctrl_poll(chan, rx_control)) { 4176525cd185SGustavo F. Padovan l2cap_send_srejtail(chan); 4177ab784b73SAndrei Emeltchenko } else { 4178ab784b73SAndrei Emeltchenko rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR); 4179ab784b73SAndrei Emeltchenko l2cap_send_sframe(chan, rx_control); 4180ab784b73SAndrei Emeltchenko } 41810a708f8fSGustavo F. Padovan } 41820a708f8fSGustavo F. Padovan 418388843ab0SAndrei Emeltchenko static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb) 41840a708f8fSGustavo F. Padovan { 418588843ab0SAndrei Emeltchenko BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len); 41860a708f8fSGustavo F. Padovan 418703f6715dSAndrei Emeltchenko if (__is_ctrl_final(chan, rx_control) && 4188e2ab4353SGustavo F. Padovan test_bit(CONN_WAIT_F, &chan->conn_state)) { 41891a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 41906a026610SGustavo F. Padovan if (chan->unacked_frames > 0) 41911a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 4192e2ab4353SGustavo F. Padovan clear_bit(CONN_WAIT_F, &chan->conn_state); 41930a708f8fSGustavo F. Padovan } 41940a708f8fSGustavo F. Padovan 4195ab784b73SAndrei Emeltchenko switch (__get_ctrl_super(chan, rx_control)) { 4196ab784b73SAndrei Emeltchenko case L2CAP_SUPER_RR: 4197525cd185SGustavo F. Padovan l2cap_data_channel_rrframe(chan, rx_control); 41980a708f8fSGustavo F. Padovan break; 41990a708f8fSGustavo F. Padovan 4200ab784b73SAndrei Emeltchenko case L2CAP_SUPER_REJ: 4201525cd185SGustavo F. Padovan l2cap_data_channel_rejframe(chan, rx_control); 42020a708f8fSGustavo F. Padovan break; 42030a708f8fSGustavo F. Padovan 4204ab784b73SAndrei Emeltchenko case L2CAP_SUPER_SREJ: 4205525cd185SGustavo F. Padovan l2cap_data_channel_srejframe(chan, rx_control); 42060a708f8fSGustavo F. Padovan break; 42070a708f8fSGustavo F. Padovan 4208ab784b73SAndrei Emeltchenko case L2CAP_SUPER_RNR: 4209525cd185SGustavo F. Padovan l2cap_data_channel_rnrframe(chan, rx_control); 42100a708f8fSGustavo F. Padovan break; 42110a708f8fSGustavo F. Padovan } 42120a708f8fSGustavo F. Padovan 42130a708f8fSGustavo F. Padovan kfree_skb(skb); 42140a708f8fSGustavo F. Padovan return 0; 42150a708f8fSGustavo F. Padovan } 42160a708f8fSGustavo F. Padovan 4217cad8f1d0SSzymon Janc static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 42180a708f8fSGustavo F. Padovan { 421988843ab0SAndrei Emeltchenko u32 control; 42200b209faeSAndrei Emeltchenko u16 req_seq; 42210a708f8fSGustavo F. Padovan int len, next_tx_seq_offset, req_seq_offset; 42220a708f8fSGustavo F. Padovan 422388843ab0SAndrei Emeltchenko control = __get_control(chan, skb->data); 422488843ab0SAndrei Emeltchenko skb_pull(skb, __ctrl_size(chan)); 42250a708f8fSGustavo F. Padovan len = skb->len; 42260a708f8fSGustavo F. Padovan 42270a708f8fSGustavo F. Padovan /* 42280a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here. 42290a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery 42300a708f8fSGustavo F. Padovan * procedures and ask retransmission. 42310a708f8fSGustavo F. Padovan */ 423247d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 42330a708f8fSGustavo F. Padovan goto drop; 42340a708f8fSGustavo F. Padovan 4235793c2f1cSAndrei Emeltchenko if (__is_sar_start(chan, control) && !__is_sframe(chan, control)) 423603a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 42370a708f8fSGustavo F. Padovan 423847d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 423903a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 42400a708f8fSGustavo F. Padovan 424147d1ec61SGustavo F. Padovan if (len > chan->mps) { 42428c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 42430a708f8fSGustavo F. Padovan goto drop; 42440a708f8fSGustavo F. Padovan } 42450a708f8fSGustavo F. Padovan 42460b209faeSAndrei Emeltchenko req_seq = __get_reqseq(chan, control); 42470a708f8fSGustavo F. Padovan 4248836be934SAndrei Emeltchenko req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq); 4249836be934SAndrei Emeltchenko 4250836be934SAndrei Emeltchenko next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq, 4251836be934SAndrei Emeltchenko chan->expected_ack_seq); 42520a708f8fSGustavo F. Padovan 42530a708f8fSGustavo F. Padovan /* check for invalid req-seq */ 42540a708f8fSGustavo F. Padovan if (req_seq_offset > next_tx_seq_offset) { 42558c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 42560a708f8fSGustavo F. Padovan goto drop; 42570a708f8fSGustavo F. Padovan } 42580a708f8fSGustavo F. Padovan 4259793c2f1cSAndrei Emeltchenko if (!__is_sframe(chan, control)) { 42600a708f8fSGustavo F. Padovan if (len < 0) { 42618c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 42620a708f8fSGustavo F. Padovan goto drop; 42630a708f8fSGustavo F. Padovan } 42640a708f8fSGustavo F. Padovan 4265525cd185SGustavo F. Padovan l2cap_data_channel_iframe(chan, control, skb); 42660a708f8fSGustavo F. Padovan } else { 42670a708f8fSGustavo F. Padovan if (len != 0) { 42680a708f8fSGustavo F. Padovan BT_ERR("%d", len); 42698c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 42700a708f8fSGustavo F. Padovan goto drop; 42710a708f8fSGustavo F. Padovan } 42720a708f8fSGustavo F. Padovan 4273525cd185SGustavo F. Padovan l2cap_data_channel_sframe(chan, control, skb); 42740a708f8fSGustavo F. Padovan } 42750a708f8fSGustavo F. Padovan 42760a708f8fSGustavo F. Padovan return 0; 42770a708f8fSGustavo F. Padovan 42780a708f8fSGustavo F. Padovan drop: 42790a708f8fSGustavo F. Padovan kfree_skb(skb); 42800a708f8fSGustavo F. Padovan return 0; 42810a708f8fSGustavo F. Padovan } 42820a708f8fSGustavo F. Padovan 42830a708f8fSGustavo F. Padovan static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb) 42840a708f8fSGustavo F. Padovan { 428548454079SGustavo F. Padovan struct l2cap_chan *chan; 428688843ab0SAndrei Emeltchenko u32 control; 4287fb45de7dSAndrei Emeltchenko u16 tx_seq; 42880a708f8fSGustavo F. Padovan int len; 42890a708f8fSGustavo F. Padovan 4290baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 429148454079SGustavo F. Padovan if (!chan) { 42920a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid); 42936be36555SAndrei Emeltchenko /* Drop packet and return */ 42943379013bSDan Carpenter kfree_skb(skb); 42956be36555SAndrei Emeltchenko return 0; 42960a708f8fSGustavo F. Padovan } 42970a708f8fSGustavo F. Padovan 42986be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 42990a708f8fSGustavo F. Padovan 430049208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len); 43010a708f8fSGustavo F. Padovan 430289bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 43030a708f8fSGustavo F. Padovan goto drop; 43040a708f8fSGustavo F. Padovan 43050c1bc5c6SGustavo F. Padovan switch (chan->mode) { 43060a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 43070a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here 43080a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable. 43090a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't 43100a708f8fSGustavo F. Padovan * provide flow control mechanism. */ 43110a708f8fSGustavo F. Padovan 43120c1bc5c6SGustavo F. Padovan if (chan->imtu < skb->len) 43130a708f8fSGustavo F. Padovan goto drop; 43140a708f8fSGustavo F. Padovan 431523070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 43160a708f8fSGustavo F. Padovan goto done; 43170a708f8fSGustavo F. Padovan break; 43180a708f8fSGustavo F. Padovan 43190a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 43205ef8cb9eSAndrei Emeltchenko l2cap_ertm_data_rcv(chan, skb); 43210a708f8fSGustavo F. Padovan 43220a708f8fSGustavo F. Padovan goto done; 43230a708f8fSGustavo F. Padovan 43240a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 432588843ab0SAndrei Emeltchenko control = __get_control(chan, skb->data); 432688843ab0SAndrei Emeltchenko skb_pull(skb, __ctrl_size(chan)); 43270a708f8fSGustavo F. Padovan len = skb->len; 43280a708f8fSGustavo F. Padovan 432947d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 43300a708f8fSGustavo F. Padovan goto drop; 43310a708f8fSGustavo F. Padovan 43327e0ef6eeSAndrei Emeltchenko if (__is_sar_start(chan, control)) 433303a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 43340a708f8fSGustavo F. Padovan 433547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 433603a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 43370a708f8fSGustavo F. Padovan 4338793c2f1cSAndrei Emeltchenko if (len > chan->mps || len < 0 || __is_sframe(chan, control)) 43390a708f8fSGustavo F. Padovan goto drop; 43400a708f8fSGustavo F. Padovan 4341fb45de7dSAndrei Emeltchenko tx_seq = __get_txseq(chan, control); 43420a708f8fSGustavo F. Padovan 434384084a31SMat Martineau if (chan->expected_tx_seq != tx_seq) { 434484084a31SMat Martineau /* Frame(s) missing - must discard partial SDU */ 434584084a31SMat Martineau kfree_skb(chan->sdu); 434684084a31SMat Martineau chan->sdu = NULL; 434784084a31SMat Martineau chan->sdu_last_frag = NULL; 434884084a31SMat Martineau chan->sdu_len = 0; 434984084a31SMat Martineau 435084084a31SMat Martineau /* TODO: Notify userland of missing data */ 435184084a31SMat Martineau } 435284084a31SMat Martineau 4353836be934SAndrei Emeltchenko chan->expected_tx_seq = __next_seq(chan, tx_seq); 43540a708f8fSGustavo F. Padovan 435584084a31SMat Martineau if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE) 435684084a31SMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 43570a708f8fSGustavo F. Padovan 43580a708f8fSGustavo F. Padovan goto done; 43590a708f8fSGustavo F. Padovan 43600a708f8fSGustavo F. Padovan default: 43610c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); 43620a708f8fSGustavo F. Padovan break; 43630a708f8fSGustavo F. Padovan } 43640a708f8fSGustavo F. Padovan 43650a708f8fSGustavo F. Padovan drop: 43660a708f8fSGustavo F. Padovan kfree_skb(skb); 43670a708f8fSGustavo F. Padovan 43680a708f8fSGustavo F. Padovan done: 43696be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 43700a708f8fSGustavo F. Padovan 43710a708f8fSGustavo F. Padovan return 0; 43720a708f8fSGustavo F. Padovan } 43730a708f8fSGustavo F. Padovan 43740a708f8fSGustavo F. Padovan static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb) 43750a708f8fSGustavo F. Padovan { 437623691d75SGustavo F. Padovan struct l2cap_chan *chan; 43770a708f8fSGustavo F. Padovan 437823691d75SGustavo F. Padovan chan = l2cap_global_chan_by_psm(0, psm, conn->src); 437923691d75SGustavo F. Padovan if (!chan) 43800a708f8fSGustavo F. Padovan goto drop; 43810a708f8fSGustavo F. Padovan 43825b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 43830a708f8fSGustavo F. Padovan 438489bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 43850a708f8fSGustavo F. Padovan goto drop; 43860a708f8fSGustavo F. Padovan 4387e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 43880a708f8fSGustavo F. Padovan goto drop; 43890a708f8fSGustavo F. Padovan 439023070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 43915b4cedaaSAndrei Emeltchenko return 0; 43920a708f8fSGustavo F. Padovan 43930a708f8fSGustavo F. Padovan drop: 43940a708f8fSGustavo F. Padovan kfree_skb(skb); 43950a708f8fSGustavo F. Padovan 43960a708f8fSGustavo F. Padovan return 0; 43970a708f8fSGustavo F. Padovan } 43980a708f8fSGustavo F. Padovan 43999f69bda6SGustavo F. Padovan static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb) 44009f69bda6SGustavo F. Padovan { 440123691d75SGustavo F. Padovan struct l2cap_chan *chan; 44029f69bda6SGustavo F. Padovan 440323691d75SGustavo F. Padovan chan = l2cap_global_chan_by_scid(0, cid, conn->src); 440423691d75SGustavo F. Padovan if (!chan) 44059f69bda6SGustavo F. Padovan goto drop; 44069f69bda6SGustavo F. Padovan 44075b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 44089f69bda6SGustavo F. Padovan 440989bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 44109f69bda6SGustavo F. Padovan goto drop; 44119f69bda6SGustavo F. Padovan 4412e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 44139f69bda6SGustavo F. Padovan goto drop; 44149f69bda6SGustavo F. Padovan 441523070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 44165b4cedaaSAndrei Emeltchenko return 0; 44179f69bda6SGustavo F. Padovan 44189f69bda6SGustavo F. Padovan drop: 44199f69bda6SGustavo F. Padovan kfree_skb(skb); 44209f69bda6SGustavo F. Padovan 44219f69bda6SGustavo F. Padovan return 0; 44229f69bda6SGustavo F. Padovan } 44239f69bda6SGustavo F. Padovan 44240a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) 44250a708f8fSGustavo F. Padovan { 44260a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data; 44270a708f8fSGustavo F. Padovan u16 cid, len; 44280a708f8fSGustavo F. Padovan __le16 psm; 44290a708f8fSGustavo F. Padovan 44300a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE); 44310a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid); 44320a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len); 44330a708f8fSGustavo F. Padovan 44340a708f8fSGustavo F. Padovan if (len != skb->len) { 44350a708f8fSGustavo F. Padovan kfree_skb(skb); 44360a708f8fSGustavo F. Padovan return; 44370a708f8fSGustavo F. Padovan } 44380a708f8fSGustavo F. Padovan 44390a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid); 44400a708f8fSGustavo F. Padovan 44410a708f8fSGustavo F. Padovan switch (cid) { 44423300d9a9SClaudio Takahasi case L2CAP_CID_LE_SIGNALING: 44430a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING: 44440a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb); 44450a708f8fSGustavo F. Padovan break; 44460a708f8fSGustavo F. Padovan 44470a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS: 4448097db76cSAndrei Emeltchenko psm = get_unaligned((__le16 *) skb->data); 44490a708f8fSGustavo F. Padovan skb_pull(skb, 2); 44500a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb); 44510a708f8fSGustavo F. Padovan break; 44520a708f8fSGustavo F. Padovan 44539f69bda6SGustavo F. Padovan case L2CAP_CID_LE_DATA: 44549f69bda6SGustavo F. Padovan l2cap_att_channel(conn, cid, skb); 44559f69bda6SGustavo F. Padovan break; 44569f69bda6SGustavo F. Padovan 4457b501d6a1SAnderson Briglia case L2CAP_CID_SMP: 4458b501d6a1SAnderson Briglia if (smp_sig_channel(conn, skb)) 4459b501d6a1SAnderson Briglia l2cap_conn_del(conn->hcon, EACCES); 4460b501d6a1SAnderson Briglia break; 4461b501d6a1SAnderson Briglia 44620a708f8fSGustavo F. Padovan default: 44630a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb); 44640a708f8fSGustavo F. Padovan break; 44650a708f8fSGustavo F. Padovan } 44660a708f8fSGustavo F. Padovan } 44670a708f8fSGustavo F. Padovan 44680a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */ 44690a708f8fSGustavo F. Padovan 4470686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) 44710a708f8fSGustavo F. Padovan { 44720a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0; 447323691d75SGustavo F. Padovan struct l2cap_chan *c; 44740a708f8fSGustavo F. Padovan 44750a708f8fSGustavo F. Padovan BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); 44760a708f8fSGustavo F. Padovan 44770a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */ 447823691d75SGustavo F. Padovan read_lock(&chan_list_lock); 447923691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 448023691d75SGustavo F. Padovan struct sock *sk = c->sk; 44814343478fSGustavo F. Padovan 448289bc500eSGustavo F. Padovan if (c->state != BT_LISTEN) 44830a708f8fSGustavo F. Padovan continue; 44840a708f8fSGustavo F. Padovan 44850a708f8fSGustavo F. Padovan if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { 44860a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT; 448743bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 44880a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER; 44890a708f8fSGustavo F. Padovan exact++; 44900a708f8fSGustavo F. Padovan } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { 44910a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT; 449243bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 44930a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER; 44940a708f8fSGustavo F. Padovan } 44950a708f8fSGustavo F. Padovan } 449623691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 44970a708f8fSGustavo F. Padovan 44980a708f8fSGustavo F. Padovan return exact ? lm1 : lm2; 44990a708f8fSGustavo F. Padovan } 45000a708f8fSGustavo F. Padovan 4501686ebf28SUlisses Furquim int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) 45020a708f8fSGustavo F. Padovan { 45030a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 45040a708f8fSGustavo F. Padovan 45050a708f8fSGustavo F. Padovan BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); 45060a708f8fSGustavo F. Padovan 45070a708f8fSGustavo F. Padovan if (!status) { 45080a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, status); 45090a708f8fSGustavo F. Padovan if (conn) 45100a708f8fSGustavo F. Padovan l2cap_conn_ready(conn); 45110a708f8fSGustavo F. Padovan } else 4512e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status)); 45130a708f8fSGustavo F. Padovan 45140a708f8fSGustavo F. Padovan return 0; 45150a708f8fSGustavo F. Padovan } 45160a708f8fSGustavo F. Padovan 4517686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon) 45180a708f8fSGustavo F. Padovan { 45190a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 45200a708f8fSGustavo F. Padovan 45210a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon); 45220a708f8fSGustavo F. Padovan 4523686ebf28SUlisses Furquim if (!conn) 45249f5a0d7bSAndrei Emeltchenko return HCI_ERROR_REMOTE_USER_TERM; 45250a708f8fSGustavo F. Padovan return conn->disc_reason; 45260a708f8fSGustavo F. Padovan } 45270a708f8fSGustavo F. Padovan 4528686ebf28SUlisses Furquim int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) 45290a708f8fSGustavo F. Padovan { 45300a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason); 45310a708f8fSGustavo F. Padovan 4532e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason)); 45330a708f8fSGustavo F. Padovan return 0; 45340a708f8fSGustavo F. Padovan } 45350a708f8fSGustavo F. Padovan 45364343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) 45370a708f8fSGustavo F. Padovan { 4538715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 45390a708f8fSGustavo F. Padovan return; 45400a708f8fSGustavo F. Padovan 45410a708f8fSGustavo F. Padovan if (encrypt == 0x00) { 45424343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) { 4543c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 4544ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); 45454343478fSGustavo F. Padovan } else if (chan->sec_level == BT_SECURITY_HIGH) 45460f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED); 45470a708f8fSGustavo F. Padovan } else { 45484343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) 4549c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 45500a708f8fSGustavo F. Padovan } 45510a708f8fSGustavo F. Padovan } 45520a708f8fSGustavo F. Padovan 4553686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) 45540a708f8fSGustavo F. Padovan { 45550a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 455648454079SGustavo F. Padovan struct l2cap_chan *chan; 45570a708f8fSGustavo F. Padovan 45580a708f8fSGustavo F. Padovan if (!conn) 45590a708f8fSGustavo F. Padovan return 0; 45600a708f8fSGustavo F. Padovan 45610a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 45620a708f8fSGustavo F. Padovan 4563160dc6acSVinicius Costa Gomes if (hcon->type == LE_LINK) { 4564160dc6acSVinicius Costa Gomes smp_distribute_keys(conn, 0); 456517cd3f37SUlisses Furquim cancel_delayed_work(&conn->security_timer); 4566160dc6acSVinicius Costa Gomes } 4567160dc6acSVinicius Costa Gomes 45683df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 45690a708f8fSGustavo F. Padovan 45703df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 45716be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 45720a708f8fSGustavo F. Padovan 4573f1cb9af5SVinicius Costa Gomes BT_DBG("chan->scid %d", chan->scid); 4574f1cb9af5SVinicius Costa Gomes 4575f1cb9af5SVinicius Costa Gomes if (chan->scid == L2CAP_CID_LE_DATA) { 4576f1cb9af5SVinicius Costa Gomes if (!status && encrypt) { 4577f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level; 4578cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 4579f1cb9af5SVinicius Costa Gomes } 4580f1cb9af5SVinicius Costa Gomes 45816be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 4582f1cb9af5SVinicius Costa Gomes continue; 4583f1cb9af5SVinicius Costa Gomes } 4584f1cb9af5SVinicius Costa Gomes 4585c1360a1cSGustavo F. Padovan if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) { 45866be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 45870a708f8fSGustavo F. Padovan continue; 45880a708f8fSGustavo F. Padovan } 45890a708f8fSGustavo F. Padovan 459089bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED || 459189bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) { 45924343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt); 45936be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 45940a708f8fSGustavo F. Padovan continue; 45950a708f8fSGustavo F. Padovan } 45960a708f8fSGustavo F. Padovan 459789bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 45980a708f8fSGustavo F. Padovan if (!status) { 45999b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 46000a708f8fSGustavo F. Padovan } else { 4601c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 4602ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 46030a708f8fSGustavo F. Padovan } 460489bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 46056be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 46060a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 4607df3c3931SJohan Hedberg __u16 res, stat; 46080a708f8fSGustavo F. Padovan 46096be36555SAndrei Emeltchenko lock_sock(sk); 46106be36555SAndrei Emeltchenko 46110a708f8fSGustavo F. Padovan if (!status) { 4612df3c3931SJohan Hedberg if (bt_sk(sk)->defer_setup) { 4613df3c3931SJohan Hedberg struct sock *parent = bt_sk(sk)->parent; 4614df3c3931SJohan Hedberg res = L2CAP_CR_PEND; 4615df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND; 461605e9a2f6SIlia Kolomisnky if (parent) 4617df3c3931SJohan Hedberg parent->sk_data_ready(parent, 0); 4618df3c3931SJohan Hedberg } else { 46190e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 4620df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS; 4621df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 4622df3c3931SJohan Hedberg } 46230a708f8fSGustavo F. Padovan } else { 46240e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_DISCONN); 4625ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 4626df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK; 4627df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 46280a708f8fSGustavo F. Padovan } 46290a708f8fSGustavo F. Padovan 46306be36555SAndrei Emeltchenko release_sock(sk); 46316be36555SAndrei Emeltchenko 4632fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 4633fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 4634df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res); 4635df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat); 4636fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 4637fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 46380a708f8fSGustavo F. Padovan } 46390a708f8fSGustavo F. Padovan 46406be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 46410a708f8fSGustavo F. Padovan } 46420a708f8fSGustavo F. Padovan 46433df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 46440a708f8fSGustavo F. Padovan 46450a708f8fSGustavo F. Padovan return 0; 46460a708f8fSGustavo F. Padovan } 46470a708f8fSGustavo F. Padovan 4648686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) 46490a708f8fSGustavo F. Padovan { 46500a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 46510a708f8fSGustavo F. Padovan 46520a708f8fSGustavo F. Padovan if (!conn) 46530a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, 0); 46540a708f8fSGustavo F. Padovan 46550a708f8fSGustavo F. Padovan if (!conn) 46560a708f8fSGustavo F. Padovan goto drop; 46570a708f8fSGustavo F. Padovan 46580a708f8fSGustavo F. Padovan BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); 46590a708f8fSGustavo F. Padovan 46600a708f8fSGustavo F. Padovan if (!(flags & ACL_CONT)) { 46610a708f8fSGustavo F. Padovan struct l2cap_hdr *hdr; 466248454079SGustavo F. Padovan struct l2cap_chan *chan; 46630a708f8fSGustavo F. Padovan u16 cid; 46640a708f8fSGustavo F. Padovan int len; 46650a708f8fSGustavo F. Padovan 46660a708f8fSGustavo F. Padovan if (conn->rx_len) { 46670a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len); 46680a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 46690a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 46700a708f8fSGustavo F. Padovan conn->rx_len = 0; 46710a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 46720a708f8fSGustavo F. Padovan } 46730a708f8fSGustavo F. Padovan 46740a708f8fSGustavo F. Padovan /* Start fragment always begin with Basic L2CAP header */ 46750a708f8fSGustavo F. Padovan if (skb->len < L2CAP_HDR_SIZE) { 46760a708f8fSGustavo F. Padovan BT_ERR("Frame is too short (len %d)", skb->len); 46770a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 46780a708f8fSGustavo F. Padovan goto drop; 46790a708f8fSGustavo F. Padovan } 46800a708f8fSGustavo F. Padovan 46810a708f8fSGustavo F. Padovan hdr = (struct l2cap_hdr *) skb->data; 46820a708f8fSGustavo F. Padovan len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; 46830a708f8fSGustavo F. Padovan cid = __le16_to_cpu(hdr->cid); 46840a708f8fSGustavo F. Padovan 46850a708f8fSGustavo F. Padovan if (len == skb->len) { 46860a708f8fSGustavo F. Padovan /* Complete frame received */ 46870a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb); 46880a708f8fSGustavo F. Padovan return 0; 46890a708f8fSGustavo F. Padovan } 46900a708f8fSGustavo F. Padovan 46910a708f8fSGustavo F. Padovan BT_DBG("Start: total len %d, frag len %d", len, skb->len); 46920a708f8fSGustavo F. Padovan 46930a708f8fSGustavo F. Padovan if (skb->len > len) { 46940a708f8fSGustavo F. Padovan BT_ERR("Frame is too long (len %d, expected len %d)", 46950a708f8fSGustavo F. Padovan skb->len, len); 46960a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 46970a708f8fSGustavo F. Padovan goto drop; 46980a708f8fSGustavo F. Padovan } 46990a708f8fSGustavo F. Padovan 4700baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 47010a708f8fSGustavo F. Padovan 470248454079SGustavo F. Padovan if (chan && chan->sk) { 470348454079SGustavo F. Padovan struct sock *sk = chan->sk; 47043df91ea2SAndrei Emeltchenko lock_sock(sk); 470548454079SGustavo F. Padovan 47060c1bc5c6SGustavo F. Padovan if (chan->imtu < len - L2CAP_HDR_SIZE) { 470748454079SGustavo F. Padovan BT_ERR("Frame exceeding recv MTU (len %d, " 470848454079SGustavo F. Padovan "MTU %d)", len, 47090c1bc5c6SGustavo F. Padovan chan->imtu); 4710aa2ac881SGustavo F. Padovan release_sock(sk); 47110a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 47120a708f8fSGustavo F. Padovan goto drop; 47130a708f8fSGustavo F. Padovan } 4714aa2ac881SGustavo F. Padovan release_sock(sk); 471548454079SGustavo F. Padovan } 47160a708f8fSGustavo F. Padovan 47170a708f8fSGustavo F. Padovan /* Allocate skb for the complete frame (with header) */ 47180a708f8fSGustavo F. Padovan conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC); 47190a708f8fSGustavo F. Padovan if (!conn->rx_skb) 47200a708f8fSGustavo F. Padovan goto drop; 47210a708f8fSGustavo F. Padovan 47220a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 47230a708f8fSGustavo F. Padovan skb->len); 47240a708f8fSGustavo F. Padovan conn->rx_len = len - skb->len; 47250a708f8fSGustavo F. Padovan } else { 47260a708f8fSGustavo F. Padovan BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); 47270a708f8fSGustavo F. Padovan 47280a708f8fSGustavo F. Padovan if (!conn->rx_len) { 47290a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len); 47300a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 47310a708f8fSGustavo F. Padovan goto drop; 47320a708f8fSGustavo F. Padovan } 47330a708f8fSGustavo F. Padovan 47340a708f8fSGustavo F. Padovan if (skb->len > conn->rx_len) { 47350a708f8fSGustavo F. Padovan BT_ERR("Fragment is too long (len %d, expected %d)", 47360a708f8fSGustavo F. Padovan skb->len, conn->rx_len); 47370a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 47380a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 47390a708f8fSGustavo F. Padovan conn->rx_len = 0; 47400a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 47410a708f8fSGustavo F. Padovan goto drop; 47420a708f8fSGustavo F. Padovan } 47430a708f8fSGustavo F. Padovan 47440a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 47450a708f8fSGustavo F. Padovan skb->len); 47460a708f8fSGustavo F. Padovan conn->rx_len -= skb->len; 47470a708f8fSGustavo F. Padovan 47480a708f8fSGustavo F. Padovan if (!conn->rx_len) { 47490a708f8fSGustavo F. Padovan /* Complete frame received */ 47500a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, conn->rx_skb); 47510a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 47520a708f8fSGustavo F. Padovan } 47530a708f8fSGustavo F. Padovan } 47540a708f8fSGustavo F. Padovan 47550a708f8fSGustavo F. Padovan drop: 47560a708f8fSGustavo F. Padovan kfree_skb(skb); 47570a708f8fSGustavo F. Padovan return 0; 47580a708f8fSGustavo F. Padovan } 47590a708f8fSGustavo F. Padovan 47600a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p) 47610a708f8fSGustavo F. Padovan { 476223691d75SGustavo F. Padovan struct l2cap_chan *c; 47630a708f8fSGustavo F. Padovan 4764333055f2SGustavo F. Padovan read_lock(&chan_list_lock); 47650a708f8fSGustavo F. Padovan 476623691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 476723691d75SGustavo F. Padovan struct sock *sk = c->sk; 47680a708f8fSGustavo F. Padovan 4769903d343eSGustavo F. Padovan seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", 47700a708f8fSGustavo F. Padovan batostr(&bt_sk(sk)->src), 47710a708f8fSGustavo F. Padovan batostr(&bt_sk(sk)->dst), 477289bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm), 477323691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu, 477423691d75SGustavo F. Padovan c->sec_level, c->mode); 47750a708f8fSGustavo F. Padovan } 47760a708f8fSGustavo F. Padovan 4777333055f2SGustavo F. Padovan read_unlock(&chan_list_lock); 47780a708f8fSGustavo F. Padovan 47790a708f8fSGustavo F. Padovan return 0; 47800a708f8fSGustavo F. Padovan } 47810a708f8fSGustavo F. Padovan 47820a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file) 47830a708f8fSGustavo F. Padovan { 47840a708f8fSGustavo F. Padovan return single_open(file, l2cap_debugfs_show, inode->i_private); 47850a708f8fSGustavo F. Padovan } 47860a708f8fSGustavo F. Padovan 47870a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = { 47880a708f8fSGustavo F. Padovan .open = l2cap_debugfs_open, 47890a708f8fSGustavo F. Padovan .read = seq_read, 47900a708f8fSGustavo F. Padovan .llseek = seq_lseek, 47910a708f8fSGustavo F. Padovan .release = single_release, 47920a708f8fSGustavo F. Padovan }; 47930a708f8fSGustavo F. Padovan 47940a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs; 47950a708f8fSGustavo F. Padovan 479664274518SGustavo F. Padovan int __init l2cap_init(void) 47970a708f8fSGustavo F. Padovan { 47980a708f8fSGustavo F. Padovan int err; 47990a708f8fSGustavo F. Padovan 4800bb58f747SGustavo F. Padovan err = l2cap_init_sockets(); 48010a708f8fSGustavo F. Padovan if (err < 0) 48020a708f8fSGustavo F. Padovan return err; 48030a708f8fSGustavo F. Padovan 48040a708f8fSGustavo F. Padovan if (bt_debugfs) { 48050a708f8fSGustavo F. Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, 48060a708f8fSGustavo F. Padovan bt_debugfs, NULL, &l2cap_debugfs_fops); 48070a708f8fSGustavo F. Padovan if (!l2cap_debugfs) 48080a708f8fSGustavo F. Padovan BT_ERR("Failed to create L2CAP debug file"); 48090a708f8fSGustavo F. Padovan } 48100a708f8fSGustavo F. Padovan 48110a708f8fSGustavo F. Padovan return 0; 48120a708f8fSGustavo F. Padovan } 48130a708f8fSGustavo F. Padovan 481464274518SGustavo F. Padovan void l2cap_exit(void) 48150a708f8fSGustavo F. Padovan { 48160a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs); 4817bb58f747SGustavo F. Padovan l2cap_cleanup_sockets(); 48180a708f8fSGustavo F. Padovan } 48190a708f8fSGustavo F. Padovan 48200a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644); 48210a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); 4822