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 7422e925bSMat Martineau Copyright (c) 2012 Code Aurora Forum. All rights reserved. 80a708f8fSGustavo F. Padovan 90a708f8fSGustavo F. Padovan Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> 100a708f8fSGustavo F. Padovan 110a708f8fSGustavo F. Padovan This program is free software; you can redistribute it and/or modify 120a708f8fSGustavo F. Padovan it under the terms of the GNU General Public License version 2 as 130a708f8fSGustavo F. Padovan published by the Free Software Foundation; 140a708f8fSGustavo F. Padovan 150a708f8fSGustavo F. Padovan THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 160a708f8fSGustavo F. Padovan OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 170a708f8fSGustavo F. Padovan FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 180a708f8fSGustavo F. Padovan IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 190a708f8fSGustavo F. Padovan CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 200a708f8fSGustavo F. Padovan WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 210a708f8fSGustavo F. Padovan ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 220a708f8fSGustavo F. Padovan OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 230a708f8fSGustavo F. Padovan 240a708f8fSGustavo F. Padovan ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 250a708f8fSGustavo F. Padovan COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 260a708f8fSGustavo F. Padovan SOFTWARE IS DISCLAIMED. 270a708f8fSGustavo F. Padovan */ 280a708f8fSGustavo F. Padovan 29bb58f747SGustavo F. Padovan /* Bluetooth L2CAP core. */ 300a708f8fSGustavo F. Padovan 310a708f8fSGustavo F. Padovan #include <linux/module.h> 320a708f8fSGustavo F. Padovan 330a708f8fSGustavo F. Padovan #include <linux/debugfs.h> 340a708f8fSGustavo F. Padovan #include <linux/crc16.h> 35dbb50887SDaniel Borkmann #include <linux/filter.h> 360a708f8fSGustavo F. Padovan 370a708f8fSGustavo F. Padovan #include <net/bluetooth/bluetooth.h> 380a708f8fSGustavo F. Padovan #include <net/bluetooth/hci_core.h> 390a708f8fSGustavo F. Padovan #include <net/bluetooth/l2cap.h> 407ef9fbf0SMarcel Holtmann 41ac4b7236SMarcel Holtmann #include "smp.h" 427024728eSMarcel Holtmann #include "a2mp.h" 437ef9fbf0SMarcel Holtmann #include "amp.h" 440a708f8fSGustavo F. Padovan 450f1bfe4eSJohan Hedberg #define LE_FLOWCTL_MAX_CREDITS 65535 460f1bfe4eSJohan Hedberg 47d1de6d46SMat Martineau bool disable_ertm; 48462fcd53SLuiz Augusto von Dentz bool enable_ecred = IS_ENABLED(CONFIG_BT_LE_L2CAP_ECRED); 490a708f8fSGustavo F. Padovan 50547d1032SMarcel Holtmann static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD; 510a708f8fSGustavo F. Padovan 52b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list); 53b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock); 540a708f8fSGustavo F. Padovan 550a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 560a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data); 574519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 584519de9aSGustavo F. Padovan void *data); 59e860d2c9SBen Seri static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size); 605e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err); 610a708f8fSGustavo F. Padovan 62d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 63608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event); 642d2cb306STetsuo Handa static void l2cap_retrans_timeout(struct work_struct *work); 652d2cb306STetsuo Handa static void l2cap_monitor_timeout(struct work_struct *work); 662d2cb306STetsuo Handa static void l2cap_ack_timeout(struct work_struct *work); 67608bcc6dSMat Martineau 68a250e048SJohan Hedberg static inline u8 bdaddr_type(u8 link_type, u8 bdaddr_type) 694f1654e0SMarcel Holtmann { 70a250e048SJohan Hedberg if (link_type == LE_LINK) { 71a250e048SJohan Hedberg if (bdaddr_type == ADDR_LE_DEV_PUBLIC) 724f1654e0SMarcel Holtmann return BDADDR_LE_PUBLIC; 734f1654e0SMarcel Holtmann else 744f1654e0SMarcel Holtmann return BDADDR_LE_RANDOM; 754f1654e0SMarcel Holtmann } 764f1654e0SMarcel Holtmann 774f1654e0SMarcel Holtmann return BDADDR_BREDR; 784f1654e0SMarcel Holtmann } 794f1654e0SMarcel Holtmann 80a250e048SJohan Hedberg static inline u8 bdaddr_src_type(struct hci_conn *hcon) 81a250e048SJohan Hedberg { 82a250e048SJohan Hedberg return bdaddr_type(hcon->type, hcon->src_type); 83a250e048SJohan Hedberg } 84a250e048SJohan Hedberg 85a250e048SJohan Hedberg static inline u8 bdaddr_dst_type(struct hci_conn *hcon) 86a250e048SJohan Hedberg { 87a250e048SJohan Hedberg return bdaddr_type(hcon->type, hcon->dst_type); 88a250e048SJohan Hedberg } 89a250e048SJohan Hedberg 900a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */ 9171ba0e56SGustavo F. Padovan 922d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, 932d792818SGustavo Padovan u16 cid) 940a708f8fSGustavo F. Padovan { 953df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 96baa7e1faSGustavo F. Padovan 973df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 983df91ea2SAndrei Emeltchenko if (c->dcid == cid) 993df91ea2SAndrei Emeltchenko return c; 1000a708f8fSGustavo F. Padovan } 1013df91ea2SAndrei Emeltchenko return NULL; 102baa7e1faSGustavo F. Padovan } 1030a708f8fSGustavo F. Padovan 1042d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, 1052d792818SGustavo Padovan u16 cid) 1060a708f8fSGustavo F. Padovan { 1073df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 108baa7e1faSGustavo F. Padovan 1093df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 1103df91ea2SAndrei Emeltchenko if (c->scid == cid) 1113df91ea2SAndrei Emeltchenko return c; 1120a708f8fSGustavo F. Padovan } 1133df91ea2SAndrei Emeltchenko return NULL; 114baa7e1faSGustavo F. Padovan } 1150a708f8fSGustavo F. Padovan 1160a708f8fSGustavo F. Padovan /* Find channel with given SCID. 117d0be8347SLuiz Augusto von Dentz * Returns a reference locked channel. 118d0be8347SLuiz Augusto von Dentz */ 1192d792818SGustavo Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, 1202d792818SGustavo Padovan u16 cid) 1210a708f8fSGustavo F. Padovan { 12248454079SGustavo F. Padovan struct l2cap_chan *c; 123baa7e1faSGustavo F. Padovan 1243df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 125baa7e1faSGustavo F. Padovan c = __l2cap_get_chan_by_scid(conn, cid); 126d0be8347SLuiz Augusto von Dentz if (c) { 127d0be8347SLuiz Augusto von Dentz /* Only lock if chan reference is not 0 */ 128d0be8347SLuiz Augusto von Dentz c = l2cap_chan_hold_unless_zero(c); 129ef191adeSMat Martineau if (c) 130ef191adeSMat Martineau l2cap_chan_lock(c); 131d0be8347SLuiz Augusto von Dentz } 1323df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 1333df91ea2SAndrei Emeltchenko 13448454079SGustavo F. Padovan return c; 1350a708f8fSGustavo F. Padovan } 1360a708f8fSGustavo F. Padovan 137b1a130b7SMat Martineau /* Find channel with given DCID. 138d0be8347SLuiz Augusto von Dentz * Returns a reference locked channel. 139b1a130b7SMat Martineau */ 140b1a130b7SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn, 141b1a130b7SMat Martineau u16 cid) 142b1a130b7SMat Martineau { 143b1a130b7SMat Martineau struct l2cap_chan *c; 144b1a130b7SMat Martineau 145b1a130b7SMat Martineau mutex_lock(&conn->chan_lock); 146b1a130b7SMat Martineau c = __l2cap_get_chan_by_dcid(conn, cid); 147d0be8347SLuiz Augusto von Dentz if (c) { 148d0be8347SLuiz Augusto von Dentz /* Only lock if chan reference is not 0 */ 149d0be8347SLuiz Augusto von Dentz c = l2cap_chan_hold_unless_zero(c); 150b1a130b7SMat Martineau if (c) 151b1a130b7SMat Martineau l2cap_chan_lock(c); 152d0be8347SLuiz Augusto von Dentz } 153b1a130b7SMat Martineau mutex_unlock(&conn->chan_lock); 154b1a130b7SMat Martineau 155b1a130b7SMat Martineau return c; 156b1a130b7SMat Martineau } 157b1a130b7SMat Martineau 1582d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, 1592d792818SGustavo Padovan u8 ident) 1600a708f8fSGustavo F. Padovan { 1613df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 162baa7e1faSGustavo F. Padovan 1633df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 1643df91ea2SAndrei Emeltchenko if (c->ident == ident) 1653df91ea2SAndrei Emeltchenko return c; 1660a708f8fSGustavo F. Padovan } 1673df91ea2SAndrei Emeltchenko return NULL; 168baa7e1faSGustavo F. Padovan } 1690a708f8fSGustavo F. Padovan 1705b155ef9SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, 1715b155ef9SMat Martineau u8 ident) 1725b155ef9SMat Martineau { 1735b155ef9SMat Martineau struct l2cap_chan *c; 1745b155ef9SMat Martineau 1755b155ef9SMat Martineau mutex_lock(&conn->chan_lock); 1765b155ef9SMat Martineau c = __l2cap_get_chan_by_ident(conn, ident); 177d0be8347SLuiz Augusto von Dentz if (c) { 178d0be8347SLuiz Augusto von Dentz /* Only lock if chan reference is not 0 */ 179d0be8347SLuiz Augusto von Dentz c = l2cap_chan_hold_unless_zero(c); 1805b155ef9SMat Martineau if (c) 1815b155ef9SMat Martineau l2cap_chan_lock(c); 182d0be8347SLuiz Augusto von Dentz } 1835b155ef9SMat Martineau mutex_unlock(&conn->chan_lock); 1845b155ef9SMat Martineau 1855b155ef9SMat Martineau return c; 1865b155ef9SMat Martineau } 1875b155ef9SMat Martineau 18800f62726SLuiz Augusto von Dentz static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src, 18900f62726SLuiz Augusto von Dentz u8 src_type) 1909e4425ffSGustavo F. Padovan { 19123691d75SGustavo F. Padovan struct l2cap_chan *c; 1929e4425ffSGustavo F. Padovan 19323691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 19400f62726SLuiz Augusto von Dentz if (src_type == BDADDR_BREDR && c->src_type != BDADDR_BREDR) 19500f62726SLuiz Augusto von Dentz continue; 19600f62726SLuiz Augusto von Dentz 19700f62726SLuiz Augusto von Dentz if (src_type != BDADDR_BREDR && c->src_type == BDADDR_BREDR) 19800f62726SLuiz Augusto von Dentz continue; 19900f62726SLuiz Augusto von Dentz 2007eafc59eSMarcel Holtmann if (c->sport == psm && !bacmp(&c->src, src)) 20123691d75SGustavo F. Padovan return c; 2029e4425ffSGustavo F. Padovan } 203250938cbSSzymon Janc return NULL; 204250938cbSSzymon Janc } 2059e4425ffSGustavo F. Padovan 2069e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) 2079e4425ffSGustavo F. Padovan { 20873b2ec18SGustavo F. Padovan int err; 20973b2ec18SGustavo F. Padovan 210333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 2119e4425ffSGustavo F. Padovan 21200f62726SLuiz Augusto von Dentz if (psm && __l2cap_global_chan_by_addr(psm, src, chan->src_type)) { 21373b2ec18SGustavo F. Padovan err = -EADDRINUSE; 21473b2ec18SGustavo F. Padovan goto done; 2159e4425ffSGustavo F. Padovan } 2169e4425ffSGustavo F. Padovan 21773b2ec18SGustavo F. Padovan if (psm) { 2189e4425ffSGustavo F. Padovan chan->psm = psm; 2199e4425ffSGustavo F. Padovan chan->sport = psm; 22073b2ec18SGustavo F. Padovan err = 0; 22173b2ec18SGustavo F. Padovan } else { 22292594a51SJohan Hedberg u16 p, start, end, incr; 22392594a51SJohan Hedberg 22492594a51SJohan Hedberg if (chan->src_type == BDADDR_BREDR) { 22592594a51SJohan Hedberg start = L2CAP_PSM_DYN_START; 22692594a51SJohan Hedberg end = L2CAP_PSM_AUTO_END; 22792594a51SJohan Hedberg incr = 2; 22892594a51SJohan Hedberg } else { 22992594a51SJohan Hedberg start = L2CAP_PSM_LE_DYN_START; 23092594a51SJohan Hedberg end = L2CAP_PSM_LE_DYN_END; 23192594a51SJohan Hedberg incr = 1; 23292594a51SJohan Hedberg } 2339e4425ffSGustavo F. Padovan 23473b2ec18SGustavo F. Padovan err = -EINVAL; 23592594a51SJohan Hedberg for (p = start; p <= end; p += incr) 23600f62726SLuiz Augusto von Dentz if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src, 23700f62726SLuiz Augusto von Dentz chan->src_type)) { 23873b2ec18SGustavo F. Padovan chan->psm = cpu_to_le16(p); 23973b2ec18SGustavo F. Padovan chan->sport = cpu_to_le16(p); 24073b2ec18SGustavo F. Padovan err = 0; 24173b2ec18SGustavo F. Padovan break; 24273b2ec18SGustavo F. Padovan } 24373b2ec18SGustavo F. Padovan } 24473b2ec18SGustavo F. Padovan 24573b2ec18SGustavo F. Padovan done: 246333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 24773b2ec18SGustavo F. Padovan return err; 2489e4425ffSGustavo F. Padovan } 2496b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_add_psm); 2509e4425ffSGustavo F. Padovan 2519e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) 2529e4425ffSGustavo F. Padovan { 253333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 2549e4425ffSGustavo F. Padovan 25514824308SJohan Hedberg /* Override the defaults (which are for conn-oriented) */ 25614824308SJohan Hedberg chan->omtu = L2CAP_DEFAULT_MTU; 25714824308SJohan Hedberg chan->chan_type = L2CAP_CHAN_FIXED; 25814824308SJohan Hedberg 2599e4425ffSGustavo F. Padovan chan->scid = scid; 2609e4425ffSGustavo F. Padovan 261333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 2629e4425ffSGustavo F. Padovan 2639e4425ffSGustavo F. Padovan return 0; 2649e4425ffSGustavo F. Padovan } 2659e4425ffSGustavo F. Padovan 266baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn) 2670a708f8fSGustavo F. Padovan { 268e77af755SJohan Hedberg u16 cid, dyn_end; 2690a708f8fSGustavo F. Padovan 270e77af755SJohan Hedberg if (conn->hcon->type == LE_LINK) 271e77af755SJohan Hedberg dyn_end = L2CAP_CID_LE_DYN_END; 272e77af755SJohan Hedberg else 273e77af755SJohan Hedberg dyn_end = L2CAP_CID_DYN_END; 274e77af755SJohan Hedberg 275ab0c127fSJohan Hedberg for (cid = L2CAP_CID_DYN_START; cid <= dyn_end; cid++) { 276baa7e1faSGustavo F. Padovan if (!__l2cap_get_chan_by_scid(conn, cid)) 2770a708f8fSGustavo F. Padovan return cid; 2780a708f8fSGustavo F. Padovan } 2790a708f8fSGustavo F. Padovan 2800a708f8fSGustavo F. Padovan return 0; 2810a708f8fSGustavo F. Padovan } 2820a708f8fSGustavo F. Padovan 283f93fa273SGustavo Padovan static void l2cap_state_change(struct l2cap_chan *chan, int state) 28489bc500eSGustavo F. Padovan { 28542d2d87cSAndrei Emeltchenko BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state), 286badaaa00SGustavo F. Padovan state_to_string(state)); 287badaaa00SGustavo F. Padovan 28889bc500eSGustavo F. Padovan chan->state = state; 28953f52121SGustavo Padovan chan->ops->state_change(chan, state, 0); 29089bc500eSGustavo F. Padovan } 29189bc500eSGustavo F. Padovan 292f8e73017SGustavo Padovan static inline void l2cap_state_change_and_error(struct l2cap_chan *chan, 293f8e73017SGustavo Padovan int state, int err) 2942e0052e4SAndrei Emeltchenko { 295f8e73017SGustavo Padovan chan->state = state; 29653f52121SGustavo Padovan chan->ops->state_change(chan, chan->state, err); 2972e0052e4SAndrei Emeltchenko } 2982e0052e4SAndrei Emeltchenko 2992e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err) 3002e0052e4SAndrei Emeltchenko { 301f8e73017SGustavo Padovan chan->ops->state_change(chan, chan->state, err); 3022e0052e4SAndrei Emeltchenko } 3032e0052e4SAndrei Emeltchenko 3044239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan) 3054239d16fSMat Martineau { 3064239d16fSMat Martineau if (!delayed_work_pending(&chan->monitor_timer) && 3074239d16fSMat Martineau chan->retrans_timeout) { 3084239d16fSMat Martineau l2cap_set_timer(chan, &chan->retrans_timer, 3094239d16fSMat Martineau msecs_to_jiffies(chan->retrans_timeout)); 3104239d16fSMat Martineau } 3114239d16fSMat Martineau } 3124239d16fSMat Martineau 3134239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan) 3144239d16fSMat Martineau { 3154239d16fSMat Martineau __clear_retrans_timer(chan); 3164239d16fSMat Martineau if (chan->monitor_timeout) { 3174239d16fSMat Martineau l2cap_set_timer(chan, &chan->monitor_timer, 3184239d16fSMat Martineau msecs_to_jiffies(chan->monitor_timeout)); 3194239d16fSMat Martineau } 3204239d16fSMat Martineau } 3214239d16fSMat Martineau 322608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head, 323608bcc6dSMat Martineau u16 seq) 324608bcc6dSMat Martineau { 325608bcc6dSMat Martineau struct sk_buff *skb; 326608bcc6dSMat Martineau 327608bcc6dSMat Martineau skb_queue_walk(head, skb) { 328a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.txseq == seq) 329608bcc6dSMat Martineau return skb; 330608bcc6dSMat Martineau } 331608bcc6dSMat Martineau 332608bcc6dSMat Martineau return NULL; 333608bcc6dSMat Martineau } 334608bcc6dSMat Martineau 3353c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */ 3363c588192SMat Martineau 3373c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for 3383c588192SMat Martineau * SREJ requests that are received and for frames that are to be 3393c588192SMat Martineau * retransmitted. These seq_list functions implement a singly-linked 3403c588192SMat Martineau * list in an array, where membership in the list can also be checked 3413c588192SMat Martineau * in constant time. Items can also be added to the tail of the list 3423c588192SMat Martineau * and removed from the head in constant time, without further memory 3433c588192SMat Martineau * allocs or frees. 3443c588192SMat Martineau */ 3453c588192SMat Martineau 3463c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size) 3473c588192SMat Martineau { 3483c588192SMat Martineau size_t alloc_size, i; 3493c588192SMat Martineau 3503c588192SMat Martineau /* Allocated size is a power of 2 to map sequence numbers 3513c588192SMat Martineau * (which may be up to 14 bits) in to a smaller array that is 3523c588192SMat Martineau * sized for the negotiated ERTM transmit windows. 3533c588192SMat Martineau */ 3543c588192SMat Martineau alloc_size = roundup_pow_of_two(size); 3553c588192SMat Martineau 3566da2ec56SKees Cook seq_list->list = kmalloc_array(alloc_size, sizeof(u16), GFP_KERNEL); 3573c588192SMat Martineau if (!seq_list->list) 3583c588192SMat Martineau return -ENOMEM; 3593c588192SMat Martineau 3603c588192SMat Martineau seq_list->mask = alloc_size - 1; 3613c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3623c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3633c588192SMat Martineau for (i = 0; i < alloc_size; i++) 3643c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 3653c588192SMat Martineau 3663c588192SMat Martineau return 0; 3673c588192SMat Martineau } 3683c588192SMat Martineau 3693c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list) 3703c588192SMat Martineau { 3713c588192SMat Martineau kfree(seq_list->list); 3723c588192SMat Martineau } 3733c588192SMat Martineau 3743c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list, 3753c588192SMat Martineau u16 seq) 3763c588192SMat Martineau { 3773c588192SMat Martineau /* Constant-time check for list membership */ 3783c588192SMat Martineau return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR; 3793c588192SMat Martineau } 3803c588192SMat Martineau 38103a0c5d6SJohan Hedberg static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list) 3823c588192SMat Martineau { 38303a0c5d6SJohan Hedberg u16 seq = seq_list->head; 3843c588192SMat Martineau u16 mask = seq_list->mask; 3853c588192SMat Martineau 3863c588192SMat Martineau seq_list->head = seq_list->list[seq & mask]; 3873c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; 3883c588192SMat Martineau 3893c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_TAIL) { 3903c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3913c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3923c588192SMat Martineau } 3933c588192SMat Martineau 3943c588192SMat Martineau return seq; 3953c588192SMat Martineau } 3963c588192SMat Martineau 3973c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list) 3983c588192SMat Martineau { 3993c588192SMat Martineau u16 i; 400f522ae36SGustavo Padovan 401f522ae36SGustavo Padovan if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) 402f522ae36SGustavo Padovan return; 403f522ae36SGustavo Padovan 4043c588192SMat Martineau for (i = 0; i <= seq_list->mask; i++) 4053c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 4063c588192SMat Martineau 4073c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 4083c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 4093c588192SMat Martineau } 4103c588192SMat Martineau 4113c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq) 4123c588192SMat Martineau { 4133c588192SMat Martineau u16 mask = seq_list->mask; 4143c588192SMat Martineau 4153c588192SMat Martineau /* All appends happen in constant time */ 4163c588192SMat Martineau 417f522ae36SGustavo Padovan if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR) 418f522ae36SGustavo Padovan return; 419f522ae36SGustavo Padovan 4203c588192SMat Martineau if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR) 4213c588192SMat Martineau seq_list->head = seq; 4223c588192SMat Martineau else 4233c588192SMat Martineau seq_list->list[seq_list->tail & mask] = seq; 4243c588192SMat Martineau 4253c588192SMat Martineau seq_list->tail = seq; 4263c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL; 4273c588192SMat Martineau } 4283c588192SMat Martineau 429721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work) 430ab07801dSGustavo F. Padovan { 431721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 432721c4181SGustavo F. Padovan chan_timer.work); 4333df91ea2SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 434ab07801dSGustavo F. Padovan int reason; 435ab07801dSGustavo F. Padovan 436e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 437ab07801dSGustavo F. Padovan 4383df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 4396c08fc89SManish Mandlik /* __set_chan_timer() calls l2cap_chan_hold(chan) while scheduling 4406c08fc89SManish Mandlik * this work. No need to call l2cap_chan_hold(chan) here again. 4416c08fc89SManish Mandlik */ 4426be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 443ab07801dSGustavo F. Padovan 44489bc500eSGustavo F. Padovan if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) 445ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 44689bc500eSGustavo F. Padovan else if (chan->state == BT_CONNECT && 447ab07801dSGustavo F. Padovan chan->sec_level != BT_SECURITY_SDP) 448ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 449ab07801dSGustavo F. Padovan else 450ab07801dSGustavo F. Padovan reason = ETIMEDOUT; 451ab07801dSGustavo F. Padovan 4520f852724SGustavo F. Padovan l2cap_chan_close(chan, reason); 453ab07801dSGustavo F. Padovan 45480b98027SGustavo Padovan chan->ops->close(chan); 4553df91ea2SAndrei Emeltchenko 4566c08fc89SManish Mandlik l2cap_chan_unlock(chan); 457371fd835SUlisses Furquim l2cap_chan_put(chan); 4586c08fc89SManish Mandlik 4596c08fc89SManish Mandlik mutex_unlock(&conn->chan_lock); 460ab07801dSGustavo F. Padovan } 461ab07801dSGustavo F. Padovan 462eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void) 4630a708f8fSGustavo F. Padovan { 46448454079SGustavo F. Padovan struct l2cap_chan *chan; 4650a708f8fSGustavo F. Padovan 46648454079SGustavo F. Padovan chan = kzalloc(sizeof(*chan), GFP_ATOMIC); 46748454079SGustavo F. Padovan if (!chan) 46848454079SGustavo F. Padovan return NULL; 4690a708f8fSGustavo F. Padovan 470be859723STetsuo Handa skb_queue_head_init(&chan->tx_q); 471be859723STetsuo Handa skb_queue_head_init(&chan->srej_q); 472c03b355eSAndrei Emeltchenko mutex_init(&chan->lock); 473c03b355eSAndrei Emeltchenko 474ff714119SJohan Hedberg /* Set default lock nesting level */ 475ff714119SJohan Hedberg atomic_set(&chan->nesting, L2CAP_NESTING_NORMAL); 476ff714119SJohan Hedberg 477333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 47823691d75SGustavo F. Padovan list_add(&chan->global_l, &chan_list); 479333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 48023691d75SGustavo F. Padovan 481721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout); 4822d2cb306STetsuo Handa INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout); 4832d2cb306STetsuo Handa INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout); 4842d2cb306STetsuo Handa INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout); 485ab07801dSGustavo F. Padovan 48689bc500eSGustavo F. Padovan chan->state = BT_OPEN; 48789bc500eSGustavo F. Padovan 488144ad330SSyam Sidhardhan kref_init(&chan->kref); 48971ba0e56SGustavo F. Padovan 4902827011fSMat Martineau /* This flag is cleared in l2cap_chan_ready() */ 4912827011fSMat Martineau set_bit(CONF_NOT_COMPLETE, &chan->conf_state); 4922827011fSMat Martineau 493eef1d9b6SGustavo Padovan BT_DBG("chan %p", chan); 494abc545b8SSzymon Janc 49548454079SGustavo F. Padovan return chan; 4960a708f8fSGustavo F. Padovan } 4976b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_create); 4980a708f8fSGustavo F. Padovan 499144ad330SSyam Sidhardhan static void l2cap_chan_destroy(struct kref *kref) 5006ff5abbfSGustavo F. Padovan { 501144ad330SSyam Sidhardhan struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref); 502144ad330SSyam Sidhardhan 5034af66c69SJaganath Kanakkassery BT_DBG("chan %p", chan); 5044af66c69SJaganath Kanakkassery 505333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 50623691d75SGustavo F. Padovan list_del(&chan->global_l); 507333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 50823691d75SGustavo F. Padovan 5094af66c69SJaganath Kanakkassery kfree(chan); 5106ff5abbfSGustavo F. Padovan } 5116ff5abbfSGustavo F. Padovan 51230648372SJaganath Kanakkassery void l2cap_chan_hold(struct l2cap_chan *c) 51330648372SJaganath Kanakkassery { 51493917fd2SKai Ye BT_DBG("chan %p orig refcnt %u", c, kref_read(&c->kref)); 51530648372SJaganath Kanakkassery 516144ad330SSyam Sidhardhan kref_get(&c->kref); 51730648372SJaganath Kanakkassery } 51830648372SJaganath Kanakkassery 519d0be8347SLuiz Augusto von Dentz struct l2cap_chan *l2cap_chan_hold_unless_zero(struct l2cap_chan *c) 520d0be8347SLuiz Augusto von Dentz { 521d0be8347SLuiz Augusto von Dentz BT_DBG("chan %p orig refcnt %u", c, kref_read(&c->kref)); 522d0be8347SLuiz Augusto von Dentz 523d0be8347SLuiz Augusto von Dentz if (!kref_get_unless_zero(&c->kref)) 524d0be8347SLuiz Augusto von Dentz return NULL; 525d0be8347SLuiz Augusto von Dentz 526d0be8347SLuiz Augusto von Dentz return c; 527d0be8347SLuiz Augusto von Dentz } 528d0be8347SLuiz Augusto von Dentz 52930648372SJaganath Kanakkassery void l2cap_chan_put(struct l2cap_chan *c) 53030648372SJaganath Kanakkassery { 53193917fd2SKai Ye BT_DBG("chan %p orig refcnt %u", c, kref_read(&c->kref)); 53230648372SJaganath Kanakkassery 533144ad330SSyam Sidhardhan kref_put(&c->kref, l2cap_chan_destroy); 53430648372SJaganath Kanakkassery } 5356b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_put); 53630648372SJaganath Kanakkassery 537bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan) 538bd4b1653SAndrei Emeltchenko { 539bd4b1653SAndrei Emeltchenko chan->fcs = L2CAP_FCS_CRC16; 540bd4b1653SAndrei Emeltchenko chan->max_tx = L2CAP_DEFAULT_MAX_TX; 541bd4b1653SAndrei Emeltchenko chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; 542bd4b1653SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 5436a5e8165SJukka Rissanen chan->remote_max_tx = chan->max_tx; 5446a5e8165SJukka Rissanen chan->remote_tx_win = chan->tx_win; 545c20f8e35SMat Martineau chan->ack_win = L2CAP_DEFAULT_TX_WINDOW; 546bd4b1653SAndrei Emeltchenko chan->sec_level = BT_SECURITY_LOW; 5476a5e8165SJukka Rissanen chan->flush_to = L2CAP_DEFAULT_FLUSH_TO; 5486a5e8165SJukka Rissanen chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO; 5496a5e8165SJukka Rissanen chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO; 5503a9d54b1SArchie Pusaka 5516a5e8165SJukka Rissanen chan->conf_state = 0; 5523a9d54b1SArchie Pusaka set_bit(CONF_NOT_COMPLETE, &chan->conf_state); 553bd4b1653SAndrei Emeltchenko 554bd4b1653SAndrei Emeltchenko set_bit(FLAG_FORCE_ACTIVE, &chan->flags); 555bd4b1653SAndrei Emeltchenko } 5566b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_set_defaults); 557bd4b1653SAndrei Emeltchenko 558ba8f5289SLuiz Augusto von Dentz static void l2cap_le_flowctl_init(struct l2cap_chan *chan, u16 tx_credits) 55938319713SJohan Hedberg { 5600ce43ce6SJohan Hedberg chan->sdu = NULL; 5610ce43ce6SJohan Hedberg chan->sdu_last_frag = NULL; 5620ce43ce6SJohan Hedberg chan->sdu_len = 0; 563ba8f5289SLuiz Augusto von Dentz chan->tx_credits = tx_credits; 564fe149310SLuiz Augusto von Dentz /* Derive MPS from connection MTU to stop HCI fragmentation */ 565fe149310SLuiz Augusto von Dentz chan->mps = min_t(u16, chan->imtu, chan->conn->mtu - L2CAP_HDR_SIZE); 56696cd8eaaSLuiz Augusto von Dentz /* Give enough credits for a full packet */ 56796cd8eaaSLuiz Augusto von Dentz chan->rx_credits = (chan->imtu / chan->mps) + 1; 5680ce43ce6SJohan Hedberg 5690ce43ce6SJohan Hedberg skb_queue_head_init(&chan->tx_q); 57038319713SJohan Hedberg } 57138319713SJohan Hedberg 57215f02b91SLuiz Augusto von Dentz static void l2cap_ecred_init(struct l2cap_chan *chan, u16 tx_credits) 57315f02b91SLuiz Augusto von Dentz { 57415f02b91SLuiz Augusto von Dentz l2cap_le_flowctl_init(chan, tx_credits); 57515f02b91SLuiz Augusto von Dentz 57615f02b91SLuiz Augusto von Dentz /* L2CAP implementations shall support a minimum MPS of 64 octets */ 57715f02b91SLuiz Augusto von Dentz if (chan->mps < L2CAP_ECRED_MIN_MPS) { 57815f02b91SLuiz Augusto von Dentz chan->mps = L2CAP_ECRED_MIN_MPS; 57915f02b91SLuiz Augusto von Dentz chan->rx_credits = (chan->imtu / chan->mps) + 1; 58015f02b91SLuiz Augusto von Dentz } 58115f02b91SLuiz Augusto von Dentz } 58215f02b91SLuiz Augusto von Dentz 58393c3e8f5SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 5840a708f8fSGustavo F. Padovan { 5850a708f8fSGustavo F. Padovan BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, 586097db76cSAndrei Emeltchenko __le16_to_cpu(chan->psm), chan->dcid); 5870a708f8fSGustavo F. Padovan 5889f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 5890a708f8fSGustavo F. Padovan 5908c1d787bSGustavo F. Padovan chan->conn = conn; 5910a708f8fSGustavo F. Padovan 5925491120eSAndrei Emeltchenko switch (chan->chan_type) { 5935491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_ORIENTED: 5940a708f8fSGustavo F. Padovan /* Alloc CID for connection-oriented socket */ 595fe4128e0SGustavo F. Padovan chan->scid = l2cap_alloc_cid(conn); 59621626e62SJohan Hedberg if (conn->hcon->type == ACL_LINK) 5970c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 5985491120eSAndrei Emeltchenko break; 5995491120eSAndrei Emeltchenko 6005491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_LESS: 6010a708f8fSGustavo F. Padovan /* Connectionless socket */ 602fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_CONN_LESS; 603fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_CONN_LESS; 6040c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 6055491120eSAndrei Emeltchenko break; 6065491120eSAndrei Emeltchenko 6072338a7e0SJohan Hedberg case L2CAP_CHAN_FIXED: 6082338a7e0SJohan Hedberg /* Caller will set CID and CID specific MTU values */ 609416fa752SAndrei Emeltchenko break; 610416fa752SAndrei Emeltchenko 6115491120eSAndrei Emeltchenko default: 6120a708f8fSGustavo F. Padovan /* Raw socket can send/recv signalling messages only */ 613fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_SIGNALING; 614fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_SIGNALING; 6150c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 6160a708f8fSGustavo F. Padovan } 6170a708f8fSGustavo F. Padovan 6188f7975b1SAndrei Emeltchenko chan->local_id = L2CAP_BESTEFFORT_ID; 6198f7975b1SAndrei Emeltchenko chan->local_stype = L2CAP_SERV_BESTEFFORT; 6208f7975b1SAndrei Emeltchenko chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE; 6218f7975b1SAndrei Emeltchenko chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME; 6228f7975b1SAndrei Emeltchenko chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT; 6238936fa6dSAndrei Emeltchenko chan->local_flush_to = L2CAP_EFS_DEFAULT_FLUSH_TO; 6248f7975b1SAndrei Emeltchenko 625371fd835SUlisses Furquim l2cap_chan_hold(chan); 626baa7e1faSGustavo F. Padovan 627c16900cfSJohan Hedberg /* Only keep a reference for fixed channels if they requested it */ 628c16900cfSJohan Hedberg if (chan->chan_type != L2CAP_CHAN_FIXED || 629c16900cfSJohan Hedberg test_bit(FLAG_HOLD_HCI_CONN, &chan->flags)) 6305ee9891dSJohan Hedberg hci_conn_hold(conn->hcon); 6315ee9891dSJohan Hedberg 6323df91ea2SAndrei Emeltchenko list_add(&chan->list, &conn->chan_l); 633643162a8SAndrei Emeltchenko } 634643162a8SAndrei Emeltchenko 635466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 636643162a8SAndrei Emeltchenko { 637643162a8SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 638643162a8SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 6393df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 6400a708f8fSGustavo F. Padovan } 6410a708f8fSGustavo F. Padovan 642466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err) 6430a708f8fSGustavo F. Padovan { 6448c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 6450a708f8fSGustavo F. Padovan 646c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 6470a708f8fSGustavo F. Padovan 64849d11741SJohan Hedberg BT_DBG("chan %p, conn %p, err %d, state %s", chan, conn, err, 64949d11741SJohan Hedberg state_to_string(chan->state)); 6500a708f8fSGustavo F. Padovan 65172847ce0SJohan Hedberg chan->ops->teardown(chan, err); 65272847ce0SJohan Hedberg 6530a708f8fSGustavo F. Padovan if (conn) { 65456f60984SAndrei Emeltchenko struct amp_mgr *mgr = conn->hcon->amp_mgr; 655baa7e1faSGustavo F. Padovan /* Delete from channel list */ 6563df91ea2SAndrei Emeltchenko list_del(&chan->list); 6573d57dc68SGustavo F. Padovan 658371fd835SUlisses Furquim l2cap_chan_put(chan); 659baa7e1faSGustavo F. Padovan 6608c1d787bSGustavo F. Padovan chan->conn = NULL; 6613cabbfdaSAndrei Emeltchenko 662c16900cfSJohan Hedberg /* Reference was only held for non-fixed channels or 663c16900cfSJohan Hedberg * fixed channels that explicitly requested it using the 664c16900cfSJohan Hedberg * FLAG_HOLD_HCI_CONN flag. 665c16900cfSJohan Hedberg */ 666c16900cfSJohan Hedberg if (chan->chan_type != L2CAP_CHAN_FIXED || 667c16900cfSJohan Hedberg test_bit(FLAG_HOLD_HCI_CONN, &chan->flags)) 66876a68ba0SDavid Herrmann hci_conn_drop(conn->hcon); 66956f60984SAndrei Emeltchenko 67056f60984SAndrei Emeltchenko if (mgr && mgr->bredr_chan == chan) 67156f60984SAndrei Emeltchenko mgr->bredr_chan = NULL; 6720a708f8fSGustavo F. Padovan } 6730a708f8fSGustavo F. Padovan 674419e08c1SAndrei Emeltchenko if (chan->hs_hchan) { 675419e08c1SAndrei Emeltchenko struct hci_chan *hs_hchan = chan->hs_hchan; 676419e08c1SAndrei Emeltchenko 677419e08c1SAndrei Emeltchenko BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan); 678419e08c1SAndrei Emeltchenko amp_disconnect_logical_link(hs_hchan); 679419e08c1SAndrei Emeltchenko } 680419e08c1SAndrei Emeltchenko 6812827011fSMat Martineau if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) 6826ff5abbfSGustavo F. Padovan return; 6832ead70b8SGustavo F. Padovan 684ee556f66SGustavo Padovan switch (chan->mode) { 685ee556f66SGustavo Padovan case L2CAP_MODE_BASIC: 686ee556f66SGustavo Padovan break; 6870a708f8fSGustavo F. Padovan 68838319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 68915f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL: 690177f8f2bSJohan Hedberg skb_queue_purge(&chan->tx_q); 69138319713SJohan Hedberg break; 69238319713SJohan Hedberg 693ee556f66SGustavo Padovan case L2CAP_MODE_ERTM: 6941a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 6951a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 6961a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 6970a708f8fSGustavo F. Padovan 698f1c6775bSGustavo F. Padovan skb_queue_purge(&chan->srej_q); 6990a708f8fSGustavo F. Padovan 7003c588192SMat Martineau l2cap_seq_list_free(&chan->srej_list); 7013c588192SMat Martineau l2cap_seq_list_free(&chan->retrans_list); 70219186c7bSGustavo A. R. Silva fallthrough; 703ee556f66SGustavo Padovan 704ee556f66SGustavo Padovan case L2CAP_MODE_STREAMING: 705ee556f66SGustavo Padovan skb_queue_purge(&chan->tx_q); 706ee556f66SGustavo Padovan break; 7070a708f8fSGustavo F. Padovan } 7080a708f8fSGustavo F. Padovan } 7096b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_del); 7100a708f8fSGustavo F. Padovan 711*9aa9d947SLuiz Augusto von Dentz static void __l2cap_chan_list_id(struct l2cap_conn *conn, u16 id, 712*9aa9d947SLuiz Augusto von Dentz l2cap_chan_func_t func, void *data) 713*9aa9d947SLuiz Augusto von Dentz { 714*9aa9d947SLuiz Augusto von Dentz struct l2cap_chan *chan, *l; 715*9aa9d947SLuiz Augusto von Dentz 716*9aa9d947SLuiz Augusto von Dentz list_for_each_entry_safe(chan, l, &conn->chan_l, list) { 717*9aa9d947SLuiz Augusto von Dentz if (chan->ident == id) 718*9aa9d947SLuiz Augusto von Dentz func(chan, data); 719*9aa9d947SLuiz Augusto von Dentz } 720*9aa9d947SLuiz Augusto von Dentz } 721*9aa9d947SLuiz Augusto von Dentz 722da49b602SLuiz Augusto von Dentz static void __l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func, 723da49b602SLuiz Augusto von Dentz void *data) 724da49b602SLuiz Augusto von Dentz { 725da49b602SLuiz Augusto von Dentz struct l2cap_chan *chan; 726da49b602SLuiz Augusto von Dentz 727da49b602SLuiz Augusto von Dentz list_for_each_entry(chan, &conn->chan_l, list) { 728da49b602SLuiz Augusto von Dentz func(chan, data); 729da49b602SLuiz Augusto von Dentz } 730da49b602SLuiz Augusto von Dentz } 731da49b602SLuiz Augusto von Dentz 732da49b602SLuiz Augusto von Dentz void l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func, 733da49b602SLuiz Augusto von Dentz void *data) 734da49b602SLuiz Augusto von Dentz { 735da49b602SLuiz Augusto von Dentz if (!conn) 736da49b602SLuiz Augusto von Dentz return; 737da49b602SLuiz Augusto von Dentz 738da49b602SLuiz Augusto von Dentz mutex_lock(&conn->chan_lock); 739da49b602SLuiz Augusto von Dentz __l2cap_chan_list(conn, func, data); 740da49b602SLuiz Augusto von Dentz mutex_unlock(&conn->chan_lock); 741da49b602SLuiz Augusto von Dentz } 742da49b602SLuiz Augusto von Dentz 743da49b602SLuiz Augusto von Dentz EXPORT_SYMBOL_GPL(l2cap_chan_list); 744da49b602SLuiz Augusto von Dentz 745f3d82d0cSJohan Hedberg static void l2cap_conn_update_id_addr(struct work_struct *work) 746387a33e3SJohan Hedberg { 747f3d82d0cSJohan Hedberg struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 748f3d82d0cSJohan Hedberg id_addr_update_work); 749f3d82d0cSJohan Hedberg struct hci_conn *hcon = conn->hcon; 750387a33e3SJohan Hedberg struct l2cap_chan *chan; 751387a33e3SJohan Hedberg 752387a33e3SJohan Hedberg mutex_lock(&conn->chan_lock); 753387a33e3SJohan Hedberg 754387a33e3SJohan Hedberg list_for_each_entry(chan, &conn->chan_l, list) { 755387a33e3SJohan Hedberg l2cap_chan_lock(chan); 756387a33e3SJohan Hedberg bacpy(&chan->dst, &hcon->dst); 757a250e048SJohan Hedberg chan->dst_type = bdaddr_dst_type(hcon); 758387a33e3SJohan Hedberg l2cap_chan_unlock(chan); 759387a33e3SJohan Hedberg } 760387a33e3SJohan Hedberg 761387a33e3SJohan Hedberg mutex_unlock(&conn->chan_lock); 762387a33e3SJohan Hedberg } 763387a33e3SJohan Hedberg 76427e2d4c8SJohan Hedberg static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan) 76527e2d4c8SJohan Hedberg { 76627e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn; 76727e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 76827e2d4c8SJohan Hedberg u16 result; 76927e2d4c8SJohan Hedberg 77027e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 771571f7390SMallikarjun Phulari result = L2CAP_CR_LE_AUTHORIZATION; 77227e2d4c8SJohan Hedberg else 773571f7390SMallikarjun Phulari result = L2CAP_CR_LE_BAD_PSM; 77427e2d4c8SJohan Hedberg 77527e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_DISCONN); 77627e2d4c8SJohan Hedberg 77727e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 77827e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 7793916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps); 7800cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits); 78127e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result); 78227e2d4c8SJohan Hedberg 78327e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), 78427e2d4c8SJohan Hedberg &rsp); 78527e2d4c8SJohan Hedberg } 78627e2d4c8SJohan Hedberg 78715f02b91SLuiz Augusto von Dentz static void l2cap_chan_ecred_connect_reject(struct l2cap_chan *chan) 78815f02b91SLuiz Augusto von Dentz { 78915f02b91SLuiz Augusto von Dentz l2cap_state_change(chan, BT_DISCONN); 79015f02b91SLuiz Augusto von Dentz 791*9aa9d947SLuiz Augusto von Dentz __l2cap_ecred_conn_rsp_defer(chan); 79215f02b91SLuiz Augusto von Dentz } 79315f02b91SLuiz Augusto von Dentz 794791d60f7SJohan Hedberg static void l2cap_chan_connect_reject(struct l2cap_chan *chan) 795791d60f7SJohan Hedberg { 796791d60f7SJohan Hedberg struct l2cap_conn *conn = chan->conn; 797791d60f7SJohan Hedberg struct l2cap_conn_rsp rsp; 798791d60f7SJohan Hedberg u16 result; 799791d60f7SJohan Hedberg 800791d60f7SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 801791d60f7SJohan Hedberg result = L2CAP_CR_SEC_BLOCK; 802791d60f7SJohan Hedberg else 803791d60f7SJohan Hedberg result = L2CAP_CR_BAD_PSM; 804791d60f7SJohan Hedberg 805791d60f7SJohan Hedberg l2cap_state_change(chan, BT_DISCONN); 806791d60f7SJohan Hedberg 807791d60f7SJohan Hedberg rsp.scid = cpu_to_le16(chan->dcid); 808791d60f7SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 809791d60f7SJohan Hedberg rsp.result = cpu_to_le16(result); 810dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 811791d60f7SJohan Hedberg 812791d60f7SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); 813791d60f7SJohan Hedberg } 814791d60f7SJohan Hedberg 8150f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason) 8164519de9aSGustavo F. Padovan { 8174519de9aSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 8184519de9aSGustavo F. Padovan 8197eafc59eSMarcel Holtmann BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 8204519de9aSGustavo F. Padovan 82189bc500eSGustavo F. Padovan switch (chan->state) { 8224519de9aSGustavo F. Padovan case BT_LISTEN: 823c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 8244519de9aSGustavo F. Padovan break; 8254519de9aSGustavo F. Padovan 8264519de9aSGustavo F. Padovan case BT_CONNECTED: 8274519de9aSGustavo F. Padovan case BT_CONFIG: 8287b25c9b3SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) { 8298d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 8305e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, reason); 8314519de9aSGustavo F. Padovan } else 8324519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 8334519de9aSGustavo F. Padovan break; 8344519de9aSGustavo F. Padovan 8354519de9aSGustavo F. Padovan case BT_CONNECT2: 836791d60f7SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) { 837791d60f7SJohan Hedberg if (conn->hcon->type == ACL_LINK) 838791d60f7SJohan Hedberg l2cap_chan_connect_reject(chan); 83915f02b91SLuiz Augusto von Dentz else if (conn->hcon->type == LE_LINK) { 84015f02b91SLuiz Augusto von Dentz switch (chan->mode) { 84115f02b91SLuiz Augusto von Dentz case L2CAP_MODE_LE_FLOWCTL: 84227e2d4c8SJohan Hedberg l2cap_chan_le_connect_reject(chan); 84315f02b91SLuiz Augusto von Dentz break; 84415f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL: 84515f02b91SLuiz Augusto von Dentz l2cap_chan_ecred_connect_reject(chan); 846*9aa9d947SLuiz Augusto von Dentz return; 84715f02b91SLuiz Augusto von Dentz } 84815f02b91SLuiz Augusto von Dentz } 8494519de9aSGustavo F. Padovan } 8504519de9aSGustavo F. Padovan 8514519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 8524519de9aSGustavo F. Padovan break; 8534519de9aSGustavo F. Padovan 8544519de9aSGustavo F. Padovan case BT_CONNECT: 8554519de9aSGustavo F. Padovan case BT_DISCONN: 8564519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 8574519de9aSGustavo F. Padovan break; 8584519de9aSGustavo F. Padovan 8594519de9aSGustavo F. Padovan default: 860c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 8614519de9aSGustavo F. Padovan break; 8624519de9aSGustavo F. Padovan } 8634519de9aSGustavo F. Padovan } 8646b8d4a6aSJukka Rissanen EXPORT_SYMBOL(l2cap_chan_close); 8654519de9aSGustavo F. Padovan 8664343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) 8670a708f8fSGustavo F. Padovan { 8686a974b50SMarcel Holtmann switch (chan->chan_type) { 8696a974b50SMarcel Holtmann case L2CAP_CHAN_RAW: 8704343478fSGustavo F. Padovan switch (chan->sec_level) { 8710a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 8727d513e92SMarcel Holtmann case BT_SECURITY_FIPS: 8730a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING_MITM; 8740a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 8750a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING; 8760a708f8fSGustavo F. Padovan default: 8770a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 8780a708f8fSGustavo F. Padovan } 8796a974b50SMarcel Holtmann break; 8803124b843SMarcel Holtmann case L2CAP_CHAN_CONN_LESS: 881dcf4adbfSJoe Perches if (chan->psm == cpu_to_le16(L2CAP_PSM_3DSP)) { 8823124b843SMarcel Holtmann if (chan->sec_level == BT_SECURITY_LOW) 8833124b843SMarcel Holtmann chan->sec_level = BT_SECURITY_SDP; 8843124b843SMarcel Holtmann } 8857d513e92SMarcel Holtmann if (chan->sec_level == BT_SECURITY_HIGH || 8867d513e92SMarcel Holtmann chan->sec_level == BT_SECURITY_FIPS) 8873124b843SMarcel Holtmann return HCI_AT_NO_BONDING_MITM; 8883124b843SMarcel Holtmann else 8893124b843SMarcel Holtmann return HCI_AT_NO_BONDING; 8903124b843SMarcel Holtmann break; 8916a974b50SMarcel Holtmann case L2CAP_CHAN_CONN_ORIENTED: 892dcf4adbfSJoe Perches if (chan->psm == cpu_to_le16(L2CAP_PSM_SDP)) { 8934343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_LOW) 8944343478fSGustavo F. Padovan chan->sec_level = BT_SECURITY_SDP; 8950a708f8fSGustavo F. Padovan 8967d513e92SMarcel Holtmann if (chan->sec_level == BT_SECURITY_HIGH || 8977d513e92SMarcel Holtmann chan->sec_level == BT_SECURITY_FIPS) 8980a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING_MITM; 8990a708f8fSGustavo F. Padovan else 9000a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 9016a974b50SMarcel Holtmann } 90219186c7bSGustavo A. R. Silva fallthrough; 90319186c7bSGustavo A. R. Silva 9046a974b50SMarcel Holtmann default: 9054343478fSGustavo F. Padovan switch (chan->sec_level) { 9060a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 9077d513e92SMarcel Holtmann case BT_SECURITY_FIPS: 9080a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING_MITM; 9090a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 9100a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING; 9110a708f8fSGustavo F. Padovan default: 9120a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 9130a708f8fSGustavo F. Padovan } 9146a974b50SMarcel Holtmann break; 9150a708f8fSGustavo F. Padovan } 9160a708f8fSGustavo F. Padovan } 9170a708f8fSGustavo F. Padovan 9180a708f8fSGustavo F. Padovan /* Service level security */ 919e7cafc45SJohan Hedberg int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator) 9200a708f8fSGustavo F. Padovan { 9218c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 9220a708f8fSGustavo F. Padovan __u8 auth_type; 9230a708f8fSGustavo F. Padovan 924a17de2feSJohan Hedberg if (conn->hcon->type == LE_LINK) 925a17de2feSJohan Hedberg return smp_conn_security(conn->hcon, chan->sec_level); 926a17de2feSJohan Hedberg 9274343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 9280a708f8fSGustavo F. Padovan 929e7cafc45SJohan Hedberg return hci_conn_security(conn->hcon, chan->sec_level, auth_type, 930e7cafc45SJohan Hedberg initiator); 9310a708f8fSGustavo F. Padovan } 9320a708f8fSGustavo F. Padovan 933b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn) 9340a708f8fSGustavo F. Padovan { 9350a708f8fSGustavo F. Padovan u8 id; 9360a708f8fSGustavo F. Padovan 9370a708f8fSGustavo F. Padovan /* Get next available identificator. 9380a708f8fSGustavo F. Padovan * 1 - 128 are used by kernel. 9390a708f8fSGustavo F. Padovan * 129 - 199 are reserved. 9400a708f8fSGustavo F. Padovan * 200 - 254 are used by utilities like l2ping, etc. 9410a708f8fSGustavo F. Padovan */ 9420a708f8fSGustavo F. Padovan 9435a54e7c8SMarcel Holtmann mutex_lock(&conn->ident_lock); 9440a708f8fSGustavo F. Padovan 9450a708f8fSGustavo F. Padovan if (++conn->tx_ident > 128) 9460a708f8fSGustavo F. Padovan conn->tx_ident = 1; 9470a708f8fSGustavo F. Padovan 9480a708f8fSGustavo F. Padovan id = conn->tx_ident; 9490a708f8fSGustavo F. Padovan 9505a54e7c8SMarcel Holtmann mutex_unlock(&conn->ident_lock); 9510a708f8fSGustavo F. Padovan 9520a708f8fSGustavo F. Padovan return id; 9530a708f8fSGustavo F. Padovan } 9540a708f8fSGustavo F. Padovan 9552d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 9562d792818SGustavo Padovan void *data) 9570a708f8fSGustavo F. Padovan { 9580a708f8fSGustavo F. Padovan struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); 9590a708f8fSGustavo F. Padovan u8 flags; 9600a708f8fSGustavo F. Padovan 9610a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x", code); 9620a708f8fSGustavo F. Padovan 9630a708f8fSGustavo F. Padovan if (!skb) 9640a708f8fSGustavo F. Padovan return; 9650a708f8fSGustavo F. Padovan 966f6af675eSSteven Walter /* Use NO_FLUSH if supported or we have an LE link (which does 967f6af675eSSteven Walter * not support auto-flushing packets) */ 968f6af675eSSteven Walter if (lmp_no_flush_capable(conn->hcon->hdev) || 969f6af675eSSteven Walter conn->hcon->type == LE_LINK) 9700a708f8fSGustavo F. Padovan flags = ACL_START_NO_FLUSH; 9710a708f8fSGustavo F. Padovan else 9720a708f8fSGustavo F. Padovan flags = ACL_START; 9730a708f8fSGustavo F. Padovan 97414b12d0bSJaikumar Ganesh bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON; 9755e59b791SLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 97614b12d0bSJaikumar Ganesh 97773d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, flags); 9780a708f8fSGustavo F. Padovan } 9790a708f8fSGustavo F. Padovan 98002b0fbb9SMat Martineau static bool __chan_is_moving(struct l2cap_chan *chan) 98102b0fbb9SMat Martineau { 98202b0fbb9SMat Martineau return chan->move_state != L2CAP_MOVE_STABLE && 98302b0fbb9SMat Martineau chan->move_state != L2CAP_MOVE_WAIT_PREPARE; 98402b0fbb9SMat Martineau } 98502b0fbb9SMat Martineau 98673d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) 98773d80debSLuiz Augusto von Dentz { 98873d80debSLuiz Augusto von Dentz struct hci_conn *hcon = chan->conn->hcon; 98973d80debSLuiz Augusto von Dentz u16 flags; 99073d80debSLuiz Augusto von Dentz 99173d80debSLuiz Augusto von Dentz BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, 99273d80debSLuiz Augusto von Dentz skb->priority); 99373d80debSLuiz Augusto von Dentz 994d5f8a75dSMat Martineau if (chan->hs_hcon && !__chan_is_moving(chan)) { 995d5f8a75dSMat Martineau if (chan->hs_hchan) 996d5f8a75dSMat Martineau hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE); 997d5f8a75dSMat Martineau else 998d5f8a75dSMat Martineau kfree_skb(skb); 999d5f8a75dSMat Martineau 1000d5f8a75dSMat Martineau return; 1001d5f8a75dSMat Martineau } 1002d5f8a75dSMat Martineau 1003f6af675eSSteven Walter /* Use NO_FLUSH for LE links (where this is the only option) or 1004f6af675eSSteven Walter * if the BR/EDR link supports it and flushing has not been 1005f6af675eSSteven Walter * explicitly requested (through FLAG_FLUSHABLE). 1006f6af675eSSteven Walter */ 1007f6af675eSSteven Walter if (hcon->type == LE_LINK || 1008f6af675eSSteven Walter (!test_bit(FLAG_FLUSHABLE, &chan->flags) && 1009f6af675eSSteven Walter lmp_no_flush_capable(hcon->hdev))) 101073d80debSLuiz Augusto von Dentz flags = ACL_START_NO_FLUSH; 101173d80debSLuiz Augusto von Dentz else 101273d80debSLuiz Augusto von Dentz flags = ACL_START; 101373d80debSLuiz Augusto von Dentz 101473d80debSLuiz Augusto von Dentz bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); 101573d80debSLuiz Augusto von Dentz hci_send_acl(chan->conn->hchan, skb, flags); 10160a708f8fSGustavo F. Padovan } 10170a708f8fSGustavo F. Padovan 1018b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control) 1019b5c6aaedSMat Martineau { 1020b5c6aaedSMat Martineau control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT; 1021b5c6aaedSMat Martineau control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT; 1022b5c6aaedSMat Martineau 1023b5c6aaedSMat Martineau if (enh & L2CAP_CTRL_FRAME_TYPE) { 1024b5c6aaedSMat Martineau /* S-Frame */ 1025b5c6aaedSMat Martineau control->sframe = 1; 1026b5c6aaedSMat Martineau control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT; 1027b5c6aaedSMat Martineau control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT; 1028b5c6aaedSMat Martineau 1029b5c6aaedSMat Martineau control->sar = 0; 1030b5c6aaedSMat Martineau control->txseq = 0; 1031b5c6aaedSMat Martineau } else { 1032b5c6aaedSMat Martineau /* I-Frame */ 1033b5c6aaedSMat Martineau control->sframe = 0; 1034b5c6aaedSMat Martineau control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT; 1035b5c6aaedSMat Martineau control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT; 1036b5c6aaedSMat Martineau 1037b5c6aaedSMat Martineau control->poll = 0; 1038b5c6aaedSMat Martineau control->super = 0; 1039b5c6aaedSMat Martineau } 1040b5c6aaedSMat Martineau } 1041b5c6aaedSMat Martineau 1042b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control) 1043b5c6aaedSMat Martineau { 1044b5c6aaedSMat Martineau control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT; 1045b5c6aaedSMat Martineau control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT; 1046b5c6aaedSMat Martineau 1047b5c6aaedSMat Martineau if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) { 1048b5c6aaedSMat Martineau /* S-Frame */ 1049b5c6aaedSMat Martineau control->sframe = 1; 1050b5c6aaedSMat Martineau control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT; 1051b5c6aaedSMat Martineau control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT; 1052b5c6aaedSMat Martineau 1053b5c6aaedSMat Martineau control->sar = 0; 1054b5c6aaedSMat Martineau control->txseq = 0; 1055b5c6aaedSMat Martineau } else { 1056b5c6aaedSMat Martineau /* I-Frame */ 1057b5c6aaedSMat Martineau control->sframe = 0; 1058b5c6aaedSMat Martineau control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT; 1059b5c6aaedSMat Martineau control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT; 1060b5c6aaedSMat Martineau 1061b5c6aaedSMat Martineau control->poll = 0; 1062b5c6aaedSMat Martineau control->super = 0; 1063b5c6aaedSMat Martineau } 1064b5c6aaedSMat Martineau } 1065b5c6aaedSMat Martineau 1066b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan, 1067b5c6aaedSMat Martineau struct sk_buff *skb) 1068b5c6aaedSMat Martineau { 1069b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 1070b5c6aaedSMat Martineau __unpack_extended_control(get_unaligned_le32(skb->data), 1071a4368ff3SJohan Hedberg &bt_cb(skb)->l2cap); 1072cec8ab6eSMat Martineau skb_pull(skb, L2CAP_EXT_CTRL_SIZE); 1073b5c6aaedSMat Martineau } else { 1074b5c6aaedSMat Martineau __unpack_enhanced_control(get_unaligned_le16(skb->data), 1075a4368ff3SJohan Hedberg &bt_cb(skb)->l2cap); 1076cec8ab6eSMat Martineau skb_pull(skb, L2CAP_ENH_CTRL_SIZE); 1077b5c6aaedSMat Martineau } 1078b5c6aaedSMat Martineau } 1079b5c6aaedSMat Martineau 1080b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control) 1081b5c6aaedSMat Martineau { 1082b5c6aaedSMat Martineau u32 packed; 1083b5c6aaedSMat Martineau 1084b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT; 1085b5c6aaedSMat Martineau packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT; 1086b5c6aaedSMat Martineau 1087b5c6aaedSMat Martineau if (control->sframe) { 1088b5c6aaedSMat Martineau packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT; 1089b5c6aaedSMat Martineau packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT; 1090b5c6aaedSMat Martineau packed |= L2CAP_EXT_CTRL_FRAME_TYPE; 1091b5c6aaedSMat Martineau } else { 1092b5c6aaedSMat Martineau packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT; 1093b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT; 1094b5c6aaedSMat Martineau } 1095b5c6aaedSMat Martineau 1096b5c6aaedSMat Martineau return packed; 1097b5c6aaedSMat Martineau } 1098b5c6aaedSMat Martineau 1099b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control) 1100b5c6aaedSMat Martineau { 1101b5c6aaedSMat Martineau u16 packed; 1102b5c6aaedSMat Martineau 1103b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT; 1104b5c6aaedSMat Martineau packed |= control->final << L2CAP_CTRL_FINAL_SHIFT; 1105b5c6aaedSMat Martineau 1106b5c6aaedSMat Martineau if (control->sframe) { 1107b5c6aaedSMat Martineau packed |= control->poll << L2CAP_CTRL_POLL_SHIFT; 1108b5c6aaedSMat Martineau packed |= control->super << L2CAP_CTRL_SUPER_SHIFT; 1109b5c6aaedSMat Martineau packed |= L2CAP_CTRL_FRAME_TYPE; 1110b5c6aaedSMat Martineau } else { 1111b5c6aaedSMat Martineau packed |= control->sar << L2CAP_CTRL_SAR_SHIFT; 1112b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT; 1113b5c6aaedSMat Martineau } 1114b5c6aaedSMat Martineau 1115b5c6aaedSMat Martineau return packed; 1116b5c6aaedSMat Martineau } 1117b5c6aaedSMat Martineau 1118b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan, 1119b5c6aaedSMat Martineau struct l2cap_ctrl *control, 1120b5c6aaedSMat Martineau struct sk_buff *skb) 1121b5c6aaedSMat Martineau { 1122b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 1123b5c6aaedSMat Martineau put_unaligned_le32(__pack_extended_control(control), 1124b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 1125b5c6aaedSMat Martineau } else { 1126b5c6aaedSMat Martineau put_unaligned_le16(__pack_enhanced_control(control), 1127b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 1128b5c6aaedSMat Martineau } 1129b5c6aaedSMat Martineau } 1130b5c6aaedSMat Martineau 1131ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan) 1132ba7aa64fSGustavo Padovan { 1133ba7aa64fSGustavo Padovan if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1134ba7aa64fSGustavo Padovan return L2CAP_EXT_HDR_SIZE; 1135ba7aa64fSGustavo Padovan else 1136ba7aa64fSGustavo Padovan return L2CAP_ENH_HDR_SIZE; 1137ba7aa64fSGustavo Padovan } 1138ba7aa64fSGustavo Padovan 1139a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan, 1140a67d7f6fSMat Martineau u32 control) 11410a708f8fSGustavo F. Padovan { 11420a708f8fSGustavo F. Padovan struct sk_buff *skb; 11430a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 1144ba7aa64fSGustavo Padovan int hlen = __ertm_hdr_size(chan); 11450a708f8fSGustavo F. Padovan 11460a708f8fSGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 114703a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 11480a708f8fSGustavo F. Padovan 1149a67d7f6fSMat Martineau skb = bt_skb_alloc(hlen, GFP_KERNEL); 11500a708f8fSGustavo F. Padovan 11510a708f8fSGustavo F. Padovan if (!skb) 1152a67d7f6fSMat Martineau return ERR_PTR(-ENOMEM); 11530a708f8fSGustavo F. Padovan 11544df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 11550a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); 1156fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 115788843ab0SAndrei Emeltchenko 1158a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1159a67d7f6fSMat Martineau put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 1160a67d7f6fSMat Martineau else 1161a67d7f6fSMat Martineau put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 11620a708f8fSGustavo F. Padovan 116347d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 1164a67d7f6fSMat Martineau u16 fcs = crc16(0, (u8 *)skb->data, skb->len); 116503a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 11660a708f8fSGustavo F. Padovan } 11670a708f8fSGustavo F. Padovan 116873d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 1169a67d7f6fSMat Martineau return skb; 1170a67d7f6fSMat Martineau } 1171a67d7f6fSMat Martineau 1172a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan, 1173a67d7f6fSMat Martineau struct l2cap_ctrl *control) 1174a67d7f6fSMat Martineau { 1175a67d7f6fSMat Martineau struct sk_buff *skb; 1176a67d7f6fSMat Martineau u32 control_field; 1177a67d7f6fSMat Martineau 1178a67d7f6fSMat Martineau BT_DBG("chan %p, control %p", chan, control); 1179a67d7f6fSMat Martineau 1180a67d7f6fSMat Martineau if (!control->sframe) 1181a67d7f6fSMat Martineau return; 1182a67d7f6fSMat Martineau 1183b99e13adSMat Martineau if (__chan_is_moving(chan)) 1184b99e13adSMat Martineau return; 1185b99e13adSMat Martineau 1186a67d7f6fSMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) && 1187a67d7f6fSMat Martineau !control->poll) 1188a67d7f6fSMat Martineau control->final = 1; 1189a67d7f6fSMat Martineau 1190a67d7f6fSMat Martineau if (control->super == L2CAP_SUPER_RR) 1191a67d7f6fSMat Martineau clear_bit(CONN_RNR_SENT, &chan->conn_state); 1192a67d7f6fSMat Martineau else if (control->super == L2CAP_SUPER_RNR) 1193a67d7f6fSMat Martineau set_bit(CONN_RNR_SENT, &chan->conn_state); 1194a67d7f6fSMat Martineau 1195a67d7f6fSMat Martineau if (control->super != L2CAP_SUPER_SREJ) { 1196a67d7f6fSMat Martineau chan->last_acked_seq = control->reqseq; 1197a67d7f6fSMat Martineau __clear_ack_timer(chan); 1198a67d7f6fSMat Martineau } 1199a67d7f6fSMat Martineau 1200a67d7f6fSMat Martineau BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq, 1201a67d7f6fSMat Martineau control->final, control->poll, control->super); 1202a67d7f6fSMat Martineau 1203a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1204a67d7f6fSMat Martineau control_field = __pack_extended_control(control); 1205a67d7f6fSMat Martineau else 1206a67d7f6fSMat Martineau control_field = __pack_enhanced_control(control); 1207a67d7f6fSMat Martineau 1208a67d7f6fSMat Martineau skb = l2cap_create_sframe_pdu(chan, control_field); 1209a67d7f6fSMat Martineau if (!IS_ERR(skb)) 121073d80debSLuiz Augusto von Dentz l2cap_do_send(chan, skb); 12110a708f8fSGustavo F. Padovan } 12120a708f8fSGustavo F. Padovan 1213c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll) 12140a708f8fSGustavo F. Padovan { 1215c9e3d5e0SMat Martineau struct l2cap_ctrl control; 12160a708f8fSGustavo F. Padovan 1217c9e3d5e0SMat Martineau BT_DBG("chan %p, poll %d", chan, poll); 1218c9e3d5e0SMat Martineau 1219c9e3d5e0SMat Martineau memset(&control, 0, sizeof(control)); 1220c9e3d5e0SMat Martineau control.sframe = 1; 1221c9e3d5e0SMat Martineau control.poll = poll; 1222c9e3d5e0SMat Martineau 1223c9e3d5e0SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 1224c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RNR; 1225c9e3d5e0SMat Martineau else 1226c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RR; 1227c9e3d5e0SMat Martineau 1228c9e3d5e0SMat Martineau control.reqseq = chan->buffer_seq; 1229c9e3d5e0SMat Martineau l2cap_send_sframe(chan, &control); 12300a708f8fSGustavo F. Padovan } 12310a708f8fSGustavo F. Padovan 1232b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) 12330a708f8fSGustavo F. Padovan { 12345ff6f34dSJohan Hedberg if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 12355ff6f34dSJohan Hedberg return true; 12365ff6f34dSJohan Hedberg 1237c1360a1cSGustavo F. Padovan return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); 12380a708f8fSGustavo F. Padovan } 12390a708f8fSGustavo F. Padovan 124093c3e8f5SAndrei Emeltchenko static bool __amp_capable(struct l2cap_chan *chan) 124193c3e8f5SAndrei Emeltchenko { 124293c3e8f5SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 12431df7b17aSMarcel Holtmann struct hci_dev *hdev; 12441df7b17aSMarcel Holtmann bool amp_available = false; 124593c3e8f5SAndrei Emeltchenko 12460bd49fc7SJohan Hedberg if (!(conn->local_fixed_chan & L2CAP_FC_A2MP)) 12471df7b17aSMarcel Holtmann return false; 12481df7b17aSMarcel Holtmann 12490bd49fc7SJohan Hedberg if (!(conn->remote_fixed_chan & L2CAP_FC_A2MP)) 12501df7b17aSMarcel Holtmann return false; 12511df7b17aSMarcel Holtmann 12521df7b17aSMarcel Holtmann read_lock(&hci_dev_list_lock); 12531df7b17aSMarcel Holtmann list_for_each_entry(hdev, &hci_dev_list, list) { 12541df7b17aSMarcel Holtmann if (hdev->amp_type != AMP_TYPE_BREDR && 12551df7b17aSMarcel Holtmann test_bit(HCI_UP, &hdev->flags)) { 12561df7b17aSMarcel Holtmann amp_available = true; 12571df7b17aSMarcel Holtmann break; 12581df7b17aSMarcel Holtmann } 12591df7b17aSMarcel Holtmann } 12601df7b17aSMarcel Holtmann read_unlock(&hci_dev_list_lock); 12611df7b17aSMarcel Holtmann 12621df7b17aSMarcel Holtmann if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED) 12631df7b17aSMarcel Holtmann return amp_available; 1264848566b3SMarcel Holtmann 126593c3e8f5SAndrei Emeltchenko return false; 126693c3e8f5SAndrei Emeltchenko } 126793c3e8f5SAndrei Emeltchenko 12685ce66b59SAndrei Emeltchenko static bool l2cap_check_efs(struct l2cap_chan *chan) 12695ce66b59SAndrei Emeltchenko { 12705ce66b59SAndrei Emeltchenko /* Check EFS parameters */ 12715ce66b59SAndrei Emeltchenko return true; 12725ce66b59SAndrei Emeltchenko } 12735ce66b59SAndrei Emeltchenko 12742766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan) 12759b27f350SAndrei Emeltchenko { 12769b27f350SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 12779b27f350SAndrei Emeltchenko struct l2cap_conn_req req; 12789b27f350SAndrei Emeltchenko 12799b27f350SAndrei Emeltchenko req.scid = cpu_to_le16(chan->scid); 12809b27f350SAndrei Emeltchenko req.psm = chan->psm; 12819b27f350SAndrei Emeltchenko 12829b27f350SAndrei Emeltchenko chan->ident = l2cap_get_ident(conn); 12839b27f350SAndrei Emeltchenko 12849b27f350SAndrei Emeltchenko set_bit(CONF_CONNECT_PEND, &chan->conf_state); 12859b27f350SAndrei Emeltchenko 12869b27f350SAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); 12879b27f350SAndrei Emeltchenko } 12889b27f350SAndrei Emeltchenko 12898eb200bdSMat Martineau static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id) 12908eb200bdSMat Martineau { 12918eb200bdSMat Martineau struct l2cap_create_chan_req req; 12928eb200bdSMat Martineau req.scid = cpu_to_le16(chan->scid); 12938eb200bdSMat Martineau req.psm = chan->psm; 12948eb200bdSMat Martineau req.amp_id = amp_id; 12958eb200bdSMat Martineau 12968eb200bdSMat Martineau chan->ident = l2cap_get_ident(chan->conn); 12978eb200bdSMat Martineau 12988eb200bdSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ, 12998eb200bdSMat Martineau sizeof(req), &req); 13008eb200bdSMat Martineau } 13018eb200bdSMat Martineau 130202b0fbb9SMat Martineau static void l2cap_move_setup(struct l2cap_chan *chan) 130302b0fbb9SMat Martineau { 130402b0fbb9SMat Martineau struct sk_buff *skb; 130502b0fbb9SMat Martineau 130602b0fbb9SMat Martineau BT_DBG("chan %p", chan); 130702b0fbb9SMat Martineau 130802b0fbb9SMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 130902b0fbb9SMat Martineau return; 131002b0fbb9SMat Martineau 131102b0fbb9SMat Martineau __clear_retrans_timer(chan); 131202b0fbb9SMat Martineau __clear_monitor_timer(chan); 131302b0fbb9SMat Martineau __clear_ack_timer(chan); 131402b0fbb9SMat Martineau 131502b0fbb9SMat Martineau chan->retry_count = 0; 131602b0fbb9SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 1317a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.retries) 1318a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 1; 131902b0fbb9SMat Martineau else 132002b0fbb9SMat Martineau break; 132102b0fbb9SMat Martineau } 132202b0fbb9SMat Martineau 132302b0fbb9SMat Martineau chan->expected_tx_seq = chan->buffer_seq; 132402b0fbb9SMat Martineau 132502b0fbb9SMat Martineau clear_bit(CONN_REJ_ACT, &chan->conn_state); 132602b0fbb9SMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 132702b0fbb9SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 132802b0fbb9SMat Martineau l2cap_seq_list_clear(&chan->srej_list); 132902b0fbb9SMat Martineau skb_queue_purge(&chan->srej_q); 133002b0fbb9SMat Martineau 133102b0fbb9SMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 133202b0fbb9SMat Martineau chan->rx_state = L2CAP_RX_STATE_MOVE; 133302b0fbb9SMat Martineau 133402b0fbb9SMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 133502b0fbb9SMat Martineau } 133602b0fbb9SMat Martineau 13375f3847a4SMat Martineau static void l2cap_move_done(struct l2cap_chan *chan) 13385f3847a4SMat Martineau { 13395f3847a4SMat Martineau u8 move_role = chan->move_role; 13405f3847a4SMat Martineau BT_DBG("chan %p", chan); 13415f3847a4SMat Martineau 13425f3847a4SMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 13435f3847a4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 13445f3847a4SMat Martineau 13455f3847a4SMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 13465f3847a4SMat Martineau return; 13475f3847a4SMat Martineau 13485f3847a4SMat Martineau switch (move_role) { 13495f3847a4SMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 13505f3847a4SMat Martineau l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL); 13515f3847a4SMat Martineau chan->rx_state = L2CAP_RX_STATE_WAIT_F; 13525f3847a4SMat Martineau break; 13535f3847a4SMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 13545f3847a4SMat Martineau chan->rx_state = L2CAP_RX_STATE_WAIT_P; 13555f3847a4SMat Martineau break; 13565f3847a4SMat Martineau } 13575f3847a4SMat Martineau } 13585f3847a4SMat Martineau 13599f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan) 13609f0caeb1SVinicius Costa Gomes { 1361315917e0SJohan Hedberg /* The channel may have already been flagged as connected in 1362315917e0SJohan Hedberg * case of receiving data before the L2CAP info req/rsp 1363315917e0SJohan Hedberg * procedure is complete. 1364315917e0SJohan Hedberg */ 1365315917e0SJohan Hedberg if (chan->state == BT_CONNECTED) 1366315917e0SJohan Hedberg return; 1367315917e0SJohan Hedberg 13682827011fSMat Martineau /* This clears all conf flags, including CONF_NOT_COMPLETE */ 13699f0caeb1SVinicius Costa Gomes chan->conf_state = 0; 13709f0caeb1SVinicius Costa Gomes __clear_chan_timer(chan); 13719f0caeb1SVinicius Costa Gomes 137215f02b91SLuiz Augusto von Dentz switch (chan->mode) { 137315f02b91SLuiz Augusto von Dentz case L2CAP_MODE_LE_FLOWCTL: 137415f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL: 137515f02b91SLuiz Augusto von Dentz if (!chan->tx_credits) 13760ce43ce6SJohan Hedberg chan->ops->suspend(chan); 137715f02b91SLuiz Augusto von Dentz break; 137815f02b91SLuiz Augusto von Dentz } 1379177f8f2bSJohan Hedberg 138054a59aa2SAndrei Emeltchenko chan->state = BT_CONNECTED; 13819f0caeb1SVinicius Costa Gomes 138254a59aa2SAndrei Emeltchenko chan->ops->ready(chan); 13839f0caeb1SVinicius Costa Gomes } 13849f0caeb1SVinicius Costa Gomes 1385f1496deeSJohan Hedberg static void l2cap_le_connect(struct l2cap_chan *chan) 1386f1496deeSJohan Hedberg { 1387f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1388f1496deeSJohan Hedberg struct l2cap_le_conn_req req; 1389f1496deeSJohan Hedberg 1390595177f3SJohan Hedberg if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags)) 1391595177f3SJohan Hedberg return; 1392595177f3SJohan Hedberg 13934b6e228eSLuiz Augusto von Dentz if (!chan->imtu) 13944b6e228eSLuiz Augusto von Dentz chan->imtu = chan->conn->mtu; 13954b6e228eSLuiz Augusto von Dentz 1396ba8f5289SLuiz Augusto von Dentz l2cap_le_flowctl_init(chan, 0); 1397fe149310SLuiz Augusto von Dentz 1398a5133fe8SXiaohui Zhang memset(&req, 0, sizeof(req)); 1399f1496deeSJohan Hedberg req.psm = chan->psm; 1400f1496deeSJohan Hedberg req.scid = cpu_to_le16(chan->scid); 1401f1496deeSJohan Hedberg req.mtu = cpu_to_le16(chan->imtu); 14023916aed8SJohan Hedberg req.mps = cpu_to_le16(chan->mps); 14030cd75f7eSJohan Hedberg req.credits = cpu_to_le16(chan->rx_credits); 1404f1496deeSJohan Hedberg 1405f1496deeSJohan Hedberg chan->ident = l2cap_get_ident(conn); 1406f1496deeSJohan Hedberg 1407f1496deeSJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ, 1408f1496deeSJohan Hedberg sizeof(req), &req); 1409f1496deeSJohan Hedberg } 1410f1496deeSJohan Hedberg 1411da49b602SLuiz Augusto von Dentz struct l2cap_ecred_conn_data { 141215f02b91SLuiz Augusto von Dentz struct { 141315f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_req req; 1414da49b602SLuiz Augusto von Dentz __le16 scid[5]; 141515f02b91SLuiz Augusto von Dentz } __packed pdu; 1416da49b602SLuiz Augusto von Dentz struct l2cap_chan *chan; 1417da49b602SLuiz Augusto von Dentz struct pid *pid; 1418da49b602SLuiz Augusto von Dentz int count; 1419da49b602SLuiz Augusto von Dentz }; 1420da49b602SLuiz Augusto von Dentz 1421da49b602SLuiz Augusto von Dentz static void l2cap_ecred_defer_connect(struct l2cap_chan *chan, void *data) 1422da49b602SLuiz Augusto von Dentz { 1423da49b602SLuiz Augusto von Dentz struct l2cap_ecred_conn_data *conn = data; 1424da49b602SLuiz Augusto von Dentz struct pid *pid; 1425da49b602SLuiz Augusto von Dentz 1426da49b602SLuiz Augusto von Dentz if (chan == conn->chan) 1427da49b602SLuiz Augusto von Dentz return; 1428da49b602SLuiz Augusto von Dentz 1429da49b602SLuiz Augusto von Dentz if (!test_and_clear_bit(FLAG_DEFER_SETUP, &chan->flags)) 1430da49b602SLuiz Augusto von Dentz return; 1431da49b602SLuiz Augusto von Dentz 1432da49b602SLuiz Augusto von Dentz pid = chan->ops->get_peer_pid(chan); 1433da49b602SLuiz Augusto von Dentz 1434da49b602SLuiz Augusto von Dentz /* Only add deferred channels with the same PID/PSM */ 1435da49b602SLuiz Augusto von Dentz if (conn->pid != pid || chan->psm != conn->chan->psm || chan->ident || 1436da49b602SLuiz Augusto von Dentz chan->mode != L2CAP_MODE_EXT_FLOWCTL || chan->state != BT_CONNECT) 1437da49b602SLuiz Augusto von Dentz return; 143815f02b91SLuiz Augusto von Dentz 143915f02b91SLuiz Augusto von Dentz if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags)) 144015f02b91SLuiz Augusto von Dentz return; 144115f02b91SLuiz Augusto von Dentz 144215f02b91SLuiz Augusto von Dentz l2cap_ecred_init(chan, 0); 144315f02b91SLuiz Augusto von Dentz 1444da49b602SLuiz Augusto von Dentz /* Set the same ident so we can match on the rsp */ 1445da49b602SLuiz Augusto von Dentz chan->ident = conn->chan->ident; 1446da49b602SLuiz Augusto von Dentz 1447da49b602SLuiz Augusto von Dentz /* Include all channels deferred */ 1448da49b602SLuiz Augusto von Dentz conn->pdu.scid[conn->count] = cpu_to_le16(chan->scid); 1449da49b602SLuiz Augusto von Dentz 1450da49b602SLuiz Augusto von Dentz conn->count++; 1451da49b602SLuiz Augusto von Dentz } 1452da49b602SLuiz Augusto von Dentz 1453da49b602SLuiz Augusto von Dentz static void l2cap_ecred_connect(struct l2cap_chan *chan) 1454da49b602SLuiz Augusto von Dentz { 1455da49b602SLuiz Augusto von Dentz struct l2cap_conn *conn = chan->conn; 1456da49b602SLuiz Augusto von Dentz struct l2cap_ecred_conn_data data; 1457da49b602SLuiz Augusto von Dentz 1458da49b602SLuiz Augusto von Dentz if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 1459da49b602SLuiz Augusto von Dentz return; 1460da49b602SLuiz Augusto von Dentz 1461da49b602SLuiz Augusto von Dentz if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags)) 1462da49b602SLuiz Augusto von Dentz return; 1463da49b602SLuiz Augusto von Dentz 1464da49b602SLuiz Augusto von Dentz l2cap_ecred_init(chan, 0); 1465da49b602SLuiz Augusto von Dentz 1466d3715b23SMinghao Chi (CGEL ZTE) memset(&data, 0, sizeof(data)); 1467da49b602SLuiz Augusto von Dentz data.pdu.req.psm = chan->psm; 1468da49b602SLuiz Augusto von Dentz data.pdu.req.mtu = cpu_to_le16(chan->imtu); 1469da49b602SLuiz Augusto von Dentz data.pdu.req.mps = cpu_to_le16(chan->mps); 1470da49b602SLuiz Augusto von Dentz data.pdu.req.credits = cpu_to_le16(chan->rx_credits); 1471da49b602SLuiz Augusto von Dentz data.pdu.scid[0] = cpu_to_le16(chan->scid); 147215f02b91SLuiz Augusto von Dentz 147315f02b91SLuiz Augusto von Dentz chan->ident = l2cap_get_ident(conn); 1474da49b602SLuiz Augusto von Dentz 1475da49b602SLuiz Augusto von Dentz data.count = 1; 1476da49b602SLuiz Augusto von Dentz data.chan = chan; 1477da49b602SLuiz Augusto von Dentz data.pid = chan->ops->get_peer_pid(chan); 1478da49b602SLuiz Augusto von Dentz 1479da49b602SLuiz Augusto von Dentz __l2cap_chan_list(conn, l2cap_ecred_defer_connect, &data); 148015f02b91SLuiz Augusto von Dentz 148115f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_CONN_REQ, 1482da49b602SLuiz Augusto von Dentz sizeof(data.pdu.req) + data.count * sizeof(__le16), 1483da49b602SLuiz Augusto von Dentz &data.pdu); 148415f02b91SLuiz Augusto von Dentz } 148515f02b91SLuiz Augusto von Dentz 1486f1496deeSJohan Hedberg static void l2cap_le_start(struct l2cap_chan *chan) 1487f1496deeSJohan Hedberg { 1488f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1489f1496deeSJohan Hedberg 1490f1496deeSJohan Hedberg if (!smp_conn_security(conn->hcon, chan->sec_level)) 1491f1496deeSJohan Hedberg return; 1492f1496deeSJohan Hedberg 1493f1496deeSJohan Hedberg if (!chan->psm) { 1494f1496deeSJohan Hedberg l2cap_chan_ready(chan); 1495f1496deeSJohan Hedberg return; 1496f1496deeSJohan Hedberg } 1497f1496deeSJohan Hedberg 149815f02b91SLuiz Augusto von Dentz if (chan->state == BT_CONNECT) { 149915f02b91SLuiz Augusto von Dentz if (chan->mode == L2CAP_MODE_EXT_FLOWCTL) 150015f02b91SLuiz Augusto von Dentz l2cap_ecred_connect(chan); 150115f02b91SLuiz Augusto von Dentz else 1502f1496deeSJohan Hedberg l2cap_le_connect(chan); 1503f1496deeSJohan Hedberg } 150415f02b91SLuiz Augusto von Dentz } 1505f1496deeSJohan Hedberg 150693c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan) 150793c3e8f5SAndrei Emeltchenko { 150893c3e8f5SAndrei Emeltchenko if (__amp_capable(chan)) { 150993c3e8f5SAndrei Emeltchenko BT_DBG("chan %p AMP capable: discover AMPs", chan); 151093c3e8f5SAndrei Emeltchenko a2mp_discover_amp(chan); 1511f1496deeSJohan Hedberg } else if (chan->conn->hcon->type == LE_LINK) { 1512f1496deeSJohan Hedberg l2cap_le_start(chan); 151393c3e8f5SAndrei Emeltchenko } else { 151493c3e8f5SAndrei Emeltchenko l2cap_send_conn_req(chan); 151593c3e8f5SAndrei Emeltchenko } 151693c3e8f5SAndrei Emeltchenko } 151793c3e8f5SAndrei Emeltchenko 1518aeaeb4bbSJohan Hedberg static void l2cap_request_info(struct l2cap_conn *conn) 15190a708f8fSGustavo F. Padovan { 15200a708f8fSGustavo F. Padovan struct l2cap_info_req req; 1521aeaeb4bbSJohan Hedberg 1522aeaeb4bbSJohan Hedberg if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1523aeaeb4bbSJohan Hedberg return; 1524aeaeb4bbSJohan Hedberg 1525dcf4adbfSJoe Perches req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 15260a708f8fSGustavo F. Padovan 15270a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 15280a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 15290a708f8fSGustavo F. Padovan 1530ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 15310a708f8fSGustavo F. Padovan 15322d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, 15332d792818SGustavo Padovan sizeof(req), &req); 15340a708f8fSGustavo F. Padovan } 1535aeaeb4bbSJohan Hedberg 1536693cd8ceSMarcel Holtmann static bool l2cap_check_enc_key_size(struct hci_conn *hcon) 1537693cd8ceSMarcel Holtmann { 1538693cd8ceSMarcel Holtmann /* The minimum encryption key size needs to be enforced by the 1539693cd8ceSMarcel Holtmann * host stack before establishing any L2CAP connections. The 1540693cd8ceSMarcel Holtmann * specification in theory allows a minimum of 1, but to align 1541693cd8ceSMarcel Holtmann * BR/EDR and LE transports, a minimum of 7 is chosen. 1542693cd8ceSMarcel Holtmann * 1543693cd8ceSMarcel Holtmann * This check might also be called for unencrypted connections 1544693cd8ceSMarcel Holtmann * that have no key size requirements. Ensure that the link is 1545693cd8ceSMarcel Holtmann * actually encrypted before enforcing a key size. 1546693cd8ceSMarcel Holtmann */ 1547288c0697SArchie Pusaka int min_key_size = hcon->hdev->min_enc_key_size; 1548288c0697SArchie Pusaka 1549288c0697SArchie Pusaka /* On FIPS security level, key size must be 16 bytes */ 1550288c0697SArchie Pusaka if (hcon->sec_level == BT_SECURITY_FIPS) 1551288c0697SArchie Pusaka min_key_size = 16; 1552288c0697SArchie Pusaka 1553693cd8ceSMarcel Holtmann return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) || 1554288c0697SArchie Pusaka hcon->enc_key_size >= min_key_size); 1555693cd8ceSMarcel Holtmann } 1556693cd8ceSMarcel Holtmann 1557aeaeb4bbSJohan Hedberg static void l2cap_do_start(struct l2cap_chan *chan) 1558aeaeb4bbSJohan Hedberg { 1559aeaeb4bbSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1560aeaeb4bbSJohan Hedberg 1561aeaeb4bbSJohan Hedberg if (conn->hcon->type == LE_LINK) { 1562aeaeb4bbSJohan Hedberg l2cap_le_start(chan); 1563aeaeb4bbSJohan Hedberg return; 1564aeaeb4bbSJohan Hedberg } 1565aeaeb4bbSJohan Hedberg 1566aeaeb4bbSJohan Hedberg if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)) { 1567aeaeb4bbSJohan Hedberg l2cap_request_info(conn); 1568aeaeb4bbSJohan Hedberg return; 1569aeaeb4bbSJohan Hedberg } 1570aeaeb4bbSJohan Hedberg 1571aeaeb4bbSJohan Hedberg if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) 1572aeaeb4bbSJohan Hedberg return; 1573aeaeb4bbSJohan Hedberg 1574693cd8ceSMarcel Holtmann if (!l2cap_chan_check_security(chan, true) || 1575693cd8ceSMarcel Holtmann !__l2cap_no_conn_pending(chan)) 1576693cd8ceSMarcel Holtmann return; 1577693cd8ceSMarcel Holtmann 1578693cd8ceSMarcel Holtmann if (l2cap_check_enc_key_size(conn->hcon)) 1579aeaeb4bbSJohan Hedberg l2cap_start_connection(chan); 1580693cd8ceSMarcel Holtmann else 1581693cd8ceSMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 15820a708f8fSGustavo F. Padovan } 15830a708f8fSGustavo F. Padovan 15840a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) 15850a708f8fSGustavo F. Padovan { 15860a708f8fSGustavo F. Padovan u32 local_feat_mask = l2cap_feat_mask; 15870a708f8fSGustavo F. Padovan if (!disable_ertm) 15880a708f8fSGustavo F. Padovan local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING; 15890a708f8fSGustavo F. Padovan 15900a708f8fSGustavo F. Padovan switch (mode) { 15910a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 15920a708f8fSGustavo F. Padovan return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask; 15930a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 15940a708f8fSGustavo F. Padovan return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask; 15950a708f8fSGustavo F. Padovan default: 15960a708f8fSGustavo F. Padovan return 0x00; 15970a708f8fSGustavo F. Padovan } 15980a708f8fSGustavo F. Padovan } 15990a708f8fSGustavo F. Padovan 16005e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err) 16010a708f8fSGustavo F. Padovan { 16025e4e3972SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 16030a708f8fSGustavo F. Padovan struct l2cap_disconn_req req; 16040a708f8fSGustavo F. Padovan 16050a708f8fSGustavo F. Padovan if (!conn) 16060a708f8fSGustavo F. Padovan return; 16070a708f8fSGustavo F. Padovan 1608aad3d0e3SAndrei Emeltchenko if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) { 16091a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 16101a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 16111a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 16120a708f8fSGustavo F. Padovan } 16130a708f8fSGustavo F. Padovan 16142338a7e0SJohan Hedberg if (chan->scid == L2CAP_CID_A2MP) { 1615d117773cSGustavo Padovan l2cap_state_change(chan, BT_DISCONN); 1616416fa752SAndrei Emeltchenko return; 1617416fa752SAndrei Emeltchenko } 1618416fa752SAndrei Emeltchenko 1619fe4128e0SGustavo F. Padovan req.dcid = cpu_to_le16(chan->dcid); 1620fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 16212d792818SGustavo Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ, 16222d792818SGustavo Padovan sizeof(req), &req); 16230a708f8fSGustavo F. Padovan 1624f8e73017SGustavo Padovan l2cap_state_change_and_error(chan, BT_DISCONN, err); 16250a708f8fSGustavo F. Padovan } 16260a708f8fSGustavo F. Padovan 16270a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */ 16280a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn) 16290a708f8fSGustavo F. Padovan { 16303df91ea2SAndrei Emeltchenko struct l2cap_chan *chan, *tmp; 16310a708f8fSGustavo F. Padovan 16320a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 16330a708f8fSGustavo F. Padovan 16343df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 16350a708f8fSGustavo F. Padovan 16363df91ea2SAndrei Emeltchenko list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 16376be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 16380a708f8fSGustavo F. Padovan 1639715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1640aeaeb4bbSJohan Hedberg l2cap_chan_ready(chan); 16416be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16420a708f8fSGustavo F. Padovan continue; 16430a708f8fSGustavo F. Padovan } 16440a708f8fSGustavo F. Padovan 164589bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 1646e7cafc45SJohan Hedberg if (!l2cap_chan_check_security(chan, true) || 1647b4450035SGustavo F. Padovan !__l2cap_no_conn_pending(chan)) { 16486be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16490a708f8fSGustavo F. Padovan continue; 16500a708f8fSGustavo F. Padovan } 16510a708f8fSGustavo F. Padovan 1652c1360a1cSGustavo F. Padovan if (!l2cap_mode_supported(chan->mode, conn->feat_mask) 1653c1360a1cSGustavo F. Padovan && test_bit(CONF_STATE2_DEVICE, 1654c1360a1cSGustavo F. Padovan &chan->conf_state)) { 16550f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 16566be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16570a708f8fSGustavo F. Padovan continue; 16580a708f8fSGustavo F. Padovan } 16590a708f8fSGustavo F. Padovan 1660693cd8ceSMarcel Holtmann if (l2cap_check_enc_key_size(conn->hcon)) 166193c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 1662693cd8ceSMarcel Holtmann else 1663693cd8ceSMarcel Holtmann l2cap_chan_close(chan, ECONNREFUSED); 16640a708f8fSGustavo F. Padovan 166589bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 16660a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 16670a708f8fSGustavo F. Padovan char buf[128]; 1668fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 1669fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 16700a708f8fSGustavo F. Padovan 1671e7cafc45SJohan Hedberg if (l2cap_chan_check_security(chan, false)) { 1672bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 1673dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_PEND); 1674dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND); 16752dc4e510SGustavo Padovan chan->ops->defer(chan); 16760a708f8fSGustavo F. Padovan 16770a708f8fSGustavo F. Padovan } else { 1678acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 1679dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 1680dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 16810a708f8fSGustavo F. Padovan } 16820a708f8fSGustavo F. Padovan } else { 1683dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_PEND); 1684dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND); 16850a708f8fSGustavo F. Padovan } 16860a708f8fSGustavo F. Padovan 1687fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 1688fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 16890a708f8fSGustavo F. Padovan 1690c1360a1cSGustavo F. Padovan if (test_bit(CONF_REQ_SENT, &chan->conf_state) || 16910a708f8fSGustavo F. Padovan rsp.result != L2CAP_CR_SUCCESS) { 16926be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16930a708f8fSGustavo F. Padovan continue; 16940a708f8fSGustavo F. Padovan } 16950a708f8fSGustavo F. Padovan 1696c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 16970a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 1698e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); 169973ffa904SGustavo F. Padovan chan->num_conf_req++; 17000a708f8fSGustavo F. Padovan } 17010a708f8fSGustavo F. Padovan 17026be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 17030a708f8fSGustavo F. Padovan } 17040a708f8fSGustavo F. Padovan 17053df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 17060a708f8fSGustavo F. Padovan } 17070a708f8fSGustavo F. Padovan 1708b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn) 1709b62f328bSVille Tervo { 1710cc8dba2bSMarcel Holtmann struct hci_conn *hcon = conn->hcon; 1711dcc36c16SJohan Hedberg struct hci_dev *hdev = hcon->hdev; 1712b62f328bSVille Tervo 1713e760ec12SJohan Hedberg BT_DBG("%s conn %p", hdev->name, conn); 1714b62f328bSVille Tervo 1715e760ec12SJohan Hedberg /* For outgoing pairing which doesn't necessarily have an 1716e760ec12SJohan Hedberg * associated socket (e.g. mgmt_pair_device). 1717e760ec12SJohan Hedberg */ 1718e760ec12SJohan Hedberg if (hcon->out) 1719e760ec12SJohan Hedberg smp_conn_security(hcon, hcon->pending_sec_level); 1720cc8dba2bSMarcel Holtmann 172174be523cSArchie Pusaka /* For LE peripheral connections, make sure the connection interval 17225153ceb9SBhaskar Chowdhury * is in the range of the minimum and maximum interval that has 172380afeb6cSMarcel Holtmann * been configured for this connection. If not, then trigger 172480afeb6cSMarcel Holtmann * the connection update procedure. 172580afeb6cSMarcel Holtmann */ 172640bef302SJohan Hedberg if (hcon->role == HCI_ROLE_SLAVE && 172780afeb6cSMarcel Holtmann (hcon->le_conn_interval < hcon->le_conn_min_interval || 172880afeb6cSMarcel Holtmann hcon->le_conn_interval > hcon->le_conn_max_interval)) { 172980afeb6cSMarcel Holtmann struct l2cap_conn_param_update_req req; 173080afeb6cSMarcel Holtmann 173180afeb6cSMarcel Holtmann req.min = cpu_to_le16(hcon->le_conn_min_interval); 173280afeb6cSMarcel Holtmann req.max = cpu_to_le16(hcon->le_conn_max_interval); 173380afeb6cSMarcel Holtmann req.latency = cpu_to_le16(hcon->le_conn_latency); 173480afeb6cSMarcel Holtmann req.to_multiplier = cpu_to_le16(hcon->le_supv_timeout); 173580afeb6cSMarcel Holtmann 173680afeb6cSMarcel Holtmann l2cap_send_cmd(conn, l2cap_get_ident(conn), 173780afeb6cSMarcel Holtmann L2CAP_CONN_PARAM_UPDATE_REQ, sizeof(req), &req); 173880afeb6cSMarcel Holtmann } 1739b62f328bSVille Tervo } 1740b62f328bSVille Tervo 17410a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn) 17420a708f8fSGustavo F. Padovan { 174348454079SGustavo F. Padovan struct l2cap_chan *chan; 1744cc110922SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 17450a708f8fSGustavo F. Padovan 17460a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 17470a708f8fSGustavo F. Padovan 1748aeaeb4bbSJohan Hedberg if (hcon->type == ACL_LINK) 1749aeaeb4bbSJohan Hedberg l2cap_request_info(conn); 1750aeaeb4bbSJohan Hedberg 1751e760ec12SJohan Hedberg mutex_lock(&conn->chan_lock); 1752e760ec12SJohan Hedberg 17533df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1754baa7e1faSGustavo F. Padovan 17556be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 17560a708f8fSGustavo F. Padovan 17572338a7e0SJohan Hedberg if (chan->scid == L2CAP_CID_A2MP) { 1758416fa752SAndrei Emeltchenko l2cap_chan_unlock(chan); 1759416fa752SAndrei Emeltchenko continue; 1760416fa752SAndrei Emeltchenko } 1761416fa752SAndrei Emeltchenko 1762cc110922SVinicius Costa Gomes if (hcon->type == LE_LINK) { 1763f1496deeSJohan Hedberg l2cap_le_start(chan); 176463128451SVinicius Costa Gomes } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1765aeaeb4bbSJohan Hedberg if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 176674e75740SGustavo Padovan l2cap_chan_ready(chan); 17671c244f79SGustavo Padovan } else if (chan->state == BT_CONNECT) { 1768fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 17691c244f79SGustavo Padovan } 17700a708f8fSGustavo F. Padovan 17716be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 17720a708f8fSGustavo F. Padovan } 17730a708f8fSGustavo F. Padovan 17743df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 177561a939c6SJohan Hedberg 177679a05727SJohan Hedberg if (hcon->type == LE_LINK) 177779a05727SJohan Hedberg l2cap_le_conn_ready(conn); 177879a05727SJohan Hedberg 177961a939c6SJohan Hedberg queue_work(hcon->hdev->workqueue, &conn->pending_rx_work); 17800a708f8fSGustavo F. Padovan } 17810a708f8fSGustavo F. Padovan 17820a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */ 17830a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) 17840a708f8fSGustavo F. Padovan { 178548454079SGustavo F. Padovan struct l2cap_chan *chan; 17860a708f8fSGustavo F. Padovan 17870a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 17880a708f8fSGustavo F. Padovan 17893df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 17900a708f8fSGustavo F. Padovan 17913df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1792ecf61bdbSAndrei Emeltchenko if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) 17931d8b1fd5SGustavo Padovan l2cap_chan_set_err(chan, err); 17940a708f8fSGustavo F. Padovan } 17950a708f8fSGustavo F. Padovan 17963df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 17970a708f8fSGustavo F. Padovan } 17980a708f8fSGustavo F. Padovan 1799f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work) 18000a708f8fSGustavo F. Padovan { 1801f878fcadSGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 1802030013d8SGustavo F. Padovan info_timer.work); 18030a708f8fSGustavo F. Padovan 18040a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 18050a708f8fSGustavo F. Padovan conn->info_ident = 0; 18060a708f8fSGustavo F. Padovan 18070a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 18080a708f8fSGustavo F. Padovan } 18090a708f8fSGustavo F. Padovan 18102c8e1411SDavid Herrmann /* 18112c8e1411SDavid Herrmann * l2cap_user 18122c8e1411SDavid Herrmann * External modules can register l2cap_user objects on l2cap_conn. The ->probe 18132c8e1411SDavid Herrmann * callback is called during registration. The ->remove callback is called 18142c8e1411SDavid Herrmann * during unregistration. 18152c8e1411SDavid Herrmann * An l2cap_user object can either be explicitly unregistered or when the 18162c8e1411SDavid Herrmann * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon, 18172c8e1411SDavid Herrmann * l2cap->hchan, .. are valid as long as the remove callback hasn't been called. 18182c8e1411SDavid Herrmann * External modules must own a reference to the l2cap_conn object if they intend 18192c8e1411SDavid Herrmann * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at 18202c8e1411SDavid Herrmann * any time if they don't. 18212c8e1411SDavid Herrmann */ 18222c8e1411SDavid Herrmann 18232c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) 18242c8e1411SDavid Herrmann { 18252c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev; 18262c8e1411SDavid Herrmann int ret; 18272c8e1411SDavid Herrmann 18282c8e1411SDavid Herrmann /* We need to check whether l2cap_conn is registered. If it is not, we 18292c8e1411SDavid Herrmann * must not register the l2cap_user. l2cap_conn_del() is unregisters 18302c8e1411SDavid Herrmann * l2cap_conn objects, but doesn't provide its own locking. Instead, it 18312c8e1411SDavid Herrmann * relies on the parent hci_conn object to be locked. This itself relies 18322c8e1411SDavid Herrmann * on the hci_dev object to be locked. So we must lock the hci device 18332c8e1411SDavid Herrmann * here, too. */ 18342c8e1411SDavid Herrmann 18352c8e1411SDavid Herrmann hci_dev_lock(hdev); 18362c8e1411SDavid Herrmann 1837835a6a2fSAlexey Dobriyan if (!list_empty(&user->list)) { 18382c8e1411SDavid Herrmann ret = -EINVAL; 18392c8e1411SDavid Herrmann goto out_unlock; 18402c8e1411SDavid Herrmann } 18412c8e1411SDavid Herrmann 18422c8e1411SDavid Herrmann /* conn->hchan is NULL after l2cap_conn_del() was called */ 18432c8e1411SDavid Herrmann if (!conn->hchan) { 18442c8e1411SDavid Herrmann ret = -ENODEV; 18452c8e1411SDavid Herrmann goto out_unlock; 18462c8e1411SDavid Herrmann } 18472c8e1411SDavid Herrmann 18482c8e1411SDavid Herrmann ret = user->probe(conn, user); 18492c8e1411SDavid Herrmann if (ret) 18502c8e1411SDavid Herrmann goto out_unlock; 18512c8e1411SDavid Herrmann 18522c8e1411SDavid Herrmann list_add(&user->list, &conn->users); 18532c8e1411SDavid Herrmann ret = 0; 18542c8e1411SDavid Herrmann 18552c8e1411SDavid Herrmann out_unlock: 18562c8e1411SDavid Herrmann hci_dev_unlock(hdev); 18572c8e1411SDavid Herrmann return ret; 18582c8e1411SDavid Herrmann } 18592c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user); 18602c8e1411SDavid Herrmann 18612c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) 18622c8e1411SDavid Herrmann { 18632c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev; 18642c8e1411SDavid Herrmann 18652c8e1411SDavid Herrmann hci_dev_lock(hdev); 18662c8e1411SDavid Herrmann 1867835a6a2fSAlexey Dobriyan if (list_empty(&user->list)) 18682c8e1411SDavid Herrmann goto out_unlock; 18692c8e1411SDavid Herrmann 1870ab944c83STedd Ho-Jeong An list_del_init(&user->list); 18712c8e1411SDavid Herrmann user->remove(conn, user); 18722c8e1411SDavid Herrmann 18732c8e1411SDavid Herrmann out_unlock: 18742c8e1411SDavid Herrmann hci_dev_unlock(hdev); 18752c8e1411SDavid Herrmann } 18762c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user); 18772c8e1411SDavid Herrmann 18782c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn) 18792c8e1411SDavid Herrmann { 18802c8e1411SDavid Herrmann struct l2cap_user *user; 18812c8e1411SDavid Herrmann 18822c8e1411SDavid Herrmann while (!list_empty(&conn->users)) { 18832c8e1411SDavid Herrmann user = list_first_entry(&conn->users, struct l2cap_user, list); 1884ab944c83STedd Ho-Jeong An list_del_init(&user->list); 18852c8e1411SDavid Herrmann user->remove(conn, user); 18862c8e1411SDavid Herrmann } 18872c8e1411SDavid Herrmann } 18882c8e1411SDavid Herrmann 18895d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err) 18905d3de7dfSVinicius Costa Gomes { 18915d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 18925d3de7dfSVinicius Costa Gomes struct l2cap_chan *chan, *l; 18935d3de7dfSVinicius Costa Gomes 18945d3de7dfSVinicius Costa Gomes if (!conn) 18955d3de7dfSVinicius Costa Gomes return; 18965d3de7dfSVinicius Costa Gomes 18975d3de7dfSVinicius Costa Gomes BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); 18985d3de7dfSVinicius Costa Gomes 18995d3de7dfSVinicius Costa Gomes kfree_skb(conn->rx_skb); 19005d3de7dfSVinicius Costa Gomes 190161a939c6SJohan Hedberg skb_queue_purge(&conn->pending_rx); 19027ab56c3aSJukka Taimisto 19037ab56c3aSJukka Taimisto /* We can not call flush_work(&conn->pending_rx_work) here since we 19047ab56c3aSJukka Taimisto * might block if we are running on a worker from the same workqueue 19057ab56c3aSJukka Taimisto * pending_rx_work is waiting on. 19067ab56c3aSJukka Taimisto */ 19077ab56c3aSJukka Taimisto if (work_pending(&conn->pending_rx_work)) 19087ab56c3aSJukka Taimisto cancel_work_sync(&conn->pending_rx_work); 190961a939c6SJohan Hedberg 1910f3d82d0cSJohan Hedberg if (work_pending(&conn->id_addr_update_work)) 1911f3d82d0cSJohan Hedberg cancel_work_sync(&conn->id_addr_update_work); 1912f3d82d0cSJohan Hedberg 19132c8e1411SDavid Herrmann l2cap_unregister_all_users(conn); 19142c8e1411SDavid Herrmann 1915e31fb860SJohan Hedberg /* Force the connection to be immediately dropped */ 1916e31fb860SJohan Hedberg hcon->disc_timeout = 0; 1917e31fb860SJohan Hedberg 19183df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 19193df91ea2SAndrei Emeltchenko 19205d3de7dfSVinicius Costa Gomes /* Kill channels */ 19215d3de7dfSVinicius Costa Gomes list_for_each_entry_safe(chan, l, &conn->chan_l, list) { 192261d6ef3eSMat Martineau l2cap_chan_hold(chan); 19236be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 19246be36555SAndrei Emeltchenko 19255d3de7dfSVinicius Costa Gomes l2cap_chan_del(chan, err); 19266be36555SAndrei Emeltchenko 192780b98027SGustavo Padovan chan->ops->close(chan); 19286c08fc89SManish Mandlik 19296c08fc89SManish Mandlik l2cap_chan_unlock(chan); 193061d6ef3eSMat Martineau l2cap_chan_put(chan); 19315d3de7dfSVinicius Costa Gomes } 19325d3de7dfSVinicius Costa Gomes 19333df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 19343df91ea2SAndrei Emeltchenko 193573d80debSLuiz Augusto von Dentz hci_chan_del(conn->hchan); 193673d80debSLuiz Augusto von Dentz 19375d3de7dfSVinicius Costa Gomes if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1938127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->info_timer); 19395d3de7dfSVinicius Costa Gomes 19405d3de7dfSVinicius Costa Gomes hcon->l2cap_data = NULL; 19419c903e37SDavid Herrmann conn->hchan = NULL; 19429c903e37SDavid Herrmann l2cap_conn_put(conn); 19435d3de7dfSVinicius Costa Gomes } 19445d3de7dfSVinicius Costa Gomes 19459c903e37SDavid Herrmann static void l2cap_conn_free(struct kref *ref) 19469c903e37SDavid Herrmann { 19479c903e37SDavid Herrmann struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref); 19489c903e37SDavid Herrmann 19499c903e37SDavid Herrmann hci_conn_put(conn->hcon); 19509c903e37SDavid Herrmann kfree(conn); 19519c903e37SDavid Herrmann } 19529c903e37SDavid Herrmann 195351bb8457SJohan Hedberg struct l2cap_conn *l2cap_conn_get(struct l2cap_conn *conn) 19549c903e37SDavid Herrmann { 19559c903e37SDavid Herrmann kref_get(&conn->ref); 195651bb8457SJohan Hedberg return conn; 19579c903e37SDavid Herrmann } 19589c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_get); 19599c903e37SDavid Herrmann 19609c903e37SDavid Herrmann void l2cap_conn_put(struct l2cap_conn *conn) 19619c903e37SDavid Herrmann { 19629c903e37SDavid Herrmann kref_put(&conn->ref, l2cap_conn_free); 19639c903e37SDavid Herrmann } 19649c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_put); 19659c903e37SDavid Herrmann 19660a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */ 19670a708f8fSGustavo F. Padovan 1968c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr. 19690a708f8fSGustavo F. Padovan * Returns closest match. 19700a708f8fSGustavo F. Padovan */ 1971c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, 1972c2287681SIdo Yariv bdaddr_t *src, 1973bf20fd4eSJohan Hedberg bdaddr_t *dst, 1974bf20fd4eSJohan Hedberg u8 link_type) 19750a708f8fSGustavo F. Padovan { 1976332f1795SLuiz Augusto von Dentz struct l2cap_chan *c, *tmp, *c1 = NULL; 19770a708f8fSGustavo F. Padovan 197823691d75SGustavo F. Padovan read_lock(&chan_list_lock); 19790a708f8fSGustavo F. Padovan 1980332f1795SLuiz Augusto von Dentz list_for_each_entry_safe(c, tmp, &chan_list, global_l) { 198189bc500eSGustavo F. Padovan if (state && c->state != state) 19820a708f8fSGustavo F. Padovan continue; 19830a708f8fSGustavo F. Padovan 1984bf20fd4eSJohan Hedberg if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR) 1985bf20fd4eSJohan Hedberg continue; 1986bf20fd4eSJohan Hedberg 1987bf20fd4eSJohan Hedberg if (link_type == LE_LINK && c->src_type == BDADDR_BREDR) 1988bf20fd4eSJohan Hedberg continue; 1989bf20fd4eSJohan Hedberg 1990f937b758SLuiz Augusto von Dentz if (c->chan_type != L2CAP_CHAN_FIXED && c->psm == psm) { 1991c2287681SIdo Yariv int src_match, dst_match; 1992c2287681SIdo Yariv int src_any, dst_any; 1993c2287681SIdo Yariv 19940a708f8fSGustavo F. Padovan /* Exact match. */ 19957eafc59eSMarcel Holtmann src_match = !bacmp(&c->src, src); 19967eafc59eSMarcel Holtmann dst_match = !bacmp(&c->dst, dst); 1997c2287681SIdo Yariv if (src_match && dst_match) { 1998fc5ae5b4SLuiz Augusto von Dentz if (!l2cap_chan_hold_unless_zero(c)) 1999fc5ae5b4SLuiz Augusto von Dentz continue; 2000fc5ae5b4SLuiz Augusto von Dentz 2001a7567b20SJohannes Berg read_unlock(&chan_list_lock); 200223691d75SGustavo F. Padovan return c; 200323691d75SGustavo F. Padovan } 20040a708f8fSGustavo F. Padovan 20050a708f8fSGustavo F. Padovan /* Closest match */ 20067eafc59eSMarcel Holtmann src_any = !bacmp(&c->src, BDADDR_ANY); 20077eafc59eSMarcel Holtmann dst_any = !bacmp(&c->dst, BDADDR_ANY); 2008c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 2009c2287681SIdo Yariv (src_any && dst_any)) 201023691d75SGustavo F. Padovan c1 = c; 20110a708f8fSGustavo F. Padovan } 20120a708f8fSGustavo F. Padovan } 20130a708f8fSGustavo F. Padovan 2014a24cce14SJohan Hedberg if (c1) 2015d0be8347SLuiz Augusto von Dentz c1 = l2cap_chan_hold_unless_zero(c1); 2016a24cce14SJohan Hedberg 201723691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 20180a708f8fSGustavo F. Padovan 201923691d75SGustavo F. Padovan return c1; 20200a708f8fSGustavo F. Padovan } 20210a708f8fSGustavo F. Padovan 2022721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work) 20230a708f8fSGustavo F. Padovan { 2024721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 2025721c4181SGustavo F. Padovan monitor_timer.work); 20260a708f8fSGustavo F. Padovan 2027525cd185SGustavo F. Padovan BT_DBG("chan %p", chan); 20280a708f8fSGustavo F. Padovan 20296be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 20306be36555SAndrei Emeltchenko 203180909e04SMat Martineau if (!chan->conn) { 20326be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 20338d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 20340a708f8fSGustavo F. Padovan return; 20350a708f8fSGustavo F. Padovan } 20360a708f8fSGustavo F. Padovan 2037401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO); 20380a708f8fSGustavo F. Padovan 20396be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 20408d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 20410a708f8fSGustavo F. Padovan } 20420a708f8fSGustavo F. Padovan 2043721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work) 20440a708f8fSGustavo F. Padovan { 2045721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 2046721c4181SGustavo F. Padovan retrans_timer.work); 20470a708f8fSGustavo F. Padovan 204849208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 20490a708f8fSGustavo F. Padovan 20506be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 20516be36555SAndrei Emeltchenko 205280909e04SMat Martineau if (!chan->conn) { 205380909e04SMat Martineau l2cap_chan_unlock(chan); 205480909e04SMat Martineau l2cap_chan_put(chan); 205580909e04SMat Martineau return; 205680909e04SMat Martineau } 20570a708f8fSGustavo F. Padovan 2058401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO); 20596be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 20608d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 20610a708f8fSGustavo F. Padovan } 20620a708f8fSGustavo F. Padovan 2063d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan, 20643733937dSMat Martineau struct sk_buff_head *skbs) 20650a708f8fSGustavo F. Padovan { 20660a708f8fSGustavo F. Padovan struct sk_buff *skb; 20673733937dSMat Martineau struct l2cap_ctrl *control; 20680a708f8fSGustavo F. Padovan 20693733937dSMat Martineau BT_DBG("chan %p, skbs %p", chan, skbs); 20703733937dSMat Martineau 2071b99e13adSMat Martineau if (__chan_is_moving(chan)) 2072b99e13adSMat Martineau return; 2073b99e13adSMat Martineau 20743733937dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 20753733937dSMat Martineau 20763733937dSMat Martineau while (!skb_queue_empty(&chan->tx_q)) { 20773733937dSMat Martineau 20783733937dSMat Martineau skb = skb_dequeue(&chan->tx_q); 20793733937dSMat Martineau 2080a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 1; 2081a4368ff3SJohan Hedberg control = &bt_cb(skb)->l2cap; 20823733937dSMat Martineau 20833733937dSMat Martineau control->reqseq = 0; 20843733937dSMat Martineau control->txseq = chan->next_tx_seq; 20853733937dSMat Martineau 20863733937dSMat Martineau __pack_control(chan, control, skb); 20870a708f8fSGustavo F. Padovan 208847d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 20893733937dSMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 20903733937dSMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 20910a708f8fSGustavo F. Padovan } 20920a708f8fSGustavo F. Padovan 20934343478fSGustavo F. Padovan l2cap_do_send(chan, skb); 20940a708f8fSGustavo F. Padovan 2095b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 20963733937dSMat Martineau 2097836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 20983733937dSMat Martineau chan->frames_sent++; 20990a708f8fSGustavo F. Padovan } 21000a708f8fSGustavo F. Padovan } 21010a708f8fSGustavo F. Padovan 210267c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan) 21030a708f8fSGustavo F. Padovan { 21040a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 210518a48e76SMat Martineau struct l2cap_ctrl *control; 210618a48e76SMat Martineau int sent = 0; 210718a48e76SMat Martineau 210818a48e76SMat Martineau BT_DBG("chan %p", chan); 21090a708f8fSGustavo F. Padovan 211089bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 21110a708f8fSGustavo F. Padovan return -ENOTCONN; 21120a708f8fSGustavo F. Padovan 211394122bbeSMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 211494122bbeSMat Martineau return 0; 211594122bbeSMat Martineau 2116b99e13adSMat Martineau if (__chan_is_moving(chan)) 2117b99e13adSMat Martineau return 0; 2118b99e13adSMat Martineau 211918a48e76SMat Martineau while (chan->tx_send_head && 212018a48e76SMat Martineau chan->unacked_frames < chan->remote_tx_win && 212118a48e76SMat Martineau chan->tx_state == L2CAP_TX_STATE_XMIT) { 21220a708f8fSGustavo F. Padovan 212318a48e76SMat Martineau skb = chan->tx_send_head; 21240a708f8fSGustavo F. Padovan 2125a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 1; 2126a4368ff3SJohan Hedberg control = &bt_cb(skb)->l2cap; 21270a708f8fSGustavo F. Padovan 2128e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 212918a48e76SMat Martineau control->final = 1; 2130e2ab4353SGustavo F. Padovan 213118a48e76SMat Martineau control->reqseq = chan->buffer_seq; 213218a48e76SMat Martineau chan->last_acked_seq = chan->buffer_seq; 213318a48e76SMat Martineau control->txseq = chan->next_tx_seq; 21340a708f8fSGustavo F. Padovan 213518a48e76SMat Martineau __pack_control(chan, control, skb); 21360a708f8fSGustavo F. Padovan 213747d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 213818a48e76SMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 213918a48e76SMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 21400a708f8fSGustavo F. Padovan } 21410a708f8fSGustavo F. Padovan 214218a48e76SMat Martineau /* Clone after data has been modified. Data is assumed to be 214318a48e76SMat Martineau read-only (for locking purposes) on cloned sk_buffs. 214418a48e76SMat Martineau */ 214518a48e76SMat Martineau tx_skb = skb_clone(skb, GFP_KERNEL); 214618a48e76SMat Martineau 214718a48e76SMat Martineau if (!tx_skb) 214818a48e76SMat Martineau break; 21490a708f8fSGustavo F. Padovan 21501a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 21510a708f8fSGustavo F. Padovan 2152836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 21536a026610SGustavo F. Padovan chan->unacked_frames++; 21546a026610SGustavo F. Padovan chan->frames_sent++; 215518a48e76SMat Martineau sent++; 21560a708f8fSGustavo F. Padovan 215758d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 215858d35f87SGustavo F. Padovan chan->tx_send_head = NULL; 21590a708f8fSGustavo F. Padovan else 216058d35f87SGustavo F. Padovan chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); 216118a48e76SMat Martineau 216218a48e76SMat Martineau l2cap_do_send(chan, tx_skb); 2163b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 21640a708f8fSGustavo F. Padovan } 21650a708f8fSGustavo F. Padovan 2166b4400672SAndrei Emeltchenko BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent, 2167b4400672SAndrei Emeltchenko chan->unacked_frames, skb_queue_len(&chan->tx_q)); 216818a48e76SMat Martineau 216918a48e76SMat Martineau return sent; 21700a708f8fSGustavo F. Padovan } 21710a708f8fSGustavo F. Padovan 2172e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan) 2173e1fbd4c1SMat Martineau { 2174e1fbd4c1SMat Martineau struct l2cap_ctrl control; 2175e1fbd4c1SMat Martineau struct sk_buff *skb; 2176e1fbd4c1SMat Martineau struct sk_buff *tx_skb; 2177e1fbd4c1SMat Martineau u16 seq; 2178e1fbd4c1SMat Martineau 2179e1fbd4c1SMat Martineau BT_DBG("chan %p", chan); 2180e1fbd4c1SMat Martineau 2181e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 2182e1fbd4c1SMat Martineau return; 2183e1fbd4c1SMat Martineau 2184b99e13adSMat Martineau if (__chan_is_moving(chan)) 2185b99e13adSMat Martineau return; 2186b99e13adSMat Martineau 2187e1fbd4c1SMat Martineau while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) { 2188e1fbd4c1SMat Martineau seq = l2cap_seq_list_pop(&chan->retrans_list); 2189e1fbd4c1SMat Martineau 2190e1fbd4c1SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq); 2191e1fbd4c1SMat Martineau if (!skb) { 2192e1fbd4c1SMat Martineau BT_DBG("Error: Can't retransmit seq %d, frame missing", 2193e1fbd4c1SMat Martineau seq); 2194e1fbd4c1SMat Martineau continue; 2195e1fbd4c1SMat Martineau } 2196e1fbd4c1SMat Martineau 2197a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries++; 2198a4368ff3SJohan Hedberg control = bt_cb(skb)->l2cap; 2199e1fbd4c1SMat Martineau 2200e1fbd4c1SMat Martineau if (chan->max_tx != 0 && 2201a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries > chan->max_tx) { 2202e1fbd4c1SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 22035e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 2204e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2205e1fbd4c1SMat Martineau break; 2206e1fbd4c1SMat Martineau } 2207e1fbd4c1SMat Martineau 2208e1fbd4c1SMat Martineau control.reqseq = chan->buffer_seq; 2209e1fbd4c1SMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 2210e1fbd4c1SMat Martineau control.final = 1; 2211e1fbd4c1SMat Martineau else 2212e1fbd4c1SMat Martineau control.final = 0; 2213e1fbd4c1SMat Martineau 2214e1fbd4c1SMat Martineau if (skb_cloned(skb)) { 2215e1fbd4c1SMat Martineau /* Cloned sk_buffs are read-only, so we need a 2216e1fbd4c1SMat Martineau * writeable copy 2217e1fbd4c1SMat Martineau */ 22188bcde1f2SGustavo Padovan tx_skb = skb_copy(skb, GFP_KERNEL); 2219e1fbd4c1SMat Martineau } else { 22208bcde1f2SGustavo Padovan tx_skb = skb_clone(skb, GFP_KERNEL); 2221e1fbd4c1SMat Martineau } 2222e1fbd4c1SMat Martineau 2223e1fbd4c1SMat Martineau if (!tx_skb) { 2224e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2225e1fbd4c1SMat Martineau break; 2226e1fbd4c1SMat Martineau } 2227e1fbd4c1SMat Martineau 2228e1fbd4c1SMat Martineau /* Update skb contents */ 2229e1fbd4c1SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 2230e1fbd4c1SMat Martineau put_unaligned_le32(__pack_extended_control(&control), 2231e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 2232e1fbd4c1SMat Martineau } else { 2233e1fbd4c1SMat Martineau put_unaligned_le16(__pack_enhanced_control(&control), 2234e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 2235e1fbd4c1SMat Martineau } 2236e1fbd4c1SMat Martineau 223713cac152SLukasz Rymanowski /* Update FCS */ 2238e1fbd4c1SMat Martineau if (chan->fcs == L2CAP_FCS_CRC16) { 223913cac152SLukasz Rymanowski u16 fcs = crc16(0, (u8 *) tx_skb->data, 224013cac152SLukasz Rymanowski tx_skb->len - L2CAP_FCS_SIZE); 224113cac152SLukasz Rymanowski put_unaligned_le16(fcs, skb_tail_pointer(tx_skb) - 224213cac152SLukasz Rymanowski L2CAP_FCS_SIZE); 2243e1fbd4c1SMat Martineau } 2244e1fbd4c1SMat Martineau 2245e1fbd4c1SMat Martineau l2cap_do_send(chan, tx_skb); 2246e1fbd4c1SMat Martineau 2247e1fbd4c1SMat Martineau BT_DBG("Resent txseq %d", control.txseq); 2248e1fbd4c1SMat Martineau 2249e1fbd4c1SMat Martineau chan->last_acked_seq = chan->buffer_seq; 2250e1fbd4c1SMat Martineau } 2251e1fbd4c1SMat Martineau } 2252e1fbd4c1SMat Martineau 2253f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan, 2254f80842a8SMat Martineau struct l2cap_ctrl *control) 2255f80842a8SMat Martineau { 2256f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2257f80842a8SMat Martineau 2258f80842a8SMat Martineau l2cap_seq_list_append(&chan->retrans_list, control->reqseq); 2259f80842a8SMat Martineau l2cap_ertm_resend(chan); 2260f80842a8SMat Martineau } 2261f80842a8SMat Martineau 2262d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan, 2263d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 2264d2a7ac5dSMat Martineau { 2265e1fbd4c1SMat Martineau struct sk_buff *skb; 2266e1fbd4c1SMat Martineau 2267e1fbd4c1SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2268e1fbd4c1SMat Martineau 2269e1fbd4c1SMat Martineau if (control->poll) 2270e1fbd4c1SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 2271e1fbd4c1SMat Martineau 2272e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2273e1fbd4c1SMat Martineau 2274e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 2275e1fbd4c1SMat Martineau return; 2276e1fbd4c1SMat Martineau 2277e1fbd4c1SMat Martineau if (chan->unacked_frames) { 2278e1fbd4c1SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 2279a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.txseq == control->reqseq || 2280e1fbd4c1SMat Martineau skb == chan->tx_send_head) 2281e1fbd4c1SMat Martineau break; 2282e1fbd4c1SMat Martineau } 2283e1fbd4c1SMat Martineau 2284e1fbd4c1SMat Martineau skb_queue_walk_from(&chan->tx_q, skb) { 2285e1fbd4c1SMat Martineau if (skb == chan->tx_send_head) 2286e1fbd4c1SMat Martineau break; 2287e1fbd4c1SMat Martineau 2288e1fbd4c1SMat Martineau l2cap_seq_list_append(&chan->retrans_list, 2289a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.txseq); 2290e1fbd4c1SMat Martineau } 2291e1fbd4c1SMat Martineau 2292e1fbd4c1SMat Martineau l2cap_ertm_resend(chan); 2293e1fbd4c1SMat Martineau } 2294d2a7ac5dSMat Martineau } 2295d2a7ac5dSMat Martineau 2296b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan) 2297b17e73bbSSzymon Janc { 22980a0aba42SMat Martineau struct l2cap_ctrl control; 22990a0aba42SMat Martineau u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq, 23000a0aba42SMat Martineau chan->last_acked_seq); 23010a0aba42SMat Martineau int threshold; 23020a0aba42SMat Martineau 23030a0aba42SMat Martineau BT_DBG("chan %p last_acked_seq %d buffer_seq %d", 23040a0aba42SMat Martineau chan, chan->last_acked_seq, chan->buffer_seq); 23050a0aba42SMat Martineau 23060a0aba42SMat Martineau memset(&control, 0, sizeof(control)); 23070a0aba42SMat Martineau control.sframe = 1; 23080a0aba42SMat Martineau 23090a0aba42SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 23100a0aba42SMat Martineau chan->rx_state == L2CAP_RX_STATE_RECV) { 2311b17e73bbSSzymon Janc __clear_ack_timer(chan); 23120a0aba42SMat Martineau control.super = L2CAP_SUPER_RNR; 23130a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 23140a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 23150a0aba42SMat Martineau } else { 23160a0aba42SMat Martineau if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) { 23170a0aba42SMat Martineau l2cap_ertm_send(chan); 23180a0aba42SMat Martineau /* If any i-frames were sent, they included an ack */ 23190a0aba42SMat Martineau if (chan->buffer_seq == chan->last_acked_seq) 23200a0aba42SMat Martineau frames_to_ack = 0; 23210a0aba42SMat Martineau } 23220a0aba42SMat Martineau 2323c20f8e35SMat Martineau /* Ack now if the window is 3/4ths full. 23240a0aba42SMat Martineau * Calculate without mul or div 23250a0aba42SMat Martineau */ 2326c20f8e35SMat Martineau threshold = chan->ack_win; 23270a0aba42SMat Martineau threshold += threshold << 1; 23280a0aba42SMat Martineau threshold >>= 2; 23290a0aba42SMat Martineau 2330b4400672SAndrei Emeltchenko BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack, 23310a0aba42SMat Martineau threshold); 23320a0aba42SMat Martineau 23330a0aba42SMat Martineau if (frames_to_ack >= threshold) { 23340a0aba42SMat Martineau __clear_ack_timer(chan); 23350a0aba42SMat Martineau control.super = L2CAP_SUPER_RR; 23360a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 23370a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 23380a0aba42SMat Martineau frames_to_ack = 0; 23390a0aba42SMat Martineau } 23400a0aba42SMat Martineau 23410a0aba42SMat Martineau if (frames_to_ack) 23420a0aba42SMat Martineau __set_ack_timer(chan); 23430a0aba42SMat Martineau } 2344b17e73bbSSzymon Janc } 2345b17e73bbSSzymon Janc 234604124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, 234704124681SGustavo F. Padovan struct msghdr *msg, int len, 234804124681SGustavo F. Padovan int count, struct sk_buff *skb) 23490a708f8fSGustavo F. Padovan { 23500952a57aSAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 23510a708f8fSGustavo F. Padovan struct sk_buff **frag; 235290338947SGustavo Padovan int sent = 0; 23530a708f8fSGustavo F. Padovan 2354cbbd26b8SAl Viro if (!copy_from_iter_full(skb_put(skb, count), count, &msg->msg_iter)) 23550a708f8fSGustavo F. Padovan return -EFAULT; 23560a708f8fSGustavo F. Padovan 23570a708f8fSGustavo F. Padovan sent += count; 23580a708f8fSGustavo F. Padovan len -= count; 23590a708f8fSGustavo F. Padovan 23600a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 23610a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 23620a708f8fSGustavo F. Padovan while (len) { 2363fbe00700SGustavo Padovan struct sk_buff *tmp; 2364fbe00700SGustavo Padovan 23650a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 23660a708f8fSGustavo F. Padovan 2367d9fbd02bSMarcel Holtmann tmp = chan->ops->alloc_skb(chan, 0, count, 236890338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 2369fbe00700SGustavo Padovan if (IS_ERR(tmp)) 2370fbe00700SGustavo Padovan return PTR_ERR(tmp); 23712f7719ceSAndrei Emeltchenko 2372fbe00700SGustavo Padovan *frag = tmp; 2373fbe00700SGustavo Padovan 2374cbbd26b8SAl Viro if (!copy_from_iter_full(skb_put(*frag, count), count, 2375cbbd26b8SAl Viro &msg->msg_iter)) 23760a708f8fSGustavo F. Padovan return -EFAULT; 23770a708f8fSGustavo F. Padovan 23780a708f8fSGustavo F. Padovan sent += count; 23790a708f8fSGustavo F. Padovan len -= count; 23800a708f8fSGustavo F. Padovan 23812d0ed3d5SGustavo Padovan skb->len += (*frag)->len; 23822d0ed3d5SGustavo Padovan skb->data_len += (*frag)->len; 23832d0ed3d5SGustavo Padovan 23840a708f8fSGustavo F. Padovan frag = &(*frag)->next; 23850a708f8fSGustavo F. Padovan } 23860a708f8fSGustavo F. Padovan 23870a708f8fSGustavo F. Padovan return sent; 23880a708f8fSGustavo F. Padovan } 23890a708f8fSGustavo F. Padovan 23905e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, 23918d46321cSMarcel Holtmann struct msghdr *msg, size_t len) 23920a708f8fSGustavo F. Padovan { 23938c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 23940a708f8fSGustavo F. Padovan struct sk_buff *skb; 239503a51213SAndrei Emeltchenko int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; 23960a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 23970a708f8fSGustavo F. Padovan 23988d46321cSMarcel Holtmann BT_DBG("chan %p psm 0x%2.2x len %zu", chan, 23998d46321cSMarcel Holtmann __le16_to_cpu(chan->psm), len); 24000a708f8fSGustavo F. Padovan 24010a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 24022f7719ceSAndrei Emeltchenko 2403d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, hlen, count, 240490338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 240590338947SGustavo Padovan if (IS_ERR(skb)) 240690338947SGustavo Padovan return skb; 24070a708f8fSGustavo F. Padovan 24080a708f8fSGustavo F. Padovan /* Create L2CAP header */ 24094df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 2410fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 2411daf6a78cSAndrei Emeltchenko lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); 241243b1b8dfSMarcel Holtmann put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE)); 24130a708f8fSGustavo F. Padovan 24140952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 24150a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 24160a708f8fSGustavo F. Padovan kfree_skb(skb); 24170a708f8fSGustavo F. Padovan return ERR_PTR(err); 24180a708f8fSGustavo F. Padovan } 24190a708f8fSGustavo F. Padovan return skb; 24200a708f8fSGustavo F. Padovan } 24210a708f8fSGustavo F. Padovan 24225e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, 24238d46321cSMarcel Holtmann struct msghdr *msg, size_t len) 24240a708f8fSGustavo F. Padovan { 24258c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 24260a708f8fSGustavo F. Padovan struct sk_buff *skb; 2427f2ba7faeSGustavo Padovan int err, count; 24280a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 24290a708f8fSGustavo F. Padovan 2430b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 24310a708f8fSGustavo F. Padovan 2432f2ba7faeSGustavo Padovan count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); 24332f7719ceSAndrei Emeltchenko 2434d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, L2CAP_HDR_SIZE, count, 243590338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 243690338947SGustavo Padovan if (IS_ERR(skb)) 243790338947SGustavo Padovan return skb; 24380a708f8fSGustavo F. Padovan 24390a708f8fSGustavo F. Padovan /* Create L2CAP header */ 24404df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 2441fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 24426ff9b5efSGustavo Padovan lh->len = cpu_to_le16(len); 24430a708f8fSGustavo F. Padovan 24440952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 24450a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 24460a708f8fSGustavo F. Padovan kfree_skb(skb); 24470a708f8fSGustavo F. Padovan return ERR_PTR(err); 24480a708f8fSGustavo F. Padovan } 24490a708f8fSGustavo F. Padovan return skb; 24500a708f8fSGustavo F. Padovan } 24510a708f8fSGustavo F. Padovan 2452ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, 2453ab0ff76dSLuiz Augusto von Dentz struct msghdr *msg, size_t len, 245494122bbeSMat Martineau u16 sdulen) 24550a708f8fSGustavo F. Padovan { 24568c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 24570a708f8fSGustavo F. Padovan struct sk_buff *skb; 2458e4ca6d98SAndrei Emeltchenko int err, count, hlen; 24590a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 24600a708f8fSGustavo F. Padovan 2461b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 24620a708f8fSGustavo F. Padovan 24630a708f8fSGustavo F. Padovan if (!conn) 24640a708f8fSGustavo F. Padovan return ERR_PTR(-ENOTCONN); 24650a708f8fSGustavo F. Padovan 2466ba7aa64fSGustavo Padovan hlen = __ertm_hdr_size(chan); 2467e4ca6d98SAndrei Emeltchenko 24680a708f8fSGustavo F. Padovan if (sdulen) 246903a51213SAndrei Emeltchenko hlen += L2CAP_SDULEN_SIZE; 24700a708f8fSGustavo F. Padovan 247147d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 247203a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 24730a708f8fSGustavo F. Padovan 24740a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 24752f7719ceSAndrei Emeltchenko 2476d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, hlen, count, 247790338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 247890338947SGustavo Padovan if (IS_ERR(skb)) 247990338947SGustavo Padovan return skb; 24800a708f8fSGustavo F. Padovan 24810a708f8fSGustavo F. Padovan /* Create L2CAP header */ 24824df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 2483fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 24840a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 248588843ab0SAndrei Emeltchenko 248618a48e76SMat Martineau /* Control header is populated later */ 248718a48e76SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 248818a48e76SMat Martineau put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 248918a48e76SMat Martineau else 249018a48e76SMat Martineau put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 249188843ab0SAndrei Emeltchenko 24920a708f8fSGustavo F. Padovan if (sdulen) 249303a51213SAndrei Emeltchenko put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 24940a708f8fSGustavo F. Padovan 24950952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 24960a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 24970a708f8fSGustavo F. Padovan kfree_skb(skb); 24980a708f8fSGustavo F. Padovan return ERR_PTR(err); 24990a708f8fSGustavo F. Padovan } 25000a708f8fSGustavo F. Padovan 2501a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.fcs = chan->fcs; 2502a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 0; 25030a708f8fSGustavo F. Padovan return skb; 25040a708f8fSGustavo F. Padovan } 25050a708f8fSGustavo F. Padovan 250694122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan, 250794122bbeSMat Martineau struct sk_buff_head *seg_queue, 250894122bbeSMat Martineau struct msghdr *msg, size_t len) 25090a708f8fSGustavo F. Padovan { 25100a708f8fSGustavo F. Padovan struct sk_buff *skb; 251194122bbeSMat Martineau u16 sdu_len; 251294122bbeSMat Martineau size_t pdu_len; 251394122bbeSMat Martineau u8 sar; 25140a708f8fSGustavo F. Padovan 2515b4400672SAndrei Emeltchenko BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); 25160a708f8fSGustavo F. Padovan 251794122bbeSMat Martineau /* It is critical that ERTM PDUs fit in a single HCI fragment, 251894122bbeSMat Martineau * so fragmented skbs are not used. The HCI layer's handling 251994122bbeSMat Martineau * of fragmented skbs is not compatible with ERTM's queueing. 252094122bbeSMat Martineau */ 252194122bbeSMat Martineau 252294122bbeSMat Martineau /* PDU size is derived from the HCI MTU */ 252394122bbeSMat Martineau pdu_len = chan->conn->mtu; 252494122bbeSMat Martineau 2525a549574dSMat Martineau /* Constrain PDU size for BR/EDR connections */ 2526a549574dSMat Martineau if (!chan->hs_hcon) 252794122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); 252894122bbeSMat Martineau 252994122bbeSMat Martineau /* Adjust for largest possible L2CAP overhead. */ 253035d401dfSGustavo Padovan if (chan->fcs) 253135d401dfSGustavo Padovan pdu_len -= L2CAP_FCS_SIZE; 253235d401dfSGustavo Padovan 2533ba7aa64fSGustavo Padovan pdu_len -= __ertm_hdr_size(chan); 253494122bbeSMat Martineau 253594122bbeSMat Martineau /* Remote device may have requested smaller PDUs */ 253694122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, chan->remote_mps); 253794122bbeSMat Martineau 253894122bbeSMat Martineau if (len <= pdu_len) { 253994122bbeSMat Martineau sar = L2CAP_SAR_UNSEGMENTED; 254094122bbeSMat Martineau sdu_len = 0; 254194122bbeSMat Martineau pdu_len = len; 254294122bbeSMat Martineau } else { 254394122bbeSMat Martineau sar = L2CAP_SAR_START; 254494122bbeSMat Martineau sdu_len = len; 254594122bbeSMat Martineau } 25460a708f8fSGustavo F. Padovan 25470a708f8fSGustavo F. Padovan while (len > 0) { 254894122bbeSMat Martineau skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len); 25490a708f8fSGustavo F. Padovan 25500a708f8fSGustavo F. Padovan if (IS_ERR(skb)) { 255194122bbeSMat Martineau __skb_queue_purge(seg_queue); 25520a708f8fSGustavo F. Padovan return PTR_ERR(skb); 25530a708f8fSGustavo F. Padovan } 25540a708f8fSGustavo F. Padovan 2555a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.sar = sar; 255694122bbeSMat Martineau __skb_queue_tail(seg_queue, skb); 25570a708f8fSGustavo F. Padovan 255894122bbeSMat Martineau len -= pdu_len; 2559069cb270SLukasz Rymanowski if (sdu_len) 256094122bbeSMat Martineau sdu_len = 0; 256194122bbeSMat Martineau 256294122bbeSMat Martineau if (len <= pdu_len) { 256394122bbeSMat Martineau sar = L2CAP_SAR_END; 256494122bbeSMat Martineau pdu_len = len; 256594122bbeSMat Martineau } else { 256694122bbeSMat Martineau sar = L2CAP_SAR_CONTINUE; 256794122bbeSMat Martineau } 256894122bbeSMat Martineau } 256994122bbeSMat Martineau 2570f0f62799SGustavo Padovan return 0; 25710a708f8fSGustavo F. Padovan } 25720a708f8fSGustavo F. Padovan 2573177f8f2bSJohan Hedberg static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan, 2574177f8f2bSJohan Hedberg struct msghdr *msg, 2575177f8f2bSJohan Hedberg size_t len, u16 sdulen) 2576177f8f2bSJohan Hedberg { 2577177f8f2bSJohan Hedberg struct l2cap_conn *conn = chan->conn; 2578177f8f2bSJohan Hedberg struct sk_buff *skb; 2579177f8f2bSJohan Hedberg int err, count, hlen; 2580177f8f2bSJohan Hedberg struct l2cap_hdr *lh; 2581177f8f2bSJohan Hedberg 2582177f8f2bSJohan Hedberg BT_DBG("chan %p len %zu", chan, len); 2583177f8f2bSJohan Hedberg 2584177f8f2bSJohan Hedberg if (!conn) 2585177f8f2bSJohan Hedberg return ERR_PTR(-ENOTCONN); 2586177f8f2bSJohan Hedberg 2587177f8f2bSJohan Hedberg hlen = L2CAP_HDR_SIZE; 2588177f8f2bSJohan Hedberg 2589177f8f2bSJohan Hedberg if (sdulen) 2590177f8f2bSJohan Hedberg hlen += L2CAP_SDULEN_SIZE; 2591177f8f2bSJohan Hedberg 2592177f8f2bSJohan Hedberg count = min_t(unsigned int, (conn->mtu - hlen), len); 2593177f8f2bSJohan Hedberg 2594d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, hlen, count, 2595177f8f2bSJohan Hedberg msg->msg_flags & MSG_DONTWAIT); 2596177f8f2bSJohan Hedberg if (IS_ERR(skb)) 2597177f8f2bSJohan Hedberg return skb; 2598177f8f2bSJohan Hedberg 2599177f8f2bSJohan Hedberg /* Create L2CAP header */ 26004df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 2601177f8f2bSJohan Hedberg lh->cid = cpu_to_le16(chan->dcid); 2602177f8f2bSJohan Hedberg lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 2603177f8f2bSJohan Hedberg 2604177f8f2bSJohan Hedberg if (sdulen) 2605177f8f2bSJohan Hedberg put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 2606177f8f2bSJohan Hedberg 2607177f8f2bSJohan Hedberg err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 2608177f8f2bSJohan Hedberg if (unlikely(err < 0)) { 2609177f8f2bSJohan Hedberg kfree_skb(skb); 2610177f8f2bSJohan Hedberg return ERR_PTR(err); 2611177f8f2bSJohan Hedberg } 2612177f8f2bSJohan Hedberg 2613177f8f2bSJohan Hedberg return skb; 2614177f8f2bSJohan Hedberg } 2615177f8f2bSJohan Hedberg 2616177f8f2bSJohan Hedberg static int l2cap_segment_le_sdu(struct l2cap_chan *chan, 2617177f8f2bSJohan Hedberg struct sk_buff_head *seg_queue, 2618177f8f2bSJohan Hedberg struct msghdr *msg, size_t len) 2619177f8f2bSJohan Hedberg { 2620177f8f2bSJohan Hedberg struct sk_buff *skb; 2621177f8f2bSJohan Hedberg size_t pdu_len; 2622177f8f2bSJohan Hedberg u16 sdu_len; 2623177f8f2bSJohan Hedberg 2624177f8f2bSJohan Hedberg BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); 2625177f8f2bSJohan Hedberg 2626177f8f2bSJohan Hedberg sdu_len = len; 262772c6fb91SJohan Hedberg pdu_len = chan->remote_mps - L2CAP_SDULEN_SIZE; 2628177f8f2bSJohan Hedberg 2629177f8f2bSJohan Hedberg while (len > 0) { 2630177f8f2bSJohan Hedberg if (len <= pdu_len) 2631177f8f2bSJohan Hedberg pdu_len = len; 2632177f8f2bSJohan Hedberg 2633177f8f2bSJohan Hedberg skb = l2cap_create_le_flowctl_pdu(chan, msg, pdu_len, sdu_len); 2634177f8f2bSJohan Hedberg if (IS_ERR(skb)) { 2635177f8f2bSJohan Hedberg __skb_queue_purge(seg_queue); 2636177f8f2bSJohan Hedberg return PTR_ERR(skb); 2637177f8f2bSJohan Hedberg } 2638177f8f2bSJohan Hedberg 2639177f8f2bSJohan Hedberg __skb_queue_tail(seg_queue, skb); 2640177f8f2bSJohan Hedberg 2641177f8f2bSJohan Hedberg len -= pdu_len; 2642177f8f2bSJohan Hedberg 2643177f8f2bSJohan Hedberg if (sdu_len) { 2644177f8f2bSJohan Hedberg sdu_len = 0; 2645177f8f2bSJohan Hedberg pdu_len += L2CAP_SDULEN_SIZE; 2646177f8f2bSJohan Hedberg } 2647177f8f2bSJohan Hedberg } 2648177f8f2bSJohan Hedberg 2649177f8f2bSJohan Hedberg return 0; 2650177f8f2bSJohan Hedberg } 2651177f8f2bSJohan Hedberg 26528a505b7fSLuiz Augusto von Dentz static void l2cap_le_flowctl_send(struct l2cap_chan *chan) 26538a505b7fSLuiz Augusto von Dentz { 26548a505b7fSLuiz Augusto von Dentz int sent = 0; 26558a505b7fSLuiz Augusto von Dentz 26568a505b7fSLuiz Augusto von Dentz BT_DBG("chan %p", chan); 26578a505b7fSLuiz Augusto von Dentz 26588a505b7fSLuiz Augusto von Dentz while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) { 26598a505b7fSLuiz Augusto von Dentz l2cap_do_send(chan, skb_dequeue(&chan->tx_q)); 26608a505b7fSLuiz Augusto von Dentz chan->tx_credits--; 26618a505b7fSLuiz Augusto von Dentz sent++; 26628a505b7fSLuiz Augusto von Dentz } 26638a505b7fSLuiz Augusto von Dentz 26648a505b7fSLuiz Augusto von Dentz BT_DBG("Sent %d credits %u queued %u", sent, chan->tx_credits, 26658a505b7fSLuiz Augusto von Dentz skb_queue_len(&chan->tx_q)); 26668a505b7fSLuiz Augusto von Dentz } 26678a505b7fSLuiz Augusto von Dentz 26688d46321cSMarcel Holtmann int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len) 26699a91a04aSGustavo F. Padovan { 26709a91a04aSGustavo F. Padovan struct sk_buff *skb; 26719a91a04aSGustavo F. Padovan int err; 267294122bbeSMat Martineau struct sk_buff_head seg_queue; 26739a91a04aSGustavo F. Padovan 267431e8ce80SSeung-Woo Kim if (!chan->conn) 267531e8ce80SSeung-Woo Kim return -ENOTCONN; 267631e8ce80SSeung-Woo Kim 26779a91a04aSGustavo F. Padovan /* Connectionless channel */ 2678715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { 26798d46321cSMarcel Holtmann skb = l2cap_create_connless_pdu(chan, msg, len); 26809a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 26819a91a04aSGustavo F. Padovan return PTR_ERR(skb); 26829a91a04aSGustavo F. Padovan 26839a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 26849a91a04aSGustavo F. Padovan return len; 26859a91a04aSGustavo F. Padovan } 26869a91a04aSGustavo F. Padovan 26879a91a04aSGustavo F. Padovan switch (chan->mode) { 268838319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 268915f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL: 2690177f8f2bSJohan Hedberg /* Check outgoing MTU */ 2691177f8f2bSJohan Hedberg if (len > chan->omtu) 2692177f8f2bSJohan Hedberg return -EMSGSIZE; 2693177f8f2bSJohan Hedberg 2694177f8f2bSJohan Hedberg __skb_queue_head_init(&seg_queue); 2695177f8f2bSJohan Hedberg 2696177f8f2bSJohan Hedberg err = l2cap_segment_le_sdu(chan, &seg_queue, msg, len); 2697177f8f2bSJohan Hedberg 2698177f8f2bSJohan Hedberg if (chan->state != BT_CONNECTED) { 2699177f8f2bSJohan Hedberg __skb_queue_purge(&seg_queue); 2700177f8f2bSJohan Hedberg err = -ENOTCONN; 2701177f8f2bSJohan Hedberg } 2702177f8f2bSJohan Hedberg 2703177f8f2bSJohan Hedberg if (err) 2704177f8f2bSJohan Hedberg return err; 2705177f8f2bSJohan Hedberg 2706177f8f2bSJohan Hedberg skb_queue_splice_tail_init(&seg_queue, &chan->tx_q); 2707177f8f2bSJohan Hedberg 27088a505b7fSLuiz Augusto von Dentz l2cap_le_flowctl_send(chan); 2709177f8f2bSJohan Hedberg 2710177f8f2bSJohan Hedberg if (!chan->tx_credits) 2711177f8f2bSJohan Hedberg chan->ops->suspend(chan); 2712177f8f2bSJohan Hedberg 2713177f8f2bSJohan Hedberg err = len; 2714177f8f2bSJohan Hedberg 2715177f8f2bSJohan Hedberg break; 2716177f8f2bSJohan Hedberg 2717fad5fc89SJohan Hedberg case L2CAP_MODE_BASIC: 27189a91a04aSGustavo F. Padovan /* Check outgoing MTU */ 27199a91a04aSGustavo F. Padovan if (len > chan->omtu) 27209a91a04aSGustavo F. Padovan return -EMSGSIZE; 27219a91a04aSGustavo F. Padovan 27229a91a04aSGustavo F. Padovan /* Create a basic PDU */ 27238d46321cSMarcel Holtmann skb = l2cap_create_basic_pdu(chan, msg, len); 27249a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 27259a91a04aSGustavo F. Padovan return PTR_ERR(skb); 27269a91a04aSGustavo F. Padovan 27279a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 27289a91a04aSGustavo F. Padovan err = len; 27299a91a04aSGustavo F. Padovan break; 27309a91a04aSGustavo F. Padovan 27319a91a04aSGustavo F. Padovan case L2CAP_MODE_ERTM: 27329a91a04aSGustavo F. Padovan case L2CAP_MODE_STREAMING: 273394122bbeSMat Martineau /* Check outgoing MTU */ 273494122bbeSMat Martineau if (len > chan->omtu) { 273594122bbeSMat Martineau err = -EMSGSIZE; 27369a91a04aSGustavo F. Padovan break; 27379a91a04aSGustavo F. Padovan } 27389a91a04aSGustavo F. Padovan 273994122bbeSMat Martineau __skb_queue_head_init(&seg_queue); 274094122bbeSMat Martineau 274194122bbeSMat Martineau /* Do segmentation before calling in to the state machine, 274294122bbeSMat Martineau * since it's possible to block while waiting for memory 274394122bbeSMat Martineau * allocation. 274494122bbeSMat Martineau */ 274594122bbeSMat Martineau err = l2cap_segment_sdu(chan, &seg_queue, msg, len); 274694122bbeSMat Martineau 274794122bbeSMat Martineau if (err) 274894122bbeSMat Martineau break; 274994122bbeSMat Martineau 27503733937dSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) 2751d660366dSGustavo Padovan l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST); 27523733937dSMat Martineau else 2753d660366dSGustavo Padovan l2cap_streaming_send(chan, &seg_queue); 275494122bbeSMat Martineau 27559a91a04aSGustavo F. Padovan err = len; 27569a91a04aSGustavo F. Padovan 275794122bbeSMat Martineau /* If the skbs were not queued for sending, they'll still be in 275894122bbeSMat Martineau * seg_queue and need to be purged. 275994122bbeSMat Martineau */ 276094122bbeSMat Martineau __skb_queue_purge(&seg_queue); 27619a91a04aSGustavo F. Padovan break; 27629a91a04aSGustavo F. Padovan 27639a91a04aSGustavo F. Padovan default: 27649a91a04aSGustavo F. Padovan BT_DBG("bad state %1.1x", chan->mode); 27659a91a04aSGustavo F. Padovan err = -EBADFD; 27669a91a04aSGustavo F. Padovan } 27679a91a04aSGustavo F. Padovan 27689a91a04aSGustavo F. Padovan return err; 27699a91a04aSGustavo F. Padovan } 27706b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_send); 27719a91a04aSGustavo F. Padovan 2772d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq) 2773d2a7ac5dSMat Martineau { 2774bed68bdeSMat Martineau struct l2cap_ctrl control; 2775bed68bdeSMat Martineau u16 seq; 2776bed68bdeSMat Martineau 2777b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2778bed68bdeSMat Martineau 2779bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2780bed68bdeSMat Martineau control.sframe = 1; 2781bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2782bed68bdeSMat Martineau 2783bed68bdeSMat Martineau for (seq = chan->expected_tx_seq; seq != txseq; 2784bed68bdeSMat Martineau seq = __next_seq(chan, seq)) { 2785bed68bdeSMat Martineau if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) { 2786bed68bdeSMat Martineau control.reqseq = seq; 2787bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2788bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2789bed68bdeSMat Martineau } 2790bed68bdeSMat Martineau } 2791bed68bdeSMat Martineau 2792bed68bdeSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 2793d2a7ac5dSMat Martineau } 2794d2a7ac5dSMat Martineau 2795d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan) 2796d2a7ac5dSMat Martineau { 2797bed68bdeSMat Martineau struct l2cap_ctrl control; 2798bed68bdeSMat Martineau 2799bed68bdeSMat Martineau BT_DBG("chan %p", chan); 2800bed68bdeSMat Martineau 2801bed68bdeSMat Martineau if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR) 2802bed68bdeSMat Martineau return; 2803bed68bdeSMat Martineau 2804bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2805bed68bdeSMat Martineau control.sframe = 1; 2806bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2807bed68bdeSMat Martineau control.reqseq = chan->srej_list.tail; 2808bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2809d2a7ac5dSMat Martineau } 2810d2a7ac5dSMat Martineau 2811d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq) 2812d2a7ac5dSMat Martineau { 2813bed68bdeSMat Martineau struct l2cap_ctrl control; 2814bed68bdeSMat Martineau u16 initial_head; 2815bed68bdeSMat Martineau u16 seq; 2816bed68bdeSMat Martineau 2817b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2818bed68bdeSMat Martineau 2819bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2820bed68bdeSMat Martineau control.sframe = 1; 2821bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2822bed68bdeSMat Martineau 2823bed68bdeSMat Martineau /* Capture initial list head to allow only one pass through the list. */ 2824bed68bdeSMat Martineau initial_head = chan->srej_list.head; 2825bed68bdeSMat Martineau 2826bed68bdeSMat Martineau do { 2827bed68bdeSMat Martineau seq = l2cap_seq_list_pop(&chan->srej_list); 2828bed68bdeSMat Martineau if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR) 2829bed68bdeSMat Martineau break; 2830bed68bdeSMat Martineau 2831bed68bdeSMat Martineau control.reqseq = seq; 2832bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2833bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2834bed68bdeSMat Martineau } while (chan->srej_list.head != initial_head); 2835d2a7ac5dSMat Martineau } 2836d2a7ac5dSMat Martineau 2837608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq) 2838608bcc6dSMat Martineau { 2839608bcc6dSMat Martineau struct sk_buff *acked_skb; 2840608bcc6dSMat Martineau u16 ackseq; 2841608bcc6dSMat Martineau 2842b4400672SAndrei Emeltchenko BT_DBG("chan %p, reqseq %u", chan, reqseq); 2843608bcc6dSMat Martineau 2844608bcc6dSMat Martineau if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq) 2845608bcc6dSMat Martineau return; 2846608bcc6dSMat Martineau 2847b4400672SAndrei Emeltchenko BT_DBG("expected_ack_seq %u, unacked_frames %u", 2848608bcc6dSMat Martineau chan->expected_ack_seq, chan->unacked_frames); 2849608bcc6dSMat Martineau 2850608bcc6dSMat Martineau for (ackseq = chan->expected_ack_seq; ackseq != reqseq; 2851608bcc6dSMat Martineau ackseq = __next_seq(chan, ackseq)) { 2852608bcc6dSMat Martineau 2853608bcc6dSMat Martineau acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq); 2854608bcc6dSMat Martineau if (acked_skb) { 2855608bcc6dSMat Martineau skb_unlink(acked_skb, &chan->tx_q); 2856608bcc6dSMat Martineau kfree_skb(acked_skb); 2857608bcc6dSMat Martineau chan->unacked_frames--; 2858608bcc6dSMat Martineau } 2859608bcc6dSMat Martineau } 2860608bcc6dSMat Martineau 2861608bcc6dSMat Martineau chan->expected_ack_seq = reqseq; 2862608bcc6dSMat Martineau 2863608bcc6dSMat Martineau if (chan->unacked_frames == 0) 2864608bcc6dSMat Martineau __clear_retrans_timer(chan); 2865608bcc6dSMat Martineau 2866b4400672SAndrei Emeltchenko BT_DBG("unacked_frames %u", chan->unacked_frames); 2867608bcc6dSMat Martineau } 2868608bcc6dSMat Martineau 2869608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan) 2870608bcc6dSMat Martineau { 2871608bcc6dSMat Martineau BT_DBG("chan %p", chan); 2872608bcc6dSMat Martineau 2873608bcc6dSMat Martineau chan->expected_tx_seq = chan->buffer_seq; 2874608bcc6dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 2875608bcc6dSMat Martineau skb_queue_purge(&chan->srej_q); 2876608bcc6dSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2877608bcc6dSMat Martineau } 2878608bcc6dSMat Martineau 2879d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan, 2880608bcc6dSMat Martineau struct l2cap_ctrl *control, 2881608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2882608bcc6dSMat Martineau { 2883608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2884608bcc6dSMat Martineau event); 2885608bcc6dSMat Martineau 2886608bcc6dSMat Martineau switch (event) { 2887608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2888608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2889608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2890608bcc6dSMat Martineau 2891608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2892608bcc6dSMat Martineau l2cap_ertm_send(chan); 2893608bcc6dSMat Martineau break; 2894608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2895608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2896608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2897608bcc6dSMat Martineau 2898608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2899608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2900608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2901608bcc6dSMat Martineau */ 2902608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2903608bcc6dSMat Martineau } 2904608bcc6dSMat Martineau 2905608bcc6dSMat Martineau l2cap_send_ack(chan); 2906608bcc6dSMat Martineau 2907608bcc6dSMat Martineau break; 2908608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2909608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2910608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2911608bcc6dSMat Martineau 2912608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2913608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2914608bcc6dSMat Martineau 2915608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2916608bcc6dSMat Martineau local_control.sframe = 1; 2917608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2918608bcc6dSMat Martineau local_control.poll = 1; 2919608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2920a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2921608bcc6dSMat Martineau 2922608bcc6dSMat Martineau chan->retry_count = 1; 2923608bcc6dSMat Martineau __set_monitor_timer(chan); 2924608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2925608bcc6dSMat Martineau } 2926608bcc6dSMat Martineau break; 2927608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2928608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2929608bcc6dSMat Martineau break; 2930608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2931608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2932608bcc6dSMat Martineau chan->retry_count = 1; 2933608bcc6dSMat Martineau __set_monitor_timer(chan); 2934608bcc6dSMat Martineau __clear_ack_timer(chan); 2935608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2936608bcc6dSMat Martineau break; 2937608bcc6dSMat Martineau case L2CAP_EV_RETRANS_TO: 2938608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2939608bcc6dSMat Martineau chan->retry_count = 1; 2940608bcc6dSMat Martineau __set_monitor_timer(chan); 2941608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2942608bcc6dSMat Martineau break; 2943608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2944608bcc6dSMat Martineau /* Nothing to process */ 2945608bcc6dSMat Martineau break; 2946608bcc6dSMat Martineau default: 2947608bcc6dSMat Martineau break; 2948608bcc6dSMat Martineau } 2949608bcc6dSMat Martineau } 2950608bcc6dSMat Martineau 2951d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan, 2952608bcc6dSMat Martineau struct l2cap_ctrl *control, 2953608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2954608bcc6dSMat Martineau { 2955608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2956608bcc6dSMat Martineau event); 2957608bcc6dSMat Martineau 2958608bcc6dSMat Martineau switch (event) { 2959608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2960608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2961608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2962608bcc6dSMat Martineau /* Queue data, but don't send. */ 2963608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2964608bcc6dSMat Martineau break; 2965608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2966608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2967608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2968608bcc6dSMat Martineau 2969608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2970608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2971608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2972608bcc6dSMat Martineau */ 2973608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2974608bcc6dSMat Martineau } 2975608bcc6dSMat Martineau 2976608bcc6dSMat Martineau l2cap_send_ack(chan); 2977608bcc6dSMat Martineau 2978608bcc6dSMat Martineau break; 2979608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2980608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2981608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2982608bcc6dSMat Martineau 2983608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2984608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2985608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2986608bcc6dSMat Martineau local_control.sframe = 1; 2987608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2988608bcc6dSMat Martineau local_control.poll = 1; 2989608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2990a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2991608bcc6dSMat Martineau 2992608bcc6dSMat Martineau chan->retry_count = 1; 2993608bcc6dSMat Martineau __set_monitor_timer(chan); 2994608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2995608bcc6dSMat Martineau } 2996608bcc6dSMat Martineau break; 2997608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2998608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 299919186c7bSGustavo A. R. Silva fallthrough; 3000608bcc6dSMat Martineau 3001608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 3002608bcc6dSMat Martineau if (control && control->final) { 3003608bcc6dSMat Martineau __clear_monitor_timer(chan); 3004608bcc6dSMat Martineau if (chan->unacked_frames > 0) 3005608bcc6dSMat Martineau __set_retrans_timer(chan); 3006608bcc6dSMat Martineau chan->retry_count = 0; 3007608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 3008608bcc6dSMat Martineau BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state); 3009608bcc6dSMat Martineau } 3010608bcc6dSMat Martineau break; 3011608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 3012608bcc6dSMat Martineau /* Ignore */ 3013608bcc6dSMat Martineau break; 3014608bcc6dSMat Martineau case L2CAP_EV_MONITOR_TO: 3015608bcc6dSMat Martineau if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) { 3016608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 3017608bcc6dSMat Martineau __set_monitor_timer(chan); 3018608bcc6dSMat Martineau chan->retry_count++; 3019608bcc6dSMat Martineau } else { 30205e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNABORTED); 3021608bcc6dSMat Martineau } 3022608bcc6dSMat Martineau break; 3023608bcc6dSMat Martineau default: 3024608bcc6dSMat Martineau break; 3025608bcc6dSMat Martineau } 3026608bcc6dSMat Martineau } 3027608bcc6dSMat Martineau 3028d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 3029608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 3030608bcc6dSMat Martineau { 3031608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d, state %d", 3032608bcc6dSMat Martineau chan, control, skbs, event, chan->tx_state); 3033608bcc6dSMat Martineau 3034608bcc6dSMat Martineau switch (chan->tx_state) { 3035608bcc6dSMat Martineau case L2CAP_TX_STATE_XMIT: 3036d660366dSGustavo Padovan l2cap_tx_state_xmit(chan, control, skbs, event); 3037608bcc6dSMat Martineau break; 3038608bcc6dSMat Martineau case L2CAP_TX_STATE_WAIT_F: 3039d660366dSGustavo Padovan l2cap_tx_state_wait_f(chan, control, skbs, event); 3040608bcc6dSMat Martineau break; 3041608bcc6dSMat Martineau default: 3042608bcc6dSMat Martineau /* Ignore event */ 3043608bcc6dSMat Martineau break; 3044608bcc6dSMat Martineau } 3045608bcc6dSMat Martineau } 3046608bcc6dSMat Martineau 30474b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan, 30484b51dae9SMat Martineau struct l2cap_ctrl *control) 30494b51dae9SMat Martineau { 30504b51dae9SMat Martineau BT_DBG("chan %p, control %p", chan, control); 3051401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT); 30524b51dae9SMat Martineau } 30534b51dae9SMat Martineau 3054f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan, 3055f80842a8SMat Martineau struct l2cap_ctrl *control) 3056f80842a8SMat Martineau { 3057f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 3058401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT); 3059f80842a8SMat Martineau } 3060f80842a8SMat Martineau 30610a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */ 30620a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 30630a708f8fSGustavo F. Padovan { 30640a708f8fSGustavo F. Padovan struct sk_buff *nskb; 306548454079SGustavo F. Padovan struct l2cap_chan *chan; 30660a708f8fSGustavo F. Padovan 30670a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 30680a708f8fSGustavo F. Padovan 30693df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 30703d57dc68SGustavo F. Padovan 30713df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 3072715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW) 30730a708f8fSGustavo F. Padovan continue; 30740a708f8fSGustavo F. Padovan 30757f5396a7SGustavo Padovan /* Don't send frame to the channel it came from */ 3076a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.chan == chan) 30770a708f8fSGustavo F. Padovan continue; 30787f5396a7SGustavo Padovan 30798bcde1f2SGustavo Padovan nskb = skb_clone(skb, GFP_KERNEL); 30800a708f8fSGustavo F. Padovan if (!nskb) 30810a708f8fSGustavo F. Padovan continue; 308280b98027SGustavo Padovan if (chan->ops->recv(chan, nskb)) 30830a708f8fSGustavo F. Padovan kfree_skb(nskb); 30840a708f8fSGustavo F. Padovan } 30853d57dc68SGustavo F. Padovan 30863df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 30870a708f8fSGustavo F. Padovan } 30880a708f8fSGustavo F. Padovan 30890a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */ 3090b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, 3091b4400672SAndrei Emeltchenko u8 ident, u16 dlen, void *data) 30920a708f8fSGustavo F. Padovan { 30930a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag; 30940a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd; 30950a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 30960a708f8fSGustavo F. Padovan int len, count; 30970a708f8fSGustavo F. Padovan 3098b4400672SAndrei Emeltchenko BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u", 30990a708f8fSGustavo F. Padovan conn, code, ident, dlen); 31000a708f8fSGustavo F. Padovan 3101300b962eSAnderson Lizardo if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE) 3102300b962eSAnderson Lizardo return NULL; 3103300b962eSAnderson Lizardo 31040a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; 31050a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 31060a708f8fSGustavo F. Padovan 31078bcde1f2SGustavo Padovan skb = bt_skb_alloc(count, GFP_KERNEL); 31080a708f8fSGustavo F. Padovan if (!skb) 31090a708f8fSGustavo F. Padovan return NULL; 31100a708f8fSGustavo F. Padovan 31114df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 31120a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); 31133300d9a9SClaudio Takahasi 31143300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 3115dcf4adbfSJoe Perches lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING); 31163300d9a9SClaudio Takahasi else 3117dcf4adbfSJoe Perches lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING); 31180a708f8fSGustavo F. Padovan 31194df864c1SJohannes Berg cmd = skb_put(skb, L2CAP_CMD_HDR_SIZE); 31200a708f8fSGustavo F. Padovan cmd->code = code; 31210a708f8fSGustavo F. Padovan cmd->ident = ident; 31220a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen); 31230a708f8fSGustavo F. Padovan 31240a708f8fSGustavo F. Padovan if (dlen) { 31250a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE; 312659ae1d12SJohannes Berg skb_put_data(skb, data, count); 31270a708f8fSGustavo F. Padovan data += count; 31280a708f8fSGustavo F. Padovan } 31290a708f8fSGustavo F. Padovan 31300a708f8fSGustavo F. Padovan len -= skb->len; 31310a708f8fSGustavo F. Padovan 31320a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 31330a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 31340a708f8fSGustavo F. Padovan while (len) { 31350a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 31360a708f8fSGustavo F. Padovan 31378bcde1f2SGustavo Padovan *frag = bt_skb_alloc(count, GFP_KERNEL); 31380a708f8fSGustavo F. Padovan if (!*frag) 31390a708f8fSGustavo F. Padovan goto fail; 31400a708f8fSGustavo F. Padovan 314159ae1d12SJohannes Berg skb_put_data(*frag, data, count); 31420a708f8fSGustavo F. Padovan 31430a708f8fSGustavo F. Padovan len -= count; 31440a708f8fSGustavo F. Padovan data += count; 31450a708f8fSGustavo F. Padovan 31460a708f8fSGustavo F. Padovan frag = &(*frag)->next; 31470a708f8fSGustavo F. Padovan } 31480a708f8fSGustavo F. Padovan 31490a708f8fSGustavo F. Padovan return skb; 31500a708f8fSGustavo F. Padovan 31510a708f8fSGustavo F. Padovan fail: 31520a708f8fSGustavo F. Padovan kfree_skb(skb); 31530a708f8fSGustavo F. Padovan return NULL; 31540a708f8fSGustavo F. Padovan } 31550a708f8fSGustavo F. Padovan 31562d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, 31572d792818SGustavo Padovan unsigned long *val) 31580a708f8fSGustavo F. Padovan { 31590a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 31600a708f8fSGustavo F. Padovan int len; 31610a708f8fSGustavo F. Padovan 31620a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len; 31630a708f8fSGustavo F. Padovan *ptr += len; 31640a708f8fSGustavo F. Padovan 31650a708f8fSGustavo F. Padovan *type = opt->type; 31660a708f8fSGustavo F. Padovan *olen = opt->len; 31670a708f8fSGustavo F. Padovan 31680a708f8fSGustavo F. Padovan switch (opt->len) { 31690a708f8fSGustavo F. Padovan case 1: 31700a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val); 31710a708f8fSGustavo F. Padovan break; 31720a708f8fSGustavo F. Padovan 31730a708f8fSGustavo F. Padovan case 2: 31740a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val); 31750a708f8fSGustavo F. Padovan break; 31760a708f8fSGustavo F. Padovan 31770a708f8fSGustavo F. Padovan case 4: 31780a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val); 31790a708f8fSGustavo F. Padovan break; 31800a708f8fSGustavo F. Padovan 31810a708f8fSGustavo F. Padovan default: 31820a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val; 31830a708f8fSGustavo F. Padovan break; 31840a708f8fSGustavo F. Padovan } 31850a708f8fSGustavo F. Padovan 3186b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val); 31870a708f8fSGustavo F. Padovan return len; 31880a708f8fSGustavo F. Padovan } 31890a708f8fSGustavo F. Padovan 3190e860d2c9SBen Seri static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size) 31910a708f8fSGustavo F. Padovan { 31920a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 31930a708f8fSGustavo F. Padovan 3194b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val); 31950a708f8fSGustavo F. Padovan 3196e860d2c9SBen Seri if (size < L2CAP_CONF_OPT_SIZE + len) 3197e860d2c9SBen Seri return; 3198e860d2c9SBen Seri 31990a708f8fSGustavo F. Padovan opt->type = type; 32000a708f8fSGustavo F. Padovan opt->len = len; 32010a708f8fSGustavo F. Padovan 32020a708f8fSGustavo F. Padovan switch (len) { 32030a708f8fSGustavo F. Padovan case 1: 32040a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val; 32050a708f8fSGustavo F. Padovan break; 32060a708f8fSGustavo F. Padovan 32070a708f8fSGustavo F. Padovan case 2: 32080a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val); 32090a708f8fSGustavo F. Padovan break; 32100a708f8fSGustavo F. Padovan 32110a708f8fSGustavo F. Padovan case 4: 32120a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val); 32130a708f8fSGustavo F. Padovan break; 32140a708f8fSGustavo F. Padovan 32150a708f8fSGustavo F. Padovan default: 32160a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len); 32170a708f8fSGustavo F. Padovan break; 32180a708f8fSGustavo F. Padovan } 32190a708f8fSGustavo F. Padovan 32200a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len; 32210a708f8fSGustavo F. Padovan } 32220a708f8fSGustavo F. Padovan 3223e860d2c9SBen Seri static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan, size_t size) 3224f89cef09SAndrei Emeltchenko { 3225f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs; 3226f89cef09SAndrei Emeltchenko 3227f89cef09SAndrei Emeltchenko switch (chan->mode) { 3228f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM: 3229f89cef09SAndrei Emeltchenko efs.id = chan->local_id; 3230f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype; 3231f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 3232f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 3233dcf4adbfSJoe Perches efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); 3234dcf4adbfSJoe Perches efs.flush_to = cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO); 3235f89cef09SAndrei Emeltchenko break; 3236f89cef09SAndrei Emeltchenko 3237f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING: 3238f89cef09SAndrei Emeltchenko efs.id = 1; 3239f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT; 3240f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 3241f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 3242f89cef09SAndrei Emeltchenko efs.acc_lat = 0; 3243f89cef09SAndrei Emeltchenko efs.flush_to = 0; 3244f89cef09SAndrei Emeltchenko break; 3245f89cef09SAndrei Emeltchenko 3246f89cef09SAndrei Emeltchenko default: 3247f89cef09SAndrei Emeltchenko return; 3248f89cef09SAndrei Emeltchenko } 3249f89cef09SAndrei Emeltchenko 3250f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), 3251e860d2c9SBen Seri (unsigned long) &efs, size); 3252f89cef09SAndrei Emeltchenko } 3253f89cef09SAndrei Emeltchenko 3254721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work) 32550a708f8fSGustavo F. Padovan { 3256721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 3257721c4181SGustavo F. Padovan ack_timer.work); 32580362520bSMat Martineau u16 frames_to_ack; 32590a708f8fSGustavo F. Padovan 32602fb9b3d4SGustavo F. Padovan BT_DBG("chan %p", chan); 32612fb9b3d4SGustavo F. Padovan 32626be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 32636be36555SAndrei Emeltchenko 32640362520bSMat Martineau frames_to_ack = __seq_offset(chan, chan->buffer_seq, 32650362520bSMat Martineau chan->last_acked_seq); 32660362520bSMat Martineau 32670362520bSMat Martineau if (frames_to_ack) 32680362520bSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 32696be36555SAndrei Emeltchenko 32706be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 327109bfb2eeSSzymon Janc l2cap_chan_put(chan); 32720a708f8fSGustavo F. Padovan } 32730a708f8fSGustavo F. Padovan 3274466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan) 32750a708f8fSGustavo F. Padovan { 32763c588192SMat Martineau int err; 32773c588192SMat Martineau 3278105bdf9eSMat Martineau chan->next_tx_seq = 0; 3279105bdf9eSMat Martineau chan->expected_tx_seq = 0; 328042e5c802SGustavo F. Padovan chan->expected_ack_seq = 0; 32816a026610SGustavo F. Padovan chan->unacked_frames = 0; 328242e5c802SGustavo F. Padovan chan->buffer_seq = 0; 32836a026610SGustavo F. Padovan chan->frames_sent = 0; 3284105bdf9eSMat Martineau chan->last_acked_seq = 0; 3285105bdf9eSMat Martineau chan->sdu = NULL; 3286105bdf9eSMat Martineau chan->sdu_last_frag = NULL; 3287105bdf9eSMat Martineau chan->sdu_len = 0; 3288105bdf9eSMat Martineau 3289d34c34fbSMat Martineau skb_queue_head_init(&chan->tx_q); 3290d34c34fbSMat Martineau 32916ed971caSMarcel Holtmann chan->local_amp_id = AMP_ID_BREDR; 32926ed971caSMarcel Holtmann chan->move_id = AMP_ID_BREDR; 329308333283SMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 329408333283SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 329508333283SMat Martineau 3296105bdf9eSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 3297105bdf9eSMat Martineau return 0; 3298105bdf9eSMat Martineau 3299105bdf9eSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 3300105bdf9eSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 33010a708f8fSGustavo F. Padovan 3302f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q); 33030a708f8fSGustavo F. Padovan 33043c588192SMat Martineau err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win); 33053c588192SMat Martineau if (err < 0) 33063c588192SMat Martineau return err; 33073c588192SMat Martineau 33089dc9affcSMat Martineau err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win); 33099dc9affcSMat Martineau if (err < 0) 33109dc9affcSMat Martineau l2cap_seq_list_free(&chan->srej_list); 33119dc9affcSMat Martineau 33129dc9affcSMat Martineau return err; 33130a708f8fSGustavo F. Padovan } 33140a708f8fSGustavo F. Padovan 33150a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) 33160a708f8fSGustavo F. Padovan { 33170a708f8fSGustavo F. Padovan switch (mode) { 33180a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 33190a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 33200a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask)) 33210a708f8fSGustavo F. Padovan return mode; 332219186c7bSGustavo A. R. Silva fallthrough; 33230a708f8fSGustavo F. Padovan default: 33240a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC; 33250a708f8fSGustavo F. Padovan } 33260a708f8fSGustavo F. Padovan } 33270a708f8fSGustavo F. Padovan 3328848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn) 33296327eb98SAndrei Emeltchenko { 33300bd49fc7SJohan Hedberg return ((conn->local_fixed_chan & L2CAP_FC_A2MP) && 33310bd49fc7SJohan Hedberg (conn->feat_mask & L2CAP_FEAT_EXT_WINDOW)); 33326327eb98SAndrei Emeltchenko } 33336327eb98SAndrei Emeltchenko 3334848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn) 3335f89cef09SAndrei Emeltchenko { 33360bd49fc7SJohan Hedberg return ((conn->local_fixed_chan & L2CAP_FC_A2MP) && 33370bd49fc7SJohan Hedberg (conn->feat_mask & L2CAP_FEAT_EXT_FLOW)); 3338f89cef09SAndrei Emeltchenko } 3339f89cef09SAndrei Emeltchenko 334036c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan, 334136c86c85SMat Martineau struct l2cap_conf_rfc *rfc) 334236c86c85SMat Martineau { 33436ed971caSMarcel Holtmann if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) { 334436c86c85SMat Martineau u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to; 334536c86c85SMat Martineau 334636c86c85SMat Martineau /* Class 1 devices have must have ERTM timeouts 334736c86c85SMat Martineau * exceeding the Link Supervision Timeout. The 334836c86c85SMat Martineau * default Link Supervision Timeout for AMP 334936c86c85SMat Martineau * controllers is 10 seconds. 335036c86c85SMat Martineau * 335136c86c85SMat Martineau * Class 1 devices use 0xffffffff for their 335236c86c85SMat Martineau * best-effort flush timeout, so the clamping logic 335336c86c85SMat Martineau * will result in a timeout that meets the above 335436c86c85SMat Martineau * requirement. ERTM timeouts are 16-bit values, so 335536c86c85SMat Martineau * the maximum timeout is 65.535 seconds. 335636c86c85SMat Martineau */ 335736c86c85SMat Martineau 335836c86c85SMat Martineau /* Convert timeout to milliseconds and round */ 335936c86c85SMat Martineau ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000); 336036c86c85SMat Martineau 336136c86c85SMat Martineau /* This is the recommended formula for class 2 devices 336236c86c85SMat Martineau * that start ERTM timers when packets are sent to the 336336c86c85SMat Martineau * controller. 336436c86c85SMat Martineau */ 336536c86c85SMat Martineau ertm_to = 3 * ertm_to + 500; 336636c86c85SMat Martineau 336736c86c85SMat Martineau if (ertm_to > 0xffff) 336836c86c85SMat Martineau ertm_to = 0xffff; 336936c86c85SMat Martineau 337036c86c85SMat Martineau rfc->retrans_timeout = cpu_to_le16((u16) ertm_to); 337136c86c85SMat Martineau rfc->monitor_timeout = rfc->retrans_timeout; 337236c86c85SMat Martineau } else { 3373dcf4adbfSJoe Perches rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 3374dcf4adbfSJoe Perches rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 337536c86c85SMat Martineau } 337636c86c85SMat Martineau } 337736c86c85SMat Martineau 33786327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan) 33796327eb98SAndrei Emeltchenko { 33806327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && 3381848566b3SMarcel Holtmann __l2cap_ews_supported(chan->conn)) { 33826327eb98SAndrei Emeltchenko /* use extended control field */ 33836327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 3384836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 3385836be934SAndrei Emeltchenko } else { 33866327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win, 33876327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 3388836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 3389836be934SAndrei Emeltchenko } 3390c20f8e35SMat Martineau chan->ack_win = chan->tx_win; 33916327eb98SAndrei Emeltchenko } 33926327eb98SAndrei Emeltchenko 33934b6e228eSLuiz Augusto von Dentz static void l2cap_mtu_auto(struct l2cap_chan *chan) 33944b6e228eSLuiz Augusto von Dentz { 33954b6e228eSLuiz Augusto von Dentz struct hci_conn *conn = chan->conn->hcon; 33964b6e228eSLuiz Augusto von Dentz 33974b6e228eSLuiz Augusto von Dentz chan->imtu = L2CAP_DEFAULT_MIN_MTU; 33984b6e228eSLuiz Augusto von Dentz 33994b6e228eSLuiz Augusto von Dentz /* The 2-DH1 packet has between 2 and 56 information bytes 34004b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header) 34014b6e228eSLuiz Augusto von Dentz */ 34024b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_2DH1)) 34034b6e228eSLuiz Augusto von Dentz chan->imtu = 54; 34044b6e228eSLuiz Augusto von Dentz 34054b6e228eSLuiz Augusto von Dentz /* The 3-DH1 packet has between 2 and 85 information bytes 34064b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header) 34074b6e228eSLuiz Augusto von Dentz */ 34084b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_3DH1)) 34094b6e228eSLuiz Augusto von Dentz chan->imtu = 83; 34104b6e228eSLuiz Augusto von Dentz 34114b6e228eSLuiz Augusto von Dentz /* The 2-DH3 packet has between 2 and 369 information bytes 34124b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header) 34134b6e228eSLuiz Augusto von Dentz */ 34144b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_2DH3)) 34154b6e228eSLuiz Augusto von Dentz chan->imtu = 367; 34164b6e228eSLuiz Augusto von Dentz 34174b6e228eSLuiz Augusto von Dentz /* The 3-DH3 packet has between 2 and 554 information bytes 34184b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header) 34194b6e228eSLuiz Augusto von Dentz */ 34204b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_3DH3)) 34214b6e228eSLuiz Augusto von Dentz chan->imtu = 552; 34224b6e228eSLuiz Augusto von Dentz 34234b6e228eSLuiz Augusto von Dentz /* The 2-DH5 packet has between 2 and 681 information bytes 34244b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header) 34254b6e228eSLuiz Augusto von Dentz */ 34264b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_2DH5)) 34274b6e228eSLuiz Augusto von Dentz chan->imtu = 679; 34284b6e228eSLuiz Augusto von Dentz 34294b6e228eSLuiz Augusto von Dentz /* The 3-DH5 packet has between 2 and 1023 information bytes 34304b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header) 34314b6e228eSLuiz Augusto von Dentz */ 34324b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_3DH5)) 34334b6e228eSLuiz Augusto von Dentz chan->imtu = 1021; 34344b6e228eSLuiz Augusto von Dentz } 34354b6e228eSLuiz Augusto von Dentz 3436e860d2c9SBen Seri static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size) 34370a708f8fSGustavo F. Padovan { 34380a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 34390c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode }; 34400a708f8fSGustavo F. Padovan void *ptr = req->data; 3441e860d2c9SBen Seri void *endptr = data + data_size; 3442c8f79162SAndrei Emeltchenko u16 size; 34430a708f8fSGustavo F. Padovan 344449208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 34450a708f8fSGustavo F. Padovan 344673ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp) 34470a708f8fSGustavo F. Padovan goto done; 34480a708f8fSGustavo F. Padovan 34490c1bc5c6SGustavo F. Padovan switch (chan->mode) { 34500a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 34510a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3452c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) 34530a708f8fSGustavo F. Padovan break; 34540a708f8fSGustavo F. Padovan 3455848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn)) 3456f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 3457f89cef09SAndrei Emeltchenko 345819186c7bSGustavo A. R. Silva fallthrough; 34590a708f8fSGustavo F. Padovan default: 34608c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); 34610a708f8fSGustavo F. Padovan break; 34620a708f8fSGustavo F. Padovan } 34630a708f8fSGustavo F. Padovan 34640a708f8fSGustavo F. Padovan done: 34654b6e228eSLuiz Augusto von Dentz if (chan->imtu != L2CAP_DEFAULT_MTU) { 34664b6e228eSLuiz Augusto von Dentz if (!chan->imtu) 34674b6e228eSLuiz Augusto von Dentz l2cap_mtu_auto(chan); 34684b6e228eSLuiz Augusto von Dentz l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, 34694b6e228eSLuiz Augusto von Dentz endptr - ptr); 34704b6e228eSLuiz Augusto von Dentz } 34710a708f8fSGustavo F. Padovan 34720c1bc5c6SGustavo F. Padovan switch (chan->mode) { 34730a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 34746fea7ad1SMarcel Holtmann if (disable_ertm) 34756fea7ad1SMarcel Holtmann break; 34766fea7ad1SMarcel Holtmann 34778c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && 34788c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) 34790a708f8fSGustavo F. Padovan break; 34800a708f8fSGustavo F. Padovan 34810a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC; 34820a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 34830a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 34840a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 34850a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 34860a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0; 34870a708f8fSGustavo F. Padovan 34880a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3489e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr); 34900a708f8fSGustavo F. Padovan break; 34910a708f8fSGustavo F. Padovan 34920a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 34930a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM; 349447d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx; 349536c86c85SMat Martineau 349636c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc); 3497c8f79162SAndrei Emeltchenko 3498c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 34992d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - 3500c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3501c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 35020a708f8fSGustavo F. Padovan 35036327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan); 35046327eb98SAndrei Emeltchenko 35056327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win, 35066327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 35070a708f8fSGustavo F. Padovan 35080a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3509e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr); 35100a708f8fSGustavo F. Padovan 3511f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 3512e860d2c9SBen Seri l2cap_add_opt_efs(&ptr, chan, endptr - ptr); 3513f89cef09SAndrei Emeltchenko 35146327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 35156327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 3516e860d2c9SBen Seri chan->tx_win, endptr - ptr); 351760918918SAndrei Emeltchenko 351860918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS) 351960918918SAndrei Emeltchenko if (chan->fcs == L2CAP_FCS_NONE || 3520f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { 352160918918SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 352260918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, 3523e860d2c9SBen Seri chan->fcs, endptr - ptr); 352460918918SAndrei Emeltchenko } 35250a708f8fSGustavo F. Padovan break; 35260a708f8fSGustavo F. Padovan 35270a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3528273759e2SMat Martineau l2cap_txwin_setup(chan); 35290a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING; 35300a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 35310a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 35320a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 35330a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 3534c8f79162SAndrei Emeltchenko 3535c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 35362d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - 3537c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3538c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 35390a708f8fSGustavo F. Padovan 35400a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3541e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr); 35420a708f8fSGustavo F. Padovan 3543f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 3544e860d2c9SBen Seri l2cap_add_opt_efs(&ptr, chan, endptr - ptr); 3545f89cef09SAndrei Emeltchenko 354660918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS) 354747d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 3548f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { 354947d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 355060918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, 3551e860d2c9SBen Seri chan->fcs, endptr - ptr); 35520a708f8fSGustavo F. Padovan } 35530a708f8fSGustavo F. Padovan break; 35540a708f8fSGustavo F. Padovan } 35550a708f8fSGustavo F. Padovan 3556fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 3557dcf4adbfSJoe Perches req->flags = cpu_to_le16(0); 35580a708f8fSGustavo F. Padovan 35590a708f8fSGustavo F. Padovan return ptr - data; 35600a708f8fSGustavo F. Padovan } 35610a708f8fSGustavo F. Padovan 3562e860d2c9SBen Seri static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data_size) 35630a708f8fSGustavo F. Padovan { 35640a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 35650a708f8fSGustavo F. Padovan void *ptr = rsp->data; 3566e860d2c9SBen Seri void *endptr = data + data_size; 356773ffa904SGustavo F. Padovan void *req = chan->conf_req; 356873ffa904SGustavo F. Padovan int len = chan->conf_len; 35690a708f8fSGustavo F. Padovan int type, hint, olen; 35700a708f8fSGustavo F. Padovan unsigned long val; 35710a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 357242dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs; 357342dceae2SAndrei Emeltchenko u8 remote_efs = 0; 35740a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU; 35750a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS; 3576c8f79162SAndrei Emeltchenko u16 size; 35770a708f8fSGustavo F. Padovan 357873ffa904SGustavo F. Padovan BT_DBG("chan %p", chan); 35790a708f8fSGustavo F. Padovan 35800a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 35810a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val); 35827c9cbd0bSMarcel Holtmann if (len < 0) 35837c9cbd0bSMarcel Holtmann break; 35840a708f8fSGustavo F. Padovan 35850a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT; 35860a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK; 35870a708f8fSGustavo F. Padovan 35880a708f8fSGustavo F. Padovan switch (type) { 35890a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 3590af3d5d1cSMarcel Holtmann if (olen != 2) 3591af3d5d1cSMarcel Holtmann break; 35920a708f8fSGustavo F. Padovan mtu = val; 35930a708f8fSGustavo F. Padovan break; 35940a708f8fSGustavo F. Padovan 35950a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 3596af3d5d1cSMarcel Holtmann if (olen != 2) 3597af3d5d1cSMarcel Holtmann break; 35980c1bc5c6SGustavo F. Padovan chan->flush_to = val; 35990a708f8fSGustavo F. Padovan break; 36000a708f8fSGustavo F. Padovan 36010a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS: 36020a708f8fSGustavo F. Padovan break; 36030a708f8fSGustavo F. Padovan 36040a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 3605af3d5d1cSMarcel Holtmann if (olen != sizeof(rfc)) 3606af3d5d1cSMarcel Holtmann break; 36070a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen); 36080a708f8fSGustavo F. Padovan break; 36090a708f8fSGustavo F. Padovan 36100a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS: 3611af3d5d1cSMarcel Holtmann if (olen != 1) 3612af3d5d1cSMarcel Holtmann break; 36130a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE) 3614f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, &chan->conf_state); 361542dceae2SAndrei Emeltchenko break; 36160a708f8fSGustavo F. Padovan 361742dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS: 3618af3d5d1cSMarcel Holtmann if (olen != sizeof(efs)) 3619af3d5d1cSMarcel Holtmann break; 362042dceae2SAndrei Emeltchenko remote_efs = 1; 362142dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen); 36220a708f8fSGustavo F. Padovan break; 36230a708f8fSGustavo F. Padovan 36246327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 3625af3d5d1cSMarcel Holtmann if (olen != 2) 3626af3d5d1cSMarcel Holtmann break; 36270bd49fc7SJohan Hedberg if (!(chan->conn->local_fixed_chan & L2CAP_FC_A2MP)) 36286327eb98SAndrei Emeltchenko return -ECONNREFUSED; 36296327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 36306327eb98SAndrei Emeltchenko set_bit(CONF_EWS_RECV, &chan->conf_state); 3631836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 36326327eb98SAndrei Emeltchenko chan->remote_tx_win = val; 36330a708f8fSGustavo F. Padovan break; 36340a708f8fSGustavo F. Padovan 36350a708f8fSGustavo F. Padovan default: 36360a708f8fSGustavo F. Padovan if (hint) 36370a708f8fSGustavo F. Padovan break; 36380a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN; 36395b8ec15dSJimmy Wahlberg l2cap_add_conf_opt(&ptr, (u8)type, sizeof(u8), type, endptr - ptr); 36400a708f8fSGustavo F. Padovan break; 36410a708f8fSGustavo F. Padovan } 36420a708f8fSGustavo F. Padovan } 36430a708f8fSGustavo F. Padovan 364473ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1) 36450a708f8fSGustavo F. Padovan goto done; 36460a708f8fSGustavo F. Padovan 36470c1bc5c6SGustavo F. Padovan switch (chan->mode) { 36480a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 36490a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3650c1360a1cSGustavo F. Padovan if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { 36510c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, 36528c1d787bSGustavo F. Padovan chan->conn->feat_mask); 36530a708f8fSGustavo F. Padovan break; 36540a708f8fSGustavo F. Padovan } 36550a708f8fSGustavo F. Padovan 365642dceae2SAndrei Emeltchenko if (remote_efs) { 3657848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn)) 365842dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 365942dceae2SAndrei Emeltchenko else 366042dceae2SAndrei Emeltchenko return -ECONNREFUSED; 366142dceae2SAndrei Emeltchenko } 366242dceae2SAndrei Emeltchenko 36630c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) 36640a708f8fSGustavo F. Padovan return -ECONNREFUSED; 36650a708f8fSGustavo F. Padovan 36660a708f8fSGustavo F. Padovan break; 36670a708f8fSGustavo F. Padovan } 36680a708f8fSGustavo F. Padovan 36690a708f8fSGustavo F. Padovan done: 36700c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) { 36710a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 36720c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 36730a708f8fSGustavo F. Padovan 367473ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1) 36750a708f8fSGustavo F. Padovan return -ECONNREFUSED; 36760a708f8fSGustavo F. Padovan 36772d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3678e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr); 36790a708f8fSGustavo F. Padovan } 36800a708f8fSGustavo F. Padovan 36810a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) { 36820a708f8fSGustavo F. Padovan /* Configure output options and let the other side know 36830a708f8fSGustavo F. Padovan * which ones we don't like. */ 36840a708f8fSGustavo F. Padovan 36850a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU) 36860a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 36870a708f8fSGustavo F. Padovan else { 36880c1bc5c6SGustavo F. Padovan chan->omtu = mtu; 3689c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state); 36900a708f8fSGustavo F. Padovan } 3691e860d2c9SBen Seri l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu, endptr - ptr); 36920a708f8fSGustavo F. Padovan 369342dceae2SAndrei Emeltchenko if (remote_efs) { 369442dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 369542dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 369642dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) { 369742dceae2SAndrei Emeltchenko 369842dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT; 369942dceae2SAndrei Emeltchenko 370042dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1) 370142dceae2SAndrei Emeltchenko return -ECONNREFUSED; 370242dceae2SAndrei Emeltchenko 370342dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 370442dceae2SAndrei Emeltchenko sizeof(efs), 3705e860d2c9SBen Seri (unsigned long) &efs, endptr - ptr); 37060e8b207eSAndrei Emeltchenko } else { 37073e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */ 37080e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING; 37090e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 371042dceae2SAndrei Emeltchenko } 371142dceae2SAndrei Emeltchenko } 371242dceae2SAndrei Emeltchenko 37130a708f8fSGustavo F. Padovan switch (rfc.mode) { 37140a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 371547d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3716c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 37170a708f8fSGustavo F. Padovan break; 37180a708f8fSGustavo F. Padovan 37190a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 37206327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state)) 37212c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size; 37226327eb98SAndrei Emeltchenko else 37236327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; 37246327eb98SAndrei Emeltchenko 37252c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit; 37260a708f8fSGustavo F. Padovan 3727c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 37282d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE - 37292d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); 3730c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3731c8f79162SAndrei Emeltchenko chan->remote_mps = size; 37320a708f8fSGustavo F. Padovan 373336c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc); 37340a708f8fSGustavo F. Padovan 3735c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 37360a708f8fSGustavo F. Padovan 37370a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 3738e860d2c9SBen Seri sizeof(rfc), (unsigned long) &rfc, endptr - ptr); 37390a708f8fSGustavo F. Padovan 3740b1a2cd50SLuiz Augusto von Dentz if (remote_efs && 3741b1a2cd50SLuiz Augusto von Dentz test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 374242dceae2SAndrei Emeltchenko chan->remote_id = efs.id; 374342dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype; 374442dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu); 374542dceae2SAndrei Emeltchenko chan->remote_flush_to = 374642dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to); 374742dceae2SAndrei Emeltchenko chan->remote_acc_lat = 374842dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat); 374942dceae2SAndrei Emeltchenko chan->remote_sdu_itime = 375042dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 375142dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 37522d792818SGustavo Padovan sizeof(efs), 3753e860d2c9SBen Seri (unsigned long) &efs, endptr - ptr); 375442dceae2SAndrei Emeltchenko } 37550a708f8fSGustavo F. Padovan break; 37560a708f8fSGustavo F. Padovan 37570a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3758c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 37592d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE - 37602d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); 3761c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3762c8f79162SAndrei Emeltchenko chan->remote_mps = size; 37630a708f8fSGustavo F. Padovan 3764c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 37650a708f8fSGustavo F. Padovan 37662d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3767e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr); 37680a708f8fSGustavo F. Padovan 37690a708f8fSGustavo F. Padovan break; 37700a708f8fSGustavo F. Padovan 37710a708f8fSGustavo F. Padovan default: 37720a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 37730a708f8fSGustavo F. Padovan 37740a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc)); 37750c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 37760a708f8fSGustavo F. Padovan } 37770a708f8fSGustavo F. Padovan 37780a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) 3779c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 37800a708f8fSGustavo F. Padovan } 3781fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 37820a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 3783dcf4adbfSJoe Perches rsp->flags = cpu_to_le16(0); 37840a708f8fSGustavo F. Padovan 37850a708f8fSGustavo F. Padovan return ptr - data; 37860a708f8fSGustavo F. Padovan } 37870a708f8fSGustavo F. Padovan 37882d792818SGustavo Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, 3789e860d2c9SBen Seri void *data, size_t size, u16 *result) 37900a708f8fSGustavo F. Padovan { 37910a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 37920a708f8fSGustavo F. Padovan void *ptr = req->data; 3793e860d2c9SBen Seri void *endptr = data + size; 37940a708f8fSGustavo F. Padovan int type, olen; 37950a708f8fSGustavo F. Padovan unsigned long val; 379636e999a8SMat Martineau struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 379766af7aafSAndrei Emeltchenko struct l2cap_conf_efs efs; 37980a708f8fSGustavo F. Padovan 3799fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); 38000a708f8fSGustavo F. Padovan 38010a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 38020a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 38037c9cbd0bSMarcel Holtmann if (len < 0) 38047c9cbd0bSMarcel Holtmann break; 38050a708f8fSGustavo F. Padovan 38060a708f8fSGustavo F. Padovan switch (type) { 38070a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 3808af3d5d1cSMarcel Holtmann if (olen != 2) 3809af3d5d1cSMarcel Holtmann break; 38100a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) { 38110a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT; 38120c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU; 38130a708f8fSGustavo F. Padovan } else 38140c1bc5c6SGustavo F. Padovan chan->imtu = val; 3815af3d5d1cSMarcel Holtmann l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, 3816af3d5d1cSMarcel Holtmann endptr - ptr); 38170a708f8fSGustavo F. Padovan break; 38180a708f8fSGustavo F. Padovan 38190a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 3820af3d5d1cSMarcel Holtmann if (olen != 2) 3821af3d5d1cSMarcel Holtmann break; 38220c1bc5c6SGustavo F. Padovan chan->flush_to = val; 3823af3d5d1cSMarcel Holtmann l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, 3824af3d5d1cSMarcel Holtmann chan->flush_to, endptr - ptr); 38250a708f8fSGustavo F. Padovan break; 38260a708f8fSGustavo F. Padovan 38270a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 3828af3d5d1cSMarcel Holtmann if (olen != sizeof(rfc)) 3829af3d5d1cSMarcel Holtmann break; 38300a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 3831c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && 38320c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode) 38330a708f8fSGustavo F. Padovan return -ECONNREFUSED; 383447d1ec61SGustavo F. Padovan chan->fcs = 0; 3835af3d5d1cSMarcel Holtmann l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3836af3d5d1cSMarcel Holtmann (unsigned long) &rfc, endptr - ptr); 38370a708f8fSGustavo F. Padovan break; 38386327eb98SAndrei Emeltchenko 38396327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 3840af3d5d1cSMarcel Holtmann if (olen != 2) 3841af3d5d1cSMarcel Holtmann break; 3842c20f8e35SMat Martineau chan->ack_win = min_t(u16, val, chan->ack_win); 38433e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 3844e860d2c9SBen Seri chan->tx_win, endptr - ptr); 38456327eb98SAndrei Emeltchenko break; 384666af7aafSAndrei Emeltchenko 384766af7aafSAndrei Emeltchenko case L2CAP_CONF_EFS: 3848af3d5d1cSMarcel Holtmann if (olen != sizeof(efs)) 3849af3d5d1cSMarcel Holtmann break; 385066af7aafSAndrei Emeltchenko memcpy(&efs, (void *)val, olen); 385166af7aafSAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 385266af7aafSAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 385366af7aafSAndrei Emeltchenko efs.stype != chan->local_stype) 385466af7aafSAndrei Emeltchenko return -ECONNREFUSED; 38552d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), 3856e860d2c9SBen Seri (unsigned long) &efs, endptr - ptr); 385766af7aafSAndrei Emeltchenko break; 3858cbabee78SAndrei Emeltchenko 3859cbabee78SAndrei Emeltchenko case L2CAP_CONF_FCS: 3860af3d5d1cSMarcel Holtmann if (olen != 1) 3861af3d5d1cSMarcel Holtmann break; 3862cbabee78SAndrei Emeltchenko if (*result == L2CAP_CONF_PENDING) 3863cbabee78SAndrei Emeltchenko if (val == L2CAP_FCS_NONE) 3864f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, 3865cbabee78SAndrei Emeltchenko &chan->conf_state); 3866cbabee78SAndrei Emeltchenko break; 38670a708f8fSGustavo F. Padovan } 38680a708f8fSGustavo F. Padovan } 38690a708f8fSGustavo F. Padovan 38700c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) 38710a708f8fSGustavo F. Padovan return -ECONNREFUSED; 38720a708f8fSGustavo F. Padovan 38730c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode; 38740a708f8fSGustavo F. Padovan 38750e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) { 38760a708f8fSGustavo F. Padovan switch (rfc.mode) { 38770a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 387847d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 387947d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 388047d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 3881c20f8e35SMat Martineau if (!test_bit(FLAG_EXT_CTRL, &chan->flags)) 3882c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 3883c20f8e35SMat Martineau rfc.txwin_size); 388466af7aafSAndrei Emeltchenko 388566af7aafSAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 388666af7aafSAndrei Emeltchenko chan->local_msdu = le16_to_cpu(efs.msdu); 388766af7aafSAndrei Emeltchenko chan->local_sdu_itime = 388866af7aafSAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 388966af7aafSAndrei Emeltchenko chan->local_acc_lat = le32_to_cpu(efs.acc_lat); 389066af7aafSAndrei Emeltchenko chan->local_flush_to = 389166af7aafSAndrei Emeltchenko le32_to_cpu(efs.flush_to); 389266af7aafSAndrei Emeltchenko } 38930a708f8fSGustavo F. Padovan break; 389466af7aafSAndrei Emeltchenko 38950a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 389647d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 38970a708f8fSGustavo F. Padovan } 38980a708f8fSGustavo F. Padovan } 38990a708f8fSGustavo F. Padovan 3900fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 3901dcf4adbfSJoe Perches req->flags = cpu_to_le16(0); 39020a708f8fSGustavo F. Padovan 39030a708f8fSGustavo F. Padovan return ptr - data; 39040a708f8fSGustavo F. Padovan } 39050a708f8fSGustavo F. Padovan 39062d792818SGustavo Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, 39072d792818SGustavo Padovan u16 result, u16 flags) 39080a708f8fSGustavo F. Padovan { 39090a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 39100a708f8fSGustavo F. Padovan void *ptr = rsp->data; 39110a708f8fSGustavo F. Padovan 3912fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan); 39130a708f8fSGustavo F. Padovan 3914fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 39150a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 39160a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags); 39170a708f8fSGustavo F. Padovan 39180a708f8fSGustavo F. Padovan return ptr - data; 39190a708f8fSGustavo F. Padovan } 39200a708f8fSGustavo F. Padovan 392127e2d4c8SJohan Hedberg void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan) 392227e2d4c8SJohan Hedberg { 392327e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 392427e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn; 392527e2d4c8SJohan Hedberg 392627e2d4c8SJohan Hedberg BT_DBG("chan %p", chan); 392727e2d4c8SJohan Hedberg 392827e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 392927e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 39303916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps); 39310cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits); 3932571f7390SMallikarjun Phulari rsp.result = cpu_to_le16(L2CAP_CR_LE_SUCCESS); 393327e2d4c8SJohan Hedberg 393427e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), 393527e2d4c8SJohan Hedberg &rsp); 393627e2d4c8SJohan Hedberg } 393727e2d4c8SJohan Hedberg 3938*9aa9d947SLuiz Augusto von Dentz static void l2cap_ecred_list_defer(struct l2cap_chan *chan, void *data) 393915f02b91SLuiz Augusto von Dentz { 3940*9aa9d947SLuiz Augusto von Dentz int *result = data; 394115f02b91SLuiz Augusto von Dentz 3942*9aa9d947SLuiz Augusto von Dentz if (*result || test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags)) 394315f02b91SLuiz Augusto von Dentz return; 394415f02b91SLuiz Augusto von Dentz 3945*9aa9d947SLuiz Augusto von Dentz switch (chan->state) { 3946*9aa9d947SLuiz Augusto von Dentz case BT_CONNECT2: 3947*9aa9d947SLuiz Augusto von Dentz /* If channel still pending accept add to result */ 3948*9aa9d947SLuiz Augusto von Dentz (*result)++; 3949*9aa9d947SLuiz Augusto von Dentz return; 3950*9aa9d947SLuiz Augusto von Dentz case BT_CONNECTED: 3951*9aa9d947SLuiz Augusto von Dentz return; 3952*9aa9d947SLuiz Augusto von Dentz default: 3953*9aa9d947SLuiz Augusto von Dentz /* If not connected or pending accept it has been refused */ 3954*9aa9d947SLuiz Augusto von Dentz *result = -ECONNREFUSED; 3955*9aa9d947SLuiz Augusto von Dentz return; 3956*9aa9d947SLuiz Augusto von Dentz } 3957*9aa9d947SLuiz Augusto von Dentz } 395815f02b91SLuiz Augusto von Dentz 3959*9aa9d947SLuiz Augusto von Dentz struct l2cap_ecred_rsp_data { 3960*9aa9d947SLuiz Augusto von Dentz struct { 3961*9aa9d947SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp rsp; 3962*9aa9d947SLuiz Augusto von Dentz __le16 scid[L2CAP_ECRED_MAX_CID]; 3963*9aa9d947SLuiz Augusto von Dentz } __packed pdu; 3964*9aa9d947SLuiz Augusto von Dentz int count; 3965*9aa9d947SLuiz Augusto von Dentz }; 396615f02b91SLuiz Augusto von Dentz 3967*9aa9d947SLuiz Augusto von Dentz static void l2cap_ecred_rsp_defer(struct l2cap_chan *chan, void *data) 3968*9aa9d947SLuiz Augusto von Dentz { 3969*9aa9d947SLuiz Augusto von Dentz struct l2cap_ecred_rsp_data *rsp = data; 397015f02b91SLuiz Augusto von Dentz 3971*9aa9d947SLuiz Augusto von Dentz if (test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags)) 3972*9aa9d947SLuiz Augusto von Dentz return; 397315f02b91SLuiz Augusto von Dentz 397415f02b91SLuiz Augusto von Dentz /* Reset ident so only one response is sent */ 397515f02b91SLuiz Augusto von Dentz chan->ident = 0; 397615f02b91SLuiz Augusto von Dentz 397715f02b91SLuiz Augusto von Dentz /* Include all channels pending with the same ident */ 3978*9aa9d947SLuiz Augusto von Dentz if (!rsp->pdu.rsp.result) 3979*9aa9d947SLuiz Augusto von Dentz rsp->pdu.rsp.dcid[rsp->count++] = cpu_to_le16(chan->scid); 3980*9aa9d947SLuiz Augusto von Dentz else 3981*9aa9d947SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNRESET); 398215f02b91SLuiz Augusto von Dentz } 398315f02b91SLuiz Augusto von Dentz 3984*9aa9d947SLuiz Augusto von Dentz void __l2cap_ecred_conn_rsp_defer(struct l2cap_chan *chan) 3985*9aa9d947SLuiz Augusto von Dentz { 3986*9aa9d947SLuiz Augusto von Dentz struct l2cap_conn *conn = chan->conn; 3987*9aa9d947SLuiz Augusto von Dentz struct l2cap_ecred_rsp_data data; 3988*9aa9d947SLuiz Augusto von Dentz u16 id = chan->ident; 3989*9aa9d947SLuiz Augusto von Dentz int result = 0; 399015f02b91SLuiz Augusto von Dentz 3991*9aa9d947SLuiz Augusto von Dentz if (!id) 3992*9aa9d947SLuiz Augusto von Dentz return; 3993*9aa9d947SLuiz Augusto von Dentz 3994*9aa9d947SLuiz Augusto von Dentz BT_DBG("chan %p id %d", chan, id); 3995*9aa9d947SLuiz Augusto von Dentz 3996*9aa9d947SLuiz Augusto von Dentz memset(&data, 0, sizeof(data)); 3997*9aa9d947SLuiz Augusto von Dentz 3998*9aa9d947SLuiz Augusto von Dentz data.pdu.rsp.mtu = cpu_to_le16(chan->imtu); 3999*9aa9d947SLuiz Augusto von Dentz data.pdu.rsp.mps = cpu_to_le16(chan->mps); 4000*9aa9d947SLuiz Augusto von Dentz data.pdu.rsp.credits = cpu_to_le16(chan->rx_credits); 4001*9aa9d947SLuiz Augusto von Dentz data.pdu.rsp.result = cpu_to_le16(L2CAP_CR_LE_SUCCESS); 4002*9aa9d947SLuiz Augusto von Dentz 4003*9aa9d947SLuiz Augusto von Dentz /* Verify that all channels are ready */ 4004*9aa9d947SLuiz Augusto von Dentz __l2cap_chan_list_id(conn, id, l2cap_ecred_list_defer, &result); 4005*9aa9d947SLuiz Augusto von Dentz 4006*9aa9d947SLuiz Augusto von Dentz if (result > 0) 4007*9aa9d947SLuiz Augusto von Dentz return; 4008*9aa9d947SLuiz Augusto von Dentz 4009*9aa9d947SLuiz Augusto von Dentz if (result < 0) 4010*9aa9d947SLuiz Augusto von Dentz data.pdu.rsp.result = cpu_to_le16(L2CAP_CR_LE_AUTHORIZATION); 4011*9aa9d947SLuiz Augusto von Dentz 4012*9aa9d947SLuiz Augusto von Dentz /* Build response */ 4013*9aa9d947SLuiz Augusto von Dentz __l2cap_chan_list_id(conn, id, l2cap_ecred_rsp_defer, &data); 4014*9aa9d947SLuiz Augusto von Dentz 4015*9aa9d947SLuiz Augusto von Dentz l2cap_send_cmd(conn, id, L2CAP_ECRED_CONN_RSP, 4016*9aa9d947SLuiz Augusto von Dentz sizeof(data.pdu.rsp) + (data.count * sizeof(__le16)), 4017*9aa9d947SLuiz Augusto von Dentz &data.pdu); 401815f02b91SLuiz Augusto von Dentz } 401915f02b91SLuiz Augusto von Dentz 40208c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) 4021710f9b0aSGustavo F. Padovan { 4022710f9b0aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 40238c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 4024710f9b0aSGustavo F. Padovan u8 buf[128]; 4025439f34acSAndrei Emeltchenko u8 rsp_code; 4026710f9b0aSGustavo F. Padovan 4027fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 4028fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 4029dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 4030dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 4031439f34acSAndrei Emeltchenko 4032439f34acSAndrei Emeltchenko if (chan->hs_hcon) 4033439f34acSAndrei Emeltchenko rsp_code = L2CAP_CREATE_CHAN_RSP; 4034439f34acSAndrei Emeltchenko else 4035439f34acSAndrei Emeltchenko rsp_code = L2CAP_CONN_RSP; 4036439f34acSAndrei Emeltchenko 4037439f34acSAndrei Emeltchenko BT_DBG("chan %p rsp_code %u", chan, rsp_code); 4038439f34acSAndrei Emeltchenko 4039439f34acSAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp); 4040710f9b0aSGustavo F. Padovan 4041c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 4042710f9b0aSGustavo F. Padovan return; 4043710f9b0aSGustavo F. Padovan 4044710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 4045e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); 4046710f9b0aSGustavo F. Padovan chan->num_conf_req++; 4047710f9b0aSGustavo F. Padovan } 4048710f9b0aSGustavo F. Padovan 404947d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) 40500a708f8fSGustavo F. Padovan { 40510a708f8fSGustavo F. Padovan int type, olen; 40520a708f8fSGustavo F. Padovan unsigned long val; 4053c20f8e35SMat Martineau /* Use sane default values in case a misbehaving remote device 4054c20f8e35SMat Martineau * did not send an RFC or extended window size option. 4055c20f8e35SMat Martineau */ 4056c20f8e35SMat Martineau u16 txwin_ext = chan->ack_win; 4057c20f8e35SMat Martineau struct l2cap_conf_rfc rfc = { 4058c20f8e35SMat Martineau .mode = chan->mode, 4059dcf4adbfSJoe Perches .retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO), 4060dcf4adbfSJoe Perches .monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO), 4061c20f8e35SMat Martineau .max_pdu_size = cpu_to_le16(chan->imtu), 4062c20f8e35SMat Martineau .txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW), 4063c20f8e35SMat Martineau }; 40640a708f8fSGustavo F. Padovan 406547d1ec61SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); 40660a708f8fSGustavo F. Padovan 40670c1bc5c6SGustavo F. Padovan if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) 40680a708f8fSGustavo F. Padovan return; 40690a708f8fSGustavo F. Padovan 40700a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 40710a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 40727c9cbd0bSMarcel Holtmann if (len < 0) 40737c9cbd0bSMarcel Holtmann break; 40740a708f8fSGustavo F. Padovan 4075c20f8e35SMat Martineau switch (type) { 4076c20f8e35SMat Martineau case L2CAP_CONF_RFC: 4077af3d5d1cSMarcel Holtmann if (olen != sizeof(rfc)) 4078af3d5d1cSMarcel Holtmann break; 40790a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 4080c20f8e35SMat Martineau break; 4081c20f8e35SMat Martineau case L2CAP_CONF_EWS: 4082af3d5d1cSMarcel Holtmann if (olen != 2) 4083af3d5d1cSMarcel Holtmann break; 4084c20f8e35SMat Martineau txwin_ext = val; 4085c20f8e35SMat Martineau break; 4086c20f8e35SMat Martineau } 40870a708f8fSGustavo F. Padovan } 40880a708f8fSGustavo F. Padovan 40890a708f8fSGustavo F. Padovan switch (rfc.mode) { 40900a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 409147d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 409247d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 409347d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 4094c20f8e35SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 4095c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, txwin_ext); 4096c20f8e35SMat Martineau else 4097c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 4098c20f8e35SMat Martineau rfc.txwin_size); 40990a708f8fSGustavo F. Padovan break; 41000a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 410147d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 41020a708f8fSGustavo F. Padovan } 41030a708f8fSGustavo F. Padovan } 41040a708f8fSGustavo F. Padovan 41052d792818SGustavo Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, 4106cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4107cb3b3152SJohan Hedberg u8 *data) 41080a708f8fSGustavo F. Padovan { 4109e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 41100a708f8fSGustavo F. Padovan 4111cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rej)) 4112cb3b3152SJohan Hedberg return -EPROTO; 4113cb3b3152SJohan Hedberg 4114e2fd318eSIlia Kolomisnky if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) 41150a708f8fSGustavo F. Padovan return 0; 41160a708f8fSGustavo F. Padovan 41170a708f8fSGustavo F. Padovan if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && 41180a708f8fSGustavo F. Padovan cmd->ident == conn->info_ident) { 411917cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 41200a708f8fSGustavo F. Padovan 41210a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 41220a708f8fSGustavo F. Padovan conn->info_ident = 0; 41230a708f8fSGustavo F. Padovan 41240a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 41250a708f8fSGustavo F. Padovan } 41260a708f8fSGustavo F. Padovan 41270a708f8fSGustavo F. Padovan return 0; 41280a708f8fSGustavo F. Padovan } 41290a708f8fSGustavo F. Padovan 41301700915fSMat Martineau static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, 41311700915fSMat Martineau struct l2cap_cmd_hdr *cmd, 41324c89b6aaSMat Martineau u8 *data, u8 rsp_code, u8 amp_id) 41330a708f8fSGustavo F. Padovan { 41340a708f8fSGustavo F. Padovan struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 41350a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 413623691d75SGustavo F. Padovan struct l2cap_chan *chan = NULL, *pchan; 41370a708f8fSGustavo F. Padovan int result, status = L2CAP_CS_NO_INFO; 41380a708f8fSGustavo F. Padovan 41390a708f8fSGustavo F. Padovan u16 dcid = 0, scid = __le16_to_cpu(req->scid); 41400a708f8fSGustavo F. Padovan __le16 psm = req->psm; 41410a708f8fSGustavo F. Padovan 4142097db76cSAndrei Emeltchenko BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); 41430a708f8fSGustavo F. Padovan 41440a708f8fSGustavo F. Padovan /* Check if we have socket listening on psm */ 41456f59b904SMarcel Holtmann pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 4146bf20fd4eSJohan Hedberg &conn->hcon->dst, ACL_LINK); 414723691d75SGustavo F. Padovan if (!pchan) { 41480a708f8fSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 41490a708f8fSGustavo F. Padovan goto sendresp; 41500a708f8fSGustavo F. Padovan } 41510a708f8fSGustavo F. Padovan 41523df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 41538ffb9290SGustavo Padovan l2cap_chan_lock(pchan); 41540a708f8fSGustavo F. Padovan 41550a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */ 4156dcf4adbfSJoe Perches if (psm != cpu_to_le16(L2CAP_PSM_SDP) && 41570a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) { 41589f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_AUTH_FAILURE; 41590a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 41600a708f8fSGustavo F. Padovan goto response; 41610a708f8fSGustavo F. Padovan } 41620a708f8fSGustavo F. Padovan 41630a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM; 41640a708f8fSGustavo F. Padovan 4165dd1a8f8aSMallikarjun Phulari /* Check for valid dynamic CID range (as per Erratum 3253) */ 4166dd1a8f8aSMallikarjun Phulari if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_DYN_END) { 4167dd1a8f8aSMallikarjun Phulari result = L2CAP_CR_INVALID_SCID; 41682dfa1003SGustavo Padovan goto response; 4169dd1a8f8aSMallikarjun Phulari } 4170dd1a8f8aSMallikarjun Phulari 4171dd1a8f8aSMallikarjun Phulari /* Check if we already have channel with that dcid */ 4172dd1a8f8aSMallikarjun Phulari if (__l2cap_get_chan_by_dcid(conn, scid)) { 4173dd1a8f8aSMallikarjun Phulari result = L2CAP_CR_SCID_IN_USE; 4174dd1a8f8aSMallikarjun Phulari goto response; 4175dd1a8f8aSMallikarjun Phulari } 41762dfa1003SGustavo Padovan 417780b98027SGustavo Padovan chan = pchan->ops->new_connection(pchan); 417880808e43SGustavo F. Padovan if (!chan) 41790a708f8fSGustavo F. Padovan goto response; 41800a708f8fSGustavo F. Padovan 4181330b6c15SSyam Sidhardhan /* For certain devices (ex: HID mouse), support for authentication, 4182330b6c15SSyam Sidhardhan * pairing and bonding is optional. For such devices, inorder to avoid 4183330b6c15SSyam Sidhardhan * the ACL alive for too long after L2CAP disconnection, reset the ACL 4184330b6c15SSyam Sidhardhan * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect. 4185330b6c15SSyam Sidhardhan */ 4186330b6c15SSyam Sidhardhan conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 4187330b6c15SSyam Sidhardhan 41887eafc59eSMarcel Holtmann bacpy(&chan->src, &conn->hcon->src); 41897eafc59eSMarcel Holtmann bacpy(&chan->dst, &conn->hcon->dst); 4190a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(conn->hcon); 4191a250e048SJohan Hedberg chan->dst_type = bdaddr_dst_type(conn->hcon); 4192fe4128e0SGustavo F. Padovan chan->psm = psm; 4193fe4128e0SGustavo F. Padovan chan->dcid = scid; 41941700915fSMat Martineau chan->local_amp_id = amp_id; 41950a708f8fSGustavo F. Padovan 41966be36555SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 419748454079SGustavo F. Padovan 4198fe4128e0SGustavo F. Padovan dcid = chan->scid; 41990a708f8fSGustavo F. Padovan 42008d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 42010a708f8fSGustavo F. Padovan 4202fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident; 42030a708f8fSGustavo F. Padovan 42040a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { 4205e7cafc45SJohan Hedberg if (l2cap_chan_check_security(chan, false)) { 4206bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 4207f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 42080a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 42090a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND; 42102dc4e510SGustavo Padovan chan->ops->defer(chan); 42110a708f8fSGustavo F. Padovan } else { 42121700915fSMat Martineau /* Force pending result for AMP controllers. 42131700915fSMat Martineau * The connection will succeed after the 42141700915fSMat Martineau * physical link is up. 42151700915fSMat Martineau */ 42166ed971caSMarcel Holtmann if (amp_id == AMP_ID_BREDR) { 4217f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 42180a708f8fSGustavo F. Padovan result = L2CAP_CR_SUCCESS; 42196ed971caSMarcel Holtmann } else { 4220f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 42216ed971caSMarcel Holtmann result = L2CAP_CR_PEND; 42221700915fSMat Martineau } 42230a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 42240a708f8fSGustavo F. Padovan } 42250a708f8fSGustavo F. Padovan } else { 4226f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 42270a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 42280a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND; 42290a708f8fSGustavo F. Padovan } 42300a708f8fSGustavo F. Padovan } else { 4231f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 42320a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 42330a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 42340a708f8fSGustavo F. Padovan } 42350a708f8fSGustavo F. Padovan 42360a708f8fSGustavo F. Padovan response: 42378ffb9290SGustavo Padovan l2cap_chan_unlock(pchan); 42383df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4239a24cce14SJohan Hedberg l2cap_chan_put(pchan); 42400a708f8fSGustavo F. Padovan 42410a708f8fSGustavo F. Padovan sendresp: 42420a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid); 42430a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid); 42440a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result); 42450a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status); 42464c89b6aaSMat Martineau l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp); 42470a708f8fSGustavo F. Padovan 42480a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { 42490a708f8fSGustavo F. Padovan struct l2cap_info_req info; 4250dcf4adbfSJoe Perches info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 42510a708f8fSGustavo F. Padovan 42520a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 42530a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 42540a708f8fSGustavo F. Padovan 4255ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 42560a708f8fSGustavo F. Padovan 42572d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, 42582d792818SGustavo Padovan sizeof(info), &info); 42590a708f8fSGustavo F. Padovan } 42600a708f8fSGustavo F. Padovan 4261c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && 42620a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) { 42630a708f8fSGustavo F. Padovan u8 buf[128]; 4264c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 42650a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 4266e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); 426773ffa904SGustavo F. Padovan chan->num_conf_req++; 42680a708f8fSGustavo F. Padovan } 42691700915fSMat Martineau 42701700915fSMat Martineau return chan; 42714c89b6aaSMat Martineau } 42720a708f8fSGustavo F. Padovan 42734c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn, 4274cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 42754c89b6aaSMat Martineau { 42767b064edaSJaganath Kanakkassery struct hci_dev *hdev = conn->hcon->hdev; 42777b064edaSJaganath Kanakkassery struct hci_conn *hcon = conn->hcon; 42787b064edaSJaganath Kanakkassery 4279cb3b3152SJohan Hedberg if (cmd_len < sizeof(struct l2cap_conn_req)) 4280cb3b3152SJohan Hedberg return -EPROTO; 4281cb3b3152SJohan Hedberg 42827b064edaSJaganath Kanakkassery hci_dev_lock(hdev); 4283d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_MGMT) && 42847b064edaSJaganath Kanakkassery !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags)) 42851c6ed31bSYu Liu mgmt_device_connected(hdev, hcon, NULL, 0); 42867b064edaSJaganath Kanakkassery hci_dev_unlock(hdev); 42877b064edaSJaganath Kanakkassery 4288300229f9SGustavo Padovan l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0); 42890a708f8fSGustavo F. Padovan return 0; 42900a708f8fSGustavo F. Padovan } 42910a708f8fSGustavo F. Padovan 42925909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn, 4293cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4294cb3b3152SJohan Hedberg u8 *data) 42950a708f8fSGustavo F. Padovan { 42960a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; 42970a708f8fSGustavo F. Padovan u16 scid, dcid, result, status; 429848454079SGustavo F. Padovan struct l2cap_chan *chan; 42990a708f8fSGustavo F. Padovan u8 req[128]; 43003df91ea2SAndrei Emeltchenko int err; 43010a708f8fSGustavo F. Padovan 4302cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp)) 4303cb3b3152SJohan Hedberg return -EPROTO; 4304cb3b3152SJohan Hedberg 43050a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 43060a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 43070a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 43080a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status); 43090a708f8fSGustavo F. Padovan 43101b009c98SAndrei Emeltchenko BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", 43111b009c98SAndrei Emeltchenko dcid, scid, result, status); 43120a708f8fSGustavo F. Padovan 43133df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 43143df91ea2SAndrei Emeltchenko 43150a708f8fSGustavo F. Padovan if (scid) { 43163df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 43173df91ea2SAndrei Emeltchenko if (!chan) { 431821870b52SJohan Hedberg err = -EBADSLT; 43193df91ea2SAndrei Emeltchenko goto unlock; 43203df91ea2SAndrei Emeltchenko } 43210a708f8fSGustavo F. Padovan } else { 43223df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 43233df91ea2SAndrei Emeltchenko if (!chan) { 432421870b52SJohan Hedberg err = -EBADSLT; 43253df91ea2SAndrei Emeltchenko goto unlock; 43263df91ea2SAndrei Emeltchenko } 43270a708f8fSGustavo F. Padovan } 43280a708f8fSGustavo F. Padovan 432935fcbc42SLuiz Augusto von Dentz chan = l2cap_chan_hold_unless_zero(chan); 433035fcbc42SLuiz Augusto von Dentz if (!chan) { 433135fcbc42SLuiz Augusto von Dentz err = -EBADSLT; 433235fcbc42SLuiz Augusto von Dentz goto unlock; 433335fcbc42SLuiz Augusto von Dentz } 433435fcbc42SLuiz Augusto von Dentz 43353df91ea2SAndrei Emeltchenko err = 0; 43363df91ea2SAndrei Emeltchenko 43376be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 433848454079SGustavo F. Padovan 43390a708f8fSGustavo F. Padovan switch (result) { 43400a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS: 434189bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 4342fc7f8a7eSGustavo F. Padovan chan->ident = 0; 4343fe4128e0SGustavo F. Padovan chan->dcid = dcid; 4344c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state); 43450a708f8fSGustavo F. Padovan 4346c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 43470a708f8fSGustavo F. Padovan break; 43480a708f8fSGustavo F. Padovan 43490a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 4350e860d2c9SBen Seri l2cap_build_conf_req(chan, req, sizeof(req)), req); 435173ffa904SGustavo F. Padovan chan->num_conf_req++; 43520a708f8fSGustavo F. Padovan break; 43530a708f8fSGustavo F. Padovan 43540a708f8fSGustavo F. Padovan case L2CAP_CR_PEND: 4355c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 43560a708f8fSGustavo F. Padovan break; 43570a708f8fSGustavo F. Padovan 43580a708f8fSGustavo F. Padovan default: 435948454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED); 43600a708f8fSGustavo F. Padovan break; 43610a708f8fSGustavo F. Padovan } 43620a708f8fSGustavo F. Padovan 43636be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 436435fcbc42SLuiz Augusto von Dentz l2cap_chan_put(chan); 43653df91ea2SAndrei Emeltchenko 43663df91ea2SAndrei Emeltchenko unlock: 43673df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 43683df91ea2SAndrei Emeltchenko 43693df91ea2SAndrei Emeltchenko return err; 43700a708f8fSGustavo F. Padovan } 43710a708f8fSGustavo F. Padovan 437247d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan) 43730a708f8fSGustavo F. Padovan { 43740a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both 43750a708f8fSGustavo F. Padovan * sides request it. 43760a708f8fSGustavo F. Padovan */ 43770c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) 437847d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 4379f2592d3eSAndrei Emeltchenko else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) 438047d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16; 43810a708f8fSGustavo F. Padovan } 43820a708f8fSGustavo F. Padovan 438329d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data, 438429d8a590SAndrei Emeltchenko u8 ident, u16 flags) 438529d8a590SAndrei Emeltchenko { 438629d8a590SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 438729d8a590SAndrei Emeltchenko 438829d8a590SAndrei Emeltchenko BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident, 438929d8a590SAndrei Emeltchenko flags); 439029d8a590SAndrei Emeltchenko 439129d8a590SAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 439229d8a590SAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 439329d8a590SAndrei Emeltchenko 439429d8a590SAndrei Emeltchenko l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP, 439529d8a590SAndrei Emeltchenko l2cap_build_conf_rsp(chan, data, 439629d8a590SAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), data); 439729d8a590SAndrei Emeltchenko } 439829d8a590SAndrei Emeltchenko 4399662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident, 4400662d652dSJohan Hedberg u16 scid, u16 dcid) 4401662d652dSJohan Hedberg { 4402662d652dSJohan Hedberg struct l2cap_cmd_rej_cid rej; 4403662d652dSJohan Hedberg 4404dcf4adbfSJoe Perches rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID); 4405662d652dSJohan Hedberg rej.scid = __cpu_to_le16(scid); 4406662d652dSJohan Hedberg rej.dcid = __cpu_to_le16(dcid); 4407662d652dSJohan Hedberg 4408662d652dSJohan Hedberg l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); 4409662d652dSJohan Hedberg } 4410662d652dSJohan Hedberg 44112d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, 44122d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len, 44132d792818SGustavo Padovan u8 *data) 44140a708f8fSGustavo F. Padovan { 44150a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; 44160a708f8fSGustavo F. Padovan u16 dcid, flags; 44170a708f8fSGustavo F. Padovan u8 rsp[64]; 441848454079SGustavo F. Padovan struct l2cap_chan *chan; 44193c588192SMat Martineau int len, err = 0; 44200a708f8fSGustavo F. Padovan 4421cb3b3152SJohan Hedberg if (cmd_len < sizeof(*req)) 4422cb3b3152SJohan Hedberg return -EPROTO; 4423cb3b3152SJohan Hedberg 44240a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 44250a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags); 44260a708f8fSGustavo F. Padovan 44270a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); 44280a708f8fSGustavo F. Padovan 4429baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid); 4430662d652dSJohan Hedberg if (!chan) { 4431662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0); 4432662d652dSJohan Hedberg return 0; 4433662d652dSJohan Hedberg } 44340a708f8fSGustavo F. Padovan 443596298f64SHoward Chung if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2 && 443696298f64SHoward Chung chan->state != BT_CONNECTED) { 4437662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, 4438662d652dSJohan Hedberg chan->dcid); 44390a708f8fSGustavo F. Padovan goto unlock; 44400a708f8fSGustavo F. Padovan } 44410a708f8fSGustavo F. Padovan 44420a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */ 44430a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req); 4444cb3b3152SJohan Hedberg if (chan->conf_len + len > sizeof(chan->conf_req)) { 44450a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 4446fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 44470a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp); 44480a708f8fSGustavo F. Padovan goto unlock; 44490a708f8fSGustavo F. Padovan } 44500a708f8fSGustavo F. Padovan 44510a708f8fSGustavo F. Padovan /* Store config. */ 445273ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len); 445373ffa904SGustavo F. Padovan chan->conf_len += len; 44540a708f8fSGustavo F. Padovan 445559e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) { 44560a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */ 44570a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 4458fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 44595325e5bbSAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), rsp); 44600a708f8fSGustavo F. Padovan goto unlock; 44610a708f8fSGustavo F. Padovan } 44620a708f8fSGustavo F. Padovan 44630a708f8fSGustavo F. Padovan /* Complete config. */ 4464e860d2c9SBen Seri len = l2cap_parse_conf_req(chan, rsp, sizeof(rsp)); 44650a708f8fSGustavo F. Padovan if (len < 0) { 44665e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 44670a708f8fSGustavo F. Padovan goto unlock; 44680a708f8fSGustavo F. Padovan } 44690a708f8fSGustavo F. Padovan 44701500109bSMat Martineau chan->ident = cmd->ident; 44710a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); 4472bcd70260SSungwoo Kim if (chan->num_conf_rsp < L2CAP_CONF_MAX_CONF_RSP) 447373ffa904SGustavo F. Padovan chan->num_conf_rsp++; 44740a708f8fSGustavo F. Padovan 44750a708f8fSGustavo F. Padovan /* Reset config buffer. */ 447673ffa904SGustavo F. Padovan chan->conf_len = 0; 44770a708f8fSGustavo F. Padovan 4478c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) 44790a708f8fSGustavo F. Padovan goto unlock; 44800a708f8fSGustavo F. Padovan 4481c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 448247d1ec61SGustavo F. Padovan set_default_fcs(chan); 44830a708f8fSGustavo F. Padovan 4484105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 4485105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 44863c588192SMat Martineau err = l2cap_ertm_init(chan); 44870a708f8fSGustavo F. Padovan 44883c588192SMat Martineau if (err < 0) 44895e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 44903c588192SMat Martineau else 4491cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 44923c588192SMat Martineau 44930a708f8fSGustavo F. Padovan goto unlock; 44940a708f8fSGustavo F. Padovan } 44950a708f8fSGustavo F. Padovan 4496c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { 44970a708f8fSGustavo F. Padovan u8 buf[64]; 44980a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 4499e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); 450073ffa904SGustavo F. Padovan chan->num_conf_req++; 45010a708f8fSGustavo F. Padovan } 45020a708f8fSGustavo F. Padovan 450349c922bbSStephen Hemminger /* Got Conf Rsp PENDING from remote side and assume we sent 45040e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */ 45050e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && 45060e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 45070e8b207eSAndrei Emeltchenko 45080e8b207eSAndrei Emeltchenko /* check compatibility */ 45090e8b207eSAndrei Emeltchenko 451079de886dSAndrei Emeltchenko /* Send rsp for BR/EDR channel */ 4511f351bc72SAndrei Emeltchenko if (!chan->hs_hcon) 451229d8a590SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags); 451379de886dSAndrei Emeltchenko else 451479de886dSAndrei Emeltchenko chan->ident = cmd->ident; 45150e8b207eSAndrei Emeltchenko } 45160e8b207eSAndrei Emeltchenko 45170a708f8fSGustavo F. Padovan unlock: 45186be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 4519d0be8347SLuiz Augusto von Dentz l2cap_chan_put(chan); 45203c588192SMat Martineau return err; 45210a708f8fSGustavo F. Padovan } 45220a708f8fSGustavo F. Padovan 45232d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, 4524cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4525cb3b3152SJohan Hedberg u8 *data) 45260a708f8fSGustavo F. Padovan { 45270a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; 45280a708f8fSGustavo F. Padovan u16 scid, flags, result; 452948454079SGustavo F. Padovan struct l2cap_chan *chan; 4530cb3b3152SJohan Hedberg int len = cmd_len - sizeof(*rsp); 45313c588192SMat Martineau int err = 0; 45320a708f8fSGustavo F. Padovan 4533cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp)) 4534cb3b3152SJohan Hedberg return -EPROTO; 4535cb3b3152SJohan Hedberg 45360a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 45370a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags); 45380a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 45390a708f8fSGustavo F. Padovan 454061386cbaSAndrei Emeltchenko BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags, 454161386cbaSAndrei Emeltchenko result, len); 45420a708f8fSGustavo F. Padovan 4543baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 454448454079SGustavo F. Padovan if (!chan) 45450a708f8fSGustavo F. Padovan return 0; 45460a708f8fSGustavo F. Padovan 45470a708f8fSGustavo F. Padovan switch (result) { 45480a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS: 454947d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len); 45500e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state); 45510a708f8fSGustavo F. Padovan break; 45520a708f8fSGustavo F. Padovan 45530e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING: 45540e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state); 45550e8b207eSAndrei Emeltchenko 45560e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 45570e8b207eSAndrei Emeltchenko char buf[64]; 45580e8b207eSAndrei Emeltchenko 45590e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len, 4560e860d2c9SBen Seri buf, sizeof(buf), &result); 45610e8b207eSAndrei Emeltchenko if (len < 0) { 45625e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 45630e8b207eSAndrei Emeltchenko goto done; 45640e8b207eSAndrei Emeltchenko } 45650e8b207eSAndrei Emeltchenko 4566f351bc72SAndrei Emeltchenko if (!chan->hs_hcon) { 456779de886dSAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, buf, cmd->ident, 456879de886dSAndrei Emeltchenko 0); 45695ce66b59SAndrei Emeltchenko } else { 45705ce66b59SAndrei Emeltchenko if (l2cap_check_efs(chan)) { 45715ce66b59SAndrei Emeltchenko amp_create_logical_link(chan); 457279de886dSAndrei Emeltchenko chan->ident = cmd->ident; 45730e8b207eSAndrei Emeltchenko } 45745ce66b59SAndrei Emeltchenko } 45755ce66b59SAndrei Emeltchenko } 45760e8b207eSAndrei Emeltchenko goto done; 45770e8b207eSAndrei Emeltchenko 457898d2c3e1SBastien Nocera case L2CAP_CONF_UNKNOWN: 45790a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT: 458073ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { 45810a708f8fSGustavo F. Padovan char req[64]; 45820a708f8fSGustavo F. Padovan 45830a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { 45845e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 45850a708f8fSGustavo F. Padovan goto done; 45860a708f8fSGustavo F. Padovan } 45870a708f8fSGustavo F. Padovan 45880a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */ 45890a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS; 4590b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len, 4591e860d2c9SBen Seri req, sizeof(req), &result); 45920a708f8fSGustavo F. Padovan if (len < 0) { 45935e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 45940a708f8fSGustavo F. Padovan goto done; 45950a708f8fSGustavo F. Padovan } 45960a708f8fSGustavo F. Padovan 45970a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 45980a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req); 459973ffa904SGustavo F. Padovan chan->num_conf_req++; 46000a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS) 46010a708f8fSGustavo F. Padovan goto done; 46020a708f8fSGustavo F. Padovan break; 46030a708f8fSGustavo F. Padovan } 460419186c7bSGustavo A. R. Silva fallthrough; 46050a708f8fSGustavo F. Padovan 46060a708f8fSGustavo F. Padovan default: 46076be36555SAndrei Emeltchenko l2cap_chan_set_err(chan, ECONNRESET); 46082e0052e4SAndrei Emeltchenko 4609ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); 46105e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 46110a708f8fSGustavo F. Padovan goto done; 46120a708f8fSGustavo F. Padovan } 46130a708f8fSGustavo F. Padovan 461459e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) 46150a708f8fSGustavo F. Padovan goto done; 46160a708f8fSGustavo F. Padovan 4617c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state); 46180a708f8fSGustavo F. Padovan 4619c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { 462047d1ec61SGustavo F. Padovan set_default_fcs(chan); 46210a708f8fSGustavo F. Padovan 4622105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 4623105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 46243c588192SMat Martineau err = l2cap_ertm_init(chan); 46250a708f8fSGustavo F. Padovan 46263c588192SMat Martineau if (err < 0) 46275e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 46283c588192SMat Martineau else 4629cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 46300a708f8fSGustavo F. Padovan } 46310a708f8fSGustavo F. Padovan 46320a708f8fSGustavo F. Padovan done: 46336be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 4634d0be8347SLuiz Augusto von Dentz l2cap_chan_put(chan); 46353c588192SMat Martineau return err; 46360a708f8fSGustavo F. Padovan } 46370a708f8fSGustavo F. Padovan 46382d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, 4639cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4640cb3b3152SJohan Hedberg u8 *data) 46410a708f8fSGustavo F. Padovan { 46420a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; 46430a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp; 46440a708f8fSGustavo F. Padovan u16 dcid, scid; 464548454079SGustavo F. Padovan struct l2cap_chan *chan; 46460a708f8fSGustavo F. Padovan 4647cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req)) 4648cb3b3152SJohan Hedberg return -EPROTO; 4649cb3b3152SJohan Hedberg 46500a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid); 46510a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 46520a708f8fSGustavo F. Padovan 46530a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); 46540a708f8fSGustavo F. Padovan 46553df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 46563df91ea2SAndrei Emeltchenko 46573df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, dcid); 46583df91ea2SAndrei Emeltchenko if (!chan) { 46593df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4660662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid); 4661662d652dSJohan Hedberg return 0; 46623df91ea2SAndrei Emeltchenko } 46630a708f8fSGustavo F. Padovan 46646c08fc89SManish Mandlik l2cap_chan_hold(chan); 46656be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 46666be36555SAndrei Emeltchenko 4667fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 4668fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 46690a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); 46700a708f8fSGustavo F. Padovan 46715ec1bbe5SGustavo Padovan chan->ops->set_shutdown(chan); 46720a708f8fSGustavo F. Padovan 467348454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET); 46746be36555SAndrei Emeltchenko 467580b98027SGustavo Padovan chan->ops->close(chan); 46766c08fc89SManish Mandlik 46776c08fc89SManish Mandlik l2cap_chan_unlock(chan); 467861d6ef3eSMat Martineau l2cap_chan_put(chan); 46793df91ea2SAndrei Emeltchenko 46803df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 46813df91ea2SAndrei Emeltchenko 46820a708f8fSGustavo F. Padovan return 0; 46830a708f8fSGustavo F. Padovan } 46840a708f8fSGustavo F. Padovan 46852d792818SGustavo Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, 4686cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4687cb3b3152SJohan Hedberg u8 *data) 46880a708f8fSGustavo F. Padovan { 46890a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; 46900a708f8fSGustavo F. Padovan u16 dcid, scid; 469148454079SGustavo F. Padovan struct l2cap_chan *chan; 46920a708f8fSGustavo F. Padovan 4693cb3b3152SJohan Hedberg if (cmd_len != sizeof(*rsp)) 4694cb3b3152SJohan Hedberg return -EPROTO; 4695cb3b3152SJohan Hedberg 46960a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 46970a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 46980a708f8fSGustavo F. Padovan 46990a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); 47000a708f8fSGustavo F. Padovan 47013df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 47023df91ea2SAndrei Emeltchenko 47033df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 47043df91ea2SAndrei Emeltchenko if (!chan) { 47053df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 47060a708f8fSGustavo F. Padovan return 0; 47073df91ea2SAndrei Emeltchenko } 47080a708f8fSGustavo F. Padovan 47096c08fc89SManish Mandlik l2cap_chan_hold(chan); 47106be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 471148454079SGustavo F. Padovan 471228261da8SMatias Karhumaa if (chan->state != BT_DISCONN) { 471328261da8SMatias Karhumaa l2cap_chan_unlock(chan); 47146c08fc89SManish Mandlik l2cap_chan_put(chan); 471528261da8SMatias Karhumaa mutex_unlock(&conn->chan_lock); 471628261da8SMatias Karhumaa return 0; 471728261da8SMatias Karhumaa } 471828261da8SMatias Karhumaa 471948454079SGustavo F. Padovan l2cap_chan_del(chan, 0); 47206be36555SAndrei Emeltchenko 472180b98027SGustavo Padovan chan->ops->close(chan); 47226c08fc89SManish Mandlik 47236c08fc89SManish Mandlik l2cap_chan_unlock(chan); 472461d6ef3eSMat Martineau l2cap_chan_put(chan); 47253df91ea2SAndrei Emeltchenko 47263df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 47273df91ea2SAndrei Emeltchenko 47280a708f8fSGustavo F. Padovan return 0; 47290a708f8fSGustavo F. Padovan } 47300a708f8fSGustavo F. Padovan 47312d792818SGustavo Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, 4732cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4733cb3b3152SJohan Hedberg u8 *data) 47340a708f8fSGustavo F. Padovan { 47350a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data; 47360a708f8fSGustavo F. Padovan u16 type; 47370a708f8fSGustavo F. Padovan 4738cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req)) 4739cb3b3152SJohan Hedberg return -EPROTO; 4740cb3b3152SJohan Hedberg 47410a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type); 47420a708f8fSGustavo F. Padovan 47430a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type); 47440a708f8fSGustavo F. Padovan 47450a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) { 47460a708f8fSGustavo F. Padovan u8 buf[8]; 47470a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask; 47480a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 4749dcf4adbfSJoe Perches rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 4750dcf4adbfSJoe Perches rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 47510a708f8fSGustavo F. Padovan if (!disable_ertm) 47520a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING 47530a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS; 47540bd49fc7SJohan Hedberg if (conn->local_fixed_chan & L2CAP_FC_A2MP) 47556327eb98SAndrei Emeltchenko feat_mask |= L2CAP_FEAT_EXT_FLOW 47566327eb98SAndrei Emeltchenko | L2CAP_FEAT_EXT_WINDOW; 4757a5fd6f30SAndrei Emeltchenko 47580a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data); 47592d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), 47602d792818SGustavo Padovan buf); 47610a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) { 47620a708f8fSGustavo F. Padovan u8 buf[12]; 47630a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 476450a147cdSMat Martineau 4765dcf4adbfSJoe Perches rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 4766dcf4adbfSJoe Perches rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 47670bd49fc7SJohan Hedberg rsp->data[0] = conn->local_fixed_chan; 47680bd49fc7SJohan Hedberg memset(rsp->data + 1, 0, 7); 47692d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), 47702d792818SGustavo Padovan buf); 47710a708f8fSGustavo F. Padovan } else { 47720a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp; 47730a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type); 4774dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP); 47752d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), 47762d792818SGustavo Padovan &rsp); 47770a708f8fSGustavo F. Padovan } 47780a708f8fSGustavo F. Padovan 47790a708f8fSGustavo F. Padovan return 0; 47800a708f8fSGustavo F. Padovan } 47810a708f8fSGustavo F. Padovan 47822d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, 4783cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4784cb3b3152SJohan Hedberg u8 *data) 47850a708f8fSGustavo F. Padovan { 47860a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; 47870a708f8fSGustavo F. Padovan u16 type, result; 47880a708f8fSGustavo F. Padovan 47893f6fa3d4SJaganath Kanakkassery if (cmd_len < sizeof(*rsp)) 4790cb3b3152SJohan Hedberg return -EPROTO; 4791cb3b3152SJohan Hedberg 47920a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type); 47930a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 47940a708f8fSGustavo F. Padovan 47950a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); 47960a708f8fSGustavo F. Padovan 4797e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */ 4798e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident || 4799e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 4800e90165beSAndrei Emeltchenko return 0; 4801e90165beSAndrei Emeltchenko 480217cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 48030a708f8fSGustavo F. Padovan 48040a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) { 48050a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 48060a708f8fSGustavo F. Padovan conn->info_ident = 0; 48070a708f8fSGustavo F. Padovan 48080a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 48090a708f8fSGustavo F. Padovan 48100a708f8fSGustavo F. Padovan return 0; 48110a708f8fSGustavo F. Padovan } 48120a708f8fSGustavo F. Padovan 4813978c93b9SAndrei Emeltchenko switch (type) { 4814978c93b9SAndrei Emeltchenko case L2CAP_IT_FEAT_MASK: 48150a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data); 48160a708f8fSGustavo F. Padovan 48170a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { 48180a708f8fSGustavo F. Padovan struct l2cap_info_req req; 4819dcf4adbfSJoe Perches req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 48200a708f8fSGustavo F. Padovan 48210a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 48220a708f8fSGustavo F. Padovan 48230a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 48240a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 48250a708f8fSGustavo F. Padovan } else { 48260a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 48270a708f8fSGustavo F. Padovan conn->info_ident = 0; 48280a708f8fSGustavo F. Padovan 48290a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 48300a708f8fSGustavo F. Padovan } 4831978c93b9SAndrei Emeltchenko break; 4832978c93b9SAndrei Emeltchenko 4833978c93b9SAndrei Emeltchenko case L2CAP_IT_FIXED_CHAN: 48340bd49fc7SJohan Hedberg conn->remote_fixed_chan = rsp->data[0]; 48350a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 48360a708f8fSGustavo F. Padovan conn->info_ident = 0; 48370a708f8fSGustavo F. Padovan 48380a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 4839978c93b9SAndrei Emeltchenko break; 48400a708f8fSGustavo F. Padovan } 48410a708f8fSGustavo F. Padovan 48420a708f8fSGustavo F. Padovan return 0; 48430a708f8fSGustavo F. Padovan } 48440a708f8fSGustavo F. Padovan 48451700915fSMat Martineau static int l2cap_create_channel_req(struct l2cap_conn *conn, 48462d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, 48472d792818SGustavo Padovan u16 cmd_len, void *data) 4848f94ff6ffSMat Martineau { 4849f94ff6ffSMat Martineau struct l2cap_create_chan_req *req = data; 48506e1df6a6SAndrei Emeltchenko struct l2cap_create_chan_rsp rsp; 48511700915fSMat Martineau struct l2cap_chan *chan; 48526e1df6a6SAndrei Emeltchenko struct hci_dev *hdev; 4853f94ff6ffSMat Martineau u16 psm, scid; 4854f94ff6ffSMat Martineau 4855f94ff6ffSMat Martineau if (cmd_len != sizeof(*req)) 4856f94ff6ffSMat Martineau return -EPROTO; 4857f94ff6ffSMat Martineau 48580bd49fc7SJohan Hedberg if (!(conn->local_fixed_chan & L2CAP_FC_A2MP)) 4859f94ff6ffSMat Martineau return -EINVAL; 4860f94ff6ffSMat Martineau 4861f94ff6ffSMat Martineau psm = le16_to_cpu(req->psm); 4862f94ff6ffSMat Martineau scid = le16_to_cpu(req->scid); 4863f94ff6ffSMat Martineau 4864ad0ac6caSAndrei Emeltchenko BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id); 4865f94ff6ffSMat Martineau 48666e1df6a6SAndrei Emeltchenko /* For controller id 0 make BR/EDR connection */ 48676ed971caSMarcel Holtmann if (req->amp_id == AMP_ID_BREDR) { 48686e1df6a6SAndrei Emeltchenko l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, 48696e1df6a6SAndrei Emeltchenko req->amp_id); 48706e1df6a6SAndrei Emeltchenko return 0; 48716e1df6a6SAndrei Emeltchenko } 48721700915fSMat Martineau 48731700915fSMat Martineau /* Validate AMP controller id */ 48741700915fSMat Martineau hdev = hci_dev_get(req->amp_id); 48756e1df6a6SAndrei Emeltchenko if (!hdev) 48766e1df6a6SAndrei Emeltchenko goto error; 48771700915fSMat Martineau 48786e1df6a6SAndrei Emeltchenko if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) { 48796e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 48806e1df6a6SAndrei Emeltchenko goto error; 48816e1df6a6SAndrei Emeltchenko } 48826e1df6a6SAndrei Emeltchenko 48836e1df6a6SAndrei Emeltchenko chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, 48846e1df6a6SAndrei Emeltchenko req->amp_id); 48856e1df6a6SAndrei Emeltchenko if (chan) { 48866e1df6a6SAndrei Emeltchenko struct amp_mgr *mgr = conn->hcon->amp_mgr; 48876e1df6a6SAndrei Emeltchenko struct hci_conn *hs_hcon; 48886e1df6a6SAndrei Emeltchenko 488998e0f7eaSMarcel Holtmann hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, 489098e0f7eaSMarcel Holtmann &conn->hcon->dst); 48916e1df6a6SAndrei Emeltchenko if (!hs_hcon) { 48926e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 4893662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, 4894662d652dSJohan Hedberg chan->dcid); 4895662d652dSJohan Hedberg return 0; 48966e1df6a6SAndrei Emeltchenko } 48976e1df6a6SAndrei Emeltchenko 48986e1df6a6SAndrei Emeltchenko BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon); 48996e1df6a6SAndrei Emeltchenko 49006e1df6a6SAndrei Emeltchenko mgr->bredr_chan = chan; 49016e1df6a6SAndrei Emeltchenko chan->hs_hcon = hs_hcon; 4902fd45bf4cSAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 49036e1df6a6SAndrei Emeltchenko conn->mtu = hdev->block_mtu; 49046e1df6a6SAndrei Emeltchenko } 49056e1df6a6SAndrei Emeltchenko 49066e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 49076e1df6a6SAndrei Emeltchenko 49086e1df6a6SAndrei Emeltchenko return 0; 49096e1df6a6SAndrei Emeltchenko 49106e1df6a6SAndrei Emeltchenko error: 4911f94ff6ffSMat Martineau rsp.dcid = 0; 4912f94ff6ffSMat Martineau rsp.scid = cpu_to_le16(scid); 4913dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_BAD_AMP); 4914dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 4915f94ff6ffSMat Martineau 4916f94ff6ffSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, 4917f94ff6ffSMat Martineau sizeof(rsp), &rsp); 4918f94ff6ffSMat Martineau 4919dc280801SJohan Hedberg return 0; 4920f94ff6ffSMat Martineau } 4921f94ff6ffSMat Martineau 49228eb200bdSMat Martineau static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id) 49238eb200bdSMat Martineau { 49248eb200bdSMat Martineau struct l2cap_move_chan_req req; 49258eb200bdSMat Martineau u8 ident; 49268eb200bdSMat Martineau 49278eb200bdSMat Martineau BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id); 49288eb200bdSMat Martineau 49298eb200bdSMat Martineau ident = l2cap_get_ident(chan->conn); 49308eb200bdSMat Martineau chan->ident = ident; 49318eb200bdSMat Martineau 49328eb200bdSMat Martineau req.icid = cpu_to_le16(chan->scid); 49338eb200bdSMat Martineau req.dest_amp_id = dest_amp_id; 49348eb200bdSMat Martineau 49358eb200bdSMat Martineau l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req), 49368eb200bdSMat Martineau &req); 49378eb200bdSMat Martineau 49388eb200bdSMat Martineau __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); 49398eb200bdSMat Martineau } 49408eb200bdSMat Martineau 49411500109bSMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result) 49428d5a04a1SMat Martineau { 49438d5a04a1SMat Martineau struct l2cap_move_chan_rsp rsp; 49448d5a04a1SMat Martineau 49451500109bSMat Martineau BT_DBG("chan %p, result 0x%4.4x", chan, result); 49468d5a04a1SMat Martineau 49471500109bSMat Martineau rsp.icid = cpu_to_le16(chan->dcid); 49488d5a04a1SMat Martineau rsp.result = cpu_to_le16(result); 49498d5a04a1SMat Martineau 49501500109bSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP, 49511500109bSMat Martineau sizeof(rsp), &rsp); 49528d5a04a1SMat Martineau } 49538d5a04a1SMat Martineau 49545b155ef9SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result) 49558d5a04a1SMat Martineau { 49568d5a04a1SMat Martineau struct l2cap_move_chan_cfm cfm; 49578d5a04a1SMat Martineau 49585b155ef9SMat Martineau BT_DBG("chan %p, result 0x%4.4x", chan, result); 49598d5a04a1SMat Martineau 49605b155ef9SMat Martineau chan->ident = l2cap_get_ident(chan->conn); 49618d5a04a1SMat Martineau 49625b155ef9SMat Martineau cfm.icid = cpu_to_le16(chan->scid); 49638d5a04a1SMat Martineau cfm.result = cpu_to_le16(result); 49648d5a04a1SMat Martineau 49655b155ef9SMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM, 49665b155ef9SMat Martineau sizeof(cfm), &cfm); 49675b155ef9SMat Martineau 49685b155ef9SMat Martineau __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); 49695b155ef9SMat Martineau } 49705b155ef9SMat Martineau 49715b155ef9SMat Martineau static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid) 49725b155ef9SMat Martineau { 49735b155ef9SMat Martineau struct l2cap_move_chan_cfm cfm; 49745b155ef9SMat Martineau 49755b155ef9SMat Martineau BT_DBG("conn %p, icid 0x%4.4x", conn, icid); 49765b155ef9SMat Martineau 49775b155ef9SMat Martineau cfm.icid = cpu_to_le16(icid); 4978dcf4adbfSJoe Perches cfm.result = cpu_to_le16(L2CAP_MC_UNCONFIRMED); 49795b155ef9SMat Martineau 49805b155ef9SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM, 49815b155ef9SMat Martineau sizeof(cfm), &cfm); 49828d5a04a1SMat Martineau } 49838d5a04a1SMat Martineau 49848d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, 49858d5a04a1SMat Martineau u16 icid) 49868d5a04a1SMat Martineau { 49878d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp rsp; 49888d5a04a1SMat Martineau 4989ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 49908d5a04a1SMat Martineau 49918d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 49928d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp); 49938d5a04a1SMat Martineau } 49948d5a04a1SMat Martineau 49955f3847a4SMat Martineau static void __release_logical_link(struct l2cap_chan *chan) 49965f3847a4SMat Martineau { 49975f3847a4SMat Martineau chan->hs_hchan = NULL; 49985f3847a4SMat Martineau chan->hs_hcon = NULL; 49995f3847a4SMat Martineau 50005f3847a4SMat Martineau /* Placeholder - release the logical link */ 50015f3847a4SMat Martineau } 50025f3847a4SMat Martineau 50031500109bSMat Martineau static void l2cap_logical_fail(struct l2cap_chan *chan) 50041500109bSMat Martineau { 50051500109bSMat Martineau /* Logical link setup failed */ 50061500109bSMat Martineau if (chan->state != BT_CONNECTED) { 50071500109bSMat Martineau /* Create channel failure, disconnect */ 50085e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 50091500109bSMat Martineau return; 50101500109bSMat Martineau } 50111500109bSMat Martineau 50121500109bSMat Martineau switch (chan->move_role) { 50131500109bSMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 50141500109bSMat Martineau l2cap_move_done(chan); 50151500109bSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP); 50161500109bSMat Martineau break; 50171500109bSMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 50181500109bSMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP || 50191500109bSMat Martineau chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) { 50201500109bSMat Martineau /* Remote has only sent pending or 50211500109bSMat Martineau * success responses, clean up 50221500109bSMat Martineau */ 50231500109bSMat Martineau l2cap_move_done(chan); 50241500109bSMat Martineau } 50251500109bSMat Martineau 50261500109bSMat Martineau /* Other amp move states imply that the move 50271500109bSMat Martineau * has already aborted 50281500109bSMat Martineau */ 50291500109bSMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 50301500109bSMat Martineau break; 50311500109bSMat Martineau } 50321500109bSMat Martineau } 50331500109bSMat Martineau 50341500109bSMat Martineau static void l2cap_logical_finish_create(struct l2cap_chan *chan, 50351500109bSMat Martineau struct hci_chan *hchan) 50361500109bSMat Martineau { 50371500109bSMat Martineau struct l2cap_conf_rsp rsp; 50381500109bSMat Martineau 5039336178a3SAndrei Emeltchenko chan->hs_hchan = hchan; 50401500109bSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 50411500109bSMat Martineau 504235ba9561SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0); 50431500109bSMat Martineau 50441500109bSMat Martineau if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 5045fe79c6feSAndrei Emeltchenko int err; 50461500109bSMat Martineau 50471500109bSMat Martineau set_default_fcs(chan); 50481500109bSMat Martineau 50491500109bSMat Martineau err = l2cap_ertm_init(chan); 50501500109bSMat Martineau if (err < 0) 50515e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 50521500109bSMat Martineau else 50531500109bSMat Martineau l2cap_chan_ready(chan); 50541500109bSMat Martineau } 50551500109bSMat Martineau } 50561500109bSMat Martineau 50571500109bSMat Martineau static void l2cap_logical_finish_move(struct l2cap_chan *chan, 50581500109bSMat Martineau struct hci_chan *hchan) 50591500109bSMat Martineau { 50601500109bSMat Martineau chan->hs_hcon = hchan->conn; 50611500109bSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 50621500109bSMat Martineau 50631500109bSMat Martineau BT_DBG("move_state %d", chan->move_state); 50641500109bSMat Martineau 50651500109bSMat Martineau switch (chan->move_state) { 50661500109bSMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_COMP: 50671500109bSMat Martineau /* Move confirm will be sent after a success 50681500109bSMat Martineau * response is received 50691500109bSMat Martineau */ 50701500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 50711500109bSMat Martineau break; 50721500109bSMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_CFM: 50731500109bSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 50741500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 50751500109bSMat Martineau } else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { 50761500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; 50771500109bSMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 50781500109bSMat Martineau } else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { 50791500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 50801500109bSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); 50811500109bSMat Martineau } 50821500109bSMat Martineau break; 50831500109bSMat Martineau default: 50841500109bSMat Martineau /* Move was not in expected state, free the channel */ 50851500109bSMat Martineau __release_logical_link(chan); 50861500109bSMat Martineau 50871500109bSMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 50881500109bSMat Martineau } 50891500109bSMat Martineau } 50901500109bSMat Martineau 50911500109bSMat Martineau /* Call with chan locked */ 509227695fb4SAndrei Emeltchenko void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan, 50935b155ef9SMat Martineau u8 status) 50945b155ef9SMat Martineau { 50951500109bSMat Martineau BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status); 50961500109bSMat Martineau 50971500109bSMat Martineau if (status) { 50981500109bSMat Martineau l2cap_logical_fail(chan); 50991500109bSMat Martineau __release_logical_link(chan); 51005b155ef9SMat Martineau return; 51015b155ef9SMat Martineau } 51025b155ef9SMat Martineau 51031500109bSMat Martineau if (chan->state != BT_CONNECTED) { 51041500109bSMat Martineau /* Ignore logical link if channel is on BR/EDR */ 51056ed971caSMarcel Holtmann if (chan->local_amp_id != AMP_ID_BREDR) 51061500109bSMat Martineau l2cap_logical_finish_create(chan, hchan); 51071500109bSMat Martineau } else { 51081500109bSMat Martineau l2cap_logical_finish_move(chan, hchan); 51091500109bSMat Martineau } 51101500109bSMat Martineau } 51111500109bSMat Martineau 51123f7a56c4SMat Martineau void l2cap_move_start(struct l2cap_chan *chan) 51133f7a56c4SMat Martineau { 51143f7a56c4SMat Martineau BT_DBG("chan %p", chan); 51153f7a56c4SMat Martineau 51166ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR) { 51173f7a56c4SMat Martineau if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED) 51183f7a56c4SMat Martineau return; 51193f7a56c4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; 51203f7a56c4SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_PREPARE; 51213f7a56c4SMat Martineau /* Placeholder - start physical link setup */ 51223f7a56c4SMat Martineau } else { 51233f7a56c4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; 51243f7a56c4SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 51253f7a56c4SMat Martineau chan->move_id = 0; 51263f7a56c4SMat Martineau l2cap_move_setup(chan); 51273f7a56c4SMat Martineau l2cap_send_move_chan_req(chan, 0); 51283f7a56c4SMat Martineau } 51293f7a56c4SMat Martineau } 51303f7a56c4SMat Martineau 51318eb200bdSMat Martineau static void l2cap_do_create(struct l2cap_chan *chan, int result, 51328eb200bdSMat Martineau u8 local_amp_id, u8 remote_amp_id) 51338eb200bdSMat Martineau { 513462748ca1SAndrei Emeltchenko BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state), 513562748ca1SAndrei Emeltchenko local_amp_id, remote_amp_id); 513662748ca1SAndrei Emeltchenko 513712d6cc60SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 513812d6cc60SAndrei Emeltchenko 513962748ca1SAndrei Emeltchenko /* Outgoing channel on AMP */ 514062748ca1SAndrei Emeltchenko if (chan->state == BT_CONNECT) { 514162748ca1SAndrei Emeltchenko if (result == L2CAP_CR_SUCCESS) { 514262748ca1SAndrei Emeltchenko chan->local_amp_id = local_amp_id; 514362748ca1SAndrei Emeltchenko l2cap_send_create_chan_req(chan, remote_amp_id); 514462748ca1SAndrei Emeltchenko } else { 514562748ca1SAndrei Emeltchenko /* Revert to BR/EDR connect */ 514662748ca1SAndrei Emeltchenko l2cap_send_conn_req(chan); 514762748ca1SAndrei Emeltchenko } 514862748ca1SAndrei Emeltchenko 514962748ca1SAndrei Emeltchenko return; 515062748ca1SAndrei Emeltchenko } 515162748ca1SAndrei Emeltchenko 515262748ca1SAndrei Emeltchenko /* Incoming channel on AMP */ 515362748ca1SAndrei Emeltchenko if (__l2cap_no_conn_pending(chan)) { 51548eb200bdSMat Martineau struct l2cap_conn_rsp rsp; 51558eb200bdSMat Martineau char buf[128]; 51568eb200bdSMat Martineau rsp.scid = cpu_to_le16(chan->dcid); 51578eb200bdSMat Martineau rsp.dcid = cpu_to_le16(chan->scid); 51588eb200bdSMat Martineau 51598eb200bdSMat Martineau if (result == L2CAP_CR_SUCCESS) { 51608eb200bdSMat Martineau /* Send successful response */ 5161dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 5162dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 51638eb200bdSMat Martineau } else { 51648eb200bdSMat Martineau /* Send negative response */ 5165dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_NO_MEM); 5166dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 51678eb200bdSMat Martineau } 51688eb200bdSMat Martineau 51698eb200bdSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP, 51708eb200bdSMat Martineau sizeof(rsp), &rsp); 51718eb200bdSMat Martineau 51728eb200bdSMat Martineau if (result == L2CAP_CR_SUCCESS) { 5173f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 51748eb200bdSMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 51758eb200bdSMat Martineau l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn), 51768eb200bdSMat Martineau L2CAP_CONF_REQ, 5177e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); 51788eb200bdSMat Martineau chan->num_conf_req++; 51798eb200bdSMat Martineau } 51808eb200bdSMat Martineau } 51818eb200bdSMat Martineau } 51828eb200bdSMat Martineau 51838eb200bdSMat Martineau static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id, 51848eb200bdSMat Martineau u8 remote_amp_id) 51858eb200bdSMat Martineau { 51868eb200bdSMat Martineau l2cap_move_setup(chan); 51878eb200bdSMat Martineau chan->move_id = local_amp_id; 51888eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP; 51898eb200bdSMat Martineau 51908eb200bdSMat Martineau l2cap_send_move_chan_req(chan, remote_amp_id); 51918eb200bdSMat Martineau } 51928eb200bdSMat Martineau 51938eb200bdSMat Martineau static void l2cap_do_move_respond(struct l2cap_chan *chan, int result) 51948eb200bdSMat Martineau { 51958eb200bdSMat Martineau struct hci_chan *hchan = NULL; 51968eb200bdSMat Martineau 51978eb200bdSMat Martineau /* Placeholder - get hci_chan for logical link */ 51988eb200bdSMat Martineau 51998eb200bdSMat Martineau if (hchan) { 52008eb200bdSMat Martineau if (hchan->state == BT_CONNECTED) { 52018eb200bdSMat Martineau /* Logical link is ready to go */ 52028eb200bdSMat Martineau chan->hs_hcon = hchan->conn; 52038eb200bdSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 52048eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 52058eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); 52068eb200bdSMat Martineau 52078eb200bdSMat Martineau l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); 52088eb200bdSMat Martineau } else { 52098eb200bdSMat Martineau /* Wait for logical link to be ready */ 52108eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 52118eb200bdSMat Martineau } 52128eb200bdSMat Martineau } else { 52138eb200bdSMat Martineau /* Logical link not available */ 52148eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED); 52158eb200bdSMat Martineau } 52168eb200bdSMat Martineau } 52178eb200bdSMat Martineau 52188eb200bdSMat Martineau static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result) 52198eb200bdSMat Martineau { 52208eb200bdSMat Martineau if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { 52218eb200bdSMat Martineau u8 rsp_result; 52228eb200bdSMat Martineau if (result == -EINVAL) 52238eb200bdSMat Martineau rsp_result = L2CAP_MR_BAD_ID; 52248eb200bdSMat Martineau else 52258eb200bdSMat Martineau rsp_result = L2CAP_MR_NOT_ALLOWED; 52268eb200bdSMat Martineau 52278eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, rsp_result); 52288eb200bdSMat Martineau } 52298eb200bdSMat Martineau 52308eb200bdSMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 52318eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 52328eb200bdSMat Martineau 52338eb200bdSMat Martineau /* Restart data transmission */ 52348eb200bdSMat Martineau l2cap_ertm_send(chan); 52358eb200bdSMat Martineau } 52368eb200bdSMat Martineau 5237a514b17fSAndrei Emeltchenko /* Invoke with locked chan */ 5238a514b17fSAndrei Emeltchenko void __l2cap_physical_cfm(struct l2cap_chan *chan, int result) 52398eb200bdSMat Martineau { 5240770bfefaSAndrei Emeltchenko u8 local_amp_id = chan->local_amp_id; 5241fffadc08SAndrei Emeltchenko u8 remote_amp_id = chan->remote_amp_id; 5242770bfefaSAndrei Emeltchenko 52438eb200bdSMat Martineau BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d", 52448eb200bdSMat Martineau chan, result, local_amp_id, remote_amp_id); 52458eb200bdSMat Martineau 5246df66499aSDan Carpenter if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) 52478eb200bdSMat Martineau return; 52488eb200bdSMat Martineau 52498eb200bdSMat Martineau if (chan->state != BT_CONNECTED) { 52508eb200bdSMat Martineau l2cap_do_create(chan, result, local_amp_id, remote_amp_id); 52518eb200bdSMat Martineau } else if (result != L2CAP_MR_SUCCESS) { 52528eb200bdSMat Martineau l2cap_do_move_cancel(chan, result); 52538eb200bdSMat Martineau } else { 52548eb200bdSMat Martineau switch (chan->move_role) { 52558eb200bdSMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 52568eb200bdSMat Martineau l2cap_do_move_initiate(chan, local_amp_id, 52578eb200bdSMat Martineau remote_amp_id); 52588eb200bdSMat Martineau break; 52598eb200bdSMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 52608eb200bdSMat Martineau l2cap_do_move_respond(chan, result); 52618eb200bdSMat Martineau break; 52628eb200bdSMat Martineau default: 52638eb200bdSMat Martineau l2cap_do_move_cancel(chan, result); 52648eb200bdSMat Martineau break; 52658eb200bdSMat Martineau } 52668eb200bdSMat Martineau } 52678eb200bdSMat Martineau } 52688eb200bdSMat Martineau 52698d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn, 5270ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5271ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 52728d5a04a1SMat Martineau { 52738d5a04a1SMat Martineau struct l2cap_move_chan_req *req = data; 52741500109bSMat Martineau struct l2cap_move_chan_rsp rsp; 527502b0fbb9SMat Martineau struct l2cap_chan *chan; 52768d5a04a1SMat Martineau u16 icid = 0; 52778d5a04a1SMat Martineau u16 result = L2CAP_MR_NOT_ALLOWED; 52788d5a04a1SMat Martineau 52798d5a04a1SMat Martineau if (cmd_len != sizeof(*req)) 52808d5a04a1SMat Martineau return -EPROTO; 52818d5a04a1SMat Martineau 52828d5a04a1SMat Martineau icid = le16_to_cpu(req->icid); 52838d5a04a1SMat Martineau 5284ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id); 52858d5a04a1SMat Martineau 52860bd49fc7SJohan Hedberg if (!(conn->local_fixed_chan & L2CAP_FC_A2MP)) 52878d5a04a1SMat Martineau return -EINVAL; 52888d5a04a1SMat Martineau 528902b0fbb9SMat Martineau chan = l2cap_get_chan_by_dcid(conn, icid); 529002b0fbb9SMat Martineau if (!chan) { 52911500109bSMat Martineau rsp.icid = cpu_to_le16(icid); 5292dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_MR_NOT_ALLOWED); 52931500109bSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP, 52941500109bSMat Martineau sizeof(rsp), &rsp); 529502b0fbb9SMat Martineau return 0; 529602b0fbb9SMat Martineau } 529702b0fbb9SMat Martineau 52981500109bSMat Martineau chan->ident = cmd->ident; 52991500109bSMat Martineau 530002b0fbb9SMat Martineau if (chan->scid < L2CAP_CID_DYN_START || 530102b0fbb9SMat Martineau chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY || 530202b0fbb9SMat Martineau (chan->mode != L2CAP_MODE_ERTM && 530302b0fbb9SMat Martineau chan->mode != L2CAP_MODE_STREAMING)) { 530402b0fbb9SMat Martineau result = L2CAP_MR_NOT_ALLOWED; 530502b0fbb9SMat Martineau goto send_move_response; 530602b0fbb9SMat Martineau } 530702b0fbb9SMat Martineau 530802b0fbb9SMat Martineau if (chan->local_amp_id == req->dest_amp_id) { 530902b0fbb9SMat Martineau result = L2CAP_MR_SAME_ID; 531002b0fbb9SMat Martineau goto send_move_response; 531102b0fbb9SMat Martineau } 531202b0fbb9SMat Martineau 53136ed971caSMarcel Holtmann if (req->dest_amp_id != AMP_ID_BREDR) { 531402b0fbb9SMat Martineau struct hci_dev *hdev; 531502b0fbb9SMat Martineau hdev = hci_dev_get(req->dest_amp_id); 531602b0fbb9SMat Martineau if (!hdev || hdev->dev_type != HCI_AMP || 531702b0fbb9SMat Martineau !test_bit(HCI_UP, &hdev->flags)) { 531802b0fbb9SMat Martineau if (hdev) 531902b0fbb9SMat Martineau hci_dev_put(hdev); 532002b0fbb9SMat Martineau 532102b0fbb9SMat Martineau result = L2CAP_MR_BAD_ID; 532202b0fbb9SMat Martineau goto send_move_response; 532302b0fbb9SMat Martineau } 532402b0fbb9SMat Martineau hci_dev_put(hdev); 532502b0fbb9SMat Martineau } 532602b0fbb9SMat Martineau 532702b0fbb9SMat Martineau /* Detect a move collision. Only send a collision response 532802b0fbb9SMat Martineau * if this side has "lost", otherwise proceed with the move. 532902b0fbb9SMat Martineau * The winner has the larger bd_addr. 533002b0fbb9SMat Martineau */ 533102b0fbb9SMat Martineau if ((__chan_is_moving(chan) || 533202b0fbb9SMat Martineau chan->move_role != L2CAP_MOVE_ROLE_NONE) && 53336f59b904SMarcel Holtmann bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) { 533402b0fbb9SMat Martineau result = L2CAP_MR_COLLISION; 533502b0fbb9SMat Martineau goto send_move_response; 533602b0fbb9SMat Martineau } 533702b0fbb9SMat Martineau 533802b0fbb9SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; 533902b0fbb9SMat Martineau l2cap_move_setup(chan); 534002b0fbb9SMat Martineau chan->move_id = req->dest_amp_id; 534102b0fbb9SMat Martineau 53426ed971caSMarcel Holtmann if (req->dest_amp_id == AMP_ID_BREDR) { 534302b0fbb9SMat Martineau /* Moving to BR/EDR */ 534402b0fbb9SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 534502b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 534602b0fbb9SMat Martineau result = L2CAP_MR_PEND; 534702b0fbb9SMat Martineau } else { 534802b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 534902b0fbb9SMat Martineau result = L2CAP_MR_SUCCESS; 535002b0fbb9SMat Martineau } 535102b0fbb9SMat Martineau } else { 535202b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_PREPARE; 535302b0fbb9SMat Martineau /* Placeholder - uncomment when amp functions are available */ 535402b0fbb9SMat Martineau /*amp_accept_physical(chan, req->dest_amp_id);*/ 535502b0fbb9SMat Martineau result = L2CAP_MR_PEND; 535602b0fbb9SMat Martineau } 535702b0fbb9SMat Martineau 535802b0fbb9SMat Martineau send_move_response: 53591500109bSMat Martineau l2cap_send_move_chan_rsp(chan, result); 53608d5a04a1SMat Martineau 536102b0fbb9SMat Martineau l2cap_chan_unlock(chan); 5362d0be8347SLuiz Augusto von Dentz l2cap_chan_put(chan); 536302b0fbb9SMat Martineau 53648d5a04a1SMat Martineau return 0; 53658d5a04a1SMat Martineau } 53668d5a04a1SMat Martineau 53675b155ef9SMat Martineau static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result) 53685b155ef9SMat Martineau { 53695b155ef9SMat Martineau struct l2cap_chan *chan; 53705b155ef9SMat Martineau struct hci_chan *hchan = NULL; 53715b155ef9SMat Martineau 53725b155ef9SMat Martineau chan = l2cap_get_chan_by_scid(conn, icid); 53735b155ef9SMat Martineau if (!chan) { 53745b155ef9SMat Martineau l2cap_send_move_chan_cfm_icid(conn, icid); 53755b155ef9SMat Martineau return; 53765b155ef9SMat Martineau } 53775b155ef9SMat Martineau 53785b155ef9SMat Martineau __clear_chan_timer(chan); 53795b155ef9SMat Martineau if (result == L2CAP_MR_PEND) 53805b155ef9SMat Martineau __set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT); 53815b155ef9SMat Martineau 53825b155ef9SMat Martineau switch (chan->move_state) { 53835b155ef9SMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_COMP: 53845b155ef9SMat Martineau /* Move confirm will be sent when logical link 53855b155ef9SMat Martineau * is complete. 53865b155ef9SMat Martineau */ 53875b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 53885b155ef9SMat Martineau break; 53895b155ef9SMat Martineau case L2CAP_MOVE_WAIT_RSP_SUCCESS: 53905b155ef9SMat Martineau if (result == L2CAP_MR_PEND) { 53915b155ef9SMat Martineau break; 53925b155ef9SMat Martineau } else if (test_bit(CONN_LOCAL_BUSY, 53935b155ef9SMat Martineau &chan->conn_state)) { 53945b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 53955b155ef9SMat Martineau } else { 53965b155ef9SMat Martineau /* Logical link is up or moving to BR/EDR, 53975b155ef9SMat Martineau * proceed with move 53985b155ef9SMat Martineau */ 53995b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; 54005b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 54015b155ef9SMat Martineau } 54025b155ef9SMat Martineau break; 54035b155ef9SMat Martineau case L2CAP_MOVE_WAIT_RSP: 54045b155ef9SMat Martineau /* Moving to AMP */ 54055b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS) { 54065b155ef9SMat Martineau /* Remote is ready, send confirm immediately 54075b155ef9SMat Martineau * after logical link is ready 54085b155ef9SMat Martineau */ 54095b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 54105b155ef9SMat Martineau } else { 54115b155ef9SMat Martineau /* Both logical link and move success 54125b155ef9SMat Martineau * are required to confirm 54135b155ef9SMat Martineau */ 54145b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP; 54155b155ef9SMat Martineau } 54165b155ef9SMat Martineau 54175b155ef9SMat Martineau /* Placeholder - get hci_chan for logical link */ 54185b155ef9SMat Martineau if (!hchan) { 54195b155ef9SMat Martineau /* Logical link not available */ 54205b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 54215b155ef9SMat Martineau break; 54225b155ef9SMat Martineau } 54235b155ef9SMat Martineau 54245b155ef9SMat Martineau /* If the logical link is not yet connected, do not 54255b155ef9SMat Martineau * send confirmation. 54265b155ef9SMat Martineau */ 54275b155ef9SMat Martineau if (hchan->state != BT_CONNECTED) 54285b155ef9SMat Martineau break; 54295b155ef9SMat Martineau 54305b155ef9SMat Martineau /* Logical link is already ready to go */ 54315b155ef9SMat Martineau 54325b155ef9SMat Martineau chan->hs_hcon = hchan->conn; 54335b155ef9SMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 54345b155ef9SMat Martineau 54355b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS) { 54365b155ef9SMat Martineau /* Can confirm now */ 54375b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 54385b155ef9SMat Martineau } else { 54395b155ef9SMat Martineau /* Now only need move success 54405b155ef9SMat Martineau * to confirm 54415b155ef9SMat Martineau */ 54425b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 54435b155ef9SMat Martineau } 54445b155ef9SMat Martineau 54455b155ef9SMat Martineau l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); 54465b155ef9SMat Martineau break; 54475b155ef9SMat Martineau default: 54485b155ef9SMat Martineau /* Any other amp move state means the move failed. */ 54495b155ef9SMat Martineau chan->move_id = chan->local_amp_id; 54505b155ef9SMat Martineau l2cap_move_done(chan); 54515b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 54525b155ef9SMat Martineau } 54535b155ef9SMat Martineau 54545b155ef9SMat Martineau l2cap_chan_unlock(chan); 5455d0be8347SLuiz Augusto von Dentz l2cap_chan_put(chan); 54565b155ef9SMat Martineau } 54575b155ef9SMat Martineau 54585b155ef9SMat Martineau static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid, 54595b155ef9SMat Martineau u16 result) 54605b155ef9SMat Martineau { 54615b155ef9SMat Martineau struct l2cap_chan *chan; 54625b155ef9SMat Martineau 54635b155ef9SMat Martineau chan = l2cap_get_chan_by_ident(conn, ident); 54645b155ef9SMat Martineau if (!chan) { 54655b155ef9SMat Martineau /* Could not locate channel, icid is best guess */ 54665b155ef9SMat Martineau l2cap_send_move_chan_cfm_icid(conn, icid); 54675b155ef9SMat Martineau return; 54685b155ef9SMat Martineau } 54695b155ef9SMat Martineau 54705b155ef9SMat Martineau __clear_chan_timer(chan); 54715b155ef9SMat Martineau 54725b155ef9SMat Martineau if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { 54735b155ef9SMat Martineau if (result == L2CAP_MR_COLLISION) { 54745b155ef9SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; 54755b155ef9SMat Martineau } else { 54765b155ef9SMat Martineau /* Cleanup - cancel move */ 54775b155ef9SMat Martineau chan->move_id = chan->local_amp_id; 54785b155ef9SMat Martineau l2cap_move_done(chan); 54795b155ef9SMat Martineau } 54805b155ef9SMat Martineau } 54815b155ef9SMat Martineau 54825b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 54835b155ef9SMat Martineau 54845b155ef9SMat Martineau l2cap_chan_unlock(chan); 5485d0be8347SLuiz Augusto von Dentz l2cap_chan_put(chan); 54865b155ef9SMat Martineau } 54875b155ef9SMat Martineau 54885b155ef9SMat Martineau static int l2cap_move_channel_rsp(struct l2cap_conn *conn, 5489ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5490ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 54918d5a04a1SMat Martineau { 54928d5a04a1SMat Martineau struct l2cap_move_chan_rsp *rsp = data; 54938d5a04a1SMat Martineau u16 icid, result; 54948d5a04a1SMat Martineau 54958d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 54968d5a04a1SMat Martineau return -EPROTO; 54978d5a04a1SMat Martineau 54988d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 54998d5a04a1SMat Martineau result = le16_to_cpu(rsp->result); 55008d5a04a1SMat Martineau 5501ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 55028d5a04a1SMat Martineau 55035b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND) 55045b155ef9SMat Martineau l2cap_move_continue(conn, icid, result); 55055b155ef9SMat Martineau else 55065b155ef9SMat Martineau l2cap_move_fail(conn, cmd->ident, icid, result); 55078d5a04a1SMat Martineau 55088d5a04a1SMat Martineau return 0; 55098d5a04a1SMat Martineau } 55108d5a04a1SMat Martineau 55115f3847a4SMat Martineau static int l2cap_move_channel_confirm(struct l2cap_conn *conn, 5512ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5513ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 55148d5a04a1SMat Martineau { 55158d5a04a1SMat Martineau struct l2cap_move_chan_cfm *cfm = data; 55165f3847a4SMat Martineau struct l2cap_chan *chan; 55178d5a04a1SMat Martineau u16 icid, result; 55188d5a04a1SMat Martineau 55198d5a04a1SMat Martineau if (cmd_len != sizeof(*cfm)) 55208d5a04a1SMat Martineau return -EPROTO; 55218d5a04a1SMat Martineau 55228d5a04a1SMat Martineau icid = le16_to_cpu(cfm->icid); 55238d5a04a1SMat Martineau result = le16_to_cpu(cfm->result); 55248d5a04a1SMat Martineau 5525ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 55268d5a04a1SMat Martineau 55275f3847a4SMat Martineau chan = l2cap_get_chan_by_dcid(conn, icid); 55285f3847a4SMat Martineau if (!chan) { 55295f3847a4SMat Martineau /* Spec requires a response even if the icid was not found */ 55308d5a04a1SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 55315f3847a4SMat Martineau return 0; 55325f3847a4SMat Martineau } 55335f3847a4SMat Martineau 55345f3847a4SMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) { 55355f3847a4SMat Martineau if (result == L2CAP_MC_CONFIRMED) { 55365f3847a4SMat Martineau chan->local_amp_id = chan->move_id; 55376ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR) 55385f3847a4SMat Martineau __release_logical_link(chan); 55395f3847a4SMat Martineau } else { 55405f3847a4SMat Martineau chan->move_id = chan->local_amp_id; 55415f3847a4SMat Martineau } 55425f3847a4SMat Martineau 55435f3847a4SMat Martineau l2cap_move_done(chan); 55445f3847a4SMat Martineau } 55455f3847a4SMat Martineau 55465f3847a4SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 55475f3847a4SMat Martineau 55485f3847a4SMat Martineau l2cap_chan_unlock(chan); 5549d0be8347SLuiz Augusto von Dentz l2cap_chan_put(chan); 55508d5a04a1SMat Martineau 55518d5a04a1SMat Martineau return 0; 55528d5a04a1SMat Martineau } 55538d5a04a1SMat Martineau 55548d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, 5555ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5556ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 55578d5a04a1SMat Martineau { 55588d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp *rsp = data; 55593fd71a0aSMat Martineau struct l2cap_chan *chan; 55608d5a04a1SMat Martineau u16 icid; 55618d5a04a1SMat Martineau 55628d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 55638d5a04a1SMat Martineau return -EPROTO; 55648d5a04a1SMat Martineau 55658d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 55668d5a04a1SMat Martineau 5567ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 55688d5a04a1SMat Martineau 55693fd71a0aSMat Martineau chan = l2cap_get_chan_by_scid(conn, icid); 55703fd71a0aSMat Martineau if (!chan) 55713fd71a0aSMat Martineau return 0; 55723fd71a0aSMat Martineau 55733fd71a0aSMat Martineau __clear_chan_timer(chan); 55743fd71a0aSMat Martineau 55753fd71a0aSMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) { 55763fd71a0aSMat Martineau chan->local_amp_id = chan->move_id; 55773fd71a0aSMat Martineau 55786ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan) 55793fd71a0aSMat Martineau __release_logical_link(chan); 55803fd71a0aSMat Martineau 55813fd71a0aSMat Martineau l2cap_move_done(chan); 55823fd71a0aSMat Martineau } 55833fd71a0aSMat Martineau 55843fd71a0aSMat Martineau l2cap_chan_unlock(chan); 5585d0be8347SLuiz Augusto von Dentz l2cap_chan_put(chan); 55863fd71a0aSMat Martineau 55878d5a04a1SMat Martineau return 0; 55888d5a04a1SMat Martineau } 55898d5a04a1SMat Martineau 5590de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, 55912d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, 5592203e639eSJohan Hedberg u16 cmd_len, u8 *data) 5593de73115aSClaudio Takahasi { 5594de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon; 5595de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req; 5596de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp; 5597203e639eSJohan Hedberg u16 min, max, latency, to_multiplier; 55982ce603ebSClaudio Takahasi int err; 5599de73115aSClaudio Takahasi 560040bef302SJohan Hedberg if (hcon->role != HCI_ROLE_MASTER) 5601de73115aSClaudio Takahasi return -EINVAL; 5602de73115aSClaudio Takahasi 5603de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) 5604de73115aSClaudio Takahasi return -EPROTO; 5605de73115aSClaudio Takahasi 5606de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data; 5607de73115aSClaudio Takahasi min = __le16_to_cpu(req->min); 5608de73115aSClaudio Takahasi max = __le16_to_cpu(req->max); 5609de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency); 5610de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier); 5611de73115aSClaudio Takahasi 5612de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", 5613de73115aSClaudio Takahasi min, max, latency, to_multiplier); 5614de73115aSClaudio Takahasi 5615de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp)); 56162ce603ebSClaudio Takahasi 5617d4905f24SAndre Guedes err = hci_check_conn_params(min, max, latency, to_multiplier); 56182ce603ebSClaudio Takahasi if (err) 5619dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); 5620de73115aSClaudio Takahasi else 5621dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); 5622de73115aSClaudio Takahasi 5623de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, 5624de73115aSClaudio Takahasi sizeof(rsp), &rsp); 5625de73115aSClaudio Takahasi 5626ffb5a827SAndre Guedes if (!err) { 5627f4869e2aSJohan Hedberg u8 store_hint; 5628ffb5a827SAndre Guedes 5629f4869e2aSJohan Hedberg store_hint = hci_le_conn_update(hcon, min, max, latency, 5630f4869e2aSJohan Hedberg to_multiplier); 5631f4869e2aSJohan Hedberg mgmt_new_conn_param(hcon->hdev, &hcon->dst, hcon->dst_type, 5632f4869e2aSJohan Hedberg store_hint, min, max, latency, 5633f4869e2aSJohan Hedberg to_multiplier); 5634f4869e2aSJohan Hedberg 5635ffb5a827SAndre Guedes } 56362ce603ebSClaudio Takahasi 5637de73115aSClaudio Takahasi return 0; 5638de73115aSClaudio Takahasi } 5639de73115aSClaudio Takahasi 5640f1496deeSJohan Hedberg static int l2cap_le_connect_rsp(struct l2cap_conn *conn, 5641f1496deeSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5642f1496deeSJohan Hedberg u8 *data) 5643f1496deeSJohan Hedberg { 5644f1496deeSJohan Hedberg struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data; 56453e64b7bdSJohan Hedberg struct hci_conn *hcon = conn->hcon; 5646f1496deeSJohan Hedberg u16 dcid, mtu, mps, credits, result; 5647f1496deeSJohan Hedberg struct l2cap_chan *chan; 56483e64b7bdSJohan Hedberg int err, sec_level; 5649f1496deeSJohan Hedberg 5650f1496deeSJohan Hedberg if (cmd_len < sizeof(*rsp)) 5651f1496deeSJohan Hedberg return -EPROTO; 5652f1496deeSJohan Hedberg 5653f1496deeSJohan Hedberg dcid = __le16_to_cpu(rsp->dcid); 5654f1496deeSJohan Hedberg mtu = __le16_to_cpu(rsp->mtu); 5655f1496deeSJohan Hedberg mps = __le16_to_cpu(rsp->mps); 5656f1496deeSJohan Hedberg credits = __le16_to_cpu(rsp->credits); 5657f1496deeSJohan Hedberg result = __le16_to_cpu(rsp->result); 5658f1496deeSJohan Hedberg 5659571f7390SMallikarjun Phulari if (result == L2CAP_CR_LE_SUCCESS && (mtu < 23 || mps < 23 || 566040624183SJohan Hedberg dcid < L2CAP_CID_DYN_START || 566140624183SJohan Hedberg dcid > L2CAP_CID_LE_DYN_END)) 5662f1496deeSJohan Hedberg return -EPROTO; 5663f1496deeSJohan Hedberg 5664f1496deeSJohan Hedberg BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x", 5665f1496deeSJohan Hedberg dcid, mtu, mps, credits, result); 5666f1496deeSJohan Hedberg 5667f1496deeSJohan Hedberg mutex_lock(&conn->chan_lock); 5668f1496deeSJohan Hedberg 5669f1496deeSJohan Hedberg chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 5670f1496deeSJohan Hedberg if (!chan) { 5671f1496deeSJohan Hedberg err = -EBADSLT; 5672f1496deeSJohan Hedberg goto unlock; 5673f1496deeSJohan Hedberg } 5674f1496deeSJohan Hedberg 5675f1496deeSJohan Hedberg err = 0; 5676f1496deeSJohan Hedberg 5677f1496deeSJohan Hedberg l2cap_chan_lock(chan); 5678f1496deeSJohan Hedberg 5679f1496deeSJohan Hedberg switch (result) { 5680571f7390SMallikarjun Phulari case L2CAP_CR_LE_SUCCESS: 568140624183SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, dcid)) { 568240624183SJohan Hedberg err = -EBADSLT; 568340624183SJohan Hedberg break; 568440624183SJohan Hedberg } 568540624183SJohan Hedberg 5686f1496deeSJohan Hedberg chan->ident = 0; 5687f1496deeSJohan Hedberg chan->dcid = dcid; 5688f1496deeSJohan Hedberg chan->omtu = mtu; 5689f1496deeSJohan Hedberg chan->remote_mps = mps; 56900cd75f7eSJohan Hedberg chan->tx_credits = credits; 5691f1496deeSJohan Hedberg l2cap_chan_ready(chan); 5692f1496deeSJohan Hedberg break; 5693f1496deeSJohan Hedberg 5694571f7390SMallikarjun Phulari case L2CAP_CR_LE_AUTHENTICATION: 5695571f7390SMallikarjun Phulari case L2CAP_CR_LE_ENCRYPTION: 56963e64b7bdSJohan Hedberg /* If we already have MITM protection we can't do 56973e64b7bdSJohan Hedberg * anything. 56983e64b7bdSJohan Hedberg */ 56993e64b7bdSJohan Hedberg if (hcon->sec_level > BT_SECURITY_MEDIUM) { 57003e64b7bdSJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED); 57013e64b7bdSJohan Hedberg break; 57023e64b7bdSJohan Hedberg } 57033e64b7bdSJohan Hedberg 57043e64b7bdSJohan Hedberg sec_level = hcon->sec_level + 1; 57053e64b7bdSJohan Hedberg if (chan->sec_level < sec_level) 57063e64b7bdSJohan Hedberg chan->sec_level = sec_level; 57073e64b7bdSJohan Hedberg 57083e64b7bdSJohan Hedberg /* We'll need to send a new Connect Request */ 57093e64b7bdSJohan Hedberg clear_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags); 57103e64b7bdSJohan Hedberg 57113e64b7bdSJohan Hedberg smp_conn_security(hcon, chan->sec_level); 57123e64b7bdSJohan Hedberg break; 57133e64b7bdSJohan Hedberg 5714f1496deeSJohan Hedberg default: 5715f1496deeSJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED); 5716f1496deeSJohan Hedberg break; 5717f1496deeSJohan Hedberg } 5718f1496deeSJohan Hedberg 5719f1496deeSJohan Hedberg l2cap_chan_unlock(chan); 5720f1496deeSJohan Hedberg 5721f1496deeSJohan Hedberg unlock: 5722f1496deeSJohan Hedberg mutex_unlock(&conn->chan_lock); 5723f1496deeSJohan Hedberg 5724f1496deeSJohan Hedberg return err; 5725f1496deeSJohan Hedberg } 5726f1496deeSJohan Hedberg 57273300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, 57282d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len, 57292d792818SGustavo Padovan u8 *data) 57303300d9a9SClaudio Takahasi { 57313300d9a9SClaudio Takahasi int err = 0; 57323300d9a9SClaudio Takahasi 57333300d9a9SClaudio Takahasi switch (cmd->code) { 57343300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 5735cb3b3152SJohan Hedberg l2cap_command_rej(conn, cmd, cmd_len, data); 57363300d9a9SClaudio Takahasi break; 57373300d9a9SClaudio Takahasi 57383300d9a9SClaudio Takahasi case L2CAP_CONN_REQ: 5739cb3b3152SJohan Hedberg err = l2cap_connect_req(conn, cmd, cmd_len, data); 57403300d9a9SClaudio Takahasi break; 57413300d9a9SClaudio Takahasi 57423300d9a9SClaudio Takahasi case L2CAP_CONN_RSP: 5743f5a2598dSMat Martineau case L2CAP_CREATE_CHAN_RSP: 57449245e737SJohan Hedberg l2cap_connect_create_rsp(conn, cmd, cmd_len, data); 57453300d9a9SClaudio Takahasi break; 57463300d9a9SClaudio Takahasi 57473300d9a9SClaudio Takahasi case L2CAP_CONF_REQ: 57483300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data); 57493300d9a9SClaudio Takahasi break; 57503300d9a9SClaudio Takahasi 57513300d9a9SClaudio Takahasi case L2CAP_CONF_RSP: 57529245e737SJohan Hedberg l2cap_config_rsp(conn, cmd, cmd_len, data); 57533300d9a9SClaudio Takahasi break; 57543300d9a9SClaudio Takahasi 57553300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ: 5756cb3b3152SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data); 57573300d9a9SClaudio Takahasi break; 57583300d9a9SClaudio Takahasi 57593300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP: 57609245e737SJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data); 57613300d9a9SClaudio Takahasi break; 57623300d9a9SClaudio Takahasi 57633300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ: 57643300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data); 57653300d9a9SClaudio Takahasi break; 57663300d9a9SClaudio Takahasi 57673300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP: 57683300d9a9SClaudio Takahasi break; 57693300d9a9SClaudio Takahasi 57703300d9a9SClaudio Takahasi case L2CAP_INFO_REQ: 5771cb3b3152SJohan Hedberg err = l2cap_information_req(conn, cmd, cmd_len, data); 57723300d9a9SClaudio Takahasi break; 57733300d9a9SClaudio Takahasi 57743300d9a9SClaudio Takahasi case L2CAP_INFO_RSP: 57759245e737SJohan Hedberg l2cap_information_rsp(conn, cmd, cmd_len, data); 57763300d9a9SClaudio Takahasi break; 57773300d9a9SClaudio Takahasi 5778f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_REQ: 5779f94ff6ffSMat Martineau err = l2cap_create_channel_req(conn, cmd, cmd_len, data); 5780f94ff6ffSMat Martineau break; 5781f94ff6ffSMat Martineau 57828d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_REQ: 57838d5a04a1SMat Martineau err = l2cap_move_channel_req(conn, cmd, cmd_len, data); 57848d5a04a1SMat Martineau break; 57858d5a04a1SMat Martineau 57868d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_RSP: 57879245e737SJohan Hedberg l2cap_move_channel_rsp(conn, cmd, cmd_len, data); 57888d5a04a1SMat Martineau break; 57898d5a04a1SMat Martineau 57908d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM: 57918d5a04a1SMat Martineau err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data); 57928d5a04a1SMat Martineau break; 57938d5a04a1SMat Martineau 57948d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM_RSP: 57959245e737SJohan Hedberg l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data); 57968d5a04a1SMat Martineau break; 57978d5a04a1SMat Martineau 57983300d9a9SClaudio Takahasi default: 57993300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code); 58003300d9a9SClaudio Takahasi err = -EINVAL; 58013300d9a9SClaudio Takahasi break; 58023300d9a9SClaudio Takahasi } 58033300d9a9SClaudio Takahasi 58043300d9a9SClaudio Takahasi return err; 58053300d9a9SClaudio Takahasi } 58063300d9a9SClaudio Takahasi 580727e2d4c8SJohan Hedberg static int l2cap_le_connect_req(struct l2cap_conn *conn, 580827e2d4c8SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 580927e2d4c8SJohan Hedberg u8 *data) 581027e2d4c8SJohan Hedberg { 581127e2d4c8SJohan Hedberg struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data; 581227e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 581327e2d4c8SJohan Hedberg struct l2cap_chan *chan, *pchan; 58140cd75f7eSJohan Hedberg u16 dcid, scid, credits, mtu, mps; 581527e2d4c8SJohan Hedberg __le16 psm; 581627e2d4c8SJohan Hedberg u8 result; 581727e2d4c8SJohan Hedberg 581827e2d4c8SJohan Hedberg if (cmd_len != sizeof(*req)) 581927e2d4c8SJohan Hedberg return -EPROTO; 582027e2d4c8SJohan Hedberg 582127e2d4c8SJohan Hedberg scid = __le16_to_cpu(req->scid); 582227e2d4c8SJohan Hedberg mtu = __le16_to_cpu(req->mtu); 582327e2d4c8SJohan Hedberg mps = __le16_to_cpu(req->mps); 582427e2d4c8SJohan Hedberg psm = req->psm; 582527e2d4c8SJohan Hedberg dcid = 0; 58260cd75f7eSJohan Hedberg credits = 0; 582727e2d4c8SJohan Hedberg 582827e2d4c8SJohan Hedberg if (mtu < 23 || mps < 23) 582927e2d4c8SJohan Hedberg return -EPROTO; 583027e2d4c8SJohan Hedberg 583127e2d4c8SJohan Hedberg BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm), 583227e2d4c8SJohan Hedberg scid, mtu, mps); 583327e2d4c8SJohan Hedberg 5834711f8c3fSLuiz Augusto von Dentz /* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 3, Part A 5835711f8c3fSLuiz Augusto von Dentz * page 1059: 5836711f8c3fSLuiz Augusto von Dentz * 5837711f8c3fSLuiz Augusto von Dentz * Valid range: 0x0001-0x00ff 5838711f8c3fSLuiz Augusto von Dentz * 5839711f8c3fSLuiz Augusto von Dentz * Table 4.15: L2CAP_LE_CREDIT_BASED_CONNECTION_REQ SPSM ranges 5840711f8c3fSLuiz Augusto von Dentz */ 5841711f8c3fSLuiz Augusto von Dentz if (!psm || __le16_to_cpu(psm) > L2CAP_PSM_LE_DYN_END) { 5842711f8c3fSLuiz Augusto von Dentz result = L2CAP_CR_LE_BAD_PSM; 5843711f8c3fSLuiz Augusto von Dentz chan = NULL; 5844711f8c3fSLuiz Augusto von Dentz goto response; 5845711f8c3fSLuiz Augusto von Dentz } 5846711f8c3fSLuiz Augusto von Dentz 584727e2d4c8SJohan Hedberg /* Check if we have socket listening on psm */ 584827e2d4c8SJohan Hedberg pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 584927e2d4c8SJohan Hedberg &conn->hcon->dst, LE_LINK); 585027e2d4c8SJohan Hedberg if (!pchan) { 5851571f7390SMallikarjun Phulari result = L2CAP_CR_LE_BAD_PSM; 585227e2d4c8SJohan Hedberg chan = NULL; 585327e2d4c8SJohan Hedberg goto response; 585427e2d4c8SJohan Hedberg } 585527e2d4c8SJohan Hedberg 585627e2d4c8SJohan Hedberg mutex_lock(&conn->chan_lock); 585727e2d4c8SJohan Hedberg l2cap_chan_lock(pchan); 585827e2d4c8SJohan Hedberg 585935dc6f83SJohan Hedberg if (!smp_sufficient_security(conn->hcon, pchan->sec_level, 586035dc6f83SJohan Hedberg SMP_ALLOW_STK)) { 5861571f7390SMallikarjun Phulari result = L2CAP_CR_LE_AUTHENTICATION; 586227e2d4c8SJohan Hedberg chan = NULL; 586327e2d4c8SJohan Hedberg goto response_unlock; 586427e2d4c8SJohan Hedberg } 586527e2d4c8SJohan Hedberg 58668a7889ccSJohan Hedberg /* Check for valid dynamic CID range */ 58678a7889ccSJohan Hedberg if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) { 5868571f7390SMallikarjun Phulari result = L2CAP_CR_LE_INVALID_SCID; 58698a7889ccSJohan Hedberg chan = NULL; 58708a7889ccSJohan Hedberg goto response_unlock; 58718a7889ccSJohan Hedberg } 58728a7889ccSJohan Hedberg 587327e2d4c8SJohan Hedberg /* Check if we already have channel with that dcid */ 587427e2d4c8SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, scid)) { 5875571f7390SMallikarjun Phulari result = L2CAP_CR_LE_SCID_IN_USE; 587627e2d4c8SJohan Hedberg chan = NULL; 587727e2d4c8SJohan Hedberg goto response_unlock; 587827e2d4c8SJohan Hedberg } 587927e2d4c8SJohan Hedberg 588027e2d4c8SJohan Hedberg chan = pchan->ops->new_connection(pchan); 588127e2d4c8SJohan Hedberg if (!chan) { 5882571f7390SMallikarjun Phulari result = L2CAP_CR_LE_NO_MEM; 588327e2d4c8SJohan Hedberg goto response_unlock; 588427e2d4c8SJohan Hedberg } 588527e2d4c8SJohan Hedberg 588627e2d4c8SJohan Hedberg bacpy(&chan->src, &conn->hcon->src); 588727e2d4c8SJohan Hedberg bacpy(&chan->dst, &conn->hcon->dst); 5888a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(conn->hcon); 5889a250e048SJohan Hedberg chan->dst_type = bdaddr_dst_type(conn->hcon); 589027e2d4c8SJohan Hedberg chan->psm = psm; 589127e2d4c8SJohan Hedberg chan->dcid = scid; 589227e2d4c8SJohan Hedberg chan->omtu = mtu; 589327e2d4c8SJohan Hedberg chan->remote_mps = mps; 589427e2d4c8SJohan Hedberg 589527e2d4c8SJohan Hedberg __l2cap_chan_add(conn, chan); 5896fe149310SLuiz Augusto von Dentz 5897ba8f5289SLuiz Augusto von Dentz l2cap_le_flowctl_init(chan, __le16_to_cpu(req->credits)); 5898fe149310SLuiz Augusto von Dentz 589927e2d4c8SJohan Hedberg dcid = chan->scid; 59000cd75f7eSJohan Hedberg credits = chan->rx_credits; 590127e2d4c8SJohan Hedberg 590227e2d4c8SJohan Hedberg __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 590327e2d4c8SJohan Hedberg 590427e2d4c8SJohan Hedberg chan->ident = cmd->ident; 590527e2d4c8SJohan Hedberg 590627e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 590727e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_CONNECT2); 5908434714dcSJohan Hedberg /* The following result value is actually not defined 5909434714dcSJohan Hedberg * for LE CoC but we use it to let the function know 5910434714dcSJohan Hedberg * that it should bail out after doing its cleanup 5911434714dcSJohan Hedberg * instead of sending a response. 5912434714dcSJohan Hedberg */ 591327e2d4c8SJohan Hedberg result = L2CAP_CR_PEND; 591427e2d4c8SJohan Hedberg chan->ops->defer(chan); 591527e2d4c8SJohan Hedberg } else { 591627e2d4c8SJohan Hedberg l2cap_chan_ready(chan); 5917571f7390SMallikarjun Phulari result = L2CAP_CR_LE_SUCCESS; 591827e2d4c8SJohan Hedberg } 591927e2d4c8SJohan Hedberg 592027e2d4c8SJohan Hedberg response_unlock: 592127e2d4c8SJohan Hedberg l2cap_chan_unlock(pchan); 592227e2d4c8SJohan Hedberg mutex_unlock(&conn->chan_lock); 5923a24cce14SJohan Hedberg l2cap_chan_put(pchan); 592427e2d4c8SJohan Hedberg 592527e2d4c8SJohan Hedberg if (result == L2CAP_CR_PEND) 592627e2d4c8SJohan Hedberg return 0; 592727e2d4c8SJohan Hedberg 592827e2d4c8SJohan Hedberg response: 592927e2d4c8SJohan Hedberg if (chan) { 593027e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 59313916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps); 593227e2d4c8SJohan Hedberg } else { 593327e2d4c8SJohan Hedberg rsp.mtu = 0; 593427e2d4c8SJohan Hedberg rsp.mps = 0; 593527e2d4c8SJohan Hedberg } 593627e2d4c8SJohan Hedberg 593727e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(dcid); 59380cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(credits); 593927e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result); 594027e2d4c8SJohan Hedberg 594127e2d4c8SJohan Hedberg l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp); 594227e2d4c8SJohan Hedberg 594327e2d4c8SJohan Hedberg return 0; 594427e2d4c8SJohan Hedberg } 594527e2d4c8SJohan Hedberg 5946fad5fc89SJohan Hedberg static inline int l2cap_le_credits(struct l2cap_conn *conn, 5947fad5fc89SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5948fad5fc89SJohan Hedberg u8 *data) 5949fad5fc89SJohan Hedberg { 5950fad5fc89SJohan Hedberg struct l2cap_le_credits *pkt; 5951fad5fc89SJohan Hedberg struct l2cap_chan *chan; 59520f1bfe4eSJohan Hedberg u16 cid, credits, max_credits; 5953fad5fc89SJohan Hedberg 5954fad5fc89SJohan Hedberg if (cmd_len != sizeof(*pkt)) 5955fad5fc89SJohan Hedberg return -EPROTO; 5956fad5fc89SJohan Hedberg 5957fad5fc89SJohan Hedberg pkt = (struct l2cap_le_credits *) data; 5958fad5fc89SJohan Hedberg cid = __le16_to_cpu(pkt->cid); 5959fad5fc89SJohan Hedberg credits = __le16_to_cpu(pkt->credits); 5960fad5fc89SJohan Hedberg 5961fad5fc89SJohan Hedberg BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits); 5962fad5fc89SJohan Hedberg 5963fad5fc89SJohan Hedberg chan = l2cap_get_chan_by_dcid(conn, cid); 5964fad5fc89SJohan Hedberg if (!chan) 5965fad5fc89SJohan Hedberg return -EBADSLT; 5966fad5fc89SJohan Hedberg 59670f1bfe4eSJohan Hedberg max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits; 59680f1bfe4eSJohan Hedberg if (credits > max_credits) { 59690f1bfe4eSJohan Hedberg BT_ERR("LE credits overflow"); 59700f1bfe4eSJohan Hedberg l2cap_send_disconn_req(chan, ECONNRESET); 59710f1bfe4eSJohan Hedberg 59720f1bfe4eSJohan Hedberg /* Return 0 so that we don't trigger an unnecessary 59730f1bfe4eSJohan Hedberg * command reject packet. 59740f1bfe4eSJohan Hedberg */ 5975d0be8347SLuiz Augusto von Dentz goto unlock; 59760f1bfe4eSJohan Hedberg } 59770f1bfe4eSJohan Hedberg 5978fad5fc89SJohan Hedberg chan->tx_credits += credits; 5979fad5fc89SJohan Hedberg 59808a505b7fSLuiz Augusto von Dentz /* Resume sending */ 59818a505b7fSLuiz Augusto von Dentz l2cap_le_flowctl_send(chan); 5982fad5fc89SJohan Hedberg 5983fad5fc89SJohan Hedberg if (chan->tx_credits) 5984fad5fc89SJohan Hedberg chan->ops->resume(chan); 5985fad5fc89SJohan Hedberg 5986d0be8347SLuiz Augusto von Dentz unlock: 5987fad5fc89SJohan Hedberg l2cap_chan_unlock(chan); 5988d0be8347SLuiz Augusto von Dentz l2cap_chan_put(chan); 5989fad5fc89SJohan Hedberg 5990fad5fc89SJohan Hedberg return 0; 5991fad5fc89SJohan Hedberg } 5992fad5fc89SJohan Hedberg 599315f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn, 599415f02b91SLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd, u16 cmd_len, 599515f02b91SLuiz Augusto von Dentz u8 *data) 599615f02b91SLuiz Augusto von Dentz { 599715f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_req *req = (void *) data; 599815f02b91SLuiz Augusto von Dentz struct { 599915f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp rsp; 60007cf3b1ddSLuiz Augusto von Dentz __le16 dcid[L2CAP_ECRED_MAX_CID]; 600115f02b91SLuiz Augusto von Dentz } __packed pdu; 600215f02b91SLuiz Augusto von Dentz struct l2cap_chan *chan, *pchan; 6003965995b7SYueHaibing u16 mtu, mps; 600415f02b91SLuiz Augusto von Dentz __le16 psm; 600515f02b91SLuiz Augusto von Dentz u8 result, len = 0; 600615f02b91SLuiz Augusto von Dentz int i, num_scid; 600715f02b91SLuiz Augusto von Dentz bool defer = false; 600815f02b91SLuiz Augusto von Dentz 60094be5ca67SLuiz Augusto von Dentz if (!enable_ecred) 60104be5ca67SLuiz Augusto von Dentz return -EINVAL; 60114be5ca67SLuiz Augusto von Dentz 601269d67b46SKonstantin Forostyan if (cmd_len < sizeof(*req) || (cmd_len - sizeof(*req)) % sizeof(u16)) { 601315f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_INVALID_PARAMS; 601415f02b91SLuiz Augusto von Dentz goto response; 601515f02b91SLuiz Augusto von Dentz } 601615f02b91SLuiz Augusto von Dentz 60177cf3b1ddSLuiz Augusto von Dentz cmd_len -= sizeof(*req); 60187cf3b1ddSLuiz Augusto von Dentz num_scid = cmd_len / sizeof(u16); 60197cf3b1ddSLuiz Augusto von Dentz 60207cf3b1ddSLuiz Augusto von Dentz if (num_scid > ARRAY_SIZE(pdu.dcid)) { 60217cf3b1ddSLuiz Augusto von Dentz result = L2CAP_CR_LE_INVALID_PARAMS; 60227cf3b1ddSLuiz Augusto von Dentz goto response; 60237cf3b1ddSLuiz Augusto von Dentz } 60247cf3b1ddSLuiz Augusto von Dentz 602515f02b91SLuiz Augusto von Dentz mtu = __le16_to_cpu(req->mtu); 602615f02b91SLuiz Augusto von Dentz mps = __le16_to_cpu(req->mps); 602715f02b91SLuiz Augusto von Dentz 602815f02b91SLuiz Augusto von Dentz if (mtu < L2CAP_ECRED_MIN_MTU || mps < L2CAP_ECRED_MIN_MPS) { 602915f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_UNACCEPT_PARAMS; 603015f02b91SLuiz Augusto von Dentz goto response; 603115f02b91SLuiz Augusto von Dentz } 603215f02b91SLuiz Augusto von Dentz 603315f02b91SLuiz Augusto von Dentz psm = req->psm; 603415f02b91SLuiz Augusto von Dentz 6035711f8c3fSLuiz Augusto von Dentz /* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 3, Part A 6036711f8c3fSLuiz Augusto von Dentz * page 1059: 6037711f8c3fSLuiz Augusto von Dentz * 6038711f8c3fSLuiz Augusto von Dentz * Valid range: 0x0001-0x00ff 6039711f8c3fSLuiz Augusto von Dentz * 6040711f8c3fSLuiz Augusto von Dentz * Table 4.15: L2CAP_LE_CREDIT_BASED_CONNECTION_REQ SPSM ranges 6041711f8c3fSLuiz Augusto von Dentz */ 6042711f8c3fSLuiz Augusto von Dentz if (!psm || __le16_to_cpu(psm) > L2CAP_PSM_LE_DYN_END) { 6043711f8c3fSLuiz Augusto von Dentz result = L2CAP_CR_LE_BAD_PSM; 6044711f8c3fSLuiz Augusto von Dentz goto response; 6045711f8c3fSLuiz Augusto von Dentz } 6046711f8c3fSLuiz Augusto von Dentz 604715f02b91SLuiz Augusto von Dentz BT_DBG("psm 0x%2.2x mtu %u mps %u", __le16_to_cpu(psm), mtu, mps); 604815f02b91SLuiz Augusto von Dentz 604915f02b91SLuiz Augusto von Dentz memset(&pdu, 0, sizeof(pdu)); 605015f02b91SLuiz Augusto von Dentz 605115f02b91SLuiz Augusto von Dentz /* Check if we have socket listening on psm */ 605215f02b91SLuiz Augusto von Dentz pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 605315f02b91SLuiz Augusto von Dentz &conn->hcon->dst, LE_LINK); 605415f02b91SLuiz Augusto von Dentz if (!pchan) { 605515f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_BAD_PSM; 605615f02b91SLuiz Augusto von Dentz goto response; 605715f02b91SLuiz Augusto von Dentz } 605815f02b91SLuiz Augusto von Dentz 605915f02b91SLuiz Augusto von Dentz mutex_lock(&conn->chan_lock); 606015f02b91SLuiz Augusto von Dentz l2cap_chan_lock(pchan); 606115f02b91SLuiz Augusto von Dentz 606215f02b91SLuiz Augusto von Dentz if (!smp_sufficient_security(conn->hcon, pchan->sec_level, 606315f02b91SLuiz Augusto von Dentz SMP_ALLOW_STK)) { 606415f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_AUTHENTICATION; 606515f02b91SLuiz Augusto von Dentz goto unlock; 606615f02b91SLuiz Augusto von Dentz } 606715f02b91SLuiz Augusto von Dentz 606815f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_SUCCESS; 606915f02b91SLuiz Augusto von Dentz 607015f02b91SLuiz Augusto von Dentz for (i = 0; i < num_scid; i++) { 607115f02b91SLuiz Augusto von Dentz u16 scid = __le16_to_cpu(req->scid[i]); 607215f02b91SLuiz Augusto von Dentz 607315f02b91SLuiz Augusto von Dentz BT_DBG("scid[%d] 0x%4.4x", i, scid); 607415f02b91SLuiz Augusto von Dentz 607515f02b91SLuiz Augusto von Dentz pdu.dcid[i] = 0x0000; 607615f02b91SLuiz Augusto von Dentz len += sizeof(*pdu.dcid); 607715f02b91SLuiz Augusto von Dentz 607815f02b91SLuiz Augusto von Dentz /* Check for valid dynamic CID range */ 607915f02b91SLuiz Augusto von Dentz if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) { 608015f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_INVALID_SCID; 608115f02b91SLuiz Augusto von Dentz continue; 608215f02b91SLuiz Augusto von Dentz } 608315f02b91SLuiz Augusto von Dentz 608415f02b91SLuiz Augusto von Dentz /* Check if we already have channel with that dcid */ 608515f02b91SLuiz Augusto von Dentz if (__l2cap_get_chan_by_dcid(conn, scid)) { 608615f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_SCID_IN_USE; 608715f02b91SLuiz Augusto von Dentz continue; 608815f02b91SLuiz Augusto von Dentz } 608915f02b91SLuiz Augusto von Dentz 609015f02b91SLuiz Augusto von Dentz chan = pchan->ops->new_connection(pchan); 609115f02b91SLuiz Augusto von Dentz if (!chan) { 609215f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_NO_MEM; 609315f02b91SLuiz Augusto von Dentz continue; 609415f02b91SLuiz Augusto von Dentz } 609515f02b91SLuiz Augusto von Dentz 609615f02b91SLuiz Augusto von Dentz bacpy(&chan->src, &conn->hcon->src); 609715f02b91SLuiz Augusto von Dentz bacpy(&chan->dst, &conn->hcon->dst); 609815f02b91SLuiz Augusto von Dentz chan->src_type = bdaddr_src_type(conn->hcon); 609915f02b91SLuiz Augusto von Dentz chan->dst_type = bdaddr_dst_type(conn->hcon); 610015f02b91SLuiz Augusto von Dentz chan->psm = psm; 610115f02b91SLuiz Augusto von Dentz chan->dcid = scid; 610215f02b91SLuiz Augusto von Dentz chan->omtu = mtu; 610315f02b91SLuiz Augusto von Dentz chan->remote_mps = mps; 610415f02b91SLuiz Augusto von Dentz 610515f02b91SLuiz Augusto von Dentz __l2cap_chan_add(conn, chan); 610615f02b91SLuiz Augusto von Dentz 610715f02b91SLuiz Augusto von Dentz l2cap_ecred_init(chan, __le16_to_cpu(req->credits)); 610815f02b91SLuiz Augusto von Dentz 610915f02b91SLuiz Augusto von Dentz /* Init response */ 611015f02b91SLuiz Augusto von Dentz if (!pdu.rsp.credits) { 611115f02b91SLuiz Augusto von Dentz pdu.rsp.mtu = cpu_to_le16(chan->imtu); 611215f02b91SLuiz Augusto von Dentz pdu.rsp.mps = cpu_to_le16(chan->mps); 611315f02b91SLuiz Augusto von Dentz pdu.rsp.credits = cpu_to_le16(chan->rx_credits); 611415f02b91SLuiz Augusto von Dentz } 611515f02b91SLuiz Augusto von Dentz 611615f02b91SLuiz Augusto von Dentz pdu.dcid[i] = cpu_to_le16(chan->scid); 611715f02b91SLuiz Augusto von Dentz 611815f02b91SLuiz Augusto von Dentz __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 611915f02b91SLuiz Augusto von Dentz 612015f02b91SLuiz Augusto von Dentz chan->ident = cmd->ident; 6121*9aa9d947SLuiz Augusto von Dentz chan->mode = L2CAP_MODE_EXT_FLOWCTL; 612215f02b91SLuiz Augusto von Dentz 612315f02b91SLuiz Augusto von Dentz if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 612415f02b91SLuiz Augusto von Dentz l2cap_state_change(chan, BT_CONNECT2); 612515f02b91SLuiz Augusto von Dentz defer = true; 612615f02b91SLuiz Augusto von Dentz chan->ops->defer(chan); 612715f02b91SLuiz Augusto von Dentz } else { 612815f02b91SLuiz Augusto von Dentz l2cap_chan_ready(chan); 612915f02b91SLuiz Augusto von Dentz } 613015f02b91SLuiz Augusto von Dentz } 613115f02b91SLuiz Augusto von Dentz 613215f02b91SLuiz Augusto von Dentz unlock: 613315f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(pchan); 613415f02b91SLuiz Augusto von Dentz mutex_unlock(&conn->chan_lock); 613515f02b91SLuiz Augusto von Dentz l2cap_chan_put(pchan); 613615f02b91SLuiz Augusto von Dentz 613715f02b91SLuiz Augusto von Dentz response: 613815f02b91SLuiz Augusto von Dentz pdu.rsp.result = cpu_to_le16(result); 613915f02b91SLuiz Augusto von Dentz 614015f02b91SLuiz Augusto von Dentz if (defer) 614115f02b91SLuiz Augusto von Dentz return 0; 614215f02b91SLuiz Augusto von Dentz 614315f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, cmd->ident, L2CAP_ECRED_CONN_RSP, 614415f02b91SLuiz Augusto von Dentz sizeof(pdu.rsp) + len, &pdu); 614515f02b91SLuiz Augusto von Dentz 614615f02b91SLuiz Augusto von Dentz return 0; 614715f02b91SLuiz Augusto von Dentz } 614815f02b91SLuiz Augusto von Dentz 614915f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn, 615015f02b91SLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd, u16 cmd_len, 615115f02b91SLuiz Augusto von Dentz u8 *data) 615215f02b91SLuiz Augusto von Dentz { 615315f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp *rsp = (void *) data; 615415f02b91SLuiz Augusto von Dentz struct hci_conn *hcon = conn->hcon; 615515f02b91SLuiz Augusto von Dentz u16 mtu, mps, credits, result; 6156de895b43SLuiz Augusto von Dentz struct l2cap_chan *chan, *tmp; 615715f02b91SLuiz Augusto von Dentz int err = 0, sec_level; 615815f02b91SLuiz Augusto von Dentz int i = 0; 615915f02b91SLuiz Augusto von Dentz 616015f02b91SLuiz Augusto von Dentz if (cmd_len < sizeof(*rsp)) 616115f02b91SLuiz Augusto von Dentz return -EPROTO; 616215f02b91SLuiz Augusto von Dentz 616315f02b91SLuiz Augusto von Dentz mtu = __le16_to_cpu(rsp->mtu); 616415f02b91SLuiz Augusto von Dentz mps = __le16_to_cpu(rsp->mps); 616515f02b91SLuiz Augusto von Dentz credits = __le16_to_cpu(rsp->credits); 616615f02b91SLuiz Augusto von Dentz result = __le16_to_cpu(rsp->result); 616715f02b91SLuiz Augusto von Dentz 616815f02b91SLuiz Augusto von Dentz BT_DBG("mtu %u mps %u credits %u result 0x%4.4x", mtu, mps, credits, 616915f02b91SLuiz Augusto von Dentz result); 617015f02b91SLuiz Augusto von Dentz 617115f02b91SLuiz Augusto von Dentz mutex_lock(&conn->chan_lock); 617215f02b91SLuiz Augusto von Dentz 617315f02b91SLuiz Augusto von Dentz cmd_len -= sizeof(*rsp); 617415f02b91SLuiz Augusto von Dentz 6175de895b43SLuiz Augusto von Dentz list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 617615f02b91SLuiz Augusto von Dentz u16 dcid; 617715f02b91SLuiz Augusto von Dentz 617815f02b91SLuiz Augusto von Dentz if (chan->ident != cmd->ident || 617915f02b91SLuiz Augusto von Dentz chan->mode != L2CAP_MODE_EXT_FLOWCTL || 618015f02b91SLuiz Augusto von Dentz chan->state == BT_CONNECTED) 618115f02b91SLuiz Augusto von Dentz continue; 618215f02b91SLuiz Augusto von Dentz 618315f02b91SLuiz Augusto von Dentz l2cap_chan_lock(chan); 618415f02b91SLuiz Augusto von Dentz 618515f02b91SLuiz Augusto von Dentz /* Check that there is a dcid for each pending channel */ 618615f02b91SLuiz Augusto von Dentz if (cmd_len < sizeof(dcid)) { 618715f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED); 618815f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(chan); 618915f02b91SLuiz Augusto von Dentz continue; 619015f02b91SLuiz Augusto von Dentz } 619115f02b91SLuiz Augusto von Dentz 619215f02b91SLuiz Augusto von Dentz dcid = __le16_to_cpu(rsp->dcid[i++]); 619315f02b91SLuiz Augusto von Dentz cmd_len -= sizeof(u16); 619415f02b91SLuiz Augusto von Dentz 619515f02b91SLuiz Augusto von Dentz BT_DBG("dcid[%d] 0x%4.4x", i, dcid); 619615f02b91SLuiz Augusto von Dentz 619715f02b91SLuiz Augusto von Dentz /* Check if dcid is already in use */ 619815f02b91SLuiz Augusto von Dentz if (dcid && __l2cap_get_chan_by_dcid(conn, dcid)) { 619915f02b91SLuiz Augusto von Dentz /* If a device receives a 620015f02b91SLuiz Augusto von Dentz * L2CAP_CREDIT_BASED_CONNECTION_RSP packet with an 620115f02b91SLuiz Augusto von Dentz * already-assigned Destination CID, then both the 620215f02b91SLuiz Augusto von Dentz * original channel and the new channel shall be 620315f02b91SLuiz Augusto von Dentz * immediately discarded and not used. 620415f02b91SLuiz Augusto von Dentz */ 620515f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED); 620615f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(chan); 620715f02b91SLuiz Augusto von Dentz chan = __l2cap_get_chan_by_dcid(conn, dcid); 620815f02b91SLuiz Augusto von Dentz l2cap_chan_lock(chan); 620915f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNRESET); 621015f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(chan); 621115f02b91SLuiz Augusto von Dentz continue; 621215f02b91SLuiz Augusto von Dentz } 621315f02b91SLuiz Augusto von Dentz 621415f02b91SLuiz Augusto von Dentz switch (result) { 621515f02b91SLuiz Augusto von Dentz case L2CAP_CR_LE_AUTHENTICATION: 621615f02b91SLuiz Augusto von Dentz case L2CAP_CR_LE_ENCRYPTION: 621715f02b91SLuiz Augusto von Dentz /* If we already have MITM protection we can't do 621815f02b91SLuiz Augusto von Dentz * anything. 621915f02b91SLuiz Augusto von Dentz */ 622015f02b91SLuiz Augusto von Dentz if (hcon->sec_level > BT_SECURITY_MEDIUM) { 622115f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED); 622215f02b91SLuiz Augusto von Dentz break; 622315f02b91SLuiz Augusto von Dentz } 622415f02b91SLuiz Augusto von Dentz 622515f02b91SLuiz Augusto von Dentz sec_level = hcon->sec_level + 1; 622615f02b91SLuiz Augusto von Dentz if (chan->sec_level < sec_level) 622715f02b91SLuiz Augusto von Dentz chan->sec_level = sec_level; 622815f02b91SLuiz Augusto von Dentz 622915f02b91SLuiz Augusto von Dentz /* We'll need to send a new Connect Request */ 623015f02b91SLuiz Augusto von Dentz clear_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags); 623115f02b91SLuiz Augusto von Dentz 623215f02b91SLuiz Augusto von Dentz smp_conn_security(hcon, chan->sec_level); 623315f02b91SLuiz Augusto von Dentz break; 623415f02b91SLuiz Augusto von Dentz 623515f02b91SLuiz Augusto von Dentz case L2CAP_CR_LE_BAD_PSM: 623615f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED); 623715f02b91SLuiz Augusto von Dentz break; 623815f02b91SLuiz Augusto von Dentz 623915f02b91SLuiz Augusto von Dentz default: 624015f02b91SLuiz Augusto von Dentz /* If dcid was not set it means channels was refused */ 624115f02b91SLuiz Augusto von Dentz if (!dcid) { 624215f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED); 624315f02b91SLuiz Augusto von Dentz break; 624415f02b91SLuiz Augusto von Dentz } 624515f02b91SLuiz Augusto von Dentz 624615f02b91SLuiz Augusto von Dentz chan->ident = 0; 624715f02b91SLuiz Augusto von Dentz chan->dcid = dcid; 624815f02b91SLuiz Augusto von Dentz chan->omtu = mtu; 624915f02b91SLuiz Augusto von Dentz chan->remote_mps = mps; 625015f02b91SLuiz Augusto von Dentz chan->tx_credits = credits; 625115f02b91SLuiz Augusto von Dentz l2cap_chan_ready(chan); 625215f02b91SLuiz Augusto von Dentz break; 625315f02b91SLuiz Augusto von Dentz } 625415f02b91SLuiz Augusto von Dentz 625515f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(chan); 625615f02b91SLuiz Augusto von Dentz } 625715f02b91SLuiz Augusto von Dentz 625815f02b91SLuiz Augusto von Dentz mutex_unlock(&conn->chan_lock); 625915f02b91SLuiz Augusto von Dentz 626015f02b91SLuiz Augusto von Dentz return err; 626115f02b91SLuiz Augusto von Dentz } 626215f02b91SLuiz Augusto von Dentz 626315f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_reconf_req(struct l2cap_conn *conn, 626415f02b91SLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd, u16 cmd_len, 626515f02b91SLuiz Augusto von Dentz u8 *data) 626615f02b91SLuiz Augusto von Dentz { 626715f02b91SLuiz Augusto von Dentz struct l2cap_ecred_reconf_req *req = (void *) data; 626815f02b91SLuiz Augusto von Dentz struct l2cap_ecred_reconf_rsp rsp; 626915f02b91SLuiz Augusto von Dentz u16 mtu, mps, result; 627015f02b91SLuiz Augusto von Dentz struct l2cap_chan *chan; 627115f02b91SLuiz Augusto von Dentz int i, num_scid; 627215f02b91SLuiz Augusto von Dentz 62734be5ca67SLuiz Augusto von Dentz if (!enable_ecred) 62744be5ca67SLuiz Augusto von Dentz return -EINVAL; 62754be5ca67SLuiz Augusto von Dentz 627615f02b91SLuiz Augusto von Dentz if (cmd_len < sizeof(*req) || cmd_len - sizeof(*req) % sizeof(u16)) { 627715f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_INVALID_PARAMS; 627815f02b91SLuiz Augusto von Dentz goto respond; 627915f02b91SLuiz Augusto von Dentz } 628015f02b91SLuiz Augusto von Dentz 628115f02b91SLuiz Augusto von Dentz mtu = __le16_to_cpu(req->mtu); 628215f02b91SLuiz Augusto von Dentz mps = __le16_to_cpu(req->mps); 628315f02b91SLuiz Augusto von Dentz 628415f02b91SLuiz Augusto von Dentz BT_DBG("mtu %u mps %u", mtu, mps); 628515f02b91SLuiz Augusto von Dentz 628615f02b91SLuiz Augusto von Dentz if (mtu < L2CAP_ECRED_MIN_MTU) { 628715f02b91SLuiz Augusto von Dentz result = L2CAP_RECONF_INVALID_MTU; 628815f02b91SLuiz Augusto von Dentz goto respond; 628915f02b91SLuiz Augusto von Dentz } 629015f02b91SLuiz Augusto von Dentz 629115f02b91SLuiz Augusto von Dentz if (mps < L2CAP_ECRED_MIN_MPS) { 629215f02b91SLuiz Augusto von Dentz result = L2CAP_RECONF_INVALID_MPS; 629315f02b91SLuiz Augusto von Dentz goto respond; 629415f02b91SLuiz Augusto von Dentz } 629515f02b91SLuiz Augusto von Dentz 629615f02b91SLuiz Augusto von Dentz cmd_len -= sizeof(*req); 629715f02b91SLuiz Augusto von Dentz num_scid = cmd_len / sizeof(u16); 629815f02b91SLuiz Augusto von Dentz result = L2CAP_RECONF_SUCCESS; 629915f02b91SLuiz Augusto von Dentz 630015f02b91SLuiz Augusto von Dentz for (i = 0; i < num_scid; i++) { 630115f02b91SLuiz Augusto von Dentz u16 scid; 630215f02b91SLuiz Augusto von Dentz 630315f02b91SLuiz Augusto von Dentz scid = __le16_to_cpu(req->scid[i]); 630415f02b91SLuiz Augusto von Dentz if (!scid) 630515f02b91SLuiz Augusto von Dentz return -EPROTO; 630615f02b91SLuiz Augusto von Dentz 630715f02b91SLuiz Augusto von Dentz chan = __l2cap_get_chan_by_dcid(conn, scid); 630815f02b91SLuiz Augusto von Dentz if (!chan) 630915f02b91SLuiz Augusto von Dentz continue; 631015f02b91SLuiz Augusto von Dentz 631115f02b91SLuiz Augusto von Dentz /* If the MTU value is decreased for any of the included 631215f02b91SLuiz Augusto von Dentz * channels, then the receiver shall disconnect all 631315f02b91SLuiz Augusto von Dentz * included channels. 631415f02b91SLuiz Augusto von Dentz */ 631515f02b91SLuiz Augusto von Dentz if (chan->omtu > mtu) { 631615f02b91SLuiz Augusto von Dentz BT_ERR("chan %p decreased MTU %u -> %u", chan, 631715f02b91SLuiz Augusto von Dentz chan->omtu, mtu); 631815f02b91SLuiz Augusto von Dentz result = L2CAP_RECONF_INVALID_MTU; 631915f02b91SLuiz Augusto von Dentz } 632015f02b91SLuiz Augusto von Dentz 632115f02b91SLuiz Augusto von Dentz chan->omtu = mtu; 632215f02b91SLuiz Augusto von Dentz chan->remote_mps = mps; 632315f02b91SLuiz Augusto von Dentz } 632415f02b91SLuiz Augusto von Dentz 632515f02b91SLuiz Augusto von Dentz respond: 632615f02b91SLuiz Augusto von Dentz rsp.result = cpu_to_le16(result); 632715f02b91SLuiz Augusto von Dentz 632815f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, cmd->ident, L2CAP_ECRED_RECONF_RSP, sizeof(rsp), 632915f02b91SLuiz Augusto von Dentz &rsp); 633015f02b91SLuiz Augusto von Dentz 633115f02b91SLuiz Augusto von Dentz return 0; 633215f02b91SLuiz Augusto von Dentz } 633315f02b91SLuiz Augusto von Dentz 633415f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn, 633515f02b91SLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd, u16 cmd_len, 633615f02b91SLuiz Augusto von Dentz u8 *data) 633715f02b91SLuiz Augusto von Dentz { 63381fa20d7dSLuiz Augusto von Dentz struct l2cap_chan *chan, *tmp; 633915f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp *rsp = (void *) data; 634015f02b91SLuiz Augusto von Dentz u16 result; 634115f02b91SLuiz Augusto von Dentz 634215f02b91SLuiz Augusto von Dentz if (cmd_len < sizeof(*rsp)) 634315f02b91SLuiz Augusto von Dentz return -EPROTO; 634415f02b91SLuiz Augusto von Dentz 634515f02b91SLuiz Augusto von Dentz result = __le16_to_cpu(rsp->result); 634615f02b91SLuiz Augusto von Dentz 634715f02b91SLuiz Augusto von Dentz BT_DBG("result 0x%4.4x", rsp->result); 634815f02b91SLuiz Augusto von Dentz 634915f02b91SLuiz Augusto von Dentz if (!result) 635015f02b91SLuiz Augusto von Dentz return 0; 635115f02b91SLuiz Augusto von Dentz 63521fa20d7dSLuiz Augusto von Dentz list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 635315f02b91SLuiz Augusto von Dentz if (chan->ident != cmd->ident) 635415f02b91SLuiz Augusto von Dentz continue; 635515f02b91SLuiz Augusto von Dentz 635615f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNRESET); 635715f02b91SLuiz Augusto von Dentz } 635815f02b91SLuiz Augusto von Dentz 635915f02b91SLuiz Augusto von Dentz return 0; 636015f02b91SLuiz Augusto von Dentz } 636115f02b91SLuiz Augusto von Dentz 636271fb4197SJohan Hedberg static inline int l2cap_le_command_rej(struct l2cap_conn *conn, 636371fb4197SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 636471fb4197SJohan Hedberg u8 *data) 636571fb4197SJohan Hedberg { 636671fb4197SJohan Hedberg struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 636771fb4197SJohan Hedberg struct l2cap_chan *chan; 636871fb4197SJohan Hedberg 636971fb4197SJohan Hedberg if (cmd_len < sizeof(*rej)) 637071fb4197SJohan Hedberg return -EPROTO; 637171fb4197SJohan Hedberg 637271fb4197SJohan Hedberg mutex_lock(&conn->chan_lock); 637371fb4197SJohan Hedberg 637471fb4197SJohan Hedberg chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 637571fb4197SJohan Hedberg if (!chan) 637671fb4197SJohan Hedberg goto done; 637771fb4197SJohan Hedberg 637871fb4197SJohan Hedberg l2cap_chan_lock(chan); 637971fb4197SJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED); 638071fb4197SJohan Hedberg l2cap_chan_unlock(chan); 638171fb4197SJohan Hedberg 638271fb4197SJohan Hedberg done: 638371fb4197SJohan Hedberg mutex_unlock(&conn->chan_lock); 638471fb4197SJohan Hedberg return 0; 638571fb4197SJohan Hedberg } 638671fb4197SJohan Hedberg 63873300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, 6388203e639eSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 6389203e639eSJohan Hedberg u8 *data) 63903300d9a9SClaudio Takahasi { 6391b5ecba64SJohan Hedberg int err = 0; 6392b5ecba64SJohan Hedberg 63933300d9a9SClaudio Takahasi switch (cmd->code) { 63943300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 639571fb4197SJohan Hedberg l2cap_le_command_rej(conn, cmd, cmd_len, data); 6396b5ecba64SJohan Hedberg break; 63973300d9a9SClaudio Takahasi 63983300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ: 6399b5ecba64SJohan Hedberg err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data); 6400b5ecba64SJohan Hedberg break; 64013300d9a9SClaudio Takahasi 64023300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP: 6403b5ecba64SJohan Hedberg break; 64043300d9a9SClaudio Takahasi 6405f1496deeSJohan Hedberg case L2CAP_LE_CONN_RSP: 6406f1496deeSJohan Hedberg l2cap_le_connect_rsp(conn, cmd, cmd_len, data); 6407b5ecba64SJohan Hedberg break; 6408f1496deeSJohan Hedberg 640927e2d4c8SJohan Hedberg case L2CAP_LE_CONN_REQ: 6410b5ecba64SJohan Hedberg err = l2cap_le_connect_req(conn, cmd, cmd_len, data); 6411b5ecba64SJohan Hedberg break; 641227e2d4c8SJohan Hedberg 6413fad5fc89SJohan Hedberg case L2CAP_LE_CREDITS: 6414fad5fc89SJohan Hedberg err = l2cap_le_credits(conn, cmd, cmd_len, data); 6415fad5fc89SJohan Hedberg break; 6416fad5fc89SJohan Hedberg 641715f02b91SLuiz Augusto von Dentz case L2CAP_ECRED_CONN_REQ: 641815f02b91SLuiz Augusto von Dentz err = l2cap_ecred_conn_req(conn, cmd, cmd_len, data); 641915f02b91SLuiz Augusto von Dentz break; 642015f02b91SLuiz Augusto von Dentz 642115f02b91SLuiz Augusto von Dentz case L2CAP_ECRED_CONN_RSP: 642215f02b91SLuiz Augusto von Dentz err = l2cap_ecred_conn_rsp(conn, cmd, cmd_len, data); 642315f02b91SLuiz Augusto von Dentz break; 642415f02b91SLuiz Augusto von Dentz 642515f02b91SLuiz Augusto von Dentz case L2CAP_ECRED_RECONF_REQ: 642615f02b91SLuiz Augusto von Dentz err = l2cap_ecred_reconf_req(conn, cmd, cmd_len, data); 642715f02b91SLuiz Augusto von Dentz break; 642815f02b91SLuiz Augusto von Dentz 642915f02b91SLuiz Augusto von Dentz case L2CAP_ECRED_RECONF_RSP: 643015f02b91SLuiz Augusto von Dentz err = l2cap_ecred_reconf_rsp(conn, cmd, cmd_len, data); 643115f02b91SLuiz Augusto von Dentz break; 643215f02b91SLuiz Augusto von Dentz 64333defe01aSJohan Hedberg case L2CAP_DISCONN_REQ: 6434b5ecba64SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data); 6435b5ecba64SJohan Hedberg break; 64363defe01aSJohan Hedberg 64373defe01aSJohan Hedberg case L2CAP_DISCONN_RSP: 64383defe01aSJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data); 6439b5ecba64SJohan Hedberg break; 64403defe01aSJohan Hedberg 64413300d9a9SClaudio Takahasi default: 64423300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code); 6443b5ecba64SJohan Hedberg err = -EINVAL; 6444b5ecba64SJohan Hedberg break; 64453300d9a9SClaudio Takahasi } 6446b5ecba64SJohan Hedberg 6447b5ecba64SJohan Hedberg return err; 64483300d9a9SClaudio Takahasi } 64493300d9a9SClaudio Takahasi 6450c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn, 6451c5623556SJohan Hedberg struct sk_buff *skb) 6452c5623556SJohan Hedberg { 645369c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon; 64544f3e219dSMarcel Holtmann struct l2cap_cmd_hdr *cmd; 64554f3e219dSMarcel Holtmann u16 len; 6456c5623556SJohan Hedberg int err; 6457c5623556SJohan Hedberg 645869c4e4e8SJohan Hedberg if (hcon->type != LE_LINK) 64593b166295SMarcel Holtmann goto drop; 646069c4e4e8SJohan Hedberg 64614f3e219dSMarcel Holtmann if (skb->len < L2CAP_CMD_HDR_SIZE) 64624f3e219dSMarcel Holtmann goto drop; 6463c5623556SJohan Hedberg 64644f3e219dSMarcel Holtmann cmd = (void *) skb->data; 64654f3e219dSMarcel Holtmann skb_pull(skb, L2CAP_CMD_HDR_SIZE); 6466c5623556SJohan Hedberg 64674f3e219dSMarcel Holtmann len = le16_to_cpu(cmd->len); 6468c5623556SJohan Hedberg 64694f3e219dSMarcel Holtmann BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident); 64704f3e219dSMarcel Holtmann 64714f3e219dSMarcel Holtmann if (len != skb->len || !cmd->ident) { 6472c5623556SJohan Hedberg BT_DBG("corrupted command"); 64734f3e219dSMarcel Holtmann goto drop; 6474c5623556SJohan Hedberg } 6475c5623556SJohan Hedberg 6476203e639eSJohan Hedberg err = l2cap_le_sig_cmd(conn, cmd, len, skb->data); 6477c5623556SJohan Hedberg if (err) { 6478c5623556SJohan Hedberg struct l2cap_cmd_rej_unk rej; 6479c5623556SJohan Hedberg 6480c5623556SJohan Hedberg BT_ERR("Wrong link type (%d)", err); 6481c5623556SJohan Hedberg 6482dcf4adbfSJoe Perches rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 64834f3e219dSMarcel Holtmann l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 6484c5623556SJohan Hedberg sizeof(rej), &rej); 6485c5623556SJohan Hedberg } 6486c5623556SJohan Hedberg 64873b166295SMarcel Holtmann drop: 6488c5623556SJohan Hedberg kfree_skb(skb); 6489c5623556SJohan Hedberg } 6490c5623556SJohan Hedberg 64913300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn, 64923300d9a9SClaudio Takahasi struct sk_buff *skb) 64930a708f8fSGustavo F. Padovan { 649469c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon; 649555cee73eSLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd; 64963300d9a9SClaudio Takahasi int err; 64970a708f8fSGustavo F. Padovan 64980a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb); 64990a708f8fSGustavo F. Padovan 650069c4e4e8SJohan Hedberg if (hcon->type != ACL_LINK) 65013b166295SMarcel Holtmann goto drop; 650269c4e4e8SJohan Hedberg 650355cee73eSLuiz Augusto von Dentz while (skb->len >= L2CAP_CMD_HDR_SIZE) { 650455cee73eSLuiz Augusto von Dentz u16 len; 65050a708f8fSGustavo F. Padovan 650655cee73eSLuiz Augusto von Dentz cmd = (void *) skb->data; 650755cee73eSLuiz Augusto von Dentz skb_pull(skb, L2CAP_CMD_HDR_SIZE); 65080a708f8fSGustavo F. Padovan 650955cee73eSLuiz Augusto von Dentz len = le16_to_cpu(cmd->len); 65100a708f8fSGustavo F. Padovan 651155cee73eSLuiz Augusto von Dentz BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, 651255cee73eSLuiz Augusto von Dentz cmd->ident); 651355cee73eSLuiz Augusto von Dentz 651455cee73eSLuiz Augusto von Dentz if (len > skb->len || !cmd->ident) { 65150a708f8fSGustavo F. Padovan BT_DBG("corrupted command"); 65160a708f8fSGustavo F. Padovan break; 65170a708f8fSGustavo F. Padovan } 65180a708f8fSGustavo F. Padovan 651955cee73eSLuiz Augusto von Dentz err = l2cap_bredr_sig_cmd(conn, cmd, len, skb->data); 65200a708f8fSGustavo F. Padovan if (err) { 6521e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk rej; 65222c6d1a2eSGustavo F. Padovan 65232c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err); 65240a708f8fSGustavo F. Padovan 6525dcf4adbfSJoe Perches rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 652655cee73eSLuiz Augusto von Dentz l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 65272d792818SGustavo Padovan sizeof(rej), &rej); 65280a708f8fSGustavo F. Padovan } 65290a708f8fSGustavo F. Padovan 653055cee73eSLuiz Augusto von Dentz skb_pull(skb, len); 65310a708f8fSGustavo F. Padovan } 65320a708f8fSGustavo F. Padovan 65333b166295SMarcel Holtmann drop: 65340a708f8fSGustavo F. Padovan kfree_skb(skb); 65350a708f8fSGustavo F. Padovan } 65360a708f8fSGustavo F. Padovan 653747d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) 65380a708f8fSGustavo F. Padovan { 65390a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs; 6540e4ca6d98SAndrei Emeltchenko int hdr_size; 6541e4ca6d98SAndrei Emeltchenko 6542e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 6543e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE; 6544e4ca6d98SAndrei Emeltchenko else 6545e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE; 65460a708f8fSGustavo F. Padovan 654747d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 654803a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE); 65490a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len); 65500a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); 65510a708f8fSGustavo F. Padovan 65520a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs) 65530a708f8fSGustavo F. Padovan return -EBADMSG; 65540a708f8fSGustavo F. Padovan } 65550a708f8fSGustavo F. Padovan return 0; 65560a708f8fSGustavo F. Padovan } 65570a708f8fSGustavo F. Padovan 65586ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) 65590a708f8fSGustavo F. Padovan { 6560e31f7633SMat Martineau struct l2cap_ctrl control; 65610a708f8fSGustavo F. Padovan 6562e31f7633SMat Martineau BT_DBG("chan %p", chan); 65630a708f8fSGustavo F. Padovan 6564e31f7633SMat Martineau memset(&control, 0, sizeof(control)); 6565e31f7633SMat Martineau control.sframe = 1; 6566e31f7633SMat Martineau control.final = 1; 6567e31f7633SMat Martineau control.reqseq = chan->buffer_seq; 6568e31f7633SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 65690a708f8fSGustavo F. Padovan 6570e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 6571e31f7633SMat Martineau control.super = L2CAP_SUPER_RNR; 6572e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 65730a708f8fSGustavo F. Padovan } 65740a708f8fSGustavo F. Padovan 6575e31f7633SMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 6576e31f7633SMat Martineau chan->unacked_frames > 0) 6577e31f7633SMat Martineau __set_retrans_timer(chan); 65780a708f8fSGustavo F. Padovan 6579e31f7633SMat Martineau /* Send pending iframes */ 6580525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 65810a708f8fSGustavo F. Padovan 6582e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 6583e31f7633SMat Martineau test_bit(CONN_SEND_FBIT, &chan->conn_state)) { 6584e31f7633SMat Martineau /* F-bit wasn't sent in an s-frame or i-frame yet, so 6585e31f7633SMat Martineau * send it now. 6586e31f7633SMat Martineau */ 6587e31f7633SMat Martineau control.super = L2CAP_SUPER_RR; 6588e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 65890a708f8fSGustavo F. Padovan } 65900a708f8fSGustavo F. Padovan } 65910a708f8fSGustavo F. Padovan 65922d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag, 65932d792818SGustavo Padovan struct sk_buff **last_frag) 65940a708f8fSGustavo F. Padovan { 659584084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments 659684084a31SMat Martineau * skb->data_len reflects only data in fragments 659784084a31SMat Martineau */ 659884084a31SMat Martineau if (!skb_has_frag_list(skb)) 659984084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag; 660084084a31SMat Martineau 660184084a31SMat Martineau new_frag->next = NULL; 660284084a31SMat Martineau 660384084a31SMat Martineau (*last_frag)->next = new_frag; 660484084a31SMat Martineau *last_frag = new_frag; 660584084a31SMat Martineau 660684084a31SMat Martineau skb->len += new_frag->len; 660784084a31SMat Martineau skb->data_len += new_frag->len; 660884084a31SMat Martineau skb->truesize += new_frag->truesize; 660984084a31SMat Martineau } 661084084a31SMat Martineau 66114b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, 66124b51dae9SMat Martineau struct l2cap_ctrl *control) 661384084a31SMat Martineau { 661484084a31SMat Martineau int err = -EINVAL; 66150a708f8fSGustavo F. Padovan 66164b51dae9SMat Martineau switch (control->sar) { 66177e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED: 661884084a31SMat Martineau if (chan->sdu) 661984084a31SMat Martineau break; 66200a708f8fSGustavo F. Padovan 662180b98027SGustavo Padovan err = chan->ops->recv(chan, skb); 662284084a31SMat Martineau break; 66230a708f8fSGustavo F. Padovan 66247e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START: 662584084a31SMat Martineau if (chan->sdu) 662684084a31SMat Martineau break; 66270a708f8fSGustavo F. Padovan 6628dbb50887SDaniel Borkmann if (!pskb_may_pull(skb, L2CAP_SDULEN_SIZE)) 6629dbb50887SDaniel Borkmann break; 6630dbb50887SDaniel Borkmann 66316f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data); 663203a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE); 66330a708f8fSGustavo F. Padovan 663484084a31SMat Martineau if (chan->sdu_len > chan->imtu) { 663584084a31SMat Martineau err = -EMSGSIZE; 663684084a31SMat Martineau break; 663784084a31SMat Martineau } 66380a708f8fSGustavo F. Padovan 663984084a31SMat Martineau if (skb->len >= chan->sdu_len) 664084084a31SMat Martineau break; 664184084a31SMat Martineau 664284084a31SMat Martineau chan->sdu = skb; 664384084a31SMat Martineau chan->sdu_last_frag = skb; 664484084a31SMat Martineau 664584084a31SMat Martineau skb = NULL; 664684084a31SMat Martineau err = 0; 66470a708f8fSGustavo F. Padovan break; 66480a708f8fSGustavo F. Padovan 66497e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE: 66506f61fd47SGustavo F. Padovan if (!chan->sdu) 665184084a31SMat Martineau break; 66520a708f8fSGustavo F. Padovan 665384084a31SMat Martineau append_skb_frag(chan->sdu, skb, 665484084a31SMat Martineau &chan->sdu_last_frag); 665584084a31SMat Martineau skb = NULL; 66560a708f8fSGustavo F. Padovan 665784084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len) 665884084a31SMat Martineau break; 66590a708f8fSGustavo F. Padovan 666084084a31SMat Martineau err = 0; 66610a708f8fSGustavo F. Padovan break; 66620a708f8fSGustavo F. Padovan 66637e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END: 66646f61fd47SGustavo F. Padovan if (!chan->sdu) 666584084a31SMat Martineau break; 66660a708f8fSGustavo F. Padovan 666784084a31SMat Martineau append_skb_frag(chan->sdu, skb, 666884084a31SMat Martineau &chan->sdu_last_frag); 666984084a31SMat Martineau skb = NULL; 66700a708f8fSGustavo F. Padovan 667184084a31SMat Martineau if (chan->sdu->len != chan->sdu_len) 667284084a31SMat Martineau break; 66730a708f8fSGustavo F. Padovan 667480b98027SGustavo Padovan err = chan->ops->recv(chan, chan->sdu); 66750a708f8fSGustavo F. Padovan 667684084a31SMat Martineau if (!err) { 667784084a31SMat Martineau /* Reassembly complete */ 667884084a31SMat Martineau chan->sdu = NULL; 667984084a31SMat Martineau chan->sdu_last_frag = NULL; 668084084a31SMat Martineau chan->sdu_len = 0; 66810a708f8fSGustavo F. Padovan } 66820a708f8fSGustavo F. Padovan break; 66830a708f8fSGustavo F. Padovan } 66840a708f8fSGustavo F. Padovan 668584084a31SMat Martineau if (err) { 66860a708f8fSGustavo F. Padovan kfree_skb(skb); 66876f61fd47SGustavo F. Padovan kfree_skb(chan->sdu); 66886f61fd47SGustavo F. Padovan chan->sdu = NULL; 668984084a31SMat Martineau chan->sdu_last_frag = NULL; 669084084a31SMat Martineau chan->sdu_len = 0; 669184084a31SMat Martineau } 66920a708f8fSGustavo F. Padovan 669384084a31SMat Martineau return err; 66940a708f8fSGustavo F. Padovan } 66950a708f8fSGustavo F. Padovan 669632b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan) 669732b32735SMat Martineau { 669832b32735SMat Martineau /* Placeholder */ 669932b32735SMat Martineau return 0; 670032b32735SMat Martineau } 670132b32735SMat Martineau 6702e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 67030a708f8fSGustavo F. Padovan { 670461aa4f5bSMat Martineau u8 event; 670561aa4f5bSMat Martineau 670661aa4f5bSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 670761aa4f5bSMat Martineau return; 670861aa4f5bSMat Martineau 670961aa4f5bSMat Martineau event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR; 6710401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, event); 67110a708f8fSGustavo F. Padovan } 67120a708f8fSGustavo F. Padovan 6713d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan) 6714d2a7ac5dSMat Martineau { 671563838725SMat Martineau int err = 0; 671663838725SMat Martineau /* Pass sequential frames to l2cap_reassemble_sdu() 671763838725SMat Martineau * until a gap is encountered. 671863838725SMat Martineau */ 671963838725SMat Martineau 672063838725SMat Martineau BT_DBG("chan %p", chan); 672163838725SMat Martineau 672263838725SMat Martineau while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 672363838725SMat Martineau struct sk_buff *skb; 672463838725SMat Martineau BT_DBG("Searching for skb with txseq %d (queue len %d)", 672563838725SMat Martineau chan->buffer_seq, skb_queue_len(&chan->srej_q)); 672663838725SMat Martineau 672763838725SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq); 672863838725SMat Martineau 672963838725SMat Martineau if (!skb) 673063838725SMat Martineau break; 673163838725SMat Martineau 673263838725SMat Martineau skb_unlink(skb, &chan->srej_q); 673363838725SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 6734a4368ff3SJohan Hedberg err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->l2cap); 673563838725SMat Martineau if (err) 673663838725SMat Martineau break; 673763838725SMat Martineau } 673863838725SMat Martineau 673963838725SMat Martineau if (skb_queue_empty(&chan->srej_q)) { 674063838725SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 674163838725SMat Martineau l2cap_send_ack(chan); 674263838725SMat Martineau } 674363838725SMat Martineau 674463838725SMat Martineau return err; 6745d2a7ac5dSMat Martineau } 6746d2a7ac5dSMat Martineau 6747d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan, 6748d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 6749d2a7ac5dSMat Martineau { 6750f80842a8SMat Martineau struct sk_buff *skb; 6751f80842a8SMat Martineau 6752f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 6753f80842a8SMat Martineau 6754f80842a8SMat Martineau if (control->reqseq == chan->next_tx_seq) { 6755f80842a8SMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 67565e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6757f80842a8SMat Martineau return; 6758f80842a8SMat Martineau } 6759f80842a8SMat Martineau 6760f80842a8SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 6761f80842a8SMat Martineau 6762f80842a8SMat Martineau if (skb == NULL) { 6763f80842a8SMat Martineau BT_DBG("Seq %d not available for retransmission", 6764f80842a8SMat Martineau control->reqseq); 6765f80842a8SMat Martineau return; 6766f80842a8SMat Martineau } 6767f80842a8SMat Martineau 6768a4368ff3SJohan Hedberg if (chan->max_tx != 0 && bt_cb(skb)->l2cap.retries >= chan->max_tx) { 6769f80842a8SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 67705e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6771f80842a8SMat Martineau return; 6772f80842a8SMat Martineau } 6773f80842a8SMat Martineau 6774f80842a8SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6775f80842a8SMat Martineau 6776f80842a8SMat Martineau if (control->poll) { 6777f80842a8SMat Martineau l2cap_pass_to_tx(chan, control); 6778f80842a8SMat Martineau 6779f80842a8SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6780f80842a8SMat Martineau l2cap_retransmit(chan, control); 6781f80842a8SMat Martineau l2cap_ertm_send(chan); 6782f80842a8SMat Martineau 6783f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 6784f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 6785f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 6786f80842a8SMat Martineau } 6787f80842a8SMat Martineau } else { 6788f80842a8SMat Martineau l2cap_pass_to_tx_fbit(chan, control); 6789f80842a8SMat Martineau 6790f80842a8SMat Martineau if (control->final) { 6791f80842a8SMat Martineau if (chan->srej_save_reqseq != control->reqseq || 6792f80842a8SMat Martineau !test_and_clear_bit(CONN_SREJ_ACT, 6793f80842a8SMat Martineau &chan->conn_state)) 6794f80842a8SMat Martineau l2cap_retransmit(chan, control); 6795f80842a8SMat Martineau } else { 6796f80842a8SMat Martineau l2cap_retransmit(chan, control); 6797f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 6798f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 6799f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 6800f80842a8SMat Martineau } 6801f80842a8SMat Martineau } 6802f80842a8SMat Martineau } 6803d2a7ac5dSMat Martineau } 6804d2a7ac5dSMat Martineau 6805d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan, 6806d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 6807d2a7ac5dSMat Martineau { 6808fcd289dfSMat Martineau struct sk_buff *skb; 6809fcd289dfSMat Martineau 6810fcd289dfSMat Martineau BT_DBG("chan %p, control %p", chan, control); 6811fcd289dfSMat Martineau 6812fcd289dfSMat Martineau if (control->reqseq == chan->next_tx_seq) { 6813fcd289dfSMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 68145e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6815fcd289dfSMat Martineau return; 6816fcd289dfSMat Martineau } 6817fcd289dfSMat Martineau 6818fcd289dfSMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 6819fcd289dfSMat Martineau 6820fcd289dfSMat Martineau if (chan->max_tx && skb && 6821a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries >= chan->max_tx) { 6822fcd289dfSMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 68235e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6824fcd289dfSMat Martineau return; 6825fcd289dfSMat Martineau } 6826fcd289dfSMat Martineau 6827fcd289dfSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6828fcd289dfSMat Martineau 6829fcd289dfSMat Martineau l2cap_pass_to_tx(chan, control); 6830fcd289dfSMat Martineau 6831fcd289dfSMat Martineau if (control->final) { 6832fcd289dfSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 6833fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 6834fcd289dfSMat Martineau } else { 6835fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 6836fcd289dfSMat Martineau l2cap_ertm_send(chan); 6837fcd289dfSMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) 6838fcd289dfSMat Martineau set_bit(CONN_REJ_ACT, &chan->conn_state); 6839fcd289dfSMat Martineau } 6840d2a7ac5dSMat Martineau } 6841d2a7ac5dSMat Martineau 68424b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) 68434b51dae9SMat Martineau { 68444b51dae9SMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 68454b51dae9SMat Martineau 68464b51dae9SMat Martineau BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq, 68474b51dae9SMat Martineau chan->expected_tx_seq); 68484b51dae9SMat Martineau 68494b51dae9SMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 68504b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 68514b51dae9SMat Martineau chan->tx_win) { 68524b51dae9SMat Martineau /* See notes below regarding "double poll" and 68534b51dae9SMat Martineau * invalid packets. 68544b51dae9SMat Martineau */ 68554b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 68564b51dae9SMat Martineau BT_DBG("Invalid/Ignore - after SREJ"); 68574b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 68584b51dae9SMat Martineau } else { 68594b51dae9SMat Martineau BT_DBG("Invalid - in window after SREJ sent"); 68604b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 68614b51dae9SMat Martineau } 68624b51dae9SMat Martineau } 68634b51dae9SMat Martineau 68644b51dae9SMat Martineau if (chan->srej_list.head == txseq) { 68654b51dae9SMat Martineau BT_DBG("Expected SREJ"); 68664b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED_SREJ; 68674b51dae9SMat Martineau } 68684b51dae9SMat Martineau 68694b51dae9SMat Martineau if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) { 68704b51dae9SMat Martineau BT_DBG("Duplicate SREJ - txseq already stored"); 68714b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE_SREJ; 68724b51dae9SMat Martineau } 68734b51dae9SMat Martineau 68744b51dae9SMat Martineau if (l2cap_seq_list_contains(&chan->srej_list, txseq)) { 68754b51dae9SMat Martineau BT_DBG("Unexpected SREJ - not requested"); 68764b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED_SREJ; 68774b51dae9SMat Martineau } 68784b51dae9SMat Martineau } 68794b51dae9SMat Martineau 68804b51dae9SMat Martineau if (chan->expected_tx_seq == txseq) { 68814b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 68824b51dae9SMat Martineau chan->tx_win) { 68834b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 68844b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 68854b51dae9SMat Martineau } else { 68864b51dae9SMat Martineau BT_DBG("Expected"); 68874b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED; 68884b51dae9SMat Martineau } 68894b51dae9SMat Martineau } 68904b51dae9SMat Martineau 68914b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) < 68922d792818SGustavo Padovan __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) { 68934b51dae9SMat Martineau BT_DBG("Duplicate - expected_tx_seq later than txseq"); 68944b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE; 68954b51dae9SMat Martineau } 68964b51dae9SMat Martineau 68974b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) { 68984b51dae9SMat Martineau /* A source of invalid packets is a "double poll" condition, 68994b51dae9SMat Martineau * where delays cause us to send multiple poll packets. If 69004b51dae9SMat Martineau * the remote stack receives and processes both polls, 69014b51dae9SMat Martineau * sequence numbers can wrap around in such a way that a 69024b51dae9SMat Martineau * resent frame has a sequence number that looks like new data 69034b51dae9SMat Martineau * with a sequence gap. This would trigger an erroneous SREJ 69044b51dae9SMat Martineau * request. 69054b51dae9SMat Martineau * 69064b51dae9SMat Martineau * Fortunately, this is impossible with a tx window that's 69074b51dae9SMat Martineau * less than half of the maximum sequence number, which allows 69084b51dae9SMat Martineau * invalid frames to be safely ignored. 69094b51dae9SMat Martineau * 69104b51dae9SMat Martineau * With tx window sizes greater than half of the tx window 69114b51dae9SMat Martineau * maximum, the frame is invalid and cannot be ignored. This 69124b51dae9SMat Martineau * causes a disconnect. 69134b51dae9SMat Martineau */ 69144b51dae9SMat Martineau 69154b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 69164b51dae9SMat Martineau BT_DBG("Invalid/Ignore - txseq outside tx window"); 69174b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 69184b51dae9SMat Martineau } else { 69194b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 69204b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 69214b51dae9SMat Martineau } 69224b51dae9SMat Martineau } else { 69234b51dae9SMat Martineau BT_DBG("Unexpected - txseq indicates missing frames"); 69244b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED; 69254b51dae9SMat Martineau } 69264b51dae9SMat Martineau } 69274b51dae9SMat Martineau 6928d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan, 6929d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 6930d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 6931d2a7ac5dSMat Martineau { 69323aff8aacSMaxim Mikityanskiy struct l2cap_ctrl local_control; 6933d2a7ac5dSMat Martineau int err = 0; 6934941247f9SPeter Senna Tschudin bool skb_in_use = false; 6935d2a7ac5dSMat Martineau 6936d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 6937d2a7ac5dSMat Martineau event); 6938d2a7ac5dSMat Martineau 6939d2a7ac5dSMat Martineau switch (event) { 6940d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 6941d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, control->txseq)) { 6942d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 6943d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6944d2a7ac5dSMat Martineau 6945d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 6946d2a7ac5dSMat Martineau BT_DBG("Busy, discarding expected seq %d", 6947d2a7ac5dSMat Martineau control->txseq); 6948d2a7ac5dSMat Martineau break; 6949d2a7ac5dSMat Martineau } 6950d2a7ac5dSMat Martineau 6951d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, 6952d2a7ac5dSMat Martineau control->txseq); 6953d2a7ac5dSMat Martineau 6954d2a7ac5dSMat Martineau chan->buffer_seq = chan->expected_tx_seq; 6955941247f9SPeter Senna Tschudin skb_in_use = true; 6956d2a7ac5dSMat Martineau 69573aff8aacSMaxim Mikityanskiy /* l2cap_reassemble_sdu may free skb, hence invalidate 69583aff8aacSMaxim Mikityanskiy * control, so make a copy in advance to use it after 69593aff8aacSMaxim Mikityanskiy * l2cap_reassemble_sdu returns and to avoid the race 69603aff8aacSMaxim Mikityanskiy * condition, for example: 69613aff8aacSMaxim Mikityanskiy * 69623aff8aacSMaxim Mikityanskiy * The current thread calls: 69633aff8aacSMaxim Mikityanskiy * l2cap_reassemble_sdu 69643aff8aacSMaxim Mikityanskiy * chan->ops->recv == l2cap_sock_recv_cb 69653aff8aacSMaxim Mikityanskiy * __sock_queue_rcv_skb 69663aff8aacSMaxim Mikityanskiy * Another thread calls: 69673aff8aacSMaxim Mikityanskiy * bt_sock_recvmsg 69683aff8aacSMaxim Mikityanskiy * skb_recv_datagram 69693aff8aacSMaxim Mikityanskiy * skb_free_datagram 69703aff8aacSMaxim Mikityanskiy * Then the current thread tries to access control, but 69713aff8aacSMaxim Mikityanskiy * it was freed by skb_free_datagram. 69723aff8aacSMaxim Mikityanskiy */ 69733aff8aacSMaxim Mikityanskiy local_control = *control; 6974d2a7ac5dSMat Martineau err = l2cap_reassemble_sdu(chan, skb, control); 6975d2a7ac5dSMat Martineau if (err) 6976d2a7ac5dSMat Martineau break; 6977d2a7ac5dSMat Martineau 69783aff8aacSMaxim Mikityanskiy if (local_control.final) { 6979d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 6980d2a7ac5dSMat Martineau &chan->conn_state)) { 69813aff8aacSMaxim Mikityanskiy local_control.final = 0; 69823aff8aacSMaxim Mikityanskiy l2cap_retransmit_all(chan, &local_control); 6983d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6984d2a7ac5dSMat Martineau } 6985d2a7ac5dSMat Martineau } 6986d2a7ac5dSMat Martineau 6987d2a7ac5dSMat Martineau if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 6988d2a7ac5dSMat Martineau l2cap_send_ack(chan); 6989d2a7ac5dSMat Martineau break; 6990d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 6991d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6992d2a7ac5dSMat Martineau 6993d2a7ac5dSMat Martineau /* Can't issue SREJ frames in the local busy state. 6994d2a7ac5dSMat Martineau * Drop this frame, it will be seen as missing 6995d2a7ac5dSMat Martineau * when local busy is exited. 6996d2a7ac5dSMat Martineau */ 6997d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 6998d2a7ac5dSMat Martineau BT_DBG("Busy, discarding unexpected seq %d", 6999d2a7ac5dSMat Martineau control->txseq); 7000d2a7ac5dSMat Martineau break; 7001d2a7ac5dSMat Martineau } 7002d2a7ac5dSMat Martineau 7003d2a7ac5dSMat Martineau /* There was a gap in the sequence, so an SREJ 7004d2a7ac5dSMat Martineau * must be sent for each missing frame. The 7005d2a7ac5dSMat Martineau * current frame is stored for later use. 7006d2a7ac5dSMat Martineau */ 7007d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 7008941247f9SPeter Senna Tschudin skb_in_use = true; 7009d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 7010d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 7011d2a7ac5dSMat Martineau 7012d2a7ac5dSMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 7013d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 7014d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 7015d2a7ac5dSMat Martineau 7016d2a7ac5dSMat Martineau chan->rx_state = L2CAP_RX_STATE_SREJ_SENT; 7017d2a7ac5dSMat Martineau break; 7018d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 7019d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7020d2a7ac5dSMat Martineau break; 7021d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 7022d2a7ac5dSMat Martineau break; 7023d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 7024d2a7ac5dSMat Martineau default: 70255e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 7026d2a7ac5dSMat Martineau break; 7027d2a7ac5dSMat Martineau } 7028d2a7ac5dSMat Martineau break; 7029d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 7030d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7031d2a7ac5dSMat Martineau if (control->final) { 7032d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 7033d2a7ac5dSMat Martineau 7034e6a3ee6eSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) && 7035e6a3ee6eSMat Martineau !__chan_is_moving(chan)) { 7036d2a7ac5dSMat Martineau control->final = 0; 7037d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 7038d2a7ac5dSMat Martineau } 7039d2a7ac5dSMat Martineau 7040d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 7041d2a7ac5dSMat Martineau } else if (control->poll) { 7042d2a7ac5dSMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 7043d2a7ac5dSMat Martineau } else { 7044d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 7045d2a7ac5dSMat Martineau &chan->conn_state) && 7046d2a7ac5dSMat Martineau chan->unacked_frames) 7047d2a7ac5dSMat Martineau __set_retrans_timer(chan); 7048d2a7ac5dSMat Martineau 7049d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 7050d2a7ac5dSMat Martineau } 7051d2a7ac5dSMat Martineau break; 7052d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 7053d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 7054d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7055d2a7ac5dSMat Martineau if (control && control->poll) { 7056d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 7057d2a7ac5dSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 7058d2a7ac5dSMat Martineau } 7059d2a7ac5dSMat Martineau __clear_retrans_timer(chan); 7060d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 7061d2a7ac5dSMat Martineau break; 7062d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 7063d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 7064d2a7ac5dSMat Martineau break; 7065d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 7066d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 7067d2a7ac5dSMat Martineau break; 7068d2a7ac5dSMat Martineau default: 7069d2a7ac5dSMat Martineau break; 7070d2a7ac5dSMat Martineau } 7071d2a7ac5dSMat Martineau 7072d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 7073d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 7074d2a7ac5dSMat Martineau kfree_skb(skb); 7075d2a7ac5dSMat Martineau } 7076d2a7ac5dSMat Martineau 7077d2a7ac5dSMat Martineau return err; 7078d2a7ac5dSMat Martineau } 7079d2a7ac5dSMat Martineau 7080d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, 7081d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 7082d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 7083d2a7ac5dSMat Martineau { 7084d2a7ac5dSMat Martineau int err = 0; 7085d2a7ac5dSMat Martineau u16 txseq = control->txseq; 7086941247f9SPeter Senna Tschudin bool skb_in_use = false; 7087d2a7ac5dSMat Martineau 7088d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 7089d2a7ac5dSMat Martineau event); 7090d2a7ac5dSMat Martineau 7091d2a7ac5dSMat Martineau switch (event) { 7092d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 7093d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, txseq)) { 7094d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 7095d2a7ac5dSMat Martineau /* Keep frame for reassembly later */ 7096d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7097d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 7098941247f9SPeter Senna Tschudin skb_in_use = true; 7099d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 7100d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 7101d2a7ac5dSMat Martineau 7102d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 7103d2a7ac5dSMat Martineau break; 7104d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED_SREJ: 7105d2a7ac5dSMat Martineau l2cap_seq_list_pop(&chan->srej_list); 7106d2a7ac5dSMat Martineau 7107d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7108d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 7109941247f9SPeter Senna Tschudin skb_in_use = true; 7110d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 7111d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 7112d2a7ac5dSMat Martineau 7113d2a7ac5dSMat Martineau err = l2cap_rx_queued_iframes(chan); 7114d2a7ac5dSMat Martineau if (err) 7115d2a7ac5dSMat Martineau break; 7116d2a7ac5dSMat Martineau 7117d2a7ac5dSMat Martineau break; 7118d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 7119d2a7ac5dSMat Martineau /* Got a frame that can't be reassembled yet. 7120d2a7ac5dSMat Martineau * Save it for later, and send SREJs to cover 7121d2a7ac5dSMat Martineau * the missing frames. 7122d2a7ac5dSMat Martineau */ 7123d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 7124941247f9SPeter Senna Tschudin skb_in_use = true; 7125d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 7126d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 7127d2a7ac5dSMat Martineau 7128d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7129d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 7130d2a7ac5dSMat Martineau break; 7131d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED_SREJ: 7132d2a7ac5dSMat Martineau /* This frame was requested with an SREJ, but 7133d2a7ac5dSMat Martineau * some expected retransmitted frames are 7134d2a7ac5dSMat Martineau * missing. Request retransmission of missing 7135d2a7ac5dSMat Martineau * SREJ'd frames. 7136d2a7ac5dSMat Martineau */ 7137d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 7138941247f9SPeter Senna Tschudin skb_in_use = true; 7139d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 7140d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 7141d2a7ac5dSMat Martineau 7142d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7143d2a7ac5dSMat Martineau l2cap_send_srej_list(chan, control->txseq); 7144d2a7ac5dSMat Martineau break; 7145d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE_SREJ: 7146d2a7ac5dSMat Martineau /* We've already queued this frame. Drop this copy. */ 7147d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7148d2a7ac5dSMat Martineau break; 7149d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 7150d2a7ac5dSMat Martineau /* Expecting a later sequence number, so this frame 7151d2a7ac5dSMat Martineau * was already received. Ignore it completely. 7152d2a7ac5dSMat Martineau */ 7153d2a7ac5dSMat Martineau break; 7154d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 7155d2a7ac5dSMat Martineau break; 7156d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 7157d2a7ac5dSMat Martineau default: 71585e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 7159d2a7ac5dSMat Martineau break; 7160d2a7ac5dSMat Martineau } 7161d2a7ac5dSMat Martineau break; 7162d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 7163d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7164d2a7ac5dSMat Martineau if (control->final) { 7165d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 7166d2a7ac5dSMat Martineau 7167d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 7168d2a7ac5dSMat Martineau &chan->conn_state)) { 7169d2a7ac5dSMat Martineau control->final = 0; 7170d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 7171d2a7ac5dSMat Martineau } 7172d2a7ac5dSMat Martineau 7173d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 7174d2a7ac5dSMat Martineau } else if (control->poll) { 7175d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 7176d2a7ac5dSMat Martineau &chan->conn_state) && 7177d2a7ac5dSMat Martineau chan->unacked_frames) { 7178d2a7ac5dSMat Martineau __set_retrans_timer(chan); 7179d2a7ac5dSMat Martineau } 7180d2a7ac5dSMat Martineau 7181d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 7182d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 7183d2a7ac5dSMat Martineau } else { 7184d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 7185d2a7ac5dSMat Martineau &chan->conn_state) && 7186d2a7ac5dSMat Martineau chan->unacked_frames) 7187d2a7ac5dSMat Martineau __set_retrans_timer(chan); 7188d2a7ac5dSMat Martineau 7189d2a7ac5dSMat Martineau l2cap_send_ack(chan); 7190d2a7ac5dSMat Martineau } 7191d2a7ac5dSMat Martineau break; 7192d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 7193d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 7194d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7195d2a7ac5dSMat Martineau if (control->poll) { 7196d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 7197d2a7ac5dSMat Martineau } else { 7198d2a7ac5dSMat Martineau struct l2cap_ctrl rr_control; 7199d2a7ac5dSMat Martineau memset(&rr_control, 0, sizeof(rr_control)); 7200d2a7ac5dSMat Martineau rr_control.sframe = 1; 7201d2a7ac5dSMat Martineau rr_control.super = L2CAP_SUPER_RR; 7202d2a7ac5dSMat Martineau rr_control.reqseq = chan->buffer_seq; 7203d2a7ac5dSMat Martineau l2cap_send_sframe(chan, &rr_control); 7204d2a7ac5dSMat Martineau } 7205d2a7ac5dSMat Martineau 7206d2a7ac5dSMat Martineau break; 7207d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 7208d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 7209d2a7ac5dSMat Martineau break; 7210d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 7211d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 7212d2a7ac5dSMat Martineau break; 7213d2a7ac5dSMat Martineau } 7214d2a7ac5dSMat Martineau 7215d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 7216d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 7217d2a7ac5dSMat Martineau kfree_skb(skb); 7218d2a7ac5dSMat Martineau } 7219d2a7ac5dSMat Martineau 7220d2a7ac5dSMat Martineau return err; 7221d2a7ac5dSMat Martineau } 7222d2a7ac5dSMat Martineau 722332b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan) 722432b32735SMat Martineau { 722532b32735SMat Martineau BT_DBG("chan %p", chan); 722632b32735SMat Martineau 722732b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 722832b32735SMat Martineau 722932b32735SMat Martineau if (chan->hs_hcon) 723032b32735SMat Martineau chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; 723132b32735SMat Martineau else 723232b32735SMat Martineau chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; 723332b32735SMat Martineau 723432b32735SMat Martineau return l2cap_resegment(chan); 723532b32735SMat Martineau } 723632b32735SMat Martineau 723732b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan, 723832b32735SMat Martineau struct l2cap_ctrl *control, 723932b32735SMat Martineau struct sk_buff *skb, u8 event) 724032b32735SMat Martineau { 724132b32735SMat Martineau int err; 724232b32735SMat Martineau 724332b32735SMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 724432b32735SMat Martineau event); 724532b32735SMat Martineau 724632b32735SMat Martineau if (!control->poll) 724732b32735SMat Martineau return -EPROTO; 724832b32735SMat Martineau 724932b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq); 725032b32735SMat Martineau 725132b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q)) 725232b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q); 725332b32735SMat Martineau else 725432b32735SMat Martineau chan->tx_send_head = NULL; 725532b32735SMat Martineau 725632b32735SMat Martineau /* Rewind next_tx_seq to the point expected 725732b32735SMat Martineau * by the receiver. 725832b32735SMat Martineau */ 725932b32735SMat Martineau chan->next_tx_seq = control->reqseq; 726032b32735SMat Martineau chan->unacked_frames = 0; 726132b32735SMat Martineau 726232b32735SMat Martineau err = l2cap_finish_move(chan); 726332b32735SMat Martineau if (err) 726432b32735SMat Martineau return err; 726532b32735SMat Martineau 726632b32735SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 726732b32735SMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 726832b32735SMat Martineau 726932b32735SMat Martineau if (event == L2CAP_EV_RECV_IFRAME) 727032b32735SMat Martineau return -EPROTO; 727132b32735SMat Martineau 727232b32735SMat Martineau return l2cap_rx_state_recv(chan, control, NULL, event); 727332b32735SMat Martineau } 727432b32735SMat Martineau 727532b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan, 727632b32735SMat Martineau struct l2cap_ctrl *control, 727732b32735SMat Martineau struct sk_buff *skb, u8 event) 727832b32735SMat Martineau { 727932b32735SMat Martineau int err; 728032b32735SMat Martineau 728132b32735SMat Martineau if (!control->final) 728232b32735SMat Martineau return -EPROTO; 728332b32735SMat Martineau 728432b32735SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 728532b32735SMat Martineau 728632b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 728732b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq); 728832b32735SMat Martineau 728932b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q)) 729032b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q); 729132b32735SMat Martineau else 729232b32735SMat Martineau chan->tx_send_head = NULL; 729332b32735SMat Martineau 729432b32735SMat Martineau /* Rewind next_tx_seq to the point expected 729532b32735SMat Martineau * by the receiver. 729632b32735SMat Martineau */ 729732b32735SMat Martineau chan->next_tx_seq = control->reqseq; 729832b32735SMat Martineau chan->unacked_frames = 0; 729932b32735SMat Martineau 730032b32735SMat Martineau if (chan->hs_hcon) 730132b32735SMat Martineau chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; 730232b32735SMat Martineau else 730332b32735SMat Martineau chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; 730432b32735SMat Martineau 730532b32735SMat Martineau err = l2cap_resegment(chan); 730632b32735SMat Martineau 730732b32735SMat Martineau if (!err) 730832b32735SMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 730932b32735SMat Martineau 731032b32735SMat Martineau return err; 731132b32735SMat Martineau } 731232b32735SMat Martineau 7313d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq) 7314d2a7ac5dSMat Martineau { 7315d2a7ac5dSMat Martineau /* Make sure reqseq is for a packet that has been sent but not acked */ 7316d2a7ac5dSMat Martineau u16 unacked; 7317d2a7ac5dSMat Martineau 7318d2a7ac5dSMat Martineau unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq); 7319d2a7ac5dSMat Martineau return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked; 7320d2a7ac5dSMat Martineau } 7321d2a7ac5dSMat Martineau 7322cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 7323cec8ab6eSMat Martineau struct sk_buff *skb, u8 event) 73240a708f8fSGustavo F. Padovan { 7325d2a7ac5dSMat Martineau int err = 0; 7326d2a7ac5dSMat Martineau 7327d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan, 7328d2a7ac5dSMat Martineau control, skb, event, chan->rx_state); 7329d2a7ac5dSMat Martineau 7330d2a7ac5dSMat Martineau if (__valid_reqseq(chan, control->reqseq)) { 7331d2a7ac5dSMat Martineau switch (chan->rx_state) { 7332d2a7ac5dSMat Martineau case L2CAP_RX_STATE_RECV: 7333d2a7ac5dSMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 7334d2a7ac5dSMat Martineau break; 7335d2a7ac5dSMat Martineau case L2CAP_RX_STATE_SREJ_SENT: 7336d2a7ac5dSMat Martineau err = l2cap_rx_state_srej_sent(chan, control, skb, 7337d2a7ac5dSMat Martineau event); 7338d2a7ac5dSMat Martineau break; 733932b32735SMat Martineau case L2CAP_RX_STATE_WAIT_P: 734032b32735SMat Martineau err = l2cap_rx_state_wait_p(chan, control, skb, event); 734132b32735SMat Martineau break; 734232b32735SMat Martineau case L2CAP_RX_STATE_WAIT_F: 734332b32735SMat Martineau err = l2cap_rx_state_wait_f(chan, control, skb, event); 734432b32735SMat Martineau break; 7345d2a7ac5dSMat Martineau default: 7346d2a7ac5dSMat Martineau /* shut it down */ 7347d2a7ac5dSMat Martineau break; 7348d2a7ac5dSMat Martineau } 7349d2a7ac5dSMat Martineau } else { 7350d2a7ac5dSMat Martineau BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d", 7351d2a7ac5dSMat Martineau control->reqseq, chan->next_tx_seq, 7352d2a7ac5dSMat Martineau chan->expected_ack_seq); 73535e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 7354d2a7ac5dSMat Martineau } 7355d2a7ac5dSMat Martineau 7356d2a7ac5dSMat Martineau return err; 7357cec8ab6eSMat Martineau } 7358cec8ab6eSMat Martineau 7359cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 7360cec8ab6eSMat Martineau struct sk_buff *skb) 7361cec8ab6eSMat Martineau { 73623aff8aacSMaxim Mikityanskiy /* l2cap_reassemble_sdu may free skb, hence invalidate control, so store 73633aff8aacSMaxim Mikityanskiy * the txseq field in advance to use it after l2cap_reassemble_sdu 73643aff8aacSMaxim Mikityanskiy * returns and to avoid the race condition, for example: 73653aff8aacSMaxim Mikityanskiy * 73663aff8aacSMaxim Mikityanskiy * The current thread calls: 73673aff8aacSMaxim Mikityanskiy * l2cap_reassemble_sdu 73683aff8aacSMaxim Mikityanskiy * chan->ops->recv == l2cap_sock_recv_cb 73693aff8aacSMaxim Mikityanskiy * __sock_queue_rcv_skb 73703aff8aacSMaxim Mikityanskiy * Another thread calls: 73713aff8aacSMaxim Mikityanskiy * bt_sock_recvmsg 73723aff8aacSMaxim Mikityanskiy * skb_recv_datagram 73733aff8aacSMaxim Mikityanskiy * skb_free_datagram 73743aff8aacSMaxim Mikityanskiy * Then the current thread tries to access control, but it was freed by 73753aff8aacSMaxim Mikityanskiy * skb_free_datagram. 73763aff8aacSMaxim Mikityanskiy */ 73773aff8aacSMaxim Mikityanskiy u16 txseq = control->txseq; 73783aff8aacSMaxim Mikityanskiy 73794b51dae9SMat Martineau BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb, 73804b51dae9SMat Martineau chan->rx_state); 73814b51dae9SMat Martineau 73823aff8aacSMaxim Mikityanskiy if (l2cap_classify_txseq(chan, txseq) == L2CAP_TXSEQ_EXPECTED) { 73834b51dae9SMat Martineau l2cap_pass_to_tx(chan, control); 73844b51dae9SMat Martineau 738593917fd2SKai Ye BT_DBG("buffer_seq %u->%u", chan->buffer_seq, 73864b51dae9SMat Martineau __next_seq(chan, chan->buffer_seq)); 73874b51dae9SMat Martineau 73884b51dae9SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 73894b51dae9SMat Martineau 73904b51dae9SMat Martineau l2cap_reassemble_sdu(chan, skb, control); 73914b51dae9SMat Martineau } else { 73924b51dae9SMat Martineau if (chan->sdu) { 73934b51dae9SMat Martineau kfree_skb(chan->sdu); 73944b51dae9SMat Martineau chan->sdu = NULL; 73954b51dae9SMat Martineau } 73964b51dae9SMat Martineau chan->sdu_last_frag = NULL; 73974b51dae9SMat Martineau chan->sdu_len = 0; 73984b51dae9SMat Martineau 73994b51dae9SMat Martineau if (skb) { 74004b51dae9SMat Martineau BT_DBG("Freeing %p", skb); 74014b51dae9SMat Martineau kfree_skb(skb); 74024b51dae9SMat Martineau } 74034b51dae9SMat Martineau } 74044b51dae9SMat Martineau 74053aff8aacSMaxim Mikityanskiy chan->last_acked_seq = txseq; 74063aff8aacSMaxim Mikityanskiy chan->expected_tx_seq = __next_seq(chan, txseq); 74074b51dae9SMat Martineau 74089a544210SPrasanna Karthik return 0; 7409cec8ab6eSMat Martineau } 7410cec8ab6eSMat Martineau 7411cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 7412cec8ab6eSMat Martineau { 7413a4368ff3SJohan Hedberg struct l2cap_ctrl *control = &bt_cb(skb)->l2cap; 7414cec8ab6eSMat Martineau u16 len; 7415cec8ab6eSMat Martineau u8 event; 74160a708f8fSGustavo F. Padovan 7417b76bbd66SMat Martineau __unpack_control(chan, skb); 7418b76bbd66SMat Martineau 74190a708f8fSGustavo F. Padovan len = skb->len; 74200a708f8fSGustavo F. Padovan 74210a708f8fSGustavo F. Padovan /* 74220a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here. 74230a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery 7424cec8ab6eSMat Martineau * procedures and ask for retransmission. 74250a708f8fSGustavo F. Padovan */ 742647d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 74270a708f8fSGustavo F. Padovan goto drop; 74280a708f8fSGustavo F. Padovan 7429cec8ab6eSMat Martineau if (!control->sframe && control->sar == L2CAP_SAR_START) 743003a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 74310a708f8fSGustavo F. Padovan 743247d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 743303a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 74340a708f8fSGustavo F. Padovan 743547d1ec61SGustavo F. Padovan if (len > chan->mps) { 74365e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 74370a708f8fSGustavo F. Padovan goto drop; 74380a708f8fSGustavo F. Padovan } 74390a708f8fSGustavo F. Padovan 7440f1942564SLuiz Augusto von Dentz if (chan->ops->filter) { 7441f1942564SLuiz Augusto von Dentz if (chan->ops->filter(chan, skb)) 7442dbb50887SDaniel Borkmann goto drop; 7443f1942564SLuiz Augusto von Dentz } 7444dbb50887SDaniel Borkmann 7445cec8ab6eSMat Martineau if (!control->sframe) { 7446cec8ab6eSMat Martineau int err; 74470a708f8fSGustavo F. Padovan 7448cec8ab6eSMat Martineau BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d", 7449cec8ab6eSMat Martineau control->sar, control->reqseq, control->final, 7450cec8ab6eSMat Martineau control->txseq); 7451836be934SAndrei Emeltchenko 7452cec8ab6eSMat Martineau /* Validate F-bit - F=0 always valid, F=1 only 7453cec8ab6eSMat Martineau * valid in TX WAIT_F 7454cec8ab6eSMat Martineau */ 7455cec8ab6eSMat Martineau if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F) 74560a708f8fSGustavo F. Padovan goto drop; 74570a708f8fSGustavo F. Padovan 7458cec8ab6eSMat Martineau if (chan->mode != L2CAP_MODE_STREAMING) { 7459cec8ab6eSMat Martineau event = L2CAP_EV_RECV_IFRAME; 7460cec8ab6eSMat Martineau err = l2cap_rx(chan, control, skb, event); 74610a708f8fSGustavo F. Padovan } else { 7462cec8ab6eSMat Martineau err = l2cap_stream_rx(chan, control, skb); 7463cec8ab6eSMat Martineau } 7464cec8ab6eSMat Martineau 7465cec8ab6eSMat Martineau if (err) 74665e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 7467cec8ab6eSMat Martineau } else { 7468cec8ab6eSMat Martineau const u8 rx_func_to_event[4] = { 7469cec8ab6eSMat Martineau L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ, 7470cec8ab6eSMat Martineau L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ 7471cec8ab6eSMat Martineau }; 7472cec8ab6eSMat Martineau 7473cec8ab6eSMat Martineau /* Only I-frames are expected in streaming mode */ 7474cec8ab6eSMat Martineau if (chan->mode == L2CAP_MODE_STREAMING) 7475cec8ab6eSMat Martineau goto drop; 7476cec8ab6eSMat Martineau 7477cec8ab6eSMat Martineau BT_DBG("sframe reqseq %d, final %d, poll %d, super %d", 7478cec8ab6eSMat Martineau control->reqseq, control->final, control->poll, 7479cec8ab6eSMat Martineau control->super); 7480cec8ab6eSMat Martineau 74810a708f8fSGustavo F. Padovan if (len != 0) { 74821bb166e6SAndrei Emeltchenko BT_ERR("Trailing bytes: %d in sframe", len); 74835e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 74840a708f8fSGustavo F. Padovan goto drop; 74850a708f8fSGustavo F. Padovan } 74860a708f8fSGustavo F. Padovan 7487cec8ab6eSMat Martineau /* Validate F and P bits */ 7488cec8ab6eSMat Martineau if (control->final && (control->poll || 7489cec8ab6eSMat Martineau chan->tx_state != L2CAP_TX_STATE_WAIT_F)) 7490cec8ab6eSMat Martineau goto drop; 7491cec8ab6eSMat Martineau 7492cec8ab6eSMat Martineau event = rx_func_to_event[control->super]; 7493cec8ab6eSMat Martineau if (l2cap_rx(chan, control, skb, event)) 74945e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 74950a708f8fSGustavo F. Padovan } 74960a708f8fSGustavo F. Padovan 74970a708f8fSGustavo F. Padovan return 0; 74980a708f8fSGustavo F. Padovan 74990a708f8fSGustavo F. Padovan drop: 75000a708f8fSGustavo F. Padovan kfree_skb(skb); 75010a708f8fSGustavo F. Padovan return 0; 75020a708f8fSGustavo F. Padovan } 75030a708f8fSGustavo F. Padovan 7504b1c325c2SJohan Hedberg static void l2cap_chan_le_send_credits(struct l2cap_chan *chan) 7505b1c325c2SJohan Hedberg { 7506b1c325c2SJohan Hedberg struct l2cap_conn *conn = chan->conn; 7507b1c325c2SJohan Hedberg struct l2cap_le_credits pkt; 7508b1c325c2SJohan Hedberg u16 return_credits; 7509b1c325c2SJohan Hedberg 751015f02b91SLuiz Augusto von Dentz return_credits = (chan->imtu / chan->mps) + 1; 7511b1c325c2SJohan Hedberg 751215f02b91SLuiz Augusto von Dentz if (chan->rx_credits >= return_credits) 751396cd8eaaSLuiz Augusto von Dentz return; 7514b1c325c2SJohan Hedberg 751515f02b91SLuiz Augusto von Dentz return_credits -= chan->rx_credits; 751615f02b91SLuiz Augusto von Dentz 7517b1c325c2SJohan Hedberg BT_DBG("chan %p returning %u credits to sender", chan, return_credits); 7518b1c325c2SJohan Hedberg 7519b1c325c2SJohan Hedberg chan->rx_credits += return_credits; 7520b1c325c2SJohan Hedberg 7521b1c325c2SJohan Hedberg pkt.cid = cpu_to_le16(chan->scid); 7522b1c325c2SJohan Hedberg pkt.credits = cpu_to_le16(return_credits); 7523b1c325c2SJohan Hedberg 7524b1c325c2SJohan Hedberg chan->ident = l2cap_get_ident(conn); 7525b1c325c2SJohan Hedberg 7526b1c325c2SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt); 7527b1c325c2SJohan Hedberg } 7528b1c325c2SJohan Hedberg 752915f02b91SLuiz Augusto von Dentz static int l2cap_ecred_recv(struct l2cap_chan *chan, struct sk_buff *skb) 753096cd8eaaSLuiz Augusto von Dentz { 753196cd8eaaSLuiz Augusto von Dentz int err; 753296cd8eaaSLuiz Augusto von Dentz 753396cd8eaaSLuiz Augusto von Dentz BT_DBG("SDU reassemble complete: chan %p skb->len %u", chan, skb->len); 753496cd8eaaSLuiz Augusto von Dentz 753596cd8eaaSLuiz Augusto von Dentz /* Wait recv to confirm reception before updating the credits */ 753696cd8eaaSLuiz Augusto von Dentz err = chan->ops->recv(chan, skb); 753796cd8eaaSLuiz Augusto von Dentz 753896cd8eaaSLuiz Augusto von Dentz /* Update credits whenever an SDU is received */ 753996cd8eaaSLuiz Augusto von Dentz l2cap_chan_le_send_credits(chan); 754096cd8eaaSLuiz Augusto von Dentz 754196cd8eaaSLuiz Augusto von Dentz return err; 754296cd8eaaSLuiz Augusto von Dentz } 754396cd8eaaSLuiz Augusto von Dentz 754415f02b91SLuiz Augusto von Dentz static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 7545fad5fc89SJohan Hedberg { 7546aac23bf6SJohan Hedberg int err; 7547fad5fc89SJohan Hedberg 7548aac23bf6SJohan Hedberg if (!chan->rx_credits) { 7549aac23bf6SJohan Hedberg BT_ERR("No credits to receive LE L2CAP data"); 7550dfd9774cSJohan Hedberg l2cap_send_disconn_req(chan, ECONNRESET); 7551fad5fc89SJohan Hedberg return -ENOBUFS; 7552aac23bf6SJohan Hedberg } 7553aac23bf6SJohan Hedberg 7554aac23bf6SJohan Hedberg if (chan->imtu < skb->len) { 7555aac23bf6SJohan Hedberg BT_ERR("Too big LE L2CAP PDU"); 7556aac23bf6SJohan Hedberg return -ENOBUFS; 7557aac23bf6SJohan Hedberg } 7558fad5fc89SJohan Hedberg 7559fad5fc89SJohan Hedberg chan->rx_credits--; 7560fad5fc89SJohan Hedberg BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits); 7561fad5fc89SJohan Hedberg 756296cd8eaaSLuiz Augusto von Dentz /* Update if remote had run out of credits, this should only happens 756396cd8eaaSLuiz Augusto von Dentz * if the remote is not using the entire MPS. 756496cd8eaaSLuiz Augusto von Dentz */ 756596cd8eaaSLuiz Augusto von Dentz if (!chan->rx_credits) 7566fad5fc89SJohan Hedberg l2cap_chan_le_send_credits(chan); 7567fad5fc89SJohan Hedberg 7568aac23bf6SJohan Hedberg err = 0; 7569aac23bf6SJohan Hedberg 7570aac23bf6SJohan Hedberg if (!chan->sdu) { 7571aac23bf6SJohan Hedberg u16 sdu_len; 7572aac23bf6SJohan Hedberg 7573aac23bf6SJohan Hedberg sdu_len = get_unaligned_le16(skb->data); 7574aac23bf6SJohan Hedberg skb_pull(skb, L2CAP_SDULEN_SIZE); 7575aac23bf6SJohan Hedberg 7576aac23bf6SJohan Hedberg BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u", 7577aac23bf6SJohan Hedberg sdu_len, skb->len, chan->imtu); 7578aac23bf6SJohan Hedberg 7579aac23bf6SJohan Hedberg if (sdu_len > chan->imtu) { 7580aac23bf6SJohan Hedberg BT_ERR("Too big LE L2CAP SDU length received"); 7581aac23bf6SJohan Hedberg err = -EMSGSIZE; 7582aac23bf6SJohan Hedberg goto failed; 7583aac23bf6SJohan Hedberg } 7584aac23bf6SJohan Hedberg 7585aac23bf6SJohan Hedberg if (skb->len > sdu_len) { 7586aac23bf6SJohan Hedberg BT_ERR("Too much LE L2CAP data received"); 7587aac23bf6SJohan Hedberg err = -EINVAL; 7588aac23bf6SJohan Hedberg goto failed; 7589aac23bf6SJohan Hedberg } 7590aac23bf6SJohan Hedberg 7591aac23bf6SJohan Hedberg if (skb->len == sdu_len) 759215f02b91SLuiz Augusto von Dentz return l2cap_ecred_recv(chan, skb); 7593aac23bf6SJohan Hedberg 7594aac23bf6SJohan Hedberg chan->sdu = skb; 7595aac23bf6SJohan Hedberg chan->sdu_len = sdu_len; 7596aac23bf6SJohan Hedberg chan->sdu_last_frag = skb; 7597aac23bf6SJohan Hedberg 7598a5c3021bSLuiz Augusto von Dentz /* Detect if remote is not able to use the selected MPS */ 7599a5c3021bSLuiz Augusto von Dentz if (skb->len + L2CAP_SDULEN_SIZE < chan->mps) { 7600a5c3021bSLuiz Augusto von Dentz u16 mps_len = skb->len + L2CAP_SDULEN_SIZE; 7601a5c3021bSLuiz Augusto von Dentz 7602a5c3021bSLuiz Augusto von Dentz /* Adjust the number of credits */ 7603a5c3021bSLuiz Augusto von Dentz BT_DBG("chan->mps %u -> %u", chan->mps, mps_len); 7604a5c3021bSLuiz Augusto von Dentz chan->mps = mps_len; 7605a5c3021bSLuiz Augusto von Dentz l2cap_chan_le_send_credits(chan); 7606a5c3021bSLuiz Augusto von Dentz } 7607a5c3021bSLuiz Augusto von Dentz 7608aac23bf6SJohan Hedberg return 0; 7609aac23bf6SJohan Hedberg } 7610aac23bf6SJohan Hedberg 7611aac23bf6SJohan Hedberg BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u", 7612aac23bf6SJohan Hedberg chan->sdu->len, skb->len, chan->sdu_len); 7613aac23bf6SJohan Hedberg 7614aac23bf6SJohan Hedberg if (chan->sdu->len + skb->len > chan->sdu_len) { 7615aac23bf6SJohan Hedberg BT_ERR("Too much LE L2CAP data received"); 7616aac23bf6SJohan Hedberg err = -EINVAL; 7617aac23bf6SJohan Hedberg goto failed; 7618aac23bf6SJohan Hedberg } 7619aac23bf6SJohan Hedberg 7620aac23bf6SJohan Hedberg append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag); 7621aac23bf6SJohan Hedberg skb = NULL; 7622aac23bf6SJohan Hedberg 7623aac23bf6SJohan Hedberg if (chan->sdu->len == chan->sdu_len) { 762415f02b91SLuiz Augusto von Dentz err = l2cap_ecred_recv(chan, chan->sdu); 7625aac23bf6SJohan Hedberg if (!err) { 7626aac23bf6SJohan Hedberg chan->sdu = NULL; 7627aac23bf6SJohan Hedberg chan->sdu_last_frag = NULL; 7628aac23bf6SJohan Hedberg chan->sdu_len = 0; 7629aac23bf6SJohan Hedberg } 7630aac23bf6SJohan Hedberg } 7631aac23bf6SJohan Hedberg 7632aac23bf6SJohan Hedberg failed: 7633aac23bf6SJohan Hedberg if (err) { 7634aac23bf6SJohan Hedberg kfree_skb(skb); 7635aac23bf6SJohan Hedberg kfree_skb(chan->sdu); 7636aac23bf6SJohan Hedberg chan->sdu = NULL; 7637aac23bf6SJohan Hedberg chan->sdu_last_frag = NULL; 7638aac23bf6SJohan Hedberg chan->sdu_len = 0; 7639aac23bf6SJohan Hedberg } 7640aac23bf6SJohan Hedberg 7641aac23bf6SJohan Hedberg /* We can't return an error here since we took care of the skb 7642aac23bf6SJohan Hedberg * freeing internally. An error return would cause the caller to 7643aac23bf6SJohan Hedberg * do a double-free of the skb. 7644aac23bf6SJohan Hedberg */ 7645aac23bf6SJohan Hedberg return 0; 7646fad5fc89SJohan Hedberg } 7647fad5fc89SJohan Hedberg 764813ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid, 764913ca56e0SAndrei Emeltchenko struct sk_buff *skb) 76500a708f8fSGustavo F. Padovan { 765148454079SGustavo F. Padovan struct l2cap_chan *chan; 76520a708f8fSGustavo F. Padovan 7653baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 765448454079SGustavo F. Padovan if (!chan) { 765597e8e89dSAndrei Emeltchenko if (cid == L2CAP_CID_A2MP) { 765697e8e89dSAndrei Emeltchenko chan = a2mp_channel_create(conn, skb); 765797e8e89dSAndrei Emeltchenko if (!chan) { 765897e8e89dSAndrei Emeltchenko kfree_skb(skb); 765913ca56e0SAndrei Emeltchenko return; 766097e8e89dSAndrei Emeltchenko } 766197e8e89dSAndrei Emeltchenko 76620d0e2d03SZhengchao Shao l2cap_chan_hold(chan); 766397e8e89dSAndrei Emeltchenko l2cap_chan_lock(chan); 766497e8e89dSAndrei Emeltchenko } else { 76650a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid); 76666be36555SAndrei Emeltchenko /* Drop packet and return */ 76673379013bSDan Carpenter kfree_skb(skb); 766813ca56e0SAndrei Emeltchenko return; 76690a708f8fSGustavo F. Padovan } 767097e8e89dSAndrei Emeltchenko } 76710a708f8fSGustavo F. Padovan 767249208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len); 76730a708f8fSGustavo F. Padovan 7674315917e0SJohan Hedberg /* If we receive data on a fixed channel before the info req/rsp 76755153ceb9SBhaskar Chowdhury * procedure is done simply assume that the channel is supported 7676315917e0SJohan Hedberg * and mark it as ready. 7677315917e0SJohan Hedberg */ 7678315917e0SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_FIXED) 7679315917e0SJohan Hedberg l2cap_chan_ready(chan); 7680315917e0SJohan Hedberg 768189bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 76820a708f8fSGustavo F. Padovan goto drop; 76830a708f8fSGustavo F. Padovan 76840c1bc5c6SGustavo F. Padovan switch (chan->mode) { 768538319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 768615f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL: 768715f02b91SLuiz Augusto von Dentz if (l2cap_ecred_data_rcv(chan, skb) < 0) 7688fad5fc89SJohan Hedberg goto drop; 7689fad5fc89SJohan Hedberg 7690fad5fc89SJohan Hedberg goto done; 7691fad5fc89SJohan Hedberg 76920a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 76930a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here 76940a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable. 76950a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't 76960a708f8fSGustavo F. Padovan * provide flow control mechanism. */ 76970a708f8fSGustavo F. Padovan 76982c96e03dSSzymon Janc if (chan->imtu < skb->len) { 76992c96e03dSSzymon Janc BT_ERR("Dropping L2CAP data: receive buffer overflow"); 77000a708f8fSGustavo F. Padovan goto drop; 77012c96e03dSSzymon Janc } 77020a708f8fSGustavo F. Padovan 770380b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 77040a708f8fSGustavo F. Padovan goto done; 77050a708f8fSGustavo F. Padovan break; 77060a708f8fSGustavo F. Padovan 77070a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 77080a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 7709cec8ab6eSMat Martineau l2cap_data_rcv(chan, skb); 77100a708f8fSGustavo F. Padovan goto done; 77110a708f8fSGustavo F. Padovan 77120a708f8fSGustavo F. Padovan default: 77130c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); 77140a708f8fSGustavo F. Padovan break; 77150a708f8fSGustavo F. Padovan } 77160a708f8fSGustavo F. Padovan 77170a708f8fSGustavo F. Padovan drop: 77180a708f8fSGustavo F. Padovan kfree_skb(skb); 77190a708f8fSGustavo F. Padovan 77200a708f8fSGustavo F. Padovan done: 77216be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 7722d0be8347SLuiz Augusto von Dentz l2cap_chan_put(chan); 77230a708f8fSGustavo F. Padovan } 77240a708f8fSGustavo F. Padovan 772584104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, 772684104b24SAndrei Emeltchenko struct sk_buff *skb) 77270a708f8fSGustavo F. Padovan { 7728ae4fd2d3SMarcel Holtmann struct hci_conn *hcon = conn->hcon; 772923691d75SGustavo F. Padovan struct l2cap_chan *chan; 77300a708f8fSGustavo F. Padovan 7731ae4fd2d3SMarcel Holtmann if (hcon->type != ACL_LINK) 7732a24cce14SJohan Hedberg goto free_skb; 7733ae4fd2d3SMarcel Holtmann 7734bf20fd4eSJohan Hedberg chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst, 7735bf20fd4eSJohan Hedberg ACL_LINK); 773623691d75SGustavo F. Padovan if (!chan) 7737a24cce14SJohan Hedberg goto free_skb; 77380a708f8fSGustavo F. Padovan 77395b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 77400a708f8fSGustavo F. Padovan 774189bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 77420a708f8fSGustavo F. Padovan goto drop; 77430a708f8fSGustavo F. Padovan 7744e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 77450a708f8fSGustavo F. Padovan goto drop; 77460a708f8fSGustavo F. Padovan 77472edf870dSMarcel Holtmann /* Store remote BD_ADDR and PSM for msg_name */ 7748a4368ff3SJohan Hedberg bacpy(&bt_cb(skb)->l2cap.bdaddr, &hcon->dst); 7749a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.psm = psm; 77502edf870dSMarcel Holtmann 7751a24cce14SJohan Hedberg if (!chan->ops->recv(chan, skb)) { 7752a24cce14SJohan Hedberg l2cap_chan_put(chan); 775384104b24SAndrei Emeltchenko return; 7754a24cce14SJohan Hedberg } 77550a708f8fSGustavo F. Padovan 77560a708f8fSGustavo F. Padovan drop: 7757a24cce14SJohan Hedberg l2cap_chan_put(chan); 7758a24cce14SJohan Hedberg free_skb: 77590a708f8fSGustavo F. Padovan kfree_skb(skb); 77600a708f8fSGustavo F. Padovan } 77610a708f8fSGustavo F. Padovan 77620a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) 77630a708f8fSGustavo F. Padovan { 77640a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data; 776561a939c6SJohan Hedberg struct hci_conn *hcon = conn->hcon; 77660a708f8fSGustavo F. Padovan u16 cid, len; 77670a708f8fSGustavo F. Padovan __le16 psm; 77680a708f8fSGustavo F. Padovan 776961a939c6SJohan Hedberg if (hcon->state != BT_CONNECTED) { 777061a939c6SJohan Hedberg BT_DBG("queueing pending rx skb"); 777161a939c6SJohan Hedberg skb_queue_tail(&conn->pending_rx, skb); 777261a939c6SJohan Hedberg return; 777361a939c6SJohan Hedberg } 777461a939c6SJohan Hedberg 77750a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE); 77760a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid); 77770a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len); 77780a708f8fSGustavo F. Padovan 77790a708f8fSGustavo F. Padovan if (len != skb->len) { 77800a708f8fSGustavo F. Padovan kfree_skb(skb); 77810a708f8fSGustavo F. Padovan return; 77820a708f8fSGustavo F. Padovan } 77830a708f8fSGustavo F. Padovan 77849e1d7e15SJohan Hedberg /* Since we can't actively block incoming LE connections we must 77859e1d7e15SJohan Hedberg * at least ensure that we ignore incoming data from them. 77869e1d7e15SJohan Hedberg */ 77879e1d7e15SJohan Hedberg if (hcon->type == LE_LINK && 77883d4f9c00SArchie Pusaka hci_bdaddr_list_lookup(&hcon->hdev->reject_list, &hcon->dst, 7789a250e048SJohan Hedberg bdaddr_dst_type(hcon))) { 7790e493150eSJohan Hedberg kfree_skb(skb); 7791e493150eSJohan Hedberg return; 7792e493150eSJohan Hedberg } 7793e493150eSJohan Hedberg 77940a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid); 77950a708f8fSGustavo F. Padovan 77960a708f8fSGustavo F. Padovan switch (cid) { 77970a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING: 77980a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb); 77990a708f8fSGustavo F. Padovan break; 78000a708f8fSGustavo F. Padovan 78010a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS: 7802097db76cSAndrei Emeltchenko psm = get_unaligned((__le16 *) skb->data); 78030181a70fSAndrei Emeltchenko skb_pull(skb, L2CAP_PSMLEN_SIZE); 78040a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb); 78050a708f8fSGustavo F. Padovan break; 78060a708f8fSGustavo F. Padovan 7807a2877629SMarcel Holtmann case L2CAP_CID_LE_SIGNALING: 7808a2877629SMarcel Holtmann l2cap_le_sig_channel(conn, skb); 7809a2877629SMarcel Holtmann break; 7810a2877629SMarcel Holtmann 78110a708f8fSGustavo F. Padovan default: 78120a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb); 78130a708f8fSGustavo F. Padovan break; 78140a708f8fSGustavo F. Padovan } 78150a708f8fSGustavo F. Padovan } 78160a708f8fSGustavo F. Padovan 781761a939c6SJohan Hedberg static void process_pending_rx(struct work_struct *work) 781861a939c6SJohan Hedberg { 781961a939c6SJohan Hedberg struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 782061a939c6SJohan Hedberg pending_rx_work); 782161a939c6SJohan Hedberg struct sk_buff *skb; 782261a939c6SJohan Hedberg 782361a939c6SJohan Hedberg BT_DBG(""); 782461a939c6SJohan Hedberg 782561a939c6SJohan Hedberg while ((skb = skb_dequeue(&conn->pending_rx))) 782661a939c6SJohan Hedberg l2cap_recv_frame(conn, skb); 782761a939c6SJohan Hedberg } 782861a939c6SJohan Hedberg 7829162b49e7SJohan Hedberg static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) 7830162b49e7SJohan Hedberg { 7831162b49e7SJohan Hedberg struct l2cap_conn *conn = hcon->l2cap_data; 7832162b49e7SJohan Hedberg struct hci_chan *hchan; 7833162b49e7SJohan Hedberg 7834162b49e7SJohan Hedberg if (conn) 7835162b49e7SJohan Hedberg return conn; 7836162b49e7SJohan Hedberg 7837162b49e7SJohan Hedberg hchan = hci_chan_create(hcon); 7838162b49e7SJohan Hedberg if (!hchan) 7839162b49e7SJohan Hedberg return NULL; 7840162b49e7SJohan Hedberg 784127f70f3eSJohan Hedberg conn = kzalloc(sizeof(*conn), GFP_KERNEL); 7842162b49e7SJohan Hedberg if (!conn) { 7843162b49e7SJohan Hedberg hci_chan_del(hchan); 7844162b49e7SJohan Hedberg return NULL; 7845162b49e7SJohan Hedberg } 7846162b49e7SJohan Hedberg 7847162b49e7SJohan Hedberg kref_init(&conn->ref); 7848162b49e7SJohan Hedberg hcon->l2cap_data = conn; 784951bb8457SJohan Hedberg conn->hcon = hci_conn_get(hcon); 7850162b49e7SJohan Hedberg conn->hchan = hchan; 7851162b49e7SJohan Hedberg 7852162b49e7SJohan Hedberg BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); 7853162b49e7SJohan Hedberg 7854162b49e7SJohan Hedberg switch (hcon->type) { 7855162b49e7SJohan Hedberg case LE_LINK: 7856162b49e7SJohan Hedberg if (hcon->hdev->le_mtu) { 7857162b49e7SJohan Hedberg conn->mtu = hcon->hdev->le_mtu; 7858162b49e7SJohan Hedberg break; 7859162b49e7SJohan Hedberg } 786019186c7bSGustavo A. R. Silva fallthrough; 7861162b49e7SJohan Hedberg default: 7862162b49e7SJohan Hedberg conn->mtu = hcon->hdev->acl_mtu; 7863162b49e7SJohan Hedberg break; 7864162b49e7SJohan Hedberg } 7865162b49e7SJohan Hedberg 7866162b49e7SJohan Hedberg conn->feat_mask = 0; 7867162b49e7SJohan Hedberg 78680bd49fc7SJohan Hedberg conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS; 78690bd49fc7SJohan Hedberg 78700bd49fc7SJohan Hedberg if (hcon->type == ACL_LINK && 7871d7a5a11dSMarcel Holtmann hci_dev_test_flag(hcon->hdev, HCI_HS_ENABLED)) 78720bd49fc7SJohan Hedberg conn->local_fixed_chan |= L2CAP_FC_A2MP; 7873162b49e7SJohan Hedberg 7874d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED) && 7875f9be9e86SMarcel Holtmann (bredr_sc_enabled(hcon->hdev) || 7876b7cb93e5SMarcel Holtmann hci_dev_test_flag(hcon->hdev, HCI_FORCE_BREDR_SMP))) 7877b5ae344dSJohan Hedberg conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR; 7878b5ae344dSJohan Hedberg 78795a54e7c8SMarcel Holtmann mutex_init(&conn->ident_lock); 7880162b49e7SJohan Hedberg mutex_init(&conn->chan_lock); 7881162b49e7SJohan Hedberg 7882162b49e7SJohan Hedberg INIT_LIST_HEAD(&conn->chan_l); 7883162b49e7SJohan Hedberg INIT_LIST_HEAD(&conn->users); 7884162b49e7SJohan Hedberg 7885162b49e7SJohan Hedberg INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); 7886162b49e7SJohan Hedberg 788761a939c6SJohan Hedberg skb_queue_head_init(&conn->pending_rx); 788861a939c6SJohan Hedberg INIT_WORK(&conn->pending_rx_work, process_pending_rx); 7889f3d82d0cSJohan Hedberg INIT_WORK(&conn->id_addr_update_work, l2cap_conn_update_id_addr); 789061a939c6SJohan Hedberg 7891162b49e7SJohan Hedberg conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 7892162b49e7SJohan Hedberg 7893162b49e7SJohan Hedberg return conn; 7894162b49e7SJohan Hedberg } 7895162b49e7SJohan Hedberg 7896149b3f13SMeng Yu static bool is_valid_psm(u16 psm, u8 dst_type) 7897149b3f13SMeng Yu { 7898162b49e7SJohan Hedberg if (!psm) 7899162b49e7SJohan Hedberg return false; 7900162b49e7SJohan Hedberg 7901162b49e7SJohan Hedberg if (bdaddr_type_is_le(dst_type)) 7902162b49e7SJohan Hedberg return (psm <= 0x00ff); 7903162b49e7SJohan Hedberg 7904162b49e7SJohan Hedberg /* PSM must be odd and lsb of upper byte must be 0 */ 7905162b49e7SJohan Hedberg return ((psm & 0x0101) == 0x0001); 7906162b49e7SJohan Hedberg } 7907162b49e7SJohan Hedberg 7908da49b602SLuiz Augusto von Dentz struct l2cap_chan_data { 7909da49b602SLuiz Augusto von Dentz struct l2cap_chan *chan; 7910da49b602SLuiz Augusto von Dentz struct pid *pid; 7911da49b602SLuiz Augusto von Dentz int count; 7912da49b602SLuiz Augusto von Dentz }; 7913da49b602SLuiz Augusto von Dentz 7914da49b602SLuiz Augusto von Dentz static void l2cap_chan_by_pid(struct l2cap_chan *chan, void *data) 7915da49b602SLuiz Augusto von Dentz { 7916da49b602SLuiz Augusto von Dentz struct l2cap_chan_data *d = data; 7917da49b602SLuiz Augusto von Dentz struct pid *pid; 7918da49b602SLuiz Augusto von Dentz 7919da49b602SLuiz Augusto von Dentz if (chan == d->chan) 7920da49b602SLuiz Augusto von Dentz return; 7921da49b602SLuiz Augusto von Dentz 7922da49b602SLuiz Augusto von Dentz if (!test_bit(FLAG_DEFER_SETUP, &chan->flags)) 7923da49b602SLuiz Augusto von Dentz return; 7924da49b602SLuiz Augusto von Dentz 7925da49b602SLuiz Augusto von Dentz pid = chan->ops->get_peer_pid(chan); 7926da49b602SLuiz Augusto von Dentz 7927da49b602SLuiz Augusto von Dentz /* Only count deferred channels with the same PID/PSM */ 7928da49b602SLuiz Augusto von Dentz if (d->pid != pid || chan->psm != d->chan->psm || chan->ident || 7929da49b602SLuiz Augusto von Dentz chan->mode != L2CAP_MODE_EXT_FLOWCTL || chan->state != BT_CONNECT) 7930da49b602SLuiz Augusto von Dentz return; 7931da49b602SLuiz Augusto von Dentz 7932da49b602SLuiz Augusto von Dentz d->count++; 7933da49b602SLuiz Augusto von Dentz } 7934da49b602SLuiz Augusto von Dentz 7935162b49e7SJohan Hedberg int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, 7936162b49e7SJohan Hedberg bdaddr_t *dst, u8 dst_type) 7937162b49e7SJohan Hedberg { 7938162b49e7SJohan Hedberg struct l2cap_conn *conn; 7939162b49e7SJohan Hedberg struct hci_conn *hcon; 7940162b49e7SJohan Hedberg struct hci_dev *hdev; 7941162b49e7SJohan Hedberg int err; 7942162b49e7SJohan Hedberg 794315f02b91SLuiz Augusto von Dentz BT_DBG("%pMR -> %pMR (type %u) psm 0x%4.4x mode 0x%2.2x", &chan->src, 794415f02b91SLuiz Augusto von Dentz dst, dst_type, __le16_to_cpu(psm), chan->mode); 7945162b49e7SJohan Hedberg 794639385cb5SJohan Hedberg hdev = hci_get_route(dst, &chan->src, chan->src_type); 7947162b49e7SJohan Hedberg if (!hdev) 7948162b49e7SJohan Hedberg return -EHOSTUNREACH; 7949162b49e7SJohan Hedberg 7950162b49e7SJohan Hedberg hci_dev_lock(hdev); 7951162b49e7SJohan Hedberg 7952162b49e7SJohan Hedberg if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid && 7953162b49e7SJohan Hedberg chan->chan_type != L2CAP_CHAN_RAW) { 7954162b49e7SJohan Hedberg err = -EINVAL; 7955162b49e7SJohan Hedberg goto done; 7956162b49e7SJohan Hedberg } 7957162b49e7SJohan Hedberg 795821626e62SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !psm) { 795921626e62SJohan Hedberg err = -EINVAL; 796021626e62SJohan Hedberg goto done; 796121626e62SJohan Hedberg } 796221626e62SJohan Hedberg 796321626e62SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_FIXED && !cid) { 7964162b49e7SJohan Hedberg err = -EINVAL; 7965162b49e7SJohan Hedberg goto done; 7966162b49e7SJohan Hedberg } 7967162b49e7SJohan Hedberg 7968162b49e7SJohan Hedberg switch (chan->mode) { 7969162b49e7SJohan Hedberg case L2CAP_MODE_BASIC: 7970162b49e7SJohan Hedberg break; 7971162b49e7SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 79724be5ca67SLuiz Augusto von Dentz break; 797315f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL: 79744be5ca67SLuiz Augusto von Dentz if (!enable_ecred) { 79754be5ca67SLuiz Augusto von Dentz err = -EOPNOTSUPP; 79764be5ca67SLuiz Augusto von Dentz goto done; 79774be5ca67SLuiz Augusto von Dentz } 7978162b49e7SJohan Hedberg break; 7979162b49e7SJohan Hedberg case L2CAP_MODE_ERTM: 7980162b49e7SJohan Hedberg case L2CAP_MODE_STREAMING: 7981162b49e7SJohan Hedberg if (!disable_ertm) 7982162b49e7SJohan Hedberg break; 798319186c7bSGustavo A. R. Silva fallthrough; 7984162b49e7SJohan Hedberg default: 7985beb19e4cSJohan Hedberg err = -EOPNOTSUPP; 7986162b49e7SJohan Hedberg goto done; 7987162b49e7SJohan Hedberg } 7988162b49e7SJohan Hedberg 7989162b49e7SJohan Hedberg switch (chan->state) { 7990162b49e7SJohan Hedberg case BT_CONNECT: 7991162b49e7SJohan Hedberg case BT_CONNECT2: 7992162b49e7SJohan Hedberg case BT_CONFIG: 7993162b49e7SJohan Hedberg /* Already connecting */ 7994162b49e7SJohan Hedberg err = 0; 7995162b49e7SJohan Hedberg goto done; 7996162b49e7SJohan Hedberg 7997162b49e7SJohan Hedberg case BT_CONNECTED: 7998162b49e7SJohan Hedberg /* Already connected */ 7999162b49e7SJohan Hedberg err = -EISCONN; 8000162b49e7SJohan Hedberg goto done; 8001162b49e7SJohan Hedberg 8002162b49e7SJohan Hedberg case BT_OPEN: 8003162b49e7SJohan Hedberg case BT_BOUND: 8004162b49e7SJohan Hedberg /* Can connect */ 8005162b49e7SJohan Hedberg break; 8006162b49e7SJohan Hedberg 8007162b49e7SJohan Hedberg default: 8008162b49e7SJohan Hedberg err = -EBADFD; 8009162b49e7SJohan Hedberg goto done; 8010162b49e7SJohan Hedberg } 8011162b49e7SJohan Hedberg 8012162b49e7SJohan Hedberg /* Set destination address and psm */ 8013162b49e7SJohan Hedberg bacpy(&chan->dst, dst); 8014162b49e7SJohan Hedberg chan->dst_type = dst_type; 8015162b49e7SJohan Hedberg 8016162b49e7SJohan Hedberg chan->psm = psm; 8017162b49e7SJohan Hedberg chan->dcid = cid; 8018162b49e7SJohan Hedberg 80196f77d8c7SAndre Guedes if (bdaddr_type_is_le(dst_type)) { 80206f77d8c7SAndre Guedes /* Convert from L2CAP channel address type to HCI address type 80216f77d8c7SAndre Guedes */ 80226f77d8c7SAndre Guedes if (dst_type == BDADDR_LE_PUBLIC) 80236f77d8c7SAndre Guedes dst_type = ADDR_LE_DEV_PUBLIC; 80246f77d8c7SAndre Guedes else 80256f77d8c7SAndre Guedes dst_type = ADDR_LE_DEV_RANDOM; 80266f77d8c7SAndre Guedes 8027d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) 8028d850bf08SLuiz Augusto von Dentz hcon = hci_connect_le(hdev, dst, dst_type, false, 8029fa142220SJakub Pawlowski chan->sec_level, 8030fa142220SJakub Pawlowski HCI_LE_CONN_TIMEOUT, 80318e8b92eeSLuiz Augusto von Dentz HCI_ROLE_SLAVE); 80320ad06aa6SJohan Hedberg else 80330ad06aa6SJohan Hedberg hcon = hci_connect_le_scan(hdev, dst, dst_type, 80340ad06aa6SJohan Hedberg chan->sec_level, 803576b13996SManish Mandlik HCI_LE_CONN_TIMEOUT, 803676b13996SManish Mandlik CONN_REASON_L2CAP_CHAN); 80370ad06aa6SJohan Hedberg 80386f77d8c7SAndre Guedes } else { 8039d93375a8SJohan Hedberg u8 auth_type = l2cap_get_auth_type(chan); 804076b13996SManish Mandlik hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type, 804176b13996SManish Mandlik CONN_REASON_L2CAP_CHAN); 80426f77d8c7SAndre Guedes } 8043162b49e7SJohan Hedberg 8044162b49e7SJohan Hedberg if (IS_ERR(hcon)) { 8045162b49e7SJohan Hedberg err = PTR_ERR(hcon); 8046162b49e7SJohan Hedberg goto done; 8047162b49e7SJohan Hedberg } 8048162b49e7SJohan Hedberg 8049162b49e7SJohan Hedberg conn = l2cap_conn_add(hcon); 8050162b49e7SJohan Hedberg if (!conn) { 8051162b49e7SJohan Hedberg hci_conn_drop(hcon); 8052162b49e7SJohan Hedberg err = -ENOMEM; 8053162b49e7SJohan Hedberg goto done; 8054162b49e7SJohan Hedberg } 8055162b49e7SJohan Hedberg 8056da49b602SLuiz Augusto von Dentz if (chan->mode == L2CAP_MODE_EXT_FLOWCTL) { 8057da49b602SLuiz Augusto von Dentz struct l2cap_chan_data data; 8058da49b602SLuiz Augusto von Dentz 8059da49b602SLuiz Augusto von Dentz data.chan = chan; 8060da49b602SLuiz Augusto von Dentz data.pid = chan->ops->get_peer_pid(chan); 8061da49b602SLuiz Augusto von Dentz data.count = 1; 8062da49b602SLuiz Augusto von Dentz 8063da49b602SLuiz Augusto von Dentz l2cap_chan_list(conn, l2cap_chan_by_pid, &data); 8064da49b602SLuiz Augusto von Dentz 8065da49b602SLuiz Augusto von Dentz /* Check if there isn't too many channels being connected */ 8066da49b602SLuiz Augusto von Dentz if (data.count > L2CAP_ECRED_CONN_SCID_MAX) { 8067da49b602SLuiz Augusto von Dentz hci_conn_drop(hcon); 8068da49b602SLuiz Augusto von Dentz err = -EPROTO; 8069da49b602SLuiz Augusto von Dentz goto done; 8070da49b602SLuiz Augusto von Dentz } 8071da49b602SLuiz Augusto von Dentz } 8072da49b602SLuiz Augusto von Dentz 807302e246aeSJohan Hedberg mutex_lock(&conn->chan_lock); 807402e246aeSJohan Hedberg l2cap_chan_lock(chan); 807502e246aeSJohan Hedberg 8076162b49e7SJohan Hedberg if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { 8077162b49e7SJohan Hedberg hci_conn_drop(hcon); 8078162b49e7SJohan Hedberg err = -EBUSY; 807902e246aeSJohan Hedberg goto chan_unlock; 8080162b49e7SJohan Hedberg } 8081162b49e7SJohan Hedberg 8082162b49e7SJohan Hedberg /* Update source addr of the socket */ 8083162b49e7SJohan Hedberg bacpy(&chan->src, &hcon->src); 8084a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(hcon); 8085162b49e7SJohan Hedberg 808602e246aeSJohan Hedberg __l2cap_chan_add(conn, chan); 8087162b49e7SJohan Hedberg 8088162b49e7SJohan Hedberg /* l2cap_chan_add takes its own ref so we can drop this one */ 8089162b49e7SJohan Hedberg hci_conn_drop(hcon); 8090162b49e7SJohan Hedberg 8091162b49e7SJohan Hedberg l2cap_state_change(chan, BT_CONNECT); 8092162b49e7SJohan Hedberg __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 8093162b49e7SJohan Hedberg 809461202e4dSJohan Hedberg /* Release chan->sport so that it can be reused by other 809561202e4dSJohan Hedberg * sockets (as it's only used for listening sockets). 809661202e4dSJohan Hedberg */ 809761202e4dSJohan Hedberg write_lock(&chan_list_lock); 809861202e4dSJohan Hedberg chan->sport = 0; 809961202e4dSJohan Hedberg write_unlock(&chan_list_lock); 810061202e4dSJohan Hedberg 8101162b49e7SJohan Hedberg if (hcon->state == BT_CONNECTED) { 8102162b49e7SJohan Hedberg if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 8103162b49e7SJohan Hedberg __clear_chan_timer(chan); 8104e7cafc45SJohan Hedberg if (l2cap_chan_check_security(chan, true)) 8105162b49e7SJohan Hedberg l2cap_state_change(chan, BT_CONNECTED); 8106162b49e7SJohan Hedberg } else 8107162b49e7SJohan Hedberg l2cap_do_start(chan); 8108162b49e7SJohan Hedberg } 8109162b49e7SJohan Hedberg 8110162b49e7SJohan Hedberg err = 0; 8111162b49e7SJohan Hedberg 811202e246aeSJohan Hedberg chan_unlock: 8113162b49e7SJohan Hedberg l2cap_chan_unlock(chan); 811402e246aeSJohan Hedberg mutex_unlock(&conn->chan_lock); 811502e246aeSJohan Hedberg done: 8116162b49e7SJohan Hedberg hci_dev_unlock(hdev); 8117162b49e7SJohan Hedberg hci_dev_put(hdev); 8118162b49e7SJohan Hedberg return err; 8119162b49e7SJohan Hedberg } 81206b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_connect); 8121162b49e7SJohan Hedberg 812215f02b91SLuiz Augusto von Dentz static void l2cap_ecred_reconfigure(struct l2cap_chan *chan) 812315f02b91SLuiz Augusto von Dentz { 812415f02b91SLuiz Augusto von Dentz struct l2cap_conn *conn = chan->conn; 812515f02b91SLuiz Augusto von Dentz struct { 812615f02b91SLuiz Augusto von Dentz struct l2cap_ecred_reconf_req req; 812715f02b91SLuiz Augusto von Dentz __le16 scid; 812815f02b91SLuiz Augusto von Dentz } pdu; 812915f02b91SLuiz Augusto von Dentz 813015f02b91SLuiz Augusto von Dentz pdu.req.mtu = cpu_to_le16(chan->imtu); 813115f02b91SLuiz Augusto von Dentz pdu.req.mps = cpu_to_le16(chan->mps); 813215f02b91SLuiz Augusto von Dentz pdu.scid = cpu_to_le16(chan->scid); 813315f02b91SLuiz Augusto von Dentz 813415f02b91SLuiz Augusto von Dentz chan->ident = l2cap_get_ident(conn); 813515f02b91SLuiz Augusto von Dentz 813615f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_RECONF_REQ, 813715f02b91SLuiz Augusto von Dentz sizeof(pdu), &pdu); 813815f02b91SLuiz Augusto von Dentz } 813915f02b91SLuiz Augusto von Dentz 814015f02b91SLuiz Augusto von Dentz int l2cap_chan_reconfigure(struct l2cap_chan *chan, __u16 mtu) 814115f02b91SLuiz Augusto von Dentz { 814215f02b91SLuiz Augusto von Dentz if (chan->imtu > mtu) 814315f02b91SLuiz Augusto von Dentz return -EINVAL; 814415f02b91SLuiz Augusto von Dentz 814515f02b91SLuiz Augusto von Dentz BT_DBG("chan %p mtu 0x%4.4x", chan, mtu); 814615f02b91SLuiz Augusto von Dentz 814715f02b91SLuiz Augusto von Dentz chan->imtu = mtu; 814815f02b91SLuiz Augusto von Dentz 814915f02b91SLuiz Augusto von Dentz l2cap_ecred_reconfigure(chan); 815015f02b91SLuiz Augusto von Dentz 815115f02b91SLuiz Augusto von Dentz return 0; 815215f02b91SLuiz Augusto von Dentz } 815315f02b91SLuiz Augusto von Dentz 81540a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */ 81550a708f8fSGustavo F. Padovan 8156686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) 81570a708f8fSGustavo F. Padovan { 81580a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0; 815923691d75SGustavo F. Padovan struct l2cap_chan *c; 81600a708f8fSGustavo F. Padovan 81616ed93dc6SAndrei Emeltchenko BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr); 81620a708f8fSGustavo F. Padovan 81630a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */ 816423691d75SGustavo F. Padovan read_lock(&chan_list_lock); 816523691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 816689bc500eSGustavo F. Padovan if (c->state != BT_LISTEN) 81670a708f8fSGustavo F. Padovan continue; 81680a708f8fSGustavo F. Padovan 81697eafc59eSMarcel Holtmann if (!bacmp(&c->src, &hdev->bdaddr)) { 81700a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT; 817143bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 81720a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER; 81730a708f8fSGustavo F. Padovan exact++; 81747eafc59eSMarcel Holtmann } else if (!bacmp(&c->src, BDADDR_ANY)) { 81750a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT; 817643bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 81770a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER; 81780a708f8fSGustavo F. Padovan } 81790a708f8fSGustavo F. Padovan } 818023691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 81810a708f8fSGustavo F. Padovan 81820a708f8fSGustavo F. Padovan return exact ? lm1 : lm2; 81830a708f8fSGustavo F. Padovan } 81840a708f8fSGustavo F. Padovan 8185e760ec12SJohan Hedberg /* Find the next fixed channel in BT_LISTEN state, continue iteration 8186e760ec12SJohan Hedberg * from an existing channel in the list or from the beginning of the 8187e760ec12SJohan Hedberg * global list (by passing NULL as first parameter). 8188e760ec12SJohan Hedberg */ 8189e760ec12SJohan Hedberg static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c, 8190327a7191SJohan Hedberg struct hci_conn *hcon) 8191e760ec12SJohan Hedberg { 8192327a7191SJohan Hedberg u8 src_type = bdaddr_src_type(hcon); 8193327a7191SJohan Hedberg 8194e760ec12SJohan Hedberg read_lock(&chan_list_lock); 8195e760ec12SJohan Hedberg 8196e760ec12SJohan Hedberg if (c) 8197e760ec12SJohan Hedberg c = list_next_entry(c, global_l); 8198e760ec12SJohan Hedberg else 8199e760ec12SJohan Hedberg c = list_entry(chan_list.next, typeof(*c), global_l); 8200e760ec12SJohan Hedberg 8201e760ec12SJohan Hedberg list_for_each_entry_from(c, &chan_list, global_l) { 8202e760ec12SJohan Hedberg if (c->chan_type != L2CAP_CHAN_FIXED) 8203e760ec12SJohan Hedberg continue; 8204e760ec12SJohan Hedberg if (c->state != BT_LISTEN) 8205e760ec12SJohan Hedberg continue; 8206327a7191SJohan Hedberg if (bacmp(&c->src, &hcon->src) && bacmp(&c->src, BDADDR_ANY)) 8207e760ec12SJohan Hedberg continue; 8208327a7191SJohan Hedberg if (src_type != c->src_type) 820954a1b626SJohan Hedberg continue; 8210e760ec12SJohan Hedberg 8211d0be8347SLuiz Augusto von Dentz c = l2cap_chan_hold_unless_zero(c); 8212e760ec12SJohan Hedberg read_unlock(&chan_list_lock); 8213e760ec12SJohan Hedberg return c; 8214e760ec12SJohan Hedberg } 8215e760ec12SJohan Hedberg 8216e760ec12SJohan Hedberg read_unlock(&chan_list_lock); 8217e760ec12SJohan Hedberg 8218e760ec12SJohan Hedberg return NULL; 8219e760ec12SJohan Hedberg } 8220e760ec12SJohan Hedberg 8221539c496dSJohan Hedberg static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) 82220a708f8fSGustavo F. Padovan { 8223e760ec12SJohan Hedberg struct hci_dev *hdev = hcon->hdev; 82240a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 8225e760ec12SJohan Hedberg struct l2cap_chan *pchan; 8226e760ec12SJohan Hedberg u8 dst_type; 82270a708f8fSGustavo F. Padovan 8228539c496dSJohan Hedberg if (hcon->type != ACL_LINK && hcon->type != LE_LINK) 8229539c496dSJohan Hedberg return; 8230539c496dSJohan Hedberg 82316ed93dc6SAndrei Emeltchenko BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status); 82320a708f8fSGustavo F. Padovan 8233dc0f5088SJohan Hedberg if (status) { 8234e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status)); 8235dc0f5088SJohan Hedberg return; 8236ba6fc317SAndrei Emeltchenko } 8237dc0f5088SJohan Hedberg 8238dc0f5088SJohan Hedberg conn = l2cap_conn_add(hcon); 8239dc0f5088SJohan Hedberg if (!conn) 8240dc0f5088SJohan Hedberg return; 8241dc0f5088SJohan Hedberg 8242a250e048SJohan Hedberg dst_type = bdaddr_dst_type(hcon); 8243e760ec12SJohan Hedberg 8244e760ec12SJohan Hedberg /* If device is blocked, do not create channels for it */ 82453d4f9c00SArchie Pusaka if (hci_bdaddr_list_lookup(&hdev->reject_list, &hcon->dst, dst_type)) 8246e760ec12SJohan Hedberg return; 8247e760ec12SJohan Hedberg 8248e760ec12SJohan Hedberg /* Find fixed channels and notify them of the new connection. We 8249e760ec12SJohan Hedberg * use multiple individual lookups, continuing each time where 8250e760ec12SJohan Hedberg * we left off, because the list lock would prevent calling the 8251e760ec12SJohan Hedberg * potentially sleeping l2cap_chan_lock() function. 8252e760ec12SJohan Hedberg */ 8253327a7191SJohan Hedberg pchan = l2cap_global_fixed_chan(NULL, hcon); 8254e760ec12SJohan Hedberg while (pchan) { 8255e760ec12SJohan Hedberg struct l2cap_chan *chan, *next; 8256e760ec12SJohan Hedberg 8257e760ec12SJohan Hedberg /* Client fixed channels should override server ones */ 8258e760ec12SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, pchan->scid)) 8259e760ec12SJohan Hedberg goto next; 8260e760ec12SJohan Hedberg 8261e760ec12SJohan Hedberg l2cap_chan_lock(pchan); 8262e760ec12SJohan Hedberg chan = pchan->ops->new_connection(pchan); 8263e760ec12SJohan Hedberg if (chan) { 8264e760ec12SJohan Hedberg bacpy(&chan->src, &hcon->src); 8265e760ec12SJohan Hedberg bacpy(&chan->dst, &hcon->dst); 8266a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(hcon); 8267e760ec12SJohan Hedberg chan->dst_type = dst_type; 8268e760ec12SJohan Hedberg 8269e760ec12SJohan Hedberg __l2cap_chan_add(conn, chan); 8270e760ec12SJohan Hedberg } 8271e760ec12SJohan Hedberg 8272e760ec12SJohan Hedberg l2cap_chan_unlock(pchan); 8273e760ec12SJohan Hedberg next: 8274327a7191SJohan Hedberg next = l2cap_global_fixed_chan(pchan, hcon); 8275e760ec12SJohan Hedberg l2cap_chan_put(pchan); 8276e760ec12SJohan Hedberg pchan = next; 8277e760ec12SJohan Hedberg } 8278e760ec12SJohan Hedberg 8279dc0f5088SJohan Hedberg l2cap_conn_ready(conn); 82800a708f8fSGustavo F. Padovan } 82810a708f8fSGustavo F. Padovan 8282686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon) 82830a708f8fSGustavo F. Padovan { 82840a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 82850a708f8fSGustavo F. Padovan 82860a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon); 82870a708f8fSGustavo F. Padovan 8288686ebf28SUlisses Furquim if (!conn) 82899f5a0d7bSAndrei Emeltchenko return HCI_ERROR_REMOTE_USER_TERM; 82900a708f8fSGustavo F. Padovan return conn->disc_reason; 82910a708f8fSGustavo F. Padovan } 82920a708f8fSGustavo F. Padovan 82933a6d576bSJohan Hedberg static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) 82940a708f8fSGustavo F. Padovan { 82953a6d576bSJohan Hedberg if (hcon->type != ACL_LINK && hcon->type != LE_LINK) 82963a6d576bSJohan Hedberg return; 82973a6d576bSJohan Hedberg 82980a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason); 82990a708f8fSGustavo F. Padovan 8300e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason)); 83010a708f8fSGustavo F. Padovan } 83020a708f8fSGustavo F. Padovan 83034343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) 83040a708f8fSGustavo F. Padovan { 8305715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 83060a708f8fSGustavo F. Padovan return; 83070a708f8fSGustavo F. Padovan 83080a708f8fSGustavo F. Padovan if (encrypt == 0x00) { 83094343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) { 8310ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); 83117d513e92SMarcel Holtmann } else if (chan->sec_level == BT_SECURITY_HIGH || 83127d513e92SMarcel Holtmann chan->sec_level == BT_SECURITY_FIPS) 83130f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED); 83140a708f8fSGustavo F. Padovan } else { 83154343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) 8316c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 83170a708f8fSGustavo F. Padovan } 83180a708f8fSGustavo F. Padovan } 83190a708f8fSGustavo F. Padovan 8320354fe804SJohan Hedberg static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) 83210a708f8fSGustavo F. Padovan { 83220a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 832348454079SGustavo F. Padovan struct l2cap_chan *chan; 83240a708f8fSGustavo F. Padovan 83250a708f8fSGustavo F. Padovan if (!conn) 8326354fe804SJohan Hedberg return; 83270a708f8fSGustavo F. Padovan 832889d8b407SAndrei Emeltchenko BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt); 83290a708f8fSGustavo F. Padovan 83303df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 83310a708f8fSGustavo F. Padovan 83323df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 83336be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 83340a708f8fSGustavo F. Padovan 833589d8b407SAndrei Emeltchenko BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, 833689d8b407SAndrei Emeltchenko state_to_string(chan->state)); 8337f1cb9af5SVinicius Costa Gomes 83382338a7e0SJohan Hedberg if (chan->scid == L2CAP_CID_A2MP) { 833978eb2f98SAndrei Emeltchenko l2cap_chan_unlock(chan); 834078eb2f98SAndrei Emeltchenko continue; 834178eb2f98SAndrei Emeltchenko } 834278eb2f98SAndrei Emeltchenko 8343191eb398SJohan Hedberg if (!status && encrypt) 8344f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level; 8345f1cb9af5SVinicius Costa Gomes 834696eff46eSAndrei Emeltchenko if (!__l2cap_no_conn_pending(chan)) { 83476be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 83480a708f8fSGustavo F. Padovan continue; 83490a708f8fSGustavo F. Padovan } 83500a708f8fSGustavo F. Padovan 835189bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED || 835289bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) { 8353d97c899bSMarcel Holtmann chan->ops->resume(chan); 83544343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt); 83556be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 83560a708f8fSGustavo F. Padovan continue; 83570a708f8fSGustavo F. Padovan } 83580a708f8fSGustavo F. Padovan 835989bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 8360693cd8ceSMarcel Holtmann if (!status && l2cap_check_enc_key_size(hcon)) 836193c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 83626d3c15daSJohan Hedberg else 8363ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 8364fa37c1aaSJohan Hedberg } else if (chan->state == BT_CONNECT2 && 836515f02b91SLuiz Augusto von Dentz !(chan->mode == L2CAP_MODE_EXT_FLOWCTL || 836615f02b91SLuiz Augusto von Dentz chan->mode == L2CAP_MODE_LE_FLOWCTL)) { 83670a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 8368df3c3931SJohan Hedberg __u16 res, stat; 83690a708f8fSGustavo F. Padovan 8370693cd8ceSMarcel Holtmann if (!status && l2cap_check_enc_key_size(hcon)) { 8371bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 8372df3c3931SJohan Hedberg res = L2CAP_CR_PEND; 8373df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND; 83742dc4e510SGustavo Padovan chan->ops->defer(chan); 8375df3c3931SJohan Hedberg } else { 8376acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 8377df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS; 8378df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 8379df3c3931SJohan Hedberg } 83800a708f8fSGustavo F. Padovan } else { 8381acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_DISCONN); 8382ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 8383df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK; 8384df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 83850a708f8fSGustavo F. Padovan } 83860a708f8fSGustavo F. Padovan 8387fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 8388fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 8389df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res); 8390df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat); 8391fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 8392fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 83932d369359SMat Martineau 83942d369359SMat Martineau if (!test_bit(CONF_REQ_SENT, &chan->conf_state) && 83952d369359SMat Martineau res == L2CAP_CR_SUCCESS) { 83962d369359SMat Martineau char buf[128]; 83972d369359SMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 83982d369359SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), 83992d369359SMat Martineau L2CAP_CONF_REQ, 8400e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), 84012d369359SMat Martineau buf); 84022d369359SMat Martineau chan->num_conf_req++; 84032d369359SMat Martineau } 84040a708f8fSGustavo F. Padovan } 84050a708f8fSGustavo F. Padovan 84066be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 84070a708f8fSGustavo F. Padovan } 84080a708f8fSGustavo F. Padovan 84093df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 84100a708f8fSGustavo F. Padovan } 84110a708f8fSGustavo F. Padovan 84124d7ea8eeSLuiz Augusto von Dentz /* Append fragment into frame respecting the maximum len of rx_skb */ 84134d7ea8eeSLuiz Augusto von Dentz static int l2cap_recv_frag(struct l2cap_conn *conn, struct sk_buff *skb, 84144d7ea8eeSLuiz Augusto von Dentz u16 len) 84154d7ea8eeSLuiz Augusto von Dentz { 84164d7ea8eeSLuiz Augusto von Dentz if (!conn->rx_skb) { 84174d7ea8eeSLuiz Augusto von Dentz /* Allocate skb for the complete frame (with header) */ 84184d7ea8eeSLuiz Augusto von Dentz conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL); 84194d7ea8eeSLuiz Augusto von Dentz if (!conn->rx_skb) 84204d7ea8eeSLuiz Augusto von Dentz return -ENOMEM; 84214d7ea8eeSLuiz Augusto von Dentz /* Init rx_len */ 84224d7ea8eeSLuiz Augusto von Dentz conn->rx_len = len; 84234d7ea8eeSLuiz Augusto von Dentz } 84244d7ea8eeSLuiz Augusto von Dentz 84254d7ea8eeSLuiz Augusto von Dentz /* Copy as much as the rx_skb can hold */ 84264d7ea8eeSLuiz Augusto von Dentz len = min_t(u16, len, skb->len); 84274d7ea8eeSLuiz Augusto von Dentz skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, len), len); 84284d7ea8eeSLuiz Augusto von Dentz skb_pull(skb, len); 84294d7ea8eeSLuiz Augusto von Dentz conn->rx_len -= len; 84304d7ea8eeSLuiz Augusto von Dentz 84314d7ea8eeSLuiz Augusto von Dentz return len; 84324d7ea8eeSLuiz Augusto von Dentz } 84334d7ea8eeSLuiz Augusto von Dentz 84344d7ea8eeSLuiz Augusto von Dentz static int l2cap_recv_len(struct l2cap_conn *conn, struct sk_buff *skb) 84354d7ea8eeSLuiz Augusto von Dentz { 84364d7ea8eeSLuiz Augusto von Dentz struct sk_buff *rx_skb; 84374d7ea8eeSLuiz Augusto von Dentz int len; 84384d7ea8eeSLuiz Augusto von Dentz 84394d7ea8eeSLuiz Augusto von Dentz /* Append just enough to complete the header */ 84404d7ea8eeSLuiz Augusto von Dentz len = l2cap_recv_frag(conn, skb, L2CAP_LEN_SIZE - conn->rx_skb->len); 84414d7ea8eeSLuiz Augusto von Dentz 84424d7ea8eeSLuiz Augusto von Dentz /* If header could not be read just continue */ 84434d7ea8eeSLuiz Augusto von Dentz if (len < 0 || conn->rx_skb->len < L2CAP_LEN_SIZE) 84444d7ea8eeSLuiz Augusto von Dentz return len; 84454d7ea8eeSLuiz Augusto von Dentz 84464d7ea8eeSLuiz Augusto von Dentz rx_skb = conn->rx_skb; 84474d7ea8eeSLuiz Augusto von Dentz len = get_unaligned_le16(rx_skb->data); 84484d7ea8eeSLuiz Augusto von Dentz 84494d7ea8eeSLuiz Augusto von Dentz /* Check if rx_skb has enough space to received all fragments */ 84504d7ea8eeSLuiz Augusto von Dentz if (len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE) <= skb_tailroom(rx_skb)) { 84514d7ea8eeSLuiz Augusto von Dentz /* Update expected len */ 84524d7ea8eeSLuiz Augusto von Dentz conn->rx_len = len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE); 84534d7ea8eeSLuiz Augusto von Dentz return L2CAP_LEN_SIZE; 84544d7ea8eeSLuiz Augusto von Dentz } 84554d7ea8eeSLuiz Augusto von Dentz 84564d7ea8eeSLuiz Augusto von Dentz /* Reset conn->rx_skb since it will need to be reallocated in order to 84574d7ea8eeSLuiz Augusto von Dentz * fit all fragments. 84584d7ea8eeSLuiz Augusto von Dentz */ 84594d7ea8eeSLuiz Augusto von Dentz conn->rx_skb = NULL; 84604d7ea8eeSLuiz Augusto von Dentz 84614d7ea8eeSLuiz Augusto von Dentz /* Reallocates rx_skb using the exact expected length */ 84624d7ea8eeSLuiz Augusto von Dentz len = l2cap_recv_frag(conn, rx_skb, 84634d7ea8eeSLuiz Augusto von Dentz len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE)); 84644d7ea8eeSLuiz Augusto von Dentz kfree_skb(rx_skb); 84654d7ea8eeSLuiz Augusto von Dentz 84664d7ea8eeSLuiz Augusto von Dentz return len; 84674d7ea8eeSLuiz Augusto von Dentz } 84684d7ea8eeSLuiz Augusto von Dentz 84694d7ea8eeSLuiz Augusto von Dentz static void l2cap_recv_reset(struct l2cap_conn *conn) 84704d7ea8eeSLuiz Augusto von Dentz { 84714d7ea8eeSLuiz Augusto von Dentz kfree_skb(conn->rx_skb); 84724d7ea8eeSLuiz Augusto von Dentz conn->rx_skb = NULL; 84734d7ea8eeSLuiz Augusto von Dentz conn->rx_len = 0; 84744d7ea8eeSLuiz Augusto von Dentz } 84754d7ea8eeSLuiz Augusto von Dentz 84769b4c3336SArron Wang void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) 84770a708f8fSGustavo F. Padovan { 84780a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 8479d73a0988SAndrei Emeltchenko int len; 84800a708f8fSGustavo F. Padovan 84811d13a254SAndrei Emeltchenko /* For AMP controller do not create l2cap conn */ 8482ca8bee5dSMarcel Holtmann if (!conn && hcon->hdev->dev_type != HCI_PRIMARY) 84831d13a254SAndrei Emeltchenko goto drop; 84840a708f8fSGustavo F. Padovan 84850a708f8fSGustavo F. Padovan if (!conn) 8486baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon); 84870a708f8fSGustavo F. Padovan 84880a708f8fSGustavo F. Padovan if (!conn) 84890a708f8fSGustavo F. Padovan goto drop; 84900a708f8fSGustavo F. Padovan 849193917fd2SKai Ye BT_DBG("conn %p len %u flags 0x%x", conn, skb->len, flags); 84920a708f8fSGustavo F. Padovan 8493d73a0988SAndrei Emeltchenko switch (flags) { 8494d73a0988SAndrei Emeltchenko case ACL_START: 8495d73a0988SAndrei Emeltchenko case ACL_START_NO_FLUSH: 8496d73a0988SAndrei Emeltchenko case ACL_COMPLETE: 84974d7ea8eeSLuiz Augusto von Dentz if (conn->rx_skb) { 84980a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len); 84994d7ea8eeSLuiz Augusto von Dentz l2cap_recv_reset(conn); 85000a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 85010a708f8fSGustavo F. Padovan } 85020a708f8fSGustavo F. Padovan 85034d7ea8eeSLuiz Augusto von Dentz /* Start fragment may not contain the L2CAP length so just 85044d7ea8eeSLuiz Augusto von Dentz * copy the initial byte when that happens and use conn->mtu as 85054d7ea8eeSLuiz Augusto von Dentz * expected length. 85064d7ea8eeSLuiz Augusto von Dentz */ 85074d7ea8eeSLuiz Augusto von Dentz if (skb->len < L2CAP_LEN_SIZE) { 85087c9524d9SHawkins Jiawei l2cap_recv_frag(conn, skb, conn->mtu); 85097c9524d9SHawkins Jiawei break; 85100a708f8fSGustavo F. Padovan } 85110a708f8fSGustavo F. Padovan 85124d7ea8eeSLuiz Augusto von Dentz len = get_unaligned_le16(skb->data) + L2CAP_HDR_SIZE; 85130a708f8fSGustavo F. Padovan 85140a708f8fSGustavo F. Padovan if (len == skb->len) { 85150a708f8fSGustavo F. Padovan /* Complete frame received */ 85160a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb); 85179b4c3336SArron Wang return; 85180a708f8fSGustavo F. Padovan } 85190a708f8fSGustavo F. Padovan 852093917fd2SKai Ye BT_DBG("Start: total len %d, frag len %u", len, skb->len); 85210a708f8fSGustavo F. Padovan 85220a708f8fSGustavo F. Padovan if (skb->len > len) { 852393917fd2SKai Ye BT_ERR("Frame is too long (len %u, expected len %d)", 85240a708f8fSGustavo F. Padovan skb->len, len); 85250a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 85260a708f8fSGustavo F. Padovan goto drop; 85270a708f8fSGustavo F. Padovan } 85280a708f8fSGustavo F. Padovan 85294d7ea8eeSLuiz Augusto von Dentz /* Append fragment into frame (with header) */ 85304d7ea8eeSLuiz Augusto von Dentz if (l2cap_recv_frag(conn, skb, len) < 0) 85310a708f8fSGustavo F. Padovan goto drop; 85320a708f8fSGustavo F. Padovan 8533d73a0988SAndrei Emeltchenko break; 8534d73a0988SAndrei Emeltchenko 8535d73a0988SAndrei Emeltchenko case ACL_CONT: 853693917fd2SKai Ye BT_DBG("Cont: frag len %u (expecting %u)", skb->len, conn->rx_len); 85370a708f8fSGustavo F. Padovan 85384d7ea8eeSLuiz Augusto von Dentz if (!conn->rx_skb) { 85390a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len); 85400a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 85410a708f8fSGustavo F. Padovan goto drop; 85420a708f8fSGustavo F. Padovan } 85430a708f8fSGustavo F. Padovan 85444d7ea8eeSLuiz Augusto von Dentz /* Complete the L2CAP length if it has not been read */ 85454d7ea8eeSLuiz Augusto von Dentz if (conn->rx_skb->len < L2CAP_LEN_SIZE) { 85464d7ea8eeSLuiz Augusto von Dentz if (l2cap_recv_len(conn, skb) < 0) { 85470a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 85480a708f8fSGustavo F. Padovan goto drop; 85490a708f8fSGustavo F. Padovan } 85500a708f8fSGustavo F. Padovan 85514d7ea8eeSLuiz Augusto von Dentz /* Header still could not be read just continue */ 85524d7ea8eeSLuiz Augusto von Dentz if (conn->rx_skb->len < L2CAP_LEN_SIZE) 85537c9524d9SHawkins Jiawei break; 85544d7ea8eeSLuiz Augusto von Dentz } 85554d7ea8eeSLuiz Augusto von Dentz 85564d7ea8eeSLuiz Augusto von Dentz if (skb->len > conn->rx_len) { 855793917fd2SKai Ye BT_ERR("Fragment is too long (len %u, expected %u)", 85584d7ea8eeSLuiz Augusto von Dentz skb->len, conn->rx_len); 85594d7ea8eeSLuiz Augusto von Dentz l2cap_recv_reset(conn); 85604d7ea8eeSLuiz Augusto von Dentz l2cap_conn_unreliable(conn, ECOMM); 85614d7ea8eeSLuiz Augusto von Dentz goto drop; 85624d7ea8eeSLuiz Augusto von Dentz } 85634d7ea8eeSLuiz Augusto von Dentz 85644d7ea8eeSLuiz Augusto von Dentz /* Append fragment into frame (with header) */ 85654d7ea8eeSLuiz Augusto von Dentz l2cap_recv_frag(conn, skb, skb->len); 85660a708f8fSGustavo F. Padovan 85670a708f8fSGustavo F. Padovan if (!conn->rx_len) { 8568c4e5bafaSJohan Hedberg /* Complete frame received. l2cap_recv_frame 8569c4e5bafaSJohan Hedberg * takes ownership of the skb so set the global 8570c4e5bafaSJohan Hedberg * rx_skb pointer to NULL first. 8571c4e5bafaSJohan Hedberg */ 8572c4e5bafaSJohan Hedberg struct sk_buff *rx_skb = conn->rx_skb; 85730a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 8574c4e5bafaSJohan Hedberg l2cap_recv_frame(conn, rx_skb); 85750a708f8fSGustavo F. Padovan } 8576d73a0988SAndrei Emeltchenko break; 85770a708f8fSGustavo F. Padovan } 85780a708f8fSGustavo F. Padovan 85790a708f8fSGustavo F. Padovan drop: 85800a708f8fSGustavo F. Padovan kfree_skb(skb); 85810a708f8fSGustavo F. Padovan } 85820a708f8fSGustavo F. Padovan 8583354fe804SJohan Hedberg static struct hci_cb l2cap_cb = { 8584354fe804SJohan Hedberg .name = "L2CAP", 8585539c496dSJohan Hedberg .connect_cfm = l2cap_connect_cfm, 85863a6d576bSJohan Hedberg .disconn_cfm = l2cap_disconn_cfm, 8587354fe804SJohan Hedberg .security_cfm = l2cap_security_cfm, 8588354fe804SJohan Hedberg }; 8589354fe804SJohan Hedberg 85900a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p) 85910a708f8fSGustavo F. Padovan { 859223691d75SGustavo F. Padovan struct l2cap_chan *c; 85930a708f8fSGustavo F. Padovan 8594333055f2SGustavo F. Padovan read_lock(&chan_list_lock); 85950a708f8fSGustavo F. Padovan 859623691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 8597eeb5a067SMarcel Holtmann seq_printf(f, "%pMR (%u) %pMR (%u) %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", 8598eeb5a067SMarcel Holtmann &c->src, c->src_type, &c->dst, c->dst_type, 859989bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm), 860023691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu, 860123691d75SGustavo F. Padovan c->sec_level, c->mode); 86020a708f8fSGustavo F. Padovan } 86030a708f8fSGustavo F. Padovan 8604333055f2SGustavo F. Padovan read_unlock(&chan_list_lock); 86050a708f8fSGustavo F. Padovan 86060a708f8fSGustavo F. Padovan return 0; 86070a708f8fSGustavo F. Padovan } 86080a708f8fSGustavo F. Padovan 86098e2924e3SYangtao Li DEFINE_SHOW_ATTRIBUTE(l2cap_debugfs); 86100a708f8fSGustavo F. Padovan 86110a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs; 86120a708f8fSGustavo F. Padovan 861364274518SGustavo F. Padovan int __init l2cap_init(void) 86140a708f8fSGustavo F. Padovan { 86150a708f8fSGustavo F. Padovan int err; 86160a708f8fSGustavo F. Padovan 8617bb58f747SGustavo F. Padovan err = l2cap_init_sockets(); 86180a708f8fSGustavo F. Padovan if (err < 0) 86190a708f8fSGustavo F. Padovan return err; 86200a708f8fSGustavo F. Padovan 8621354fe804SJohan Hedberg hci_register_cb(&l2cap_cb); 8622354fe804SJohan Hedberg 86231120e4bfSMarcel Holtmann if (IS_ERR_OR_NULL(bt_debugfs)) 86241120e4bfSMarcel Holtmann return 0; 86251120e4bfSMarcel Holtmann 86262d792818SGustavo Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, 86272d792818SGustavo Padovan NULL, &l2cap_debugfs_fops); 86280a708f8fSGustavo F. Padovan 86290a708f8fSGustavo F. Padovan return 0; 86300a708f8fSGustavo F. Padovan } 86310a708f8fSGustavo F. Padovan 863264274518SGustavo F. Padovan void l2cap_exit(void) 86330a708f8fSGustavo F. Padovan { 86340a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs); 8635354fe804SJohan Hedberg hci_unregister_cb(&l2cap_cb); 8636bb58f747SGustavo F. Padovan l2cap_cleanup_sockets(); 86370a708f8fSGustavo F. Padovan } 86380a708f8fSGustavo F. Padovan 86390a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644); 86400a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); 86414be5ca67SLuiz Augusto von Dentz 86424be5ca67SLuiz Augusto von Dentz module_param(enable_ecred, bool, 0644); 86434be5ca67SLuiz Augusto von Dentz MODULE_PARM_DESC(enable_ecred, "Enable enhanced credit flow control mode"); 8644