xref: /openbmc/linux/net/bluetooth/l2cap_core.c (revision b76bbd66)
10a708f8fSGustavo F. Padovan /*
20a708f8fSGustavo F. Padovan    BlueZ - Bluetooth protocol stack for Linux
30a708f8fSGustavo F. Padovan    Copyright (C) 2000-2001 Qualcomm Incorporated
40a708f8fSGustavo F. Padovan    Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
50a708f8fSGustavo F. Padovan    Copyright (C) 2010 Google Inc.
6590051deSGustavo F. Padovan    Copyright (C) 2011 ProFUSION Embedded Systems
70a708f8fSGustavo F. Padovan 
80a708f8fSGustavo F. Padovan    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
90a708f8fSGustavo F. Padovan 
100a708f8fSGustavo F. Padovan    This program is free software; you can redistribute it and/or modify
110a708f8fSGustavo F. Padovan    it under the terms of the GNU General Public License version 2 as
120a708f8fSGustavo F. Padovan    published by the Free Software Foundation;
130a708f8fSGustavo F. Padovan 
140a708f8fSGustavo F. Padovan    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
150a708f8fSGustavo F. Padovan    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
160a708f8fSGustavo F. Padovan    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
170a708f8fSGustavo F. Padovan    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
180a708f8fSGustavo F. Padovan    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
190a708f8fSGustavo F. Padovan    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
200a708f8fSGustavo F. Padovan    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
210a708f8fSGustavo F. Padovan    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
220a708f8fSGustavo F. Padovan 
230a708f8fSGustavo F. Padovan    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
240a708f8fSGustavo F. Padovan    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
250a708f8fSGustavo F. Padovan    SOFTWARE IS DISCLAIMED.
260a708f8fSGustavo F. Padovan */
270a708f8fSGustavo F. Padovan 
28bb58f747SGustavo F. Padovan /* Bluetooth L2CAP core. */
290a708f8fSGustavo F. Padovan 
300a708f8fSGustavo F. Padovan #include <linux/module.h>
310a708f8fSGustavo F. Padovan 
320a708f8fSGustavo F. Padovan #include <linux/types.h>
330a708f8fSGustavo F. Padovan #include <linux/capability.h>
340a708f8fSGustavo F. Padovan #include <linux/errno.h>
350a708f8fSGustavo F. Padovan #include <linux/kernel.h>
360a708f8fSGustavo F. Padovan #include <linux/sched.h>
370a708f8fSGustavo F. Padovan #include <linux/slab.h>
380a708f8fSGustavo F. Padovan #include <linux/poll.h>
390a708f8fSGustavo F. Padovan #include <linux/fcntl.h>
400a708f8fSGustavo F. Padovan #include <linux/init.h>
410a708f8fSGustavo F. Padovan #include <linux/interrupt.h>
420a708f8fSGustavo F. Padovan #include <linux/socket.h>
430a708f8fSGustavo F. Padovan #include <linux/skbuff.h>
440a708f8fSGustavo F. Padovan #include <linux/list.h>
450a708f8fSGustavo F. Padovan #include <linux/device.h>
460a708f8fSGustavo F. Padovan #include <linux/debugfs.h>
470a708f8fSGustavo F. Padovan #include <linux/seq_file.h>
480a708f8fSGustavo F. Padovan #include <linux/uaccess.h>
490a708f8fSGustavo F. Padovan #include <linux/crc16.h>
500a708f8fSGustavo F. Padovan #include <net/sock.h>
510a708f8fSGustavo F. Padovan 
520a708f8fSGustavo F. Padovan #include <asm/unaligned.h>
530a708f8fSGustavo F. Padovan 
540a708f8fSGustavo F. Padovan #include <net/bluetooth/bluetooth.h>
550a708f8fSGustavo F. Padovan #include <net/bluetooth/hci_core.h>
560a708f8fSGustavo F. Padovan #include <net/bluetooth/l2cap.h>
57b501d6a1SAnderson Briglia #include <net/bluetooth/smp.h>
580a708f8fSGustavo F. Padovan 
59eb939922SRusty Russell bool disable_ertm;
600a708f8fSGustavo F. Padovan 
610a708f8fSGustavo F. Padovan static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
6250a147cdSMat Martineau static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
630a708f8fSGustavo F. Padovan 
64b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list);
65b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock);
660a708f8fSGustavo F. Padovan 
670a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
680a708f8fSGustavo F. Padovan 				u8 code, u8 ident, u16 dlen, void *data);
694519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
704519de9aSGustavo F. Padovan 								void *data);
71710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
724519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn,
734519de9aSGustavo F. Padovan 				struct l2cap_chan *chan, int err);
740a708f8fSGustavo F. Padovan 
750a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */
7671ba0e56SGustavo F. Padovan 
77baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
780a708f8fSGustavo F. Padovan {
793df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
80baa7e1faSGustavo F. Padovan 
813df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
823df91ea2SAndrei Emeltchenko 		if (c->dcid == cid)
833df91ea2SAndrei Emeltchenko 			return c;
840a708f8fSGustavo F. Padovan 	}
853df91ea2SAndrei Emeltchenko 	return NULL;
86baa7e1faSGustavo F. Padovan }
870a708f8fSGustavo F. Padovan 
88baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
890a708f8fSGustavo F. Padovan {
903df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
91baa7e1faSGustavo F. Padovan 
923df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
933df91ea2SAndrei Emeltchenko 		if (c->scid == cid)
943df91ea2SAndrei Emeltchenko 			return c;
950a708f8fSGustavo F. Padovan 	}
963df91ea2SAndrei Emeltchenko 	return NULL;
97baa7e1faSGustavo F. Padovan }
980a708f8fSGustavo F. Padovan 
990a708f8fSGustavo F. Padovan /* Find channel with given SCID.
1000a708f8fSGustavo F. Padovan  * Returns locked socket */
101baa7e1faSGustavo F. Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
1020a708f8fSGustavo F. Padovan {
10348454079SGustavo F. Padovan 	struct l2cap_chan *c;
104baa7e1faSGustavo F. Padovan 
1053df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
106baa7e1faSGustavo F. Padovan 	c = __l2cap_get_chan_by_scid(conn, cid);
1073df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
1083df91ea2SAndrei Emeltchenko 
10948454079SGustavo F. Padovan 	return c;
1100a708f8fSGustavo F. Padovan }
1110a708f8fSGustavo F. Padovan 
112baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
1130a708f8fSGustavo F. Padovan {
1143df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
115baa7e1faSGustavo F. Padovan 
1163df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1173df91ea2SAndrei Emeltchenko 		if (c->ident == ident)
1183df91ea2SAndrei Emeltchenko 			return c;
1190a708f8fSGustavo F. Padovan 	}
1203df91ea2SAndrei Emeltchenko 	return NULL;
121baa7e1faSGustavo F. Padovan }
1220a708f8fSGustavo F. Padovan 
123baa7e1faSGustavo F. Padovan static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
1240a708f8fSGustavo F. Padovan {
12548454079SGustavo F. Padovan 	struct l2cap_chan *c;
126baa7e1faSGustavo F. Padovan 
1273df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
128baa7e1faSGustavo F. Padovan 	c = __l2cap_get_chan_by_ident(conn, ident);
1293df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
1303df91ea2SAndrei Emeltchenko 
13148454079SGustavo F. Padovan 	return c;
1320a708f8fSGustavo F. Padovan }
1330a708f8fSGustavo F. Padovan 
13423691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
1359e4425ffSGustavo F. Padovan {
13623691d75SGustavo F. Padovan 	struct l2cap_chan *c;
1379e4425ffSGustavo F. Padovan 
13823691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
13923691d75SGustavo F. Padovan 		if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
14023691d75SGustavo F. Padovan 			return c;
1419e4425ffSGustavo F. Padovan 	}
142250938cbSSzymon Janc 	return NULL;
143250938cbSSzymon Janc }
1449e4425ffSGustavo F. Padovan 
1459e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
1469e4425ffSGustavo F. Padovan {
14773b2ec18SGustavo F. Padovan 	int err;
14873b2ec18SGustavo F. Padovan 
149333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1509e4425ffSGustavo F. Padovan 
15123691d75SGustavo F. Padovan 	if (psm && __l2cap_global_chan_by_addr(psm, src)) {
15273b2ec18SGustavo F. Padovan 		err = -EADDRINUSE;
15373b2ec18SGustavo F. Padovan 		goto done;
1549e4425ffSGustavo F. Padovan 	}
1559e4425ffSGustavo F. Padovan 
15673b2ec18SGustavo F. Padovan 	if (psm) {
1579e4425ffSGustavo F. Padovan 		chan->psm = psm;
1589e4425ffSGustavo F. Padovan 		chan->sport = psm;
15973b2ec18SGustavo F. Padovan 		err = 0;
16073b2ec18SGustavo F. Padovan 	} else {
16173b2ec18SGustavo F. Padovan 		u16 p;
1629e4425ffSGustavo F. Padovan 
16373b2ec18SGustavo F. Padovan 		err = -EINVAL;
16473b2ec18SGustavo F. Padovan 		for (p = 0x1001; p < 0x1100; p += 2)
16523691d75SGustavo F. Padovan 			if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
16673b2ec18SGustavo F. Padovan 				chan->psm   = cpu_to_le16(p);
16773b2ec18SGustavo F. Padovan 				chan->sport = cpu_to_le16(p);
16873b2ec18SGustavo F. Padovan 				err = 0;
16973b2ec18SGustavo F. Padovan 				break;
17073b2ec18SGustavo F. Padovan 			}
17173b2ec18SGustavo F. Padovan 	}
17273b2ec18SGustavo F. Padovan 
17373b2ec18SGustavo F. Padovan done:
174333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
17573b2ec18SGustavo F. Padovan 	return err;
1769e4425ffSGustavo F. Padovan }
1779e4425ffSGustavo F. Padovan 
1789e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
1799e4425ffSGustavo F. Padovan {
180333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1819e4425ffSGustavo F. Padovan 
1829e4425ffSGustavo F. Padovan 	chan->scid = scid;
1839e4425ffSGustavo F. Padovan 
184333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
1859e4425ffSGustavo F. Padovan 
1869e4425ffSGustavo F. Padovan 	return 0;
1879e4425ffSGustavo F. Padovan }
1889e4425ffSGustavo F. Padovan 
189baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
1900a708f8fSGustavo F. Padovan {
1910a708f8fSGustavo F. Padovan 	u16 cid = L2CAP_CID_DYN_START;
1920a708f8fSGustavo F. Padovan 
1930a708f8fSGustavo F. Padovan 	for (; cid < L2CAP_CID_DYN_END; cid++) {
194baa7e1faSGustavo F. Padovan 		if (!__l2cap_get_chan_by_scid(conn, cid))
1950a708f8fSGustavo F. Padovan 			return cid;
1960a708f8fSGustavo F. Padovan 	}
1970a708f8fSGustavo F. Padovan 
1980a708f8fSGustavo F. Padovan 	return 0;
1990a708f8fSGustavo F. Padovan }
2000a708f8fSGustavo F. Padovan 
2010e587be7SAndrei Emeltchenko static void __l2cap_state_change(struct l2cap_chan *chan, int state)
20289bc500eSGustavo F. Padovan {
20342d2d87cSAndrei Emeltchenko 	BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
204badaaa00SGustavo F. Padovan 						state_to_string(state));
205badaaa00SGustavo F. Padovan 
20689bc500eSGustavo F. Padovan 	chan->state = state;
20789bc500eSGustavo F. Padovan 	chan->ops->state_change(chan->data, state);
20889bc500eSGustavo F. Padovan }
20989bc500eSGustavo F. Padovan 
2100e587be7SAndrei Emeltchenko static void l2cap_state_change(struct l2cap_chan *chan, int state)
2110e587be7SAndrei Emeltchenko {
2120e587be7SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2130e587be7SAndrei Emeltchenko 
2140e587be7SAndrei Emeltchenko 	lock_sock(sk);
2150e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, state);
2160e587be7SAndrei Emeltchenko 	release_sock(sk);
2170e587be7SAndrei Emeltchenko }
2180e587be7SAndrei Emeltchenko 
2192e0052e4SAndrei Emeltchenko static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2202e0052e4SAndrei Emeltchenko {
2212e0052e4SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2222e0052e4SAndrei Emeltchenko 
2232e0052e4SAndrei Emeltchenko 	sk->sk_err = err;
2242e0052e4SAndrei Emeltchenko }
2252e0052e4SAndrei Emeltchenko 
2262e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2272e0052e4SAndrei Emeltchenko {
2282e0052e4SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2292e0052e4SAndrei Emeltchenko 
2302e0052e4SAndrei Emeltchenko 	lock_sock(sk);
2312e0052e4SAndrei Emeltchenko 	__l2cap_chan_set_err(chan, err);
2322e0052e4SAndrei Emeltchenko 	release_sock(sk);
2332e0052e4SAndrei Emeltchenko }
2342e0052e4SAndrei Emeltchenko 
2353c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */
2363c588192SMat Martineau 
2373c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for
2383c588192SMat Martineau  * SREJ requests that are received and for frames that are to be
2393c588192SMat Martineau  * retransmitted. These seq_list functions implement a singly-linked
2403c588192SMat Martineau  * list in an array, where membership in the list can also be checked
2413c588192SMat Martineau  * in constant time. Items can also be added to the tail of the list
2423c588192SMat Martineau  * and removed from the head in constant time, without further memory
2433c588192SMat Martineau  * allocs or frees.
2443c588192SMat Martineau  */
2453c588192SMat Martineau 
2463c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
2473c588192SMat Martineau {
2483c588192SMat Martineau 	size_t alloc_size, i;
2493c588192SMat Martineau 
2503c588192SMat Martineau 	/* Allocated size is a power of 2 to map sequence numbers
2513c588192SMat Martineau 	 * (which may be up to 14 bits) in to a smaller array that is
2523c588192SMat Martineau 	 * sized for the negotiated ERTM transmit windows.
2533c588192SMat Martineau 	 */
2543c588192SMat Martineau 	alloc_size = roundup_pow_of_two(size);
2553c588192SMat Martineau 
2563c588192SMat Martineau 	seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL);
2573c588192SMat Martineau 	if (!seq_list->list)
2583c588192SMat Martineau 		return -ENOMEM;
2593c588192SMat Martineau 
2603c588192SMat Martineau 	seq_list->mask = alloc_size - 1;
2613c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
2623c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
2633c588192SMat Martineau 	for (i = 0; i < alloc_size; i++)
2643c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
2653c588192SMat Martineau 
2663c588192SMat Martineau 	return 0;
2673c588192SMat Martineau }
2683c588192SMat Martineau 
2693c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
2703c588192SMat Martineau {
2713c588192SMat Martineau 	kfree(seq_list->list);
2723c588192SMat Martineau }
2733c588192SMat Martineau 
2743c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
2753c588192SMat Martineau 					   u16 seq)
2763c588192SMat Martineau {
2773c588192SMat Martineau 	/* Constant-time check for list membership */
2783c588192SMat Martineau 	return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
2793c588192SMat Martineau }
2803c588192SMat Martineau 
2813c588192SMat Martineau static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq)
2823c588192SMat Martineau {
2833c588192SMat Martineau 	u16 mask = seq_list->mask;
2843c588192SMat Martineau 
2853c588192SMat Martineau 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) {
2863c588192SMat Martineau 		/* In case someone tries to pop the head of an empty list */
2873c588192SMat Martineau 		return L2CAP_SEQ_LIST_CLEAR;
2883c588192SMat Martineau 	} else if (seq_list->head == seq) {
2893c588192SMat Martineau 		/* Head can be removed in constant time */
2903c588192SMat Martineau 		seq_list->head = seq_list->list[seq & mask];
2913c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
2923c588192SMat Martineau 
2933c588192SMat Martineau 		if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
2943c588192SMat Martineau 			seq_list->head = L2CAP_SEQ_LIST_CLEAR;
2953c588192SMat Martineau 			seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
2963c588192SMat Martineau 		}
2973c588192SMat Martineau 	} else {
2983c588192SMat Martineau 		/* Walk the list to find the sequence number */
2993c588192SMat Martineau 		u16 prev = seq_list->head;
3003c588192SMat Martineau 		while (seq_list->list[prev & mask] != seq) {
3013c588192SMat Martineau 			prev = seq_list->list[prev & mask];
3023c588192SMat Martineau 			if (prev == L2CAP_SEQ_LIST_TAIL)
3033c588192SMat Martineau 				return L2CAP_SEQ_LIST_CLEAR;
3043c588192SMat Martineau 		}
3053c588192SMat Martineau 
3063c588192SMat Martineau 		/* Unlink the number from the list and clear it */
3073c588192SMat Martineau 		seq_list->list[prev & mask] = seq_list->list[seq & mask];
3083c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3093c588192SMat Martineau 		if (seq_list->tail == seq)
3103c588192SMat Martineau 			seq_list->tail = prev;
3113c588192SMat Martineau 	}
3123c588192SMat Martineau 	return seq;
3133c588192SMat Martineau }
3143c588192SMat Martineau 
3153c588192SMat Martineau static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
3163c588192SMat Martineau {
3173c588192SMat Martineau 	/* Remove the head in constant time */
3183c588192SMat Martineau 	return l2cap_seq_list_remove(seq_list, seq_list->head);
3193c588192SMat Martineau }
3203c588192SMat Martineau 
3213c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
3223c588192SMat Martineau {
3233c588192SMat Martineau 	if (seq_list->head != L2CAP_SEQ_LIST_CLEAR) {
3243c588192SMat Martineau 		u16 i;
3253c588192SMat Martineau 		for (i = 0; i <= seq_list->mask; i++)
3263c588192SMat Martineau 			seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3273c588192SMat Martineau 
3283c588192SMat Martineau 		seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3293c588192SMat Martineau 		seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3303c588192SMat Martineau 	}
3313c588192SMat Martineau }
3323c588192SMat Martineau 
3333c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
3343c588192SMat Martineau {
3353c588192SMat Martineau 	u16 mask = seq_list->mask;
3363c588192SMat Martineau 
3373c588192SMat Martineau 	/* All appends happen in constant time */
3383c588192SMat Martineau 
3393c588192SMat Martineau 	if (seq_list->list[seq & mask] == L2CAP_SEQ_LIST_CLEAR) {
3403c588192SMat Martineau 		if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
3413c588192SMat Martineau 			seq_list->head = seq;
3423c588192SMat Martineau 		else
3433c588192SMat Martineau 			seq_list->list[seq_list->tail & mask] = seq;
3443c588192SMat Martineau 
3453c588192SMat Martineau 		seq_list->tail = seq;
3463c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
3473c588192SMat Martineau 	}
3483c588192SMat Martineau }
3493c588192SMat Martineau 
350721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work)
351ab07801dSGustavo F. Padovan {
352721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
353721c4181SGustavo F. Padovan 							chan_timer.work);
3543df91ea2SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
355ab07801dSGustavo F. Padovan 	int reason;
356ab07801dSGustavo F. Padovan 
357e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
358ab07801dSGustavo F. Padovan 
3593df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
3606be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
361ab07801dSGustavo F. Padovan 
36289bc500eSGustavo F. Padovan 	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
363ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
36489bc500eSGustavo F. Padovan 	else if (chan->state == BT_CONNECT &&
365ab07801dSGustavo F. Padovan 					chan->sec_level != BT_SECURITY_SDP)
366ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
367ab07801dSGustavo F. Padovan 	else
368ab07801dSGustavo F. Padovan 		reason = ETIMEDOUT;
369ab07801dSGustavo F. Padovan 
3700f852724SGustavo F. Padovan 	l2cap_chan_close(chan, reason);
371ab07801dSGustavo F. Padovan 
3726be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
373ab07801dSGustavo F. Padovan 
374ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
3753df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
3763df91ea2SAndrei Emeltchenko 
377371fd835SUlisses Furquim 	l2cap_chan_put(chan);
378ab07801dSGustavo F. Padovan }
379ab07801dSGustavo F. Padovan 
380eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void)
3810a708f8fSGustavo F. Padovan {
38248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
3830a708f8fSGustavo F. Padovan 
38448454079SGustavo F. Padovan 	chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
38548454079SGustavo F. Padovan 	if (!chan)
38648454079SGustavo F. Padovan 		return NULL;
3870a708f8fSGustavo F. Padovan 
388c03b355eSAndrei Emeltchenko 	mutex_init(&chan->lock);
389c03b355eSAndrei Emeltchenko 
390333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
39123691d75SGustavo F. Padovan 	list_add(&chan->global_l, &chan_list);
392333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
39323691d75SGustavo F. Padovan 
394721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
395ab07801dSGustavo F. Padovan 
39689bc500eSGustavo F. Padovan 	chan->state = BT_OPEN;
39789bc500eSGustavo F. Padovan 
39871ba0e56SGustavo F. Padovan 	atomic_set(&chan->refcnt, 1);
39971ba0e56SGustavo F. Padovan 
400eef1d9b6SGustavo Padovan 	BT_DBG("chan %p", chan);
401abc545b8SSzymon Janc 
40248454079SGustavo F. Padovan 	return chan;
4030a708f8fSGustavo F. Padovan }
4040a708f8fSGustavo F. Padovan 
40523691d75SGustavo F. Padovan void l2cap_chan_destroy(struct l2cap_chan *chan)
4066ff5abbfSGustavo F. Padovan {
407333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
40823691d75SGustavo F. Padovan 	list_del(&chan->global_l);
409333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
41023691d75SGustavo F. Padovan 
411371fd835SUlisses Furquim 	l2cap_chan_put(chan);
4126ff5abbfSGustavo F. Padovan }
4136ff5abbfSGustavo F. Padovan 
414bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan)
415bd4b1653SAndrei Emeltchenko {
416bd4b1653SAndrei Emeltchenko 	chan->fcs  = L2CAP_FCS_CRC16;
417bd4b1653SAndrei Emeltchenko 	chan->max_tx = L2CAP_DEFAULT_MAX_TX;
418bd4b1653SAndrei Emeltchenko 	chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
419bd4b1653SAndrei Emeltchenko 	chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
420bd4b1653SAndrei Emeltchenko 	chan->sec_level = BT_SECURITY_LOW;
421bd4b1653SAndrei Emeltchenko 
422bd4b1653SAndrei Emeltchenko 	set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
423bd4b1653SAndrei Emeltchenko }
424bd4b1653SAndrei Emeltchenko 
42514a28491SAndrei Emeltchenko static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
4260a708f8fSGustavo F. Padovan {
4270a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
428097db76cSAndrei Emeltchenko 	       __le16_to_cpu(chan->psm), chan->dcid);
4290a708f8fSGustavo F. Padovan 
4309f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
4310a708f8fSGustavo F. Padovan 
4328c1d787bSGustavo F. Padovan 	chan->conn = conn;
4330a708f8fSGustavo F. Padovan 
4345491120eSAndrei Emeltchenko 	switch (chan->chan_type) {
4355491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_ORIENTED:
436b62f328bSVille Tervo 		if (conn->hcon->type == LE_LINK) {
437b62f328bSVille Tervo 			/* LE connection */
4380c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_LE_DEFAULT_MTU;
439fe4128e0SGustavo F. Padovan 			chan->scid = L2CAP_CID_LE_DATA;
440fe4128e0SGustavo F. Padovan 			chan->dcid = L2CAP_CID_LE_DATA;
441b62f328bSVille Tervo 		} else {
4420a708f8fSGustavo F. Padovan 			/* Alloc CID for connection-oriented socket */
443fe4128e0SGustavo F. Padovan 			chan->scid = l2cap_alloc_cid(conn);
4440c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_DEFAULT_MTU;
445b62f328bSVille Tervo 		}
4465491120eSAndrei Emeltchenko 		break;
4475491120eSAndrei Emeltchenko 
4485491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_LESS:
4490a708f8fSGustavo F. Padovan 		/* Connectionless socket */
450fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_CONN_LESS;
451fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_CONN_LESS;
4520c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
4535491120eSAndrei Emeltchenko 		break;
4545491120eSAndrei Emeltchenko 
4555491120eSAndrei Emeltchenko 	default:
4560a708f8fSGustavo F. Padovan 		/* Raw socket can send/recv signalling messages only */
457fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_SIGNALING;
458fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_SIGNALING;
4590c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
4600a708f8fSGustavo F. Padovan 	}
4610a708f8fSGustavo F. Padovan 
4628f7975b1SAndrei Emeltchenko 	chan->local_id		= L2CAP_BESTEFFORT_ID;
4638f7975b1SAndrei Emeltchenko 	chan->local_stype	= L2CAP_SERV_BESTEFFORT;
4648f7975b1SAndrei Emeltchenko 	chan->local_msdu	= L2CAP_DEFAULT_MAX_SDU_SIZE;
4658f7975b1SAndrei Emeltchenko 	chan->local_sdu_itime	= L2CAP_DEFAULT_SDU_ITIME;
4668f7975b1SAndrei Emeltchenko 	chan->local_acc_lat	= L2CAP_DEFAULT_ACC_LAT;
4678f7975b1SAndrei Emeltchenko 	chan->local_flush_to	= L2CAP_DEFAULT_FLUSH_TO;
4688f7975b1SAndrei Emeltchenko 
469371fd835SUlisses Furquim 	l2cap_chan_hold(chan);
470baa7e1faSGustavo F. Padovan 
4713df91ea2SAndrei Emeltchenko 	list_add(&chan->list, &conn->chan_l);
472643162a8SAndrei Emeltchenko }
473643162a8SAndrei Emeltchenko 
47414a28491SAndrei Emeltchenko static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
475643162a8SAndrei Emeltchenko {
476643162a8SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
477643162a8SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
4783df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
4790a708f8fSGustavo F. Padovan }
4800a708f8fSGustavo F. Padovan 
4814519de9aSGustavo F. Padovan static void l2cap_chan_del(struct l2cap_chan *chan, int err)
4820a708f8fSGustavo F. Padovan {
48348454079SGustavo F. Padovan 	struct sock *sk = chan->sk;
4848c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
4850a708f8fSGustavo F. Padovan 	struct sock *parent = bt_sk(sk)->parent;
4860a708f8fSGustavo F. Padovan 
487c9b66675SGustavo F. Padovan 	__clear_chan_timer(chan);
4880a708f8fSGustavo F. Padovan 
48949208c9cSGustavo F. Padovan 	BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
4900a708f8fSGustavo F. Padovan 
4910a708f8fSGustavo F. Padovan 	if (conn) {
492baa7e1faSGustavo F. Padovan 		/* Delete from channel list */
4933df91ea2SAndrei Emeltchenko 		list_del(&chan->list);
4943d57dc68SGustavo F. Padovan 
495371fd835SUlisses Furquim 		l2cap_chan_put(chan);
496baa7e1faSGustavo F. Padovan 
4978c1d787bSGustavo F. Padovan 		chan->conn = NULL;
4980a708f8fSGustavo F. Padovan 		hci_conn_put(conn->hcon);
4990a708f8fSGustavo F. Padovan 	}
5000a708f8fSGustavo F. Padovan 
5016be36555SAndrei Emeltchenko 	lock_sock(sk);
5026be36555SAndrei Emeltchenko 
5030e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_CLOSED);
5040a708f8fSGustavo F. Padovan 	sock_set_flag(sk, SOCK_ZAPPED);
5050a708f8fSGustavo F. Padovan 
5060a708f8fSGustavo F. Padovan 	if (err)
5072e0052e4SAndrei Emeltchenko 		__l2cap_chan_set_err(chan, err);
5080a708f8fSGustavo F. Padovan 
5090a708f8fSGustavo F. Padovan 	if (parent) {
5100a708f8fSGustavo F. Padovan 		bt_accept_unlink(sk);
5110a708f8fSGustavo F. Padovan 		parent->sk_data_ready(parent, 0);
5120a708f8fSGustavo F. Padovan 	} else
5130a708f8fSGustavo F. Padovan 		sk->sk_state_change(sk);
5140a708f8fSGustavo F. Padovan 
5156be36555SAndrei Emeltchenko 	release_sock(sk);
5166be36555SAndrei Emeltchenko 
517c1360a1cSGustavo F. Padovan 	if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
518c1360a1cSGustavo F. Padovan 			test_bit(CONF_INPUT_DONE, &chan->conf_state)))
5196ff5abbfSGustavo F. Padovan 		return;
5202ead70b8SGustavo F. Padovan 
52158d35f87SGustavo F. Padovan 	skb_queue_purge(&chan->tx_q);
5220a708f8fSGustavo F. Padovan 
5230c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_ERTM) {
5240a708f8fSGustavo F. Padovan 		struct srej_list *l, *tmp;
5250a708f8fSGustavo F. Padovan 
5261a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
5271a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
5281a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
5290a708f8fSGustavo F. Padovan 
530f1c6775bSGustavo F. Padovan 		skb_queue_purge(&chan->srej_q);
5310a708f8fSGustavo F. Padovan 
5323c588192SMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
5333c588192SMat Martineau 		l2cap_seq_list_free(&chan->retrans_list);
53439d5a3eeSGustavo F. Padovan 		list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
5350a708f8fSGustavo F. Padovan 			list_del(&l->list);
5360a708f8fSGustavo F. Padovan 			kfree(l);
5370a708f8fSGustavo F. Padovan 		}
5380a708f8fSGustavo F. Padovan 	}
5390a708f8fSGustavo F. Padovan }
5400a708f8fSGustavo F. Padovan 
5414519de9aSGustavo F. Padovan static void l2cap_chan_cleanup_listen(struct sock *parent)
5424519de9aSGustavo F. Padovan {
5434519de9aSGustavo F. Padovan 	struct sock *sk;
5444519de9aSGustavo F. Padovan 
5454519de9aSGustavo F. Padovan 	BT_DBG("parent %p", parent);
5464519de9aSGustavo F. Padovan 
5474519de9aSGustavo F. Padovan 	/* Close not yet accepted channels */
5480f852724SGustavo F. Padovan 	while ((sk = bt_accept_dequeue(parent, NULL))) {
549ba3bd0eeSGustavo F. Padovan 		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
5503df91ea2SAndrei Emeltchenko 
5516be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
552c9b66675SGustavo F. Padovan 		__clear_chan_timer(chan);
553ba3bd0eeSGustavo F. Padovan 		l2cap_chan_close(chan, ECONNRESET);
5546be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
5553df91ea2SAndrei Emeltchenko 
556ba3bd0eeSGustavo F. Padovan 		chan->ops->close(chan->data);
5570f852724SGustavo F. Padovan 	}
5584519de9aSGustavo F. Padovan }
5594519de9aSGustavo F. Padovan 
5600f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason)
5614519de9aSGustavo F. Padovan {
5624519de9aSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
5634519de9aSGustavo F. Padovan 	struct sock *sk = chan->sk;
5644519de9aSGustavo F. Padovan 
565e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s sk %p", chan,
566e05dcc32SAndrei Emeltchenko 					state_to_string(chan->state), sk);
5674519de9aSGustavo F. Padovan 
56889bc500eSGustavo F. Padovan 	switch (chan->state) {
5694519de9aSGustavo F. Padovan 	case BT_LISTEN:
5706be36555SAndrei Emeltchenko 		lock_sock(sk);
5714519de9aSGustavo F. Padovan 		l2cap_chan_cleanup_listen(sk);
57289bc500eSGustavo F. Padovan 
5730e587be7SAndrei Emeltchenko 		__l2cap_state_change(chan, BT_CLOSED);
57489bc500eSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
5756be36555SAndrei Emeltchenko 		release_sock(sk);
5764519de9aSGustavo F. Padovan 		break;
5774519de9aSGustavo F. Padovan 
5784519de9aSGustavo F. Padovan 	case BT_CONNECTED:
5794519de9aSGustavo F. Padovan 	case BT_CONFIG:
580715ec005SGustavo F. Padovan 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
5814519de9aSGustavo F. Padovan 					conn->hcon->type == ACL_LINK) {
582c9b66675SGustavo F. Padovan 			__set_chan_timer(chan, sk->sk_sndtimeo);
5834519de9aSGustavo F. Padovan 			l2cap_send_disconn_req(conn, chan, reason);
5844519de9aSGustavo F. Padovan 		} else
5854519de9aSGustavo F. Padovan 			l2cap_chan_del(chan, reason);
5864519de9aSGustavo F. Padovan 		break;
5874519de9aSGustavo F. Padovan 
5884519de9aSGustavo F. Padovan 	case BT_CONNECT2:
589715ec005SGustavo F. Padovan 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
5904519de9aSGustavo F. Padovan 					conn->hcon->type == ACL_LINK) {
5914519de9aSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
5924519de9aSGustavo F. Padovan 			__u16 result;
5934519de9aSGustavo F. Padovan 
5944519de9aSGustavo F. Padovan 			if (bt_sk(sk)->defer_setup)
5954519de9aSGustavo F. Padovan 				result = L2CAP_CR_SEC_BLOCK;
5964519de9aSGustavo F. Padovan 			else
5974519de9aSGustavo F. Padovan 				result = L2CAP_CR_BAD_PSM;
59889bc500eSGustavo F. Padovan 			l2cap_state_change(chan, BT_DISCONN);
5994519de9aSGustavo F. Padovan 
6004519de9aSGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
6014519de9aSGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
6024519de9aSGustavo F. Padovan 			rsp.result = cpu_to_le16(result);
6034519de9aSGustavo F. Padovan 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
6044519de9aSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
6054519de9aSGustavo F. Padovan 							sizeof(rsp), &rsp);
6064519de9aSGustavo F. Padovan 		}
6074519de9aSGustavo F. Padovan 
6084519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
6094519de9aSGustavo F. Padovan 		break;
6104519de9aSGustavo F. Padovan 
6114519de9aSGustavo F. Padovan 	case BT_CONNECT:
6124519de9aSGustavo F. Padovan 	case BT_DISCONN:
6134519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
6144519de9aSGustavo F. Padovan 		break;
6154519de9aSGustavo F. Padovan 
6164519de9aSGustavo F. Padovan 	default:
6176be36555SAndrei Emeltchenko 		lock_sock(sk);
6184519de9aSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
6196be36555SAndrei Emeltchenko 		release_sock(sk);
6204519de9aSGustavo F. Padovan 		break;
6214519de9aSGustavo F. Padovan 	}
6224519de9aSGustavo F. Padovan }
6234519de9aSGustavo F. Padovan 
6244343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
6250a708f8fSGustavo F. Padovan {
626715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_RAW) {
6274343478fSGustavo F. Padovan 		switch (chan->sec_level) {
6280a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
6290a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING_MITM;
6300a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
6310a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING;
6320a708f8fSGustavo F. Padovan 		default:
6330a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6340a708f8fSGustavo F. Padovan 		}
635fe4128e0SGustavo F. Padovan 	} else if (chan->psm == cpu_to_le16(0x0001)) {
6364343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_LOW)
6374343478fSGustavo F. Padovan 			chan->sec_level = BT_SECURITY_SDP;
6380a708f8fSGustavo F. Padovan 
6394343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_HIGH)
6400a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING_MITM;
6410a708f8fSGustavo F. Padovan 		else
6420a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6430a708f8fSGustavo F. Padovan 	} else {
6444343478fSGustavo F. Padovan 		switch (chan->sec_level) {
6450a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
6460a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING_MITM;
6470a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
6480a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING;
6490a708f8fSGustavo F. Padovan 		default:
6500a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6510a708f8fSGustavo F. Padovan 		}
6520a708f8fSGustavo F. Padovan 	}
6530a708f8fSGustavo F. Padovan }
6540a708f8fSGustavo F. Padovan 
6550a708f8fSGustavo F. Padovan /* Service level security */
656d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan)
6570a708f8fSGustavo F. Padovan {
6588c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
6590a708f8fSGustavo F. Padovan 	__u8 auth_type;
6600a708f8fSGustavo F. Padovan 
6614343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
6620a708f8fSGustavo F. Padovan 
6634343478fSGustavo F. Padovan 	return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
6640a708f8fSGustavo F. Padovan }
6650a708f8fSGustavo F. Padovan 
666b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn)
6670a708f8fSGustavo F. Padovan {
6680a708f8fSGustavo F. Padovan 	u8 id;
6690a708f8fSGustavo F. Padovan 
6700a708f8fSGustavo F. Padovan 	/* Get next available identificator.
6710a708f8fSGustavo F. Padovan 	 *    1 - 128 are used by kernel.
6720a708f8fSGustavo F. Padovan 	 *  129 - 199 are reserved.
6730a708f8fSGustavo F. Padovan 	 *  200 - 254 are used by utilities like l2ping, etc.
6740a708f8fSGustavo F. Padovan 	 */
6750a708f8fSGustavo F. Padovan 
676333055f2SGustavo F. Padovan 	spin_lock(&conn->lock);
6770a708f8fSGustavo F. Padovan 
6780a708f8fSGustavo F. Padovan 	if (++conn->tx_ident > 128)
6790a708f8fSGustavo F. Padovan 		conn->tx_ident = 1;
6800a708f8fSGustavo F. Padovan 
6810a708f8fSGustavo F. Padovan 	id = conn->tx_ident;
6820a708f8fSGustavo F. Padovan 
683333055f2SGustavo F. Padovan 	spin_unlock(&conn->lock);
6840a708f8fSGustavo F. Padovan 
6850a708f8fSGustavo F. Padovan 	return id;
6860a708f8fSGustavo F. Padovan }
6870a708f8fSGustavo F. Padovan 
6884519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
6890a708f8fSGustavo F. Padovan {
6900a708f8fSGustavo F. Padovan 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
6910a708f8fSGustavo F. Padovan 	u8 flags;
6920a708f8fSGustavo F. Padovan 
6930a708f8fSGustavo F. Padovan 	BT_DBG("code 0x%2.2x", code);
6940a708f8fSGustavo F. Padovan 
6950a708f8fSGustavo F. Padovan 	if (!skb)
6960a708f8fSGustavo F. Padovan 		return;
6970a708f8fSGustavo F. Padovan 
6980a708f8fSGustavo F. Padovan 	if (lmp_no_flush_capable(conn->hcon->hdev))
6990a708f8fSGustavo F. Padovan 		flags = ACL_START_NO_FLUSH;
7000a708f8fSGustavo F. Padovan 	else
7010a708f8fSGustavo F. Padovan 		flags = ACL_START;
7020a708f8fSGustavo F. Padovan 
70314b12d0bSJaikumar Ganesh 	bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
7045e59b791SLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
70514b12d0bSJaikumar Ganesh 
70673d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, flags);
7070a708f8fSGustavo F. Padovan }
7080a708f8fSGustavo F. Padovan 
70973d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
71073d80debSLuiz Augusto von Dentz {
71173d80debSLuiz Augusto von Dentz 	struct hci_conn *hcon = chan->conn->hcon;
71273d80debSLuiz Augusto von Dentz 	u16 flags;
71373d80debSLuiz Augusto von Dentz 
71473d80debSLuiz Augusto von Dentz 	BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
71573d80debSLuiz Augusto von Dentz 							skb->priority);
71673d80debSLuiz Augusto von Dentz 
71773d80debSLuiz Augusto von Dentz 	if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
71873d80debSLuiz Augusto von Dentz 					lmp_no_flush_capable(hcon->hdev))
71973d80debSLuiz Augusto von Dentz 		flags = ACL_START_NO_FLUSH;
72073d80debSLuiz Augusto von Dentz 	else
72173d80debSLuiz Augusto von Dentz 		flags = ACL_START;
72273d80debSLuiz Augusto von Dentz 
72373d80debSLuiz Augusto von Dentz 	bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
72473d80debSLuiz Augusto von Dentz 	hci_send_acl(chan->conn->hchan, skb, flags);
7250a708f8fSGustavo F. Padovan }
7260a708f8fSGustavo F. Padovan 
72788843ab0SAndrei Emeltchenko static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
7280a708f8fSGustavo F. Padovan {
7290a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
7300a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
7318c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
732e4ca6d98SAndrei Emeltchenko 	int count, hlen;
7330a708f8fSGustavo F. Padovan 
73489bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
7350a708f8fSGustavo F. Padovan 		return;
7360a708f8fSGustavo F. Padovan 
737e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
738e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_EXT_HDR_SIZE;
739e4ca6d98SAndrei Emeltchenko 	else
740e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_ENH_HDR_SIZE;
7410a708f8fSGustavo F. Padovan 
7420a708f8fSGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
74303a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
7440a708f8fSGustavo F. Padovan 
74588843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, control 0x%8.8x", chan, control);
7460a708f8fSGustavo F. Padovan 
7470a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, hlen);
748793c2f1cSAndrei Emeltchenko 
749793c2f1cSAndrei Emeltchenko 	control |= __set_sframe(chan);
7500a708f8fSGustavo F. Padovan 
751e2ab4353SGustavo F. Padovan 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
75203f6715dSAndrei Emeltchenko 		control |= __set_ctrl_final(chan);
7530a708f8fSGustavo F. Padovan 
754e2ab4353SGustavo F. Padovan 	if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
755e3781735SAndrei Emeltchenko 		control |= __set_ctrl_poll(chan);
7560a708f8fSGustavo F. Padovan 
7570a708f8fSGustavo F. Padovan 	skb = bt_skb_alloc(count, GFP_ATOMIC);
7580a708f8fSGustavo F. Padovan 	if (!skb)
7590a708f8fSGustavo F. Padovan 		return;
7600a708f8fSGustavo F. Padovan 
7610a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
7620a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
763fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
76488843ab0SAndrei Emeltchenko 
76588843ab0SAndrei Emeltchenko 	__put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
7660a708f8fSGustavo F. Padovan 
76747d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
76803a51213SAndrei Emeltchenko 		u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
76903a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
7700a708f8fSGustavo F. Padovan 	}
7710a708f8fSGustavo F. Padovan 
77273d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
77373d80debSLuiz Augusto von Dentz 	l2cap_do_send(chan, skb);
7740a708f8fSGustavo F. Padovan }
7750a708f8fSGustavo F. Padovan 
77688843ab0SAndrei Emeltchenko static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
7770a708f8fSGustavo F. Padovan {
778e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
779ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
780e2ab4353SGustavo F. Padovan 		set_bit(CONN_RNR_SENT, &chan->conn_state);
7810a708f8fSGustavo F. Padovan 	} else
782ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
7830a708f8fSGustavo F. Padovan 
7840b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
7850a708f8fSGustavo F. Padovan 
786525cd185SGustavo F. Padovan 	l2cap_send_sframe(chan, control);
7870a708f8fSGustavo F. Padovan }
7880a708f8fSGustavo F. Padovan 
789b76bbd66SMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
790b76bbd66SMat Martineau {
791b76bbd66SMat Martineau 	u16 packed;
792b76bbd66SMat Martineau 
793b76bbd66SMat Martineau 	packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
794b76bbd66SMat Martineau 	packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
795b76bbd66SMat Martineau 
796b76bbd66SMat Martineau 	if (control->sframe) {
797b76bbd66SMat Martineau 		packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
798b76bbd66SMat Martineau 		packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
799b76bbd66SMat Martineau 		packed |= L2CAP_CTRL_FRAME_TYPE;
800b76bbd66SMat Martineau 	} else {
801b76bbd66SMat Martineau 		packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
802b76bbd66SMat Martineau 		packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
803b76bbd66SMat Martineau 	}
804b76bbd66SMat Martineau 
805b76bbd66SMat Martineau 	return packed;
806b76bbd66SMat Martineau }
807b76bbd66SMat Martineau 
808b76bbd66SMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
809b76bbd66SMat Martineau {
810b76bbd66SMat Martineau 	control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
811b76bbd66SMat Martineau 	control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
812b76bbd66SMat Martineau 
813b76bbd66SMat Martineau 	if (enh & L2CAP_CTRL_FRAME_TYPE) {
814b76bbd66SMat Martineau 		/* S-Frame */
815b76bbd66SMat Martineau 		control->sframe = 1;
816b76bbd66SMat Martineau 		control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
817b76bbd66SMat Martineau 		control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
818b76bbd66SMat Martineau 
819b76bbd66SMat Martineau 		control->sar = 0;
820b76bbd66SMat Martineau 		control->txseq = 0;
821b76bbd66SMat Martineau 	} else {
822b76bbd66SMat Martineau 		/* I-Frame */
823b76bbd66SMat Martineau 		control->sframe = 0;
824b76bbd66SMat Martineau 		control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
825b76bbd66SMat Martineau 		control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
826b76bbd66SMat Martineau 
827b76bbd66SMat Martineau 		control->poll = 0;
828b76bbd66SMat Martineau 		control->super = 0;
829b76bbd66SMat Martineau 	}
830b76bbd66SMat Martineau }
831b76bbd66SMat Martineau 
832b76bbd66SMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control)
833b76bbd66SMat Martineau {
834b76bbd66SMat Martineau 	u32 packed;
835b76bbd66SMat Martineau 
836b76bbd66SMat Martineau 	packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
837b76bbd66SMat Martineau 	packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
838b76bbd66SMat Martineau 
839b76bbd66SMat Martineau 	if (control->sframe) {
840b76bbd66SMat Martineau 		packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
841b76bbd66SMat Martineau 		packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
842b76bbd66SMat Martineau 		packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
843b76bbd66SMat Martineau 	} else {
844b76bbd66SMat Martineau 		packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
845b76bbd66SMat Martineau 		packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
846b76bbd66SMat Martineau 	}
847b76bbd66SMat Martineau 
848b76bbd66SMat Martineau 	return packed;
849b76bbd66SMat Martineau }
850b76bbd66SMat Martineau 
851b76bbd66SMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
852b76bbd66SMat Martineau {
853b76bbd66SMat Martineau 	control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
854b76bbd66SMat Martineau 	control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
855b76bbd66SMat Martineau 
856b76bbd66SMat Martineau 	if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
857b76bbd66SMat Martineau 		/* S-Frame */
858b76bbd66SMat Martineau 		control->sframe = 1;
859b76bbd66SMat Martineau 		control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
860b76bbd66SMat Martineau 		control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
861b76bbd66SMat Martineau 
862b76bbd66SMat Martineau 		control->sar = 0;
863b76bbd66SMat Martineau 		control->txseq = 0;
864b76bbd66SMat Martineau 	} else {
865b76bbd66SMat Martineau 		/* I-Frame */
866b76bbd66SMat Martineau 		control->sframe = 0;
867b76bbd66SMat Martineau 		control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
868b76bbd66SMat Martineau 		control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
869b76bbd66SMat Martineau 
870b76bbd66SMat Martineau 		control->poll = 0;
871b76bbd66SMat Martineau 		control->super = 0;
872b76bbd66SMat Martineau 	}
873b76bbd66SMat Martineau }
874b76bbd66SMat Martineau 
875b76bbd66SMat Martineau static inline void __unpack_control(struct l2cap_chan *chan,
876b76bbd66SMat Martineau 				    struct sk_buff *skb)
877b76bbd66SMat Martineau {
878b76bbd66SMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
879b76bbd66SMat Martineau 		__unpack_extended_control(get_unaligned_le32(skb->data),
880b76bbd66SMat Martineau 					  &bt_cb(skb)->control);
881b76bbd66SMat Martineau 	} else {
882b76bbd66SMat Martineau 		__unpack_enhanced_control(get_unaligned_le16(skb->data),
883b76bbd66SMat Martineau 					  &bt_cb(skb)->control);
884b76bbd66SMat Martineau 	}
885b76bbd66SMat Martineau }
886b76bbd66SMat Martineau 
887b76bbd66SMat Martineau static inline void __pack_control(struct l2cap_chan *chan,
888b76bbd66SMat Martineau 				  struct l2cap_ctrl *control,
889b76bbd66SMat Martineau 				  struct sk_buff *skb)
890b76bbd66SMat Martineau {
891b76bbd66SMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
892b76bbd66SMat Martineau 		put_unaligned_le32(__pack_extended_control(control),
893b76bbd66SMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
894b76bbd66SMat Martineau 	} else {
895b76bbd66SMat Martineau 		put_unaligned_le16(__pack_enhanced_control(control),
896b76bbd66SMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
897b76bbd66SMat Martineau 	}
898b76bbd66SMat Martineau }
899b76bbd66SMat Martineau 
900b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
9010a708f8fSGustavo F. Padovan {
902c1360a1cSGustavo F. Padovan 	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
9030a708f8fSGustavo F. Padovan }
9040a708f8fSGustavo F. Padovan 
9059b27f350SAndrei Emeltchenko static void l2cap_send_conn_req(struct l2cap_chan *chan)
9069b27f350SAndrei Emeltchenko {
9079b27f350SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
9089b27f350SAndrei Emeltchenko 	struct l2cap_conn_req req;
9099b27f350SAndrei Emeltchenko 
9109b27f350SAndrei Emeltchenko 	req.scid = cpu_to_le16(chan->scid);
9119b27f350SAndrei Emeltchenko 	req.psm  = chan->psm;
9129b27f350SAndrei Emeltchenko 
9139b27f350SAndrei Emeltchenko 	chan->ident = l2cap_get_ident(conn);
9149b27f350SAndrei Emeltchenko 
9159b27f350SAndrei Emeltchenko 	set_bit(CONF_CONNECT_PEND, &chan->conf_state);
9169b27f350SAndrei Emeltchenko 
9179b27f350SAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
9189b27f350SAndrei Emeltchenko }
9199b27f350SAndrei Emeltchenko 
920fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan)
9210a708f8fSGustavo F. Padovan {
9228c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
9230a708f8fSGustavo F. Padovan 
9240a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
9250a708f8fSGustavo F. Padovan 		if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
9260a708f8fSGustavo F. Padovan 			return;
9270a708f8fSGustavo F. Padovan 
928d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan) &&
9299b27f350SAndrei Emeltchenko 				__l2cap_no_conn_pending(chan))
9309b27f350SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
9310a708f8fSGustavo F. Padovan 	} else {
9320a708f8fSGustavo F. Padovan 		struct l2cap_info_req req;
9330a708f8fSGustavo F. Padovan 		req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
9340a708f8fSGustavo F. Padovan 
9350a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
9360a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
9370a708f8fSGustavo F. Padovan 
938ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
9390a708f8fSGustavo F. Padovan 
9400a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, conn->info_ident,
9410a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(req), &req);
9420a708f8fSGustavo F. Padovan 	}
9430a708f8fSGustavo F. Padovan }
9440a708f8fSGustavo F. Padovan 
9450a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
9460a708f8fSGustavo F. Padovan {
9470a708f8fSGustavo F. Padovan 	u32 local_feat_mask = l2cap_feat_mask;
9480a708f8fSGustavo F. Padovan 	if (!disable_ertm)
9490a708f8fSGustavo F. Padovan 		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
9500a708f8fSGustavo F. Padovan 
9510a708f8fSGustavo F. Padovan 	switch (mode) {
9520a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
9530a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
9540a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
9550a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
9560a708f8fSGustavo F. Padovan 	default:
9570a708f8fSGustavo F. Padovan 		return 0x00;
9580a708f8fSGustavo F. Padovan 	}
9590a708f8fSGustavo F. Padovan }
9600a708f8fSGustavo F. Padovan 
9614519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
9620a708f8fSGustavo F. Padovan {
9636be36555SAndrei Emeltchenko 	struct sock *sk = chan->sk;
9640a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req req;
9650a708f8fSGustavo F. Padovan 
9660a708f8fSGustavo F. Padovan 	if (!conn)
9670a708f8fSGustavo F. Padovan 		return;
9680a708f8fSGustavo F. Padovan 
9690c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_ERTM) {
9701a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
9711a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
9721a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
9730a708f8fSGustavo F. Padovan 	}
9740a708f8fSGustavo F. Padovan 
975fe4128e0SGustavo F. Padovan 	req.dcid = cpu_to_le16(chan->dcid);
976fe4128e0SGustavo F. Padovan 	req.scid = cpu_to_le16(chan->scid);
9770a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn),
9780a708f8fSGustavo F. Padovan 			L2CAP_DISCONN_REQ, sizeof(req), &req);
9790a708f8fSGustavo F. Padovan 
9806be36555SAndrei Emeltchenko 	lock_sock(sk);
9810e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_DISCONN);
9822e0052e4SAndrei Emeltchenko 	__l2cap_chan_set_err(chan, err);
9836be36555SAndrei Emeltchenko 	release_sock(sk);
9840a708f8fSGustavo F. Padovan }
9850a708f8fSGustavo F. Padovan 
9860a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
9870a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
9880a708f8fSGustavo F. Padovan {
9893df91ea2SAndrei Emeltchenko 	struct l2cap_chan *chan, *tmp;
9900a708f8fSGustavo F. Padovan 
9910a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
9920a708f8fSGustavo F. Padovan 
9933df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
9940a708f8fSGustavo F. Padovan 
9953df91ea2SAndrei Emeltchenko 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
99648454079SGustavo F. Padovan 		struct sock *sk = chan->sk;
997baa7e1faSGustavo F. Padovan 
9986be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
9990a708f8fSGustavo F. Padovan 
1000715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
10016be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
10020a708f8fSGustavo F. Padovan 			continue;
10030a708f8fSGustavo F. Padovan 		}
10040a708f8fSGustavo F. Padovan 
100589bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
1006d45fc423SGustavo F. Padovan 			if (!l2cap_chan_check_security(chan) ||
1007b4450035SGustavo F. Padovan 					!__l2cap_no_conn_pending(chan)) {
10086be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10090a708f8fSGustavo F. Padovan 				continue;
10100a708f8fSGustavo F. Padovan 			}
10110a708f8fSGustavo F. Padovan 
1012c1360a1cSGustavo F. Padovan 			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1013c1360a1cSGustavo F. Padovan 					&& test_bit(CONF_STATE2_DEVICE,
1014c1360a1cSGustavo F. Padovan 					&chan->conf_state)) {
10150f852724SGustavo F. Padovan 				l2cap_chan_close(chan, ECONNRESET);
10166be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10170a708f8fSGustavo F. Padovan 				continue;
10180a708f8fSGustavo F. Padovan 			}
10190a708f8fSGustavo F. Padovan 
10209b27f350SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
10210a708f8fSGustavo F. Padovan 
102289bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
10230a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
10240a708f8fSGustavo F. Padovan 			char buf[128];
1025fe4128e0SGustavo F. Padovan 			rsp.scid = cpu_to_le16(chan->dcid);
1026fe4128e0SGustavo F. Padovan 			rsp.dcid = cpu_to_le16(chan->scid);
10270a708f8fSGustavo F. Padovan 
1028d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan)) {
10296be36555SAndrei Emeltchenko 				lock_sock(sk);
10300a708f8fSGustavo F. Padovan 				if (bt_sk(sk)->defer_setup) {
10310a708f8fSGustavo F. Padovan 					struct sock *parent = bt_sk(sk)->parent;
10320a708f8fSGustavo F. Padovan 					rsp.result = cpu_to_le16(L2CAP_CR_PEND);
10330a708f8fSGustavo F. Padovan 					rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
103405e9a2f6SIlia Kolomisnky 					if (parent)
10350a708f8fSGustavo F. Padovan 						parent->sk_data_ready(parent, 0);
10360a708f8fSGustavo F. Padovan 
10370a708f8fSGustavo F. Padovan 				} else {
10380e587be7SAndrei Emeltchenko 					__l2cap_state_change(chan, BT_CONFIG);
10390a708f8fSGustavo F. Padovan 					rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
10400a708f8fSGustavo F. Padovan 					rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
10410a708f8fSGustavo F. Padovan 				}
10426be36555SAndrei Emeltchenko 				release_sock(sk);
10430a708f8fSGustavo F. Padovan 			} else {
10440a708f8fSGustavo F. Padovan 				rsp.result = cpu_to_le16(L2CAP_CR_PEND);
10450a708f8fSGustavo F. Padovan 				rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
10460a708f8fSGustavo F. Padovan 			}
10470a708f8fSGustavo F. Padovan 
1048fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1049fc7f8a7eSGustavo F. Padovan 							sizeof(rsp), &rsp);
10500a708f8fSGustavo F. Padovan 
1051c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
10520a708f8fSGustavo F. Padovan 					rsp.result != L2CAP_CR_SUCCESS) {
10536be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10540a708f8fSGustavo F. Padovan 				continue;
10550a708f8fSGustavo F. Padovan 			}
10560a708f8fSGustavo F. Padovan 
1057c1360a1cSGustavo F. Padovan 			set_bit(CONF_REQ_SENT, &chan->conf_state);
10580a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
105973ffa904SGustavo F. Padovan 						l2cap_build_conf_req(chan, buf), buf);
106073ffa904SGustavo F. Padovan 			chan->num_conf_req++;
10610a708f8fSGustavo F. Padovan 		}
10620a708f8fSGustavo F. Padovan 
10636be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
10640a708f8fSGustavo F. Padovan 	}
10650a708f8fSGustavo F. Padovan 
10663df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
10670a708f8fSGustavo F. Padovan }
10680a708f8fSGustavo F. Padovan 
1069b62f328bSVille Tervo /* Find socket with cid and source bdaddr.
1070b62f328bSVille Tervo  * Returns closest match, locked.
1071b62f328bSVille Tervo  */
1072d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
1073d9b88702SAndrei Emeltchenko 						    bdaddr_t *src)
1074b62f328bSVille Tervo {
107523691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
1076b62f328bSVille Tervo 
107723691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
1078b62f328bSVille Tervo 
107923691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
108023691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
1081fe4128e0SGustavo F. Padovan 
108289bc500eSGustavo F. Padovan 		if (state && c->state != state)
1083b62f328bSVille Tervo 			continue;
1084b62f328bSVille Tervo 
108523691d75SGustavo F. Padovan 		if (c->scid == cid) {
1086b62f328bSVille Tervo 			/* Exact match. */
108723691d75SGustavo F. Padovan 			if (!bacmp(&bt_sk(sk)->src, src)) {
108823691d75SGustavo F. Padovan 				read_unlock(&chan_list_lock);
108923691d75SGustavo F. Padovan 				return c;
109023691d75SGustavo F. Padovan 			}
1091b62f328bSVille Tervo 
1092b62f328bSVille Tervo 			/* Closest match */
1093b62f328bSVille Tervo 			if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
109423691d75SGustavo F. Padovan 				c1 = c;
1095b62f328bSVille Tervo 		}
1096b62f328bSVille Tervo 	}
1097280f294fSGustavo F. Padovan 
109823691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
1099b62f328bSVille Tervo 
110023691d75SGustavo F. Padovan 	return c1;
1101b62f328bSVille Tervo }
1102b62f328bSVille Tervo 
1103b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1104b62f328bSVille Tervo {
1105c916fbe4SGustavo F. Padovan 	struct sock *parent, *sk;
110623691d75SGustavo F. Padovan 	struct l2cap_chan *chan, *pchan;
1107b62f328bSVille Tervo 
1108b62f328bSVille Tervo 	BT_DBG("");
1109b62f328bSVille Tervo 
1110b62f328bSVille Tervo 	/* Check if we have socket listening on cid */
111123691d75SGustavo F. Padovan 	pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
1112b62f328bSVille Tervo 							conn->src);
111323691d75SGustavo F. Padovan 	if (!pchan)
1114b62f328bSVille Tervo 		return;
1115b62f328bSVille Tervo 
111623691d75SGustavo F. Padovan 	parent = pchan->sk;
111723691d75SGustavo F. Padovan 
1118aa2ac881SGustavo F. Padovan 	lock_sock(parent);
111962f3a2cfSGustavo F. Padovan 
1120b62f328bSVille Tervo 	/* Check for backlog size */
1121b62f328bSVille Tervo 	if (sk_acceptq_is_full(parent)) {
1122b62f328bSVille Tervo 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
1123b62f328bSVille Tervo 		goto clean;
1124b62f328bSVille Tervo 	}
1125b62f328bSVille Tervo 
112680808e43SGustavo F. Padovan 	chan = pchan->ops->new_connection(pchan->data);
112780808e43SGustavo F. Padovan 	if (!chan)
1128b62f328bSVille Tervo 		goto clean;
1129b62f328bSVille Tervo 
113080808e43SGustavo F. Padovan 	sk = chan->sk;
11315d41ce1dSGustavo F. Padovan 
1132b62f328bSVille Tervo 	hci_conn_hold(conn->hcon);
1133b62f328bSVille Tervo 
1134b62f328bSVille Tervo 	bacpy(&bt_sk(sk)->src, conn->src);
1135b62f328bSVille Tervo 	bacpy(&bt_sk(sk)->dst, conn->dst);
1136b62f328bSVille Tervo 
1137d1010240SGustavo F. Padovan 	bt_accept_enqueue(parent, sk);
1138d1010240SGustavo F. Padovan 
11393d57dc68SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
114048454079SGustavo F. Padovan 
1141c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
1142b62f328bSVille Tervo 
11430e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_CONNECTED);
1144b62f328bSVille Tervo 	parent->sk_data_ready(parent, 0);
1145b62f328bSVille Tervo 
1146b62f328bSVille Tervo clean:
1147aa2ac881SGustavo F. Padovan 	release_sock(parent);
1148b62f328bSVille Tervo }
1149b62f328bSVille Tervo 
1150cf4cd009SAndrei Emeltchenko static void l2cap_chan_ready(struct l2cap_chan *chan)
1151f1cb9af5SVinicius Costa Gomes {
1152cf4cd009SAndrei Emeltchenko 	struct sock *sk = chan->sk;
11536be36555SAndrei Emeltchenko 	struct sock *parent;
11546be36555SAndrei Emeltchenko 
11556be36555SAndrei Emeltchenko 	lock_sock(sk);
11566be36555SAndrei Emeltchenko 
11576be36555SAndrei Emeltchenko 	parent = bt_sk(sk)->parent;
1158f1cb9af5SVinicius Costa Gomes 
1159f1cb9af5SVinicius Costa Gomes 	BT_DBG("sk %p, parent %p", sk, parent);
1160f1cb9af5SVinicius Costa Gomes 
1161f1cb9af5SVinicius Costa Gomes 	chan->conf_state = 0;
1162f1cb9af5SVinicius Costa Gomes 	__clear_chan_timer(chan);
1163f1cb9af5SVinicius Costa Gomes 
11640e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_CONNECTED);
1165f1cb9af5SVinicius Costa Gomes 	sk->sk_state_change(sk);
1166f1cb9af5SVinicius Costa Gomes 
1167f1cb9af5SVinicius Costa Gomes 	if (parent)
1168f1cb9af5SVinicius Costa Gomes 		parent->sk_data_ready(parent, 0);
11696be36555SAndrei Emeltchenko 
11706be36555SAndrei Emeltchenko 	release_sock(sk);
1171f1cb9af5SVinicius Costa Gomes }
1172f1cb9af5SVinicius Costa Gomes 
11730a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
11740a708f8fSGustavo F. Padovan {
117548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
11760a708f8fSGustavo F. Padovan 
11770a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
11780a708f8fSGustavo F. Padovan 
1179b62f328bSVille Tervo 	if (!conn->hcon->out && conn->hcon->type == LE_LINK)
1180b62f328bSVille Tervo 		l2cap_le_conn_ready(conn);
1181b62f328bSVille Tervo 
1182160dc6acSVinicius Costa Gomes 	if (conn->hcon->out && conn->hcon->type == LE_LINK)
1183160dc6acSVinicius Costa Gomes 		smp_conn_security(conn, conn->hcon->pending_sec_level);
1184160dc6acSVinicius Costa Gomes 
11853df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
11860a708f8fSGustavo F. Padovan 
11873df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1188baa7e1faSGustavo F. Padovan 
11896be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
11900a708f8fSGustavo F. Padovan 
119163128451SVinicius Costa Gomes 		if (conn->hcon->type == LE_LINK) {
1192b501d6a1SAnderson Briglia 			if (smp_conn_security(conn, chan->sec_level))
1193cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
1194acd7d370SVille Tervo 
119563128451SVinicius Costa Gomes 		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
11966be36555SAndrei Emeltchenko 			struct sock *sk = chan->sk;
1197c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
11986be36555SAndrei Emeltchenko 			lock_sock(sk);
11990e587be7SAndrei Emeltchenko 			__l2cap_state_change(chan, BT_CONNECTED);
12000a708f8fSGustavo F. Padovan 			sk->sk_state_change(sk);
12016be36555SAndrei Emeltchenko 			release_sock(sk);
1202b501d6a1SAnderson Briglia 
120389bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT)
1204fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
12050a708f8fSGustavo F. Padovan 
12066be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
12070a708f8fSGustavo F. Padovan 	}
12080a708f8fSGustavo F. Padovan 
12093df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12100a708f8fSGustavo F. Padovan }
12110a708f8fSGustavo F. Padovan 
12120a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
12130a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
12140a708f8fSGustavo F. Padovan {
121548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
12160a708f8fSGustavo F. Padovan 
12170a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
12180a708f8fSGustavo F. Padovan 
12193df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
12200a708f8fSGustavo F. Padovan 
12213df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1222ecf61bdbSAndrei Emeltchenko 		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
12232e0052e4SAndrei Emeltchenko 			__l2cap_chan_set_err(chan, err);
12240a708f8fSGustavo F. Padovan 	}
12250a708f8fSGustavo F. Padovan 
12263df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12270a708f8fSGustavo F. Padovan }
12280a708f8fSGustavo F. Padovan 
1229f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
12300a708f8fSGustavo F. Padovan {
1231f878fcadSGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1232030013d8SGustavo F. Padovan 							info_timer.work);
12330a708f8fSGustavo F. Padovan 
12340a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
12350a708f8fSGustavo F. Padovan 	conn->info_ident = 0;
12360a708f8fSGustavo F. Padovan 
12370a708f8fSGustavo F. Padovan 	l2cap_conn_start(conn);
12380a708f8fSGustavo F. Padovan }
12390a708f8fSGustavo F. Padovan 
12405d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
12415d3de7dfSVinicius Costa Gomes {
12425d3de7dfSVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
12435d3de7dfSVinicius Costa Gomes 	struct l2cap_chan *chan, *l;
12445d3de7dfSVinicius Costa Gomes 
12455d3de7dfSVinicius Costa Gomes 	if (!conn)
12465d3de7dfSVinicius Costa Gomes 		return;
12475d3de7dfSVinicius Costa Gomes 
12485d3de7dfSVinicius Costa Gomes 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
12495d3de7dfSVinicius Costa Gomes 
12505d3de7dfSVinicius Costa Gomes 	kfree_skb(conn->rx_skb);
12515d3de7dfSVinicius Costa Gomes 
12523df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
12533df91ea2SAndrei Emeltchenko 
12545d3de7dfSVinicius Costa Gomes 	/* Kill channels */
12555d3de7dfSVinicius Costa Gomes 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
12566be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
12576be36555SAndrei Emeltchenko 
12585d3de7dfSVinicius Costa Gomes 		l2cap_chan_del(chan, err);
12596be36555SAndrei Emeltchenko 
12606be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
12616be36555SAndrei Emeltchenko 
12625d3de7dfSVinicius Costa Gomes 		chan->ops->close(chan->data);
12635d3de7dfSVinicius Costa Gomes 	}
12645d3de7dfSVinicius Costa Gomes 
12653df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12663df91ea2SAndrei Emeltchenko 
126773d80debSLuiz Augusto von Dentz 	hci_chan_del(conn->hchan);
126873d80debSLuiz Augusto von Dentz 
12695d3de7dfSVinicius Costa Gomes 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1270127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->info_timer);
12715d3de7dfSVinicius Costa Gomes 
127251a8efd7SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
1273127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->security_timer);
12748aab4757SVinicius Costa Gomes 		smp_chan_destroy(conn);
1275d26a2345SVinicius Costa Gomes 	}
12765d3de7dfSVinicius Costa Gomes 
12775d3de7dfSVinicius Costa Gomes 	hcon->l2cap_data = NULL;
12785d3de7dfSVinicius Costa Gomes 	kfree(conn);
12795d3de7dfSVinicius Costa Gomes }
12805d3de7dfSVinicius Costa Gomes 
12816c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work)
12825d3de7dfSVinicius Costa Gomes {
12836c9d42a1SGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
12846c9d42a1SGustavo F. Padovan 						security_timer.work);
12855d3de7dfSVinicius Costa Gomes 
12865d3de7dfSVinicius Costa Gomes 	l2cap_conn_del(conn->hcon, ETIMEDOUT);
12875d3de7dfSVinicius Costa Gomes }
12885d3de7dfSVinicius Costa Gomes 
12890a708f8fSGustavo F. Padovan static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
12900a708f8fSGustavo F. Padovan {
12910a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
129273d80debSLuiz Augusto von Dentz 	struct hci_chan *hchan;
12930a708f8fSGustavo F. Padovan 
12940a708f8fSGustavo F. Padovan 	if (conn || status)
12950a708f8fSGustavo F. Padovan 		return conn;
12960a708f8fSGustavo F. Padovan 
129773d80debSLuiz Augusto von Dentz 	hchan = hci_chan_create(hcon);
129873d80debSLuiz Augusto von Dentz 	if (!hchan)
12990a708f8fSGustavo F. Padovan 		return NULL;
13000a708f8fSGustavo F. Padovan 
130173d80debSLuiz Augusto von Dentz 	conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
130273d80debSLuiz Augusto von Dentz 	if (!conn) {
130373d80debSLuiz Augusto von Dentz 		hci_chan_del(hchan);
130473d80debSLuiz Augusto von Dentz 		return NULL;
130573d80debSLuiz Augusto von Dentz 	}
130673d80debSLuiz Augusto von Dentz 
13070a708f8fSGustavo F. Padovan 	hcon->l2cap_data = conn;
13080a708f8fSGustavo F. Padovan 	conn->hcon = hcon;
130973d80debSLuiz Augusto von Dentz 	conn->hchan = hchan;
13100a708f8fSGustavo F. Padovan 
131173d80debSLuiz Augusto von Dentz 	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
13120a708f8fSGustavo F. Padovan 
1313acd7d370SVille Tervo 	if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1314acd7d370SVille Tervo 		conn->mtu = hcon->hdev->le_mtu;
1315acd7d370SVille Tervo 	else
13160a708f8fSGustavo F. Padovan 		conn->mtu = hcon->hdev->acl_mtu;
1317acd7d370SVille Tervo 
13180a708f8fSGustavo F. Padovan 	conn->src = &hcon->hdev->bdaddr;
13190a708f8fSGustavo F. Padovan 	conn->dst = &hcon->dst;
13200a708f8fSGustavo F. Padovan 
13210a708f8fSGustavo F. Padovan 	conn->feat_mask = 0;
13220a708f8fSGustavo F. Padovan 
13230a708f8fSGustavo F. Padovan 	spin_lock_init(&conn->lock);
13243df91ea2SAndrei Emeltchenko 	mutex_init(&conn->chan_lock);
1325baa7e1faSGustavo F. Padovan 
1326baa7e1faSGustavo F. Padovan 	INIT_LIST_HEAD(&conn->chan_l);
13270a708f8fSGustavo F. Padovan 
13285d3de7dfSVinicius Costa Gomes 	if (hcon->type == LE_LINK)
13296c9d42a1SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
13305d3de7dfSVinicius Costa Gomes 	else
1331030013d8SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
13320a708f8fSGustavo F. Padovan 
13339f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
13340a708f8fSGustavo F. Padovan 
13350a708f8fSGustavo F. Padovan 	return conn;
13360a708f8fSGustavo F. Padovan }
13370a708f8fSGustavo F. Padovan 
13380a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */
13390a708f8fSGustavo F. Padovan 
13400a708f8fSGustavo F. Padovan /* Find socket with psm and source bdaddr.
13410a708f8fSGustavo F. Padovan  * Returns closest match.
13420a708f8fSGustavo F. Padovan  */
134323691d75SGustavo F. Padovan static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
13440a708f8fSGustavo F. Padovan {
134523691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
13460a708f8fSGustavo F. Padovan 
134723691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
13480a708f8fSGustavo F. Padovan 
134923691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
135023691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
1351fe4128e0SGustavo F. Padovan 
135289bc500eSGustavo F. Padovan 		if (state && c->state != state)
13530a708f8fSGustavo F. Padovan 			continue;
13540a708f8fSGustavo F. Padovan 
135523691d75SGustavo F. Padovan 		if (c->psm == psm) {
13560a708f8fSGustavo F. Padovan 			/* Exact match. */
135723691d75SGustavo F. Padovan 			if (!bacmp(&bt_sk(sk)->src, src)) {
1358a7567b20SJohannes Berg 				read_unlock(&chan_list_lock);
135923691d75SGustavo F. Padovan 				return c;
136023691d75SGustavo F. Padovan 			}
13610a708f8fSGustavo F. Padovan 
13620a708f8fSGustavo F. Padovan 			/* Closest match */
13630a708f8fSGustavo F. Padovan 			if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
136423691d75SGustavo F. Padovan 				c1 = c;
13650a708f8fSGustavo F. Padovan 		}
13660a708f8fSGustavo F. Padovan 	}
13670a708f8fSGustavo F. Padovan 
136823691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
13690a708f8fSGustavo F. Padovan 
137023691d75SGustavo F. Padovan 	return c1;
13710a708f8fSGustavo F. Padovan }
13720a708f8fSGustavo F. Padovan 
1373cbe8fed4SJohan Hedberg int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst)
13740a708f8fSGustavo F. Padovan {
13755d41ce1dSGustavo F. Padovan 	struct sock *sk = chan->sk;
13760a708f8fSGustavo F. Padovan 	bdaddr_t *src = &bt_sk(sk)->src;
13770a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
13780a708f8fSGustavo F. Padovan 	struct hci_conn *hcon;
13790a708f8fSGustavo F. Padovan 	struct hci_dev *hdev;
13800a708f8fSGustavo F. Padovan 	__u8 auth_type;
13810a708f8fSGustavo F. Padovan 	int err;
13820a708f8fSGustavo F. Padovan 
13830a708f8fSGustavo F. Padovan 	BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
1384097db76cSAndrei Emeltchenko 	       __le16_to_cpu(chan->psm));
13850a708f8fSGustavo F. Padovan 
13860a708f8fSGustavo F. Padovan 	hdev = hci_get_route(dst, src);
13870a708f8fSGustavo F. Padovan 	if (!hdev)
13880a708f8fSGustavo F. Padovan 		return -EHOSTUNREACH;
13890a708f8fSGustavo F. Padovan 
139009fd0de5SGustavo F. Padovan 	hci_dev_lock(hdev);
13910a708f8fSGustavo F. Padovan 
13926be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
139303a00194SGustavo F. Padovan 
139403a00194SGustavo F. Padovan 	/* PSM must be odd and lsb of upper byte must be 0 */
139503a00194SGustavo F. Padovan 	if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
139603a00194SGustavo F. Padovan 					chan->chan_type != L2CAP_CHAN_RAW) {
139703a00194SGustavo F. Padovan 		err = -EINVAL;
139803a00194SGustavo F. Padovan 		goto done;
139903a00194SGustavo F. Padovan 	}
140003a00194SGustavo F. Padovan 
140103a00194SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
140203a00194SGustavo F. Padovan 		err = -EINVAL;
140303a00194SGustavo F. Padovan 		goto done;
140403a00194SGustavo F. Padovan 	}
140503a00194SGustavo F. Padovan 
140603a00194SGustavo F. Padovan 	switch (chan->mode) {
140703a00194SGustavo F. Padovan 	case L2CAP_MODE_BASIC:
140803a00194SGustavo F. Padovan 		break;
140903a00194SGustavo F. Padovan 	case L2CAP_MODE_ERTM:
141003a00194SGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
141103a00194SGustavo F. Padovan 		if (!disable_ertm)
141203a00194SGustavo F. Padovan 			break;
141303a00194SGustavo F. Padovan 		/* fall through */
141403a00194SGustavo F. Padovan 	default:
141503a00194SGustavo F. Padovan 		err = -ENOTSUPP;
141603a00194SGustavo F. Padovan 		goto done;
141703a00194SGustavo F. Padovan 	}
141803a00194SGustavo F. Padovan 
14196be36555SAndrei Emeltchenko 	lock_sock(sk);
14206be36555SAndrei Emeltchenko 
142103a00194SGustavo F. Padovan 	switch (sk->sk_state) {
142203a00194SGustavo F. Padovan 	case BT_CONNECT:
142303a00194SGustavo F. Padovan 	case BT_CONNECT2:
142403a00194SGustavo F. Padovan 	case BT_CONFIG:
142503a00194SGustavo F. Padovan 		/* Already connecting */
142603a00194SGustavo F. Padovan 		err = 0;
14276be36555SAndrei Emeltchenko 		release_sock(sk);
142803a00194SGustavo F. Padovan 		goto done;
142903a00194SGustavo F. Padovan 
143003a00194SGustavo F. Padovan 	case BT_CONNECTED:
143103a00194SGustavo F. Padovan 		/* Already connected */
143203a00194SGustavo F. Padovan 		err = -EISCONN;
14336be36555SAndrei Emeltchenko 		release_sock(sk);
143403a00194SGustavo F. Padovan 		goto done;
143503a00194SGustavo F. Padovan 
143603a00194SGustavo F. Padovan 	case BT_OPEN:
143703a00194SGustavo F. Padovan 	case BT_BOUND:
143803a00194SGustavo F. Padovan 		/* Can connect */
143903a00194SGustavo F. Padovan 		break;
144003a00194SGustavo F. Padovan 
144103a00194SGustavo F. Padovan 	default:
144203a00194SGustavo F. Padovan 		err = -EBADFD;
14436be36555SAndrei Emeltchenko 		release_sock(sk);
144403a00194SGustavo F. Padovan 		goto done;
144503a00194SGustavo F. Padovan 	}
144603a00194SGustavo F. Padovan 
144703a00194SGustavo F. Padovan 	/* Set destination address and psm */
14489219b2a0SGustavo F. Padovan 	bacpy(&bt_sk(sk)->dst, dst);
14496be36555SAndrei Emeltchenko 
14506be36555SAndrei Emeltchenko 	release_sock(sk);
14516be36555SAndrei Emeltchenko 
145203a00194SGustavo F. Padovan 	chan->psm = psm;
145303a00194SGustavo F. Padovan 	chan->dcid = cid;
14540a708f8fSGustavo F. Padovan 
14554343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
14560a708f8fSGustavo F. Padovan 
1457fe4128e0SGustavo F. Padovan 	if (chan->dcid == L2CAP_CID_LE_DATA)
1458acd7d370SVille Tervo 		hcon = hci_connect(hdev, LE_LINK, dst,
14594343478fSGustavo F. Padovan 					chan->sec_level, auth_type);
1460acd7d370SVille Tervo 	else
14610a708f8fSGustavo F. Padovan 		hcon = hci_connect(hdev, ACL_LINK, dst,
14624343478fSGustavo F. Padovan 					chan->sec_level, auth_type);
1463acd7d370SVille Tervo 
146430e76272SVille Tervo 	if (IS_ERR(hcon)) {
146530e76272SVille Tervo 		err = PTR_ERR(hcon);
14660a708f8fSGustavo F. Padovan 		goto done;
146730e76272SVille Tervo 	}
14680a708f8fSGustavo F. Padovan 
14690a708f8fSGustavo F. Padovan 	conn = l2cap_conn_add(hcon, 0);
14700a708f8fSGustavo F. Padovan 	if (!conn) {
14710a708f8fSGustavo F. Padovan 		hci_conn_put(hcon);
147230e76272SVille Tervo 		err = -ENOMEM;
14730a708f8fSGustavo F. Padovan 		goto done;
14740a708f8fSGustavo F. Padovan 	}
14750a708f8fSGustavo F. Padovan 
14760a708f8fSGustavo F. Padovan 	/* Update source addr of the socket */
14770a708f8fSGustavo F. Padovan 	bacpy(src, conn->src);
14780a708f8fSGustavo F. Padovan 
14796be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
148048454079SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
14816be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
148248454079SGustavo F. Padovan 
14836be36555SAndrei Emeltchenko 	l2cap_state_change(chan, BT_CONNECT);
1484c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
14850a708f8fSGustavo F. Padovan 
14860a708f8fSGustavo F. Padovan 	if (hcon->state == BT_CONNECTED) {
1487715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1488c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
1489d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan))
14906be36555SAndrei Emeltchenko 				l2cap_state_change(chan, BT_CONNECTED);
14910a708f8fSGustavo F. Padovan 		} else
1492fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
14930a708f8fSGustavo F. Padovan 	}
14940a708f8fSGustavo F. Padovan 
149530e76272SVille Tervo 	err = 0;
149630e76272SVille Tervo 
14970a708f8fSGustavo F. Padovan done:
14986be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
149909fd0de5SGustavo F. Padovan 	hci_dev_unlock(hdev);
15000a708f8fSGustavo F. Padovan 	hci_dev_put(hdev);
15010a708f8fSGustavo F. Padovan 	return err;
15020a708f8fSGustavo F. Padovan }
15030a708f8fSGustavo F. Padovan 
1504dcba0dbaSGustavo F. Padovan int __l2cap_wait_ack(struct sock *sk)
15050a708f8fSGustavo F. Padovan {
15068c1d787bSGustavo F. Padovan 	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
15070a708f8fSGustavo F. Padovan 	DECLARE_WAITQUEUE(wait, current);
15080a708f8fSGustavo F. Padovan 	int err = 0;
15090a708f8fSGustavo F. Padovan 	int timeo = HZ/5;
15100a708f8fSGustavo F. Padovan 
15110a708f8fSGustavo F. Padovan 	add_wait_queue(sk_sleep(sk), &wait);
15120a708f8fSGustavo F. Padovan 	set_current_state(TASK_INTERRUPTIBLE);
1513a71a0cf4SPeter Hurley 	while (chan->unacked_frames > 0 && chan->conn) {
15140a708f8fSGustavo F. Padovan 		if (!timeo)
15150a708f8fSGustavo F. Padovan 			timeo = HZ/5;
15160a708f8fSGustavo F. Padovan 
15170a708f8fSGustavo F. Padovan 		if (signal_pending(current)) {
15180a708f8fSGustavo F. Padovan 			err = sock_intr_errno(timeo);
15190a708f8fSGustavo F. Padovan 			break;
15200a708f8fSGustavo F. Padovan 		}
15210a708f8fSGustavo F. Padovan 
15220a708f8fSGustavo F. Padovan 		release_sock(sk);
15230a708f8fSGustavo F. Padovan 		timeo = schedule_timeout(timeo);
15240a708f8fSGustavo F. Padovan 		lock_sock(sk);
1525a71a0cf4SPeter Hurley 		set_current_state(TASK_INTERRUPTIBLE);
15260a708f8fSGustavo F. Padovan 
15270a708f8fSGustavo F. Padovan 		err = sock_error(sk);
15280a708f8fSGustavo F. Padovan 		if (err)
15290a708f8fSGustavo F. Padovan 			break;
15300a708f8fSGustavo F. Padovan 	}
15310a708f8fSGustavo F. Padovan 	set_current_state(TASK_RUNNING);
15320a708f8fSGustavo F. Padovan 	remove_wait_queue(sk_sleep(sk), &wait);
15330a708f8fSGustavo F. Padovan 	return err;
15340a708f8fSGustavo F. Padovan }
15350a708f8fSGustavo F. Padovan 
1536721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work)
15370a708f8fSGustavo F. Padovan {
1538721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1539721c4181SGustavo F. Padovan 							monitor_timer.work);
15400a708f8fSGustavo F. Padovan 
1541525cd185SGustavo F. Padovan 	BT_DBG("chan %p", chan);
15420a708f8fSGustavo F. Padovan 
15436be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
15446be36555SAndrei Emeltchenko 
15452c03a7a4SGustavo F. Padovan 	if (chan->retry_count >= chan->remote_max_tx) {
15468c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
15476be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
15488d7e1c7fSAndrei Emeltchenko 		l2cap_chan_put(chan);
15490a708f8fSGustavo F. Padovan 		return;
15500a708f8fSGustavo F. Padovan 	}
15510a708f8fSGustavo F. Padovan 
15526a026610SGustavo F. Padovan 	chan->retry_count++;
15531a09bcb9SGustavo F. Padovan 	__set_monitor_timer(chan);
15540a708f8fSGustavo F. Padovan 
1555525cd185SGustavo F. Padovan 	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
15566be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
15578d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
15580a708f8fSGustavo F. Padovan }
15590a708f8fSGustavo F. Padovan 
1560721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work)
15610a708f8fSGustavo F. Padovan {
1562721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1563721c4181SGustavo F. Padovan 							retrans_timer.work);
15640a708f8fSGustavo F. Padovan 
156549208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
15660a708f8fSGustavo F. Padovan 
15676be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
15686be36555SAndrei Emeltchenko 
15696a026610SGustavo F. Padovan 	chan->retry_count = 1;
15701a09bcb9SGustavo F. Padovan 	__set_monitor_timer(chan);
15710a708f8fSGustavo F. Padovan 
1572e2ab4353SGustavo F. Padovan 	set_bit(CONN_WAIT_F, &chan->conn_state);
15730a708f8fSGustavo F. Padovan 
1574525cd185SGustavo F. Padovan 	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
15756be36555SAndrei Emeltchenko 
15766be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
15778d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
15780a708f8fSGustavo F. Padovan }
15790a708f8fSGustavo F. Padovan 
158042e5c802SGustavo F. Padovan static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
15810a708f8fSGustavo F. Padovan {
15820a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
15830a708f8fSGustavo F. Padovan 
158458d35f87SGustavo F. Padovan 	while ((skb = skb_peek(&chan->tx_q)) &&
15856a026610SGustavo F. Padovan 			chan->unacked_frames) {
158642e5c802SGustavo F. Padovan 		if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
15870a708f8fSGustavo F. Padovan 			break;
15880a708f8fSGustavo F. Padovan 
158958d35f87SGustavo F. Padovan 		skb = skb_dequeue(&chan->tx_q);
15900a708f8fSGustavo F. Padovan 		kfree_skb(skb);
15910a708f8fSGustavo F. Padovan 
15926a026610SGustavo F. Padovan 		chan->unacked_frames--;
15930a708f8fSGustavo F. Padovan 	}
15940a708f8fSGustavo F. Padovan 
15956a026610SGustavo F. Padovan 	if (!chan->unacked_frames)
15961a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
15970a708f8fSGustavo F. Padovan }
15980a708f8fSGustavo F. Padovan 
159967c9e840SSzymon Janc static void l2cap_streaming_send(struct l2cap_chan *chan)
16000a708f8fSGustavo F. Padovan {
16010a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
160288843ab0SAndrei Emeltchenko 	u32 control;
160388843ab0SAndrei Emeltchenko 	u16 fcs;
16040a708f8fSGustavo F. Padovan 
160558d35f87SGustavo F. Padovan 	while ((skb = skb_dequeue(&chan->tx_q))) {
160688843ab0SAndrei Emeltchenko 		control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
1607fb45de7dSAndrei Emeltchenko 		control |= __set_txseq(chan, chan->next_tx_seq);
160888843ab0SAndrei Emeltchenko 		__put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
16090a708f8fSGustavo F. Padovan 
161047d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
161103a51213SAndrei Emeltchenko 			fcs = crc16(0, (u8 *)skb->data,
161203a51213SAndrei Emeltchenko 						skb->len - L2CAP_FCS_SIZE);
161303a51213SAndrei Emeltchenko 			put_unaligned_le16(fcs,
161403a51213SAndrei Emeltchenko 					skb->data + skb->len - L2CAP_FCS_SIZE);
16150a708f8fSGustavo F. Padovan 		}
16160a708f8fSGustavo F. Padovan 
16174343478fSGustavo F. Padovan 		l2cap_do_send(chan, skb);
16180a708f8fSGustavo F. Padovan 
1619836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
16200a708f8fSGustavo F. Padovan 	}
16210a708f8fSGustavo F. Padovan }
16220a708f8fSGustavo F. Padovan 
1623fb45de7dSAndrei Emeltchenko static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
16240a708f8fSGustavo F. Padovan {
16250a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
162688843ab0SAndrei Emeltchenko 	u16 fcs;
162788843ab0SAndrei Emeltchenko 	u32 control;
16280a708f8fSGustavo F. Padovan 
162958d35f87SGustavo F. Padovan 	skb = skb_peek(&chan->tx_q);
16300a708f8fSGustavo F. Padovan 	if (!skb)
16310a708f8fSGustavo F. Padovan 		return;
16320a708f8fSGustavo F. Padovan 
1633d1726b6dSSzymon Janc 	while (bt_cb(skb)->tx_seq != tx_seq) {
163458d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
16350a708f8fSGustavo F. Padovan 			return;
16360a708f8fSGustavo F. Padovan 
1637d1726b6dSSzymon Janc 		skb = skb_queue_next(&chan->tx_q, skb);
1638d1726b6dSSzymon Janc 	}
16390a708f8fSGustavo F. Padovan 
16402c03a7a4SGustavo F. Padovan 	if (chan->remote_max_tx &&
16412c03a7a4SGustavo F. Padovan 			bt_cb(skb)->retries == chan->remote_max_tx) {
16428c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
16430a708f8fSGustavo F. Padovan 		return;
16440a708f8fSGustavo F. Padovan 	}
16450a708f8fSGustavo F. Padovan 
16460a708f8fSGustavo F. Padovan 	tx_skb = skb_clone(skb, GFP_ATOMIC);
16470a708f8fSGustavo F. Padovan 	bt_cb(skb)->retries++;
164888843ab0SAndrei Emeltchenko 
164988843ab0SAndrei Emeltchenko 	control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
16507e0ef6eeSAndrei Emeltchenko 	control &= __get_sar_mask(chan);
16510a708f8fSGustavo F. Padovan 
1652e2ab4353SGustavo F. Padovan 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
165303f6715dSAndrei Emeltchenko 		control |= __set_ctrl_final(chan);
16540a708f8fSGustavo F. Padovan 
16550b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
1656fb45de7dSAndrei Emeltchenko 	control |= __set_txseq(chan, tx_seq);
16570a708f8fSGustavo F. Padovan 
165888843ab0SAndrei Emeltchenko 	__put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
16590a708f8fSGustavo F. Padovan 
166047d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
166103a51213SAndrei Emeltchenko 		fcs = crc16(0, (u8 *)tx_skb->data,
166203a51213SAndrei Emeltchenko 						tx_skb->len - L2CAP_FCS_SIZE);
166303a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs,
166403a51213SAndrei Emeltchenko 				tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
16650a708f8fSGustavo F. Padovan 	}
16660a708f8fSGustavo F. Padovan 
16674343478fSGustavo F. Padovan 	l2cap_do_send(chan, tx_skb);
16680a708f8fSGustavo F. Padovan }
16690a708f8fSGustavo F. Padovan 
167067c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan)
16710a708f8fSGustavo F. Padovan {
16720a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
167388843ab0SAndrei Emeltchenko 	u16 fcs;
167488843ab0SAndrei Emeltchenko 	u32 control;
16750a708f8fSGustavo F. Padovan 	int nsent = 0;
16760a708f8fSGustavo F. Padovan 
167789bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
16780a708f8fSGustavo F. Padovan 		return -ENOTCONN;
16790a708f8fSGustavo F. Padovan 
168058d35f87SGustavo F. Padovan 	while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
16810a708f8fSGustavo F. Padovan 
16822c03a7a4SGustavo F. Padovan 		if (chan->remote_max_tx &&
16832c03a7a4SGustavo F. Padovan 				bt_cb(skb)->retries == chan->remote_max_tx) {
16848c1d787bSGustavo F. Padovan 			l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
16850a708f8fSGustavo F. Padovan 			break;
16860a708f8fSGustavo F. Padovan 		}
16870a708f8fSGustavo F. Padovan 
16880a708f8fSGustavo F. Padovan 		tx_skb = skb_clone(skb, GFP_ATOMIC);
16890a708f8fSGustavo F. Padovan 
16900a708f8fSGustavo F. Padovan 		bt_cb(skb)->retries++;
16910a708f8fSGustavo F. Padovan 
169288843ab0SAndrei Emeltchenko 		control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
16937e0ef6eeSAndrei Emeltchenko 		control &= __get_sar_mask(chan);
16940a708f8fSGustavo F. Padovan 
1695e2ab4353SGustavo F. Padovan 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
169603f6715dSAndrei Emeltchenko 			control |= __set_ctrl_final(chan);
1697e2ab4353SGustavo F. Padovan 
16980b209faeSAndrei Emeltchenko 		control |= __set_reqseq(chan, chan->buffer_seq);
1699fb45de7dSAndrei Emeltchenko 		control |= __set_txseq(chan, chan->next_tx_seq);
17000a708f8fSGustavo F. Padovan 
170188843ab0SAndrei Emeltchenko 		__put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
17020a708f8fSGustavo F. Padovan 
170347d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
170403a51213SAndrei Emeltchenko 			fcs = crc16(0, (u8 *)skb->data,
170503a51213SAndrei Emeltchenko 						tx_skb->len - L2CAP_FCS_SIZE);
170603a51213SAndrei Emeltchenko 			put_unaligned_le16(fcs, skb->data +
170703a51213SAndrei Emeltchenko 						tx_skb->len - L2CAP_FCS_SIZE);
17080a708f8fSGustavo F. Padovan 		}
17090a708f8fSGustavo F. Padovan 
17104343478fSGustavo F. Padovan 		l2cap_do_send(chan, tx_skb);
17110a708f8fSGustavo F. Padovan 
17121a09bcb9SGustavo F. Padovan 		__set_retrans_timer(chan);
17130a708f8fSGustavo F. Padovan 
171442e5c802SGustavo F. Padovan 		bt_cb(skb)->tx_seq = chan->next_tx_seq;
1715836be934SAndrei Emeltchenko 
1716836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
17170a708f8fSGustavo F. Padovan 
17188ed7a0aeSSzymon Janc 		if (bt_cb(skb)->retries == 1) {
17196a026610SGustavo F. Padovan 			chan->unacked_frames++;
1720930fa4aeSSzymon Janc 
1721930fa4aeSSzymon Janc 			if (!nsent++)
1722930fa4aeSSzymon Janc 				__clear_ack_timer(chan);
17238ed7a0aeSSzymon Janc 		}
172423e9fde2SSuraj Sumangala 
17256a026610SGustavo F. Padovan 		chan->frames_sent++;
17260a708f8fSGustavo F. Padovan 
172758d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
172858d35f87SGustavo F. Padovan 			chan->tx_send_head = NULL;
17290a708f8fSGustavo F. Padovan 		else
173058d35f87SGustavo F. Padovan 			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
17310a708f8fSGustavo F. Padovan 	}
17320a708f8fSGustavo F. Padovan 
17330a708f8fSGustavo F. Padovan 	return nsent;
17340a708f8fSGustavo F. Padovan }
17350a708f8fSGustavo F. Padovan 
1736525cd185SGustavo F. Padovan static int l2cap_retransmit_frames(struct l2cap_chan *chan)
17370a708f8fSGustavo F. Padovan {
17380a708f8fSGustavo F. Padovan 	int ret;
17390a708f8fSGustavo F. Padovan 
174058d35f87SGustavo F. Padovan 	if (!skb_queue_empty(&chan->tx_q))
174158d35f87SGustavo F. Padovan 		chan->tx_send_head = chan->tx_q.next;
17420a708f8fSGustavo F. Padovan 
174342e5c802SGustavo F. Padovan 	chan->next_tx_seq = chan->expected_ack_seq;
1744525cd185SGustavo F. Padovan 	ret = l2cap_ertm_send(chan);
17450a708f8fSGustavo F. Padovan 	return ret;
17460a708f8fSGustavo F. Padovan }
17470a708f8fSGustavo F. Padovan 
1748b17e73bbSSzymon Janc static void __l2cap_send_ack(struct l2cap_chan *chan)
17490a708f8fSGustavo F. Padovan {
175088843ab0SAndrei Emeltchenko 	u32 control = 0;
17510a708f8fSGustavo F. Padovan 
17520b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
17530a708f8fSGustavo F. Padovan 
1754e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
1755ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
1756e2ab4353SGustavo F. Padovan 		set_bit(CONN_RNR_SENT, &chan->conn_state);
1757525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
17580a708f8fSGustavo F. Padovan 		return;
17590a708f8fSGustavo F. Padovan 	}
17600a708f8fSGustavo F. Padovan 
1761525cd185SGustavo F. Padovan 	if (l2cap_ertm_send(chan) > 0)
17620a708f8fSGustavo F. Padovan 		return;
17630a708f8fSGustavo F. Padovan 
1764ab784b73SAndrei Emeltchenko 	control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
1765525cd185SGustavo F. Padovan 	l2cap_send_sframe(chan, control);
17660a708f8fSGustavo F. Padovan }
17670a708f8fSGustavo F. Padovan 
1768b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan)
1769b17e73bbSSzymon Janc {
1770b17e73bbSSzymon Janc 	__clear_ack_timer(chan);
1771b17e73bbSSzymon Janc 	__l2cap_send_ack(chan);
1772b17e73bbSSzymon Janc }
1773b17e73bbSSzymon Janc 
1774525cd185SGustavo F. Padovan static void l2cap_send_srejtail(struct l2cap_chan *chan)
17750a708f8fSGustavo F. Padovan {
17760a708f8fSGustavo F. Padovan 	struct srej_list *tail;
177788843ab0SAndrei Emeltchenko 	u32 control;
17780a708f8fSGustavo F. Padovan 
1779ab784b73SAndrei Emeltchenko 	control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
178003f6715dSAndrei Emeltchenko 	control |= __set_ctrl_final(chan);
17810a708f8fSGustavo F. Padovan 
178239d5a3eeSGustavo F. Padovan 	tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
17830b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, tail->tx_seq);
17840a708f8fSGustavo F. Padovan 
1785525cd185SGustavo F. Padovan 	l2cap_send_sframe(chan, control);
17860a708f8fSGustavo F. Padovan }
17870a708f8fSGustavo F. Padovan 
178804124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
178904124681SGustavo F. Padovan 					 struct msghdr *msg, int len,
179004124681SGustavo F. Padovan 					 int count, struct sk_buff *skb)
17910a708f8fSGustavo F. Padovan {
17920952a57aSAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
17930a708f8fSGustavo F. Padovan 	struct sk_buff **frag;
179490338947SGustavo Padovan 	int sent = 0;
17950a708f8fSGustavo F. Padovan 
17960a708f8fSGustavo F. Padovan 	if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
17970a708f8fSGustavo F. Padovan 		return -EFAULT;
17980a708f8fSGustavo F. Padovan 
17990a708f8fSGustavo F. Padovan 	sent += count;
18000a708f8fSGustavo F. Padovan 	len  -= count;
18010a708f8fSGustavo F. Padovan 
18020a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
18030a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
18040a708f8fSGustavo F. Padovan 	while (len) {
18050a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
18060a708f8fSGustavo F. Padovan 
18072f7719ceSAndrei Emeltchenko 		*frag = chan->ops->alloc_skb(chan, count,
180890338947SGustavo Padovan 					     msg->msg_flags & MSG_DONTWAIT);
18092f7719ceSAndrei Emeltchenko 
181090338947SGustavo Padovan 		if (IS_ERR(*frag))
181190338947SGustavo Padovan 			return PTR_ERR(*frag);
18120a708f8fSGustavo F. Padovan 		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
18130a708f8fSGustavo F. Padovan 			return -EFAULT;
18140a708f8fSGustavo F. Padovan 
18155e59b791SLuiz Augusto von Dentz 		(*frag)->priority = skb->priority;
18165e59b791SLuiz Augusto von Dentz 
18170a708f8fSGustavo F. Padovan 		sent += count;
18180a708f8fSGustavo F. Padovan 		len  -= count;
18190a708f8fSGustavo F. Padovan 
18200a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
18210a708f8fSGustavo F. Padovan 	}
18220a708f8fSGustavo F. Padovan 
18230a708f8fSGustavo F. Padovan 	return sent;
18240a708f8fSGustavo F. Padovan }
18250a708f8fSGustavo F. Padovan 
18265e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
18275e59b791SLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
18285e59b791SLuiz Augusto von Dentz 						u32 priority)
18290a708f8fSGustavo F. Padovan {
18308c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
18310a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
183203a51213SAndrei Emeltchenko 	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
18330a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
18340a708f8fSGustavo F. Padovan 
18356d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d priority %u", chan, (int)len, priority);
18360a708f8fSGustavo F. Padovan 
18370a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
18382f7719ceSAndrei Emeltchenko 
18392f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
184090338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
184190338947SGustavo Padovan 	if (IS_ERR(skb))
184290338947SGustavo Padovan 		return skb;
18430a708f8fSGustavo F. Padovan 
18445e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
18455e59b791SLuiz Augusto von Dentz 
18460a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
18470a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1848fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
18490a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1850097db76cSAndrei Emeltchenko 	put_unaligned(chan->psm, skb_put(skb, 2));
18510a708f8fSGustavo F. Padovan 
18520952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
18530a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
18540a708f8fSGustavo F. Padovan 		kfree_skb(skb);
18550a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
18560a708f8fSGustavo F. Padovan 	}
18570a708f8fSGustavo F. Padovan 	return skb;
18580a708f8fSGustavo F. Padovan }
18590a708f8fSGustavo F. Padovan 
18605e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
18615e59b791SLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
18625e59b791SLuiz Augusto von Dentz 						u32 priority)
18630a708f8fSGustavo F. Padovan {
18648c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
18650a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
18660a708f8fSGustavo F. Padovan 	int err, count, hlen = L2CAP_HDR_SIZE;
18670a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
18680a708f8fSGustavo F. Padovan 
18696d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d", chan, (int)len);
18700a708f8fSGustavo F. Padovan 
18710a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
18722f7719ceSAndrei Emeltchenko 
18732f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
187490338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
187590338947SGustavo Padovan 	if (IS_ERR(skb))
187690338947SGustavo Padovan 		return skb;
18770a708f8fSGustavo F. Padovan 
18785e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
18795e59b791SLuiz Augusto von Dentz 
18800a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
18810a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1882fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
18830a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
18840a708f8fSGustavo F. Padovan 
18850952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
18860a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
18870a708f8fSGustavo F. Padovan 		kfree_skb(skb);
18880a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
18890a708f8fSGustavo F. Padovan 	}
18900a708f8fSGustavo F. Padovan 	return skb;
18910a708f8fSGustavo F. Padovan }
18920a708f8fSGustavo F. Padovan 
1893ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1894ab0ff76dSLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
189588843ab0SAndrei Emeltchenko 						u32 control, u16 sdulen)
18960a708f8fSGustavo F. Padovan {
18978c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
18980a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
1899e4ca6d98SAndrei Emeltchenko 	int err, count, hlen;
19000a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
19010a708f8fSGustavo F. Padovan 
19026d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d", chan, (int)len);
19030a708f8fSGustavo F. Padovan 
19040a708f8fSGustavo F. Padovan 	if (!conn)
19050a708f8fSGustavo F. Padovan 		return ERR_PTR(-ENOTCONN);
19060a708f8fSGustavo F. Padovan 
1907e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1908e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_EXT_HDR_SIZE;
1909e4ca6d98SAndrei Emeltchenko 	else
1910e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_ENH_HDR_SIZE;
1911e4ca6d98SAndrei Emeltchenko 
19120a708f8fSGustavo F. Padovan 	if (sdulen)
191303a51213SAndrei Emeltchenko 		hlen += L2CAP_SDULEN_SIZE;
19140a708f8fSGustavo F. Padovan 
191547d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
191603a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
19170a708f8fSGustavo F. Padovan 
19180a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
19192f7719ceSAndrei Emeltchenko 
19202f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
192190338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
192290338947SGustavo Padovan 	if (IS_ERR(skb))
192390338947SGustavo Padovan 		return skb;
19240a708f8fSGustavo F. Padovan 
19250a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
19260a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1927fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
19280a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
192988843ab0SAndrei Emeltchenko 
193088843ab0SAndrei Emeltchenko 	__put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
193188843ab0SAndrei Emeltchenko 
19320a708f8fSGustavo F. Padovan 	if (sdulen)
193303a51213SAndrei Emeltchenko 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
19340a708f8fSGustavo F. Padovan 
19350952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
19360a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
19370a708f8fSGustavo F. Padovan 		kfree_skb(skb);
19380a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
19390a708f8fSGustavo F. Padovan 	}
19400a708f8fSGustavo F. Padovan 
194147d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
194203a51213SAndrei Emeltchenko 		put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
19430a708f8fSGustavo F. Padovan 
19440a708f8fSGustavo F. Padovan 	bt_cb(skb)->retries = 0;
19450a708f8fSGustavo F. Padovan 	return skb;
19460a708f8fSGustavo F. Padovan }
19470a708f8fSGustavo F. Padovan 
194867c9e840SSzymon Janc static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
19490a708f8fSGustavo F. Padovan {
19500a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
19510a708f8fSGustavo F. Padovan 	struct sk_buff_head sar_queue;
195288843ab0SAndrei Emeltchenko 	u32 control;
19530a708f8fSGustavo F. Padovan 	size_t size = 0;
19540a708f8fSGustavo F. Padovan 
19550a708f8fSGustavo F. Padovan 	skb_queue_head_init(&sar_queue);
19567e0ef6eeSAndrei Emeltchenko 	control = __set_ctrl_sar(chan, L2CAP_SAR_START);
195747d1ec61SGustavo F. Padovan 	skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
19580a708f8fSGustavo F. Padovan 	if (IS_ERR(skb))
19590a708f8fSGustavo F. Padovan 		return PTR_ERR(skb);
19600a708f8fSGustavo F. Padovan 
19610a708f8fSGustavo F. Padovan 	__skb_queue_tail(&sar_queue, skb);
19622c03a7a4SGustavo F. Padovan 	len -= chan->remote_mps;
19632c03a7a4SGustavo F. Padovan 	size += chan->remote_mps;
19640a708f8fSGustavo F. Padovan 
19650a708f8fSGustavo F. Padovan 	while (len > 0) {
19660a708f8fSGustavo F. Padovan 		size_t buflen;
19670a708f8fSGustavo F. Padovan 
19682c03a7a4SGustavo F. Padovan 		if (len > chan->remote_mps) {
19697e0ef6eeSAndrei Emeltchenko 			control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
19702c03a7a4SGustavo F. Padovan 			buflen = chan->remote_mps;
19710a708f8fSGustavo F. Padovan 		} else {
19727e0ef6eeSAndrei Emeltchenko 			control = __set_ctrl_sar(chan, L2CAP_SAR_END);
19730a708f8fSGustavo F. Padovan 			buflen = len;
19740a708f8fSGustavo F. Padovan 		}
19750a708f8fSGustavo F. Padovan 
197647d1ec61SGustavo F. Padovan 		skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
19770a708f8fSGustavo F. Padovan 		if (IS_ERR(skb)) {
19780a708f8fSGustavo F. Padovan 			skb_queue_purge(&sar_queue);
19790a708f8fSGustavo F. Padovan 			return PTR_ERR(skb);
19800a708f8fSGustavo F. Padovan 		}
19810a708f8fSGustavo F. Padovan 
19820a708f8fSGustavo F. Padovan 		__skb_queue_tail(&sar_queue, skb);
19830a708f8fSGustavo F. Padovan 		len -= buflen;
19840a708f8fSGustavo F. Padovan 		size += buflen;
19850a708f8fSGustavo F. Padovan 	}
198658d35f87SGustavo F. Padovan 	skb_queue_splice_tail(&sar_queue, &chan->tx_q);
198758d35f87SGustavo F. Padovan 	if (chan->tx_send_head == NULL)
198858d35f87SGustavo F. Padovan 		chan->tx_send_head = sar_queue.next;
19890a708f8fSGustavo F. Padovan 
19900a708f8fSGustavo F. Padovan 	return size;
19910a708f8fSGustavo F. Padovan }
19920a708f8fSGustavo F. Padovan 
19935e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
19945e59b791SLuiz Augusto von Dentz 								u32 priority)
19959a91a04aSGustavo F. Padovan {
19969a91a04aSGustavo F. Padovan 	struct sk_buff *skb;
199788843ab0SAndrei Emeltchenko 	u32 control;
19989a91a04aSGustavo F. Padovan 	int err;
19999a91a04aSGustavo F. Padovan 
20009a91a04aSGustavo F. Padovan 	/* Connectionless channel */
2001715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
20025e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_connless_pdu(chan, msg, len, priority);
20039a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
20049a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
20059a91a04aSGustavo F. Padovan 
20069a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
20079a91a04aSGustavo F. Padovan 		return len;
20089a91a04aSGustavo F. Padovan 	}
20099a91a04aSGustavo F. Padovan 
20109a91a04aSGustavo F. Padovan 	switch (chan->mode) {
20119a91a04aSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
20129a91a04aSGustavo F. Padovan 		/* Check outgoing MTU */
20139a91a04aSGustavo F. Padovan 		if (len > chan->omtu)
20149a91a04aSGustavo F. Padovan 			return -EMSGSIZE;
20159a91a04aSGustavo F. Padovan 
20169a91a04aSGustavo F. Padovan 		/* Create a basic PDU */
20175e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_basic_pdu(chan, msg, len, priority);
20189a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
20199a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
20209a91a04aSGustavo F. Padovan 
20219a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
20229a91a04aSGustavo F. Padovan 		err = len;
20239a91a04aSGustavo F. Padovan 		break;
20249a91a04aSGustavo F. Padovan 
20259a91a04aSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
20269a91a04aSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
20279a91a04aSGustavo F. Padovan 		/* Entire SDU fits into one PDU */
20289a91a04aSGustavo F. Padovan 		if (len <= chan->remote_mps) {
20297e0ef6eeSAndrei Emeltchenko 			control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
20309a91a04aSGustavo F. Padovan 			skb = l2cap_create_iframe_pdu(chan, msg, len, control,
20319a91a04aSGustavo F. Padovan 									0);
20329a91a04aSGustavo F. Padovan 			if (IS_ERR(skb))
20339a91a04aSGustavo F. Padovan 				return PTR_ERR(skb);
20349a91a04aSGustavo F. Padovan 
20359a91a04aSGustavo F. Padovan 			__skb_queue_tail(&chan->tx_q, skb);
20369a91a04aSGustavo F. Padovan 
20379a91a04aSGustavo F. Padovan 			if (chan->tx_send_head == NULL)
20389a91a04aSGustavo F. Padovan 				chan->tx_send_head = skb;
20399a91a04aSGustavo F. Padovan 
20409a91a04aSGustavo F. Padovan 		} else {
20419a91a04aSGustavo F. Padovan 			/* Segment SDU into multiples PDUs */
20429a91a04aSGustavo F. Padovan 			err = l2cap_sar_segment_sdu(chan, msg, len);
20439a91a04aSGustavo F. Padovan 			if (err < 0)
20449a91a04aSGustavo F. Padovan 				return err;
20459a91a04aSGustavo F. Padovan 		}
20469a91a04aSGustavo F. Padovan 
20479a91a04aSGustavo F. Padovan 		if (chan->mode == L2CAP_MODE_STREAMING) {
20489a91a04aSGustavo F. Padovan 			l2cap_streaming_send(chan);
20499a91a04aSGustavo F. Padovan 			err = len;
20509a91a04aSGustavo F. Padovan 			break;
20519a91a04aSGustavo F. Padovan 		}
20529a91a04aSGustavo F. Padovan 
2053e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
2054e2ab4353SGustavo F. Padovan 				test_bit(CONN_WAIT_F, &chan->conn_state)) {
20559a91a04aSGustavo F. Padovan 			err = len;
20569a91a04aSGustavo F. Padovan 			break;
20579a91a04aSGustavo F. Padovan 		}
20589a91a04aSGustavo F. Padovan 
20599a91a04aSGustavo F. Padovan 		err = l2cap_ertm_send(chan);
20609a91a04aSGustavo F. Padovan 		if (err >= 0)
20619a91a04aSGustavo F. Padovan 			err = len;
20629a91a04aSGustavo F. Padovan 
20639a91a04aSGustavo F. Padovan 		break;
20649a91a04aSGustavo F. Padovan 
20659a91a04aSGustavo F. Padovan 	default:
20669a91a04aSGustavo F. Padovan 		BT_DBG("bad state %1.1x", chan->mode);
20679a91a04aSGustavo F. Padovan 		err = -EBADFD;
20689a91a04aSGustavo F. Padovan 	}
20699a91a04aSGustavo F. Padovan 
20709a91a04aSGustavo F. Padovan 	return err;
20719a91a04aSGustavo F. Padovan }
20729a91a04aSGustavo F. Padovan 
20730a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */
20740a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
20750a708f8fSGustavo F. Padovan {
20760a708f8fSGustavo F. Padovan 	struct sk_buff *nskb;
207748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
20780a708f8fSGustavo F. Padovan 
20790a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
20800a708f8fSGustavo F. Padovan 
20813df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
20823d57dc68SGustavo F. Padovan 
20833df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
208448454079SGustavo F. Padovan 		struct sock *sk = chan->sk;
2085715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_RAW)
20860a708f8fSGustavo F. Padovan 			continue;
20870a708f8fSGustavo F. Padovan 
20880a708f8fSGustavo F. Padovan 		/* Don't send frame to the socket it came from */
20890a708f8fSGustavo F. Padovan 		if (skb->sk == sk)
20900a708f8fSGustavo F. Padovan 			continue;
20910a708f8fSGustavo F. Padovan 		nskb = skb_clone(skb, GFP_ATOMIC);
20920a708f8fSGustavo F. Padovan 		if (!nskb)
20930a708f8fSGustavo F. Padovan 			continue;
20940a708f8fSGustavo F. Padovan 
209523070494SGustavo F. Padovan 		if (chan->ops->recv(chan->data, nskb))
20960a708f8fSGustavo F. Padovan 			kfree_skb(nskb);
20970a708f8fSGustavo F. Padovan 	}
20983d57dc68SGustavo F. Padovan 
20993df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
21000a708f8fSGustavo F. Padovan }
21010a708f8fSGustavo F. Padovan 
21020a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
21030a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
21040a708f8fSGustavo F. Padovan 				u8 code, u8 ident, u16 dlen, void *data)
21050a708f8fSGustavo F. Padovan {
21060a708f8fSGustavo F. Padovan 	struct sk_buff *skb, **frag;
21070a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr *cmd;
21080a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
21090a708f8fSGustavo F. Padovan 	int len, count;
21100a708f8fSGustavo F. Padovan 
21110a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
21120a708f8fSGustavo F. Padovan 			conn, code, ident, dlen);
21130a708f8fSGustavo F. Padovan 
21140a708f8fSGustavo F. Padovan 	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
21150a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, len);
21160a708f8fSGustavo F. Padovan 
21170a708f8fSGustavo F. Padovan 	skb = bt_skb_alloc(count, GFP_ATOMIC);
21180a708f8fSGustavo F. Padovan 	if (!skb)
21190a708f8fSGustavo F. Padovan 		return NULL;
21200a708f8fSGustavo F. Padovan 
21210a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
21220a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
21233300d9a9SClaudio Takahasi 
21243300d9a9SClaudio Takahasi 	if (conn->hcon->type == LE_LINK)
21253300d9a9SClaudio Takahasi 		lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
21263300d9a9SClaudio Takahasi 	else
21270a708f8fSGustavo F. Padovan 		lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
21280a708f8fSGustavo F. Padovan 
21290a708f8fSGustavo F. Padovan 	cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
21300a708f8fSGustavo F. Padovan 	cmd->code  = code;
21310a708f8fSGustavo F. Padovan 	cmd->ident = ident;
21320a708f8fSGustavo F. Padovan 	cmd->len   = cpu_to_le16(dlen);
21330a708f8fSGustavo F. Padovan 
21340a708f8fSGustavo F. Padovan 	if (dlen) {
21350a708f8fSGustavo F. Padovan 		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
21360a708f8fSGustavo F. Padovan 		memcpy(skb_put(skb, count), data, count);
21370a708f8fSGustavo F. Padovan 		data += count;
21380a708f8fSGustavo F. Padovan 	}
21390a708f8fSGustavo F. Padovan 
21400a708f8fSGustavo F. Padovan 	len -= skb->len;
21410a708f8fSGustavo F. Padovan 
21420a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
21430a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
21440a708f8fSGustavo F. Padovan 	while (len) {
21450a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
21460a708f8fSGustavo F. Padovan 
21470a708f8fSGustavo F. Padovan 		*frag = bt_skb_alloc(count, GFP_ATOMIC);
21480a708f8fSGustavo F. Padovan 		if (!*frag)
21490a708f8fSGustavo F. Padovan 			goto fail;
21500a708f8fSGustavo F. Padovan 
21510a708f8fSGustavo F. Padovan 		memcpy(skb_put(*frag, count), data, count);
21520a708f8fSGustavo F. Padovan 
21530a708f8fSGustavo F. Padovan 		len  -= count;
21540a708f8fSGustavo F. Padovan 		data += count;
21550a708f8fSGustavo F. Padovan 
21560a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
21570a708f8fSGustavo F. Padovan 	}
21580a708f8fSGustavo F. Padovan 
21590a708f8fSGustavo F. Padovan 	return skb;
21600a708f8fSGustavo F. Padovan 
21610a708f8fSGustavo F. Padovan fail:
21620a708f8fSGustavo F. Padovan 	kfree_skb(skb);
21630a708f8fSGustavo F. Padovan 	return NULL;
21640a708f8fSGustavo F. Padovan }
21650a708f8fSGustavo F. Padovan 
21660a708f8fSGustavo F. Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
21670a708f8fSGustavo F. Padovan {
21680a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
21690a708f8fSGustavo F. Padovan 	int len;
21700a708f8fSGustavo F. Padovan 
21710a708f8fSGustavo F. Padovan 	len = L2CAP_CONF_OPT_SIZE + opt->len;
21720a708f8fSGustavo F. Padovan 	*ptr += len;
21730a708f8fSGustavo F. Padovan 
21740a708f8fSGustavo F. Padovan 	*type = opt->type;
21750a708f8fSGustavo F. Padovan 	*olen = opt->len;
21760a708f8fSGustavo F. Padovan 
21770a708f8fSGustavo F. Padovan 	switch (opt->len) {
21780a708f8fSGustavo F. Padovan 	case 1:
21790a708f8fSGustavo F. Padovan 		*val = *((u8 *) opt->val);
21800a708f8fSGustavo F. Padovan 		break;
21810a708f8fSGustavo F. Padovan 
21820a708f8fSGustavo F. Padovan 	case 2:
21830a708f8fSGustavo F. Padovan 		*val = get_unaligned_le16(opt->val);
21840a708f8fSGustavo F. Padovan 		break;
21850a708f8fSGustavo F. Padovan 
21860a708f8fSGustavo F. Padovan 	case 4:
21870a708f8fSGustavo F. Padovan 		*val = get_unaligned_le32(opt->val);
21880a708f8fSGustavo F. Padovan 		break;
21890a708f8fSGustavo F. Padovan 
21900a708f8fSGustavo F. Padovan 	default:
21910a708f8fSGustavo F. Padovan 		*val = (unsigned long) opt->val;
21920a708f8fSGustavo F. Padovan 		break;
21930a708f8fSGustavo F. Padovan 	}
21940a708f8fSGustavo F. Padovan 
21950a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
21960a708f8fSGustavo F. Padovan 	return len;
21970a708f8fSGustavo F. Padovan }
21980a708f8fSGustavo F. Padovan 
21990a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
22000a708f8fSGustavo F. Padovan {
22010a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
22020a708f8fSGustavo F. Padovan 
22030a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
22040a708f8fSGustavo F. Padovan 
22050a708f8fSGustavo F. Padovan 	opt->type = type;
22060a708f8fSGustavo F. Padovan 	opt->len  = len;
22070a708f8fSGustavo F. Padovan 
22080a708f8fSGustavo F. Padovan 	switch (len) {
22090a708f8fSGustavo F. Padovan 	case 1:
22100a708f8fSGustavo F. Padovan 		*((u8 *) opt->val)  = val;
22110a708f8fSGustavo F. Padovan 		break;
22120a708f8fSGustavo F. Padovan 
22130a708f8fSGustavo F. Padovan 	case 2:
22140a708f8fSGustavo F. Padovan 		put_unaligned_le16(val, opt->val);
22150a708f8fSGustavo F. Padovan 		break;
22160a708f8fSGustavo F. Padovan 
22170a708f8fSGustavo F. Padovan 	case 4:
22180a708f8fSGustavo F. Padovan 		put_unaligned_le32(val, opt->val);
22190a708f8fSGustavo F. Padovan 		break;
22200a708f8fSGustavo F. Padovan 
22210a708f8fSGustavo F. Padovan 	default:
22220a708f8fSGustavo F. Padovan 		memcpy(opt->val, (void *) val, len);
22230a708f8fSGustavo F. Padovan 		break;
22240a708f8fSGustavo F. Padovan 	}
22250a708f8fSGustavo F. Padovan 
22260a708f8fSGustavo F. Padovan 	*ptr += L2CAP_CONF_OPT_SIZE + len;
22270a708f8fSGustavo F. Padovan }
22280a708f8fSGustavo F. Padovan 
2229f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
2230f89cef09SAndrei Emeltchenko {
2231f89cef09SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
2232f89cef09SAndrei Emeltchenko 
2233f89cef09SAndrei Emeltchenko 	switch (chan->mode) {
2234f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_ERTM:
2235f89cef09SAndrei Emeltchenko 		efs.id		= chan->local_id;
2236f89cef09SAndrei Emeltchenko 		efs.stype	= chan->local_stype;
2237f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
2238f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
2239f89cef09SAndrei Emeltchenko 		efs.acc_lat	= cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
2240f89cef09SAndrei Emeltchenko 		efs.flush_to	= cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
2241f89cef09SAndrei Emeltchenko 		break;
2242f89cef09SAndrei Emeltchenko 
2243f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_STREAMING:
2244f89cef09SAndrei Emeltchenko 		efs.id		= 1;
2245f89cef09SAndrei Emeltchenko 		efs.stype	= L2CAP_SERV_BESTEFFORT;
2246f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
2247f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
2248f89cef09SAndrei Emeltchenko 		efs.acc_lat	= 0;
2249f89cef09SAndrei Emeltchenko 		efs.flush_to	= 0;
2250f89cef09SAndrei Emeltchenko 		break;
2251f89cef09SAndrei Emeltchenko 
2252f89cef09SAndrei Emeltchenko 	default:
2253f89cef09SAndrei Emeltchenko 		return;
2254f89cef09SAndrei Emeltchenko 	}
2255f89cef09SAndrei Emeltchenko 
2256f89cef09SAndrei Emeltchenko 	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
2257f89cef09SAndrei Emeltchenko 							(unsigned long) &efs);
2258f89cef09SAndrei Emeltchenko }
2259f89cef09SAndrei Emeltchenko 
2260721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
22610a708f8fSGustavo F. Padovan {
2262721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2263721c4181SGustavo F. Padovan 							ack_timer.work);
22640a708f8fSGustavo F. Padovan 
22652fb9b3d4SGustavo F. Padovan 	BT_DBG("chan %p", chan);
22662fb9b3d4SGustavo F. Padovan 
22676be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
22686be36555SAndrei Emeltchenko 
2269b17e73bbSSzymon Janc 	__l2cap_send_ack(chan);
22706be36555SAndrei Emeltchenko 
22716be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
227209bfb2eeSSzymon Janc 
227309bfb2eeSSzymon Janc 	l2cap_chan_put(chan);
22740a708f8fSGustavo F. Padovan }
22750a708f8fSGustavo F. Padovan 
22763c588192SMat Martineau static inline int l2cap_ertm_init(struct l2cap_chan *chan)
22770a708f8fSGustavo F. Padovan {
22783c588192SMat Martineau 	int err;
22793c588192SMat Martineau 
228042e5c802SGustavo F. Padovan 	chan->expected_ack_seq = 0;
22816a026610SGustavo F. Padovan 	chan->unacked_frames = 0;
228242e5c802SGustavo F. Padovan 	chan->buffer_seq = 0;
22836a026610SGustavo F. Padovan 	chan->num_acked = 0;
22846a026610SGustavo F. Padovan 	chan->frames_sent = 0;
22850a708f8fSGustavo F. Padovan 
2286721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
2287721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
2288721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
22890a708f8fSGustavo F. Padovan 
2290f1c6775bSGustavo F. Padovan 	skb_queue_head_init(&chan->srej_q);
22910a708f8fSGustavo F. Padovan 
229239d5a3eeSGustavo F. Padovan 	INIT_LIST_HEAD(&chan->srej_l);
22933c588192SMat Martineau 	err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
22943c588192SMat Martineau 	if (err < 0)
22953c588192SMat Martineau 		return err;
22963c588192SMat Martineau 
22973c588192SMat Martineau 	return l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
22980a708f8fSGustavo F. Padovan }
22990a708f8fSGustavo F. Padovan 
23000a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
23010a708f8fSGustavo F. Padovan {
23020a708f8fSGustavo F. Padovan 	switch (mode) {
23030a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
23040a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
23050a708f8fSGustavo F. Padovan 		if (l2cap_mode_supported(mode, remote_feat_mask))
23060a708f8fSGustavo F. Padovan 			return mode;
23070a708f8fSGustavo F. Padovan 		/* fall through */
23080a708f8fSGustavo F. Padovan 	default:
23090a708f8fSGustavo F. Padovan 		return L2CAP_MODE_BASIC;
23100a708f8fSGustavo F. Padovan 	}
23110a708f8fSGustavo F. Padovan }
23120a708f8fSGustavo F. Padovan 
23136327eb98SAndrei Emeltchenko static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
23146327eb98SAndrei Emeltchenko {
23156327eb98SAndrei Emeltchenko 	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
23166327eb98SAndrei Emeltchenko }
23176327eb98SAndrei Emeltchenko 
2318f89cef09SAndrei Emeltchenko static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2319f89cef09SAndrei Emeltchenko {
2320f89cef09SAndrei Emeltchenko 	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2321f89cef09SAndrei Emeltchenko }
2322f89cef09SAndrei Emeltchenko 
23236327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
23246327eb98SAndrei Emeltchenko {
23256327eb98SAndrei Emeltchenko 	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
2326836be934SAndrei Emeltchenko 						__l2cap_ews_supported(chan)) {
23276327eb98SAndrei Emeltchenko 		/* use extended control field */
23286327eb98SAndrei Emeltchenko 		set_bit(FLAG_EXT_CTRL, &chan->flags);
2329836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2330836be934SAndrei Emeltchenko 	} else {
23316327eb98SAndrei Emeltchenko 		chan->tx_win = min_t(u16, chan->tx_win,
23326327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_TX_WINDOW);
2333836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2334836be934SAndrei Emeltchenko 	}
23356327eb98SAndrei Emeltchenko }
23366327eb98SAndrei Emeltchenko 
2337710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
23380a708f8fSGustavo F. Padovan {
23390a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
23400c1bc5c6SGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
23410a708f8fSGustavo F. Padovan 	void *ptr = req->data;
2342c8f79162SAndrei Emeltchenko 	u16 size;
23430a708f8fSGustavo F. Padovan 
234449208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
23450a708f8fSGustavo F. Padovan 
234673ffa904SGustavo F. Padovan 	if (chan->num_conf_req || chan->num_conf_rsp)
23470a708f8fSGustavo F. Padovan 		goto done;
23480a708f8fSGustavo F. Padovan 
23490c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
23500a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
23510a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
2352c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
23530a708f8fSGustavo F. Padovan 			break;
23540a708f8fSGustavo F. Padovan 
2355f89cef09SAndrei Emeltchenko 		if (__l2cap_efs_supported(chan))
2356f89cef09SAndrei Emeltchenko 			set_bit(FLAG_EFS_ENABLE, &chan->flags);
2357f89cef09SAndrei Emeltchenko 
23580a708f8fSGustavo F. Padovan 		/* fall through */
23590a708f8fSGustavo F. Padovan 	default:
23608c1d787bSGustavo F. Padovan 		chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
23610a708f8fSGustavo F. Padovan 		break;
23620a708f8fSGustavo F. Padovan 	}
23630a708f8fSGustavo F. Padovan 
23640a708f8fSGustavo F. Padovan done:
23650c1bc5c6SGustavo F. Padovan 	if (chan->imtu != L2CAP_DEFAULT_MTU)
23660c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
23670a708f8fSGustavo F. Padovan 
23680c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
23690a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
23708c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
23718c1d787bSGustavo F. Padovan 				!(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
23720a708f8fSGustavo F. Padovan 			break;
23730a708f8fSGustavo F. Padovan 
23740a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_BASIC;
23750a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
23760a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
23770a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
23780a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
23790a708f8fSGustavo F. Padovan 		rfc.max_pdu_size    = 0;
23800a708f8fSGustavo F. Padovan 
23810a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
23820a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
23830a708f8fSGustavo F. Padovan 		break;
23840a708f8fSGustavo F. Padovan 
23850a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
23860a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_ERTM;
238747d1ec61SGustavo F. Padovan 		rfc.max_transmit    = chan->max_tx;
23880a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
23890a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
2390c8f79162SAndrei Emeltchenko 
2391c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2392c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2393c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2394c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2395c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
23960a708f8fSGustavo F. Padovan 
23976327eb98SAndrei Emeltchenko 		l2cap_txwin_setup(chan);
23986327eb98SAndrei Emeltchenko 
23996327eb98SAndrei Emeltchenko 		rfc.txwin_size = min_t(u16, chan->tx_win,
24006327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_TX_WINDOW);
24010a708f8fSGustavo F. Padovan 
24020a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
24030a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
24040a708f8fSGustavo F. Padovan 
2405f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2406f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
2407f89cef09SAndrei Emeltchenko 
24088c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
24090a708f8fSGustavo F. Padovan 			break;
24100a708f8fSGustavo F. Padovan 
241147d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_NONE ||
2412c1360a1cSGustavo F. Padovan 				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
241347d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
241447d1ec61SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
24150a708f8fSGustavo F. Padovan 		}
24166327eb98SAndrei Emeltchenko 
24176327eb98SAndrei Emeltchenko 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
24186327eb98SAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
24196327eb98SAndrei Emeltchenko 								chan->tx_win);
24200a708f8fSGustavo F. Padovan 		break;
24210a708f8fSGustavo F. Padovan 
24220a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
24230a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_STREAMING;
24240a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
24250a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
24260a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
24270a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
2428c8f79162SAndrei Emeltchenko 
2429c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2430c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2431c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2432c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2433c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
24340a708f8fSGustavo F. Padovan 
24350a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
24360a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
24370a708f8fSGustavo F. Padovan 
2438f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2439f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
2440f89cef09SAndrei Emeltchenko 
24418c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
24420a708f8fSGustavo F. Padovan 			break;
24430a708f8fSGustavo F. Padovan 
244447d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_NONE ||
2445c1360a1cSGustavo F. Padovan 				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
244647d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
244747d1ec61SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
24480a708f8fSGustavo F. Padovan 		}
24490a708f8fSGustavo F. Padovan 		break;
24500a708f8fSGustavo F. Padovan 	}
24510a708f8fSGustavo F. Padovan 
2452fe4128e0SGustavo F. Padovan 	req->dcid  = cpu_to_le16(chan->dcid);
24530a708f8fSGustavo F. Padovan 	req->flags = cpu_to_le16(0);
24540a708f8fSGustavo F. Padovan 
24550a708f8fSGustavo F. Padovan 	return ptr - data;
24560a708f8fSGustavo F. Padovan }
24570a708f8fSGustavo F. Padovan 
245873ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
24590a708f8fSGustavo F. Padovan {
24600a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
24610a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
246273ffa904SGustavo F. Padovan 	void *req = chan->conf_req;
246373ffa904SGustavo F. Padovan 	int len = chan->conf_len;
24640a708f8fSGustavo F. Padovan 	int type, hint, olen;
24650a708f8fSGustavo F. Padovan 	unsigned long val;
24660a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
246742dceae2SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
246842dceae2SAndrei Emeltchenko 	u8 remote_efs = 0;
24690a708f8fSGustavo F. Padovan 	u16 mtu = L2CAP_DEFAULT_MTU;
24700a708f8fSGustavo F. Padovan 	u16 result = L2CAP_CONF_SUCCESS;
2471c8f79162SAndrei Emeltchenko 	u16 size;
24720a708f8fSGustavo F. Padovan 
247373ffa904SGustavo F. Padovan 	BT_DBG("chan %p", chan);
24740a708f8fSGustavo F. Padovan 
24750a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
24760a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
24770a708f8fSGustavo F. Padovan 
24780a708f8fSGustavo F. Padovan 		hint  = type & L2CAP_CONF_HINT;
24790a708f8fSGustavo F. Padovan 		type &= L2CAP_CONF_MASK;
24800a708f8fSGustavo F. Padovan 
24810a708f8fSGustavo F. Padovan 		switch (type) {
24820a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
24830a708f8fSGustavo F. Padovan 			mtu = val;
24840a708f8fSGustavo F. Padovan 			break;
24850a708f8fSGustavo F. Padovan 
24860a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
24870c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
24880a708f8fSGustavo F. Padovan 			break;
24890a708f8fSGustavo F. Padovan 
24900a708f8fSGustavo F. Padovan 		case L2CAP_CONF_QOS:
24910a708f8fSGustavo F. Padovan 			break;
24920a708f8fSGustavo F. Padovan 
24930a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
24940a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
24950a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *) val, olen);
24960a708f8fSGustavo F. Padovan 			break;
24970a708f8fSGustavo F. Padovan 
24980a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FCS:
24990a708f8fSGustavo F. Padovan 			if (val == L2CAP_FCS_NONE)
2500c1360a1cSGustavo F. Padovan 				set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
250142dceae2SAndrei Emeltchenko 			break;
25020a708f8fSGustavo F. Padovan 
250342dceae2SAndrei Emeltchenko 		case L2CAP_CONF_EFS:
250442dceae2SAndrei Emeltchenko 			remote_efs = 1;
250542dceae2SAndrei Emeltchenko 			if (olen == sizeof(efs))
250642dceae2SAndrei Emeltchenko 				memcpy(&efs, (void *) val, olen);
25070a708f8fSGustavo F. Padovan 			break;
25080a708f8fSGustavo F. Padovan 
25096327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
25106327eb98SAndrei Emeltchenko 			if (!enable_hs)
25116327eb98SAndrei Emeltchenko 				return -ECONNREFUSED;
25126327eb98SAndrei Emeltchenko 
25136327eb98SAndrei Emeltchenko 			set_bit(FLAG_EXT_CTRL, &chan->flags);
25146327eb98SAndrei Emeltchenko 			set_bit(CONF_EWS_RECV, &chan->conf_state);
2515836be934SAndrei Emeltchenko 			chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
25166327eb98SAndrei Emeltchenko 			chan->remote_tx_win = val;
25170a708f8fSGustavo F. Padovan 			break;
25180a708f8fSGustavo F. Padovan 
25190a708f8fSGustavo F. Padovan 		default:
25200a708f8fSGustavo F. Padovan 			if (hint)
25210a708f8fSGustavo F. Padovan 				break;
25220a708f8fSGustavo F. Padovan 
25230a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNKNOWN;
25240a708f8fSGustavo F. Padovan 			*((u8 *) ptr++) = type;
25250a708f8fSGustavo F. Padovan 			break;
25260a708f8fSGustavo F. Padovan 		}
25270a708f8fSGustavo F. Padovan 	}
25280a708f8fSGustavo F. Padovan 
252973ffa904SGustavo F. Padovan 	if (chan->num_conf_rsp || chan->num_conf_req > 1)
25300a708f8fSGustavo F. Padovan 		goto done;
25310a708f8fSGustavo F. Padovan 
25320c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
25330a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
25340a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
2535c1360a1cSGustavo F. Padovan 		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
25360c1bc5c6SGustavo F. Padovan 			chan->mode = l2cap_select_mode(rfc.mode,
25378c1d787bSGustavo F. Padovan 					chan->conn->feat_mask);
25380a708f8fSGustavo F. Padovan 			break;
25390a708f8fSGustavo F. Padovan 		}
25400a708f8fSGustavo F. Padovan 
254142dceae2SAndrei Emeltchenko 		if (remote_efs) {
254242dceae2SAndrei Emeltchenko 			if (__l2cap_efs_supported(chan))
254342dceae2SAndrei Emeltchenko 				set_bit(FLAG_EFS_ENABLE, &chan->flags);
254442dceae2SAndrei Emeltchenko 			else
254542dceae2SAndrei Emeltchenko 				return -ECONNREFUSED;
254642dceae2SAndrei Emeltchenko 		}
254742dceae2SAndrei Emeltchenko 
25480c1bc5c6SGustavo F. Padovan 		if (chan->mode != rfc.mode)
25490a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
25500a708f8fSGustavo F. Padovan 
25510a708f8fSGustavo F. Padovan 		break;
25520a708f8fSGustavo F. Padovan 	}
25530a708f8fSGustavo F. Padovan 
25540a708f8fSGustavo F. Padovan done:
25550c1bc5c6SGustavo F. Padovan 	if (chan->mode != rfc.mode) {
25560a708f8fSGustavo F. Padovan 		result = L2CAP_CONF_UNACCEPT;
25570c1bc5c6SGustavo F. Padovan 		rfc.mode = chan->mode;
25580a708f8fSGustavo F. Padovan 
255973ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp == 1)
25600a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
25610a708f8fSGustavo F. Padovan 
25620a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
25630a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
25640a708f8fSGustavo F. Padovan 	}
25650a708f8fSGustavo F. Padovan 
25660a708f8fSGustavo F. Padovan 	if (result == L2CAP_CONF_SUCCESS) {
25670a708f8fSGustavo F. Padovan 		/* Configure output options and let the other side know
25680a708f8fSGustavo F. Padovan 		 * which ones we don't like. */
25690a708f8fSGustavo F. Padovan 
25700a708f8fSGustavo F. Padovan 		if (mtu < L2CAP_DEFAULT_MIN_MTU)
25710a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
25720a708f8fSGustavo F. Padovan 		else {
25730c1bc5c6SGustavo F. Padovan 			chan->omtu = mtu;
2574c1360a1cSGustavo F. Padovan 			set_bit(CONF_MTU_DONE, &chan->conf_state);
25750a708f8fSGustavo F. Padovan 		}
25760c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
25770a708f8fSGustavo F. Padovan 
257842dceae2SAndrei Emeltchenko 		if (remote_efs) {
257942dceae2SAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
258042dceae2SAndrei Emeltchenko 					efs.stype != L2CAP_SERV_NOTRAFIC &&
258142dceae2SAndrei Emeltchenko 					efs.stype != chan->local_stype) {
258242dceae2SAndrei Emeltchenko 
258342dceae2SAndrei Emeltchenko 				result = L2CAP_CONF_UNACCEPT;
258442dceae2SAndrei Emeltchenko 
258542dceae2SAndrei Emeltchenko 				if (chan->num_conf_req >= 1)
258642dceae2SAndrei Emeltchenko 					return -ECONNREFUSED;
258742dceae2SAndrei Emeltchenko 
258842dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
258942dceae2SAndrei Emeltchenko 							sizeof(efs),
259042dceae2SAndrei Emeltchenko 							(unsigned long) &efs);
25910e8b207eSAndrei Emeltchenko 			} else {
25923e6b3b95SGustavo F. Padovan 				/* Send PENDING Conf Rsp */
25930e8b207eSAndrei Emeltchenko 				result = L2CAP_CONF_PENDING;
25940e8b207eSAndrei Emeltchenko 				set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
259542dceae2SAndrei Emeltchenko 			}
259642dceae2SAndrei Emeltchenko 		}
259742dceae2SAndrei Emeltchenko 
25980a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
25990a708f8fSGustavo F. Padovan 		case L2CAP_MODE_BASIC:
260047d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
2601c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
26020a708f8fSGustavo F. Padovan 			break;
26030a708f8fSGustavo F. Padovan 
26040a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
26056327eb98SAndrei Emeltchenko 			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
26062c03a7a4SGustavo F. Padovan 				chan->remote_tx_win = rfc.txwin_size;
26076327eb98SAndrei Emeltchenko 			else
26086327eb98SAndrei Emeltchenko 				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
26096327eb98SAndrei Emeltchenko 
26102c03a7a4SGustavo F. Padovan 			chan->remote_max_tx = rfc.max_transmit;
26110a708f8fSGustavo F. Padovan 
2612c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2613c8f79162SAndrei Emeltchenko 						chan->conn->mtu -
2614c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2615c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2616c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2617c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
2618c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
26190a708f8fSGustavo F. Padovan 
26200a708f8fSGustavo F. Padovan 			rfc.retrans_timeout =
26214fd21a88SAndrei Emeltchenko 				__constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
26220a708f8fSGustavo F. Padovan 			rfc.monitor_timeout =
26234fd21a88SAndrei Emeltchenko 				__constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
26240a708f8fSGustavo F. Padovan 
2625c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
26260a708f8fSGustavo F. Padovan 
26270a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
26280a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
26290a708f8fSGustavo F. Padovan 
263042dceae2SAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
263142dceae2SAndrei Emeltchenko 				chan->remote_id = efs.id;
263242dceae2SAndrei Emeltchenko 				chan->remote_stype = efs.stype;
263342dceae2SAndrei Emeltchenko 				chan->remote_msdu = le16_to_cpu(efs.msdu);
263442dceae2SAndrei Emeltchenko 				chan->remote_flush_to =
263542dceae2SAndrei Emeltchenko 						le32_to_cpu(efs.flush_to);
263642dceae2SAndrei Emeltchenko 				chan->remote_acc_lat =
263742dceae2SAndrei Emeltchenko 						le32_to_cpu(efs.acc_lat);
263842dceae2SAndrei Emeltchenko 				chan->remote_sdu_itime =
263942dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
264042dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
264142dceae2SAndrei Emeltchenko 					sizeof(efs), (unsigned long) &efs);
264242dceae2SAndrei Emeltchenko 			}
26430a708f8fSGustavo F. Padovan 			break;
26440a708f8fSGustavo F. Padovan 
26450a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
2646c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2647c8f79162SAndrei Emeltchenko 						chan->conn->mtu -
2648c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2649c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2650c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2651c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
2652c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
26530a708f8fSGustavo F. Padovan 
2654c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
26550a708f8fSGustavo F. Padovan 
26560a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
26570a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
26580a708f8fSGustavo F. Padovan 
26590a708f8fSGustavo F. Padovan 			break;
26600a708f8fSGustavo F. Padovan 
26610a708f8fSGustavo F. Padovan 		default:
26620a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
26630a708f8fSGustavo F. Padovan 
26640a708f8fSGustavo F. Padovan 			memset(&rfc, 0, sizeof(rfc));
26650c1bc5c6SGustavo F. Padovan 			rfc.mode = chan->mode;
26660a708f8fSGustavo F. Padovan 		}
26670a708f8fSGustavo F. Padovan 
26680a708f8fSGustavo F. Padovan 		if (result == L2CAP_CONF_SUCCESS)
2669c1360a1cSGustavo F. Padovan 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
26700a708f8fSGustavo F. Padovan 	}
2671fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
26720a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
26730a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(0x0000);
26740a708f8fSGustavo F. Padovan 
26750a708f8fSGustavo F. Padovan 	return ptr - data;
26760a708f8fSGustavo F. Padovan }
26770a708f8fSGustavo F. Padovan 
2678b4450035SGustavo F. Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result)
26790a708f8fSGustavo F. Padovan {
26800a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
26810a708f8fSGustavo F. Padovan 	void *ptr = req->data;
26820a708f8fSGustavo F. Padovan 	int type, olen;
26830a708f8fSGustavo F. Padovan 	unsigned long val;
268436e999a8SMat Martineau 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
268566af7aafSAndrei Emeltchenko 	struct l2cap_conf_efs efs;
26860a708f8fSGustavo F. Padovan 
2687fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
26880a708f8fSGustavo F. Padovan 
26890a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
26900a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
26910a708f8fSGustavo F. Padovan 
26920a708f8fSGustavo F. Padovan 		switch (type) {
26930a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
26940a708f8fSGustavo F. Padovan 			if (val < L2CAP_DEFAULT_MIN_MTU) {
26950a708f8fSGustavo F. Padovan 				*result = L2CAP_CONF_UNACCEPT;
26960c1bc5c6SGustavo F. Padovan 				chan->imtu = L2CAP_DEFAULT_MIN_MTU;
26970a708f8fSGustavo F. Padovan 			} else
26980c1bc5c6SGustavo F. Padovan 				chan->imtu = val;
26990c1bc5c6SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
27000a708f8fSGustavo F. Padovan 			break;
27010a708f8fSGustavo F. Padovan 
27020a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
27030c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
27040a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
27050c1bc5c6SGustavo F. Padovan 							2, chan->flush_to);
27060a708f8fSGustavo F. Padovan 			break;
27070a708f8fSGustavo F. Padovan 
27080a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
27090a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
27100a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
27110a708f8fSGustavo F. Padovan 
2712c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
27130c1bc5c6SGustavo F. Padovan 							rfc.mode != chan->mode)
27140a708f8fSGustavo F. Padovan 				return -ECONNREFUSED;
27150a708f8fSGustavo F. Padovan 
271647d1ec61SGustavo F. Padovan 			chan->fcs = 0;
27170a708f8fSGustavo F. Padovan 
27180a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
27190a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
27200a708f8fSGustavo F. Padovan 			break;
27216327eb98SAndrei Emeltchenko 
27226327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
27236327eb98SAndrei Emeltchenko 			chan->tx_win = min_t(u16, val,
27246327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_EXT_WINDOW);
27253e6b3b95SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
27263e6b3b95SGustavo F. Padovan 							chan->tx_win);
27276327eb98SAndrei Emeltchenko 			break;
272866af7aafSAndrei Emeltchenko 
272966af7aafSAndrei Emeltchenko 		case L2CAP_CONF_EFS:
273066af7aafSAndrei Emeltchenko 			if (olen == sizeof(efs))
273166af7aafSAndrei Emeltchenko 				memcpy(&efs, (void *)val, olen);
273266af7aafSAndrei Emeltchenko 
273366af7aafSAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
273466af7aafSAndrei Emeltchenko 					efs.stype != L2CAP_SERV_NOTRAFIC &&
273566af7aafSAndrei Emeltchenko 					efs.stype != chan->local_stype)
273666af7aafSAndrei Emeltchenko 				return -ECONNREFUSED;
273766af7aafSAndrei Emeltchenko 
273866af7aafSAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
273966af7aafSAndrei Emeltchenko 					sizeof(efs), (unsigned long) &efs);
274066af7aafSAndrei Emeltchenko 			break;
27410a708f8fSGustavo F. Padovan 		}
27420a708f8fSGustavo F. Padovan 	}
27430a708f8fSGustavo F. Padovan 
27440c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
27450a708f8fSGustavo F. Padovan 		return -ECONNREFUSED;
27460a708f8fSGustavo F. Padovan 
27470c1bc5c6SGustavo F. Padovan 	chan->mode = rfc.mode;
27480a708f8fSGustavo F. Padovan 
27490e8b207eSAndrei Emeltchenko 	if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
27500a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
27510a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
275247d1ec61SGustavo F. Padovan 			chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
275347d1ec61SGustavo F. Padovan 			chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
275447d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
275566af7aafSAndrei Emeltchenko 
275666af7aafSAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
275766af7aafSAndrei Emeltchenko 				chan->local_msdu = le16_to_cpu(efs.msdu);
275866af7aafSAndrei Emeltchenko 				chan->local_sdu_itime =
275966af7aafSAndrei Emeltchenko 						le32_to_cpu(efs.sdu_itime);
276066af7aafSAndrei Emeltchenko 				chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
276166af7aafSAndrei Emeltchenko 				chan->local_flush_to =
276266af7aafSAndrei Emeltchenko 						le32_to_cpu(efs.flush_to);
276366af7aafSAndrei Emeltchenko 			}
27640a708f8fSGustavo F. Padovan 			break;
276566af7aafSAndrei Emeltchenko 
27660a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
276747d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
27680a708f8fSGustavo F. Padovan 		}
27690a708f8fSGustavo F. Padovan 	}
27700a708f8fSGustavo F. Padovan 
2771fe4128e0SGustavo F. Padovan 	req->dcid   = cpu_to_le16(chan->dcid);
27720a708f8fSGustavo F. Padovan 	req->flags  = cpu_to_le16(0x0000);
27730a708f8fSGustavo F. Padovan 
27740a708f8fSGustavo F. Padovan 	return ptr - data;
27750a708f8fSGustavo F. Padovan }
27760a708f8fSGustavo F. Padovan 
2777fe4128e0SGustavo F. Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
27780a708f8fSGustavo F. Padovan {
27790a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
27800a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
27810a708f8fSGustavo F. Padovan 
2782fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p", chan);
27830a708f8fSGustavo F. Padovan 
2784fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
27850a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
27860a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(flags);
27870a708f8fSGustavo F. Padovan 
27880a708f8fSGustavo F. Padovan 	return ptr - data;
27890a708f8fSGustavo F. Padovan }
27900a708f8fSGustavo F. Padovan 
27918c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
2792710f9b0aSGustavo F. Padovan {
2793710f9b0aSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
27948c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
2795710f9b0aSGustavo F. Padovan 	u8 buf[128];
2796710f9b0aSGustavo F. Padovan 
2797fe4128e0SGustavo F. Padovan 	rsp.scid   = cpu_to_le16(chan->dcid);
2798fe4128e0SGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(chan->scid);
2799710f9b0aSGustavo F. Padovan 	rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2800710f9b0aSGustavo F. Padovan 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2801710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, chan->ident,
2802710f9b0aSGustavo F. Padovan 				L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2803710f9b0aSGustavo F. Padovan 
2804c1360a1cSGustavo F. Padovan 	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
2805710f9b0aSGustavo F. Padovan 		return;
2806710f9b0aSGustavo F. Padovan 
2807710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2808710f9b0aSGustavo F. Padovan 			l2cap_build_conf_req(chan, buf), buf);
2809710f9b0aSGustavo F. Padovan 	chan->num_conf_req++;
2810710f9b0aSGustavo F. Padovan }
2811710f9b0aSGustavo F. Padovan 
281247d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
28130a708f8fSGustavo F. Padovan {
28140a708f8fSGustavo F. Padovan 	int type, olen;
28150a708f8fSGustavo F. Padovan 	unsigned long val;
28160a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc;
28170a708f8fSGustavo F. Padovan 
281847d1ec61SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
28190a708f8fSGustavo F. Padovan 
28200c1bc5c6SGustavo F. Padovan 	if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
28210a708f8fSGustavo F. Padovan 		return;
28220a708f8fSGustavo F. Padovan 
28230a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
28240a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
28250a708f8fSGustavo F. Padovan 
28260a708f8fSGustavo F. Padovan 		switch (type) {
28270a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
28280a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
28290a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
28300a708f8fSGustavo F. Padovan 			goto done;
28310a708f8fSGustavo F. Padovan 		}
28320a708f8fSGustavo F. Padovan 	}
28330a708f8fSGustavo F. Padovan 
283436e999a8SMat Martineau 	/* Use sane default values in case a misbehaving remote device
283536e999a8SMat Martineau 	 * did not send an RFC option.
283636e999a8SMat Martineau 	 */
283736e999a8SMat Martineau 	rfc.mode = chan->mode;
283836e999a8SMat Martineau 	rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
283936e999a8SMat Martineau 	rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
284036e999a8SMat Martineau 	rfc.max_pdu_size = cpu_to_le16(chan->imtu);
284136e999a8SMat Martineau 
284236e999a8SMat Martineau 	BT_ERR("Expected RFC option was not found, using defaults");
284336e999a8SMat Martineau 
28440a708f8fSGustavo F. Padovan done:
28450a708f8fSGustavo F. Padovan 	switch (rfc.mode) {
28460a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
284747d1ec61SGustavo F. Padovan 		chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
284847d1ec61SGustavo F. Padovan 		chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
284947d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
28500a708f8fSGustavo F. Padovan 		break;
28510a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
285247d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
28530a708f8fSGustavo F. Padovan 	}
28540a708f8fSGustavo F. Padovan }
28550a708f8fSGustavo F. Padovan 
28560a708f8fSGustavo F. Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
28570a708f8fSGustavo F. Padovan {
2858e2fd318eSIlia Kolomisnky 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
28590a708f8fSGustavo F. Padovan 
2860e2fd318eSIlia Kolomisnky 	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
28610a708f8fSGustavo F. Padovan 		return 0;
28620a708f8fSGustavo F. Padovan 
28630a708f8fSGustavo F. Padovan 	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
28640a708f8fSGustavo F. Padovan 					cmd->ident == conn->info_ident) {
286517cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->info_timer);
28660a708f8fSGustavo F. Padovan 
28670a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
28680a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
28690a708f8fSGustavo F. Padovan 
28700a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
28710a708f8fSGustavo F. Padovan 	}
28720a708f8fSGustavo F. Padovan 
28730a708f8fSGustavo F. Padovan 	return 0;
28740a708f8fSGustavo F. Padovan }
28750a708f8fSGustavo F. Padovan 
28760a708f8fSGustavo F. Padovan static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
28770a708f8fSGustavo F. Padovan {
28780a708f8fSGustavo F. Padovan 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
28790a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
288023691d75SGustavo F. Padovan 	struct l2cap_chan *chan = NULL, *pchan;
28810a708f8fSGustavo F. Padovan 	struct sock *parent, *sk = NULL;
28820a708f8fSGustavo F. Padovan 	int result, status = L2CAP_CS_NO_INFO;
28830a708f8fSGustavo F. Padovan 
28840a708f8fSGustavo F. Padovan 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
28850a708f8fSGustavo F. Padovan 	__le16 psm = req->psm;
28860a708f8fSGustavo F. Padovan 
2887097db76cSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
28880a708f8fSGustavo F. Padovan 
28890a708f8fSGustavo F. Padovan 	/* Check if we have socket listening on psm */
289023691d75SGustavo F. Padovan 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
289123691d75SGustavo F. Padovan 	if (!pchan) {
28920a708f8fSGustavo F. Padovan 		result = L2CAP_CR_BAD_PSM;
28930a708f8fSGustavo F. Padovan 		goto sendresp;
28940a708f8fSGustavo F. Padovan 	}
28950a708f8fSGustavo F. Padovan 
289623691d75SGustavo F. Padovan 	parent = pchan->sk;
289723691d75SGustavo F. Padovan 
28983df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
2899aa2ac881SGustavo F. Padovan 	lock_sock(parent);
29000a708f8fSGustavo F. Padovan 
29010a708f8fSGustavo F. Padovan 	/* Check if the ACL is secure enough (if not SDP) */
29020a708f8fSGustavo F. Padovan 	if (psm != cpu_to_le16(0x0001) &&
29030a708f8fSGustavo F. Padovan 				!hci_conn_check_link_mode(conn->hcon)) {
29049f5a0d7bSAndrei Emeltchenko 		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
29050a708f8fSGustavo F. Padovan 		result = L2CAP_CR_SEC_BLOCK;
29060a708f8fSGustavo F. Padovan 		goto response;
29070a708f8fSGustavo F. Padovan 	}
29080a708f8fSGustavo F. Padovan 
29090a708f8fSGustavo F. Padovan 	result = L2CAP_CR_NO_MEM;
29100a708f8fSGustavo F. Padovan 
29110a708f8fSGustavo F. Padovan 	/* Check for backlog size */
29120a708f8fSGustavo F. Padovan 	if (sk_acceptq_is_full(parent)) {
29130a708f8fSGustavo F. Padovan 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
29140a708f8fSGustavo F. Padovan 		goto response;
29150a708f8fSGustavo F. Padovan 	}
29160a708f8fSGustavo F. Padovan 
291780808e43SGustavo F. Padovan 	chan = pchan->ops->new_connection(pchan->data);
291880808e43SGustavo F. Padovan 	if (!chan)
29190a708f8fSGustavo F. Padovan 		goto response;
29200a708f8fSGustavo F. Padovan 
292180808e43SGustavo F. Padovan 	sk = chan->sk;
292280808e43SGustavo F. Padovan 
29230a708f8fSGustavo F. Padovan 	/* Check if we already have channel with that dcid */
2924baa7e1faSGustavo F. Padovan 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
29250a708f8fSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
2926ba3bd0eeSGustavo F. Padovan 		chan->ops->close(chan->data);
29270a708f8fSGustavo F. Padovan 		goto response;
29280a708f8fSGustavo F. Padovan 	}
29290a708f8fSGustavo F. Padovan 
29300a708f8fSGustavo F. Padovan 	hci_conn_hold(conn->hcon);
29310a708f8fSGustavo F. Padovan 
29320a708f8fSGustavo F. Padovan 	bacpy(&bt_sk(sk)->src, conn->src);
29330a708f8fSGustavo F. Padovan 	bacpy(&bt_sk(sk)->dst, conn->dst);
2934fe4128e0SGustavo F. Padovan 	chan->psm  = psm;
2935fe4128e0SGustavo F. Padovan 	chan->dcid = scid;
29360a708f8fSGustavo F. Padovan 
2937d1010240SGustavo F. Padovan 	bt_accept_enqueue(parent, sk);
2938d1010240SGustavo F. Padovan 
29396be36555SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
294048454079SGustavo F. Padovan 
2941fe4128e0SGustavo F. Padovan 	dcid = chan->scid;
29420a708f8fSGustavo F. Padovan 
2943c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
29440a708f8fSGustavo F. Padovan 
2945fc7f8a7eSGustavo F. Padovan 	chan->ident = cmd->ident;
29460a708f8fSGustavo F. Padovan 
29470a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
2948d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan)) {
29490a708f8fSGustavo F. Padovan 			if (bt_sk(sk)->defer_setup) {
29500e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_CONNECT2);
29510a708f8fSGustavo F. Padovan 				result = L2CAP_CR_PEND;
29520a708f8fSGustavo F. Padovan 				status = L2CAP_CS_AUTHOR_PEND;
29530a708f8fSGustavo F. Padovan 				parent->sk_data_ready(parent, 0);
29540a708f8fSGustavo F. Padovan 			} else {
29550e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_CONFIG);
29560a708f8fSGustavo F. Padovan 				result = L2CAP_CR_SUCCESS;
29570a708f8fSGustavo F. Padovan 				status = L2CAP_CS_NO_INFO;
29580a708f8fSGustavo F. Padovan 			}
29590a708f8fSGustavo F. Padovan 		} else {
29600e587be7SAndrei Emeltchenko 			__l2cap_state_change(chan, BT_CONNECT2);
29610a708f8fSGustavo F. Padovan 			result = L2CAP_CR_PEND;
29620a708f8fSGustavo F. Padovan 			status = L2CAP_CS_AUTHEN_PEND;
29630a708f8fSGustavo F. Padovan 		}
29640a708f8fSGustavo F. Padovan 	} else {
29650e587be7SAndrei Emeltchenko 		__l2cap_state_change(chan, BT_CONNECT2);
29660a708f8fSGustavo F. Padovan 		result = L2CAP_CR_PEND;
29670a708f8fSGustavo F. Padovan 		status = L2CAP_CS_NO_INFO;
29680a708f8fSGustavo F. Padovan 	}
29690a708f8fSGustavo F. Padovan 
29700a708f8fSGustavo F. Padovan response:
2971aa2ac881SGustavo F. Padovan 	release_sock(parent);
29723df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
29730a708f8fSGustavo F. Padovan 
29740a708f8fSGustavo F. Padovan sendresp:
29750a708f8fSGustavo F. Padovan 	rsp.scid   = cpu_to_le16(scid);
29760a708f8fSGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(dcid);
29770a708f8fSGustavo F. Padovan 	rsp.result = cpu_to_le16(result);
29780a708f8fSGustavo F. Padovan 	rsp.status = cpu_to_le16(status);
29790a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
29800a708f8fSGustavo F. Padovan 
29810a708f8fSGustavo F. Padovan 	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
29820a708f8fSGustavo F. Padovan 		struct l2cap_info_req info;
29830a708f8fSGustavo F. Padovan 		info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
29840a708f8fSGustavo F. Padovan 
29850a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
29860a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
29870a708f8fSGustavo F. Padovan 
2988ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
29890a708f8fSGustavo F. Padovan 
29900a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, conn->info_ident,
29910a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(info), &info);
29920a708f8fSGustavo F. Padovan 	}
29930a708f8fSGustavo F. Padovan 
2994c1360a1cSGustavo F. Padovan 	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
29950a708f8fSGustavo F. Padovan 				result == L2CAP_CR_SUCCESS) {
29960a708f8fSGustavo F. Padovan 		u8 buf[128];
2997c1360a1cSGustavo F. Padovan 		set_bit(CONF_REQ_SENT, &chan->conf_state);
29980a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
299973ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, buf), buf);
300073ffa904SGustavo F. Padovan 		chan->num_conf_req++;
30010a708f8fSGustavo F. Padovan 	}
30020a708f8fSGustavo F. Padovan 
30030a708f8fSGustavo F. Padovan 	return 0;
30040a708f8fSGustavo F. Padovan }
30050a708f8fSGustavo F. Padovan 
30060a708f8fSGustavo F. Padovan static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
30070a708f8fSGustavo F. Padovan {
30080a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
30090a708f8fSGustavo F. Padovan 	u16 scid, dcid, result, status;
301048454079SGustavo F. Padovan 	struct l2cap_chan *chan;
30110a708f8fSGustavo F. Padovan 	u8 req[128];
30123df91ea2SAndrei Emeltchenko 	int err;
30130a708f8fSGustavo F. Padovan 
30140a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
30150a708f8fSGustavo F. Padovan 	dcid   = __le16_to_cpu(rsp->dcid);
30160a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
30170a708f8fSGustavo F. Padovan 	status = __le16_to_cpu(rsp->status);
30180a708f8fSGustavo F. Padovan 
30191b009c98SAndrei Emeltchenko 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
30201b009c98SAndrei Emeltchenko 						dcid, scid, result, status);
30210a708f8fSGustavo F. Padovan 
30223df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
30233df91ea2SAndrei Emeltchenko 
30240a708f8fSGustavo F. Padovan 	if (scid) {
30253df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_scid(conn, scid);
30263df91ea2SAndrei Emeltchenko 		if (!chan) {
30273df91ea2SAndrei Emeltchenko 			err = -EFAULT;
30283df91ea2SAndrei Emeltchenko 			goto unlock;
30293df91ea2SAndrei Emeltchenko 		}
30300a708f8fSGustavo F. Padovan 	} else {
30313df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
30323df91ea2SAndrei Emeltchenko 		if (!chan) {
30333df91ea2SAndrei Emeltchenko 			err = -EFAULT;
30343df91ea2SAndrei Emeltchenko 			goto unlock;
30353df91ea2SAndrei Emeltchenko 		}
30360a708f8fSGustavo F. Padovan 	}
30370a708f8fSGustavo F. Padovan 
30383df91ea2SAndrei Emeltchenko 	err = 0;
30393df91ea2SAndrei Emeltchenko 
30406be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
304148454079SGustavo F. Padovan 
30420a708f8fSGustavo F. Padovan 	switch (result) {
30430a708f8fSGustavo F. Padovan 	case L2CAP_CR_SUCCESS:
304489bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONFIG);
3045fc7f8a7eSGustavo F. Padovan 		chan->ident = 0;
3046fe4128e0SGustavo F. Padovan 		chan->dcid = dcid;
3047c1360a1cSGustavo F. Padovan 		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
30480a708f8fSGustavo F. Padovan 
3049c1360a1cSGustavo F. Padovan 		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
30500a708f8fSGustavo F. Padovan 			break;
30510a708f8fSGustavo F. Padovan 
30520a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
305373ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, req), req);
305473ffa904SGustavo F. Padovan 		chan->num_conf_req++;
30550a708f8fSGustavo F. Padovan 		break;
30560a708f8fSGustavo F. Padovan 
30570a708f8fSGustavo F. Padovan 	case L2CAP_CR_PEND:
3058c1360a1cSGustavo F. Padovan 		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
30590a708f8fSGustavo F. Padovan 		break;
30600a708f8fSGustavo F. Padovan 
30610a708f8fSGustavo F. Padovan 	default:
306248454079SGustavo F. Padovan 		l2cap_chan_del(chan, ECONNREFUSED);
30630a708f8fSGustavo F. Padovan 		break;
30640a708f8fSGustavo F. Padovan 	}
30650a708f8fSGustavo F. Padovan 
30666be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
30673df91ea2SAndrei Emeltchenko 
30683df91ea2SAndrei Emeltchenko unlock:
30693df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
30703df91ea2SAndrei Emeltchenko 
30713df91ea2SAndrei Emeltchenko 	return err;
30720a708f8fSGustavo F. Padovan }
30730a708f8fSGustavo F. Padovan 
307447d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
30750a708f8fSGustavo F. Padovan {
30760a708f8fSGustavo F. Padovan 	/* FCS is enabled only in ERTM or streaming mode, if one or both
30770a708f8fSGustavo F. Padovan 	 * sides request it.
30780a708f8fSGustavo F. Padovan 	 */
30790c1bc5c6SGustavo F. Padovan 	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
308047d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_NONE;
3081c1360a1cSGustavo F. Padovan 	else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
308247d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_CRC16;
30830a708f8fSGustavo F. Padovan }
30840a708f8fSGustavo F. Padovan 
30850a708f8fSGustavo F. Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
30860a708f8fSGustavo F. Padovan {
30870a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
30880a708f8fSGustavo F. Padovan 	u16 dcid, flags;
30890a708f8fSGustavo F. Padovan 	u8 rsp[64];
309048454079SGustavo F. Padovan 	struct l2cap_chan *chan;
30913c588192SMat Martineau 	int len, err = 0;
30920a708f8fSGustavo F. Padovan 
30930a708f8fSGustavo F. Padovan 	dcid  = __le16_to_cpu(req->dcid);
30940a708f8fSGustavo F. Padovan 	flags = __le16_to_cpu(req->flags);
30950a708f8fSGustavo F. Padovan 
30960a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
30970a708f8fSGustavo F. Padovan 
3098baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, dcid);
309948454079SGustavo F. Padovan 	if (!chan)
31000a708f8fSGustavo F. Padovan 		return -ENOENT;
31010a708f8fSGustavo F. Padovan 
31026be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
310348454079SGustavo F. Padovan 
3104033b1142SDavid S. Miller 	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
3105e2fd318eSIlia Kolomisnky 		struct l2cap_cmd_rej_cid rej;
31060a708f8fSGustavo F. Padovan 
3107e2fd318eSIlia Kolomisnky 		rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
3108e2fd318eSIlia Kolomisnky 		rej.scid = cpu_to_le16(chan->scid);
3109e2fd318eSIlia Kolomisnky 		rej.dcid = cpu_to_le16(chan->dcid);
3110e2fd318eSIlia Kolomisnky 
31110a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
31120a708f8fSGustavo F. Padovan 				sizeof(rej), &rej);
31130a708f8fSGustavo F. Padovan 		goto unlock;
31140a708f8fSGustavo F. Padovan 	}
31150a708f8fSGustavo F. Padovan 
31160a708f8fSGustavo F. Padovan 	/* Reject if config buffer is too small. */
31170a708f8fSGustavo F. Padovan 	len = cmd_len - sizeof(*req);
31187ac28817SDan Rosenberg 	if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
31190a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3120fe4128e0SGustavo F. Padovan 				l2cap_build_conf_rsp(chan, rsp,
31210a708f8fSGustavo F. Padovan 					L2CAP_CONF_REJECT, flags), rsp);
31220a708f8fSGustavo F. Padovan 		goto unlock;
31230a708f8fSGustavo F. Padovan 	}
31240a708f8fSGustavo F. Padovan 
31250a708f8fSGustavo F. Padovan 	/* Store config. */
312673ffa904SGustavo F. Padovan 	memcpy(chan->conf_req + chan->conf_len, req->data, len);
312773ffa904SGustavo F. Padovan 	chan->conf_len += len;
31280a708f8fSGustavo F. Padovan 
31290a708f8fSGustavo F. Padovan 	if (flags & 0x0001) {
31300a708f8fSGustavo F. Padovan 		/* Incomplete config. Send empty response. */
31310a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3132fe4128e0SGustavo F. Padovan 				l2cap_build_conf_rsp(chan, rsp,
31330a708f8fSGustavo F. Padovan 					L2CAP_CONF_SUCCESS, 0x0001), rsp);
31340a708f8fSGustavo F. Padovan 		goto unlock;
31350a708f8fSGustavo F. Padovan 	}
31360a708f8fSGustavo F. Padovan 
31370a708f8fSGustavo F. Padovan 	/* Complete config. */
313873ffa904SGustavo F. Padovan 	len = l2cap_parse_conf_req(chan, rsp);
31390a708f8fSGustavo F. Padovan 	if (len < 0) {
3140e92c8e70SGustavo F. Padovan 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
31410a708f8fSGustavo F. Padovan 		goto unlock;
31420a708f8fSGustavo F. Padovan 	}
31430a708f8fSGustavo F. Padovan 
31440a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
314573ffa904SGustavo F. Padovan 	chan->num_conf_rsp++;
31460a708f8fSGustavo F. Padovan 
31470a708f8fSGustavo F. Padovan 	/* Reset config buffer. */
314873ffa904SGustavo F. Padovan 	chan->conf_len = 0;
31490a708f8fSGustavo F. Padovan 
3150c1360a1cSGustavo F. Padovan 	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
31510a708f8fSGustavo F. Padovan 		goto unlock;
31520a708f8fSGustavo F. Padovan 
3153c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
315447d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
31550a708f8fSGustavo F. Padovan 
315689bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONNECTED);
31570a708f8fSGustavo F. Padovan 
315842e5c802SGustavo F. Padovan 		chan->next_tx_seq = 0;
315942e5c802SGustavo F. Padovan 		chan->expected_tx_seq = 0;
316058d35f87SGustavo F. Padovan 		skb_queue_head_init(&chan->tx_q);
31610c1bc5c6SGustavo F. Padovan 		if (chan->mode == L2CAP_MODE_ERTM)
31623c588192SMat Martineau 			err = l2cap_ertm_init(chan);
31630a708f8fSGustavo F. Padovan 
31643c588192SMat Martineau 		if (err < 0)
31653c588192SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, -err);
31663c588192SMat Martineau 		else
3167cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
31683c588192SMat Martineau 
31690a708f8fSGustavo F. Padovan 		goto unlock;
31700a708f8fSGustavo F. Padovan 	}
31710a708f8fSGustavo F. Padovan 
3172c1360a1cSGustavo F. Padovan 	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
31730a708f8fSGustavo F. Padovan 		u8 buf[64];
31740a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
317573ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, buf), buf);
317673ffa904SGustavo F. Padovan 		chan->num_conf_req++;
31770a708f8fSGustavo F. Padovan 	}
31780a708f8fSGustavo F. Padovan 
31790e8b207eSAndrei Emeltchenko 	/* Got Conf Rsp PENDING from remote side and asume we sent
31800e8b207eSAndrei Emeltchenko 	   Conf Rsp PENDING in the code above */
31810e8b207eSAndrei Emeltchenko 	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
31820e8b207eSAndrei Emeltchenko 			test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
31830e8b207eSAndrei Emeltchenko 
31840e8b207eSAndrei Emeltchenko 		/* check compatibility */
31850e8b207eSAndrei Emeltchenko 
31860e8b207eSAndrei Emeltchenko 		clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
31870e8b207eSAndrei Emeltchenko 		set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
31880e8b207eSAndrei Emeltchenko 
31890e8b207eSAndrei Emeltchenko 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
31900e8b207eSAndrei Emeltchenko 					l2cap_build_conf_rsp(chan, rsp,
31910e8b207eSAndrei Emeltchenko 					L2CAP_CONF_SUCCESS, 0x0000), rsp);
31920e8b207eSAndrei Emeltchenko 	}
31930e8b207eSAndrei Emeltchenko 
31940a708f8fSGustavo F. Padovan unlock:
31956be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
31963c588192SMat Martineau 	return err;
31970a708f8fSGustavo F. Padovan }
31980a708f8fSGustavo F. Padovan 
31990a708f8fSGustavo F. Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
32000a708f8fSGustavo F. Padovan {
32010a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
32020a708f8fSGustavo F. Padovan 	u16 scid, flags, result;
320348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
320461386cbaSAndrei Emeltchenko 	int len = le16_to_cpu(cmd->len) - sizeof(*rsp);
32053c588192SMat Martineau 	int err = 0;
32060a708f8fSGustavo F. Padovan 
32070a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
32080a708f8fSGustavo F. Padovan 	flags  = __le16_to_cpu(rsp->flags);
32090a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
32100a708f8fSGustavo F. Padovan 
321161386cbaSAndrei Emeltchenko 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
321261386cbaSAndrei Emeltchenko 	       result, len);
32130a708f8fSGustavo F. Padovan 
3214baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, scid);
321548454079SGustavo F. Padovan 	if (!chan)
32160a708f8fSGustavo F. Padovan 		return 0;
32170a708f8fSGustavo F. Padovan 
32186be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
321948454079SGustavo F. Padovan 
32200a708f8fSGustavo F. Padovan 	switch (result) {
32210a708f8fSGustavo F. Padovan 	case L2CAP_CONF_SUCCESS:
322247d1ec61SGustavo F. Padovan 		l2cap_conf_rfc_get(chan, rsp->data, len);
32230e8b207eSAndrei Emeltchenko 		clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
32240a708f8fSGustavo F. Padovan 		break;
32250a708f8fSGustavo F. Padovan 
32260e8b207eSAndrei Emeltchenko 	case L2CAP_CONF_PENDING:
32270e8b207eSAndrei Emeltchenko 		set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
32280e8b207eSAndrei Emeltchenko 
32290e8b207eSAndrei Emeltchenko 		if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
32300e8b207eSAndrei Emeltchenko 			char buf[64];
32310e8b207eSAndrei Emeltchenko 
32320e8b207eSAndrei Emeltchenko 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
32330e8b207eSAndrei Emeltchenko 								buf, &result);
32340e8b207eSAndrei Emeltchenko 			if (len < 0) {
32350e8b207eSAndrei Emeltchenko 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
32360e8b207eSAndrei Emeltchenko 				goto done;
32370e8b207eSAndrei Emeltchenko 			}
32380e8b207eSAndrei Emeltchenko 
32390e8b207eSAndrei Emeltchenko 			/* check compatibility */
32400e8b207eSAndrei Emeltchenko 
32410e8b207eSAndrei Emeltchenko 			clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
32420e8b207eSAndrei Emeltchenko 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
32430e8b207eSAndrei Emeltchenko 
32440e8b207eSAndrei Emeltchenko 			l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
32450e8b207eSAndrei Emeltchenko 						l2cap_build_conf_rsp(chan, buf,
32460e8b207eSAndrei Emeltchenko 						L2CAP_CONF_SUCCESS, 0x0000), buf);
32470e8b207eSAndrei Emeltchenko 		}
32480e8b207eSAndrei Emeltchenko 		goto done;
32490e8b207eSAndrei Emeltchenko 
32500a708f8fSGustavo F. Padovan 	case L2CAP_CONF_UNACCEPT:
325173ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
32520a708f8fSGustavo F. Padovan 			char req[64];
32530a708f8fSGustavo F. Padovan 
32540a708f8fSGustavo F. Padovan 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
3255e92c8e70SGustavo F. Padovan 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
32560a708f8fSGustavo F. Padovan 				goto done;
32570a708f8fSGustavo F. Padovan 			}
32580a708f8fSGustavo F. Padovan 
32590a708f8fSGustavo F. Padovan 			/* throw out any old stored conf requests */
32600a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_SUCCESS;
3261b4450035SGustavo F. Padovan 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
3262b4450035SGustavo F. Padovan 								req, &result);
32630a708f8fSGustavo F. Padovan 			if (len < 0) {
3264e92c8e70SGustavo F. Padovan 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
32650a708f8fSGustavo F. Padovan 				goto done;
32660a708f8fSGustavo F. Padovan 			}
32670a708f8fSGustavo F. Padovan 
32680a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn),
32690a708f8fSGustavo F. Padovan 						L2CAP_CONF_REQ, len, req);
327073ffa904SGustavo F. Padovan 			chan->num_conf_req++;
32710a708f8fSGustavo F. Padovan 			if (result != L2CAP_CONF_SUCCESS)
32720a708f8fSGustavo F. Padovan 				goto done;
32730a708f8fSGustavo F. Padovan 			break;
32740a708f8fSGustavo F. Padovan 		}
32750a708f8fSGustavo F. Padovan 
32760a708f8fSGustavo F. Padovan 	default:
32776be36555SAndrei Emeltchenko 		l2cap_chan_set_err(chan, ECONNRESET);
32782e0052e4SAndrei Emeltchenko 
3279ba13ccd9SMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
3280e92c8e70SGustavo F. Padovan 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
32810a708f8fSGustavo F. Padovan 		goto done;
32820a708f8fSGustavo F. Padovan 	}
32830a708f8fSGustavo F. Padovan 
32840a708f8fSGustavo F. Padovan 	if (flags & 0x01)
32850a708f8fSGustavo F. Padovan 		goto done;
32860a708f8fSGustavo F. Padovan 
3287c1360a1cSGustavo F. Padovan 	set_bit(CONF_INPUT_DONE, &chan->conf_state);
32880a708f8fSGustavo F. Padovan 
3289c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
329047d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
32910a708f8fSGustavo F. Padovan 
329289bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONNECTED);
329342e5c802SGustavo F. Padovan 		chan->next_tx_seq = 0;
329442e5c802SGustavo F. Padovan 		chan->expected_tx_seq = 0;
329558d35f87SGustavo F. Padovan 		skb_queue_head_init(&chan->tx_q);
32960c1bc5c6SGustavo F. Padovan 		if (chan->mode ==  L2CAP_MODE_ERTM)
32973c588192SMat Martineau 			err = l2cap_ertm_init(chan);
32980a708f8fSGustavo F. Padovan 
32993c588192SMat Martineau 		if (err < 0)
33003c588192SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, -err);
33013c588192SMat Martineau 		else
3302cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
33030a708f8fSGustavo F. Padovan 	}
33040a708f8fSGustavo F. Padovan 
33050a708f8fSGustavo F. Padovan done:
33066be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
33073c588192SMat Martineau 	return err;
33080a708f8fSGustavo F. Padovan }
33090a708f8fSGustavo F. Padovan 
33100a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
33110a708f8fSGustavo F. Padovan {
33120a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
33130a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp rsp;
33140a708f8fSGustavo F. Padovan 	u16 dcid, scid;
331548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
33160a708f8fSGustavo F. Padovan 	struct sock *sk;
33170a708f8fSGustavo F. Padovan 
33180a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(req->scid);
33190a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(req->dcid);
33200a708f8fSGustavo F. Padovan 
33210a708f8fSGustavo F. Padovan 	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
33220a708f8fSGustavo F. Padovan 
33233df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
33243df91ea2SAndrei Emeltchenko 
33253df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, dcid);
33263df91ea2SAndrei Emeltchenko 	if (!chan) {
33273df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
33280a708f8fSGustavo F. Padovan 		return 0;
33293df91ea2SAndrei Emeltchenko 	}
33300a708f8fSGustavo F. Padovan 
33316be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
33326be36555SAndrei Emeltchenko 
333348454079SGustavo F. Padovan 	sk = chan->sk;
333448454079SGustavo F. Padovan 
3335fe4128e0SGustavo F. Padovan 	rsp.dcid = cpu_to_le16(chan->scid);
3336fe4128e0SGustavo F. Padovan 	rsp.scid = cpu_to_le16(chan->dcid);
33370a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
33380a708f8fSGustavo F. Padovan 
33396be36555SAndrei Emeltchenko 	lock_sock(sk);
33400a708f8fSGustavo F. Padovan 	sk->sk_shutdown = SHUTDOWN_MASK;
33416be36555SAndrei Emeltchenko 	release_sock(sk);
33420a708f8fSGustavo F. Padovan 
334348454079SGustavo F. Padovan 	l2cap_chan_del(chan, ECONNRESET);
33446be36555SAndrei Emeltchenko 
33456be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
33460a708f8fSGustavo F. Padovan 
3347ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
33483df91ea2SAndrei Emeltchenko 
33493df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
33503df91ea2SAndrei Emeltchenko 
33510a708f8fSGustavo F. Padovan 	return 0;
33520a708f8fSGustavo F. Padovan }
33530a708f8fSGustavo F. Padovan 
33540a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
33550a708f8fSGustavo F. Padovan {
33560a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
33570a708f8fSGustavo F. Padovan 	u16 dcid, scid;
335848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
33590a708f8fSGustavo F. Padovan 
33600a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(rsp->scid);
33610a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(rsp->dcid);
33620a708f8fSGustavo F. Padovan 
33630a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
33640a708f8fSGustavo F. Padovan 
33653df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
33663df91ea2SAndrei Emeltchenko 
33673df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, scid);
33683df91ea2SAndrei Emeltchenko 	if (!chan) {
33693df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
33700a708f8fSGustavo F. Padovan 		return 0;
33713df91ea2SAndrei Emeltchenko 	}
33720a708f8fSGustavo F. Padovan 
33736be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
337448454079SGustavo F. Padovan 
337548454079SGustavo F. Padovan 	l2cap_chan_del(chan, 0);
33766be36555SAndrei Emeltchenko 
33776be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
33780a708f8fSGustavo F. Padovan 
3379ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
33803df91ea2SAndrei Emeltchenko 
33813df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
33823df91ea2SAndrei Emeltchenko 
33830a708f8fSGustavo F. Padovan 	return 0;
33840a708f8fSGustavo F. Padovan }
33850a708f8fSGustavo F. Padovan 
33860a708f8fSGustavo F. Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
33870a708f8fSGustavo F. Padovan {
33880a708f8fSGustavo F. Padovan 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
33890a708f8fSGustavo F. Padovan 	u16 type;
33900a708f8fSGustavo F. Padovan 
33910a708f8fSGustavo F. Padovan 	type = __le16_to_cpu(req->type);
33920a708f8fSGustavo F. Padovan 
33930a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x", type);
33940a708f8fSGustavo F. Padovan 
33950a708f8fSGustavo F. Padovan 	if (type == L2CAP_IT_FEAT_MASK) {
33960a708f8fSGustavo F. Padovan 		u8 buf[8];
33970a708f8fSGustavo F. Padovan 		u32 feat_mask = l2cap_feat_mask;
33980a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
33990a708f8fSGustavo F. Padovan 		rsp->type   = cpu_to_le16(L2CAP_IT_FEAT_MASK);
34000a708f8fSGustavo F. Padovan 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
34010a708f8fSGustavo F. Padovan 		if (!disable_ertm)
34020a708f8fSGustavo F. Padovan 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
34030a708f8fSGustavo F. Padovan 							 | L2CAP_FEAT_FCS;
3404a5fd6f30SAndrei Emeltchenko 		if (enable_hs)
34056327eb98SAndrei Emeltchenko 			feat_mask |= L2CAP_FEAT_EXT_FLOW
34066327eb98SAndrei Emeltchenko 						| L2CAP_FEAT_EXT_WINDOW;
3407a5fd6f30SAndrei Emeltchenko 
34080a708f8fSGustavo F. Padovan 		put_unaligned_le32(feat_mask, rsp->data);
34090a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
34100a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(buf), buf);
34110a708f8fSGustavo F. Padovan 	} else if (type == L2CAP_IT_FIXED_CHAN) {
34120a708f8fSGustavo F. Padovan 		u8 buf[12];
34130a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
341450a147cdSMat Martineau 
341550a147cdSMat Martineau 		if (enable_hs)
341650a147cdSMat Martineau 			l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
341750a147cdSMat Martineau 		else
341850a147cdSMat Martineau 			l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
341950a147cdSMat Martineau 
34200a708f8fSGustavo F. Padovan 		rsp->type   = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
34210a708f8fSGustavo F. Padovan 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
3422c6337ea6SAndrei Emeltchenko 		memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
34230a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
34240a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(buf), buf);
34250a708f8fSGustavo F. Padovan 	} else {
34260a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp rsp;
34270a708f8fSGustavo F. Padovan 		rsp.type   = cpu_to_le16(type);
34280a708f8fSGustavo F. Padovan 		rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
34290a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
34300a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(rsp), &rsp);
34310a708f8fSGustavo F. Padovan 	}
34320a708f8fSGustavo F. Padovan 
34330a708f8fSGustavo F. Padovan 	return 0;
34340a708f8fSGustavo F. Padovan }
34350a708f8fSGustavo F. Padovan 
34360a708f8fSGustavo F. Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
34370a708f8fSGustavo F. Padovan {
34380a708f8fSGustavo F. Padovan 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
34390a708f8fSGustavo F. Padovan 	u16 type, result;
34400a708f8fSGustavo F. Padovan 
34410a708f8fSGustavo F. Padovan 	type   = __le16_to_cpu(rsp->type);
34420a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
34430a708f8fSGustavo F. Padovan 
34440a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
34450a708f8fSGustavo F. Padovan 
3446e90165beSAndrei Emeltchenko 	/* L2CAP Info req/rsp are unbound to channels, add extra checks */
3447e90165beSAndrei Emeltchenko 	if (cmd->ident != conn->info_ident ||
3448e90165beSAndrei Emeltchenko 			conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3449e90165beSAndrei Emeltchenko 		return 0;
3450e90165beSAndrei Emeltchenko 
345117cd3f37SUlisses Furquim 	cancel_delayed_work(&conn->info_timer);
34520a708f8fSGustavo F. Padovan 
34530a708f8fSGustavo F. Padovan 	if (result != L2CAP_IR_SUCCESS) {
34540a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
34550a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
34560a708f8fSGustavo F. Padovan 
34570a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
34580a708f8fSGustavo F. Padovan 
34590a708f8fSGustavo F. Padovan 		return 0;
34600a708f8fSGustavo F. Padovan 	}
34610a708f8fSGustavo F. Padovan 
3462978c93b9SAndrei Emeltchenko 	switch (type) {
3463978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FEAT_MASK:
34640a708f8fSGustavo F. Padovan 		conn->feat_mask = get_unaligned_le32(rsp->data);
34650a708f8fSGustavo F. Padovan 
34660a708f8fSGustavo F. Padovan 		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
34670a708f8fSGustavo F. Padovan 			struct l2cap_info_req req;
34680a708f8fSGustavo F. Padovan 			req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
34690a708f8fSGustavo F. Padovan 
34700a708f8fSGustavo F. Padovan 			conn->info_ident = l2cap_get_ident(conn);
34710a708f8fSGustavo F. Padovan 
34720a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, conn->info_ident,
34730a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(req), &req);
34740a708f8fSGustavo F. Padovan 		} else {
34750a708f8fSGustavo F. Padovan 			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
34760a708f8fSGustavo F. Padovan 			conn->info_ident = 0;
34770a708f8fSGustavo F. Padovan 
34780a708f8fSGustavo F. Padovan 			l2cap_conn_start(conn);
34790a708f8fSGustavo F. Padovan 		}
3480978c93b9SAndrei Emeltchenko 		break;
3481978c93b9SAndrei Emeltchenko 
3482978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FIXED_CHAN:
3483978c93b9SAndrei Emeltchenko 		conn->fixed_chan_mask = rsp->data[0];
34840a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
34850a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
34860a708f8fSGustavo F. Padovan 
34870a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
3488978c93b9SAndrei Emeltchenko 		break;
34890a708f8fSGustavo F. Padovan 	}
34900a708f8fSGustavo F. Padovan 
34910a708f8fSGustavo F. Padovan 	return 0;
34920a708f8fSGustavo F. Padovan }
34930a708f8fSGustavo F. Padovan 
3494f94ff6ffSMat Martineau static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3495f94ff6ffSMat Martineau 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3496f94ff6ffSMat Martineau 					void *data)
3497f94ff6ffSMat Martineau {
3498f94ff6ffSMat Martineau 	struct l2cap_create_chan_req *req = data;
3499f94ff6ffSMat Martineau 	struct l2cap_create_chan_rsp rsp;
3500f94ff6ffSMat Martineau 	u16 psm, scid;
3501f94ff6ffSMat Martineau 
3502f94ff6ffSMat Martineau 	if (cmd_len != sizeof(*req))
3503f94ff6ffSMat Martineau 		return -EPROTO;
3504f94ff6ffSMat Martineau 
3505f94ff6ffSMat Martineau 	if (!enable_hs)
3506f94ff6ffSMat Martineau 		return -EINVAL;
3507f94ff6ffSMat Martineau 
3508f94ff6ffSMat Martineau 	psm = le16_to_cpu(req->psm);
3509f94ff6ffSMat Martineau 	scid = le16_to_cpu(req->scid);
3510f94ff6ffSMat Martineau 
3511f94ff6ffSMat Martineau 	BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3512f94ff6ffSMat Martineau 
3513f94ff6ffSMat Martineau 	/* Placeholder: Always reject */
3514f94ff6ffSMat Martineau 	rsp.dcid = 0;
3515f94ff6ffSMat Martineau 	rsp.scid = cpu_to_le16(scid);
35168ce0c498SAndrei Emeltchenko 	rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
35178ce0c498SAndrei Emeltchenko 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
3518f94ff6ffSMat Martineau 
3519f94ff6ffSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3520f94ff6ffSMat Martineau 		       sizeof(rsp), &rsp);
3521f94ff6ffSMat Martineau 
3522f94ff6ffSMat Martineau 	return 0;
3523f94ff6ffSMat Martineau }
3524f94ff6ffSMat Martineau 
3525f94ff6ffSMat Martineau static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3526f94ff6ffSMat Martineau 					struct l2cap_cmd_hdr *cmd, void *data)
3527f94ff6ffSMat Martineau {
3528f94ff6ffSMat Martineau 	BT_DBG("conn %p", conn);
3529f94ff6ffSMat Martineau 
3530f94ff6ffSMat Martineau 	return l2cap_connect_rsp(conn, cmd, data);
3531f94ff6ffSMat Martineau }
3532f94ff6ffSMat Martineau 
35338d5a04a1SMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
35348d5a04a1SMat Martineau 							u16 icid, u16 result)
35358d5a04a1SMat Martineau {
35368d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp rsp;
35378d5a04a1SMat Martineau 
35388d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
35398d5a04a1SMat Martineau 
35408d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
35418d5a04a1SMat Martineau 	rsp.result = cpu_to_le16(result);
35428d5a04a1SMat Martineau 
35438d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
35448d5a04a1SMat Martineau }
35458d5a04a1SMat Martineau 
35468d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
35478d5a04a1SMat Martineau 				struct l2cap_chan *chan, u16 icid, u16 result)
35488d5a04a1SMat Martineau {
35498d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm cfm;
35508d5a04a1SMat Martineau 	u8 ident;
35518d5a04a1SMat Martineau 
35528d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
35538d5a04a1SMat Martineau 
35548d5a04a1SMat Martineau 	ident = l2cap_get_ident(conn);
35558d5a04a1SMat Martineau 	if (chan)
35568d5a04a1SMat Martineau 		chan->ident = ident;
35578d5a04a1SMat Martineau 
35588d5a04a1SMat Martineau 	cfm.icid = cpu_to_le16(icid);
35598d5a04a1SMat Martineau 	cfm.result = cpu_to_le16(result);
35608d5a04a1SMat Martineau 
35618d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
35628d5a04a1SMat Martineau }
35638d5a04a1SMat Martineau 
35648d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
35658d5a04a1SMat Martineau 								u16 icid)
35668d5a04a1SMat Martineau {
35678d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp rsp;
35688d5a04a1SMat Martineau 
35698d5a04a1SMat Martineau 	BT_DBG("icid %d", icid);
35708d5a04a1SMat Martineau 
35718d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
35728d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
35738d5a04a1SMat Martineau }
35748d5a04a1SMat Martineau 
35758d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
35768d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
35778d5a04a1SMat Martineau {
35788d5a04a1SMat Martineau 	struct l2cap_move_chan_req *req = data;
35798d5a04a1SMat Martineau 	u16 icid = 0;
35808d5a04a1SMat Martineau 	u16 result = L2CAP_MR_NOT_ALLOWED;
35818d5a04a1SMat Martineau 
35828d5a04a1SMat Martineau 	if (cmd_len != sizeof(*req))
35838d5a04a1SMat Martineau 		return -EPROTO;
35848d5a04a1SMat Martineau 
35858d5a04a1SMat Martineau 	icid = le16_to_cpu(req->icid);
35868d5a04a1SMat Martineau 
35878d5a04a1SMat Martineau 	BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
35888d5a04a1SMat Martineau 
35898d5a04a1SMat Martineau 	if (!enable_hs)
35908d5a04a1SMat Martineau 		return -EINVAL;
35918d5a04a1SMat Martineau 
35928d5a04a1SMat Martineau 	/* Placeholder: Always refuse */
35938d5a04a1SMat Martineau 	l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
35948d5a04a1SMat Martineau 
35958d5a04a1SMat Martineau 	return 0;
35968d5a04a1SMat Martineau }
35978d5a04a1SMat Martineau 
35988d5a04a1SMat Martineau static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
35998d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
36008d5a04a1SMat Martineau {
36018d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp *rsp = data;
36028d5a04a1SMat Martineau 	u16 icid, result;
36038d5a04a1SMat Martineau 
36048d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
36058d5a04a1SMat Martineau 		return -EPROTO;
36068d5a04a1SMat Martineau 
36078d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
36088d5a04a1SMat Martineau 	result = le16_to_cpu(rsp->result);
36098d5a04a1SMat Martineau 
36108d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
36118d5a04a1SMat Martineau 
36128d5a04a1SMat Martineau 	/* Placeholder: Always unconfirmed */
36138d5a04a1SMat Martineau 	l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
36148d5a04a1SMat Martineau 
36158d5a04a1SMat Martineau 	return 0;
36168d5a04a1SMat Martineau }
36178d5a04a1SMat Martineau 
36188d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
36198d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
36208d5a04a1SMat Martineau {
36218d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm *cfm = data;
36228d5a04a1SMat Martineau 	u16 icid, result;
36238d5a04a1SMat Martineau 
36248d5a04a1SMat Martineau 	if (cmd_len != sizeof(*cfm))
36258d5a04a1SMat Martineau 		return -EPROTO;
36268d5a04a1SMat Martineau 
36278d5a04a1SMat Martineau 	icid = le16_to_cpu(cfm->icid);
36288d5a04a1SMat Martineau 	result = le16_to_cpu(cfm->result);
36298d5a04a1SMat Martineau 
36308d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
36318d5a04a1SMat Martineau 
36328d5a04a1SMat Martineau 	l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
36338d5a04a1SMat Martineau 
36348d5a04a1SMat Martineau 	return 0;
36358d5a04a1SMat Martineau }
36368d5a04a1SMat Martineau 
36378d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
36388d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
36398d5a04a1SMat Martineau {
36408d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp *rsp = data;
36418d5a04a1SMat Martineau 	u16 icid;
36428d5a04a1SMat Martineau 
36438d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
36448d5a04a1SMat Martineau 		return -EPROTO;
36458d5a04a1SMat Martineau 
36468d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
36478d5a04a1SMat Martineau 
36488d5a04a1SMat Martineau 	BT_DBG("icid %d", icid);
36498d5a04a1SMat Martineau 
36508d5a04a1SMat Martineau 	return 0;
36518d5a04a1SMat Martineau }
36528d5a04a1SMat Martineau 
3653e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
3654de73115aSClaudio Takahasi 							u16 to_multiplier)
3655de73115aSClaudio Takahasi {
3656de73115aSClaudio Takahasi 	u16 max_latency;
3657de73115aSClaudio Takahasi 
3658de73115aSClaudio Takahasi 	if (min > max || min < 6 || max > 3200)
3659de73115aSClaudio Takahasi 		return -EINVAL;
3660de73115aSClaudio Takahasi 
3661de73115aSClaudio Takahasi 	if (to_multiplier < 10 || to_multiplier > 3200)
3662de73115aSClaudio Takahasi 		return -EINVAL;
3663de73115aSClaudio Takahasi 
3664de73115aSClaudio Takahasi 	if (max >= to_multiplier * 8)
3665de73115aSClaudio Takahasi 		return -EINVAL;
3666de73115aSClaudio Takahasi 
3667de73115aSClaudio Takahasi 	max_latency = (to_multiplier * 8 / max) - 1;
3668de73115aSClaudio Takahasi 	if (latency > 499 || latency > max_latency)
3669de73115aSClaudio Takahasi 		return -EINVAL;
3670de73115aSClaudio Takahasi 
3671de73115aSClaudio Takahasi 	return 0;
3672de73115aSClaudio Takahasi }
3673de73115aSClaudio Takahasi 
3674de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3675de73115aSClaudio Takahasi 					struct l2cap_cmd_hdr *cmd, u8 *data)
3676de73115aSClaudio Takahasi {
3677de73115aSClaudio Takahasi 	struct hci_conn *hcon = conn->hcon;
3678de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_req *req;
3679de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_rsp rsp;
3680de73115aSClaudio Takahasi 	u16 min, max, latency, to_multiplier, cmd_len;
36812ce603ebSClaudio Takahasi 	int err;
3682de73115aSClaudio Takahasi 
3683de73115aSClaudio Takahasi 	if (!(hcon->link_mode & HCI_LM_MASTER))
3684de73115aSClaudio Takahasi 		return -EINVAL;
3685de73115aSClaudio Takahasi 
3686de73115aSClaudio Takahasi 	cmd_len = __le16_to_cpu(cmd->len);
3687de73115aSClaudio Takahasi 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3688de73115aSClaudio Takahasi 		return -EPROTO;
3689de73115aSClaudio Takahasi 
3690de73115aSClaudio Takahasi 	req = (struct l2cap_conn_param_update_req *) data;
3691de73115aSClaudio Takahasi 	min		= __le16_to_cpu(req->min);
3692de73115aSClaudio Takahasi 	max		= __le16_to_cpu(req->max);
3693de73115aSClaudio Takahasi 	latency		= __le16_to_cpu(req->latency);
3694de73115aSClaudio Takahasi 	to_multiplier	= __le16_to_cpu(req->to_multiplier);
3695de73115aSClaudio Takahasi 
3696de73115aSClaudio Takahasi 	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3697de73115aSClaudio Takahasi 						min, max, latency, to_multiplier);
3698de73115aSClaudio Takahasi 
3699de73115aSClaudio Takahasi 	memset(&rsp, 0, sizeof(rsp));
37002ce603ebSClaudio Takahasi 
37012ce603ebSClaudio Takahasi 	err = l2cap_check_conn_param(min, max, latency, to_multiplier);
37022ce603ebSClaudio Takahasi 	if (err)
3703de73115aSClaudio Takahasi 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3704de73115aSClaudio Takahasi 	else
3705de73115aSClaudio Takahasi 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3706de73115aSClaudio Takahasi 
3707de73115aSClaudio Takahasi 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3708de73115aSClaudio Takahasi 							sizeof(rsp), &rsp);
3709de73115aSClaudio Takahasi 
37102ce603ebSClaudio Takahasi 	if (!err)
37112ce603ebSClaudio Takahasi 		hci_le_conn_update(hcon, min, max, latency, to_multiplier);
37122ce603ebSClaudio Takahasi 
3713de73115aSClaudio Takahasi 	return 0;
3714de73115aSClaudio Takahasi }
3715de73115aSClaudio Takahasi 
37163300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
37173300d9a9SClaudio Takahasi 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
37183300d9a9SClaudio Takahasi {
37193300d9a9SClaudio Takahasi 	int err = 0;
37203300d9a9SClaudio Takahasi 
37213300d9a9SClaudio Takahasi 	switch (cmd->code) {
37223300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
37233300d9a9SClaudio Takahasi 		l2cap_command_rej(conn, cmd, data);
37243300d9a9SClaudio Takahasi 		break;
37253300d9a9SClaudio Takahasi 
37263300d9a9SClaudio Takahasi 	case L2CAP_CONN_REQ:
37273300d9a9SClaudio Takahasi 		err = l2cap_connect_req(conn, cmd, data);
37283300d9a9SClaudio Takahasi 		break;
37293300d9a9SClaudio Takahasi 
37303300d9a9SClaudio Takahasi 	case L2CAP_CONN_RSP:
37313300d9a9SClaudio Takahasi 		err = l2cap_connect_rsp(conn, cmd, data);
37323300d9a9SClaudio Takahasi 		break;
37333300d9a9SClaudio Takahasi 
37343300d9a9SClaudio Takahasi 	case L2CAP_CONF_REQ:
37353300d9a9SClaudio Takahasi 		err = l2cap_config_req(conn, cmd, cmd_len, data);
37363300d9a9SClaudio Takahasi 		break;
37373300d9a9SClaudio Takahasi 
37383300d9a9SClaudio Takahasi 	case L2CAP_CONF_RSP:
37393300d9a9SClaudio Takahasi 		err = l2cap_config_rsp(conn, cmd, data);
37403300d9a9SClaudio Takahasi 		break;
37413300d9a9SClaudio Takahasi 
37423300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_REQ:
37433300d9a9SClaudio Takahasi 		err = l2cap_disconnect_req(conn, cmd, data);
37443300d9a9SClaudio Takahasi 		break;
37453300d9a9SClaudio Takahasi 
37463300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_RSP:
37473300d9a9SClaudio Takahasi 		err = l2cap_disconnect_rsp(conn, cmd, data);
37483300d9a9SClaudio Takahasi 		break;
37493300d9a9SClaudio Takahasi 
37503300d9a9SClaudio Takahasi 	case L2CAP_ECHO_REQ:
37513300d9a9SClaudio Takahasi 		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
37523300d9a9SClaudio Takahasi 		break;
37533300d9a9SClaudio Takahasi 
37543300d9a9SClaudio Takahasi 	case L2CAP_ECHO_RSP:
37553300d9a9SClaudio Takahasi 		break;
37563300d9a9SClaudio Takahasi 
37573300d9a9SClaudio Takahasi 	case L2CAP_INFO_REQ:
37583300d9a9SClaudio Takahasi 		err = l2cap_information_req(conn, cmd, data);
37593300d9a9SClaudio Takahasi 		break;
37603300d9a9SClaudio Takahasi 
37613300d9a9SClaudio Takahasi 	case L2CAP_INFO_RSP:
37623300d9a9SClaudio Takahasi 		err = l2cap_information_rsp(conn, cmd, data);
37633300d9a9SClaudio Takahasi 		break;
37643300d9a9SClaudio Takahasi 
3765f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_REQ:
3766f94ff6ffSMat Martineau 		err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3767f94ff6ffSMat Martineau 		break;
3768f94ff6ffSMat Martineau 
3769f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_RSP:
3770f94ff6ffSMat Martineau 		err = l2cap_create_channel_rsp(conn, cmd, data);
3771f94ff6ffSMat Martineau 		break;
3772f94ff6ffSMat Martineau 
37738d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_REQ:
37748d5a04a1SMat Martineau 		err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
37758d5a04a1SMat Martineau 		break;
37768d5a04a1SMat Martineau 
37778d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_RSP:
37788d5a04a1SMat Martineau 		err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
37798d5a04a1SMat Martineau 		break;
37808d5a04a1SMat Martineau 
37818d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM:
37828d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
37838d5a04a1SMat Martineau 		break;
37848d5a04a1SMat Martineau 
37858d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM_RSP:
37868d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
37878d5a04a1SMat Martineau 		break;
37888d5a04a1SMat Martineau 
37893300d9a9SClaudio Takahasi 	default:
37903300d9a9SClaudio Takahasi 		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
37913300d9a9SClaudio Takahasi 		err = -EINVAL;
37923300d9a9SClaudio Takahasi 		break;
37933300d9a9SClaudio Takahasi 	}
37943300d9a9SClaudio Takahasi 
37953300d9a9SClaudio Takahasi 	return err;
37963300d9a9SClaudio Takahasi }
37973300d9a9SClaudio Takahasi 
37983300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
37993300d9a9SClaudio Takahasi 					struct l2cap_cmd_hdr *cmd, u8 *data)
38003300d9a9SClaudio Takahasi {
38013300d9a9SClaudio Takahasi 	switch (cmd->code) {
38023300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
38033300d9a9SClaudio Takahasi 		return 0;
38043300d9a9SClaudio Takahasi 
38053300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_REQ:
3806de73115aSClaudio Takahasi 		return l2cap_conn_param_update_req(conn, cmd, data);
38073300d9a9SClaudio Takahasi 
38083300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_RSP:
38093300d9a9SClaudio Takahasi 		return 0;
38103300d9a9SClaudio Takahasi 
38113300d9a9SClaudio Takahasi 	default:
38123300d9a9SClaudio Takahasi 		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
38133300d9a9SClaudio Takahasi 		return -EINVAL;
38143300d9a9SClaudio Takahasi 	}
38153300d9a9SClaudio Takahasi }
38163300d9a9SClaudio Takahasi 
38173300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
38183300d9a9SClaudio Takahasi 							struct sk_buff *skb)
38190a708f8fSGustavo F. Padovan {
38200a708f8fSGustavo F. Padovan 	u8 *data = skb->data;
38210a708f8fSGustavo F. Padovan 	int len = skb->len;
38220a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr cmd;
38233300d9a9SClaudio Takahasi 	int err;
38240a708f8fSGustavo F. Padovan 
38250a708f8fSGustavo F. Padovan 	l2cap_raw_recv(conn, skb);
38260a708f8fSGustavo F. Padovan 
38270a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CMD_HDR_SIZE) {
38280a708f8fSGustavo F. Padovan 		u16 cmd_len;
38290a708f8fSGustavo F. Padovan 		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
38300a708f8fSGustavo F. Padovan 		data += L2CAP_CMD_HDR_SIZE;
38310a708f8fSGustavo F. Padovan 		len  -= L2CAP_CMD_HDR_SIZE;
38320a708f8fSGustavo F. Padovan 
38330a708f8fSGustavo F. Padovan 		cmd_len = le16_to_cpu(cmd.len);
38340a708f8fSGustavo F. Padovan 
38350a708f8fSGustavo F. Padovan 		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident);
38360a708f8fSGustavo F. Padovan 
38370a708f8fSGustavo F. Padovan 		if (cmd_len > len || !cmd.ident) {
38380a708f8fSGustavo F. Padovan 			BT_DBG("corrupted command");
38390a708f8fSGustavo F. Padovan 			break;
38400a708f8fSGustavo F. Padovan 		}
38410a708f8fSGustavo F. Padovan 
38423300d9a9SClaudio Takahasi 		if (conn->hcon->type == LE_LINK)
38433300d9a9SClaudio Takahasi 			err = l2cap_le_sig_cmd(conn, &cmd, data);
38443300d9a9SClaudio Takahasi 		else
38453300d9a9SClaudio Takahasi 			err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
38460a708f8fSGustavo F. Padovan 
38470a708f8fSGustavo F. Padovan 		if (err) {
3848e2fd318eSIlia Kolomisnky 			struct l2cap_cmd_rej_unk rej;
38492c6d1a2eSGustavo F. Padovan 
38502c6d1a2eSGustavo F. Padovan 			BT_ERR("Wrong link type (%d)", err);
38510a708f8fSGustavo F. Padovan 
38520a708f8fSGustavo F. Padovan 			/* FIXME: Map err to a valid reason */
3853e2fd318eSIlia Kolomisnky 			rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
38540a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
38550a708f8fSGustavo F. Padovan 		}
38560a708f8fSGustavo F. Padovan 
38570a708f8fSGustavo F. Padovan 		data += cmd_len;
38580a708f8fSGustavo F. Padovan 		len  -= cmd_len;
38590a708f8fSGustavo F. Padovan 	}
38600a708f8fSGustavo F. Padovan 
38610a708f8fSGustavo F. Padovan 	kfree_skb(skb);
38620a708f8fSGustavo F. Padovan }
38630a708f8fSGustavo F. Padovan 
386447d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
38650a708f8fSGustavo F. Padovan {
38660a708f8fSGustavo F. Padovan 	u16 our_fcs, rcv_fcs;
3867e4ca6d98SAndrei Emeltchenko 	int hdr_size;
3868e4ca6d98SAndrei Emeltchenko 
3869e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3870e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_EXT_HDR_SIZE;
3871e4ca6d98SAndrei Emeltchenko 	else
3872e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_ENH_HDR_SIZE;
38730a708f8fSGustavo F. Padovan 
387447d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
387503a51213SAndrei Emeltchenko 		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
38760a708f8fSGustavo F. Padovan 		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
38770a708f8fSGustavo F. Padovan 		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
38780a708f8fSGustavo F. Padovan 
38790a708f8fSGustavo F. Padovan 		if (our_fcs != rcv_fcs)
38800a708f8fSGustavo F. Padovan 			return -EBADMSG;
38810a708f8fSGustavo F. Padovan 	}
38820a708f8fSGustavo F. Padovan 	return 0;
38830a708f8fSGustavo F. Padovan }
38840a708f8fSGustavo F. Padovan 
3885525cd185SGustavo F. Padovan static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
38860a708f8fSGustavo F. Padovan {
388788843ab0SAndrei Emeltchenko 	u32 control = 0;
38880a708f8fSGustavo F. Padovan 
38896a026610SGustavo F. Padovan 	chan->frames_sent = 0;
38900a708f8fSGustavo F. Padovan 
38910b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
38920a708f8fSGustavo F. Padovan 
3893e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3894ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
3895525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
3896e2ab4353SGustavo F. Padovan 		set_bit(CONN_RNR_SENT, &chan->conn_state);
38970a708f8fSGustavo F. Padovan 	}
38980a708f8fSGustavo F. Padovan 
3899e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
3900525cd185SGustavo F. Padovan 		l2cap_retransmit_frames(chan);
39010a708f8fSGustavo F. Padovan 
3902525cd185SGustavo F. Padovan 	l2cap_ertm_send(chan);
39030a708f8fSGustavo F. Padovan 
3904e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
39056a026610SGustavo F. Padovan 			chan->frames_sent == 0) {
3906ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
3907525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
39080a708f8fSGustavo F. Padovan 	}
39090a708f8fSGustavo F. Padovan }
39100a708f8fSGustavo F. Padovan 
3911fb45de7dSAndrei Emeltchenko static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u16 tx_seq, u8 sar)
39120a708f8fSGustavo F. Padovan {
39130a708f8fSGustavo F. Padovan 	struct sk_buff *next_skb;
39140a708f8fSGustavo F. Padovan 	int tx_seq_offset, next_tx_seq_offset;
39150a708f8fSGustavo F. Padovan 
39160a708f8fSGustavo F. Padovan 	bt_cb(skb)->tx_seq = tx_seq;
39170a708f8fSGustavo F. Padovan 	bt_cb(skb)->sar = sar;
39180a708f8fSGustavo F. Padovan 
3919f1c6775bSGustavo F. Padovan 	next_skb = skb_peek(&chan->srej_q);
39200a708f8fSGustavo F. Padovan 
3921836be934SAndrei Emeltchenko 	tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
39220a708f8fSGustavo F. Padovan 
3923039d9572SSzymon Janc 	while (next_skb) {
39240a708f8fSGustavo F. Padovan 		if (bt_cb(next_skb)->tx_seq == tx_seq)
39250a708f8fSGustavo F. Padovan 			return -EINVAL;
39260a708f8fSGustavo F. Padovan 
3927836be934SAndrei Emeltchenko 		next_tx_seq_offset = __seq_offset(chan,
3928836be934SAndrei Emeltchenko 				bt_cb(next_skb)->tx_seq, chan->buffer_seq);
39290a708f8fSGustavo F. Padovan 
39300a708f8fSGustavo F. Padovan 		if (next_tx_seq_offset > tx_seq_offset) {
3931f1c6775bSGustavo F. Padovan 			__skb_queue_before(&chan->srej_q, next_skb, skb);
39320a708f8fSGustavo F. Padovan 			return 0;
39330a708f8fSGustavo F. Padovan 		}
39340a708f8fSGustavo F. Padovan 
3935f1c6775bSGustavo F. Padovan 		if (skb_queue_is_last(&chan->srej_q, next_skb))
3936039d9572SSzymon Janc 			next_skb = NULL;
3937039d9572SSzymon Janc 		else
3938039d9572SSzymon Janc 			next_skb = skb_queue_next(&chan->srej_q, next_skb);
3939039d9572SSzymon Janc 	}
39400a708f8fSGustavo F. Padovan 
3941f1c6775bSGustavo F. Padovan 	__skb_queue_tail(&chan->srej_q, skb);
39420a708f8fSGustavo F. Padovan 
39430a708f8fSGustavo F. Padovan 	return 0;
39440a708f8fSGustavo F. Padovan }
39450a708f8fSGustavo F. Padovan 
394684084a31SMat Martineau static void append_skb_frag(struct sk_buff *skb,
394784084a31SMat Martineau 			struct sk_buff *new_frag, struct sk_buff **last_frag)
39480a708f8fSGustavo F. Padovan {
394984084a31SMat Martineau 	/* skb->len reflects data in skb as well as all fragments
395084084a31SMat Martineau 	 * skb->data_len reflects only data in fragments
395184084a31SMat Martineau 	 */
395284084a31SMat Martineau 	if (!skb_has_frag_list(skb))
395384084a31SMat Martineau 		skb_shinfo(skb)->frag_list = new_frag;
395484084a31SMat Martineau 
395584084a31SMat Martineau 	new_frag->next = NULL;
395684084a31SMat Martineau 
395784084a31SMat Martineau 	(*last_frag)->next = new_frag;
395884084a31SMat Martineau 	*last_frag = new_frag;
395984084a31SMat Martineau 
396084084a31SMat Martineau 	skb->len += new_frag->len;
396184084a31SMat Martineau 	skb->data_len += new_frag->len;
396284084a31SMat Martineau 	skb->truesize += new_frag->truesize;
396384084a31SMat Martineau }
396484084a31SMat Martineau 
396588843ab0SAndrei Emeltchenko static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
396684084a31SMat Martineau {
396784084a31SMat Martineau 	int err = -EINVAL;
39680a708f8fSGustavo F. Padovan 
39697e0ef6eeSAndrei Emeltchenko 	switch (__get_ctrl_sar(chan, control)) {
39707e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_UNSEGMENTED:
397184084a31SMat Martineau 		if (chan->sdu)
397284084a31SMat Martineau 			break;
39730a708f8fSGustavo F. Padovan 
397484084a31SMat Martineau 		err = chan->ops->recv(chan->data, skb);
397584084a31SMat Martineau 		break;
39760a708f8fSGustavo F. Padovan 
39777e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_START:
397884084a31SMat Martineau 		if (chan->sdu)
397984084a31SMat Martineau 			break;
39800a708f8fSGustavo F. Padovan 
39816f61fd47SGustavo F. Padovan 		chan->sdu_len = get_unaligned_le16(skb->data);
398203a51213SAndrei Emeltchenko 		skb_pull(skb, L2CAP_SDULEN_SIZE);
39830a708f8fSGustavo F. Padovan 
398484084a31SMat Martineau 		if (chan->sdu_len > chan->imtu) {
398584084a31SMat Martineau 			err = -EMSGSIZE;
398684084a31SMat Martineau 			break;
398784084a31SMat Martineau 		}
39880a708f8fSGustavo F. Padovan 
398984084a31SMat Martineau 		if (skb->len >= chan->sdu_len)
399084084a31SMat Martineau 			break;
399184084a31SMat Martineau 
399284084a31SMat Martineau 		chan->sdu = skb;
399384084a31SMat Martineau 		chan->sdu_last_frag = skb;
399484084a31SMat Martineau 
399584084a31SMat Martineau 		skb = NULL;
399684084a31SMat Martineau 		err = 0;
39970a708f8fSGustavo F. Padovan 		break;
39980a708f8fSGustavo F. Padovan 
39997e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_CONTINUE:
40006f61fd47SGustavo F. Padovan 		if (!chan->sdu)
400184084a31SMat Martineau 			break;
40020a708f8fSGustavo F. Padovan 
400384084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
400484084a31SMat Martineau 				&chan->sdu_last_frag);
400584084a31SMat Martineau 		skb = NULL;
40060a708f8fSGustavo F. Padovan 
400784084a31SMat Martineau 		if (chan->sdu->len >= chan->sdu_len)
400884084a31SMat Martineau 			break;
40090a708f8fSGustavo F. Padovan 
401084084a31SMat Martineau 		err = 0;
40110a708f8fSGustavo F. Padovan 		break;
40120a708f8fSGustavo F. Padovan 
40137e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_END:
40146f61fd47SGustavo F. Padovan 		if (!chan->sdu)
401584084a31SMat Martineau 			break;
40160a708f8fSGustavo F. Padovan 
401784084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
401884084a31SMat Martineau 				&chan->sdu_last_frag);
401984084a31SMat Martineau 		skb = NULL;
40200a708f8fSGustavo F. Padovan 
402184084a31SMat Martineau 		if (chan->sdu->len != chan->sdu_len)
402284084a31SMat Martineau 			break;
40230a708f8fSGustavo F. Padovan 
402484084a31SMat Martineau 		err = chan->ops->recv(chan->data, chan->sdu);
40250a708f8fSGustavo F. Padovan 
402684084a31SMat Martineau 		if (!err) {
402784084a31SMat Martineau 			/* Reassembly complete */
402884084a31SMat Martineau 			chan->sdu = NULL;
402984084a31SMat Martineau 			chan->sdu_last_frag = NULL;
403084084a31SMat Martineau 			chan->sdu_len = 0;
40310a708f8fSGustavo F. Padovan 		}
40320a708f8fSGustavo F. Padovan 		break;
40330a708f8fSGustavo F. Padovan 	}
40340a708f8fSGustavo F. Padovan 
403584084a31SMat Martineau 	if (err) {
40360a708f8fSGustavo F. Padovan 		kfree_skb(skb);
40376f61fd47SGustavo F. Padovan 		kfree_skb(chan->sdu);
40386f61fd47SGustavo F. Padovan 		chan->sdu = NULL;
403984084a31SMat Martineau 		chan->sdu_last_frag = NULL;
404084084a31SMat Martineau 		chan->sdu_len = 0;
404184084a31SMat Martineau 	}
40420a708f8fSGustavo F. Padovan 
404384084a31SMat Martineau 	return err;
40440a708f8fSGustavo F. Padovan }
40450a708f8fSGustavo F. Padovan 
404626f880d2SMat Martineau static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
40470a708f8fSGustavo F. Padovan {
404826f880d2SMat Martineau 	BT_DBG("chan %p, Enter local busy", chan);
404926f880d2SMat Martineau 
405026f880d2SMat Martineau 	set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
40513c588192SMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
405226f880d2SMat Martineau 
405377f918bcSSzymon Janc 	__set_ack_timer(chan);
40540a708f8fSGustavo F. Padovan }
40550a708f8fSGustavo F. Padovan 
405626f880d2SMat Martineau static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
405726f880d2SMat Martineau {
405888843ab0SAndrei Emeltchenko 	u32 control;
40590a708f8fSGustavo F. Padovan 
4060e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
40610a708f8fSGustavo F. Padovan 		goto done;
40620a708f8fSGustavo F. Padovan 
40630b209faeSAndrei Emeltchenko 	control = __set_reqseq(chan, chan->buffer_seq);
4064e3781735SAndrei Emeltchenko 	control |= __set_ctrl_poll(chan);
4065ab784b73SAndrei Emeltchenko 	control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
4066525cd185SGustavo F. Padovan 	l2cap_send_sframe(chan, control);
40676a026610SGustavo F. Padovan 	chan->retry_count = 1;
40680a708f8fSGustavo F. Padovan 
40691a09bcb9SGustavo F. Padovan 	__clear_retrans_timer(chan);
40701a09bcb9SGustavo F. Padovan 	__set_monitor_timer(chan);
40710a708f8fSGustavo F. Padovan 
4072e2ab4353SGustavo F. Padovan 	set_bit(CONN_WAIT_F, &chan->conn_state);
40730a708f8fSGustavo F. Padovan 
40740a708f8fSGustavo F. Padovan done:
4075e2ab4353SGustavo F. Padovan 	clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
4076e2ab4353SGustavo F. Padovan 	clear_bit(CONN_RNR_SENT, &chan->conn_state);
40770a708f8fSGustavo F. Padovan 
407849208c9cSGustavo F. Padovan 	BT_DBG("chan %p, Exit local busy", chan);
40790a708f8fSGustavo F. Padovan }
40800a708f8fSGustavo F. Padovan 
4081e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
40820a708f8fSGustavo F. Padovan {
4083e328140fSMat Martineau 	if (chan->mode == L2CAP_MODE_ERTM) {
4084e328140fSMat Martineau 		if (busy)
408526f880d2SMat Martineau 			l2cap_ertm_enter_local_busy(chan);
4086e328140fSMat Martineau 		else
4087e328140fSMat Martineau 			l2cap_ertm_exit_local_busy(chan);
40880a708f8fSGustavo F. Padovan 	}
40890a708f8fSGustavo F. Padovan }
40900a708f8fSGustavo F. Padovan 
4091fb45de7dSAndrei Emeltchenko static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
40920a708f8fSGustavo F. Padovan {
40930a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
409488843ab0SAndrei Emeltchenko 	u32 control;
40950a708f8fSGustavo F. Padovan 
4096e328140fSMat Martineau 	while ((skb = skb_peek(&chan->srej_q)) &&
4097e328140fSMat Martineau 			!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4098e328140fSMat Martineau 		int err;
4099e328140fSMat Martineau 
41000a708f8fSGustavo F. Padovan 		if (bt_cb(skb)->tx_seq != tx_seq)
41010a708f8fSGustavo F. Padovan 			break;
41020a708f8fSGustavo F. Padovan 
4103f1c6775bSGustavo F. Padovan 		skb = skb_dequeue(&chan->srej_q);
41047e0ef6eeSAndrei Emeltchenko 		control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
410584084a31SMat Martineau 		err = l2cap_reassemble_sdu(chan, skb, control);
4106e328140fSMat Martineau 
4107e328140fSMat Martineau 		if (err < 0) {
4108e328140fSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4109e328140fSMat Martineau 			break;
4110e328140fSMat Martineau 		}
4111e328140fSMat Martineau 
4112836be934SAndrei Emeltchenko 		chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
4113836be934SAndrei Emeltchenko 		tx_seq = __next_seq(chan, tx_seq);
41140a708f8fSGustavo F. Padovan 	}
41150a708f8fSGustavo F. Padovan }
41160a708f8fSGustavo F. Padovan 
4117fb45de7dSAndrei Emeltchenko static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
41180a708f8fSGustavo F. Padovan {
41190a708f8fSGustavo F. Padovan 	struct srej_list *l, *tmp;
412088843ab0SAndrei Emeltchenko 	u32 control;
41210a708f8fSGustavo F. Padovan 
412239d5a3eeSGustavo F. Padovan 	list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
41230a708f8fSGustavo F. Padovan 		if (l->tx_seq == tx_seq) {
41240a708f8fSGustavo F. Padovan 			list_del(&l->list);
41250a708f8fSGustavo F. Padovan 			kfree(l);
41260a708f8fSGustavo F. Padovan 			return;
41270a708f8fSGustavo F. Padovan 		}
4128ab784b73SAndrei Emeltchenko 		control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
41290b209faeSAndrei Emeltchenko 		control |= __set_reqseq(chan, l->tx_seq);
4130525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
41310a708f8fSGustavo F. Padovan 		list_del(&l->list);
413239d5a3eeSGustavo F. Padovan 		list_add_tail(&l->list, &chan->srej_l);
41330a708f8fSGustavo F. Padovan 	}
41340a708f8fSGustavo F. Padovan }
41350a708f8fSGustavo F. Padovan 
4136aef89f21SSzymon Janc static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
41370a708f8fSGustavo F. Padovan {
41380a708f8fSGustavo F. Padovan 	struct srej_list *new;
413988843ab0SAndrei Emeltchenko 	u32 control;
41400a708f8fSGustavo F. Padovan 
414142e5c802SGustavo F. Padovan 	while (tx_seq != chan->expected_tx_seq) {
4142ab784b73SAndrei Emeltchenko 		control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
41430b209faeSAndrei Emeltchenko 		control |= __set_reqseq(chan, chan->expected_tx_seq);
41443c588192SMat Martineau 		l2cap_seq_list_append(&chan->srej_list, chan->expected_tx_seq);
4145525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
41460a708f8fSGustavo F. Padovan 
41470a708f8fSGustavo F. Padovan 		new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
4148aef89f21SSzymon Janc 		if (!new)
4149aef89f21SSzymon Janc 			return -ENOMEM;
4150aef89f21SSzymon Janc 
415142e5c802SGustavo F. Padovan 		new->tx_seq = chan->expected_tx_seq;
4152836be934SAndrei Emeltchenko 
4153836be934SAndrei Emeltchenko 		chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
4154836be934SAndrei Emeltchenko 
415539d5a3eeSGustavo F. Padovan 		list_add_tail(&new->list, &chan->srej_l);
41560a708f8fSGustavo F. Padovan 	}
4157836be934SAndrei Emeltchenko 
4158836be934SAndrei Emeltchenko 	chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
4159aef89f21SSzymon Janc 
4160aef89f21SSzymon Janc 	return 0;
41610a708f8fSGustavo F. Padovan }
41620a708f8fSGustavo F. Padovan 
416388843ab0SAndrei Emeltchenko static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
41640a708f8fSGustavo F. Padovan {
4165fb45de7dSAndrei Emeltchenko 	u16 tx_seq = __get_txseq(chan, rx_control);
41660b209faeSAndrei Emeltchenko 	u16 req_seq = __get_reqseq(chan, rx_control);
41677e0ef6eeSAndrei Emeltchenko 	u8 sar = __get_ctrl_sar(chan, rx_control);
41680a708f8fSGustavo F. Padovan 	int tx_seq_offset, expected_tx_seq_offset;
416947d1ec61SGustavo F. Padovan 	int num_to_ack = (chan->tx_win/6) + 1;
41700a708f8fSGustavo F. Padovan 	int err = 0;
41710a708f8fSGustavo F. Padovan 
417288843ab0SAndrei Emeltchenko 	BT_DBG("chan %p len %d tx_seq %d rx_control 0x%8.8x", chan, skb->len,
4173525cd185SGustavo F. Padovan 							tx_seq, rx_control);
41740a708f8fSGustavo F. Padovan 
417503f6715dSAndrei Emeltchenko 	if (__is_ctrl_final(chan, rx_control) &&
4176e2ab4353SGustavo F. Padovan 			test_bit(CONN_WAIT_F, &chan->conn_state)) {
41771a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
41786a026610SGustavo F. Padovan 		if (chan->unacked_frames > 0)
41791a09bcb9SGustavo F. Padovan 			__set_retrans_timer(chan);
4180e2ab4353SGustavo F. Padovan 		clear_bit(CONN_WAIT_F, &chan->conn_state);
41810a708f8fSGustavo F. Padovan 	}
41820a708f8fSGustavo F. Padovan 
418342e5c802SGustavo F. Padovan 	chan->expected_ack_seq = req_seq;
418442e5c802SGustavo F. Padovan 	l2cap_drop_acked_frames(chan);
41850a708f8fSGustavo F. Padovan 
4186836be934SAndrei Emeltchenko 	tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
41870a708f8fSGustavo F. Padovan 
41880a708f8fSGustavo F. Padovan 	/* invalid tx_seq */
418947d1ec61SGustavo F. Padovan 	if (tx_seq_offset >= chan->tx_win) {
41908c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
41910a708f8fSGustavo F. Padovan 		goto drop;
41920a708f8fSGustavo F. Padovan 	}
41930a708f8fSGustavo F. Padovan 
419477f918bcSSzymon Janc 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
419577f918bcSSzymon Janc 		if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
419677f918bcSSzymon Janc 			l2cap_send_ack(chan);
41970a708f8fSGustavo F. Padovan 		goto drop;
419877f918bcSSzymon Janc 	}
41990a708f8fSGustavo F. Padovan 
420002f1b641SMat Martineau 	if (tx_seq == chan->expected_tx_seq)
420102f1b641SMat Martineau 		goto expected;
420202f1b641SMat Martineau 
4203e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
42040a708f8fSGustavo F. Padovan 		struct srej_list *first;
42050a708f8fSGustavo F. Padovan 
420639d5a3eeSGustavo F. Padovan 		first = list_first_entry(&chan->srej_l,
42070a708f8fSGustavo F. Padovan 				struct srej_list, list);
42080a708f8fSGustavo F. Padovan 		if (tx_seq == first->tx_seq) {
420942e5c802SGustavo F. Padovan 			l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
4210525cd185SGustavo F. Padovan 			l2cap_check_srej_gap(chan, tx_seq);
42110a708f8fSGustavo F. Padovan 
42120a708f8fSGustavo F. Padovan 			list_del(&first->list);
42130a708f8fSGustavo F. Padovan 			kfree(first);
42140a708f8fSGustavo F. Padovan 
421539d5a3eeSGustavo F. Padovan 			if (list_empty(&chan->srej_l)) {
421642e5c802SGustavo F. Padovan 				chan->buffer_seq = chan->buffer_seq_srej;
4217e2ab4353SGustavo F. Padovan 				clear_bit(CONN_SREJ_SENT, &chan->conn_state);
4218525cd185SGustavo F. Padovan 				l2cap_send_ack(chan);
421949208c9cSGustavo F. Padovan 				BT_DBG("chan %p, Exit SREJ_SENT", chan);
42200a708f8fSGustavo F. Padovan 			}
42210a708f8fSGustavo F. Padovan 		} else {
42220a708f8fSGustavo F. Padovan 			struct srej_list *l;
42230a708f8fSGustavo F. Padovan 
42240a708f8fSGustavo F. Padovan 			/* duplicated tx_seq */
422542e5c802SGustavo F. Padovan 			if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
42260a708f8fSGustavo F. Padovan 				goto drop;
42270a708f8fSGustavo F. Padovan 
422839d5a3eeSGustavo F. Padovan 			list_for_each_entry(l, &chan->srej_l, list) {
42290a708f8fSGustavo F. Padovan 				if (l->tx_seq == tx_seq) {
4230525cd185SGustavo F. Padovan 					l2cap_resend_srejframe(chan, tx_seq);
42310a708f8fSGustavo F. Padovan 					return 0;
42320a708f8fSGustavo F. Padovan 				}
42330a708f8fSGustavo F. Padovan 			}
4234aef89f21SSzymon Janc 
4235aef89f21SSzymon Janc 			err = l2cap_send_srejframe(chan, tx_seq);
4236aef89f21SSzymon Janc 			if (err < 0) {
4237aef89f21SSzymon Janc 				l2cap_send_disconn_req(chan->conn, chan, -err);
4238aef89f21SSzymon Janc 				return err;
4239aef89f21SSzymon Janc 			}
42400a708f8fSGustavo F. Padovan 		}
42410a708f8fSGustavo F. Padovan 	} else {
4242836be934SAndrei Emeltchenko 		expected_tx_seq_offset = __seq_offset(chan,
4243836be934SAndrei Emeltchenko 				chan->expected_tx_seq, chan->buffer_seq);
42440a708f8fSGustavo F. Padovan 
42450a708f8fSGustavo F. Padovan 		/* duplicated tx_seq */
42460a708f8fSGustavo F. Padovan 		if (tx_seq_offset < expected_tx_seq_offset)
42470a708f8fSGustavo F. Padovan 			goto drop;
42480a708f8fSGustavo F. Padovan 
4249e2ab4353SGustavo F. Padovan 		set_bit(CONN_SREJ_SENT, &chan->conn_state);
42500a708f8fSGustavo F. Padovan 
425149208c9cSGustavo F. Padovan 		BT_DBG("chan %p, Enter SREJ", chan);
42520a708f8fSGustavo F. Padovan 
425339d5a3eeSGustavo F. Padovan 		INIT_LIST_HEAD(&chan->srej_l);
425442e5c802SGustavo F. Padovan 		chan->buffer_seq_srej = chan->buffer_seq;
42550a708f8fSGustavo F. Padovan 
4256f1c6775bSGustavo F. Padovan 		__skb_queue_head_init(&chan->srej_q);
425742e5c802SGustavo F. Padovan 		l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
42580a708f8fSGustavo F. Padovan 
42590ef3ef0fSSzymon Janc 		/* Set P-bit only if there are some I-frames to ack. */
42600ef3ef0fSSzymon Janc 		if (__clear_ack_timer(chan))
4261e2ab4353SGustavo F. Padovan 			set_bit(CONN_SEND_PBIT, &chan->conn_state);
42620a708f8fSGustavo F. Padovan 
4263aef89f21SSzymon Janc 		err = l2cap_send_srejframe(chan, tx_seq);
4264aef89f21SSzymon Janc 		if (err < 0) {
4265aef89f21SSzymon Janc 			l2cap_send_disconn_req(chan->conn, chan, -err);
4266aef89f21SSzymon Janc 			return err;
4267aef89f21SSzymon Janc 		}
42680a708f8fSGustavo F. Padovan 	}
42690a708f8fSGustavo F. Padovan 	return 0;
42700a708f8fSGustavo F. Padovan 
42710a708f8fSGustavo F. Padovan expected:
4272836be934SAndrei Emeltchenko 	chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
42730a708f8fSGustavo F. Padovan 
4274e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
42750a708f8fSGustavo F. Padovan 		bt_cb(skb)->tx_seq = tx_seq;
42760a708f8fSGustavo F. Padovan 		bt_cb(skb)->sar = sar;
4277f1c6775bSGustavo F. Padovan 		__skb_queue_tail(&chan->srej_q, skb);
42780a708f8fSGustavo F. Padovan 		return 0;
42790a708f8fSGustavo F. Padovan 	}
42800a708f8fSGustavo F. Padovan 
428184084a31SMat Martineau 	err = l2cap_reassemble_sdu(chan, skb, rx_control);
4282836be934SAndrei Emeltchenko 	chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
4283836be934SAndrei Emeltchenko 
4284e328140fSMat Martineau 	if (err < 0) {
4285e328140fSMat Martineau 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4286e328140fSMat Martineau 		return err;
4287e328140fSMat Martineau 	}
42880a708f8fSGustavo F. Padovan 
428903f6715dSAndrei Emeltchenko 	if (__is_ctrl_final(chan, rx_control)) {
4290e2ab4353SGustavo F. Padovan 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
4291525cd185SGustavo F. Padovan 			l2cap_retransmit_frames(chan);
42920a708f8fSGustavo F. Padovan 	}
42930a708f8fSGustavo F. Padovan 
42940a708f8fSGustavo F. Padovan 
42956a026610SGustavo F. Padovan 	chan->num_acked = (chan->num_acked + 1) % num_to_ack;
42966a026610SGustavo F. Padovan 	if (chan->num_acked == num_to_ack - 1)
4297525cd185SGustavo F. Padovan 		l2cap_send_ack(chan);
42984d611e4dSGustavo F. Padovan 	else
42994d611e4dSGustavo F. Padovan 		__set_ack_timer(chan);
43000a708f8fSGustavo F. Padovan 
43010a708f8fSGustavo F. Padovan 	return 0;
43020a708f8fSGustavo F. Padovan 
43030a708f8fSGustavo F. Padovan drop:
43040a708f8fSGustavo F. Padovan 	kfree_skb(skb);
43050a708f8fSGustavo F. Padovan 	return 0;
43060a708f8fSGustavo F. Padovan }
43070a708f8fSGustavo F. Padovan 
430888843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
43090a708f8fSGustavo F. Padovan {
431088843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
43110b209faeSAndrei Emeltchenko 				__get_reqseq(chan, rx_control), rx_control);
43120a708f8fSGustavo F. Padovan 
43130b209faeSAndrei Emeltchenko 	chan->expected_ack_seq = __get_reqseq(chan, rx_control);
431442e5c802SGustavo F. Padovan 	l2cap_drop_acked_frames(chan);
43150a708f8fSGustavo F. Padovan 
4316e3781735SAndrei Emeltchenko 	if (__is_ctrl_poll(chan, rx_control)) {
4317e2ab4353SGustavo F. Padovan 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
4318e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
4319e2ab4353SGustavo F. Padovan 			if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
43206a026610SGustavo F. Padovan 					(chan->unacked_frames > 0))
43211a09bcb9SGustavo F. Padovan 				__set_retrans_timer(chan);
43220a708f8fSGustavo F. Padovan 
4323e2ab4353SGustavo F. Padovan 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4324525cd185SGustavo F. Padovan 			l2cap_send_srejtail(chan);
43250a708f8fSGustavo F. Padovan 		} else {
4326525cd185SGustavo F. Padovan 			l2cap_send_i_or_rr_or_rnr(chan);
43270a708f8fSGustavo F. Padovan 		}
43280a708f8fSGustavo F. Padovan 
432903f6715dSAndrei Emeltchenko 	} else if (__is_ctrl_final(chan, rx_control)) {
4330e2ab4353SGustavo F. Padovan 		clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
43310a708f8fSGustavo F. Padovan 
4332e2ab4353SGustavo F. Padovan 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
4333525cd185SGustavo F. Padovan 			l2cap_retransmit_frames(chan);
43340a708f8fSGustavo F. Padovan 
43350a708f8fSGustavo F. Padovan 	} else {
4336e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
43376a026610SGustavo F. Padovan 				(chan->unacked_frames > 0))
43381a09bcb9SGustavo F. Padovan 			__set_retrans_timer(chan);
43390a708f8fSGustavo F. Padovan 
4340e2ab4353SGustavo F. Padovan 		clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4341e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
4342525cd185SGustavo F. Padovan 			l2cap_send_ack(chan);
43430a708f8fSGustavo F. Padovan 		else
4344525cd185SGustavo F. Padovan 			l2cap_ertm_send(chan);
43450a708f8fSGustavo F. Padovan 	}
43460a708f8fSGustavo F. Padovan }
43470a708f8fSGustavo F. Padovan 
434888843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
43490a708f8fSGustavo F. Padovan {
43500b209faeSAndrei Emeltchenko 	u16 tx_seq = __get_reqseq(chan, rx_control);
43510a708f8fSGustavo F. Padovan 
435288843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
43530a708f8fSGustavo F. Padovan 
4354e2ab4353SGustavo F. Padovan 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
43550a708f8fSGustavo F. Padovan 
435642e5c802SGustavo F. Padovan 	chan->expected_ack_seq = tx_seq;
435742e5c802SGustavo F. Padovan 	l2cap_drop_acked_frames(chan);
43580a708f8fSGustavo F. Padovan 
435903f6715dSAndrei Emeltchenko 	if (__is_ctrl_final(chan, rx_control)) {
4360e2ab4353SGustavo F. Padovan 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
4361525cd185SGustavo F. Padovan 			l2cap_retransmit_frames(chan);
43620a708f8fSGustavo F. Padovan 	} else {
4363525cd185SGustavo F. Padovan 		l2cap_retransmit_frames(chan);
43640a708f8fSGustavo F. Padovan 
4365e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_WAIT_F, &chan->conn_state))
4366e2ab4353SGustavo F. Padovan 			set_bit(CONN_REJ_ACT, &chan->conn_state);
43670a708f8fSGustavo F. Padovan 	}
43680a708f8fSGustavo F. Padovan }
436988843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
43700a708f8fSGustavo F. Padovan {
43710b209faeSAndrei Emeltchenko 	u16 tx_seq = __get_reqseq(chan, rx_control);
43720a708f8fSGustavo F. Padovan 
437388843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
43740a708f8fSGustavo F. Padovan 
4375e2ab4353SGustavo F. Padovan 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
43760a708f8fSGustavo F. Padovan 
4377e3781735SAndrei Emeltchenko 	if (__is_ctrl_poll(chan, rx_control)) {
437842e5c802SGustavo F. Padovan 		chan->expected_ack_seq = tx_seq;
437942e5c802SGustavo F. Padovan 		l2cap_drop_acked_frames(chan);
43800a708f8fSGustavo F. Padovan 
4381e2ab4353SGustavo F. Padovan 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
4382525cd185SGustavo F. Padovan 		l2cap_retransmit_one_frame(chan, tx_seq);
43830a708f8fSGustavo F. Padovan 
4384525cd185SGustavo F. Padovan 		l2cap_ertm_send(chan);
43850a708f8fSGustavo F. Padovan 
4386e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
43876a026610SGustavo F. Padovan 			chan->srej_save_reqseq = tx_seq;
4388e2ab4353SGustavo F. Padovan 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
43890a708f8fSGustavo F. Padovan 		}
439003f6715dSAndrei Emeltchenko 	} else if (__is_ctrl_final(chan, rx_control)) {
4391e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
43926a026610SGustavo F. Padovan 				chan->srej_save_reqseq == tx_seq)
4393e2ab4353SGustavo F. Padovan 			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
43940a708f8fSGustavo F. Padovan 		else
4395525cd185SGustavo F. Padovan 			l2cap_retransmit_one_frame(chan, tx_seq);
43960a708f8fSGustavo F. Padovan 	} else {
4397525cd185SGustavo F. Padovan 		l2cap_retransmit_one_frame(chan, tx_seq);
4398e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
43996a026610SGustavo F. Padovan 			chan->srej_save_reqseq = tx_seq;
4400e2ab4353SGustavo F. Padovan 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
44010a708f8fSGustavo F. Padovan 		}
44020a708f8fSGustavo F. Padovan 	}
44030a708f8fSGustavo F. Padovan }
44040a708f8fSGustavo F. Padovan 
440588843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
44060a708f8fSGustavo F. Padovan {
44070b209faeSAndrei Emeltchenko 	u16 tx_seq = __get_reqseq(chan, rx_control);
44080a708f8fSGustavo F. Padovan 
440988843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
44100a708f8fSGustavo F. Padovan 
4411e2ab4353SGustavo F. Padovan 	set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
441242e5c802SGustavo F. Padovan 	chan->expected_ack_seq = tx_seq;
441342e5c802SGustavo F. Padovan 	l2cap_drop_acked_frames(chan);
44140a708f8fSGustavo F. Padovan 
4415e3781735SAndrei Emeltchenko 	if (__is_ctrl_poll(chan, rx_control))
4416e2ab4353SGustavo F. Padovan 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
44170a708f8fSGustavo F. Padovan 
4418e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
44191a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
4420e3781735SAndrei Emeltchenko 		if (__is_ctrl_poll(chan, rx_control))
4421525cd185SGustavo F. Padovan 			l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
44220a708f8fSGustavo F. Padovan 		return;
44230a708f8fSGustavo F. Padovan 	}
44240a708f8fSGustavo F. Padovan 
4425e3781735SAndrei Emeltchenko 	if (__is_ctrl_poll(chan, rx_control)) {
4426525cd185SGustavo F. Padovan 		l2cap_send_srejtail(chan);
4427ab784b73SAndrei Emeltchenko 	} else {
4428ab784b73SAndrei Emeltchenko 		rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4429ab784b73SAndrei Emeltchenko 		l2cap_send_sframe(chan, rx_control);
4430ab784b73SAndrei Emeltchenko 	}
44310a708f8fSGustavo F. Padovan }
44320a708f8fSGustavo F. Padovan 
443388843ab0SAndrei Emeltchenko static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
44340a708f8fSGustavo F. Padovan {
443588843ab0SAndrei Emeltchenko 	BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
44360a708f8fSGustavo F. Padovan 
443703f6715dSAndrei Emeltchenko 	if (__is_ctrl_final(chan, rx_control) &&
4438e2ab4353SGustavo F. Padovan 			test_bit(CONN_WAIT_F, &chan->conn_state)) {
44391a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
44406a026610SGustavo F. Padovan 		if (chan->unacked_frames > 0)
44411a09bcb9SGustavo F. Padovan 			__set_retrans_timer(chan);
4442e2ab4353SGustavo F. Padovan 		clear_bit(CONN_WAIT_F, &chan->conn_state);
44430a708f8fSGustavo F. Padovan 	}
44440a708f8fSGustavo F. Padovan 
4445ab784b73SAndrei Emeltchenko 	switch (__get_ctrl_super(chan, rx_control)) {
4446ab784b73SAndrei Emeltchenko 	case L2CAP_SUPER_RR:
4447525cd185SGustavo F. Padovan 		l2cap_data_channel_rrframe(chan, rx_control);
44480a708f8fSGustavo F. Padovan 		break;
44490a708f8fSGustavo F. Padovan 
4450ab784b73SAndrei Emeltchenko 	case L2CAP_SUPER_REJ:
4451525cd185SGustavo F. Padovan 		l2cap_data_channel_rejframe(chan, rx_control);
44520a708f8fSGustavo F. Padovan 		break;
44530a708f8fSGustavo F. Padovan 
4454ab784b73SAndrei Emeltchenko 	case L2CAP_SUPER_SREJ:
4455525cd185SGustavo F. Padovan 		l2cap_data_channel_srejframe(chan, rx_control);
44560a708f8fSGustavo F. Padovan 		break;
44570a708f8fSGustavo F. Padovan 
4458ab784b73SAndrei Emeltchenko 	case L2CAP_SUPER_RNR:
4459525cd185SGustavo F. Padovan 		l2cap_data_channel_rnrframe(chan, rx_control);
44600a708f8fSGustavo F. Padovan 		break;
44610a708f8fSGustavo F. Padovan 	}
44620a708f8fSGustavo F. Padovan 
44630a708f8fSGustavo F. Padovan 	kfree_skb(skb);
44640a708f8fSGustavo F. Padovan 	return 0;
44650a708f8fSGustavo F. Padovan }
44660a708f8fSGustavo F. Padovan 
4467cad8f1d0SSzymon Janc static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
44680a708f8fSGustavo F. Padovan {
446988843ab0SAndrei Emeltchenko 	u32 control;
44700b209faeSAndrei Emeltchenko 	u16 req_seq;
44710a708f8fSGustavo F. Padovan 	int len, next_tx_seq_offset, req_seq_offset;
44720a708f8fSGustavo F. Padovan 
4473b76bbd66SMat Martineau 	__unpack_control(chan, skb);
4474b76bbd66SMat Martineau 
447588843ab0SAndrei Emeltchenko 	control = __get_control(chan, skb->data);
447688843ab0SAndrei Emeltchenko 	skb_pull(skb, __ctrl_size(chan));
44770a708f8fSGustavo F. Padovan 	len = skb->len;
44780a708f8fSGustavo F. Padovan 
44790a708f8fSGustavo F. Padovan 	/*
44800a708f8fSGustavo F. Padovan 	 * We can just drop the corrupted I-frame here.
44810a708f8fSGustavo F. Padovan 	 * Receiver will miss it and start proper recovery
44820a708f8fSGustavo F. Padovan 	 * procedures and ask retransmission.
44830a708f8fSGustavo F. Padovan 	 */
448447d1ec61SGustavo F. Padovan 	if (l2cap_check_fcs(chan, skb))
44850a708f8fSGustavo F. Padovan 		goto drop;
44860a708f8fSGustavo F. Padovan 
4487793c2f1cSAndrei Emeltchenko 	if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
448803a51213SAndrei Emeltchenko 		len -= L2CAP_SDULEN_SIZE;
44890a708f8fSGustavo F. Padovan 
449047d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
449103a51213SAndrei Emeltchenko 		len -= L2CAP_FCS_SIZE;
44920a708f8fSGustavo F. Padovan 
449347d1ec61SGustavo F. Padovan 	if (len > chan->mps) {
44948c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
44950a708f8fSGustavo F. Padovan 		goto drop;
44960a708f8fSGustavo F. Padovan 	}
44970a708f8fSGustavo F. Padovan 
44980b209faeSAndrei Emeltchenko 	req_seq = __get_reqseq(chan, control);
44990a708f8fSGustavo F. Padovan 
4500836be934SAndrei Emeltchenko 	req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
4501836be934SAndrei Emeltchenko 
4502836be934SAndrei Emeltchenko 	next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
4503836be934SAndrei Emeltchenko 						chan->expected_ack_seq);
45040a708f8fSGustavo F. Padovan 
45050a708f8fSGustavo F. Padovan 	/* check for invalid req-seq */
45060a708f8fSGustavo F. Padovan 	if (req_seq_offset > next_tx_seq_offset) {
45078c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
45080a708f8fSGustavo F. Padovan 		goto drop;
45090a708f8fSGustavo F. Padovan 	}
45100a708f8fSGustavo F. Padovan 
4511793c2f1cSAndrei Emeltchenko 	if (!__is_sframe(chan, control)) {
45120a708f8fSGustavo F. Padovan 		if (len < 0) {
45138c1d787bSGustavo F. Padovan 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
45140a708f8fSGustavo F. Padovan 			goto drop;
45150a708f8fSGustavo F. Padovan 		}
45160a708f8fSGustavo F. Padovan 
4517525cd185SGustavo F. Padovan 		l2cap_data_channel_iframe(chan, control, skb);
45180a708f8fSGustavo F. Padovan 	} else {
45190a708f8fSGustavo F. Padovan 		if (len != 0) {
45200a708f8fSGustavo F. Padovan 			BT_ERR("%d", len);
45218c1d787bSGustavo F. Padovan 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
45220a708f8fSGustavo F. Padovan 			goto drop;
45230a708f8fSGustavo F. Padovan 		}
45240a708f8fSGustavo F. Padovan 
4525525cd185SGustavo F. Padovan 		l2cap_data_channel_sframe(chan, control, skb);
45260a708f8fSGustavo F. Padovan 	}
45270a708f8fSGustavo F. Padovan 
45280a708f8fSGustavo F. Padovan 	return 0;
45290a708f8fSGustavo F. Padovan 
45300a708f8fSGustavo F. Padovan drop:
45310a708f8fSGustavo F. Padovan 	kfree_skb(skb);
45320a708f8fSGustavo F. Padovan 	return 0;
45330a708f8fSGustavo F. Padovan }
45340a708f8fSGustavo F. Padovan 
45350a708f8fSGustavo F. Padovan static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
45360a708f8fSGustavo F. Padovan {
453748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
453888843ab0SAndrei Emeltchenko 	u32 control;
4539fb45de7dSAndrei Emeltchenko 	u16 tx_seq;
45400a708f8fSGustavo F. Padovan 	int len;
45410a708f8fSGustavo F. Padovan 
4542baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, cid);
454348454079SGustavo F. Padovan 	if (!chan) {
45440a708f8fSGustavo F. Padovan 		BT_DBG("unknown cid 0x%4.4x", cid);
45456be36555SAndrei Emeltchenko 		/* Drop packet and return */
45463379013bSDan Carpenter 		kfree_skb(skb);
45476be36555SAndrei Emeltchenko 		return 0;
45480a708f8fSGustavo F. Padovan 	}
45490a708f8fSGustavo F. Padovan 
45506be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
45510a708f8fSGustavo F. Padovan 
455249208c9cSGustavo F. Padovan 	BT_DBG("chan %p, len %d", chan, skb->len);
45530a708f8fSGustavo F. Padovan 
455489bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
45550a708f8fSGustavo F. Padovan 		goto drop;
45560a708f8fSGustavo F. Padovan 
45570c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
45580a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
45590a708f8fSGustavo F. Padovan 		/* If socket recv buffers overflows we drop data here
45600a708f8fSGustavo F. Padovan 		 * which is *bad* because L2CAP has to be reliable.
45610a708f8fSGustavo F. Padovan 		 * But we don't have any other choice. L2CAP doesn't
45620a708f8fSGustavo F. Padovan 		 * provide flow control mechanism. */
45630a708f8fSGustavo F. Padovan 
45640c1bc5c6SGustavo F. Padovan 		if (chan->imtu < skb->len)
45650a708f8fSGustavo F. Padovan 			goto drop;
45660a708f8fSGustavo F. Padovan 
456723070494SGustavo F. Padovan 		if (!chan->ops->recv(chan->data, skb))
45680a708f8fSGustavo F. Padovan 			goto done;
45690a708f8fSGustavo F. Padovan 		break;
45700a708f8fSGustavo F. Padovan 
45710a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
45725ef8cb9eSAndrei Emeltchenko 		l2cap_ertm_data_rcv(chan, skb);
45730a708f8fSGustavo F. Padovan 
45740a708f8fSGustavo F. Padovan 		goto done;
45750a708f8fSGustavo F. Padovan 
45760a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
457788843ab0SAndrei Emeltchenko 		control = __get_control(chan, skb->data);
457888843ab0SAndrei Emeltchenko 		skb_pull(skb, __ctrl_size(chan));
45790a708f8fSGustavo F. Padovan 		len = skb->len;
45800a708f8fSGustavo F. Padovan 
458147d1ec61SGustavo F. Padovan 		if (l2cap_check_fcs(chan, skb))
45820a708f8fSGustavo F. Padovan 			goto drop;
45830a708f8fSGustavo F. Padovan 
45847e0ef6eeSAndrei Emeltchenko 		if (__is_sar_start(chan, control))
458503a51213SAndrei Emeltchenko 			len -= L2CAP_SDULEN_SIZE;
45860a708f8fSGustavo F. Padovan 
458747d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16)
458803a51213SAndrei Emeltchenko 			len -= L2CAP_FCS_SIZE;
45890a708f8fSGustavo F. Padovan 
4590793c2f1cSAndrei Emeltchenko 		if (len > chan->mps || len < 0 || __is_sframe(chan, control))
45910a708f8fSGustavo F. Padovan 			goto drop;
45920a708f8fSGustavo F. Padovan 
4593fb45de7dSAndrei Emeltchenko 		tx_seq = __get_txseq(chan, control);
45940a708f8fSGustavo F. Padovan 
459584084a31SMat Martineau 		if (chan->expected_tx_seq != tx_seq) {
459684084a31SMat Martineau 			/* Frame(s) missing - must discard partial SDU */
459784084a31SMat Martineau 			kfree_skb(chan->sdu);
459884084a31SMat Martineau 			chan->sdu = NULL;
459984084a31SMat Martineau 			chan->sdu_last_frag = NULL;
460084084a31SMat Martineau 			chan->sdu_len = 0;
460184084a31SMat Martineau 
460284084a31SMat Martineau 			/* TODO: Notify userland of missing data */
460384084a31SMat Martineau 		}
460484084a31SMat Martineau 
4605836be934SAndrei Emeltchenko 		chan->expected_tx_seq = __next_seq(chan, tx_seq);
46060a708f8fSGustavo F. Padovan 
460784084a31SMat Martineau 		if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
460884084a31SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
46090a708f8fSGustavo F. Padovan 
46100a708f8fSGustavo F. Padovan 		goto done;
46110a708f8fSGustavo F. Padovan 
46120a708f8fSGustavo F. Padovan 	default:
46130c1bc5c6SGustavo F. Padovan 		BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
46140a708f8fSGustavo F. Padovan 		break;
46150a708f8fSGustavo F. Padovan 	}
46160a708f8fSGustavo F. Padovan 
46170a708f8fSGustavo F. Padovan drop:
46180a708f8fSGustavo F. Padovan 	kfree_skb(skb);
46190a708f8fSGustavo F. Padovan 
46200a708f8fSGustavo F. Padovan done:
46216be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
46220a708f8fSGustavo F. Padovan 
46230a708f8fSGustavo F. Padovan 	return 0;
46240a708f8fSGustavo F. Padovan }
46250a708f8fSGustavo F. Padovan 
46260a708f8fSGustavo F. Padovan static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
46270a708f8fSGustavo F. Padovan {
462823691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
46290a708f8fSGustavo F. Padovan 
463023691d75SGustavo F. Padovan 	chan = l2cap_global_chan_by_psm(0, psm, conn->src);
463123691d75SGustavo F. Padovan 	if (!chan)
46320a708f8fSGustavo F. Padovan 		goto drop;
46330a708f8fSGustavo F. Padovan 
46345b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
46350a708f8fSGustavo F. Padovan 
463689bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
46370a708f8fSGustavo F. Padovan 		goto drop;
46380a708f8fSGustavo F. Padovan 
4639e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
46400a708f8fSGustavo F. Padovan 		goto drop;
46410a708f8fSGustavo F. Padovan 
464223070494SGustavo F. Padovan 	if (!chan->ops->recv(chan->data, skb))
46435b4cedaaSAndrei Emeltchenko 		return 0;
46440a708f8fSGustavo F. Padovan 
46450a708f8fSGustavo F. Padovan drop:
46460a708f8fSGustavo F. Padovan 	kfree_skb(skb);
46470a708f8fSGustavo F. Padovan 
46480a708f8fSGustavo F. Padovan 	return 0;
46490a708f8fSGustavo F. Padovan }
46500a708f8fSGustavo F. Padovan 
4651d9b88702SAndrei Emeltchenko static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid,
4652d9b88702SAndrei Emeltchenko 				    struct sk_buff *skb)
46539f69bda6SGustavo F. Padovan {
465423691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
46559f69bda6SGustavo F. Padovan 
465623691d75SGustavo F. Padovan 	chan = l2cap_global_chan_by_scid(0, cid, conn->src);
465723691d75SGustavo F. Padovan 	if (!chan)
46589f69bda6SGustavo F. Padovan 		goto drop;
46599f69bda6SGustavo F. Padovan 
46605b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
46619f69bda6SGustavo F. Padovan 
466289bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
46639f69bda6SGustavo F. Padovan 		goto drop;
46649f69bda6SGustavo F. Padovan 
4665e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
46669f69bda6SGustavo F. Padovan 		goto drop;
46679f69bda6SGustavo F. Padovan 
466823070494SGustavo F. Padovan 	if (!chan->ops->recv(chan->data, skb))
46695b4cedaaSAndrei Emeltchenko 		return 0;
46709f69bda6SGustavo F. Padovan 
46719f69bda6SGustavo F. Padovan drop:
46729f69bda6SGustavo F. Padovan 	kfree_skb(skb);
46739f69bda6SGustavo F. Padovan 
46749f69bda6SGustavo F. Padovan 	return 0;
46759f69bda6SGustavo F. Padovan }
46769f69bda6SGustavo F. Padovan 
46770a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
46780a708f8fSGustavo F. Padovan {
46790a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh = (void *) skb->data;
46800a708f8fSGustavo F. Padovan 	u16 cid, len;
46810a708f8fSGustavo F. Padovan 	__le16 psm;
46820a708f8fSGustavo F. Padovan 
46830a708f8fSGustavo F. Padovan 	skb_pull(skb, L2CAP_HDR_SIZE);
46840a708f8fSGustavo F. Padovan 	cid = __le16_to_cpu(lh->cid);
46850a708f8fSGustavo F. Padovan 	len = __le16_to_cpu(lh->len);
46860a708f8fSGustavo F. Padovan 
46870a708f8fSGustavo F. Padovan 	if (len != skb->len) {
46880a708f8fSGustavo F. Padovan 		kfree_skb(skb);
46890a708f8fSGustavo F. Padovan 		return;
46900a708f8fSGustavo F. Padovan 	}
46910a708f8fSGustavo F. Padovan 
46920a708f8fSGustavo F. Padovan 	BT_DBG("len %d, cid 0x%4.4x", len, cid);
46930a708f8fSGustavo F. Padovan 
46940a708f8fSGustavo F. Padovan 	switch (cid) {
46953300d9a9SClaudio Takahasi 	case L2CAP_CID_LE_SIGNALING:
46960a708f8fSGustavo F. Padovan 	case L2CAP_CID_SIGNALING:
46970a708f8fSGustavo F. Padovan 		l2cap_sig_channel(conn, skb);
46980a708f8fSGustavo F. Padovan 		break;
46990a708f8fSGustavo F. Padovan 
47000a708f8fSGustavo F. Padovan 	case L2CAP_CID_CONN_LESS:
4701097db76cSAndrei Emeltchenko 		psm = get_unaligned((__le16 *) skb->data);
47020a708f8fSGustavo F. Padovan 		skb_pull(skb, 2);
47030a708f8fSGustavo F. Padovan 		l2cap_conless_channel(conn, psm, skb);
47040a708f8fSGustavo F. Padovan 		break;
47050a708f8fSGustavo F. Padovan 
47069f69bda6SGustavo F. Padovan 	case L2CAP_CID_LE_DATA:
47079f69bda6SGustavo F. Padovan 		l2cap_att_channel(conn, cid, skb);
47089f69bda6SGustavo F. Padovan 		break;
47099f69bda6SGustavo F. Padovan 
4710b501d6a1SAnderson Briglia 	case L2CAP_CID_SMP:
4711b501d6a1SAnderson Briglia 		if (smp_sig_channel(conn, skb))
4712b501d6a1SAnderson Briglia 			l2cap_conn_del(conn->hcon, EACCES);
4713b501d6a1SAnderson Briglia 		break;
4714b501d6a1SAnderson Briglia 
47150a708f8fSGustavo F. Padovan 	default:
47160a708f8fSGustavo F. Padovan 		l2cap_data_channel(conn, cid, skb);
47170a708f8fSGustavo F. Padovan 		break;
47180a708f8fSGustavo F. Padovan 	}
47190a708f8fSGustavo F. Padovan }
47200a708f8fSGustavo F. Padovan 
47210a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
47220a708f8fSGustavo F. Padovan 
4723686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
47240a708f8fSGustavo F. Padovan {
47250a708f8fSGustavo F. Padovan 	int exact = 0, lm1 = 0, lm2 = 0;
472623691d75SGustavo F. Padovan 	struct l2cap_chan *c;
47270a708f8fSGustavo F. Padovan 
47280a708f8fSGustavo F. Padovan 	BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
47290a708f8fSGustavo F. Padovan 
47300a708f8fSGustavo F. Padovan 	/* Find listening sockets and check their link_mode */
473123691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
473223691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
473323691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
47344343478fSGustavo F. Padovan 
473589bc500eSGustavo F. Padovan 		if (c->state != BT_LISTEN)
47360a708f8fSGustavo F. Padovan 			continue;
47370a708f8fSGustavo F. Padovan 
47380a708f8fSGustavo F. Padovan 		if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
47390a708f8fSGustavo F. Padovan 			lm1 |= HCI_LM_ACCEPT;
474043bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
47410a708f8fSGustavo F. Padovan 				lm1 |= HCI_LM_MASTER;
47420a708f8fSGustavo F. Padovan 			exact++;
47430a708f8fSGustavo F. Padovan 		} else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
47440a708f8fSGustavo F. Padovan 			lm2 |= HCI_LM_ACCEPT;
474543bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
47460a708f8fSGustavo F. Padovan 				lm2 |= HCI_LM_MASTER;
47470a708f8fSGustavo F. Padovan 		}
47480a708f8fSGustavo F. Padovan 	}
474923691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
47500a708f8fSGustavo F. Padovan 
47510a708f8fSGustavo F. Padovan 	return exact ? lm1 : lm2;
47520a708f8fSGustavo F. Padovan }
47530a708f8fSGustavo F. Padovan 
4754686ebf28SUlisses Furquim int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
47550a708f8fSGustavo F. Padovan {
47560a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
47570a708f8fSGustavo F. Padovan 
47580a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
47590a708f8fSGustavo F. Padovan 
47600a708f8fSGustavo F. Padovan 	if (!status) {
47610a708f8fSGustavo F. Padovan 		conn = l2cap_conn_add(hcon, status);
47620a708f8fSGustavo F. Padovan 		if (conn)
47630a708f8fSGustavo F. Padovan 			l2cap_conn_ready(conn);
47640a708f8fSGustavo F. Padovan 	} else
4765e175072fSJoe Perches 		l2cap_conn_del(hcon, bt_to_errno(status));
47660a708f8fSGustavo F. Padovan 
47670a708f8fSGustavo F. Padovan 	return 0;
47680a708f8fSGustavo F. Padovan }
47690a708f8fSGustavo F. Padovan 
4770686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
47710a708f8fSGustavo F. Padovan {
47720a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
47730a708f8fSGustavo F. Padovan 
47740a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p", hcon);
47750a708f8fSGustavo F. Padovan 
4776686ebf28SUlisses Furquim 	if (!conn)
47779f5a0d7bSAndrei Emeltchenko 		return HCI_ERROR_REMOTE_USER_TERM;
47780a708f8fSGustavo F. Padovan 	return conn->disc_reason;
47790a708f8fSGustavo F. Padovan }
47800a708f8fSGustavo F. Padovan 
4781686ebf28SUlisses Furquim int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
47820a708f8fSGustavo F. Padovan {
47830a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p reason %d", hcon, reason);
47840a708f8fSGustavo F. Padovan 
4785e175072fSJoe Perches 	l2cap_conn_del(hcon, bt_to_errno(reason));
47860a708f8fSGustavo F. Padovan 	return 0;
47870a708f8fSGustavo F. Padovan }
47880a708f8fSGustavo F. Padovan 
47894343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
47900a708f8fSGustavo F. Padovan {
4791715ec005SGustavo F. Padovan 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
47920a708f8fSGustavo F. Padovan 		return;
47930a708f8fSGustavo F. Padovan 
47940a708f8fSGustavo F. Padovan 	if (encrypt == 0x00) {
47954343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM) {
4796ba13ccd9SMarcel Holtmann 			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
47974343478fSGustavo F. Padovan 		} else if (chan->sec_level == BT_SECURITY_HIGH)
47980f852724SGustavo F. Padovan 			l2cap_chan_close(chan, ECONNREFUSED);
47990a708f8fSGustavo F. Padovan 	} else {
48004343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM)
4801c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
48020a708f8fSGustavo F. Padovan 	}
48030a708f8fSGustavo F. Padovan }
48040a708f8fSGustavo F. Padovan 
4805686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
48060a708f8fSGustavo F. Padovan {
48070a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
480848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
48090a708f8fSGustavo F. Padovan 
48100a708f8fSGustavo F. Padovan 	if (!conn)
48110a708f8fSGustavo F. Padovan 		return 0;
48120a708f8fSGustavo F. Padovan 
48130a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
48140a708f8fSGustavo F. Padovan 
4815160dc6acSVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
4816160dc6acSVinicius Costa Gomes 		smp_distribute_keys(conn, 0);
481717cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->security_timer);
4818160dc6acSVinicius Costa Gomes 	}
4819160dc6acSVinicius Costa Gomes 
48203df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
48210a708f8fSGustavo F. Padovan 
48223df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
48236be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
48240a708f8fSGustavo F. Padovan 
4825f1cb9af5SVinicius Costa Gomes 		BT_DBG("chan->scid %d", chan->scid);
4826f1cb9af5SVinicius Costa Gomes 
4827f1cb9af5SVinicius Costa Gomes 		if (chan->scid == L2CAP_CID_LE_DATA) {
4828f1cb9af5SVinicius Costa Gomes 			if (!status && encrypt) {
4829f1cb9af5SVinicius Costa Gomes 				chan->sec_level = hcon->sec_level;
4830cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
4831f1cb9af5SVinicius Costa Gomes 			}
4832f1cb9af5SVinicius Costa Gomes 
48336be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
4834f1cb9af5SVinicius Costa Gomes 			continue;
4835f1cb9af5SVinicius Costa Gomes 		}
4836f1cb9af5SVinicius Costa Gomes 
4837c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
48386be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
48390a708f8fSGustavo F. Padovan 			continue;
48400a708f8fSGustavo F. Padovan 		}
48410a708f8fSGustavo F. Padovan 
484289bc500eSGustavo F. Padovan 		if (!status && (chan->state == BT_CONNECTED ||
484389bc500eSGustavo F. Padovan 						chan->state == BT_CONFIG)) {
48444343478fSGustavo F. Padovan 			l2cap_check_encryption(chan, encrypt);
48456be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
48460a708f8fSGustavo F. Padovan 			continue;
48470a708f8fSGustavo F. Padovan 		}
48480a708f8fSGustavo F. Padovan 
484989bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
48500a708f8fSGustavo F. Padovan 			if (!status) {
48519b27f350SAndrei Emeltchenko 				l2cap_send_conn_req(chan);
48520a708f8fSGustavo F. Padovan 			} else {
4853ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
48540a708f8fSGustavo F. Padovan 			}
485589bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
48566be36555SAndrei Emeltchenko 			struct sock *sk = chan->sk;
48570a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
4858df3c3931SJohan Hedberg 			__u16 res, stat;
48590a708f8fSGustavo F. Padovan 
48606be36555SAndrei Emeltchenko 			lock_sock(sk);
48616be36555SAndrei Emeltchenko 
48620a708f8fSGustavo F. Padovan 			if (!status) {
4863df3c3931SJohan Hedberg 				if (bt_sk(sk)->defer_setup) {
4864df3c3931SJohan Hedberg 					struct sock *parent = bt_sk(sk)->parent;
4865df3c3931SJohan Hedberg 					res = L2CAP_CR_PEND;
4866df3c3931SJohan Hedberg 					stat = L2CAP_CS_AUTHOR_PEND;
486705e9a2f6SIlia Kolomisnky 					if (parent)
4868df3c3931SJohan Hedberg 						parent->sk_data_ready(parent, 0);
4869df3c3931SJohan Hedberg 				} else {
48700e587be7SAndrei Emeltchenko 					__l2cap_state_change(chan, BT_CONFIG);
4871df3c3931SJohan Hedberg 					res = L2CAP_CR_SUCCESS;
4872df3c3931SJohan Hedberg 					stat = L2CAP_CS_NO_INFO;
4873df3c3931SJohan Hedberg 				}
48740a708f8fSGustavo F. Padovan 			} else {
48750e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_DISCONN);
4876ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
4877df3c3931SJohan Hedberg 				res = L2CAP_CR_SEC_BLOCK;
4878df3c3931SJohan Hedberg 				stat = L2CAP_CS_NO_INFO;
48790a708f8fSGustavo F. Padovan 			}
48800a708f8fSGustavo F. Padovan 
48816be36555SAndrei Emeltchenko 			release_sock(sk);
48826be36555SAndrei Emeltchenko 
4883fe4128e0SGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
4884fe4128e0SGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
4885df3c3931SJohan Hedberg 			rsp.result = cpu_to_le16(res);
4886df3c3931SJohan Hedberg 			rsp.status = cpu_to_le16(stat);
4887fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4888fc7f8a7eSGustavo F. Padovan 							sizeof(rsp), &rsp);
48890a708f8fSGustavo F. Padovan 		}
48900a708f8fSGustavo F. Padovan 
48916be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
48920a708f8fSGustavo F. Padovan 	}
48930a708f8fSGustavo F. Padovan 
48943df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
48950a708f8fSGustavo F. Padovan 
48960a708f8fSGustavo F. Padovan 	return 0;
48970a708f8fSGustavo F. Padovan }
48980a708f8fSGustavo F. Padovan 
4899686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
49000a708f8fSGustavo F. Padovan {
49010a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
49020a708f8fSGustavo F. Padovan 
49030a708f8fSGustavo F. Padovan 	if (!conn)
49040a708f8fSGustavo F. Padovan 		conn = l2cap_conn_add(hcon, 0);
49050a708f8fSGustavo F. Padovan 
49060a708f8fSGustavo F. Padovan 	if (!conn)
49070a708f8fSGustavo F. Padovan 		goto drop;
49080a708f8fSGustavo F. Padovan 
49090a708f8fSGustavo F. Padovan 	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
49100a708f8fSGustavo F. Padovan 
49110a708f8fSGustavo F. Padovan 	if (!(flags & ACL_CONT)) {
49120a708f8fSGustavo F. Padovan 		struct l2cap_hdr *hdr;
491348454079SGustavo F. Padovan 		struct l2cap_chan *chan;
49140a708f8fSGustavo F. Padovan 		u16 cid;
49150a708f8fSGustavo F. Padovan 		int len;
49160a708f8fSGustavo F. Padovan 
49170a708f8fSGustavo F. Padovan 		if (conn->rx_len) {
49180a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected start frame (len %d)", skb->len);
49190a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
49200a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
49210a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
49220a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
49230a708f8fSGustavo F. Padovan 		}
49240a708f8fSGustavo F. Padovan 
49250a708f8fSGustavo F. Padovan 		/* Start fragment always begin with Basic L2CAP header */
49260a708f8fSGustavo F. Padovan 		if (skb->len < L2CAP_HDR_SIZE) {
49270a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too short (len %d)", skb->len);
49280a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
49290a708f8fSGustavo F. Padovan 			goto drop;
49300a708f8fSGustavo F. Padovan 		}
49310a708f8fSGustavo F. Padovan 
49320a708f8fSGustavo F. Padovan 		hdr = (struct l2cap_hdr *) skb->data;
49330a708f8fSGustavo F. Padovan 		len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
49340a708f8fSGustavo F. Padovan 		cid = __le16_to_cpu(hdr->cid);
49350a708f8fSGustavo F. Padovan 
49360a708f8fSGustavo F. Padovan 		if (len == skb->len) {
49370a708f8fSGustavo F. Padovan 			/* Complete frame received */
49380a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, skb);
49390a708f8fSGustavo F. Padovan 			return 0;
49400a708f8fSGustavo F. Padovan 		}
49410a708f8fSGustavo F. Padovan 
49420a708f8fSGustavo F. Padovan 		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
49430a708f8fSGustavo F. Padovan 
49440a708f8fSGustavo F. Padovan 		if (skb->len > len) {
49450a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too long (len %d, expected len %d)",
49460a708f8fSGustavo F. Padovan 				skb->len, len);
49470a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
49480a708f8fSGustavo F. Padovan 			goto drop;
49490a708f8fSGustavo F. Padovan 		}
49500a708f8fSGustavo F. Padovan 
4951baa7e1faSGustavo F. Padovan 		chan = l2cap_get_chan_by_scid(conn, cid);
49520a708f8fSGustavo F. Padovan 
495348454079SGustavo F. Padovan 		if (chan && chan->sk) {
495448454079SGustavo F. Padovan 			struct sock *sk = chan->sk;
49553df91ea2SAndrei Emeltchenko 			lock_sock(sk);
495648454079SGustavo F. Padovan 
49570c1bc5c6SGustavo F. Padovan 			if (chan->imtu < len - L2CAP_HDR_SIZE) {
495848454079SGustavo F. Padovan 				BT_ERR("Frame exceeding recv MTU (len %d, "
495948454079SGustavo F. Padovan 							"MTU %d)", len,
49600c1bc5c6SGustavo F. Padovan 							chan->imtu);
4961aa2ac881SGustavo F. Padovan 				release_sock(sk);
49620a708f8fSGustavo F. Padovan 				l2cap_conn_unreliable(conn, ECOMM);
49630a708f8fSGustavo F. Padovan 				goto drop;
49640a708f8fSGustavo F. Padovan 			}
4965aa2ac881SGustavo F. Padovan 			release_sock(sk);
496648454079SGustavo F. Padovan 		}
49670a708f8fSGustavo F. Padovan 
49680a708f8fSGustavo F. Padovan 		/* Allocate skb for the complete frame (with header) */
49690a708f8fSGustavo F. Padovan 		conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
49700a708f8fSGustavo F. Padovan 		if (!conn->rx_skb)
49710a708f8fSGustavo F. Padovan 			goto drop;
49720a708f8fSGustavo F. Padovan 
49730a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
49740a708f8fSGustavo F. Padovan 								skb->len);
49750a708f8fSGustavo F. Padovan 		conn->rx_len = len - skb->len;
49760a708f8fSGustavo F. Padovan 	} else {
49770a708f8fSGustavo F. Padovan 		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
49780a708f8fSGustavo F. Padovan 
49790a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
49800a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
49810a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
49820a708f8fSGustavo F. Padovan 			goto drop;
49830a708f8fSGustavo F. Padovan 		}
49840a708f8fSGustavo F. Padovan 
49850a708f8fSGustavo F. Padovan 		if (skb->len > conn->rx_len) {
49860a708f8fSGustavo F. Padovan 			BT_ERR("Fragment is too long (len %d, expected %d)",
49870a708f8fSGustavo F. Padovan 					skb->len, conn->rx_len);
49880a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
49890a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
49900a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
49910a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
49920a708f8fSGustavo F. Padovan 			goto drop;
49930a708f8fSGustavo F. Padovan 		}
49940a708f8fSGustavo F. Padovan 
49950a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
49960a708f8fSGustavo F. Padovan 								skb->len);
49970a708f8fSGustavo F. Padovan 		conn->rx_len -= skb->len;
49980a708f8fSGustavo F. Padovan 
49990a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
50000a708f8fSGustavo F. Padovan 			/* Complete frame received */
50010a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, conn->rx_skb);
50020a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
50030a708f8fSGustavo F. Padovan 		}
50040a708f8fSGustavo F. Padovan 	}
50050a708f8fSGustavo F. Padovan 
50060a708f8fSGustavo F. Padovan drop:
50070a708f8fSGustavo F. Padovan 	kfree_skb(skb);
50080a708f8fSGustavo F. Padovan 	return 0;
50090a708f8fSGustavo F. Padovan }
50100a708f8fSGustavo F. Padovan 
50110a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
50120a708f8fSGustavo F. Padovan {
501323691d75SGustavo F. Padovan 	struct l2cap_chan *c;
50140a708f8fSGustavo F. Padovan 
5015333055f2SGustavo F. Padovan 	read_lock(&chan_list_lock);
50160a708f8fSGustavo F. Padovan 
501723691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
501823691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
50190a708f8fSGustavo F. Padovan 
5020903d343eSGustavo F. Padovan 		seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
50210a708f8fSGustavo F. Padovan 					batostr(&bt_sk(sk)->src),
50220a708f8fSGustavo F. Padovan 					batostr(&bt_sk(sk)->dst),
502389bc500eSGustavo F. Padovan 					c->state, __le16_to_cpu(c->psm),
502423691d75SGustavo F. Padovan 					c->scid, c->dcid, c->imtu, c->omtu,
502523691d75SGustavo F. Padovan 					c->sec_level, c->mode);
50260a708f8fSGustavo F. Padovan 	}
50270a708f8fSGustavo F. Padovan 
5028333055f2SGustavo F. Padovan 	read_unlock(&chan_list_lock);
50290a708f8fSGustavo F. Padovan 
50300a708f8fSGustavo F. Padovan 	return 0;
50310a708f8fSGustavo F. Padovan }
50320a708f8fSGustavo F. Padovan 
50330a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file)
50340a708f8fSGustavo F. Padovan {
50350a708f8fSGustavo F. Padovan 	return single_open(file, l2cap_debugfs_show, inode->i_private);
50360a708f8fSGustavo F. Padovan }
50370a708f8fSGustavo F. Padovan 
50380a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = {
50390a708f8fSGustavo F. Padovan 	.open		= l2cap_debugfs_open,
50400a708f8fSGustavo F. Padovan 	.read		= seq_read,
50410a708f8fSGustavo F. Padovan 	.llseek		= seq_lseek,
50420a708f8fSGustavo F. Padovan 	.release	= single_release,
50430a708f8fSGustavo F. Padovan };
50440a708f8fSGustavo F. Padovan 
50450a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
50460a708f8fSGustavo F. Padovan 
504764274518SGustavo F. Padovan int __init l2cap_init(void)
50480a708f8fSGustavo F. Padovan {
50490a708f8fSGustavo F. Padovan 	int err;
50500a708f8fSGustavo F. Padovan 
5051bb58f747SGustavo F. Padovan 	err = l2cap_init_sockets();
50520a708f8fSGustavo F. Padovan 	if (err < 0)
50530a708f8fSGustavo F. Padovan 		return err;
50540a708f8fSGustavo F. Padovan 
50550a708f8fSGustavo F. Padovan 	if (bt_debugfs) {
50560a708f8fSGustavo F. Padovan 		l2cap_debugfs = debugfs_create_file("l2cap", 0444,
50570a708f8fSGustavo F. Padovan 					bt_debugfs, NULL, &l2cap_debugfs_fops);
50580a708f8fSGustavo F. Padovan 		if (!l2cap_debugfs)
50590a708f8fSGustavo F. Padovan 			BT_ERR("Failed to create L2CAP debug file");
50600a708f8fSGustavo F. Padovan 	}
50610a708f8fSGustavo F. Padovan 
50620a708f8fSGustavo F. Padovan 	return 0;
50630a708f8fSGustavo F. Padovan }
50640a708f8fSGustavo F. Padovan 
506564274518SGustavo F. Padovan void l2cap_exit(void)
50660a708f8fSGustavo F. Padovan {
50670a708f8fSGustavo F. Padovan 	debugfs_remove(l2cap_debugfs);
5068bb58f747SGustavo F. Padovan 	l2cap_cleanup_sockets();
50690a708f8fSGustavo F. Padovan }
50700a708f8fSGustavo F. Padovan 
50710a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
50720a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
5073