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
1223df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock);
123baa7e1faSGustavo F. Padovan c = __l2cap_get_chan_by_scid(conn, cid);
124d0be8347SLuiz Augusto von Dentz if (c) {
125d0be8347SLuiz Augusto von Dentz /* Only lock if chan reference is not 0 */
126d0be8347SLuiz Augusto von Dentz c = l2cap_chan_hold_unless_zero(c);
127ef191adeSMat Martineau if (c)
128ef191adeSMat Martineau l2cap_chan_lock(c);
129d0be8347SLuiz Augusto von Dentz }
1303df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock);
1313df91ea2SAndrei Emeltchenko
13248454079SGustavo F. Padovan return c;
1330a708f8fSGustavo F. Padovan }
1340a708f8fSGustavo F. Padovan
135b1a130b7SMat Martineau /* Find channel with given DCID.
136d0be8347SLuiz Augusto von Dentz * Returns a reference locked channel.
137b1a130b7SMat Martineau */
l2cap_get_chan_by_dcid(struct l2cap_conn * conn,u16 cid)138b1a130b7SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
139b1a130b7SMat Martineau u16 cid)
140b1a130b7SMat Martineau {
141b1a130b7SMat Martineau struct l2cap_chan *c;
142b1a130b7SMat Martineau
143b1a130b7SMat Martineau mutex_lock(&conn->chan_lock);
144b1a130b7SMat Martineau c = __l2cap_get_chan_by_dcid(conn, cid);
145d0be8347SLuiz Augusto von Dentz if (c) {
146d0be8347SLuiz Augusto von Dentz /* Only lock if chan reference is not 0 */
147d0be8347SLuiz Augusto von Dentz c = l2cap_chan_hold_unless_zero(c);
148b1a130b7SMat Martineau if (c)
149b1a130b7SMat Martineau l2cap_chan_lock(c);
150d0be8347SLuiz Augusto von Dentz }
151b1a130b7SMat Martineau mutex_unlock(&conn->chan_lock);
152b1a130b7SMat Martineau
153b1a130b7SMat Martineau return c;
154b1a130b7SMat Martineau }
155b1a130b7SMat Martineau
__l2cap_get_chan_by_ident(struct l2cap_conn * conn,u8 ident)1562d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn,
1572d792818SGustavo Padovan u8 ident)
1580a708f8fSGustavo F. Padovan {
1593df91ea2SAndrei Emeltchenko struct l2cap_chan *c;
160baa7e1faSGustavo F. Padovan
1613df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) {
1623df91ea2SAndrei Emeltchenko if (c->ident == ident)
1633df91ea2SAndrei Emeltchenko return c;
1640a708f8fSGustavo F. Padovan }
1653df91ea2SAndrei Emeltchenko return NULL;
166baa7e1faSGustavo F. Padovan }
1670a708f8fSGustavo F. Padovan
__l2cap_global_chan_by_addr(__le16 psm,bdaddr_t * src,u8 src_type)16800f62726SLuiz Augusto von Dentz static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src,
16900f62726SLuiz Augusto von Dentz u8 src_type)
1709e4425ffSGustavo F. Padovan {
17123691d75SGustavo F. Padovan struct l2cap_chan *c;
1729e4425ffSGustavo F. Padovan
17323691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) {
17400f62726SLuiz Augusto von Dentz if (src_type == BDADDR_BREDR && c->src_type != BDADDR_BREDR)
17500f62726SLuiz Augusto von Dentz continue;
17600f62726SLuiz Augusto von Dentz
17700f62726SLuiz Augusto von Dentz if (src_type != BDADDR_BREDR && c->src_type == BDADDR_BREDR)
17800f62726SLuiz Augusto von Dentz continue;
17900f62726SLuiz Augusto von Dentz
1807eafc59eSMarcel Holtmann if (c->sport == psm && !bacmp(&c->src, src))
18123691d75SGustavo F. Padovan return c;
1829e4425ffSGustavo F. Padovan }
183250938cbSSzymon Janc return NULL;
184250938cbSSzymon Janc }
1859e4425ffSGustavo F. Padovan
l2cap_add_psm(struct l2cap_chan * chan,bdaddr_t * src,__le16 psm)1869e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
1879e4425ffSGustavo F. Padovan {
18873b2ec18SGustavo F. Padovan int err;
18973b2ec18SGustavo F. Padovan
190333055f2SGustavo F. Padovan write_lock(&chan_list_lock);
1919e4425ffSGustavo F. Padovan
19200f62726SLuiz Augusto von Dentz if (psm && __l2cap_global_chan_by_addr(psm, src, chan->src_type)) {
19373b2ec18SGustavo F. Padovan err = -EADDRINUSE;
19473b2ec18SGustavo F. Padovan goto done;
1959e4425ffSGustavo F. Padovan }
1969e4425ffSGustavo F. Padovan
19773b2ec18SGustavo F. Padovan if (psm) {
1989e4425ffSGustavo F. Padovan chan->psm = psm;
1999e4425ffSGustavo F. Padovan chan->sport = psm;
20073b2ec18SGustavo F. Padovan err = 0;
20173b2ec18SGustavo F. Padovan } else {
20292594a51SJohan Hedberg u16 p, start, end, incr;
20392594a51SJohan Hedberg
20492594a51SJohan Hedberg if (chan->src_type == BDADDR_BREDR) {
20592594a51SJohan Hedberg start = L2CAP_PSM_DYN_START;
20692594a51SJohan Hedberg end = L2CAP_PSM_AUTO_END;
20792594a51SJohan Hedberg incr = 2;
20892594a51SJohan Hedberg } else {
20992594a51SJohan Hedberg start = L2CAP_PSM_LE_DYN_START;
21092594a51SJohan Hedberg end = L2CAP_PSM_LE_DYN_END;
21192594a51SJohan Hedberg incr = 1;
21292594a51SJohan Hedberg }
2139e4425ffSGustavo F. Padovan
21473b2ec18SGustavo F. Padovan err = -EINVAL;
21592594a51SJohan Hedberg for (p = start; p <= end; p += incr)
21600f62726SLuiz Augusto von Dentz if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src,
21700f62726SLuiz Augusto von Dentz chan->src_type)) {
21873b2ec18SGustavo F. Padovan chan->psm = cpu_to_le16(p);
21973b2ec18SGustavo F. Padovan chan->sport = cpu_to_le16(p);
22073b2ec18SGustavo F. Padovan err = 0;
22173b2ec18SGustavo F. Padovan break;
22273b2ec18SGustavo F. Padovan }
22373b2ec18SGustavo F. Padovan }
22473b2ec18SGustavo F. Padovan
22573b2ec18SGustavo F. Padovan done:
226333055f2SGustavo F. Padovan write_unlock(&chan_list_lock);
22773b2ec18SGustavo F. Padovan return err;
2289e4425ffSGustavo F. Padovan }
2296b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_add_psm);
2309e4425ffSGustavo F. Padovan
l2cap_add_scid(struct l2cap_chan * chan,__u16 scid)2319e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
2329e4425ffSGustavo F. Padovan {
233333055f2SGustavo F. Padovan write_lock(&chan_list_lock);
2349e4425ffSGustavo F. Padovan
23514824308SJohan Hedberg /* Override the defaults (which are for conn-oriented) */
23614824308SJohan Hedberg chan->omtu = L2CAP_DEFAULT_MTU;
23714824308SJohan Hedberg chan->chan_type = L2CAP_CHAN_FIXED;
23814824308SJohan Hedberg
2399e4425ffSGustavo F. Padovan chan->scid = scid;
2409e4425ffSGustavo F. Padovan
241333055f2SGustavo F. Padovan write_unlock(&chan_list_lock);
2429e4425ffSGustavo F. Padovan
2439e4425ffSGustavo F. Padovan return 0;
2449e4425ffSGustavo F. Padovan }
2459e4425ffSGustavo F. Padovan
l2cap_alloc_cid(struct l2cap_conn * conn)246baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
2470a708f8fSGustavo F. Padovan {
248e77af755SJohan Hedberg u16 cid, dyn_end;
2490a708f8fSGustavo F. Padovan
250e77af755SJohan Hedberg if (conn->hcon->type == LE_LINK)
251e77af755SJohan Hedberg dyn_end = L2CAP_CID_LE_DYN_END;
252e77af755SJohan Hedberg else
253e77af755SJohan Hedberg dyn_end = L2CAP_CID_DYN_END;
254e77af755SJohan Hedberg
255ab0c127fSJohan Hedberg for (cid = L2CAP_CID_DYN_START; cid <= dyn_end; cid++) {
256baa7e1faSGustavo F. Padovan if (!__l2cap_get_chan_by_scid(conn, cid))
2570a708f8fSGustavo F. Padovan return cid;
2580a708f8fSGustavo F. Padovan }
2590a708f8fSGustavo F. Padovan
2600a708f8fSGustavo F. Padovan return 0;
2610a708f8fSGustavo F. Padovan }
2620a708f8fSGustavo F. Padovan
l2cap_state_change(struct l2cap_chan * chan,int state)263f93fa273SGustavo Padovan static void l2cap_state_change(struct l2cap_chan *chan, int state)
26489bc500eSGustavo F. Padovan {
26542d2d87cSAndrei Emeltchenko BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
266badaaa00SGustavo F. Padovan state_to_string(state));
267badaaa00SGustavo F. Padovan
26889bc500eSGustavo F. Padovan chan->state = state;
26953f52121SGustavo Padovan chan->ops->state_change(chan, state, 0);
27089bc500eSGustavo F. Padovan }
27189bc500eSGustavo F. Padovan
l2cap_state_change_and_error(struct l2cap_chan * chan,int state,int err)272f8e73017SGustavo Padovan static inline void l2cap_state_change_and_error(struct l2cap_chan *chan,
273f8e73017SGustavo Padovan int state, int err)
2742e0052e4SAndrei Emeltchenko {
275f8e73017SGustavo Padovan chan->state = state;
27653f52121SGustavo Padovan chan->ops->state_change(chan, chan->state, err);
2772e0052e4SAndrei Emeltchenko }
2782e0052e4SAndrei Emeltchenko
l2cap_chan_set_err(struct l2cap_chan * chan,int err)2792e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2802e0052e4SAndrei Emeltchenko {
281f8e73017SGustavo Padovan chan->ops->state_change(chan, chan->state, err);
2822e0052e4SAndrei Emeltchenko }
2832e0052e4SAndrei Emeltchenko
__set_retrans_timer(struct l2cap_chan * chan)2844239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan)
2854239d16fSMat Martineau {
2864239d16fSMat Martineau if (!delayed_work_pending(&chan->monitor_timer) &&
2874239d16fSMat Martineau chan->retrans_timeout) {
2884239d16fSMat Martineau l2cap_set_timer(chan, &chan->retrans_timer,
2894239d16fSMat Martineau msecs_to_jiffies(chan->retrans_timeout));
2904239d16fSMat Martineau }
2914239d16fSMat Martineau }
2924239d16fSMat Martineau
__set_monitor_timer(struct l2cap_chan * chan)2934239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan)
2944239d16fSMat Martineau {
2954239d16fSMat Martineau __clear_retrans_timer(chan);
2964239d16fSMat Martineau if (chan->monitor_timeout) {
2974239d16fSMat Martineau l2cap_set_timer(chan, &chan->monitor_timer,
2984239d16fSMat Martineau msecs_to_jiffies(chan->monitor_timeout));
2994239d16fSMat Martineau }
3004239d16fSMat Martineau }
3014239d16fSMat Martineau
l2cap_ertm_seq_in_queue(struct sk_buff_head * head,u16 seq)302608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head,
303608bcc6dSMat Martineau u16 seq)
304608bcc6dSMat Martineau {
305608bcc6dSMat Martineau struct sk_buff *skb;
306608bcc6dSMat Martineau
307608bcc6dSMat Martineau skb_queue_walk(head, skb) {
308a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.txseq == seq)
309608bcc6dSMat Martineau return skb;
310608bcc6dSMat Martineau }
311608bcc6dSMat Martineau
312608bcc6dSMat Martineau return NULL;
313608bcc6dSMat Martineau }
314608bcc6dSMat Martineau
3153c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */
3163c588192SMat Martineau
3173c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for
3183c588192SMat Martineau * SREJ requests that are received and for frames that are to be
3193c588192SMat Martineau * retransmitted. These seq_list functions implement a singly-linked
3203c588192SMat Martineau * list in an array, where membership in the list can also be checked
3213c588192SMat Martineau * in constant time. Items can also be added to the tail of the list
3223c588192SMat Martineau * and removed from the head in constant time, without further memory
3233c588192SMat Martineau * allocs or frees.
3243c588192SMat Martineau */
3253c588192SMat Martineau
l2cap_seq_list_init(struct l2cap_seq_list * seq_list,u16 size)3263c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
3273c588192SMat Martineau {
3283c588192SMat Martineau size_t alloc_size, i;
3293c588192SMat Martineau
3303c588192SMat Martineau /* Allocated size is a power of 2 to map sequence numbers
3313c588192SMat Martineau * (which may be up to 14 bits) in to a smaller array that is
3323c588192SMat Martineau * sized for the negotiated ERTM transmit windows.
3333c588192SMat Martineau */
3343c588192SMat Martineau alloc_size = roundup_pow_of_two(size);
3353c588192SMat Martineau
3366da2ec56SKees Cook seq_list->list = kmalloc_array(alloc_size, sizeof(u16), GFP_KERNEL);
3373c588192SMat Martineau if (!seq_list->list)
3383c588192SMat Martineau return -ENOMEM;
3393c588192SMat Martineau
3403c588192SMat Martineau seq_list->mask = alloc_size - 1;
3413c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3423c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3433c588192SMat Martineau for (i = 0; i < alloc_size; i++)
3443c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3453c588192SMat Martineau
3463c588192SMat Martineau return 0;
3473c588192SMat Martineau }
3483c588192SMat Martineau
l2cap_seq_list_free(struct l2cap_seq_list * seq_list)3493c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
3503c588192SMat Martineau {
3513c588192SMat Martineau kfree(seq_list->list);
3523c588192SMat Martineau }
3533c588192SMat Martineau
l2cap_seq_list_contains(struct l2cap_seq_list * seq_list,u16 seq)3543c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
3553c588192SMat Martineau u16 seq)
3563c588192SMat Martineau {
3573c588192SMat Martineau /* Constant-time check for list membership */
3583c588192SMat Martineau return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
3593c588192SMat Martineau }
3603c588192SMat Martineau
l2cap_seq_list_pop(struct l2cap_seq_list * seq_list)36103a0c5d6SJohan Hedberg static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
3623c588192SMat Martineau {
36303a0c5d6SJohan Hedberg u16 seq = seq_list->head;
3643c588192SMat Martineau u16 mask = seq_list->mask;
3653c588192SMat Martineau
3663c588192SMat Martineau seq_list->head = seq_list->list[seq & mask];
3673c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3683c588192SMat Martineau
3693c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
3703c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3713c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3723c588192SMat Martineau }
3733c588192SMat Martineau
3743c588192SMat Martineau return seq;
3753c588192SMat Martineau }
3763c588192SMat Martineau
l2cap_seq_list_clear(struct l2cap_seq_list * seq_list)3773c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
3783c588192SMat Martineau {
3793c588192SMat Martineau u16 i;
380f522ae36SGustavo Padovan
381f522ae36SGustavo Padovan if (seq_list->head == L2CAP_SEQ_LIST_CLEAR)
382f522ae36SGustavo Padovan return;
383f522ae36SGustavo Padovan
3843c588192SMat Martineau for (i = 0; i <= seq_list->mask; i++)
3853c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3863c588192SMat Martineau
3873c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3883c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3893c588192SMat Martineau }
3903c588192SMat Martineau
l2cap_seq_list_append(struct l2cap_seq_list * seq_list,u16 seq)3913c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
3923c588192SMat Martineau {
3933c588192SMat Martineau u16 mask = seq_list->mask;
3943c588192SMat Martineau
3953c588192SMat Martineau /* All appends happen in constant time */
3963c588192SMat Martineau
397f522ae36SGustavo Padovan if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR)
398f522ae36SGustavo Padovan return;
399f522ae36SGustavo Padovan
4003c588192SMat Martineau if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
4013c588192SMat Martineau seq_list->head = seq;
4023c588192SMat Martineau else
4033c588192SMat Martineau seq_list->list[seq_list->tail & mask] = seq;
4043c588192SMat Martineau
4053c588192SMat Martineau seq_list->tail = seq;
4063c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
4073c588192SMat Martineau }
4083c588192SMat Martineau
l2cap_chan_timeout(struct work_struct * work)409721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work)
410ab07801dSGustavo F. Padovan {
411721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
412721c4181SGustavo F. Padovan chan_timer.work);
4133df91ea2SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn;
414ab07801dSGustavo F. Padovan int reason;
415ab07801dSGustavo F. Padovan
416e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
417ab07801dSGustavo F. Padovan
418955b5b6cSDuoming Zhou if (!conn)
419955b5b6cSDuoming Zhou return;
420955b5b6cSDuoming Zhou
4213df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock);
4226c08fc89SManish Mandlik /* __set_chan_timer() calls l2cap_chan_hold(chan) while scheduling
4236c08fc89SManish Mandlik * this work. No need to call l2cap_chan_hold(chan) here again.
4246c08fc89SManish Mandlik */
4256be36555SAndrei Emeltchenko l2cap_chan_lock(chan);
426ab07801dSGustavo F. Padovan
42789bc500eSGustavo F. Padovan if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
428ab07801dSGustavo F. Padovan reason = ECONNREFUSED;
42989bc500eSGustavo F. Padovan else if (chan->state == BT_CONNECT &&
430ab07801dSGustavo F. Padovan chan->sec_level != BT_SECURITY_SDP)
431ab07801dSGustavo F. Padovan reason = ECONNREFUSED;
432ab07801dSGustavo F. Padovan else
433ab07801dSGustavo F. Padovan reason = ETIMEDOUT;
434ab07801dSGustavo F. Padovan
4350f852724SGustavo F. Padovan l2cap_chan_close(chan, reason);
436ab07801dSGustavo F. Padovan
43780b98027SGustavo Padovan chan->ops->close(chan);
4383df91ea2SAndrei Emeltchenko
4396c08fc89SManish Mandlik l2cap_chan_unlock(chan);
440371fd835SUlisses Furquim l2cap_chan_put(chan);
4416c08fc89SManish Mandlik
4426c08fc89SManish Mandlik mutex_unlock(&conn->chan_lock);
443ab07801dSGustavo F. Padovan }
444ab07801dSGustavo F. Padovan
l2cap_chan_create(void)445eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void)
4460a708f8fSGustavo F. Padovan {
44748454079SGustavo F. Padovan struct l2cap_chan *chan;
4480a708f8fSGustavo F. Padovan
44948454079SGustavo F. Padovan chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
45048454079SGustavo F. Padovan if (!chan)
45148454079SGustavo F. Padovan return NULL;
4520a708f8fSGustavo F. Padovan
453be859723STetsuo Handa skb_queue_head_init(&chan->tx_q);
454be859723STetsuo Handa skb_queue_head_init(&chan->srej_q);
455c03b355eSAndrei Emeltchenko mutex_init(&chan->lock);
456c03b355eSAndrei Emeltchenko
457ff714119SJohan Hedberg /* Set default lock nesting level */
458ff714119SJohan Hedberg atomic_set(&chan->nesting, L2CAP_NESTING_NORMAL);
459ff714119SJohan Hedberg
460e2310343SSebastian Urban /* Available receive buffer space is initially unknown */
461e2310343SSebastian Urban chan->rx_avail = -1;
462e2310343SSebastian Urban
463333055f2SGustavo F. Padovan write_lock(&chan_list_lock);
46423691d75SGustavo F. Padovan list_add(&chan->global_l, &chan_list);
465333055f2SGustavo F. Padovan write_unlock(&chan_list_lock);
46623691d75SGustavo F. Padovan
467721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
4682d2cb306STetsuo Handa INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
4692d2cb306STetsuo Handa INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
4702d2cb306STetsuo Handa INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
471ab07801dSGustavo F. Padovan
47289bc500eSGustavo F. Padovan chan->state = BT_OPEN;
47389bc500eSGustavo F. Padovan
474144ad330SSyam Sidhardhan kref_init(&chan->kref);
47571ba0e56SGustavo F. Padovan
4762827011fSMat Martineau /* This flag is cleared in l2cap_chan_ready() */
4772827011fSMat Martineau set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
4782827011fSMat Martineau
479eef1d9b6SGustavo Padovan BT_DBG("chan %p", chan);
480abc545b8SSzymon Janc
48148454079SGustavo F. Padovan return chan;
4820a708f8fSGustavo F. Padovan }
4836b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_create);
4840a708f8fSGustavo F. Padovan
l2cap_chan_destroy(struct kref * kref)485144ad330SSyam Sidhardhan static void l2cap_chan_destroy(struct kref *kref)
4866ff5abbfSGustavo F. Padovan {
487144ad330SSyam Sidhardhan struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref);
488144ad330SSyam Sidhardhan
4894af66c69SJaganath Kanakkassery BT_DBG("chan %p", chan);
4904af66c69SJaganath Kanakkassery
491333055f2SGustavo F. Padovan write_lock(&chan_list_lock);
49223691d75SGustavo F. Padovan list_del(&chan->global_l);
493333055f2SGustavo F. Padovan write_unlock(&chan_list_lock);
49423691d75SGustavo F. Padovan
4954af66c69SJaganath Kanakkassery kfree(chan);
4966ff5abbfSGustavo F. Padovan }
4976ff5abbfSGustavo F. Padovan
l2cap_chan_hold(struct l2cap_chan * c)49830648372SJaganath Kanakkassery void l2cap_chan_hold(struct l2cap_chan *c)
49930648372SJaganath Kanakkassery {
50093917fd2SKai Ye BT_DBG("chan %p orig refcnt %u", c, kref_read(&c->kref));
50130648372SJaganath Kanakkassery
502144ad330SSyam Sidhardhan kref_get(&c->kref);
50330648372SJaganath Kanakkassery }
50430648372SJaganath Kanakkassery
l2cap_chan_hold_unless_zero(struct l2cap_chan * c)505d0be8347SLuiz Augusto von Dentz struct l2cap_chan *l2cap_chan_hold_unless_zero(struct l2cap_chan *c)
506d0be8347SLuiz Augusto von Dentz {
507d0be8347SLuiz Augusto von Dentz BT_DBG("chan %p orig refcnt %u", c, kref_read(&c->kref));
508d0be8347SLuiz Augusto von Dentz
509d0be8347SLuiz Augusto von Dentz if (!kref_get_unless_zero(&c->kref))
510d0be8347SLuiz Augusto von Dentz return NULL;
511d0be8347SLuiz Augusto von Dentz
512d0be8347SLuiz Augusto von Dentz return c;
513d0be8347SLuiz Augusto von Dentz }
514d0be8347SLuiz Augusto von Dentz
l2cap_chan_put(struct l2cap_chan * c)51530648372SJaganath Kanakkassery void l2cap_chan_put(struct l2cap_chan *c)
51630648372SJaganath Kanakkassery {
51793917fd2SKai Ye BT_DBG("chan %p orig refcnt %u", c, kref_read(&c->kref));
51830648372SJaganath Kanakkassery
519144ad330SSyam Sidhardhan kref_put(&c->kref, l2cap_chan_destroy);
52030648372SJaganath Kanakkassery }
5216b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_put);
52230648372SJaganath Kanakkassery
l2cap_chan_set_defaults(struct l2cap_chan * chan)523bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan)
524bd4b1653SAndrei Emeltchenko {
525bd4b1653SAndrei Emeltchenko chan->fcs = L2CAP_FCS_CRC16;
526bd4b1653SAndrei Emeltchenko chan->max_tx = L2CAP_DEFAULT_MAX_TX;
527bd4b1653SAndrei Emeltchenko chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
528bd4b1653SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
5296a5e8165SJukka Rissanen chan->remote_max_tx = chan->max_tx;
5306a5e8165SJukka Rissanen chan->remote_tx_win = chan->tx_win;
531c20f8e35SMat Martineau chan->ack_win = L2CAP_DEFAULT_TX_WINDOW;
532bd4b1653SAndrei Emeltchenko chan->sec_level = BT_SECURITY_LOW;
5336a5e8165SJukka Rissanen chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
5346a5e8165SJukka Rissanen chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
5356a5e8165SJukka Rissanen chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
5363a9d54b1SArchie Pusaka
5376a5e8165SJukka Rissanen chan->conf_state = 0;
5383a9d54b1SArchie Pusaka set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
539bd4b1653SAndrei Emeltchenko
540bd4b1653SAndrei Emeltchenko set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
541bd4b1653SAndrei Emeltchenko }
5426b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_set_defaults);
543bd4b1653SAndrei Emeltchenko
l2cap_le_rx_credits(struct l2cap_chan * chan)544e2310343SSebastian Urban static __u16 l2cap_le_rx_credits(struct l2cap_chan *chan)
545e2310343SSebastian Urban {
546e2310343SSebastian Urban size_t sdu_len = chan->sdu ? chan->sdu->len : 0;
547e2310343SSebastian Urban
548e2310343SSebastian Urban if (chan->mps == 0)
549e2310343SSebastian Urban return 0;
550e2310343SSebastian Urban
551e2310343SSebastian Urban /* If we don't know the available space in the receiver buffer, give
552e2310343SSebastian Urban * enough credits for a full packet.
553e2310343SSebastian Urban */
554e2310343SSebastian Urban if (chan->rx_avail == -1)
555e2310343SSebastian Urban return (chan->imtu / chan->mps) + 1;
556e2310343SSebastian Urban
557e2310343SSebastian Urban /* If we know how much space is available in the receive buffer, give
558e2310343SSebastian Urban * out as many credits as would fill the buffer.
559e2310343SSebastian Urban */
560e2310343SSebastian Urban if (chan->rx_avail <= sdu_len)
561e2310343SSebastian Urban return 0;
562e2310343SSebastian Urban
563e2310343SSebastian Urban return DIV_ROUND_UP(chan->rx_avail - sdu_len, chan->mps);
564e2310343SSebastian Urban }
565e2310343SSebastian Urban
l2cap_le_flowctl_init(struct l2cap_chan * chan,u16 tx_credits)566ba8f5289SLuiz Augusto von Dentz static void l2cap_le_flowctl_init(struct l2cap_chan *chan, u16 tx_credits)
56738319713SJohan Hedberg {
5680ce43ce6SJohan Hedberg chan->sdu = NULL;
5690ce43ce6SJohan Hedberg chan->sdu_last_frag = NULL;
5700ce43ce6SJohan Hedberg chan->sdu_len = 0;
571ba8f5289SLuiz Augusto von Dentz chan->tx_credits = tx_credits;
572fe149310SLuiz Augusto von Dentz /* Derive MPS from connection MTU to stop HCI fragmentation */
573fe149310SLuiz Augusto von Dentz chan->mps = min_t(u16, chan->imtu, chan->conn->mtu - L2CAP_HDR_SIZE);
574e2310343SSebastian Urban chan->rx_credits = l2cap_le_rx_credits(chan);
5750ce43ce6SJohan Hedberg
5760ce43ce6SJohan Hedberg skb_queue_head_init(&chan->tx_q);
57738319713SJohan Hedberg }
57838319713SJohan Hedberg
l2cap_ecred_init(struct l2cap_chan * chan,u16 tx_credits)57915f02b91SLuiz Augusto von Dentz static void l2cap_ecred_init(struct l2cap_chan *chan, u16 tx_credits)
58015f02b91SLuiz Augusto von Dentz {
58115f02b91SLuiz Augusto von Dentz l2cap_le_flowctl_init(chan, tx_credits);
58215f02b91SLuiz Augusto von Dentz
58315f02b91SLuiz Augusto von Dentz /* L2CAP implementations shall support a minimum MPS of 64 octets */
58415f02b91SLuiz Augusto von Dentz if (chan->mps < L2CAP_ECRED_MIN_MPS) {
58515f02b91SLuiz Augusto von Dentz chan->mps = L2CAP_ECRED_MIN_MPS;
586e2310343SSebastian Urban chan->rx_credits = l2cap_le_rx_credits(chan);
58715f02b91SLuiz Augusto von Dentz }
58815f02b91SLuiz Augusto von Dentz }
58915f02b91SLuiz Augusto von Dentz
__l2cap_chan_add(struct l2cap_conn * conn,struct l2cap_chan * chan)59093c3e8f5SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
5910a708f8fSGustavo F. Padovan {
5920a708f8fSGustavo F. Padovan BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
593097db76cSAndrei Emeltchenko __le16_to_cpu(chan->psm), chan->dcid);
5940a708f8fSGustavo F. Padovan
5959f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
5960a708f8fSGustavo F. Padovan
5978c1d787bSGustavo F. Padovan chan->conn = conn;
5980a708f8fSGustavo F. Padovan
5995491120eSAndrei Emeltchenko switch (chan->chan_type) {
6005491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_ORIENTED:
6010a708f8fSGustavo F. Padovan /* Alloc CID for connection-oriented socket */
602fe4128e0SGustavo F. Padovan chan->scid = l2cap_alloc_cid(conn);
60321626e62SJohan Hedberg if (conn->hcon->type == ACL_LINK)
6040c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU;
6055491120eSAndrei Emeltchenko break;
6065491120eSAndrei Emeltchenko
6075491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_LESS:
6080a708f8fSGustavo F. Padovan /* Connectionless socket */
609fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_CONN_LESS;
610fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_CONN_LESS;
6110c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU;
6125491120eSAndrei Emeltchenko break;
6135491120eSAndrei Emeltchenko
6142338a7e0SJohan Hedberg case L2CAP_CHAN_FIXED:
6152338a7e0SJohan Hedberg /* Caller will set CID and CID specific MTU values */
616416fa752SAndrei Emeltchenko break;
617416fa752SAndrei Emeltchenko
6185491120eSAndrei Emeltchenko default:
6190a708f8fSGustavo F. Padovan /* Raw socket can send/recv signalling messages only */
620fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_SIGNALING;
621fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_SIGNALING;
6220c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU;
6230a708f8fSGustavo F. Padovan }
6240a708f8fSGustavo F. Padovan
6258f7975b1SAndrei Emeltchenko chan->local_id = L2CAP_BESTEFFORT_ID;
6268f7975b1SAndrei Emeltchenko chan->local_stype = L2CAP_SERV_BESTEFFORT;
6278f7975b1SAndrei Emeltchenko chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE;
6288f7975b1SAndrei Emeltchenko chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME;
6298f7975b1SAndrei Emeltchenko chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
6308936fa6dSAndrei Emeltchenko chan->local_flush_to = L2CAP_EFS_DEFAULT_FLUSH_TO;
6318f7975b1SAndrei Emeltchenko
632371fd835SUlisses Furquim l2cap_chan_hold(chan);
633baa7e1faSGustavo F. Padovan
634c16900cfSJohan Hedberg /* Only keep a reference for fixed channels if they requested it */
635c16900cfSJohan Hedberg if (chan->chan_type != L2CAP_CHAN_FIXED ||
636c16900cfSJohan Hedberg test_bit(FLAG_HOLD_HCI_CONN, &chan->flags))
6375ee9891dSJohan Hedberg hci_conn_hold(conn->hcon);
6385ee9891dSJohan Hedberg
6393df91ea2SAndrei Emeltchenko list_add(&chan->list, &conn->chan_l);
640643162a8SAndrei Emeltchenko }
641643162a8SAndrei Emeltchenko
l2cap_chan_add(struct l2cap_conn * conn,struct l2cap_chan * chan)642466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
643643162a8SAndrei Emeltchenko {
644643162a8SAndrei Emeltchenko mutex_lock(&conn->chan_lock);
645643162a8SAndrei Emeltchenko __l2cap_chan_add(conn, chan);
6463df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock);
6470a708f8fSGustavo F. Padovan }
6480a708f8fSGustavo F. Padovan
l2cap_chan_del(struct l2cap_chan * chan,int err)649466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err)
6500a708f8fSGustavo F. Padovan {
6518c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn;
6520a708f8fSGustavo F. Padovan
653c9b66675SGustavo F. Padovan __clear_chan_timer(chan);
6540a708f8fSGustavo F. Padovan
65549d11741SJohan Hedberg BT_DBG("chan %p, conn %p, err %d, state %s", chan, conn, err,
65649d11741SJohan Hedberg state_to_string(chan->state));
6570a708f8fSGustavo F. Padovan
65872847ce0SJohan Hedberg chan->ops->teardown(chan, err);
65972847ce0SJohan Hedberg
6600a708f8fSGustavo F. Padovan if (conn) {
661baa7e1faSGustavo F. Padovan /* Delete from channel list */
6623df91ea2SAndrei Emeltchenko list_del(&chan->list);
6633d57dc68SGustavo F. Padovan
664371fd835SUlisses Furquim l2cap_chan_put(chan);
665baa7e1faSGustavo F. Padovan
6668c1d787bSGustavo F. Padovan chan->conn = NULL;
6673cabbfdaSAndrei Emeltchenko
668c16900cfSJohan Hedberg /* Reference was only held for non-fixed channels or
669c16900cfSJohan Hedberg * fixed channels that explicitly requested it using the
670c16900cfSJohan Hedberg * FLAG_HOLD_HCI_CONN flag.
671c16900cfSJohan Hedberg */
672c16900cfSJohan Hedberg if (chan->chan_type != L2CAP_CHAN_FIXED ||
673c16900cfSJohan Hedberg test_bit(FLAG_HOLD_HCI_CONN, &chan->flags))
67476a68ba0SDavid Herrmann hci_conn_drop(conn->hcon);
675419e08c1SAndrei Emeltchenko }
676419e08c1SAndrei Emeltchenko
6772827011fSMat Martineau if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
6786ff5abbfSGustavo F. Padovan return;
6792ead70b8SGustavo F. Padovan
680ee556f66SGustavo Padovan switch (chan->mode) {
681ee556f66SGustavo Padovan case L2CAP_MODE_BASIC:
682ee556f66SGustavo Padovan break;
6830a708f8fSGustavo F. Padovan
68438319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL:
68515f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL:
686177f8f2bSJohan Hedberg skb_queue_purge(&chan->tx_q);
68738319713SJohan Hedberg break;
68838319713SJohan Hedberg
689ee556f66SGustavo Padovan case L2CAP_MODE_ERTM:
6901a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan);
6911a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan);
6921a09bcb9SGustavo F. Padovan __clear_ack_timer(chan);
6930a708f8fSGustavo F. Padovan
694f1c6775bSGustavo F. Padovan skb_queue_purge(&chan->srej_q);
6950a708f8fSGustavo F. Padovan
6963c588192SMat Martineau l2cap_seq_list_free(&chan->srej_list);
6973c588192SMat Martineau l2cap_seq_list_free(&chan->retrans_list);
69819186c7bSGustavo A. R. Silva fallthrough;
699ee556f66SGustavo Padovan
700ee556f66SGustavo Padovan case L2CAP_MODE_STREAMING:
701ee556f66SGustavo Padovan skb_queue_purge(&chan->tx_q);
702ee556f66SGustavo Padovan break;
7030a708f8fSGustavo F. Padovan }
7040a708f8fSGustavo F. Padovan }
7056b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_del);
7060a708f8fSGustavo F. Padovan
__l2cap_chan_list_id(struct l2cap_conn * conn,u16 id,l2cap_chan_func_t func,void * data)7079aa9d947SLuiz Augusto von Dentz static void __l2cap_chan_list_id(struct l2cap_conn *conn, u16 id,
7089aa9d947SLuiz Augusto von Dentz l2cap_chan_func_t func, void *data)
7099aa9d947SLuiz Augusto von Dentz {
7109aa9d947SLuiz Augusto von Dentz struct l2cap_chan *chan, *l;
7119aa9d947SLuiz Augusto von Dentz
7129aa9d947SLuiz Augusto von Dentz list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
7139aa9d947SLuiz Augusto von Dentz if (chan->ident == id)
7149aa9d947SLuiz Augusto von Dentz func(chan, data);
7159aa9d947SLuiz Augusto von Dentz }
7169aa9d947SLuiz Augusto von Dentz }
7179aa9d947SLuiz Augusto von Dentz
__l2cap_chan_list(struct l2cap_conn * conn,l2cap_chan_func_t func,void * data)718da49b602SLuiz Augusto von Dentz static void __l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func,
719da49b602SLuiz Augusto von Dentz void *data)
720da49b602SLuiz Augusto von Dentz {
721da49b602SLuiz Augusto von Dentz struct l2cap_chan *chan;
722da49b602SLuiz Augusto von Dentz
723da49b602SLuiz Augusto von Dentz list_for_each_entry(chan, &conn->chan_l, list) {
724da49b602SLuiz Augusto von Dentz func(chan, data);
725da49b602SLuiz Augusto von Dentz }
726da49b602SLuiz Augusto von Dentz }
727da49b602SLuiz Augusto von Dentz
l2cap_chan_list(struct l2cap_conn * conn,l2cap_chan_func_t func,void * data)728da49b602SLuiz Augusto von Dentz void l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func,
729da49b602SLuiz Augusto von Dentz void *data)
730da49b602SLuiz Augusto von Dentz {
731da49b602SLuiz Augusto von Dentz if (!conn)
732da49b602SLuiz Augusto von Dentz return;
733da49b602SLuiz Augusto von Dentz
734da49b602SLuiz Augusto von Dentz mutex_lock(&conn->chan_lock);
735da49b602SLuiz Augusto von Dentz __l2cap_chan_list(conn, func, data);
736da49b602SLuiz Augusto von Dentz mutex_unlock(&conn->chan_lock);
737da49b602SLuiz Augusto von Dentz }
738da49b602SLuiz Augusto von Dentz
739da49b602SLuiz Augusto von Dentz EXPORT_SYMBOL_GPL(l2cap_chan_list);
740da49b602SLuiz Augusto von Dentz
l2cap_conn_update_id_addr(struct work_struct * work)741f3d82d0cSJohan Hedberg static void l2cap_conn_update_id_addr(struct work_struct *work)
742387a33e3SJohan Hedberg {
743f3d82d0cSJohan Hedberg struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
744b8b23001SLuiz Augusto von Dentz id_addr_timer.work);
745f3d82d0cSJohan Hedberg struct hci_conn *hcon = conn->hcon;
746387a33e3SJohan Hedberg struct l2cap_chan *chan;
747387a33e3SJohan Hedberg
748387a33e3SJohan Hedberg mutex_lock(&conn->chan_lock);
749387a33e3SJohan Hedberg
750387a33e3SJohan Hedberg list_for_each_entry(chan, &conn->chan_l, list) {
751387a33e3SJohan Hedberg l2cap_chan_lock(chan);
752387a33e3SJohan Hedberg bacpy(&chan->dst, &hcon->dst);
753a250e048SJohan Hedberg chan->dst_type = bdaddr_dst_type(hcon);
754387a33e3SJohan Hedberg l2cap_chan_unlock(chan);
755387a33e3SJohan Hedberg }
756387a33e3SJohan Hedberg
757387a33e3SJohan Hedberg mutex_unlock(&conn->chan_lock);
758387a33e3SJohan Hedberg }
759387a33e3SJohan Hedberg
l2cap_chan_le_connect_reject(struct l2cap_chan * chan)76027e2d4c8SJohan Hedberg static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan)
76127e2d4c8SJohan Hedberg {
76227e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn;
76327e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp;
76427e2d4c8SJohan Hedberg u16 result;
76527e2d4c8SJohan Hedberg
76627e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
767571f7390SMallikarjun Phulari result = L2CAP_CR_LE_AUTHORIZATION;
76827e2d4c8SJohan Hedberg else
769571f7390SMallikarjun Phulari result = L2CAP_CR_LE_BAD_PSM;
77027e2d4c8SJohan Hedberg
77127e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_DISCONN);
77227e2d4c8SJohan Hedberg
77327e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid);
77427e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu);
7753916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps);
7760cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits);
77727e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result);
77827e2d4c8SJohan Hedberg
77927e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
78027e2d4c8SJohan Hedberg &rsp);
78127e2d4c8SJohan Hedberg }
78227e2d4c8SJohan Hedberg
l2cap_chan_ecred_connect_reject(struct l2cap_chan * chan)78315f02b91SLuiz Augusto von Dentz static void l2cap_chan_ecred_connect_reject(struct l2cap_chan *chan)
78415f02b91SLuiz Augusto von Dentz {
78515f02b91SLuiz Augusto von Dentz l2cap_state_change(chan, BT_DISCONN);
78615f02b91SLuiz Augusto von Dentz
7879aa9d947SLuiz Augusto von Dentz __l2cap_ecred_conn_rsp_defer(chan);
78815f02b91SLuiz Augusto von Dentz }
78915f02b91SLuiz Augusto von Dentz
l2cap_chan_connect_reject(struct l2cap_chan * chan)790791d60f7SJohan Hedberg static void l2cap_chan_connect_reject(struct l2cap_chan *chan)
791791d60f7SJohan Hedberg {
792791d60f7SJohan Hedberg struct l2cap_conn *conn = chan->conn;
793791d60f7SJohan Hedberg struct l2cap_conn_rsp rsp;
794791d60f7SJohan Hedberg u16 result;
795791d60f7SJohan Hedberg
796791d60f7SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
797791d60f7SJohan Hedberg result = L2CAP_CR_SEC_BLOCK;
798791d60f7SJohan Hedberg else
799791d60f7SJohan Hedberg result = L2CAP_CR_BAD_PSM;
800791d60f7SJohan Hedberg
801791d60f7SJohan Hedberg l2cap_state_change(chan, BT_DISCONN);
802791d60f7SJohan Hedberg
803791d60f7SJohan Hedberg rsp.scid = cpu_to_le16(chan->dcid);
804791d60f7SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid);
805791d60f7SJohan Hedberg rsp.result = cpu_to_le16(result);
806dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
807791d60f7SJohan Hedberg
808791d60f7SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
809791d60f7SJohan Hedberg }
810791d60f7SJohan Hedberg
l2cap_chan_close(struct l2cap_chan * chan,int reason)8110f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason)
8124519de9aSGustavo F. Padovan {
8134519de9aSGustavo F. Padovan struct l2cap_conn *conn = chan->conn;
8144519de9aSGustavo F. Padovan
8157eafc59eSMarcel Holtmann BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
8164519de9aSGustavo F. Padovan
81789bc500eSGustavo F. Padovan switch (chan->state) {
8184519de9aSGustavo F. Padovan case BT_LISTEN:
819c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0);
8204519de9aSGustavo F. Padovan break;
8214519de9aSGustavo F. Padovan
8224519de9aSGustavo F. Padovan case BT_CONNECTED:
8234519de9aSGustavo F. Padovan case BT_CONFIG:
8247b25c9b3SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
8258d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
8265e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, reason);
8274519de9aSGustavo F. Padovan } else
8284519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason);
8294519de9aSGustavo F. Padovan break;
8304519de9aSGustavo F. Padovan
8314519de9aSGustavo F. Padovan case BT_CONNECT2:
832791d60f7SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
833791d60f7SJohan Hedberg if (conn->hcon->type == ACL_LINK)
834791d60f7SJohan Hedberg l2cap_chan_connect_reject(chan);
83515f02b91SLuiz Augusto von Dentz else if (conn->hcon->type == LE_LINK) {
83615f02b91SLuiz Augusto von Dentz switch (chan->mode) {
83715f02b91SLuiz Augusto von Dentz case L2CAP_MODE_LE_FLOWCTL:
83827e2d4c8SJohan Hedberg l2cap_chan_le_connect_reject(chan);
83915f02b91SLuiz Augusto von Dentz break;
84015f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL:
84115f02b91SLuiz Augusto von Dentz l2cap_chan_ecred_connect_reject(chan);
8429aa9d947SLuiz Augusto von Dentz return;
84315f02b91SLuiz Augusto von Dentz }
84415f02b91SLuiz Augusto von Dentz }
8454519de9aSGustavo F. Padovan }
8464519de9aSGustavo F. Padovan
8474519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason);
8484519de9aSGustavo F. Padovan break;
8494519de9aSGustavo F. Padovan
8504519de9aSGustavo F. Padovan case BT_CONNECT:
8514519de9aSGustavo F. Padovan case BT_DISCONN:
8524519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason);
8534519de9aSGustavo F. Padovan break;
8544519de9aSGustavo F. Padovan
8554519de9aSGustavo F. Padovan default:
856c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0);
8574519de9aSGustavo F. Padovan break;
8584519de9aSGustavo F. Padovan }
8594519de9aSGustavo F. Padovan }
8606b8d4a6aSJukka Rissanen EXPORT_SYMBOL(l2cap_chan_close);
8614519de9aSGustavo F. Padovan
l2cap_get_auth_type(struct l2cap_chan * chan)8624343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
8630a708f8fSGustavo F. Padovan {
8646a974b50SMarcel Holtmann switch (chan->chan_type) {
8656a974b50SMarcel Holtmann case L2CAP_CHAN_RAW:
8664343478fSGustavo F. Padovan switch (chan->sec_level) {
8670a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH:
8687d513e92SMarcel Holtmann case BT_SECURITY_FIPS:
8690a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING_MITM;
8700a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM:
8710a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING;
8720a708f8fSGustavo F. Padovan default:
8730a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING;
8740a708f8fSGustavo F. Padovan }
8756a974b50SMarcel Holtmann break;
8763124b843SMarcel Holtmann case L2CAP_CHAN_CONN_LESS:
877dcf4adbfSJoe Perches if (chan->psm == cpu_to_le16(L2CAP_PSM_3DSP)) {
8783124b843SMarcel Holtmann if (chan->sec_level == BT_SECURITY_LOW)
8793124b843SMarcel Holtmann chan->sec_level = BT_SECURITY_SDP;
8803124b843SMarcel Holtmann }
8817d513e92SMarcel Holtmann if (chan->sec_level == BT_SECURITY_HIGH ||
8827d513e92SMarcel Holtmann chan->sec_level == BT_SECURITY_FIPS)
8833124b843SMarcel Holtmann return HCI_AT_NO_BONDING_MITM;
8843124b843SMarcel Holtmann else
8853124b843SMarcel Holtmann return HCI_AT_NO_BONDING;
8863124b843SMarcel Holtmann break;
8876a974b50SMarcel Holtmann case L2CAP_CHAN_CONN_ORIENTED:
888dcf4adbfSJoe Perches if (chan->psm == cpu_to_le16(L2CAP_PSM_SDP)) {
8894343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_LOW)
8904343478fSGustavo F. Padovan chan->sec_level = BT_SECURITY_SDP;
8910a708f8fSGustavo F. Padovan
8927d513e92SMarcel Holtmann if (chan->sec_level == BT_SECURITY_HIGH ||
8937d513e92SMarcel Holtmann chan->sec_level == BT_SECURITY_FIPS)
8940a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING_MITM;
8950a708f8fSGustavo F. Padovan else
8960a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING;
8976a974b50SMarcel Holtmann }
89819186c7bSGustavo A. R. Silva fallthrough;
89919186c7bSGustavo A. R. Silva
9006a974b50SMarcel Holtmann default:
9014343478fSGustavo F. Padovan switch (chan->sec_level) {
9020a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH:
9037d513e92SMarcel Holtmann case BT_SECURITY_FIPS:
9040a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING_MITM;
9050a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM:
9060a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING;
9070a708f8fSGustavo F. Padovan default:
9080a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING;
9090a708f8fSGustavo F. Padovan }
9106a974b50SMarcel Holtmann break;
9110a708f8fSGustavo F. Padovan }
9120a708f8fSGustavo F. Padovan }
9130a708f8fSGustavo F. Padovan
9140a708f8fSGustavo F. Padovan /* Service level security */
l2cap_chan_check_security(struct l2cap_chan * chan,bool initiator)915e7cafc45SJohan Hedberg int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator)
9160a708f8fSGustavo F. Padovan {
9178c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn;
9180a708f8fSGustavo F. Padovan __u8 auth_type;
9190a708f8fSGustavo F. Padovan
920a17de2feSJohan Hedberg if (conn->hcon->type == LE_LINK)
921a17de2feSJohan Hedberg return smp_conn_security(conn->hcon, chan->sec_level);
922a17de2feSJohan Hedberg
9234343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan);
9240a708f8fSGustavo F. Padovan
925e7cafc45SJohan Hedberg return hci_conn_security(conn->hcon, chan->sec_level, auth_type,
926e7cafc45SJohan Hedberg initiator);
9270a708f8fSGustavo F. Padovan }
9280a708f8fSGustavo F. Padovan
l2cap_get_ident(struct l2cap_conn * conn)929b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn)
9300a708f8fSGustavo F. Padovan {
9310a708f8fSGustavo F. Padovan u8 id;
9320a708f8fSGustavo F. Padovan
9330a708f8fSGustavo F. Padovan /* Get next available identificator.
9340a708f8fSGustavo F. Padovan * 1 - 128 are used by kernel.
9350a708f8fSGustavo F. Padovan * 129 - 199 are reserved.
9360a708f8fSGustavo F. Padovan * 200 - 254 are used by utilities like l2ping, etc.
9370a708f8fSGustavo F. Padovan */
9380a708f8fSGustavo F. Padovan
9395a54e7c8SMarcel Holtmann mutex_lock(&conn->ident_lock);
9400a708f8fSGustavo F. Padovan
9410a708f8fSGustavo F. Padovan if (++conn->tx_ident > 128)
9420a708f8fSGustavo F. Padovan conn->tx_ident = 1;
9430a708f8fSGustavo F. Padovan
9440a708f8fSGustavo F. Padovan id = conn->tx_ident;
9450a708f8fSGustavo F. Padovan
9465a54e7c8SMarcel Holtmann mutex_unlock(&conn->ident_lock);
9470a708f8fSGustavo F. Padovan
9480a708f8fSGustavo F. Padovan return id;
9490a708f8fSGustavo F. Padovan }
9500a708f8fSGustavo F. Padovan
l2cap_send_cmd(struct l2cap_conn * conn,u8 ident,u8 code,u16 len,void * data)9512d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
9522d792818SGustavo Padovan void *data)
9530a708f8fSGustavo F. Padovan {
9540a708f8fSGustavo F. Padovan struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
9550a708f8fSGustavo F. Padovan u8 flags;
9560a708f8fSGustavo F. Padovan
9570a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x", code);
9580a708f8fSGustavo F. Padovan
9590a708f8fSGustavo F. Padovan if (!skb)
9600a708f8fSGustavo F. Padovan return;
9610a708f8fSGustavo F. Padovan
962f6af675eSSteven Walter /* Use NO_FLUSH if supported or we have an LE link (which does
963f6af675eSSteven Walter * not support auto-flushing packets) */
964f6af675eSSteven Walter if (lmp_no_flush_capable(conn->hcon->hdev) ||
965f6af675eSSteven Walter conn->hcon->type == LE_LINK)
9660a708f8fSGustavo F. Padovan flags = ACL_START_NO_FLUSH;
9670a708f8fSGustavo F. Padovan else
9680a708f8fSGustavo F. Padovan flags = ACL_START;
9690a708f8fSGustavo F. Padovan
97014b12d0bSJaikumar Ganesh bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
9715e59b791SLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX;
97214b12d0bSJaikumar Ganesh
97373d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, flags);
9740a708f8fSGustavo F. Padovan }
9750a708f8fSGustavo F. Padovan
l2cap_do_send(struct l2cap_chan * chan,struct sk_buff * skb)97673d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
97773d80debSLuiz Augusto von Dentz {
97873d80debSLuiz Augusto von Dentz struct hci_conn *hcon = chan->conn->hcon;
97973d80debSLuiz Augusto von Dentz u16 flags;
98073d80debSLuiz Augusto von Dentz
98173d80debSLuiz Augusto von Dentz BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
98273d80debSLuiz Augusto von Dentz skb->priority);
98373d80debSLuiz Augusto von Dentz
984f6af675eSSteven Walter /* Use NO_FLUSH for LE links (where this is the only option) or
985f6af675eSSteven Walter * if the BR/EDR link supports it and flushing has not been
986f6af675eSSteven Walter * explicitly requested (through FLAG_FLUSHABLE).
987f6af675eSSteven Walter */
988f6af675eSSteven Walter if (hcon->type == LE_LINK ||
989f6af675eSSteven Walter (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
990f6af675eSSteven Walter lmp_no_flush_capable(hcon->hdev)))
99173d80debSLuiz Augusto von Dentz flags = ACL_START_NO_FLUSH;
99273d80debSLuiz Augusto von Dentz else
99373d80debSLuiz Augusto von Dentz flags = ACL_START;
99473d80debSLuiz Augusto von Dentz
99573d80debSLuiz Augusto von Dentz bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
99673d80debSLuiz Augusto von Dentz hci_send_acl(chan->conn->hchan, skb, flags);
9970a708f8fSGustavo F. Padovan }
9980a708f8fSGustavo F. Padovan
__unpack_enhanced_control(u16 enh,struct l2cap_ctrl * control)999b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
1000b5c6aaedSMat Martineau {
1001b5c6aaedSMat Martineau control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
1002b5c6aaedSMat Martineau control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
1003b5c6aaedSMat Martineau
1004b5c6aaedSMat Martineau if (enh & L2CAP_CTRL_FRAME_TYPE) {
1005b5c6aaedSMat Martineau /* S-Frame */
1006b5c6aaedSMat Martineau control->sframe = 1;
1007b5c6aaedSMat Martineau control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
1008b5c6aaedSMat Martineau control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
1009b5c6aaedSMat Martineau
1010b5c6aaedSMat Martineau control->sar = 0;
1011b5c6aaedSMat Martineau control->txseq = 0;
1012b5c6aaedSMat Martineau } else {
1013b5c6aaedSMat Martineau /* I-Frame */
1014b5c6aaedSMat Martineau control->sframe = 0;
1015b5c6aaedSMat Martineau control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
1016b5c6aaedSMat Martineau control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
1017b5c6aaedSMat Martineau
1018b5c6aaedSMat Martineau control->poll = 0;
1019b5c6aaedSMat Martineau control->super = 0;
1020b5c6aaedSMat Martineau }
1021b5c6aaedSMat Martineau }
1022b5c6aaedSMat Martineau
__unpack_extended_control(u32 ext,struct l2cap_ctrl * control)1023b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
1024b5c6aaedSMat Martineau {
1025b5c6aaedSMat Martineau control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
1026b5c6aaedSMat Martineau control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
1027b5c6aaedSMat Martineau
1028b5c6aaedSMat Martineau if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
1029b5c6aaedSMat Martineau /* S-Frame */
1030b5c6aaedSMat Martineau control->sframe = 1;
1031b5c6aaedSMat Martineau control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
1032b5c6aaedSMat Martineau control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
1033b5c6aaedSMat Martineau
1034b5c6aaedSMat Martineau control->sar = 0;
1035b5c6aaedSMat Martineau control->txseq = 0;
1036b5c6aaedSMat Martineau } else {
1037b5c6aaedSMat Martineau /* I-Frame */
1038b5c6aaedSMat Martineau control->sframe = 0;
1039b5c6aaedSMat Martineau control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
1040b5c6aaedSMat Martineau control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
1041b5c6aaedSMat Martineau
1042b5c6aaedSMat Martineau control->poll = 0;
1043b5c6aaedSMat Martineau control->super = 0;
1044b5c6aaedSMat Martineau }
1045b5c6aaedSMat Martineau }
1046b5c6aaedSMat Martineau
__unpack_control(struct l2cap_chan * chan,struct sk_buff * skb)1047b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan,
1048b5c6aaedSMat Martineau struct sk_buff *skb)
1049b5c6aaedSMat Martineau {
1050b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
1051b5c6aaedSMat Martineau __unpack_extended_control(get_unaligned_le32(skb->data),
1052a4368ff3SJohan Hedberg &bt_cb(skb)->l2cap);
1053cec8ab6eSMat Martineau skb_pull(skb, L2CAP_EXT_CTRL_SIZE);
1054b5c6aaedSMat Martineau } else {
1055b5c6aaedSMat Martineau __unpack_enhanced_control(get_unaligned_le16(skb->data),
1056a4368ff3SJohan Hedberg &bt_cb(skb)->l2cap);
1057cec8ab6eSMat Martineau skb_pull(skb, L2CAP_ENH_CTRL_SIZE);
1058b5c6aaedSMat Martineau }
1059b5c6aaedSMat Martineau }
1060b5c6aaedSMat Martineau
__pack_extended_control(struct l2cap_ctrl * control)1061b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control)
1062b5c6aaedSMat Martineau {
1063b5c6aaedSMat Martineau u32 packed;
1064b5c6aaedSMat Martineau
1065b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
1066b5c6aaedSMat Martineau packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
1067b5c6aaedSMat Martineau
1068b5c6aaedSMat Martineau if (control->sframe) {
1069b5c6aaedSMat Martineau packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
1070b5c6aaedSMat Martineau packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
1071b5c6aaedSMat Martineau packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
1072b5c6aaedSMat Martineau } else {
1073b5c6aaedSMat Martineau packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
1074b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
1075b5c6aaedSMat Martineau }
1076b5c6aaedSMat Martineau
1077b5c6aaedSMat Martineau return packed;
1078b5c6aaedSMat Martineau }
1079b5c6aaedSMat Martineau
__pack_enhanced_control(struct l2cap_ctrl * control)1080b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
1081b5c6aaedSMat Martineau {
1082b5c6aaedSMat Martineau u16 packed;
1083b5c6aaedSMat Martineau
1084b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
1085b5c6aaedSMat Martineau packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
1086b5c6aaedSMat Martineau
1087b5c6aaedSMat Martineau if (control->sframe) {
1088b5c6aaedSMat Martineau packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
1089b5c6aaedSMat Martineau packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
1090b5c6aaedSMat Martineau packed |= L2CAP_CTRL_FRAME_TYPE;
1091b5c6aaedSMat Martineau } else {
1092b5c6aaedSMat Martineau packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
1093b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
1094b5c6aaedSMat Martineau }
1095b5c6aaedSMat Martineau
1096b5c6aaedSMat Martineau return packed;
1097b5c6aaedSMat Martineau }
1098b5c6aaedSMat Martineau
__pack_control(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff * skb)1099b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan,
1100b5c6aaedSMat Martineau struct l2cap_ctrl *control,
1101b5c6aaedSMat Martineau struct sk_buff *skb)
1102b5c6aaedSMat Martineau {
1103b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
1104b5c6aaedSMat Martineau put_unaligned_le32(__pack_extended_control(control),
1105b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE);
1106b5c6aaedSMat Martineau } else {
1107b5c6aaedSMat Martineau put_unaligned_le16(__pack_enhanced_control(control),
1108b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE);
1109b5c6aaedSMat Martineau }
1110b5c6aaedSMat Martineau }
1111b5c6aaedSMat Martineau
__ertm_hdr_size(struct l2cap_chan * chan)1112ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan)
1113ba7aa64fSGustavo Padovan {
1114ba7aa64fSGustavo Padovan if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1115ba7aa64fSGustavo Padovan return L2CAP_EXT_HDR_SIZE;
1116ba7aa64fSGustavo Padovan else
1117ba7aa64fSGustavo Padovan return L2CAP_ENH_HDR_SIZE;
1118ba7aa64fSGustavo Padovan }
1119ba7aa64fSGustavo Padovan
l2cap_create_sframe_pdu(struct l2cap_chan * chan,u32 control)1120a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan,
1121a67d7f6fSMat Martineau u32 control)
11220a708f8fSGustavo F. Padovan {
11230a708f8fSGustavo F. Padovan struct sk_buff *skb;
11240a708f8fSGustavo F. Padovan struct l2cap_hdr *lh;
1125ba7aa64fSGustavo Padovan int hlen = __ertm_hdr_size(chan);
11260a708f8fSGustavo F. Padovan
11270a708f8fSGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16)
112803a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE;
11290a708f8fSGustavo F. Padovan
1130a67d7f6fSMat Martineau skb = bt_skb_alloc(hlen, GFP_KERNEL);
11310a708f8fSGustavo F. Padovan
11320a708f8fSGustavo F. Padovan if (!skb)
1133a67d7f6fSMat Martineau return ERR_PTR(-ENOMEM);
11340a708f8fSGustavo F. Padovan
11354df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE);
11360a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
1137fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid);
113888843ab0SAndrei Emeltchenko
1139a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1140a67d7f6fSMat Martineau put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
1141a67d7f6fSMat Martineau else
1142a67d7f6fSMat Martineau put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
11430a708f8fSGustavo F. Padovan
114447d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) {
1145a67d7f6fSMat Martineau u16 fcs = crc16(0, (u8 *)skb->data, skb->len);
114603a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
11470a708f8fSGustavo F. Padovan }
11480a708f8fSGustavo F. Padovan
114973d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX;
1150a67d7f6fSMat Martineau return skb;
1151a67d7f6fSMat Martineau }
1152a67d7f6fSMat Martineau
l2cap_send_sframe(struct l2cap_chan * chan,struct l2cap_ctrl * control)1153a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan,
1154a67d7f6fSMat Martineau struct l2cap_ctrl *control)
1155a67d7f6fSMat Martineau {
1156a67d7f6fSMat Martineau struct sk_buff *skb;
1157a67d7f6fSMat Martineau u32 control_field;
1158a67d7f6fSMat Martineau
1159a67d7f6fSMat Martineau BT_DBG("chan %p, control %p", chan, control);
1160a67d7f6fSMat Martineau
1161a67d7f6fSMat Martineau if (!control->sframe)
1162a67d7f6fSMat Martineau return;
1163a67d7f6fSMat Martineau
1164a67d7f6fSMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
1165a67d7f6fSMat Martineau !control->poll)
1166a67d7f6fSMat Martineau control->final = 1;
1167a67d7f6fSMat Martineau
1168a67d7f6fSMat Martineau if (control->super == L2CAP_SUPER_RR)
1169a67d7f6fSMat Martineau clear_bit(CONN_RNR_SENT, &chan->conn_state);
1170a67d7f6fSMat Martineau else if (control->super == L2CAP_SUPER_RNR)
1171a67d7f6fSMat Martineau set_bit(CONN_RNR_SENT, &chan->conn_state);
1172a67d7f6fSMat Martineau
1173a67d7f6fSMat Martineau if (control->super != L2CAP_SUPER_SREJ) {
1174a67d7f6fSMat Martineau chan->last_acked_seq = control->reqseq;
1175a67d7f6fSMat Martineau __clear_ack_timer(chan);
1176a67d7f6fSMat Martineau }
1177a67d7f6fSMat Martineau
1178a67d7f6fSMat Martineau BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq,
1179a67d7f6fSMat Martineau control->final, control->poll, control->super);
1180a67d7f6fSMat Martineau
1181a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1182a67d7f6fSMat Martineau control_field = __pack_extended_control(control);
1183a67d7f6fSMat Martineau else
1184a67d7f6fSMat Martineau control_field = __pack_enhanced_control(control);
1185a67d7f6fSMat Martineau
1186a67d7f6fSMat Martineau skb = l2cap_create_sframe_pdu(chan, control_field);
1187a67d7f6fSMat Martineau if (!IS_ERR(skb))
118873d80debSLuiz Augusto von Dentz l2cap_do_send(chan, skb);
11890a708f8fSGustavo F. Padovan }
11900a708f8fSGustavo F. Padovan
l2cap_send_rr_or_rnr(struct l2cap_chan * chan,bool poll)1191c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll)
11920a708f8fSGustavo F. Padovan {
1193c9e3d5e0SMat Martineau struct l2cap_ctrl control;
11940a708f8fSGustavo F. Padovan
1195c9e3d5e0SMat Martineau BT_DBG("chan %p, poll %d", chan, poll);
1196c9e3d5e0SMat Martineau
1197c9e3d5e0SMat Martineau memset(&control, 0, sizeof(control));
1198c9e3d5e0SMat Martineau control.sframe = 1;
1199c9e3d5e0SMat Martineau control.poll = poll;
1200c9e3d5e0SMat Martineau
1201c9e3d5e0SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
1202c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RNR;
1203c9e3d5e0SMat Martineau else
1204c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RR;
1205c9e3d5e0SMat Martineau
1206c9e3d5e0SMat Martineau control.reqseq = chan->buffer_seq;
1207c9e3d5e0SMat Martineau l2cap_send_sframe(chan, &control);
12080a708f8fSGustavo F. Padovan }
12090a708f8fSGustavo F. Padovan
__l2cap_no_conn_pending(struct l2cap_chan * chan)1210b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
12110a708f8fSGustavo F. Padovan {
12125ff6f34dSJohan Hedberg if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
12135ff6f34dSJohan Hedberg return true;
12145ff6f34dSJohan Hedberg
1215c1360a1cSGustavo F. Padovan return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
12160a708f8fSGustavo F. Padovan }
12170a708f8fSGustavo F. Padovan
l2cap_send_conn_req(struct l2cap_chan * chan)12182766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan)
12199b27f350SAndrei Emeltchenko {
12209b27f350SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn;
12219b27f350SAndrei Emeltchenko struct l2cap_conn_req req;
12229b27f350SAndrei Emeltchenko
12239b27f350SAndrei Emeltchenko req.scid = cpu_to_le16(chan->scid);
12249b27f350SAndrei Emeltchenko req.psm = chan->psm;
12259b27f350SAndrei Emeltchenko
12269b27f350SAndrei Emeltchenko chan->ident = l2cap_get_ident(conn);
12279b27f350SAndrei Emeltchenko
12289b27f350SAndrei Emeltchenko set_bit(CONF_CONNECT_PEND, &chan->conf_state);
12299b27f350SAndrei Emeltchenko
12309b27f350SAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
12319b27f350SAndrei Emeltchenko }
12329b27f350SAndrei Emeltchenko
l2cap_chan_ready(struct l2cap_chan * chan)12339f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan)
12349f0caeb1SVinicius Costa Gomes {
1235315917e0SJohan Hedberg /* The channel may have already been flagged as connected in
1236315917e0SJohan Hedberg * case of receiving data before the L2CAP info req/rsp
1237315917e0SJohan Hedberg * procedure is complete.
1238315917e0SJohan Hedberg */
1239315917e0SJohan Hedberg if (chan->state == BT_CONNECTED)
1240315917e0SJohan Hedberg return;
1241315917e0SJohan Hedberg
12422827011fSMat Martineau /* This clears all conf flags, including CONF_NOT_COMPLETE */
12439f0caeb1SVinicius Costa Gomes chan->conf_state = 0;
12449f0caeb1SVinicius Costa Gomes __clear_chan_timer(chan);
12459f0caeb1SVinicius Costa Gomes
124615f02b91SLuiz Augusto von Dentz switch (chan->mode) {
124715f02b91SLuiz Augusto von Dentz case L2CAP_MODE_LE_FLOWCTL:
124815f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL:
124915f02b91SLuiz Augusto von Dentz if (!chan->tx_credits)
12500ce43ce6SJohan Hedberg chan->ops->suspend(chan);
125115f02b91SLuiz Augusto von Dentz break;
125215f02b91SLuiz Augusto von Dentz }
1253177f8f2bSJohan Hedberg
125454a59aa2SAndrei Emeltchenko chan->state = BT_CONNECTED;
12559f0caeb1SVinicius Costa Gomes
125654a59aa2SAndrei Emeltchenko chan->ops->ready(chan);
12579f0caeb1SVinicius Costa Gomes }
12589f0caeb1SVinicius Costa Gomes
l2cap_le_connect(struct l2cap_chan * chan)1259f1496deeSJohan Hedberg static void l2cap_le_connect(struct l2cap_chan *chan)
1260f1496deeSJohan Hedberg {
1261f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn;
1262f1496deeSJohan Hedberg struct l2cap_le_conn_req req;
1263f1496deeSJohan Hedberg
1264595177f3SJohan Hedberg if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags))
1265595177f3SJohan Hedberg return;
1266595177f3SJohan Hedberg
12674b6e228eSLuiz Augusto von Dentz if (!chan->imtu)
12684b6e228eSLuiz Augusto von Dentz chan->imtu = chan->conn->mtu;
12694b6e228eSLuiz Augusto von Dentz
1270ba8f5289SLuiz Augusto von Dentz l2cap_le_flowctl_init(chan, 0);
1271fe149310SLuiz Augusto von Dentz
1272a5133fe8SXiaohui Zhang memset(&req, 0, sizeof(req));
1273f1496deeSJohan Hedberg req.psm = chan->psm;
1274f1496deeSJohan Hedberg req.scid = cpu_to_le16(chan->scid);
1275f1496deeSJohan Hedberg req.mtu = cpu_to_le16(chan->imtu);
12763916aed8SJohan Hedberg req.mps = cpu_to_le16(chan->mps);
12770cd75f7eSJohan Hedberg req.credits = cpu_to_le16(chan->rx_credits);
1278f1496deeSJohan Hedberg
1279f1496deeSJohan Hedberg chan->ident = l2cap_get_ident(conn);
1280f1496deeSJohan Hedberg
1281f1496deeSJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ,
1282f1496deeSJohan Hedberg sizeof(req), &req);
1283f1496deeSJohan Hedberg }
1284f1496deeSJohan Hedberg
1285da49b602SLuiz Augusto von Dentz struct l2cap_ecred_conn_data {
128615f02b91SLuiz Augusto von Dentz struct {
128715f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_req req;
1288da49b602SLuiz Augusto von Dentz __le16 scid[5];
128915f02b91SLuiz Augusto von Dentz } __packed pdu;
1290da49b602SLuiz Augusto von Dentz struct l2cap_chan *chan;
1291da49b602SLuiz Augusto von Dentz struct pid *pid;
1292da49b602SLuiz Augusto von Dentz int count;
1293da49b602SLuiz Augusto von Dentz };
1294da49b602SLuiz Augusto von Dentz
l2cap_ecred_defer_connect(struct l2cap_chan * chan,void * data)1295da49b602SLuiz Augusto von Dentz static void l2cap_ecred_defer_connect(struct l2cap_chan *chan, void *data)
1296da49b602SLuiz Augusto von Dentz {
1297da49b602SLuiz Augusto von Dentz struct l2cap_ecred_conn_data *conn = data;
1298da49b602SLuiz Augusto von Dentz struct pid *pid;
1299da49b602SLuiz Augusto von Dentz
1300da49b602SLuiz Augusto von Dentz if (chan == conn->chan)
1301da49b602SLuiz Augusto von Dentz return;
1302da49b602SLuiz Augusto von Dentz
1303da49b602SLuiz Augusto von Dentz if (!test_and_clear_bit(FLAG_DEFER_SETUP, &chan->flags))
1304da49b602SLuiz Augusto von Dentz return;
1305da49b602SLuiz Augusto von Dentz
1306da49b602SLuiz Augusto von Dentz pid = chan->ops->get_peer_pid(chan);
1307da49b602SLuiz Augusto von Dentz
1308da49b602SLuiz Augusto von Dentz /* Only add deferred channels with the same PID/PSM */
1309da49b602SLuiz Augusto von Dentz if (conn->pid != pid || chan->psm != conn->chan->psm || chan->ident ||
1310da49b602SLuiz Augusto von Dentz chan->mode != L2CAP_MODE_EXT_FLOWCTL || chan->state != BT_CONNECT)
1311da49b602SLuiz Augusto von Dentz return;
131215f02b91SLuiz Augusto von Dentz
131315f02b91SLuiz Augusto von Dentz if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
131415f02b91SLuiz Augusto von Dentz return;
131515f02b91SLuiz Augusto von Dentz
131615f02b91SLuiz Augusto von Dentz l2cap_ecred_init(chan, 0);
131715f02b91SLuiz Augusto von Dentz
1318da49b602SLuiz Augusto von Dentz /* Set the same ident so we can match on the rsp */
1319da49b602SLuiz Augusto von Dentz chan->ident = conn->chan->ident;
1320da49b602SLuiz Augusto von Dentz
1321da49b602SLuiz Augusto von Dentz /* Include all channels deferred */
1322da49b602SLuiz Augusto von Dentz conn->pdu.scid[conn->count] = cpu_to_le16(chan->scid);
1323da49b602SLuiz Augusto von Dentz
1324da49b602SLuiz Augusto von Dentz conn->count++;
1325da49b602SLuiz Augusto von Dentz }
1326da49b602SLuiz Augusto von Dentz
l2cap_ecred_connect(struct l2cap_chan * chan)1327da49b602SLuiz Augusto von Dentz static void l2cap_ecred_connect(struct l2cap_chan *chan)
1328da49b602SLuiz Augusto von Dentz {
1329da49b602SLuiz Augusto von Dentz struct l2cap_conn *conn = chan->conn;
1330da49b602SLuiz Augusto von Dentz struct l2cap_ecred_conn_data data;
1331da49b602SLuiz Augusto von Dentz
1332da49b602SLuiz Augusto von Dentz if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
1333da49b602SLuiz Augusto von Dentz return;
1334da49b602SLuiz Augusto von Dentz
1335da49b602SLuiz Augusto von Dentz if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
1336da49b602SLuiz Augusto von Dentz return;
1337da49b602SLuiz Augusto von Dentz
1338da49b602SLuiz Augusto von Dentz l2cap_ecred_init(chan, 0);
1339da49b602SLuiz Augusto von Dentz
1340d3715b23SMinghao Chi (CGEL ZTE) memset(&data, 0, sizeof(data));
1341da49b602SLuiz Augusto von Dentz data.pdu.req.psm = chan->psm;
1342da49b602SLuiz Augusto von Dentz data.pdu.req.mtu = cpu_to_le16(chan->imtu);
1343da49b602SLuiz Augusto von Dentz data.pdu.req.mps = cpu_to_le16(chan->mps);
1344da49b602SLuiz Augusto von Dentz data.pdu.req.credits = cpu_to_le16(chan->rx_credits);
1345da49b602SLuiz Augusto von Dentz data.pdu.scid[0] = cpu_to_le16(chan->scid);
134615f02b91SLuiz Augusto von Dentz
134715f02b91SLuiz Augusto von Dentz chan->ident = l2cap_get_ident(conn);
1348da49b602SLuiz Augusto von Dentz
1349da49b602SLuiz Augusto von Dentz data.count = 1;
1350da49b602SLuiz Augusto von Dentz data.chan = chan;
1351da49b602SLuiz Augusto von Dentz data.pid = chan->ops->get_peer_pid(chan);
1352da49b602SLuiz Augusto von Dentz
1353da49b602SLuiz Augusto von Dentz __l2cap_chan_list(conn, l2cap_ecred_defer_connect, &data);
135415f02b91SLuiz Augusto von Dentz
135515f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_CONN_REQ,
1356da49b602SLuiz Augusto von Dentz sizeof(data.pdu.req) + data.count * sizeof(__le16),
1357da49b602SLuiz Augusto von Dentz &data.pdu);
135815f02b91SLuiz Augusto von Dentz }
135915f02b91SLuiz Augusto von Dentz
l2cap_le_start(struct l2cap_chan * chan)1360f1496deeSJohan Hedberg static void l2cap_le_start(struct l2cap_chan *chan)
1361f1496deeSJohan Hedberg {
1362f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn;
1363f1496deeSJohan Hedberg
1364f1496deeSJohan Hedberg if (!smp_conn_security(conn->hcon, chan->sec_level))
1365f1496deeSJohan Hedberg return;
1366f1496deeSJohan Hedberg
1367f1496deeSJohan Hedberg if (!chan->psm) {
1368f1496deeSJohan Hedberg l2cap_chan_ready(chan);
1369f1496deeSJohan Hedberg return;
1370f1496deeSJohan Hedberg }
1371f1496deeSJohan Hedberg
137215f02b91SLuiz Augusto von Dentz if (chan->state == BT_CONNECT) {
137315f02b91SLuiz Augusto von Dentz if (chan->mode == L2CAP_MODE_EXT_FLOWCTL)
137415f02b91SLuiz Augusto von Dentz l2cap_ecred_connect(chan);
137515f02b91SLuiz Augusto von Dentz else
1376f1496deeSJohan Hedberg l2cap_le_connect(chan);
1377f1496deeSJohan Hedberg }
137815f02b91SLuiz Augusto von Dentz }
1379f1496deeSJohan Hedberg
l2cap_start_connection(struct l2cap_chan * chan)138093c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan)
138193c3e8f5SAndrei Emeltchenko {
1382cd5d26a9SLuiz Augusto von Dentz if (chan->conn->hcon->type == LE_LINK) {
1383f1496deeSJohan Hedberg l2cap_le_start(chan);
138493c3e8f5SAndrei Emeltchenko } else {
138593c3e8f5SAndrei Emeltchenko l2cap_send_conn_req(chan);
138693c3e8f5SAndrei Emeltchenko }
138793c3e8f5SAndrei Emeltchenko }
138893c3e8f5SAndrei Emeltchenko
l2cap_request_info(struct l2cap_conn * conn)1389aeaeb4bbSJohan Hedberg static void l2cap_request_info(struct l2cap_conn *conn)
13900a708f8fSGustavo F. Padovan {
13910a708f8fSGustavo F. Padovan struct l2cap_info_req req;
1392aeaeb4bbSJohan Hedberg
1393aeaeb4bbSJohan Hedberg if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1394aeaeb4bbSJohan Hedberg return;
1395aeaeb4bbSJohan Hedberg
1396dcf4adbfSJoe Perches req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
13970a708f8fSGustavo F. Padovan
13980a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
13990a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn);
14000a708f8fSGustavo F. Padovan
1401ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
14020a708f8fSGustavo F. Padovan
14032d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
14042d792818SGustavo Padovan sizeof(req), &req);
14050a708f8fSGustavo F. Padovan }
1406aeaeb4bbSJohan Hedberg
l2cap_check_enc_key_size(struct hci_conn * hcon)1407693cd8ceSMarcel Holtmann static bool l2cap_check_enc_key_size(struct hci_conn *hcon)
1408693cd8ceSMarcel Holtmann {
1409693cd8ceSMarcel Holtmann /* The minimum encryption key size needs to be enforced by the
1410693cd8ceSMarcel Holtmann * host stack before establishing any L2CAP connections. The
1411693cd8ceSMarcel Holtmann * specification in theory allows a minimum of 1, but to align
1412693cd8ceSMarcel Holtmann * BR/EDR and LE transports, a minimum of 7 is chosen.
1413693cd8ceSMarcel Holtmann *
1414693cd8ceSMarcel Holtmann * This check might also be called for unencrypted connections
1415693cd8ceSMarcel Holtmann * that have no key size requirements. Ensure that the link is
1416693cd8ceSMarcel Holtmann * actually encrypted before enforcing a key size.
1417693cd8ceSMarcel Holtmann */
1418288c0697SArchie Pusaka int min_key_size = hcon->hdev->min_enc_key_size;
1419288c0697SArchie Pusaka
1420288c0697SArchie Pusaka /* On FIPS security level, key size must be 16 bytes */
1421288c0697SArchie Pusaka if (hcon->sec_level == BT_SECURITY_FIPS)
1422288c0697SArchie Pusaka min_key_size = 16;
1423288c0697SArchie Pusaka
1424693cd8ceSMarcel Holtmann return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) ||
1425288c0697SArchie Pusaka hcon->enc_key_size >= min_key_size);
1426693cd8ceSMarcel Holtmann }
1427693cd8ceSMarcel Holtmann
l2cap_do_start(struct l2cap_chan * chan)1428aeaeb4bbSJohan Hedberg static void l2cap_do_start(struct l2cap_chan *chan)
1429aeaeb4bbSJohan Hedberg {
1430aeaeb4bbSJohan Hedberg struct l2cap_conn *conn = chan->conn;
1431aeaeb4bbSJohan Hedberg
1432aeaeb4bbSJohan Hedberg if (conn->hcon->type == LE_LINK) {
1433aeaeb4bbSJohan Hedberg l2cap_le_start(chan);
1434aeaeb4bbSJohan Hedberg return;
1435aeaeb4bbSJohan Hedberg }
1436aeaeb4bbSJohan Hedberg
1437aeaeb4bbSJohan Hedberg if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)) {
1438aeaeb4bbSJohan Hedberg l2cap_request_info(conn);
1439aeaeb4bbSJohan Hedberg return;
1440aeaeb4bbSJohan Hedberg }
1441aeaeb4bbSJohan Hedberg
1442aeaeb4bbSJohan Hedberg if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
1443aeaeb4bbSJohan Hedberg return;
1444aeaeb4bbSJohan Hedberg
1445693cd8ceSMarcel Holtmann if (!l2cap_chan_check_security(chan, true) ||
1446693cd8ceSMarcel Holtmann !__l2cap_no_conn_pending(chan))
1447693cd8ceSMarcel Holtmann return;
1448693cd8ceSMarcel Holtmann
1449693cd8ceSMarcel Holtmann if (l2cap_check_enc_key_size(conn->hcon))
1450aeaeb4bbSJohan Hedberg l2cap_start_connection(chan);
1451693cd8ceSMarcel Holtmann else
1452693cd8ceSMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
14530a708f8fSGustavo F. Padovan }
14540a708f8fSGustavo F. Padovan
l2cap_mode_supported(__u8 mode,__u32 feat_mask)14550a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
14560a708f8fSGustavo F. Padovan {
14570a708f8fSGustavo F. Padovan u32 local_feat_mask = l2cap_feat_mask;
14580a708f8fSGustavo F. Padovan if (!disable_ertm)
14590a708f8fSGustavo F. Padovan local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
14600a708f8fSGustavo F. Padovan
14610a708f8fSGustavo F. Padovan switch (mode) {
14620a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM:
14630a708f8fSGustavo F. Padovan return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
14640a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING:
14650a708f8fSGustavo F. Padovan return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
14660a708f8fSGustavo F. Padovan default:
14670a708f8fSGustavo F. Padovan return 0x00;
14680a708f8fSGustavo F. Padovan }
14690a708f8fSGustavo F. Padovan }
14700a708f8fSGustavo F. Padovan
l2cap_send_disconn_req(struct l2cap_chan * chan,int err)14715e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
14720a708f8fSGustavo F. Padovan {
14735e4e3972SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn;
14740a708f8fSGustavo F. Padovan struct l2cap_disconn_req req;
14750a708f8fSGustavo F. Padovan
14760a708f8fSGustavo F. Padovan if (!conn)
14770a708f8fSGustavo F. Padovan return;
14780a708f8fSGustavo F. Padovan
1479aad3d0e3SAndrei Emeltchenko if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) {
14801a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan);
14811a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan);
14821a09bcb9SGustavo F. Padovan __clear_ack_timer(chan);
14830a708f8fSGustavo F. Padovan }
14840a708f8fSGustavo F. Padovan
1485fe4128e0SGustavo F. Padovan req.dcid = cpu_to_le16(chan->dcid);
1486fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid);
14872d792818SGustavo Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ,
14882d792818SGustavo Padovan sizeof(req), &req);
14890a708f8fSGustavo F. Padovan
1490f8e73017SGustavo Padovan l2cap_state_change_and_error(chan, BT_DISCONN, err);
14910a708f8fSGustavo F. Padovan }
14920a708f8fSGustavo F. Padovan
14930a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
l2cap_conn_start(struct l2cap_conn * conn)14940a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
14950a708f8fSGustavo F. Padovan {
14963df91ea2SAndrei Emeltchenko struct l2cap_chan *chan, *tmp;
14970a708f8fSGustavo F. Padovan
14980a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn);
14990a708f8fSGustavo F. Padovan
15003df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock);
15010a708f8fSGustavo F. Padovan
15023df91ea2SAndrei Emeltchenko list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
15036be36555SAndrei Emeltchenko l2cap_chan_lock(chan);
15040a708f8fSGustavo F. Padovan
1505715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1506aeaeb4bbSJohan Hedberg l2cap_chan_ready(chan);
15076be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
15080a708f8fSGustavo F. Padovan continue;
15090a708f8fSGustavo F. Padovan }
15100a708f8fSGustavo F. Padovan
151189bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) {
1512e7cafc45SJohan Hedberg if (!l2cap_chan_check_security(chan, true) ||
1513b4450035SGustavo F. Padovan !__l2cap_no_conn_pending(chan)) {
15146be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
15150a708f8fSGustavo F. Padovan continue;
15160a708f8fSGustavo F. Padovan }
15170a708f8fSGustavo F. Padovan
1518c1360a1cSGustavo F. Padovan if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1519c1360a1cSGustavo F. Padovan && test_bit(CONF_STATE2_DEVICE,
1520c1360a1cSGustavo F. Padovan &chan->conf_state)) {
15210f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET);
15226be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
15230a708f8fSGustavo F. Padovan continue;
15240a708f8fSGustavo F. Padovan }
15250a708f8fSGustavo F. Padovan
1526693cd8ceSMarcel Holtmann if (l2cap_check_enc_key_size(conn->hcon))
152793c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan);
1528693cd8ceSMarcel Holtmann else
1529693cd8ceSMarcel Holtmann l2cap_chan_close(chan, ECONNREFUSED);
15300a708f8fSGustavo F. Padovan
153189bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) {
15320a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp;
15330a708f8fSGustavo F. Padovan char buf[128];
1534fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid);
1535fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid);
15360a708f8fSGustavo F. Padovan
1537e7cafc45SJohan Hedberg if (l2cap_chan_check_security(chan, false)) {
1538bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
1539dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1540dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
15412dc4e510SGustavo Padovan chan->ops->defer(chan);
15420a708f8fSGustavo F. Padovan
15430a708f8fSGustavo F. Padovan } else {
1544acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG);
1545dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1546dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
15470a708f8fSGustavo F. Padovan }
15480a708f8fSGustavo F. Padovan } else {
1549dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1550dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
15510a708f8fSGustavo F. Padovan }
15520a708f8fSGustavo F. Padovan
1553fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1554fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp);
15550a708f8fSGustavo F. Padovan
1556c1360a1cSGustavo F. Padovan if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
15570a708f8fSGustavo F. Padovan rsp.result != L2CAP_CR_SUCCESS) {
15586be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
15590a708f8fSGustavo F. Padovan continue;
15600a708f8fSGustavo F. Padovan }
15610a708f8fSGustavo F. Padovan
1562c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state);
15630a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1564e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
156573ffa904SGustavo F. Padovan chan->num_conf_req++;
15660a708f8fSGustavo F. Padovan }
15670a708f8fSGustavo F. Padovan
15686be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
15690a708f8fSGustavo F. Padovan }
15700a708f8fSGustavo F. Padovan
15713df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock);
15720a708f8fSGustavo F. Padovan }
15730a708f8fSGustavo F. Padovan
l2cap_le_conn_ready(struct l2cap_conn * conn)1574b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1575b62f328bSVille Tervo {
1576cc8dba2bSMarcel Holtmann struct hci_conn *hcon = conn->hcon;
1577dcc36c16SJohan Hedberg struct hci_dev *hdev = hcon->hdev;
1578b62f328bSVille Tervo
1579e760ec12SJohan Hedberg BT_DBG("%s conn %p", hdev->name, conn);
1580b62f328bSVille Tervo
1581e760ec12SJohan Hedberg /* For outgoing pairing which doesn't necessarily have an
1582e760ec12SJohan Hedberg * associated socket (e.g. mgmt_pair_device).
1583e760ec12SJohan Hedberg */
1584e760ec12SJohan Hedberg if (hcon->out)
1585e760ec12SJohan Hedberg smp_conn_security(hcon, hcon->pending_sec_level);
1586cc8dba2bSMarcel Holtmann
158774be523cSArchie Pusaka /* For LE peripheral connections, make sure the connection interval
15885153ceb9SBhaskar Chowdhury * is in the range of the minimum and maximum interval that has
158980afeb6cSMarcel Holtmann * been configured for this connection. If not, then trigger
159080afeb6cSMarcel Holtmann * the connection update procedure.
159180afeb6cSMarcel Holtmann */
159240bef302SJohan Hedberg if (hcon->role == HCI_ROLE_SLAVE &&
159380afeb6cSMarcel Holtmann (hcon->le_conn_interval < hcon->le_conn_min_interval ||
159480afeb6cSMarcel Holtmann hcon->le_conn_interval > hcon->le_conn_max_interval)) {
159580afeb6cSMarcel Holtmann struct l2cap_conn_param_update_req req;
159680afeb6cSMarcel Holtmann
159780afeb6cSMarcel Holtmann req.min = cpu_to_le16(hcon->le_conn_min_interval);
159880afeb6cSMarcel Holtmann req.max = cpu_to_le16(hcon->le_conn_max_interval);
159980afeb6cSMarcel Holtmann req.latency = cpu_to_le16(hcon->le_conn_latency);
160080afeb6cSMarcel Holtmann req.to_multiplier = cpu_to_le16(hcon->le_supv_timeout);
160180afeb6cSMarcel Holtmann
160280afeb6cSMarcel Holtmann l2cap_send_cmd(conn, l2cap_get_ident(conn),
160380afeb6cSMarcel Holtmann L2CAP_CONN_PARAM_UPDATE_REQ, sizeof(req), &req);
160480afeb6cSMarcel Holtmann }
1605b62f328bSVille Tervo }
1606b62f328bSVille Tervo
l2cap_conn_ready(struct l2cap_conn * conn)16070a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
16080a708f8fSGustavo F. Padovan {
160948454079SGustavo F. Padovan struct l2cap_chan *chan;
1610cc110922SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon;
16110a708f8fSGustavo F. Padovan
16120a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn);
16130a708f8fSGustavo F. Padovan
1614aeaeb4bbSJohan Hedberg if (hcon->type == ACL_LINK)
1615aeaeb4bbSJohan Hedberg l2cap_request_info(conn);
1616aeaeb4bbSJohan Hedberg
1617e760ec12SJohan Hedberg mutex_lock(&conn->chan_lock);
1618e760ec12SJohan Hedberg
16193df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) {
1620baa7e1faSGustavo F. Padovan
16216be36555SAndrei Emeltchenko l2cap_chan_lock(chan);
16220a708f8fSGustavo F. Padovan
1623cc110922SVinicius Costa Gomes if (hcon->type == LE_LINK) {
1624f1496deeSJohan Hedberg l2cap_le_start(chan);
162563128451SVinicius Costa Gomes } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1626aeaeb4bbSJohan Hedberg if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
162774e75740SGustavo Padovan l2cap_chan_ready(chan);
16281c244f79SGustavo Padovan } else if (chan->state == BT_CONNECT) {
1629fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan);
16301c244f79SGustavo Padovan }
16310a708f8fSGustavo F. Padovan
16326be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
16330a708f8fSGustavo F. Padovan }
16340a708f8fSGustavo F. Padovan
16353df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock);
163661a939c6SJohan Hedberg
163779a05727SJohan Hedberg if (hcon->type == LE_LINK)
163879a05727SJohan Hedberg l2cap_le_conn_ready(conn);
163979a05727SJohan Hedberg
164061a939c6SJohan Hedberg queue_work(hcon->hdev->workqueue, &conn->pending_rx_work);
16410a708f8fSGustavo F. Padovan }
16420a708f8fSGustavo F. Padovan
16430a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
l2cap_conn_unreliable(struct l2cap_conn * conn,int err)16440a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
16450a708f8fSGustavo F. Padovan {
164648454079SGustavo F. Padovan struct l2cap_chan *chan;
16470a708f8fSGustavo F. Padovan
16480a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn);
16490a708f8fSGustavo F. Padovan
16503df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock);
16510a708f8fSGustavo F. Padovan
16523df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) {
1653ecf61bdbSAndrei Emeltchenko if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
16541d8b1fd5SGustavo Padovan l2cap_chan_set_err(chan, err);
16550a708f8fSGustavo F. Padovan }
16560a708f8fSGustavo F. Padovan
16573df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock);
16580a708f8fSGustavo F. Padovan }
16590a708f8fSGustavo F. Padovan
l2cap_info_timeout(struct work_struct * work)1660f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
16610a708f8fSGustavo F. Padovan {
1662f878fcadSGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1663030013d8SGustavo F. Padovan info_timer.work);
16640a708f8fSGustavo F. Padovan
16650a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
16660a708f8fSGustavo F. Padovan conn->info_ident = 0;
16670a708f8fSGustavo F. Padovan
16680a708f8fSGustavo F. Padovan l2cap_conn_start(conn);
16690a708f8fSGustavo F. Padovan }
16700a708f8fSGustavo F. Padovan
16712c8e1411SDavid Herrmann /*
16722c8e1411SDavid Herrmann * l2cap_user
16732c8e1411SDavid Herrmann * External modules can register l2cap_user objects on l2cap_conn. The ->probe
16742c8e1411SDavid Herrmann * callback is called during registration. The ->remove callback is called
16752c8e1411SDavid Herrmann * during unregistration.
16762c8e1411SDavid Herrmann * An l2cap_user object can either be explicitly unregistered or when the
16772c8e1411SDavid Herrmann * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon,
16782c8e1411SDavid Herrmann * l2cap->hchan, .. are valid as long as the remove callback hasn't been called.
16792c8e1411SDavid Herrmann * External modules must own a reference to the l2cap_conn object if they intend
16802c8e1411SDavid Herrmann * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at
16812c8e1411SDavid Herrmann * any time if they don't.
16822c8e1411SDavid Herrmann */
16832c8e1411SDavid Herrmann
l2cap_register_user(struct l2cap_conn * conn,struct l2cap_user * user)16842c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user)
16852c8e1411SDavid Herrmann {
16862c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev;
16872c8e1411SDavid Herrmann int ret;
16882c8e1411SDavid Herrmann
16892c8e1411SDavid Herrmann /* We need to check whether l2cap_conn is registered. If it is not, we
16902c8e1411SDavid Herrmann * must not register the l2cap_user. l2cap_conn_del() is unregisters
16912c8e1411SDavid Herrmann * l2cap_conn objects, but doesn't provide its own locking. Instead, it
16922c8e1411SDavid Herrmann * relies on the parent hci_conn object to be locked. This itself relies
16932c8e1411SDavid Herrmann * on the hci_dev object to be locked. So we must lock the hci device
16942c8e1411SDavid Herrmann * here, too. */
16952c8e1411SDavid Herrmann
16962c8e1411SDavid Herrmann hci_dev_lock(hdev);
16972c8e1411SDavid Herrmann
1698835a6a2fSAlexey Dobriyan if (!list_empty(&user->list)) {
16992c8e1411SDavid Herrmann ret = -EINVAL;
17002c8e1411SDavid Herrmann goto out_unlock;
17012c8e1411SDavid Herrmann }
17022c8e1411SDavid Herrmann
17032c8e1411SDavid Herrmann /* conn->hchan is NULL after l2cap_conn_del() was called */
17042c8e1411SDavid Herrmann if (!conn->hchan) {
17052c8e1411SDavid Herrmann ret = -ENODEV;
17062c8e1411SDavid Herrmann goto out_unlock;
17072c8e1411SDavid Herrmann }
17082c8e1411SDavid Herrmann
17092c8e1411SDavid Herrmann ret = user->probe(conn, user);
17102c8e1411SDavid Herrmann if (ret)
17112c8e1411SDavid Herrmann goto out_unlock;
17122c8e1411SDavid Herrmann
17132c8e1411SDavid Herrmann list_add(&user->list, &conn->users);
17142c8e1411SDavid Herrmann ret = 0;
17152c8e1411SDavid Herrmann
17162c8e1411SDavid Herrmann out_unlock:
17172c8e1411SDavid Herrmann hci_dev_unlock(hdev);
17182c8e1411SDavid Herrmann return ret;
17192c8e1411SDavid Herrmann }
17202c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user);
17212c8e1411SDavid Herrmann
l2cap_unregister_user(struct l2cap_conn * conn,struct l2cap_user * user)17222c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user)
17232c8e1411SDavid Herrmann {
17242c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev;
17252c8e1411SDavid Herrmann
17262c8e1411SDavid Herrmann hci_dev_lock(hdev);
17272c8e1411SDavid Herrmann
1728835a6a2fSAlexey Dobriyan if (list_empty(&user->list))
17292c8e1411SDavid Herrmann goto out_unlock;
17302c8e1411SDavid Herrmann
1731ab944c83STedd Ho-Jeong An list_del_init(&user->list);
17322c8e1411SDavid Herrmann user->remove(conn, user);
17332c8e1411SDavid Herrmann
17342c8e1411SDavid Herrmann out_unlock:
17352c8e1411SDavid Herrmann hci_dev_unlock(hdev);
17362c8e1411SDavid Herrmann }
17372c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user);
17382c8e1411SDavid Herrmann
l2cap_unregister_all_users(struct l2cap_conn * conn)17392c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn)
17402c8e1411SDavid Herrmann {
17412c8e1411SDavid Herrmann struct l2cap_user *user;
17422c8e1411SDavid Herrmann
17432c8e1411SDavid Herrmann while (!list_empty(&conn->users)) {
17442c8e1411SDavid Herrmann user = list_first_entry(&conn->users, struct l2cap_user, list);
1745ab944c83STedd Ho-Jeong An list_del_init(&user->list);
17462c8e1411SDavid Herrmann user->remove(conn, user);
17472c8e1411SDavid Herrmann }
17482c8e1411SDavid Herrmann }
17492c8e1411SDavid Herrmann
l2cap_conn_del(struct hci_conn * hcon,int err)17505d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
17515d3de7dfSVinicius Costa Gomes {
17525d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data;
17535d3de7dfSVinicius Costa Gomes struct l2cap_chan *chan, *l;
17545d3de7dfSVinicius Costa Gomes
17555d3de7dfSVinicius Costa Gomes if (!conn)
17565d3de7dfSVinicius Costa Gomes return;
17575d3de7dfSVinicius Costa Gomes
17585d3de7dfSVinicius Costa Gomes BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
17595d3de7dfSVinicius Costa Gomes
17605d3de7dfSVinicius Costa Gomes kfree_skb(conn->rx_skb);
17615d3de7dfSVinicius Costa Gomes
176261a939c6SJohan Hedberg skb_queue_purge(&conn->pending_rx);
17637ab56c3aSJukka Taimisto
17647ab56c3aSJukka Taimisto /* We can not call flush_work(&conn->pending_rx_work) here since we
17657ab56c3aSJukka Taimisto * might block if we are running on a worker from the same workqueue
17667ab56c3aSJukka Taimisto * pending_rx_work is waiting on.
17677ab56c3aSJukka Taimisto */
17687ab56c3aSJukka Taimisto if (work_pending(&conn->pending_rx_work))
17697ab56c3aSJukka Taimisto cancel_work_sync(&conn->pending_rx_work);
177061a939c6SJohan Hedberg
1771b8b23001SLuiz Augusto von Dentz cancel_delayed_work_sync(&conn->id_addr_timer);
1772f3d82d0cSJohan Hedberg
17732c8e1411SDavid Herrmann l2cap_unregister_all_users(conn);
17742c8e1411SDavid Herrmann
1775e31fb860SJohan Hedberg /* Force the connection to be immediately dropped */
1776e31fb860SJohan Hedberg hcon->disc_timeout = 0;
1777e31fb860SJohan Hedberg
17783df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock);
17793df91ea2SAndrei Emeltchenko
17805d3de7dfSVinicius Costa Gomes /* Kill channels */
17815d3de7dfSVinicius Costa Gomes list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
178261d6ef3eSMat Martineau l2cap_chan_hold(chan);
17836be36555SAndrei Emeltchenko l2cap_chan_lock(chan);
17846be36555SAndrei Emeltchenko
17855d3de7dfSVinicius Costa Gomes l2cap_chan_del(chan, err);
17866be36555SAndrei Emeltchenko
178780b98027SGustavo Padovan chan->ops->close(chan);
17886c08fc89SManish Mandlik
17896c08fc89SManish Mandlik l2cap_chan_unlock(chan);
179061d6ef3eSMat Martineau l2cap_chan_put(chan);
17915d3de7dfSVinicius Costa Gomes }
17925d3de7dfSVinicius Costa Gomes
17933df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock);
17943df91ea2SAndrei Emeltchenko
179573d80debSLuiz Augusto von Dentz hci_chan_del(conn->hchan);
179673d80debSLuiz Augusto von Dentz
17975d3de7dfSVinicius Costa Gomes if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1798127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->info_timer);
17995d3de7dfSVinicius Costa Gomes
18005d3de7dfSVinicius Costa Gomes hcon->l2cap_data = NULL;
18019c903e37SDavid Herrmann conn->hchan = NULL;
18029c903e37SDavid Herrmann l2cap_conn_put(conn);
18035d3de7dfSVinicius Costa Gomes }
18045d3de7dfSVinicius Costa Gomes
l2cap_conn_free(struct kref * ref)18059c903e37SDavid Herrmann static void 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
l2cap_conn_get(struct l2cap_conn * conn)181351bb8457SJohan Hedberg struct l2cap_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
l2cap_conn_put(struct l2cap_conn * conn)18209c903e37SDavid Herrmann void 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 */
l2cap_global_chan_by_psm(int state,__le16 psm,bdaddr_t * src,bdaddr_t * dst,u8 link_type)1831c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
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
l2cap_monitor_timeout(struct work_struct * work)1882721c4181SGustavo F. Padovan static void 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
l2cap_retrans_timeout(struct work_struct * work)1903721c4181SGustavo F. Padovan static void 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
l2cap_streaming_send(struct l2cap_chan * chan,struct sk_buff_head * skbs)1923d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan,
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
l2cap_ertm_send(struct l2cap_chan * chan)195967c9e840SSzymon Janc static int 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
l2cap_ertm_resend(struct l2cap_chan * chan)2026e1fbd4c1SMat Martineau static void 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
l2cap_retransmit(struct l2cap_chan * chan,struct l2cap_ctrl * control)2104f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan,
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
l2cap_retransmit_all(struct l2cap_chan * chan,struct l2cap_ctrl * control)2113d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan,
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
l2cap_send_ack(struct l2cap_chan * chan)2147b17e73bbSSzymon Janc static void 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
l2cap_skbuff_fromiovec(struct l2cap_chan * chan,struct msghdr * msg,int len,int count,struct sk_buff * skb)219704124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
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
l2cap_create_connless_pdu(struct l2cap_chan * chan,struct msghdr * msg,size_t len)22415e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
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
l2cap_create_basic_pdu(struct l2cap_chan * chan,struct msghdr * msg,size_t len)22735e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
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
l2cap_create_iframe_pdu(struct l2cap_chan * chan,struct msghdr * msg,size_t len,u16 sdulen)2303ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
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
l2cap_segment_sdu(struct l2cap_chan * chan,struct sk_buff_head * seg_queue,struct msghdr * msg,size_t len)235794122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan,
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
l2cap_create_le_flowctl_pdu(struct l2cap_chan * chan,struct msghdr * msg,size_t len,u16 sdulen)2423177f8f2bSJohan Hedberg static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan,
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
l2cap_segment_le_sdu(struct l2cap_chan * chan,struct sk_buff_head * seg_queue,struct msghdr * msg,size_t len)2466177f8f2bSJohan Hedberg static int l2cap_segment_le_sdu(struct l2cap_chan *chan,
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
l2cap_le_flowctl_send(struct l2cap_chan * chan)25028a505b7fSLuiz Augusto von Dentz static void 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
l2cap_chan_send(struct l2cap_chan * chan,struct msghdr * msg,size_t len)25188d46321cSMarcel Holtmann int 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
l2cap_send_srej(struct l2cap_chan * chan,u16 txseq)2622d2a7ac5dSMat Martineau static void 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
l2cap_send_srej_tail(struct l2cap_chan * chan)2645d2a7ac5dSMat Martineau static void 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
l2cap_send_srej_list(struct l2cap_chan * chan,u16 txseq)2661d2a7ac5dSMat Martineau static void 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
l2cap_process_reqseq(struct l2cap_chan * chan,u16 reqseq)2687608bcc6dSMat Martineau static void 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
l2cap_abort_rx_srej_sent(struct l2cap_chan * chan)2719608bcc6dSMat Martineau static void 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
l2cap_tx_state_xmit(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff_head * skbs,u8 event)2729d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan,
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
l2cap_tx_state_wait_f(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff_head * skbs,u8 event)2801d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan,
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
l2cap_tx(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff_head * skbs,u8 event)2878d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
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
l2cap_pass_to_tx(struct l2cap_chan * chan,struct l2cap_ctrl * control)28974b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan,
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
l2cap_pass_to_tx_fbit(struct l2cap_chan * chan,struct l2cap_ctrl * control)2904f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan,
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 */
l2cap_raw_recv(struct l2cap_conn * conn,struct sk_buff * skb)29120a708f8fSGustavo F. Padovan static void 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 mutex_lock(&conn->chan_lock);
29203d57dc68SGustavo F. Padovan
29213df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) {
2922715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW)
29230a708f8fSGustavo F. Padovan continue;
29240a708f8fSGustavo F. Padovan
29257f5396a7SGustavo Padovan /* Don't send frame to the channel it came from */
2926a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.chan == chan)
29270a708f8fSGustavo F. Padovan continue;
29287f5396a7SGustavo Padovan
29298bcde1f2SGustavo Padovan nskb = skb_clone(skb, GFP_KERNEL);
29300a708f8fSGustavo F. Padovan if (!nskb)
29310a708f8fSGustavo F. Padovan continue;
293280b98027SGustavo Padovan if (chan->ops->recv(chan, nskb))
29330a708f8fSGustavo F. Padovan kfree_skb(nskb);
29340a708f8fSGustavo F. Padovan }
29353d57dc68SGustavo F. Padovan
29363df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock);
29370a708f8fSGustavo F. Padovan }
29380a708f8fSGustavo F. Padovan
29390a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
l2cap_build_cmd(struct l2cap_conn * conn,u8 code,u8 ident,u16 dlen,void * data)2940b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
2941b4400672SAndrei Emeltchenko u8 ident, u16 dlen, void *data)
29420a708f8fSGustavo F. Padovan {
29430a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag;
29440a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd;
29450a708f8fSGustavo F. Padovan struct l2cap_hdr *lh;
29460a708f8fSGustavo F. Padovan int len, count;
29470a708f8fSGustavo F. Padovan
2948b4400672SAndrei Emeltchenko BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u",
29490a708f8fSGustavo F. Padovan conn, code, ident, dlen);
29500a708f8fSGustavo F. Padovan
2951300b962eSAnderson Lizardo if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE)
2952300b962eSAnderson Lizardo return NULL;
2953300b962eSAnderson Lizardo
29540a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
29550a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len);
29560a708f8fSGustavo F. Padovan
29578bcde1f2SGustavo Padovan skb = bt_skb_alloc(count, GFP_KERNEL);
29580a708f8fSGustavo F. Padovan if (!skb)
29590a708f8fSGustavo F. Padovan return NULL;
29600a708f8fSGustavo F. Padovan
29614df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE);
29620a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
29633300d9a9SClaudio Takahasi
29643300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK)
2965dcf4adbfSJoe Perches lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
29663300d9a9SClaudio Takahasi else
2967dcf4adbfSJoe Perches lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
29680a708f8fSGustavo F. Padovan
29694df864c1SJohannes Berg cmd = skb_put(skb, L2CAP_CMD_HDR_SIZE);
29700a708f8fSGustavo F. Padovan cmd->code = code;
29710a708f8fSGustavo F. Padovan cmd->ident = ident;
29720a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen);
29730a708f8fSGustavo F. Padovan
29740a708f8fSGustavo F. Padovan if (dlen) {
29750a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
297659ae1d12SJohannes Berg skb_put_data(skb, data, count);
29770a708f8fSGustavo F. Padovan data += count;
29780a708f8fSGustavo F. Padovan }
29790a708f8fSGustavo F. Padovan
29800a708f8fSGustavo F. Padovan len -= skb->len;
29810a708f8fSGustavo F. Padovan
29820a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */
29830a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list;
29840a708f8fSGustavo F. Padovan while (len) {
29850a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len);
29860a708f8fSGustavo F. Padovan
29878bcde1f2SGustavo Padovan *frag = bt_skb_alloc(count, GFP_KERNEL);
29880a708f8fSGustavo F. Padovan if (!*frag)
29890a708f8fSGustavo F. Padovan goto fail;
29900a708f8fSGustavo F. Padovan
299159ae1d12SJohannes Berg skb_put_data(*frag, data, count);
29920a708f8fSGustavo F. Padovan
29930a708f8fSGustavo F. Padovan len -= count;
29940a708f8fSGustavo F. Padovan data += count;
29950a708f8fSGustavo F. Padovan
29960a708f8fSGustavo F. Padovan frag = &(*frag)->next;
29970a708f8fSGustavo F. Padovan }
29980a708f8fSGustavo F. Padovan
29990a708f8fSGustavo F. Padovan return skb;
30000a708f8fSGustavo F. Padovan
30010a708f8fSGustavo F. Padovan fail:
30020a708f8fSGustavo F. Padovan kfree_skb(skb);
30030a708f8fSGustavo F. Padovan return NULL;
30040a708f8fSGustavo F. Padovan }
30050a708f8fSGustavo F. Padovan
l2cap_get_conf_opt(void ** ptr,int * type,int * olen,unsigned long * val)30062d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen,
30072d792818SGustavo Padovan unsigned long *val)
30080a708f8fSGustavo F. Padovan {
30090a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr;
30100a708f8fSGustavo F. Padovan int len;
30110a708f8fSGustavo F. Padovan
30120a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len;
30130a708f8fSGustavo F. Padovan *ptr += len;
30140a708f8fSGustavo F. Padovan
30150a708f8fSGustavo F. Padovan *type = opt->type;
30160a708f8fSGustavo F. Padovan *olen = opt->len;
30170a708f8fSGustavo F. Padovan
30180a708f8fSGustavo F. Padovan switch (opt->len) {
30190a708f8fSGustavo F. Padovan case 1:
30200a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val);
30210a708f8fSGustavo F. Padovan break;
30220a708f8fSGustavo F. Padovan
30230a708f8fSGustavo F. Padovan case 2:
30240a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val);
30250a708f8fSGustavo F. Padovan break;
30260a708f8fSGustavo F. Padovan
30270a708f8fSGustavo F. Padovan case 4:
30280a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val);
30290a708f8fSGustavo F. Padovan break;
30300a708f8fSGustavo F. Padovan
30310a708f8fSGustavo F. Padovan default:
30320a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val;
30330a708f8fSGustavo F. Padovan break;
30340a708f8fSGustavo F. Padovan }
30350a708f8fSGustavo F. Padovan
3036b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val);
30370a708f8fSGustavo F. Padovan return len;
30380a708f8fSGustavo F. Padovan }
30390a708f8fSGustavo F. Padovan
l2cap_add_conf_opt(void ** ptr,u8 type,u8 len,unsigned long val,size_t size)3040e860d2c9SBen Seri static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size)
30410a708f8fSGustavo F. Padovan {
30420a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr;
30430a708f8fSGustavo F. Padovan
3044b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val);
30450a708f8fSGustavo F. Padovan
3046e860d2c9SBen Seri if (size < L2CAP_CONF_OPT_SIZE + len)
3047e860d2c9SBen Seri return;
3048e860d2c9SBen Seri
30490a708f8fSGustavo F. Padovan opt->type = type;
30500a708f8fSGustavo F. Padovan opt->len = len;
30510a708f8fSGustavo F. Padovan
30520a708f8fSGustavo F. Padovan switch (len) {
30530a708f8fSGustavo F. Padovan case 1:
30540a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val;
30550a708f8fSGustavo F. Padovan break;
30560a708f8fSGustavo F. Padovan
30570a708f8fSGustavo F. Padovan case 2:
30580a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val);
30590a708f8fSGustavo F. Padovan break;
30600a708f8fSGustavo F. Padovan
30610a708f8fSGustavo F. Padovan case 4:
30620a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val);
30630a708f8fSGustavo F. Padovan break;
30640a708f8fSGustavo F. Padovan
30650a708f8fSGustavo F. Padovan default:
30660a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len);
30670a708f8fSGustavo F. Padovan break;
30680a708f8fSGustavo F. Padovan }
30690a708f8fSGustavo F. Padovan
30700a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len;
30710a708f8fSGustavo F. Padovan }
30720a708f8fSGustavo F. Padovan
l2cap_add_opt_efs(void ** ptr,struct l2cap_chan * chan,size_t size)3073e860d2c9SBen Seri static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan, size_t size)
3074f89cef09SAndrei Emeltchenko {
3075f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs;
3076f89cef09SAndrei Emeltchenko
3077f89cef09SAndrei Emeltchenko switch (chan->mode) {
3078f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM:
3079f89cef09SAndrei Emeltchenko efs.id = chan->local_id;
3080f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype;
3081f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu);
3082f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
3083dcf4adbfSJoe Perches efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
3084dcf4adbfSJoe Perches efs.flush_to = cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO);
3085f89cef09SAndrei Emeltchenko break;
3086f89cef09SAndrei Emeltchenko
3087f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING:
3088f89cef09SAndrei Emeltchenko efs.id = 1;
3089f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT;
3090f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu);
3091f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
3092f89cef09SAndrei Emeltchenko efs.acc_lat = 0;
3093f89cef09SAndrei Emeltchenko efs.flush_to = 0;
3094f89cef09SAndrei Emeltchenko break;
3095f89cef09SAndrei Emeltchenko
3096f89cef09SAndrei Emeltchenko default:
3097f89cef09SAndrei Emeltchenko return;
3098f89cef09SAndrei Emeltchenko }
3099f89cef09SAndrei Emeltchenko
3100f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
3101e860d2c9SBen Seri (unsigned long) &efs, size);
3102f89cef09SAndrei Emeltchenko }
3103f89cef09SAndrei Emeltchenko
l2cap_ack_timeout(struct work_struct * work)3104721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
31050a708f8fSGustavo F. Padovan {
3106721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
3107721c4181SGustavo F. Padovan ack_timer.work);
31080362520bSMat Martineau u16 frames_to_ack;
31090a708f8fSGustavo F. Padovan
31102fb9b3d4SGustavo F. Padovan BT_DBG("chan %p", chan);
31112fb9b3d4SGustavo F. Padovan
31126be36555SAndrei Emeltchenko l2cap_chan_lock(chan);
31136be36555SAndrei Emeltchenko
31140362520bSMat Martineau frames_to_ack = __seq_offset(chan, chan->buffer_seq,
31150362520bSMat Martineau chan->last_acked_seq);
31160362520bSMat Martineau
31170362520bSMat Martineau if (frames_to_ack)
31180362520bSMat Martineau l2cap_send_rr_or_rnr(chan, 0);
31196be36555SAndrei Emeltchenko
31206be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
312109bfb2eeSSzymon Janc l2cap_chan_put(chan);
31220a708f8fSGustavo F. Padovan }
31230a708f8fSGustavo F. Padovan
l2cap_ertm_init(struct l2cap_chan * chan)3124466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan)
31250a708f8fSGustavo F. Padovan {
31263c588192SMat Martineau int err;
31273c588192SMat Martineau
3128105bdf9eSMat Martineau chan->next_tx_seq = 0;
3129105bdf9eSMat Martineau chan->expected_tx_seq = 0;
313042e5c802SGustavo F. Padovan chan->expected_ack_seq = 0;
31316a026610SGustavo F. Padovan chan->unacked_frames = 0;
313242e5c802SGustavo F. Padovan chan->buffer_seq = 0;
31336a026610SGustavo F. Padovan chan->frames_sent = 0;
3134105bdf9eSMat Martineau chan->last_acked_seq = 0;
3135105bdf9eSMat Martineau chan->sdu = NULL;
3136105bdf9eSMat Martineau chan->sdu_last_frag = NULL;
3137105bdf9eSMat Martineau chan->sdu_len = 0;
3138105bdf9eSMat Martineau
3139d34c34fbSMat Martineau skb_queue_head_init(&chan->tx_q);
3140d34c34fbSMat Martineau
3141105bdf9eSMat Martineau if (chan->mode != L2CAP_MODE_ERTM)
3142105bdf9eSMat Martineau return 0;
3143105bdf9eSMat Martineau
3144105bdf9eSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV;
3145105bdf9eSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT;
31460a708f8fSGustavo F. Padovan
3147f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q);
31480a708f8fSGustavo F. Padovan
31493c588192SMat Martineau err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
31503c588192SMat Martineau if (err < 0)
31513c588192SMat Martineau return err;
31523c588192SMat Martineau
31539dc9affcSMat Martineau err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
31549dc9affcSMat Martineau if (err < 0)
31559dc9affcSMat Martineau l2cap_seq_list_free(&chan->srej_list);
31569dc9affcSMat Martineau
31579dc9affcSMat Martineau return err;
31580a708f8fSGustavo F. Padovan }
31590a708f8fSGustavo F. Padovan
l2cap_select_mode(__u8 mode,__u16 remote_feat_mask)31600a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
31610a708f8fSGustavo F. Padovan {
31620a708f8fSGustavo F. Padovan switch (mode) {
31630a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING:
31640a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM:
31650a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask))
31660a708f8fSGustavo F. Padovan return mode;
316719186c7bSGustavo A. R. Silva fallthrough;
31680a708f8fSGustavo F. Padovan default:
31690a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC;
31700a708f8fSGustavo F. Padovan }
31710a708f8fSGustavo F. Padovan }
31720a708f8fSGustavo F. Padovan
__l2cap_ews_supported(struct l2cap_conn * conn)3173848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn)
31746327eb98SAndrei Emeltchenko {
3175cd5d26a9SLuiz Augusto von Dentz return (conn->feat_mask & L2CAP_FEAT_EXT_WINDOW);
31766327eb98SAndrei Emeltchenko }
31776327eb98SAndrei Emeltchenko
__l2cap_efs_supported(struct l2cap_conn * conn)3178848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn)
3179f89cef09SAndrei Emeltchenko {
3180cd5d26a9SLuiz Augusto von Dentz return (conn->feat_mask & L2CAP_FEAT_EXT_FLOW);
3181f89cef09SAndrei Emeltchenko }
3182f89cef09SAndrei Emeltchenko
__l2cap_set_ertm_timeouts(struct l2cap_chan * chan,struct l2cap_conf_rfc * rfc)318336c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
318436c86c85SMat Martineau struct l2cap_conf_rfc *rfc)
318536c86c85SMat Martineau {
3186dcf4adbfSJoe Perches rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
3187dcf4adbfSJoe Perches rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
318836c86c85SMat Martineau }
318936c86c85SMat Martineau
l2cap_txwin_setup(struct l2cap_chan * chan)31906327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
31916327eb98SAndrei Emeltchenko {
31926327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
3193848566b3SMarcel Holtmann __l2cap_ews_supported(chan->conn)) {
31946327eb98SAndrei Emeltchenko /* use extended control field */
31956327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags);
3196836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
3197836be934SAndrei Emeltchenko } else {
31986327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win,
31996327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW);
3200836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
3201836be934SAndrei Emeltchenko }
3202c20f8e35SMat Martineau chan->ack_win = chan->tx_win;
32036327eb98SAndrei Emeltchenko }
32046327eb98SAndrei Emeltchenko
l2cap_mtu_auto(struct l2cap_chan * chan)32054b6e228eSLuiz Augusto von Dentz static void l2cap_mtu_auto(struct l2cap_chan *chan)
32064b6e228eSLuiz Augusto von Dentz {
32074b6e228eSLuiz Augusto von Dentz struct hci_conn *conn = chan->conn->hcon;
32084b6e228eSLuiz Augusto von Dentz
32094b6e228eSLuiz Augusto von Dentz chan->imtu = L2CAP_DEFAULT_MIN_MTU;
32104b6e228eSLuiz Augusto von Dentz
32114b6e228eSLuiz Augusto von Dentz /* The 2-DH1 packet has between 2 and 56 information bytes
32124b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header)
32134b6e228eSLuiz Augusto von Dentz */
32144b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_2DH1))
32154b6e228eSLuiz Augusto von Dentz chan->imtu = 54;
32164b6e228eSLuiz Augusto von Dentz
32174b6e228eSLuiz Augusto von Dentz /* The 3-DH1 packet has between 2 and 85 information bytes
32184b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header)
32194b6e228eSLuiz Augusto von Dentz */
32204b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_3DH1))
32214b6e228eSLuiz Augusto von Dentz chan->imtu = 83;
32224b6e228eSLuiz Augusto von Dentz
32234b6e228eSLuiz Augusto von Dentz /* The 2-DH3 packet has between 2 and 369 information bytes
32244b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header)
32254b6e228eSLuiz Augusto von Dentz */
32264b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_2DH3))
32274b6e228eSLuiz Augusto von Dentz chan->imtu = 367;
32284b6e228eSLuiz Augusto von Dentz
32294b6e228eSLuiz Augusto von Dentz /* The 3-DH3 packet has between 2 and 554 information bytes
32304b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header)
32314b6e228eSLuiz Augusto von Dentz */
32324b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_3DH3))
32334b6e228eSLuiz Augusto von Dentz chan->imtu = 552;
32344b6e228eSLuiz Augusto von Dentz
32354b6e228eSLuiz Augusto von Dentz /* The 2-DH5 packet has between 2 and 681 information bytes
32364b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header)
32374b6e228eSLuiz Augusto von Dentz */
32384b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_2DH5))
32394b6e228eSLuiz Augusto von Dentz chan->imtu = 679;
32404b6e228eSLuiz Augusto von Dentz
32414b6e228eSLuiz Augusto von Dentz /* The 3-DH5 packet has between 2 and 1023 information bytes
32424b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header)
32434b6e228eSLuiz Augusto von Dentz */
32444b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_3DH5))
32454b6e228eSLuiz Augusto von Dentz chan->imtu = 1021;
32464b6e228eSLuiz Augusto von Dentz }
32474b6e228eSLuiz Augusto von Dentz
l2cap_build_conf_req(struct l2cap_chan * chan,void * data,size_t data_size)3248e860d2c9SBen Seri static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
32490a708f8fSGustavo F. Padovan {
32500a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data;
32510c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode };
32520a708f8fSGustavo F. Padovan void *ptr = req->data;
3253e860d2c9SBen Seri void *endptr = data + data_size;
3254c8f79162SAndrei Emeltchenko u16 size;
32550a708f8fSGustavo F. Padovan
325649208c9cSGustavo F. Padovan BT_DBG("chan %p", chan);
32570a708f8fSGustavo F. Padovan
325873ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp)
32590a708f8fSGustavo F. Padovan goto done;
32600a708f8fSGustavo F. Padovan
32610c1bc5c6SGustavo F. Padovan switch (chan->mode) {
32620a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING:
32630a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM:
3264c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
32650a708f8fSGustavo F. Padovan break;
32660a708f8fSGustavo F. Padovan
3267848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn))
3268f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags);
3269f89cef09SAndrei Emeltchenko
327019186c7bSGustavo A. R. Silva fallthrough;
32710a708f8fSGustavo F. Padovan default:
32728c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
32730a708f8fSGustavo F. Padovan break;
32740a708f8fSGustavo F. Padovan }
32750a708f8fSGustavo F. Padovan
32760a708f8fSGustavo F. Padovan done:
32774b6e228eSLuiz Augusto von Dentz if (chan->imtu != L2CAP_DEFAULT_MTU) {
32784b6e228eSLuiz Augusto von Dentz if (!chan->imtu)
32794b6e228eSLuiz Augusto von Dentz l2cap_mtu_auto(chan);
32804b6e228eSLuiz Augusto von Dentz l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu,
32814b6e228eSLuiz Augusto von Dentz endptr - ptr);
32824b6e228eSLuiz Augusto von Dentz }
32830a708f8fSGustavo F. Padovan
32840c1bc5c6SGustavo F. Padovan switch (chan->mode) {
32850a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC:
32866fea7ad1SMarcel Holtmann if (disable_ertm)
32876fea7ad1SMarcel Holtmann break;
32886fea7ad1SMarcel Holtmann
32898c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
32908c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
32910a708f8fSGustavo F. Padovan break;
32920a708f8fSGustavo F. Padovan
32930a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC;
32940a708f8fSGustavo F. Padovan rfc.txwin_size = 0;
32950a708f8fSGustavo F. Padovan rfc.max_transmit = 0;
32960a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0;
32970a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0;
32980a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0;
32990a708f8fSGustavo F. Padovan
33000a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3301e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr);
33020a708f8fSGustavo F. Padovan break;
33030a708f8fSGustavo F. Padovan
33040a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM:
33050a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM;
330647d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx;
330736c86c85SMat Martineau
330836c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc);
3309c8f79162SAndrei Emeltchenko
3310c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
33112d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3312c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE);
3313c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size);
33140a708f8fSGustavo F. Padovan
33156327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan);
33166327eb98SAndrei Emeltchenko
33176327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win,
33186327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW);
33190a708f8fSGustavo F. Padovan
33200a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3321e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr);
33220a708f8fSGustavo F. Padovan
3323f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3324e860d2c9SBen Seri l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
3325f89cef09SAndrei Emeltchenko
33266327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags))
33276327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
3328e860d2c9SBen Seri chan->tx_win, endptr - ptr);
332960918918SAndrei Emeltchenko
333060918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
333160918918SAndrei Emeltchenko if (chan->fcs == L2CAP_FCS_NONE ||
3332f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
333360918918SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE;
333460918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
3335e860d2c9SBen Seri chan->fcs, endptr - ptr);
333660918918SAndrei Emeltchenko }
33370a708f8fSGustavo F. Padovan break;
33380a708f8fSGustavo F. Padovan
33390a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING:
3340273759e2SMat Martineau l2cap_txwin_setup(chan);
33410a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING;
33420a708f8fSGustavo F. Padovan rfc.txwin_size = 0;
33430a708f8fSGustavo F. Padovan rfc.max_transmit = 0;
33440a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0;
33450a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0;
3346c8f79162SAndrei Emeltchenko
3347c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
33482d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3349c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE);
3350c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size);
33510a708f8fSGustavo F. Padovan
33520a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3353e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr);
33540a708f8fSGustavo F. Padovan
3355f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3356e860d2c9SBen Seri l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
3357f89cef09SAndrei Emeltchenko
335860918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
335947d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE ||
3360f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
336147d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE;
336260918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
3363e860d2c9SBen Seri chan->fcs, endptr - ptr);
33640a708f8fSGustavo F. Padovan }
33650a708f8fSGustavo F. Padovan break;
33660a708f8fSGustavo F. Padovan }
33670a708f8fSGustavo F. Padovan
3368fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid);
3369dcf4adbfSJoe Perches req->flags = cpu_to_le16(0);
33700a708f8fSGustavo F. Padovan
33710a708f8fSGustavo F. Padovan return ptr - data;
33720a708f8fSGustavo F. Padovan }
33730a708f8fSGustavo F. Padovan
l2cap_parse_conf_req(struct l2cap_chan * chan,void * data,size_t data_size)3374e860d2c9SBen Seri static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
33750a708f8fSGustavo F. Padovan {
33760a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data;
33770a708f8fSGustavo F. Padovan void *ptr = rsp->data;
3378e860d2c9SBen Seri void *endptr = data + data_size;
337973ffa904SGustavo F. Padovan void *req = chan->conf_req;
338073ffa904SGustavo F. Padovan int len = chan->conf_len;
33810a708f8fSGustavo F. Padovan int type, hint, olen;
33820a708f8fSGustavo F. Padovan unsigned long val;
33830a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
338442dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs;
338542dceae2SAndrei Emeltchenko u8 remote_efs = 0;
33860a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU;
33870a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS;
3388c8f79162SAndrei Emeltchenko u16 size;
33890a708f8fSGustavo F. Padovan
339073ffa904SGustavo F. Padovan BT_DBG("chan %p", chan);
33910a708f8fSGustavo F. Padovan
33920a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) {
33930a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
33947c9cbd0bSMarcel Holtmann if (len < 0)
33957c9cbd0bSMarcel Holtmann break;
33960a708f8fSGustavo F. Padovan
33970a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT;
33980a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK;
33990a708f8fSGustavo F. Padovan
34000a708f8fSGustavo F. Padovan switch (type) {
34010a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU:
3402af3d5d1cSMarcel Holtmann if (olen != 2)
3403af3d5d1cSMarcel Holtmann break;
34040a708f8fSGustavo F. Padovan mtu = val;
34050a708f8fSGustavo F. Padovan break;
34060a708f8fSGustavo F. Padovan
34070a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO:
3408af3d5d1cSMarcel Holtmann if (olen != 2)
3409af3d5d1cSMarcel Holtmann break;
34100c1bc5c6SGustavo F. Padovan chan->flush_to = val;
34110a708f8fSGustavo F. Padovan break;
34120a708f8fSGustavo F. Padovan
34130a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS:
34140a708f8fSGustavo F. Padovan break;
34150a708f8fSGustavo F. Padovan
34160a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC:
3417af3d5d1cSMarcel Holtmann if (olen != sizeof(rfc))
3418af3d5d1cSMarcel Holtmann break;
34190a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen);
34200a708f8fSGustavo F. Padovan break;
34210a708f8fSGustavo F. Padovan
34220a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS:
3423af3d5d1cSMarcel Holtmann if (olen != 1)
3424af3d5d1cSMarcel Holtmann break;
34250a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE)
3426f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, &chan->conf_state);
342742dceae2SAndrei Emeltchenko break;
34280a708f8fSGustavo F. Padovan
342942dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS:
3430af3d5d1cSMarcel Holtmann if (olen != sizeof(efs))
3431af3d5d1cSMarcel Holtmann break;
343242dceae2SAndrei Emeltchenko remote_efs = 1;
343342dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen);
34340a708f8fSGustavo F. Padovan break;
34350a708f8fSGustavo F. Padovan
34366327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS:
3437af3d5d1cSMarcel Holtmann if (olen != 2)
3438af3d5d1cSMarcel Holtmann break;
34396327eb98SAndrei Emeltchenko return -ECONNREFUSED;
34400a708f8fSGustavo F. Padovan
34410a708f8fSGustavo F. Padovan default:
34420a708f8fSGustavo F. Padovan if (hint)
34430a708f8fSGustavo F. Padovan break;
34440a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN;
34455b8ec15dSJimmy Wahlberg l2cap_add_conf_opt(&ptr, (u8)type, sizeof(u8), type, endptr - ptr);
34460a708f8fSGustavo F. Padovan break;
34470a708f8fSGustavo F. Padovan }
34480a708f8fSGustavo F. Padovan }
34490a708f8fSGustavo F. Padovan
345073ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1)
34510a708f8fSGustavo F. Padovan goto done;
34520a708f8fSGustavo F. Padovan
34530c1bc5c6SGustavo F. Padovan switch (chan->mode) {
34540a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING:
34550a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM:
3456c1360a1cSGustavo F. Padovan if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
34570c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode,
34588c1d787bSGustavo F. Padovan chan->conn->feat_mask);
34590a708f8fSGustavo F. Padovan break;
34600a708f8fSGustavo F. Padovan }
34610a708f8fSGustavo F. Padovan
346242dceae2SAndrei Emeltchenko if (remote_efs) {
3463848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn))
346442dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags);
346542dceae2SAndrei Emeltchenko else
346642dceae2SAndrei Emeltchenko return -ECONNREFUSED;
346742dceae2SAndrei Emeltchenko }
346842dceae2SAndrei Emeltchenko
34690c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode)
34700a708f8fSGustavo F. Padovan return -ECONNREFUSED;
34710a708f8fSGustavo F. Padovan
34720a708f8fSGustavo F. Padovan break;
34730a708f8fSGustavo F. Padovan }
34740a708f8fSGustavo F. Padovan
34750a708f8fSGustavo F. Padovan done:
34760c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) {
34770a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT;
34780c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode;
34790a708f8fSGustavo F. Padovan
348073ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1)
34810a708f8fSGustavo F. Padovan return -ECONNREFUSED;
34820a708f8fSGustavo F. Padovan
34832d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3484e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr);
34850a708f8fSGustavo F. Padovan }
34860a708f8fSGustavo F. Padovan
34870a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) {
34880a708f8fSGustavo F. Padovan /* Configure output options and let the other side know
34890a708f8fSGustavo F. Padovan * which ones we don't like. */
34900a708f8fSGustavo F. Padovan
34910a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU)
34920a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT;
34930a708f8fSGustavo F. Padovan else {
34940c1bc5c6SGustavo F. Padovan chan->omtu = mtu;
3495c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state);
34960a708f8fSGustavo F. Padovan }
3497e860d2c9SBen Seri l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu, endptr - ptr);
34980a708f8fSGustavo F. Padovan
349942dceae2SAndrei Emeltchenko if (remote_efs) {
350042dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
350142dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC &&
350242dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) {
350342dceae2SAndrei Emeltchenko
350442dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT;
350542dceae2SAndrei Emeltchenko
350642dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1)
350742dceae2SAndrei Emeltchenko return -ECONNREFUSED;
350842dceae2SAndrei Emeltchenko
350942dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
351042dceae2SAndrei Emeltchenko sizeof(efs),
3511e860d2c9SBen Seri (unsigned long) &efs, endptr - ptr);
35120e8b207eSAndrei Emeltchenko } else {
35133e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */
35140e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING;
35150e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
351642dceae2SAndrei Emeltchenko }
351742dceae2SAndrei Emeltchenko }
351842dceae2SAndrei Emeltchenko
35190a708f8fSGustavo F. Padovan switch (rfc.mode) {
35200a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC:
352147d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE;
3522c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state);
35230a708f8fSGustavo F. Padovan break;
35240a708f8fSGustavo F. Padovan
35250a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM:
35266327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
35272c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size;
35286327eb98SAndrei Emeltchenko else
35296327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
35306327eb98SAndrei Emeltchenko
35312c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit;
35320a708f8fSGustavo F. Padovan
3533c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
35342d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
35352d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3536c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size);
3537c8f79162SAndrei Emeltchenko chan->remote_mps = size;
35380a708f8fSGustavo F. Padovan
353936c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc);
35400a708f8fSGustavo F. Padovan
3541c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state);
35420a708f8fSGustavo F. Padovan
35430a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
3544e860d2c9SBen Seri sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
35450a708f8fSGustavo F. Padovan
3546b1a2cd50SLuiz Augusto von Dentz if (remote_efs &&
3547b1a2cd50SLuiz Augusto von Dentz test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
354842dceae2SAndrei Emeltchenko chan->remote_id = efs.id;
354942dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype;
355042dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu);
355142dceae2SAndrei Emeltchenko chan->remote_flush_to =
355242dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to);
355342dceae2SAndrei Emeltchenko chan->remote_acc_lat =
355442dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat);
355542dceae2SAndrei Emeltchenko chan->remote_sdu_itime =
355642dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime);
355742dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
35582d792818SGustavo Padovan sizeof(efs),
3559e860d2c9SBen Seri (unsigned long) &efs, endptr - ptr);
356042dceae2SAndrei Emeltchenko }
35610a708f8fSGustavo F. Padovan break;
35620a708f8fSGustavo F. Padovan
35630a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING:
3564c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
35652d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
35662d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3567c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size);
3568c8f79162SAndrei Emeltchenko chan->remote_mps = size;
35690a708f8fSGustavo F. Padovan
3570c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state);
35710a708f8fSGustavo F. Padovan
35722d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3573e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr);
35740a708f8fSGustavo F. Padovan
35750a708f8fSGustavo F. Padovan break;
35760a708f8fSGustavo F. Padovan
35770a708f8fSGustavo F. Padovan default:
35780a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT;
35790a708f8fSGustavo F. Padovan
35800a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc));
35810c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode;
35820a708f8fSGustavo F. Padovan }
35830a708f8fSGustavo F. Padovan
35840a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS)
3585c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
35860a708f8fSGustavo F. Padovan }
3587fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid);
35880a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result);
3589dcf4adbfSJoe Perches rsp->flags = cpu_to_le16(0);
35900a708f8fSGustavo F. Padovan
35910a708f8fSGustavo F. Padovan return ptr - data;
35920a708f8fSGustavo F. Padovan }
35930a708f8fSGustavo F. Padovan
l2cap_parse_conf_rsp(struct l2cap_chan * chan,void * rsp,int len,void * data,size_t size,u16 * result)35942d792818SGustavo Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
3595e860d2c9SBen Seri void *data, size_t size, u16 *result)
35960a708f8fSGustavo F. Padovan {
35970a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data;
35980a708f8fSGustavo F. Padovan void *ptr = req->data;
3599e860d2c9SBen Seri void *endptr = data + size;
36000a708f8fSGustavo F. Padovan int type, olen;
36010a708f8fSGustavo F. Padovan unsigned long val;
360236e999a8SMat Martineau struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
360366af7aafSAndrei Emeltchenko struct l2cap_conf_efs efs;
36040a708f8fSGustavo F. Padovan
3605fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
36060a708f8fSGustavo F. Padovan
36070a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) {
36080a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
36097c9cbd0bSMarcel Holtmann if (len < 0)
36107c9cbd0bSMarcel Holtmann break;
36110a708f8fSGustavo F. Padovan
36120a708f8fSGustavo F. Padovan switch (type) {
36130a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU:
3614af3d5d1cSMarcel Holtmann if (olen != 2)
3615af3d5d1cSMarcel Holtmann break;
36160a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) {
36170a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT;
36180c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU;
36190a708f8fSGustavo F. Padovan } else
36200c1bc5c6SGustavo F. Padovan chan->imtu = val;
3621af3d5d1cSMarcel Holtmann l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu,
3622af3d5d1cSMarcel Holtmann endptr - ptr);
36230a708f8fSGustavo F. Padovan break;
36240a708f8fSGustavo F. Padovan
36250a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO:
3626af3d5d1cSMarcel Holtmann if (olen != 2)
3627af3d5d1cSMarcel Holtmann break;
36280c1bc5c6SGustavo F. Padovan chan->flush_to = val;
3629af3d5d1cSMarcel Holtmann l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2,
3630af3d5d1cSMarcel Holtmann chan->flush_to, endptr - ptr);
36310a708f8fSGustavo F. Padovan break;
36320a708f8fSGustavo F. Padovan
36330a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC:
3634af3d5d1cSMarcel Holtmann if (olen != sizeof(rfc))
3635af3d5d1cSMarcel Holtmann break;
36360a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen);
3637c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
36380c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode)
36390a708f8fSGustavo F. Padovan return -ECONNREFUSED;
364047d1ec61SGustavo F. Padovan chan->fcs = 0;
3641af3d5d1cSMarcel Holtmann l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3642af3d5d1cSMarcel Holtmann (unsigned long) &rfc, endptr - ptr);
36430a708f8fSGustavo F. Padovan break;
36446327eb98SAndrei Emeltchenko
36456327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS:
3646af3d5d1cSMarcel Holtmann if (olen != 2)
3647af3d5d1cSMarcel Holtmann break;
3648c20f8e35SMat Martineau chan->ack_win = min_t(u16, val, chan->ack_win);
36493e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
3650e860d2c9SBen Seri chan->tx_win, endptr - ptr);
36516327eb98SAndrei Emeltchenko break;
365266af7aafSAndrei Emeltchenko
365366af7aafSAndrei Emeltchenko case L2CAP_CONF_EFS:
3654af3d5d1cSMarcel Holtmann if (olen != sizeof(efs))
3655af3d5d1cSMarcel Holtmann break;
365666af7aafSAndrei Emeltchenko memcpy(&efs, (void *)val, olen);
365766af7aafSAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
365866af7aafSAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC &&
365966af7aafSAndrei Emeltchenko efs.stype != chan->local_stype)
366066af7aafSAndrei Emeltchenko return -ECONNREFUSED;
36612d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs),
3662e860d2c9SBen Seri (unsigned long) &efs, endptr - ptr);
366366af7aafSAndrei Emeltchenko break;
3664cbabee78SAndrei Emeltchenko
3665cbabee78SAndrei Emeltchenko case L2CAP_CONF_FCS:
3666af3d5d1cSMarcel Holtmann if (olen != 1)
3667af3d5d1cSMarcel Holtmann break;
3668cbabee78SAndrei Emeltchenko if (*result == L2CAP_CONF_PENDING)
3669cbabee78SAndrei Emeltchenko if (val == L2CAP_FCS_NONE)
3670f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS,
3671cbabee78SAndrei Emeltchenko &chan->conf_state);
3672cbabee78SAndrei Emeltchenko break;
36730a708f8fSGustavo F. Padovan }
36740a708f8fSGustavo F. Padovan }
36750a708f8fSGustavo F. Padovan
36760c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
36770a708f8fSGustavo F. Padovan return -ECONNREFUSED;
36780a708f8fSGustavo F. Padovan
36790c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode;
36800a708f8fSGustavo F. Padovan
36810e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
36820a708f8fSGustavo F. Padovan switch (rfc.mode) {
36830a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM:
368447d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
368547d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
368647d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size);
3687c20f8e35SMat Martineau if (!test_bit(FLAG_EXT_CTRL, &chan->flags))
3688c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win,
3689c20f8e35SMat Martineau rfc.txwin_size);
369066af7aafSAndrei Emeltchenko
369166af7aafSAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
369266af7aafSAndrei Emeltchenko chan->local_msdu = le16_to_cpu(efs.msdu);
369366af7aafSAndrei Emeltchenko chan->local_sdu_itime =
369466af7aafSAndrei Emeltchenko le32_to_cpu(efs.sdu_itime);
369566af7aafSAndrei Emeltchenko chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
369666af7aafSAndrei Emeltchenko chan->local_flush_to =
369766af7aafSAndrei Emeltchenko le32_to_cpu(efs.flush_to);
369866af7aafSAndrei Emeltchenko }
36990a708f8fSGustavo F. Padovan break;
370066af7aafSAndrei Emeltchenko
37010a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING:
370247d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size);
37030a708f8fSGustavo F. Padovan }
37040a708f8fSGustavo F. Padovan }
37050a708f8fSGustavo F. Padovan
3706fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid);
3707dcf4adbfSJoe Perches req->flags = cpu_to_le16(0);
37080a708f8fSGustavo F. Padovan
37090a708f8fSGustavo F. Padovan return ptr - data;
37100a708f8fSGustavo F. Padovan }
37110a708f8fSGustavo F. Padovan
l2cap_build_conf_rsp(struct l2cap_chan * chan,void * data,u16 result,u16 flags)37122d792818SGustavo Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data,
37132d792818SGustavo Padovan u16 result, u16 flags)
37140a708f8fSGustavo F. Padovan {
37150a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data;
37160a708f8fSGustavo F. Padovan void *ptr = rsp->data;
37170a708f8fSGustavo F. Padovan
3718fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan);
37190a708f8fSGustavo F. Padovan
3720fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid);
37210a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result);
37220a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags);
37230a708f8fSGustavo F. Padovan
37240a708f8fSGustavo F. Padovan return ptr - data;
37250a708f8fSGustavo F. Padovan }
37260a708f8fSGustavo F. Padovan
__l2cap_le_connect_rsp_defer(struct l2cap_chan * chan)372727e2d4c8SJohan Hedberg void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan)
372827e2d4c8SJohan Hedberg {
372927e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp;
373027e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn;
373127e2d4c8SJohan Hedberg
373227e2d4c8SJohan Hedberg BT_DBG("chan %p", chan);
373327e2d4c8SJohan Hedberg
373427e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid);
373527e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu);
37363916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps);
37370cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits);
3738571f7390SMallikarjun Phulari rsp.result = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
373927e2d4c8SJohan Hedberg
374027e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
374127e2d4c8SJohan Hedberg &rsp);
374227e2d4c8SJohan Hedberg }
374327e2d4c8SJohan Hedberg
l2cap_ecred_list_defer(struct l2cap_chan * chan,void * data)37449aa9d947SLuiz Augusto von Dentz static void l2cap_ecred_list_defer(struct l2cap_chan *chan, void *data)
374515f02b91SLuiz Augusto von Dentz {
37469aa9d947SLuiz Augusto von Dentz int *result = data;
374715f02b91SLuiz Augusto von Dentz
37489aa9d947SLuiz Augusto von Dentz if (*result || test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
374915f02b91SLuiz Augusto von Dentz return;
375015f02b91SLuiz Augusto von Dentz
37519aa9d947SLuiz Augusto von Dentz switch (chan->state) {
37529aa9d947SLuiz Augusto von Dentz case BT_CONNECT2:
37539aa9d947SLuiz Augusto von Dentz /* If channel still pending accept add to result */
37549aa9d947SLuiz Augusto von Dentz (*result)++;
37559aa9d947SLuiz Augusto von Dentz return;
37569aa9d947SLuiz Augusto von Dentz case BT_CONNECTED:
37579aa9d947SLuiz Augusto von Dentz return;
37589aa9d947SLuiz Augusto von Dentz default:
37599aa9d947SLuiz Augusto von Dentz /* If not connected or pending accept it has been refused */
37609aa9d947SLuiz Augusto von Dentz *result = -ECONNREFUSED;
37619aa9d947SLuiz Augusto von Dentz return;
37629aa9d947SLuiz Augusto von Dentz }
37639aa9d947SLuiz Augusto von Dentz }
376415f02b91SLuiz Augusto von Dentz
37659aa9d947SLuiz Augusto von Dentz struct l2cap_ecred_rsp_data {
37669aa9d947SLuiz Augusto von Dentz struct {
37679aa9d947SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp rsp;
37689aa9d947SLuiz Augusto von Dentz __le16 scid[L2CAP_ECRED_MAX_CID];
37699aa9d947SLuiz Augusto von Dentz } __packed pdu;
37709aa9d947SLuiz Augusto von Dentz int count;
37719aa9d947SLuiz Augusto von Dentz };
377215f02b91SLuiz Augusto von Dentz
l2cap_ecred_rsp_defer(struct l2cap_chan * chan,void * data)37739aa9d947SLuiz Augusto von Dentz static void l2cap_ecred_rsp_defer(struct l2cap_chan *chan, void *data)
37749aa9d947SLuiz Augusto von Dentz {
37759aa9d947SLuiz Augusto von Dentz struct l2cap_ecred_rsp_data *rsp = data;
377615f02b91SLuiz Augusto von Dentz
37779aa9d947SLuiz Augusto von Dentz if (test_bit(FLAG_ECRED_CONN_REQ_SENT, &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
__l2cap_ecred_conn_rsp_defer(struct l2cap_chan * chan)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;
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
__l2cap_connect_rsp_defer(struct l2cap_chan * chan)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];
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
l2cap_conf_rfc_get(struct l2cap_chan * chan,void * rsp,int len)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
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
l2cap_command_rej(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)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;
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
l2cap_connect(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u8 * data,u8 rsp_code)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;
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
39533df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock);
39548ffb9290SGustavo Padovan l2cap_chan_lock(pchan);
39550a708f8fSGustavo F. Padovan
39560a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */
3957dcf4adbfSJoe Perches if (psm != cpu_to_le16(L2CAP_PSM_SDP) &&
39580a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) {
39599f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
39600a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK;
39610a708f8fSGustavo F. Padovan goto response;
39620a708f8fSGustavo F. Padovan }
39630a708f8fSGustavo F. Padovan
39640a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM;
39650a708f8fSGustavo F. Padovan
3966dd1a8f8aSMallikarjun Phulari /* Check for valid dynamic CID range (as per Erratum 3253) */
3967dd1a8f8aSMallikarjun Phulari if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_DYN_END) {
3968dd1a8f8aSMallikarjun Phulari result = L2CAP_CR_INVALID_SCID;
39692dfa1003SGustavo Padovan goto response;
3970dd1a8f8aSMallikarjun Phulari }
3971dd1a8f8aSMallikarjun Phulari
3972dd1a8f8aSMallikarjun Phulari /* Check if we already have channel with that dcid */
3973dd1a8f8aSMallikarjun Phulari if (__l2cap_get_chan_by_dcid(conn, scid)) {
3974dd1a8f8aSMallikarjun Phulari result = L2CAP_CR_SCID_IN_USE;
3975dd1a8f8aSMallikarjun Phulari goto response;
3976dd1a8f8aSMallikarjun Phulari }
39772dfa1003SGustavo Padovan
397880b98027SGustavo Padovan chan = pchan->ops->new_connection(pchan);
397980808e43SGustavo F. Padovan if (!chan)
39800a708f8fSGustavo F. Padovan goto response;
39810a708f8fSGustavo F. Padovan
3982330b6c15SSyam Sidhardhan /* For certain devices (ex: HID mouse), support for authentication,
3983330b6c15SSyam Sidhardhan * pairing and bonding is optional. For such devices, inorder to avoid
3984330b6c15SSyam Sidhardhan * the ACL alive for too long after L2CAP disconnection, reset the ACL
3985330b6c15SSyam Sidhardhan * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect.
3986330b6c15SSyam Sidhardhan */
3987330b6c15SSyam Sidhardhan conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3988330b6c15SSyam Sidhardhan
39897eafc59eSMarcel Holtmann bacpy(&chan->src, &conn->hcon->src);
39907eafc59eSMarcel Holtmann bacpy(&chan->dst, &conn->hcon->dst);
3991a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(conn->hcon);
3992a250e048SJohan Hedberg chan->dst_type = bdaddr_dst_type(conn->hcon);
3993fe4128e0SGustavo F. Padovan chan->psm = psm;
3994fe4128e0SGustavo F. Padovan chan->dcid = scid;
39950a708f8fSGustavo F. Padovan
39966be36555SAndrei Emeltchenko __l2cap_chan_add(conn, chan);
399748454079SGustavo F. Padovan
3998fe4128e0SGustavo F. Padovan dcid = chan->scid;
39990a708f8fSGustavo F. Padovan
40008d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
40010a708f8fSGustavo F. Padovan
4002fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident;
40030a708f8fSGustavo F. Padovan
40040a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
4005e7cafc45SJohan Hedberg if (l2cap_chan_check_security(chan, false)) {
4006bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
4007f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2);
40080a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND;
40090a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND;
40102dc4e510SGustavo Padovan chan->ops->defer(chan);
40110a708f8fSGustavo F. Padovan } else {
40127ccca396SPauli Virtanen l2cap_state_change(chan, BT_CONFIG);
40137ccca396SPauli Virtanen result = L2CAP_CR_SUCCESS;
40140a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO;
40150a708f8fSGustavo F. Padovan }
40160a708f8fSGustavo F. Padovan } else {
4017f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2);
40180a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND;
40190a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND;
40200a708f8fSGustavo F. Padovan }
40210a708f8fSGustavo F. Padovan } else {
4022f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2);
40230a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND;
40240a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO;
40250a708f8fSGustavo F. Padovan }
40260a708f8fSGustavo F. Padovan
40270a708f8fSGustavo F. Padovan response:
40280a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid);
40290a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid);
40300a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result);
40310a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status);
40324c89b6aaSMat Martineau l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp);
40330a708f8fSGustavo F. Padovan
4034cfe560c7SSungwoo Kim if (!pchan)
4035cfe560c7SSungwoo Kim return;
4036cfe560c7SSungwoo Kim
40370a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
40380a708f8fSGustavo F. Padovan struct l2cap_info_req info;
4039dcf4adbfSJoe Perches info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
40400a708f8fSGustavo F. Padovan
40410a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
40420a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn);
40430a708f8fSGustavo F. Padovan
4044ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
40450a708f8fSGustavo F. Padovan
40462d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
40472d792818SGustavo Padovan sizeof(info), &info);
40480a708f8fSGustavo F. Padovan }
40490a708f8fSGustavo F. Padovan
4050c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
40510a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) {
40520a708f8fSGustavo F. Padovan u8 buf[128];
4053c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state);
40540a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4055e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
405673ffa904SGustavo F. Padovan chan->num_conf_req++;
40570a708f8fSGustavo F. Padovan }
40581700915fSMat Martineau
4059cfe560c7SSungwoo Kim l2cap_chan_unlock(pchan);
4060cfe560c7SSungwoo Kim mutex_unlock(&conn->chan_lock);
4061cfe560c7SSungwoo Kim l2cap_chan_put(pchan);
40624c89b6aaSMat Martineau }
40630a708f8fSGustavo F. Padovan
l2cap_connect_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)40644c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn,
4065cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
40664c89b6aaSMat Martineau {
40677b064edaSJaganath Kanakkassery struct hci_dev *hdev = conn->hcon->hdev;
40687b064edaSJaganath Kanakkassery struct hci_conn *hcon = conn->hcon;
40697b064edaSJaganath Kanakkassery
4070cb3b3152SJohan Hedberg if (cmd_len < sizeof(struct l2cap_conn_req))
4071cb3b3152SJohan Hedberg return -EPROTO;
4072cb3b3152SJohan Hedberg
40737b064edaSJaganath Kanakkassery hci_dev_lock(hdev);
4074e2c680fcSArchie Pusaka if (hci_dev_test_flag(hdev, HCI_MGMT))
40751c6ed31bSYu Liu mgmt_device_connected(hdev, hcon, NULL, 0);
40767b064edaSJaganath Kanakkassery hci_dev_unlock(hdev);
40777b064edaSJaganath Kanakkassery
40785af2e235SLuiz Augusto von Dentz l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP);
40790a708f8fSGustavo F. Padovan return 0;
40800a708f8fSGustavo F. Padovan }
40810a708f8fSGustavo F. Padovan
l2cap_connect_create_rsp(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)40825909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
4083cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4084cb3b3152SJohan Hedberg u8 *data)
40850a708f8fSGustavo F. Padovan {
40860a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
40870a708f8fSGustavo F. Padovan u16 scid, dcid, result, status;
408848454079SGustavo F. Padovan struct l2cap_chan *chan;
40890a708f8fSGustavo F. Padovan u8 req[128];
40903df91ea2SAndrei Emeltchenko int err;
40910a708f8fSGustavo F. Padovan
4092cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp))
4093cb3b3152SJohan Hedberg return -EPROTO;
4094cb3b3152SJohan Hedberg
40950a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid);
40960a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid);
40970a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result);
40980a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status);
40990a708f8fSGustavo F. Padovan
410075767213SSungwoo Kim if (result == L2CAP_CR_SUCCESS && (dcid < L2CAP_CID_DYN_START ||
410175767213SSungwoo Kim dcid > L2CAP_CID_DYN_END))
410275767213SSungwoo Kim return -EPROTO;
410375767213SSungwoo Kim
41041b009c98SAndrei Emeltchenko BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
41051b009c98SAndrei Emeltchenko dcid, scid, result, status);
41060a708f8fSGustavo F. Padovan
41073df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock);
41083df91ea2SAndrei Emeltchenko
41090a708f8fSGustavo F. Padovan if (scid) {
41103df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid);
41113df91ea2SAndrei Emeltchenko if (!chan) {
411221870b52SJohan Hedberg err = -EBADSLT;
41133df91ea2SAndrei Emeltchenko goto unlock;
41143df91ea2SAndrei Emeltchenko }
41150a708f8fSGustavo F. Padovan } else {
41163df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
41173df91ea2SAndrei Emeltchenko if (!chan) {
411821870b52SJohan Hedberg err = -EBADSLT;
41193df91ea2SAndrei Emeltchenko goto unlock;
41203df91ea2SAndrei Emeltchenko }
41210a708f8fSGustavo F. Padovan }
41220a708f8fSGustavo F. Padovan
412335fcbc42SLuiz Augusto von Dentz chan = l2cap_chan_hold_unless_zero(chan);
412435fcbc42SLuiz Augusto von Dentz if (!chan) {
412535fcbc42SLuiz Augusto von Dentz err = -EBADSLT;
412635fcbc42SLuiz Augusto von Dentz goto unlock;
412735fcbc42SLuiz Augusto von Dentz }
412835fcbc42SLuiz Augusto von Dentz
41293df91ea2SAndrei Emeltchenko err = 0;
41303df91ea2SAndrei Emeltchenko
41316be36555SAndrei Emeltchenko l2cap_chan_lock(chan);
413248454079SGustavo F. Padovan
41330a708f8fSGustavo F. Padovan switch (result) {
41340a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS:
413575767213SSungwoo Kim if (__l2cap_get_chan_by_dcid(conn, dcid)) {
413675767213SSungwoo Kim err = -EBADSLT;
413775767213SSungwoo Kim break;
413875767213SSungwoo Kim }
413975767213SSungwoo Kim
414089bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG);
4141fc7f8a7eSGustavo F. Padovan chan->ident = 0;
4142fe4128e0SGustavo F. Padovan chan->dcid = dcid;
4143c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
41440a708f8fSGustavo F. Padovan
4145c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
41460a708f8fSGustavo F. Padovan break;
41470a708f8fSGustavo F. Padovan
41480a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4149e860d2c9SBen Seri l2cap_build_conf_req(chan, req, sizeof(req)), req);
415073ffa904SGustavo F. Padovan chan->num_conf_req++;
41510a708f8fSGustavo F. Padovan break;
41520a708f8fSGustavo F. Padovan
41530a708f8fSGustavo F. Padovan case L2CAP_CR_PEND:
4154c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state);
41550a708f8fSGustavo F. Padovan break;
41560a708f8fSGustavo F. Padovan
41570a708f8fSGustavo F. Padovan default:
415848454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED);
41590a708f8fSGustavo F. Padovan break;
41600a708f8fSGustavo F. Padovan }
41610a708f8fSGustavo F. Padovan
41626be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
416335fcbc42SLuiz Augusto von Dentz l2cap_chan_put(chan);
41643df91ea2SAndrei Emeltchenko
41653df91ea2SAndrei Emeltchenko unlock:
41663df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock);
41673df91ea2SAndrei Emeltchenko
41683df91ea2SAndrei Emeltchenko return err;
41690a708f8fSGustavo F. Padovan }
41700a708f8fSGustavo F. Padovan
set_default_fcs(struct l2cap_chan * chan)417147d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
41720a708f8fSGustavo F. Padovan {
41730a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both
41740a708f8fSGustavo F. Padovan * sides request it.
41750a708f8fSGustavo F. Padovan */
41760c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
417747d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE;
4178f2592d3eSAndrei Emeltchenko else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state))
417947d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16;
41800a708f8fSGustavo F. Padovan }
41810a708f8fSGustavo F. Padovan
l2cap_send_efs_conf_rsp(struct l2cap_chan * chan,void * data,u8 ident,u16 flags)418229d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data,
418329d8a590SAndrei Emeltchenko u8 ident, u16 flags)
418429d8a590SAndrei Emeltchenko {
418529d8a590SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn;
418629d8a590SAndrei Emeltchenko
418729d8a590SAndrei Emeltchenko BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident,
418829d8a590SAndrei Emeltchenko flags);
418929d8a590SAndrei Emeltchenko
419029d8a590SAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
419129d8a590SAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
419229d8a590SAndrei Emeltchenko
419329d8a590SAndrei Emeltchenko l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP,
419429d8a590SAndrei Emeltchenko l2cap_build_conf_rsp(chan, data,
419529d8a590SAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), data);
419629d8a590SAndrei Emeltchenko }
419729d8a590SAndrei Emeltchenko
cmd_reject_invalid_cid(struct l2cap_conn * conn,u8 ident,u16 scid,u16 dcid)4198662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident,
4199662d652dSJohan Hedberg u16 scid, u16 dcid)
4200662d652dSJohan Hedberg {
4201662d652dSJohan Hedberg struct l2cap_cmd_rej_cid rej;
4202662d652dSJohan Hedberg
4203dcf4adbfSJoe Perches rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
4204662d652dSJohan Hedberg rej.scid = __cpu_to_le16(scid);
4205662d652dSJohan Hedberg rej.dcid = __cpu_to_le16(dcid);
4206662d652dSJohan Hedberg
4207662d652dSJohan Hedberg l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
4208662d652dSJohan Hedberg }
4209662d652dSJohan Hedberg
l2cap_config_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)42102d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn,
42112d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len,
42122d792818SGustavo Padovan u8 *data)
42130a708f8fSGustavo F. Padovan {
42140a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
42150a708f8fSGustavo F. Padovan u16 dcid, flags;
42160a708f8fSGustavo F. Padovan u8 rsp[64];
421748454079SGustavo F. Padovan struct l2cap_chan *chan;
42183c588192SMat Martineau int len, err = 0;
42190a708f8fSGustavo F. Padovan
4220cb3b3152SJohan Hedberg if (cmd_len < sizeof(*req))
4221cb3b3152SJohan Hedberg return -EPROTO;
4222cb3b3152SJohan Hedberg
42230a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid);
42240a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags);
42250a708f8fSGustavo F. Padovan
42260a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
42270a708f8fSGustavo F. Padovan
4228baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid);
4229662d652dSJohan Hedberg if (!chan) {
4230662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0);
4231662d652dSJohan Hedberg return 0;
4232662d652dSJohan Hedberg }
42330a708f8fSGustavo F. Padovan
423496298f64SHoward Chung if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2 &&
423596298f64SHoward Chung chan->state != BT_CONNECTED) {
4236662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4237662d652dSJohan Hedberg chan->dcid);
42380a708f8fSGustavo F. Padovan goto unlock;
42390a708f8fSGustavo F. Padovan }
42400a708f8fSGustavo F. Padovan
42410a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */
42420a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req);
4243cb3b3152SJohan Hedberg if (chan->conf_len + len > sizeof(chan->conf_req)) {
42440a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4245fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp,
42460a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp);
42470a708f8fSGustavo F. Padovan goto unlock;
42480a708f8fSGustavo F. Padovan }
42490a708f8fSGustavo F. Padovan
42500a708f8fSGustavo F. Padovan /* Store config. */
425173ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len);
425273ffa904SGustavo F. Padovan chan->conf_len += len;
42530a708f8fSGustavo F. Padovan
425459e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) {
42550a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */
42560a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4257fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp,
42585325e5bbSAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), rsp);
42590a708f8fSGustavo F. Padovan goto unlock;
42600a708f8fSGustavo F. Padovan }
42610a708f8fSGustavo F. Padovan
42620a708f8fSGustavo F. Padovan /* Complete config. */
4263e860d2c9SBen Seri len = l2cap_parse_conf_req(chan, rsp, sizeof(rsp));
42640a708f8fSGustavo F. Padovan if (len < 0) {
42655e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
42660a708f8fSGustavo F. Padovan goto unlock;
42670a708f8fSGustavo F. Padovan }
42680a708f8fSGustavo F. Padovan
42691500109bSMat Martineau chan->ident = cmd->ident;
42700a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
4271bcd70260SSungwoo Kim if (chan->num_conf_rsp < L2CAP_CONF_MAX_CONF_RSP)
427273ffa904SGustavo F. Padovan chan->num_conf_rsp++;
42730a708f8fSGustavo F. Padovan
42740a708f8fSGustavo F. Padovan /* Reset config buffer. */
427573ffa904SGustavo F. Padovan chan->conf_len = 0;
42760a708f8fSGustavo F. Padovan
4277c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
42780a708f8fSGustavo F. Padovan goto unlock;
42790a708f8fSGustavo F. Padovan
4280c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
428147d1ec61SGustavo F. Padovan set_default_fcs(chan);
42820a708f8fSGustavo F. Padovan
4283105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM ||
4284105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING)
42853c588192SMat Martineau err = l2cap_ertm_init(chan);
42860a708f8fSGustavo F. Padovan
42873c588192SMat Martineau if (err < 0)
42885e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err);
42893c588192SMat Martineau else
4290cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan);
42913c588192SMat Martineau
42920a708f8fSGustavo F. Padovan goto unlock;
42930a708f8fSGustavo F. Padovan }
42940a708f8fSGustavo F. Padovan
4295c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
42960a708f8fSGustavo F. Padovan u8 buf[64];
42970a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4298e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
429973ffa904SGustavo F. Padovan chan->num_conf_req++;
43000a708f8fSGustavo F. Padovan }
43010a708f8fSGustavo F. Padovan
430249c922bbSStephen Hemminger /* Got Conf Rsp PENDING from remote side and assume we sent
43030e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */
43040e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
43050e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
43060e8b207eSAndrei Emeltchenko
43070e8b207eSAndrei Emeltchenko /* check compatibility */
43080e8b207eSAndrei Emeltchenko
430979de886dSAndrei Emeltchenko /* Send rsp for BR/EDR channel */
431029d8a590SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags);
43110e8b207eSAndrei Emeltchenko }
43120e8b207eSAndrei Emeltchenko
43130a708f8fSGustavo F. Padovan unlock:
43146be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
4315d0be8347SLuiz Augusto von Dentz l2cap_chan_put(chan);
43163c588192SMat Martineau return err;
43170a708f8fSGustavo F. Padovan }
43180a708f8fSGustavo F. Padovan
l2cap_config_rsp(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)43192d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn,
4320cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4321cb3b3152SJohan Hedberg u8 *data)
43220a708f8fSGustavo F. Padovan {
43230a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
43240a708f8fSGustavo F. Padovan u16 scid, flags, result;
432548454079SGustavo F. Padovan struct l2cap_chan *chan;
4326cb3b3152SJohan Hedberg int len = cmd_len - sizeof(*rsp);
43273c588192SMat Martineau int err = 0;
43280a708f8fSGustavo F. Padovan
4329cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp))
4330cb3b3152SJohan Hedberg return -EPROTO;
4331cb3b3152SJohan Hedberg
43320a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid);
43330a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags);
43340a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result);
43350a708f8fSGustavo F. Padovan
433661386cbaSAndrei Emeltchenko BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
433761386cbaSAndrei Emeltchenko result, len);
43380a708f8fSGustavo F. Padovan
4339baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid);
434048454079SGustavo F. Padovan if (!chan)
43410a708f8fSGustavo F. Padovan return 0;
43420a708f8fSGustavo F. Padovan
43430a708f8fSGustavo F. Padovan switch (result) {
43440a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS:
434547d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len);
43460e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
43470a708f8fSGustavo F. Padovan break;
43480a708f8fSGustavo F. Padovan
43490e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING:
43500e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
43510e8b207eSAndrei Emeltchenko
43520e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
43530e8b207eSAndrei Emeltchenko char buf[64];
43540e8b207eSAndrei Emeltchenko
43550e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4356e860d2c9SBen Seri buf, sizeof(buf), &result);
43570e8b207eSAndrei Emeltchenko if (len < 0) {
43585e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
43590e8b207eSAndrei Emeltchenko goto done;
43600e8b207eSAndrei Emeltchenko }
43610e8b207eSAndrei Emeltchenko
4362cd5d26a9SLuiz Augusto von Dentz l2cap_send_efs_conf_rsp(chan, buf, cmd->ident, 0);
43635ce66b59SAndrei Emeltchenko }
43640e8b207eSAndrei Emeltchenko goto done;
43650e8b207eSAndrei Emeltchenko
436698d2c3e1SBastien Nocera case L2CAP_CONF_UNKNOWN:
43670a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT:
436873ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
43690a708f8fSGustavo F. Padovan char req[64];
43700a708f8fSGustavo F. Padovan
43710a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
43725e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
43730a708f8fSGustavo F. Padovan goto done;
43740a708f8fSGustavo F. Padovan }
43750a708f8fSGustavo F. Padovan
43760a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */
43770a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS;
4378b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4379e860d2c9SBen Seri req, sizeof(req), &result);
43800a708f8fSGustavo F. Padovan if (len < 0) {
43815e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
43820a708f8fSGustavo F. Padovan goto done;
43830a708f8fSGustavo F. Padovan }
43840a708f8fSGustavo F. Padovan
43850a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn),
43860a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req);
438773ffa904SGustavo F. Padovan chan->num_conf_req++;
43880a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS)
43890a708f8fSGustavo F. Padovan goto done;
43900a708f8fSGustavo F. Padovan break;
43910a708f8fSGustavo F. Padovan }
439219186c7bSGustavo A. R. Silva fallthrough;
43930a708f8fSGustavo F. Padovan
43940a708f8fSGustavo F. Padovan default:
43956be36555SAndrei Emeltchenko l2cap_chan_set_err(chan, ECONNRESET);
43962e0052e4SAndrei Emeltchenko
4397ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
43985e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
43990a708f8fSGustavo F. Padovan goto done;
44000a708f8fSGustavo F. Padovan }
44010a708f8fSGustavo F. Padovan
440259e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION)
44030a708f8fSGustavo F. Padovan goto done;
44040a708f8fSGustavo F. Padovan
4405c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state);
44060a708f8fSGustavo F. Padovan
4407c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
440847d1ec61SGustavo F. Padovan set_default_fcs(chan);
44090a708f8fSGustavo F. Padovan
4410105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM ||
4411105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING)
44123c588192SMat Martineau err = l2cap_ertm_init(chan);
44130a708f8fSGustavo F. Padovan
44143c588192SMat Martineau if (err < 0)
44155e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err);
44163c588192SMat Martineau else
4417cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan);
44180a708f8fSGustavo F. Padovan }
44190a708f8fSGustavo F. Padovan
44200a708f8fSGustavo F. Padovan done:
44216be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
4422d0be8347SLuiz Augusto von Dentz l2cap_chan_put(chan);
44233c588192SMat Martineau return err;
44240a708f8fSGustavo F. Padovan }
44250a708f8fSGustavo F. Padovan
l2cap_disconnect_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)44262d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
4427cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4428cb3b3152SJohan Hedberg u8 *data)
44290a708f8fSGustavo F. Padovan {
44300a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
44310a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp;
44320a708f8fSGustavo F. Padovan u16 dcid, scid;
443348454079SGustavo F. Padovan struct l2cap_chan *chan;
44340a708f8fSGustavo F. Padovan
4435cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req))
4436cb3b3152SJohan Hedberg return -EPROTO;
4437cb3b3152SJohan Hedberg
44380a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid);
44390a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid);
44400a708f8fSGustavo F. Padovan
44410a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
44420a708f8fSGustavo F. Padovan
4443a2a9339eSLuiz Augusto von Dentz chan = l2cap_get_chan_by_scid(conn, dcid);
44443df91ea2SAndrei Emeltchenko if (!chan) {
4445662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid);
4446662d652dSJohan Hedberg return 0;
44473df91ea2SAndrei Emeltchenko }
44480a708f8fSGustavo F. Padovan
4449fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid);
4450fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid);
44510a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
44520a708f8fSGustavo F. Padovan
44535ec1bbe5SGustavo Padovan chan->ops->set_shutdown(chan);
44540a708f8fSGustavo F. Padovan
445502c5ea52SYing Hsu l2cap_chan_unlock(chan);
4456a2a9339eSLuiz Augusto von Dentz mutex_lock(&conn->chan_lock);
445702c5ea52SYing Hsu l2cap_chan_lock(chan);
445848454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET);
4459a2a9339eSLuiz Augusto von Dentz mutex_unlock(&conn->chan_lock);
44606be36555SAndrei Emeltchenko
446180b98027SGustavo Padovan chan->ops->close(chan);
44626c08fc89SManish Mandlik
44636c08fc89SManish Mandlik l2cap_chan_unlock(chan);
446461d6ef3eSMat Martineau l2cap_chan_put(chan);
44653df91ea2SAndrei Emeltchenko
44660a708f8fSGustavo F. Padovan return 0;
44670a708f8fSGustavo F. Padovan }
44680a708f8fSGustavo F. Padovan
l2cap_disconnect_rsp(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)44692d792818SGustavo Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
4470cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4471cb3b3152SJohan Hedberg u8 *data)
44720a708f8fSGustavo F. Padovan {
44730a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
44740a708f8fSGustavo F. Padovan u16 dcid, scid;
447548454079SGustavo F. Padovan struct l2cap_chan *chan;
44760a708f8fSGustavo F. Padovan
4477cb3b3152SJohan Hedberg if (cmd_len != sizeof(*rsp))
4478cb3b3152SJohan Hedberg return -EPROTO;
4479cb3b3152SJohan Hedberg
44800a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid);
44810a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid);
44820a708f8fSGustavo F. Padovan
44830a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
44840a708f8fSGustavo F. Padovan
4485a2a9339eSLuiz Augusto von Dentz chan = l2cap_get_chan_by_scid(conn, scid);
44863df91ea2SAndrei Emeltchenko if (!chan) {
44870a708f8fSGustavo F. Padovan return 0;
44883df91ea2SAndrei Emeltchenko }
44890a708f8fSGustavo F. Padovan
449028261da8SMatias Karhumaa if (chan->state != BT_DISCONN) {
449128261da8SMatias Karhumaa l2cap_chan_unlock(chan);
44926c08fc89SManish Mandlik l2cap_chan_put(chan);
449328261da8SMatias Karhumaa return 0;
449428261da8SMatias Karhumaa }
449528261da8SMatias Karhumaa
449602c5ea52SYing Hsu l2cap_chan_unlock(chan);
4497a2a9339eSLuiz Augusto von Dentz mutex_lock(&conn->chan_lock);
449802c5ea52SYing Hsu l2cap_chan_lock(chan);
449948454079SGustavo F. Padovan l2cap_chan_del(chan, 0);
4500a2a9339eSLuiz Augusto von Dentz mutex_unlock(&conn->chan_lock);
45016be36555SAndrei Emeltchenko
450280b98027SGustavo Padovan chan->ops->close(chan);
45036c08fc89SManish Mandlik
45046c08fc89SManish Mandlik l2cap_chan_unlock(chan);
450561d6ef3eSMat Martineau l2cap_chan_put(chan);
45063df91ea2SAndrei Emeltchenko
45070a708f8fSGustavo F. Padovan return 0;
45080a708f8fSGustavo F. Padovan }
45090a708f8fSGustavo F. Padovan
l2cap_information_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)45102d792818SGustavo Padovan static inline int l2cap_information_req(struct l2cap_conn *conn,
4511cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4512cb3b3152SJohan Hedberg u8 *data)
45130a708f8fSGustavo F. Padovan {
45140a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data;
45150a708f8fSGustavo F. Padovan u16 type;
45160a708f8fSGustavo F. Padovan
4517cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req))
4518cb3b3152SJohan Hedberg return -EPROTO;
4519cb3b3152SJohan Hedberg
45200a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type);
45210a708f8fSGustavo F. Padovan
45220a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type);
45230a708f8fSGustavo F. Padovan
45240a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) {
45250a708f8fSGustavo F. Padovan u8 buf[8];
45260a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask;
45270a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
4528dcf4adbfSJoe Perches rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
4529dcf4adbfSJoe Perches rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
45300a708f8fSGustavo F. Padovan if (!disable_ertm)
45310a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
45320a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS;
4533a5fd6f30SAndrei Emeltchenko
45340a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data);
45352d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
45362d792818SGustavo Padovan buf);
45370a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) {
45380a708f8fSGustavo F. Padovan u8 buf[12];
45390a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
454050a147cdSMat Martineau
4541dcf4adbfSJoe Perches rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
4542dcf4adbfSJoe Perches rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
45430bd49fc7SJohan Hedberg rsp->data[0] = conn->local_fixed_chan;
45440bd49fc7SJohan Hedberg memset(rsp->data + 1, 0, 7);
45452d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
45462d792818SGustavo Padovan buf);
45470a708f8fSGustavo F. Padovan } else {
45480a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp;
45490a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type);
4550dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
45512d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp),
45522d792818SGustavo Padovan &rsp);
45530a708f8fSGustavo F. Padovan }
45540a708f8fSGustavo F. Padovan
45550a708f8fSGustavo F. Padovan return 0;
45560a708f8fSGustavo F. Padovan }
45570a708f8fSGustavo F. Padovan
l2cap_information_rsp(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)45582d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn,
4559cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4560cb3b3152SJohan Hedberg u8 *data)
45610a708f8fSGustavo F. Padovan {
45620a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
45630a708f8fSGustavo F. Padovan u16 type, result;
45640a708f8fSGustavo F. Padovan
45653f6fa3d4SJaganath Kanakkassery if (cmd_len < sizeof(*rsp))
4566cb3b3152SJohan Hedberg return -EPROTO;
4567cb3b3152SJohan Hedberg
45680a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type);
45690a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result);
45700a708f8fSGustavo F. Padovan
45710a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
45720a708f8fSGustavo F. Padovan
4573e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */
4574e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident ||
4575e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
4576e90165beSAndrei Emeltchenko return 0;
4577e90165beSAndrei Emeltchenko
457817cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer);
45790a708f8fSGustavo F. Padovan
45800a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) {
45810a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
45820a708f8fSGustavo F. Padovan conn->info_ident = 0;
45830a708f8fSGustavo F. Padovan
45840a708f8fSGustavo F. Padovan l2cap_conn_start(conn);
45850a708f8fSGustavo F. Padovan
45860a708f8fSGustavo F. Padovan return 0;
45870a708f8fSGustavo F. Padovan }
45880a708f8fSGustavo F. Padovan
4589978c93b9SAndrei Emeltchenko switch (type) {
4590978c93b9SAndrei Emeltchenko case L2CAP_IT_FEAT_MASK:
45910a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data);
45920a708f8fSGustavo F. Padovan
45930a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
45940a708f8fSGustavo F. Padovan struct l2cap_info_req req;
4595dcf4adbfSJoe Perches req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
45960a708f8fSGustavo F. Padovan
45970a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn);
45980a708f8fSGustavo F. Padovan
45990a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident,
46000a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req);
46010a708f8fSGustavo F. Padovan } else {
46020a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
46030a708f8fSGustavo F. Padovan conn->info_ident = 0;
46040a708f8fSGustavo F. Padovan
46050a708f8fSGustavo F. Padovan l2cap_conn_start(conn);
46060a708f8fSGustavo F. Padovan }
4607978c93b9SAndrei Emeltchenko break;
4608978c93b9SAndrei Emeltchenko
4609978c93b9SAndrei Emeltchenko case L2CAP_IT_FIXED_CHAN:
46100bd49fc7SJohan Hedberg conn->remote_fixed_chan = rsp->data[0];
46110a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
46120a708f8fSGustavo F. Padovan conn->info_ident = 0;
46130a708f8fSGustavo F. Padovan
46140a708f8fSGustavo F. Padovan l2cap_conn_start(conn);
4615978c93b9SAndrei Emeltchenko break;
46160a708f8fSGustavo F. Padovan }
46170a708f8fSGustavo F. Padovan
46180a708f8fSGustavo F. Padovan return 0;
46190a708f8fSGustavo F. Padovan }
46200a708f8fSGustavo F. Padovan
l2cap_conn_param_update_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)4621de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
46222d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd,
4623203e639eSJohan Hedberg u16 cmd_len, u8 *data)
4624de73115aSClaudio Takahasi {
4625de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon;
4626de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req;
4627de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp;
4628203e639eSJohan Hedberg u16 min, max, latency, to_multiplier;
46292ce603ebSClaudio Takahasi int err;
4630de73115aSClaudio Takahasi
463140bef302SJohan Hedberg if (hcon->role != HCI_ROLE_MASTER)
4632de73115aSClaudio Takahasi return -EINVAL;
4633de73115aSClaudio Takahasi
4634de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
4635de73115aSClaudio Takahasi return -EPROTO;
4636de73115aSClaudio Takahasi
4637de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data;
4638de73115aSClaudio Takahasi min = __le16_to_cpu(req->min);
4639de73115aSClaudio Takahasi max = __le16_to_cpu(req->max);
4640de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency);
4641de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier);
4642de73115aSClaudio Takahasi
4643de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
4644de73115aSClaudio Takahasi min, max, latency, to_multiplier);
4645de73115aSClaudio Takahasi
4646de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp));
46472ce603ebSClaudio Takahasi
4648d4905f24SAndre Guedes err = hci_check_conn_params(min, max, latency, to_multiplier);
46492ce603ebSClaudio Takahasi if (err)
4650dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
4651de73115aSClaudio Takahasi else
4652dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
4653de73115aSClaudio Takahasi
4654de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
4655de73115aSClaudio Takahasi sizeof(rsp), &rsp);
4656de73115aSClaudio Takahasi
4657ffb5a827SAndre Guedes if (!err) {
4658f4869e2aSJohan Hedberg u8 store_hint;
4659ffb5a827SAndre Guedes
4660f4869e2aSJohan Hedberg store_hint = hci_le_conn_update(hcon, min, max, latency,
4661f4869e2aSJohan Hedberg to_multiplier);
4662f4869e2aSJohan Hedberg mgmt_new_conn_param(hcon->hdev, &hcon->dst, hcon->dst_type,
4663f4869e2aSJohan Hedberg store_hint, min, max, latency,
4664f4869e2aSJohan Hedberg to_multiplier);
4665f4869e2aSJohan Hedberg
4666ffb5a827SAndre Guedes }
46672ce603ebSClaudio Takahasi
4668de73115aSClaudio Takahasi return 0;
4669de73115aSClaudio Takahasi }
4670de73115aSClaudio Takahasi
l2cap_le_connect_rsp(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)4671f1496deeSJohan Hedberg static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
4672f1496deeSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4673f1496deeSJohan Hedberg u8 *data)
4674f1496deeSJohan Hedberg {
4675f1496deeSJohan Hedberg struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data;
46763e64b7bdSJohan Hedberg struct hci_conn *hcon = conn->hcon;
4677f1496deeSJohan Hedberg u16 dcid, mtu, mps, credits, result;
4678f1496deeSJohan Hedberg struct l2cap_chan *chan;
46793e64b7bdSJohan Hedberg int err, sec_level;
4680f1496deeSJohan Hedberg
4681f1496deeSJohan Hedberg if (cmd_len < sizeof(*rsp))
4682f1496deeSJohan Hedberg return -EPROTO;
4683f1496deeSJohan Hedberg
4684f1496deeSJohan Hedberg dcid = __le16_to_cpu(rsp->dcid);
4685f1496deeSJohan Hedberg mtu = __le16_to_cpu(rsp->mtu);
4686f1496deeSJohan Hedberg mps = __le16_to_cpu(rsp->mps);
4687f1496deeSJohan Hedberg credits = __le16_to_cpu(rsp->credits);
4688f1496deeSJohan Hedberg result = __le16_to_cpu(rsp->result);
4689f1496deeSJohan Hedberg
4690571f7390SMallikarjun Phulari if (result == L2CAP_CR_LE_SUCCESS && (mtu < 23 || mps < 23 ||
469140624183SJohan Hedberg dcid < L2CAP_CID_DYN_START ||
469240624183SJohan Hedberg dcid > L2CAP_CID_LE_DYN_END))
4693f1496deeSJohan Hedberg return -EPROTO;
4694f1496deeSJohan Hedberg
4695f1496deeSJohan Hedberg BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x",
4696f1496deeSJohan Hedberg dcid, mtu, mps, credits, result);
4697f1496deeSJohan Hedberg
4698f1496deeSJohan Hedberg mutex_lock(&conn->chan_lock);
4699f1496deeSJohan Hedberg
4700f1496deeSJohan Hedberg chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
4701f1496deeSJohan Hedberg if (!chan) {
4702f1496deeSJohan Hedberg err = -EBADSLT;
4703f1496deeSJohan Hedberg goto unlock;
4704f1496deeSJohan Hedberg }
4705f1496deeSJohan Hedberg
4706f1496deeSJohan Hedberg err = 0;
4707f1496deeSJohan Hedberg
4708f1496deeSJohan Hedberg l2cap_chan_lock(chan);
4709f1496deeSJohan Hedberg
4710f1496deeSJohan Hedberg switch (result) {
4711571f7390SMallikarjun Phulari case L2CAP_CR_LE_SUCCESS:
471240624183SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, dcid)) {
471340624183SJohan Hedberg err = -EBADSLT;
471440624183SJohan Hedberg break;
471540624183SJohan Hedberg }
471640624183SJohan Hedberg
4717f1496deeSJohan Hedberg chan->ident = 0;
4718f1496deeSJohan Hedberg chan->dcid = dcid;
4719f1496deeSJohan Hedberg chan->omtu = mtu;
4720f1496deeSJohan Hedberg chan->remote_mps = mps;
47210cd75f7eSJohan Hedberg chan->tx_credits = credits;
4722f1496deeSJohan Hedberg l2cap_chan_ready(chan);
4723f1496deeSJohan Hedberg break;
4724f1496deeSJohan Hedberg
4725571f7390SMallikarjun Phulari case L2CAP_CR_LE_AUTHENTICATION:
4726571f7390SMallikarjun Phulari case L2CAP_CR_LE_ENCRYPTION:
47273e64b7bdSJohan Hedberg /* If we already have MITM protection we can't do
47283e64b7bdSJohan Hedberg * anything.
47293e64b7bdSJohan Hedberg */
47303e64b7bdSJohan Hedberg if (hcon->sec_level > BT_SECURITY_MEDIUM) {
47313e64b7bdSJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED);
47323e64b7bdSJohan Hedberg break;
47333e64b7bdSJohan Hedberg }
47343e64b7bdSJohan Hedberg
47353e64b7bdSJohan Hedberg sec_level = hcon->sec_level + 1;
47363e64b7bdSJohan Hedberg if (chan->sec_level < sec_level)
47373e64b7bdSJohan Hedberg chan->sec_level = sec_level;
47383e64b7bdSJohan Hedberg
47393e64b7bdSJohan Hedberg /* We'll need to send a new Connect Request */
47403e64b7bdSJohan Hedberg clear_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags);
47413e64b7bdSJohan Hedberg
47423e64b7bdSJohan Hedberg smp_conn_security(hcon, chan->sec_level);
47433e64b7bdSJohan Hedberg break;
47443e64b7bdSJohan Hedberg
4745f1496deeSJohan Hedberg default:
4746f1496deeSJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED);
4747f1496deeSJohan Hedberg break;
4748f1496deeSJohan Hedberg }
4749f1496deeSJohan Hedberg
4750f1496deeSJohan Hedberg l2cap_chan_unlock(chan);
4751f1496deeSJohan Hedberg
4752f1496deeSJohan Hedberg unlock:
4753f1496deeSJohan Hedberg mutex_unlock(&conn->chan_lock);
4754f1496deeSJohan Hedberg
4755f1496deeSJohan Hedberg return err;
4756f1496deeSJohan Hedberg }
4757f1496deeSJohan Hedberg
l2cap_bredr_sig_cmd(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)47583300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
47592d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len,
47602d792818SGustavo Padovan u8 *data)
47613300d9a9SClaudio Takahasi {
47623300d9a9SClaudio Takahasi int err = 0;
47633300d9a9SClaudio Takahasi
47643300d9a9SClaudio Takahasi switch (cmd->code) {
47653300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ:
4766cb3b3152SJohan Hedberg l2cap_command_rej(conn, cmd, cmd_len, data);
47673300d9a9SClaudio Takahasi break;
47683300d9a9SClaudio Takahasi
47693300d9a9SClaudio Takahasi case L2CAP_CONN_REQ:
4770cb3b3152SJohan Hedberg err = l2cap_connect_req(conn, cmd, cmd_len, data);
47713300d9a9SClaudio Takahasi break;
47723300d9a9SClaudio Takahasi
47733300d9a9SClaudio Takahasi case L2CAP_CONN_RSP:
47749245e737SJohan Hedberg l2cap_connect_create_rsp(conn, cmd, cmd_len, data);
47753300d9a9SClaudio Takahasi break;
47763300d9a9SClaudio Takahasi
47773300d9a9SClaudio Takahasi case L2CAP_CONF_REQ:
47783300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data);
47793300d9a9SClaudio Takahasi break;
47803300d9a9SClaudio Takahasi
47813300d9a9SClaudio Takahasi case L2CAP_CONF_RSP:
47829245e737SJohan Hedberg l2cap_config_rsp(conn, cmd, cmd_len, data);
47833300d9a9SClaudio Takahasi break;
47843300d9a9SClaudio Takahasi
47853300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ:
4786cb3b3152SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
47873300d9a9SClaudio Takahasi break;
47883300d9a9SClaudio Takahasi
47893300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP:
47909245e737SJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
47913300d9a9SClaudio Takahasi break;
47923300d9a9SClaudio Takahasi
47933300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ:
47943300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
47953300d9a9SClaudio Takahasi break;
47963300d9a9SClaudio Takahasi
47973300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP:
47983300d9a9SClaudio Takahasi break;
47993300d9a9SClaudio Takahasi
48003300d9a9SClaudio Takahasi case L2CAP_INFO_REQ:
4801cb3b3152SJohan Hedberg err = l2cap_information_req(conn, cmd, cmd_len, data);
48023300d9a9SClaudio Takahasi break;
48033300d9a9SClaudio Takahasi
48043300d9a9SClaudio Takahasi case L2CAP_INFO_RSP:
48059245e737SJohan Hedberg l2cap_information_rsp(conn, cmd, cmd_len, data);
48063300d9a9SClaudio Takahasi break;
48073300d9a9SClaudio Takahasi
48083300d9a9SClaudio Takahasi default:
48093300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
48103300d9a9SClaudio Takahasi err = -EINVAL;
48113300d9a9SClaudio Takahasi break;
48123300d9a9SClaudio Takahasi }
48133300d9a9SClaudio Takahasi
48143300d9a9SClaudio Takahasi return err;
48153300d9a9SClaudio Takahasi }
48163300d9a9SClaudio Takahasi
l2cap_le_connect_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)481727e2d4c8SJohan Hedberg static int l2cap_le_connect_req(struct l2cap_conn *conn,
481827e2d4c8SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
481927e2d4c8SJohan Hedberg u8 *data)
482027e2d4c8SJohan Hedberg {
482127e2d4c8SJohan Hedberg struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data;
482227e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp;
482327e2d4c8SJohan Hedberg struct l2cap_chan *chan, *pchan;
48240cd75f7eSJohan Hedberg u16 dcid, scid, credits, mtu, mps;
482527e2d4c8SJohan Hedberg __le16 psm;
482627e2d4c8SJohan Hedberg u8 result;
482727e2d4c8SJohan Hedberg
482827e2d4c8SJohan Hedberg if (cmd_len != sizeof(*req))
482927e2d4c8SJohan Hedberg return -EPROTO;
483027e2d4c8SJohan Hedberg
483127e2d4c8SJohan Hedberg scid = __le16_to_cpu(req->scid);
483227e2d4c8SJohan Hedberg mtu = __le16_to_cpu(req->mtu);
483327e2d4c8SJohan Hedberg mps = __le16_to_cpu(req->mps);
483427e2d4c8SJohan Hedberg psm = req->psm;
483527e2d4c8SJohan Hedberg dcid = 0;
48360cd75f7eSJohan Hedberg credits = 0;
483727e2d4c8SJohan Hedberg
483827e2d4c8SJohan Hedberg if (mtu < 23 || mps < 23)
483927e2d4c8SJohan Hedberg return -EPROTO;
484027e2d4c8SJohan Hedberg
484127e2d4c8SJohan Hedberg BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm),
484227e2d4c8SJohan Hedberg scid, mtu, mps);
484327e2d4c8SJohan Hedberg
4844711f8c3fSLuiz Augusto von Dentz /* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 3, Part A
4845711f8c3fSLuiz Augusto von Dentz * page 1059:
4846711f8c3fSLuiz Augusto von Dentz *
4847711f8c3fSLuiz Augusto von Dentz * Valid range: 0x0001-0x00ff
4848711f8c3fSLuiz Augusto von Dentz *
4849711f8c3fSLuiz Augusto von Dentz * Table 4.15: L2CAP_LE_CREDIT_BASED_CONNECTION_REQ SPSM ranges
4850711f8c3fSLuiz Augusto von Dentz */
4851711f8c3fSLuiz Augusto von Dentz if (!psm || __le16_to_cpu(psm) > L2CAP_PSM_LE_DYN_END) {
4852711f8c3fSLuiz Augusto von Dentz result = L2CAP_CR_LE_BAD_PSM;
4853711f8c3fSLuiz Augusto von Dentz chan = NULL;
4854711f8c3fSLuiz Augusto von Dentz goto response;
4855711f8c3fSLuiz Augusto von Dentz }
4856711f8c3fSLuiz Augusto von Dentz
485727e2d4c8SJohan Hedberg /* Check if we have socket listening on psm */
485827e2d4c8SJohan Hedberg pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
485927e2d4c8SJohan Hedberg &conn->hcon->dst, LE_LINK);
486027e2d4c8SJohan Hedberg if (!pchan) {
4861571f7390SMallikarjun Phulari result = L2CAP_CR_LE_BAD_PSM;
486227e2d4c8SJohan Hedberg chan = NULL;
486327e2d4c8SJohan Hedberg goto response;
486427e2d4c8SJohan Hedberg }
486527e2d4c8SJohan Hedberg
486627e2d4c8SJohan Hedberg mutex_lock(&conn->chan_lock);
486727e2d4c8SJohan Hedberg l2cap_chan_lock(pchan);
486827e2d4c8SJohan Hedberg
486935dc6f83SJohan Hedberg if (!smp_sufficient_security(conn->hcon, pchan->sec_level,
487035dc6f83SJohan Hedberg SMP_ALLOW_STK)) {
4871571f7390SMallikarjun Phulari result = L2CAP_CR_LE_AUTHENTICATION;
487227e2d4c8SJohan Hedberg chan = NULL;
487327e2d4c8SJohan Hedberg goto response_unlock;
487427e2d4c8SJohan Hedberg }
487527e2d4c8SJohan Hedberg
48768a7889ccSJohan Hedberg /* Check for valid dynamic CID range */
48778a7889ccSJohan Hedberg if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) {
4878571f7390SMallikarjun Phulari result = L2CAP_CR_LE_INVALID_SCID;
48798a7889ccSJohan Hedberg chan = NULL;
48808a7889ccSJohan Hedberg goto response_unlock;
48818a7889ccSJohan Hedberg }
48828a7889ccSJohan Hedberg
488327e2d4c8SJohan Hedberg /* Check if we already have channel with that dcid */
488427e2d4c8SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, scid)) {
4885571f7390SMallikarjun Phulari result = L2CAP_CR_LE_SCID_IN_USE;
488627e2d4c8SJohan Hedberg chan = NULL;
488727e2d4c8SJohan Hedberg goto response_unlock;
488827e2d4c8SJohan Hedberg }
488927e2d4c8SJohan Hedberg
489027e2d4c8SJohan Hedberg chan = pchan->ops->new_connection(pchan);
489127e2d4c8SJohan Hedberg if (!chan) {
4892571f7390SMallikarjun Phulari result = L2CAP_CR_LE_NO_MEM;
489327e2d4c8SJohan Hedberg goto response_unlock;
489427e2d4c8SJohan Hedberg }
489527e2d4c8SJohan Hedberg
489627e2d4c8SJohan Hedberg bacpy(&chan->src, &conn->hcon->src);
489727e2d4c8SJohan Hedberg bacpy(&chan->dst, &conn->hcon->dst);
4898a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(conn->hcon);
4899a250e048SJohan Hedberg chan->dst_type = bdaddr_dst_type(conn->hcon);
490027e2d4c8SJohan Hedberg chan->psm = psm;
490127e2d4c8SJohan Hedberg chan->dcid = scid;
490227e2d4c8SJohan Hedberg chan->omtu = mtu;
490327e2d4c8SJohan Hedberg chan->remote_mps = mps;
490427e2d4c8SJohan Hedberg
490527e2d4c8SJohan Hedberg __l2cap_chan_add(conn, chan);
4906fe149310SLuiz Augusto von Dentz
4907ba8f5289SLuiz Augusto von Dentz l2cap_le_flowctl_init(chan, __le16_to_cpu(req->credits));
4908fe149310SLuiz Augusto von Dentz
490927e2d4c8SJohan Hedberg dcid = chan->scid;
49100cd75f7eSJohan Hedberg credits = chan->rx_credits;
491127e2d4c8SJohan Hedberg
491227e2d4c8SJohan Hedberg __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
491327e2d4c8SJohan Hedberg
491427e2d4c8SJohan Hedberg chan->ident = cmd->ident;
491527e2d4c8SJohan Hedberg
491627e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
491727e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_CONNECT2);
4918434714dcSJohan Hedberg /* The following result value is actually not defined
4919434714dcSJohan Hedberg * for LE CoC but we use it to let the function know
4920434714dcSJohan Hedberg * that it should bail out after doing its cleanup
4921434714dcSJohan Hedberg * instead of sending a response.
4922434714dcSJohan Hedberg */
492327e2d4c8SJohan Hedberg result = L2CAP_CR_PEND;
492427e2d4c8SJohan Hedberg chan->ops->defer(chan);
492527e2d4c8SJohan Hedberg } else {
492627e2d4c8SJohan Hedberg l2cap_chan_ready(chan);
4927571f7390SMallikarjun Phulari result = L2CAP_CR_LE_SUCCESS;
492827e2d4c8SJohan Hedberg }
492927e2d4c8SJohan Hedberg
493027e2d4c8SJohan Hedberg response_unlock:
493127e2d4c8SJohan Hedberg l2cap_chan_unlock(pchan);
493227e2d4c8SJohan Hedberg mutex_unlock(&conn->chan_lock);
4933a24cce14SJohan Hedberg l2cap_chan_put(pchan);
493427e2d4c8SJohan Hedberg
493527e2d4c8SJohan Hedberg if (result == L2CAP_CR_PEND)
493627e2d4c8SJohan Hedberg return 0;
493727e2d4c8SJohan Hedberg
493827e2d4c8SJohan Hedberg response:
493927e2d4c8SJohan Hedberg if (chan) {
494027e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu);
49413916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps);
494227e2d4c8SJohan Hedberg } else {
494327e2d4c8SJohan Hedberg rsp.mtu = 0;
494427e2d4c8SJohan Hedberg rsp.mps = 0;
494527e2d4c8SJohan Hedberg }
494627e2d4c8SJohan Hedberg
494727e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(dcid);
49480cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(credits);
494927e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result);
495027e2d4c8SJohan Hedberg
495127e2d4c8SJohan Hedberg l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp);
495227e2d4c8SJohan Hedberg
495327e2d4c8SJohan Hedberg return 0;
495427e2d4c8SJohan Hedberg }
495527e2d4c8SJohan Hedberg
l2cap_le_credits(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)4956fad5fc89SJohan Hedberg static inline int l2cap_le_credits(struct l2cap_conn *conn,
4957fad5fc89SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4958fad5fc89SJohan Hedberg u8 *data)
4959fad5fc89SJohan Hedberg {
4960fad5fc89SJohan Hedberg struct l2cap_le_credits *pkt;
4961fad5fc89SJohan Hedberg struct l2cap_chan *chan;
49620f1bfe4eSJohan Hedberg u16 cid, credits, max_credits;
4963fad5fc89SJohan Hedberg
4964fad5fc89SJohan Hedberg if (cmd_len != sizeof(*pkt))
4965fad5fc89SJohan Hedberg return -EPROTO;
4966fad5fc89SJohan Hedberg
4967fad5fc89SJohan Hedberg pkt = (struct l2cap_le_credits *) data;
4968fad5fc89SJohan Hedberg cid = __le16_to_cpu(pkt->cid);
4969fad5fc89SJohan Hedberg credits = __le16_to_cpu(pkt->credits);
4970fad5fc89SJohan Hedberg
4971fad5fc89SJohan Hedberg BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits);
4972fad5fc89SJohan Hedberg
4973fad5fc89SJohan Hedberg chan = l2cap_get_chan_by_dcid(conn, cid);
4974fad5fc89SJohan Hedberg if (!chan)
4975fad5fc89SJohan Hedberg return -EBADSLT;
4976fad5fc89SJohan Hedberg
49770f1bfe4eSJohan Hedberg max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits;
49780f1bfe4eSJohan Hedberg if (credits > max_credits) {
49790f1bfe4eSJohan Hedberg BT_ERR("LE credits overflow");
49800f1bfe4eSJohan Hedberg l2cap_send_disconn_req(chan, ECONNRESET);
49810f1bfe4eSJohan Hedberg
49820f1bfe4eSJohan Hedberg /* Return 0 so that we don't trigger an unnecessary
49830f1bfe4eSJohan Hedberg * command reject packet.
49840f1bfe4eSJohan Hedberg */
4985d0be8347SLuiz Augusto von Dentz goto unlock;
49860f1bfe4eSJohan Hedberg }
49870f1bfe4eSJohan Hedberg
4988fad5fc89SJohan Hedberg chan->tx_credits += credits;
4989fad5fc89SJohan Hedberg
49908a505b7fSLuiz Augusto von Dentz /* Resume sending */
49918a505b7fSLuiz Augusto von Dentz l2cap_le_flowctl_send(chan);
4992fad5fc89SJohan Hedberg
4993fad5fc89SJohan Hedberg if (chan->tx_credits)
4994fad5fc89SJohan Hedberg chan->ops->resume(chan);
4995fad5fc89SJohan Hedberg
4996d0be8347SLuiz Augusto von Dentz unlock:
4997fad5fc89SJohan Hedberg l2cap_chan_unlock(chan);
4998d0be8347SLuiz Augusto von Dentz l2cap_chan_put(chan);
4999fad5fc89SJohan Hedberg
5000fad5fc89SJohan Hedberg return 0;
5001fad5fc89SJohan Hedberg }
5002fad5fc89SJohan Hedberg
l2cap_ecred_conn_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)500315f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
500415f02b91SLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd, u16 cmd_len,
500515f02b91SLuiz Augusto von Dentz u8 *data)
500615f02b91SLuiz Augusto von Dentz {
500715f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_req *req = (void *) data;
500815f02b91SLuiz Augusto von Dentz struct {
500915f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp rsp;
50107cf3b1ddSLuiz Augusto von Dentz __le16 dcid[L2CAP_ECRED_MAX_CID];
501115f02b91SLuiz Augusto von Dentz } __packed pdu;
501215f02b91SLuiz Augusto von Dentz struct l2cap_chan *chan, *pchan;
5013965995b7SYueHaibing u16 mtu, mps;
501415f02b91SLuiz Augusto von Dentz __le16 psm;
501515f02b91SLuiz Augusto von Dentz u8 result, len = 0;
501615f02b91SLuiz Augusto von Dentz int i, num_scid;
501715f02b91SLuiz Augusto von Dentz bool defer = false;
501815f02b91SLuiz Augusto von Dentz
50194be5ca67SLuiz Augusto von Dentz if (!enable_ecred)
50204be5ca67SLuiz Augusto von Dentz return -EINVAL;
50214be5ca67SLuiz Augusto von Dentz
502269d67b46SKonstantin Forostyan if (cmd_len < sizeof(*req) || (cmd_len - sizeof(*req)) % sizeof(u16)) {
502315f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_INVALID_PARAMS;
502415f02b91SLuiz Augusto von Dentz goto response;
502515f02b91SLuiz Augusto von Dentz }
502615f02b91SLuiz Augusto von Dentz
50277cf3b1ddSLuiz Augusto von Dentz cmd_len -= sizeof(*req);
50287cf3b1ddSLuiz Augusto von Dentz num_scid = cmd_len / sizeof(u16);
50297cf3b1ddSLuiz Augusto von Dentz
50307cf3b1ddSLuiz Augusto von Dentz if (num_scid > ARRAY_SIZE(pdu.dcid)) {
50317cf3b1ddSLuiz Augusto von Dentz result = L2CAP_CR_LE_INVALID_PARAMS;
50327cf3b1ddSLuiz Augusto von Dentz goto response;
50337cf3b1ddSLuiz Augusto von Dentz }
50347cf3b1ddSLuiz Augusto von Dentz
503515f02b91SLuiz Augusto von Dentz mtu = __le16_to_cpu(req->mtu);
503615f02b91SLuiz Augusto von Dentz mps = __le16_to_cpu(req->mps);
503715f02b91SLuiz Augusto von Dentz
503815f02b91SLuiz Augusto von Dentz if (mtu < L2CAP_ECRED_MIN_MTU || mps < L2CAP_ECRED_MIN_MPS) {
503915f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_UNACCEPT_PARAMS;
504015f02b91SLuiz Augusto von Dentz goto response;
504115f02b91SLuiz Augusto von Dentz }
504215f02b91SLuiz Augusto von Dentz
504315f02b91SLuiz Augusto von Dentz psm = req->psm;
504415f02b91SLuiz Augusto von Dentz
5045711f8c3fSLuiz Augusto von Dentz /* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 3, Part A
5046711f8c3fSLuiz Augusto von Dentz * page 1059:
5047711f8c3fSLuiz Augusto von Dentz *
5048711f8c3fSLuiz Augusto von Dentz * Valid range: 0x0001-0x00ff
5049711f8c3fSLuiz Augusto von Dentz *
5050711f8c3fSLuiz Augusto von Dentz * Table 4.15: L2CAP_LE_CREDIT_BASED_CONNECTION_REQ SPSM ranges
5051711f8c3fSLuiz Augusto von Dentz */
5052711f8c3fSLuiz Augusto von Dentz if (!psm || __le16_to_cpu(psm) > L2CAP_PSM_LE_DYN_END) {
5053711f8c3fSLuiz Augusto von Dentz result = L2CAP_CR_LE_BAD_PSM;
5054711f8c3fSLuiz Augusto von Dentz goto response;
5055711f8c3fSLuiz Augusto von Dentz }
5056711f8c3fSLuiz Augusto von Dentz
505715f02b91SLuiz Augusto von Dentz BT_DBG("psm 0x%2.2x mtu %u mps %u", __le16_to_cpu(psm), mtu, mps);
505815f02b91SLuiz Augusto von Dentz
505915f02b91SLuiz Augusto von Dentz memset(&pdu, 0, sizeof(pdu));
506015f02b91SLuiz Augusto von Dentz
506115f02b91SLuiz Augusto von Dentz /* Check if we have socket listening on psm */
506215f02b91SLuiz Augusto von Dentz pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
506315f02b91SLuiz Augusto von Dentz &conn->hcon->dst, LE_LINK);
506415f02b91SLuiz Augusto von Dentz if (!pchan) {
506515f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_BAD_PSM;
506615f02b91SLuiz Augusto von Dentz goto response;
506715f02b91SLuiz Augusto von Dentz }
506815f02b91SLuiz Augusto von Dentz
506915f02b91SLuiz Augusto von Dentz mutex_lock(&conn->chan_lock);
507015f02b91SLuiz Augusto von Dentz l2cap_chan_lock(pchan);
507115f02b91SLuiz Augusto von Dentz
507215f02b91SLuiz Augusto von Dentz if (!smp_sufficient_security(conn->hcon, pchan->sec_level,
507315f02b91SLuiz Augusto von Dentz SMP_ALLOW_STK)) {
507415f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_AUTHENTICATION;
507515f02b91SLuiz Augusto von Dentz goto unlock;
507615f02b91SLuiz Augusto von Dentz }
507715f02b91SLuiz Augusto von Dentz
507815f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_SUCCESS;
507915f02b91SLuiz Augusto von Dentz
508015f02b91SLuiz Augusto von Dentz for (i = 0; i < num_scid; i++) {
508115f02b91SLuiz Augusto von Dentz u16 scid = __le16_to_cpu(req->scid[i]);
508215f02b91SLuiz Augusto von Dentz
508315f02b91SLuiz Augusto von Dentz BT_DBG("scid[%d] 0x%4.4x", i, scid);
508415f02b91SLuiz Augusto von Dentz
508515f02b91SLuiz Augusto von Dentz pdu.dcid[i] = 0x0000;
508615f02b91SLuiz Augusto von Dentz len += sizeof(*pdu.dcid);
508715f02b91SLuiz Augusto von Dentz
508815f02b91SLuiz Augusto von Dentz /* Check for valid dynamic CID range */
508915f02b91SLuiz Augusto von Dentz if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) {
509015f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_INVALID_SCID;
509115f02b91SLuiz Augusto von Dentz continue;
509215f02b91SLuiz Augusto von Dentz }
509315f02b91SLuiz Augusto von Dentz
509415f02b91SLuiz Augusto von Dentz /* Check if we already have channel with that dcid */
509515f02b91SLuiz Augusto von Dentz if (__l2cap_get_chan_by_dcid(conn, scid)) {
509615f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_SCID_IN_USE;
509715f02b91SLuiz Augusto von Dentz continue;
509815f02b91SLuiz Augusto von Dentz }
509915f02b91SLuiz Augusto von Dentz
510015f02b91SLuiz Augusto von Dentz chan = pchan->ops->new_connection(pchan);
510115f02b91SLuiz Augusto von Dentz if (!chan) {
510215f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_NO_MEM;
510315f02b91SLuiz Augusto von Dentz continue;
510415f02b91SLuiz Augusto von Dentz }
510515f02b91SLuiz Augusto von Dentz
510615f02b91SLuiz Augusto von Dentz bacpy(&chan->src, &conn->hcon->src);
510715f02b91SLuiz Augusto von Dentz bacpy(&chan->dst, &conn->hcon->dst);
510815f02b91SLuiz Augusto von Dentz chan->src_type = bdaddr_src_type(conn->hcon);
510915f02b91SLuiz Augusto von Dentz chan->dst_type = bdaddr_dst_type(conn->hcon);
511015f02b91SLuiz Augusto von Dentz chan->psm = psm;
511115f02b91SLuiz Augusto von Dentz chan->dcid = scid;
511215f02b91SLuiz Augusto von Dentz chan->omtu = mtu;
511315f02b91SLuiz Augusto von Dentz chan->remote_mps = mps;
511415f02b91SLuiz Augusto von Dentz
511515f02b91SLuiz Augusto von Dentz __l2cap_chan_add(conn, chan);
511615f02b91SLuiz Augusto von Dentz
511715f02b91SLuiz Augusto von Dentz l2cap_ecred_init(chan, __le16_to_cpu(req->credits));
511815f02b91SLuiz Augusto von Dentz
511915f02b91SLuiz Augusto von Dentz /* Init response */
512015f02b91SLuiz Augusto von Dentz if (!pdu.rsp.credits) {
512115f02b91SLuiz Augusto von Dentz pdu.rsp.mtu = cpu_to_le16(chan->imtu);
512215f02b91SLuiz Augusto von Dentz pdu.rsp.mps = cpu_to_le16(chan->mps);
512315f02b91SLuiz Augusto von Dentz pdu.rsp.credits = cpu_to_le16(chan->rx_credits);
512415f02b91SLuiz Augusto von Dentz }
512515f02b91SLuiz Augusto von Dentz
512615f02b91SLuiz Augusto von Dentz pdu.dcid[i] = cpu_to_le16(chan->scid);
512715f02b91SLuiz Augusto von Dentz
512815f02b91SLuiz Augusto von Dentz __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
512915f02b91SLuiz Augusto von Dentz
513015f02b91SLuiz Augusto von Dentz chan->ident = cmd->ident;
51319aa9d947SLuiz Augusto von Dentz chan->mode = L2CAP_MODE_EXT_FLOWCTL;
513215f02b91SLuiz Augusto von Dentz
513315f02b91SLuiz Augusto von Dentz if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
513415f02b91SLuiz Augusto von Dentz l2cap_state_change(chan, BT_CONNECT2);
513515f02b91SLuiz Augusto von Dentz defer = true;
513615f02b91SLuiz Augusto von Dentz chan->ops->defer(chan);
513715f02b91SLuiz Augusto von Dentz } else {
513815f02b91SLuiz Augusto von Dentz l2cap_chan_ready(chan);
513915f02b91SLuiz Augusto von Dentz }
514015f02b91SLuiz Augusto von Dentz }
514115f02b91SLuiz Augusto von Dentz
514215f02b91SLuiz Augusto von Dentz unlock:
514315f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(pchan);
514415f02b91SLuiz Augusto von Dentz mutex_unlock(&conn->chan_lock);
514515f02b91SLuiz Augusto von Dentz l2cap_chan_put(pchan);
514615f02b91SLuiz Augusto von Dentz
514715f02b91SLuiz Augusto von Dentz response:
514815f02b91SLuiz Augusto von Dentz pdu.rsp.result = cpu_to_le16(result);
514915f02b91SLuiz Augusto von Dentz
515015f02b91SLuiz Augusto von Dentz if (defer)
515115f02b91SLuiz Augusto von Dentz return 0;
515215f02b91SLuiz Augusto von Dentz
515315f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, cmd->ident, L2CAP_ECRED_CONN_RSP,
515415f02b91SLuiz Augusto von Dentz sizeof(pdu.rsp) + len, &pdu);
515515f02b91SLuiz Augusto von Dentz
515615f02b91SLuiz Augusto von Dentz return 0;
515715f02b91SLuiz Augusto von Dentz }
515815f02b91SLuiz Augusto von Dentz
l2cap_ecred_conn_rsp(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)515915f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
516015f02b91SLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd, u16 cmd_len,
516115f02b91SLuiz Augusto von Dentz u8 *data)
516215f02b91SLuiz Augusto von Dentz {
516315f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp *rsp = (void *) data;
516415f02b91SLuiz Augusto von Dentz struct hci_conn *hcon = conn->hcon;
516515f02b91SLuiz Augusto von Dentz u16 mtu, mps, credits, result;
5166de895b43SLuiz Augusto von Dentz struct l2cap_chan *chan, *tmp;
516715f02b91SLuiz Augusto von Dentz int err = 0, sec_level;
516815f02b91SLuiz Augusto von Dentz int i = 0;
516915f02b91SLuiz Augusto von Dentz
517015f02b91SLuiz Augusto von Dentz if (cmd_len < sizeof(*rsp))
517115f02b91SLuiz Augusto von Dentz return -EPROTO;
517215f02b91SLuiz Augusto von Dentz
517315f02b91SLuiz Augusto von Dentz mtu = __le16_to_cpu(rsp->mtu);
517415f02b91SLuiz Augusto von Dentz mps = __le16_to_cpu(rsp->mps);
517515f02b91SLuiz Augusto von Dentz credits = __le16_to_cpu(rsp->credits);
517615f02b91SLuiz Augusto von Dentz result = __le16_to_cpu(rsp->result);
517715f02b91SLuiz Augusto von Dentz
517815f02b91SLuiz Augusto von Dentz BT_DBG("mtu %u mps %u credits %u result 0x%4.4x", mtu, mps, credits,
517915f02b91SLuiz Augusto von Dentz result);
518015f02b91SLuiz Augusto von Dentz
518115f02b91SLuiz Augusto von Dentz mutex_lock(&conn->chan_lock);
518215f02b91SLuiz Augusto von Dentz
518315f02b91SLuiz Augusto von Dentz cmd_len -= sizeof(*rsp);
518415f02b91SLuiz Augusto von Dentz
5185de895b43SLuiz Augusto von Dentz list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
518615f02b91SLuiz Augusto von Dentz u16 dcid;
518715f02b91SLuiz Augusto von Dentz
518815f02b91SLuiz Augusto von Dentz if (chan->ident != cmd->ident ||
518915f02b91SLuiz Augusto von Dentz chan->mode != L2CAP_MODE_EXT_FLOWCTL ||
519015f02b91SLuiz Augusto von Dentz chan->state == BT_CONNECTED)
519115f02b91SLuiz Augusto von Dentz continue;
519215f02b91SLuiz Augusto von Dentz
519315f02b91SLuiz Augusto von Dentz l2cap_chan_lock(chan);
519415f02b91SLuiz Augusto von Dentz
519515f02b91SLuiz Augusto von Dentz /* Check that there is a dcid for each pending channel */
519615f02b91SLuiz Augusto von Dentz if (cmd_len < sizeof(dcid)) {
519715f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED);
519815f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(chan);
519915f02b91SLuiz Augusto von Dentz continue;
520015f02b91SLuiz Augusto von Dentz }
520115f02b91SLuiz Augusto von Dentz
520215f02b91SLuiz Augusto von Dentz dcid = __le16_to_cpu(rsp->dcid[i++]);
520315f02b91SLuiz Augusto von Dentz cmd_len -= sizeof(u16);
520415f02b91SLuiz Augusto von Dentz
520515f02b91SLuiz Augusto von Dentz BT_DBG("dcid[%d] 0x%4.4x", i, dcid);
520615f02b91SLuiz Augusto von Dentz
520715f02b91SLuiz Augusto von Dentz /* Check if dcid is already in use */
520815f02b91SLuiz Augusto von Dentz if (dcid && __l2cap_get_chan_by_dcid(conn, dcid)) {
520915f02b91SLuiz Augusto von Dentz /* If a device receives a
521015f02b91SLuiz Augusto von Dentz * L2CAP_CREDIT_BASED_CONNECTION_RSP packet with an
521115f02b91SLuiz Augusto von Dentz * already-assigned Destination CID, then both the
521215f02b91SLuiz Augusto von Dentz * original channel and the new channel shall be
521315f02b91SLuiz Augusto von Dentz * immediately discarded and not used.
521415f02b91SLuiz Augusto von Dentz */
521515f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED);
521615f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(chan);
521715f02b91SLuiz Augusto von Dentz chan = __l2cap_get_chan_by_dcid(conn, dcid);
521815f02b91SLuiz Augusto von Dentz l2cap_chan_lock(chan);
521915f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNRESET);
522015f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(chan);
522115f02b91SLuiz Augusto von Dentz continue;
522215f02b91SLuiz Augusto von Dentz }
522315f02b91SLuiz Augusto von Dentz
522415f02b91SLuiz Augusto von Dentz switch (result) {
522515f02b91SLuiz Augusto von Dentz case L2CAP_CR_LE_AUTHENTICATION:
522615f02b91SLuiz Augusto von Dentz case L2CAP_CR_LE_ENCRYPTION:
522715f02b91SLuiz Augusto von Dentz /* If we already have MITM protection we can't do
522815f02b91SLuiz Augusto von Dentz * anything.
522915f02b91SLuiz Augusto von Dentz */
523015f02b91SLuiz Augusto von Dentz if (hcon->sec_level > BT_SECURITY_MEDIUM) {
523115f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED);
523215f02b91SLuiz Augusto von Dentz break;
523315f02b91SLuiz Augusto von Dentz }
523415f02b91SLuiz Augusto von Dentz
523515f02b91SLuiz Augusto von Dentz sec_level = hcon->sec_level + 1;
523615f02b91SLuiz Augusto von Dentz if (chan->sec_level < sec_level)
523715f02b91SLuiz Augusto von Dentz chan->sec_level = sec_level;
523815f02b91SLuiz Augusto von Dentz
523915f02b91SLuiz Augusto von Dentz /* We'll need to send a new Connect Request */
524015f02b91SLuiz Augusto von Dentz clear_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags);
524115f02b91SLuiz Augusto von Dentz
524215f02b91SLuiz Augusto von Dentz smp_conn_security(hcon, chan->sec_level);
524315f02b91SLuiz Augusto von Dentz break;
524415f02b91SLuiz Augusto von Dentz
524515f02b91SLuiz Augusto von Dentz case L2CAP_CR_LE_BAD_PSM:
524615f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED);
524715f02b91SLuiz Augusto von Dentz break;
524815f02b91SLuiz Augusto von Dentz
524915f02b91SLuiz Augusto von Dentz default:
525015f02b91SLuiz Augusto von Dentz /* If dcid was not set it means channels was refused */
525115f02b91SLuiz Augusto von Dentz if (!dcid) {
525215f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED);
525315f02b91SLuiz Augusto von Dentz break;
525415f02b91SLuiz Augusto von Dentz }
525515f02b91SLuiz Augusto von Dentz
525615f02b91SLuiz Augusto von Dentz chan->ident = 0;
525715f02b91SLuiz Augusto von Dentz chan->dcid = dcid;
525815f02b91SLuiz Augusto von Dentz chan->omtu = mtu;
525915f02b91SLuiz Augusto von Dentz chan->remote_mps = mps;
526015f02b91SLuiz Augusto von Dentz chan->tx_credits = credits;
526115f02b91SLuiz Augusto von Dentz l2cap_chan_ready(chan);
526215f02b91SLuiz Augusto von Dentz break;
526315f02b91SLuiz Augusto von Dentz }
526415f02b91SLuiz Augusto von Dentz
526515f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(chan);
526615f02b91SLuiz Augusto von Dentz }
526715f02b91SLuiz Augusto von Dentz
526815f02b91SLuiz Augusto von Dentz mutex_unlock(&conn->chan_lock);
526915f02b91SLuiz Augusto von Dentz
527015f02b91SLuiz Augusto von Dentz return err;
527115f02b91SLuiz Augusto von Dentz }
527215f02b91SLuiz Augusto von Dentz
l2cap_ecred_reconf_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)527315f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_reconf_req(struct l2cap_conn *conn,
527415f02b91SLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd, u16 cmd_len,
527515f02b91SLuiz Augusto von Dentz u8 *data)
527615f02b91SLuiz Augusto von Dentz {
527715f02b91SLuiz Augusto von Dentz struct l2cap_ecred_reconf_req *req = (void *) data;
527815f02b91SLuiz Augusto von Dentz struct l2cap_ecred_reconf_rsp rsp;
527915f02b91SLuiz Augusto von Dentz u16 mtu, mps, result;
528015f02b91SLuiz Augusto von Dentz struct l2cap_chan *chan;
528115f02b91SLuiz Augusto von Dentz int i, num_scid;
528215f02b91SLuiz Augusto von Dentz
52834be5ca67SLuiz Augusto von Dentz if (!enable_ecred)
52844be5ca67SLuiz Augusto von Dentz return -EINVAL;
52854be5ca67SLuiz Augusto von Dentz
528615f02b91SLuiz Augusto von Dentz if (cmd_len < sizeof(*req) || cmd_len - sizeof(*req) % sizeof(u16)) {
528715f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_INVALID_PARAMS;
528815f02b91SLuiz Augusto von Dentz goto respond;
528915f02b91SLuiz Augusto von Dentz }
529015f02b91SLuiz Augusto von Dentz
529115f02b91SLuiz Augusto von Dentz mtu = __le16_to_cpu(req->mtu);
529215f02b91SLuiz Augusto von Dentz mps = __le16_to_cpu(req->mps);
529315f02b91SLuiz Augusto von Dentz
529415f02b91SLuiz Augusto von Dentz BT_DBG("mtu %u mps %u", mtu, mps);
529515f02b91SLuiz Augusto von Dentz
529615f02b91SLuiz Augusto von Dentz if (mtu < L2CAP_ECRED_MIN_MTU) {
529715f02b91SLuiz Augusto von Dentz result = L2CAP_RECONF_INVALID_MTU;
529815f02b91SLuiz Augusto von Dentz goto respond;
529915f02b91SLuiz Augusto von Dentz }
530015f02b91SLuiz Augusto von Dentz
530115f02b91SLuiz Augusto von Dentz if (mps < L2CAP_ECRED_MIN_MPS) {
530215f02b91SLuiz Augusto von Dentz result = L2CAP_RECONF_INVALID_MPS;
530315f02b91SLuiz Augusto von Dentz goto respond;
530415f02b91SLuiz Augusto von Dentz }
530515f02b91SLuiz Augusto von Dentz
530615f02b91SLuiz Augusto von Dentz cmd_len -= sizeof(*req);
530715f02b91SLuiz Augusto von Dentz num_scid = cmd_len / sizeof(u16);
530815f02b91SLuiz Augusto von Dentz result = L2CAP_RECONF_SUCCESS;
530915f02b91SLuiz Augusto von Dentz
531015f02b91SLuiz Augusto von Dentz for (i = 0; i < num_scid; i++) {
531115f02b91SLuiz Augusto von Dentz u16 scid;
531215f02b91SLuiz Augusto von Dentz
531315f02b91SLuiz Augusto von Dentz scid = __le16_to_cpu(req->scid[i]);
531415f02b91SLuiz Augusto von Dentz if (!scid)
531515f02b91SLuiz Augusto von Dentz return -EPROTO;
531615f02b91SLuiz Augusto von Dentz
531715f02b91SLuiz Augusto von Dentz chan = __l2cap_get_chan_by_dcid(conn, scid);
531815f02b91SLuiz Augusto von Dentz if (!chan)
531915f02b91SLuiz Augusto von Dentz continue;
532015f02b91SLuiz Augusto von Dentz
532115f02b91SLuiz Augusto von Dentz /* If the MTU value is decreased for any of the included
532215f02b91SLuiz Augusto von Dentz * channels, then the receiver shall disconnect all
532315f02b91SLuiz Augusto von Dentz * included channels.
532415f02b91SLuiz Augusto von Dentz */
532515f02b91SLuiz Augusto von Dentz if (chan->omtu > mtu) {
532615f02b91SLuiz Augusto von Dentz BT_ERR("chan %p decreased MTU %u -> %u", chan,
532715f02b91SLuiz Augusto von Dentz chan->omtu, mtu);
532815f02b91SLuiz Augusto von Dentz result = L2CAP_RECONF_INVALID_MTU;
532915f02b91SLuiz Augusto von Dentz }
533015f02b91SLuiz Augusto von Dentz
533115f02b91SLuiz Augusto von Dentz chan->omtu = mtu;
533215f02b91SLuiz Augusto von Dentz chan->remote_mps = mps;
533315f02b91SLuiz Augusto von Dentz }
533415f02b91SLuiz Augusto von Dentz
533515f02b91SLuiz Augusto von Dentz respond:
533615f02b91SLuiz Augusto von Dentz rsp.result = cpu_to_le16(result);
533715f02b91SLuiz Augusto von Dentz
533815f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, cmd->ident, L2CAP_ECRED_RECONF_RSP, sizeof(rsp),
533915f02b91SLuiz Augusto von Dentz &rsp);
534015f02b91SLuiz Augusto von Dentz
534115f02b91SLuiz Augusto von Dentz return 0;
534215f02b91SLuiz Augusto von Dentz }
534315f02b91SLuiz Augusto von Dentz
l2cap_ecred_reconf_rsp(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)534415f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
534515f02b91SLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd, u16 cmd_len,
534615f02b91SLuiz Augusto von Dentz u8 *data)
534715f02b91SLuiz Augusto von Dentz {
53481fa20d7dSLuiz Augusto von Dentz struct l2cap_chan *chan, *tmp;
534915f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp *rsp = (void *) data;
535015f02b91SLuiz Augusto von Dentz u16 result;
535115f02b91SLuiz Augusto von Dentz
535215f02b91SLuiz Augusto von Dentz if (cmd_len < sizeof(*rsp))
535315f02b91SLuiz Augusto von Dentz return -EPROTO;
535415f02b91SLuiz Augusto von Dentz
535515f02b91SLuiz Augusto von Dentz result = __le16_to_cpu(rsp->result);
535615f02b91SLuiz Augusto von Dentz
535715f02b91SLuiz Augusto von Dentz BT_DBG("result 0x%4.4x", rsp->result);
535815f02b91SLuiz Augusto von Dentz
535915f02b91SLuiz Augusto von Dentz if (!result)
536015f02b91SLuiz Augusto von Dentz return 0;
536115f02b91SLuiz Augusto von Dentz
53621fa20d7dSLuiz Augusto von Dentz list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
536315f02b91SLuiz Augusto von Dentz if (chan->ident != cmd->ident)
536415f02b91SLuiz Augusto von Dentz continue;
536515f02b91SLuiz Augusto von Dentz
536615f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNRESET);
536715f02b91SLuiz Augusto von Dentz }
536815f02b91SLuiz Augusto von Dentz
536915f02b91SLuiz Augusto von Dentz return 0;
537015f02b91SLuiz Augusto von Dentz }
537115f02b91SLuiz Augusto von Dentz
l2cap_le_command_rej(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)537271fb4197SJohan Hedberg static inline int l2cap_le_command_rej(struct l2cap_conn *conn,
537371fb4197SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
537471fb4197SJohan Hedberg u8 *data)
537571fb4197SJohan Hedberg {
537671fb4197SJohan Hedberg struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
537771fb4197SJohan Hedberg struct l2cap_chan *chan;
537871fb4197SJohan Hedberg
537971fb4197SJohan Hedberg if (cmd_len < sizeof(*rej))
538071fb4197SJohan Hedberg return -EPROTO;
538171fb4197SJohan Hedberg
538271fb4197SJohan Hedberg mutex_lock(&conn->chan_lock);
538371fb4197SJohan Hedberg
538471fb4197SJohan Hedberg chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
538571fb4197SJohan Hedberg if (!chan)
538671fb4197SJohan Hedberg goto done;
538771fb4197SJohan Hedberg
5388f752a0b3SZhengping Jiang chan = l2cap_chan_hold_unless_zero(chan);
5389f752a0b3SZhengping Jiang if (!chan)
5390f752a0b3SZhengping Jiang goto done;
5391f752a0b3SZhengping Jiang
539271fb4197SJohan Hedberg l2cap_chan_lock(chan);
539371fb4197SJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED);
539471fb4197SJohan Hedberg l2cap_chan_unlock(chan);
5395f752a0b3SZhengping Jiang l2cap_chan_put(chan);
539671fb4197SJohan Hedberg
539771fb4197SJohan Hedberg done:
539871fb4197SJohan Hedberg mutex_unlock(&conn->chan_lock);
539971fb4197SJohan Hedberg return 0;
540071fb4197SJohan Hedberg }
540171fb4197SJohan Hedberg
l2cap_le_sig_cmd(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)54023300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
5403203e639eSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5404203e639eSJohan Hedberg u8 *data)
54053300d9a9SClaudio Takahasi {
5406b5ecba64SJohan Hedberg int err = 0;
5407b5ecba64SJohan Hedberg
54083300d9a9SClaudio Takahasi switch (cmd->code) {
54093300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ:
541071fb4197SJohan Hedberg l2cap_le_command_rej(conn, cmd, cmd_len, data);
5411b5ecba64SJohan Hedberg break;
54123300d9a9SClaudio Takahasi
54133300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ:
5414b5ecba64SJohan Hedberg err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data);
5415b5ecba64SJohan Hedberg break;
54163300d9a9SClaudio Takahasi
54173300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP:
5418b5ecba64SJohan Hedberg break;
54193300d9a9SClaudio Takahasi
5420f1496deeSJohan Hedberg case L2CAP_LE_CONN_RSP:
5421f1496deeSJohan Hedberg l2cap_le_connect_rsp(conn, cmd, cmd_len, data);
5422b5ecba64SJohan Hedberg break;
5423f1496deeSJohan Hedberg
542427e2d4c8SJohan Hedberg case L2CAP_LE_CONN_REQ:
5425b5ecba64SJohan Hedberg err = l2cap_le_connect_req(conn, cmd, cmd_len, data);
5426b5ecba64SJohan Hedberg break;
542727e2d4c8SJohan Hedberg
5428fad5fc89SJohan Hedberg case L2CAP_LE_CREDITS:
5429fad5fc89SJohan Hedberg err = l2cap_le_credits(conn, cmd, cmd_len, data);
5430fad5fc89SJohan Hedberg break;
5431fad5fc89SJohan Hedberg
543215f02b91SLuiz Augusto von Dentz case L2CAP_ECRED_CONN_REQ:
543315f02b91SLuiz Augusto von Dentz err = l2cap_ecred_conn_req(conn, cmd, cmd_len, data);
543415f02b91SLuiz Augusto von Dentz break;
543515f02b91SLuiz Augusto von Dentz
543615f02b91SLuiz Augusto von Dentz case L2CAP_ECRED_CONN_RSP:
543715f02b91SLuiz Augusto von Dentz err = l2cap_ecred_conn_rsp(conn, cmd, cmd_len, data);
543815f02b91SLuiz Augusto von Dentz break;
543915f02b91SLuiz Augusto von Dentz
544015f02b91SLuiz Augusto von Dentz case L2CAP_ECRED_RECONF_REQ:
544115f02b91SLuiz Augusto von Dentz err = l2cap_ecred_reconf_req(conn, cmd, cmd_len, data);
544215f02b91SLuiz Augusto von Dentz break;
544315f02b91SLuiz Augusto von Dentz
544415f02b91SLuiz Augusto von Dentz case L2CAP_ECRED_RECONF_RSP:
544515f02b91SLuiz Augusto von Dentz err = l2cap_ecred_reconf_rsp(conn, cmd, cmd_len, data);
544615f02b91SLuiz Augusto von Dentz break;
544715f02b91SLuiz Augusto von Dentz
54483defe01aSJohan Hedberg case L2CAP_DISCONN_REQ:
5449b5ecba64SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
5450b5ecba64SJohan Hedberg break;
54513defe01aSJohan Hedberg
54523defe01aSJohan Hedberg case L2CAP_DISCONN_RSP:
54533defe01aSJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
5454b5ecba64SJohan Hedberg break;
54553defe01aSJohan Hedberg
54563300d9a9SClaudio Takahasi default:
54573300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
5458b5ecba64SJohan Hedberg err = -EINVAL;
5459b5ecba64SJohan Hedberg break;
54603300d9a9SClaudio Takahasi }
5461b5ecba64SJohan Hedberg
5462b5ecba64SJohan Hedberg return err;
54633300d9a9SClaudio Takahasi }
54643300d9a9SClaudio Takahasi
l2cap_le_sig_channel(struct l2cap_conn * conn,struct sk_buff * skb)5465c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
5466c5623556SJohan Hedberg struct sk_buff *skb)
5467c5623556SJohan Hedberg {
546869c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon;
54694f3e219dSMarcel Holtmann struct l2cap_cmd_hdr *cmd;
54704f3e219dSMarcel Holtmann u16 len;
5471c5623556SJohan Hedberg int err;
5472c5623556SJohan Hedberg
547369c4e4e8SJohan Hedberg if (hcon->type != LE_LINK)
54743b166295SMarcel Holtmann goto drop;
547569c4e4e8SJohan Hedberg
54764f3e219dSMarcel Holtmann if (skb->len < L2CAP_CMD_HDR_SIZE)
54774f3e219dSMarcel Holtmann goto drop;
5478c5623556SJohan Hedberg
54794f3e219dSMarcel Holtmann cmd = (void *) skb->data;
54804f3e219dSMarcel Holtmann skb_pull(skb, L2CAP_CMD_HDR_SIZE);
5481c5623556SJohan Hedberg
54824f3e219dSMarcel Holtmann len = le16_to_cpu(cmd->len);
5483c5623556SJohan Hedberg
54844f3e219dSMarcel Holtmann BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);
54854f3e219dSMarcel Holtmann
54864f3e219dSMarcel Holtmann if (len != skb->len || !cmd->ident) {
5487c5623556SJohan Hedberg BT_DBG("corrupted command");
54884f3e219dSMarcel Holtmann goto drop;
5489c5623556SJohan Hedberg }
5490c5623556SJohan Hedberg
5491203e639eSJohan Hedberg err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
5492c5623556SJohan Hedberg if (err) {
5493c5623556SJohan Hedberg struct l2cap_cmd_rej_unk rej;
5494c5623556SJohan Hedberg
5495c5623556SJohan Hedberg BT_ERR("Wrong link type (%d)", err);
5496c5623556SJohan Hedberg
5497dcf4adbfSJoe Perches rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
54984f3e219dSMarcel Holtmann l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
5499c5623556SJohan Hedberg sizeof(rej), &rej);
5500c5623556SJohan Hedberg }
5501c5623556SJohan Hedberg
55023b166295SMarcel Holtmann drop:
5503c5623556SJohan Hedberg kfree_skb(skb);
5504c5623556SJohan Hedberg }
5505c5623556SJohan Hedberg
l2cap_sig_send_rej(struct l2cap_conn * conn,u16 ident)55060974347aSFrédéric Danis static inline void l2cap_sig_send_rej(struct l2cap_conn *conn, u16 ident)
55070974347aSFrédéric Danis {
55080974347aSFrédéric Danis struct l2cap_cmd_rej_unk rej;
55090974347aSFrédéric Danis
55100974347aSFrédéric Danis rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
55110974347aSFrédéric Danis l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
55120974347aSFrédéric Danis }
55130974347aSFrédéric Danis
l2cap_sig_channel(struct l2cap_conn * conn,struct sk_buff * skb)55143300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
55153300d9a9SClaudio Takahasi struct sk_buff *skb)
55160a708f8fSGustavo F. Padovan {
551769c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon;
551855cee73eSLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd;
55193300d9a9SClaudio Takahasi int err;
55200a708f8fSGustavo F. Padovan
55210a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb);
55220a708f8fSGustavo F. Padovan
552369c4e4e8SJohan Hedberg if (hcon->type != ACL_LINK)
55243b166295SMarcel Holtmann goto drop;
552569c4e4e8SJohan Hedberg
552655cee73eSLuiz Augusto von Dentz while (skb->len >= L2CAP_CMD_HDR_SIZE) {
552755cee73eSLuiz Augusto von Dentz u16 len;
55280a708f8fSGustavo F. Padovan
552955cee73eSLuiz Augusto von Dentz cmd = (void *) skb->data;
553055cee73eSLuiz Augusto von Dentz skb_pull(skb, L2CAP_CMD_HDR_SIZE);
55310a708f8fSGustavo F. Padovan
553255cee73eSLuiz Augusto von Dentz len = le16_to_cpu(cmd->len);
55330a708f8fSGustavo F. Padovan
553455cee73eSLuiz Augusto von Dentz BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len,
553555cee73eSLuiz Augusto von Dentz cmd->ident);
553655cee73eSLuiz Augusto von Dentz
553755cee73eSLuiz Augusto von Dentz if (len > skb->len || !cmd->ident) {
55380a708f8fSGustavo F. Padovan BT_DBG("corrupted command");
55390974347aSFrédéric Danis l2cap_sig_send_rej(conn, cmd->ident);
5540100089a1SFrédéric Danis skb_pull(skb, len > skb->len ? skb->len : len);
5541100089a1SFrédéric Danis continue;
55420a708f8fSGustavo F. Padovan }
55430a708f8fSGustavo F. Padovan
554455cee73eSLuiz Augusto von Dentz err = l2cap_bredr_sig_cmd(conn, cmd, len, skb->data);
55450a708f8fSGustavo F. Padovan if (err) {
55462c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err);
55470974347aSFrédéric Danis l2cap_sig_send_rej(conn, cmd->ident);
55480a708f8fSGustavo F. Padovan }
55490a708f8fSGustavo F. Padovan
555055cee73eSLuiz Augusto von Dentz skb_pull(skb, len);
55510a708f8fSGustavo F. Padovan }
55520a708f8fSGustavo F. Padovan
55530974347aSFrédéric Danis if (skb->len > 0) {
55540974347aSFrédéric Danis BT_DBG("corrupted command");
55550974347aSFrédéric Danis l2cap_sig_send_rej(conn, 0);
55560974347aSFrédéric Danis }
55570974347aSFrédéric Danis
55583b166295SMarcel Holtmann drop:
55590a708f8fSGustavo F. Padovan kfree_skb(skb);
55600a708f8fSGustavo F. Padovan }
55610a708f8fSGustavo F. Padovan
l2cap_check_fcs(struct l2cap_chan * chan,struct sk_buff * skb)556247d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
55630a708f8fSGustavo F. Padovan {
55640a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs;
5565e4ca6d98SAndrei Emeltchenko int hdr_size;
5566e4ca6d98SAndrei Emeltchenko
5567e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags))
5568e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE;
5569e4ca6d98SAndrei Emeltchenko else
5570e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE;
55710a708f8fSGustavo F. Padovan
557247d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) {
557303a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
55740a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len);
55750a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
55760a708f8fSGustavo F. Padovan
55770a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs)
55780a708f8fSGustavo F. Padovan return -EBADMSG;
55790a708f8fSGustavo F. Padovan }
55800a708f8fSGustavo F. Padovan return 0;
55810a708f8fSGustavo F. Padovan }
55820a708f8fSGustavo F. Padovan
l2cap_send_i_or_rr_or_rnr(struct l2cap_chan * chan)55836ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
55840a708f8fSGustavo F. Padovan {
5585e31f7633SMat Martineau struct l2cap_ctrl control;
55860a708f8fSGustavo F. Padovan
5587e31f7633SMat Martineau BT_DBG("chan %p", chan);
55880a708f8fSGustavo F. Padovan
5589e31f7633SMat Martineau memset(&control, 0, sizeof(control));
5590e31f7633SMat Martineau control.sframe = 1;
5591e31f7633SMat Martineau control.final = 1;
5592e31f7633SMat Martineau control.reqseq = chan->buffer_seq;
5593e31f7633SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state);
55940a708f8fSGustavo F. Padovan
5595e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
5596e31f7633SMat Martineau control.super = L2CAP_SUPER_RNR;
5597e31f7633SMat Martineau l2cap_send_sframe(chan, &control);
55980a708f8fSGustavo F. Padovan }
55990a708f8fSGustavo F. Padovan
5600e31f7633SMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
5601e31f7633SMat Martineau chan->unacked_frames > 0)
5602e31f7633SMat Martineau __set_retrans_timer(chan);
56030a708f8fSGustavo F. Padovan
5604e31f7633SMat Martineau /* Send pending iframes */
5605525cd185SGustavo F. Padovan l2cap_ertm_send(chan);
56060a708f8fSGustavo F. Padovan
5607e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
5608e31f7633SMat Martineau test_bit(CONN_SEND_FBIT, &chan->conn_state)) {
5609e31f7633SMat Martineau /* F-bit wasn't sent in an s-frame or i-frame yet, so
5610e31f7633SMat Martineau * send it now.
5611e31f7633SMat Martineau */
5612e31f7633SMat Martineau control.super = L2CAP_SUPER_RR;
5613e31f7633SMat Martineau l2cap_send_sframe(chan, &control);
56140a708f8fSGustavo F. Padovan }
56150a708f8fSGustavo F. Padovan }
56160a708f8fSGustavo F. Padovan
append_skb_frag(struct sk_buff * skb,struct sk_buff * new_frag,struct sk_buff ** last_frag)56172d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag,
56182d792818SGustavo Padovan struct sk_buff **last_frag)
56190a708f8fSGustavo F. Padovan {
562084084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments
562184084a31SMat Martineau * skb->data_len reflects only data in fragments
562284084a31SMat Martineau */
562384084a31SMat Martineau if (!skb_has_frag_list(skb))
562484084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag;
562584084a31SMat Martineau
562684084a31SMat Martineau new_frag->next = NULL;
562784084a31SMat Martineau
562884084a31SMat Martineau (*last_frag)->next = new_frag;
562984084a31SMat Martineau *last_frag = new_frag;
563084084a31SMat Martineau
563184084a31SMat Martineau skb->len += new_frag->len;
563284084a31SMat Martineau skb->data_len += new_frag->len;
563384084a31SMat Martineau skb->truesize += new_frag->truesize;
563484084a31SMat Martineau }
563584084a31SMat Martineau
l2cap_reassemble_sdu(struct l2cap_chan * chan,struct sk_buff * skb,struct l2cap_ctrl * control)56364b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
56374b51dae9SMat Martineau struct l2cap_ctrl *control)
563884084a31SMat Martineau {
563984084a31SMat Martineau int err = -EINVAL;
56400a708f8fSGustavo F. Padovan
56414b51dae9SMat Martineau switch (control->sar) {
56427e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED:
564384084a31SMat Martineau if (chan->sdu)
564484084a31SMat Martineau break;
56450a708f8fSGustavo F. Padovan
564680b98027SGustavo Padovan err = chan->ops->recv(chan, skb);
564784084a31SMat Martineau break;
56480a708f8fSGustavo F. Padovan
56497e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START:
565084084a31SMat Martineau if (chan->sdu)
565184084a31SMat Martineau break;
56520a708f8fSGustavo F. Padovan
5653dbb50887SDaniel Borkmann if (!pskb_may_pull(skb, L2CAP_SDULEN_SIZE))
5654dbb50887SDaniel Borkmann break;
5655dbb50887SDaniel Borkmann
56566f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data);
565703a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE);
56580a708f8fSGustavo F. Padovan
565984084a31SMat Martineau if (chan->sdu_len > chan->imtu) {
566084084a31SMat Martineau err = -EMSGSIZE;
566184084a31SMat Martineau break;
566284084a31SMat Martineau }
56630a708f8fSGustavo F. Padovan
566484084a31SMat Martineau if (skb->len >= chan->sdu_len)
566584084a31SMat Martineau break;
566684084a31SMat Martineau
566784084a31SMat Martineau chan->sdu = skb;
566884084a31SMat Martineau chan->sdu_last_frag = skb;
566984084a31SMat Martineau
567084084a31SMat Martineau skb = NULL;
567184084a31SMat Martineau err = 0;
56720a708f8fSGustavo F. Padovan break;
56730a708f8fSGustavo F. Padovan
56747e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE:
56756f61fd47SGustavo F. Padovan if (!chan->sdu)
567684084a31SMat Martineau break;
56770a708f8fSGustavo F. Padovan
567884084a31SMat Martineau append_skb_frag(chan->sdu, skb,
567984084a31SMat Martineau &chan->sdu_last_frag);
568084084a31SMat Martineau skb = NULL;
56810a708f8fSGustavo F. Padovan
568284084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len)
568384084a31SMat Martineau break;
56840a708f8fSGustavo F. Padovan
568584084a31SMat Martineau err = 0;
56860a708f8fSGustavo F. Padovan break;
56870a708f8fSGustavo F. Padovan
56887e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END:
56896f61fd47SGustavo F. Padovan if (!chan->sdu)
569084084a31SMat Martineau break;
56910a708f8fSGustavo F. Padovan
569284084a31SMat Martineau append_skb_frag(chan->sdu, skb,
569384084a31SMat Martineau &chan->sdu_last_frag);
569484084a31SMat Martineau skb = NULL;
56950a708f8fSGustavo F. Padovan
569684084a31SMat Martineau if (chan->sdu->len != chan->sdu_len)
569784084a31SMat Martineau break;
56980a708f8fSGustavo F. Padovan
569980b98027SGustavo Padovan err = chan->ops->recv(chan, chan->sdu);
57000a708f8fSGustavo F. Padovan
570184084a31SMat Martineau if (!err) {
570284084a31SMat Martineau /* Reassembly complete */
570384084a31SMat Martineau chan->sdu = NULL;
570484084a31SMat Martineau chan->sdu_last_frag = NULL;
570584084a31SMat Martineau chan->sdu_len = 0;
57060a708f8fSGustavo F. Padovan }
57070a708f8fSGustavo F. Padovan break;
57080a708f8fSGustavo F. Padovan }
57090a708f8fSGustavo F. Padovan
571084084a31SMat Martineau if (err) {
57110a708f8fSGustavo F. Padovan kfree_skb(skb);
57126f61fd47SGustavo F. Padovan kfree_skb(chan->sdu);
57136f61fd47SGustavo F. Padovan chan->sdu = NULL;
571484084a31SMat Martineau chan->sdu_last_frag = NULL;
571584084a31SMat Martineau chan->sdu_len = 0;
571684084a31SMat Martineau }
57170a708f8fSGustavo F. Padovan
571884084a31SMat Martineau return err;
57190a708f8fSGustavo F. Padovan }
57200a708f8fSGustavo F. Padovan
l2cap_resegment(struct l2cap_chan * chan)572132b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan)
572232b32735SMat Martineau {
572332b32735SMat Martineau /* Placeholder */
572432b32735SMat Martineau return 0;
572532b32735SMat Martineau }
572632b32735SMat Martineau
l2cap_chan_busy(struct l2cap_chan * chan,int busy)5727e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
57280a708f8fSGustavo F. Padovan {
572961aa4f5bSMat Martineau u8 event;
573061aa4f5bSMat Martineau
573161aa4f5bSMat Martineau if (chan->mode != L2CAP_MODE_ERTM)
573261aa4f5bSMat Martineau return;
573361aa4f5bSMat Martineau
573461aa4f5bSMat Martineau event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR;
5735401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, event);
57360a708f8fSGustavo F. Padovan }
57370a708f8fSGustavo F. Padovan
l2cap_rx_queued_iframes(struct l2cap_chan * chan)5738d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan)
5739d2a7ac5dSMat Martineau {
574063838725SMat Martineau int err = 0;
574163838725SMat Martineau /* Pass sequential frames to l2cap_reassemble_sdu()
574263838725SMat Martineau * until a gap is encountered.
574363838725SMat Martineau */
574463838725SMat Martineau
574563838725SMat Martineau BT_DBG("chan %p", chan);
574663838725SMat Martineau
574763838725SMat Martineau while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
574863838725SMat Martineau struct sk_buff *skb;
574963838725SMat Martineau BT_DBG("Searching for skb with txseq %d (queue len %d)",
575063838725SMat Martineau chan->buffer_seq, skb_queue_len(&chan->srej_q));
575163838725SMat Martineau
575263838725SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq);
575363838725SMat Martineau
575463838725SMat Martineau if (!skb)
575563838725SMat Martineau break;
575663838725SMat Martineau
575763838725SMat Martineau skb_unlink(skb, &chan->srej_q);
575863838725SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
5759a4368ff3SJohan Hedberg err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->l2cap);
576063838725SMat Martineau if (err)
576163838725SMat Martineau break;
576263838725SMat Martineau }
576363838725SMat Martineau
576463838725SMat Martineau if (skb_queue_empty(&chan->srej_q)) {
576563838725SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV;
576663838725SMat Martineau l2cap_send_ack(chan);
576763838725SMat Martineau }
576863838725SMat Martineau
576963838725SMat Martineau return err;
5770d2a7ac5dSMat Martineau }
5771d2a7ac5dSMat Martineau
l2cap_handle_srej(struct l2cap_chan * chan,struct l2cap_ctrl * control)5772d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan,
5773d2a7ac5dSMat Martineau struct l2cap_ctrl *control)
5774d2a7ac5dSMat Martineau {
5775f80842a8SMat Martineau struct sk_buff *skb;
5776f80842a8SMat Martineau
5777f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control);
5778f80842a8SMat Martineau
5779f80842a8SMat Martineau if (control->reqseq == chan->next_tx_seq) {
5780f80842a8SMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
57815e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
5782f80842a8SMat Martineau return;
5783f80842a8SMat Martineau }
5784f80842a8SMat Martineau
5785f80842a8SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
5786f80842a8SMat Martineau
5787f80842a8SMat Martineau if (skb == NULL) {
5788f80842a8SMat Martineau BT_DBG("Seq %d not available for retransmission",
5789f80842a8SMat Martineau control->reqseq);
5790f80842a8SMat Martineau return;
5791f80842a8SMat Martineau }
5792f80842a8SMat Martineau
5793a4368ff3SJohan Hedberg if (chan->max_tx != 0 && bt_cb(skb)->l2cap.retries >= chan->max_tx) {
5794f80842a8SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
57955e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
5796f80842a8SMat Martineau return;
5797f80842a8SMat Martineau }
5798f80842a8SMat Martineau
5799f80842a8SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
5800f80842a8SMat Martineau
5801f80842a8SMat Martineau if (control->poll) {
5802f80842a8SMat Martineau l2cap_pass_to_tx(chan, control);
5803f80842a8SMat Martineau
5804f80842a8SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state);
5805f80842a8SMat Martineau l2cap_retransmit(chan, control);
5806f80842a8SMat Martineau l2cap_ertm_send(chan);
5807f80842a8SMat Martineau
5808f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
5809f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state);
5810f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq;
5811f80842a8SMat Martineau }
5812f80842a8SMat Martineau } else {
5813f80842a8SMat Martineau l2cap_pass_to_tx_fbit(chan, control);
5814f80842a8SMat Martineau
5815f80842a8SMat Martineau if (control->final) {
5816f80842a8SMat Martineau if (chan->srej_save_reqseq != control->reqseq ||
5817f80842a8SMat Martineau !test_and_clear_bit(CONN_SREJ_ACT,
5818f80842a8SMat Martineau &chan->conn_state))
5819f80842a8SMat Martineau l2cap_retransmit(chan, control);
5820f80842a8SMat Martineau } else {
5821f80842a8SMat Martineau l2cap_retransmit(chan, control);
5822f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
5823f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state);
5824f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq;
5825f80842a8SMat Martineau }
5826f80842a8SMat Martineau }
5827f80842a8SMat Martineau }
5828d2a7ac5dSMat Martineau }
5829d2a7ac5dSMat Martineau
l2cap_handle_rej(struct l2cap_chan * chan,struct l2cap_ctrl * control)5830d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan,
5831d2a7ac5dSMat Martineau struct l2cap_ctrl *control)
5832d2a7ac5dSMat Martineau {
5833fcd289dfSMat Martineau struct sk_buff *skb;
5834fcd289dfSMat Martineau
5835fcd289dfSMat Martineau BT_DBG("chan %p, control %p", chan, control);
5836fcd289dfSMat Martineau
5837fcd289dfSMat Martineau if (control->reqseq == chan->next_tx_seq) {
5838fcd289dfSMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
58395e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
5840fcd289dfSMat Martineau return;
5841fcd289dfSMat Martineau }
5842fcd289dfSMat Martineau
5843fcd289dfSMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
5844fcd289dfSMat Martineau
5845fcd289dfSMat Martineau if (chan->max_tx && skb &&
5846a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries >= chan->max_tx) {
5847fcd289dfSMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
58485e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
5849fcd289dfSMat Martineau return;
5850fcd289dfSMat Martineau }
5851fcd289dfSMat Martineau
5852fcd289dfSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
5853fcd289dfSMat Martineau
5854fcd289dfSMat Martineau l2cap_pass_to_tx(chan, control);
5855fcd289dfSMat Martineau
5856fcd289dfSMat Martineau if (control->final) {
5857fcd289dfSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
5858fcd289dfSMat Martineau l2cap_retransmit_all(chan, control);
5859fcd289dfSMat Martineau } else {
5860fcd289dfSMat Martineau l2cap_retransmit_all(chan, control);
5861fcd289dfSMat Martineau l2cap_ertm_send(chan);
5862fcd289dfSMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F)
5863fcd289dfSMat Martineau set_bit(CONN_REJ_ACT, &chan->conn_state);
5864fcd289dfSMat Martineau }
5865d2a7ac5dSMat Martineau }
5866d2a7ac5dSMat Martineau
l2cap_classify_txseq(struct l2cap_chan * chan,u16 txseq)58674b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
58684b51dae9SMat Martineau {
58694b51dae9SMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq);
58704b51dae9SMat Martineau
58714b51dae9SMat Martineau BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq,
58724b51dae9SMat Martineau chan->expected_tx_seq);
58734b51dae9SMat Martineau
58744b51dae9SMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
58754b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
58764b51dae9SMat Martineau chan->tx_win) {
58774b51dae9SMat Martineau /* See notes below regarding "double poll" and
58784b51dae9SMat Martineau * invalid packets.
58794b51dae9SMat Martineau */
58804b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
58814b51dae9SMat Martineau BT_DBG("Invalid/Ignore - after SREJ");
58824b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE;
58834b51dae9SMat Martineau } else {
58844b51dae9SMat Martineau BT_DBG("Invalid - in window after SREJ sent");
58854b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID;
58864b51dae9SMat Martineau }
58874b51dae9SMat Martineau }
58884b51dae9SMat Martineau
58894b51dae9SMat Martineau if (chan->srej_list.head == txseq) {
58904b51dae9SMat Martineau BT_DBG("Expected SREJ");
58914b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED_SREJ;
58924b51dae9SMat Martineau }
58934b51dae9SMat Martineau
58944b51dae9SMat Martineau if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) {
58954b51dae9SMat Martineau BT_DBG("Duplicate SREJ - txseq already stored");
58964b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE_SREJ;
58974b51dae9SMat Martineau }
58984b51dae9SMat Martineau
58994b51dae9SMat Martineau if (l2cap_seq_list_contains(&chan->srej_list, txseq)) {
59004b51dae9SMat Martineau BT_DBG("Unexpected SREJ - not requested");
59014b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED_SREJ;
59024b51dae9SMat Martineau }
59034b51dae9SMat Martineau }
59044b51dae9SMat Martineau
59054b51dae9SMat Martineau if (chan->expected_tx_seq == txseq) {
59064b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
59074b51dae9SMat Martineau chan->tx_win) {
59084b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window");
59094b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID;
59104b51dae9SMat Martineau } else {
59114b51dae9SMat Martineau BT_DBG("Expected");
59124b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED;
59134b51dae9SMat Martineau }
59144b51dae9SMat Martineau }
59154b51dae9SMat Martineau
59164b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) <
59172d792818SGustavo Padovan __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) {
59184b51dae9SMat Martineau BT_DBG("Duplicate - expected_tx_seq later than txseq");
59194b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE;
59204b51dae9SMat Martineau }
59214b51dae9SMat Martineau
59224b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) {
59234b51dae9SMat Martineau /* A source of invalid packets is a "double poll" condition,
59244b51dae9SMat Martineau * where delays cause us to send multiple poll packets. If
59254b51dae9SMat Martineau * the remote stack receives and processes both polls,
59264b51dae9SMat Martineau * sequence numbers can wrap around in such a way that a
59274b51dae9SMat Martineau * resent frame has a sequence number that looks like new data
59284b51dae9SMat Martineau * with a sequence gap. This would trigger an erroneous SREJ
59294b51dae9SMat Martineau * request.
59304b51dae9SMat Martineau *
59314b51dae9SMat Martineau * Fortunately, this is impossible with a tx window that's
59324b51dae9SMat Martineau * less than half of the maximum sequence number, which allows
59334b51dae9SMat Martineau * invalid frames to be safely ignored.
59344b51dae9SMat Martineau *
59354b51dae9SMat Martineau * With tx window sizes greater than half of the tx window
59364b51dae9SMat Martineau * maximum, the frame is invalid and cannot be ignored. This
59374b51dae9SMat Martineau * causes a disconnect.
59384b51dae9SMat Martineau */
59394b51dae9SMat Martineau
59404b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
59414b51dae9SMat Martineau BT_DBG("Invalid/Ignore - txseq outside tx window");
59424b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE;
59434b51dae9SMat Martineau } else {
59444b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window");
59454b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID;
59464b51dae9SMat Martineau }
59474b51dae9SMat Martineau } else {
59484b51dae9SMat Martineau BT_DBG("Unexpected - txseq indicates missing frames");
59494b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED;
59504b51dae9SMat Martineau }
59514b51dae9SMat Martineau }
59524b51dae9SMat Martineau
l2cap_rx_state_recv(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff * skb,u8 event)5953d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan,
5954d2a7ac5dSMat Martineau struct l2cap_ctrl *control,
5955d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event)
5956d2a7ac5dSMat Martineau {
59573aff8aacSMaxim Mikityanskiy struct l2cap_ctrl local_control;
5958d2a7ac5dSMat Martineau int err = 0;
5959941247f9SPeter Senna Tschudin bool skb_in_use = false;
5960d2a7ac5dSMat Martineau
5961d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
5962d2a7ac5dSMat Martineau event);
5963d2a7ac5dSMat Martineau
5964d2a7ac5dSMat Martineau switch (event) {
5965d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME:
5966d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, control->txseq)) {
5967d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED:
5968d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
5969d2a7ac5dSMat Martineau
5970d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
5971d2a7ac5dSMat Martineau BT_DBG("Busy, discarding expected seq %d",
5972d2a7ac5dSMat Martineau control->txseq);
5973d2a7ac5dSMat Martineau break;
5974d2a7ac5dSMat Martineau }
5975d2a7ac5dSMat Martineau
5976d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan,
5977d2a7ac5dSMat Martineau control->txseq);
5978d2a7ac5dSMat Martineau
5979d2a7ac5dSMat Martineau chan->buffer_seq = chan->expected_tx_seq;
5980941247f9SPeter Senna Tschudin skb_in_use = true;
5981d2a7ac5dSMat Martineau
59823aff8aacSMaxim Mikityanskiy /* l2cap_reassemble_sdu may free skb, hence invalidate
59833aff8aacSMaxim Mikityanskiy * control, so make a copy in advance to use it after
59843aff8aacSMaxim Mikityanskiy * l2cap_reassemble_sdu returns and to avoid the race
59853aff8aacSMaxim Mikityanskiy * condition, for example:
59863aff8aacSMaxim Mikityanskiy *
59873aff8aacSMaxim Mikityanskiy * The current thread calls:
59883aff8aacSMaxim Mikityanskiy * l2cap_reassemble_sdu
59893aff8aacSMaxim Mikityanskiy * chan->ops->recv == l2cap_sock_recv_cb
59903aff8aacSMaxim Mikityanskiy * __sock_queue_rcv_skb
59913aff8aacSMaxim Mikityanskiy * Another thread calls:
59923aff8aacSMaxim Mikityanskiy * bt_sock_recvmsg
59933aff8aacSMaxim Mikityanskiy * skb_recv_datagram
59943aff8aacSMaxim Mikityanskiy * skb_free_datagram
59953aff8aacSMaxim Mikityanskiy * Then the current thread tries to access control, but
59963aff8aacSMaxim Mikityanskiy * it was freed by skb_free_datagram.
59973aff8aacSMaxim Mikityanskiy */
59983aff8aacSMaxim Mikityanskiy local_control = *control;
5999d2a7ac5dSMat Martineau err = l2cap_reassemble_sdu(chan, skb, control);
6000d2a7ac5dSMat Martineau if (err)
6001d2a7ac5dSMat Martineau break;
6002d2a7ac5dSMat Martineau
60033aff8aacSMaxim Mikityanskiy if (local_control.final) {
6004d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT,
6005d2a7ac5dSMat Martineau &chan->conn_state)) {
60063aff8aacSMaxim Mikityanskiy local_control.final = 0;
60073aff8aacSMaxim Mikityanskiy l2cap_retransmit_all(chan, &local_control);
6008d2a7ac5dSMat Martineau l2cap_ertm_send(chan);
6009d2a7ac5dSMat Martineau }
6010d2a7ac5dSMat Martineau }
6011d2a7ac5dSMat Martineau
6012d2a7ac5dSMat Martineau if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
6013d2a7ac5dSMat Martineau l2cap_send_ack(chan);
6014d2a7ac5dSMat Martineau break;
6015d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED:
6016d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
6017d2a7ac5dSMat Martineau
6018d2a7ac5dSMat Martineau /* Can't issue SREJ frames in the local busy state.
6019d2a7ac5dSMat Martineau * Drop this frame, it will be seen as missing
6020d2a7ac5dSMat Martineau * when local busy is exited.
6021d2a7ac5dSMat Martineau */
6022d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6023d2a7ac5dSMat Martineau BT_DBG("Busy, discarding unexpected seq %d",
6024d2a7ac5dSMat Martineau control->txseq);
6025d2a7ac5dSMat Martineau break;
6026d2a7ac5dSMat Martineau }
6027d2a7ac5dSMat Martineau
6028d2a7ac5dSMat Martineau /* There was a gap in the sequence, so an SREJ
6029d2a7ac5dSMat Martineau * must be sent for each missing frame. The
6030d2a7ac5dSMat Martineau * current frame is stored for later use.
6031d2a7ac5dSMat Martineau */
6032d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb);
6033941247f9SPeter Senna Tschudin skb_in_use = true;
6034d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb,
6035d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q));
6036d2a7ac5dSMat Martineau
6037d2a7ac5dSMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state);
6038d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->srej_list);
6039d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq);
6040d2a7ac5dSMat Martineau
6041d2a7ac5dSMat Martineau chan->rx_state = L2CAP_RX_STATE_SREJ_SENT;
6042d2a7ac5dSMat Martineau break;
6043d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE:
6044d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
6045d2a7ac5dSMat Martineau break;
6046d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE:
6047d2a7ac5dSMat Martineau break;
6048d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID:
6049d2a7ac5dSMat Martineau default:
60505e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
6051d2a7ac5dSMat Martineau break;
6052d2a7ac5dSMat Martineau }
6053d2a7ac5dSMat Martineau break;
6054d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR:
6055d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
6056d2a7ac5dSMat Martineau if (control->final) {
6057d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6058d2a7ac5dSMat Martineau
6059cd5d26a9SLuiz Augusto von Dentz if (!test_and_clear_bit(CONN_REJ_ACT,
6060cd5d26a9SLuiz Augusto von Dentz &chan->conn_state)) {
6061d2a7ac5dSMat Martineau control->final = 0;
6062d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control);
6063d2a7ac5dSMat Martineau }
6064d2a7ac5dSMat Martineau
6065d2a7ac5dSMat Martineau l2cap_ertm_send(chan);
6066d2a7ac5dSMat Martineau } else if (control->poll) {
6067d2a7ac5dSMat Martineau l2cap_send_i_or_rr_or_rnr(chan);
6068d2a7ac5dSMat Martineau } else {
6069d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY,
6070d2a7ac5dSMat Martineau &chan->conn_state) &&
6071d2a7ac5dSMat Martineau chan->unacked_frames)
6072d2a7ac5dSMat Martineau __set_retrans_timer(chan);
6073d2a7ac5dSMat Martineau
6074d2a7ac5dSMat Martineau l2cap_ertm_send(chan);
6075d2a7ac5dSMat Martineau }
6076d2a7ac5dSMat Martineau break;
6077d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR:
6078d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6079d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
6080d2a7ac5dSMat Martineau if (control && control->poll) {
6081d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state);
6082d2a7ac5dSMat Martineau l2cap_send_rr_or_rnr(chan, 0);
6083d2a7ac5dSMat Martineau }
6084d2a7ac5dSMat Martineau __clear_retrans_timer(chan);
6085d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->retrans_list);
6086d2a7ac5dSMat Martineau break;
6087d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ:
6088d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control);
6089d2a7ac5dSMat Martineau break;
6090d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ:
6091d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control);
6092d2a7ac5dSMat Martineau break;
6093d2a7ac5dSMat Martineau default:
6094d2a7ac5dSMat Martineau break;
6095d2a7ac5dSMat Martineau }
6096d2a7ac5dSMat Martineau
6097d2a7ac5dSMat Martineau if (skb && !skb_in_use) {
6098d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb);
6099d2a7ac5dSMat Martineau kfree_skb(skb);
6100d2a7ac5dSMat Martineau }
6101d2a7ac5dSMat Martineau
6102d2a7ac5dSMat Martineau return err;
6103d2a7ac5dSMat Martineau }
6104d2a7ac5dSMat Martineau
l2cap_rx_state_srej_sent(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff * skb,u8 event)6105d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
6106d2a7ac5dSMat Martineau struct l2cap_ctrl *control,
6107d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event)
6108d2a7ac5dSMat Martineau {
6109d2a7ac5dSMat Martineau int err = 0;
6110d2a7ac5dSMat Martineau u16 txseq = control->txseq;
6111941247f9SPeter Senna Tschudin bool skb_in_use = false;
6112d2a7ac5dSMat Martineau
6113d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
6114d2a7ac5dSMat Martineau event);
6115d2a7ac5dSMat Martineau
6116d2a7ac5dSMat Martineau switch (event) {
6117d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME:
6118d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, txseq)) {
6119d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED:
6120d2a7ac5dSMat Martineau /* Keep frame for reassembly later */
6121d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
6122d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb);
6123941247f9SPeter Senna Tschudin skb_in_use = true;
6124d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb,
6125d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q));
6126d2a7ac5dSMat Martineau
6127d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq);
6128d2a7ac5dSMat Martineau break;
6129d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED_SREJ:
6130d2a7ac5dSMat Martineau l2cap_seq_list_pop(&chan->srej_list);
6131d2a7ac5dSMat Martineau
6132d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
6133d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb);
6134941247f9SPeter Senna Tschudin skb_in_use = true;
6135d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb,
6136d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q));
6137d2a7ac5dSMat Martineau
6138d2a7ac5dSMat Martineau err = l2cap_rx_queued_iframes(chan);
6139d2a7ac5dSMat Martineau if (err)
6140d2a7ac5dSMat Martineau break;
6141d2a7ac5dSMat Martineau
6142d2a7ac5dSMat Martineau break;
6143d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED:
6144d2a7ac5dSMat Martineau /* Got a frame that can't be reassembled yet.
6145d2a7ac5dSMat Martineau * Save it for later, and send SREJs to cover
6146d2a7ac5dSMat Martineau * the missing frames.
6147d2a7ac5dSMat Martineau */
6148d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb);
6149941247f9SPeter Senna Tschudin skb_in_use = true;
6150d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb,
6151d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q));
6152d2a7ac5dSMat Martineau
6153d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
6154d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq);
6155d2a7ac5dSMat Martineau break;
6156d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED_SREJ:
6157d2a7ac5dSMat Martineau /* This frame was requested with an SREJ, but
6158d2a7ac5dSMat Martineau * some expected retransmitted frames are
6159d2a7ac5dSMat Martineau * missing. Request retransmission of missing
6160d2a7ac5dSMat Martineau * SREJ'd frames.
6161d2a7ac5dSMat Martineau */
6162d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb);
6163941247f9SPeter Senna Tschudin skb_in_use = true;
6164d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb,
6165d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q));
6166d2a7ac5dSMat Martineau
6167d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
6168d2a7ac5dSMat Martineau l2cap_send_srej_list(chan, control->txseq);
6169d2a7ac5dSMat Martineau break;
6170d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE_SREJ:
6171d2a7ac5dSMat Martineau /* We've already queued this frame. Drop this copy. */
6172d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
6173d2a7ac5dSMat Martineau break;
6174d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE:
6175d2a7ac5dSMat Martineau /* Expecting a later sequence number, so this frame
6176d2a7ac5dSMat Martineau * was already received. Ignore it completely.
6177d2a7ac5dSMat Martineau */
6178d2a7ac5dSMat Martineau break;
6179d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE:
6180d2a7ac5dSMat Martineau break;
6181d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID:
6182d2a7ac5dSMat Martineau default:
61835e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
6184d2a7ac5dSMat Martineau break;
6185d2a7ac5dSMat Martineau }
6186d2a7ac5dSMat Martineau break;
6187d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR:
6188d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
6189d2a7ac5dSMat Martineau if (control->final) {
6190d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6191d2a7ac5dSMat Martineau
6192d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT,
6193d2a7ac5dSMat Martineau &chan->conn_state)) {
6194d2a7ac5dSMat Martineau control->final = 0;
6195d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control);
6196d2a7ac5dSMat Martineau }
6197d2a7ac5dSMat Martineau
6198d2a7ac5dSMat Martineau l2cap_ertm_send(chan);
6199d2a7ac5dSMat Martineau } else if (control->poll) {
6200d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY,
6201d2a7ac5dSMat Martineau &chan->conn_state) &&
6202d2a7ac5dSMat Martineau chan->unacked_frames) {
6203d2a7ac5dSMat Martineau __set_retrans_timer(chan);
6204d2a7ac5dSMat Martineau }
6205d2a7ac5dSMat Martineau
6206d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state);
6207d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan);
6208d2a7ac5dSMat Martineau } else {
6209d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY,
6210d2a7ac5dSMat Martineau &chan->conn_state) &&
6211d2a7ac5dSMat Martineau chan->unacked_frames)
6212d2a7ac5dSMat Martineau __set_retrans_timer(chan);
6213d2a7ac5dSMat Martineau
6214d2a7ac5dSMat Martineau l2cap_send_ack(chan);
6215d2a7ac5dSMat Martineau }
6216d2a7ac5dSMat Martineau break;
6217d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR:
6218d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6219d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control);
6220d2a7ac5dSMat Martineau if (control->poll) {
6221d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan);
6222d2a7ac5dSMat Martineau } else {
6223d2a7ac5dSMat Martineau struct l2cap_ctrl rr_control;
6224d2a7ac5dSMat Martineau memset(&rr_control, 0, sizeof(rr_control));
6225d2a7ac5dSMat Martineau rr_control.sframe = 1;
6226d2a7ac5dSMat Martineau rr_control.super = L2CAP_SUPER_RR;
6227d2a7ac5dSMat Martineau rr_control.reqseq = chan->buffer_seq;
6228d2a7ac5dSMat Martineau l2cap_send_sframe(chan, &rr_control);
6229d2a7ac5dSMat Martineau }
6230d2a7ac5dSMat Martineau
6231d2a7ac5dSMat Martineau break;
6232d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ:
6233d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control);
6234d2a7ac5dSMat Martineau break;
6235d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ:
6236d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control);
6237d2a7ac5dSMat Martineau break;
6238d2a7ac5dSMat Martineau }
6239d2a7ac5dSMat Martineau
6240d2a7ac5dSMat Martineau if (skb && !skb_in_use) {
6241d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb);
6242d2a7ac5dSMat Martineau kfree_skb(skb);
6243d2a7ac5dSMat Martineau }
6244d2a7ac5dSMat Martineau
6245d2a7ac5dSMat Martineau return err;
6246d2a7ac5dSMat Martineau }
6247d2a7ac5dSMat Martineau
l2cap_finish_move(struct l2cap_chan * chan)624832b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan)
624932b32735SMat Martineau {
625032b32735SMat Martineau BT_DBG("chan %p", chan);
625132b32735SMat Martineau
625232b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV;
6253ad3f7986SSungwoo Kim chan->conn->mtu = chan->conn->hcon->mtu;
625432b32735SMat Martineau
625532b32735SMat Martineau return l2cap_resegment(chan);
625632b32735SMat Martineau }
625732b32735SMat Martineau
l2cap_rx_state_wait_p(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff * skb,u8 event)625832b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan,
625932b32735SMat Martineau struct l2cap_ctrl *control,
626032b32735SMat Martineau struct sk_buff *skb, u8 event)
626132b32735SMat Martineau {
626232b32735SMat Martineau int err;
626332b32735SMat Martineau
626432b32735SMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
626532b32735SMat Martineau event);
626632b32735SMat Martineau
626732b32735SMat Martineau if (!control->poll)
626832b32735SMat Martineau return -EPROTO;
626932b32735SMat Martineau
627032b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq);
627132b32735SMat Martineau
627232b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q))
627332b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q);
627432b32735SMat Martineau else
627532b32735SMat Martineau chan->tx_send_head = NULL;
627632b32735SMat Martineau
627732b32735SMat Martineau /* Rewind next_tx_seq to the point expected
627832b32735SMat Martineau * by the receiver.
627932b32735SMat Martineau */
628032b32735SMat Martineau chan->next_tx_seq = control->reqseq;
628132b32735SMat Martineau chan->unacked_frames = 0;
628232b32735SMat Martineau
628332b32735SMat Martineau err = l2cap_finish_move(chan);
628432b32735SMat Martineau if (err)
628532b32735SMat Martineau return err;
628632b32735SMat Martineau
628732b32735SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state);
628832b32735SMat Martineau l2cap_send_i_or_rr_or_rnr(chan);
628932b32735SMat Martineau
629032b32735SMat Martineau if (event == L2CAP_EV_RECV_IFRAME)
629132b32735SMat Martineau return -EPROTO;
629232b32735SMat Martineau
629332b32735SMat Martineau return l2cap_rx_state_recv(chan, control, NULL, event);
629432b32735SMat Martineau }
629532b32735SMat Martineau
l2cap_rx_state_wait_f(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff * skb,u8 event)629632b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan,
629732b32735SMat Martineau struct l2cap_ctrl *control,
629832b32735SMat Martineau struct sk_buff *skb, u8 event)
629932b32735SMat Martineau {
630032b32735SMat Martineau int err;
630132b32735SMat Martineau
630232b32735SMat Martineau if (!control->final)
630332b32735SMat Martineau return -EPROTO;
630432b32735SMat Martineau
630532b32735SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
630632b32735SMat Martineau
630732b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV;
630832b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq);
630932b32735SMat Martineau
631032b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q))
631132b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q);
631232b32735SMat Martineau else
631332b32735SMat Martineau chan->tx_send_head = NULL;
631432b32735SMat Martineau
631532b32735SMat Martineau /* Rewind next_tx_seq to the point expected
631632b32735SMat Martineau * by the receiver.
631732b32735SMat Martineau */
631832b32735SMat Martineau chan->next_tx_seq = control->reqseq;
631932b32735SMat Martineau chan->unacked_frames = 0;
6320ad3f7986SSungwoo Kim chan->conn->mtu = chan->conn->hcon->mtu;
632132b32735SMat Martineau
632232b32735SMat Martineau err = l2cap_resegment(chan);
632332b32735SMat Martineau
632432b32735SMat Martineau if (!err)
632532b32735SMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event);
632632b32735SMat Martineau
632732b32735SMat Martineau return err;
632832b32735SMat Martineau }
632932b32735SMat Martineau
__valid_reqseq(struct l2cap_chan * chan,u16 reqseq)6330d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
6331d2a7ac5dSMat Martineau {
6332d2a7ac5dSMat Martineau /* Make sure reqseq is for a packet that has been sent but not acked */
6333d2a7ac5dSMat Martineau u16 unacked;
6334d2a7ac5dSMat Martineau
6335d2a7ac5dSMat Martineau unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq);
6336d2a7ac5dSMat Martineau return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked;
6337d2a7ac5dSMat Martineau }
6338d2a7ac5dSMat Martineau
l2cap_rx(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff * skb,u8 event)6339cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
6340cec8ab6eSMat Martineau struct sk_buff *skb, u8 event)
63410a708f8fSGustavo F. Padovan {
6342d2a7ac5dSMat Martineau int err = 0;
6343d2a7ac5dSMat Martineau
6344d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan,
6345d2a7ac5dSMat Martineau control, skb, event, chan->rx_state);
6346d2a7ac5dSMat Martineau
6347d2a7ac5dSMat Martineau if (__valid_reqseq(chan, control->reqseq)) {
6348d2a7ac5dSMat Martineau switch (chan->rx_state) {
6349d2a7ac5dSMat Martineau case L2CAP_RX_STATE_RECV:
6350d2a7ac5dSMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event);
6351d2a7ac5dSMat Martineau break;
6352d2a7ac5dSMat Martineau case L2CAP_RX_STATE_SREJ_SENT:
6353d2a7ac5dSMat Martineau err = l2cap_rx_state_srej_sent(chan, control, skb,
6354d2a7ac5dSMat Martineau event);
6355d2a7ac5dSMat Martineau break;
635632b32735SMat Martineau case L2CAP_RX_STATE_WAIT_P:
635732b32735SMat Martineau err = l2cap_rx_state_wait_p(chan, control, skb, event);
635832b32735SMat Martineau break;
635932b32735SMat Martineau case L2CAP_RX_STATE_WAIT_F:
636032b32735SMat Martineau err = l2cap_rx_state_wait_f(chan, control, skb, event);
636132b32735SMat Martineau break;
6362d2a7ac5dSMat Martineau default:
6363d2a7ac5dSMat Martineau /* shut it down */
6364d2a7ac5dSMat Martineau break;
6365d2a7ac5dSMat Martineau }
6366d2a7ac5dSMat Martineau } else {
6367d2a7ac5dSMat Martineau BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d",
6368d2a7ac5dSMat Martineau control->reqseq, chan->next_tx_seq,
6369d2a7ac5dSMat Martineau chan->expected_ack_seq);
63705e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
6371d2a7ac5dSMat Martineau }
6372d2a7ac5dSMat Martineau
6373d2a7ac5dSMat Martineau return err;
6374cec8ab6eSMat Martineau }
6375cec8ab6eSMat Martineau
l2cap_stream_rx(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff * skb)6376cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
6377cec8ab6eSMat Martineau struct sk_buff *skb)
6378cec8ab6eSMat Martineau {
63793aff8aacSMaxim Mikityanskiy /* l2cap_reassemble_sdu may free skb, hence invalidate control, so store
63803aff8aacSMaxim Mikityanskiy * the txseq field in advance to use it after l2cap_reassemble_sdu
63813aff8aacSMaxim Mikityanskiy * returns and to avoid the race condition, for example:
63823aff8aacSMaxim Mikityanskiy *
63833aff8aacSMaxim Mikityanskiy * The current thread calls:
63843aff8aacSMaxim Mikityanskiy * l2cap_reassemble_sdu
63853aff8aacSMaxim Mikityanskiy * chan->ops->recv == l2cap_sock_recv_cb
63863aff8aacSMaxim Mikityanskiy * __sock_queue_rcv_skb
63873aff8aacSMaxim Mikityanskiy * Another thread calls:
63883aff8aacSMaxim Mikityanskiy * bt_sock_recvmsg
63893aff8aacSMaxim Mikityanskiy * skb_recv_datagram
63903aff8aacSMaxim Mikityanskiy * skb_free_datagram
63913aff8aacSMaxim Mikityanskiy * Then the current thread tries to access control, but it was freed by
63923aff8aacSMaxim Mikityanskiy * skb_free_datagram.
63933aff8aacSMaxim Mikityanskiy */
63943aff8aacSMaxim Mikityanskiy u16 txseq = control->txseq;
63953aff8aacSMaxim Mikityanskiy
63964b51dae9SMat Martineau BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
63974b51dae9SMat Martineau chan->rx_state);
63984b51dae9SMat Martineau
63993aff8aacSMaxim Mikityanskiy if (l2cap_classify_txseq(chan, txseq) == L2CAP_TXSEQ_EXPECTED) {
64004b51dae9SMat Martineau l2cap_pass_to_tx(chan, control);
64014b51dae9SMat Martineau
640293917fd2SKai Ye BT_DBG("buffer_seq %u->%u", chan->buffer_seq,
64034b51dae9SMat Martineau __next_seq(chan, chan->buffer_seq));
64044b51dae9SMat Martineau
64054b51dae9SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
64064b51dae9SMat Martineau
64074b51dae9SMat Martineau l2cap_reassemble_sdu(chan, skb, control);
64084b51dae9SMat Martineau } else {
64094b51dae9SMat Martineau if (chan->sdu) {
64104b51dae9SMat Martineau kfree_skb(chan->sdu);
64114b51dae9SMat Martineau chan->sdu = NULL;
64124b51dae9SMat Martineau }
64134b51dae9SMat Martineau chan->sdu_last_frag = NULL;
64144b51dae9SMat Martineau chan->sdu_len = 0;
64154b51dae9SMat Martineau
64164b51dae9SMat Martineau if (skb) {
64174b51dae9SMat Martineau BT_DBG("Freeing %p", skb);
64184b51dae9SMat Martineau kfree_skb(skb);
64194b51dae9SMat Martineau }
64204b51dae9SMat Martineau }
64214b51dae9SMat Martineau
64223aff8aacSMaxim Mikityanskiy chan->last_acked_seq = txseq;
64233aff8aacSMaxim Mikityanskiy chan->expected_tx_seq = __next_seq(chan, txseq);
64244b51dae9SMat Martineau
64259a544210SPrasanna Karthik return 0;
6426cec8ab6eSMat Martineau }
6427cec8ab6eSMat Martineau
l2cap_data_rcv(struct l2cap_chan * chan,struct sk_buff * skb)6428cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
6429cec8ab6eSMat Martineau {
6430a4368ff3SJohan Hedberg struct l2cap_ctrl *control = &bt_cb(skb)->l2cap;
6431cec8ab6eSMat Martineau u16 len;
6432cec8ab6eSMat Martineau u8 event;
64330a708f8fSGustavo F. Padovan
6434b76bbd66SMat Martineau __unpack_control(chan, skb);
6435b76bbd66SMat Martineau
64360a708f8fSGustavo F. Padovan len = skb->len;
64370a708f8fSGustavo F. Padovan
64380a708f8fSGustavo F. Padovan /*
64390a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here.
64400a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery
6441cec8ab6eSMat Martineau * procedures and ask for retransmission.
64420a708f8fSGustavo F. Padovan */
644347d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb))
64440a708f8fSGustavo F. Padovan goto drop;
64450a708f8fSGustavo F. Padovan
6446cec8ab6eSMat Martineau if (!control->sframe && control->sar == L2CAP_SAR_START)
644703a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE;
64480a708f8fSGustavo F. Padovan
644947d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16)
645003a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE;
64510a708f8fSGustavo F. Padovan
645247d1ec61SGustavo F. Padovan if (len > chan->mps) {
64535e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
64540a708f8fSGustavo F. Padovan goto drop;
64550a708f8fSGustavo F. Padovan }
64560a708f8fSGustavo F. Padovan
6457f1942564SLuiz Augusto von Dentz if (chan->ops->filter) {
6458f1942564SLuiz Augusto von Dentz if (chan->ops->filter(chan, skb))
6459dbb50887SDaniel Borkmann goto drop;
6460f1942564SLuiz Augusto von Dentz }
6461dbb50887SDaniel Borkmann
6462cec8ab6eSMat Martineau if (!control->sframe) {
6463cec8ab6eSMat Martineau int err;
64640a708f8fSGustavo F. Padovan
6465cec8ab6eSMat Martineau BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d",
6466cec8ab6eSMat Martineau control->sar, control->reqseq, control->final,
6467cec8ab6eSMat Martineau control->txseq);
6468836be934SAndrei Emeltchenko
6469cec8ab6eSMat Martineau /* Validate F-bit - F=0 always valid, F=1 only
6470cec8ab6eSMat Martineau * valid in TX WAIT_F
6471cec8ab6eSMat Martineau */
6472cec8ab6eSMat Martineau if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F)
64730a708f8fSGustavo F. Padovan goto drop;
64740a708f8fSGustavo F. Padovan
6475cec8ab6eSMat Martineau if (chan->mode != L2CAP_MODE_STREAMING) {
6476cec8ab6eSMat Martineau event = L2CAP_EV_RECV_IFRAME;
6477cec8ab6eSMat Martineau err = l2cap_rx(chan, control, skb, event);
64780a708f8fSGustavo F. Padovan } else {
6479cec8ab6eSMat Martineau err = l2cap_stream_rx(chan, control, skb);
6480cec8ab6eSMat Martineau }
6481cec8ab6eSMat Martineau
6482cec8ab6eSMat Martineau if (err)
64835e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
6484cec8ab6eSMat Martineau } else {
6485cec8ab6eSMat Martineau const u8 rx_func_to_event[4] = {
6486cec8ab6eSMat Martineau L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
6487cec8ab6eSMat Martineau L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ
6488cec8ab6eSMat Martineau };
6489cec8ab6eSMat Martineau
6490cec8ab6eSMat Martineau /* Only I-frames are expected in streaming mode */
6491cec8ab6eSMat Martineau if (chan->mode == L2CAP_MODE_STREAMING)
6492cec8ab6eSMat Martineau goto drop;
6493cec8ab6eSMat Martineau
6494cec8ab6eSMat Martineau BT_DBG("sframe reqseq %d, final %d, poll %d, super %d",
6495cec8ab6eSMat Martineau control->reqseq, control->final, control->poll,
6496cec8ab6eSMat Martineau control->super);
6497cec8ab6eSMat Martineau
64980a708f8fSGustavo F. Padovan if (len != 0) {
64991bb166e6SAndrei Emeltchenko BT_ERR("Trailing bytes: %d in sframe", len);
65005e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
65010a708f8fSGustavo F. Padovan goto drop;
65020a708f8fSGustavo F. Padovan }
65030a708f8fSGustavo F. Padovan
6504cec8ab6eSMat Martineau /* Validate F and P bits */
6505cec8ab6eSMat Martineau if (control->final && (control->poll ||
6506cec8ab6eSMat Martineau chan->tx_state != L2CAP_TX_STATE_WAIT_F))
6507cec8ab6eSMat Martineau goto drop;
6508cec8ab6eSMat Martineau
6509cec8ab6eSMat Martineau event = rx_func_to_event[control->super];
6510cec8ab6eSMat Martineau if (l2cap_rx(chan, control, skb, event))
65115e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET);
65120a708f8fSGustavo F. Padovan }
65130a708f8fSGustavo F. Padovan
65140a708f8fSGustavo F. Padovan return 0;
65150a708f8fSGustavo F. Padovan
65160a708f8fSGustavo F. Padovan drop:
65170a708f8fSGustavo F. Padovan kfree_skb(skb);
65180a708f8fSGustavo F. Padovan return 0;
65190a708f8fSGustavo F. Padovan }
65200a708f8fSGustavo F. Padovan
l2cap_chan_le_send_credits(struct l2cap_chan * chan)6521b1c325c2SJohan Hedberg static void l2cap_chan_le_send_credits(struct l2cap_chan *chan)
6522b1c325c2SJohan Hedberg {
6523b1c325c2SJohan Hedberg struct l2cap_conn *conn = chan->conn;
6524b1c325c2SJohan Hedberg struct l2cap_le_credits pkt;
6525e2310343SSebastian Urban u16 return_credits = l2cap_le_rx_credits(chan);
6526b1c325c2SJohan Hedberg
652715f02b91SLuiz Augusto von Dentz if (chan->rx_credits >= return_credits)
652896cd8eaaSLuiz Augusto von Dentz return;
6529b1c325c2SJohan Hedberg
653015f02b91SLuiz Augusto von Dentz return_credits -= chan->rx_credits;
653115f02b91SLuiz Augusto von Dentz
6532b1c325c2SJohan Hedberg BT_DBG("chan %p returning %u credits to sender", chan, return_credits);
6533b1c325c2SJohan Hedberg
6534b1c325c2SJohan Hedberg chan->rx_credits += return_credits;
6535b1c325c2SJohan Hedberg
6536b1c325c2SJohan Hedberg pkt.cid = cpu_to_le16(chan->scid);
6537b1c325c2SJohan Hedberg pkt.credits = cpu_to_le16(return_credits);
6538b1c325c2SJohan Hedberg
6539b1c325c2SJohan Hedberg chan->ident = l2cap_get_ident(conn);
6540b1c325c2SJohan Hedberg
6541b1c325c2SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt);
6542b1c325c2SJohan Hedberg }
6543b1c325c2SJohan Hedberg
l2cap_chan_rx_avail(struct l2cap_chan * chan,ssize_t rx_avail)6544e2310343SSebastian Urban void l2cap_chan_rx_avail(struct l2cap_chan *chan, ssize_t rx_avail)
6545e2310343SSebastian Urban {
6546e2310343SSebastian Urban if (chan->rx_avail == rx_avail)
6547e2310343SSebastian Urban return;
6548e2310343SSebastian Urban
6549e2310343SSebastian Urban BT_DBG("chan %p has %zd bytes avail for rx", chan, rx_avail);
6550e2310343SSebastian Urban
6551e2310343SSebastian Urban chan->rx_avail = rx_avail;
6552e2310343SSebastian Urban
6553e2310343SSebastian Urban if (chan->state == BT_CONNECTED)
6554e2310343SSebastian Urban l2cap_chan_le_send_credits(chan);
6555e2310343SSebastian Urban }
6556e2310343SSebastian Urban
l2cap_ecred_recv(struct l2cap_chan * chan,struct sk_buff * skb)655715f02b91SLuiz Augusto von Dentz static int l2cap_ecred_recv(struct l2cap_chan *chan, struct sk_buff *skb)
655896cd8eaaSLuiz Augusto von Dentz {
655996cd8eaaSLuiz Augusto von Dentz int err;
656096cd8eaaSLuiz Augusto von Dentz
656196cd8eaaSLuiz Augusto von Dentz BT_DBG("SDU reassemble complete: chan %p skb->len %u", chan, skb->len);
656296cd8eaaSLuiz Augusto von Dentz
656396cd8eaaSLuiz Augusto von Dentz /* Wait recv to confirm reception before updating the credits */
656496cd8eaaSLuiz Augusto von Dentz err = chan->ops->recv(chan, skb);
656596cd8eaaSLuiz Augusto von Dentz
6566e2310343SSebastian Urban if (err < 0 && chan->rx_avail != -1) {
6567e2310343SSebastian Urban BT_ERR("Queueing received LE L2CAP data failed");
6568e2310343SSebastian Urban l2cap_send_disconn_req(chan, ECONNRESET);
6569e2310343SSebastian Urban return err;
6570e2310343SSebastian Urban }
6571e2310343SSebastian Urban
657296cd8eaaSLuiz Augusto von Dentz /* Update credits whenever an SDU is received */
657396cd8eaaSLuiz Augusto von Dentz l2cap_chan_le_send_credits(chan);
657496cd8eaaSLuiz Augusto von Dentz
657596cd8eaaSLuiz Augusto von Dentz return err;
657696cd8eaaSLuiz Augusto von Dentz }
657796cd8eaaSLuiz Augusto von Dentz
l2cap_ecred_data_rcv(struct l2cap_chan * chan,struct sk_buff * skb)657815f02b91SLuiz Augusto von Dentz static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
6579fad5fc89SJohan Hedberg {
6580aac23bf6SJohan Hedberg int err;
6581fad5fc89SJohan Hedberg
6582aac23bf6SJohan Hedberg if (!chan->rx_credits) {
6583aac23bf6SJohan Hedberg BT_ERR("No credits to receive LE L2CAP data");
6584dfd9774cSJohan Hedberg l2cap_send_disconn_req(chan, ECONNRESET);
6585fad5fc89SJohan Hedberg return -ENOBUFS;
6586aac23bf6SJohan Hedberg }
6587aac23bf6SJohan Hedberg
6588aac23bf6SJohan Hedberg if (chan->imtu < skb->len) {
6589aac23bf6SJohan Hedberg BT_ERR("Too big LE L2CAP PDU");
6590aac23bf6SJohan Hedberg return -ENOBUFS;
6591aac23bf6SJohan Hedberg }
6592fad5fc89SJohan Hedberg
6593fad5fc89SJohan Hedberg chan->rx_credits--;
6594e2310343SSebastian Urban BT_DBG("chan %p: rx_credits %u -> %u",
6595e2310343SSebastian Urban chan, chan->rx_credits + 1, chan->rx_credits);
6596fad5fc89SJohan Hedberg
659796cd8eaaSLuiz Augusto von Dentz /* Update if remote had run out of credits, this should only happens
659896cd8eaaSLuiz Augusto von Dentz * if the remote is not using the entire MPS.
659996cd8eaaSLuiz Augusto von Dentz */
660096cd8eaaSLuiz Augusto von Dentz if (!chan->rx_credits)
6601fad5fc89SJohan Hedberg l2cap_chan_le_send_credits(chan);
6602fad5fc89SJohan Hedberg
6603aac23bf6SJohan Hedberg err = 0;
6604aac23bf6SJohan Hedberg
6605aac23bf6SJohan Hedberg if (!chan->sdu) {
6606aac23bf6SJohan Hedberg u16 sdu_len;
6607aac23bf6SJohan Hedberg
6608aac23bf6SJohan Hedberg sdu_len = get_unaligned_le16(skb->data);
6609aac23bf6SJohan Hedberg skb_pull(skb, L2CAP_SDULEN_SIZE);
6610aac23bf6SJohan Hedberg
6611aac23bf6SJohan Hedberg BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u",
6612aac23bf6SJohan Hedberg sdu_len, skb->len, chan->imtu);
6613aac23bf6SJohan Hedberg
6614aac23bf6SJohan Hedberg if (sdu_len > chan->imtu) {
6615aac23bf6SJohan Hedberg BT_ERR("Too big LE L2CAP SDU length received");
6616aac23bf6SJohan Hedberg err = -EMSGSIZE;
6617aac23bf6SJohan Hedberg goto failed;
6618aac23bf6SJohan Hedberg }
6619aac23bf6SJohan Hedberg
6620aac23bf6SJohan Hedberg if (skb->len > sdu_len) {
6621aac23bf6SJohan Hedberg BT_ERR("Too much LE L2CAP data received");
6622aac23bf6SJohan Hedberg err = -EINVAL;
6623aac23bf6SJohan Hedberg goto failed;
6624aac23bf6SJohan Hedberg }
6625aac23bf6SJohan Hedberg
6626aac23bf6SJohan Hedberg if (skb->len == sdu_len)
662715f02b91SLuiz Augusto von Dentz return l2cap_ecred_recv(chan, skb);
6628aac23bf6SJohan Hedberg
6629aac23bf6SJohan Hedberg chan->sdu = skb;
6630aac23bf6SJohan Hedberg chan->sdu_len = sdu_len;
6631aac23bf6SJohan Hedberg chan->sdu_last_frag = skb;
6632aac23bf6SJohan Hedberg
6633a5c3021bSLuiz Augusto von Dentz /* Detect if remote is not able to use the selected MPS */
6634a5c3021bSLuiz Augusto von Dentz if (skb->len + L2CAP_SDULEN_SIZE < chan->mps) {
6635a5c3021bSLuiz Augusto von Dentz u16 mps_len = skb->len + L2CAP_SDULEN_SIZE;
6636a5c3021bSLuiz Augusto von Dentz
6637a5c3021bSLuiz Augusto von Dentz /* Adjust the number of credits */
6638a5c3021bSLuiz Augusto von Dentz BT_DBG("chan->mps %u -> %u", chan->mps, mps_len);
6639a5c3021bSLuiz Augusto von Dentz chan->mps = mps_len;
6640a5c3021bSLuiz Augusto von Dentz l2cap_chan_le_send_credits(chan);
6641a5c3021bSLuiz Augusto von Dentz }
6642a5c3021bSLuiz Augusto von Dentz
6643aac23bf6SJohan Hedberg return 0;
6644aac23bf6SJohan Hedberg }
6645aac23bf6SJohan Hedberg
6646aac23bf6SJohan Hedberg BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u",
6647aac23bf6SJohan Hedberg chan->sdu->len, skb->len, chan->sdu_len);
6648aac23bf6SJohan Hedberg
6649aac23bf6SJohan Hedberg if (chan->sdu->len + skb->len > chan->sdu_len) {
6650aac23bf6SJohan Hedberg BT_ERR("Too much LE L2CAP data received");
6651aac23bf6SJohan Hedberg err = -EINVAL;
6652aac23bf6SJohan Hedberg goto failed;
6653aac23bf6SJohan Hedberg }
6654aac23bf6SJohan Hedberg
6655aac23bf6SJohan Hedberg append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag);
6656aac23bf6SJohan Hedberg skb = NULL;
6657aac23bf6SJohan Hedberg
6658aac23bf6SJohan Hedberg if (chan->sdu->len == chan->sdu_len) {
665915f02b91SLuiz Augusto von Dentz err = l2cap_ecred_recv(chan, chan->sdu);
6660aac23bf6SJohan Hedberg if (!err) {
6661aac23bf6SJohan Hedberg chan->sdu = NULL;
6662aac23bf6SJohan Hedberg chan->sdu_last_frag = NULL;
6663aac23bf6SJohan Hedberg chan->sdu_len = 0;
6664aac23bf6SJohan Hedberg }
6665aac23bf6SJohan Hedberg }
6666aac23bf6SJohan Hedberg
6667aac23bf6SJohan Hedberg failed:
6668aac23bf6SJohan Hedberg if (err) {
6669aac23bf6SJohan Hedberg kfree_skb(skb);
6670aac23bf6SJohan Hedberg kfree_skb(chan->sdu);
6671aac23bf6SJohan Hedberg chan->sdu = NULL;
6672aac23bf6SJohan Hedberg chan->sdu_last_frag = NULL;
6673aac23bf6SJohan Hedberg chan->sdu_len = 0;
6674aac23bf6SJohan Hedberg }
6675aac23bf6SJohan Hedberg
6676aac23bf6SJohan Hedberg /* We can't return an error here since we took care of the skb
6677aac23bf6SJohan Hedberg * freeing internally. An error return would cause the caller to
6678aac23bf6SJohan Hedberg * do a double-free of the skb.
6679aac23bf6SJohan Hedberg */
6680aac23bf6SJohan Hedberg return 0;
6681fad5fc89SJohan Hedberg }
6682fad5fc89SJohan Hedberg
l2cap_data_channel(struct l2cap_conn * conn,u16 cid,struct sk_buff * skb)668313ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
668413ca56e0SAndrei Emeltchenko struct sk_buff *skb)
66850a708f8fSGustavo F. Padovan {
668648454079SGustavo F. Padovan struct l2cap_chan *chan;
66870a708f8fSGustavo F. Padovan
6688baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid);
668948454079SGustavo F. Padovan if (!chan) {
66900a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid);
66916be36555SAndrei Emeltchenko /* Drop packet and return */
66923379013bSDan Carpenter kfree_skb(skb);
669313ca56e0SAndrei Emeltchenko return;
66940a708f8fSGustavo F. Padovan }
66950a708f8fSGustavo F. Padovan
669649208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len);
66970a708f8fSGustavo F. Padovan
6698315917e0SJohan Hedberg /* If we receive data on a fixed channel before the info req/rsp
66995153ceb9SBhaskar Chowdhury * procedure is done simply assume that the channel is supported
6700315917e0SJohan Hedberg * and mark it as ready.
6701315917e0SJohan Hedberg */
6702315917e0SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_FIXED)
6703315917e0SJohan Hedberg l2cap_chan_ready(chan);
6704315917e0SJohan Hedberg
670589bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED)
67060a708f8fSGustavo F. Padovan goto drop;
67070a708f8fSGustavo F. Padovan
67080c1bc5c6SGustavo F. Padovan switch (chan->mode) {
670938319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL:
671015f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL:
671115f02b91SLuiz Augusto von Dentz if (l2cap_ecred_data_rcv(chan, skb) < 0)
6712fad5fc89SJohan Hedberg goto drop;
6713fad5fc89SJohan Hedberg
6714fad5fc89SJohan Hedberg goto done;
6715fad5fc89SJohan Hedberg
67160a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC:
67170a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here
67180a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable.
67190a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't
67200a708f8fSGustavo F. Padovan * provide flow control mechanism. */
67210a708f8fSGustavo F. Padovan
67222c96e03dSSzymon Janc if (chan->imtu < skb->len) {
67232c96e03dSSzymon Janc BT_ERR("Dropping L2CAP data: receive buffer overflow");
67240a708f8fSGustavo F. Padovan goto drop;
67252c96e03dSSzymon Janc }
67260a708f8fSGustavo F. Padovan
672780b98027SGustavo Padovan if (!chan->ops->recv(chan, skb))
67280a708f8fSGustavo F. Padovan goto done;
67290a708f8fSGustavo F. Padovan break;
67300a708f8fSGustavo F. Padovan
67310a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM:
67320a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING:
6733cec8ab6eSMat Martineau l2cap_data_rcv(chan, skb);
67340a708f8fSGustavo F. Padovan goto done;
67350a708f8fSGustavo F. Padovan
67360a708f8fSGustavo F. Padovan default:
67370c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
67380a708f8fSGustavo F. Padovan break;
67390a708f8fSGustavo F. Padovan }
67400a708f8fSGustavo F. Padovan
67410a708f8fSGustavo F. Padovan drop:
67420a708f8fSGustavo F. Padovan kfree_skb(skb);
67430a708f8fSGustavo F. Padovan
67440a708f8fSGustavo F. Padovan done:
67456be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
6746d0be8347SLuiz Augusto von Dentz l2cap_chan_put(chan);
67470a708f8fSGustavo F. Padovan }
67480a708f8fSGustavo F. Padovan
l2cap_conless_channel(struct l2cap_conn * conn,__le16 psm,struct sk_buff * skb)674984104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
675084104b24SAndrei Emeltchenko struct sk_buff *skb)
67510a708f8fSGustavo F. Padovan {
6752ae4fd2d3SMarcel Holtmann struct hci_conn *hcon = conn->hcon;
675323691d75SGustavo F. Padovan struct l2cap_chan *chan;
67540a708f8fSGustavo F. Padovan
6755ae4fd2d3SMarcel Holtmann if (hcon->type != ACL_LINK)
6756a24cce14SJohan Hedberg goto free_skb;
6757ae4fd2d3SMarcel Holtmann
6758bf20fd4eSJohan Hedberg chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst,
6759bf20fd4eSJohan Hedberg ACL_LINK);
676023691d75SGustavo F. Padovan if (!chan)
6761a24cce14SJohan Hedberg goto free_skb;
67620a708f8fSGustavo F. Padovan
67635b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len);
67640a708f8fSGustavo F. Padovan
676589bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
67660a708f8fSGustavo F. Padovan goto drop;
67670a708f8fSGustavo F. Padovan
6768e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len)
67690a708f8fSGustavo F. Padovan goto drop;
67700a708f8fSGustavo F. Padovan
67712edf870dSMarcel Holtmann /* Store remote BD_ADDR and PSM for msg_name */
6772a4368ff3SJohan Hedberg bacpy(&bt_cb(skb)->l2cap.bdaddr, &hcon->dst);
6773a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.psm = psm;
67742edf870dSMarcel Holtmann
6775a24cce14SJohan Hedberg if (!chan->ops->recv(chan, skb)) {
6776a24cce14SJohan Hedberg l2cap_chan_put(chan);
677784104b24SAndrei Emeltchenko return;
6778a24cce14SJohan Hedberg }
67790a708f8fSGustavo F. Padovan
67800a708f8fSGustavo F. Padovan drop:
6781a24cce14SJohan Hedberg l2cap_chan_put(chan);
6782a24cce14SJohan Hedberg free_skb:
67830a708f8fSGustavo F. Padovan kfree_skb(skb);
67840a708f8fSGustavo F. Padovan }
67850a708f8fSGustavo F. Padovan
l2cap_recv_frame(struct l2cap_conn * conn,struct sk_buff * skb)67860a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
67870a708f8fSGustavo F. Padovan {
67880a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data;
678961a939c6SJohan Hedberg struct hci_conn *hcon = conn->hcon;
67900a708f8fSGustavo F. Padovan u16 cid, len;
67910a708f8fSGustavo F. Padovan __le16 psm;
67920a708f8fSGustavo F. Padovan
679361a939c6SJohan Hedberg if (hcon->state != BT_CONNECTED) {
679461a939c6SJohan Hedberg BT_DBG("queueing pending rx skb");
679561a939c6SJohan Hedberg skb_queue_tail(&conn->pending_rx, skb);
679661a939c6SJohan Hedberg return;
679761a939c6SJohan Hedberg }
679861a939c6SJohan Hedberg
67990a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE);
68000a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid);
68010a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len);
68020a708f8fSGustavo F. Padovan
68030a708f8fSGustavo F. Padovan if (len != skb->len) {
68040a708f8fSGustavo F. Padovan kfree_skb(skb);
68050a708f8fSGustavo F. Padovan return;
68060a708f8fSGustavo F. Padovan }
68070a708f8fSGustavo F. Padovan
68089e1d7e15SJohan Hedberg /* Since we can't actively block incoming LE connections we must
68099e1d7e15SJohan Hedberg * at least ensure that we ignore incoming data from them.
68109e1d7e15SJohan Hedberg */
68119e1d7e15SJohan Hedberg if (hcon->type == LE_LINK &&
68123d4f9c00SArchie Pusaka hci_bdaddr_list_lookup(&hcon->hdev->reject_list, &hcon->dst,
6813a250e048SJohan Hedberg bdaddr_dst_type(hcon))) {
6814e493150eSJohan Hedberg kfree_skb(skb);
6815e493150eSJohan Hedberg return;
6816e493150eSJohan Hedberg }
6817e493150eSJohan Hedberg
68180a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid);
68190a708f8fSGustavo F. Padovan
68200a708f8fSGustavo F. Padovan switch (cid) {
68210a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING:
68220a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb);
68230a708f8fSGustavo F. Padovan break;
68240a708f8fSGustavo F. Padovan
68250a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS:
6826097db76cSAndrei Emeltchenko psm = get_unaligned((__le16 *) skb->data);
68270181a70fSAndrei Emeltchenko skb_pull(skb, L2CAP_PSMLEN_SIZE);
68280a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb);
68290a708f8fSGustavo F. Padovan break;
68300a708f8fSGustavo F. Padovan
6831a2877629SMarcel Holtmann case L2CAP_CID_LE_SIGNALING:
6832a2877629SMarcel Holtmann l2cap_le_sig_channel(conn, skb);
6833a2877629SMarcel Holtmann break;
6834a2877629SMarcel Holtmann
68350a708f8fSGustavo F. Padovan default:
68360a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb);
68370a708f8fSGustavo F. Padovan break;
68380a708f8fSGustavo F. Padovan }
68390a708f8fSGustavo F. Padovan }
68400a708f8fSGustavo F. Padovan
process_pending_rx(struct work_struct * work)684161a939c6SJohan Hedberg static void process_pending_rx(struct work_struct *work)
684261a939c6SJohan Hedberg {
684361a939c6SJohan Hedberg struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
684461a939c6SJohan Hedberg pending_rx_work);
684561a939c6SJohan Hedberg struct sk_buff *skb;
684661a939c6SJohan Hedberg
684761a939c6SJohan Hedberg BT_DBG("");
684861a939c6SJohan Hedberg
684961a939c6SJohan Hedberg while ((skb = skb_dequeue(&conn->pending_rx)))
685061a939c6SJohan Hedberg l2cap_recv_frame(conn, skb);
685161a939c6SJohan Hedberg }
685261a939c6SJohan Hedberg
l2cap_conn_add(struct hci_conn * hcon)6853162b49e7SJohan Hedberg static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
6854162b49e7SJohan Hedberg {
6855162b49e7SJohan Hedberg struct l2cap_conn *conn = hcon->l2cap_data;
6856162b49e7SJohan Hedberg struct hci_chan *hchan;
6857162b49e7SJohan Hedberg
6858162b49e7SJohan Hedberg if (conn)
6859162b49e7SJohan Hedberg return conn;
6860162b49e7SJohan Hedberg
6861162b49e7SJohan Hedberg hchan = hci_chan_create(hcon);
6862162b49e7SJohan Hedberg if (!hchan)
6863162b49e7SJohan Hedberg return NULL;
6864162b49e7SJohan Hedberg
686527f70f3eSJohan Hedberg conn = kzalloc(sizeof(*conn), GFP_KERNEL);
6866162b49e7SJohan Hedberg if (!conn) {
6867162b49e7SJohan Hedberg hci_chan_del(hchan);
6868162b49e7SJohan Hedberg return NULL;
6869162b49e7SJohan Hedberg }
6870162b49e7SJohan Hedberg
6871162b49e7SJohan Hedberg kref_init(&conn->ref);
6872162b49e7SJohan Hedberg hcon->l2cap_data = conn;
687351bb8457SJohan Hedberg conn->hcon = hci_conn_get(hcon);
6874162b49e7SJohan Hedberg conn->hchan = hchan;
6875162b49e7SJohan Hedberg
6876162b49e7SJohan Hedberg BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
6877162b49e7SJohan Hedberg
6878ad3f7986SSungwoo Kim conn->mtu = hcon->mtu;
6879162b49e7SJohan Hedberg conn->feat_mask = 0;
6880162b49e7SJohan Hedberg
68810bd49fc7SJohan Hedberg conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS;
68820bd49fc7SJohan Hedberg
6883d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED) &&
6884f9be9e86SMarcel Holtmann (bredr_sc_enabled(hcon->hdev) ||
6885b7cb93e5SMarcel Holtmann hci_dev_test_flag(hcon->hdev, HCI_FORCE_BREDR_SMP)))
6886b5ae344dSJohan Hedberg conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR;
6887b5ae344dSJohan Hedberg
68885a54e7c8SMarcel Holtmann mutex_init(&conn->ident_lock);
6889162b49e7SJohan Hedberg mutex_init(&conn->chan_lock);
6890162b49e7SJohan Hedberg
6891162b49e7SJohan Hedberg INIT_LIST_HEAD(&conn->chan_l);
6892162b49e7SJohan Hedberg INIT_LIST_HEAD(&conn->users);
6893162b49e7SJohan Hedberg
6894162b49e7SJohan Hedberg INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
6895162b49e7SJohan Hedberg
689661a939c6SJohan Hedberg skb_queue_head_init(&conn->pending_rx);
689761a939c6SJohan Hedberg INIT_WORK(&conn->pending_rx_work, process_pending_rx);
6898b8b23001SLuiz Augusto von Dentz INIT_DELAYED_WORK(&conn->id_addr_timer, l2cap_conn_update_id_addr);
689961a939c6SJohan Hedberg
6900162b49e7SJohan Hedberg conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
6901162b49e7SJohan Hedberg
6902162b49e7SJohan Hedberg return conn;
6903162b49e7SJohan Hedberg }
6904162b49e7SJohan Hedberg
is_valid_psm(u16 psm,u8 dst_type)6905149b3f13SMeng Yu static bool is_valid_psm(u16 psm, u8 dst_type)
6906149b3f13SMeng Yu {
6907162b49e7SJohan Hedberg if (!psm)
6908162b49e7SJohan Hedberg return false;
6909162b49e7SJohan Hedberg
6910162b49e7SJohan Hedberg if (bdaddr_type_is_le(dst_type))
6911162b49e7SJohan Hedberg return (psm <= 0x00ff);
6912162b49e7SJohan Hedberg
6913162b49e7SJohan Hedberg /* PSM must be odd and lsb of upper byte must be 0 */
6914162b49e7SJohan Hedberg return ((psm & 0x0101) == 0x0001);
6915162b49e7SJohan Hedberg }
6916162b49e7SJohan Hedberg
6917da49b602SLuiz Augusto von Dentz struct l2cap_chan_data {
6918da49b602SLuiz Augusto von Dentz struct l2cap_chan *chan;
6919da49b602SLuiz Augusto von Dentz struct pid *pid;
6920da49b602SLuiz Augusto von Dentz int count;
6921da49b602SLuiz Augusto von Dentz };
6922da49b602SLuiz Augusto von Dentz
l2cap_chan_by_pid(struct l2cap_chan * chan,void * data)6923da49b602SLuiz Augusto von Dentz static void l2cap_chan_by_pid(struct l2cap_chan *chan, void *data)
6924da49b602SLuiz Augusto von Dentz {
6925da49b602SLuiz Augusto von Dentz struct l2cap_chan_data *d = data;
6926da49b602SLuiz Augusto von Dentz struct pid *pid;
6927da49b602SLuiz Augusto von Dentz
6928da49b602SLuiz Augusto von Dentz if (chan == d->chan)
6929da49b602SLuiz Augusto von Dentz return;
6930da49b602SLuiz Augusto von Dentz
6931da49b602SLuiz Augusto von Dentz if (!test_bit(FLAG_DEFER_SETUP, &chan->flags))
6932da49b602SLuiz Augusto von Dentz return;
6933da49b602SLuiz Augusto von Dentz
6934da49b602SLuiz Augusto von Dentz pid = chan->ops->get_peer_pid(chan);
6935da49b602SLuiz Augusto von Dentz
6936da49b602SLuiz Augusto von Dentz /* Only count deferred channels with the same PID/PSM */
6937da49b602SLuiz Augusto von Dentz if (d->pid != pid || chan->psm != d->chan->psm || chan->ident ||
6938da49b602SLuiz Augusto von Dentz chan->mode != L2CAP_MODE_EXT_FLOWCTL || chan->state != BT_CONNECT)
6939da49b602SLuiz Augusto von Dentz return;
6940da49b602SLuiz Augusto von Dentz
6941da49b602SLuiz Augusto von Dentz d->count++;
6942da49b602SLuiz Augusto von Dentz }
6943da49b602SLuiz Augusto von Dentz
l2cap_chan_connect(struct l2cap_chan * chan,__le16 psm,u16 cid,bdaddr_t * dst,u8 dst_type)6944162b49e7SJohan Hedberg int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
6945162b49e7SJohan Hedberg bdaddr_t *dst, u8 dst_type)
6946162b49e7SJohan Hedberg {
6947162b49e7SJohan Hedberg struct l2cap_conn *conn;
6948162b49e7SJohan Hedberg struct hci_conn *hcon;
6949162b49e7SJohan Hedberg struct hci_dev *hdev;
6950162b49e7SJohan Hedberg int err;
6951162b49e7SJohan Hedberg
695215f02b91SLuiz Augusto von Dentz BT_DBG("%pMR -> %pMR (type %u) psm 0x%4.4x mode 0x%2.2x", &chan->src,
695315f02b91SLuiz Augusto von Dentz dst, dst_type, __le16_to_cpu(psm), chan->mode);
6954162b49e7SJohan Hedberg
695539385cb5SJohan Hedberg hdev = hci_get_route(dst, &chan->src, chan->src_type);
6956162b49e7SJohan Hedberg if (!hdev)
6957162b49e7SJohan Hedberg return -EHOSTUNREACH;
6958162b49e7SJohan Hedberg
6959162b49e7SJohan Hedberg hci_dev_lock(hdev);
6960162b49e7SJohan Hedberg
6961162b49e7SJohan Hedberg if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid &&
6962162b49e7SJohan Hedberg chan->chan_type != L2CAP_CHAN_RAW) {
6963162b49e7SJohan Hedberg err = -EINVAL;
6964162b49e7SJohan Hedberg goto done;
6965162b49e7SJohan Hedberg }
6966162b49e7SJohan Hedberg
696721626e62SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !psm) {
696821626e62SJohan Hedberg err = -EINVAL;
696921626e62SJohan Hedberg goto done;
697021626e62SJohan Hedberg }
697121626e62SJohan Hedberg
697221626e62SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_FIXED && !cid) {
6973162b49e7SJohan Hedberg err = -EINVAL;
6974162b49e7SJohan Hedberg goto done;
6975162b49e7SJohan Hedberg }
6976162b49e7SJohan Hedberg
6977162b49e7SJohan Hedberg switch (chan->mode) {
6978162b49e7SJohan Hedberg case L2CAP_MODE_BASIC:
6979162b49e7SJohan Hedberg break;
6980162b49e7SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL:
69814be5ca67SLuiz Augusto von Dentz break;
698215f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL:
69834be5ca67SLuiz Augusto von Dentz if (!enable_ecred) {
69844be5ca67SLuiz Augusto von Dentz err = -EOPNOTSUPP;
69854be5ca67SLuiz Augusto von Dentz goto done;
69864be5ca67SLuiz Augusto von Dentz }
6987162b49e7SJohan Hedberg break;
6988162b49e7SJohan Hedberg case L2CAP_MODE_ERTM:
6989162b49e7SJohan Hedberg case L2CAP_MODE_STREAMING:
6990162b49e7SJohan Hedberg if (!disable_ertm)
6991162b49e7SJohan Hedberg break;
699219186c7bSGustavo A. R. Silva fallthrough;
6993162b49e7SJohan Hedberg default:
6994beb19e4cSJohan Hedberg err = -EOPNOTSUPP;
6995162b49e7SJohan Hedberg goto done;
6996162b49e7SJohan Hedberg }
6997162b49e7SJohan Hedberg
6998162b49e7SJohan Hedberg switch (chan->state) {
6999162b49e7SJohan Hedberg case BT_CONNECT:
7000162b49e7SJohan Hedberg case BT_CONNECT2:
7001162b49e7SJohan Hedberg case BT_CONFIG:
7002162b49e7SJohan Hedberg /* Already connecting */
7003162b49e7SJohan Hedberg err = 0;
7004162b49e7SJohan Hedberg goto done;
7005162b49e7SJohan Hedberg
7006162b49e7SJohan Hedberg case BT_CONNECTED:
7007162b49e7SJohan Hedberg /* Already connected */
7008162b49e7SJohan Hedberg err = -EISCONN;
7009162b49e7SJohan Hedberg goto done;
7010162b49e7SJohan Hedberg
7011162b49e7SJohan Hedberg case BT_OPEN:
7012162b49e7SJohan Hedberg case BT_BOUND:
7013162b49e7SJohan Hedberg /* Can connect */
7014162b49e7SJohan Hedberg break;
7015162b49e7SJohan Hedberg
7016162b49e7SJohan Hedberg default:
7017162b49e7SJohan Hedberg err = -EBADFD;
7018162b49e7SJohan Hedberg goto done;
7019162b49e7SJohan Hedberg }
7020162b49e7SJohan Hedberg
7021162b49e7SJohan Hedberg /* Set destination address and psm */
7022162b49e7SJohan Hedberg bacpy(&chan->dst, dst);
7023162b49e7SJohan Hedberg chan->dst_type = dst_type;
7024162b49e7SJohan Hedberg
7025162b49e7SJohan Hedberg chan->psm = psm;
7026162b49e7SJohan Hedberg chan->dcid = cid;
7027162b49e7SJohan Hedberg
70286f77d8c7SAndre Guedes if (bdaddr_type_is_le(dst_type)) {
70296f77d8c7SAndre Guedes /* Convert from L2CAP channel address type to HCI address type
70306f77d8c7SAndre Guedes */
70316f77d8c7SAndre Guedes if (dst_type == BDADDR_LE_PUBLIC)
70326f77d8c7SAndre Guedes dst_type = ADDR_LE_DEV_PUBLIC;
70336f77d8c7SAndre Guedes else
70346f77d8c7SAndre Guedes dst_type = ADDR_LE_DEV_RANDOM;
70356f77d8c7SAndre Guedes
7036d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
7037d850bf08SLuiz Augusto von Dentz hcon = hci_connect_le(hdev, dst, dst_type, false,
7038fa142220SJakub Pawlowski chan->sec_level,
7039fa142220SJakub Pawlowski HCI_LE_CONN_TIMEOUT,
70408e8b92eeSLuiz Augusto von Dentz HCI_ROLE_SLAVE);
70410ad06aa6SJohan Hedberg else
70420ad06aa6SJohan Hedberg hcon = hci_connect_le_scan(hdev, dst, dst_type,
70430ad06aa6SJohan Hedberg chan->sec_level,
704476b13996SManish Mandlik HCI_LE_CONN_TIMEOUT,
704576b13996SManish Mandlik CONN_REASON_L2CAP_CHAN);
70460ad06aa6SJohan Hedberg
70476f77d8c7SAndre Guedes } else {
7048d93375a8SJohan Hedberg u8 auth_type = l2cap_get_auth_type(chan);
704976b13996SManish Mandlik hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type,
705076b13996SManish Mandlik CONN_REASON_L2CAP_CHAN);
70516f77d8c7SAndre Guedes }
7052162b49e7SJohan Hedberg
7053162b49e7SJohan Hedberg if (IS_ERR(hcon)) {
7054162b49e7SJohan Hedberg err = PTR_ERR(hcon);
7055162b49e7SJohan Hedberg goto done;
7056162b49e7SJohan Hedberg }
7057162b49e7SJohan Hedberg
7058162b49e7SJohan Hedberg conn = l2cap_conn_add(hcon);
7059162b49e7SJohan Hedberg if (!conn) {
7060162b49e7SJohan Hedberg hci_conn_drop(hcon);
7061162b49e7SJohan Hedberg err = -ENOMEM;
7062162b49e7SJohan Hedberg goto done;
7063162b49e7SJohan Hedberg }
7064162b49e7SJohan Hedberg
7065da49b602SLuiz Augusto von Dentz if (chan->mode == L2CAP_MODE_EXT_FLOWCTL) {
7066da49b602SLuiz Augusto von Dentz struct l2cap_chan_data data;
7067da49b602SLuiz Augusto von Dentz
7068da49b602SLuiz Augusto von Dentz data.chan = chan;
7069da49b602SLuiz Augusto von Dentz data.pid = chan->ops->get_peer_pid(chan);
7070da49b602SLuiz Augusto von Dentz data.count = 1;
7071da49b602SLuiz Augusto von Dentz
7072da49b602SLuiz Augusto von Dentz l2cap_chan_list(conn, l2cap_chan_by_pid, &data);
7073da49b602SLuiz Augusto von Dentz
7074da49b602SLuiz Augusto von Dentz /* Check if there isn't too many channels being connected */
7075da49b602SLuiz Augusto von Dentz if (data.count > L2CAP_ECRED_CONN_SCID_MAX) {
7076da49b602SLuiz Augusto von Dentz hci_conn_drop(hcon);
7077da49b602SLuiz Augusto von Dentz err = -EPROTO;
7078da49b602SLuiz Augusto von Dentz goto done;
7079da49b602SLuiz Augusto von Dentz }
7080da49b602SLuiz Augusto von Dentz }
7081da49b602SLuiz Augusto von Dentz
708202e246aeSJohan Hedberg mutex_lock(&conn->chan_lock);
708302e246aeSJohan Hedberg l2cap_chan_lock(chan);
708402e246aeSJohan Hedberg
7085162b49e7SJohan Hedberg if (cid && __l2cap_get_chan_by_dcid(conn, cid)) {
7086162b49e7SJohan Hedberg hci_conn_drop(hcon);
7087162b49e7SJohan Hedberg err = -EBUSY;
708802e246aeSJohan Hedberg goto chan_unlock;
7089162b49e7SJohan Hedberg }
7090162b49e7SJohan Hedberg
7091162b49e7SJohan Hedberg /* Update source addr of the socket */
7092162b49e7SJohan Hedberg bacpy(&chan->src, &hcon->src);
7093a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(hcon);
7094162b49e7SJohan Hedberg
709502e246aeSJohan Hedberg __l2cap_chan_add(conn, chan);
7096162b49e7SJohan Hedberg
7097162b49e7SJohan Hedberg /* l2cap_chan_add takes its own ref so we can drop this one */
7098162b49e7SJohan Hedberg hci_conn_drop(hcon);
7099162b49e7SJohan Hedberg
7100162b49e7SJohan Hedberg l2cap_state_change(chan, BT_CONNECT);
7101162b49e7SJohan Hedberg __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
7102162b49e7SJohan Hedberg
710361202e4dSJohan Hedberg /* Release chan->sport so that it can be reused by other
710461202e4dSJohan Hedberg * sockets (as it's only used for listening sockets).
710561202e4dSJohan Hedberg */
710661202e4dSJohan Hedberg write_lock(&chan_list_lock);
710761202e4dSJohan Hedberg chan->sport = 0;
710861202e4dSJohan Hedberg write_unlock(&chan_list_lock);
710961202e4dSJohan Hedberg
7110162b49e7SJohan Hedberg if (hcon->state == BT_CONNECTED) {
7111162b49e7SJohan Hedberg if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
7112162b49e7SJohan Hedberg __clear_chan_timer(chan);
7113e7cafc45SJohan Hedberg if (l2cap_chan_check_security(chan, true))
7114162b49e7SJohan Hedberg l2cap_state_change(chan, BT_CONNECTED);
7115162b49e7SJohan Hedberg } else
7116162b49e7SJohan Hedberg l2cap_do_start(chan);
7117162b49e7SJohan Hedberg }
7118162b49e7SJohan Hedberg
7119162b49e7SJohan Hedberg err = 0;
7120162b49e7SJohan Hedberg
712102e246aeSJohan Hedberg chan_unlock:
7122162b49e7SJohan Hedberg l2cap_chan_unlock(chan);
712302e246aeSJohan Hedberg mutex_unlock(&conn->chan_lock);
712402e246aeSJohan Hedberg done:
7125162b49e7SJohan Hedberg hci_dev_unlock(hdev);
7126162b49e7SJohan Hedberg hci_dev_put(hdev);
7127162b49e7SJohan Hedberg return err;
7128162b49e7SJohan Hedberg }
71296b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_connect);
7130162b49e7SJohan Hedberg
l2cap_ecred_reconfigure(struct l2cap_chan * chan)713115f02b91SLuiz Augusto von Dentz static void l2cap_ecred_reconfigure(struct l2cap_chan *chan)
713215f02b91SLuiz Augusto von Dentz {
713315f02b91SLuiz Augusto von Dentz struct l2cap_conn *conn = chan->conn;
713415f02b91SLuiz Augusto von Dentz struct {
713515f02b91SLuiz Augusto von Dentz struct l2cap_ecred_reconf_req req;
713615f02b91SLuiz Augusto von Dentz __le16 scid;
713715f02b91SLuiz Augusto von Dentz } pdu;
713815f02b91SLuiz Augusto von Dentz
713915f02b91SLuiz Augusto von Dentz pdu.req.mtu = cpu_to_le16(chan->imtu);
714015f02b91SLuiz Augusto von Dentz pdu.req.mps = cpu_to_le16(chan->mps);
714115f02b91SLuiz Augusto von Dentz pdu.scid = cpu_to_le16(chan->scid);
714215f02b91SLuiz Augusto von Dentz
714315f02b91SLuiz Augusto von Dentz chan->ident = l2cap_get_ident(conn);
714415f02b91SLuiz Augusto von Dentz
714515f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_RECONF_REQ,
714615f02b91SLuiz Augusto von Dentz sizeof(pdu), &pdu);
714715f02b91SLuiz Augusto von Dentz }
714815f02b91SLuiz Augusto von Dentz
l2cap_chan_reconfigure(struct l2cap_chan * chan,__u16 mtu)714915f02b91SLuiz Augusto von Dentz int l2cap_chan_reconfigure(struct l2cap_chan *chan, __u16 mtu)
715015f02b91SLuiz Augusto von Dentz {
715115f02b91SLuiz Augusto von Dentz if (chan->imtu > mtu)
715215f02b91SLuiz Augusto von Dentz return -EINVAL;
715315f02b91SLuiz Augusto von Dentz
715415f02b91SLuiz Augusto von Dentz BT_DBG("chan %p mtu 0x%4.4x", chan, mtu);
715515f02b91SLuiz Augusto von Dentz
715615f02b91SLuiz Augusto von Dentz chan->imtu = mtu;
715715f02b91SLuiz Augusto von Dentz
715815f02b91SLuiz Augusto von Dentz l2cap_ecred_reconfigure(chan);
715915f02b91SLuiz Augusto von Dentz
716015f02b91SLuiz Augusto von Dentz return 0;
716115f02b91SLuiz Augusto von Dentz }
716215f02b91SLuiz Augusto von Dentz
71630a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
71640a708f8fSGustavo F. Padovan
l2cap_connect_ind(struct hci_dev * hdev,bdaddr_t * bdaddr)7165686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
71660a708f8fSGustavo F. Padovan {
71670a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0;
716823691d75SGustavo F. Padovan struct l2cap_chan *c;
71690a708f8fSGustavo F. Padovan
71706ed93dc6SAndrei Emeltchenko BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr);
71710a708f8fSGustavo F. Padovan
71720a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */
717323691d75SGustavo F. Padovan read_lock(&chan_list_lock);
717423691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) {
717589bc500eSGustavo F. Padovan if (c->state != BT_LISTEN)
71760a708f8fSGustavo F. Padovan continue;
71770a708f8fSGustavo F. Padovan
71787eafc59eSMarcel Holtmann if (!bacmp(&c->src, &hdev->bdaddr)) {
71790a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT;
718043bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
71810a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER;
71820a708f8fSGustavo F. Padovan exact++;
71837eafc59eSMarcel Holtmann } else if (!bacmp(&c->src, BDADDR_ANY)) {
71840a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT;
718543bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
71860a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER;
71870a708f8fSGustavo F. Padovan }
71880a708f8fSGustavo F. Padovan }
718923691d75SGustavo F. Padovan read_unlock(&chan_list_lock);
71900a708f8fSGustavo F. Padovan
71910a708f8fSGustavo F. Padovan return exact ? lm1 : lm2;
71920a708f8fSGustavo F. Padovan }
71930a708f8fSGustavo F. Padovan
7194e760ec12SJohan Hedberg /* Find the next fixed channel in BT_LISTEN state, continue iteration
7195e760ec12SJohan Hedberg * from an existing channel in the list or from the beginning of the
7196e760ec12SJohan Hedberg * global list (by passing NULL as first parameter).
7197e760ec12SJohan Hedberg */
l2cap_global_fixed_chan(struct l2cap_chan * c,struct hci_conn * hcon)7198e760ec12SJohan Hedberg static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c,
7199327a7191SJohan Hedberg struct hci_conn *hcon)
7200e760ec12SJohan Hedberg {
7201327a7191SJohan Hedberg u8 src_type = bdaddr_src_type(hcon);
7202327a7191SJohan Hedberg
7203e760ec12SJohan Hedberg read_lock(&chan_list_lock);
7204e760ec12SJohan Hedberg
7205e760ec12SJohan Hedberg if (c)
7206e760ec12SJohan Hedberg c = list_next_entry(c, global_l);
7207e760ec12SJohan Hedberg else
7208e760ec12SJohan Hedberg c = list_entry(chan_list.next, typeof(*c), global_l);
7209e760ec12SJohan Hedberg
7210e760ec12SJohan Hedberg list_for_each_entry_from(c, &chan_list, global_l) {
7211e760ec12SJohan Hedberg if (c->chan_type != L2CAP_CHAN_FIXED)
7212e760ec12SJohan Hedberg continue;
7213e760ec12SJohan Hedberg if (c->state != BT_LISTEN)
7214e760ec12SJohan Hedberg continue;
7215327a7191SJohan Hedberg if (bacmp(&c->src, &hcon->src) && bacmp(&c->src, BDADDR_ANY))
7216e760ec12SJohan Hedberg continue;
7217327a7191SJohan Hedberg if (src_type != c->src_type)
721854a1b626SJohan Hedberg continue;
7219e760ec12SJohan Hedberg
7220d0be8347SLuiz Augusto von Dentz c = l2cap_chan_hold_unless_zero(c);
7221e760ec12SJohan Hedberg read_unlock(&chan_list_lock);
7222e760ec12SJohan Hedberg return c;
7223e760ec12SJohan Hedberg }
7224e760ec12SJohan Hedberg
7225e760ec12SJohan Hedberg read_unlock(&chan_list_lock);
7226e760ec12SJohan Hedberg
7227e760ec12SJohan Hedberg return NULL;
7228e760ec12SJohan Hedberg }
7229e760ec12SJohan Hedberg
l2cap_connect_cfm(struct hci_conn * hcon,u8 status)7230539c496dSJohan Hedberg static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
72310a708f8fSGustavo F. Padovan {
7232e760ec12SJohan Hedberg struct hci_dev *hdev = hcon->hdev;
72330a708f8fSGustavo F. Padovan struct l2cap_conn *conn;
7234e760ec12SJohan Hedberg struct l2cap_chan *pchan;
7235e760ec12SJohan Hedberg u8 dst_type;
72360a708f8fSGustavo F. Padovan
7237539c496dSJohan Hedberg if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
7238539c496dSJohan Hedberg return;
7239539c496dSJohan Hedberg
72406ed93dc6SAndrei Emeltchenko BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
72410a708f8fSGustavo F. Padovan
7242dc0f5088SJohan Hedberg if (status) {
7243e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status));
7244dc0f5088SJohan Hedberg return;
7245ba6fc317SAndrei Emeltchenko }
7246dc0f5088SJohan Hedberg
7247dc0f5088SJohan Hedberg conn = l2cap_conn_add(hcon);
7248dc0f5088SJohan Hedberg if (!conn)
7249dc0f5088SJohan Hedberg return;
7250dc0f5088SJohan Hedberg
7251a250e048SJohan Hedberg dst_type = bdaddr_dst_type(hcon);
7252e760ec12SJohan Hedberg
7253e760ec12SJohan Hedberg /* If device is blocked, do not create channels for it */
72543d4f9c00SArchie Pusaka if (hci_bdaddr_list_lookup(&hdev->reject_list, &hcon->dst, dst_type))
7255e760ec12SJohan Hedberg return;
7256e760ec12SJohan Hedberg
7257e760ec12SJohan Hedberg /* Find fixed channels and notify them of the new connection. We
7258e760ec12SJohan Hedberg * use multiple individual lookups, continuing each time where
7259e760ec12SJohan Hedberg * we left off, because the list lock would prevent calling the
7260e760ec12SJohan Hedberg * potentially sleeping l2cap_chan_lock() function.
7261e760ec12SJohan Hedberg */
7262327a7191SJohan Hedberg pchan = l2cap_global_fixed_chan(NULL, hcon);
7263e760ec12SJohan Hedberg while (pchan) {
7264e760ec12SJohan Hedberg struct l2cap_chan *chan, *next;
7265e760ec12SJohan Hedberg
7266e760ec12SJohan Hedberg /* Client fixed channels should override server ones */
7267e760ec12SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, pchan->scid))
7268e760ec12SJohan Hedberg goto next;
7269e760ec12SJohan Hedberg
7270e760ec12SJohan Hedberg l2cap_chan_lock(pchan);
7271e760ec12SJohan Hedberg chan = pchan->ops->new_connection(pchan);
7272e760ec12SJohan Hedberg if (chan) {
7273e760ec12SJohan Hedberg bacpy(&chan->src, &hcon->src);
7274e760ec12SJohan Hedberg bacpy(&chan->dst, &hcon->dst);
7275a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(hcon);
7276e760ec12SJohan Hedberg chan->dst_type = dst_type;
7277e760ec12SJohan Hedberg
7278e760ec12SJohan Hedberg __l2cap_chan_add(conn, chan);
7279e760ec12SJohan Hedberg }
7280e760ec12SJohan Hedberg
7281e760ec12SJohan Hedberg l2cap_chan_unlock(pchan);
7282e760ec12SJohan Hedberg next:
7283327a7191SJohan Hedberg next = l2cap_global_fixed_chan(pchan, hcon);
7284e760ec12SJohan Hedberg l2cap_chan_put(pchan);
7285e760ec12SJohan Hedberg pchan = next;
7286e760ec12SJohan Hedberg }
7287e760ec12SJohan Hedberg
7288dc0f5088SJohan Hedberg l2cap_conn_ready(conn);
72890a708f8fSGustavo F. Padovan }
72900a708f8fSGustavo F. Padovan
l2cap_disconn_ind(struct hci_conn * hcon)7291686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
72920a708f8fSGustavo F. Padovan {
72930a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data;
72940a708f8fSGustavo F. Padovan
72950a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon);
72960a708f8fSGustavo F. Padovan
7297686ebf28SUlisses Furquim if (!conn)
72989f5a0d7bSAndrei Emeltchenko return HCI_ERROR_REMOTE_USER_TERM;
72990a708f8fSGustavo F. Padovan return conn->disc_reason;
73000a708f8fSGustavo F. Padovan }
73010a708f8fSGustavo F. Padovan
l2cap_disconn_cfm(struct hci_conn * hcon,u8 reason)73023a6d576bSJohan Hedberg static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
73030a708f8fSGustavo F. Padovan {
73043a6d576bSJohan Hedberg if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
73053a6d576bSJohan Hedberg return;
73063a6d576bSJohan Hedberg
73070a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason);
73080a708f8fSGustavo F. Padovan
7309e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason));
73100a708f8fSGustavo F. Padovan }
73110a708f8fSGustavo F. Padovan
l2cap_check_encryption(struct l2cap_chan * chan,u8 encrypt)73124343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
73130a708f8fSGustavo F. Padovan {
7314715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
73150a708f8fSGustavo F. Padovan return;
73160a708f8fSGustavo F. Padovan
73170a708f8fSGustavo F. Padovan if (encrypt == 0x00) {
73184343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) {
7319ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
73207d513e92SMarcel Holtmann } else if (chan->sec_level == BT_SECURITY_HIGH ||
73217d513e92SMarcel Holtmann chan->sec_level == BT_SECURITY_FIPS)
73220f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED);
73230a708f8fSGustavo F. Padovan } else {
73244343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM)
7325c9b66675SGustavo F. Padovan __clear_chan_timer(chan);
73260a708f8fSGustavo F. Padovan }
73270a708f8fSGustavo F. Padovan }
73280a708f8fSGustavo F. Padovan
l2cap_security_cfm(struct hci_conn * hcon,u8 status,u8 encrypt)7329354fe804SJohan Hedberg static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
73300a708f8fSGustavo F. Padovan {
73310a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data;
733248454079SGustavo F. Padovan struct l2cap_chan *chan;
73330a708f8fSGustavo F. Padovan
73340a708f8fSGustavo F. Padovan if (!conn)
7335354fe804SJohan Hedberg return;
73360a708f8fSGustavo F. Padovan
733789d8b407SAndrei Emeltchenko BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt);
73380a708f8fSGustavo F. Padovan
73393df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock);
73400a708f8fSGustavo F. Padovan
73413df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) {
73426be36555SAndrei Emeltchenko l2cap_chan_lock(chan);
73430a708f8fSGustavo F. Padovan
734489d8b407SAndrei Emeltchenko BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
734589d8b407SAndrei Emeltchenko state_to_string(chan->state));
7346f1cb9af5SVinicius Costa Gomes
7347191eb398SJohan Hedberg if (!status && encrypt)
7348f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level;
7349f1cb9af5SVinicius Costa Gomes
735096eff46eSAndrei Emeltchenko if (!__l2cap_no_conn_pending(chan)) {
73516be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
73520a708f8fSGustavo F. Padovan continue;
73530a708f8fSGustavo F. Padovan }
73540a708f8fSGustavo F. Padovan
735589bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED ||
735689bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) {
7357d97c899bSMarcel Holtmann chan->ops->resume(chan);
73584343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt);
73596be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
73600a708f8fSGustavo F. Padovan continue;
73610a708f8fSGustavo F. Padovan }
73620a708f8fSGustavo F. Padovan
736389bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) {
7364693cd8ceSMarcel Holtmann if (!status && l2cap_check_enc_key_size(hcon))
736593c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan);
73666d3c15daSJohan Hedberg else
7367ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
7368fa37c1aaSJohan Hedberg } else if (chan->state == BT_CONNECT2 &&
736915f02b91SLuiz Augusto von Dentz !(chan->mode == L2CAP_MODE_EXT_FLOWCTL ||
737015f02b91SLuiz Augusto von Dentz chan->mode == L2CAP_MODE_LE_FLOWCTL)) {
73710a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp;
7372df3c3931SJohan Hedberg __u16 res, stat;
73730a708f8fSGustavo F. Padovan
7374693cd8ceSMarcel Holtmann if (!status && l2cap_check_enc_key_size(hcon)) {
7375bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
7376df3c3931SJohan Hedberg res = L2CAP_CR_PEND;
7377df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND;
73782dc4e510SGustavo Padovan chan->ops->defer(chan);
7379df3c3931SJohan Hedberg } else {
7380acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG);
7381df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS;
7382df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO;
7383df3c3931SJohan Hedberg }
73840a708f8fSGustavo F. Padovan } else {
7385acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_DISCONN);
7386ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
7387df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK;
7388df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO;
73890a708f8fSGustavo F. Padovan }
73900a708f8fSGustavo F. Padovan
7391fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid);
7392fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid);
7393df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res);
7394df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat);
7395fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
7396fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp);
73972d369359SMat Martineau
73982d369359SMat Martineau if (!test_bit(CONF_REQ_SENT, &chan->conf_state) &&
73992d369359SMat Martineau res == L2CAP_CR_SUCCESS) {
74002d369359SMat Martineau char buf[128];
74012d369359SMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state);
74022d369359SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn),
74032d369359SMat Martineau L2CAP_CONF_REQ,
7404e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)),
74052d369359SMat Martineau buf);
74062d369359SMat Martineau chan->num_conf_req++;
74072d369359SMat Martineau }
74080a708f8fSGustavo F. Padovan }
74090a708f8fSGustavo F. Padovan
74106be36555SAndrei Emeltchenko l2cap_chan_unlock(chan);
74110a708f8fSGustavo F. Padovan }
74120a708f8fSGustavo F. Padovan
74133df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock);
74140a708f8fSGustavo F. Padovan }
74150a708f8fSGustavo F. Padovan
74164d7ea8eeSLuiz Augusto von Dentz /* Append fragment into frame respecting the maximum len of rx_skb */
l2cap_recv_frag(struct l2cap_conn * conn,struct sk_buff * skb,u16 len)74174d7ea8eeSLuiz Augusto von Dentz static int l2cap_recv_frag(struct l2cap_conn *conn, struct sk_buff *skb,
74184d7ea8eeSLuiz Augusto von Dentz u16 len)
74194d7ea8eeSLuiz Augusto von Dentz {
74204d7ea8eeSLuiz Augusto von Dentz if (!conn->rx_skb) {
74214d7ea8eeSLuiz Augusto von Dentz /* Allocate skb for the complete frame (with header) */
74224d7ea8eeSLuiz Augusto von Dentz conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL);
74234d7ea8eeSLuiz Augusto von Dentz if (!conn->rx_skb)
74244d7ea8eeSLuiz Augusto von Dentz return -ENOMEM;
74254d7ea8eeSLuiz Augusto von Dentz /* Init rx_len */
74264d7ea8eeSLuiz Augusto von Dentz conn->rx_len = len;
74274d7ea8eeSLuiz Augusto von Dentz }
74284d7ea8eeSLuiz Augusto von Dentz
74294d7ea8eeSLuiz Augusto von Dentz /* Copy as much as the rx_skb can hold */
74304d7ea8eeSLuiz Augusto von Dentz len = min_t(u16, len, skb->len);
74314d7ea8eeSLuiz Augusto von Dentz skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, len), len);
74324d7ea8eeSLuiz Augusto von Dentz skb_pull(skb, len);
74334d7ea8eeSLuiz Augusto von Dentz conn->rx_len -= len;
74344d7ea8eeSLuiz Augusto von Dentz
74354d7ea8eeSLuiz Augusto von Dentz return len;
74364d7ea8eeSLuiz Augusto von Dentz }
74374d7ea8eeSLuiz Augusto von Dentz
l2cap_recv_len(struct l2cap_conn * conn,struct sk_buff * skb)74384d7ea8eeSLuiz Augusto von Dentz static int l2cap_recv_len(struct l2cap_conn *conn, struct sk_buff *skb)
74394d7ea8eeSLuiz Augusto von Dentz {
74404d7ea8eeSLuiz Augusto von Dentz struct sk_buff *rx_skb;
74414d7ea8eeSLuiz Augusto von Dentz int len;
74424d7ea8eeSLuiz Augusto von Dentz
74434d7ea8eeSLuiz Augusto von Dentz /* Append just enough to complete the header */
74444d7ea8eeSLuiz Augusto von Dentz len = l2cap_recv_frag(conn, skb, L2CAP_LEN_SIZE - conn->rx_skb->len);
74454d7ea8eeSLuiz Augusto von Dentz
74464d7ea8eeSLuiz Augusto von Dentz /* If header could not be read just continue */
74474d7ea8eeSLuiz Augusto von Dentz if (len < 0 || conn->rx_skb->len < L2CAP_LEN_SIZE)
74484d7ea8eeSLuiz Augusto von Dentz return len;
74494d7ea8eeSLuiz Augusto von Dentz
74504d7ea8eeSLuiz Augusto von Dentz rx_skb = conn->rx_skb;
74514d7ea8eeSLuiz Augusto von Dentz len = get_unaligned_le16(rx_skb->data);
74524d7ea8eeSLuiz Augusto von Dentz
74534d7ea8eeSLuiz Augusto von Dentz /* Check if rx_skb has enough space to received all fragments */
74544d7ea8eeSLuiz Augusto von Dentz if (len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE) <= skb_tailroom(rx_skb)) {
74554d7ea8eeSLuiz Augusto von Dentz /* Update expected len */
74564d7ea8eeSLuiz Augusto von Dentz conn->rx_len = len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE);
74574d7ea8eeSLuiz Augusto von Dentz return L2CAP_LEN_SIZE;
74584d7ea8eeSLuiz Augusto von Dentz }
74594d7ea8eeSLuiz Augusto von Dentz
74604d7ea8eeSLuiz Augusto von Dentz /* Reset conn->rx_skb since it will need to be reallocated in order to
74614d7ea8eeSLuiz Augusto von Dentz * fit all fragments.
74624d7ea8eeSLuiz Augusto von Dentz */
74634d7ea8eeSLuiz Augusto von Dentz conn->rx_skb = NULL;
74644d7ea8eeSLuiz Augusto von Dentz
74654d7ea8eeSLuiz Augusto von Dentz /* Reallocates rx_skb using the exact expected length */
74664d7ea8eeSLuiz Augusto von Dentz len = l2cap_recv_frag(conn, rx_skb,
74674d7ea8eeSLuiz Augusto von Dentz len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE));
74684d7ea8eeSLuiz Augusto von Dentz kfree_skb(rx_skb);
74694d7ea8eeSLuiz Augusto von Dentz
74704d7ea8eeSLuiz Augusto von Dentz return len;
74714d7ea8eeSLuiz Augusto von Dentz }
74724d7ea8eeSLuiz Augusto von Dentz
l2cap_recv_reset(struct l2cap_conn * conn)74734d7ea8eeSLuiz Augusto von Dentz static void l2cap_recv_reset(struct l2cap_conn *conn)
74744d7ea8eeSLuiz Augusto von Dentz {
74754d7ea8eeSLuiz Augusto von Dentz kfree_skb(conn->rx_skb);
74764d7ea8eeSLuiz Augusto von Dentz conn->rx_skb = NULL;
74774d7ea8eeSLuiz Augusto von Dentz conn->rx_len = 0;
74784d7ea8eeSLuiz Augusto von Dentz }
74794d7ea8eeSLuiz Augusto von Dentz
l2cap_recv_acldata(struct hci_conn * hcon,struct sk_buff * skb,u16 flags)74809b4c3336SArron Wang void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
74810a708f8fSGustavo F. Padovan {
74820a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data;
7483d73a0988SAndrei Emeltchenko int len;
74840a708f8fSGustavo F. Padovan
74850a708f8fSGustavo F. Padovan if (!conn)
7486baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon);
74870a708f8fSGustavo F. Padovan
74880a708f8fSGustavo F. Padovan if (!conn)
74890a708f8fSGustavo F. Padovan goto drop;
74900a708f8fSGustavo F. Padovan
749193917fd2SKai Ye BT_DBG("conn %p len %u flags 0x%x", conn, skb->len, flags);
74920a708f8fSGustavo F. Padovan
7493d73a0988SAndrei Emeltchenko switch (flags) {
7494d73a0988SAndrei Emeltchenko case ACL_START:
7495d73a0988SAndrei Emeltchenko case ACL_START_NO_FLUSH:
7496d73a0988SAndrei Emeltchenko case ACL_COMPLETE:
74974d7ea8eeSLuiz Augusto von Dentz if (conn->rx_skb) {
74980a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len);
74994d7ea8eeSLuiz Augusto von Dentz l2cap_recv_reset(conn);
75000a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM);
75010a708f8fSGustavo F. Padovan }
75020a708f8fSGustavo F. Padovan
75034d7ea8eeSLuiz Augusto von Dentz /* Start fragment may not contain the L2CAP length so just
75044d7ea8eeSLuiz Augusto von Dentz * copy the initial byte when that happens and use conn->mtu as
75054d7ea8eeSLuiz Augusto von Dentz * expected length.
75064d7ea8eeSLuiz Augusto von Dentz */
75074d7ea8eeSLuiz Augusto von Dentz if (skb->len < L2CAP_LEN_SIZE) {
75087c9524d9SHawkins Jiawei l2cap_recv_frag(conn, skb, conn->mtu);
75097c9524d9SHawkins Jiawei break;
75100a708f8fSGustavo F. Padovan }
75110a708f8fSGustavo F. Padovan
75124d7ea8eeSLuiz Augusto von Dentz len = get_unaligned_le16(skb->data) + L2CAP_HDR_SIZE;
75130a708f8fSGustavo F. Padovan
75140a708f8fSGustavo F. Padovan if (len == skb->len) {
75150a708f8fSGustavo F. Padovan /* Complete frame received */
75160a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb);
75179b4c3336SArron Wang return;
75180a708f8fSGustavo F. Padovan }
75190a708f8fSGustavo F. Padovan
752093917fd2SKai Ye BT_DBG("Start: total len %d, frag len %u", len, skb->len);
75210a708f8fSGustavo F. Padovan
75220a708f8fSGustavo F. Padovan if (skb->len > len) {
752393917fd2SKai Ye BT_ERR("Frame is too long (len %u, expected len %d)",
75240a708f8fSGustavo F. Padovan skb->len, len);
75250a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM);
75260a708f8fSGustavo F. Padovan goto drop;
75270a708f8fSGustavo F. Padovan }
75280a708f8fSGustavo F. Padovan
75294d7ea8eeSLuiz Augusto von Dentz /* Append fragment into frame (with header) */
75304d7ea8eeSLuiz Augusto von Dentz if (l2cap_recv_frag(conn, skb, len) < 0)
75310a708f8fSGustavo F. Padovan goto drop;
75320a708f8fSGustavo F. Padovan
7533d73a0988SAndrei Emeltchenko break;
7534d73a0988SAndrei Emeltchenko
7535d73a0988SAndrei Emeltchenko case ACL_CONT:
753693917fd2SKai Ye BT_DBG("Cont: frag len %u (expecting %u)", skb->len, conn->rx_len);
75370a708f8fSGustavo F. Padovan
75384d7ea8eeSLuiz Augusto von Dentz if (!conn->rx_skb) {
75390a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len);
75400a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM);
75410a708f8fSGustavo F. Padovan goto drop;
75420a708f8fSGustavo F. Padovan }
75430a708f8fSGustavo F. Padovan
75444d7ea8eeSLuiz Augusto von Dentz /* Complete the L2CAP length if it has not been read */
75454d7ea8eeSLuiz Augusto von Dentz if (conn->rx_skb->len < L2CAP_LEN_SIZE) {
75464d7ea8eeSLuiz Augusto von Dentz if (l2cap_recv_len(conn, skb) < 0) {
75470a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM);
75480a708f8fSGustavo F. Padovan goto drop;
75490a708f8fSGustavo F. Padovan }
75500a708f8fSGustavo F. Padovan
75514d7ea8eeSLuiz Augusto von Dentz /* Header still could not be read just continue */
75524d7ea8eeSLuiz Augusto von Dentz if (conn->rx_skb->len < L2CAP_LEN_SIZE)
75537c9524d9SHawkins Jiawei break;
75544d7ea8eeSLuiz Augusto von Dentz }
75554d7ea8eeSLuiz Augusto von Dentz
75564d7ea8eeSLuiz Augusto von Dentz if (skb->len > conn->rx_len) {
755793917fd2SKai Ye BT_ERR("Fragment is too long (len %u, expected %u)",
75584d7ea8eeSLuiz Augusto von Dentz skb->len, conn->rx_len);
75594d7ea8eeSLuiz Augusto von Dentz l2cap_recv_reset(conn);
75604d7ea8eeSLuiz Augusto von Dentz l2cap_conn_unreliable(conn, ECOMM);
75614d7ea8eeSLuiz Augusto von Dentz goto drop;
75624d7ea8eeSLuiz Augusto von Dentz }
75634d7ea8eeSLuiz Augusto von Dentz
75644d7ea8eeSLuiz Augusto von Dentz /* Append fragment into frame (with header) */
75654d7ea8eeSLuiz Augusto von Dentz l2cap_recv_frag(conn, skb, skb->len);
75660a708f8fSGustavo F. Padovan
75670a708f8fSGustavo F. Padovan if (!conn->rx_len) {
7568c4e5bafaSJohan Hedberg /* Complete frame received. l2cap_recv_frame
7569c4e5bafaSJohan Hedberg * takes ownership of the skb so set the global
7570c4e5bafaSJohan Hedberg * rx_skb pointer to NULL first.
7571c4e5bafaSJohan Hedberg */
7572c4e5bafaSJohan Hedberg struct sk_buff *rx_skb = conn->rx_skb;
75730a708f8fSGustavo F. Padovan conn->rx_skb = NULL;
7574c4e5bafaSJohan Hedberg l2cap_recv_frame(conn, rx_skb);
75750a708f8fSGustavo F. Padovan }
7576d73a0988SAndrei Emeltchenko break;
75770a708f8fSGustavo F. Padovan }
75780a708f8fSGustavo F. Padovan
75790a708f8fSGustavo F. Padovan drop:
75800a708f8fSGustavo F. Padovan kfree_skb(skb);
75810a708f8fSGustavo F. Padovan }
75820a708f8fSGustavo F. Padovan
7583354fe804SJohan Hedberg static struct hci_cb l2cap_cb = {
7584354fe804SJohan Hedberg .name = "L2CAP",
7585539c496dSJohan Hedberg .connect_cfm = l2cap_connect_cfm,
75863a6d576bSJohan Hedberg .disconn_cfm = l2cap_disconn_cfm,
7587354fe804SJohan Hedberg .security_cfm = l2cap_security_cfm,
7588354fe804SJohan Hedberg };
7589354fe804SJohan Hedberg
l2cap_debugfs_show(struct seq_file * f,void * p)75900a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
75910a708f8fSGustavo F. Padovan {
759223691d75SGustavo F. Padovan struct l2cap_chan *c;
75930a708f8fSGustavo F. Padovan
7594333055f2SGustavo F. Padovan read_lock(&chan_list_lock);
75950a708f8fSGustavo F. Padovan
759623691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) {
7597eeb5a067SMarcel Holtmann seq_printf(f, "%pMR (%u) %pMR (%u) %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
7598eeb5a067SMarcel Holtmann &c->src, c->src_type, &c->dst, c->dst_type,
759989bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm),
760023691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu,
760123691d75SGustavo F. Padovan c->sec_level, c->mode);
76020a708f8fSGustavo F. Padovan }
76030a708f8fSGustavo F. Padovan
7604333055f2SGustavo F. Padovan read_unlock(&chan_list_lock);
76050a708f8fSGustavo F. Padovan
76060a708f8fSGustavo F. Padovan return 0;
76070a708f8fSGustavo F. Padovan }
76080a708f8fSGustavo F. Padovan
76098e2924e3SYangtao Li DEFINE_SHOW_ATTRIBUTE(l2cap_debugfs);
76100a708f8fSGustavo F. Padovan
76110a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
76120a708f8fSGustavo F. Padovan
l2cap_init(void)761364274518SGustavo F. Padovan int __init l2cap_init(void)
76140a708f8fSGustavo F. Padovan {
76150a708f8fSGustavo F. Padovan int err;
76160a708f8fSGustavo F. Padovan
7617bb58f747SGustavo F. Padovan err = l2cap_init_sockets();
76180a708f8fSGustavo F. Padovan if (err < 0)
76190a708f8fSGustavo F. Padovan return err;
76200a708f8fSGustavo F. Padovan
7621354fe804SJohan Hedberg hci_register_cb(&l2cap_cb);
7622354fe804SJohan Hedberg
76231120e4bfSMarcel Holtmann if (IS_ERR_OR_NULL(bt_debugfs))
76241120e4bfSMarcel Holtmann return 0;
76251120e4bfSMarcel Holtmann
76262d792818SGustavo Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
76272d792818SGustavo Padovan NULL, &l2cap_debugfs_fops);
76280a708f8fSGustavo F. Padovan
76290a708f8fSGustavo F. Padovan return 0;
76300a708f8fSGustavo F. Padovan }
76310a708f8fSGustavo F. Padovan
l2cap_exit(void)763264274518SGustavo F. Padovan void l2cap_exit(void)
76330a708f8fSGustavo F. Padovan {
76340a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs);
7635354fe804SJohan Hedberg hci_unregister_cb(&l2cap_cb);
7636bb58f747SGustavo F. Padovan l2cap_cleanup_sockets();
76370a708f8fSGustavo F. Padovan }
76380a708f8fSGustavo F. Padovan
76390a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
76400a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
76414be5ca67SLuiz Augusto von Dentz
76424be5ca67SLuiz Augusto von Dentz module_param(enable_ecred, bool, 0644);
76434be5ca67SLuiz Augusto von Dentz MODULE_PARM_DESC(enable_ecred, "Enable enhanced credit flow control mode");
7644