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"
420a708f8fSGustavo F. Padovan
430f1bfe4eSJohan Hedberg #define LE_FLOWCTL_MAX_CREDITS 65535
440f1bfe4eSJohan Hedberg
45d1de6d46SMat Martineau bool disable_ertm;
46462fcd53SLuiz Augusto von Dentz bool enable_ecred = IS_ENABLED(CONFIG_BT_LE_L2CAP_ECRED);
470a708f8fSGustavo F. Padovan
48547d1032SMarcel Holtmann static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD;
490a708f8fSGustavo F. Padovan
50b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list);
51b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock);
520a708f8fSGustavo F. Padovan
530a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
540a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data);
554519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
564519de9aSGustavo F. Padovan void *data);
57e860d2c9SBen Seri static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size);
585e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err);
590a708f8fSGustavo F. Padovan
60d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
61608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event);
622d2cb306STetsuo Handa static void l2cap_retrans_timeout(struct work_struct *work);
632d2cb306STetsuo Handa static void l2cap_monitor_timeout(struct work_struct *work);
642d2cb306STetsuo Handa static void l2cap_ack_timeout(struct work_struct *work);
65608bcc6dSMat Martineau
bdaddr_type(u8 link_type,u8 bdaddr_type)66a250e048SJohan Hedberg static inline u8 bdaddr_type(u8 link_type, u8 bdaddr_type)
674f1654e0SMarcel Holtmann {
68a250e048SJohan Hedberg if (link_type == LE_LINK) {
69a250e048SJohan Hedberg if (bdaddr_type == ADDR_LE_DEV_PUBLIC)
704f1654e0SMarcel Holtmann return BDADDR_LE_PUBLIC;
714f1654e0SMarcel Holtmann else
724f1654e0SMarcel Holtmann return BDADDR_LE_RANDOM;
734f1654e0SMarcel Holtmann }
744f1654e0SMarcel Holtmann
754f1654e0SMarcel Holtmann return BDADDR_BREDR;
764f1654e0SMarcel Holtmann }
774f1654e0SMarcel Holtmann
bdaddr_src_type(struct hci_conn * hcon)78a250e048SJohan Hedberg static inline u8 bdaddr_src_type(struct hci_conn *hcon)
79a250e048SJohan Hedberg {
80a250e048SJohan Hedberg return bdaddr_type(hcon->type, hcon->src_type);
81a250e048SJohan Hedberg }
82a250e048SJohan Hedberg
bdaddr_dst_type(struct hci_conn * hcon)83a250e048SJohan Hedberg static inline u8 bdaddr_dst_type(struct hci_conn *hcon)
84a250e048SJohan Hedberg {
85a250e048SJohan Hedberg return bdaddr_type(hcon->type, hcon->dst_type);
86a250e048SJohan Hedberg }
87a250e048SJohan Hedberg
880a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */
8971ba0e56SGustavo F. Padovan
__l2cap_get_chan_by_dcid(struct l2cap_conn * conn,u16 cid)902d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
912d792818SGustavo Padovan u16 cid)
920a708f8fSGustavo F. Padovan {
933df91ea2SAndrei Emeltchenko struct l2cap_chan *c;
94baa7e1faSGustavo F. Padovan
953df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) {
963df91ea2SAndrei Emeltchenko if (c->dcid == cid)
973df91ea2SAndrei Emeltchenko return c;
980a708f8fSGustavo F. Padovan }
993df91ea2SAndrei Emeltchenko return NULL;
100baa7e1faSGustavo F. Padovan }
1010a708f8fSGustavo F. Padovan
__l2cap_get_chan_by_scid(struct l2cap_conn * conn,u16 cid)1022d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn,
1032d792818SGustavo Padovan u16 cid)
1040a708f8fSGustavo F. Padovan {
1053df91ea2SAndrei Emeltchenko struct l2cap_chan *c;
106baa7e1faSGustavo F. Padovan
1073df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) {
1083df91ea2SAndrei Emeltchenko if (c->scid == cid)
1093df91ea2SAndrei Emeltchenko return c;
1100a708f8fSGustavo F. Padovan }
1113df91ea2SAndrei Emeltchenko return NULL;
112baa7e1faSGustavo F. Padovan }
1130a708f8fSGustavo F. Padovan
1140a708f8fSGustavo F. Padovan /* Find channel with given SCID.
115d0be8347SLuiz Augusto von Dentz * Returns a reference locked channel.
116d0be8347SLuiz Augusto von Dentz */
l2cap_get_chan_by_scid(struct l2cap_conn * conn,u16 cid)1172d792818SGustavo Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn,
1182d792818SGustavo Padovan u16 cid)
1190a708f8fSGustavo F. Padovan {
12048454079SGustavo F. Padovan struct l2cap_chan *c;
121baa7e1faSGustavo F. Padovan
122baa7e1faSGustavo F. Padovan c = __l2cap_get_chan_by_scid(conn, cid);
123d0be8347SLuiz Augusto von Dentz if (c) {
124d0be8347SLuiz Augusto von Dentz /* Only lock if chan reference is not 0 */
125d0be8347SLuiz Augusto von Dentz c = l2cap_chan_hold_unless_zero(c);
126ef191adeSMat Martineau if (c)
127ef191adeSMat Martineau l2cap_chan_lock(c);
128d0be8347SLuiz Augusto von Dentz }
1293df91ea2SAndrei Emeltchenko
13048454079SGustavo F. Padovan return c;
1310a708f8fSGustavo F. Padovan }
1320a708f8fSGustavo F. Padovan
133b1a130b7SMat Martineau /* Find channel with given DCID.
134d0be8347SLuiz Augusto von Dentz * Returns a reference locked channel.
135b1a130b7SMat Martineau */
136b1a130b7SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
137b1a130b7SMat Martineau u16 cid)
l2cap_get_chan_by_dcid(struct l2cap_conn * conn,u16 cid)138b1a130b7SMat Martineau {
139b1a130b7SMat Martineau struct l2cap_chan *c;
140b1a130b7SMat Martineau
141b1a130b7SMat Martineau c = __l2cap_get_chan_by_dcid(conn, cid);
142d0be8347SLuiz Augusto von Dentz if (c) {
143d0be8347SLuiz Augusto von Dentz /* Only lock if chan reference is not 0 */
144d0be8347SLuiz Augusto von Dentz c = l2cap_chan_hold_unless_zero(c);
145b1a130b7SMat Martineau if (c)
146b1a130b7SMat Martineau l2cap_chan_lock(c);
147d0be8347SLuiz Augusto von Dentz }
148b1a130b7SMat Martineau
149b1a130b7SMat Martineau return c;
150b1a130b7SMat Martineau }
151b1a130b7SMat Martineau
1522d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn,
1532d792818SGustavo Padovan u8 ident)
1540a708f8fSGustavo F. Padovan {
1553df91ea2SAndrei Emeltchenko struct l2cap_chan *c;
__l2cap_get_chan_by_ident(struct l2cap_conn * conn,u8 ident)156baa7e1faSGustavo F. Padovan
1573df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) {
1583df91ea2SAndrei Emeltchenko if (c->ident == ident)
1593df91ea2SAndrei Emeltchenko return c;
1600a708f8fSGustavo F. Padovan }
1613df91ea2SAndrei Emeltchenko return NULL;
162baa7e1faSGustavo F. Padovan }
1630a708f8fSGustavo F. Padovan
16400f62726SLuiz Augusto von Dentz static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src,
16500f62726SLuiz Augusto von Dentz u8 src_type)
1669e4425ffSGustavo F. Padovan {
16723691d75SGustavo F. Padovan struct l2cap_chan *c;
__l2cap_global_chan_by_addr(__le16 psm,bdaddr_t * src,u8 src_type)1689e4425ffSGustavo F. Padovan
16923691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) {
17000f62726SLuiz Augusto von Dentz if (src_type == BDADDR_BREDR && c->src_type != BDADDR_BREDR)
17100f62726SLuiz Augusto von Dentz continue;
17200f62726SLuiz Augusto von Dentz
17300f62726SLuiz Augusto von Dentz if (src_type != BDADDR_BREDR && c->src_type == BDADDR_BREDR)
17400f62726SLuiz Augusto von Dentz continue;
17500f62726SLuiz Augusto von Dentz
1767eafc59eSMarcel Holtmann if (c->sport == psm && !bacmp(&c->src, src))
17723691d75SGustavo F. Padovan return c;
1789e4425ffSGustavo F. Padovan }
179250938cbSSzymon Janc return NULL;
180250938cbSSzymon Janc }
1819e4425ffSGustavo F. Padovan
1829e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
1839e4425ffSGustavo F. Padovan {
18473b2ec18SGustavo F. Padovan int err;
18573b2ec18SGustavo F. Padovan
l2cap_add_psm(struct l2cap_chan * chan,bdaddr_t * src,__le16 psm)186333055f2SGustavo F. Padovan write_lock(&chan_list_lock);
1879e4425ffSGustavo F. Padovan
18800f62726SLuiz Augusto von Dentz if (psm && __l2cap_global_chan_by_addr(psm, src, chan->src_type)) {
18973b2ec18SGustavo F. Padovan err = -EADDRINUSE;
19073b2ec18SGustavo F. Padovan goto done;
1919e4425ffSGustavo F. Padovan }
1929e4425ffSGustavo F. Padovan
19373b2ec18SGustavo F. Padovan if (psm) {
1949e4425ffSGustavo F. Padovan chan->psm = psm;
1959e4425ffSGustavo F. Padovan chan->sport = psm;
19673b2ec18SGustavo F. Padovan err = 0;
19773b2ec18SGustavo F. Padovan } else {
19892594a51SJohan Hedberg u16 p, start, end, incr;
19992594a51SJohan Hedberg
20092594a51SJohan Hedberg if (chan->src_type == BDADDR_BREDR) {
20192594a51SJohan Hedberg start = L2CAP_PSM_DYN_START;
20292594a51SJohan Hedberg end = L2CAP_PSM_AUTO_END;
20392594a51SJohan Hedberg incr = 2;
20492594a51SJohan Hedberg } else {
20592594a51SJohan Hedberg start = L2CAP_PSM_LE_DYN_START;
20692594a51SJohan Hedberg end = L2CAP_PSM_LE_DYN_END;
20792594a51SJohan Hedberg incr = 1;
20892594a51SJohan Hedberg }
2099e4425ffSGustavo F. Padovan
21073b2ec18SGustavo F. Padovan err = -EINVAL;
21192594a51SJohan Hedberg for (p = start; p <= end; p += incr)
21200f62726SLuiz Augusto von Dentz if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src,
21300f62726SLuiz Augusto von Dentz chan->src_type)) {
21473b2ec18SGustavo F. Padovan chan->psm = cpu_to_le16(p);
21573b2ec18SGustavo F. Padovan chan->sport = cpu_to_le16(p);
21673b2ec18SGustavo F. Padovan err = 0;
21773b2ec18SGustavo F. Padovan break;
21873b2ec18SGustavo F. Padovan }
21973b2ec18SGustavo F. Padovan }
22073b2ec18SGustavo F. Padovan
22173b2ec18SGustavo F. Padovan done:
222333055f2SGustavo F. Padovan write_unlock(&chan_list_lock);
22373b2ec18SGustavo F. Padovan return err;
2249e4425ffSGustavo F. Padovan }
2256b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_add_psm);
2269e4425ffSGustavo F. Padovan
2279e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
2289e4425ffSGustavo F. Padovan {
229333055f2SGustavo F. Padovan write_lock(&chan_list_lock);
2309e4425ffSGustavo F. Padovan
l2cap_add_scid(struct l2cap_chan * chan,__u16 scid)23114824308SJohan Hedberg /* Override the defaults (which are for conn-oriented) */
23214824308SJohan Hedberg chan->omtu = L2CAP_DEFAULT_MTU;
23314824308SJohan Hedberg chan->chan_type = L2CAP_CHAN_FIXED;
23414824308SJohan Hedberg
2359e4425ffSGustavo F. Padovan chan->scid = scid;
2369e4425ffSGustavo F. Padovan
237333055f2SGustavo F. Padovan write_unlock(&chan_list_lock);
2389e4425ffSGustavo F. Padovan
2399e4425ffSGustavo F. Padovan return 0;
2409e4425ffSGustavo F. Padovan }
2419e4425ffSGustavo F. Padovan
242baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
2430a708f8fSGustavo F. Padovan {
244e77af755SJohan Hedberg u16 cid, dyn_end;
2450a708f8fSGustavo F. Padovan
l2cap_alloc_cid(struct l2cap_conn * conn)246e77af755SJohan Hedberg if (conn->hcon->type == LE_LINK)
247e77af755SJohan Hedberg dyn_end = L2CAP_CID_LE_DYN_END;
248e77af755SJohan Hedberg else
249e77af755SJohan Hedberg dyn_end = L2CAP_CID_DYN_END;
250e77af755SJohan Hedberg
251ab0c127fSJohan Hedberg for (cid = L2CAP_CID_DYN_START; cid <= dyn_end; cid++) {
252baa7e1faSGustavo F. Padovan if (!__l2cap_get_chan_by_scid(conn, cid))
2530a708f8fSGustavo F. Padovan return cid;
2540a708f8fSGustavo F. Padovan }
2550a708f8fSGustavo F. Padovan
2560a708f8fSGustavo F. Padovan return 0;
2570a708f8fSGustavo F. Padovan }
2580a708f8fSGustavo F. Padovan
259f93fa273SGustavo Padovan static void l2cap_state_change(struct l2cap_chan *chan, int state)
26089bc500eSGustavo F. Padovan {
26142d2d87cSAndrei Emeltchenko BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
262badaaa00SGustavo F. Padovan state_to_string(state));
l2cap_state_change(struct l2cap_chan * chan,int state)263badaaa00SGustavo F. Padovan
26489bc500eSGustavo F. Padovan chan->state = state;
26553f52121SGustavo Padovan chan->ops->state_change(chan, state, 0);
26689bc500eSGustavo F. Padovan }
26789bc500eSGustavo F. Padovan
268f8e73017SGustavo Padovan static inline void l2cap_state_change_and_error(struct l2cap_chan *chan,
269f8e73017SGustavo Padovan int state, int err)
2702e0052e4SAndrei Emeltchenko {
271f8e73017SGustavo Padovan chan->state = state;
l2cap_state_change_and_error(struct l2cap_chan * chan,int state,int err)27253f52121SGustavo Padovan chan->ops->state_change(chan, chan->state, err);
2732e0052e4SAndrei Emeltchenko }
2742e0052e4SAndrei Emeltchenko
2752e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2762e0052e4SAndrei Emeltchenko {
277f8e73017SGustavo Padovan chan->ops->state_change(chan, chan->state, err);
2782e0052e4SAndrei Emeltchenko }
l2cap_chan_set_err(struct l2cap_chan * chan,int err)2792e0052e4SAndrei Emeltchenko
2804239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan)
2814239d16fSMat Martineau {
2824239d16fSMat Martineau if (!delayed_work_pending(&chan->monitor_timer) &&
2834239d16fSMat Martineau chan->retrans_timeout) {
2844239d16fSMat Martineau l2cap_set_timer(chan, &chan->retrans_timer,
2854239d16fSMat Martineau msecs_to_jiffies(chan->retrans_timeout));
2864239d16fSMat Martineau }
2874239d16fSMat Martineau }
2884239d16fSMat Martineau
2894239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan)
2904239d16fSMat Martineau {
2914239d16fSMat Martineau __clear_retrans_timer(chan);
2924239d16fSMat Martineau if (chan->monitor_timeout) {
__set_monitor_timer(struct l2cap_chan * chan)2934239d16fSMat Martineau l2cap_set_timer(chan, &chan->monitor_timer,
2944239d16fSMat Martineau msecs_to_jiffies(chan->monitor_timeout));
2954239d16fSMat Martineau }
2964239d16fSMat Martineau }
2974239d16fSMat Martineau
298608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head,
299608bcc6dSMat Martineau u16 seq)
300608bcc6dSMat Martineau {
301608bcc6dSMat Martineau struct sk_buff *skb;
l2cap_ertm_seq_in_queue(struct sk_buff_head * head,u16 seq)302608bcc6dSMat Martineau
303608bcc6dSMat Martineau skb_queue_walk(head, skb) {
304a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.txseq == seq)
305608bcc6dSMat Martineau return skb;
306608bcc6dSMat Martineau }
307608bcc6dSMat Martineau
308608bcc6dSMat Martineau return NULL;
309608bcc6dSMat Martineau }
310608bcc6dSMat Martineau
3113c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */
3123c588192SMat Martineau
3133c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for
3143c588192SMat Martineau * SREJ requests that are received and for frames that are to be
3153c588192SMat Martineau * retransmitted. These seq_list functions implement a singly-linked
3163c588192SMat Martineau * list in an array, where membership in the list can also be checked
3173c588192SMat Martineau * in constant time. Items can also be added to the tail of the list
3183c588192SMat Martineau * and removed from the head in constant time, without further memory
3193c588192SMat Martineau * allocs or frees.
3203c588192SMat Martineau */
3213c588192SMat Martineau
3223c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
3233c588192SMat Martineau {
3243c588192SMat Martineau size_t alloc_size, i;
3253c588192SMat Martineau
l2cap_seq_list_init(struct l2cap_seq_list * seq_list,u16 size)3263c588192SMat Martineau /* Allocated size is a power of 2 to map sequence numbers
3273c588192SMat Martineau * (which may be up to 14 bits) in to a smaller array that is
3283c588192SMat Martineau * sized for the negotiated ERTM transmit windows.
3293c588192SMat Martineau */
3303c588192SMat Martineau alloc_size = roundup_pow_of_two(size);
3313c588192SMat Martineau
3326da2ec56SKees Cook seq_list->list = kmalloc_array(alloc_size, sizeof(u16), GFP_KERNEL);
3333c588192SMat Martineau if (!seq_list->list)
3343c588192SMat Martineau return -ENOMEM;
3353c588192SMat Martineau
3363c588192SMat Martineau seq_list->mask = alloc_size - 1;
3373c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3383c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3393c588192SMat Martineau for (i = 0; i < alloc_size; i++)
3403c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3413c588192SMat Martineau
3423c588192SMat Martineau return 0;
3433c588192SMat Martineau }
3443c588192SMat Martineau
3453c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
3463c588192SMat Martineau {
3473c588192SMat Martineau kfree(seq_list->list);
3483c588192SMat Martineau }
l2cap_seq_list_free(struct l2cap_seq_list * seq_list)3493c588192SMat Martineau
3503c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
3513c588192SMat Martineau u16 seq)
3523c588192SMat Martineau {
3533c588192SMat Martineau /* Constant-time check for list membership */
3543c588192SMat Martineau return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
3553c588192SMat Martineau }
3563c588192SMat Martineau
35703a0c5d6SJohan Hedberg static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
3583c588192SMat Martineau {
35903a0c5d6SJohan Hedberg u16 seq = seq_list->head;
3603c588192SMat Martineau u16 mask = seq_list->mask;
l2cap_seq_list_pop(struct l2cap_seq_list * seq_list)3613c588192SMat Martineau
3623c588192SMat Martineau seq_list->head = seq_list->list[seq & mask];
3633c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3643c588192SMat Martineau
3653c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
3663c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3673c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3683c588192SMat Martineau }
3693c588192SMat Martineau
3703c588192SMat Martineau return seq;
3713c588192SMat Martineau }
3723c588192SMat Martineau
3733c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
3743c588192SMat Martineau {
3753c588192SMat Martineau u16 i;
376f522ae36SGustavo Padovan
l2cap_seq_list_clear(struct l2cap_seq_list * seq_list)377f522ae36SGustavo Padovan if (seq_list->head == L2CAP_SEQ_LIST_CLEAR)
378f522ae36SGustavo Padovan return;
379f522ae36SGustavo Padovan
3803c588192SMat Martineau for (i = 0; i <= seq_list->mask; i++)
3813c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3823c588192SMat Martineau
3833c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3843c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3853c588192SMat Martineau }
3863c588192SMat Martineau
3873c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
3883c588192SMat Martineau {
3893c588192SMat Martineau u16 mask = seq_list->mask;
3903c588192SMat Martineau
l2cap_seq_list_append(struct l2cap_seq_list * seq_list,u16 seq)3913c588192SMat Martineau /* All appends happen in constant time */
3923c588192SMat Martineau
393f522ae36SGustavo Padovan if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR)
394f522ae36SGustavo Padovan return;
395f522ae36SGustavo Padovan
3963c588192SMat Martineau if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
3973c588192SMat Martineau seq_list->head = seq;
3983c588192SMat Martineau else
3993c588192SMat Martineau seq_list->list[seq_list->tail & mask] = seq;
4003c588192SMat Martineau
4013c588192SMat Martineau seq_list->tail = seq;
4023c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
4033c588192SMat Martineau }
4043c588192SMat Martineau
405721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work)
406ab07801dSGustavo F. Padovan {
407721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
408721c4181SGustavo F. Padovan chan_timer.work);
l2cap_chan_timeout(struct work_struct * work)4093df91ea2SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn;
410ab07801dSGustavo F. Padovan int reason;
411ab07801dSGustavo F. Padovan
412e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
413ab07801dSGustavo F. Padovan
414955b5b6cSDuoming Zhou if (!conn)
415955b5b6cSDuoming Zhou return;
416955b5b6cSDuoming Zhou
417*efc30877SLuiz Augusto von Dentz mutex_lock(&conn->lock);
4186c08fc89SManish Mandlik /* __set_chan_timer() calls l2cap_chan_hold(chan) while scheduling
4196c08fc89SManish Mandlik * this work. No need to call l2cap_chan_hold(chan) here again.
4206c08fc89SManish Mandlik */
4216be36555SAndrei Emeltchenko l2cap_chan_lock(chan);
422ab07801dSGustavo F. Padovan
42389bc500eSGustavo F. Padovan if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
424ab07801dSGustavo F. Padovan reason = ECONNREFUSED;
42589bc500eSGustavo F. Padovan else if (chan->state == BT_CONNECT &&
426ab07801dSGustavo F. Padovan chan->sec_level != BT_SECURITY_SDP)
427ab07801dSGustavo F. Padovan reason = ECONNREFUSED;
428ab07801dSGustavo F. Padovan else
429ab07801dSGustavo F. Padovan reason = ETIMEDOUT;
430ab07801dSGustavo F. Padovan
4310f852724SGustavo F. Padovan l2cap_chan_close(chan, reason);
432ab07801dSGustavo F. Padovan
43380b98027SGustavo Padovan chan->ops->close(chan);
4343df91ea2SAndrei Emeltchenko
4356c08fc89SManish Mandlik l2cap_chan_unlock(chan);
436371fd835SUlisses Furquim l2cap_chan_put(chan);
4376c08fc89SManish Mandlik
438*efc30877SLuiz Augusto von Dentz mutex_unlock(&conn->lock);
439ab07801dSGustavo F. Padovan }
440ab07801dSGustavo F. Padovan
441eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void)
4420a708f8fSGustavo F. Padovan {
44348454079SGustavo F. Padovan struct l2cap_chan *chan;
4440a708f8fSGustavo F. Padovan
l2cap_chan_create(void)44548454079SGustavo F. Padovan chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
44648454079SGustavo F. Padovan if (!chan)
44748454079SGustavo F. Padovan return NULL;
4480a708f8fSGustavo F. Padovan
449be859723STetsuo Handa skb_queue_head_init(&chan->tx_q);
450be859723STetsuo Handa skb_queue_head_init(&chan->srej_q);
451c03b355eSAndrei Emeltchenko mutex_init(&chan->lock);
452c03b355eSAndrei Emeltchenko
453ff714119SJohan Hedberg /* Set default lock nesting level */
454ff714119SJohan Hedberg atomic_set(&chan->nesting, L2CAP_NESTING_NORMAL);
455ff714119SJohan Hedberg
456e2310343SSebastian Urban /* Available receive buffer space is initially unknown */
457e2310343SSebastian Urban chan->rx_avail = -1;
458e2310343SSebastian Urban
459333055f2SGustavo F. Padovan write_lock(&chan_list_lock);
46023691d75SGustavo F. Padovan list_add(&chan->global_l, &chan_list);
461333055f2SGustavo F. Padovan write_unlock(&chan_list_lock);
46223691d75SGustavo F. Padovan
463721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
4642d2cb306STetsuo Handa INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
4652d2cb306STetsuo Handa INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
4662d2cb306STetsuo Handa INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
467ab07801dSGustavo F. Padovan
46889bc500eSGustavo F. Padovan chan->state = BT_OPEN;
46989bc500eSGustavo F. Padovan
470144ad330SSyam Sidhardhan kref_init(&chan->kref);
47171ba0e56SGustavo F. Padovan
4722827011fSMat Martineau /* This flag is cleared in l2cap_chan_ready() */
4732827011fSMat Martineau set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
4742827011fSMat Martineau
475eef1d9b6SGustavo Padovan BT_DBG("chan %p", chan);
476abc545b8SSzymon Janc
47748454079SGustavo F. Padovan return chan;
4780a708f8fSGustavo F. Padovan }
4796b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_create);
4800a708f8fSGustavo F. Padovan
481144ad330SSyam Sidhardhan static void l2cap_chan_destroy(struct kref *kref)
4826ff5abbfSGustavo F. Padovan {
483144ad330SSyam Sidhardhan struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref);
484144ad330SSyam Sidhardhan
l2cap_chan_destroy(struct kref * kref)4854af66c69SJaganath Kanakkassery BT_DBG("chan %p", chan);
4864af66c69SJaganath Kanakkassery
487333055f2SGustavo F. Padovan write_lock(&chan_list_lock);
48823691d75SGustavo F. Padovan list_del(&chan->global_l);
489333055f2SGustavo F. Padovan write_unlock(&chan_list_lock);
49023691d75SGustavo F. Padovan
4914af66c69SJaganath Kanakkassery kfree(chan);
4926ff5abbfSGustavo F. Padovan }
4936ff5abbfSGustavo F. Padovan
49430648372SJaganath Kanakkassery void l2cap_chan_hold(struct l2cap_chan *c)
49530648372SJaganath Kanakkassery {
49693917fd2SKai Ye BT_DBG("chan %p orig refcnt %u", c, kref_read(&c->kref));
49730648372SJaganath Kanakkassery
l2cap_chan_hold(struct l2cap_chan * c)498144ad330SSyam Sidhardhan kref_get(&c->kref);
49930648372SJaganath Kanakkassery }
50030648372SJaganath Kanakkassery
501d0be8347SLuiz Augusto von Dentz struct l2cap_chan *l2cap_chan_hold_unless_zero(struct l2cap_chan *c)
502d0be8347SLuiz Augusto von Dentz {
503d0be8347SLuiz Augusto von Dentz BT_DBG("chan %p orig refcnt %u", c, kref_read(&c->kref));
504d0be8347SLuiz Augusto von Dentz
l2cap_chan_hold_unless_zero(struct l2cap_chan * c)505d0be8347SLuiz Augusto von Dentz if (!kref_get_unless_zero(&c->kref))
506d0be8347SLuiz Augusto von Dentz return NULL;
507d0be8347SLuiz Augusto von Dentz
508d0be8347SLuiz Augusto von Dentz return c;
509d0be8347SLuiz Augusto von Dentz }
510d0be8347SLuiz Augusto von Dentz
51130648372SJaganath Kanakkassery void l2cap_chan_put(struct l2cap_chan *c)
51230648372SJaganath Kanakkassery {
51393917fd2SKai Ye BT_DBG("chan %p orig refcnt %u", c, kref_read(&c->kref));
51430648372SJaganath Kanakkassery
l2cap_chan_put(struct l2cap_chan * c)515144ad330SSyam Sidhardhan kref_put(&c->kref, l2cap_chan_destroy);
51630648372SJaganath Kanakkassery }
5176b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_put);
51830648372SJaganath Kanakkassery
519bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan)
520bd4b1653SAndrei Emeltchenko {
521bd4b1653SAndrei Emeltchenko chan->fcs = L2CAP_FCS_CRC16;
522bd4b1653SAndrei Emeltchenko chan->max_tx = L2CAP_DEFAULT_MAX_TX;
l2cap_chan_set_defaults(struct l2cap_chan * chan)523bd4b1653SAndrei Emeltchenko chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
524bd4b1653SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
5256a5e8165SJukka Rissanen chan->remote_max_tx = chan->max_tx;
5266a5e8165SJukka Rissanen chan->remote_tx_win = chan->tx_win;
527c20f8e35SMat Martineau chan->ack_win = L2CAP_DEFAULT_TX_WINDOW;
528bd4b1653SAndrei Emeltchenko chan->sec_level = BT_SECURITY_LOW;
5296a5e8165SJukka Rissanen chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
5306a5e8165SJukka Rissanen chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
5316a5e8165SJukka Rissanen chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
5323a9d54b1SArchie Pusaka
5336a5e8165SJukka Rissanen chan->conf_state = 0;
5343a9d54b1SArchie Pusaka set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
535bd4b1653SAndrei Emeltchenko
536bd4b1653SAndrei Emeltchenko set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
537bd4b1653SAndrei Emeltchenko }
5386b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_set_defaults);
539bd4b1653SAndrei Emeltchenko
540e2310343SSebastian Urban static __u16 l2cap_le_rx_credits(struct l2cap_chan *chan)
541e2310343SSebastian Urban {
542e2310343SSebastian Urban size_t sdu_len = chan->sdu ? chan->sdu->len : 0;
543e2310343SSebastian Urban
l2cap_le_rx_credits(struct l2cap_chan * chan)544e2310343SSebastian Urban if (chan->mps == 0)
545e2310343SSebastian Urban return 0;
546e2310343SSebastian Urban
547e2310343SSebastian Urban /* If we don't know the available space in the receiver buffer, give
548e2310343SSebastian Urban * enough credits for a full packet.
549e2310343SSebastian Urban */
550e2310343SSebastian Urban if (chan->rx_avail == -1)
551e2310343SSebastian Urban return (chan->imtu / chan->mps) + 1;
552e2310343SSebastian Urban
553e2310343SSebastian Urban /* If we know how much space is available in the receive buffer, give
554e2310343SSebastian Urban * out as many credits as would fill the buffer.
555e2310343SSebastian Urban */
556e2310343SSebastian Urban if (chan->rx_avail <= sdu_len)
557e2310343SSebastian Urban return 0;
558e2310343SSebastian Urban
559e2310343SSebastian Urban return DIV_ROUND_UP(chan->rx_avail - sdu_len, chan->mps);
560e2310343SSebastian Urban }
561e2310343SSebastian Urban
562ba8f5289SLuiz Augusto von Dentz static void l2cap_le_flowctl_init(struct l2cap_chan *chan, u16 tx_credits)
56338319713SJohan Hedberg {
5640ce43ce6SJohan Hedberg chan->sdu = NULL;
5650ce43ce6SJohan Hedberg chan->sdu_last_frag = NULL;
l2cap_le_flowctl_init(struct l2cap_chan * chan,u16 tx_credits)5660ce43ce6SJohan Hedberg chan->sdu_len = 0;
567ba8f5289SLuiz Augusto von Dentz chan->tx_credits = tx_credits;
568fe149310SLuiz Augusto von Dentz /* Derive MPS from connection MTU to stop HCI fragmentation */
569fe149310SLuiz Augusto von Dentz chan->mps = min_t(u16, chan->imtu, chan->conn->mtu - L2CAP_HDR_SIZE);
570e2310343SSebastian Urban chan->rx_credits = l2cap_le_rx_credits(chan);
5710ce43ce6SJohan Hedberg
5720ce43ce6SJohan Hedberg skb_queue_head_init(&chan->tx_q);
57338319713SJohan Hedberg }
57438319713SJohan Hedberg
57515f02b91SLuiz Augusto von Dentz static void l2cap_ecred_init(struct l2cap_chan *chan, u16 tx_credits)
57615f02b91SLuiz Augusto von Dentz {
57715f02b91SLuiz Augusto von Dentz l2cap_le_flowctl_init(chan, tx_credits);
57815f02b91SLuiz Augusto von Dentz
l2cap_ecred_init(struct l2cap_chan * chan,u16 tx_credits)57915f02b91SLuiz Augusto von Dentz /* L2CAP implementations shall support a minimum MPS of 64 octets */
58015f02b91SLuiz Augusto von Dentz if (chan->mps < L2CAP_ECRED_MIN_MPS) {
58115f02b91SLuiz Augusto von Dentz chan->mps = L2CAP_ECRED_MIN_MPS;
582e2310343SSebastian Urban chan->rx_credits = l2cap_le_rx_credits(chan);
58315f02b91SLuiz Augusto von Dentz }
58415f02b91SLuiz Augusto von Dentz }
58515f02b91SLuiz Augusto von Dentz
58693c3e8f5SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
5870a708f8fSGustavo F. Padovan {
5880a708f8fSGustavo F. Padovan BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
589097db76cSAndrei Emeltchenko __le16_to_cpu(chan->psm), chan->dcid);
__l2cap_chan_add(struct l2cap_conn * conn,struct l2cap_chan * chan)5900a708f8fSGustavo F. Padovan
5919f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
5920a708f8fSGustavo F. Padovan
5938c1d787bSGustavo F. Padovan chan->conn = conn;
5940a708f8fSGustavo F. Padovan
5955491120eSAndrei Emeltchenko switch (chan->chan_type) {
5965491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_ORIENTED:
5970a708f8fSGustavo F. Padovan /* Alloc CID for connection-oriented socket */
598fe4128e0SGustavo F. Padovan chan->scid = l2cap_alloc_cid(conn);
59921626e62SJohan Hedberg if (conn->hcon->type == ACL_LINK)
6000c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU;
6015491120eSAndrei Emeltchenko break;
6025491120eSAndrei Emeltchenko
6035491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_LESS:
6040a708f8fSGustavo F. Padovan /* Connectionless socket */
605fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_CONN_LESS;
606fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_CONN_LESS;
6070c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU;
6085491120eSAndrei Emeltchenko break;
6095491120eSAndrei Emeltchenko
6102338a7e0SJohan Hedberg case L2CAP_CHAN_FIXED:
6112338a7e0SJohan Hedberg /* Caller will set CID and CID specific MTU values */
612416fa752SAndrei Emeltchenko break;
613416fa752SAndrei Emeltchenko
6145491120eSAndrei Emeltchenko default:
6150a708f8fSGustavo F. Padovan /* Raw socket can send/recv signalling messages only */
616fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_SIGNALING;
617fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_SIGNALING;
6180c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU;
6190a708f8fSGustavo F. Padovan }
6200a708f8fSGustavo F. Padovan
6218f7975b1SAndrei Emeltchenko chan->local_id = L2CAP_BESTEFFORT_ID;
6228f7975b1SAndrei Emeltchenko chan->local_stype = L2CAP_SERV_BESTEFFORT;
6238f7975b1SAndrei Emeltchenko chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE;
6248f7975b1SAndrei Emeltchenko chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME;
6258f7975b1SAndrei Emeltchenko chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
6268936fa6dSAndrei Emeltchenko chan->local_flush_to = L2CAP_EFS_DEFAULT_FLUSH_TO;
6278f7975b1SAndrei Emeltchenko
628371fd835SUlisses Furquim l2cap_chan_hold(chan);
629baa7e1faSGustavo F. Padovan
630c16900cfSJohan Hedberg /* Only keep a reference for fixed channels if they requested it */
631c16900cfSJohan Hedberg if (chan->chan_type != L2CAP_CHAN_FIXED ||
632c16900cfSJohan Hedberg test_bit(FLAG_HOLD_HCI_CONN, &chan->flags))
6335ee9891dSJohan Hedberg hci_conn_hold(conn->hcon);
6345ee9891dSJohan Hedberg
635fbe5582aSLuiz Augusto von Dentz /* Append to the list since the order matters for ECRED */
636fbe5582aSLuiz Augusto von Dentz list_add_tail(&chan->list, &conn->chan_l);
637643162a8SAndrei Emeltchenko }
638643162a8SAndrei Emeltchenko
639466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
640643162a8SAndrei Emeltchenko {
641*efc30877SLuiz Augusto von Dentz mutex_lock(&conn->lock);
642643162a8SAndrei Emeltchenko __l2cap_chan_add(conn, chan);
l2cap_chan_add(struct l2cap_conn * conn,struct l2cap_chan * chan)643*efc30877SLuiz Augusto von Dentz mutex_unlock(&conn->lock);
6440a708f8fSGustavo F. Padovan }
6450a708f8fSGustavo F. Padovan
646466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err)
6470a708f8fSGustavo F. Padovan {
6488c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn;
6490a708f8fSGustavo F. Padovan
l2cap_chan_del(struct l2cap_chan * chan,int err)650c9b66675SGustavo F. Padovan __clear_chan_timer(chan);
6510a708f8fSGustavo F. Padovan
65249d11741SJohan Hedberg BT_DBG("chan %p, conn %p, err %d, state %s", chan, conn, err,
65349d11741SJohan Hedberg state_to_string(chan->state));
6540a708f8fSGustavo F. Padovan
65572847ce0SJohan Hedberg chan->ops->teardown(chan, err);
65672847ce0SJohan Hedberg
6570a708f8fSGustavo F. Padovan if (conn) {
658baa7e1faSGustavo F. Padovan /* Delete from channel list */
6593df91ea2SAndrei Emeltchenko list_del(&chan->list);
6603d57dc68SGustavo F. Padovan
661371fd835SUlisses Furquim l2cap_chan_put(chan);
662baa7e1faSGustavo F. Padovan
6638c1d787bSGustavo F. Padovan chan->conn = NULL;
6643cabbfdaSAndrei Emeltchenko
665c16900cfSJohan Hedberg /* Reference was only held for non-fixed channels or
666c16900cfSJohan Hedberg * fixed channels that explicitly requested it using the
667c16900cfSJohan Hedberg * FLAG_HOLD_HCI_CONN flag.
668c16900cfSJohan Hedberg */
669c16900cfSJohan Hedberg if (chan->chan_type != L2CAP_CHAN_FIXED ||
670c16900cfSJohan Hedberg test_bit(FLAG_HOLD_HCI_CONN, &chan->flags))
67176a68ba0SDavid Herrmann hci_conn_drop(conn->hcon);
672419e08c1SAndrei Emeltchenko }
673419e08c1SAndrei Emeltchenko
6742827011fSMat Martineau if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
6756ff5abbfSGustavo F. Padovan return;
6762ead70b8SGustavo F. Padovan
677ee556f66SGustavo Padovan switch (chan->mode) {
678ee556f66SGustavo Padovan case L2CAP_MODE_BASIC:
679ee556f66SGustavo Padovan break;
6800a708f8fSGustavo F. Padovan
68138319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL:
68215f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL:
683177f8f2bSJohan Hedberg skb_queue_purge(&chan->tx_q);
68438319713SJohan Hedberg break;
68538319713SJohan Hedberg
686ee556f66SGustavo Padovan case L2CAP_MODE_ERTM:
6871a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan);
6881a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan);
6891a09bcb9SGustavo F. Padovan __clear_ack_timer(chan);
6900a708f8fSGustavo F. Padovan
691f1c6775bSGustavo F. Padovan skb_queue_purge(&chan->srej_q);
6920a708f8fSGustavo F. Padovan
6933c588192SMat Martineau l2cap_seq_list_free(&chan->srej_list);
6943c588192SMat Martineau l2cap_seq_list_free(&chan->retrans_list);
69519186c7bSGustavo A. R. Silva fallthrough;
696ee556f66SGustavo Padovan
697ee556f66SGustavo Padovan case L2CAP_MODE_STREAMING:
698ee556f66SGustavo Padovan skb_queue_purge(&chan->tx_q);
699ee556f66SGustavo Padovan break;
7000a708f8fSGustavo F. Padovan }
7010a708f8fSGustavo F. Padovan }
7026b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_del);
7030a708f8fSGustavo F. Padovan
7049aa9d947SLuiz Augusto von Dentz static void __l2cap_chan_list_id(struct l2cap_conn *conn, u16 id,
7059aa9d947SLuiz Augusto von Dentz l2cap_chan_func_t func, void *data)
7069aa9d947SLuiz Augusto von Dentz {
7079aa9d947SLuiz Augusto von Dentz struct l2cap_chan *chan, *l;
__l2cap_chan_list_id(struct l2cap_conn * conn,u16 id,l2cap_chan_func_t func,void * data)7089aa9d947SLuiz Augusto von Dentz
7099aa9d947SLuiz Augusto von Dentz list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
7109aa9d947SLuiz Augusto von Dentz if (chan->ident == id)
7119aa9d947SLuiz Augusto von Dentz func(chan, data);
7129aa9d947SLuiz Augusto von Dentz }
7139aa9d947SLuiz Augusto von Dentz }
7149aa9d947SLuiz Augusto von Dentz
715da49b602SLuiz Augusto von Dentz static void __l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func,
716da49b602SLuiz Augusto von Dentz void *data)
717da49b602SLuiz Augusto von Dentz {
718da49b602SLuiz Augusto von Dentz struct l2cap_chan *chan;
__l2cap_chan_list(struct l2cap_conn * conn,l2cap_chan_func_t func,void * data)719da49b602SLuiz Augusto von Dentz
720da49b602SLuiz Augusto von Dentz list_for_each_entry(chan, &conn->chan_l, list) {
721da49b602SLuiz Augusto von Dentz func(chan, data);
722da49b602SLuiz Augusto von Dentz }
723da49b602SLuiz Augusto von Dentz }
724da49b602SLuiz Augusto von Dentz
725da49b602SLuiz Augusto von Dentz void l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func,
726da49b602SLuiz Augusto von Dentz void *data)
727da49b602SLuiz Augusto von Dentz {
728da49b602SLuiz Augusto von Dentz if (!conn)
l2cap_chan_list(struct l2cap_conn * conn,l2cap_chan_func_t func,void * data)729da49b602SLuiz Augusto von Dentz return;
730da49b602SLuiz Augusto von Dentz
731*efc30877SLuiz Augusto von Dentz mutex_lock(&conn->lock);
732da49b602SLuiz Augusto von Dentz __l2cap_chan_list(conn, func, data);
733*efc30877SLuiz Augusto von Dentz mutex_unlock(&conn->lock);
734da49b602SLuiz Augusto von Dentz }
735da49b602SLuiz Augusto von Dentz
736da49b602SLuiz Augusto von Dentz EXPORT_SYMBOL_GPL(l2cap_chan_list);
737da49b602SLuiz Augusto von Dentz
738f3d82d0cSJohan Hedberg static void l2cap_conn_update_id_addr(struct work_struct *work)
739387a33e3SJohan Hedberg {
740f3d82d0cSJohan Hedberg struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
741b8b23001SLuiz Augusto von Dentz id_addr_timer.work);
l2cap_conn_update_id_addr(struct work_struct * work)742f3d82d0cSJohan Hedberg struct hci_conn *hcon = conn->hcon;
743387a33e3SJohan Hedberg struct l2cap_chan *chan;
744387a33e3SJohan Hedberg
745*efc30877SLuiz Augusto von Dentz mutex_lock(&conn->lock);
746387a33e3SJohan Hedberg
747387a33e3SJohan Hedberg list_for_each_entry(chan, &conn->chan_l, list) {
748387a33e3SJohan Hedberg l2cap_chan_lock(chan);
749387a33e3SJohan Hedberg bacpy(&chan->dst, &hcon->dst);
750a250e048SJohan Hedberg chan->dst_type = bdaddr_dst_type(hcon);
751387a33e3SJohan Hedberg l2cap_chan_unlock(chan);
752387a33e3SJohan Hedberg }
753387a33e3SJohan Hedberg
754*efc30877SLuiz Augusto von Dentz mutex_unlock(&conn->lock);
755387a33e3SJohan Hedberg }
756387a33e3SJohan Hedberg
75727e2d4c8SJohan Hedberg static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan)
75827e2d4c8SJohan Hedberg {
75927e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn;
76027e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp;
l2cap_chan_le_connect_reject(struct l2cap_chan * chan)76127e2d4c8SJohan Hedberg u16 result;
76227e2d4c8SJohan Hedberg
76327e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
764571f7390SMallikarjun Phulari result = L2CAP_CR_LE_AUTHORIZATION;
76527e2d4c8SJohan Hedberg else
766571f7390SMallikarjun Phulari result = L2CAP_CR_LE_BAD_PSM;
76727e2d4c8SJohan Hedberg
76827e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_DISCONN);
76927e2d4c8SJohan Hedberg
77027e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid);
77127e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu);
7723916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps);
7730cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits);
77427e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result);
77527e2d4c8SJohan Hedberg
77627e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
77727e2d4c8SJohan Hedberg &rsp);
77827e2d4c8SJohan Hedberg }
77927e2d4c8SJohan Hedberg
78015f02b91SLuiz Augusto von Dentz static void l2cap_chan_ecred_connect_reject(struct l2cap_chan *chan)
78115f02b91SLuiz Augusto von Dentz {
78215f02b91SLuiz Augusto von Dentz l2cap_state_change(chan, BT_DISCONN);
78315f02b91SLuiz Augusto von Dentz
l2cap_chan_ecred_connect_reject(struct l2cap_chan * chan)7849aa9d947SLuiz Augusto von Dentz __l2cap_ecred_conn_rsp_defer(chan);
78515f02b91SLuiz Augusto von Dentz }
78615f02b91SLuiz Augusto von Dentz
787791d60f7SJohan Hedberg static void l2cap_chan_connect_reject(struct l2cap_chan *chan)
788791d60f7SJohan Hedberg {
789791d60f7SJohan Hedberg struct l2cap_conn *conn = chan->conn;
790791d60f7SJohan Hedberg struct l2cap_conn_rsp rsp;
l2cap_chan_connect_reject(struct l2cap_chan * chan)791791d60f7SJohan Hedberg u16 result;
792791d60f7SJohan Hedberg
793791d60f7SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
794791d60f7SJohan Hedberg result = L2CAP_CR_SEC_BLOCK;
795791d60f7SJohan Hedberg else
796791d60f7SJohan Hedberg result = L2CAP_CR_BAD_PSM;
797791d60f7SJohan Hedberg
798791d60f7SJohan Hedberg l2cap_state_change(chan, BT_DISCONN);
799791d60f7SJohan Hedberg
800791d60f7SJohan Hedberg rsp.scid = cpu_to_le16(chan->dcid);
801791d60f7SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid);
802791d60f7SJohan Hedberg rsp.result = cpu_to_le16(result);
803dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
804791d60f7SJohan Hedberg
805791d60f7SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
806791d60f7SJohan Hedberg }
807791d60f7SJohan Hedberg
8080f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason)
8094519de9aSGustavo F. Padovan {
8104519de9aSGustavo F. Padovan struct l2cap_conn *conn = chan->conn;
8114519de9aSGustavo F. Padovan
l2cap_chan_close(struct l2cap_chan * chan,int reason)8127eafc59eSMarcel Holtmann BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
8134519de9aSGustavo F. Padovan
81489bc500eSGustavo F. Padovan switch (chan->state) {
8154519de9aSGustavo F. Padovan case BT_LISTEN:
816c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0);
8174519de9aSGustavo F. Padovan break;
8184519de9aSGustavo F. Padovan
8194519de9aSGustavo F. Padovan case BT_CONNECTED:
8204519de9aSGustavo F. Padovan case BT_CONFIG:
8217b25c9b3SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
8228d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
8235e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, reason);
8244519de9aSGustavo F. Padovan } else
8254519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason);
8264519de9aSGustavo F. Padovan break;
8274519de9aSGustavo F. Padovan
8284519de9aSGustavo F. Padovan case BT_CONNECT2:
829791d60f7SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
830791d60f7SJohan Hedberg if (conn->hcon->type == ACL_LINK)
831791d60f7SJohan Hedberg l2cap_chan_connect_reject(chan);
83215f02b91SLuiz Augusto von Dentz else if (conn->hcon->type == LE_LINK) {
83315f02b91SLuiz Augusto von Dentz switch (chan->mode) {
83415f02b91SLuiz Augusto von Dentz case L2CAP_MODE_LE_FLOWCTL:
83527e2d4c8SJohan Hedberg l2cap_chan_le_connect_reject(chan);
83615f02b91SLuiz Augusto von Dentz break;
83715f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL:
83815f02b91SLuiz Augusto von Dentz l2cap_chan_ecred_connect_reject(chan);
8399aa9d947SLuiz Augusto von Dentz return;
84015f02b91SLuiz Augusto von Dentz }
84115f02b91SLuiz Augusto von Dentz }
8424519de9aSGustavo F. Padovan }
8434519de9aSGustavo F. Padovan
8444519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason);
8454519de9aSGustavo F. Padovan break;
8464519de9aSGustavo F. Padovan
8474519de9aSGustavo F. Padovan case BT_CONNECT:
8484519de9aSGustavo F. Padovan case BT_DISCONN:
8494519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason);
8504519de9aSGustavo F. Padovan break;
8514519de9aSGustavo F. Padovan
8524519de9aSGustavo F. Padovan default:
853c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0);
8544519de9aSGustavo F. Padovan break;
8554519de9aSGustavo F. Padovan }
8564519de9aSGustavo F. Padovan }
8576b8d4a6aSJukka Rissanen EXPORT_SYMBOL(l2cap_chan_close);
8584519de9aSGustavo F. Padovan
8594343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
8600a708f8fSGustavo F. Padovan {
8616a974b50SMarcel Holtmann switch (chan->chan_type) {
8626a974b50SMarcel Holtmann case L2CAP_CHAN_RAW:
l2cap_get_auth_type(struct l2cap_chan * chan)8634343478fSGustavo F. Padovan switch (chan->sec_level) {
8640a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH:
8657d513e92SMarcel Holtmann case BT_SECURITY_FIPS:
8660a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING_MITM;
8670a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM:
8680a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING;
8690a708f8fSGustavo F. Padovan default:
8700a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING;
8710a708f8fSGustavo F. Padovan }
8726a974b50SMarcel Holtmann break;
8733124b843SMarcel Holtmann case L2CAP_CHAN_CONN_LESS:
874dcf4adbfSJoe Perches if (chan->psm == cpu_to_le16(L2CAP_PSM_3DSP)) {
8753124b843SMarcel Holtmann if (chan->sec_level == BT_SECURITY_LOW)
8763124b843SMarcel Holtmann chan->sec_level = BT_SECURITY_SDP;
8773124b843SMarcel Holtmann }
8787d513e92SMarcel Holtmann if (chan->sec_level == BT_SECURITY_HIGH ||
8797d513e92SMarcel Holtmann chan->sec_level == BT_SECURITY_FIPS)
8803124b843SMarcel Holtmann return HCI_AT_NO_BONDING_MITM;
8813124b843SMarcel Holtmann else
8823124b843SMarcel Holtmann return HCI_AT_NO_BONDING;
8833124b843SMarcel Holtmann break;
8846a974b50SMarcel Holtmann case L2CAP_CHAN_CONN_ORIENTED:
885dcf4adbfSJoe Perches if (chan->psm == cpu_to_le16(L2CAP_PSM_SDP)) {
8864343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_LOW)
8874343478fSGustavo F. Padovan chan->sec_level = BT_SECURITY_SDP;
8880a708f8fSGustavo F. Padovan
8897d513e92SMarcel Holtmann if (chan->sec_level == BT_SECURITY_HIGH ||
8907d513e92SMarcel Holtmann chan->sec_level == BT_SECURITY_FIPS)
8910a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING_MITM;
8920a708f8fSGustavo F. Padovan else
8930a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING;
8946a974b50SMarcel Holtmann }
89519186c7bSGustavo A. R. Silva fallthrough;
89619186c7bSGustavo A. R. Silva
8976a974b50SMarcel Holtmann default:
8984343478fSGustavo F. Padovan switch (chan->sec_level) {
8990a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH:
9007d513e92SMarcel Holtmann case BT_SECURITY_FIPS:
9010a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING_MITM;
9020a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM:
9030a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING;
9040a708f8fSGustavo F. Padovan default:
9050a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING;
9060a708f8fSGustavo F. Padovan }
9076a974b50SMarcel Holtmann break;
9080a708f8fSGustavo F. Padovan }
9090a708f8fSGustavo F. Padovan }
9100a708f8fSGustavo F. Padovan
9110a708f8fSGustavo F. Padovan /* Service level security */
912e7cafc45SJohan Hedberg int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator)
9130a708f8fSGustavo F. Padovan {
9148c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn;
9150a708f8fSGustavo F. Padovan __u8 auth_type;
l2cap_chan_check_security(struct l2cap_chan * chan,bool initiator)9160a708f8fSGustavo F. Padovan
917a17de2feSJohan Hedberg if (conn->hcon->type == LE_LINK)
918a17de2feSJohan Hedberg return smp_conn_security(conn->hcon, chan->sec_level);
919a17de2feSJohan Hedberg
9204343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan);
9210a708f8fSGustavo F. Padovan
922e7cafc45SJohan Hedberg return hci_conn_security(conn->hcon, chan->sec_level, auth_type,
923e7cafc45SJohan Hedberg initiator);
9240a708f8fSGustavo F. Padovan }
9250a708f8fSGustavo F. Padovan
926b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn)
9270a708f8fSGustavo F. Padovan {
9280a708f8fSGustavo F. Padovan u8 id;
9290a708f8fSGustavo F. Padovan
l2cap_get_ident(struct l2cap_conn * conn)9300a708f8fSGustavo F. Padovan /* Get next available identificator.
9310a708f8fSGustavo F. Padovan * 1 - 128 are used by kernel.
9320a708f8fSGustavo F. Padovan * 129 - 199 are reserved.
9330a708f8fSGustavo F. Padovan * 200 - 254 are used by utilities like l2ping, etc.
9340a708f8fSGustavo F. Padovan */
9350a708f8fSGustavo F. Padovan
9365a54e7c8SMarcel Holtmann mutex_lock(&conn->ident_lock);
9370a708f8fSGustavo F. Padovan
9380a708f8fSGustavo F. Padovan if (++conn->tx_ident > 128)
9390a708f8fSGustavo F. Padovan conn->tx_ident = 1;
9400a708f8fSGustavo F. Padovan
9410a708f8fSGustavo F. Padovan id = conn->tx_ident;
9420a708f8fSGustavo F. Padovan
9435a54e7c8SMarcel Holtmann mutex_unlock(&conn->ident_lock);
9440a708f8fSGustavo F. Padovan
9450a708f8fSGustavo F. Padovan return id;
9460a708f8fSGustavo F. Padovan }
9470a708f8fSGustavo F. Padovan
948c96cce85SLuiz Augusto von Dentz static void l2cap_send_acl(struct l2cap_conn *conn, struct sk_buff *skb,
949c96cce85SLuiz Augusto von Dentz u8 flags)
950c96cce85SLuiz Augusto von Dentz {
951c96cce85SLuiz Augusto von Dentz /* Check if the hcon still valid before attempting to send */
l2cap_send_cmd(struct l2cap_conn * conn,u8 ident,u8 code,u16 len,void * data)952c96cce85SLuiz Augusto von Dentz if (hci_conn_valid(conn->hcon->hdev, conn->hcon))
953c96cce85SLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, flags);
954c96cce85SLuiz Augusto von Dentz else
955c96cce85SLuiz Augusto von Dentz kfree_skb(skb);
956c96cce85SLuiz Augusto von Dentz }
957c96cce85SLuiz Augusto von Dentz
9582d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
9592d792818SGustavo Padovan void *data)
9600a708f8fSGustavo F. Padovan {
9610a708f8fSGustavo F. Padovan struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
9620a708f8fSGustavo F. Padovan u8 flags;
9630a708f8fSGustavo F. Padovan
9640a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x", code);
9650a708f8fSGustavo F. Padovan
9660a708f8fSGustavo F. Padovan if (!skb)
9670a708f8fSGustavo F. Padovan return;
9680a708f8fSGustavo F. Padovan
969f6af675eSSteven Walter /* Use NO_FLUSH if supported or we have an LE link (which does
970f6af675eSSteven Walter * not support auto-flushing packets) */
971f6af675eSSteven Walter if (lmp_no_flush_capable(conn->hcon->hdev) ||
972f6af675eSSteven Walter conn->hcon->type == LE_LINK)
9730a708f8fSGustavo F. Padovan flags = ACL_START_NO_FLUSH;
9740a708f8fSGustavo F. Padovan else
9750a708f8fSGustavo F. Padovan flags = ACL_START;
9760a708f8fSGustavo F. Padovan
l2cap_do_send(struct l2cap_chan * chan,struct sk_buff * skb)97714b12d0bSJaikumar Ganesh bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
9785e59b791SLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX;
97914b12d0bSJaikumar Ganesh
980c96cce85SLuiz Augusto von Dentz l2cap_send_acl(conn, skb, flags);
9810a708f8fSGustavo F. Padovan }
9820a708f8fSGustavo F. Padovan
98373d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
98473d80debSLuiz Augusto von Dentz {
98573d80debSLuiz Augusto von Dentz struct hci_conn *hcon = chan->conn->hcon;
98673d80debSLuiz Augusto von Dentz u16 flags;
98773d80debSLuiz Augusto von Dentz
98873d80debSLuiz Augusto von Dentz BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
98973d80debSLuiz Augusto von Dentz skb->priority);
99073d80debSLuiz Augusto von Dentz
991f6af675eSSteven Walter /* Use NO_FLUSH for LE links (where this is the only option) or
992f6af675eSSteven Walter * if the BR/EDR link supports it and flushing has not been
993f6af675eSSteven Walter * explicitly requested (through FLAG_FLUSHABLE).
994f6af675eSSteven Walter */
995f6af675eSSteven Walter if (hcon->type == LE_LINK ||
996f6af675eSSteven Walter (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
997f6af675eSSteven Walter lmp_no_flush_capable(hcon->hdev)))
99873d80debSLuiz Augusto von Dentz flags = ACL_START_NO_FLUSH;
99973d80debSLuiz Augusto von Dentz else
__unpack_enhanced_control(u16 enh,struct l2cap_ctrl * control)100073d80debSLuiz Augusto von Dentz flags = ACL_START;
100173d80debSLuiz Augusto von Dentz
100273d80debSLuiz Augusto von Dentz bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
100373d80debSLuiz Augusto von Dentz hci_send_acl(chan->conn->hchan, skb, flags);
10040a708f8fSGustavo F. Padovan }
10050a708f8fSGustavo F. Padovan
1006b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
1007b5c6aaedSMat Martineau {
1008b5c6aaedSMat Martineau control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
1009b5c6aaedSMat Martineau control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
1010b5c6aaedSMat Martineau
1011b5c6aaedSMat Martineau if (enh & L2CAP_CTRL_FRAME_TYPE) {
1012b5c6aaedSMat Martineau /* S-Frame */
1013b5c6aaedSMat Martineau control->sframe = 1;
1014b5c6aaedSMat Martineau control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
1015b5c6aaedSMat Martineau control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
1016b5c6aaedSMat Martineau
1017b5c6aaedSMat Martineau control->sar = 0;
1018b5c6aaedSMat Martineau control->txseq = 0;
1019b5c6aaedSMat Martineau } else {
1020b5c6aaedSMat Martineau /* I-Frame */
1021b5c6aaedSMat Martineau control->sframe = 0;
1022b5c6aaedSMat Martineau control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
1023b5c6aaedSMat Martineau control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
__unpack_extended_control(u32 ext,struct l2cap_ctrl * control)1024b5c6aaedSMat Martineau
1025b5c6aaedSMat Martineau control->poll = 0;
1026b5c6aaedSMat Martineau control->super = 0;
1027b5c6aaedSMat Martineau }
1028b5c6aaedSMat Martineau }
1029b5c6aaedSMat Martineau
1030b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
1031b5c6aaedSMat Martineau {
1032b5c6aaedSMat Martineau control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
1033b5c6aaedSMat Martineau control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
1034b5c6aaedSMat Martineau
1035b5c6aaedSMat Martineau if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
1036b5c6aaedSMat Martineau /* S-Frame */
1037b5c6aaedSMat Martineau control->sframe = 1;
1038b5c6aaedSMat Martineau control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
1039b5c6aaedSMat Martineau control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
1040b5c6aaedSMat Martineau
1041b5c6aaedSMat Martineau control->sar = 0;
1042b5c6aaedSMat Martineau control->txseq = 0;
1043b5c6aaedSMat Martineau } else {
1044b5c6aaedSMat Martineau /* I-Frame */
1045b5c6aaedSMat Martineau control->sframe = 0;
1046b5c6aaedSMat Martineau control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
1047b5c6aaedSMat Martineau control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
__unpack_control(struct l2cap_chan * chan,struct sk_buff * skb)1048b5c6aaedSMat Martineau
1049b5c6aaedSMat Martineau control->poll = 0;
1050b5c6aaedSMat Martineau control->super = 0;
1051b5c6aaedSMat Martineau }
1052b5c6aaedSMat Martineau }
1053b5c6aaedSMat Martineau
1054b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan,
1055b5c6aaedSMat Martineau struct sk_buff *skb)
1056b5c6aaedSMat Martineau {
1057b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
1058b5c6aaedSMat Martineau __unpack_extended_control(get_unaligned_le32(skb->data),
1059a4368ff3SJohan Hedberg &bt_cb(skb)->l2cap);
1060cec8ab6eSMat Martineau skb_pull(skb, L2CAP_EXT_CTRL_SIZE);
1061b5c6aaedSMat Martineau } else {
__pack_extended_control(struct l2cap_ctrl * control)1062b5c6aaedSMat Martineau __unpack_enhanced_control(get_unaligned_le16(skb->data),
1063a4368ff3SJohan Hedberg &bt_cb(skb)->l2cap);
1064cec8ab6eSMat Martineau skb_pull(skb, L2CAP_ENH_CTRL_SIZE);
1065b5c6aaedSMat Martineau }
1066b5c6aaedSMat Martineau }
1067b5c6aaedSMat Martineau
1068b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control)
1069b5c6aaedSMat Martineau {
1070b5c6aaedSMat Martineau u32 packed;
1071b5c6aaedSMat Martineau
1072b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
1073b5c6aaedSMat Martineau packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
1074b5c6aaedSMat Martineau
1075b5c6aaedSMat Martineau if (control->sframe) {
1076b5c6aaedSMat Martineau packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
1077b5c6aaedSMat Martineau packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
1078b5c6aaedSMat Martineau packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
1079b5c6aaedSMat Martineau } else {
1080b5c6aaedSMat Martineau packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
__pack_enhanced_control(struct l2cap_ctrl * control)1081b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
1082b5c6aaedSMat Martineau }
1083b5c6aaedSMat Martineau
1084b5c6aaedSMat Martineau return packed;
1085b5c6aaedSMat Martineau }
1086b5c6aaedSMat Martineau
1087b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
1088b5c6aaedSMat Martineau {
1089b5c6aaedSMat Martineau u16 packed;
1090b5c6aaedSMat Martineau
1091b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
1092b5c6aaedSMat Martineau packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
1093b5c6aaedSMat Martineau
1094b5c6aaedSMat Martineau if (control->sframe) {
1095b5c6aaedSMat Martineau packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
1096b5c6aaedSMat Martineau packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
1097b5c6aaedSMat Martineau packed |= L2CAP_CTRL_FRAME_TYPE;
1098b5c6aaedSMat Martineau } else {
1099b5c6aaedSMat Martineau packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
__pack_control(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff * skb)1100b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
1101b5c6aaedSMat Martineau }
1102b5c6aaedSMat Martineau
1103b5c6aaedSMat Martineau return packed;
1104b5c6aaedSMat Martineau }
1105b5c6aaedSMat Martineau
1106b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan,
1107b5c6aaedSMat Martineau struct l2cap_ctrl *control,
1108b5c6aaedSMat Martineau struct sk_buff *skb)
1109b5c6aaedSMat Martineau {
1110b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
1111b5c6aaedSMat Martineau put_unaligned_le32(__pack_extended_control(control),
1112b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE);
__ertm_hdr_size(struct l2cap_chan * chan)1113b5c6aaedSMat Martineau } else {
1114b5c6aaedSMat Martineau put_unaligned_le16(__pack_enhanced_control(control),
1115b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE);
1116b5c6aaedSMat Martineau }
1117b5c6aaedSMat Martineau }
1118b5c6aaedSMat Martineau
1119ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan)
1120ba7aa64fSGustavo Padovan {
l2cap_create_sframe_pdu(struct l2cap_chan * chan,u32 control)1121ba7aa64fSGustavo Padovan if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1122ba7aa64fSGustavo Padovan return L2CAP_EXT_HDR_SIZE;
1123ba7aa64fSGustavo Padovan else
1124ba7aa64fSGustavo Padovan return L2CAP_ENH_HDR_SIZE;
1125ba7aa64fSGustavo Padovan }
1126ba7aa64fSGustavo Padovan
1127a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan,
1128a67d7f6fSMat Martineau u32 control)
11290a708f8fSGustavo F. Padovan {
11300a708f8fSGustavo F. Padovan struct sk_buff *skb;
11310a708f8fSGustavo F. Padovan struct l2cap_hdr *lh;
1132ba7aa64fSGustavo Padovan int hlen = __ertm_hdr_size(chan);
11330a708f8fSGustavo F. Padovan
11340a708f8fSGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16)
113503a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE;
11360a708f8fSGustavo F. Padovan
1137a67d7f6fSMat Martineau skb = bt_skb_alloc(hlen, GFP_KERNEL);
11380a708f8fSGustavo F. Padovan
11390a708f8fSGustavo F. Padovan if (!skb)
1140a67d7f6fSMat Martineau return ERR_PTR(-ENOMEM);
11410a708f8fSGustavo F. Padovan
11424df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE);
11430a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
1144fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid);
114588843ab0SAndrei Emeltchenko
1146a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1147a67d7f6fSMat Martineau put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
1148a67d7f6fSMat Martineau else
1149a67d7f6fSMat Martineau put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
11500a708f8fSGustavo F. Padovan
115147d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) {
1152a67d7f6fSMat Martineau u16 fcs = crc16(0, (u8 *)skb->data, skb->len);
115303a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
l2cap_send_sframe(struct l2cap_chan * chan,struct l2cap_ctrl * control)11540a708f8fSGustavo F. Padovan }
11550a708f8fSGustavo F. Padovan
115673d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX;
1157a67d7f6fSMat Martineau return skb;
1158a67d7f6fSMat Martineau }
1159a67d7f6fSMat Martineau
1160a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan,
1161a67d7f6fSMat Martineau struct l2cap_ctrl *control)
1162a67d7f6fSMat Martineau {
1163a67d7f6fSMat Martineau struct sk_buff *skb;
1164a67d7f6fSMat Martineau u32 control_field;
1165a67d7f6fSMat Martineau
1166a67d7f6fSMat Martineau BT_DBG("chan %p, control %p", chan, control);
1167a67d7f6fSMat Martineau
1168a67d7f6fSMat Martineau if (!control->sframe)
1169a67d7f6fSMat Martineau return;
1170a67d7f6fSMat Martineau
1171a67d7f6fSMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
1172a67d7f6fSMat Martineau !control->poll)
1173a67d7f6fSMat Martineau control->final = 1;
1174a67d7f6fSMat Martineau
1175a67d7f6fSMat Martineau if (control->super == L2CAP_SUPER_RR)
1176a67d7f6fSMat Martineau clear_bit(CONN_RNR_SENT, &chan->conn_state);
1177a67d7f6fSMat Martineau else if (control->super == L2CAP_SUPER_RNR)
1178a67d7f6fSMat Martineau set_bit(CONN_RNR_SENT, &chan->conn_state);
1179a67d7f6fSMat Martineau
1180a67d7f6fSMat Martineau if (control->super != L2CAP_SUPER_SREJ) {
1181a67d7f6fSMat Martineau chan->last_acked_seq = control->reqseq;
1182a67d7f6fSMat Martineau __clear_ack_timer(chan);
1183a67d7f6fSMat Martineau }
1184a67d7f6fSMat Martineau
1185a67d7f6fSMat Martineau BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq,
1186a67d7f6fSMat Martineau control->final, control->poll, control->super);
1187a67d7f6fSMat Martineau
1188a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1189a67d7f6fSMat Martineau control_field = __pack_extended_control(control);
1190a67d7f6fSMat Martineau else
1191a67d7f6fSMat Martineau control_field = __pack_enhanced_control(control);
l2cap_send_rr_or_rnr(struct l2cap_chan * chan,bool poll)1192a67d7f6fSMat Martineau
1193a67d7f6fSMat Martineau skb = l2cap_create_sframe_pdu(chan, control_field);
1194a67d7f6fSMat Martineau if (!IS_ERR(skb))
119573d80debSLuiz Augusto von Dentz l2cap_do_send(chan, skb);
11960a708f8fSGustavo F. Padovan }
11970a708f8fSGustavo F. Padovan
1198c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll)
11990a708f8fSGustavo F. Padovan {
1200c9e3d5e0SMat Martineau struct l2cap_ctrl control;
12010a708f8fSGustavo F. Padovan
1202c9e3d5e0SMat Martineau BT_DBG("chan %p, poll %d", chan, poll);
1203c9e3d5e0SMat Martineau
1204c9e3d5e0SMat Martineau memset(&control, 0, sizeof(control));
1205c9e3d5e0SMat Martineau control.sframe = 1;
1206c9e3d5e0SMat Martineau control.poll = poll;
1207c9e3d5e0SMat Martineau
1208c9e3d5e0SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
1209c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RNR;
1210c9e3d5e0SMat Martineau else
__l2cap_no_conn_pending(struct l2cap_chan * chan)1211c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RR;
1212c9e3d5e0SMat Martineau
1213c9e3d5e0SMat Martineau control.reqseq = chan->buffer_seq;
1214c9e3d5e0SMat Martineau l2cap_send_sframe(chan, &control);
12150a708f8fSGustavo F. Padovan }
12160a708f8fSGustavo F. Padovan
1217b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
12180a708f8fSGustavo F. Padovan {
l2cap_send_conn_req(struct l2cap_chan * chan)12195ff6f34dSJohan Hedberg if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
12205ff6f34dSJohan Hedberg return true;
12215ff6f34dSJohan Hedberg
1222c1360a1cSGustavo F. Padovan return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
12230a708f8fSGustavo F. Padovan }
12240a708f8fSGustavo F. Padovan
12252766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan)
12269b27f350SAndrei Emeltchenko {
12279b27f350SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn;
12289b27f350SAndrei Emeltchenko struct l2cap_conn_req req;
12299b27f350SAndrei Emeltchenko
12309b27f350SAndrei Emeltchenko req.scid = cpu_to_le16(chan->scid);
12319b27f350SAndrei Emeltchenko req.psm = chan->psm;
12329b27f350SAndrei Emeltchenko
12339b27f350SAndrei Emeltchenko chan->ident = l2cap_get_ident(conn);
l2cap_chan_ready(struct l2cap_chan * chan)12349b27f350SAndrei Emeltchenko
12359b27f350SAndrei Emeltchenko set_bit(CONF_CONNECT_PEND, &chan->conf_state);
12369b27f350SAndrei Emeltchenko
12379b27f350SAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
12389b27f350SAndrei Emeltchenko }
12399b27f350SAndrei Emeltchenko
12409f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan)
12419f0caeb1SVinicius Costa Gomes {
1242315917e0SJohan Hedberg /* The channel may have already been flagged as connected in
1243315917e0SJohan Hedberg * case of receiving data before the L2CAP info req/rsp
1244315917e0SJohan Hedberg * procedure is complete.
1245315917e0SJohan Hedberg */
1246315917e0SJohan Hedberg if (chan->state == BT_CONNECTED)
1247315917e0SJohan Hedberg return;
1248315917e0SJohan Hedberg
12492827011fSMat Martineau /* This clears all conf flags, including CONF_NOT_COMPLETE */
12509f0caeb1SVinicius Costa Gomes chan->conf_state = 0;
12519f0caeb1SVinicius Costa Gomes __clear_chan_timer(chan);
12529f0caeb1SVinicius Costa Gomes
125315f02b91SLuiz Augusto von Dentz switch (chan->mode) {
125415f02b91SLuiz Augusto von Dentz case L2CAP_MODE_LE_FLOWCTL:
125515f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL:
125615f02b91SLuiz Augusto von Dentz if (!chan->tx_credits)
12570ce43ce6SJohan Hedberg chan->ops->suspend(chan);
125815f02b91SLuiz Augusto von Dentz break;
125915f02b91SLuiz Augusto von Dentz }
l2cap_le_connect(struct l2cap_chan * chan)1260177f8f2bSJohan Hedberg
126154a59aa2SAndrei Emeltchenko chan->state = BT_CONNECTED;
12629f0caeb1SVinicius Costa Gomes
126354a59aa2SAndrei Emeltchenko chan->ops->ready(chan);
12649f0caeb1SVinicius Costa Gomes }
12659f0caeb1SVinicius Costa Gomes
1266f1496deeSJohan Hedberg static void l2cap_le_connect(struct l2cap_chan *chan)
1267f1496deeSJohan Hedberg {
1268f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn;
1269f1496deeSJohan Hedberg struct l2cap_le_conn_req req;
1270f1496deeSJohan Hedberg
1271595177f3SJohan Hedberg if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags))
1272595177f3SJohan Hedberg return;
1273595177f3SJohan Hedberg
12744b6e228eSLuiz Augusto von Dentz if (!chan->imtu)
12754b6e228eSLuiz Augusto von Dentz chan->imtu = chan->conn->mtu;
12764b6e228eSLuiz Augusto von Dentz
1277ba8f5289SLuiz Augusto von Dentz l2cap_le_flowctl_init(chan, 0);
1278fe149310SLuiz Augusto von Dentz
1279a5133fe8SXiaohui Zhang memset(&req, 0, sizeof(req));
1280f1496deeSJohan Hedberg req.psm = chan->psm;
1281f1496deeSJohan Hedberg req.scid = cpu_to_le16(chan->scid);
1282f1496deeSJohan Hedberg req.mtu = cpu_to_le16(chan->imtu);
12833916aed8SJohan Hedberg req.mps = cpu_to_le16(chan->mps);
12840cd75f7eSJohan Hedberg req.credits = cpu_to_le16(chan->rx_credits);
1285f1496deeSJohan Hedberg
1286f1496deeSJohan Hedberg chan->ident = l2cap_get_ident(conn);
1287f1496deeSJohan Hedberg
1288f1496deeSJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ,
1289f1496deeSJohan Hedberg sizeof(req), &req);
1290f1496deeSJohan Hedberg }
1291f1496deeSJohan Hedberg
1292da49b602SLuiz Augusto von Dentz struct l2cap_ecred_conn_data {
129315f02b91SLuiz Augusto von Dentz struct {
129415f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_req req;
1295da49b602SLuiz Augusto von Dentz __le16 scid[5];
l2cap_ecred_defer_connect(struct l2cap_chan * chan,void * data)129615f02b91SLuiz Augusto von Dentz } __packed pdu;
1297da49b602SLuiz Augusto von Dentz struct l2cap_chan *chan;
1298da49b602SLuiz Augusto von Dentz struct pid *pid;
1299da49b602SLuiz Augusto von Dentz int count;
1300da49b602SLuiz Augusto von Dentz };
1301da49b602SLuiz Augusto von Dentz
1302da49b602SLuiz Augusto von Dentz static void l2cap_ecred_defer_connect(struct l2cap_chan *chan, void *data)
1303da49b602SLuiz Augusto von Dentz {
1304da49b602SLuiz Augusto von Dentz struct l2cap_ecred_conn_data *conn = data;
1305da49b602SLuiz Augusto von Dentz struct pid *pid;
1306da49b602SLuiz Augusto von Dentz
1307da49b602SLuiz Augusto von Dentz if (chan == conn->chan)
1308da49b602SLuiz Augusto von Dentz return;
1309da49b602SLuiz Augusto von Dentz
1310da49b602SLuiz Augusto von Dentz if (!test_and_clear_bit(FLAG_DEFER_SETUP, &chan->flags))
1311da49b602SLuiz Augusto von Dentz return;
1312da49b602SLuiz Augusto von Dentz
1313da49b602SLuiz Augusto von Dentz pid = chan->ops->get_peer_pid(chan);
1314da49b602SLuiz Augusto von Dentz
1315da49b602SLuiz Augusto von Dentz /* Only add deferred channels with the same PID/PSM */
1316da49b602SLuiz Augusto von Dentz if (conn->pid != pid || chan->psm != conn->chan->psm || chan->ident ||
1317da49b602SLuiz Augusto von Dentz chan->mode != L2CAP_MODE_EXT_FLOWCTL || chan->state != BT_CONNECT)
1318da49b602SLuiz Augusto von Dentz return;
131915f02b91SLuiz Augusto von Dentz
132015f02b91SLuiz Augusto von Dentz if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
132115f02b91SLuiz Augusto von Dentz return;
132215f02b91SLuiz Augusto von Dentz
132315f02b91SLuiz Augusto von Dentz l2cap_ecred_init(chan, 0);
132415f02b91SLuiz Augusto von Dentz
1325da49b602SLuiz Augusto von Dentz /* Set the same ident so we can match on the rsp */
1326da49b602SLuiz Augusto von Dentz chan->ident = conn->chan->ident;
1327da49b602SLuiz Augusto von Dentz
l2cap_ecred_connect(struct l2cap_chan * chan)1328da49b602SLuiz Augusto von Dentz /* Include all channels deferred */
1329da49b602SLuiz Augusto von Dentz conn->pdu.scid[conn->count] = cpu_to_le16(chan->scid);
1330da49b602SLuiz Augusto von Dentz
1331da49b602SLuiz Augusto von Dentz conn->count++;
1332da49b602SLuiz Augusto von Dentz }
1333da49b602SLuiz Augusto von Dentz
1334da49b602SLuiz Augusto von Dentz static void l2cap_ecred_connect(struct l2cap_chan *chan)
1335da49b602SLuiz Augusto von Dentz {
1336da49b602SLuiz Augusto von Dentz struct l2cap_conn *conn = chan->conn;
1337da49b602SLuiz Augusto von Dentz struct l2cap_ecred_conn_data data;
1338da49b602SLuiz Augusto von Dentz
1339da49b602SLuiz Augusto von Dentz if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
1340da49b602SLuiz Augusto von Dentz return;
1341da49b602SLuiz Augusto von Dentz
1342da49b602SLuiz Augusto von Dentz if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
1343da49b602SLuiz Augusto von Dentz return;
1344da49b602SLuiz Augusto von Dentz
1345da49b602SLuiz Augusto von Dentz l2cap_ecred_init(chan, 0);
1346da49b602SLuiz Augusto von Dentz
1347d3715b23SMinghao Chi (CGEL ZTE) memset(&data, 0, sizeof(data));
1348da49b602SLuiz Augusto von Dentz data.pdu.req.psm = chan->psm;
1349da49b602SLuiz Augusto von Dentz data.pdu.req.mtu = cpu_to_le16(chan->imtu);
1350da49b602SLuiz Augusto von Dentz data.pdu.req.mps = cpu_to_le16(chan->mps);
1351da49b602SLuiz Augusto von Dentz data.pdu.req.credits = cpu_to_le16(chan->rx_credits);
1352da49b602SLuiz Augusto von Dentz data.pdu.scid[0] = cpu_to_le16(chan->scid);
135315f02b91SLuiz Augusto von Dentz
135415f02b91SLuiz Augusto von Dentz chan->ident = l2cap_get_ident(conn);
1355da49b602SLuiz Augusto von Dentz
1356da49b602SLuiz Augusto von Dentz data.count = 1;
1357da49b602SLuiz Augusto von Dentz data.chan = chan;
1358da49b602SLuiz Augusto von Dentz data.pid = chan->ops->get_peer_pid(chan);
1359da49b602SLuiz Augusto von Dentz
1360da49b602SLuiz Augusto von Dentz __l2cap_chan_list(conn, l2cap_ecred_defer_connect, &data);
l2cap_le_start(struct l2cap_chan * chan)136115f02b91SLuiz Augusto von Dentz
136215f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_CONN_REQ,
1363da49b602SLuiz Augusto von Dentz sizeof(data.pdu.req) + data.count * sizeof(__le16),
1364da49b602SLuiz Augusto von Dentz &data.pdu);
136515f02b91SLuiz Augusto von Dentz }
136615f02b91SLuiz Augusto von Dentz
1367f1496deeSJohan Hedberg static void l2cap_le_start(struct l2cap_chan *chan)
1368f1496deeSJohan Hedberg {
1369f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn;
1370f1496deeSJohan Hedberg
1371f1496deeSJohan Hedberg if (!smp_conn_security(conn->hcon, chan->sec_level))
1372f1496deeSJohan Hedberg return;
1373f1496deeSJohan Hedberg
1374f1496deeSJohan Hedberg if (!chan->psm) {
1375f1496deeSJohan Hedberg l2cap_chan_ready(chan);
1376f1496deeSJohan Hedberg return;
1377f1496deeSJohan Hedberg }
1378f1496deeSJohan Hedberg
137915f02b91SLuiz Augusto von Dentz if (chan->state == BT_CONNECT) {
138015f02b91SLuiz Augusto von Dentz if (chan->mode == L2CAP_MODE_EXT_FLOWCTL)
l2cap_start_connection(struct l2cap_chan * chan)138115f02b91SLuiz Augusto von Dentz l2cap_ecred_connect(chan);
138215f02b91SLuiz Augusto von Dentz else
1383f1496deeSJohan Hedberg l2cap_le_connect(chan);
1384f1496deeSJohan Hedberg }
138515f02b91SLuiz Augusto von Dentz }
1386f1496deeSJohan Hedberg
138793c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan)
138893c3e8f5SAndrei Emeltchenko {
1389cd5d26a9SLuiz Augusto von Dentz if (chan->conn->hcon->type == LE_LINK) {
l2cap_request_info(struct l2cap_conn * conn)1390f1496deeSJohan Hedberg l2cap_le_start(chan);
139193c3e8f5SAndrei Emeltchenko } else {
139293c3e8f5SAndrei Emeltchenko l2cap_send_conn_req(chan);
139393c3e8f5SAndrei Emeltchenko }
139493c3e8f5SAndrei Emeltchenko }
139593c3e8f5SAndrei Emeltchenko
1396aeaeb4bbSJohan Hedberg static void l2cap_request_info(struct l2cap_conn *conn)
13970a708f8fSGustavo F. Padovan {
13980a708f8fSGustavo F. Padovan struct l2cap_info_req req;
1399aeaeb4bbSJohan Hedberg
1400aeaeb4bbSJohan Hedberg if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1401aeaeb4bbSJohan Hedberg return;
1402aeaeb4bbSJohan Hedberg
1403dcf4adbfSJoe Perches req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
14040a708f8fSGustavo F. Padovan
14050a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
14060a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn);
14070a708f8fSGustavo F. Padovan
l2cap_check_enc_key_size(struct hci_conn * hcon)1408ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
14090a708f8fSGustavo F. Padovan
14102d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
14112d792818SGustavo Padovan sizeof(req), &req);
14120a708f8fSGustavo F. Padovan }
1413aeaeb4bbSJohan Hedberg
1414693cd8ceSMarcel Holtmann static bool l2cap_check_enc_key_size(struct hci_conn *hcon)
1415693cd8ceSMarcel Holtmann {
1416693cd8ceSMarcel Holtmann /* The minimum encryption key size needs to be enforced by the
1417693cd8ceSMarcel Holtmann * host stack before establishing any L2CAP connections. The
1418693cd8ceSMarcel Holtmann * specification in theory allows a minimum of 1, but to align
1419693cd8ceSMarcel Holtmann * BR/EDR and LE transports, a minimum of 7 is chosen.
1420693cd8ceSMarcel Holtmann *
1421693cd8ceSMarcel Holtmann * This check might also be called for unencrypted connections
1422693cd8ceSMarcel Holtmann * that have no key size requirements. Ensure that the link is
1423693cd8ceSMarcel Holtmann * actually encrypted before enforcing a key size.
1424693cd8ceSMarcel Holtmann */
1425288c0697SArchie Pusaka int min_key_size = hcon->hdev->min_enc_key_size;
1426288c0697SArchie Pusaka
1427288c0697SArchie Pusaka /* On FIPS security level, key size must be 16 bytes */
1428288c0697SArchie Pusaka if (hcon->sec_level == BT_SECURITY_FIPS)
l2cap_do_start(struct l2cap_chan * chan)1429288c0697SArchie Pusaka min_key_size = 16;
1430288c0697SArchie Pusaka
1431693cd8ceSMarcel Holtmann return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) ||
1432288c0697SArchie Pusaka hcon->enc_key_size >= min_key_size);
1433693cd8ceSMarcel Holtmann }
1434693cd8ceSMarcel Holtmann
1435aeaeb4bbSJohan Hedberg static void l2cap_do_start(struct l2cap_chan *chan)
1436aeaeb4bbSJohan Hedberg {
1437aeaeb4bbSJohan Hedberg struct l2cap_conn *conn = chan->conn;
1438aeaeb4bbSJohan Hedberg
1439aeaeb4bbSJohan Hedberg if (conn->hcon->type == LE_LINK) {
1440aeaeb4bbSJohan Hedberg l2cap_le_start(chan);
1441aeaeb4bbSJohan Hedberg return;
1442aeaeb4bbSJohan Hedberg }
1443aeaeb4bbSJohan Hedberg
1444aeaeb4bbSJohan Hedberg if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)) {
1445aeaeb4bbSJohan Hedberg l2cap_request_info(conn);
1446aeaeb4bbSJohan Hedberg return;
1447aeaeb4bbSJohan Hedberg }
1448aeaeb4bbSJohan Hedberg
1449aeaeb4bbSJohan Hedberg if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
1450aeaeb4bbSJohan Hedberg return;
1451aeaeb4bbSJohan Hedberg
1452693cd8ceSMarcel Holtmann if (!l2cap_chan_check_security(chan, true) ||
1453693cd8ceSMarcel Holtmann !__l2cap_no_conn_pending(chan))
1454693cd8ceSMarcel Holtmann return;
1455693cd8ceSMarcel Holtmann
l2cap_mode_supported(__u8 mode,__u32 feat_mask)1456693cd8ceSMarcel Holtmann if (l2cap_check_enc_key_size(conn->hcon))
1457aeaeb4bbSJohan Hedberg l2cap_start_connection(chan);
1458693cd8ceSMarcel Holtmann else
1459693cd8ceSMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
14600a708f8fSGustavo F. Padovan }
14610a708f8fSGustavo F. Padovan
14620a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
14630a708f8fSGustavo F. Padovan {
14640a708f8fSGustavo F. Padovan u32 local_feat_mask = l2cap_feat_mask;
14650a708f8fSGustavo F. Padovan if (!disable_ertm)
14660a708f8fSGustavo F. Padovan local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
14670a708f8fSGustavo F. Padovan
14680a708f8fSGustavo F. Padovan switch (mode) {
14690a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM:
14700a708f8fSGustavo F. Padovan return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
14710a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING:
l2cap_send_disconn_req(struct l2cap_chan * chan,int err)14720a708f8fSGustavo F. Padovan return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
14730a708f8fSGustavo F. Padovan default:
14740a708f8fSGustavo F. Padovan return 0x00;
14750a708f8fSGustavo F. Padovan }
14760a708f8fSGustavo F. Padovan }
14770a708f8fSGustavo F. Padovan
14785e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
14790a708f8fSGustavo F. Padovan {
14805e4e3972SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn;
14810a708f8fSGustavo F. Padovan struct l2cap_disconn_req req;
14820a708f8fSGustavo F. Padovan
14830a708f8fSGustavo F. Padovan if (!conn)
14840a708f8fSGustavo F. Padovan return;
14850a708f8fSGustavo F. Padovan
1486aad3d0e3SAndrei Emeltchenko if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) {
14871a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan);
14881a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan);
14891a09bcb9SGustavo F. Padovan __clear_ack_timer(chan);
14900a708f8fSGustavo F. Padovan }
14910a708f8fSGustavo F. Padovan
1492fe4128e0SGustavo F. Padovan req.dcid = cpu_to_le16(chan->dcid);
1493fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid);
14942d792818SGustavo Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ,
l2cap_conn_start(struct l2cap_conn * conn)14952d792818SGustavo Padovan sizeof(req), &req);
14960a708f8fSGustavo F. Padovan
1497f8e73017SGustavo Padovan l2cap_state_change_and_error(chan, BT_DISCONN, err);
14980a708f8fSGustavo F. Padovan }
14990a708f8fSGustavo F. Padovan
15000a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
15010a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
15020a708f8fSGustavo F. Padovan {
15033df91ea2SAndrei Emeltchenko struct l2cap_chan *chan, *tmp;
15040a708f8fSGustavo F. Padovan
15050a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn);
15060a708f8fSGustavo F. Padovan
15073df91ea2SAndrei Emeltchenko list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
15086be36555SAndrei Emeltchenko l2cap_chan_lock(chan);
15090a708f8fSGustavo F. Padovan
1510715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1511aeaeb4bbSJohan Hedberg l2cap_chan_ready(chan);
15126be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
15130a708f8fSGustavo F. Padovan continue;
15140a708f8fSGustavo F. Padovan }
15150a708f8fSGustavo F. Padovan
151689bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) {
1517e7cafc45SJohan Hedberg if (!l2cap_chan_check_security(chan, true) ||
1518b4450035SGustavo F. Padovan !__l2cap_no_conn_pending(chan)) {
15196be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
15200a708f8fSGustavo F. Padovan continue;
15210a708f8fSGustavo F. Padovan }
15220a708f8fSGustavo F. Padovan
1523c1360a1cSGustavo F. Padovan if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1524c1360a1cSGustavo F. Padovan && test_bit(CONF_STATE2_DEVICE,
1525c1360a1cSGustavo F. Padovan &chan->conf_state)) {
15260f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET);
15276be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
15280a708f8fSGustavo F. Padovan continue;
15290a708f8fSGustavo F. Padovan }
15300a708f8fSGustavo F. Padovan
1531693cd8ceSMarcel Holtmann if (l2cap_check_enc_key_size(conn->hcon))
153293c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan);
1533693cd8ceSMarcel Holtmann else
1534693cd8ceSMarcel Holtmann l2cap_chan_close(chan, ECONNREFUSED);
15350a708f8fSGustavo F. Padovan
153689bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) {
15370a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp;
15380a708f8fSGustavo F. Padovan char buf[128];
1539fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid);
1540fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid);
15410a708f8fSGustavo F. Padovan
1542e7cafc45SJohan Hedberg if (l2cap_chan_check_security(chan, false)) {
1543bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
1544dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1545dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
15462dc4e510SGustavo Padovan chan->ops->defer(chan);
15470a708f8fSGustavo F. Padovan
15480a708f8fSGustavo F. Padovan } else {
1549acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG);
1550dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1551dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
15520a708f8fSGustavo F. Padovan }
15530a708f8fSGustavo F. Padovan } else {
1554dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1555dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
15560a708f8fSGustavo F. Padovan }
15570a708f8fSGustavo F. Padovan
1558fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1559fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp);
15600a708f8fSGustavo F. Padovan
1561c1360a1cSGustavo F. Padovan if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
15620a708f8fSGustavo F. Padovan rsp.result != L2CAP_CR_SUCCESS) {
15636be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
15640a708f8fSGustavo F. Padovan continue;
15650a708f8fSGustavo F. Padovan }
15660a708f8fSGustavo F. Padovan
1567c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state);
15680a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1569e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
157073ffa904SGustavo F. Padovan chan->num_conf_req++;
15710a708f8fSGustavo F. Padovan }
15720a708f8fSGustavo F. Padovan
15736be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
15740a708f8fSGustavo F. Padovan }
l2cap_le_conn_ready(struct l2cap_conn * conn)15750a708f8fSGustavo F. Padovan }
15760a708f8fSGustavo F. Padovan
1577b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1578b62f328bSVille Tervo {
1579cc8dba2bSMarcel Holtmann struct hci_conn *hcon = conn->hcon;
1580dcc36c16SJohan Hedberg struct hci_dev *hdev = hcon->hdev;
1581b62f328bSVille Tervo
1582e760ec12SJohan Hedberg BT_DBG("%s conn %p", hdev->name, conn);
1583b62f328bSVille Tervo
1584e760ec12SJohan Hedberg /* For outgoing pairing which doesn't necessarily have an
1585e760ec12SJohan Hedberg * associated socket (e.g. mgmt_pair_device).
1586e760ec12SJohan Hedberg */
1587e760ec12SJohan Hedberg if (hcon->out)
1588e760ec12SJohan Hedberg smp_conn_security(hcon, hcon->pending_sec_level);
1589cc8dba2bSMarcel Holtmann
159074be523cSArchie Pusaka /* For LE peripheral connections, make sure the connection interval
15915153ceb9SBhaskar Chowdhury * is in the range of the minimum and maximum interval that has
159280afeb6cSMarcel Holtmann * been configured for this connection. If not, then trigger
159380afeb6cSMarcel Holtmann * the connection update procedure.
159480afeb6cSMarcel Holtmann */
159540bef302SJohan Hedberg if (hcon->role == HCI_ROLE_SLAVE &&
159680afeb6cSMarcel Holtmann (hcon->le_conn_interval < hcon->le_conn_min_interval ||
159780afeb6cSMarcel Holtmann hcon->le_conn_interval > hcon->le_conn_max_interval)) {
159880afeb6cSMarcel Holtmann struct l2cap_conn_param_update_req req;
159980afeb6cSMarcel Holtmann
160080afeb6cSMarcel Holtmann req.min = cpu_to_le16(hcon->le_conn_min_interval);
160180afeb6cSMarcel Holtmann req.max = cpu_to_le16(hcon->le_conn_max_interval);
160280afeb6cSMarcel Holtmann req.latency = cpu_to_le16(hcon->le_conn_latency);
160380afeb6cSMarcel Holtmann req.to_multiplier = cpu_to_le16(hcon->le_supv_timeout);
160480afeb6cSMarcel Holtmann
160580afeb6cSMarcel Holtmann l2cap_send_cmd(conn, l2cap_get_ident(conn),
160680afeb6cSMarcel Holtmann L2CAP_CONN_PARAM_UPDATE_REQ, sizeof(req), &req);
160780afeb6cSMarcel Holtmann }
1608b62f328bSVille Tervo }
1609b62f328bSVille Tervo
16100a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
16110a708f8fSGustavo F. Padovan {
161248454079SGustavo F. Padovan struct l2cap_chan *chan;
1613cc110922SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon;
16140a708f8fSGustavo F. Padovan
16150a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn);
16160a708f8fSGustavo F. Padovan
1617aeaeb4bbSJohan Hedberg if (hcon->type == ACL_LINK)
1618aeaeb4bbSJohan Hedberg l2cap_request_info(conn);
1619aeaeb4bbSJohan Hedberg
1620*efc30877SLuiz Augusto von Dentz mutex_lock(&conn->lock);
1621e760ec12SJohan Hedberg
16223df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) {
1623baa7e1faSGustavo F. Padovan
16246be36555SAndrei Emeltchenko l2cap_chan_lock(chan);
16250a708f8fSGustavo F. Padovan
1626cc110922SVinicius Costa Gomes if (hcon->type == LE_LINK) {
1627f1496deeSJohan Hedberg l2cap_le_start(chan);
162863128451SVinicius Costa Gomes } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1629aeaeb4bbSJohan Hedberg if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
163074e75740SGustavo Padovan l2cap_chan_ready(chan);
16311c244f79SGustavo Padovan } else if (chan->state == BT_CONNECT) {
1632fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan);
16331c244f79SGustavo Padovan }
16340a708f8fSGustavo F. Padovan
16356be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
16360a708f8fSGustavo F. Padovan }
16370a708f8fSGustavo F. Padovan
1638*efc30877SLuiz Augusto von Dentz mutex_unlock(&conn->lock);
163961a939c6SJohan Hedberg
164079a05727SJohan Hedberg if (hcon->type == LE_LINK)
164179a05727SJohan Hedberg l2cap_le_conn_ready(conn);
164279a05727SJohan Hedberg
164361a939c6SJohan Hedberg queue_work(hcon->hdev->workqueue, &conn->pending_rx_work);
16440a708f8fSGustavo F. Padovan }
l2cap_conn_unreliable(struct l2cap_conn * conn,int err)16450a708f8fSGustavo F. Padovan
16460a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
16470a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
16480a708f8fSGustavo F. Padovan {
164948454079SGustavo F. Padovan struct l2cap_chan *chan;
16500a708f8fSGustavo F. Padovan
16510a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn);
16520a708f8fSGustavo F. Padovan
16533df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) {
1654ecf61bdbSAndrei Emeltchenko if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
16551d8b1fd5SGustavo Padovan l2cap_chan_set_err(chan, err);
16560a708f8fSGustavo F. Padovan }
16570a708f8fSGustavo F. Padovan }
16580a708f8fSGustavo F. Padovan
1659f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
16600a708f8fSGustavo F. Padovan {
l2cap_info_timeout(struct work_struct * work)1661f878fcadSGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1662030013d8SGustavo F. Padovan info_timer.work);
16630a708f8fSGustavo F. Padovan
16640a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
16650a708f8fSGustavo F. Padovan conn->info_ident = 0;
16660a708f8fSGustavo F. Padovan
1667*efc30877SLuiz Augusto von Dentz mutex_lock(&conn->lock);
16680a708f8fSGustavo F. Padovan l2cap_conn_start(conn);
1669*efc30877SLuiz Augusto von Dentz mutex_unlock(&conn->lock);
16700a708f8fSGustavo F. Padovan }
16710a708f8fSGustavo F. Padovan
16722c8e1411SDavid Herrmann /*
16732c8e1411SDavid Herrmann * l2cap_user
16742c8e1411SDavid Herrmann * External modules can register l2cap_user objects on l2cap_conn. The ->probe
16752c8e1411SDavid Herrmann * callback is called during registration. The ->remove callback is called
16762c8e1411SDavid Herrmann * during unregistration.
16772c8e1411SDavid Herrmann * An l2cap_user object can either be explicitly unregistered or when the
16782c8e1411SDavid Herrmann * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon,
16792c8e1411SDavid Herrmann * l2cap->hchan, .. are valid as long as the remove callback hasn't been called.
16802c8e1411SDavid Herrmann * External modules must own a reference to the l2cap_conn object if they intend
16812c8e1411SDavid Herrmann * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at
16822c8e1411SDavid Herrmann * any time if they don't.
16832c8e1411SDavid Herrmann */
16842c8e1411SDavid Herrmann
l2cap_register_user(struct l2cap_conn * conn,struct l2cap_user * user)16852c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user)
16862c8e1411SDavid Herrmann {
16872c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev;
16882c8e1411SDavid Herrmann int ret;
16892c8e1411SDavid Herrmann
16902c8e1411SDavid Herrmann /* We need to check whether l2cap_conn is registered. If it is not, we
16912c8e1411SDavid Herrmann * must not register the l2cap_user. l2cap_conn_del() is unregisters
16922c8e1411SDavid Herrmann * l2cap_conn objects, but doesn't provide its own locking. Instead, it
16932c8e1411SDavid Herrmann * relies on the parent hci_conn object to be locked. This itself relies
16942c8e1411SDavid Herrmann * on the hci_dev object to be locked. So we must lock the hci device
16952c8e1411SDavid Herrmann * here, too. */
16962c8e1411SDavid Herrmann
16972c8e1411SDavid Herrmann hci_dev_lock(hdev);
16982c8e1411SDavid Herrmann
1699835a6a2fSAlexey Dobriyan if (!list_empty(&user->list)) {
17002c8e1411SDavid Herrmann ret = -EINVAL;
17012c8e1411SDavid Herrmann goto out_unlock;
17022c8e1411SDavid Herrmann }
17032c8e1411SDavid Herrmann
17042c8e1411SDavid Herrmann /* conn->hchan is NULL after l2cap_conn_del() was called */
17052c8e1411SDavid Herrmann if (!conn->hchan) {
17062c8e1411SDavid Herrmann ret = -ENODEV;
17072c8e1411SDavid Herrmann goto out_unlock;
17082c8e1411SDavid Herrmann }
17092c8e1411SDavid Herrmann
17102c8e1411SDavid Herrmann ret = user->probe(conn, user);
17112c8e1411SDavid Herrmann if (ret)
17122c8e1411SDavid Herrmann goto out_unlock;
17132c8e1411SDavid Herrmann
17142c8e1411SDavid Herrmann list_add(&user->list, &conn->users);
17152c8e1411SDavid Herrmann ret = 0;
17162c8e1411SDavid Herrmann
17172c8e1411SDavid Herrmann out_unlock:
17182c8e1411SDavid Herrmann hci_dev_unlock(hdev);
17192c8e1411SDavid Herrmann return ret;
17202c8e1411SDavid Herrmann }
17212c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user);
17222c8e1411SDavid Herrmann
l2cap_unregister_user(struct l2cap_conn * conn,struct l2cap_user * user)17232c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user)
17242c8e1411SDavid Herrmann {
17252c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev;
17262c8e1411SDavid Herrmann
17272c8e1411SDavid Herrmann hci_dev_lock(hdev);
17282c8e1411SDavid Herrmann
1729835a6a2fSAlexey Dobriyan if (list_empty(&user->list))
17302c8e1411SDavid Herrmann goto out_unlock;
17312c8e1411SDavid Herrmann
1732ab944c83STedd Ho-Jeong An list_del_init(&user->list);
17332c8e1411SDavid Herrmann user->remove(conn, user);
17342c8e1411SDavid Herrmann
17352c8e1411SDavid Herrmann out_unlock:
17362c8e1411SDavid Herrmann hci_dev_unlock(hdev);
17372c8e1411SDavid Herrmann }
17382c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user);
17392c8e1411SDavid Herrmann
l2cap_unregister_all_users(struct l2cap_conn * conn)17402c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn)
17412c8e1411SDavid Herrmann {
17422c8e1411SDavid Herrmann struct l2cap_user *user;
17432c8e1411SDavid Herrmann
17442c8e1411SDavid Herrmann while (!list_empty(&conn->users)) {
17452c8e1411SDavid Herrmann user = list_first_entry(&conn->users, struct l2cap_user, list);
1746ab944c83STedd Ho-Jeong An list_del_init(&user->list);
17472c8e1411SDavid Herrmann user->remove(conn, user);
17482c8e1411SDavid Herrmann }
17492c8e1411SDavid Herrmann }
17502c8e1411SDavid Herrmann
l2cap_conn_del(struct hci_conn * hcon,int err)17515d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
17525d3de7dfSVinicius Costa Gomes {
17535d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data;
17545d3de7dfSVinicius Costa Gomes struct l2cap_chan *chan, *l;
17555d3de7dfSVinicius Costa Gomes
17565d3de7dfSVinicius Costa Gomes if (!conn)
17575d3de7dfSVinicius Costa Gomes return;
17585d3de7dfSVinicius Costa Gomes
17595d3de7dfSVinicius Costa Gomes BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
17605d3de7dfSVinicius Costa Gomes
1761*efc30877SLuiz Augusto von Dentz mutex_lock(&conn->lock);
1762*efc30877SLuiz Augusto von Dentz
17635d3de7dfSVinicius Costa Gomes kfree_skb(conn->rx_skb);
17645d3de7dfSVinicius Costa Gomes
176561a939c6SJohan Hedberg skb_queue_purge(&conn->pending_rx);
17667ab56c3aSJukka Taimisto
17677ab56c3aSJukka Taimisto /* We can not call flush_work(&conn->pending_rx_work) here since we
17687ab56c3aSJukka Taimisto * might block if we are running on a worker from the same workqueue
17697ab56c3aSJukka Taimisto * pending_rx_work is waiting on.
17707ab56c3aSJukka Taimisto */
17717ab56c3aSJukka Taimisto if (work_pending(&conn->pending_rx_work))
17727ab56c3aSJukka Taimisto cancel_work_sync(&conn->pending_rx_work);
177361a939c6SJohan Hedberg
1774b8b23001SLuiz Augusto von Dentz cancel_delayed_work_sync(&conn->id_addr_timer);
1775f3d82d0cSJohan Hedberg
17762c8e1411SDavid Herrmann l2cap_unregister_all_users(conn);
17772c8e1411SDavid Herrmann
1778e31fb860SJohan Hedberg /* Force the connection to be immediately dropped */
1779e31fb860SJohan Hedberg hcon->disc_timeout = 0;
1780e31fb860SJohan Hedberg
17815d3de7dfSVinicius Costa Gomes /* Kill channels */
17825d3de7dfSVinicius Costa Gomes list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
178361d6ef3eSMat Martineau l2cap_chan_hold(chan);
17846be36555SAndrei Emeltchenko l2cap_chan_lock(chan);
17856be36555SAndrei Emeltchenko
17865d3de7dfSVinicius Costa Gomes l2cap_chan_del(chan, err);
17876be36555SAndrei Emeltchenko
178880b98027SGustavo Padovan chan->ops->close(chan);
17896c08fc89SManish Mandlik
17906c08fc89SManish Mandlik l2cap_chan_unlock(chan);
179161d6ef3eSMat Martineau l2cap_chan_put(chan);
17925d3de7dfSVinicius Costa Gomes }
17935d3de7dfSVinicius Costa Gomes
17945d3de7dfSVinicius Costa Gomes if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1795127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->info_timer);
17965d3de7dfSVinicius Costa Gomes
1797*efc30877SLuiz Augusto von Dentz hci_chan_del(conn->hchan);
1798*efc30877SLuiz Augusto von Dentz conn->hchan = NULL;
1799*efc30877SLuiz Augusto von Dentz
18005d3de7dfSVinicius Costa Gomes hcon->l2cap_data = NULL;
1801*efc30877SLuiz Augusto von Dentz mutex_unlock(&conn->lock);
18029c903e37SDavid Herrmann l2cap_conn_put(conn);
18035d3de7dfSVinicius Costa Gomes }
18045d3de7dfSVinicius Costa Gomes
18059c903e37SDavid Herrmann static void l2cap_conn_free(struct kref *ref)
l2cap_conn_free(struct kref * ref)18069c903e37SDavid Herrmann {
18079c903e37SDavid Herrmann struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref);
18089c903e37SDavid Herrmann
18099c903e37SDavid Herrmann hci_conn_put(conn->hcon);
18109c903e37SDavid Herrmann kfree(conn);
18119c903e37SDavid Herrmann }
18129c903e37SDavid Herrmann
181351bb8457SJohan Hedberg struct l2cap_conn *l2cap_conn_get(struct l2cap_conn *conn)
l2cap_conn_get(struct l2cap_conn * conn)18149c903e37SDavid Herrmann {
18159c903e37SDavid Herrmann kref_get(&conn->ref);
181651bb8457SJohan Hedberg return conn;
18179c903e37SDavid Herrmann }
18189c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_get);
18199c903e37SDavid Herrmann
18209c903e37SDavid Herrmann void l2cap_conn_put(struct l2cap_conn *conn)
l2cap_conn_put(struct l2cap_conn * conn)18219c903e37SDavid Herrmann {
18229c903e37SDavid Herrmann kref_put(&conn->ref, l2cap_conn_free);
18239c903e37SDavid Herrmann }
18249c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_put);
18259c903e37SDavid Herrmann
18260a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */
18270a708f8fSGustavo F. Padovan
1828c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr.
18290a708f8fSGustavo F. Padovan * Returns closest match.
18300a708f8fSGustavo F. Padovan */
1831c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
l2cap_global_chan_by_psm(int state,__le16 psm,bdaddr_t * src,bdaddr_t * dst,u8 link_type)1832c2287681SIdo Yariv bdaddr_t *src,
1833bf20fd4eSJohan Hedberg bdaddr_t *dst,
1834bf20fd4eSJohan Hedberg u8 link_type)
18350a708f8fSGustavo F. Padovan {
1836332f1795SLuiz Augusto von Dentz struct l2cap_chan *c, *tmp, *c1 = NULL;
18370a708f8fSGustavo F. Padovan
183823691d75SGustavo F. Padovan read_lock(&chan_list_lock);
18390a708f8fSGustavo F. Padovan
1840332f1795SLuiz Augusto von Dentz list_for_each_entry_safe(c, tmp, &chan_list, global_l) {
184189bc500eSGustavo F. Padovan if (state && c->state != state)
18420a708f8fSGustavo F. Padovan continue;
18430a708f8fSGustavo F. Padovan
1844bf20fd4eSJohan Hedberg if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR)
1845bf20fd4eSJohan Hedberg continue;
1846bf20fd4eSJohan Hedberg
1847bf20fd4eSJohan Hedberg if (link_type == LE_LINK && c->src_type == BDADDR_BREDR)
1848bf20fd4eSJohan Hedberg continue;
1849bf20fd4eSJohan Hedberg
1850f937b758SLuiz Augusto von Dentz if (c->chan_type != L2CAP_CHAN_FIXED && c->psm == psm) {
1851c2287681SIdo Yariv int src_match, dst_match;
1852c2287681SIdo Yariv int src_any, dst_any;
1853c2287681SIdo Yariv
18540a708f8fSGustavo F. Padovan /* Exact match. */
18557eafc59eSMarcel Holtmann src_match = !bacmp(&c->src, src);
18567eafc59eSMarcel Holtmann dst_match = !bacmp(&c->dst, dst);
1857c2287681SIdo Yariv if (src_match && dst_match) {
1858fc5ae5b4SLuiz Augusto von Dentz if (!l2cap_chan_hold_unless_zero(c))
1859fc5ae5b4SLuiz Augusto von Dentz continue;
1860fc5ae5b4SLuiz Augusto von Dentz
1861a7567b20SJohannes Berg read_unlock(&chan_list_lock);
186223691d75SGustavo F. Padovan return c;
186323691d75SGustavo F. Padovan }
18640a708f8fSGustavo F. Padovan
18650a708f8fSGustavo F. Padovan /* Closest match */
18667eafc59eSMarcel Holtmann src_any = !bacmp(&c->src, BDADDR_ANY);
18677eafc59eSMarcel Holtmann dst_any = !bacmp(&c->dst, BDADDR_ANY);
1868c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) ||
1869c2287681SIdo Yariv (src_any && dst_any))
187023691d75SGustavo F. Padovan c1 = c;
18710a708f8fSGustavo F. Padovan }
18720a708f8fSGustavo F. Padovan }
18730a708f8fSGustavo F. Padovan
1874a24cce14SJohan Hedberg if (c1)
1875d0be8347SLuiz Augusto von Dentz c1 = l2cap_chan_hold_unless_zero(c1);
1876a24cce14SJohan Hedberg
187723691d75SGustavo F. Padovan read_unlock(&chan_list_lock);
18780a708f8fSGustavo F. Padovan
187923691d75SGustavo F. Padovan return c1;
18800a708f8fSGustavo F. Padovan }
18810a708f8fSGustavo F. Padovan
1882721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work)
l2cap_monitor_timeout(struct work_struct * work)18830a708f8fSGustavo F. Padovan {
1884721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1885721c4181SGustavo F. Padovan monitor_timer.work);
18860a708f8fSGustavo F. Padovan
1887525cd185SGustavo F. Padovan BT_DBG("chan %p", chan);
18880a708f8fSGustavo F. Padovan
18896be36555SAndrei Emeltchenko l2cap_chan_lock(chan);
18906be36555SAndrei Emeltchenko
189180909e04SMat Martineau if (!chan->conn) {
18926be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
18938d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan);
18940a708f8fSGustavo F. Padovan return;
18950a708f8fSGustavo F. Padovan }
18960a708f8fSGustavo F. Padovan
1897401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO);
18980a708f8fSGustavo F. Padovan
18996be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
19008d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan);
19010a708f8fSGustavo F. Padovan }
19020a708f8fSGustavo F. Padovan
1903721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work)
l2cap_retrans_timeout(struct work_struct * work)19040a708f8fSGustavo F. Padovan {
1905721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1906721c4181SGustavo F. Padovan retrans_timer.work);
19070a708f8fSGustavo F. Padovan
190849208c9cSGustavo F. Padovan BT_DBG("chan %p", chan);
19090a708f8fSGustavo F. Padovan
19106be36555SAndrei Emeltchenko l2cap_chan_lock(chan);
19116be36555SAndrei Emeltchenko
191280909e04SMat Martineau if (!chan->conn) {
191380909e04SMat Martineau l2cap_chan_unlock(chan);
191480909e04SMat Martineau l2cap_chan_put(chan);
191580909e04SMat Martineau return;
191680909e04SMat Martineau }
19170a708f8fSGustavo F. Padovan
1918401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO);
19196be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
19208d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan);
19210a708f8fSGustavo F. Padovan }
19220a708f8fSGustavo F. Padovan
1923d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan,
l2cap_streaming_send(struct l2cap_chan * chan,struct sk_buff_head * skbs)19243733937dSMat Martineau struct sk_buff_head *skbs)
19250a708f8fSGustavo F. Padovan {
19260a708f8fSGustavo F. Padovan struct sk_buff *skb;
19273733937dSMat Martineau struct l2cap_ctrl *control;
19280a708f8fSGustavo F. Padovan
19293733937dSMat Martineau BT_DBG("chan %p, skbs %p", chan, skbs);
19303733937dSMat Martineau
19313733937dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q);
19323733937dSMat Martineau
19333733937dSMat Martineau while (!skb_queue_empty(&chan->tx_q)) {
19343733937dSMat Martineau
19353733937dSMat Martineau skb = skb_dequeue(&chan->tx_q);
19363733937dSMat Martineau
1937a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 1;
1938a4368ff3SJohan Hedberg control = &bt_cb(skb)->l2cap;
19393733937dSMat Martineau
19403733937dSMat Martineau control->reqseq = 0;
19413733937dSMat Martineau control->txseq = chan->next_tx_seq;
19423733937dSMat Martineau
19433733937dSMat Martineau __pack_control(chan, control, skb);
19440a708f8fSGustavo F. Padovan
194547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) {
19463733937dSMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
19473733937dSMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
19480a708f8fSGustavo F. Padovan }
19490a708f8fSGustavo F. Padovan
19504343478fSGustavo F. Padovan l2cap_do_send(chan, skb);
19510a708f8fSGustavo F. Padovan
1952b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq);
19533733937dSMat Martineau
1954836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
19553733937dSMat Martineau chan->frames_sent++;
19560a708f8fSGustavo F. Padovan }
19570a708f8fSGustavo F. Padovan }
19580a708f8fSGustavo F. Padovan
195967c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan)
l2cap_ertm_send(struct l2cap_chan * chan)19600a708f8fSGustavo F. Padovan {
19610a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb;
196218a48e76SMat Martineau struct l2cap_ctrl *control;
196318a48e76SMat Martineau int sent = 0;
196418a48e76SMat Martineau
196518a48e76SMat Martineau BT_DBG("chan %p", chan);
19660a708f8fSGustavo F. Padovan
196789bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED)
19680a708f8fSGustavo F. Padovan return -ENOTCONN;
19690a708f8fSGustavo F. Padovan
197094122bbeSMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
197194122bbeSMat Martineau return 0;
197294122bbeSMat Martineau
197318a48e76SMat Martineau while (chan->tx_send_head &&
197418a48e76SMat Martineau chan->unacked_frames < chan->remote_tx_win &&
197518a48e76SMat Martineau chan->tx_state == L2CAP_TX_STATE_XMIT) {
19760a708f8fSGustavo F. Padovan
197718a48e76SMat Martineau skb = chan->tx_send_head;
19780a708f8fSGustavo F. Padovan
1979a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 1;
1980a4368ff3SJohan Hedberg control = &bt_cb(skb)->l2cap;
19810a708f8fSGustavo F. Padovan
1982e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
198318a48e76SMat Martineau control->final = 1;
1984e2ab4353SGustavo F. Padovan
198518a48e76SMat Martineau control->reqseq = chan->buffer_seq;
198618a48e76SMat Martineau chan->last_acked_seq = chan->buffer_seq;
198718a48e76SMat Martineau control->txseq = chan->next_tx_seq;
19880a708f8fSGustavo F. Padovan
198918a48e76SMat Martineau __pack_control(chan, control, skb);
19900a708f8fSGustavo F. Padovan
199147d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) {
199218a48e76SMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
199318a48e76SMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
19940a708f8fSGustavo F. Padovan }
19950a708f8fSGustavo F. Padovan
199618a48e76SMat Martineau /* Clone after data has been modified. Data is assumed to be
199718a48e76SMat Martineau read-only (for locking purposes) on cloned sk_buffs.
199818a48e76SMat Martineau */
199918a48e76SMat Martineau tx_skb = skb_clone(skb, GFP_KERNEL);
200018a48e76SMat Martineau
200118a48e76SMat Martineau if (!tx_skb)
200218a48e76SMat Martineau break;
20030a708f8fSGustavo F. Padovan
20041a09bcb9SGustavo F. Padovan __set_retrans_timer(chan);
20050a708f8fSGustavo F. Padovan
2006836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
20076a026610SGustavo F. Padovan chan->unacked_frames++;
20086a026610SGustavo F. Padovan chan->frames_sent++;
200918a48e76SMat Martineau sent++;
20100a708f8fSGustavo F. Padovan
201158d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb))
201258d35f87SGustavo F. Padovan chan->tx_send_head = NULL;
20130a708f8fSGustavo F. Padovan else
201458d35f87SGustavo F. Padovan chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
201518a48e76SMat Martineau
201618a48e76SMat Martineau l2cap_do_send(chan, tx_skb);
2017b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq);
20180a708f8fSGustavo F. Padovan }
20190a708f8fSGustavo F. Padovan
2020b4400672SAndrei Emeltchenko BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent,
2021b4400672SAndrei Emeltchenko chan->unacked_frames, skb_queue_len(&chan->tx_q));
202218a48e76SMat Martineau
202318a48e76SMat Martineau return sent;
20240a708f8fSGustavo F. Padovan }
20250a708f8fSGustavo F. Padovan
2026e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan)
l2cap_ertm_resend(struct l2cap_chan * chan)2027e1fbd4c1SMat Martineau {
2028e1fbd4c1SMat Martineau struct l2cap_ctrl control;
2029e1fbd4c1SMat Martineau struct sk_buff *skb;
2030e1fbd4c1SMat Martineau struct sk_buff *tx_skb;
2031e1fbd4c1SMat Martineau u16 seq;
2032e1fbd4c1SMat Martineau
2033e1fbd4c1SMat Martineau BT_DBG("chan %p", chan);
2034e1fbd4c1SMat Martineau
2035e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
2036e1fbd4c1SMat Martineau return;
2037e1fbd4c1SMat Martineau
2038e1fbd4c1SMat Martineau while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) {
2039e1fbd4c1SMat Martineau seq = l2cap_seq_list_pop(&chan->retrans_list);
2040e1fbd4c1SMat Martineau
2041e1fbd4c1SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq);
2042e1fbd4c1SMat Martineau if (!skb) {
2043e1fbd4c1SMat Martineau BT_DBG("Error: Can't retransmit seq %d, frame missing",
2044e1fbd4c1SMat Martineau seq);
2045e1fbd4c1SMat Martineau continue;
2046e1fbd4c1SMat Martineau }
2047e1fbd4c1SMat Martineau
2048a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries++;
2049a4368ff3SJohan Hedberg control = bt_cb(skb)->l2cap;
2050e1fbd4c1SMat Martineau
2051e1fbd4c1SMat Martineau if (chan->max_tx != 0 &&
2052a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries > chan->max_tx) {
2053e1fbd4c1SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
20545e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
2055e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list);
2056e1fbd4c1SMat Martineau break;
2057e1fbd4c1SMat Martineau }
2058e1fbd4c1SMat Martineau
2059e1fbd4c1SMat Martineau control.reqseq = chan->buffer_seq;
2060e1fbd4c1SMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
2061e1fbd4c1SMat Martineau control.final = 1;
2062e1fbd4c1SMat Martineau else
2063e1fbd4c1SMat Martineau control.final = 0;
2064e1fbd4c1SMat Martineau
2065e1fbd4c1SMat Martineau if (skb_cloned(skb)) {
2066e1fbd4c1SMat Martineau /* Cloned sk_buffs are read-only, so we need a
2067e1fbd4c1SMat Martineau * writeable copy
2068e1fbd4c1SMat Martineau */
20698bcde1f2SGustavo Padovan tx_skb = skb_copy(skb, GFP_KERNEL);
2070e1fbd4c1SMat Martineau } else {
20718bcde1f2SGustavo Padovan tx_skb = skb_clone(skb, GFP_KERNEL);
2072e1fbd4c1SMat Martineau }
2073e1fbd4c1SMat Martineau
2074e1fbd4c1SMat Martineau if (!tx_skb) {
2075e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list);
2076e1fbd4c1SMat Martineau break;
2077e1fbd4c1SMat Martineau }
2078e1fbd4c1SMat Martineau
2079e1fbd4c1SMat Martineau /* Update skb contents */
2080e1fbd4c1SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
2081e1fbd4c1SMat Martineau put_unaligned_le32(__pack_extended_control(&control),
2082e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE);
2083e1fbd4c1SMat Martineau } else {
2084e1fbd4c1SMat Martineau put_unaligned_le16(__pack_enhanced_control(&control),
2085e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE);
2086e1fbd4c1SMat Martineau }
2087e1fbd4c1SMat Martineau
208813cac152SLukasz Rymanowski /* Update FCS */
2089e1fbd4c1SMat Martineau if (chan->fcs == L2CAP_FCS_CRC16) {
209013cac152SLukasz Rymanowski u16 fcs = crc16(0, (u8 *) tx_skb->data,
209113cac152SLukasz Rymanowski tx_skb->len - L2CAP_FCS_SIZE);
209213cac152SLukasz Rymanowski put_unaligned_le16(fcs, skb_tail_pointer(tx_skb) -
209313cac152SLukasz Rymanowski L2CAP_FCS_SIZE);
2094e1fbd4c1SMat Martineau }
2095e1fbd4c1SMat Martineau
2096e1fbd4c1SMat Martineau l2cap_do_send(chan, tx_skb);
2097e1fbd4c1SMat Martineau
2098e1fbd4c1SMat Martineau BT_DBG("Resent txseq %d", control.txseq);
2099e1fbd4c1SMat Martineau
2100e1fbd4c1SMat Martineau chan->last_acked_seq = chan->buffer_seq;
2101e1fbd4c1SMat Martineau }
2102e1fbd4c1SMat Martineau }
2103e1fbd4c1SMat Martineau
2104f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan,
l2cap_retransmit(struct l2cap_chan * chan,struct l2cap_ctrl * control)2105f80842a8SMat Martineau struct l2cap_ctrl *control)
2106f80842a8SMat Martineau {
2107f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control);
2108f80842a8SMat Martineau
2109f80842a8SMat Martineau l2cap_seq_list_append(&chan->retrans_list, control->reqseq);
2110f80842a8SMat Martineau l2cap_ertm_resend(chan);
2111f80842a8SMat Martineau }
2112f80842a8SMat Martineau
2113d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan,
l2cap_retransmit_all(struct l2cap_chan * chan,struct l2cap_ctrl * control)2114d2a7ac5dSMat Martineau struct l2cap_ctrl *control)
2115d2a7ac5dSMat Martineau {
2116e1fbd4c1SMat Martineau struct sk_buff *skb;
2117e1fbd4c1SMat Martineau
2118e1fbd4c1SMat Martineau BT_DBG("chan %p, control %p", chan, control);
2119e1fbd4c1SMat Martineau
2120e1fbd4c1SMat Martineau if (control->poll)
2121e1fbd4c1SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state);
2122e1fbd4c1SMat Martineau
2123e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list);
2124e1fbd4c1SMat Martineau
2125e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
2126e1fbd4c1SMat Martineau return;
2127e1fbd4c1SMat Martineau
2128e1fbd4c1SMat Martineau if (chan->unacked_frames) {
2129e1fbd4c1SMat Martineau skb_queue_walk(&chan->tx_q, skb) {
2130a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.txseq == control->reqseq ||
2131e1fbd4c1SMat Martineau skb == chan->tx_send_head)
2132e1fbd4c1SMat Martineau break;
2133e1fbd4c1SMat Martineau }
2134e1fbd4c1SMat Martineau
2135e1fbd4c1SMat Martineau skb_queue_walk_from(&chan->tx_q, skb) {
2136e1fbd4c1SMat Martineau if (skb == chan->tx_send_head)
2137e1fbd4c1SMat Martineau break;
2138e1fbd4c1SMat Martineau
2139e1fbd4c1SMat Martineau l2cap_seq_list_append(&chan->retrans_list,
2140a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.txseq);
2141e1fbd4c1SMat Martineau }
2142e1fbd4c1SMat Martineau
2143e1fbd4c1SMat Martineau l2cap_ertm_resend(chan);
2144e1fbd4c1SMat Martineau }
2145d2a7ac5dSMat Martineau }
2146d2a7ac5dSMat Martineau
2147b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan)
l2cap_send_ack(struct l2cap_chan * chan)2148b17e73bbSSzymon Janc {
21490a0aba42SMat Martineau struct l2cap_ctrl control;
21500a0aba42SMat Martineau u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq,
21510a0aba42SMat Martineau chan->last_acked_seq);
21520a0aba42SMat Martineau int threshold;
21530a0aba42SMat Martineau
21540a0aba42SMat Martineau BT_DBG("chan %p last_acked_seq %d buffer_seq %d",
21550a0aba42SMat Martineau chan, chan->last_acked_seq, chan->buffer_seq);
21560a0aba42SMat Martineau
21570a0aba42SMat Martineau memset(&control, 0, sizeof(control));
21580a0aba42SMat Martineau control.sframe = 1;
21590a0aba42SMat Martineau
21600a0aba42SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
21610a0aba42SMat Martineau chan->rx_state == L2CAP_RX_STATE_RECV) {
2162b17e73bbSSzymon Janc __clear_ack_timer(chan);
21630a0aba42SMat Martineau control.super = L2CAP_SUPER_RNR;
21640a0aba42SMat Martineau control.reqseq = chan->buffer_seq;
21650a0aba42SMat Martineau l2cap_send_sframe(chan, &control);
21660a0aba42SMat Martineau } else {
21670a0aba42SMat Martineau if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) {
21680a0aba42SMat Martineau l2cap_ertm_send(chan);
21690a0aba42SMat Martineau /* If any i-frames were sent, they included an ack */
21700a0aba42SMat Martineau if (chan->buffer_seq == chan->last_acked_seq)
21710a0aba42SMat Martineau frames_to_ack = 0;
21720a0aba42SMat Martineau }
21730a0aba42SMat Martineau
2174c20f8e35SMat Martineau /* Ack now if the window is 3/4ths full.
21750a0aba42SMat Martineau * Calculate without mul or div
21760a0aba42SMat Martineau */
2177c20f8e35SMat Martineau threshold = chan->ack_win;
21780a0aba42SMat Martineau threshold += threshold << 1;
21790a0aba42SMat Martineau threshold >>= 2;
21800a0aba42SMat Martineau
2181b4400672SAndrei Emeltchenko BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack,
21820a0aba42SMat Martineau threshold);
21830a0aba42SMat Martineau
21840a0aba42SMat Martineau if (frames_to_ack >= threshold) {
21850a0aba42SMat Martineau __clear_ack_timer(chan);
21860a0aba42SMat Martineau control.super = L2CAP_SUPER_RR;
21870a0aba42SMat Martineau control.reqseq = chan->buffer_seq;
21880a0aba42SMat Martineau l2cap_send_sframe(chan, &control);
21890a0aba42SMat Martineau frames_to_ack = 0;
21900a0aba42SMat Martineau }
21910a0aba42SMat Martineau
21920a0aba42SMat Martineau if (frames_to_ack)
21930a0aba42SMat Martineau __set_ack_timer(chan);
21940a0aba42SMat Martineau }
2195b17e73bbSSzymon Janc }
2196b17e73bbSSzymon Janc
219704124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
l2cap_skbuff_fromiovec(struct l2cap_chan * chan,struct msghdr * msg,int len,int count,struct sk_buff * skb)219804124681SGustavo F. Padovan struct msghdr *msg, int len,
219904124681SGustavo F. Padovan int count, struct sk_buff *skb)
22000a708f8fSGustavo F. Padovan {
22010952a57aSAndrei Emeltchenko struct l2cap_conn *conn = chan->conn;
22020a708f8fSGustavo F. Padovan struct sk_buff **frag;
220390338947SGustavo Padovan int sent = 0;
22040a708f8fSGustavo F. Padovan
2205cbbd26b8SAl Viro if (!copy_from_iter_full(skb_put(skb, count), count, &msg->msg_iter))
22060a708f8fSGustavo F. Padovan return -EFAULT;
22070a708f8fSGustavo F. Padovan
22080a708f8fSGustavo F. Padovan sent += count;
22090a708f8fSGustavo F. Padovan len -= count;
22100a708f8fSGustavo F. Padovan
22110a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */
22120a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list;
22130a708f8fSGustavo F. Padovan while (len) {
2214fbe00700SGustavo Padovan struct sk_buff *tmp;
2215fbe00700SGustavo Padovan
22160a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len);
22170a708f8fSGustavo F. Padovan
2218d9fbd02bSMarcel Holtmann tmp = chan->ops->alloc_skb(chan, 0, count,
221990338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT);
2220fbe00700SGustavo Padovan if (IS_ERR(tmp))
2221fbe00700SGustavo Padovan return PTR_ERR(tmp);
22222f7719ceSAndrei Emeltchenko
2223fbe00700SGustavo Padovan *frag = tmp;
2224fbe00700SGustavo Padovan
2225cbbd26b8SAl Viro if (!copy_from_iter_full(skb_put(*frag, count), count,
2226cbbd26b8SAl Viro &msg->msg_iter))
22270a708f8fSGustavo F. Padovan return -EFAULT;
22280a708f8fSGustavo F. Padovan
22290a708f8fSGustavo F. Padovan sent += count;
22300a708f8fSGustavo F. Padovan len -= count;
22310a708f8fSGustavo F. Padovan
22322d0ed3d5SGustavo Padovan skb->len += (*frag)->len;
22332d0ed3d5SGustavo Padovan skb->data_len += (*frag)->len;
22342d0ed3d5SGustavo Padovan
22350a708f8fSGustavo F. Padovan frag = &(*frag)->next;
22360a708f8fSGustavo F. Padovan }
22370a708f8fSGustavo F. Padovan
22380a708f8fSGustavo F. Padovan return sent;
22390a708f8fSGustavo F. Padovan }
22400a708f8fSGustavo F. Padovan
22415e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
l2cap_create_connless_pdu(struct l2cap_chan * chan,struct msghdr * msg,size_t len)22428d46321cSMarcel Holtmann struct msghdr *msg, size_t len)
22430a708f8fSGustavo F. Padovan {
22448c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn;
22450a708f8fSGustavo F. Padovan struct sk_buff *skb;
224603a51213SAndrei Emeltchenko int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
22470a708f8fSGustavo F. Padovan struct l2cap_hdr *lh;
22480a708f8fSGustavo F. Padovan
22498d46321cSMarcel Holtmann BT_DBG("chan %p psm 0x%2.2x len %zu", chan,
22508d46321cSMarcel Holtmann __le16_to_cpu(chan->psm), len);
22510a708f8fSGustavo F. Padovan
22520a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len);
22532f7719ceSAndrei Emeltchenko
2254d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, hlen, count,
225590338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT);
225690338947SGustavo Padovan if (IS_ERR(skb))
225790338947SGustavo Padovan return skb;
22580a708f8fSGustavo F. Padovan
22590a708f8fSGustavo F. Padovan /* Create L2CAP header */
22604df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE);
2261fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid);
2262daf6a78cSAndrei Emeltchenko lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
226343b1b8dfSMarcel Holtmann put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE));
22640a708f8fSGustavo F. Padovan
22650952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
22660a708f8fSGustavo F. Padovan if (unlikely(err < 0)) {
22670a708f8fSGustavo F. Padovan kfree_skb(skb);
22680a708f8fSGustavo F. Padovan return ERR_PTR(err);
22690a708f8fSGustavo F. Padovan }
22700a708f8fSGustavo F. Padovan return skb;
22710a708f8fSGustavo F. Padovan }
22720a708f8fSGustavo F. Padovan
22735e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
l2cap_create_basic_pdu(struct l2cap_chan * chan,struct msghdr * msg,size_t len)22748d46321cSMarcel Holtmann struct msghdr *msg, size_t len)
22750a708f8fSGustavo F. Padovan {
22768c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn;
22770a708f8fSGustavo F. Padovan struct sk_buff *skb;
2278f2ba7faeSGustavo Padovan int err, count;
22790a708f8fSGustavo F. Padovan struct l2cap_hdr *lh;
22800a708f8fSGustavo F. Padovan
2281b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len);
22820a708f8fSGustavo F. Padovan
2283f2ba7faeSGustavo Padovan count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
22842f7719ceSAndrei Emeltchenko
2285d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, L2CAP_HDR_SIZE, count,
228690338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT);
228790338947SGustavo Padovan if (IS_ERR(skb))
228890338947SGustavo Padovan return skb;
22890a708f8fSGustavo F. Padovan
22900a708f8fSGustavo F. Padovan /* Create L2CAP header */
22914df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE);
2292fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid);
22936ff9b5efSGustavo Padovan lh->len = cpu_to_le16(len);
22940a708f8fSGustavo F. Padovan
22950952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
22960a708f8fSGustavo F. Padovan if (unlikely(err < 0)) {
22970a708f8fSGustavo F. Padovan kfree_skb(skb);
22980a708f8fSGustavo F. Padovan return ERR_PTR(err);
22990a708f8fSGustavo F. Padovan }
23000a708f8fSGustavo F. Padovan return skb;
23010a708f8fSGustavo F. Padovan }
23020a708f8fSGustavo F. Padovan
2303ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
l2cap_create_iframe_pdu(struct l2cap_chan * chan,struct msghdr * msg,size_t len,u16 sdulen)2304ab0ff76dSLuiz Augusto von Dentz struct msghdr *msg, size_t len,
230594122bbeSMat Martineau u16 sdulen)
23060a708f8fSGustavo F. Padovan {
23078c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn;
23080a708f8fSGustavo F. Padovan struct sk_buff *skb;
2309e4ca6d98SAndrei Emeltchenko int err, count, hlen;
23100a708f8fSGustavo F. Padovan struct l2cap_hdr *lh;
23110a708f8fSGustavo F. Padovan
2312b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len);
23130a708f8fSGustavo F. Padovan
23140a708f8fSGustavo F. Padovan if (!conn)
23150a708f8fSGustavo F. Padovan return ERR_PTR(-ENOTCONN);
23160a708f8fSGustavo F. Padovan
2317ba7aa64fSGustavo Padovan hlen = __ertm_hdr_size(chan);
2318e4ca6d98SAndrei Emeltchenko
23190a708f8fSGustavo F. Padovan if (sdulen)
232003a51213SAndrei Emeltchenko hlen += L2CAP_SDULEN_SIZE;
23210a708f8fSGustavo F. Padovan
232247d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16)
232303a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE;
23240a708f8fSGustavo F. Padovan
23250a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len);
23262f7719ceSAndrei Emeltchenko
2327d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, hlen, count,
232890338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT);
232990338947SGustavo Padovan if (IS_ERR(skb))
233090338947SGustavo Padovan return skb;
23310a708f8fSGustavo F. Padovan
23320a708f8fSGustavo F. Padovan /* Create L2CAP header */
23334df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE);
2334fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid);
23350a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
233688843ab0SAndrei Emeltchenko
233718a48e76SMat Martineau /* Control header is populated later */
233818a48e76SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags))
233918a48e76SMat Martineau put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
234018a48e76SMat Martineau else
234118a48e76SMat Martineau put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
234288843ab0SAndrei Emeltchenko
23430a708f8fSGustavo F. Padovan if (sdulen)
234403a51213SAndrei Emeltchenko put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
23450a708f8fSGustavo F. Padovan
23460952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
23470a708f8fSGustavo F. Padovan if (unlikely(err < 0)) {
23480a708f8fSGustavo F. Padovan kfree_skb(skb);
23490a708f8fSGustavo F. Padovan return ERR_PTR(err);
23500a708f8fSGustavo F. Padovan }
23510a708f8fSGustavo F. Padovan
2352a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.fcs = chan->fcs;
2353a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 0;
23540a708f8fSGustavo F. Padovan return skb;
23550a708f8fSGustavo F. Padovan }
23560a708f8fSGustavo F. Padovan
235794122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan,
l2cap_segment_sdu(struct l2cap_chan * chan,struct sk_buff_head * seg_queue,struct msghdr * msg,size_t len)235894122bbeSMat Martineau struct sk_buff_head *seg_queue,
235994122bbeSMat Martineau struct msghdr *msg, size_t len)
23600a708f8fSGustavo F. Padovan {
23610a708f8fSGustavo F. Padovan struct sk_buff *skb;
236294122bbeSMat Martineau u16 sdu_len;
236394122bbeSMat Martineau size_t pdu_len;
236494122bbeSMat Martineau u8 sar;
23650a708f8fSGustavo F. Padovan
2366b4400672SAndrei Emeltchenko BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
23670a708f8fSGustavo F. Padovan
236894122bbeSMat Martineau /* It is critical that ERTM PDUs fit in a single HCI fragment,
236994122bbeSMat Martineau * so fragmented skbs are not used. The HCI layer's handling
237094122bbeSMat Martineau * of fragmented skbs is not compatible with ERTM's queueing.
237194122bbeSMat Martineau */
237294122bbeSMat Martineau
237394122bbeSMat Martineau /* PDU size is derived from the HCI MTU */
237494122bbeSMat Martineau pdu_len = chan->conn->mtu;
237594122bbeSMat Martineau
2376a549574dSMat Martineau /* Constrain PDU size for BR/EDR connections */
237794122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
237894122bbeSMat Martineau
237994122bbeSMat Martineau /* Adjust for largest possible L2CAP overhead. */
238035d401dfSGustavo Padovan if (chan->fcs)
238135d401dfSGustavo Padovan pdu_len -= L2CAP_FCS_SIZE;
238235d401dfSGustavo Padovan
2383ba7aa64fSGustavo Padovan pdu_len -= __ertm_hdr_size(chan);
238494122bbeSMat Martineau
238594122bbeSMat Martineau /* Remote device may have requested smaller PDUs */
238694122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
238794122bbeSMat Martineau
238894122bbeSMat Martineau if (len <= pdu_len) {
238994122bbeSMat Martineau sar = L2CAP_SAR_UNSEGMENTED;
239094122bbeSMat Martineau sdu_len = 0;
239194122bbeSMat Martineau pdu_len = len;
239294122bbeSMat Martineau } else {
239394122bbeSMat Martineau sar = L2CAP_SAR_START;
239494122bbeSMat Martineau sdu_len = len;
239594122bbeSMat Martineau }
23960a708f8fSGustavo F. Padovan
23970a708f8fSGustavo F. Padovan while (len > 0) {
239894122bbeSMat Martineau skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
23990a708f8fSGustavo F. Padovan
24000a708f8fSGustavo F. Padovan if (IS_ERR(skb)) {
240194122bbeSMat Martineau __skb_queue_purge(seg_queue);
24020a708f8fSGustavo F. Padovan return PTR_ERR(skb);
24030a708f8fSGustavo F. Padovan }
24040a708f8fSGustavo F. Padovan
2405a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.sar = sar;
240694122bbeSMat Martineau __skb_queue_tail(seg_queue, skb);
24070a708f8fSGustavo F. Padovan
240894122bbeSMat Martineau len -= pdu_len;
2409069cb270SLukasz Rymanowski if (sdu_len)
241094122bbeSMat Martineau sdu_len = 0;
241194122bbeSMat Martineau
241294122bbeSMat Martineau if (len <= pdu_len) {
241394122bbeSMat Martineau sar = L2CAP_SAR_END;
241494122bbeSMat Martineau pdu_len = len;
241594122bbeSMat Martineau } else {
241694122bbeSMat Martineau sar = L2CAP_SAR_CONTINUE;
241794122bbeSMat Martineau }
241894122bbeSMat Martineau }
241994122bbeSMat Martineau
2420f0f62799SGustavo Padovan return 0;
24210a708f8fSGustavo F. Padovan }
24220a708f8fSGustavo F. Padovan
2423177f8f2bSJohan Hedberg static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan,
l2cap_create_le_flowctl_pdu(struct l2cap_chan * chan,struct msghdr * msg,size_t len,u16 sdulen)2424177f8f2bSJohan Hedberg struct msghdr *msg,
2425177f8f2bSJohan Hedberg size_t len, u16 sdulen)
2426177f8f2bSJohan Hedberg {
2427177f8f2bSJohan Hedberg struct l2cap_conn *conn = chan->conn;
2428177f8f2bSJohan Hedberg struct sk_buff *skb;
2429177f8f2bSJohan Hedberg int err, count, hlen;
2430177f8f2bSJohan Hedberg struct l2cap_hdr *lh;
2431177f8f2bSJohan Hedberg
2432177f8f2bSJohan Hedberg BT_DBG("chan %p len %zu", chan, len);
2433177f8f2bSJohan Hedberg
2434177f8f2bSJohan Hedberg if (!conn)
2435177f8f2bSJohan Hedberg return ERR_PTR(-ENOTCONN);
2436177f8f2bSJohan Hedberg
2437177f8f2bSJohan Hedberg hlen = L2CAP_HDR_SIZE;
2438177f8f2bSJohan Hedberg
2439177f8f2bSJohan Hedberg if (sdulen)
2440177f8f2bSJohan Hedberg hlen += L2CAP_SDULEN_SIZE;
2441177f8f2bSJohan Hedberg
2442177f8f2bSJohan Hedberg count = min_t(unsigned int, (conn->mtu - hlen), len);
2443177f8f2bSJohan Hedberg
2444d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, hlen, count,
2445177f8f2bSJohan Hedberg msg->msg_flags & MSG_DONTWAIT);
2446177f8f2bSJohan Hedberg if (IS_ERR(skb))
2447177f8f2bSJohan Hedberg return skb;
2448177f8f2bSJohan Hedberg
2449177f8f2bSJohan Hedberg /* Create L2CAP header */
24504df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE);
2451177f8f2bSJohan Hedberg lh->cid = cpu_to_le16(chan->dcid);
2452177f8f2bSJohan Hedberg lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
2453177f8f2bSJohan Hedberg
2454177f8f2bSJohan Hedberg if (sdulen)
2455177f8f2bSJohan Hedberg put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
2456177f8f2bSJohan Hedberg
2457177f8f2bSJohan Hedberg err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
2458177f8f2bSJohan Hedberg if (unlikely(err < 0)) {
2459177f8f2bSJohan Hedberg kfree_skb(skb);
2460177f8f2bSJohan Hedberg return ERR_PTR(err);
2461177f8f2bSJohan Hedberg }
2462177f8f2bSJohan Hedberg
2463177f8f2bSJohan Hedberg return skb;
2464177f8f2bSJohan Hedberg }
2465177f8f2bSJohan Hedberg
2466177f8f2bSJohan Hedberg static int l2cap_segment_le_sdu(struct l2cap_chan *chan,
l2cap_segment_le_sdu(struct l2cap_chan * chan,struct sk_buff_head * seg_queue,struct msghdr * msg,size_t len)2467177f8f2bSJohan Hedberg struct sk_buff_head *seg_queue,
2468177f8f2bSJohan Hedberg struct msghdr *msg, size_t len)
2469177f8f2bSJohan Hedberg {
2470177f8f2bSJohan Hedberg struct sk_buff *skb;
2471177f8f2bSJohan Hedberg size_t pdu_len;
2472177f8f2bSJohan Hedberg u16 sdu_len;
2473177f8f2bSJohan Hedberg
2474177f8f2bSJohan Hedberg BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
2475177f8f2bSJohan Hedberg
2476177f8f2bSJohan Hedberg sdu_len = len;
247772c6fb91SJohan Hedberg pdu_len = chan->remote_mps - L2CAP_SDULEN_SIZE;
2478177f8f2bSJohan Hedberg
2479177f8f2bSJohan Hedberg while (len > 0) {
2480177f8f2bSJohan Hedberg if (len <= pdu_len)
2481177f8f2bSJohan Hedberg pdu_len = len;
2482177f8f2bSJohan Hedberg
2483177f8f2bSJohan Hedberg skb = l2cap_create_le_flowctl_pdu(chan, msg, pdu_len, sdu_len);
2484177f8f2bSJohan Hedberg if (IS_ERR(skb)) {
2485177f8f2bSJohan Hedberg __skb_queue_purge(seg_queue);
2486177f8f2bSJohan Hedberg return PTR_ERR(skb);
2487177f8f2bSJohan Hedberg }
2488177f8f2bSJohan Hedberg
2489177f8f2bSJohan Hedberg __skb_queue_tail(seg_queue, skb);
2490177f8f2bSJohan Hedberg
2491177f8f2bSJohan Hedberg len -= pdu_len;
2492177f8f2bSJohan Hedberg
2493177f8f2bSJohan Hedberg if (sdu_len) {
2494177f8f2bSJohan Hedberg sdu_len = 0;
2495177f8f2bSJohan Hedberg pdu_len += L2CAP_SDULEN_SIZE;
2496177f8f2bSJohan Hedberg }
2497177f8f2bSJohan Hedberg }
2498177f8f2bSJohan Hedberg
2499177f8f2bSJohan Hedberg return 0;
2500177f8f2bSJohan Hedberg }
2501177f8f2bSJohan Hedberg
25028a505b7fSLuiz Augusto von Dentz static void l2cap_le_flowctl_send(struct l2cap_chan *chan)
l2cap_le_flowctl_send(struct l2cap_chan * chan)25038a505b7fSLuiz Augusto von Dentz {
25048a505b7fSLuiz Augusto von Dentz int sent = 0;
25058a505b7fSLuiz Augusto von Dentz
25068a505b7fSLuiz Augusto von Dentz BT_DBG("chan %p", chan);
25078a505b7fSLuiz Augusto von Dentz
25088a505b7fSLuiz Augusto von Dentz while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) {
25098a505b7fSLuiz Augusto von Dentz l2cap_do_send(chan, skb_dequeue(&chan->tx_q));
25108a505b7fSLuiz Augusto von Dentz chan->tx_credits--;
25118a505b7fSLuiz Augusto von Dentz sent++;
25128a505b7fSLuiz Augusto von Dentz }
25138a505b7fSLuiz Augusto von Dentz
25148a505b7fSLuiz Augusto von Dentz BT_DBG("Sent %d credits %u queued %u", sent, chan->tx_credits,
25158a505b7fSLuiz Augusto von Dentz skb_queue_len(&chan->tx_q));
25168a505b7fSLuiz Augusto von Dentz }
25178a505b7fSLuiz Augusto von Dentz
25188d46321cSMarcel Holtmann int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
l2cap_chan_send(struct l2cap_chan * chan,struct msghdr * msg,size_t len)25199a91a04aSGustavo F. Padovan {
25209a91a04aSGustavo F. Padovan struct sk_buff *skb;
25219a91a04aSGustavo F. Padovan int err;
252294122bbeSMat Martineau struct sk_buff_head seg_queue;
25239a91a04aSGustavo F. Padovan
252431e8ce80SSeung-Woo Kim if (!chan->conn)
252531e8ce80SSeung-Woo Kim return -ENOTCONN;
252631e8ce80SSeung-Woo Kim
25279a91a04aSGustavo F. Padovan /* Connectionless channel */
2528715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
25298d46321cSMarcel Holtmann skb = l2cap_create_connless_pdu(chan, msg, len);
25309a91a04aSGustavo F. Padovan if (IS_ERR(skb))
25319a91a04aSGustavo F. Padovan return PTR_ERR(skb);
25329a91a04aSGustavo F. Padovan
25339a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb);
25349a91a04aSGustavo F. Padovan return len;
25359a91a04aSGustavo F. Padovan }
25369a91a04aSGustavo F. Padovan
25379a91a04aSGustavo F. Padovan switch (chan->mode) {
253838319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL:
253915f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL:
2540177f8f2bSJohan Hedberg /* Check outgoing MTU */
2541177f8f2bSJohan Hedberg if (len > chan->omtu)
2542177f8f2bSJohan Hedberg return -EMSGSIZE;
2543177f8f2bSJohan Hedberg
2544177f8f2bSJohan Hedberg __skb_queue_head_init(&seg_queue);
2545177f8f2bSJohan Hedberg
2546177f8f2bSJohan Hedberg err = l2cap_segment_le_sdu(chan, &seg_queue, msg, len);
2547177f8f2bSJohan Hedberg
2548177f8f2bSJohan Hedberg if (chan->state != BT_CONNECTED) {
2549177f8f2bSJohan Hedberg __skb_queue_purge(&seg_queue);
2550177f8f2bSJohan Hedberg err = -ENOTCONN;
2551177f8f2bSJohan Hedberg }
2552177f8f2bSJohan Hedberg
2553177f8f2bSJohan Hedberg if (err)
2554177f8f2bSJohan Hedberg return err;
2555177f8f2bSJohan Hedberg
2556177f8f2bSJohan Hedberg skb_queue_splice_tail_init(&seg_queue, &chan->tx_q);
2557177f8f2bSJohan Hedberg
25588a505b7fSLuiz Augusto von Dentz l2cap_le_flowctl_send(chan);
2559177f8f2bSJohan Hedberg
2560177f8f2bSJohan Hedberg if (!chan->tx_credits)
2561177f8f2bSJohan Hedberg chan->ops->suspend(chan);
2562177f8f2bSJohan Hedberg
2563177f8f2bSJohan Hedberg err = len;
2564177f8f2bSJohan Hedberg
2565177f8f2bSJohan Hedberg break;
2566177f8f2bSJohan Hedberg
2567fad5fc89SJohan Hedberg case L2CAP_MODE_BASIC:
25689a91a04aSGustavo F. Padovan /* Check outgoing MTU */
25699a91a04aSGustavo F. Padovan if (len > chan->omtu)
25709a91a04aSGustavo F. Padovan return -EMSGSIZE;
25719a91a04aSGustavo F. Padovan
25729a91a04aSGustavo F. Padovan /* Create a basic PDU */
25738d46321cSMarcel Holtmann skb = l2cap_create_basic_pdu(chan, msg, len);
25749a91a04aSGustavo F. Padovan if (IS_ERR(skb))
25759a91a04aSGustavo F. Padovan return PTR_ERR(skb);
25769a91a04aSGustavo F. Padovan
25779a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb);
25789a91a04aSGustavo F. Padovan err = len;
25799a91a04aSGustavo F. Padovan break;
25809a91a04aSGustavo F. Padovan
25819a91a04aSGustavo F. Padovan case L2CAP_MODE_ERTM:
25829a91a04aSGustavo F. Padovan case L2CAP_MODE_STREAMING:
258394122bbeSMat Martineau /* Check outgoing MTU */
258494122bbeSMat Martineau if (len > chan->omtu) {
258594122bbeSMat Martineau err = -EMSGSIZE;
25869a91a04aSGustavo F. Padovan break;
25879a91a04aSGustavo F. Padovan }
25889a91a04aSGustavo F. Padovan
258994122bbeSMat Martineau __skb_queue_head_init(&seg_queue);
259094122bbeSMat Martineau
259194122bbeSMat Martineau /* Do segmentation before calling in to the state machine,
259294122bbeSMat Martineau * since it's possible to block while waiting for memory
259394122bbeSMat Martineau * allocation.
259494122bbeSMat Martineau */
259594122bbeSMat Martineau err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
259694122bbeSMat Martineau
259794122bbeSMat Martineau if (err)
259894122bbeSMat Martineau break;
259994122bbeSMat Martineau
26003733937dSMat Martineau if (chan->mode == L2CAP_MODE_ERTM)
2601d660366dSGustavo Padovan l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST);
26023733937dSMat Martineau else
2603d660366dSGustavo Padovan l2cap_streaming_send(chan, &seg_queue);
260494122bbeSMat Martineau
26059a91a04aSGustavo F. Padovan err = len;
26069a91a04aSGustavo F. Padovan
260794122bbeSMat Martineau /* If the skbs were not queued for sending, they'll still be in
260894122bbeSMat Martineau * seg_queue and need to be purged.
260994122bbeSMat Martineau */
261094122bbeSMat Martineau __skb_queue_purge(&seg_queue);
26119a91a04aSGustavo F. Padovan break;
26129a91a04aSGustavo F. Padovan
26139a91a04aSGustavo F. Padovan default:
26149a91a04aSGustavo F. Padovan BT_DBG("bad state %1.1x", chan->mode);
26159a91a04aSGustavo F. Padovan err = -EBADFD;
26169a91a04aSGustavo F. Padovan }
26179a91a04aSGustavo F. Padovan
26189a91a04aSGustavo F. Padovan return err;
26199a91a04aSGustavo F. Padovan }
26206b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_send);
26219a91a04aSGustavo F. Padovan
2622d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq)
l2cap_send_srej(struct l2cap_chan * chan,u16 txseq)2623d2a7ac5dSMat Martineau {
2624bed68bdeSMat Martineau struct l2cap_ctrl control;
2625bed68bdeSMat Martineau u16 seq;
2626bed68bdeSMat Martineau
2627b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq);
2628bed68bdeSMat Martineau
2629bed68bdeSMat Martineau memset(&control, 0, sizeof(control));
2630bed68bdeSMat Martineau control.sframe = 1;
2631bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ;
2632bed68bdeSMat Martineau
2633bed68bdeSMat Martineau for (seq = chan->expected_tx_seq; seq != txseq;
2634bed68bdeSMat Martineau seq = __next_seq(chan, seq)) {
2635bed68bdeSMat Martineau if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) {
2636bed68bdeSMat Martineau control.reqseq = seq;
2637bed68bdeSMat Martineau l2cap_send_sframe(chan, &control);
2638bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq);
2639bed68bdeSMat Martineau }
2640bed68bdeSMat Martineau }
2641bed68bdeSMat Martineau
2642bed68bdeSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq);
2643d2a7ac5dSMat Martineau }
2644d2a7ac5dSMat Martineau
2645d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan)
l2cap_send_srej_tail(struct l2cap_chan * chan)2646d2a7ac5dSMat Martineau {
2647bed68bdeSMat Martineau struct l2cap_ctrl control;
2648bed68bdeSMat Martineau
2649bed68bdeSMat Martineau BT_DBG("chan %p", chan);
2650bed68bdeSMat Martineau
2651bed68bdeSMat Martineau if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR)
2652bed68bdeSMat Martineau return;
2653bed68bdeSMat Martineau
2654bed68bdeSMat Martineau memset(&control, 0, sizeof(control));
2655bed68bdeSMat Martineau control.sframe = 1;
2656bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ;
2657bed68bdeSMat Martineau control.reqseq = chan->srej_list.tail;
2658bed68bdeSMat Martineau l2cap_send_sframe(chan, &control);
2659d2a7ac5dSMat Martineau }
2660d2a7ac5dSMat Martineau
2661d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq)
l2cap_send_srej_list(struct l2cap_chan * chan,u16 txseq)2662d2a7ac5dSMat Martineau {
2663bed68bdeSMat Martineau struct l2cap_ctrl control;
2664bed68bdeSMat Martineau u16 initial_head;
2665bed68bdeSMat Martineau u16 seq;
2666bed68bdeSMat Martineau
2667b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq);
2668bed68bdeSMat Martineau
2669bed68bdeSMat Martineau memset(&control, 0, sizeof(control));
2670bed68bdeSMat Martineau control.sframe = 1;
2671bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ;
2672bed68bdeSMat Martineau
2673bed68bdeSMat Martineau /* Capture initial list head to allow only one pass through the list. */
2674bed68bdeSMat Martineau initial_head = chan->srej_list.head;
2675bed68bdeSMat Martineau
2676bed68bdeSMat Martineau do {
2677bed68bdeSMat Martineau seq = l2cap_seq_list_pop(&chan->srej_list);
2678bed68bdeSMat Martineau if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR)
2679bed68bdeSMat Martineau break;
2680bed68bdeSMat Martineau
2681bed68bdeSMat Martineau control.reqseq = seq;
2682bed68bdeSMat Martineau l2cap_send_sframe(chan, &control);
2683bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq);
2684bed68bdeSMat Martineau } while (chan->srej_list.head != initial_head);
2685d2a7ac5dSMat Martineau }
2686d2a7ac5dSMat Martineau
2687608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq)
l2cap_process_reqseq(struct l2cap_chan * chan,u16 reqseq)2688608bcc6dSMat Martineau {
2689608bcc6dSMat Martineau struct sk_buff *acked_skb;
2690608bcc6dSMat Martineau u16 ackseq;
2691608bcc6dSMat Martineau
2692b4400672SAndrei Emeltchenko BT_DBG("chan %p, reqseq %u", chan, reqseq);
2693608bcc6dSMat Martineau
2694608bcc6dSMat Martineau if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq)
2695608bcc6dSMat Martineau return;
2696608bcc6dSMat Martineau
2697b4400672SAndrei Emeltchenko BT_DBG("expected_ack_seq %u, unacked_frames %u",
2698608bcc6dSMat Martineau chan->expected_ack_seq, chan->unacked_frames);
2699608bcc6dSMat Martineau
2700608bcc6dSMat Martineau for (ackseq = chan->expected_ack_seq; ackseq != reqseq;
2701608bcc6dSMat Martineau ackseq = __next_seq(chan, ackseq)) {
2702608bcc6dSMat Martineau
2703608bcc6dSMat Martineau acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq);
2704608bcc6dSMat Martineau if (acked_skb) {
2705608bcc6dSMat Martineau skb_unlink(acked_skb, &chan->tx_q);
2706608bcc6dSMat Martineau kfree_skb(acked_skb);
2707608bcc6dSMat Martineau chan->unacked_frames--;
2708608bcc6dSMat Martineau }
2709608bcc6dSMat Martineau }
2710608bcc6dSMat Martineau
2711608bcc6dSMat Martineau chan->expected_ack_seq = reqseq;
2712608bcc6dSMat Martineau
2713608bcc6dSMat Martineau if (chan->unacked_frames == 0)
2714608bcc6dSMat Martineau __clear_retrans_timer(chan);
2715608bcc6dSMat Martineau
2716b4400672SAndrei Emeltchenko BT_DBG("unacked_frames %u", chan->unacked_frames);
2717608bcc6dSMat Martineau }
2718608bcc6dSMat Martineau
2719608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan)
l2cap_abort_rx_srej_sent(struct l2cap_chan * chan)2720608bcc6dSMat Martineau {
2721608bcc6dSMat Martineau BT_DBG("chan %p", chan);
2722608bcc6dSMat Martineau
2723608bcc6dSMat Martineau chan->expected_tx_seq = chan->buffer_seq;
2724608bcc6dSMat Martineau l2cap_seq_list_clear(&chan->srej_list);
2725608bcc6dSMat Martineau skb_queue_purge(&chan->srej_q);
2726608bcc6dSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV;
2727608bcc6dSMat Martineau }
2728608bcc6dSMat Martineau
2729d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan,
l2cap_tx_state_xmit(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff_head * skbs,u8 event)2730608bcc6dSMat Martineau struct l2cap_ctrl *control,
2731608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event)
2732608bcc6dSMat Martineau {
2733608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2734608bcc6dSMat Martineau event);
2735608bcc6dSMat Martineau
2736608bcc6dSMat Martineau switch (event) {
2737608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST:
2738608bcc6dSMat Martineau if (chan->tx_send_head == NULL)
2739608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs);
2740608bcc6dSMat Martineau
2741608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q);
2742608bcc6dSMat Martineau l2cap_ertm_send(chan);
2743608bcc6dSMat Martineau break;
2744608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED:
2745608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY");
2746608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2747608bcc6dSMat Martineau
2748608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2749608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to
2750608bcc6dSMat Martineau * enter the LOCAL_BUSY state.
2751608bcc6dSMat Martineau */
2752608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan);
2753608bcc6dSMat Martineau }
2754608bcc6dSMat Martineau
2755608bcc6dSMat Martineau l2cap_send_ack(chan);
2756608bcc6dSMat Martineau
2757608bcc6dSMat Martineau break;
2758608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR:
2759608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY");
2760608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2761608bcc6dSMat Martineau
2762608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2763608bcc6dSMat Martineau struct l2cap_ctrl local_control;
2764608bcc6dSMat Martineau
2765608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control));
2766608bcc6dSMat Martineau local_control.sframe = 1;
2767608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR;
2768608bcc6dSMat Martineau local_control.poll = 1;
2769608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq;
2770a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control);
2771608bcc6dSMat Martineau
2772608bcc6dSMat Martineau chan->retry_count = 1;
2773608bcc6dSMat Martineau __set_monitor_timer(chan);
2774608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2775608bcc6dSMat Martineau }
2776608bcc6dSMat Martineau break;
2777608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2778608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq);
2779608bcc6dSMat Martineau break;
2780608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL:
2781608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1);
2782608bcc6dSMat Martineau chan->retry_count = 1;
2783608bcc6dSMat Martineau __set_monitor_timer(chan);
2784608bcc6dSMat Martineau __clear_ack_timer(chan);
2785608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2786608bcc6dSMat Martineau break;
2787608bcc6dSMat Martineau case L2CAP_EV_RETRANS_TO:
2788608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1);
2789608bcc6dSMat Martineau chan->retry_count = 1;
2790608bcc6dSMat Martineau __set_monitor_timer(chan);
2791608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2792608bcc6dSMat Martineau break;
2793608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT:
2794608bcc6dSMat Martineau /* Nothing to process */
2795608bcc6dSMat Martineau break;
2796608bcc6dSMat Martineau default:
2797608bcc6dSMat Martineau break;
2798608bcc6dSMat Martineau }
2799608bcc6dSMat Martineau }
2800608bcc6dSMat Martineau
2801d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan,
l2cap_tx_state_wait_f(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff_head * skbs,u8 event)2802608bcc6dSMat Martineau struct l2cap_ctrl *control,
2803608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event)
2804608bcc6dSMat Martineau {
2805608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2806608bcc6dSMat Martineau event);
2807608bcc6dSMat Martineau
2808608bcc6dSMat Martineau switch (event) {
2809608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST:
2810608bcc6dSMat Martineau if (chan->tx_send_head == NULL)
2811608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs);
2812608bcc6dSMat Martineau /* Queue data, but don't send. */
2813608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q);
2814608bcc6dSMat Martineau break;
2815608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED:
2816608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY");
2817608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2818608bcc6dSMat Martineau
2819608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2820608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to
2821608bcc6dSMat Martineau * enter the LOCAL_BUSY state.
2822608bcc6dSMat Martineau */
2823608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan);
2824608bcc6dSMat Martineau }
2825608bcc6dSMat Martineau
2826608bcc6dSMat Martineau l2cap_send_ack(chan);
2827608bcc6dSMat Martineau
2828608bcc6dSMat Martineau break;
2829608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR:
2830608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY");
2831608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2832608bcc6dSMat Martineau
2833608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2834608bcc6dSMat Martineau struct l2cap_ctrl local_control;
2835608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control));
2836608bcc6dSMat Martineau local_control.sframe = 1;
2837608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR;
2838608bcc6dSMat Martineau local_control.poll = 1;
2839608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq;
2840a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control);
2841608bcc6dSMat Martineau
2842608bcc6dSMat Martineau chan->retry_count = 1;
2843608bcc6dSMat Martineau __set_monitor_timer(chan);
2844608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2845608bcc6dSMat Martineau }
2846608bcc6dSMat Martineau break;
2847608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2848608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq);
284919186c7bSGustavo A. R. Silva fallthrough;
2850608bcc6dSMat Martineau
2851608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT:
2852608bcc6dSMat Martineau if (control && control->final) {
2853608bcc6dSMat Martineau __clear_monitor_timer(chan);
2854608bcc6dSMat Martineau if (chan->unacked_frames > 0)
2855608bcc6dSMat Martineau __set_retrans_timer(chan);
2856608bcc6dSMat Martineau chan->retry_count = 0;
2857608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT;
2858608bcc6dSMat Martineau BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state);
2859608bcc6dSMat Martineau }
2860608bcc6dSMat Martineau break;
2861608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL:
2862608bcc6dSMat Martineau /* Ignore */
2863608bcc6dSMat Martineau break;
2864608bcc6dSMat Martineau case L2CAP_EV_MONITOR_TO:
2865608bcc6dSMat Martineau if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) {
2866608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1);
2867608bcc6dSMat Martineau __set_monitor_timer(chan);
2868608bcc6dSMat Martineau chan->retry_count++;
2869608bcc6dSMat Martineau } else {
28705e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNABORTED);
2871608bcc6dSMat Martineau }
2872608bcc6dSMat Martineau break;
2873608bcc6dSMat Martineau default:
2874608bcc6dSMat Martineau break;
2875608bcc6dSMat Martineau }
2876608bcc6dSMat Martineau }
2877608bcc6dSMat Martineau
2878d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
l2cap_tx(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff_head * skbs,u8 event)2879608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event)
2880608bcc6dSMat Martineau {
2881608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d, state %d",
2882608bcc6dSMat Martineau chan, control, skbs, event, chan->tx_state);
2883608bcc6dSMat Martineau
2884608bcc6dSMat Martineau switch (chan->tx_state) {
2885608bcc6dSMat Martineau case L2CAP_TX_STATE_XMIT:
2886d660366dSGustavo Padovan l2cap_tx_state_xmit(chan, control, skbs, event);
2887608bcc6dSMat Martineau break;
2888608bcc6dSMat Martineau case L2CAP_TX_STATE_WAIT_F:
2889d660366dSGustavo Padovan l2cap_tx_state_wait_f(chan, control, skbs, event);
2890608bcc6dSMat Martineau break;
2891608bcc6dSMat Martineau default:
2892608bcc6dSMat Martineau /* Ignore event */
2893608bcc6dSMat Martineau break;
2894608bcc6dSMat Martineau }
2895608bcc6dSMat Martineau }
2896608bcc6dSMat Martineau
28974b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan,
l2cap_pass_to_tx(struct l2cap_chan * chan,struct l2cap_ctrl * control)28984b51dae9SMat Martineau struct l2cap_ctrl *control)
28994b51dae9SMat Martineau {
29004b51dae9SMat Martineau BT_DBG("chan %p, control %p", chan, control);
2901401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT);
29024b51dae9SMat Martineau }
29034b51dae9SMat Martineau
2904f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan,
l2cap_pass_to_tx_fbit(struct l2cap_chan * chan,struct l2cap_ctrl * control)2905f80842a8SMat Martineau struct l2cap_ctrl *control)
2906f80842a8SMat Martineau {
2907f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control);
2908401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT);
2909f80842a8SMat Martineau }
2910f80842a8SMat Martineau
29110a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */
29120a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
l2cap_raw_recv(struct l2cap_conn * conn,struct sk_buff * skb)29130a708f8fSGustavo F. Padovan {
29140a708f8fSGustavo F. Padovan struct sk_buff *nskb;
291548454079SGustavo F. Padovan struct l2cap_chan *chan;
29160a708f8fSGustavo F. Padovan
29170a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn);
29180a708f8fSGustavo F. Padovan
29193df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) {
2920715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW)
29210a708f8fSGustavo F. Padovan continue;
29220a708f8fSGustavo F. Padovan
29237f5396a7SGustavo Padovan /* Don't send frame to the channel it came from */
2924a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.chan == chan)
29250a708f8fSGustavo F. Padovan continue;
29267f5396a7SGustavo Padovan
29278bcde1f2SGustavo Padovan nskb = skb_clone(skb, GFP_KERNEL);
29280a708f8fSGustavo F. Padovan if (!nskb)
29290a708f8fSGustavo F. Padovan continue;
293080b98027SGustavo Padovan if (chan->ops->recv(chan, nskb))
29310a708f8fSGustavo F. Padovan kfree_skb(nskb);
29320a708f8fSGustavo F. Padovan }
29330a708f8fSGustavo F. Padovan }
29340a708f8fSGustavo F. Padovan
29350a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
2936b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
2937b4400672SAndrei Emeltchenko u8 ident, u16 dlen, void *data)
29380a708f8fSGustavo F. Padovan {
29390a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag;
29400a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd;
l2cap_build_cmd(struct l2cap_conn * conn,u8 code,u8 ident,u16 dlen,void * data)29410a708f8fSGustavo F. Padovan struct l2cap_hdr *lh;
29420a708f8fSGustavo F. Padovan int len, count;
29430a708f8fSGustavo F. Padovan
2944b4400672SAndrei Emeltchenko BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u",
29450a708f8fSGustavo F. Padovan conn, code, ident, dlen);
29460a708f8fSGustavo F. Padovan
2947300b962eSAnderson Lizardo if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE)
2948300b962eSAnderson Lizardo return NULL;
2949300b962eSAnderson Lizardo
29500a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
29510a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len);
29520a708f8fSGustavo F. Padovan
29538bcde1f2SGustavo Padovan skb = bt_skb_alloc(count, GFP_KERNEL);
29540a708f8fSGustavo F. Padovan if (!skb)
29550a708f8fSGustavo F. Padovan return NULL;
29560a708f8fSGustavo F. Padovan
29574df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE);
29580a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
29593300d9a9SClaudio Takahasi
29603300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK)
2961dcf4adbfSJoe Perches lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
29623300d9a9SClaudio Takahasi else
2963dcf4adbfSJoe Perches lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
29640a708f8fSGustavo F. Padovan
29654df864c1SJohannes Berg cmd = skb_put(skb, L2CAP_CMD_HDR_SIZE);
29660a708f8fSGustavo F. Padovan cmd->code = code;
29670a708f8fSGustavo F. Padovan cmd->ident = ident;
29680a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen);
29690a708f8fSGustavo F. Padovan
29700a708f8fSGustavo F. Padovan if (dlen) {
29710a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
297259ae1d12SJohannes Berg skb_put_data(skb, data, count);
29730a708f8fSGustavo F. Padovan data += count;
29740a708f8fSGustavo F. Padovan }
29750a708f8fSGustavo F. Padovan
29760a708f8fSGustavo F. Padovan len -= skb->len;
29770a708f8fSGustavo F. Padovan
29780a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */
29790a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list;
29800a708f8fSGustavo F. Padovan while (len) {
29810a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len);
29820a708f8fSGustavo F. Padovan
29838bcde1f2SGustavo Padovan *frag = bt_skb_alloc(count, GFP_KERNEL);
29840a708f8fSGustavo F. Padovan if (!*frag)
29850a708f8fSGustavo F. Padovan goto fail;
29860a708f8fSGustavo F. Padovan
298759ae1d12SJohannes Berg skb_put_data(*frag, data, count);
29880a708f8fSGustavo F. Padovan
29890a708f8fSGustavo F. Padovan len -= count;
29900a708f8fSGustavo F. Padovan data += count;
29910a708f8fSGustavo F. Padovan
29920a708f8fSGustavo F. Padovan frag = &(*frag)->next;
29930a708f8fSGustavo F. Padovan }
29940a708f8fSGustavo F. Padovan
29950a708f8fSGustavo F. Padovan return skb;
29960a708f8fSGustavo F. Padovan
29970a708f8fSGustavo F. Padovan fail:
29980a708f8fSGustavo F. Padovan kfree_skb(skb);
29990a708f8fSGustavo F. Padovan return NULL;
30000a708f8fSGustavo F. Padovan }
30010a708f8fSGustavo F. Padovan
30022d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen,
30032d792818SGustavo Padovan unsigned long *val)
30040a708f8fSGustavo F. Padovan {
30050a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr;
30060a708f8fSGustavo F. Padovan int len;
l2cap_get_conf_opt(void ** ptr,int * type,int * olen,unsigned long * val)30070a708f8fSGustavo F. Padovan
30080a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len;
30090a708f8fSGustavo F. Padovan *ptr += len;
30100a708f8fSGustavo F. Padovan
30110a708f8fSGustavo F. Padovan *type = opt->type;
30120a708f8fSGustavo F. Padovan *olen = opt->len;
30130a708f8fSGustavo F. Padovan
30140a708f8fSGustavo F. Padovan switch (opt->len) {
30150a708f8fSGustavo F. Padovan case 1:
30160a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val);
30170a708f8fSGustavo F. Padovan break;
30180a708f8fSGustavo F. Padovan
30190a708f8fSGustavo F. Padovan case 2:
30200a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val);
30210a708f8fSGustavo F. Padovan break;
30220a708f8fSGustavo F. Padovan
30230a708f8fSGustavo F. Padovan case 4:
30240a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val);
30250a708f8fSGustavo F. Padovan break;
30260a708f8fSGustavo F. Padovan
30270a708f8fSGustavo F. Padovan default:
30280a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val;
30290a708f8fSGustavo F. Padovan break;
30300a708f8fSGustavo F. Padovan }
30310a708f8fSGustavo F. Padovan
3032b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val);
30330a708f8fSGustavo F. Padovan return len;
30340a708f8fSGustavo F. Padovan }
30350a708f8fSGustavo F. Padovan
3036e860d2c9SBen Seri static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size)
30370a708f8fSGustavo F. Padovan {
30380a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr;
30390a708f8fSGustavo F. Padovan
3040b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val);
l2cap_add_conf_opt(void ** ptr,u8 type,u8 len,unsigned long val,size_t size)30410a708f8fSGustavo F. Padovan
3042e860d2c9SBen Seri if (size < L2CAP_CONF_OPT_SIZE + len)
3043e860d2c9SBen Seri return;
3044e860d2c9SBen Seri
30450a708f8fSGustavo F. Padovan opt->type = type;
30460a708f8fSGustavo F. Padovan opt->len = len;
30470a708f8fSGustavo F. Padovan
30480a708f8fSGustavo F. Padovan switch (len) {
30490a708f8fSGustavo F. Padovan case 1:
30500a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val;
30510a708f8fSGustavo F. Padovan break;
30520a708f8fSGustavo F. Padovan
30530a708f8fSGustavo F. Padovan case 2:
30540a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val);
30550a708f8fSGustavo F. Padovan break;
30560a708f8fSGustavo F. Padovan
30570a708f8fSGustavo F. Padovan case 4:
30580a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val);
30590a708f8fSGustavo F. Padovan break;
30600a708f8fSGustavo F. Padovan
30610a708f8fSGustavo F. Padovan default:
30620a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len);
30630a708f8fSGustavo F. Padovan break;
30640a708f8fSGustavo F. Padovan }
30650a708f8fSGustavo F. Padovan
30660a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len;
30670a708f8fSGustavo F. Padovan }
30680a708f8fSGustavo F. Padovan
3069e860d2c9SBen Seri static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan, size_t size)
3070f89cef09SAndrei Emeltchenko {
3071f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs;
3072f89cef09SAndrei Emeltchenko
3073f89cef09SAndrei Emeltchenko switch (chan->mode) {
l2cap_add_opt_efs(void ** ptr,struct l2cap_chan * chan,size_t size)3074f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM:
3075f89cef09SAndrei Emeltchenko efs.id = chan->local_id;
3076f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype;
3077f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu);
3078f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
3079dcf4adbfSJoe Perches efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
3080dcf4adbfSJoe Perches efs.flush_to = cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO);
3081f89cef09SAndrei Emeltchenko break;
3082f89cef09SAndrei Emeltchenko
3083f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING:
3084f89cef09SAndrei Emeltchenko efs.id = 1;
3085f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT;
3086f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu);
3087f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
3088f89cef09SAndrei Emeltchenko efs.acc_lat = 0;
3089f89cef09SAndrei Emeltchenko efs.flush_to = 0;
3090f89cef09SAndrei Emeltchenko break;
3091f89cef09SAndrei Emeltchenko
3092f89cef09SAndrei Emeltchenko default:
3093f89cef09SAndrei Emeltchenko return;
3094f89cef09SAndrei Emeltchenko }
3095f89cef09SAndrei Emeltchenko
3096f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
3097e860d2c9SBen Seri (unsigned long) &efs, size);
3098f89cef09SAndrei Emeltchenko }
3099f89cef09SAndrei Emeltchenko
3100721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
31010a708f8fSGustavo F. Padovan {
3102721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
3103721c4181SGustavo F. Padovan ack_timer.work);
31040362520bSMat Martineau u16 frames_to_ack;
l2cap_ack_timeout(struct work_struct * work)31050a708f8fSGustavo F. Padovan
31062fb9b3d4SGustavo F. Padovan BT_DBG("chan %p", chan);
31072fb9b3d4SGustavo F. Padovan
31086be36555SAndrei Emeltchenko l2cap_chan_lock(chan);
31096be36555SAndrei Emeltchenko
31100362520bSMat Martineau frames_to_ack = __seq_offset(chan, chan->buffer_seq,
31110362520bSMat Martineau chan->last_acked_seq);
31120362520bSMat Martineau
31130362520bSMat Martineau if (frames_to_ack)
31140362520bSMat Martineau l2cap_send_rr_or_rnr(chan, 0);
31156be36555SAndrei Emeltchenko
31166be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
311709bfb2eeSSzymon Janc l2cap_chan_put(chan);
31180a708f8fSGustavo F. Padovan }
31190a708f8fSGustavo F. Padovan
3120466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan)
31210a708f8fSGustavo F. Padovan {
31223c588192SMat Martineau int err;
31233c588192SMat Martineau
3124105bdf9eSMat Martineau chan->next_tx_seq = 0;
l2cap_ertm_init(struct l2cap_chan * chan)3125105bdf9eSMat Martineau chan->expected_tx_seq = 0;
312642e5c802SGustavo F. Padovan chan->expected_ack_seq = 0;
31276a026610SGustavo F. Padovan chan->unacked_frames = 0;
312842e5c802SGustavo F. Padovan chan->buffer_seq = 0;
31296a026610SGustavo F. Padovan chan->frames_sent = 0;
3130105bdf9eSMat Martineau chan->last_acked_seq = 0;
3131105bdf9eSMat Martineau chan->sdu = NULL;
3132105bdf9eSMat Martineau chan->sdu_last_frag = NULL;
3133105bdf9eSMat Martineau chan->sdu_len = 0;
3134105bdf9eSMat Martineau
3135d34c34fbSMat Martineau skb_queue_head_init(&chan->tx_q);
3136d34c34fbSMat Martineau
3137105bdf9eSMat Martineau if (chan->mode != L2CAP_MODE_ERTM)
3138105bdf9eSMat Martineau return 0;
3139105bdf9eSMat Martineau
3140105bdf9eSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV;
3141105bdf9eSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT;
31420a708f8fSGustavo F. Padovan
3143f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q);
31440a708f8fSGustavo F. Padovan
31453c588192SMat Martineau err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
31463c588192SMat Martineau if (err < 0)
31473c588192SMat Martineau return err;
31483c588192SMat Martineau
31499dc9affcSMat Martineau err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
31509dc9affcSMat Martineau if (err < 0)
31519dc9affcSMat Martineau l2cap_seq_list_free(&chan->srej_list);
31529dc9affcSMat Martineau
31539dc9affcSMat Martineau return err;
31540a708f8fSGustavo F. Padovan }
31550a708f8fSGustavo F. Padovan
31560a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
31570a708f8fSGustavo F. Padovan {
31580a708f8fSGustavo F. Padovan switch (mode) {
31590a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING:
31600a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM:
l2cap_select_mode(__u8 mode,__u16 remote_feat_mask)31610a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask))
31620a708f8fSGustavo F. Padovan return mode;
316319186c7bSGustavo A. R. Silva fallthrough;
31640a708f8fSGustavo F. Padovan default:
31650a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC;
31660a708f8fSGustavo F. Padovan }
31670a708f8fSGustavo F. Padovan }
31680a708f8fSGustavo F. Padovan
3169848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn)
31706327eb98SAndrei Emeltchenko {
3171cd5d26a9SLuiz Augusto von Dentz return (conn->feat_mask & L2CAP_FEAT_EXT_WINDOW);
31726327eb98SAndrei Emeltchenko }
31736327eb98SAndrei Emeltchenko
__l2cap_ews_supported(struct l2cap_conn * conn)3174848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn)
3175f89cef09SAndrei Emeltchenko {
3176cd5d26a9SLuiz Augusto von Dentz return (conn->feat_mask & L2CAP_FEAT_EXT_FLOW);
3177f89cef09SAndrei Emeltchenko }
3178f89cef09SAndrei Emeltchenko
__l2cap_efs_supported(struct l2cap_conn * conn)317936c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
318036c86c85SMat Martineau struct l2cap_conf_rfc *rfc)
318136c86c85SMat Martineau {
3182dcf4adbfSJoe Perches rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
3183dcf4adbfSJoe Perches rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
318436c86c85SMat Martineau }
318536c86c85SMat Martineau
31866327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
31876327eb98SAndrei Emeltchenko {
31886327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
3189848566b3SMarcel Holtmann __l2cap_ews_supported(chan->conn)) {
31906327eb98SAndrei Emeltchenko /* use extended control field */
l2cap_txwin_setup(struct l2cap_chan * chan)31916327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags);
3192836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
3193836be934SAndrei Emeltchenko } else {
31946327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win,
31956327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW);
3196836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
3197836be934SAndrei Emeltchenko }
3198c20f8e35SMat Martineau chan->ack_win = chan->tx_win;
31996327eb98SAndrei Emeltchenko }
32006327eb98SAndrei Emeltchenko
32014b6e228eSLuiz Augusto von Dentz static void l2cap_mtu_auto(struct l2cap_chan *chan)
32024b6e228eSLuiz Augusto von Dentz {
32034b6e228eSLuiz Augusto von Dentz struct hci_conn *conn = chan->conn->hcon;
32044b6e228eSLuiz Augusto von Dentz
32054b6e228eSLuiz Augusto von Dentz chan->imtu = L2CAP_DEFAULT_MIN_MTU;
l2cap_mtu_auto(struct l2cap_chan * chan)32064b6e228eSLuiz Augusto von Dentz
32074b6e228eSLuiz Augusto von Dentz /* The 2-DH1 packet has between 2 and 56 information bytes
32084b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header)
32094b6e228eSLuiz Augusto von Dentz */
32104b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_2DH1))
32114b6e228eSLuiz Augusto von Dentz chan->imtu = 54;
32124b6e228eSLuiz Augusto von Dentz
32134b6e228eSLuiz Augusto von Dentz /* The 3-DH1 packet has between 2 and 85 information bytes
32144b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header)
32154b6e228eSLuiz Augusto von Dentz */
32164b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_3DH1))
32174b6e228eSLuiz Augusto von Dentz chan->imtu = 83;
32184b6e228eSLuiz Augusto von Dentz
32194b6e228eSLuiz Augusto von Dentz /* The 2-DH3 packet has between 2 and 369 information bytes
32204b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header)
32214b6e228eSLuiz Augusto von Dentz */
32224b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_2DH3))
32234b6e228eSLuiz Augusto von Dentz chan->imtu = 367;
32244b6e228eSLuiz Augusto von Dentz
32254b6e228eSLuiz Augusto von Dentz /* The 3-DH3 packet has between 2 and 554 information bytes
32264b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header)
32274b6e228eSLuiz Augusto von Dentz */
32284b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_3DH3))
32294b6e228eSLuiz Augusto von Dentz chan->imtu = 552;
32304b6e228eSLuiz Augusto von Dentz
32314b6e228eSLuiz Augusto von Dentz /* The 2-DH5 packet has between 2 and 681 information bytes
32324b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header)
32334b6e228eSLuiz Augusto von Dentz */
32344b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_2DH5))
32354b6e228eSLuiz Augusto von Dentz chan->imtu = 679;
32364b6e228eSLuiz Augusto von Dentz
32374b6e228eSLuiz Augusto von Dentz /* The 3-DH5 packet has between 2 and 1023 information bytes
32384b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header)
32394b6e228eSLuiz Augusto von Dentz */
32404b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_3DH5))
32414b6e228eSLuiz Augusto von Dentz chan->imtu = 1021;
32424b6e228eSLuiz Augusto von Dentz }
32434b6e228eSLuiz Augusto von Dentz
3244e860d2c9SBen Seri static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
32450a708f8fSGustavo F. Padovan {
32460a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data;
32470c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode };
32480a708f8fSGustavo F. Padovan void *ptr = req->data;
l2cap_build_conf_req(struct l2cap_chan * chan,void * data,size_t data_size)3249e860d2c9SBen Seri void *endptr = data + data_size;
3250c8f79162SAndrei Emeltchenko u16 size;
32510a708f8fSGustavo F. Padovan
325249208c9cSGustavo F. Padovan BT_DBG("chan %p", chan);
32530a708f8fSGustavo F. Padovan
325473ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp)
32550a708f8fSGustavo F. Padovan goto done;
32560a708f8fSGustavo F. Padovan
32570c1bc5c6SGustavo F. Padovan switch (chan->mode) {
32580a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING:
32590a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM:
3260c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
32610a708f8fSGustavo F. Padovan break;
32620a708f8fSGustavo F. Padovan
3263848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn))
3264f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags);
3265f89cef09SAndrei Emeltchenko
326619186c7bSGustavo A. R. Silva fallthrough;
32670a708f8fSGustavo F. Padovan default:
32688c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
32690a708f8fSGustavo F. Padovan break;
32700a708f8fSGustavo F. Padovan }
32710a708f8fSGustavo F. Padovan
32720a708f8fSGustavo F. Padovan done:
32734b6e228eSLuiz Augusto von Dentz if (chan->imtu != L2CAP_DEFAULT_MTU) {
32744b6e228eSLuiz Augusto von Dentz if (!chan->imtu)
32754b6e228eSLuiz Augusto von Dentz l2cap_mtu_auto(chan);
32764b6e228eSLuiz Augusto von Dentz l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu,
32774b6e228eSLuiz Augusto von Dentz endptr - ptr);
32784b6e228eSLuiz Augusto von Dentz }
32790a708f8fSGustavo F. Padovan
32800c1bc5c6SGustavo F. Padovan switch (chan->mode) {
32810a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC:
32826fea7ad1SMarcel Holtmann if (disable_ertm)
32836fea7ad1SMarcel Holtmann break;
32846fea7ad1SMarcel Holtmann
32858c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
32868c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
32870a708f8fSGustavo F. Padovan break;
32880a708f8fSGustavo F. Padovan
32890a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC;
32900a708f8fSGustavo F. Padovan rfc.txwin_size = 0;
32910a708f8fSGustavo F. Padovan rfc.max_transmit = 0;
32920a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0;
32930a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0;
32940a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0;
32950a708f8fSGustavo F. Padovan
32960a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3297e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr);
32980a708f8fSGustavo F. Padovan break;
32990a708f8fSGustavo F. Padovan
33000a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM:
33010a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM;
330247d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx;
330336c86c85SMat Martineau
330436c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc);
3305c8f79162SAndrei Emeltchenko
3306c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
33072d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3308c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE);
3309c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size);
33100a708f8fSGustavo F. Padovan
33116327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan);
33126327eb98SAndrei Emeltchenko
33136327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win,
33146327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW);
33150a708f8fSGustavo F. Padovan
33160a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3317e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr);
33180a708f8fSGustavo F. Padovan
3319f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3320e860d2c9SBen Seri l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
3321f89cef09SAndrei Emeltchenko
33226327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags))
33236327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
3324e860d2c9SBen Seri chan->tx_win, endptr - ptr);
332560918918SAndrei Emeltchenko
332660918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
332760918918SAndrei Emeltchenko if (chan->fcs == L2CAP_FCS_NONE ||
3328f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
332960918918SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE;
333060918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
3331e860d2c9SBen Seri chan->fcs, endptr - ptr);
333260918918SAndrei Emeltchenko }
33330a708f8fSGustavo F. Padovan break;
33340a708f8fSGustavo F. Padovan
33350a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING:
3336273759e2SMat Martineau l2cap_txwin_setup(chan);
33370a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING;
33380a708f8fSGustavo F. Padovan rfc.txwin_size = 0;
33390a708f8fSGustavo F. Padovan rfc.max_transmit = 0;
33400a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0;
33410a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0;
3342c8f79162SAndrei Emeltchenko
3343c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
33442d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3345c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE);
3346c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size);
33470a708f8fSGustavo F. Padovan
33480a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3349e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr);
33500a708f8fSGustavo F. Padovan
3351f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3352e860d2c9SBen Seri l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
3353f89cef09SAndrei Emeltchenko
335460918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
335547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE ||
3356f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
335747d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE;
335860918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
3359e860d2c9SBen Seri chan->fcs, endptr - ptr);
33600a708f8fSGustavo F. Padovan }
33610a708f8fSGustavo F. Padovan break;
33620a708f8fSGustavo F. Padovan }
33630a708f8fSGustavo F. Padovan
3364fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid);
3365dcf4adbfSJoe Perches req->flags = cpu_to_le16(0);
33660a708f8fSGustavo F. Padovan
33670a708f8fSGustavo F. Padovan return ptr - data;
33680a708f8fSGustavo F. Padovan }
33690a708f8fSGustavo F. Padovan
3370e860d2c9SBen Seri static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
33710a708f8fSGustavo F. Padovan {
33720a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data;
33730a708f8fSGustavo F. Padovan void *ptr = rsp->data;
3374e860d2c9SBen Seri void *endptr = data + data_size;
l2cap_parse_conf_req(struct l2cap_chan * chan,void * data,size_t data_size)337573ffa904SGustavo F. Padovan void *req = chan->conf_req;
337673ffa904SGustavo F. Padovan int len = chan->conf_len;
33770a708f8fSGustavo F. Padovan int type, hint, olen;
33780a708f8fSGustavo F. Padovan unsigned long val;
33790a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
338042dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs;
338142dceae2SAndrei Emeltchenko u8 remote_efs = 0;
33820a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU;
33830a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS;
3384c8f79162SAndrei Emeltchenko u16 size;
33850a708f8fSGustavo F. Padovan
338673ffa904SGustavo F. Padovan BT_DBG("chan %p", chan);
33870a708f8fSGustavo F. Padovan
33880a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) {
33890a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
33907c9cbd0bSMarcel Holtmann if (len < 0)
33917c9cbd0bSMarcel Holtmann break;
33920a708f8fSGustavo F. Padovan
33930a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT;
33940a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK;
33950a708f8fSGustavo F. Padovan
33960a708f8fSGustavo F. Padovan switch (type) {
33970a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU:
3398af3d5d1cSMarcel Holtmann if (olen != 2)
3399af3d5d1cSMarcel Holtmann break;
34000a708f8fSGustavo F. Padovan mtu = val;
34010a708f8fSGustavo F. Padovan break;
34020a708f8fSGustavo F. Padovan
34030a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO:
3404af3d5d1cSMarcel Holtmann if (olen != 2)
3405af3d5d1cSMarcel Holtmann break;
34060c1bc5c6SGustavo F. Padovan chan->flush_to = val;
34070a708f8fSGustavo F. Padovan break;
34080a708f8fSGustavo F. Padovan
34090a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS:
34100a708f8fSGustavo F. Padovan break;
34110a708f8fSGustavo F. Padovan
34120a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC:
3413af3d5d1cSMarcel Holtmann if (olen != sizeof(rfc))
3414af3d5d1cSMarcel Holtmann break;
34150a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen);
34160a708f8fSGustavo F. Padovan break;
34170a708f8fSGustavo F. Padovan
34180a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS:
3419af3d5d1cSMarcel Holtmann if (olen != 1)
3420af3d5d1cSMarcel Holtmann break;
34210a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE)
3422f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, &chan->conf_state);
342342dceae2SAndrei Emeltchenko break;
34240a708f8fSGustavo F. Padovan
342542dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS:
3426af3d5d1cSMarcel Holtmann if (olen != sizeof(efs))
3427af3d5d1cSMarcel Holtmann break;
342842dceae2SAndrei Emeltchenko remote_efs = 1;
342942dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen);
34300a708f8fSGustavo F. Padovan break;
34310a708f8fSGustavo F. Padovan
34326327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS:
3433af3d5d1cSMarcel Holtmann if (olen != 2)
3434af3d5d1cSMarcel Holtmann break;
34356327eb98SAndrei Emeltchenko return -ECONNREFUSED;
34360a708f8fSGustavo F. Padovan
34370a708f8fSGustavo F. Padovan default:
34380a708f8fSGustavo F. Padovan if (hint)
34390a708f8fSGustavo F. Padovan break;
34400a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN;
34415b8ec15dSJimmy Wahlberg l2cap_add_conf_opt(&ptr, (u8)type, sizeof(u8), type, endptr - ptr);
34420a708f8fSGustavo F. Padovan break;
34430a708f8fSGustavo F. Padovan }
34440a708f8fSGustavo F. Padovan }
34450a708f8fSGustavo F. Padovan
344673ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1)
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)) {
34530c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode,
34548c1d787bSGustavo F. Padovan chan->conn->feat_mask);
34550a708f8fSGustavo F. Padovan break;
34560a708f8fSGustavo F. Padovan }
34570a708f8fSGustavo F. Padovan
345842dceae2SAndrei Emeltchenko if (remote_efs) {
3459848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn))
346042dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags);
346142dceae2SAndrei Emeltchenko else
346242dceae2SAndrei Emeltchenko return -ECONNREFUSED;
346342dceae2SAndrei Emeltchenko }
346442dceae2SAndrei Emeltchenko
34650c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode)
34660a708f8fSGustavo F. Padovan return -ECONNREFUSED;
34670a708f8fSGustavo F. Padovan
34680a708f8fSGustavo F. Padovan break;
34690a708f8fSGustavo F. Padovan }
34700a708f8fSGustavo F. Padovan
34710a708f8fSGustavo F. Padovan done:
34720c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) {
34730a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT;
34740c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode;
34750a708f8fSGustavo F. Padovan
347673ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1)
34770a708f8fSGustavo F. Padovan return -ECONNREFUSED;
34780a708f8fSGustavo F. Padovan
34792d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3480e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr);
34810a708f8fSGustavo F. Padovan }
34820a708f8fSGustavo F. Padovan
34830a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) {
34840a708f8fSGustavo F. Padovan /* Configure output options and let the other side know
34850a708f8fSGustavo F. Padovan * which ones we don't like. */
34860a708f8fSGustavo F. Padovan
34870a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU)
34880a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT;
34890a708f8fSGustavo F. Padovan else {
34900c1bc5c6SGustavo F. Padovan chan->omtu = mtu;
3491c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state);
34920a708f8fSGustavo F. Padovan }
3493e860d2c9SBen Seri l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu, endptr - ptr);
34940a708f8fSGustavo F. Padovan
349542dceae2SAndrei Emeltchenko if (remote_efs) {
349642dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
349742dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC &&
349842dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) {
349942dceae2SAndrei Emeltchenko
350042dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT;
350142dceae2SAndrei Emeltchenko
350242dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1)
350342dceae2SAndrei Emeltchenko return -ECONNREFUSED;
350442dceae2SAndrei Emeltchenko
350542dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
350642dceae2SAndrei Emeltchenko sizeof(efs),
3507e860d2c9SBen Seri (unsigned long) &efs, endptr - ptr);
35080e8b207eSAndrei Emeltchenko } else {
35093e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */
35100e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING;
35110e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
351242dceae2SAndrei Emeltchenko }
351342dceae2SAndrei Emeltchenko }
351442dceae2SAndrei Emeltchenko
35150a708f8fSGustavo F. Padovan switch (rfc.mode) {
35160a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC:
351747d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE;
3518c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state);
35190a708f8fSGustavo F. Padovan break;
35200a708f8fSGustavo F. Padovan
35210a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM:
35226327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
35232c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size;
35246327eb98SAndrei Emeltchenko else
35256327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
35266327eb98SAndrei Emeltchenko
35272c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit;
35280a708f8fSGustavo F. Padovan
3529c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
35302d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
35312d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3532c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size);
3533c8f79162SAndrei Emeltchenko chan->remote_mps = size;
35340a708f8fSGustavo F. Padovan
353536c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc);
35360a708f8fSGustavo F. Padovan
3537c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state);
35380a708f8fSGustavo F. Padovan
35390a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
3540e860d2c9SBen Seri sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
35410a708f8fSGustavo F. Padovan
3542b1a2cd50SLuiz Augusto von Dentz if (remote_efs &&
3543b1a2cd50SLuiz Augusto von Dentz test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
354442dceae2SAndrei Emeltchenko chan->remote_id = efs.id;
354542dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype;
354642dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu);
354742dceae2SAndrei Emeltchenko chan->remote_flush_to =
354842dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to);
354942dceae2SAndrei Emeltchenko chan->remote_acc_lat =
355042dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat);
355142dceae2SAndrei Emeltchenko chan->remote_sdu_itime =
355242dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime);
355342dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
35542d792818SGustavo Padovan sizeof(efs),
3555e860d2c9SBen Seri (unsigned long) &efs, endptr - ptr);
355642dceae2SAndrei Emeltchenko }
35570a708f8fSGustavo F. Padovan break;
35580a708f8fSGustavo F. Padovan
35590a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING:
3560c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
35612d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
35622d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3563c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size);
3564c8f79162SAndrei Emeltchenko chan->remote_mps = size;
35650a708f8fSGustavo F. Padovan
3566c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state);
35670a708f8fSGustavo F. Padovan
35682d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3569e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr);
35700a708f8fSGustavo F. Padovan
35710a708f8fSGustavo F. Padovan break;
35720a708f8fSGustavo F. Padovan
35730a708f8fSGustavo F. Padovan default:
35740a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT;
35750a708f8fSGustavo F. Padovan
35760a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc));
35770c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode;
35780a708f8fSGustavo F. Padovan }
35790a708f8fSGustavo F. Padovan
35800a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS)
3581c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
35820a708f8fSGustavo F. Padovan }
3583fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid);
35840a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result);
3585dcf4adbfSJoe Perches rsp->flags = cpu_to_le16(0);
35860a708f8fSGustavo F. Padovan
35870a708f8fSGustavo F. Padovan return ptr - data;
35880a708f8fSGustavo F. Padovan }
35890a708f8fSGustavo F. Padovan
35902d792818SGustavo Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
3591e860d2c9SBen Seri void *data, size_t size, u16 *result)
35920a708f8fSGustavo F. Padovan {
35930a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data;
35940a708f8fSGustavo F. Padovan void *ptr = req->data;
l2cap_parse_conf_rsp(struct l2cap_chan * chan,void * rsp,int len,void * data,size_t size,u16 * result)3595e860d2c9SBen Seri void *endptr = data + size;
35960a708f8fSGustavo F. Padovan int type, olen;
35970a708f8fSGustavo F. Padovan unsigned long val;
359836e999a8SMat Martineau struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
359966af7aafSAndrei Emeltchenko struct l2cap_conf_efs efs;
36000a708f8fSGustavo F. Padovan
3601fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
36020a708f8fSGustavo F. Padovan
36030a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) {
36040a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
36057c9cbd0bSMarcel Holtmann if (len < 0)
36067c9cbd0bSMarcel Holtmann break;
36070a708f8fSGustavo F. Padovan
36080a708f8fSGustavo F. Padovan switch (type) {
36090a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU:
3610af3d5d1cSMarcel Holtmann if (olen != 2)
3611af3d5d1cSMarcel Holtmann break;
36120a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) {
36130a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT;
36140c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU;
36150a708f8fSGustavo F. Padovan } else
36160c1bc5c6SGustavo F. Padovan chan->imtu = val;
3617af3d5d1cSMarcel Holtmann l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu,
3618af3d5d1cSMarcel Holtmann endptr - ptr);
36190a708f8fSGustavo F. Padovan break;
36200a708f8fSGustavo F. Padovan
36210a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO:
3622af3d5d1cSMarcel Holtmann if (olen != 2)
3623af3d5d1cSMarcel Holtmann break;
36240c1bc5c6SGustavo F. Padovan chan->flush_to = val;
3625af3d5d1cSMarcel Holtmann l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2,
3626af3d5d1cSMarcel Holtmann chan->flush_to, endptr - ptr);
36270a708f8fSGustavo F. Padovan break;
36280a708f8fSGustavo F. Padovan
36290a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC:
3630af3d5d1cSMarcel Holtmann if (olen != sizeof(rfc))
3631af3d5d1cSMarcel Holtmann break;
36320a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen);
3633c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
36340c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode)
36350a708f8fSGustavo F. Padovan return -ECONNREFUSED;
363647d1ec61SGustavo F. Padovan chan->fcs = 0;
3637af3d5d1cSMarcel Holtmann l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3638af3d5d1cSMarcel Holtmann (unsigned long) &rfc, endptr - ptr);
36390a708f8fSGustavo F. Padovan break;
36406327eb98SAndrei Emeltchenko
36416327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS:
3642af3d5d1cSMarcel Holtmann if (olen != 2)
3643af3d5d1cSMarcel Holtmann break;
3644c20f8e35SMat Martineau chan->ack_win = min_t(u16, val, chan->ack_win);
36453e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
3646e860d2c9SBen Seri chan->tx_win, endptr - ptr);
36476327eb98SAndrei Emeltchenko break;
364866af7aafSAndrei Emeltchenko
364966af7aafSAndrei Emeltchenko case L2CAP_CONF_EFS:
3650af3d5d1cSMarcel Holtmann if (olen != sizeof(efs))
3651af3d5d1cSMarcel Holtmann break;
365266af7aafSAndrei Emeltchenko memcpy(&efs, (void *)val, olen);
365366af7aafSAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
365466af7aafSAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC &&
365566af7aafSAndrei Emeltchenko efs.stype != chan->local_stype)
365666af7aafSAndrei Emeltchenko return -ECONNREFUSED;
36572d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs),
3658e860d2c9SBen Seri (unsigned long) &efs, endptr - ptr);
365966af7aafSAndrei Emeltchenko break;
3660cbabee78SAndrei Emeltchenko
3661cbabee78SAndrei Emeltchenko case L2CAP_CONF_FCS:
3662af3d5d1cSMarcel Holtmann if (olen != 1)
3663af3d5d1cSMarcel Holtmann break;
3664cbabee78SAndrei Emeltchenko if (*result == L2CAP_CONF_PENDING)
3665cbabee78SAndrei Emeltchenko if (val == L2CAP_FCS_NONE)
3666f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS,
3667cbabee78SAndrei Emeltchenko &chan->conf_state);
3668cbabee78SAndrei Emeltchenko break;
36690a708f8fSGustavo F. Padovan }
36700a708f8fSGustavo F. Padovan }
36710a708f8fSGustavo F. Padovan
36720c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
36730a708f8fSGustavo F. Padovan return -ECONNREFUSED;
36740a708f8fSGustavo F. Padovan
36750c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode;
36760a708f8fSGustavo F. Padovan
36770e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
36780a708f8fSGustavo F. Padovan switch (rfc.mode) {
36790a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM:
368047d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
368147d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
368247d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size);
3683c20f8e35SMat Martineau if (!test_bit(FLAG_EXT_CTRL, &chan->flags))
3684c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win,
3685c20f8e35SMat Martineau rfc.txwin_size);
368666af7aafSAndrei Emeltchenko
368766af7aafSAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
368866af7aafSAndrei Emeltchenko chan->local_msdu = le16_to_cpu(efs.msdu);
368966af7aafSAndrei Emeltchenko chan->local_sdu_itime =
369066af7aafSAndrei Emeltchenko le32_to_cpu(efs.sdu_itime);
369166af7aafSAndrei Emeltchenko chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
369266af7aafSAndrei Emeltchenko chan->local_flush_to =
369366af7aafSAndrei Emeltchenko le32_to_cpu(efs.flush_to);
369466af7aafSAndrei Emeltchenko }
36950a708f8fSGustavo F. Padovan break;
369666af7aafSAndrei Emeltchenko
36970a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING:
369847d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size);
36990a708f8fSGustavo F. Padovan }
37000a708f8fSGustavo F. Padovan }
37010a708f8fSGustavo F. Padovan
3702fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid);
3703dcf4adbfSJoe Perches req->flags = cpu_to_le16(0);
37040a708f8fSGustavo F. Padovan
37050a708f8fSGustavo F. Padovan return ptr - data;
37060a708f8fSGustavo F. Padovan }
37070a708f8fSGustavo F. Padovan
37082d792818SGustavo Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data,
37092d792818SGustavo Padovan u16 result, u16 flags)
37100a708f8fSGustavo F. Padovan {
37110a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data;
37120a708f8fSGustavo F. Padovan void *ptr = rsp->data;
l2cap_build_conf_rsp(struct l2cap_chan * chan,void * data,u16 result,u16 flags)37130a708f8fSGustavo F. Padovan
3714fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan);
37150a708f8fSGustavo F. Padovan
3716fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid);
37170a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result);
37180a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags);
37190a708f8fSGustavo F. Padovan
37200a708f8fSGustavo F. Padovan return ptr - data;
37210a708f8fSGustavo F. Padovan }
37220a708f8fSGustavo F. Padovan
372327e2d4c8SJohan Hedberg void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan)
372427e2d4c8SJohan Hedberg {
372527e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp;
372627e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn;
372727e2d4c8SJohan Hedberg
__l2cap_le_connect_rsp_defer(struct l2cap_chan * chan)372827e2d4c8SJohan Hedberg BT_DBG("chan %p", chan);
372927e2d4c8SJohan Hedberg
373027e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid);
373127e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu);
37323916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps);
37330cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits);
3734571f7390SMallikarjun Phulari rsp.result = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
373527e2d4c8SJohan Hedberg
373627e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
373727e2d4c8SJohan Hedberg &rsp);
373827e2d4c8SJohan Hedberg }
373927e2d4c8SJohan Hedberg
37409aa9d947SLuiz Augusto von Dentz static void l2cap_ecred_list_defer(struct l2cap_chan *chan, void *data)
374115f02b91SLuiz Augusto von Dentz {
37429aa9d947SLuiz Augusto von Dentz int *result = data;
374315f02b91SLuiz Augusto von Dentz
37449aa9d947SLuiz Augusto von Dentz if (*result || test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
l2cap_ecred_list_defer(struct l2cap_chan * chan,void * data)374515f02b91SLuiz Augusto von Dentz return;
374615f02b91SLuiz Augusto von Dentz
37479aa9d947SLuiz Augusto von Dentz switch (chan->state) {
37489aa9d947SLuiz Augusto von Dentz case BT_CONNECT2:
37499aa9d947SLuiz Augusto von Dentz /* If channel still pending accept add to result */
37509aa9d947SLuiz Augusto von Dentz (*result)++;
37519aa9d947SLuiz Augusto von Dentz return;
37529aa9d947SLuiz Augusto von Dentz case BT_CONNECTED:
37539aa9d947SLuiz Augusto von Dentz return;
37549aa9d947SLuiz Augusto von Dentz default:
37559aa9d947SLuiz Augusto von Dentz /* If not connected or pending accept it has been refused */
37569aa9d947SLuiz Augusto von Dentz *result = -ECONNREFUSED;
37579aa9d947SLuiz Augusto von Dentz return;
37589aa9d947SLuiz Augusto von Dentz }
37599aa9d947SLuiz Augusto von Dentz }
376015f02b91SLuiz Augusto von Dentz
37619aa9d947SLuiz Augusto von Dentz struct l2cap_ecred_rsp_data {
37629aa9d947SLuiz Augusto von Dentz struct {
37639aa9d947SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp rsp;
37649aa9d947SLuiz Augusto von Dentz __le16 scid[L2CAP_ECRED_MAX_CID];
37659aa9d947SLuiz Augusto von Dentz } __packed pdu;
37669aa9d947SLuiz Augusto von Dentz int count;
37679aa9d947SLuiz Augusto von Dentz };
376815f02b91SLuiz Augusto von Dentz
37699aa9d947SLuiz Augusto von Dentz static void l2cap_ecred_rsp_defer(struct l2cap_chan *chan, void *data)
37709aa9d947SLuiz Augusto von Dentz {
37719aa9d947SLuiz Augusto von Dentz struct l2cap_ecred_rsp_data *rsp = data;
377215f02b91SLuiz Augusto von Dentz
3773fbe5582aSLuiz Augusto von Dentz /* Check if channel for outgoing connection or if it wasn't deferred
l2cap_ecred_rsp_defer(struct l2cap_chan * chan,void * data)3774fbe5582aSLuiz Augusto von Dentz * since in those cases it must be skipped.
3775fbe5582aSLuiz Augusto von Dentz */
3776fbe5582aSLuiz Augusto von Dentz if (test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags) ||
3777fbe5582aSLuiz Augusto von Dentz !test_and_clear_bit(FLAG_DEFER_SETUP, &chan->flags))
37789aa9d947SLuiz Augusto von Dentz return;
377915f02b91SLuiz Augusto von Dentz
378015f02b91SLuiz Augusto von Dentz /* Reset ident so only one response is sent */
378115f02b91SLuiz Augusto von Dentz chan->ident = 0;
378215f02b91SLuiz Augusto von Dentz
378315f02b91SLuiz Augusto von Dentz /* Include all channels pending with the same ident */
37849aa9d947SLuiz Augusto von Dentz if (!rsp->pdu.rsp.result)
37859aa9d947SLuiz Augusto von Dentz rsp->pdu.rsp.dcid[rsp->count++] = cpu_to_le16(chan->scid);
37869aa9d947SLuiz Augusto von Dentz else
37879aa9d947SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNRESET);
378815f02b91SLuiz Augusto von Dentz }
378915f02b91SLuiz Augusto von Dentz
37909aa9d947SLuiz Augusto von Dentz void __l2cap_ecred_conn_rsp_defer(struct l2cap_chan *chan)
37919aa9d947SLuiz Augusto von Dentz {
37929aa9d947SLuiz Augusto von Dentz struct l2cap_conn *conn = chan->conn;
37939aa9d947SLuiz Augusto von Dentz struct l2cap_ecred_rsp_data data;
37949aa9d947SLuiz Augusto von Dentz u16 id = chan->ident;
__l2cap_ecred_conn_rsp_defer(struct l2cap_chan * chan)37959aa9d947SLuiz Augusto von Dentz int result = 0;
379615f02b91SLuiz Augusto von Dentz
37979aa9d947SLuiz Augusto von Dentz if (!id)
37989aa9d947SLuiz Augusto von Dentz return;
37999aa9d947SLuiz Augusto von Dentz
38009aa9d947SLuiz Augusto von Dentz BT_DBG("chan %p id %d", chan, id);
38019aa9d947SLuiz Augusto von Dentz
38029aa9d947SLuiz Augusto von Dentz memset(&data, 0, sizeof(data));
38039aa9d947SLuiz Augusto von Dentz
38049aa9d947SLuiz Augusto von Dentz data.pdu.rsp.mtu = cpu_to_le16(chan->imtu);
38059aa9d947SLuiz Augusto von Dentz data.pdu.rsp.mps = cpu_to_le16(chan->mps);
38069aa9d947SLuiz Augusto von Dentz data.pdu.rsp.credits = cpu_to_le16(chan->rx_credits);
38079aa9d947SLuiz Augusto von Dentz data.pdu.rsp.result = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
38089aa9d947SLuiz Augusto von Dentz
38099aa9d947SLuiz Augusto von Dentz /* Verify that all channels are ready */
38109aa9d947SLuiz Augusto von Dentz __l2cap_chan_list_id(conn, id, l2cap_ecred_list_defer, &result);
38119aa9d947SLuiz Augusto von Dentz
38129aa9d947SLuiz Augusto von Dentz if (result > 0)
38139aa9d947SLuiz Augusto von Dentz return;
38149aa9d947SLuiz Augusto von Dentz
38159aa9d947SLuiz Augusto von Dentz if (result < 0)
38169aa9d947SLuiz Augusto von Dentz data.pdu.rsp.result = cpu_to_le16(L2CAP_CR_LE_AUTHORIZATION);
38179aa9d947SLuiz Augusto von Dentz
38189aa9d947SLuiz Augusto von Dentz /* Build response */
38199aa9d947SLuiz Augusto von Dentz __l2cap_chan_list_id(conn, id, l2cap_ecred_rsp_defer, &data);
38209aa9d947SLuiz Augusto von Dentz
38219aa9d947SLuiz Augusto von Dentz l2cap_send_cmd(conn, id, L2CAP_ECRED_CONN_RSP,
38229aa9d947SLuiz Augusto von Dentz sizeof(data.pdu.rsp) + (data.count * sizeof(__le16)),
38239aa9d947SLuiz Augusto von Dentz &data.pdu);
382415f02b91SLuiz Augusto von Dentz }
382515f02b91SLuiz Augusto von Dentz
38268c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
3827710f9b0aSGustavo F. Padovan {
3828710f9b0aSGustavo F. Padovan struct l2cap_conn_rsp rsp;
38298c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn;
3830710f9b0aSGustavo F. Padovan u8 buf[128];
__l2cap_connect_rsp_defer(struct l2cap_chan * chan)3831439f34acSAndrei Emeltchenko u8 rsp_code;
3832710f9b0aSGustavo F. Padovan
3833fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid);
3834fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid);
3835dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
3836dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
3837439f34acSAndrei Emeltchenko rsp_code = L2CAP_CONN_RSP;
3838439f34acSAndrei Emeltchenko
3839439f34acSAndrei Emeltchenko BT_DBG("chan %p rsp_code %u", chan, rsp_code);
3840439f34acSAndrei Emeltchenko
3841439f34acSAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp);
3842710f9b0aSGustavo F. Padovan
3843c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
3844710f9b0aSGustavo F. Padovan return;
3845710f9b0aSGustavo F. Padovan
3846710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3847e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
3848710f9b0aSGustavo F. Padovan chan->num_conf_req++;
3849710f9b0aSGustavo F. Padovan }
3850710f9b0aSGustavo F. Padovan
385147d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
38520a708f8fSGustavo F. Padovan {
38530a708f8fSGustavo F. Padovan int type, olen;
38540a708f8fSGustavo F. Padovan unsigned long val;
3855c20f8e35SMat Martineau /* Use sane default values in case a misbehaving remote device
l2cap_conf_rfc_get(struct l2cap_chan * chan,void * rsp,int len)3856c20f8e35SMat Martineau * did not send an RFC or extended window size option.
3857c20f8e35SMat Martineau */
3858c20f8e35SMat Martineau u16 txwin_ext = chan->ack_win;
3859c20f8e35SMat Martineau struct l2cap_conf_rfc rfc = {
3860c20f8e35SMat Martineau .mode = chan->mode,
3861dcf4adbfSJoe Perches .retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO),
3862dcf4adbfSJoe Perches .monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO),
3863c20f8e35SMat Martineau .max_pdu_size = cpu_to_le16(chan->imtu),
3864c20f8e35SMat Martineau .txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW),
3865c20f8e35SMat Martineau };
38660a708f8fSGustavo F. Padovan
386747d1ec61SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
38680a708f8fSGustavo F. Padovan
38690c1bc5c6SGustavo F. Padovan if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
38700a708f8fSGustavo F. Padovan return;
38710a708f8fSGustavo F. Padovan
38720a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) {
38730a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
38747c9cbd0bSMarcel Holtmann if (len < 0)
38757c9cbd0bSMarcel Holtmann break;
38760a708f8fSGustavo F. Padovan
3877c20f8e35SMat Martineau switch (type) {
3878c20f8e35SMat Martineau case L2CAP_CONF_RFC:
3879af3d5d1cSMarcel Holtmann if (olen != sizeof(rfc))
3880af3d5d1cSMarcel Holtmann break;
38810a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen);
3882c20f8e35SMat Martineau break;
3883c20f8e35SMat Martineau case L2CAP_CONF_EWS:
3884af3d5d1cSMarcel Holtmann if (olen != 2)
3885af3d5d1cSMarcel Holtmann break;
3886c20f8e35SMat Martineau txwin_ext = val;
3887c20f8e35SMat Martineau break;
3888c20f8e35SMat Martineau }
38890a708f8fSGustavo F. Padovan }
38900a708f8fSGustavo F. Padovan
38910a708f8fSGustavo F. Padovan switch (rfc.mode) {
38920a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM:
389347d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
389447d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
389547d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size);
3896c20f8e35SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3897c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, txwin_ext);
3898c20f8e35SMat Martineau else
3899c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win,
3900c20f8e35SMat Martineau rfc.txwin_size);
39010a708f8fSGustavo F. Padovan break;
39020a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING:
390347d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size);
39040a708f8fSGustavo F. Padovan }
39050a708f8fSGustavo F. Padovan }
39060a708f8fSGustavo F. Padovan
39072d792818SGustavo Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn,
3908cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3909cb3b3152SJohan Hedberg u8 *data)
39100a708f8fSGustavo F. Padovan {
3911e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
l2cap_command_rej(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)39120a708f8fSGustavo F. Padovan
3913cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rej))
3914cb3b3152SJohan Hedberg return -EPROTO;
3915cb3b3152SJohan Hedberg
3916e2fd318eSIlia Kolomisnky if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
39170a708f8fSGustavo F. Padovan return 0;
39180a708f8fSGustavo F. Padovan
39190a708f8fSGustavo F. Padovan if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
39200a708f8fSGustavo F. Padovan cmd->ident == conn->info_ident) {
392117cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer);
39220a708f8fSGustavo F. Padovan
39230a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
39240a708f8fSGustavo F. Padovan conn->info_ident = 0;
39250a708f8fSGustavo F. Padovan
39260a708f8fSGustavo F. Padovan l2cap_conn_start(conn);
39270a708f8fSGustavo F. Padovan }
39280a708f8fSGustavo F. Padovan
39290a708f8fSGustavo F. Padovan return 0;
39300a708f8fSGustavo F. Padovan }
39310a708f8fSGustavo F. Padovan
3932cfe560c7SSungwoo Kim static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
39335af2e235SLuiz Augusto von Dentz u8 *data, u8 rsp_code)
39340a708f8fSGustavo F. Padovan {
39350a708f8fSGustavo F. Padovan struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
39360a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp;
l2cap_connect(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u8 * data,u8 rsp_code)3937cfe560c7SSungwoo Kim struct l2cap_chan *chan = NULL, *pchan = NULL;
39380a708f8fSGustavo F. Padovan int result, status = L2CAP_CS_NO_INFO;
39390a708f8fSGustavo F. Padovan
39400a708f8fSGustavo F. Padovan u16 dcid = 0, scid = __le16_to_cpu(req->scid);
39410a708f8fSGustavo F. Padovan __le16 psm = req->psm;
39420a708f8fSGustavo F. Padovan
3943097db76cSAndrei Emeltchenko BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
39440a708f8fSGustavo F. Padovan
39450a708f8fSGustavo F. Padovan /* Check if we have socket listening on psm */
39466f59b904SMarcel Holtmann pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
3947bf20fd4eSJohan Hedberg &conn->hcon->dst, ACL_LINK);
394823691d75SGustavo F. Padovan if (!pchan) {
39490a708f8fSGustavo F. Padovan result = L2CAP_CR_BAD_PSM;
3950cfe560c7SSungwoo Kim goto response;
39510a708f8fSGustavo F. Padovan }
39520a708f8fSGustavo F. Padovan
39538ffb9290SGustavo Padovan l2cap_chan_lock(pchan);
39540a708f8fSGustavo F. Padovan
39550a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */
3956dcf4adbfSJoe Perches if (psm != cpu_to_le16(L2CAP_PSM_SDP) &&
39570a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) {
39589f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
39590a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK;
39600a708f8fSGustavo F. Padovan goto response;
39610a708f8fSGustavo F. Padovan }
39620a708f8fSGustavo F. Padovan
39630a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM;
39640a708f8fSGustavo F. Padovan
3965dd1a8f8aSMallikarjun Phulari /* Check for valid dynamic CID range (as per Erratum 3253) */
3966dd1a8f8aSMallikarjun Phulari if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_DYN_END) {
3967dd1a8f8aSMallikarjun Phulari result = L2CAP_CR_INVALID_SCID;
39682dfa1003SGustavo Padovan goto response;
3969dd1a8f8aSMallikarjun Phulari }
3970dd1a8f8aSMallikarjun Phulari
3971dd1a8f8aSMallikarjun Phulari /* Check if we already have channel with that dcid */
3972dd1a8f8aSMallikarjun Phulari if (__l2cap_get_chan_by_dcid(conn, scid)) {
3973dd1a8f8aSMallikarjun Phulari result = L2CAP_CR_SCID_IN_USE;
3974dd1a8f8aSMallikarjun Phulari goto response;
3975dd1a8f8aSMallikarjun Phulari }
39762dfa1003SGustavo Padovan
397780b98027SGustavo Padovan chan = pchan->ops->new_connection(pchan);
397880808e43SGustavo F. Padovan if (!chan)
39790a708f8fSGustavo F. Padovan goto response;
39800a708f8fSGustavo F. Padovan
3981330b6c15SSyam Sidhardhan /* For certain devices (ex: HID mouse), support for authentication,
3982330b6c15SSyam Sidhardhan * pairing and bonding is optional. For such devices, inorder to avoid
3983330b6c15SSyam Sidhardhan * the ACL alive for too long after L2CAP disconnection, reset the ACL
3984330b6c15SSyam Sidhardhan * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect.
3985330b6c15SSyam Sidhardhan */
3986330b6c15SSyam Sidhardhan conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3987330b6c15SSyam Sidhardhan
39887eafc59eSMarcel Holtmann bacpy(&chan->src, &conn->hcon->src);
39897eafc59eSMarcel Holtmann bacpy(&chan->dst, &conn->hcon->dst);
3990a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(conn->hcon);
3991a250e048SJohan Hedberg chan->dst_type = bdaddr_dst_type(conn->hcon);
3992fe4128e0SGustavo F. Padovan chan->psm = psm;
3993fe4128e0SGustavo F. Padovan chan->dcid = scid;
39940a708f8fSGustavo F. Padovan
39956be36555SAndrei Emeltchenko __l2cap_chan_add(conn, chan);
399648454079SGustavo F. Padovan
3997fe4128e0SGustavo F. Padovan dcid = chan->scid;
39980a708f8fSGustavo F. Padovan
39998d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
40000a708f8fSGustavo F. Padovan
4001fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident;
40020a708f8fSGustavo F. Padovan
40030a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
4004e7cafc45SJohan Hedberg if (l2cap_chan_check_security(chan, false)) {
4005bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
4006f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2);
40070a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND;
40080a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND;
40092dc4e510SGustavo Padovan chan->ops->defer(chan);
40100a708f8fSGustavo F. Padovan } else {
40117ccca396SPauli Virtanen l2cap_state_change(chan, BT_CONFIG);
40127ccca396SPauli Virtanen result = L2CAP_CR_SUCCESS;
40130a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO;
40140a708f8fSGustavo F. Padovan }
40150a708f8fSGustavo F. Padovan } else {
4016f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2);
40170a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND;
40180a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND;
40190a708f8fSGustavo F. Padovan }
40200a708f8fSGustavo F. Padovan } else {
4021f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2);
40220a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND;
40230a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO;
40240a708f8fSGustavo F. Padovan }
40250a708f8fSGustavo F. Padovan
40260a708f8fSGustavo F. Padovan response:
40270a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid);
40280a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid);
40290a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result);
40300a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status);
40314c89b6aaSMat Martineau l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp);
40320a708f8fSGustavo F. Padovan
4033cfe560c7SSungwoo Kim if (!pchan)
4034cfe560c7SSungwoo Kim return;
4035cfe560c7SSungwoo Kim
40360a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
40370a708f8fSGustavo F. Padovan struct l2cap_info_req info;
4038dcf4adbfSJoe Perches info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
40390a708f8fSGustavo F. Padovan
40400a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
40410a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn);
40420a708f8fSGustavo F. Padovan
4043ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
40440a708f8fSGustavo F. Padovan
40452d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
40462d792818SGustavo Padovan sizeof(info), &info);
40470a708f8fSGustavo F. Padovan }
40480a708f8fSGustavo F. Padovan
4049c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
40500a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) {
40510a708f8fSGustavo F. Padovan u8 buf[128];
4052c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state);
40530a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4054e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
405573ffa904SGustavo F. Padovan chan->num_conf_req++;
40560a708f8fSGustavo F. Padovan }
40571700915fSMat Martineau
4058cfe560c7SSungwoo Kim l2cap_chan_unlock(pchan);
4059cfe560c7SSungwoo Kim l2cap_chan_put(pchan);
40604c89b6aaSMat Martineau }
40610a708f8fSGustavo F. Padovan
40624c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn,
4063cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
40644c89b6aaSMat Martineau {
4065cb3b3152SJohan Hedberg if (cmd_len < sizeof(struct l2cap_conn_req))
4066cb3b3152SJohan Hedberg return -EPROTO;
4067cb3b3152SJohan Hedberg
40685af2e235SLuiz Augusto von Dentz l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP);
l2cap_connect_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)40690a708f8fSGustavo F. Padovan return 0;
40700a708f8fSGustavo F. Padovan }
40710a708f8fSGustavo F. Padovan
40725909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
4073cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4074cb3b3152SJohan Hedberg u8 *data)
40750a708f8fSGustavo F. Padovan {
40760a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
40770a708f8fSGustavo F. Padovan u16 scid, dcid, result, status;
407848454079SGustavo F. Padovan struct l2cap_chan *chan;
l2cap_connect_create_rsp(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)40790a708f8fSGustavo F. Padovan u8 req[128];
40803df91ea2SAndrei Emeltchenko int err;
40810a708f8fSGustavo F. Padovan
4082cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp))
4083cb3b3152SJohan Hedberg return -EPROTO;
4084cb3b3152SJohan Hedberg
40850a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid);
40860a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid);
40870a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result);
40880a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status);
40890a708f8fSGustavo F. Padovan
409075767213SSungwoo Kim if (result == L2CAP_CR_SUCCESS && (dcid < L2CAP_CID_DYN_START ||
409175767213SSungwoo Kim dcid > L2CAP_CID_DYN_END))
409275767213SSungwoo Kim return -EPROTO;
409375767213SSungwoo Kim
40941b009c98SAndrei Emeltchenko BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
40951b009c98SAndrei Emeltchenko dcid, scid, result, status);
40960a708f8fSGustavo F. Padovan
40970a708f8fSGustavo F. Padovan if (scid) {
40983df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid);
4099*efc30877SLuiz Augusto von Dentz if (!chan)
4100*efc30877SLuiz Augusto von Dentz return -EBADSLT;
41010a708f8fSGustavo F. Padovan } else {
41023df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
4103*efc30877SLuiz Augusto von Dentz if (!chan)
4104*efc30877SLuiz Augusto von Dentz return -EBADSLT;
41050a708f8fSGustavo F. Padovan }
41060a708f8fSGustavo F. Padovan
410735fcbc42SLuiz Augusto von Dentz chan = l2cap_chan_hold_unless_zero(chan);
4108*efc30877SLuiz Augusto von Dentz if (!chan)
4109*efc30877SLuiz Augusto von Dentz return -EBADSLT;
411035fcbc42SLuiz Augusto von Dentz
41113df91ea2SAndrei Emeltchenko err = 0;
41123df91ea2SAndrei Emeltchenko
41136be36555SAndrei Emeltchenko l2cap_chan_lock(chan);
411448454079SGustavo F. Padovan
41150a708f8fSGustavo F. Padovan switch (result) {
41160a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS:
411775767213SSungwoo Kim if (__l2cap_get_chan_by_dcid(conn, dcid)) {
411875767213SSungwoo Kim err = -EBADSLT;
411975767213SSungwoo Kim break;
412075767213SSungwoo Kim }
412175767213SSungwoo Kim
412289bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG);
4123fc7f8a7eSGustavo F. Padovan chan->ident = 0;
4124fe4128e0SGustavo F. Padovan chan->dcid = dcid;
4125c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
41260a708f8fSGustavo F. Padovan
4127c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
41280a708f8fSGustavo F. Padovan break;
41290a708f8fSGustavo F. Padovan
41300a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4131e860d2c9SBen Seri l2cap_build_conf_req(chan, req, sizeof(req)), req);
413273ffa904SGustavo F. Padovan chan->num_conf_req++;
41330a708f8fSGustavo F. Padovan break;
41340a708f8fSGustavo F. Padovan
41350a708f8fSGustavo F. Padovan case L2CAP_CR_PEND:
4136c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state);
41370a708f8fSGustavo F. Padovan break;
41380a708f8fSGustavo F. Padovan
41390a708f8fSGustavo F. Padovan default:
414048454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED);
41410a708f8fSGustavo F. Padovan break;
41420a708f8fSGustavo F. Padovan }
41430a708f8fSGustavo F. Padovan
41446be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
414535fcbc42SLuiz Augusto von Dentz l2cap_chan_put(chan);
41463df91ea2SAndrei Emeltchenko
41473df91ea2SAndrei Emeltchenko return err;
41480a708f8fSGustavo F. Padovan }
41490a708f8fSGustavo F. Padovan
415047d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
41510a708f8fSGustavo F. Padovan {
41520a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both
41530a708f8fSGustavo F. Padovan * sides request it.
41540a708f8fSGustavo F. Padovan */
41550c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
415647d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE;
4157f2592d3eSAndrei Emeltchenko else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state))
415847d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16;
41590a708f8fSGustavo F. Padovan }
41600a708f8fSGustavo F. Padovan
416129d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data,
416229d8a590SAndrei Emeltchenko u8 ident, u16 flags)
416329d8a590SAndrei Emeltchenko {
416429d8a590SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn;
416529d8a590SAndrei Emeltchenko
416629d8a590SAndrei Emeltchenko BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident,
416729d8a590SAndrei Emeltchenko flags);
set_default_fcs(struct l2cap_chan * chan)416829d8a590SAndrei Emeltchenko
416929d8a590SAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
417029d8a590SAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
417129d8a590SAndrei Emeltchenko
417229d8a590SAndrei Emeltchenko l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP,
417329d8a590SAndrei Emeltchenko l2cap_build_conf_rsp(chan, data,
417429d8a590SAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), data);
417529d8a590SAndrei Emeltchenko }
417629d8a590SAndrei Emeltchenko
4177662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident,
4178662d652dSJohan Hedberg u16 scid, u16 dcid)
l2cap_send_efs_conf_rsp(struct l2cap_chan * chan,void * data,u8 ident,u16 flags)4179662d652dSJohan Hedberg {
4180662d652dSJohan Hedberg struct l2cap_cmd_rej_cid rej;
4181662d652dSJohan Hedberg
4182dcf4adbfSJoe Perches rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
4183662d652dSJohan Hedberg rej.scid = __cpu_to_le16(scid);
4184662d652dSJohan Hedberg rej.dcid = __cpu_to_le16(dcid);
4185662d652dSJohan Hedberg
4186662d652dSJohan Hedberg l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
4187662d652dSJohan Hedberg }
4188662d652dSJohan Hedberg
41892d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn,
41902d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len,
41912d792818SGustavo Padovan u8 *data)
41920a708f8fSGustavo F. Padovan {
41930a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
41940a708f8fSGustavo F. Padovan u16 dcid, flags;
cmd_reject_invalid_cid(struct l2cap_conn * conn,u8 ident,u16 scid,u16 dcid)41950a708f8fSGustavo F. Padovan u8 rsp[64];
419648454079SGustavo F. Padovan struct l2cap_chan *chan;
41973c588192SMat Martineau int len, err = 0;
41980a708f8fSGustavo F. Padovan
4199cb3b3152SJohan Hedberg if (cmd_len < sizeof(*req))
4200cb3b3152SJohan Hedberg return -EPROTO;
4201cb3b3152SJohan Hedberg
42020a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid);
42030a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags);
42040a708f8fSGustavo F. Padovan
42050a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
42060a708f8fSGustavo F. Padovan
l2cap_config_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)4207baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid);
4208662d652dSJohan Hedberg if (!chan) {
4209662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0);
4210662d652dSJohan Hedberg return 0;
4211662d652dSJohan Hedberg }
42120a708f8fSGustavo F. Padovan
421396298f64SHoward Chung if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2 &&
421496298f64SHoward Chung chan->state != BT_CONNECTED) {
4215662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4216662d652dSJohan Hedberg chan->dcid);
42170a708f8fSGustavo F. Padovan goto unlock;
42180a708f8fSGustavo F. Padovan }
42190a708f8fSGustavo F. Padovan
42200a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */
42210a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req);
4222cb3b3152SJohan Hedberg if (chan->conf_len + len > sizeof(chan->conf_req)) {
42230a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4224fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp,
42250a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp);
42260a708f8fSGustavo F. Padovan goto unlock;
42270a708f8fSGustavo F. Padovan }
42280a708f8fSGustavo F. Padovan
42290a708f8fSGustavo F. Padovan /* Store config. */
423073ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len);
423173ffa904SGustavo F. Padovan chan->conf_len += len;
42320a708f8fSGustavo F. Padovan
423359e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) {
42340a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */
42350a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4236fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp,
42375325e5bbSAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), rsp);
42380a708f8fSGustavo F. Padovan goto unlock;
42390a708f8fSGustavo F. Padovan }
42400a708f8fSGustavo F. Padovan
42410a708f8fSGustavo F. Padovan /* Complete config. */
4242e860d2c9SBen Seri len = l2cap_parse_conf_req(chan, rsp, sizeof(rsp));
42430a708f8fSGustavo F. Padovan if (len < 0) {
42445e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
42450a708f8fSGustavo F. Padovan goto unlock;
42460a708f8fSGustavo F. Padovan }
42470a708f8fSGustavo F. Padovan
42481500109bSMat Martineau chan->ident = cmd->ident;
42490a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
4250bcd70260SSungwoo Kim if (chan->num_conf_rsp < L2CAP_CONF_MAX_CONF_RSP)
425173ffa904SGustavo F. Padovan chan->num_conf_rsp++;
42520a708f8fSGustavo F. Padovan
42530a708f8fSGustavo F. Padovan /* Reset config buffer. */
425473ffa904SGustavo F. Padovan chan->conf_len = 0;
42550a708f8fSGustavo F. Padovan
4256c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
42570a708f8fSGustavo F. Padovan goto unlock;
42580a708f8fSGustavo F. Padovan
4259c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
426047d1ec61SGustavo F. Padovan set_default_fcs(chan);
42610a708f8fSGustavo F. Padovan
4262105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM ||
4263105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING)
42643c588192SMat Martineau err = l2cap_ertm_init(chan);
42650a708f8fSGustavo F. Padovan
42663c588192SMat Martineau if (err < 0)
42675e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err);
42683c588192SMat Martineau else
4269cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan);
42703c588192SMat Martineau
42710a708f8fSGustavo F. Padovan goto unlock;
42720a708f8fSGustavo F. Padovan }
42730a708f8fSGustavo F. Padovan
4274c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
42750a708f8fSGustavo F. Padovan u8 buf[64];
42760a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4277e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
427873ffa904SGustavo F. Padovan chan->num_conf_req++;
42790a708f8fSGustavo F. Padovan }
42800a708f8fSGustavo F. Padovan
428149c922bbSStephen Hemminger /* Got Conf Rsp PENDING from remote side and assume we sent
42820e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */
42830e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
42840e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
42850e8b207eSAndrei Emeltchenko
42860e8b207eSAndrei Emeltchenko /* check compatibility */
42870e8b207eSAndrei Emeltchenko
428879de886dSAndrei Emeltchenko /* Send rsp for BR/EDR channel */
428929d8a590SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags);
42900e8b207eSAndrei Emeltchenko }
42910e8b207eSAndrei Emeltchenko
42920a708f8fSGustavo F. Padovan unlock:
42936be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
4294d0be8347SLuiz Augusto von Dentz l2cap_chan_put(chan);
42953c588192SMat Martineau return err;
42960a708f8fSGustavo F. Padovan }
42970a708f8fSGustavo F. Padovan
42982d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn,
4299cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4300cb3b3152SJohan Hedberg u8 *data)
43010a708f8fSGustavo F. Padovan {
43020a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
43030a708f8fSGustavo F. Padovan u16 scid, flags, result;
430448454079SGustavo F. Padovan struct l2cap_chan *chan;
4305cb3b3152SJohan Hedberg int len = cmd_len - sizeof(*rsp);
43063c588192SMat Martineau int err = 0;
43070a708f8fSGustavo F. Padovan
4308cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp))
4309cb3b3152SJohan Hedberg return -EPROTO;
4310cb3b3152SJohan Hedberg
43110a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid);
43120a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags);
43130a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result);
43140a708f8fSGustavo F. Padovan
431561386cbaSAndrei Emeltchenko BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
l2cap_config_rsp(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)431661386cbaSAndrei Emeltchenko result, len);
43170a708f8fSGustavo F. Padovan
4318baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid);
431948454079SGustavo F. Padovan if (!chan)
43200a708f8fSGustavo F. Padovan return 0;
43210a708f8fSGustavo F. Padovan
43220a708f8fSGustavo F. Padovan switch (result) {
43230a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS:
432447d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len);
43250e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
43260a708f8fSGustavo F. Padovan break;
43270a708f8fSGustavo F. Padovan
43280e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING:
43290e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
43300e8b207eSAndrei Emeltchenko
43310e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
43320e8b207eSAndrei Emeltchenko char buf[64];
43330e8b207eSAndrei Emeltchenko
43340e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4335e860d2c9SBen Seri buf, sizeof(buf), &result);
43360e8b207eSAndrei Emeltchenko if (len < 0) {
43375e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
43380e8b207eSAndrei Emeltchenko goto done;
43390e8b207eSAndrei Emeltchenko }
43400e8b207eSAndrei Emeltchenko
4341cd5d26a9SLuiz Augusto von Dentz l2cap_send_efs_conf_rsp(chan, buf, cmd->ident, 0);
43425ce66b59SAndrei Emeltchenko }
43430e8b207eSAndrei Emeltchenko goto done;
43440e8b207eSAndrei Emeltchenko
434598d2c3e1SBastien Nocera case L2CAP_CONF_UNKNOWN:
43460a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT:
434773ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
43480a708f8fSGustavo F. Padovan char req[64];
43490a708f8fSGustavo F. Padovan
43500a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
43515e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
43520a708f8fSGustavo F. Padovan goto done;
43530a708f8fSGustavo F. Padovan }
43540a708f8fSGustavo F. Padovan
43550a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */
43560a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS;
4357b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4358e860d2c9SBen Seri req, sizeof(req), &result);
43590a708f8fSGustavo F. Padovan if (len < 0) {
43605e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
43610a708f8fSGustavo F. Padovan goto done;
43620a708f8fSGustavo F. Padovan }
43630a708f8fSGustavo F. Padovan
43640a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn),
43650a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req);
436673ffa904SGustavo F. Padovan chan->num_conf_req++;
43670a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS)
43680a708f8fSGustavo F. Padovan goto done;
43690a708f8fSGustavo F. Padovan break;
43700a708f8fSGustavo F. Padovan }
437119186c7bSGustavo A. R. Silva fallthrough;
43720a708f8fSGustavo F. Padovan
43730a708f8fSGustavo F. Padovan default:
43746be36555SAndrei Emeltchenko l2cap_chan_set_err(chan, ECONNRESET);
43752e0052e4SAndrei Emeltchenko
4376ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
43775e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
43780a708f8fSGustavo F. Padovan goto done;
43790a708f8fSGustavo F. Padovan }
43800a708f8fSGustavo F. Padovan
438159e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION)
43820a708f8fSGustavo F. Padovan goto done;
43830a708f8fSGustavo F. Padovan
4384c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state);
43850a708f8fSGustavo F. Padovan
4386c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
438747d1ec61SGustavo F. Padovan set_default_fcs(chan);
43880a708f8fSGustavo F. Padovan
4389105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM ||
4390105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING)
43913c588192SMat Martineau err = l2cap_ertm_init(chan);
43920a708f8fSGustavo F. Padovan
43933c588192SMat Martineau if (err < 0)
43945e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err);
43953c588192SMat Martineau else
4396cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan);
43970a708f8fSGustavo F. Padovan }
43980a708f8fSGustavo F. Padovan
43990a708f8fSGustavo F. Padovan done:
44006be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
4401d0be8347SLuiz Augusto von Dentz l2cap_chan_put(chan);
44023c588192SMat Martineau return err;
44030a708f8fSGustavo F. Padovan }
44040a708f8fSGustavo F. Padovan
44052d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
4406cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4407cb3b3152SJohan Hedberg u8 *data)
44080a708f8fSGustavo F. Padovan {
44090a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
44100a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp;
44110a708f8fSGustavo F. Padovan u16 dcid, scid;
441248454079SGustavo F. Padovan struct l2cap_chan *chan;
44130a708f8fSGustavo F. Padovan
4414cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req))
4415cb3b3152SJohan Hedberg return -EPROTO;
4416cb3b3152SJohan Hedberg
44170a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid);
44180a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid);
44190a708f8fSGustavo F. Padovan
44200a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
44210a708f8fSGustavo F. Padovan
4422a2a9339eSLuiz Augusto von Dentz chan = l2cap_get_chan_by_scid(conn, dcid);
l2cap_disconnect_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)44233df91ea2SAndrei Emeltchenko if (!chan) {
4424662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid);
4425662d652dSJohan Hedberg return 0;
44263df91ea2SAndrei Emeltchenko }
44270a708f8fSGustavo F. Padovan
4428fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid);
4429fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid);
44300a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
44310a708f8fSGustavo F. Padovan
44325ec1bbe5SGustavo Padovan chan->ops->set_shutdown(chan);
44330a708f8fSGustavo F. Padovan
443448454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET);
44356be36555SAndrei Emeltchenko
443680b98027SGustavo Padovan chan->ops->close(chan);
44376c08fc89SManish Mandlik
44386c08fc89SManish Mandlik l2cap_chan_unlock(chan);
443961d6ef3eSMat Martineau l2cap_chan_put(chan);
44403df91ea2SAndrei Emeltchenko
44410a708f8fSGustavo F. Padovan return 0;
44420a708f8fSGustavo F. Padovan }
44430a708f8fSGustavo F. Padovan
44442d792818SGustavo Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
4445cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4446cb3b3152SJohan Hedberg u8 *data)
44470a708f8fSGustavo F. Padovan {
44480a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
44490a708f8fSGustavo F. Padovan u16 dcid, scid;
445048454079SGustavo F. Padovan struct l2cap_chan *chan;
44510a708f8fSGustavo F. Padovan
4452cb3b3152SJohan Hedberg if (cmd_len != sizeof(*rsp))
4453cb3b3152SJohan Hedberg return -EPROTO;
4454cb3b3152SJohan Hedberg
44550a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid);
44560a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid);
44570a708f8fSGustavo F. Padovan
44580a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
44590a708f8fSGustavo F. Padovan
4460a2a9339eSLuiz Augusto von Dentz chan = l2cap_get_chan_by_scid(conn, scid);
44613df91ea2SAndrei Emeltchenko if (!chan) {
44620a708f8fSGustavo F. Padovan return 0;
44633df91ea2SAndrei Emeltchenko }
44640a708f8fSGustavo F. Padovan
446528261da8SMatias Karhumaa if (chan->state != BT_DISCONN) {
l2cap_disconnect_rsp(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)446628261da8SMatias Karhumaa l2cap_chan_unlock(chan);
44676c08fc89SManish Mandlik l2cap_chan_put(chan);
446828261da8SMatias Karhumaa return 0;
446928261da8SMatias Karhumaa }
447028261da8SMatias Karhumaa
447148454079SGustavo F. Padovan l2cap_chan_del(chan, 0);
44726be36555SAndrei Emeltchenko
447380b98027SGustavo Padovan chan->ops->close(chan);
44746c08fc89SManish Mandlik
44756c08fc89SManish Mandlik l2cap_chan_unlock(chan);
447661d6ef3eSMat Martineau l2cap_chan_put(chan);
44773df91ea2SAndrei Emeltchenko
44780a708f8fSGustavo F. Padovan return 0;
44790a708f8fSGustavo F. Padovan }
44800a708f8fSGustavo F. Padovan
44812d792818SGustavo Padovan static inline int l2cap_information_req(struct l2cap_conn *conn,
4482cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4483cb3b3152SJohan Hedberg u8 *data)
44840a708f8fSGustavo F. Padovan {
44850a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data;
44860a708f8fSGustavo F. Padovan u16 type;
44870a708f8fSGustavo F. Padovan
4488cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req))
4489cb3b3152SJohan Hedberg return -EPROTO;
4490cb3b3152SJohan Hedberg
44910a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type);
44920a708f8fSGustavo F. Padovan
44930a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type);
44940a708f8fSGustavo F. Padovan
44950a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) {
44960a708f8fSGustavo F. Padovan u8 buf[8];
44970a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask;
44980a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
4499dcf4adbfSJoe Perches rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
4500dcf4adbfSJoe Perches rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
45010a708f8fSGustavo F. Padovan if (!disable_ertm)
45020a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
45030a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS;
4504a5fd6f30SAndrei Emeltchenko
45050a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data);
45062d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
l2cap_information_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)45072d792818SGustavo Padovan buf);
45080a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) {
45090a708f8fSGustavo F. Padovan u8 buf[12];
45100a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
451150a147cdSMat Martineau
4512dcf4adbfSJoe Perches rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
4513dcf4adbfSJoe Perches rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
45140bd49fc7SJohan Hedberg rsp->data[0] = conn->local_fixed_chan;
45150bd49fc7SJohan Hedberg memset(rsp->data + 1, 0, 7);
45162d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
45172d792818SGustavo Padovan buf);
45180a708f8fSGustavo F. Padovan } else {
45190a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp;
45200a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type);
4521dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
45222d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp),
45232d792818SGustavo Padovan &rsp);
45240a708f8fSGustavo F. Padovan }
45250a708f8fSGustavo F. Padovan
45260a708f8fSGustavo F. Padovan return 0;
45270a708f8fSGustavo F. Padovan }
45280a708f8fSGustavo F. Padovan
45292d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn,
4530cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4531cb3b3152SJohan Hedberg u8 *data)
45320a708f8fSGustavo F. Padovan {
45330a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
45340a708f8fSGustavo F. Padovan u16 type, result;
45350a708f8fSGustavo F. Padovan
45363f6fa3d4SJaganath Kanakkassery if (cmd_len < sizeof(*rsp))
4537cb3b3152SJohan Hedberg return -EPROTO;
4538cb3b3152SJohan Hedberg
45390a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type);
45400a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result);
45410a708f8fSGustavo F. Padovan
45420a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
45430a708f8fSGustavo F. Padovan
4544e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */
4545e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident ||
4546e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
4547e90165beSAndrei Emeltchenko return 0;
4548e90165beSAndrei Emeltchenko
454917cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer);
45500a708f8fSGustavo F. Padovan
45510a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) {
45520a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
45530a708f8fSGustavo F. Padovan conn->info_ident = 0;
45540a708f8fSGustavo F. Padovan
l2cap_information_rsp(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)45550a708f8fSGustavo F. Padovan l2cap_conn_start(conn);
45560a708f8fSGustavo F. Padovan
45570a708f8fSGustavo F. Padovan return 0;
45580a708f8fSGustavo F. Padovan }
45590a708f8fSGustavo F. Padovan
4560978c93b9SAndrei Emeltchenko switch (type) {
4561978c93b9SAndrei Emeltchenko case L2CAP_IT_FEAT_MASK:
45620a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data);
45630a708f8fSGustavo F. Padovan
45640a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
45650a708f8fSGustavo F. Padovan struct l2cap_info_req req;
4566dcf4adbfSJoe Perches req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
45670a708f8fSGustavo F. Padovan
45680a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn);
45690a708f8fSGustavo F. Padovan
45700a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident,
45710a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req);
45720a708f8fSGustavo F. Padovan } else {
45730a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
45740a708f8fSGustavo F. Padovan conn->info_ident = 0;
45750a708f8fSGustavo F. Padovan
45760a708f8fSGustavo F. Padovan l2cap_conn_start(conn);
45770a708f8fSGustavo F. Padovan }
4578978c93b9SAndrei Emeltchenko break;
4579978c93b9SAndrei Emeltchenko
4580978c93b9SAndrei Emeltchenko case L2CAP_IT_FIXED_CHAN:
45810bd49fc7SJohan Hedberg conn->remote_fixed_chan = rsp->data[0];
45820a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
45830a708f8fSGustavo F. Padovan conn->info_ident = 0;
45840a708f8fSGustavo F. Padovan
45850a708f8fSGustavo F. Padovan l2cap_conn_start(conn);
4586978c93b9SAndrei Emeltchenko break;
45870a708f8fSGustavo F. Padovan }
45880a708f8fSGustavo F. Padovan
45890a708f8fSGustavo F. Padovan return 0;
45900a708f8fSGustavo F. Padovan }
45910a708f8fSGustavo F. Padovan
4592de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
45932d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd,
4594203e639eSJohan Hedberg u16 cmd_len, u8 *data)
4595de73115aSClaudio Takahasi {
4596de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon;
4597de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req;
4598de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp;
4599203e639eSJohan Hedberg u16 min, max, latency, to_multiplier;
46002ce603ebSClaudio Takahasi int err;
4601de73115aSClaudio Takahasi
460240bef302SJohan Hedberg if (hcon->role != HCI_ROLE_MASTER)
4603de73115aSClaudio Takahasi return -EINVAL;
4604de73115aSClaudio Takahasi
4605de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
4606de73115aSClaudio Takahasi return -EPROTO;
4607de73115aSClaudio Takahasi
4608de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data;
4609de73115aSClaudio Takahasi min = __le16_to_cpu(req->min);
4610de73115aSClaudio Takahasi max = __le16_to_cpu(req->max);
4611de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency);
4612de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier);
4613de73115aSClaudio Takahasi
4614de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
4615de73115aSClaudio Takahasi min, max, latency, to_multiplier);
4616de73115aSClaudio Takahasi
4617de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp));
l2cap_conn_param_update_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)46182ce603ebSClaudio Takahasi
4619d4905f24SAndre Guedes err = hci_check_conn_params(min, max, latency, to_multiplier);
46202ce603ebSClaudio Takahasi if (err)
4621dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
4622de73115aSClaudio Takahasi else
4623dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
4624de73115aSClaudio Takahasi
4625de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
4626de73115aSClaudio Takahasi sizeof(rsp), &rsp);
4627de73115aSClaudio Takahasi
4628ffb5a827SAndre Guedes if (!err) {
4629f4869e2aSJohan Hedberg u8 store_hint;
4630ffb5a827SAndre Guedes
4631f4869e2aSJohan Hedberg store_hint = hci_le_conn_update(hcon, min, max, latency,
4632f4869e2aSJohan Hedberg to_multiplier);
4633f4869e2aSJohan Hedberg mgmt_new_conn_param(hcon->hdev, &hcon->dst, hcon->dst_type,
4634f4869e2aSJohan Hedberg store_hint, min, max, latency,
4635f4869e2aSJohan Hedberg to_multiplier);
4636f4869e2aSJohan Hedberg
4637ffb5a827SAndre Guedes }
46382ce603ebSClaudio Takahasi
4639de73115aSClaudio Takahasi return 0;
4640de73115aSClaudio Takahasi }
4641de73115aSClaudio Takahasi
4642f1496deeSJohan Hedberg static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
4643f1496deeSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4644f1496deeSJohan Hedberg u8 *data)
4645f1496deeSJohan Hedberg {
4646f1496deeSJohan Hedberg struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data;
46473e64b7bdSJohan Hedberg struct hci_conn *hcon = conn->hcon;
4648f1496deeSJohan Hedberg u16 dcid, mtu, mps, credits, result;
4649f1496deeSJohan Hedberg struct l2cap_chan *chan;
46503e64b7bdSJohan Hedberg int err, sec_level;
4651f1496deeSJohan Hedberg
4652f1496deeSJohan Hedberg if (cmd_len < sizeof(*rsp))
4653f1496deeSJohan Hedberg return -EPROTO;
4654f1496deeSJohan Hedberg
4655f1496deeSJohan Hedberg dcid = __le16_to_cpu(rsp->dcid);
4656f1496deeSJohan Hedberg mtu = __le16_to_cpu(rsp->mtu);
4657f1496deeSJohan Hedberg mps = __le16_to_cpu(rsp->mps);
4658f1496deeSJohan Hedberg credits = __le16_to_cpu(rsp->credits);
4659f1496deeSJohan Hedberg result = __le16_to_cpu(rsp->result);
4660f1496deeSJohan Hedberg
4661571f7390SMallikarjun Phulari if (result == L2CAP_CR_LE_SUCCESS && (mtu < 23 || mps < 23 ||
466240624183SJohan Hedberg dcid < L2CAP_CID_DYN_START ||
466340624183SJohan Hedberg dcid > L2CAP_CID_LE_DYN_END))
4664f1496deeSJohan Hedberg return -EPROTO;
4665f1496deeSJohan Hedberg
4666f1496deeSJohan Hedberg BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x",
4667f1496deeSJohan Hedberg dcid, mtu, mps, credits, result);
l2cap_le_connect_rsp(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)4668f1496deeSJohan Hedberg
4669f1496deeSJohan Hedberg chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
4670*efc30877SLuiz Augusto von Dentz if (!chan)
4671*efc30877SLuiz Augusto von Dentz return -EBADSLT;
4672f1496deeSJohan Hedberg
4673f1496deeSJohan Hedberg err = 0;
4674f1496deeSJohan Hedberg
4675f1496deeSJohan Hedberg l2cap_chan_lock(chan);
4676f1496deeSJohan Hedberg
4677f1496deeSJohan Hedberg switch (result) {
4678571f7390SMallikarjun Phulari case L2CAP_CR_LE_SUCCESS:
467940624183SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, dcid)) {
468040624183SJohan Hedberg err = -EBADSLT;
468140624183SJohan Hedberg break;
468240624183SJohan Hedberg }
468340624183SJohan Hedberg
4684f1496deeSJohan Hedberg chan->ident = 0;
4685f1496deeSJohan Hedberg chan->dcid = dcid;
4686f1496deeSJohan Hedberg chan->omtu = mtu;
4687f1496deeSJohan Hedberg chan->remote_mps = mps;
46880cd75f7eSJohan Hedberg chan->tx_credits = credits;
4689f1496deeSJohan Hedberg l2cap_chan_ready(chan);
4690f1496deeSJohan Hedberg break;
4691f1496deeSJohan Hedberg
4692571f7390SMallikarjun Phulari case L2CAP_CR_LE_AUTHENTICATION:
4693571f7390SMallikarjun Phulari case L2CAP_CR_LE_ENCRYPTION:
46943e64b7bdSJohan Hedberg /* If we already have MITM protection we can't do
46953e64b7bdSJohan Hedberg * anything.
46963e64b7bdSJohan Hedberg */
46973e64b7bdSJohan Hedberg if (hcon->sec_level > BT_SECURITY_MEDIUM) {
46983e64b7bdSJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED);
46993e64b7bdSJohan Hedberg break;
47003e64b7bdSJohan Hedberg }
47013e64b7bdSJohan Hedberg
47023e64b7bdSJohan Hedberg sec_level = hcon->sec_level + 1;
47033e64b7bdSJohan Hedberg if (chan->sec_level < sec_level)
47043e64b7bdSJohan Hedberg chan->sec_level = sec_level;
47053e64b7bdSJohan Hedberg
47063e64b7bdSJohan Hedberg /* We'll need to send a new Connect Request */
47073e64b7bdSJohan Hedberg clear_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags);
47083e64b7bdSJohan Hedberg
47093e64b7bdSJohan Hedberg smp_conn_security(hcon, chan->sec_level);
47103e64b7bdSJohan Hedberg break;
47113e64b7bdSJohan Hedberg
4712f1496deeSJohan Hedberg default:
4713f1496deeSJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED);
4714f1496deeSJohan Hedberg break;
4715f1496deeSJohan Hedberg }
4716f1496deeSJohan Hedberg
4717f1496deeSJohan Hedberg l2cap_chan_unlock(chan);
4718f1496deeSJohan Hedberg
4719f1496deeSJohan Hedberg return err;
4720f1496deeSJohan Hedberg }
4721f1496deeSJohan Hedberg
47223300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
47232d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len,
47242d792818SGustavo Padovan u8 *data)
47253300d9a9SClaudio Takahasi {
47263300d9a9SClaudio Takahasi int err = 0;
47273300d9a9SClaudio Takahasi
47283300d9a9SClaudio Takahasi switch (cmd->code) {
47293300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ:
4730cb3b3152SJohan Hedberg l2cap_command_rej(conn, cmd, cmd_len, data);
47313300d9a9SClaudio Takahasi break;
47323300d9a9SClaudio Takahasi
47333300d9a9SClaudio Takahasi case L2CAP_CONN_REQ:
4734cb3b3152SJohan Hedberg err = l2cap_connect_req(conn, cmd, cmd_len, data);
47353300d9a9SClaudio Takahasi break;
47363300d9a9SClaudio Takahasi
47373300d9a9SClaudio Takahasi case L2CAP_CONN_RSP:
47389245e737SJohan Hedberg l2cap_connect_create_rsp(conn, cmd, cmd_len, data);
47393300d9a9SClaudio Takahasi break;
47403300d9a9SClaudio Takahasi
47413300d9a9SClaudio Takahasi case L2CAP_CONF_REQ:
47423300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data);
47433300d9a9SClaudio Takahasi break;
47443300d9a9SClaudio Takahasi
47453300d9a9SClaudio Takahasi case L2CAP_CONF_RSP:
47469245e737SJohan Hedberg l2cap_config_rsp(conn, cmd, cmd_len, data);
47473300d9a9SClaudio Takahasi break;
47483300d9a9SClaudio Takahasi
47493300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ:
4750cb3b3152SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
47513300d9a9SClaudio Takahasi break;
47523300d9a9SClaudio Takahasi
47533300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP:
47549245e737SJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
l2cap_bredr_sig_cmd(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)47553300d9a9SClaudio Takahasi break;
47563300d9a9SClaudio Takahasi
47573300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ:
47583300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
47593300d9a9SClaudio Takahasi break;
47603300d9a9SClaudio Takahasi
47613300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP:
47623300d9a9SClaudio Takahasi break;
47633300d9a9SClaudio Takahasi
47643300d9a9SClaudio Takahasi case L2CAP_INFO_REQ:
4765cb3b3152SJohan Hedberg err = l2cap_information_req(conn, cmd, cmd_len, data);
47663300d9a9SClaudio Takahasi break;
47673300d9a9SClaudio Takahasi
47683300d9a9SClaudio Takahasi case L2CAP_INFO_RSP:
47699245e737SJohan Hedberg l2cap_information_rsp(conn, cmd, cmd_len, data);
47703300d9a9SClaudio Takahasi break;
47713300d9a9SClaudio Takahasi
47723300d9a9SClaudio Takahasi default:
47733300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
47743300d9a9SClaudio Takahasi err = -EINVAL;
47753300d9a9SClaudio Takahasi break;
47763300d9a9SClaudio Takahasi }
47773300d9a9SClaudio Takahasi
47783300d9a9SClaudio Takahasi return err;
47793300d9a9SClaudio Takahasi }
47803300d9a9SClaudio Takahasi
478127e2d4c8SJohan Hedberg static int l2cap_le_connect_req(struct l2cap_conn *conn,
478227e2d4c8SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
478327e2d4c8SJohan Hedberg u8 *data)
478427e2d4c8SJohan Hedberg {
478527e2d4c8SJohan Hedberg struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data;
478627e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp;
478727e2d4c8SJohan Hedberg struct l2cap_chan *chan, *pchan;
47880cd75f7eSJohan Hedberg u16 dcid, scid, credits, mtu, mps;
478927e2d4c8SJohan Hedberg __le16 psm;
479027e2d4c8SJohan Hedberg u8 result;
479127e2d4c8SJohan Hedberg
479227e2d4c8SJohan Hedberg if (cmd_len != sizeof(*req))
479327e2d4c8SJohan Hedberg return -EPROTO;
479427e2d4c8SJohan Hedberg
479527e2d4c8SJohan Hedberg scid = __le16_to_cpu(req->scid);
479627e2d4c8SJohan Hedberg mtu = __le16_to_cpu(req->mtu);
479727e2d4c8SJohan Hedberg mps = __le16_to_cpu(req->mps);
479827e2d4c8SJohan Hedberg psm = req->psm;
479927e2d4c8SJohan Hedberg dcid = 0;
48000cd75f7eSJohan Hedberg credits = 0;
480127e2d4c8SJohan Hedberg
480227e2d4c8SJohan Hedberg if (mtu < 23 || mps < 23)
480327e2d4c8SJohan Hedberg return -EPROTO;
480427e2d4c8SJohan Hedberg
480527e2d4c8SJohan Hedberg BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm),
480627e2d4c8SJohan Hedberg scid, mtu, mps);
480727e2d4c8SJohan Hedberg
4808711f8c3fSLuiz Augusto von Dentz /* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 3, Part A
4809711f8c3fSLuiz Augusto von Dentz * page 1059:
4810711f8c3fSLuiz Augusto von Dentz *
4811711f8c3fSLuiz Augusto von Dentz * Valid range: 0x0001-0x00ff
4812711f8c3fSLuiz Augusto von Dentz *
4813711f8c3fSLuiz Augusto von Dentz * Table 4.15: L2CAP_LE_CREDIT_BASED_CONNECTION_REQ SPSM ranges
l2cap_le_connect_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)4814711f8c3fSLuiz Augusto von Dentz */
4815711f8c3fSLuiz Augusto von Dentz if (!psm || __le16_to_cpu(psm) > L2CAP_PSM_LE_DYN_END) {
4816711f8c3fSLuiz Augusto von Dentz result = L2CAP_CR_LE_BAD_PSM;
4817711f8c3fSLuiz Augusto von Dentz chan = NULL;
4818711f8c3fSLuiz Augusto von Dentz goto response;
4819711f8c3fSLuiz Augusto von Dentz }
4820711f8c3fSLuiz Augusto von Dentz
482127e2d4c8SJohan Hedberg /* Check if we have socket listening on psm */
482227e2d4c8SJohan Hedberg pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
482327e2d4c8SJohan Hedberg &conn->hcon->dst, LE_LINK);
482427e2d4c8SJohan Hedberg if (!pchan) {
4825571f7390SMallikarjun Phulari result = L2CAP_CR_LE_BAD_PSM;
482627e2d4c8SJohan Hedberg chan = NULL;
482727e2d4c8SJohan Hedberg goto response;
482827e2d4c8SJohan Hedberg }
482927e2d4c8SJohan Hedberg
483027e2d4c8SJohan Hedberg l2cap_chan_lock(pchan);
483127e2d4c8SJohan Hedberg
483235dc6f83SJohan Hedberg if (!smp_sufficient_security(conn->hcon, pchan->sec_level,
483335dc6f83SJohan Hedberg SMP_ALLOW_STK)) {
4834571f7390SMallikarjun Phulari result = L2CAP_CR_LE_AUTHENTICATION;
483527e2d4c8SJohan Hedberg chan = NULL;
483627e2d4c8SJohan Hedberg goto response_unlock;
483727e2d4c8SJohan Hedberg }
483827e2d4c8SJohan Hedberg
48398a7889ccSJohan Hedberg /* Check for valid dynamic CID range */
48408a7889ccSJohan Hedberg if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) {
4841571f7390SMallikarjun Phulari result = L2CAP_CR_LE_INVALID_SCID;
48428a7889ccSJohan Hedberg chan = NULL;
48438a7889ccSJohan Hedberg goto response_unlock;
48448a7889ccSJohan Hedberg }
48458a7889ccSJohan Hedberg
484627e2d4c8SJohan Hedberg /* Check if we already have channel with that dcid */
484727e2d4c8SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, scid)) {
4848571f7390SMallikarjun Phulari result = L2CAP_CR_LE_SCID_IN_USE;
484927e2d4c8SJohan Hedberg chan = NULL;
485027e2d4c8SJohan Hedberg goto response_unlock;
485127e2d4c8SJohan Hedberg }
485227e2d4c8SJohan Hedberg
485327e2d4c8SJohan Hedberg chan = pchan->ops->new_connection(pchan);
485427e2d4c8SJohan Hedberg if (!chan) {
4855571f7390SMallikarjun Phulari result = L2CAP_CR_LE_NO_MEM;
485627e2d4c8SJohan Hedberg goto response_unlock;
485727e2d4c8SJohan Hedberg }
485827e2d4c8SJohan Hedberg
485927e2d4c8SJohan Hedberg bacpy(&chan->src, &conn->hcon->src);
486027e2d4c8SJohan Hedberg bacpy(&chan->dst, &conn->hcon->dst);
4861a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(conn->hcon);
4862a250e048SJohan Hedberg chan->dst_type = bdaddr_dst_type(conn->hcon);
486327e2d4c8SJohan Hedberg chan->psm = psm;
486427e2d4c8SJohan Hedberg chan->dcid = scid;
486527e2d4c8SJohan Hedberg chan->omtu = mtu;
486627e2d4c8SJohan Hedberg chan->remote_mps = mps;
486727e2d4c8SJohan Hedberg
486827e2d4c8SJohan Hedberg __l2cap_chan_add(conn, chan);
4869fe149310SLuiz Augusto von Dentz
4870ba8f5289SLuiz Augusto von Dentz l2cap_le_flowctl_init(chan, __le16_to_cpu(req->credits));
4871fe149310SLuiz Augusto von Dentz
487227e2d4c8SJohan Hedberg dcid = chan->scid;
48730cd75f7eSJohan Hedberg credits = chan->rx_credits;
487427e2d4c8SJohan Hedberg
487527e2d4c8SJohan Hedberg __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
487627e2d4c8SJohan Hedberg
487727e2d4c8SJohan Hedberg chan->ident = cmd->ident;
487827e2d4c8SJohan Hedberg
487927e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
488027e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_CONNECT2);
4881434714dcSJohan Hedberg /* The following result value is actually not defined
4882434714dcSJohan Hedberg * for LE CoC but we use it to let the function know
4883434714dcSJohan Hedberg * that it should bail out after doing its cleanup
4884434714dcSJohan Hedberg * instead of sending a response.
4885434714dcSJohan Hedberg */
488627e2d4c8SJohan Hedberg result = L2CAP_CR_PEND;
488727e2d4c8SJohan Hedberg chan->ops->defer(chan);
488827e2d4c8SJohan Hedberg } else {
488927e2d4c8SJohan Hedberg l2cap_chan_ready(chan);
4890571f7390SMallikarjun Phulari result = L2CAP_CR_LE_SUCCESS;
489127e2d4c8SJohan Hedberg }
489227e2d4c8SJohan Hedberg
489327e2d4c8SJohan Hedberg response_unlock:
489427e2d4c8SJohan Hedberg l2cap_chan_unlock(pchan);
4895a24cce14SJohan Hedberg l2cap_chan_put(pchan);
489627e2d4c8SJohan Hedberg
489727e2d4c8SJohan Hedberg if (result == L2CAP_CR_PEND)
489827e2d4c8SJohan Hedberg return 0;
489927e2d4c8SJohan Hedberg
490027e2d4c8SJohan Hedberg response:
490127e2d4c8SJohan Hedberg if (chan) {
490227e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu);
49033916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps);
490427e2d4c8SJohan Hedberg } else {
490527e2d4c8SJohan Hedberg rsp.mtu = 0;
490627e2d4c8SJohan Hedberg rsp.mps = 0;
490727e2d4c8SJohan Hedberg }
490827e2d4c8SJohan Hedberg
490927e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(dcid);
49100cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(credits);
491127e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result);
491227e2d4c8SJohan Hedberg
491327e2d4c8SJohan Hedberg l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp);
491427e2d4c8SJohan Hedberg
491527e2d4c8SJohan Hedberg return 0;
491627e2d4c8SJohan Hedberg }
491727e2d4c8SJohan Hedberg
4918fad5fc89SJohan Hedberg static inline int l2cap_le_credits(struct l2cap_conn *conn,
4919fad5fc89SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4920fad5fc89SJohan Hedberg u8 *data)
4921fad5fc89SJohan Hedberg {
4922fad5fc89SJohan Hedberg struct l2cap_le_credits *pkt;
4923fad5fc89SJohan Hedberg struct l2cap_chan *chan;
49240f1bfe4eSJohan Hedberg u16 cid, credits, max_credits;
4925fad5fc89SJohan Hedberg
4926fad5fc89SJohan Hedberg if (cmd_len != sizeof(*pkt))
4927fad5fc89SJohan Hedberg return -EPROTO;
4928fad5fc89SJohan Hedberg
4929fad5fc89SJohan Hedberg pkt = (struct l2cap_le_credits *) data;
4930fad5fc89SJohan Hedberg cid = __le16_to_cpu(pkt->cid);
4931fad5fc89SJohan Hedberg credits = __le16_to_cpu(pkt->credits);
4932fad5fc89SJohan Hedberg
4933fad5fc89SJohan Hedberg BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits);
4934fad5fc89SJohan Hedberg
4935fad5fc89SJohan Hedberg chan = l2cap_get_chan_by_dcid(conn, cid);
4936fad5fc89SJohan Hedberg if (!chan)
4937fad5fc89SJohan Hedberg return -EBADSLT;
4938fad5fc89SJohan Hedberg
49390f1bfe4eSJohan Hedberg max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits;
49400f1bfe4eSJohan Hedberg if (credits > max_credits) {
49410f1bfe4eSJohan Hedberg BT_ERR("LE credits overflow");
49420f1bfe4eSJohan Hedberg l2cap_send_disconn_req(chan, ECONNRESET);
49430f1bfe4eSJohan Hedberg
49440f1bfe4eSJohan Hedberg /* Return 0 so that we don't trigger an unnecessary
49450f1bfe4eSJohan Hedberg * command reject packet.
49460f1bfe4eSJohan Hedberg */
4947d0be8347SLuiz Augusto von Dentz goto unlock;
49480f1bfe4eSJohan Hedberg }
49490f1bfe4eSJohan Hedberg
4950fad5fc89SJohan Hedberg chan->tx_credits += credits;
4951fad5fc89SJohan Hedberg
49528a505b7fSLuiz Augusto von Dentz /* Resume sending */
l2cap_le_credits(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)49538a505b7fSLuiz Augusto von Dentz l2cap_le_flowctl_send(chan);
4954fad5fc89SJohan Hedberg
4955fad5fc89SJohan Hedberg if (chan->tx_credits)
4956fad5fc89SJohan Hedberg chan->ops->resume(chan);
4957fad5fc89SJohan Hedberg
4958d0be8347SLuiz Augusto von Dentz unlock:
4959fad5fc89SJohan Hedberg l2cap_chan_unlock(chan);
4960d0be8347SLuiz Augusto von Dentz l2cap_chan_put(chan);
4961fad5fc89SJohan Hedberg
4962fad5fc89SJohan Hedberg return 0;
4963fad5fc89SJohan Hedberg }
4964fad5fc89SJohan Hedberg
496515f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
496615f02b91SLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd, u16 cmd_len,
496715f02b91SLuiz Augusto von Dentz u8 *data)
496815f02b91SLuiz Augusto von Dentz {
496915f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_req *req = (void *) data;
497015f02b91SLuiz Augusto von Dentz struct {
497115f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp rsp;
49727cf3b1ddSLuiz Augusto von Dentz __le16 dcid[L2CAP_ECRED_MAX_CID];
497315f02b91SLuiz Augusto von Dentz } __packed pdu;
497415f02b91SLuiz Augusto von Dentz struct l2cap_chan *chan, *pchan;
4975965995b7SYueHaibing u16 mtu, mps;
497615f02b91SLuiz Augusto von Dentz __le16 psm;
497715f02b91SLuiz Augusto von Dentz u8 result, len = 0;
497815f02b91SLuiz Augusto von Dentz int i, num_scid;
497915f02b91SLuiz Augusto von Dentz bool defer = false;
498015f02b91SLuiz Augusto von Dentz
49814be5ca67SLuiz Augusto von Dentz if (!enable_ecred)
49824be5ca67SLuiz Augusto von Dentz return -EINVAL;
49834be5ca67SLuiz Augusto von Dentz
498469d67b46SKonstantin Forostyan if (cmd_len < sizeof(*req) || (cmd_len - sizeof(*req)) % sizeof(u16)) {
498515f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_INVALID_PARAMS;
498615f02b91SLuiz Augusto von Dentz goto response;
498715f02b91SLuiz Augusto von Dentz }
498815f02b91SLuiz Augusto von Dentz
49897cf3b1ddSLuiz Augusto von Dentz cmd_len -= sizeof(*req);
49907cf3b1ddSLuiz Augusto von Dentz num_scid = cmd_len / sizeof(u16);
49917cf3b1ddSLuiz Augusto von Dentz
49927cf3b1ddSLuiz Augusto von Dentz if (num_scid > ARRAY_SIZE(pdu.dcid)) {
49937cf3b1ddSLuiz Augusto von Dentz result = L2CAP_CR_LE_INVALID_PARAMS;
49947cf3b1ddSLuiz Augusto von Dentz goto response;
49957cf3b1ddSLuiz Augusto von Dentz }
49967cf3b1ddSLuiz Augusto von Dentz
499715f02b91SLuiz Augusto von Dentz mtu = __le16_to_cpu(req->mtu);
499815f02b91SLuiz Augusto von Dentz mps = __le16_to_cpu(req->mps);
499915f02b91SLuiz Augusto von Dentz
l2cap_ecred_conn_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)500015f02b91SLuiz Augusto von Dentz if (mtu < L2CAP_ECRED_MIN_MTU || mps < L2CAP_ECRED_MIN_MPS) {
500115f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_UNACCEPT_PARAMS;
500215f02b91SLuiz Augusto von Dentz goto response;
500315f02b91SLuiz Augusto von Dentz }
500415f02b91SLuiz Augusto von Dentz
500515f02b91SLuiz Augusto von Dentz psm = req->psm;
500615f02b91SLuiz Augusto von Dentz
5007711f8c3fSLuiz Augusto von Dentz /* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 3, Part A
5008711f8c3fSLuiz Augusto von Dentz * page 1059:
5009711f8c3fSLuiz Augusto von Dentz *
5010711f8c3fSLuiz Augusto von Dentz * Valid range: 0x0001-0x00ff
5011711f8c3fSLuiz Augusto von Dentz *
5012711f8c3fSLuiz Augusto von Dentz * Table 4.15: L2CAP_LE_CREDIT_BASED_CONNECTION_REQ SPSM ranges
5013711f8c3fSLuiz Augusto von Dentz */
5014711f8c3fSLuiz Augusto von Dentz if (!psm || __le16_to_cpu(psm) > L2CAP_PSM_LE_DYN_END) {
5015711f8c3fSLuiz Augusto von Dentz result = L2CAP_CR_LE_BAD_PSM;
5016711f8c3fSLuiz Augusto von Dentz goto response;
5017711f8c3fSLuiz Augusto von Dentz }
5018711f8c3fSLuiz Augusto von Dentz
501915f02b91SLuiz Augusto von Dentz BT_DBG("psm 0x%2.2x mtu %u mps %u", __le16_to_cpu(psm), mtu, mps);
502015f02b91SLuiz Augusto von Dentz
502115f02b91SLuiz Augusto von Dentz memset(&pdu, 0, sizeof(pdu));
502215f02b91SLuiz Augusto von Dentz
502315f02b91SLuiz Augusto von Dentz /* Check if we have socket listening on psm */
502415f02b91SLuiz Augusto von Dentz pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
502515f02b91SLuiz Augusto von Dentz &conn->hcon->dst, LE_LINK);
502615f02b91SLuiz Augusto von Dentz if (!pchan) {
502715f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_BAD_PSM;
502815f02b91SLuiz Augusto von Dentz goto response;
502915f02b91SLuiz Augusto von Dentz }
503015f02b91SLuiz Augusto von Dentz
503115f02b91SLuiz Augusto von Dentz l2cap_chan_lock(pchan);
503215f02b91SLuiz Augusto von Dentz
503315f02b91SLuiz Augusto von Dentz if (!smp_sufficient_security(conn->hcon, pchan->sec_level,
503415f02b91SLuiz Augusto von Dentz SMP_ALLOW_STK)) {
503515f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_AUTHENTICATION;
503615f02b91SLuiz Augusto von Dentz goto unlock;
503715f02b91SLuiz Augusto von Dentz }
503815f02b91SLuiz Augusto von Dentz
503915f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_SUCCESS;
504015f02b91SLuiz Augusto von Dentz
504115f02b91SLuiz Augusto von Dentz for (i = 0; i < num_scid; i++) {
504215f02b91SLuiz Augusto von Dentz u16 scid = __le16_to_cpu(req->scid[i]);
504315f02b91SLuiz Augusto von Dentz
504415f02b91SLuiz Augusto von Dentz BT_DBG("scid[%d] 0x%4.4x", i, scid);
504515f02b91SLuiz Augusto von Dentz
504615f02b91SLuiz Augusto von Dentz pdu.dcid[i] = 0x0000;
504715f02b91SLuiz Augusto von Dentz len += sizeof(*pdu.dcid);
504815f02b91SLuiz Augusto von Dentz
504915f02b91SLuiz Augusto von Dentz /* Check for valid dynamic CID range */
505015f02b91SLuiz Augusto von Dentz if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) {
505115f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_INVALID_SCID;
505215f02b91SLuiz Augusto von Dentz continue;
505315f02b91SLuiz Augusto von Dentz }
505415f02b91SLuiz Augusto von Dentz
505515f02b91SLuiz Augusto von Dentz /* Check if we already have channel with that dcid */
505615f02b91SLuiz Augusto von Dentz if (__l2cap_get_chan_by_dcid(conn, scid)) {
505715f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_SCID_IN_USE;
505815f02b91SLuiz Augusto von Dentz continue;
505915f02b91SLuiz Augusto von Dentz }
506015f02b91SLuiz Augusto von Dentz
506115f02b91SLuiz Augusto von Dentz chan = pchan->ops->new_connection(pchan);
506215f02b91SLuiz Augusto von Dentz if (!chan) {
506315f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_NO_MEM;
506415f02b91SLuiz Augusto von Dentz continue;
506515f02b91SLuiz Augusto von Dentz }
506615f02b91SLuiz Augusto von Dentz
506715f02b91SLuiz Augusto von Dentz bacpy(&chan->src, &conn->hcon->src);
506815f02b91SLuiz Augusto von Dentz bacpy(&chan->dst, &conn->hcon->dst);
506915f02b91SLuiz Augusto von Dentz chan->src_type = bdaddr_src_type(conn->hcon);
507015f02b91SLuiz Augusto von Dentz chan->dst_type = bdaddr_dst_type(conn->hcon);
507115f02b91SLuiz Augusto von Dentz chan->psm = psm;
507215f02b91SLuiz Augusto von Dentz chan->dcid = scid;
507315f02b91SLuiz Augusto von Dentz chan->omtu = mtu;
507415f02b91SLuiz Augusto von Dentz chan->remote_mps = mps;
507515f02b91SLuiz Augusto von Dentz
507615f02b91SLuiz Augusto von Dentz __l2cap_chan_add(conn, chan);
507715f02b91SLuiz Augusto von Dentz
507815f02b91SLuiz Augusto von Dentz l2cap_ecred_init(chan, __le16_to_cpu(req->credits));
507915f02b91SLuiz Augusto von Dentz
508015f02b91SLuiz Augusto von Dentz /* Init response */
508115f02b91SLuiz Augusto von Dentz if (!pdu.rsp.credits) {
508215f02b91SLuiz Augusto von Dentz pdu.rsp.mtu = cpu_to_le16(chan->imtu);
508315f02b91SLuiz Augusto von Dentz pdu.rsp.mps = cpu_to_le16(chan->mps);
508415f02b91SLuiz Augusto von Dentz pdu.rsp.credits = cpu_to_le16(chan->rx_credits);
508515f02b91SLuiz Augusto von Dentz }
508615f02b91SLuiz Augusto von Dentz
508715f02b91SLuiz Augusto von Dentz pdu.dcid[i] = cpu_to_le16(chan->scid);
508815f02b91SLuiz Augusto von Dentz
508915f02b91SLuiz Augusto von Dentz __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
509015f02b91SLuiz Augusto von Dentz
509115f02b91SLuiz Augusto von Dentz chan->ident = cmd->ident;
50929aa9d947SLuiz Augusto von Dentz chan->mode = L2CAP_MODE_EXT_FLOWCTL;
509315f02b91SLuiz Augusto von Dentz
509415f02b91SLuiz Augusto von Dentz if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
509515f02b91SLuiz Augusto von Dentz l2cap_state_change(chan, BT_CONNECT2);
509615f02b91SLuiz Augusto von Dentz defer = true;
509715f02b91SLuiz Augusto von Dentz chan->ops->defer(chan);
509815f02b91SLuiz Augusto von Dentz } else {
509915f02b91SLuiz Augusto von Dentz l2cap_chan_ready(chan);
510015f02b91SLuiz Augusto von Dentz }
510115f02b91SLuiz Augusto von Dentz }
510215f02b91SLuiz Augusto von Dentz
510315f02b91SLuiz Augusto von Dentz unlock:
510415f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(pchan);
510515f02b91SLuiz Augusto von Dentz l2cap_chan_put(pchan);
510615f02b91SLuiz Augusto von Dentz
510715f02b91SLuiz Augusto von Dentz response:
510815f02b91SLuiz Augusto von Dentz pdu.rsp.result = cpu_to_le16(result);
510915f02b91SLuiz Augusto von Dentz
511015f02b91SLuiz Augusto von Dentz if (defer)
511115f02b91SLuiz Augusto von Dentz return 0;
511215f02b91SLuiz Augusto von Dentz
511315f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, cmd->ident, L2CAP_ECRED_CONN_RSP,
511415f02b91SLuiz Augusto von Dentz sizeof(pdu.rsp) + len, &pdu);
511515f02b91SLuiz Augusto von Dentz
511615f02b91SLuiz Augusto von Dentz return 0;
511715f02b91SLuiz Augusto von Dentz }
511815f02b91SLuiz Augusto von Dentz
511915f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
512015f02b91SLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd, u16 cmd_len,
512115f02b91SLuiz Augusto von Dentz u8 *data)
512215f02b91SLuiz Augusto von Dentz {
512315f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp *rsp = (void *) data;
512415f02b91SLuiz Augusto von Dentz struct hci_conn *hcon = conn->hcon;
512515f02b91SLuiz Augusto von Dentz u16 mtu, mps, credits, result;
5126de895b43SLuiz Augusto von Dentz struct l2cap_chan *chan, *tmp;
512715f02b91SLuiz Augusto von Dentz int err = 0, sec_level;
512815f02b91SLuiz Augusto von Dentz int i = 0;
512915f02b91SLuiz Augusto von Dentz
513015f02b91SLuiz Augusto von Dentz if (cmd_len < sizeof(*rsp))
513115f02b91SLuiz Augusto von Dentz return -EPROTO;
513215f02b91SLuiz Augusto von Dentz
513315f02b91SLuiz Augusto von Dentz mtu = __le16_to_cpu(rsp->mtu);
513415f02b91SLuiz Augusto von Dentz mps = __le16_to_cpu(rsp->mps);
513515f02b91SLuiz Augusto von Dentz credits = __le16_to_cpu(rsp->credits);
513615f02b91SLuiz Augusto von Dentz result = __le16_to_cpu(rsp->result);
513715f02b91SLuiz Augusto von Dentz
513815f02b91SLuiz Augusto von Dentz BT_DBG("mtu %u mps %u credits %u result 0x%4.4x", mtu, mps, credits,
513915f02b91SLuiz Augusto von Dentz result);
514015f02b91SLuiz Augusto von Dentz
514115f02b91SLuiz Augusto von Dentz cmd_len -= sizeof(*rsp);
514215f02b91SLuiz Augusto von Dentz
5143de895b43SLuiz Augusto von Dentz list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
514415f02b91SLuiz Augusto von Dentz u16 dcid;
514515f02b91SLuiz Augusto von Dentz
514615f02b91SLuiz Augusto von Dentz if (chan->ident != cmd->ident ||
514715f02b91SLuiz Augusto von Dentz chan->mode != L2CAP_MODE_EXT_FLOWCTL ||
514815f02b91SLuiz Augusto von Dentz chan->state == BT_CONNECTED)
514915f02b91SLuiz Augusto von Dentz continue;
515015f02b91SLuiz Augusto von Dentz
515115f02b91SLuiz Augusto von Dentz l2cap_chan_lock(chan);
515215f02b91SLuiz Augusto von Dentz
515315f02b91SLuiz Augusto von Dentz /* Check that there is a dcid for each pending channel */
515415f02b91SLuiz Augusto von Dentz if (cmd_len < sizeof(dcid)) {
515515f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED);
l2cap_ecred_conn_rsp(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)515615f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(chan);
515715f02b91SLuiz Augusto von Dentz continue;
515815f02b91SLuiz Augusto von Dentz }
515915f02b91SLuiz Augusto von Dentz
516015f02b91SLuiz Augusto von Dentz dcid = __le16_to_cpu(rsp->dcid[i++]);
516115f02b91SLuiz Augusto von Dentz cmd_len -= sizeof(u16);
516215f02b91SLuiz Augusto von Dentz
516315f02b91SLuiz Augusto von Dentz BT_DBG("dcid[%d] 0x%4.4x", i, dcid);
516415f02b91SLuiz Augusto von Dentz
516515f02b91SLuiz Augusto von Dentz /* Check if dcid is already in use */
516615f02b91SLuiz Augusto von Dentz if (dcid && __l2cap_get_chan_by_dcid(conn, dcid)) {
516715f02b91SLuiz Augusto von Dentz /* If a device receives a
516815f02b91SLuiz Augusto von Dentz * L2CAP_CREDIT_BASED_CONNECTION_RSP packet with an
516915f02b91SLuiz Augusto von Dentz * already-assigned Destination CID, then both the
517015f02b91SLuiz Augusto von Dentz * original channel and the new channel shall be
517115f02b91SLuiz Augusto von Dentz * immediately discarded and not used.
517215f02b91SLuiz Augusto von Dentz */
517315f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED);
517415f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(chan);
517515f02b91SLuiz Augusto von Dentz chan = __l2cap_get_chan_by_dcid(conn, dcid);
517615f02b91SLuiz Augusto von Dentz l2cap_chan_lock(chan);
517715f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNRESET);
517815f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(chan);
517915f02b91SLuiz Augusto von Dentz continue;
518015f02b91SLuiz Augusto von Dentz }
518115f02b91SLuiz Augusto von Dentz
518215f02b91SLuiz Augusto von Dentz switch (result) {
518315f02b91SLuiz Augusto von Dentz case L2CAP_CR_LE_AUTHENTICATION:
518415f02b91SLuiz Augusto von Dentz case L2CAP_CR_LE_ENCRYPTION:
518515f02b91SLuiz Augusto von Dentz /* If we already have MITM protection we can't do
518615f02b91SLuiz Augusto von Dentz * anything.
518715f02b91SLuiz Augusto von Dentz */
518815f02b91SLuiz Augusto von Dentz if (hcon->sec_level > BT_SECURITY_MEDIUM) {
518915f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED);
519015f02b91SLuiz Augusto von Dentz break;
519115f02b91SLuiz Augusto von Dentz }
519215f02b91SLuiz Augusto von Dentz
519315f02b91SLuiz Augusto von Dentz sec_level = hcon->sec_level + 1;
519415f02b91SLuiz Augusto von Dentz if (chan->sec_level < sec_level)
519515f02b91SLuiz Augusto von Dentz chan->sec_level = sec_level;
519615f02b91SLuiz Augusto von Dentz
519715f02b91SLuiz Augusto von Dentz /* We'll need to send a new Connect Request */
519815f02b91SLuiz Augusto von Dentz clear_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags);
519915f02b91SLuiz Augusto von Dentz
520015f02b91SLuiz Augusto von Dentz smp_conn_security(hcon, chan->sec_level);
520115f02b91SLuiz Augusto von Dentz break;
520215f02b91SLuiz Augusto von Dentz
520315f02b91SLuiz Augusto von Dentz case L2CAP_CR_LE_BAD_PSM:
520415f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED);
520515f02b91SLuiz Augusto von Dentz break;
520615f02b91SLuiz Augusto von Dentz
520715f02b91SLuiz Augusto von Dentz default:
520815f02b91SLuiz Augusto von Dentz /* If dcid was not set it means channels was refused */
520915f02b91SLuiz Augusto von Dentz if (!dcid) {
521015f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED);
521115f02b91SLuiz Augusto von Dentz break;
521215f02b91SLuiz Augusto von Dentz }
521315f02b91SLuiz Augusto von Dentz
521415f02b91SLuiz Augusto von Dentz chan->ident = 0;
521515f02b91SLuiz Augusto von Dentz chan->dcid = dcid;
521615f02b91SLuiz Augusto von Dentz chan->omtu = mtu;
521715f02b91SLuiz Augusto von Dentz chan->remote_mps = mps;
521815f02b91SLuiz Augusto von Dentz chan->tx_credits = credits;
521915f02b91SLuiz Augusto von Dentz l2cap_chan_ready(chan);
522015f02b91SLuiz Augusto von Dentz break;
522115f02b91SLuiz Augusto von Dentz }
522215f02b91SLuiz Augusto von Dentz
522315f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(chan);
522415f02b91SLuiz Augusto von Dentz }
522515f02b91SLuiz Augusto von Dentz
522615f02b91SLuiz Augusto von Dentz return err;
522715f02b91SLuiz Augusto von Dentz }
522815f02b91SLuiz Augusto von Dentz
522915f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_reconf_req(struct l2cap_conn *conn,
523015f02b91SLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd, u16 cmd_len,
523115f02b91SLuiz Augusto von Dentz u8 *data)
523215f02b91SLuiz Augusto von Dentz {
523315f02b91SLuiz Augusto von Dentz struct l2cap_ecred_reconf_req *req = (void *) data;
523415f02b91SLuiz Augusto von Dentz struct l2cap_ecred_reconf_rsp rsp;
523515f02b91SLuiz Augusto von Dentz u16 mtu, mps, result;
523615f02b91SLuiz Augusto von Dentz struct l2cap_chan *chan;
523715f02b91SLuiz Augusto von Dentz int i, num_scid;
523815f02b91SLuiz Augusto von Dentz
52394be5ca67SLuiz Augusto von Dentz if (!enable_ecred)
52404be5ca67SLuiz Augusto von Dentz return -EINVAL;
52414be5ca67SLuiz Augusto von Dentz
524215f02b91SLuiz Augusto von Dentz if (cmd_len < sizeof(*req) || cmd_len - sizeof(*req) % sizeof(u16)) {
524315f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_INVALID_PARAMS;
524415f02b91SLuiz Augusto von Dentz goto respond;
524515f02b91SLuiz Augusto von Dentz }
524615f02b91SLuiz Augusto von Dentz
524715f02b91SLuiz Augusto von Dentz mtu = __le16_to_cpu(req->mtu);
524815f02b91SLuiz Augusto von Dentz mps = __le16_to_cpu(req->mps);
524915f02b91SLuiz Augusto von Dentz
525015f02b91SLuiz Augusto von Dentz BT_DBG("mtu %u mps %u", mtu, mps);
525115f02b91SLuiz Augusto von Dentz
525215f02b91SLuiz Augusto von Dentz if (mtu < L2CAP_ECRED_MIN_MTU) {
525315f02b91SLuiz Augusto von Dentz result = L2CAP_RECONF_INVALID_MTU;
525415f02b91SLuiz Augusto von Dentz goto respond;
525515f02b91SLuiz Augusto von Dentz }
525615f02b91SLuiz Augusto von Dentz
525715f02b91SLuiz Augusto von Dentz if (mps < L2CAP_ECRED_MIN_MPS) {
525815f02b91SLuiz Augusto von Dentz result = L2CAP_RECONF_INVALID_MPS;
525915f02b91SLuiz Augusto von Dentz goto respond;
526015f02b91SLuiz Augusto von Dentz }
526115f02b91SLuiz Augusto von Dentz
526215f02b91SLuiz Augusto von Dentz cmd_len -= sizeof(*req);
526315f02b91SLuiz Augusto von Dentz num_scid = cmd_len / sizeof(u16);
526415f02b91SLuiz Augusto von Dentz result = L2CAP_RECONF_SUCCESS;
526515f02b91SLuiz Augusto von Dentz
526615f02b91SLuiz Augusto von Dentz for (i = 0; i < num_scid; i++) {
526715f02b91SLuiz Augusto von Dentz u16 scid;
526815f02b91SLuiz Augusto von Dentz
526915f02b91SLuiz Augusto von Dentz scid = __le16_to_cpu(req->scid[i]);
l2cap_ecred_reconf_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)527015f02b91SLuiz Augusto von Dentz if (!scid)
527115f02b91SLuiz Augusto von Dentz return -EPROTO;
527215f02b91SLuiz Augusto von Dentz
527315f02b91SLuiz Augusto von Dentz chan = __l2cap_get_chan_by_dcid(conn, scid);
527415f02b91SLuiz Augusto von Dentz if (!chan)
527515f02b91SLuiz Augusto von Dentz continue;
527615f02b91SLuiz Augusto von Dentz
527715f02b91SLuiz Augusto von Dentz /* If the MTU value is decreased for any of the included
527815f02b91SLuiz Augusto von Dentz * channels, then the receiver shall disconnect all
527915f02b91SLuiz Augusto von Dentz * included channels.
528015f02b91SLuiz Augusto von Dentz */
528115f02b91SLuiz Augusto von Dentz if (chan->omtu > mtu) {
528215f02b91SLuiz Augusto von Dentz BT_ERR("chan %p decreased MTU %u -> %u", chan,
528315f02b91SLuiz Augusto von Dentz chan->omtu, mtu);
528415f02b91SLuiz Augusto von Dentz result = L2CAP_RECONF_INVALID_MTU;
528515f02b91SLuiz Augusto von Dentz }
528615f02b91SLuiz Augusto von Dentz
528715f02b91SLuiz Augusto von Dentz chan->omtu = mtu;
528815f02b91SLuiz Augusto von Dentz chan->remote_mps = mps;
528915f02b91SLuiz Augusto von Dentz }
529015f02b91SLuiz Augusto von Dentz
529115f02b91SLuiz Augusto von Dentz respond:
529215f02b91SLuiz Augusto von Dentz rsp.result = cpu_to_le16(result);
529315f02b91SLuiz Augusto von Dentz
529415f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, cmd->ident, L2CAP_ECRED_RECONF_RSP, sizeof(rsp),
529515f02b91SLuiz Augusto von Dentz &rsp);
529615f02b91SLuiz Augusto von Dentz
529715f02b91SLuiz Augusto von Dentz return 0;
529815f02b91SLuiz Augusto von Dentz }
529915f02b91SLuiz Augusto von Dentz
530015f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
530115f02b91SLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd, u16 cmd_len,
530215f02b91SLuiz Augusto von Dentz u8 *data)
530315f02b91SLuiz Augusto von Dentz {
53041fa20d7dSLuiz Augusto von Dentz struct l2cap_chan *chan, *tmp;
530515f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp *rsp = (void *) data;
530615f02b91SLuiz Augusto von Dentz u16 result;
530715f02b91SLuiz Augusto von Dentz
530815f02b91SLuiz Augusto von Dentz if (cmd_len < sizeof(*rsp))
530915f02b91SLuiz Augusto von Dentz return -EPROTO;
531015f02b91SLuiz Augusto von Dentz
531115f02b91SLuiz Augusto von Dentz result = __le16_to_cpu(rsp->result);
531215f02b91SLuiz Augusto von Dentz
531315f02b91SLuiz Augusto von Dentz BT_DBG("result 0x%4.4x", rsp->result);
531415f02b91SLuiz Augusto von Dentz
531515f02b91SLuiz Augusto von Dentz if (!result)
531615f02b91SLuiz Augusto von Dentz return 0;
531715f02b91SLuiz Augusto von Dentz
53181fa20d7dSLuiz Augusto von Dentz list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
531915f02b91SLuiz Augusto von Dentz if (chan->ident != cmd->ident)
532015f02b91SLuiz Augusto von Dentz continue;
532115f02b91SLuiz Augusto von Dentz
532215f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNRESET);
532315f02b91SLuiz Augusto von Dentz }
532415f02b91SLuiz Augusto von Dentz
532515f02b91SLuiz Augusto von Dentz return 0;
532615f02b91SLuiz Augusto von Dentz }
532715f02b91SLuiz Augusto von Dentz
532871fb4197SJohan Hedberg static inline int l2cap_le_command_rej(struct l2cap_conn *conn,
532971fb4197SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
533071fb4197SJohan Hedberg u8 *data)
533171fb4197SJohan Hedberg {
533271fb4197SJohan Hedberg struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
533371fb4197SJohan Hedberg struct l2cap_chan *chan;
533471fb4197SJohan Hedberg
533571fb4197SJohan Hedberg if (cmd_len < sizeof(*rej))
533671fb4197SJohan Hedberg return -EPROTO;
533771fb4197SJohan Hedberg
533871fb4197SJohan Hedberg chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
533971fb4197SJohan Hedberg if (!chan)
534071fb4197SJohan Hedberg goto done;
l2cap_ecred_reconf_rsp(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)534171fb4197SJohan Hedberg
5342f752a0b3SZhengping Jiang chan = l2cap_chan_hold_unless_zero(chan);
5343f752a0b3SZhengping Jiang if (!chan)
5344f752a0b3SZhengping Jiang goto done;
5345f752a0b3SZhengping Jiang
534671fb4197SJohan Hedberg l2cap_chan_lock(chan);
534771fb4197SJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED);
534871fb4197SJohan Hedberg l2cap_chan_unlock(chan);
5349f752a0b3SZhengping Jiang l2cap_chan_put(chan);
535071fb4197SJohan Hedberg
535171fb4197SJohan Hedberg done:
535271fb4197SJohan Hedberg return 0;
535371fb4197SJohan Hedberg }
535471fb4197SJohan Hedberg
53553300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
5356203e639eSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5357203e639eSJohan Hedberg u8 *data)
53583300d9a9SClaudio Takahasi {
5359b5ecba64SJohan Hedberg int err = 0;
5360b5ecba64SJohan Hedberg
53613300d9a9SClaudio Takahasi switch (cmd->code) {
53623300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ:
536371fb4197SJohan Hedberg l2cap_le_command_rej(conn, cmd, cmd_len, data);
5364b5ecba64SJohan Hedberg break;
53653300d9a9SClaudio Takahasi
53663300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ:
5367b5ecba64SJohan Hedberg err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data);
5368b5ecba64SJohan Hedberg break;
l2cap_le_command_rej(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)53693300d9a9SClaudio Takahasi
53703300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP:
5371b5ecba64SJohan Hedberg break;
53723300d9a9SClaudio Takahasi
5373f1496deeSJohan Hedberg case L2CAP_LE_CONN_RSP:
5374f1496deeSJohan Hedberg l2cap_le_connect_rsp(conn, cmd, cmd_len, data);
5375b5ecba64SJohan Hedberg break;
5376f1496deeSJohan Hedberg
537727e2d4c8SJohan Hedberg case L2CAP_LE_CONN_REQ:
5378b5ecba64SJohan Hedberg err = l2cap_le_connect_req(conn, cmd, cmd_len, data);
5379b5ecba64SJohan Hedberg break;
538027e2d4c8SJohan Hedberg
5381fad5fc89SJohan Hedberg case L2CAP_LE_CREDITS:
5382fad5fc89SJohan Hedberg err = l2cap_le_credits(conn, cmd, cmd_len, data);
5383fad5fc89SJohan Hedberg break;
5384fad5fc89SJohan Hedberg
538515f02b91SLuiz Augusto von Dentz case L2CAP_ECRED_CONN_REQ:
538615f02b91SLuiz Augusto von Dentz err = l2cap_ecred_conn_req(conn, cmd, cmd_len, data);
538715f02b91SLuiz Augusto von Dentz break;
538815f02b91SLuiz Augusto von Dentz
538915f02b91SLuiz Augusto von Dentz case L2CAP_ECRED_CONN_RSP:
539015f02b91SLuiz Augusto von Dentz err = l2cap_ecred_conn_rsp(conn, cmd, cmd_len, data);
539115f02b91SLuiz Augusto von Dentz break;
539215f02b91SLuiz Augusto von Dentz
539315f02b91SLuiz Augusto von Dentz case L2CAP_ECRED_RECONF_REQ:
539415f02b91SLuiz Augusto von Dentz err = l2cap_ecred_reconf_req(conn, cmd, cmd_len, data);
539515f02b91SLuiz Augusto von Dentz break;
539615f02b91SLuiz Augusto von Dentz
539715f02b91SLuiz Augusto von Dentz case L2CAP_ECRED_RECONF_RSP:
539815f02b91SLuiz Augusto von Dentz err = l2cap_ecred_reconf_rsp(conn, cmd, cmd_len, data);
l2cap_le_sig_cmd(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)539915f02b91SLuiz Augusto von Dentz break;
540015f02b91SLuiz Augusto von Dentz
54013defe01aSJohan Hedberg case L2CAP_DISCONN_REQ:
5402b5ecba64SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
5403b5ecba64SJohan Hedberg break;
54043defe01aSJohan Hedberg
54053defe01aSJohan Hedberg case L2CAP_DISCONN_RSP:
54063defe01aSJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
5407b5ecba64SJohan Hedberg break;
54083defe01aSJohan Hedberg
54093300d9a9SClaudio Takahasi default:
54103300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
5411b5ecba64SJohan Hedberg err = -EINVAL;
5412b5ecba64SJohan Hedberg break;
54133300d9a9SClaudio Takahasi }
5414b5ecba64SJohan Hedberg
5415b5ecba64SJohan Hedberg return err;
54163300d9a9SClaudio Takahasi }
54173300d9a9SClaudio Takahasi
5418c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
5419c5623556SJohan Hedberg struct sk_buff *skb)
5420c5623556SJohan Hedberg {
542169c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon;
54224f3e219dSMarcel Holtmann struct l2cap_cmd_hdr *cmd;
54234f3e219dSMarcel Holtmann u16 len;
5424c5623556SJohan Hedberg int err;
5425c5623556SJohan Hedberg
542669c4e4e8SJohan Hedberg if (hcon->type != LE_LINK)
54273b166295SMarcel Holtmann goto drop;
542869c4e4e8SJohan Hedberg
54294f3e219dSMarcel Holtmann if (skb->len < L2CAP_CMD_HDR_SIZE)
54304f3e219dSMarcel Holtmann goto drop;
5431c5623556SJohan Hedberg
54324f3e219dSMarcel Holtmann cmd = (void *) skb->data;
54334f3e219dSMarcel Holtmann skb_pull(skb, L2CAP_CMD_HDR_SIZE);
5434c5623556SJohan Hedberg
54354f3e219dSMarcel Holtmann len = le16_to_cpu(cmd->len);
5436c5623556SJohan Hedberg
54374f3e219dSMarcel Holtmann BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);
54384f3e219dSMarcel Holtmann
54394f3e219dSMarcel Holtmann if (len != skb->len || !cmd->ident) {
5440c5623556SJohan Hedberg BT_DBG("corrupted command");
54414f3e219dSMarcel Holtmann goto drop;
5442c5623556SJohan Hedberg }
5443c5623556SJohan Hedberg
5444203e639eSJohan Hedberg err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
5445c5623556SJohan Hedberg if (err) {
5446c5623556SJohan Hedberg struct l2cap_cmd_rej_unk rej;
5447c5623556SJohan Hedberg
5448c5623556SJohan Hedberg BT_ERR("Wrong link type (%d)", err);
5449c5623556SJohan Hedberg
5450dcf4adbfSJoe Perches rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
54514f3e219dSMarcel Holtmann l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
5452c5623556SJohan Hedberg sizeof(rej), &rej);
5453c5623556SJohan Hedberg }
5454c5623556SJohan Hedberg
54553b166295SMarcel Holtmann drop:
5456c5623556SJohan Hedberg kfree_skb(skb);
5457c5623556SJohan Hedberg }
5458c5623556SJohan Hedberg
54590974347aSFrédéric Danis static inline void l2cap_sig_send_rej(struct l2cap_conn *conn, u16 ident)
54600974347aSFrédéric Danis {
54610974347aSFrédéric Danis struct l2cap_cmd_rej_unk rej;
l2cap_le_sig_channel(struct l2cap_conn * conn,struct sk_buff * skb)54620974347aSFrédéric Danis
54630974347aSFrédéric Danis rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
54640974347aSFrédéric Danis l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
54650974347aSFrédéric Danis }
54660974347aSFrédéric Danis
54673300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
54683300d9a9SClaudio Takahasi struct sk_buff *skb)
54690a708f8fSGustavo F. Padovan {
547069c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon;
547155cee73eSLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd;
54723300d9a9SClaudio Takahasi int err;
54730a708f8fSGustavo F. Padovan
54740a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb);
54750a708f8fSGustavo F. Padovan
547669c4e4e8SJohan Hedberg if (hcon->type != ACL_LINK)
54773b166295SMarcel Holtmann goto drop;
547869c4e4e8SJohan Hedberg
547955cee73eSLuiz Augusto von Dentz while (skb->len >= L2CAP_CMD_HDR_SIZE) {
548055cee73eSLuiz Augusto von Dentz u16 len;
54810a708f8fSGustavo F. Padovan
548255cee73eSLuiz Augusto von Dentz cmd = (void *) skb->data;
548355cee73eSLuiz Augusto von Dentz skb_pull(skb, L2CAP_CMD_HDR_SIZE);
54840a708f8fSGustavo F. Padovan
548555cee73eSLuiz Augusto von Dentz len = le16_to_cpu(cmd->len);
54860a708f8fSGustavo F. Padovan
548755cee73eSLuiz Augusto von Dentz BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len,
548855cee73eSLuiz Augusto von Dentz cmd->ident);
548955cee73eSLuiz Augusto von Dentz
549055cee73eSLuiz Augusto von Dentz if (len > skb->len || !cmd->ident) {
54910a708f8fSGustavo F. Padovan BT_DBG("corrupted command");
54920974347aSFrédéric Danis l2cap_sig_send_rej(conn, cmd->ident);
5493100089a1SFrédéric Danis skb_pull(skb, len > skb->len ? skb->len : len);
5494100089a1SFrédéric Danis continue;
54950a708f8fSGustavo F. Padovan }
54960a708f8fSGustavo F. Padovan
549755cee73eSLuiz Augusto von Dentz err = l2cap_bredr_sig_cmd(conn, cmd, len, skb->data);
54980a708f8fSGustavo F. Padovan if (err) {
54992c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err);
55000974347aSFrédéric Danis l2cap_sig_send_rej(conn, cmd->ident);
55010a708f8fSGustavo F. Padovan }
55020a708f8fSGustavo F. Padovan
l2cap_sig_send_rej(struct l2cap_conn * conn,u16 ident)550355cee73eSLuiz Augusto von Dentz skb_pull(skb, len);
55040a708f8fSGustavo F. Padovan }
55050a708f8fSGustavo F. Padovan
55060974347aSFrédéric Danis if (skb->len > 0) {
55070974347aSFrédéric Danis BT_DBG("corrupted command");
55080974347aSFrédéric Danis l2cap_sig_send_rej(conn, 0);
55090974347aSFrédéric Danis }
55100974347aSFrédéric Danis
l2cap_sig_channel(struct l2cap_conn * conn,struct sk_buff * skb)55113b166295SMarcel Holtmann drop:
55120a708f8fSGustavo F. Padovan kfree_skb(skb);
55130a708f8fSGustavo F. Padovan }
55140a708f8fSGustavo F. Padovan
551547d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
55160a708f8fSGustavo F. Padovan {
55170a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs;
5518e4ca6d98SAndrei Emeltchenko int hdr_size;
5519e4ca6d98SAndrei Emeltchenko
5520e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags))
5521e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE;
5522e4ca6d98SAndrei Emeltchenko else
5523e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE;
55240a708f8fSGustavo F. Padovan
552547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) {
552603a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
55270a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len);
55280a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
55290a708f8fSGustavo F. Padovan
55300a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs)
55310a708f8fSGustavo F. Padovan return -EBADMSG;
55320a708f8fSGustavo F. Padovan }
55330a708f8fSGustavo F. Padovan return 0;
55340a708f8fSGustavo F. Padovan }
55350a708f8fSGustavo F. Padovan
55366ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
55370a708f8fSGustavo F. Padovan {
5538e31f7633SMat Martineau struct l2cap_ctrl control;
55390a708f8fSGustavo F. Padovan
5540e31f7633SMat Martineau BT_DBG("chan %p", chan);
55410a708f8fSGustavo F. Padovan
5542e31f7633SMat Martineau memset(&control, 0, sizeof(control));
5543e31f7633SMat Martineau control.sframe = 1;
5544e31f7633SMat Martineau control.final = 1;
5545e31f7633SMat Martineau control.reqseq = chan->buffer_seq;
5546e31f7633SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state);
55470a708f8fSGustavo F. Padovan
5548e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
5549e31f7633SMat Martineau control.super = L2CAP_SUPER_RNR;
5550e31f7633SMat Martineau l2cap_send_sframe(chan, &control);
55510a708f8fSGustavo F. Padovan }
55520a708f8fSGustavo F. Padovan
5553e31f7633SMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
5554e31f7633SMat Martineau chan->unacked_frames > 0)
5555e31f7633SMat Martineau __set_retrans_timer(chan);
55560a708f8fSGustavo F. Padovan
5557e31f7633SMat Martineau /* Send pending iframes */
5558525cd185SGustavo F. Padovan l2cap_ertm_send(chan);
l2cap_check_fcs(struct l2cap_chan * chan,struct sk_buff * skb)55590a708f8fSGustavo F. Padovan
5560e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
5561e31f7633SMat Martineau test_bit(CONN_SEND_FBIT, &chan->conn_state)) {
5562e31f7633SMat Martineau /* F-bit wasn't sent in an s-frame or i-frame yet, so
5563e31f7633SMat Martineau * send it now.
5564e31f7633SMat Martineau */
5565e31f7633SMat Martineau control.super = L2CAP_SUPER_RR;
5566e31f7633SMat Martineau l2cap_send_sframe(chan, &control);
55670a708f8fSGustavo F. Padovan }
55680a708f8fSGustavo F. Padovan }
55690a708f8fSGustavo F. Padovan
55702d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag,
55712d792818SGustavo Padovan struct sk_buff **last_frag)
55720a708f8fSGustavo F. Padovan {
557384084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments
557484084a31SMat Martineau * skb->data_len reflects only data in fragments
557584084a31SMat Martineau */
557684084a31SMat Martineau if (!skb_has_frag_list(skb))
557784084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag;
557884084a31SMat Martineau
557984084a31SMat Martineau new_frag->next = NULL;
l2cap_send_i_or_rr_or_rnr(struct l2cap_chan * chan)558084084a31SMat Martineau
558184084a31SMat Martineau (*last_frag)->next = new_frag;
558284084a31SMat Martineau *last_frag = new_frag;
558384084a31SMat Martineau
558484084a31SMat Martineau skb->len += new_frag->len;
558584084a31SMat Martineau skb->data_len += new_frag->len;
558684084a31SMat Martineau skb->truesize += new_frag->truesize;
558784084a31SMat Martineau }
558884084a31SMat Martineau
55894b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
55904b51dae9SMat Martineau struct l2cap_ctrl *control)
559184084a31SMat Martineau {
559284084a31SMat Martineau int err = -EINVAL;
55930a708f8fSGustavo F. Padovan
55944b51dae9SMat Martineau switch (control->sar) {
55957e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED:
559684084a31SMat Martineau if (chan->sdu)
559784084a31SMat Martineau break;
55980a708f8fSGustavo F. Padovan
559980b98027SGustavo Padovan err = chan->ops->recv(chan, skb);
560084084a31SMat Martineau break;
56010a708f8fSGustavo F. Padovan
56027e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START:
560384084a31SMat Martineau if (chan->sdu)
560484084a31SMat Martineau break;
56050a708f8fSGustavo F. Padovan
5606dbb50887SDaniel Borkmann if (!pskb_may_pull(skb, L2CAP_SDULEN_SIZE))
5607dbb50887SDaniel Borkmann break;
5608dbb50887SDaniel Borkmann
56096f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data);
561003a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE);
56110a708f8fSGustavo F. Padovan
561284084a31SMat Martineau if (chan->sdu_len > chan->imtu) {
561384084a31SMat Martineau err = -EMSGSIZE;
append_skb_frag(struct sk_buff * skb,struct sk_buff * new_frag,struct sk_buff ** last_frag)561484084a31SMat Martineau break;
561584084a31SMat Martineau }
56160a708f8fSGustavo F. Padovan
561784084a31SMat Martineau if (skb->len >= chan->sdu_len)
561884084a31SMat Martineau break;
561984084a31SMat Martineau
562084084a31SMat Martineau chan->sdu = skb;
562184084a31SMat Martineau chan->sdu_last_frag = skb;
562284084a31SMat Martineau
562384084a31SMat Martineau skb = NULL;
562484084a31SMat Martineau err = 0;
56250a708f8fSGustavo F. Padovan break;
56260a708f8fSGustavo F. Padovan
56277e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE:
56286f61fd47SGustavo F. Padovan if (!chan->sdu)
562984084a31SMat Martineau break;
56300a708f8fSGustavo F. Padovan
563184084a31SMat Martineau append_skb_frag(chan->sdu, skb,
563284084a31SMat Martineau &chan->sdu_last_frag);
l2cap_reassemble_sdu(struct l2cap_chan * chan,struct sk_buff * skb,struct l2cap_ctrl * control)563384084a31SMat Martineau skb = NULL;
56340a708f8fSGustavo F. Padovan
563584084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len)
563684084a31SMat Martineau break;
56370a708f8fSGustavo F. Padovan
563884084a31SMat Martineau err = 0;
56390a708f8fSGustavo F. Padovan break;
56400a708f8fSGustavo F. Padovan
56417e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END:
56426f61fd47SGustavo F. Padovan if (!chan->sdu)
564384084a31SMat Martineau break;
56440a708f8fSGustavo F. Padovan
564584084a31SMat Martineau append_skb_frag(chan->sdu, skb,
564684084a31SMat Martineau &chan->sdu_last_frag);
564784084a31SMat Martineau skb = NULL;
56480a708f8fSGustavo F. Padovan
564984084a31SMat Martineau if (chan->sdu->len != chan->sdu_len)
565084084a31SMat Martineau break;
56510a708f8fSGustavo F. Padovan
565280b98027SGustavo Padovan err = chan->ops->recv(chan, chan->sdu);
56530a708f8fSGustavo F. Padovan
565484084a31SMat Martineau if (!err) {
565584084a31SMat Martineau /* Reassembly complete */
565684084a31SMat Martineau chan->sdu = NULL;
565784084a31SMat Martineau chan->sdu_last_frag = NULL;
565884084a31SMat Martineau chan->sdu_len = 0;
56590a708f8fSGustavo F. Padovan }
56600a708f8fSGustavo F. Padovan break;
56610a708f8fSGustavo F. Padovan }
56620a708f8fSGustavo F. Padovan
566384084a31SMat Martineau if (err) {
56640a708f8fSGustavo F. Padovan kfree_skb(skb);
56656f61fd47SGustavo F. Padovan kfree_skb(chan->sdu);
56666f61fd47SGustavo F. Padovan chan->sdu = NULL;
566784084a31SMat Martineau chan->sdu_last_frag = NULL;
566884084a31SMat Martineau chan->sdu_len = 0;
566984084a31SMat Martineau }
56700a708f8fSGustavo F. Padovan
567184084a31SMat Martineau return err;
56720a708f8fSGustavo F. Padovan }
56730a708f8fSGustavo F. Padovan
567432b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan)
567532b32735SMat Martineau {
567632b32735SMat Martineau /* Placeholder */
567732b32735SMat Martineau return 0;
567832b32735SMat Martineau }
567932b32735SMat Martineau
5680e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
56810a708f8fSGustavo F. Padovan {
568261aa4f5bSMat Martineau u8 event;
568361aa4f5bSMat Martineau
568461aa4f5bSMat Martineau if (chan->mode != L2CAP_MODE_ERTM)
568561aa4f5bSMat Martineau return;
568661aa4f5bSMat Martineau
568761aa4f5bSMat Martineau event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR;
5688401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, event);
56890a708f8fSGustavo F. Padovan }
56900a708f8fSGustavo F. Padovan
5691d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan)
5692d2a7ac5dSMat Martineau {
569363838725SMat Martineau int err = 0;
569463838725SMat Martineau /* Pass sequential frames to l2cap_reassemble_sdu()
569563838725SMat Martineau * until a gap is encountered.
569663838725SMat Martineau */
569763838725SMat Martineau
569863838725SMat Martineau BT_DBG("chan %p", chan);
569963838725SMat Martineau
570063838725SMat Martineau while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
570163838725SMat Martineau struct sk_buff *skb;
570263838725SMat Martineau BT_DBG("Searching for skb with txseq %d (queue len %d)",
570363838725SMat Martineau chan->buffer_seq, skb_queue_len(&chan->srej_q));
570463838725SMat Martineau
570563838725SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq);
570663838725SMat Martineau
570763838725SMat Martineau if (!skb)
570863838725SMat Martineau break;
570963838725SMat Martineau
571063838725SMat Martineau skb_unlink(skb, &chan->srej_q);
571163838725SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
5712a4368ff3SJohan Hedberg err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->l2cap);
571363838725SMat Martineau if (err)
571463838725SMat Martineau break;
571563838725SMat Martineau }
571663838725SMat Martineau
571763838725SMat Martineau if (skb_queue_empty(&chan->srej_q)) {
l2cap_resegment(struct l2cap_chan * chan)571863838725SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV;
571963838725SMat Martineau l2cap_send_ack(chan);
572063838725SMat Martineau }
572163838725SMat Martineau
572263838725SMat Martineau return err;
5723d2a7ac5dSMat Martineau }
l2cap_chan_busy(struct l2cap_chan * chan,int busy)5724d2a7ac5dSMat Martineau
5725d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan,
5726d2a7ac5dSMat Martineau struct l2cap_ctrl *control)
5727d2a7ac5dSMat Martineau {
5728f80842a8SMat Martineau struct sk_buff *skb;
5729f80842a8SMat Martineau
5730f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control);
5731f80842a8SMat Martineau
5732f80842a8SMat Martineau if (control->reqseq == chan->next_tx_seq) {
5733f80842a8SMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
57345e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
5735f80842a8SMat Martineau return;
5736f80842a8SMat Martineau }
5737f80842a8SMat Martineau
5738f80842a8SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
5739f80842a8SMat Martineau
5740f80842a8SMat Martineau if (skb == NULL) {
5741f80842a8SMat Martineau BT_DBG("Seq %d not available for retransmission",
5742f80842a8SMat Martineau control->reqseq);
5743f80842a8SMat Martineau return;
5744f80842a8SMat Martineau }
5745f80842a8SMat Martineau
5746a4368ff3SJohan Hedberg if (chan->max_tx != 0 && bt_cb(skb)->l2cap.retries >= chan->max_tx) {
5747f80842a8SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
57485e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
5749f80842a8SMat Martineau return;
5750f80842a8SMat Martineau }
5751f80842a8SMat Martineau
5752f80842a8SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
5753f80842a8SMat Martineau
5754f80842a8SMat Martineau if (control->poll) {
5755f80842a8SMat Martineau l2cap_pass_to_tx(chan, control);
5756f80842a8SMat Martineau
5757f80842a8SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state);
5758f80842a8SMat Martineau l2cap_retransmit(chan, control);
5759f80842a8SMat Martineau l2cap_ertm_send(chan);
5760f80842a8SMat Martineau
5761f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
5762f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state);
5763f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq;
5764f80842a8SMat Martineau }
5765f80842a8SMat Martineau } else {
5766f80842a8SMat Martineau l2cap_pass_to_tx_fbit(chan, control);
5767f80842a8SMat Martineau
5768f80842a8SMat Martineau if (control->final) {
5769f80842a8SMat Martineau if (chan->srej_save_reqseq != control->reqseq ||
5770f80842a8SMat Martineau !test_and_clear_bit(CONN_SREJ_ACT,
5771f80842a8SMat Martineau &chan->conn_state))
5772f80842a8SMat Martineau l2cap_retransmit(chan, control);
5773f80842a8SMat Martineau } else {
5774f80842a8SMat Martineau l2cap_retransmit(chan, control);
5775f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
5776f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state);
5777f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq;
5778f80842a8SMat Martineau }
5779f80842a8SMat Martineau }
5780f80842a8SMat Martineau }
5781d2a7ac5dSMat Martineau }
5782d2a7ac5dSMat Martineau
5783d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan,
5784d2a7ac5dSMat Martineau struct l2cap_ctrl *control)
5785d2a7ac5dSMat Martineau {
5786fcd289dfSMat Martineau struct sk_buff *skb;
5787fcd289dfSMat Martineau
5788fcd289dfSMat Martineau BT_DBG("chan %p, control %p", chan, control);
5789fcd289dfSMat Martineau
5790fcd289dfSMat Martineau if (control->reqseq == chan->next_tx_seq) {
5791fcd289dfSMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
57925e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
5793fcd289dfSMat Martineau return;
5794fcd289dfSMat Martineau }
5795fcd289dfSMat Martineau
5796fcd289dfSMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
5797fcd289dfSMat Martineau
5798fcd289dfSMat Martineau if (chan->max_tx && skb &&
5799a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries >= chan->max_tx) {
5800fcd289dfSMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
58015e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
5802fcd289dfSMat Martineau return;
5803fcd289dfSMat Martineau }
5804fcd289dfSMat Martineau
5805fcd289dfSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
5806fcd289dfSMat Martineau
5807fcd289dfSMat Martineau l2cap_pass_to_tx(chan, control);
5808fcd289dfSMat Martineau
5809fcd289dfSMat Martineau if (control->final) {
5810fcd289dfSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
5811fcd289dfSMat Martineau l2cap_retransmit_all(chan, control);
5812fcd289dfSMat Martineau } else {
5813fcd289dfSMat Martineau l2cap_retransmit_all(chan, control);
5814fcd289dfSMat Martineau l2cap_ertm_send(chan);
5815fcd289dfSMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F)
5816fcd289dfSMat Martineau set_bit(CONN_REJ_ACT, &chan->conn_state);
5817fcd289dfSMat Martineau }
5818d2a7ac5dSMat Martineau }
5819d2a7ac5dSMat Martineau
58204b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
58214b51dae9SMat Martineau {
58224b51dae9SMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq);
58234b51dae9SMat Martineau
58244b51dae9SMat Martineau BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq,
58254b51dae9SMat Martineau chan->expected_tx_seq);
58264b51dae9SMat Martineau
l2cap_handle_rej(struct l2cap_chan * chan,struct l2cap_ctrl * control)58274b51dae9SMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
58284b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
58294b51dae9SMat Martineau chan->tx_win) {
58304b51dae9SMat Martineau /* See notes below regarding "double poll" and
58314b51dae9SMat Martineau * invalid packets.
58324b51dae9SMat Martineau */
58334b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
58344b51dae9SMat Martineau BT_DBG("Invalid/Ignore - after SREJ");
58354b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE;
58364b51dae9SMat Martineau } else {
58374b51dae9SMat Martineau BT_DBG("Invalid - in window after SREJ sent");
58384b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID;
58394b51dae9SMat Martineau }
58404b51dae9SMat Martineau }
58414b51dae9SMat Martineau
58424b51dae9SMat Martineau if (chan->srej_list.head == txseq) {
58434b51dae9SMat Martineau BT_DBG("Expected SREJ");
58444b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED_SREJ;
58454b51dae9SMat Martineau }
58464b51dae9SMat Martineau
58474b51dae9SMat Martineau if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) {
58484b51dae9SMat Martineau BT_DBG("Duplicate SREJ - txseq already stored");
58494b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE_SREJ;
58504b51dae9SMat Martineau }
58514b51dae9SMat Martineau
58524b51dae9SMat Martineau if (l2cap_seq_list_contains(&chan->srej_list, txseq)) {
58534b51dae9SMat Martineau BT_DBG("Unexpected SREJ - not requested");
58544b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED_SREJ;
58554b51dae9SMat Martineau }
58564b51dae9SMat Martineau }
58574b51dae9SMat Martineau
58584b51dae9SMat Martineau if (chan->expected_tx_seq == txseq) {
58594b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
58604b51dae9SMat Martineau chan->tx_win) {
58614b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window");
58624b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID;
58634b51dae9SMat Martineau } else {
l2cap_classify_txseq(struct l2cap_chan * chan,u16 txseq)58644b51dae9SMat Martineau BT_DBG("Expected");
58654b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED;
58664b51dae9SMat Martineau }
58674b51dae9SMat Martineau }
58684b51dae9SMat Martineau
58694b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) <
58702d792818SGustavo Padovan __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) {
58714b51dae9SMat Martineau BT_DBG("Duplicate - expected_tx_seq later than txseq");
58724b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE;
58734b51dae9SMat Martineau }
58744b51dae9SMat Martineau
58754b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) {
58764b51dae9SMat Martineau /* A source of invalid packets is a "double poll" condition,
58774b51dae9SMat Martineau * where delays cause us to send multiple poll packets. If
58784b51dae9SMat Martineau * the remote stack receives and processes both polls,
58794b51dae9SMat Martineau * sequence numbers can wrap around in such a way that a
58804b51dae9SMat Martineau * resent frame has a sequence number that looks like new data
58814b51dae9SMat Martineau * with a sequence gap. This would trigger an erroneous SREJ
58824b51dae9SMat Martineau * request.
58834b51dae9SMat Martineau *
58844b51dae9SMat Martineau * Fortunately, this is impossible with a tx window that's
58854b51dae9SMat Martineau * less than half of the maximum sequence number, which allows
58864b51dae9SMat Martineau * invalid frames to be safely ignored.
58874b51dae9SMat Martineau *
58884b51dae9SMat Martineau * With tx window sizes greater than half of the tx window
58894b51dae9SMat Martineau * maximum, the frame is invalid and cannot be ignored. This
58904b51dae9SMat Martineau * causes a disconnect.
58914b51dae9SMat Martineau */
58924b51dae9SMat Martineau
58934b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
58944b51dae9SMat Martineau BT_DBG("Invalid/Ignore - txseq outside tx window");
58954b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE;
58964b51dae9SMat Martineau } else {
58974b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window");
58984b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID;
58994b51dae9SMat Martineau }
59004b51dae9SMat Martineau } else {
59014b51dae9SMat Martineau BT_DBG("Unexpected - txseq indicates missing frames");
59024b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED;
59034b51dae9SMat Martineau }
59044b51dae9SMat Martineau }
59054b51dae9SMat Martineau
5906d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan,
5907d2a7ac5dSMat Martineau struct l2cap_ctrl *control,
5908d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event)
5909d2a7ac5dSMat Martineau {
59103aff8aacSMaxim Mikityanskiy struct l2cap_ctrl local_control;
5911d2a7ac5dSMat Martineau int err = 0;
5912941247f9SPeter Senna Tschudin bool skb_in_use = false;
5913d2a7ac5dSMat Martineau
5914d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
5915d2a7ac5dSMat Martineau event);
5916d2a7ac5dSMat Martineau
5917d2a7ac5dSMat Martineau switch (event) {
5918d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME:
5919d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, control->txseq)) {
5920d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED:
5921d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
5922d2a7ac5dSMat Martineau
5923d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
5924d2a7ac5dSMat Martineau BT_DBG("Busy, discarding expected seq %d",
5925d2a7ac5dSMat Martineau control->txseq);
5926d2a7ac5dSMat Martineau break;
5927d2a7ac5dSMat Martineau }
5928d2a7ac5dSMat Martineau
5929d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan,
5930d2a7ac5dSMat Martineau control->txseq);
5931d2a7ac5dSMat Martineau
5932d2a7ac5dSMat Martineau chan->buffer_seq = chan->expected_tx_seq;
5933941247f9SPeter Senna Tschudin skb_in_use = true;
5934d2a7ac5dSMat Martineau
59353aff8aacSMaxim Mikityanskiy /* l2cap_reassemble_sdu may free skb, hence invalidate
59363aff8aacSMaxim Mikityanskiy * control, so make a copy in advance to use it after
59373aff8aacSMaxim Mikityanskiy * l2cap_reassemble_sdu returns and to avoid the race
59383aff8aacSMaxim Mikityanskiy * condition, for example:
59393aff8aacSMaxim Mikityanskiy *
59403aff8aacSMaxim Mikityanskiy * The current thread calls:
59413aff8aacSMaxim Mikityanskiy * l2cap_reassemble_sdu
59423aff8aacSMaxim Mikityanskiy * chan->ops->recv == l2cap_sock_recv_cb
59433aff8aacSMaxim Mikityanskiy * __sock_queue_rcv_skb
59443aff8aacSMaxim Mikityanskiy * Another thread calls:
59453aff8aacSMaxim Mikityanskiy * bt_sock_recvmsg
59463aff8aacSMaxim Mikityanskiy * skb_recv_datagram
59473aff8aacSMaxim Mikityanskiy * skb_free_datagram
59483aff8aacSMaxim Mikityanskiy * Then the current thread tries to access control, but
59493aff8aacSMaxim Mikityanskiy * it was freed by skb_free_datagram.
l2cap_rx_state_recv(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff * skb,u8 event)59503aff8aacSMaxim Mikityanskiy */
59513aff8aacSMaxim Mikityanskiy local_control = *control;
5952d2a7ac5dSMat Martineau err = l2cap_reassemble_sdu(chan, skb, control);
5953d2a7ac5dSMat Martineau if (err)
5954d2a7ac5dSMat Martineau break;
5955d2a7ac5dSMat Martineau
59563aff8aacSMaxim Mikityanskiy if (local_control.final) {
5957d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT,
5958d2a7ac5dSMat Martineau &chan->conn_state)) {
59593aff8aacSMaxim Mikityanskiy local_control.final = 0;
59603aff8aacSMaxim Mikityanskiy l2cap_retransmit_all(chan, &local_control);
5961d2a7ac5dSMat Martineau l2cap_ertm_send(chan);
5962d2a7ac5dSMat Martineau }
5963d2a7ac5dSMat Martineau }
5964d2a7ac5dSMat Martineau
5965d2a7ac5dSMat Martineau if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
5966d2a7ac5dSMat Martineau l2cap_send_ack(chan);
5967d2a7ac5dSMat Martineau break;
5968d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED:
5969d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
5970d2a7ac5dSMat Martineau
5971d2a7ac5dSMat Martineau /* Can't issue SREJ frames in the local busy state.
5972d2a7ac5dSMat Martineau * Drop this frame, it will be seen as missing
5973d2a7ac5dSMat Martineau * when local busy is exited.
5974d2a7ac5dSMat Martineau */
5975d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
5976d2a7ac5dSMat Martineau BT_DBG("Busy, discarding unexpected seq %d",
5977d2a7ac5dSMat Martineau control->txseq);
5978d2a7ac5dSMat Martineau break;
5979d2a7ac5dSMat Martineau }
5980d2a7ac5dSMat Martineau
5981d2a7ac5dSMat Martineau /* There was a gap in the sequence, so an SREJ
5982d2a7ac5dSMat Martineau * must be sent for each missing frame. The
5983d2a7ac5dSMat Martineau * current frame is stored for later use.
5984d2a7ac5dSMat Martineau */
5985d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb);
5986941247f9SPeter Senna Tschudin skb_in_use = true;
5987d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb,
5988d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q));
5989d2a7ac5dSMat Martineau
5990d2a7ac5dSMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state);
5991d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->srej_list);
5992d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq);
5993d2a7ac5dSMat Martineau
5994d2a7ac5dSMat Martineau chan->rx_state = L2CAP_RX_STATE_SREJ_SENT;
5995d2a7ac5dSMat Martineau break;
5996d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE:
5997d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
5998d2a7ac5dSMat Martineau break;
5999d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE:
6000d2a7ac5dSMat Martineau break;
6001d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID:
6002d2a7ac5dSMat Martineau default:
60035e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
6004d2a7ac5dSMat Martineau break;
6005d2a7ac5dSMat Martineau }
6006d2a7ac5dSMat Martineau break;
6007d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR:
6008d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
6009d2a7ac5dSMat Martineau if (control->final) {
6010d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6011d2a7ac5dSMat Martineau
6012cd5d26a9SLuiz Augusto von Dentz if (!test_and_clear_bit(CONN_REJ_ACT,
6013cd5d26a9SLuiz Augusto von Dentz &chan->conn_state)) {
6014d2a7ac5dSMat Martineau control->final = 0;
6015d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control);
6016d2a7ac5dSMat Martineau }
6017d2a7ac5dSMat Martineau
6018d2a7ac5dSMat Martineau l2cap_ertm_send(chan);
6019d2a7ac5dSMat Martineau } else if (control->poll) {
6020d2a7ac5dSMat Martineau l2cap_send_i_or_rr_or_rnr(chan);
6021d2a7ac5dSMat Martineau } else {
6022d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY,
6023d2a7ac5dSMat Martineau &chan->conn_state) &&
6024d2a7ac5dSMat Martineau chan->unacked_frames)
6025d2a7ac5dSMat Martineau __set_retrans_timer(chan);
6026d2a7ac5dSMat Martineau
6027d2a7ac5dSMat Martineau l2cap_ertm_send(chan);
6028d2a7ac5dSMat Martineau }
6029d2a7ac5dSMat Martineau break;
6030d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR:
6031d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6032d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
6033d2a7ac5dSMat Martineau if (control && control->poll) {
6034d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state);
6035d2a7ac5dSMat Martineau l2cap_send_rr_or_rnr(chan, 0);
6036d2a7ac5dSMat Martineau }
6037d2a7ac5dSMat Martineau __clear_retrans_timer(chan);
6038d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->retrans_list);
6039d2a7ac5dSMat Martineau break;
6040d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ:
6041d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control);
6042d2a7ac5dSMat Martineau break;
6043d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ:
6044d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control);
6045d2a7ac5dSMat Martineau break;
6046d2a7ac5dSMat Martineau default:
6047d2a7ac5dSMat Martineau break;
6048d2a7ac5dSMat Martineau }
6049d2a7ac5dSMat Martineau
6050d2a7ac5dSMat Martineau if (skb && !skb_in_use) {
6051d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb);
6052d2a7ac5dSMat Martineau kfree_skb(skb);
6053d2a7ac5dSMat Martineau }
6054d2a7ac5dSMat Martineau
6055d2a7ac5dSMat Martineau return err;
6056d2a7ac5dSMat Martineau }
6057d2a7ac5dSMat Martineau
6058d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
6059d2a7ac5dSMat Martineau struct l2cap_ctrl *control,
6060d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event)
6061d2a7ac5dSMat Martineau {
6062d2a7ac5dSMat Martineau int err = 0;
6063d2a7ac5dSMat Martineau u16 txseq = control->txseq;
6064941247f9SPeter Senna Tschudin bool skb_in_use = false;
6065d2a7ac5dSMat Martineau
6066d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
6067d2a7ac5dSMat Martineau event);
6068d2a7ac5dSMat Martineau
6069d2a7ac5dSMat Martineau switch (event) {
6070d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME:
6071d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, txseq)) {
6072d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED:
6073d2a7ac5dSMat Martineau /* Keep frame for reassembly later */
6074d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
6075d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb);
6076941247f9SPeter Senna Tschudin skb_in_use = true;
6077d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb,
6078d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q));
6079d2a7ac5dSMat Martineau
6080d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq);
6081d2a7ac5dSMat Martineau break;
6082d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED_SREJ:
6083d2a7ac5dSMat Martineau l2cap_seq_list_pop(&chan->srej_list);
6084d2a7ac5dSMat Martineau
6085d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
6086d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb);
6087941247f9SPeter Senna Tschudin skb_in_use = true;
6088d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb,
6089d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q));
6090d2a7ac5dSMat Martineau
6091d2a7ac5dSMat Martineau err = l2cap_rx_queued_iframes(chan);
6092d2a7ac5dSMat Martineau if (err)
6093d2a7ac5dSMat Martineau break;
6094d2a7ac5dSMat Martineau
6095d2a7ac5dSMat Martineau break;
6096d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED:
6097d2a7ac5dSMat Martineau /* Got a frame that can't be reassembled yet.
6098d2a7ac5dSMat Martineau * Save it for later, and send SREJs to cover
6099d2a7ac5dSMat Martineau * the missing frames.
6100d2a7ac5dSMat Martineau */
6101d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb);
l2cap_rx_state_srej_sent(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff * skb,u8 event)6102941247f9SPeter Senna Tschudin skb_in_use = true;
6103d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb,
6104d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q));
6105d2a7ac5dSMat Martineau
6106d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
6107d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq);
6108d2a7ac5dSMat Martineau break;
6109d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED_SREJ:
6110d2a7ac5dSMat Martineau /* This frame was requested with an SREJ, but
6111d2a7ac5dSMat Martineau * some expected retransmitted frames are
6112d2a7ac5dSMat Martineau * missing. Request retransmission of missing
6113d2a7ac5dSMat Martineau * SREJ'd frames.
6114d2a7ac5dSMat Martineau */
6115d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb);
6116941247f9SPeter Senna Tschudin skb_in_use = true;
6117d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb,
6118d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q));
6119d2a7ac5dSMat Martineau
6120d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
6121d2a7ac5dSMat Martineau l2cap_send_srej_list(chan, control->txseq);
6122d2a7ac5dSMat Martineau break;
6123d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE_SREJ:
6124d2a7ac5dSMat Martineau /* We've already queued this frame. Drop this copy. */
6125d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
6126d2a7ac5dSMat Martineau break;
6127d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE:
6128d2a7ac5dSMat Martineau /* Expecting a later sequence number, so this frame
6129d2a7ac5dSMat Martineau * was already received. Ignore it completely.
6130d2a7ac5dSMat Martineau */
6131d2a7ac5dSMat Martineau break;
6132d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE:
6133d2a7ac5dSMat Martineau break;
6134d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID:
6135d2a7ac5dSMat Martineau default:
61365e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
6137d2a7ac5dSMat Martineau break;
6138d2a7ac5dSMat Martineau }
6139d2a7ac5dSMat Martineau break;
6140d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR:
6141d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
6142d2a7ac5dSMat Martineau if (control->final) {
6143d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6144d2a7ac5dSMat Martineau
6145d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT,
6146d2a7ac5dSMat Martineau &chan->conn_state)) {
6147d2a7ac5dSMat Martineau control->final = 0;
6148d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control);
6149d2a7ac5dSMat Martineau }
6150d2a7ac5dSMat Martineau
6151d2a7ac5dSMat Martineau l2cap_ertm_send(chan);
6152d2a7ac5dSMat Martineau } else if (control->poll) {
6153d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY,
6154d2a7ac5dSMat Martineau &chan->conn_state) &&
6155d2a7ac5dSMat Martineau chan->unacked_frames) {
6156d2a7ac5dSMat Martineau __set_retrans_timer(chan);
6157d2a7ac5dSMat Martineau }
6158d2a7ac5dSMat Martineau
6159d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state);
6160d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan);
6161d2a7ac5dSMat Martineau } else {
6162d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY,
6163d2a7ac5dSMat Martineau &chan->conn_state) &&
6164d2a7ac5dSMat Martineau chan->unacked_frames)
6165d2a7ac5dSMat Martineau __set_retrans_timer(chan);
6166d2a7ac5dSMat Martineau
6167d2a7ac5dSMat Martineau l2cap_send_ack(chan);
6168d2a7ac5dSMat Martineau }
6169d2a7ac5dSMat Martineau break;
6170d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR:
6171d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6172d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
6173d2a7ac5dSMat Martineau if (control->poll) {
6174d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan);
6175d2a7ac5dSMat Martineau } else {
6176d2a7ac5dSMat Martineau struct l2cap_ctrl rr_control;
6177d2a7ac5dSMat Martineau memset(&rr_control, 0, sizeof(rr_control));
6178d2a7ac5dSMat Martineau rr_control.sframe = 1;
6179d2a7ac5dSMat Martineau rr_control.super = L2CAP_SUPER_RR;
6180d2a7ac5dSMat Martineau rr_control.reqseq = chan->buffer_seq;
6181d2a7ac5dSMat Martineau l2cap_send_sframe(chan, &rr_control);
6182d2a7ac5dSMat Martineau }
6183d2a7ac5dSMat Martineau
6184d2a7ac5dSMat Martineau break;
6185d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ:
6186d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control);
6187d2a7ac5dSMat Martineau break;
6188d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ:
6189d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control);
6190d2a7ac5dSMat Martineau break;
6191d2a7ac5dSMat Martineau }
6192d2a7ac5dSMat Martineau
6193d2a7ac5dSMat Martineau if (skb && !skb_in_use) {
6194d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb);
6195d2a7ac5dSMat Martineau kfree_skb(skb);
6196d2a7ac5dSMat Martineau }
6197d2a7ac5dSMat Martineau
6198d2a7ac5dSMat Martineau return err;
6199d2a7ac5dSMat Martineau }
6200d2a7ac5dSMat Martineau
620132b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan)
620232b32735SMat Martineau {
620332b32735SMat Martineau BT_DBG("chan %p", chan);
620432b32735SMat Martineau
620532b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV;
6206ad3f7986SSungwoo Kim chan->conn->mtu = chan->conn->hcon->mtu;
620732b32735SMat Martineau
620832b32735SMat Martineau return l2cap_resegment(chan);
620932b32735SMat Martineau }
621032b32735SMat Martineau
621132b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan,
621232b32735SMat Martineau struct l2cap_ctrl *control,
621332b32735SMat Martineau struct sk_buff *skb, u8 event)
621432b32735SMat Martineau {
621532b32735SMat Martineau int err;
621632b32735SMat Martineau
621732b32735SMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
621832b32735SMat Martineau event);
621932b32735SMat Martineau
622032b32735SMat Martineau if (!control->poll)
622132b32735SMat Martineau return -EPROTO;
622232b32735SMat Martineau
622332b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq);
622432b32735SMat Martineau
622532b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q))
622632b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q);
622732b32735SMat Martineau else
622832b32735SMat Martineau chan->tx_send_head = NULL;
622932b32735SMat Martineau
623032b32735SMat Martineau /* Rewind next_tx_seq to the point expected
623132b32735SMat Martineau * by the receiver.
623232b32735SMat Martineau */
623332b32735SMat Martineau chan->next_tx_seq = control->reqseq;
623432b32735SMat Martineau chan->unacked_frames = 0;
623532b32735SMat Martineau
623632b32735SMat Martineau err = l2cap_finish_move(chan);
623732b32735SMat Martineau if (err)
623832b32735SMat Martineau return err;
623932b32735SMat Martineau
624032b32735SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state);
624132b32735SMat Martineau l2cap_send_i_or_rr_or_rnr(chan);
624232b32735SMat Martineau
624332b32735SMat Martineau if (event == L2CAP_EV_RECV_IFRAME)
624432b32735SMat Martineau return -EPROTO;
l2cap_finish_move(struct l2cap_chan * chan)624532b32735SMat Martineau
624632b32735SMat Martineau return l2cap_rx_state_recv(chan, control, NULL, event);
624732b32735SMat Martineau }
624832b32735SMat Martineau
624932b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan,
625032b32735SMat Martineau struct l2cap_ctrl *control,
625132b32735SMat Martineau struct sk_buff *skb, u8 event)
625232b32735SMat Martineau {
625332b32735SMat Martineau int err;
625432b32735SMat Martineau
l2cap_rx_state_wait_p(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff * skb,u8 event)625532b32735SMat Martineau if (!control->final)
625632b32735SMat Martineau return -EPROTO;
625732b32735SMat Martineau
625832b32735SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
625932b32735SMat Martineau
626032b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV;
626132b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq);
626232b32735SMat Martineau
626332b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q))
626432b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q);
626532b32735SMat Martineau else
626632b32735SMat Martineau chan->tx_send_head = NULL;
626732b32735SMat Martineau
626832b32735SMat Martineau /* Rewind next_tx_seq to the point expected
626932b32735SMat Martineau * by the receiver.
627032b32735SMat Martineau */
627132b32735SMat Martineau chan->next_tx_seq = control->reqseq;
627232b32735SMat Martineau chan->unacked_frames = 0;
6273ad3f7986SSungwoo Kim chan->conn->mtu = chan->conn->hcon->mtu;
627432b32735SMat Martineau
627532b32735SMat Martineau err = l2cap_resegment(chan);
627632b32735SMat Martineau
627732b32735SMat Martineau if (!err)
627832b32735SMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event);
627932b32735SMat Martineau
628032b32735SMat Martineau return err;
628132b32735SMat Martineau }
628232b32735SMat Martineau
6283d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
6284d2a7ac5dSMat Martineau {
6285d2a7ac5dSMat Martineau /* Make sure reqseq is for a packet that has been sent but not acked */
6286d2a7ac5dSMat Martineau u16 unacked;
6287d2a7ac5dSMat Martineau
6288d2a7ac5dSMat Martineau unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq);
6289d2a7ac5dSMat Martineau return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked;
6290d2a7ac5dSMat Martineau }
6291d2a7ac5dSMat Martineau
6292cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
l2cap_rx_state_wait_f(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff * skb,u8 event)6293cec8ab6eSMat Martineau struct sk_buff *skb, u8 event)
62940a708f8fSGustavo F. Padovan {
6295d2a7ac5dSMat Martineau int err = 0;
6296d2a7ac5dSMat Martineau
6297d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan,
6298d2a7ac5dSMat Martineau control, skb, event, chan->rx_state);
6299d2a7ac5dSMat Martineau
6300d2a7ac5dSMat Martineau if (__valid_reqseq(chan, control->reqseq)) {
6301d2a7ac5dSMat Martineau switch (chan->rx_state) {
6302d2a7ac5dSMat Martineau case L2CAP_RX_STATE_RECV:
6303d2a7ac5dSMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event);
6304d2a7ac5dSMat Martineau break;
6305d2a7ac5dSMat Martineau case L2CAP_RX_STATE_SREJ_SENT:
6306d2a7ac5dSMat Martineau err = l2cap_rx_state_srej_sent(chan, control, skb,
6307d2a7ac5dSMat Martineau event);
6308d2a7ac5dSMat Martineau break;
630932b32735SMat Martineau case L2CAP_RX_STATE_WAIT_P:
631032b32735SMat Martineau err = l2cap_rx_state_wait_p(chan, control, skb, event);
631132b32735SMat Martineau break;
631232b32735SMat Martineau case L2CAP_RX_STATE_WAIT_F:
631332b32735SMat Martineau err = l2cap_rx_state_wait_f(chan, control, skb, event);
631432b32735SMat Martineau break;
6315d2a7ac5dSMat Martineau default:
6316d2a7ac5dSMat Martineau /* shut it down */
6317d2a7ac5dSMat Martineau break;
6318d2a7ac5dSMat Martineau }
6319d2a7ac5dSMat Martineau } else {
6320d2a7ac5dSMat Martineau BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d",
6321d2a7ac5dSMat Martineau control->reqseq, chan->next_tx_seq,
6322d2a7ac5dSMat Martineau chan->expected_ack_seq);
63235e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
6324d2a7ac5dSMat Martineau }
6325d2a7ac5dSMat Martineau
6326d2a7ac5dSMat Martineau return err;
6327cec8ab6eSMat Martineau }
6328cec8ab6eSMat Martineau
6329cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
6330cec8ab6eSMat Martineau struct sk_buff *skb)
6331cec8ab6eSMat Martineau {
63323aff8aacSMaxim Mikityanskiy /* l2cap_reassemble_sdu may free skb, hence invalidate control, so store
63333aff8aacSMaxim Mikityanskiy * the txseq field in advance to use it after l2cap_reassemble_sdu
63343aff8aacSMaxim Mikityanskiy * returns and to avoid the race condition, for example:
63353aff8aacSMaxim Mikityanskiy *
l2cap_rx(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff * skb,u8 event)63363aff8aacSMaxim Mikityanskiy * The current thread calls:
63373aff8aacSMaxim Mikityanskiy * l2cap_reassemble_sdu
63383aff8aacSMaxim Mikityanskiy * chan->ops->recv == l2cap_sock_recv_cb
63393aff8aacSMaxim Mikityanskiy * __sock_queue_rcv_skb
63403aff8aacSMaxim Mikityanskiy * Another thread calls:
63413aff8aacSMaxim Mikityanskiy * bt_sock_recvmsg
63423aff8aacSMaxim Mikityanskiy * skb_recv_datagram
63433aff8aacSMaxim Mikityanskiy * skb_free_datagram
63443aff8aacSMaxim Mikityanskiy * Then the current thread tries to access control, but it was freed by
63453aff8aacSMaxim Mikityanskiy * skb_free_datagram.
63463aff8aacSMaxim Mikityanskiy */
63473aff8aacSMaxim Mikityanskiy u16 txseq = control->txseq;
63483aff8aacSMaxim Mikityanskiy
63494b51dae9SMat Martineau BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
63504b51dae9SMat Martineau chan->rx_state);
63514b51dae9SMat Martineau
63523aff8aacSMaxim Mikityanskiy if (l2cap_classify_txseq(chan, txseq) == L2CAP_TXSEQ_EXPECTED) {
63534b51dae9SMat Martineau l2cap_pass_to_tx(chan, control);
63544b51dae9SMat Martineau
635593917fd2SKai Ye BT_DBG("buffer_seq %u->%u", chan->buffer_seq,
63564b51dae9SMat Martineau __next_seq(chan, chan->buffer_seq));
63574b51dae9SMat Martineau
63584b51dae9SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
63594b51dae9SMat Martineau
63604b51dae9SMat Martineau l2cap_reassemble_sdu(chan, skb, control);
63614b51dae9SMat Martineau } else {
63624b51dae9SMat Martineau if (chan->sdu) {
63634b51dae9SMat Martineau kfree_skb(chan->sdu);
63644b51dae9SMat Martineau chan->sdu = NULL;
63654b51dae9SMat Martineau }
63664b51dae9SMat Martineau chan->sdu_last_frag = NULL;
63674b51dae9SMat Martineau chan->sdu_len = 0;
63684b51dae9SMat Martineau
63694b51dae9SMat Martineau if (skb) {
63704b51dae9SMat Martineau BT_DBG("Freeing %p", skb);
63714b51dae9SMat Martineau kfree_skb(skb);
63724b51dae9SMat Martineau }
l2cap_stream_rx(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff * skb)63734b51dae9SMat Martineau }
63744b51dae9SMat Martineau
63753aff8aacSMaxim Mikityanskiy chan->last_acked_seq = txseq;
63763aff8aacSMaxim Mikityanskiy chan->expected_tx_seq = __next_seq(chan, txseq);
63774b51dae9SMat Martineau
63789a544210SPrasanna Karthik return 0;
6379cec8ab6eSMat Martineau }
6380cec8ab6eSMat Martineau
6381cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
6382cec8ab6eSMat Martineau {
6383a4368ff3SJohan Hedberg struct l2cap_ctrl *control = &bt_cb(skb)->l2cap;
6384cec8ab6eSMat Martineau u16 len;
6385cec8ab6eSMat Martineau u8 event;
63860a708f8fSGustavo F. Padovan
6387b76bbd66SMat Martineau __unpack_control(chan, skb);
6388b76bbd66SMat Martineau
63890a708f8fSGustavo F. Padovan len = skb->len;
63900a708f8fSGustavo F. Padovan
63910a708f8fSGustavo F. Padovan /*
63920a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here.
63930a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery
6394cec8ab6eSMat Martineau * procedures and ask for retransmission.
63950a708f8fSGustavo F. Padovan */
639647d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb))
63970a708f8fSGustavo F. Padovan goto drop;
63980a708f8fSGustavo F. Padovan
6399cec8ab6eSMat Martineau if (!control->sframe && control->sar == L2CAP_SAR_START)
640003a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE;
64010a708f8fSGustavo F. Padovan
640247d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16)
640303a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE;
64040a708f8fSGustavo F. Padovan
640547d1ec61SGustavo F. Padovan if (len > chan->mps) {
64065e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
64070a708f8fSGustavo F. Padovan goto drop;
64080a708f8fSGustavo F. Padovan }
64090a708f8fSGustavo F. Padovan
6410f1942564SLuiz Augusto von Dentz if (chan->ops->filter) {
6411f1942564SLuiz Augusto von Dentz if (chan->ops->filter(chan, skb))
6412dbb50887SDaniel Borkmann goto drop;
6413f1942564SLuiz Augusto von Dentz }
6414dbb50887SDaniel Borkmann
6415cec8ab6eSMat Martineau if (!control->sframe) {
6416cec8ab6eSMat Martineau int err;
64170a708f8fSGustavo F. Padovan
6418cec8ab6eSMat Martineau BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d",
6419cec8ab6eSMat Martineau control->sar, control->reqseq, control->final,
6420cec8ab6eSMat Martineau control->txseq);
6421836be934SAndrei Emeltchenko
6422cec8ab6eSMat Martineau /* Validate F-bit - F=0 always valid, F=1 only
6423cec8ab6eSMat Martineau * valid in TX WAIT_F
6424cec8ab6eSMat Martineau */
l2cap_data_rcv(struct l2cap_chan * chan,struct sk_buff * skb)6425cec8ab6eSMat Martineau if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F)
64260a708f8fSGustavo F. Padovan goto drop;
64270a708f8fSGustavo F. Padovan
6428cec8ab6eSMat Martineau if (chan->mode != L2CAP_MODE_STREAMING) {
6429cec8ab6eSMat Martineau event = L2CAP_EV_RECV_IFRAME;
6430cec8ab6eSMat Martineau err = l2cap_rx(chan, control, skb, event);
64310a708f8fSGustavo F. Padovan } else {
6432cec8ab6eSMat Martineau err = l2cap_stream_rx(chan, control, skb);
6433cec8ab6eSMat Martineau }
6434cec8ab6eSMat Martineau
6435cec8ab6eSMat Martineau if (err)
64365e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
6437cec8ab6eSMat Martineau } else {
6438cec8ab6eSMat Martineau const u8 rx_func_to_event[4] = {
6439cec8ab6eSMat Martineau L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
6440cec8ab6eSMat Martineau L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ
6441cec8ab6eSMat Martineau };
6442cec8ab6eSMat Martineau
6443cec8ab6eSMat Martineau /* Only I-frames are expected in streaming mode */
6444cec8ab6eSMat Martineau if (chan->mode == L2CAP_MODE_STREAMING)
6445cec8ab6eSMat Martineau goto drop;
6446cec8ab6eSMat Martineau
6447cec8ab6eSMat Martineau BT_DBG("sframe reqseq %d, final %d, poll %d, super %d",
6448cec8ab6eSMat Martineau control->reqseq, control->final, control->poll,
6449cec8ab6eSMat Martineau control->super);
6450cec8ab6eSMat Martineau
64510a708f8fSGustavo F. Padovan if (len != 0) {
64521bb166e6SAndrei Emeltchenko BT_ERR("Trailing bytes: %d in sframe", len);
64535e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
64540a708f8fSGustavo F. Padovan goto drop;
64550a708f8fSGustavo F. Padovan }
64560a708f8fSGustavo F. Padovan
6457cec8ab6eSMat Martineau /* Validate F and P bits */
6458cec8ab6eSMat Martineau if (control->final && (control->poll ||
6459cec8ab6eSMat Martineau chan->tx_state != L2CAP_TX_STATE_WAIT_F))
6460cec8ab6eSMat Martineau goto drop;
6461cec8ab6eSMat Martineau
6462cec8ab6eSMat Martineau event = rx_func_to_event[control->super];
6463cec8ab6eSMat Martineau if (l2cap_rx(chan, control, skb, event))
64645e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
64650a708f8fSGustavo F. Padovan }
64660a708f8fSGustavo F. Padovan
64670a708f8fSGustavo F. Padovan return 0;
64680a708f8fSGustavo F. Padovan
64690a708f8fSGustavo F. Padovan drop:
64700a708f8fSGustavo F. Padovan kfree_skb(skb);
64710a708f8fSGustavo F. Padovan return 0;
64720a708f8fSGustavo F. Padovan }
64730a708f8fSGustavo F. Padovan
6474b1c325c2SJohan Hedberg static void l2cap_chan_le_send_credits(struct l2cap_chan *chan)
6475b1c325c2SJohan Hedberg {
6476b1c325c2SJohan Hedberg struct l2cap_conn *conn = chan->conn;
6477b1c325c2SJohan Hedberg struct l2cap_le_credits pkt;
6478e2310343SSebastian Urban u16 return_credits = l2cap_le_rx_credits(chan);
6479b1c325c2SJohan Hedberg
648015f02b91SLuiz Augusto von Dentz if (chan->rx_credits >= return_credits)
648196cd8eaaSLuiz Augusto von Dentz return;
6482b1c325c2SJohan Hedberg
648315f02b91SLuiz Augusto von Dentz return_credits -= chan->rx_credits;
648415f02b91SLuiz Augusto von Dentz
6485b1c325c2SJohan Hedberg BT_DBG("chan %p returning %u credits to sender", chan, return_credits);
6486b1c325c2SJohan Hedberg
6487b1c325c2SJohan Hedberg chan->rx_credits += return_credits;
6488b1c325c2SJohan Hedberg
6489b1c325c2SJohan Hedberg pkt.cid = cpu_to_le16(chan->scid);
6490b1c325c2SJohan Hedberg pkt.credits = cpu_to_le16(return_credits);
6491b1c325c2SJohan Hedberg
6492b1c325c2SJohan Hedberg chan->ident = l2cap_get_ident(conn);
6493b1c325c2SJohan Hedberg
6494b1c325c2SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt);
6495b1c325c2SJohan Hedberg }
6496b1c325c2SJohan Hedberg
6497e2310343SSebastian Urban void l2cap_chan_rx_avail(struct l2cap_chan *chan, ssize_t rx_avail)
6498e2310343SSebastian Urban {
6499e2310343SSebastian Urban if (chan->rx_avail == rx_avail)
6500e2310343SSebastian Urban return;
6501e2310343SSebastian Urban
6502e2310343SSebastian Urban BT_DBG("chan %p has %zd bytes avail for rx", chan, rx_avail);
6503e2310343SSebastian Urban
6504e2310343SSebastian Urban chan->rx_avail = rx_avail;
6505e2310343SSebastian Urban
6506e2310343SSebastian Urban if (chan->state == BT_CONNECTED)
6507e2310343SSebastian Urban l2cap_chan_le_send_credits(chan);
6508e2310343SSebastian Urban }
6509e2310343SSebastian Urban
651015f02b91SLuiz Augusto von Dentz static int l2cap_ecred_recv(struct l2cap_chan *chan, struct sk_buff *skb)
651196cd8eaaSLuiz Augusto von Dentz {
651296cd8eaaSLuiz Augusto von Dentz int err;
651396cd8eaaSLuiz Augusto von Dentz
651496cd8eaaSLuiz Augusto von Dentz BT_DBG("SDU reassemble complete: chan %p skb->len %u", chan, skb->len);
651596cd8eaaSLuiz Augusto von Dentz
651696cd8eaaSLuiz Augusto von Dentz /* Wait recv to confirm reception before updating the credits */
651796cd8eaaSLuiz Augusto von Dentz err = chan->ops->recv(chan, skb);
l2cap_chan_le_send_credits(struct l2cap_chan * chan)651896cd8eaaSLuiz Augusto von Dentz
6519e2310343SSebastian Urban if (err < 0 && chan->rx_avail != -1) {
6520e2310343SSebastian Urban BT_ERR("Queueing received LE L2CAP data failed");
6521e2310343SSebastian Urban l2cap_send_disconn_req(chan, ECONNRESET);
6522e2310343SSebastian Urban return err;
6523e2310343SSebastian Urban }
6524e2310343SSebastian Urban
652596cd8eaaSLuiz Augusto von Dentz /* Update credits whenever an SDU is received */
652696cd8eaaSLuiz Augusto von Dentz l2cap_chan_le_send_credits(chan);
652796cd8eaaSLuiz Augusto von Dentz
652896cd8eaaSLuiz Augusto von Dentz return err;
652996cd8eaaSLuiz Augusto von Dentz }
653096cd8eaaSLuiz Augusto von Dentz
653115f02b91SLuiz Augusto von Dentz static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
6532fad5fc89SJohan Hedberg {
6533aac23bf6SJohan Hedberg int err;
6534fad5fc89SJohan Hedberg
6535aac23bf6SJohan Hedberg if (!chan->rx_credits) {
6536aac23bf6SJohan Hedberg BT_ERR("No credits to receive LE L2CAP data");
6537dfd9774cSJohan Hedberg l2cap_send_disconn_req(chan, ECONNRESET);
6538fad5fc89SJohan Hedberg return -ENOBUFS;
6539aac23bf6SJohan Hedberg }
6540aac23bf6SJohan Hedberg
l2cap_chan_rx_avail(struct l2cap_chan * chan,ssize_t rx_avail)6541aac23bf6SJohan Hedberg if (chan->imtu < skb->len) {
6542aac23bf6SJohan Hedberg BT_ERR("Too big LE L2CAP PDU");
6543aac23bf6SJohan Hedberg return -ENOBUFS;
6544aac23bf6SJohan Hedberg }
6545fad5fc89SJohan Hedberg
6546fad5fc89SJohan Hedberg chan->rx_credits--;
6547e2310343SSebastian Urban BT_DBG("chan %p: rx_credits %u -> %u",
6548e2310343SSebastian Urban chan, chan->rx_credits + 1, chan->rx_credits);
6549fad5fc89SJohan Hedberg
655096cd8eaaSLuiz Augusto von Dentz /* Update if remote had run out of credits, this should only happens
655196cd8eaaSLuiz Augusto von Dentz * if the remote is not using the entire MPS.
655296cd8eaaSLuiz Augusto von Dentz */
655396cd8eaaSLuiz Augusto von Dentz if (!chan->rx_credits)
l2cap_ecred_recv(struct l2cap_chan * chan,struct sk_buff * skb)6554fad5fc89SJohan Hedberg l2cap_chan_le_send_credits(chan);
6555fad5fc89SJohan Hedberg
6556aac23bf6SJohan Hedberg err = 0;
6557aac23bf6SJohan Hedberg
6558aac23bf6SJohan Hedberg if (!chan->sdu) {
6559aac23bf6SJohan Hedberg u16 sdu_len;
6560aac23bf6SJohan Hedberg
6561aac23bf6SJohan Hedberg sdu_len = get_unaligned_le16(skb->data);
6562aac23bf6SJohan Hedberg skb_pull(skb, L2CAP_SDULEN_SIZE);
6563aac23bf6SJohan Hedberg
6564aac23bf6SJohan Hedberg BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u",
6565aac23bf6SJohan Hedberg sdu_len, skb->len, chan->imtu);
6566aac23bf6SJohan Hedberg
6567aac23bf6SJohan Hedberg if (sdu_len > chan->imtu) {
6568aac23bf6SJohan Hedberg BT_ERR("Too big LE L2CAP SDU length received");
6569aac23bf6SJohan Hedberg err = -EMSGSIZE;
6570aac23bf6SJohan Hedberg goto failed;
6571aac23bf6SJohan Hedberg }
6572aac23bf6SJohan Hedberg
6573aac23bf6SJohan Hedberg if (skb->len > sdu_len) {
6574aac23bf6SJohan Hedberg BT_ERR("Too much LE L2CAP data received");
l2cap_ecred_data_rcv(struct l2cap_chan * chan,struct sk_buff * skb)6575aac23bf6SJohan Hedberg err = -EINVAL;
6576aac23bf6SJohan Hedberg goto failed;
6577aac23bf6SJohan Hedberg }
6578aac23bf6SJohan Hedberg
6579aac23bf6SJohan Hedberg if (skb->len == sdu_len)
658015f02b91SLuiz Augusto von Dentz return l2cap_ecred_recv(chan, skb);
6581aac23bf6SJohan Hedberg
6582aac23bf6SJohan Hedberg chan->sdu = skb;
6583aac23bf6SJohan Hedberg chan->sdu_len = sdu_len;
6584aac23bf6SJohan Hedberg chan->sdu_last_frag = skb;
6585aac23bf6SJohan Hedberg
6586a5c3021bSLuiz Augusto von Dentz /* Detect if remote is not able to use the selected MPS */
6587a5c3021bSLuiz Augusto von Dentz if (skb->len + L2CAP_SDULEN_SIZE < chan->mps) {
6588a5c3021bSLuiz Augusto von Dentz u16 mps_len = skb->len + L2CAP_SDULEN_SIZE;
6589a5c3021bSLuiz Augusto von Dentz
6590a5c3021bSLuiz Augusto von Dentz /* Adjust the number of credits */
6591a5c3021bSLuiz Augusto von Dentz BT_DBG("chan->mps %u -> %u", chan->mps, mps_len);
6592a5c3021bSLuiz Augusto von Dentz chan->mps = mps_len;
6593a5c3021bSLuiz Augusto von Dentz l2cap_chan_le_send_credits(chan);
6594a5c3021bSLuiz Augusto von Dentz }
6595a5c3021bSLuiz Augusto von Dentz
6596aac23bf6SJohan Hedberg return 0;
6597aac23bf6SJohan Hedberg }
6598aac23bf6SJohan Hedberg
6599aac23bf6SJohan Hedberg BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u",
6600aac23bf6SJohan Hedberg chan->sdu->len, skb->len, chan->sdu_len);
6601aac23bf6SJohan Hedberg
6602aac23bf6SJohan Hedberg if (chan->sdu->len + skb->len > chan->sdu_len) {
6603aac23bf6SJohan Hedberg BT_ERR("Too much LE L2CAP data received");
6604aac23bf6SJohan Hedberg err = -EINVAL;
6605aac23bf6SJohan Hedberg goto failed;
6606aac23bf6SJohan Hedberg }
6607aac23bf6SJohan Hedberg
6608aac23bf6SJohan Hedberg append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag);
6609aac23bf6SJohan Hedberg skb = NULL;
6610aac23bf6SJohan Hedberg
6611aac23bf6SJohan Hedberg if (chan->sdu->len == chan->sdu_len) {
661215f02b91SLuiz Augusto von Dentz err = l2cap_ecred_recv(chan, chan->sdu);
6613aac23bf6SJohan Hedberg if (!err) {
6614aac23bf6SJohan Hedberg chan->sdu = NULL;
6615aac23bf6SJohan Hedberg chan->sdu_last_frag = NULL;
6616aac23bf6SJohan Hedberg chan->sdu_len = 0;
6617aac23bf6SJohan Hedberg }
6618aac23bf6SJohan Hedberg }
6619aac23bf6SJohan Hedberg
6620aac23bf6SJohan Hedberg failed:
6621aac23bf6SJohan Hedberg if (err) {
6622aac23bf6SJohan Hedberg kfree_skb(skb);
6623aac23bf6SJohan Hedberg kfree_skb(chan->sdu);
6624aac23bf6SJohan Hedberg chan->sdu = NULL;
6625aac23bf6SJohan Hedberg chan->sdu_last_frag = NULL;
6626aac23bf6SJohan Hedberg chan->sdu_len = 0;
6627aac23bf6SJohan Hedberg }
6628aac23bf6SJohan Hedberg
6629aac23bf6SJohan Hedberg /* We can't return an error here since we took care of the skb
6630aac23bf6SJohan Hedberg * freeing internally. An error return would cause the caller to
6631aac23bf6SJohan Hedberg * do a double-free of the skb.
6632aac23bf6SJohan Hedberg */
6633aac23bf6SJohan Hedberg return 0;
6634fad5fc89SJohan Hedberg }
6635fad5fc89SJohan Hedberg
663613ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
663713ca56e0SAndrei Emeltchenko struct sk_buff *skb)
66380a708f8fSGustavo F. Padovan {
663948454079SGustavo F. Padovan struct l2cap_chan *chan;
66400a708f8fSGustavo F. Padovan
6641baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid);
664248454079SGustavo F. Padovan if (!chan) {
66430a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid);
66446be36555SAndrei Emeltchenko /* Drop packet and return */
66453379013bSDan Carpenter kfree_skb(skb);
664613ca56e0SAndrei Emeltchenko return;
66470a708f8fSGustavo F. Padovan }
66480a708f8fSGustavo F. Padovan
664949208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len);
66500a708f8fSGustavo F. Padovan
6651315917e0SJohan Hedberg /* If we receive data on a fixed channel before the info req/rsp
66525153ceb9SBhaskar Chowdhury * procedure is done simply assume that the channel is supported
6653315917e0SJohan Hedberg * and mark it as ready.
6654315917e0SJohan Hedberg */
6655315917e0SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_FIXED)
6656315917e0SJohan Hedberg l2cap_chan_ready(chan);
6657315917e0SJohan Hedberg
665889bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED)
66590a708f8fSGustavo F. Padovan goto drop;
66600a708f8fSGustavo F. Padovan
66610c1bc5c6SGustavo F. Padovan switch (chan->mode) {
666238319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL:
666315f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL:
666415f02b91SLuiz Augusto von Dentz if (l2cap_ecred_data_rcv(chan, skb) < 0)
6665fad5fc89SJohan Hedberg goto drop;
6666fad5fc89SJohan Hedberg
6667fad5fc89SJohan Hedberg goto done;
6668fad5fc89SJohan Hedberg
66690a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC:
66700a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here
66710a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable.
66720a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't
66730a708f8fSGustavo F. Padovan * provide flow control mechanism. */
66740a708f8fSGustavo F. Padovan
66752c96e03dSSzymon Janc if (chan->imtu < skb->len) {
66762c96e03dSSzymon Janc BT_ERR("Dropping L2CAP data: receive buffer overflow");
66770a708f8fSGustavo F. Padovan goto drop;
66782c96e03dSSzymon Janc }
66790a708f8fSGustavo F. Padovan
l2cap_data_channel(struct l2cap_conn * conn,u16 cid,struct sk_buff * skb)668080b98027SGustavo Padovan if (!chan->ops->recv(chan, skb))
66810a708f8fSGustavo F. Padovan goto done;
66820a708f8fSGustavo F. Padovan break;
66830a708f8fSGustavo F. Padovan
66840a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM:
66850a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING:
6686cec8ab6eSMat Martineau l2cap_data_rcv(chan, skb);
66870a708f8fSGustavo F. Padovan goto done;
66880a708f8fSGustavo F. Padovan
66890a708f8fSGustavo F. Padovan default:
66900c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
66910a708f8fSGustavo F. Padovan break;
66920a708f8fSGustavo F. Padovan }
66930a708f8fSGustavo F. Padovan
66940a708f8fSGustavo F. Padovan drop:
66950a708f8fSGustavo F. Padovan kfree_skb(skb);
66960a708f8fSGustavo F. Padovan
66970a708f8fSGustavo F. Padovan done:
66986be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
6699d0be8347SLuiz Augusto von Dentz l2cap_chan_put(chan);
67000a708f8fSGustavo F. Padovan }
67010a708f8fSGustavo F. Padovan
670284104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
670384104b24SAndrei Emeltchenko struct sk_buff *skb)
67040a708f8fSGustavo F. Padovan {
6705ae4fd2d3SMarcel Holtmann struct hci_conn *hcon = conn->hcon;
670623691d75SGustavo F. Padovan struct l2cap_chan *chan;
67070a708f8fSGustavo F. Padovan
6708ae4fd2d3SMarcel Holtmann if (hcon->type != ACL_LINK)
6709a24cce14SJohan Hedberg goto free_skb;
6710ae4fd2d3SMarcel Holtmann
6711bf20fd4eSJohan Hedberg chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst,
6712bf20fd4eSJohan Hedberg ACL_LINK);
671323691d75SGustavo F. Padovan if (!chan)
6714a24cce14SJohan Hedberg goto free_skb;
67150a708f8fSGustavo F. Padovan
67165b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len);
67170a708f8fSGustavo F. Padovan
6718b0fc1bd2SLuiz Augusto von Dentz l2cap_chan_lock(chan);
6719b0fc1bd2SLuiz Augusto von Dentz
672089bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
67210a708f8fSGustavo F. Padovan goto drop;
67220a708f8fSGustavo F. Padovan
6723e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len)
67240a708f8fSGustavo F. Padovan goto drop;
67250a708f8fSGustavo F. Padovan
67262edf870dSMarcel Holtmann /* Store remote BD_ADDR and PSM for msg_name */
6727a4368ff3SJohan Hedberg bacpy(&bt_cb(skb)->l2cap.bdaddr, &hcon->dst);
6728a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.psm = psm;
67292edf870dSMarcel Holtmann
6730a24cce14SJohan Hedberg if (!chan->ops->recv(chan, skb)) {
6731b4af69d5SDmitry Antipov l2cap_chan_unlock(chan);
6732a24cce14SJohan Hedberg l2cap_chan_put(chan);
673384104b24SAndrei Emeltchenko return;
6734a24cce14SJohan Hedberg }
67350a708f8fSGustavo F. Padovan
67360a708f8fSGustavo F. Padovan drop:
6737b0fc1bd2SLuiz Augusto von Dentz l2cap_chan_unlock(chan);
6738a24cce14SJohan Hedberg l2cap_chan_put(chan);
6739a24cce14SJohan Hedberg free_skb:
67400a708f8fSGustavo F. Padovan kfree_skb(skb);
67410a708f8fSGustavo F. Padovan }
67420a708f8fSGustavo F. Padovan
67430a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
67440a708f8fSGustavo F. Padovan {
67450a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data;
l2cap_conless_channel(struct l2cap_conn * conn,__le16 psm,struct sk_buff * skb)674661a939c6SJohan Hedberg struct hci_conn *hcon = conn->hcon;
67470a708f8fSGustavo F. Padovan u16 cid, len;
67480a708f8fSGustavo F. Padovan __le16 psm;
67490a708f8fSGustavo F. Padovan
675061a939c6SJohan Hedberg if (hcon->state != BT_CONNECTED) {
675161a939c6SJohan Hedberg BT_DBG("queueing pending rx skb");
675261a939c6SJohan Hedberg skb_queue_tail(&conn->pending_rx, skb);
675361a939c6SJohan Hedberg return;
675461a939c6SJohan Hedberg }
675561a939c6SJohan Hedberg
67560a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE);
67570a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid);
67580a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len);
67590a708f8fSGustavo F. Padovan
67600a708f8fSGustavo F. Padovan if (len != skb->len) {
67610a708f8fSGustavo F. Padovan kfree_skb(skb);
67620a708f8fSGustavo F. Padovan return;
67630a708f8fSGustavo F. Padovan }
67640a708f8fSGustavo F. Padovan
67659e1d7e15SJohan Hedberg /* Since we can't actively block incoming LE connections we must
67669e1d7e15SJohan Hedberg * at least ensure that we ignore incoming data from them.
67679e1d7e15SJohan Hedberg */
67689e1d7e15SJohan Hedberg if (hcon->type == LE_LINK &&
67693d4f9c00SArchie Pusaka hci_bdaddr_list_lookup(&hcon->hdev->reject_list, &hcon->dst,
6770a250e048SJohan Hedberg bdaddr_dst_type(hcon))) {
6771e493150eSJohan Hedberg kfree_skb(skb);
6772e493150eSJohan Hedberg return;
6773e493150eSJohan Hedberg }
6774e493150eSJohan Hedberg
67750a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid);
67760a708f8fSGustavo F. Padovan
67770a708f8fSGustavo F. Padovan switch (cid) {
67780a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING:
67790a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb);
67800a708f8fSGustavo F. Padovan break;
67810a708f8fSGustavo F. Padovan
67820a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS:
6783097db76cSAndrei Emeltchenko psm = get_unaligned((__le16 *) skb->data);
67840181a70fSAndrei Emeltchenko skb_pull(skb, L2CAP_PSMLEN_SIZE);
67850a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb);
67860a708f8fSGustavo F. Padovan break;
l2cap_recv_frame(struct l2cap_conn * conn,struct sk_buff * skb)67870a708f8fSGustavo F. Padovan
6788a2877629SMarcel Holtmann case L2CAP_CID_LE_SIGNALING:
6789a2877629SMarcel Holtmann l2cap_le_sig_channel(conn, skb);
6790a2877629SMarcel Holtmann break;
6791a2877629SMarcel Holtmann
67920a708f8fSGustavo F. Padovan default:
67930a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb);
67940a708f8fSGustavo F. Padovan break;
67950a708f8fSGustavo F. Padovan }
67960a708f8fSGustavo F. Padovan }
67970a708f8fSGustavo F. Padovan
679861a939c6SJohan Hedberg static void process_pending_rx(struct work_struct *work)
679961a939c6SJohan Hedberg {
680061a939c6SJohan Hedberg struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
680161a939c6SJohan Hedberg pending_rx_work);
680261a939c6SJohan Hedberg struct sk_buff *skb;
680361a939c6SJohan Hedberg
680461a939c6SJohan Hedberg BT_DBG("");
680561a939c6SJohan Hedberg
6806*efc30877SLuiz Augusto von Dentz mutex_lock(&conn->lock);
6807*efc30877SLuiz Augusto von Dentz
680861a939c6SJohan Hedberg while ((skb = skb_dequeue(&conn->pending_rx)))
680961a939c6SJohan Hedberg l2cap_recv_frame(conn, skb);
6810*efc30877SLuiz Augusto von Dentz
6811*efc30877SLuiz Augusto von Dentz mutex_unlock(&conn->lock);
681261a939c6SJohan Hedberg }
681361a939c6SJohan Hedberg
6814162b49e7SJohan Hedberg static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
6815162b49e7SJohan Hedberg {
6816162b49e7SJohan Hedberg struct l2cap_conn *conn = hcon->l2cap_data;
6817162b49e7SJohan Hedberg struct hci_chan *hchan;
6818162b49e7SJohan Hedberg
6819162b49e7SJohan Hedberg if (conn)
6820162b49e7SJohan Hedberg return conn;
6821162b49e7SJohan Hedberg
6822162b49e7SJohan Hedberg hchan = hci_chan_create(hcon);
6823162b49e7SJohan Hedberg if (!hchan)
6824162b49e7SJohan Hedberg return NULL;
6825162b49e7SJohan Hedberg
682627f70f3eSJohan Hedberg conn = kzalloc(sizeof(*conn), GFP_KERNEL);
6827162b49e7SJohan Hedberg if (!conn) {
6828162b49e7SJohan Hedberg hci_chan_del(hchan);
6829162b49e7SJohan Hedberg return NULL;
6830162b49e7SJohan Hedberg }
6831162b49e7SJohan Hedberg
6832162b49e7SJohan Hedberg kref_init(&conn->ref);
6833162b49e7SJohan Hedberg hcon->l2cap_data = conn;
683451bb8457SJohan Hedberg conn->hcon = hci_conn_get(hcon);
6835162b49e7SJohan Hedberg conn->hchan = hchan;
6836162b49e7SJohan Hedberg
6837162b49e7SJohan Hedberg BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
6838162b49e7SJohan Hedberg
6839ad3f7986SSungwoo Kim conn->mtu = hcon->mtu;
6840162b49e7SJohan Hedberg conn->feat_mask = 0;
6841162b49e7SJohan Hedberg
process_pending_rx(struct work_struct * work)68420bd49fc7SJohan Hedberg conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS;
68430bd49fc7SJohan Hedberg
6844d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED) &&
6845f9be9e86SMarcel Holtmann (bredr_sc_enabled(hcon->hdev) ||
6846b7cb93e5SMarcel Holtmann hci_dev_test_flag(hcon->hdev, HCI_FORCE_BREDR_SMP)))
6847b5ae344dSJohan Hedberg conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR;
6848b5ae344dSJohan Hedberg
68495a54e7c8SMarcel Holtmann mutex_init(&conn->ident_lock);
6850*efc30877SLuiz Augusto von Dentz mutex_init(&conn->lock);
6851162b49e7SJohan Hedberg
6852162b49e7SJohan Hedberg INIT_LIST_HEAD(&conn->chan_l);
6853162b49e7SJohan Hedberg INIT_LIST_HEAD(&conn->users);
l2cap_conn_add(struct hci_conn * hcon)6854162b49e7SJohan Hedberg
6855162b49e7SJohan Hedberg INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
6856162b49e7SJohan Hedberg
685761a939c6SJohan Hedberg skb_queue_head_init(&conn->pending_rx);
685861a939c6SJohan Hedberg INIT_WORK(&conn->pending_rx_work, process_pending_rx);
6859b8b23001SLuiz Augusto von Dentz INIT_DELAYED_WORK(&conn->id_addr_timer, l2cap_conn_update_id_addr);
686061a939c6SJohan Hedberg
6861162b49e7SJohan Hedberg conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
6862162b49e7SJohan Hedberg
6863162b49e7SJohan Hedberg return conn;
6864162b49e7SJohan Hedberg }
6865162b49e7SJohan Hedberg
6866149b3f13SMeng Yu static bool is_valid_psm(u16 psm, u8 dst_type)
6867149b3f13SMeng Yu {
6868162b49e7SJohan Hedberg if (!psm)
6869162b49e7SJohan Hedberg return false;
6870162b49e7SJohan Hedberg
6871162b49e7SJohan Hedberg if (bdaddr_type_is_le(dst_type))
6872162b49e7SJohan Hedberg return (psm <= 0x00ff);
6873162b49e7SJohan Hedberg
6874162b49e7SJohan Hedberg /* PSM must be odd and lsb of upper byte must be 0 */
6875162b49e7SJohan Hedberg return ((psm & 0x0101) == 0x0001);
6876162b49e7SJohan Hedberg }
6877162b49e7SJohan Hedberg
6878da49b602SLuiz Augusto von Dentz struct l2cap_chan_data {
6879da49b602SLuiz Augusto von Dentz struct l2cap_chan *chan;
6880da49b602SLuiz Augusto von Dentz struct pid *pid;
6881da49b602SLuiz Augusto von Dentz int count;
6882da49b602SLuiz Augusto von Dentz };
6883da49b602SLuiz Augusto von Dentz
6884da49b602SLuiz Augusto von Dentz static void l2cap_chan_by_pid(struct l2cap_chan *chan, void *data)
6885da49b602SLuiz Augusto von Dentz {
6886da49b602SLuiz Augusto von Dentz struct l2cap_chan_data *d = data;
6887da49b602SLuiz Augusto von Dentz struct pid *pid;
6888da49b602SLuiz Augusto von Dentz
6889da49b602SLuiz Augusto von Dentz if (chan == d->chan)
6890da49b602SLuiz Augusto von Dentz return;
6891da49b602SLuiz Augusto von Dentz
6892da49b602SLuiz Augusto von Dentz if (!test_bit(FLAG_DEFER_SETUP, &chan->flags))
6893da49b602SLuiz Augusto von Dentz return;
6894da49b602SLuiz Augusto von Dentz
6895da49b602SLuiz Augusto von Dentz pid = chan->ops->get_peer_pid(chan);
6896da49b602SLuiz Augusto von Dentz
6897da49b602SLuiz Augusto von Dentz /* Only count deferred channels with the same PID/PSM */
6898da49b602SLuiz Augusto von Dentz if (d->pid != pid || chan->psm != d->chan->psm || chan->ident ||
6899da49b602SLuiz Augusto von Dentz chan->mode != L2CAP_MODE_EXT_FLOWCTL || chan->state != BT_CONNECT)
6900da49b602SLuiz Augusto von Dentz return;
6901da49b602SLuiz Augusto von Dentz
6902da49b602SLuiz Augusto von Dentz d->count++;
6903da49b602SLuiz Augusto von Dentz }
6904da49b602SLuiz Augusto von Dentz
6905162b49e7SJohan Hedberg int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
is_valid_psm(u16 psm,u8 dst_type)6906162b49e7SJohan Hedberg bdaddr_t *dst, u8 dst_type)
6907162b49e7SJohan Hedberg {
6908162b49e7SJohan Hedberg struct l2cap_conn *conn;
6909162b49e7SJohan Hedberg struct hci_conn *hcon;
6910162b49e7SJohan Hedberg struct hci_dev *hdev;
6911162b49e7SJohan Hedberg int err;
6912162b49e7SJohan Hedberg
691315f02b91SLuiz Augusto von Dentz BT_DBG("%pMR -> %pMR (type %u) psm 0x%4.4x mode 0x%2.2x", &chan->src,
691415f02b91SLuiz Augusto von Dentz dst, dst_type, __le16_to_cpu(psm), chan->mode);
6915162b49e7SJohan Hedberg
691639385cb5SJohan Hedberg hdev = hci_get_route(dst, &chan->src, chan->src_type);
6917162b49e7SJohan Hedberg if (!hdev)
6918162b49e7SJohan Hedberg return -EHOSTUNREACH;
6919162b49e7SJohan Hedberg
6920162b49e7SJohan Hedberg hci_dev_lock(hdev);
6921162b49e7SJohan Hedberg
6922162b49e7SJohan Hedberg if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid &&
6923162b49e7SJohan Hedberg chan->chan_type != L2CAP_CHAN_RAW) {
6924162b49e7SJohan Hedberg err = -EINVAL;
6925162b49e7SJohan Hedberg goto done;
6926162b49e7SJohan Hedberg }
6927162b49e7SJohan Hedberg
692821626e62SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !psm) {
692921626e62SJohan Hedberg err = -EINVAL;
693021626e62SJohan Hedberg goto done;
693121626e62SJohan Hedberg }
693221626e62SJohan Hedberg
693321626e62SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_FIXED && !cid) {
6934162b49e7SJohan Hedberg err = -EINVAL;
6935162b49e7SJohan Hedberg goto done;
6936162b49e7SJohan Hedberg }
6937162b49e7SJohan Hedberg
6938162b49e7SJohan Hedberg switch (chan->mode) {
6939162b49e7SJohan Hedberg case L2CAP_MODE_BASIC:
6940162b49e7SJohan Hedberg break;
6941162b49e7SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL:
69424be5ca67SLuiz Augusto von Dentz break;
694315f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL:
69444be5ca67SLuiz Augusto von Dentz if (!enable_ecred) {
69454be5ca67SLuiz Augusto von Dentz err = -EOPNOTSUPP;
69464be5ca67SLuiz Augusto von Dentz goto done;
69474be5ca67SLuiz Augusto von Dentz }
6948162b49e7SJohan Hedberg break;
6949162b49e7SJohan Hedberg case L2CAP_MODE_ERTM:
6950162b49e7SJohan Hedberg case L2CAP_MODE_STREAMING:
6951162b49e7SJohan Hedberg if (!disable_ertm)
6952162b49e7SJohan Hedberg break;
695319186c7bSGustavo A. R. Silva fallthrough;
6954162b49e7SJohan Hedberg default:
6955beb19e4cSJohan Hedberg err = -EOPNOTSUPP;
6956162b49e7SJohan Hedberg goto done;
6957162b49e7SJohan Hedberg }
6958162b49e7SJohan Hedberg
6959162b49e7SJohan Hedberg switch (chan->state) {
6960162b49e7SJohan Hedberg case BT_CONNECT:
6961162b49e7SJohan Hedberg case BT_CONNECT2:
6962162b49e7SJohan Hedberg case BT_CONFIG:
6963162b49e7SJohan Hedberg /* Already connecting */
6964162b49e7SJohan Hedberg err = 0;
6965162b49e7SJohan Hedberg goto done;
6966162b49e7SJohan Hedberg
6967162b49e7SJohan Hedberg case BT_CONNECTED:
6968162b49e7SJohan Hedberg /* Already connected */
6969162b49e7SJohan Hedberg err = -EISCONN;
6970162b49e7SJohan Hedberg goto done;
6971162b49e7SJohan Hedberg
6972162b49e7SJohan Hedberg case BT_OPEN:
6973162b49e7SJohan Hedberg case BT_BOUND:
6974162b49e7SJohan Hedberg /* Can connect */
6975162b49e7SJohan Hedberg break;
6976162b49e7SJohan Hedberg
6977162b49e7SJohan Hedberg default:
6978162b49e7SJohan Hedberg err = -EBADFD;
6979162b49e7SJohan Hedberg goto done;
6980162b49e7SJohan Hedberg }
6981162b49e7SJohan Hedberg
6982162b49e7SJohan Hedberg /* Set destination address and psm */
6983162b49e7SJohan Hedberg bacpy(&chan->dst, dst);
6984162b49e7SJohan Hedberg chan->dst_type = dst_type;
6985162b49e7SJohan Hedberg
6986162b49e7SJohan Hedberg chan->psm = psm;
6987162b49e7SJohan Hedberg chan->dcid = cid;
6988162b49e7SJohan Hedberg
69896f77d8c7SAndre Guedes if (bdaddr_type_is_le(dst_type)) {
69906f77d8c7SAndre Guedes /* Convert from L2CAP channel address type to HCI address type
69916f77d8c7SAndre Guedes */
69926f77d8c7SAndre Guedes if (dst_type == BDADDR_LE_PUBLIC)
69936f77d8c7SAndre Guedes dst_type = ADDR_LE_DEV_PUBLIC;
69946f77d8c7SAndre Guedes else
69956f77d8c7SAndre Guedes dst_type = ADDR_LE_DEV_RANDOM;
69966f77d8c7SAndre Guedes
6997d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
6998d850bf08SLuiz Augusto von Dentz hcon = hci_connect_le(hdev, dst, dst_type, false,
6999fa142220SJakub Pawlowski chan->sec_level,
7000fa142220SJakub Pawlowski HCI_LE_CONN_TIMEOUT,
70018e8b92eeSLuiz Augusto von Dentz HCI_ROLE_SLAVE);
70020ad06aa6SJohan Hedberg else
70030ad06aa6SJohan Hedberg hcon = hci_connect_le_scan(hdev, dst, dst_type,
70040ad06aa6SJohan Hedberg chan->sec_level,
700576b13996SManish Mandlik HCI_LE_CONN_TIMEOUT,
700676b13996SManish Mandlik CONN_REASON_L2CAP_CHAN);
70070ad06aa6SJohan Hedberg
70086f77d8c7SAndre Guedes } else {
7009d93375a8SJohan Hedberg u8 auth_type = l2cap_get_auth_type(chan);
701076b13996SManish Mandlik hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type,
701176b13996SManish Mandlik CONN_REASON_L2CAP_CHAN);
70126f77d8c7SAndre Guedes }
7013162b49e7SJohan Hedberg
7014162b49e7SJohan Hedberg if (IS_ERR(hcon)) {
7015162b49e7SJohan Hedberg err = PTR_ERR(hcon);
7016162b49e7SJohan Hedberg goto done;
7017162b49e7SJohan Hedberg }
7018162b49e7SJohan Hedberg
7019162b49e7SJohan Hedberg conn = l2cap_conn_add(hcon);
7020162b49e7SJohan Hedberg if (!conn) {
7021162b49e7SJohan Hedberg hci_conn_drop(hcon);
7022162b49e7SJohan Hedberg err = -ENOMEM;
7023162b49e7SJohan Hedberg goto done;
7024162b49e7SJohan Hedberg }
7025162b49e7SJohan Hedberg
7026da49b602SLuiz Augusto von Dentz if (chan->mode == L2CAP_MODE_EXT_FLOWCTL) {
7027da49b602SLuiz Augusto von Dentz struct l2cap_chan_data data;
7028da49b602SLuiz Augusto von Dentz
7029da49b602SLuiz Augusto von Dentz data.chan = chan;
7030da49b602SLuiz Augusto von Dentz data.pid = chan->ops->get_peer_pid(chan);
7031da49b602SLuiz Augusto von Dentz data.count = 1;
7032da49b602SLuiz Augusto von Dentz
7033da49b602SLuiz Augusto von Dentz l2cap_chan_list(conn, l2cap_chan_by_pid, &data);
7034da49b602SLuiz Augusto von Dentz
7035da49b602SLuiz Augusto von Dentz /* Check if there isn't too many channels being connected */
7036da49b602SLuiz Augusto von Dentz if (data.count > L2CAP_ECRED_CONN_SCID_MAX) {
7037da49b602SLuiz Augusto von Dentz hci_conn_drop(hcon);
7038da49b602SLuiz Augusto von Dentz err = -EPROTO;
7039da49b602SLuiz Augusto von Dentz goto done;
7040da49b602SLuiz Augusto von Dentz }
7041da49b602SLuiz Augusto von Dentz }
7042da49b602SLuiz Augusto von Dentz
7043*efc30877SLuiz Augusto von Dentz mutex_lock(&conn->lock);
704402e246aeSJohan Hedberg l2cap_chan_lock(chan);
704502e246aeSJohan Hedberg
7046162b49e7SJohan Hedberg if (cid && __l2cap_get_chan_by_dcid(conn, cid)) {
7047162b49e7SJohan Hedberg hci_conn_drop(hcon);
7048162b49e7SJohan Hedberg err = -EBUSY;
704902e246aeSJohan Hedberg goto chan_unlock;
7050162b49e7SJohan Hedberg }
7051162b49e7SJohan Hedberg
7052162b49e7SJohan Hedberg /* Update source addr of the socket */
7053162b49e7SJohan Hedberg bacpy(&chan->src, &hcon->src);
7054a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(hcon);
7055162b49e7SJohan Hedberg
705602e246aeSJohan Hedberg __l2cap_chan_add(conn, chan);
7057162b49e7SJohan Hedberg
7058162b49e7SJohan Hedberg /* l2cap_chan_add takes its own ref so we can drop this one */
7059162b49e7SJohan Hedberg hci_conn_drop(hcon);
7060162b49e7SJohan Hedberg
7061162b49e7SJohan Hedberg l2cap_state_change(chan, BT_CONNECT);
7062162b49e7SJohan Hedberg __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
7063162b49e7SJohan Hedberg
706461202e4dSJohan Hedberg /* Release chan->sport so that it can be reused by other
706561202e4dSJohan Hedberg * sockets (as it's only used for listening sockets).
706661202e4dSJohan Hedberg */
706761202e4dSJohan Hedberg write_lock(&chan_list_lock);
706861202e4dSJohan Hedberg chan->sport = 0;
706961202e4dSJohan Hedberg write_unlock(&chan_list_lock);
707061202e4dSJohan Hedberg
7071162b49e7SJohan Hedberg if (hcon->state == BT_CONNECTED) {
7072162b49e7SJohan Hedberg if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
7073162b49e7SJohan Hedberg __clear_chan_timer(chan);
7074e7cafc45SJohan Hedberg if (l2cap_chan_check_security(chan, true))
7075162b49e7SJohan Hedberg l2cap_state_change(chan, BT_CONNECTED);
7076162b49e7SJohan Hedberg } else
7077162b49e7SJohan Hedberg l2cap_do_start(chan);
7078162b49e7SJohan Hedberg }
7079162b49e7SJohan Hedberg
7080162b49e7SJohan Hedberg err = 0;
7081162b49e7SJohan Hedberg
708202e246aeSJohan Hedberg chan_unlock:
7083162b49e7SJohan Hedberg l2cap_chan_unlock(chan);
7084*efc30877SLuiz Augusto von Dentz mutex_unlock(&conn->lock);
708502e246aeSJohan Hedberg done:
7086162b49e7SJohan Hedberg hci_dev_unlock(hdev);
7087162b49e7SJohan Hedberg hci_dev_put(hdev);
7088162b49e7SJohan Hedberg return err;
7089162b49e7SJohan Hedberg }
70906b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_connect);
7091162b49e7SJohan Hedberg
709215f02b91SLuiz Augusto von Dentz static void l2cap_ecred_reconfigure(struct l2cap_chan *chan)
709315f02b91SLuiz Augusto von Dentz {
709415f02b91SLuiz Augusto von Dentz struct l2cap_conn *conn = chan->conn;
709515f02b91SLuiz Augusto von Dentz struct {
709615f02b91SLuiz Augusto von Dentz struct l2cap_ecred_reconf_req req;
709715f02b91SLuiz Augusto von Dentz __le16 scid;
709815f02b91SLuiz Augusto von Dentz } pdu;
709915f02b91SLuiz Augusto von Dentz
710015f02b91SLuiz Augusto von Dentz pdu.req.mtu = cpu_to_le16(chan->imtu);
710115f02b91SLuiz Augusto von Dentz pdu.req.mps = cpu_to_le16(chan->mps);
710215f02b91SLuiz Augusto von Dentz pdu.scid = cpu_to_le16(chan->scid);
710315f02b91SLuiz Augusto von Dentz
710415f02b91SLuiz Augusto von Dentz chan->ident = l2cap_get_ident(conn);
710515f02b91SLuiz Augusto von Dentz
710615f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_RECONF_REQ,
710715f02b91SLuiz Augusto von Dentz sizeof(pdu), &pdu);
710815f02b91SLuiz Augusto von Dentz }
710915f02b91SLuiz Augusto von Dentz
711015f02b91SLuiz Augusto von Dentz int l2cap_chan_reconfigure(struct l2cap_chan *chan, __u16 mtu)
711115f02b91SLuiz Augusto von Dentz {
711215f02b91SLuiz Augusto von Dentz if (chan->imtu > mtu)
711315f02b91SLuiz Augusto von Dentz return -EINVAL;
711415f02b91SLuiz Augusto von Dentz
711515f02b91SLuiz Augusto von Dentz BT_DBG("chan %p mtu 0x%4.4x", chan, mtu);
711615f02b91SLuiz Augusto von Dentz
711715f02b91SLuiz Augusto von Dentz chan->imtu = mtu;
711815f02b91SLuiz Augusto von Dentz
711915f02b91SLuiz Augusto von Dentz l2cap_ecred_reconfigure(chan);
712015f02b91SLuiz Augusto von Dentz
712115f02b91SLuiz Augusto von Dentz return 0;
712215f02b91SLuiz Augusto von Dentz }
712315f02b91SLuiz Augusto von Dentz
71240a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
71250a708f8fSGustavo F. Padovan
7126686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
71270a708f8fSGustavo F. Padovan {
71280a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0;
712923691d75SGustavo F. Padovan struct l2cap_chan *c;
71300a708f8fSGustavo F. Padovan
71316ed93dc6SAndrei Emeltchenko BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr);
l2cap_ecred_reconfigure(struct l2cap_chan * chan)71320a708f8fSGustavo F. Padovan
71330a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */
713423691d75SGustavo F. Padovan read_lock(&chan_list_lock);
713523691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) {
713689bc500eSGustavo F. Padovan if (c->state != BT_LISTEN)
71370a708f8fSGustavo F. Padovan continue;
71380a708f8fSGustavo F. Padovan
71397eafc59eSMarcel Holtmann if (!bacmp(&c->src, &hdev->bdaddr)) {
71400a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT;
714143bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
71420a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER;
71430a708f8fSGustavo F. Padovan exact++;
71447eafc59eSMarcel Holtmann } else if (!bacmp(&c->src, BDADDR_ANY)) {
71450a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT;
714643bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
71470a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER;
71480a708f8fSGustavo F. Padovan }
71490a708f8fSGustavo F. Padovan }
l2cap_chan_reconfigure(struct l2cap_chan * chan,__u16 mtu)715023691d75SGustavo F. Padovan read_unlock(&chan_list_lock);
71510a708f8fSGustavo F. Padovan
71520a708f8fSGustavo F. Padovan return exact ? lm1 : lm2;
71530a708f8fSGustavo F. Padovan }
71540a708f8fSGustavo F. Padovan
7155e760ec12SJohan Hedberg /* Find the next fixed channel in BT_LISTEN state, continue iteration
7156e760ec12SJohan Hedberg * from an existing channel in the list or from the beginning of the
7157e760ec12SJohan Hedberg * global list (by passing NULL as first parameter).
7158e760ec12SJohan Hedberg */
7159e760ec12SJohan Hedberg static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c,
7160327a7191SJohan Hedberg struct hci_conn *hcon)
7161e760ec12SJohan Hedberg {
7162327a7191SJohan Hedberg u8 src_type = bdaddr_src_type(hcon);
7163327a7191SJohan Hedberg
7164e760ec12SJohan Hedberg read_lock(&chan_list_lock);
7165e760ec12SJohan Hedberg
l2cap_connect_ind(struct hci_dev * hdev,bdaddr_t * bdaddr)7166e760ec12SJohan Hedberg if (c)
7167e760ec12SJohan Hedberg c = list_next_entry(c, global_l);
7168e760ec12SJohan Hedberg else
7169e760ec12SJohan Hedberg c = list_entry(chan_list.next, typeof(*c), global_l);
7170e760ec12SJohan Hedberg
7171e760ec12SJohan Hedberg list_for_each_entry_from(c, &chan_list, global_l) {
7172e760ec12SJohan Hedberg if (c->chan_type != L2CAP_CHAN_FIXED)
7173e760ec12SJohan Hedberg continue;
7174e760ec12SJohan Hedberg if (c->state != BT_LISTEN)
7175e760ec12SJohan Hedberg continue;
7176327a7191SJohan Hedberg if (bacmp(&c->src, &hcon->src) && bacmp(&c->src, BDADDR_ANY))
7177e760ec12SJohan Hedberg continue;
7178327a7191SJohan Hedberg if (src_type != c->src_type)
717954a1b626SJohan Hedberg continue;
7180e760ec12SJohan Hedberg
7181d0be8347SLuiz Augusto von Dentz c = l2cap_chan_hold_unless_zero(c);
7182e760ec12SJohan Hedberg read_unlock(&chan_list_lock);
7183e760ec12SJohan Hedberg return c;
7184e760ec12SJohan Hedberg }
7185e760ec12SJohan Hedberg
7186e760ec12SJohan Hedberg read_unlock(&chan_list_lock);
7187e760ec12SJohan Hedberg
7188e760ec12SJohan Hedberg return NULL;
7189e760ec12SJohan Hedberg }
7190e760ec12SJohan Hedberg
7191539c496dSJohan Hedberg static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
71920a708f8fSGustavo F. Padovan {
7193e760ec12SJohan Hedberg struct hci_dev *hdev = hcon->hdev;
71940a708f8fSGustavo F. Padovan struct l2cap_conn *conn;
7195e760ec12SJohan Hedberg struct l2cap_chan *pchan;
7196e760ec12SJohan Hedberg u8 dst_type;
71970a708f8fSGustavo F. Padovan
71985e8ce74fSLuiz Augusto von Dentz if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
l2cap_global_fixed_chan(struct l2cap_chan * c,struct hci_conn * hcon)71995e8ce74fSLuiz Augusto von Dentz return;
72005e8ce74fSLuiz Augusto von Dentz
72016ed93dc6SAndrei Emeltchenko BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
72020a708f8fSGustavo F. Padovan
7203dc0f5088SJohan Hedberg if (status) {
7204e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status));
7205dc0f5088SJohan Hedberg return;
7206ba6fc317SAndrei Emeltchenko }
7207dc0f5088SJohan Hedberg
7208dc0f5088SJohan Hedberg conn = l2cap_conn_add(hcon);
7209dc0f5088SJohan Hedberg if (!conn)
7210dc0f5088SJohan Hedberg return;
7211dc0f5088SJohan Hedberg
7212a250e048SJohan Hedberg dst_type = bdaddr_dst_type(hcon);
7213e760ec12SJohan Hedberg
7214e760ec12SJohan Hedberg /* If device is blocked, do not create channels for it */
72153d4f9c00SArchie Pusaka if (hci_bdaddr_list_lookup(&hdev->reject_list, &hcon->dst, dst_type))
7216e760ec12SJohan Hedberg return;
7217e760ec12SJohan Hedberg
7218e760ec12SJohan Hedberg /* Find fixed channels and notify them of the new connection. We
7219e760ec12SJohan Hedberg * use multiple individual lookups, continuing each time where
7220e760ec12SJohan Hedberg * we left off, because the list lock would prevent calling the
7221e760ec12SJohan Hedberg * potentially sleeping l2cap_chan_lock() function.
7222e760ec12SJohan Hedberg */
7223327a7191SJohan Hedberg pchan = l2cap_global_fixed_chan(NULL, hcon);
7224e760ec12SJohan Hedberg while (pchan) {
7225e760ec12SJohan Hedberg struct l2cap_chan *chan, *next;
7226e760ec12SJohan Hedberg
7227e760ec12SJohan Hedberg /* Client fixed channels should override server ones */
7228e760ec12SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, pchan->scid))
7229e760ec12SJohan Hedberg goto next;
7230e760ec12SJohan Hedberg
l2cap_match(struct hci_conn * hcon)7231e760ec12SJohan Hedberg l2cap_chan_lock(pchan);
7232e760ec12SJohan Hedberg chan = pchan->ops->new_connection(pchan);
7233e760ec12SJohan Hedberg if (chan) {
7234e760ec12SJohan Hedberg bacpy(&chan->src, &hcon->src);
7235e760ec12SJohan Hedberg bacpy(&chan->dst, &hcon->dst);
l2cap_connect_cfm(struct hci_conn * hcon,u8 status)7236a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(hcon);
7237e760ec12SJohan Hedberg chan->dst_type = dst_type;
7238e760ec12SJohan Hedberg
7239e760ec12SJohan Hedberg __l2cap_chan_add(conn, chan);
7240e760ec12SJohan Hedberg }
7241e760ec12SJohan Hedberg
7242e760ec12SJohan Hedberg l2cap_chan_unlock(pchan);
7243e760ec12SJohan Hedberg next:
7244327a7191SJohan Hedberg next = l2cap_global_fixed_chan(pchan, hcon);
7245e760ec12SJohan Hedberg l2cap_chan_put(pchan);
7246e760ec12SJohan Hedberg pchan = next;
7247e760ec12SJohan Hedberg }
7248e760ec12SJohan Hedberg
7249dc0f5088SJohan Hedberg l2cap_conn_ready(conn);
72500a708f8fSGustavo F. Padovan }
72510a708f8fSGustavo F. Padovan
7252686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
72530a708f8fSGustavo F. Padovan {
72540a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data;
72550a708f8fSGustavo F. Padovan
72560a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon);
72570a708f8fSGustavo F. Padovan
7258686ebf28SUlisses Furquim if (!conn)
72599f5a0d7bSAndrei Emeltchenko return HCI_ERROR_REMOTE_USER_TERM;
72600a708f8fSGustavo F. Padovan return conn->disc_reason;
72610a708f8fSGustavo F. Padovan }
72620a708f8fSGustavo F. Padovan
72633a6d576bSJohan Hedberg static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
72640a708f8fSGustavo F. Padovan {
72655e8ce74fSLuiz Augusto von Dentz if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
72665e8ce74fSLuiz Augusto von Dentz return;
72675e8ce74fSLuiz Augusto von Dentz
72680a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason);
72690a708f8fSGustavo F. Padovan
7270e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason));
72710a708f8fSGustavo F. Padovan }
72720a708f8fSGustavo F. Padovan
72734343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
72740a708f8fSGustavo F. Padovan {
7275715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
72760a708f8fSGustavo F. Padovan return;
72770a708f8fSGustavo F. Padovan
72780a708f8fSGustavo F. Padovan if (encrypt == 0x00) {
72794343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) {
7280ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
72817d513e92SMarcel Holtmann } else if (chan->sec_level == BT_SECURITY_HIGH ||
72827d513e92SMarcel Holtmann chan->sec_level == BT_SECURITY_FIPS)
72830f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED);
72840a708f8fSGustavo F. Padovan } else {
72854343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM)
7286c9b66675SGustavo F. Padovan __clear_chan_timer(chan);
72870a708f8fSGustavo F. Padovan }
72880a708f8fSGustavo F. Padovan }
72890a708f8fSGustavo F. Padovan
7290354fe804SJohan Hedberg static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
72910a708f8fSGustavo F. Padovan {
72920a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data;
729348454079SGustavo F. Padovan struct l2cap_chan *chan;
l2cap_disconn_ind(struct hci_conn * hcon)72940a708f8fSGustavo F. Padovan
72950a708f8fSGustavo F. Padovan if (!conn)
7296354fe804SJohan Hedberg return;
72970a708f8fSGustavo F. Padovan
729889d8b407SAndrei Emeltchenko BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt);
72990a708f8fSGustavo F. Padovan
7300*efc30877SLuiz Augusto von Dentz mutex_lock(&conn->lock);
73010a708f8fSGustavo F. Padovan
73023df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) {
73036be36555SAndrei Emeltchenko l2cap_chan_lock(chan);
73040a708f8fSGustavo F. Padovan
l2cap_disconn_cfm(struct hci_conn * hcon,u8 reason)730589d8b407SAndrei Emeltchenko BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
730689d8b407SAndrei Emeltchenko state_to_string(chan->state));
7307f1cb9af5SVinicius Costa Gomes
7308191eb398SJohan Hedberg if (!status && encrypt)
7309f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level;
7310f1cb9af5SVinicius Costa Gomes
731196eff46eSAndrei Emeltchenko if (!__l2cap_no_conn_pending(chan)) {
l2cap_check_encryption(struct l2cap_chan * chan,u8 encrypt)73126be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
73130a708f8fSGustavo F. Padovan continue;
73140a708f8fSGustavo F. Padovan }
73150a708f8fSGustavo F. Padovan
731689bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED ||
731789bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) {
7318d97c899bSMarcel Holtmann chan->ops->resume(chan);
73194343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt);
73206be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
73210a708f8fSGustavo F. Padovan continue;
73220a708f8fSGustavo F. Padovan }
73230a708f8fSGustavo F. Padovan
732489bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) {
7325693cd8ceSMarcel Holtmann if (!status && l2cap_check_enc_key_size(hcon))
732693c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan);
73276d3c15daSJohan Hedberg else
7328ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
l2cap_security_cfm(struct hci_conn * hcon,u8 status,u8 encrypt)7329fa37c1aaSJohan Hedberg } else if (chan->state == BT_CONNECT2 &&
733015f02b91SLuiz Augusto von Dentz !(chan->mode == L2CAP_MODE_EXT_FLOWCTL ||
733115f02b91SLuiz Augusto von Dentz chan->mode == L2CAP_MODE_LE_FLOWCTL)) {
73320a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp;
7333df3c3931SJohan Hedberg __u16 res, stat;
73340a708f8fSGustavo F. Padovan
7335693cd8ceSMarcel Holtmann if (!status && l2cap_check_enc_key_size(hcon)) {
7336bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
7337df3c3931SJohan Hedberg res = L2CAP_CR_PEND;
7338df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND;
73392dc4e510SGustavo Padovan chan->ops->defer(chan);
7340df3c3931SJohan Hedberg } else {
7341acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG);
7342df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS;
7343df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO;
7344df3c3931SJohan Hedberg }
73450a708f8fSGustavo F. Padovan } else {
7346acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_DISCONN);
7347ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
7348df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK;
7349df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO;
73500a708f8fSGustavo F. Padovan }
73510a708f8fSGustavo F. Padovan
7352fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid);
7353fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid);
7354df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res);
7355df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat);
7356fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
7357fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp);
73582d369359SMat Martineau
73592d369359SMat Martineau if (!test_bit(CONF_REQ_SENT, &chan->conf_state) &&
73602d369359SMat Martineau res == L2CAP_CR_SUCCESS) {
73612d369359SMat Martineau char buf[128];
73622d369359SMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state);
73632d369359SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn),
73642d369359SMat Martineau L2CAP_CONF_REQ,
7365e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)),
73662d369359SMat Martineau buf);
73672d369359SMat Martineau chan->num_conf_req++;
73682d369359SMat Martineau }
73690a708f8fSGustavo F. Padovan }
73700a708f8fSGustavo F. Padovan
73716be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
73720a708f8fSGustavo F. Padovan }
73730a708f8fSGustavo F. Padovan
7374*efc30877SLuiz Augusto von Dentz mutex_unlock(&conn->lock);
73750a708f8fSGustavo F. Padovan }
73760a708f8fSGustavo F. Padovan
73774d7ea8eeSLuiz Augusto von Dentz /* Append fragment into frame respecting the maximum len of rx_skb */
73784d7ea8eeSLuiz Augusto von Dentz static int l2cap_recv_frag(struct l2cap_conn *conn, struct sk_buff *skb,
73794d7ea8eeSLuiz Augusto von Dentz u16 len)
73804d7ea8eeSLuiz Augusto von Dentz {
73814d7ea8eeSLuiz Augusto von Dentz if (!conn->rx_skb) {
73824d7ea8eeSLuiz Augusto von Dentz /* Allocate skb for the complete frame (with header) */
73834d7ea8eeSLuiz Augusto von Dentz conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL);
73844d7ea8eeSLuiz Augusto von Dentz if (!conn->rx_skb)
73854d7ea8eeSLuiz Augusto von Dentz return -ENOMEM;
73864d7ea8eeSLuiz Augusto von Dentz /* Init rx_len */
73874d7ea8eeSLuiz Augusto von Dentz conn->rx_len = len;
73884d7ea8eeSLuiz Augusto von Dentz }
73894d7ea8eeSLuiz Augusto von Dentz
73904d7ea8eeSLuiz Augusto von Dentz /* Copy as much as the rx_skb can hold */
73914d7ea8eeSLuiz Augusto von Dentz len = min_t(u16, len, skb->len);
73924d7ea8eeSLuiz Augusto von Dentz skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, len), len);
73934d7ea8eeSLuiz Augusto von Dentz skb_pull(skb, len);
73944d7ea8eeSLuiz Augusto von Dentz conn->rx_len -= len;
73954d7ea8eeSLuiz Augusto von Dentz
73964d7ea8eeSLuiz Augusto von Dentz return len;
73974d7ea8eeSLuiz Augusto von Dentz }
73984d7ea8eeSLuiz Augusto von Dentz
73994d7ea8eeSLuiz Augusto von Dentz static int l2cap_recv_len(struct l2cap_conn *conn, struct sk_buff *skb)
74004d7ea8eeSLuiz Augusto von Dentz {
74014d7ea8eeSLuiz Augusto von Dentz struct sk_buff *rx_skb;
74024d7ea8eeSLuiz Augusto von Dentz int len;
74034d7ea8eeSLuiz Augusto von Dentz
74044d7ea8eeSLuiz Augusto von Dentz /* Append just enough to complete the header */
74054d7ea8eeSLuiz Augusto von Dentz len = l2cap_recv_frag(conn, skb, L2CAP_LEN_SIZE - conn->rx_skb->len);
74064d7ea8eeSLuiz Augusto von Dentz
74074d7ea8eeSLuiz Augusto von Dentz /* If header could not be read just continue */
74084d7ea8eeSLuiz Augusto von Dentz if (len < 0 || conn->rx_skb->len < L2CAP_LEN_SIZE)
74094d7ea8eeSLuiz Augusto von Dentz return len;
74104d7ea8eeSLuiz Augusto von Dentz
74114d7ea8eeSLuiz Augusto von Dentz rx_skb = conn->rx_skb;
74124d7ea8eeSLuiz Augusto von Dentz len = get_unaligned_le16(rx_skb->data);
74134d7ea8eeSLuiz Augusto von Dentz
74144d7ea8eeSLuiz Augusto von Dentz /* Check if rx_skb has enough space to received all fragments */
74154d7ea8eeSLuiz Augusto von Dentz if (len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE) <= skb_tailroom(rx_skb)) {
74164d7ea8eeSLuiz Augusto von Dentz /* Update expected len */
l2cap_recv_frag(struct l2cap_conn * conn,struct sk_buff * skb,u16 len)74174d7ea8eeSLuiz Augusto von Dentz conn->rx_len = len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE);
74184d7ea8eeSLuiz Augusto von Dentz return L2CAP_LEN_SIZE;
74194d7ea8eeSLuiz Augusto von Dentz }
74204d7ea8eeSLuiz Augusto von Dentz
74214d7ea8eeSLuiz Augusto von Dentz /* Reset conn->rx_skb since it will need to be reallocated in order to
74224d7ea8eeSLuiz Augusto von Dentz * fit all fragments.
74234d7ea8eeSLuiz Augusto von Dentz */
74244d7ea8eeSLuiz Augusto von Dentz conn->rx_skb = NULL;
74254d7ea8eeSLuiz Augusto von Dentz
74264d7ea8eeSLuiz Augusto von Dentz /* Reallocates rx_skb using the exact expected length */
74274d7ea8eeSLuiz Augusto von Dentz len = l2cap_recv_frag(conn, rx_skb,
74284d7ea8eeSLuiz Augusto von Dentz len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE));
74294d7ea8eeSLuiz Augusto von Dentz kfree_skb(rx_skb);
74304d7ea8eeSLuiz Augusto von Dentz
74314d7ea8eeSLuiz Augusto von Dentz return len;
74324d7ea8eeSLuiz Augusto von Dentz }
74334d7ea8eeSLuiz Augusto von Dentz
74344d7ea8eeSLuiz Augusto von Dentz static void l2cap_recv_reset(struct l2cap_conn *conn)
74354d7ea8eeSLuiz Augusto von Dentz {
74364d7ea8eeSLuiz Augusto von Dentz kfree_skb(conn->rx_skb);
74374d7ea8eeSLuiz Augusto von Dentz conn->rx_skb = NULL;
l2cap_recv_len(struct l2cap_conn * conn,struct sk_buff * skb)74384d7ea8eeSLuiz Augusto von Dentz conn->rx_len = 0;
74394d7ea8eeSLuiz Augusto von Dentz }
74404d7ea8eeSLuiz Augusto von Dentz
7441*efc30877SLuiz Augusto von Dentz struct l2cap_conn *l2cap_conn_hold_unless_zero(struct l2cap_conn *c)
7442c96cce85SLuiz Augusto von Dentz {
7443*efc30877SLuiz Augusto von Dentz if (!c)
7444*efc30877SLuiz Augusto von Dentz return NULL;
7445*efc30877SLuiz Augusto von Dentz
7446c96cce85SLuiz Augusto von Dentz BT_DBG("conn %p orig refcnt %u", c, kref_read(&c->ref));
7447c96cce85SLuiz Augusto von Dentz
7448c96cce85SLuiz Augusto von Dentz if (!kref_get_unless_zero(&c->ref))
7449c96cce85SLuiz Augusto von Dentz return NULL;
7450c96cce85SLuiz Augusto von Dentz
7451c96cce85SLuiz Augusto von Dentz return c;
7452c96cce85SLuiz Augusto von Dentz }
7453c96cce85SLuiz Augusto von Dentz
74549b4c3336SArron Wang void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
74550a708f8fSGustavo F. Padovan {
7456c96cce85SLuiz Augusto von Dentz struct l2cap_conn *conn;
7457d73a0988SAndrei Emeltchenko int len;
74580a708f8fSGustavo F. Padovan
7459c96cce85SLuiz Augusto von Dentz /* Lock hdev to access l2cap_data to avoid race with l2cap_conn_del */
7460c96cce85SLuiz Augusto von Dentz hci_dev_lock(hcon->hdev);
7461c96cce85SLuiz Augusto von Dentz
7462c96cce85SLuiz Augusto von Dentz conn = hcon->l2cap_data;
7463c96cce85SLuiz Augusto von Dentz
74640a708f8fSGustavo F. Padovan if (!conn)
7465baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon);
74660a708f8fSGustavo F. Padovan
7467c96cce85SLuiz Augusto von Dentz conn = l2cap_conn_hold_unless_zero(conn);
7468c96cce85SLuiz Augusto von Dentz
7469c96cce85SLuiz Augusto von Dentz hci_dev_unlock(hcon->hdev);
7470c96cce85SLuiz Augusto von Dentz
7471*efc30877SLuiz Augusto von Dentz if (!conn) {
7472*efc30877SLuiz Augusto von Dentz kfree_skb(skb);
l2cap_recv_reset(struct l2cap_conn * conn)7473*efc30877SLuiz Augusto von Dentz return;
7474*efc30877SLuiz Augusto von Dentz }
74750a708f8fSGustavo F. Padovan
747693917fd2SKai Ye BT_DBG("conn %p len %u flags 0x%x", conn, skb->len, flags);
74770a708f8fSGustavo F. Padovan
7478*efc30877SLuiz Augusto von Dentz mutex_lock(&conn->lock);
7479*efc30877SLuiz Augusto von Dentz
l2cap_recv_acldata(struct hci_conn * hcon,struct sk_buff * skb,u16 flags)7480d73a0988SAndrei Emeltchenko switch (flags) {
7481d73a0988SAndrei Emeltchenko case ACL_START:
7482d73a0988SAndrei Emeltchenko case ACL_START_NO_FLUSH:
7483d73a0988SAndrei Emeltchenko case ACL_COMPLETE:
74844d7ea8eeSLuiz Augusto von Dentz if (conn->rx_skb) {
74850a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len);
74864d7ea8eeSLuiz Augusto von Dentz l2cap_recv_reset(conn);
74870a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM);
74880a708f8fSGustavo F. Padovan }
74890a708f8fSGustavo F. Padovan
74904d7ea8eeSLuiz Augusto von Dentz /* Start fragment may not contain the L2CAP length so just
74914d7ea8eeSLuiz Augusto von Dentz * copy the initial byte when that happens and use conn->mtu as
74924d7ea8eeSLuiz Augusto von Dentz * expected length.
74934d7ea8eeSLuiz Augusto von Dentz */
74944d7ea8eeSLuiz Augusto von Dentz if (skb->len < L2CAP_LEN_SIZE) {
74957c9524d9SHawkins Jiawei l2cap_recv_frag(conn, skb, conn->mtu);
74967c9524d9SHawkins Jiawei break;
74970a708f8fSGustavo F. Padovan }
74980a708f8fSGustavo F. Padovan
74994d7ea8eeSLuiz Augusto von Dentz len = get_unaligned_le16(skb->data) + L2CAP_HDR_SIZE;
75000a708f8fSGustavo F. Padovan
75010a708f8fSGustavo F. Padovan if (len == skb->len) {
75020a708f8fSGustavo F. Padovan /* Complete frame received */
75030a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb);
7504*efc30877SLuiz Augusto von Dentz goto unlock;
75050a708f8fSGustavo F. Padovan }
75060a708f8fSGustavo F. Padovan
750793917fd2SKai Ye BT_DBG("Start: total len %d, frag len %u", len, skb->len);
75080a708f8fSGustavo F. Padovan
75090a708f8fSGustavo F. Padovan if (skb->len > len) {
751093917fd2SKai Ye BT_ERR("Frame is too long (len %u, expected len %d)",
75110a708f8fSGustavo F. Padovan skb->len, len);
75120a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM);
75130a708f8fSGustavo F. Padovan goto drop;
75140a708f8fSGustavo F. Padovan }
75150a708f8fSGustavo F. Padovan
75164d7ea8eeSLuiz Augusto von Dentz /* Append fragment into frame (with header) */
75174d7ea8eeSLuiz Augusto von Dentz if (l2cap_recv_frag(conn, skb, len) < 0)
75180a708f8fSGustavo F. Padovan goto drop;
75190a708f8fSGustavo F. Padovan
7520d73a0988SAndrei Emeltchenko break;
7521d73a0988SAndrei Emeltchenko
7522d73a0988SAndrei Emeltchenko case ACL_CONT:
752393917fd2SKai Ye BT_DBG("Cont: frag len %u (expecting %u)", skb->len, conn->rx_len);
75240a708f8fSGustavo F. Padovan
75254d7ea8eeSLuiz Augusto von Dentz if (!conn->rx_skb) {
75260a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len);
75270a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM);
75280a708f8fSGustavo F. Padovan goto drop;
75290a708f8fSGustavo F. Padovan }
75300a708f8fSGustavo F. Padovan
75314d7ea8eeSLuiz Augusto von Dentz /* Complete the L2CAP length if it has not been read */
75324d7ea8eeSLuiz Augusto von Dentz if (conn->rx_skb->len < L2CAP_LEN_SIZE) {
75334d7ea8eeSLuiz Augusto von Dentz if (l2cap_recv_len(conn, skb) < 0) {
75340a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM);
75350a708f8fSGustavo F. Padovan goto drop;
75360a708f8fSGustavo F. Padovan }
75370a708f8fSGustavo F. Padovan
75384d7ea8eeSLuiz Augusto von Dentz /* Header still could not be read just continue */
75394d7ea8eeSLuiz Augusto von Dentz if (conn->rx_skb->len < L2CAP_LEN_SIZE)
75407c9524d9SHawkins Jiawei break;
75414d7ea8eeSLuiz Augusto von Dentz }
75424d7ea8eeSLuiz Augusto von Dentz
75434d7ea8eeSLuiz Augusto von Dentz if (skb->len > conn->rx_len) {
754493917fd2SKai Ye BT_ERR("Fragment is too long (len %u, expected %u)",
75454d7ea8eeSLuiz Augusto von Dentz skb->len, conn->rx_len);
75464d7ea8eeSLuiz Augusto von Dentz l2cap_recv_reset(conn);
75474d7ea8eeSLuiz Augusto von Dentz l2cap_conn_unreliable(conn, ECOMM);
75484d7ea8eeSLuiz Augusto von Dentz goto drop;
75494d7ea8eeSLuiz Augusto von Dentz }
75504d7ea8eeSLuiz Augusto von Dentz
75514d7ea8eeSLuiz Augusto von Dentz /* Append fragment into frame (with header) */
75524d7ea8eeSLuiz Augusto von Dentz l2cap_recv_frag(conn, skb, skb->len);
75530a708f8fSGustavo F. Padovan
75540a708f8fSGustavo F. Padovan if (!conn->rx_len) {
7555c4e5bafaSJohan Hedberg /* Complete frame received. l2cap_recv_frame
7556c4e5bafaSJohan Hedberg * takes ownership of the skb so set the global
7557c4e5bafaSJohan Hedberg * rx_skb pointer to NULL first.
7558c4e5bafaSJohan Hedberg */
7559c4e5bafaSJohan Hedberg struct sk_buff *rx_skb = conn->rx_skb;
75600a708f8fSGustavo F. Padovan conn->rx_skb = NULL;
7561c4e5bafaSJohan Hedberg l2cap_recv_frame(conn, rx_skb);
75620a708f8fSGustavo F. Padovan }
7563d73a0988SAndrei Emeltchenko break;
75640a708f8fSGustavo F. Padovan }
75650a708f8fSGustavo F. Padovan
75660a708f8fSGustavo F. Padovan drop:
75670a708f8fSGustavo F. Padovan kfree_skb(skb);
7568*efc30877SLuiz Augusto von Dentz unlock:
7569*efc30877SLuiz Augusto von Dentz mutex_unlock(&conn->lock);
7570*efc30877SLuiz Augusto von Dentz l2cap_conn_put(conn);
75710a708f8fSGustavo F. Padovan }
75720a708f8fSGustavo F. Padovan
7573354fe804SJohan Hedberg static struct hci_cb l2cap_cb = {
7574354fe804SJohan Hedberg .name = "L2CAP",
7575539c496dSJohan Hedberg .connect_cfm = l2cap_connect_cfm,
75763a6d576bSJohan Hedberg .disconn_cfm = l2cap_disconn_cfm,
7577354fe804SJohan Hedberg .security_cfm = l2cap_security_cfm,
7578354fe804SJohan Hedberg };
7579354fe804SJohan Hedberg
75800a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
75810a708f8fSGustavo F. Padovan {
758223691d75SGustavo F. Padovan struct l2cap_chan *c;
75830a708f8fSGustavo F. Padovan
7584333055f2SGustavo F. Padovan read_lock(&chan_list_lock);
75850a708f8fSGustavo F. Padovan
758623691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) {
7587eeb5a067SMarcel Holtmann seq_printf(f, "%pMR (%u) %pMR (%u) %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
7588eeb5a067SMarcel Holtmann &c->src, c->src_type, &c->dst, c->dst_type,
758989bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm),
759023691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu,
l2cap_debugfs_show(struct seq_file * f,void * p)759123691d75SGustavo F. Padovan c->sec_level, c->mode);
75920a708f8fSGustavo F. Padovan }
75930a708f8fSGustavo F. Padovan
7594333055f2SGustavo F. Padovan read_unlock(&chan_list_lock);
75950a708f8fSGustavo F. Padovan
75960a708f8fSGustavo F. Padovan return 0;
75970a708f8fSGustavo F. Padovan }
75980a708f8fSGustavo F. Padovan
75998e2924e3SYangtao Li DEFINE_SHOW_ATTRIBUTE(l2cap_debugfs);
76000a708f8fSGustavo F. Padovan
76010a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
76020a708f8fSGustavo F. Padovan
760364274518SGustavo F. Padovan int __init l2cap_init(void)
76040a708f8fSGustavo F. Padovan {
76050a708f8fSGustavo F. Padovan int err;
76060a708f8fSGustavo F. Padovan
7607bb58f747SGustavo F. Padovan err = l2cap_init_sockets();
76080a708f8fSGustavo F. Padovan if (err < 0)
76090a708f8fSGustavo F. Padovan return err;
76100a708f8fSGustavo F. Padovan
7611354fe804SJohan Hedberg hci_register_cb(&l2cap_cb);
7612354fe804SJohan Hedberg
76131120e4bfSMarcel Holtmann if (IS_ERR_OR_NULL(bt_debugfs))
l2cap_init(void)76141120e4bfSMarcel Holtmann return 0;
76151120e4bfSMarcel Holtmann
76162d792818SGustavo Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
76172d792818SGustavo Padovan NULL, &l2cap_debugfs_fops);
76180a708f8fSGustavo F. Padovan
76190a708f8fSGustavo F. Padovan return 0;
76200a708f8fSGustavo F. Padovan }
76210a708f8fSGustavo F. Padovan
762264274518SGustavo F. Padovan void l2cap_exit(void)
76230a708f8fSGustavo F. Padovan {
76240a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs);
7625354fe804SJohan Hedberg hci_unregister_cb(&l2cap_cb);
7626bb58f747SGustavo F. Padovan l2cap_cleanup_sockets();
76270a708f8fSGustavo F. Padovan }
76280a708f8fSGustavo F. Padovan
76290a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
76300a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
76314be5ca67SLuiz Augusto von Dentz
76324be5ca67SLuiz Augusto von Dentz module_param(enable_ecred, bool, 0644);
l2cap_exit(void)76334be5ca67SLuiz Augusto von Dentz MODULE_PARM_DESC(enable_ecred, "Enable enhanced credit flow control mode");
7634