xref: /openbmc/linux/net/bluetooth/l2cap_core.c (revision b191e031)
10a708f8fSGustavo F. Padovan /*
20a708f8fSGustavo F. Padovan    BlueZ - Bluetooth protocol stack for Linux
30a708f8fSGustavo F. Padovan    Copyright (C) 2000-2001 Qualcomm Incorporated
40a708f8fSGustavo F. Padovan    Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
50a708f8fSGustavo F. Padovan    Copyright (C) 2010 Google Inc.
6590051deSGustavo F. Padovan    Copyright (C) 2011 ProFUSION Embedded Systems
7422e925bSMat Martineau    Copyright (c) 2012 Code Aurora Forum.  All rights reserved.
80a708f8fSGustavo F. Padovan 
90a708f8fSGustavo F. Padovan    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
100a708f8fSGustavo F. Padovan 
110a708f8fSGustavo F. Padovan    This program is free software; you can redistribute it and/or modify
120a708f8fSGustavo F. Padovan    it under the terms of the GNU General Public License version 2 as
130a708f8fSGustavo F. Padovan    published by the Free Software Foundation;
140a708f8fSGustavo F. Padovan 
150a708f8fSGustavo F. Padovan    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
160a708f8fSGustavo F. Padovan    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
170a708f8fSGustavo F. Padovan    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
180a708f8fSGustavo F. Padovan    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
190a708f8fSGustavo F. Padovan    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
200a708f8fSGustavo F. Padovan    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
210a708f8fSGustavo F. Padovan    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
220a708f8fSGustavo F. Padovan    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
230a708f8fSGustavo F. Padovan 
240a708f8fSGustavo F. Padovan    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
250a708f8fSGustavo F. Padovan    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
260a708f8fSGustavo F. Padovan    SOFTWARE IS DISCLAIMED.
270a708f8fSGustavo F. Padovan */
280a708f8fSGustavo F. Padovan 
29bb58f747SGustavo F. Padovan /* Bluetooth L2CAP core. */
300a708f8fSGustavo F. Padovan 
310a708f8fSGustavo F. Padovan #include <linux/module.h>
320a708f8fSGustavo F. Padovan 
330a708f8fSGustavo F. Padovan #include <linux/types.h>
340a708f8fSGustavo F. Padovan #include <linux/capability.h>
350a708f8fSGustavo F. Padovan #include <linux/errno.h>
360a708f8fSGustavo F. Padovan #include <linux/kernel.h>
370a708f8fSGustavo F. Padovan #include <linux/sched.h>
380a708f8fSGustavo F. Padovan #include <linux/slab.h>
390a708f8fSGustavo F. Padovan #include <linux/poll.h>
400a708f8fSGustavo F. Padovan #include <linux/fcntl.h>
410a708f8fSGustavo F. Padovan #include <linux/init.h>
420a708f8fSGustavo F. Padovan #include <linux/interrupt.h>
430a708f8fSGustavo F. Padovan #include <linux/socket.h>
440a708f8fSGustavo F. Padovan #include <linux/skbuff.h>
450a708f8fSGustavo F. Padovan #include <linux/list.h>
460a708f8fSGustavo F. Padovan #include <linux/device.h>
470a708f8fSGustavo F. Padovan #include <linux/debugfs.h>
480a708f8fSGustavo F. Padovan #include <linux/seq_file.h>
490a708f8fSGustavo F. Padovan #include <linux/uaccess.h>
500a708f8fSGustavo F. Padovan #include <linux/crc16.h>
510a708f8fSGustavo F. Padovan #include <net/sock.h>
520a708f8fSGustavo F. Padovan 
530a708f8fSGustavo F. Padovan #include <asm/unaligned.h>
540a708f8fSGustavo F. Padovan 
550a708f8fSGustavo F. Padovan #include <net/bluetooth/bluetooth.h>
560a708f8fSGustavo F. Padovan #include <net/bluetooth/hci_core.h>
570a708f8fSGustavo F. Padovan #include <net/bluetooth/l2cap.h>
58b501d6a1SAnderson Briglia #include <net/bluetooth/smp.h>
590a708f8fSGustavo F. Padovan 
60b191e031SMat Martineau bool disable_ertm = 1;
610a708f8fSGustavo F. Padovan 
620a708f8fSGustavo F. Padovan static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
6350a147cdSMat Martineau static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
640a708f8fSGustavo F. Padovan 
65b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list);
66b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock);
670a708f8fSGustavo F. Padovan 
680a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
690a708f8fSGustavo F. Padovan 				u8 code, u8 ident, u16 dlen, void *data);
704519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
714519de9aSGustavo F. Padovan 								void *data);
72710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
734519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn,
744519de9aSGustavo F. Padovan 				   struct l2cap_chan *chan, int err);
750a708f8fSGustavo F. Padovan 
760a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */
7771ba0e56SGustavo F. Padovan 
78baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
790a708f8fSGustavo F. Padovan {
803df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
81baa7e1faSGustavo F. Padovan 
823df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
833df91ea2SAndrei Emeltchenko 		if (c->dcid == cid)
843df91ea2SAndrei Emeltchenko 			return c;
850a708f8fSGustavo F. Padovan 	}
863df91ea2SAndrei Emeltchenko 	return NULL;
87baa7e1faSGustavo F. Padovan }
880a708f8fSGustavo F. Padovan 
89baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
900a708f8fSGustavo F. Padovan {
913df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
92baa7e1faSGustavo F. Padovan 
933df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
943df91ea2SAndrei Emeltchenko 		if (c->scid == cid)
953df91ea2SAndrei Emeltchenko 			return c;
960a708f8fSGustavo F. Padovan 	}
973df91ea2SAndrei Emeltchenko 	return NULL;
98baa7e1faSGustavo F. Padovan }
990a708f8fSGustavo F. Padovan 
1000a708f8fSGustavo F. Padovan /* Find channel with given SCID.
101ef191adeSMat Martineau  * Returns locked channel. */
102baa7e1faSGustavo F. Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
1030a708f8fSGustavo F. Padovan {
10448454079SGustavo F. Padovan 	struct l2cap_chan *c;
105baa7e1faSGustavo F. Padovan 
1063df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
107baa7e1faSGustavo F. Padovan 	c = __l2cap_get_chan_by_scid(conn, cid);
108ef191adeSMat Martineau 	if (c)
109ef191adeSMat Martineau 		l2cap_chan_lock(c);
1103df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
1113df91ea2SAndrei Emeltchenko 
11248454079SGustavo F. Padovan 	return c;
1130a708f8fSGustavo F. Padovan }
1140a708f8fSGustavo F. Padovan 
115baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
1160a708f8fSGustavo F. Padovan {
1173df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
118baa7e1faSGustavo F. Padovan 
1193df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1203df91ea2SAndrei Emeltchenko 		if (c->ident == ident)
1213df91ea2SAndrei Emeltchenko 			return c;
1220a708f8fSGustavo F. Padovan 	}
1233df91ea2SAndrei Emeltchenko 	return NULL;
124baa7e1faSGustavo F. Padovan }
1250a708f8fSGustavo F. Padovan 
12623691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
1279e4425ffSGustavo F. Padovan {
12823691d75SGustavo F. Padovan 	struct l2cap_chan *c;
1299e4425ffSGustavo F. Padovan 
13023691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
13123691d75SGustavo F. Padovan 		if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
13223691d75SGustavo F. Padovan 			return c;
1339e4425ffSGustavo F. Padovan 	}
134250938cbSSzymon Janc 	return NULL;
135250938cbSSzymon Janc }
1369e4425ffSGustavo F. Padovan 
1379e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
1389e4425ffSGustavo F. Padovan {
13973b2ec18SGustavo F. Padovan 	int err;
14073b2ec18SGustavo F. Padovan 
141333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1429e4425ffSGustavo F. Padovan 
14323691d75SGustavo F. Padovan 	if (psm && __l2cap_global_chan_by_addr(psm, src)) {
14473b2ec18SGustavo F. Padovan 		err = -EADDRINUSE;
14573b2ec18SGustavo F. Padovan 		goto done;
1469e4425ffSGustavo F. Padovan 	}
1479e4425ffSGustavo F. Padovan 
14873b2ec18SGustavo F. Padovan 	if (psm) {
1499e4425ffSGustavo F. Padovan 		chan->psm = psm;
1509e4425ffSGustavo F. Padovan 		chan->sport = psm;
15173b2ec18SGustavo F. Padovan 		err = 0;
15273b2ec18SGustavo F. Padovan 	} else {
15373b2ec18SGustavo F. Padovan 		u16 p;
1549e4425ffSGustavo F. Padovan 
15573b2ec18SGustavo F. Padovan 		err = -EINVAL;
15673b2ec18SGustavo F. Padovan 		for (p = 0x1001; p < 0x1100; p += 2)
15723691d75SGustavo F. Padovan 			if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
15873b2ec18SGustavo F. Padovan 				chan->psm   = cpu_to_le16(p);
15973b2ec18SGustavo F. Padovan 				chan->sport = cpu_to_le16(p);
16073b2ec18SGustavo F. Padovan 				err = 0;
16173b2ec18SGustavo F. Padovan 				break;
16273b2ec18SGustavo F. Padovan 			}
16373b2ec18SGustavo F. Padovan 	}
16473b2ec18SGustavo F. Padovan 
16573b2ec18SGustavo F. Padovan done:
166333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
16773b2ec18SGustavo F. Padovan 	return err;
1689e4425ffSGustavo F. Padovan }
1699e4425ffSGustavo F. Padovan 
1709e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
1719e4425ffSGustavo F. Padovan {
172333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1739e4425ffSGustavo F. Padovan 
1749e4425ffSGustavo F. Padovan 	chan->scid = scid;
1759e4425ffSGustavo F. Padovan 
176333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
1779e4425ffSGustavo F. Padovan 
1789e4425ffSGustavo F. Padovan 	return 0;
1799e4425ffSGustavo F. Padovan }
1809e4425ffSGustavo F. Padovan 
181baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
1820a708f8fSGustavo F. Padovan {
1830a708f8fSGustavo F. Padovan 	u16 cid = L2CAP_CID_DYN_START;
1840a708f8fSGustavo F. Padovan 
1850a708f8fSGustavo F. Padovan 	for (; cid < L2CAP_CID_DYN_END; cid++) {
186baa7e1faSGustavo F. Padovan 		if (!__l2cap_get_chan_by_scid(conn, cid))
1870a708f8fSGustavo F. Padovan 			return cid;
1880a708f8fSGustavo F. Padovan 	}
1890a708f8fSGustavo F. Padovan 
1900a708f8fSGustavo F. Padovan 	return 0;
1910a708f8fSGustavo F. Padovan }
1920a708f8fSGustavo F. Padovan 
1930e587be7SAndrei Emeltchenko static void __l2cap_state_change(struct l2cap_chan *chan, int state)
19489bc500eSGustavo F. Padovan {
19542d2d87cSAndrei Emeltchenko 	BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
196badaaa00SGustavo F. Padovan 						state_to_string(state));
197badaaa00SGustavo F. Padovan 
19889bc500eSGustavo F. Padovan 	chan->state = state;
19989bc500eSGustavo F. Padovan 	chan->ops->state_change(chan->data, state);
20089bc500eSGustavo F. Padovan }
20189bc500eSGustavo F. Padovan 
2020e587be7SAndrei Emeltchenko static void l2cap_state_change(struct l2cap_chan *chan, int state)
2030e587be7SAndrei Emeltchenko {
2040e587be7SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2050e587be7SAndrei Emeltchenko 
2060e587be7SAndrei Emeltchenko 	lock_sock(sk);
2070e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, state);
2080e587be7SAndrei Emeltchenko 	release_sock(sk);
2090e587be7SAndrei Emeltchenko }
2100e587be7SAndrei Emeltchenko 
2112e0052e4SAndrei Emeltchenko static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2122e0052e4SAndrei Emeltchenko {
2132e0052e4SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2142e0052e4SAndrei Emeltchenko 
2152e0052e4SAndrei Emeltchenko 	sk->sk_err = err;
2162e0052e4SAndrei Emeltchenko }
2172e0052e4SAndrei Emeltchenko 
2182e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2192e0052e4SAndrei Emeltchenko {
2202e0052e4SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2212e0052e4SAndrei Emeltchenko 
2222e0052e4SAndrei Emeltchenko 	lock_sock(sk);
2232e0052e4SAndrei Emeltchenko 	__l2cap_chan_set_err(chan, err);
2242e0052e4SAndrei Emeltchenko 	release_sock(sk);
2252e0052e4SAndrei Emeltchenko }
2262e0052e4SAndrei Emeltchenko 
2273c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */
2283c588192SMat Martineau 
2293c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for
2303c588192SMat Martineau  * SREJ requests that are received and for frames that are to be
2313c588192SMat Martineau  * retransmitted. These seq_list functions implement a singly-linked
2323c588192SMat Martineau  * list in an array, where membership in the list can also be checked
2333c588192SMat Martineau  * in constant time. Items can also be added to the tail of the list
2343c588192SMat Martineau  * and removed from the head in constant time, without further memory
2353c588192SMat Martineau  * allocs or frees.
2363c588192SMat Martineau  */
2373c588192SMat Martineau 
2383c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
2393c588192SMat Martineau {
2403c588192SMat Martineau 	size_t alloc_size, i;
2413c588192SMat Martineau 
2423c588192SMat Martineau 	/* Allocated size is a power of 2 to map sequence numbers
2433c588192SMat Martineau 	 * (which may be up to 14 bits) in to a smaller array that is
2443c588192SMat Martineau 	 * sized for the negotiated ERTM transmit windows.
2453c588192SMat Martineau 	 */
2463c588192SMat Martineau 	alloc_size = roundup_pow_of_two(size);
2473c588192SMat Martineau 
2483c588192SMat Martineau 	seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL);
2493c588192SMat Martineau 	if (!seq_list->list)
2503c588192SMat Martineau 		return -ENOMEM;
2513c588192SMat Martineau 
2523c588192SMat Martineau 	seq_list->mask = alloc_size - 1;
2533c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
2543c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
2553c588192SMat Martineau 	for (i = 0; i < alloc_size; i++)
2563c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
2573c588192SMat Martineau 
2583c588192SMat Martineau 	return 0;
2593c588192SMat Martineau }
2603c588192SMat Martineau 
2613c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
2623c588192SMat Martineau {
2633c588192SMat Martineau 	kfree(seq_list->list);
2643c588192SMat Martineau }
2653c588192SMat Martineau 
2663c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
2673c588192SMat Martineau 					   u16 seq)
2683c588192SMat Martineau {
2693c588192SMat Martineau 	/* Constant-time check for list membership */
2703c588192SMat Martineau 	return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
2713c588192SMat Martineau }
2723c588192SMat Martineau 
2733c588192SMat Martineau static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq)
2743c588192SMat Martineau {
2753c588192SMat Martineau 	u16 mask = seq_list->mask;
2763c588192SMat Martineau 
2773c588192SMat Martineau 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) {
2783c588192SMat Martineau 		/* In case someone tries to pop the head of an empty list */
2793c588192SMat Martineau 		return L2CAP_SEQ_LIST_CLEAR;
2803c588192SMat Martineau 	} else if (seq_list->head == seq) {
2813c588192SMat Martineau 		/* Head can be removed in constant time */
2823c588192SMat Martineau 		seq_list->head = seq_list->list[seq & mask];
2833c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
2843c588192SMat Martineau 
2853c588192SMat Martineau 		if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
2863c588192SMat Martineau 			seq_list->head = L2CAP_SEQ_LIST_CLEAR;
2873c588192SMat Martineau 			seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
2883c588192SMat Martineau 		}
2893c588192SMat Martineau 	} else {
2903c588192SMat Martineau 		/* Walk the list to find the sequence number */
2913c588192SMat Martineau 		u16 prev = seq_list->head;
2923c588192SMat Martineau 		while (seq_list->list[prev & mask] != seq) {
2933c588192SMat Martineau 			prev = seq_list->list[prev & mask];
2943c588192SMat Martineau 			if (prev == L2CAP_SEQ_LIST_TAIL)
2953c588192SMat Martineau 				return L2CAP_SEQ_LIST_CLEAR;
2963c588192SMat Martineau 		}
2973c588192SMat Martineau 
2983c588192SMat Martineau 		/* Unlink the number from the list and clear it */
2993c588192SMat Martineau 		seq_list->list[prev & mask] = seq_list->list[seq & mask];
3003c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3013c588192SMat Martineau 		if (seq_list->tail == seq)
3023c588192SMat Martineau 			seq_list->tail = prev;
3033c588192SMat Martineau 	}
3043c588192SMat Martineau 	return seq;
3053c588192SMat Martineau }
3063c588192SMat Martineau 
3073c588192SMat Martineau static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
3083c588192SMat Martineau {
3093c588192SMat Martineau 	/* Remove the head in constant time */
3103c588192SMat Martineau 	return l2cap_seq_list_remove(seq_list, seq_list->head);
3113c588192SMat Martineau }
3123c588192SMat Martineau 
3133c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
3143c588192SMat Martineau {
3153c588192SMat Martineau 	u16 i;
316f522ae36SGustavo Padovan 
317f522ae36SGustavo Padovan 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR)
318f522ae36SGustavo Padovan 		return;
319f522ae36SGustavo Padovan 
3203c588192SMat Martineau 	for (i = 0; i <= seq_list->mask; i++)
3213c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3223c588192SMat Martineau 
3233c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3243c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3253c588192SMat Martineau }
3263c588192SMat Martineau 
3273c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
3283c588192SMat Martineau {
3293c588192SMat Martineau 	u16 mask = seq_list->mask;
3303c588192SMat Martineau 
3313c588192SMat Martineau 	/* All appends happen in constant time */
3323c588192SMat Martineau 
333f522ae36SGustavo Padovan 	if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR)
334f522ae36SGustavo Padovan 		return;
335f522ae36SGustavo Padovan 
3363c588192SMat Martineau 	if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
3373c588192SMat Martineau 		seq_list->head = seq;
3383c588192SMat Martineau 	else
3393c588192SMat Martineau 		seq_list->list[seq_list->tail & mask] = seq;
3403c588192SMat Martineau 
3413c588192SMat Martineau 	seq_list->tail = seq;
3423c588192SMat Martineau 	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
3433c588192SMat Martineau }
3443c588192SMat Martineau 
345721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work)
346ab07801dSGustavo F. Padovan {
347721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
348721c4181SGustavo F. Padovan 							chan_timer.work);
3493df91ea2SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
350ab07801dSGustavo F. Padovan 	int reason;
351ab07801dSGustavo F. Padovan 
352e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
353ab07801dSGustavo F. Padovan 
3543df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
3556be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
356ab07801dSGustavo F. Padovan 
35789bc500eSGustavo F. Padovan 	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
358ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
35989bc500eSGustavo F. Padovan 	else if (chan->state == BT_CONNECT &&
360ab07801dSGustavo F. Padovan 					chan->sec_level != BT_SECURITY_SDP)
361ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
362ab07801dSGustavo F. Padovan 	else
363ab07801dSGustavo F. Padovan 		reason = ETIMEDOUT;
364ab07801dSGustavo F. Padovan 
3650f852724SGustavo F. Padovan 	l2cap_chan_close(chan, reason);
366ab07801dSGustavo F. Padovan 
3676be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
368ab07801dSGustavo F. Padovan 
369ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
3703df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
3713df91ea2SAndrei Emeltchenko 
372371fd835SUlisses Furquim 	l2cap_chan_put(chan);
373ab07801dSGustavo F. Padovan }
374ab07801dSGustavo F. Padovan 
375eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void)
3760a708f8fSGustavo F. Padovan {
37748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
3780a708f8fSGustavo F. Padovan 
37948454079SGustavo F. Padovan 	chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
38048454079SGustavo F. Padovan 	if (!chan)
38148454079SGustavo F. Padovan 		return NULL;
3820a708f8fSGustavo F. Padovan 
383c03b355eSAndrei Emeltchenko 	mutex_init(&chan->lock);
384c03b355eSAndrei Emeltchenko 
385333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
38623691d75SGustavo F. Padovan 	list_add(&chan->global_l, &chan_list);
387333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
38823691d75SGustavo F. Padovan 
389721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
390ab07801dSGustavo F. Padovan 
39189bc500eSGustavo F. Padovan 	chan->state = BT_OPEN;
39289bc500eSGustavo F. Padovan 
39371ba0e56SGustavo F. Padovan 	atomic_set(&chan->refcnt, 1);
39471ba0e56SGustavo F. Padovan 
3952827011fSMat Martineau 	/* This flag is cleared in l2cap_chan_ready() */
3962827011fSMat Martineau 	set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
3972827011fSMat Martineau 
398eef1d9b6SGustavo Padovan 	BT_DBG("chan %p", chan);
399abc545b8SSzymon Janc 
40048454079SGustavo F. Padovan 	return chan;
4010a708f8fSGustavo F. Padovan }
4020a708f8fSGustavo F. Padovan 
40323691d75SGustavo F. Padovan void l2cap_chan_destroy(struct l2cap_chan *chan)
4046ff5abbfSGustavo F. Padovan {
405333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
40623691d75SGustavo F. Padovan 	list_del(&chan->global_l);
407333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
40823691d75SGustavo F. Padovan 
409371fd835SUlisses Furquim 	l2cap_chan_put(chan);
4106ff5abbfSGustavo F. Padovan }
4116ff5abbfSGustavo F. Padovan 
412bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan)
413bd4b1653SAndrei Emeltchenko {
414bd4b1653SAndrei Emeltchenko 	chan->fcs  = L2CAP_FCS_CRC16;
415bd4b1653SAndrei Emeltchenko 	chan->max_tx = L2CAP_DEFAULT_MAX_TX;
416bd4b1653SAndrei Emeltchenko 	chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
417bd4b1653SAndrei Emeltchenko 	chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
418bd4b1653SAndrei Emeltchenko 	chan->sec_level = BT_SECURITY_LOW;
419bd4b1653SAndrei Emeltchenko 
420bd4b1653SAndrei Emeltchenko 	set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
421bd4b1653SAndrei Emeltchenko }
422bd4b1653SAndrei Emeltchenko 
42314a28491SAndrei Emeltchenko static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
4240a708f8fSGustavo F. Padovan {
4250a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
426097db76cSAndrei Emeltchenko 	       __le16_to_cpu(chan->psm), chan->dcid);
4270a708f8fSGustavo F. Padovan 
4289f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
4290a708f8fSGustavo F. Padovan 
4308c1d787bSGustavo F. Padovan 	chan->conn = conn;
4310a708f8fSGustavo F. Padovan 
4325491120eSAndrei Emeltchenko 	switch (chan->chan_type) {
4335491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_ORIENTED:
434b62f328bSVille Tervo 		if (conn->hcon->type == LE_LINK) {
435b62f328bSVille Tervo 			/* LE connection */
4360c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_LE_DEFAULT_MTU;
437fe4128e0SGustavo F. Padovan 			chan->scid = L2CAP_CID_LE_DATA;
438fe4128e0SGustavo F. Padovan 			chan->dcid = L2CAP_CID_LE_DATA;
439b62f328bSVille Tervo 		} else {
4400a708f8fSGustavo F. Padovan 			/* Alloc CID for connection-oriented socket */
441fe4128e0SGustavo F. Padovan 			chan->scid = l2cap_alloc_cid(conn);
4420c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_DEFAULT_MTU;
443b62f328bSVille Tervo 		}
4445491120eSAndrei Emeltchenko 		break;
4455491120eSAndrei Emeltchenko 
4465491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_LESS:
4470a708f8fSGustavo F. Padovan 		/* Connectionless socket */
448fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_CONN_LESS;
449fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_CONN_LESS;
4500c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
4515491120eSAndrei Emeltchenko 		break;
4525491120eSAndrei Emeltchenko 
4535491120eSAndrei Emeltchenko 	default:
4540a708f8fSGustavo F. Padovan 		/* Raw socket can send/recv signalling messages only */
455fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_SIGNALING;
456fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_SIGNALING;
4570c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
4580a708f8fSGustavo F. Padovan 	}
4590a708f8fSGustavo F. Padovan 
4608f7975b1SAndrei Emeltchenko 	chan->local_id		= L2CAP_BESTEFFORT_ID;
4618f7975b1SAndrei Emeltchenko 	chan->local_stype	= L2CAP_SERV_BESTEFFORT;
4628f7975b1SAndrei Emeltchenko 	chan->local_msdu	= L2CAP_DEFAULT_MAX_SDU_SIZE;
4638f7975b1SAndrei Emeltchenko 	chan->local_sdu_itime	= L2CAP_DEFAULT_SDU_ITIME;
4648f7975b1SAndrei Emeltchenko 	chan->local_acc_lat	= L2CAP_DEFAULT_ACC_LAT;
4658f7975b1SAndrei Emeltchenko 	chan->local_flush_to	= L2CAP_DEFAULT_FLUSH_TO;
4668f7975b1SAndrei Emeltchenko 
467371fd835SUlisses Furquim 	l2cap_chan_hold(chan);
468baa7e1faSGustavo F. Padovan 
4693df91ea2SAndrei Emeltchenko 	list_add(&chan->list, &conn->chan_l);
470643162a8SAndrei Emeltchenko }
471643162a8SAndrei Emeltchenko 
47214a28491SAndrei Emeltchenko static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
473643162a8SAndrei Emeltchenko {
474643162a8SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
475643162a8SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
4763df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
4770a708f8fSGustavo F. Padovan }
4780a708f8fSGustavo F. Padovan 
4794519de9aSGustavo F. Padovan static void l2cap_chan_del(struct l2cap_chan *chan, int err)
4800a708f8fSGustavo F. Padovan {
48148454079SGustavo F. Padovan 	struct sock *sk = chan->sk;
4828c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
4830a708f8fSGustavo F. Padovan 	struct sock *parent = bt_sk(sk)->parent;
4840a708f8fSGustavo F. Padovan 
485c9b66675SGustavo F. Padovan 	__clear_chan_timer(chan);
4860a708f8fSGustavo F. Padovan 
48749208c9cSGustavo F. Padovan 	BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
4880a708f8fSGustavo F. Padovan 
4890a708f8fSGustavo F. Padovan 	if (conn) {
490baa7e1faSGustavo F. Padovan 		/* Delete from channel list */
4913df91ea2SAndrei Emeltchenko 		list_del(&chan->list);
4923d57dc68SGustavo F. Padovan 
493371fd835SUlisses Furquim 		l2cap_chan_put(chan);
494baa7e1faSGustavo F. Padovan 
4958c1d787bSGustavo F. Padovan 		chan->conn = NULL;
4960a708f8fSGustavo F. Padovan 		hci_conn_put(conn->hcon);
4970a708f8fSGustavo F. Padovan 	}
4980a708f8fSGustavo F. Padovan 
4996be36555SAndrei Emeltchenko 	lock_sock(sk);
5006be36555SAndrei Emeltchenko 
5010e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_CLOSED);
5020a708f8fSGustavo F. Padovan 	sock_set_flag(sk, SOCK_ZAPPED);
5030a708f8fSGustavo F. Padovan 
5040a708f8fSGustavo F. Padovan 	if (err)
5052e0052e4SAndrei Emeltchenko 		__l2cap_chan_set_err(chan, err);
5060a708f8fSGustavo F. Padovan 
5070a708f8fSGustavo F. Padovan 	if (parent) {
5080a708f8fSGustavo F. Padovan 		bt_accept_unlink(sk);
5090a708f8fSGustavo F. Padovan 		parent->sk_data_ready(parent, 0);
5100a708f8fSGustavo F. Padovan 	} else
5110a708f8fSGustavo F. Padovan 		sk->sk_state_change(sk);
5120a708f8fSGustavo F. Padovan 
5136be36555SAndrei Emeltchenko 	release_sock(sk);
5146be36555SAndrei Emeltchenko 
5152827011fSMat Martineau 	if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
5166ff5abbfSGustavo F. Padovan 		return;
5172ead70b8SGustavo F. Padovan 
51858d35f87SGustavo F. Padovan 	skb_queue_purge(&chan->tx_q);
5190a708f8fSGustavo F. Padovan 
5200c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_ERTM) {
5210a708f8fSGustavo F. Padovan 		struct srej_list *l, *tmp;
5220a708f8fSGustavo F. Padovan 
5231a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
5241a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
5251a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
5260a708f8fSGustavo F. Padovan 
527f1c6775bSGustavo F. Padovan 		skb_queue_purge(&chan->srej_q);
5280a708f8fSGustavo F. Padovan 
5293c588192SMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
5303c588192SMat Martineau 		l2cap_seq_list_free(&chan->retrans_list);
53139d5a3eeSGustavo F. Padovan 		list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
5320a708f8fSGustavo F. Padovan 			list_del(&l->list);
5330a708f8fSGustavo F. Padovan 			kfree(l);
5340a708f8fSGustavo F. Padovan 		}
5350a708f8fSGustavo F. Padovan 	}
5360a708f8fSGustavo F. Padovan }
5370a708f8fSGustavo F. Padovan 
5384519de9aSGustavo F. Padovan static void l2cap_chan_cleanup_listen(struct sock *parent)
5394519de9aSGustavo F. Padovan {
5404519de9aSGustavo F. Padovan 	struct sock *sk;
5414519de9aSGustavo F. Padovan 
5424519de9aSGustavo F. Padovan 	BT_DBG("parent %p", parent);
5434519de9aSGustavo F. Padovan 
5444519de9aSGustavo F. Padovan 	/* Close not yet accepted channels */
5450f852724SGustavo F. Padovan 	while ((sk = bt_accept_dequeue(parent, NULL))) {
546ba3bd0eeSGustavo F. Padovan 		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
5473df91ea2SAndrei Emeltchenko 
5486be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
549c9b66675SGustavo F. Padovan 		__clear_chan_timer(chan);
550ba3bd0eeSGustavo F. Padovan 		l2cap_chan_close(chan, ECONNRESET);
5516be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
5523df91ea2SAndrei Emeltchenko 
553ba3bd0eeSGustavo F. Padovan 		chan->ops->close(chan->data);
5540f852724SGustavo F. Padovan 	}
5554519de9aSGustavo F. Padovan }
5564519de9aSGustavo F. Padovan 
5570f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason)
5584519de9aSGustavo F. Padovan {
5594519de9aSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
5604519de9aSGustavo F. Padovan 	struct sock *sk = chan->sk;
5614519de9aSGustavo F. Padovan 
562e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s sk %p", chan,
563e05dcc32SAndrei Emeltchenko 					state_to_string(chan->state), sk);
5644519de9aSGustavo F. Padovan 
56589bc500eSGustavo F. Padovan 	switch (chan->state) {
5664519de9aSGustavo F. Padovan 	case BT_LISTEN:
5676be36555SAndrei Emeltchenko 		lock_sock(sk);
5684519de9aSGustavo F. Padovan 		l2cap_chan_cleanup_listen(sk);
56989bc500eSGustavo F. Padovan 
5700e587be7SAndrei Emeltchenko 		__l2cap_state_change(chan, BT_CLOSED);
57189bc500eSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
5726be36555SAndrei Emeltchenko 		release_sock(sk);
5734519de9aSGustavo F. Padovan 		break;
5744519de9aSGustavo F. Padovan 
5754519de9aSGustavo F. Padovan 	case BT_CONNECTED:
5764519de9aSGustavo F. Padovan 	case BT_CONFIG:
577715ec005SGustavo F. Padovan 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
5784519de9aSGustavo F. Padovan 					conn->hcon->type == ACL_LINK) {
579c9b66675SGustavo F. Padovan 			__set_chan_timer(chan, sk->sk_sndtimeo);
5804519de9aSGustavo F. Padovan 			l2cap_send_disconn_req(conn, chan, reason);
5814519de9aSGustavo F. Padovan 		} else
5824519de9aSGustavo F. Padovan 			l2cap_chan_del(chan, reason);
5834519de9aSGustavo F. Padovan 		break;
5844519de9aSGustavo F. Padovan 
5854519de9aSGustavo F. Padovan 	case BT_CONNECT2:
586715ec005SGustavo F. Padovan 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
5874519de9aSGustavo F. Padovan 					conn->hcon->type == ACL_LINK) {
5884519de9aSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
5894519de9aSGustavo F. Padovan 			__u16 result;
5904519de9aSGustavo F. Padovan 
591c5daa683SGustavo Padovan 			if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))
5924519de9aSGustavo F. Padovan 				result = L2CAP_CR_SEC_BLOCK;
5934519de9aSGustavo F. Padovan 			else
5944519de9aSGustavo F. Padovan 				result = L2CAP_CR_BAD_PSM;
59589bc500eSGustavo F. Padovan 			l2cap_state_change(chan, BT_DISCONN);
5964519de9aSGustavo F. Padovan 
5974519de9aSGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
5984519de9aSGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
5994519de9aSGustavo F. Padovan 			rsp.result = cpu_to_le16(result);
6004519de9aSGustavo F. Padovan 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
6014519de9aSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
6024519de9aSGustavo F. Padovan 							sizeof(rsp), &rsp);
6034519de9aSGustavo F. Padovan 		}
6044519de9aSGustavo F. Padovan 
6054519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
6064519de9aSGustavo F. Padovan 		break;
6074519de9aSGustavo F. Padovan 
6084519de9aSGustavo F. Padovan 	case BT_CONNECT:
6094519de9aSGustavo F. Padovan 	case BT_DISCONN:
6104519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
6114519de9aSGustavo F. Padovan 		break;
6124519de9aSGustavo F. Padovan 
6134519de9aSGustavo F. Padovan 	default:
6146be36555SAndrei Emeltchenko 		lock_sock(sk);
6154519de9aSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
6166be36555SAndrei Emeltchenko 		release_sock(sk);
6174519de9aSGustavo F. Padovan 		break;
6184519de9aSGustavo F. Padovan 	}
6194519de9aSGustavo F. Padovan }
6204519de9aSGustavo F. Padovan 
6214343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
6220a708f8fSGustavo F. Padovan {
623715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_RAW) {
6244343478fSGustavo F. Padovan 		switch (chan->sec_level) {
6250a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
6260a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING_MITM;
6270a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
6280a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING;
6290a708f8fSGustavo F. Padovan 		default:
6300a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6310a708f8fSGustavo F. Padovan 		}
632fe4128e0SGustavo F. Padovan 	} else if (chan->psm == cpu_to_le16(0x0001)) {
6334343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_LOW)
6344343478fSGustavo F. Padovan 			chan->sec_level = BT_SECURITY_SDP;
6350a708f8fSGustavo F. Padovan 
6364343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_HIGH)
6370a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING_MITM;
6380a708f8fSGustavo F. Padovan 		else
6390a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6400a708f8fSGustavo F. Padovan 	} else {
6414343478fSGustavo F. Padovan 		switch (chan->sec_level) {
6420a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
6430a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING_MITM;
6440a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
6450a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING;
6460a708f8fSGustavo F. Padovan 		default:
6470a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6480a708f8fSGustavo F. Padovan 		}
6490a708f8fSGustavo F. Padovan 	}
6500a708f8fSGustavo F. Padovan }
6510a708f8fSGustavo F. Padovan 
6520a708f8fSGustavo F. Padovan /* Service level security */
653d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan)
6540a708f8fSGustavo F. Padovan {
6558c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
6560a708f8fSGustavo F. Padovan 	__u8 auth_type;
6570a708f8fSGustavo F. Padovan 
6584343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
6590a708f8fSGustavo F. Padovan 
6604343478fSGustavo F. Padovan 	return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
6610a708f8fSGustavo F. Padovan }
6620a708f8fSGustavo F. Padovan 
663b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn)
6640a708f8fSGustavo F. Padovan {
6650a708f8fSGustavo F. Padovan 	u8 id;
6660a708f8fSGustavo F. Padovan 
6670a708f8fSGustavo F. Padovan 	/* Get next available identificator.
6680a708f8fSGustavo F. Padovan 	 *    1 - 128 are used by kernel.
6690a708f8fSGustavo F. Padovan 	 *  129 - 199 are reserved.
6700a708f8fSGustavo F. Padovan 	 *  200 - 254 are used by utilities like l2ping, etc.
6710a708f8fSGustavo F. Padovan 	 */
6720a708f8fSGustavo F. Padovan 
673333055f2SGustavo F. Padovan 	spin_lock(&conn->lock);
6740a708f8fSGustavo F. Padovan 
6750a708f8fSGustavo F. Padovan 	if (++conn->tx_ident > 128)
6760a708f8fSGustavo F. Padovan 		conn->tx_ident = 1;
6770a708f8fSGustavo F. Padovan 
6780a708f8fSGustavo F. Padovan 	id = conn->tx_ident;
6790a708f8fSGustavo F. Padovan 
680333055f2SGustavo F. Padovan 	spin_unlock(&conn->lock);
6810a708f8fSGustavo F. Padovan 
6820a708f8fSGustavo F. Padovan 	return id;
6830a708f8fSGustavo F. Padovan }
6840a708f8fSGustavo F. Padovan 
6854519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
6860a708f8fSGustavo F. Padovan {
6870a708f8fSGustavo F. Padovan 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
6880a708f8fSGustavo F. Padovan 	u8 flags;
6890a708f8fSGustavo F. Padovan 
6900a708f8fSGustavo F. Padovan 	BT_DBG("code 0x%2.2x", code);
6910a708f8fSGustavo F. Padovan 
6920a708f8fSGustavo F. Padovan 	if (!skb)
6930a708f8fSGustavo F. Padovan 		return;
6940a708f8fSGustavo F. Padovan 
6950a708f8fSGustavo F. Padovan 	if (lmp_no_flush_capable(conn->hcon->hdev))
6960a708f8fSGustavo F. Padovan 		flags = ACL_START_NO_FLUSH;
6970a708f8fSGustavo F. Padovan 	else
6980a708f8fSGustavo F. Padovan 		flags = ACL_START;
6990a708f8fSGustavo F. Padovan 
70014b12d0bSJaikumar Ganesh 	bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
7015e59b791SLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
70214b12d0bSJaikumar Ganesh 
70373d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, flags);
7040a708f8fSGustavo F. Padovan }
7050a708f8fSGustavo F. Padovan 
70673d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
70773d80debSLuiz Augusto von Dentz {
70873d80debSLuiz Augusto von Dentz 	struct hci_conn *hcon = chan->conn->hcon;
70973d80debSLuiz Augusto von Dentz 	u16 flags;
71073d80debSLuiz Augusto von Dentz 
71173d80debSLuiz Augusto von Dentz 	BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
71273d80debSLuiz Augusto von Dentz 							skb->priority);
71373d80debSLuiz Augusto von Dentz 
71473d80debSLuiz Augusto von Dentz 	if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
71573d80debSLuiz Augusto von Dentz 					lmp_no_flush_capable(hcon->hdev))
71673d80debSLuiz Augusto von Dentz 		flags = ACL_START_NO_FLUSH;
71773d80debSLuiz Augusto von Dentz 	else
71873d80debSLuiz Augusto von Dentz 		flags = ACL_START;
71973d80debSLuiz Augusto von Dentz 
72073d80debSLuiz Augusto von Dentz 	bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
72173d80debSLuiz Augusto von Dentz 	hci_send_acl(chan->conn->hchan, skb, flags);
7220a708f8fSGustavo F. Padovan }
7230a708f8fSGustavo F. Padovan 
724b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
725b5c6aaedSMat Martineau {
726b5c6aaedSMat Martineau 	control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
727b5c6aaedSMat Martineau 	control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
728b5c6aaedSMat Martineau 
729b5c6aaedSMat Martineau 	if (enh & L2CAP_CTRL_FRAME_TYPE) {
730b5c6aaedSMat Martineau 		/* S-Frame */
731b5c6aaedSMat Martineau 		control->sframe = 1;
732b5c6aaedSMat Martineau 		control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
733b5c6aaedSMat Martineau 		control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
734b5c6aaedSMat Martineau 
735b5c6aaedSMat Martineau 		control->sar = 0;
736b5c6aaedSMat Martineau 		control->txseq = 0;
737b5c6aaedSMat Martineau 	} else {
738b5c6aaedSMat Martineau 		/* I-Frame */
739b5c6aaedSMat Martineau 		control->sframe = 0;
740b5c6aaedSMat Martineau 		control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
741b5c6aaedSMat Martineau 		control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
742b5c6aaedSMat Martineau 
743b5c6aaedSMat Martineau 		control->poll = 0;
744b5c6aaedSMat Martineau 		control->super = 0;
745b5c6aaedSMat Martineau 	}
746b5c6aaedSMat Martineau }
747b5c6aaedSMat Martineau 
748b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
749b5c6aaedSMat Martineau {
750b5c6aaedSMat Martineau 	control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
751b5c6aaedSMat Martineau 	control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
752b5c6aaedSMat Martineau 
753b5c6aaedSMat Martineau 	if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
754b5c6aaedSMat Martineau 		/* S-Frame */
755b5c6aaedSMat Martineau 		control->sframe = 1;
756b5c6aaedSMat Martineau 		control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
757b5c6aaedSMat Martineau 		control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
758b5c6aaedSMat Martineau 
759b5c6aaedSMat Martineau 		control->sar = 0;
760b5c6aaedSMat Martineau 		control->txseq = 0;
761b5c6aaedSMat Martineau 	} else {
762b5c6aaedSMat Martineau 		/* I-Frame */
763b5c6aaedSMat Martineau 		control->sframe = 0;
764b5c6aaedSMat Martineau 		control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
765b5c6aaedSMat Martineau 		control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
766b5c6aaedSMat Martineau 
767b5c6aaedSMat Martineau 		control->poll = 0;
768b5c6aaedSMat Martineau 		control->super = 0;
769b5c6aaedSMat Martineau 	}
770b5c6aaedSMat Martineau }
771b5c6aaedSMat Martineau 
772b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan,
773b5c6aaedSMat Martineau 				    struct sk_buff *skb)
774b5c6aaedSMat Martineau {
775b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
776b5c6aaedSMat Martineau 		__unpack_extended_control(get_unaligned_le32(skb->data),
777b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
778b5c6aaedSMat Martineau 	} else {
779b5c6aaedSMat Martineau 		__unpack_enhanced_control(get_unaligned_le16(skb->data),
780b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
781b5c6aaedSMat Martineau 	}
782b5c6aaedSMat Martineau }
783b5c6aaedSMat Martineau 
784b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control)
785b5c6aaedSMat Martineau {
786b5c6aaedSMat Martineau 	u32 packed;
787b5c6aaedSMat Martineau 
788b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
789b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
790b5c6aaedSMat Martineau 
791b5c6aaedSMat Martineau 	if (control->sframe) {
792b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
793b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
794b5c6aaedSMat Martineau 		packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
795b5c6aaedSMat Martineau 	} else {
796b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
797b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
798b5c6aaedSMat Martineau 	}
799b5c6aaedSMat Martineau 
800b5c6aaedSMat Martineau 	return packed;
801b5c6aaedSMat Martineau }
802b5c6aaedSMat Martineau 
803b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
804b5c6aaedSMat Martineau {
805b5c6aaedSMat Martineau 	u16 packed;
806b5c6aaedSMat Martineau 
807b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
808b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
809b5c6aaedSMat Martineau 
810b5c6aaedSMat Martineau 	if (control->sframe) {
811b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
812b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
813b5c6aaedSMat Martineau 		packed |= L2CAP_CTRL_FRAME_TYPE;
814b5c6aaedSMat Martineau 	} else {
815b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
816b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
817b5c6aaedSMat Martineau 	}
818b5c6aaedSMat Martineau 
819b5c6aaedSMat Martineau 	return packed;
820b5c6aaedSMat Martineau }
821b5c6aaedSMat Martineau 
822b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan,
823b5c6aaedSMat Martineau 				  struct l2cap_ctrl *control,
824b5c6aaedSMat Martineau 				  struct sk_buff *skb)
825b5c6aaedSMat Martineau {
826b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
827b5c6aaedSMat Martineau 		put_unaligned_le32(__pack_extended_control(control),
828b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
829b5c6aaedSMat Martineau 	} else {
830b5c6aaedSMat Martineau 		put_unaligned_le16(__pack_enhanced_control(control),
831b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
832b5c6aaedSMat Martineau 	}
833b5c6aaedSMat Martineau }
834b5c6aaedSMat Martineau 
83588843ab0SAndrei Emeltchenko static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
8360a708f8fSGustavo F. Padovan {
8370a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
8380a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
8398c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
840e4ca6d98SAndrei Emeltchenko 	int count, hlen;
8410a708f8fSGustavo F. Padovan 
84289bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
8430a708f8fSGustavo F. Padovan 		return;
8440a708f8fSGustavo F. Padovan 
845e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
846e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_EXT_HDR_SIZE;
847e4ca6d98SAndrei Emeltchenko 	else
848e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_ENH_HDR_SIZE;
8490a708f8fSGustavo F. Padovan 
8500a708f8fSGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
85103a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
8520a708f8fSGustavo F. Padovan 
85388843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, control 0x%8.8x", chan, control);
8540a708f8fSGustavo F. Padovan 
8550a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, hlen);
856793c2f1cSAndrei Emeltchenko 
857793c2f1cSAndrei Emeltchenko 	control |= __set_sframe(chan);
8580a708f8fSGustavo F. Padovan 
859e2ab4353SGustavo F. Padovan 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
86003f6715dSAndrei Emeltchenko 		control |= __set_ctrl_final(chan);
8610a708f8fSGustavo F. Padovan 
862e2ab4353SGustavo F. Padovan 	if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
863e3781735SAndrei Emeltchenko 		control |= __set_ctrl_poll(chan);
8640a708f8fSGustavo F. Padovan 
8650a708f8fSGustavo F. Padovan 	skb = bt_skb_alloc(count, GFP_ATOMIC);
8660a708f8fSGustavo F. Padovan 	if (!skb)
8670a708f8fSGustavo F. Padovan 		return;
8680a708f8fSGustavo F. Padovan 
8690a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
8700a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
871fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
87288843ab0SAndrei Emeltchenko 
87388843ab0SAndrei Emeltchenko 	__put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
8740a708f8fSGustavo F. Padovan 
87547d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
87603a51213SAndrei Emeltchenko 		u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
87703a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
8780a708f8fSGustavo F. Padovan 	}
8790a708f8fSGustavo F. Padovan 
88073d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
88173d80debSLuiz Augusto von Dentz 	l2cap_do_send(chan, skb);
8820a708f8fSGustavo F. Padovan }
8830a708f8fSGustavo F. Padovan 
88488843ab0SAndrei Emeltchenko static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
8850a708f8fSGustavo F. Padovan {
886e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
887ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
888e2ab4353SGustavo F. Padovan 		set_bit(CONN_RNR_SENT, &chan->conn_state);
8890a708f8fSGustavo F. Padovan 	} else
890ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
8910a708f8fSGustavo F. Padovan 
8920b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
8930a708f8fSGustavo F. Padovan 
894525cd185SGustavo F. Padovan 	l2cap_send_sframe(chan, control);
8950a708f8fSGustavo F. Padovan }
8960a708f8fSGustavo F. Padovan 
897b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
8980a708f8fSGustavo F. Padovan {
899c1360a1cSGustavo F. Padovan 	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
9000a708f8fSGustavo F. Padovan }
9010a708f8fSGustavo F. Padovan 
9029b27f350SAndrei Emeltchenko static void l2cap_send_conn_req(struct l2cap_chan *chan)
9039b27f350SAndrei Emeltchenko {
9049b27f350SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
9059b27f350SAndrei Emeltchenko 	struct l2cap_conn_req req;
9069b27f350SAndrei Emeltchenko 
9079b27f350SAndrei Emeltchenko 	req.scid = cpu_to_le16(chan->scid);
9089b27f350SAndrei Emeltchenko 	req.psm  = chan->psm;
9099b27f350SAndrei Emeltchenko 
9109b27f350SAndrei Emeltchenko 	chan->ident = l2cap_get_ident(conn);
9119b27f350SAndrei Emeltchenko 
9129b27f350SAndrei Emeltchenko 	set_bit(CONF_CONNECT_PEND, &chan->conf_state);
9139b27f350SAndrei Emeltchenko 
9149b27f350SAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
9159b27f350SAndrei Emeltchenko }
9169b27f350SAndrei Emeltchenko 
9179f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan)
9189f0caeb1SVinicius Costa Gomes {
9199f0caeb1SVinicius Costa Gomes 	struct sock *sk = chan->sk;
9209f0caeb1SVinicius Costa Gomes 	struct sock *parent;
9219f0caeb1SVinicius Costa Gomes 
9229f0caeb1SVinicius Costa Gomes 	lock_sock(sk);
9239f0caeb1SVinicius Costa Gomes 
9249f0caeb1SVinicius Costa Gomes 	parent = bt_sk(sk)->parent;
9259f0caeb1SVinicius Costa Gomes 
9269f0caeb1SVinicius Costa Gomes 	BT_DBG("sk %p, parent %p", sk, parent);
9279f0caeb1SVinicius Costa Gomes 
9282827011fSMat Martineau 	/* This clears all conf flags, including CONF_NOT_COMPLETE */
9299f0caeb1SVinicius Costa Gomes 	chan->conf_state = 0;
9309f0caeb1SVinicius Costa Gomes 	__clear_chan_timer(chan);
9319f0caeb1SVinicius Costa Gomes 
9329f0caeb1SVinicius Costa Gomes 	__l2cap_state_change(chan, BT_CONNECTED);
9339f0caeb1SVinicius Costa Gomes 	sk->sk_state_change(sk);
9349f0caeb1SVinicius Costa Gomes 
9359f0caeb1SVinicius Costa Gomes 	if (parent)
9369f0caeb1SVinicius Costa Gomes 		parent->sk_data_ready(parent, 0);
9379f0caeb1SVinicius Costa Gomes 
9389f0caeb1SVinicius Costa Gomes 	release_sock(sk);
9399f0caeb1SVinicius Costa Gomes }
9409f0caeb1SVinicius Costa Gomes 
941fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan)
9420a708f8fSGustavo F. Padovan {
9438c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
9440a708f8fSGustavo F. Padovan 
9459f0caeb1SVinicius Costa Gomes 	if (conn->hcon->type == LE_LINK) {
9469f0caeb1SVinicius Costa Gomes 		l2cap_chan_ready(chan);
9479f0caeb1SVinicius Costa Gomes 		return;
9489f0caeb1SVinicius Costa Gomes 	}
9499f0caeb1SVinicius Costa Gomes 
9500a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
9510a708f8fSGustavo F. Padovan 		if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
9520a708f8fSGustavo F. Padovan 			return;
9530a708f8fSGustavo F. Padovan 
954d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan) &&
9559b27f350SAndrei Emeltchenko 				__l2cap_no_conn_pending(chan))
9569b27f350SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
9570a708f8fSGustavo F. Padovan 	} else {
9580a708f8fSGustavo F. Padovan 		struct l2cap_info_req req;
9590a708f8fSGustavo F. Padovan 		req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
9600a708f8fSGustavo F. Padovan 
9610a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
9620a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
9630a708f8fSGustavo F. Padovan 
964ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
9650a708f8fSGustavo F. Padovan 
9660a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, conn->info_ident,
9670a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(req), &req);
9680a708f8fSGustavo F. Padovan 	}
9690a708f8fSGustavo F. Padovan }
9700a708f8fSGustavo F. Padovan 
9710a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
9720a708f8fSGustavo F. Padovan {
9730a708f8fSGustavo F. Padovan 	u32 local_feat_mask = l2cap_feat_mask;
9740a708f8fSGustavo F. Padovan 	if (!disable_ertm)
9750a708f8fSGustavo F. Padovan 		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
9760a708f8fSGustavo F. Padovan 
9770a708f8fSGustavo F. Padovan 	switch (mode) {
9780a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
9790a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
9800a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
9810a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
9820a708f8fSGustavo F. Padovan 	default:
9830a708f8fSGustavo F. Padovan 		return 0x00;
9840a708f8fSGustavo F. Padovan 	}
9850a708f8fSGustavo F. Padovan }
9860a708f8fSGustavo F. Padovan 
9874519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
9880a708f8fSGustavo F. Padovan {
9896be36555SAndrei Emeltchenko 	struct sock *sk = chan->sk;
9900a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req req;
9910a708f8fSGustavo F. Padovan 
9920a708f8fSGustavo F. Padovan 	if (!conn)
9930a708f8fSGustavo F. Padovan 		return;
9940a708f8fSGustavo F. Padovan 
9950c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_ERTM) {
9961a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
9971a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
9981a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
9990a708f8fSGustavo F. Padovan 	}
10000a708f8fSGustavo F. Padovan 
1001fe4128e0SGustavo F. Padovan 	req.dcid = cpu_to_le16(chan->dcid);
1002fe4128e0SGustavo F. Padovan 	req.scid = cpu_to_le16(chan->scid);
10030a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn),
10040a708f8fSGustavo F. Padovan 			L2CAP_DISCONN_REQ, sizeof(req), &req);
10050a708f8fSGustavo F. Padovan 
10066be36555SAndrei Emeltchenko 	lock_sock(sk);
10070e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_DISCONN);
10082e0052e4SAndrei Emeltchenko 	__l2cap_chan_set_err(chan, err);
10096be36555SAndrei Emeltchenko 	release_sock(sk);
10100a708f8fSGustavo F. Padovan }
10110a708f8fSGustavo F. Padovan 
10120a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
10130a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
10140a708f8fSGustavo F. Padovan {
10153df91ea2SAndrei Emeltchenko 	struct l2cap_chan *chan, *tmp;
10160a708f8fSGustavo F. Padovan 
10170a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
10180a708f8fSGustavo F. Padovan 
10193df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
10200a708f8fSGustavo F. Padovan 
10213df91ea2SAndrei Emeltchenko 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
102248454079SGustavo F. Padovan 		struct sock *sk = chan->sk;
1023baa7e1faSGustavo F. Padovan 
10246be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
10250a708f8fSGustavo F. Padovan 
1026715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
10276be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
10280a708f8fSGustavo F. Padovan 			continue;
10290a708f8fSGustavo F. Padovan 		}
10300a708f8fSGustavo F. Padovan 
103189bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
1032d45fc423SGustavo F. Padovan 			if (!l2cap_chan_check_security(chan) ||
1033b4450035SGustavo F. Padovan 					!__l2cap_no_conn_pending(chan)) {
10346be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10350a708f8fSGustavo F. Padovan 				continue;
10360a708f8fSGustavo F. Padovan 			}
10370a708f8fSGustavo F. Padovan 
1038c1360a1cSGustavo F. Padovan 			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1039c1360a1cSGustavo F. Padovan 					&& test_bit(CONF_STATE2_DEVICE,
1040c1360a1cSGustavo F. Padovan 					&chan->conf_state)) {
10410f852724SGustavo F. Padovan 				l2cap_chan_close(chan, ECONNRESET);
10426be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10430a708f8fSGustavo F. Padovan 				continue;
10440a708f8fSGustavo F. Padovan 			}
10450a708f8fSGustavo F. Padovan 
10469b27f350SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
10470a708f8fSGustavo F. Padovan 
104889bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
10490a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
10500a708f8fSGustavo F. Padovan 			char buf[128];
1051fe4128e0SGustavo F. Padovan 			rsp.scid = cpu_to_le16(chan->dcid);
1052fe4128e0SGustavo F. Padovan 			rsp.dcid = cpu_to_le16(chan->scid);
10530a708f8fSGustavo F. Padovan 
1054d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan)) {
10556be36555SAndrei Emeltchenko 				lock_sock(sk);
1056c5daa683SGustavo Padovan 				if (test_bit(BT_SK_DEFER_SETUP,
1057c5daa683SGustavo Padovan 					     &bt_sk(sk)->flags)) {
10580a708f8fSGustavo F. Padovan 					struct sock *parent = bt_sk(sk)->parent;
10590a708f8fSGustavo F. Padovan 					rsp.result = cpu_to_le16(L2CAP_CR_PEND);
10600a708f8fSGustavo F. Padovan 					rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
106105e9a2f6SIlia Kolomisnky 					if (parent)
10620a708f8fSGustavo F. Padovan 						parent->sk_data_ready(parent, 0);
10630a708f8fSGustavo F. Padovan 
10640a708f8fSGustavo F. Padovan 				} else {
10650e587be7SAndrei Emeltchenko 					__l2cap_state_change(chan, BT_CONFIG);
10660a708f8fSGustavo F. Padovan 					rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
10670a708f8fSGustavo F. Padovan 					rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
10680a708f8fSGustavo F. Padovan 				}
10696be36555SAndrei Emeltchenko 				release_sock(sk);
10700a708f8fSGustavo F. Padovan 			} else {
10710a708f8fSGustavo F. Padovan 				rsp.result = cpu_to_le16(L2CAP_CR_PEND);
10720a708f8fSGustavo F. Padovan 				rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
10730a708f8fSGustavo F. Padovan 			}
10740a708f8fSGustavo F. Padovan 
1075fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1076fc7f8a7eSGustavo F. Padovan 							sizeof(rsp), &rsp);
10770a708f8fSGustavo F. Padovan 
1078c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
10790a708f8fSGustavo F. Padovan 					rsp.result != L2CAP_CR_SUCCESS) {
10806be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10810a708f8fSGustavo F. Padovan 				continue;
10820a708f8fSGustavo F. Padovan 			}
10830a708f8fSGustavo F. Padovan 
1084c1360a1cSGustavo F. Padovan 			set_bit(CONF_REQ_SENT, &chan->conf_state);
10850a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
108673ffa904SGustavo F. Padovan 						l2cap_build_conf_req(chan, buf), buf);
108773ffa904SGustavo F. Padovan 			chan->num_conf_req++;
10880a708f8fSGustavo F. Padovan 		}
10890a708f8fSGustavo F. Padovan 
10906be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
10910a708f8fSGustavo F. Padovan 	}
10920a708f8fSGustavo F. Padovan 
10933df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
10940a708f8fSGustavo F. Padovan }
10950a708f8fSGustavo F. Padovan 
1096c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr.
1097b62f328bSVille Tervo  * Returns closest match, locked.
1098b62f328bSVille Tervo  */
1099d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
1100c2287681SIdo Yariv 						    bdaddr_t *src,
1101c2287681SIdo Yariv 						    bdaddr_t *dst)
1102b62f328bSVille Tervo {
110323691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
1104b62f328bSVille Tervo 
110523691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
1106b62f328bSVille Tervo 
110723691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
110823691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
1109fe4128e0SGustavo F. Padovan 
111089bc500eSGustavo F. Padovan 		if (state && c->state != state)
1111b62f328bSVille Tervo 			continue;
1112b62f328bSVille Tervo 
111323691d75SGustavo F. Padovan 		if (c->scid == cid) {
1114c2287681SIdo Yariv 			int src_match, dst_match;
1115c2287681SIdo Yariv 			int src_any, dst_any;
1116c2287681SIdo Yariv 
1117b62f328bSVille Tervo 			/* Exact match. */
1118c2287681SIdo Yariv 			src_match = !bacmp(&bt_sk(sk)->src, src);
1119c2287681SIdo Yariv 			dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1120c2287681SIdo Yariv 			if (src_match && dst_match) {
112123691d75SGustavo F. Padovan 				read_unlock(&chan_list_lock);
112223691d75SGustavo F. Padovan 				return c;
112323691d75SGustavo F. Padovan 			}
1124b62f328bSVille Tervo 
1125b62f328bSVille Tervo 			/* Closest match */
1126c2287681SIdo Yariv 			src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1127c2287681SIdo Yariv 			dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1128c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1129c2287681SIdo Yariv 			    (src_any && dst_any))
113023691d75SGustavo F. Padovan 				c1 = c;
1131b62f328bSVille Tervo 		}
1132b62f328bSVille Tervo 	}
1133280f294fSGustavo F. Padovan 
113423691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
1135b62f328bSVille Tervo 
113623691d75SGustavo F. Padovan 	return c1;
1137b62f328bSVille Tervo }
1138b62f328bSVille Tervo 
1139b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1140b62f328bSVille Tervo {
1141c916fbe4SGustavo F. Padovan 	struct sock *parent, *sk;
114223691d75SGustavo F. Padovan 	struct l2cap_chan *chan, *pchan;
1143b62f328bSVille Tervo 
1144b62f328bSVille Tervo 	BT_DBG("");
1145b62f328bSVille Tervo 
1146b62f328bSVille Tervo 	/* Check if we have socket listening on cid */
114723691d75SGustavo F. Padovan 	pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
1148c2287681SIdo Yariv 					  conn->src, conn->dst);
114923691d75SGustavo F. Padovan 	if (!pchan)
1150b62f328bSVille Tervo 		return;
1151b62f328bSVille Tervo 
115223691d75SGustavo F. Padovan 	parent = pchan->sk;
115323691d75SGustavo F. Padovan 
1154aa2ac881SGustavo F. Padovan 	lock_sock(parent);
115562f3a2cfSGustavo F. Padovan 
1156b62f328bSVille Tervo 	/* Check for backlog size */
1157b62f328bSVille Tervo 	if (sk_acceptq_is_full(parent)) {
1158b62f328bSVille Tervo 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
1159b62f328bSVille Tervo 		goto clean;
1160b62f328bSVille Tervo 	}
1161b62f328bSVille Tervo 
116280808e43SGustavo F. Padovan 	chan = pchan->ops->new_connection(pchan->data);
116380808e43SGustavo F. Padovan 	if (!chan)
1164b62f328bSVille Tervo 		goto clean;
1165b62f328bSVille Tervo 
116680808e43SGustavo F. Padovan 	sk = chan->sk;
11675d41ce1dSGustavo F. Padovan 
1168b62f328bSVille Tervo 	hci_conn_hold(conn->hcon);
1169b62f328bSVille Tervo 
1170b62f328bSVille Tervo 	bacpy(&bt_sk(sk)->src, conn->src);
1171b62f328bSVille Tervo 	bacpy(&bt_sk(sk)->dst, conn->dst);
1172b62f328bSVille Tervo 
1173d1010240SGustavo F. Padovan 	bt_accept_enqueue(parent, sk);
1174d1010240SGustavo F. Padovan 
11753d57dc68SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
117648454079SGustavo F. Padovan 
1177c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
1178b62f328bSVille Tervo 
11790e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_CONNECTED);
1180b62f328bSVille Tervo 	parent->sk_data_ready(parent, 0);
1181b62f328bSVille Tervo 
1182b62f328bSVille Tervo clean:
1183aa2ac881SGustavo F. Padovan 	release_sock(parent);
1184b62f328bSVille Tervo }
1185b62f328bSVille Tervo 
11860a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
11870a708f8fSGustavo F. Padovan {
118848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
11890a708f8fSGustavo F. Padovan 
11900a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
11910a708f8fSGustavo F. Padovan 
1192b62f328bSVille Tervo 	if (!conn->hcon->out && conn->hcon->type == LE_LINK)
1193b62f328bSVille Tervo 		l2cap_le_conn_ready(conn);
1194b62f328bSVille Tervo 
1195160dc6acSVinicius Costa Gomes 	if (conn->hcon->out && conn->hcon->type == LE_LINK)
1196160dc6acSVinicius Costa Gomes 		smp_conn_security(conn, conn->hcon->pending_sec_level);
1197160dc6acSVinicius Costa Gomes 
11983df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
11990a708f8fSGustavo F. Padovan 
12003df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1201baa7e1faSGustavo F. Padovan 
12026be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
12030a708f8fSGustavo F. Padovan 
120463128451SVinicius Costa Gomes 		if (conn->hcon->type == LE_LINK) {
1205b501d6a1SAnderson Briglia 			if (smp_conn_security(conn, chan->sec_level))
1206cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
1207acd7d370SVille Tervo 
120863128451SVinicius Costa Gomes 		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
12096be36555SAndrei Emeltchenko 			struct sock *sk = chan->sk;
1210c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
12116be36555SAndrei Emeltchenko 			lock_sock(sk);
12120e587be7SAndrei Emeltchenko 			__l2cap_state_change(chan, BT_CONNECTED);
12130a708f8fSGustavo F. Padovan 			sk->sk_state_change(sk);
12146be36555SAndrei Emeltchenko 			release_sock(sk);
1215b501d6a1SAnderson Briglia 
121689bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT)
1217fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
12180a708f8fSGustavo F. Padovan 
12196be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
12200a708f8fSGustavo F. Padovan 	}
12210a708f8fSGustavo F. Padovan 
12223df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12230a708f8fSGustavo F. Padovan }
12240a708f8fSGustavo F. Padovan 
12250a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
12260a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
12270a708f8fSGustavo F. Padovan {
122848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
12290a708f8fSGustavo F. Padovan 
12300a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
12310a708f8fSGustavo F. Padovan 
12323df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
12330a708f8fSGustavo F. Padovan 
12343df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1235ecf61bdbSAndrei Emeltchenko 		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
12362e0052e4SAndrei Emeltchenko 			__l2cap_chan_set_err(chan, err);
12370a708f8fSGustavo F. Padovan 	}
12380a708f8fSGustavo F. Padovan 
12393df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12400a708f8fSGustavo F. Padovan }
12410a708f8fSGustavo F. Padovan 
1242f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
12430a708f8fSGustavo F. Padovan {
1244f878fcadSGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1245030013d8SGustavo F. Padovan 							info_timer.work);
12460a708f8fSGustavo F. Padovan 
12470a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
12480a708f8fSGustavo F. Padovan 	conn->info_ident = 0;
12490a708f8fSGustavo F. Padovan 
12500a708f8fSGustavo F. Padovan 	l2cap_conn_start(conn);
12510a708f8fSGustavo F. Padovan }
12520a708f8fSGustavo F. Padovan 
12535d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
12545d3de7dfSVinicius Costa Gomes {
12555d3de7dfSVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
12565d3de7dfSVinicius Costa Gomes 	struct l2cap_chan *chan, *l;
12575d3de7dfSVinicius Costa Gomes 
12585d3de7dfSVinicius Costa Gomes 	if (!conn)
12595d3de7dfSVinicius Costa Gomes 		return;
12605d3de7dfSVinicius Costa Gomes 
12615d3de7dfSVinicius Costa Gomes 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
12625d3de7dfSVinicius Costa Gomes 
12635d3de7dfSVinicius Costa Gomes 	kfree_skb(conn->rx_skb);
12645d3de7dfSVinicius Costa Gomes 
12653df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
12663df91ea2SAndrei Emeltchenko 
12675d3de7dfSVinicius Costa Gomes 	/* Kill channels */
12685d3de7dfSVinicius Costa Gomes 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
126961d6ef3eSMat Martineau 		l2cap_chan_hold(chan);
12706be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
12716be36555SAndrei Emeltchenko 
12725d3de7dfSVinicius Costa Gomes 		l2cap_chan_del(chan, err);
12736be36555SAndrei Emeltchenko 
12746be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
12756be36555SAndrei Emeltchenko 
12765d3de7dfSVinicius Costa Gomes 		chan->ops->close(chan->data);
127761d6ef3eSMat Martineau 		l2cap_chan_put(chan);
12785d3de7dfSVinicius Costa Gomes 	}
12795d3de7dfSVinicius Costa Gomes 
12803df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12813df91ea2SAndrei Emeltchenko 
128273d80debSLuiz Augusto von Dentz 	hci_chan_del(conn->hchan);
128373d80debSLuiz Augusto von Dentz 
12845d3de7dfSVinicius Costa Gomes 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1285127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->info_timer);
12865d3de7dfSVinicius Costa Gomes 
128751a8efd7SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
1288127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->security_timer);
12898aab4757SVinicius Costa Gomes 		smp_chan_destroy(conn);
1290d26a2345SVinicius Costa Gomes 	}
12915d3de7dfSVinicius Costa Gomes 
12925d3de7dfSVinicius Costa Gomes 	hcon->l2cap_data = NULL;
12935d3de7dfSVinicius Costa Gomes 	kfree(conn);
12945d3de7dfSVinicius Costa Gomes }
12955d3de7dfSVinicius Costa Gomes 
12966c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work)
12975d3de7dfSVinicius Costa Gomes {
12986c9d42a1SGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
12996c9d42a1SGustavo F. Padovan 						security_timer.work);
13005d3de7dfSVinicius Costa Gomes 
13015d3de7dfSVinicius Costa Gomes 	l2cap_conn_del(conn->hcon, ETIMEDOUT);
13025d3de7dfSVinicius Costa Gomes }
13035d3de7dfSVinicius Costa Gomes 
13040a708f8fSGustavo F. Padovan static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
13050a708f8fSGustavo F. Padovan {
13060a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
130773d80debSLuiz Augusto von Dentz 	struct hci_chan *hchan;
13080a708f8fSGustavo F. Padovan 
13090a708f8fSGustavo F. Padovan 	if (conn || status)
13100a708f8fSGustavo F. Padovan 		return conn;
13110a708f8fSGustavo F. Padovan 
131273d80debSLuiz Augusto von Dentz 	hchan = hci_chan_create(hcon);
131373d80debSLuiz Augusto von Dentz 	if (!hchan)
13140a708f8fSGustavo F. Padovan 		return NULL;
13150a708f8fSGustavo F. Padovan 
131673d80debSLuiz Augusto von Dentz 	conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
131773d80debSLuiz Augusto von Dentz 	if (!conn) {
131873d80debSLuiz Augusto von Dentz 		hci_chan_del(hchan);
131973d80debSLuiz Augusto von Dentz 		return NULL;
132073d80debSLuiz Augusto von Dentz 	}
132173d80debSLuiz Augusto von Dentz 
13220a708f8fSGustavo F. Padovan 	hcon->l2cap_data = conn;
13230a708f8fSGustavo F. Padovan 	conn->hcon = hcon;
132473d80debSLuiz Augusto von Dentz 	conn->hchan = hchan;
13250a708f8fSGustavo F. Padovan 
132673d80debSLuiz Augusto von Dentz 	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
13270a708f8fSGustavo F. Padovan 
1328acd7d370SVille Tervo 	if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1329acd7d370SVille Tervo 		conn->mtu = hcon->hdev->le_mtu;
1330acd7d370SVille Tervo 	else
13310a708f8fSGustavo F. Padovan 		conn->mtu = hcon->hdev->acl_mtu;
1332acd7d370SVille Tervo 
13330a708f8fSGustavo F. Padovan 	conn->src = &hcon->hdev->bdaddr;
13340a708f8fSGustavo F. Padovan 	conn->dst = &hcon->dst;
13350a708f8fSGustavo F. Padovan 
13360a708f8fSGustavo F. Padovan 	conn->feat_mask = 0;
13370a708f8fSGustavo F. Padovan 
13380a708f8fSGustavo F. Padovan 	spin_lock_init(&conn->lock);
13393df91ea2SAndrei Emeltchenko 	mutex_init(&conn->chan_lock);
1340baa7e1faSGustavo F. Padovan 
1341baa7e1faSGustavo F. Padovan 	INIT_LIST_HEAD(&conn->chan_l);
13420a708f8fSGustavo F. Padovan 
13435d3de7dfSVinicius Costa Gomes 	if (hcon->type == LE_LINK)
13446c9d42a1SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
13455d3de7dfSVinicius Costa Gomes 	else
1346030013d8SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
13470a708f8fSGustavo F. Padovan 
13489f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
13490a708f8fSGustavo F. Padovan 
13500a708f8fSGustavo F. Padovan 	return conn;
13510a708f8fSGustavo F. Padovan }
13520a708f8fSGustavo F. Padovan 
13530a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */
13540a708f8fSGustavo F. Padovan 
1355c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr.
13560a708f8fSGustavo F. Padovan  * Returns closest match.
13570a708f8fSGustavo F. Padovan  */
1358c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1359c2287681SIdo Yariv 						   bdaddr_t *src,
1360c2287681SIdo Yariv 						   bdaddr_t *dst)
13610a708f8fSGustavo F. Padovan {
136223691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
13630a708f8fSGustavo F. Padovan 
136423691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
13650a708f8fSGustavo F. Padovan 
136623691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
136723691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
1368fe4128e0SGustavo F. Padovan 
136989bc500eSGustavo F. Padovan 		if (state && c->state != state)
13700a708f8fSGustavo F. Padovan 			continue;
13710a708f8fSGustavo F. Padovan 
137223691d75SGustavo F. Padovan 		if (c->psm == psm) {
1373c2287681SIdo Yariv 			int src_match, dst_match;
1374c2287681SIdo Yariv 			int src_any, dst_any;
1375c2287681SIdo Yariv 
13760a708f8fSGustavo F. Padovan 			/* Exact match. */
1377c2287681SIdo Yariv 			src_match = !bacmp(&bt_sk(sk)->src, src);
1378c2287681SIdo Yariv 			dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1379c2287681SIdo Yariv 			if (src_match && dst_match) {
1380a7567b20SJohannes Berg 				read_unlock(&chan_list_lock);
138123691d75SGustavo F. Padovan 				return c;
138223691d75SGustavo F. Padovan 			}
13830a708f8fSGustavo F. Padovan 
13840a708f8fSGustavo F. Padovan 			/* Closest match */
1385c2287681SIdo Yariv 			src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1386c2287681SIdo Yariv 			dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1387c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1388c2287681SIdo Yariv 			    (src_any && dst_any))
138923691d75SGustavo F. Padovan 				c1 = c;
13900a708f8fSGustavo F. Padovan 		}
13910a708f8fSGustavo F. Padovan 	}
13920a708f8fSGustavo F. Padovan 
139323691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
13940a708f8fSGustavo F. Padovan 
139523691d75SGustavo F. Padovan 	return c1;
13960a708f8fSGustavo F. Padovan }
13970a708f8fSGustavo F. Padovan 
13988e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
13998e9f9892SAndre Guedes 		       bdaddr_t *dst, u8 dst_type)
14000a708f8fSGustavo F. Padovan {
14015d41ce1dSGustavo F. Padovan 	struct sock *sk = chan->sk;
14020a708f8fSGustavo F. Padovan 	bdaddr_t *src = &bt_sk(sk)->src;
14030a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
14040a708f8fSGustavo F. Padovan 	struct hci_conn *hcon;
14050a708f8fSGustavo F. Padovan 	struct hci_dev *hdev;
14060a708f8fSGustavo F. Padovan 	__u8 auth_type;
14070a708f8fSGustavo F. Padovan 	int err;
14080a708f8fSGustavo F. Padovan 
14098e9f9892SAndre Guedes 	BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst),
14108e9f9892SAndre Guedes 	       dst_type, __le16_to_cpu(chan->psm));
14110a708f8fSGustavo F. Padovan 
14120a708f8fSGustavo F. Padovan 	hdev = hci_get_route(dst, src);
14130a708f8fSGustavo F. Padovan 	if (!hdev)
14140a708f8fSGustavo F. Padovan 		return -EHOSTUNREACH;
14150a708f8fSGustavo F. Padovan 
141609fd0de5SGustavo F. Padovan 	hci_dev_lock(hdev);
14170a708f8fSGustavo F. Padovan 
14186be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
141903a00194SGustavo F. Padovan 
142003a00194SGustavo F. Padovan 	/* PSM must be odd and lsb of upper byte must be 0 */
142103a00194SGustavo F. Padovan 	if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
142203a00194SGustavo F. Padovan 					chan->chan_type != L2CAP_CHAN_RAW) {
142303a00194SGustavo F. Padovan 		err = -EINVAL;
142403a00194SGustavo F. Padovan 		goto done;
142503a00194SGustavo F. Padovan 	}
142603a00194SGustavo F. Padovan 
142703a00194SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
142803a00194SGustavo F. Padovan 		err = -EINVAL;
142903a00194SGustavo F. Padovan 		goto done;
143003a00194SGustavo F. Padovan 	}
143103a00194SGustavo F. Padovan 
143203a00194SGustavo F. Padovan 	switch (chan->mode) {
143303a00194SGustavo F. Padovan 	case L2CAP_MODE_BASIC:
143403a00194SGustavo F. Padovan 		break;
143503a00194SGustavo F. Padovan 	case L2CAP_MODE_ERTM:
143603a00194SGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
143703a00194SGustavo F. Padovan 		if (!disable_ertm)
143803a00194SGustavo F. Padovan 			break;
143903a00194SGustavo F. Padovan 		/* fall through */
144003a00194SGustavo F. Padovan 	default:
144103a00194SGustavo F. Padovan 		err = -ENOTSUPP;
144203a00194SGustavo F. Padovan 		goto done;
144303a00194SGustavo F. Padovan 	}
144403a00194SGustavo F. Padovan 
14456be36555SAndrei Emeltchenko 	lock_sock(sk);
14466be36555SAndrei Emeltchenko 
144703a00194SGustavo F. Padovan 	switch (sk->sk_state) {
144803a00194SGustavo F. Padovan 	case BT_CONNECT:
144903a00194SGustavo F. Padovan 	case BT_CONNECT2:
145003a00194SGustavo F. Padovan 	case BT_CONFIG:
145103a00194SGustavo F. Padovan 		/* Already connecting */
145203a00194SGustavo F. Padovan 		err = 0;
14536be36555SAndrei Emeltchenko 		release_sock(sk);
145403a00194SGustavo F. Padovan 		goto done;
145503a00194SGustavo F. Padovan 
145603a00194SGustavo F. Padovan 	case BT_CONNECTED:
145703a00194SGustavo F. Padovan 		/* Already connected */
145803a00194SGustavo F. Padovan 		err = -EISCONN;
14596be36555SAndrei Emeltchenko 		release_sock(sk);
146003a00194SGustavo F. Padovan 		goto done;
146103a00194SGustavo F. Padovan 
146203a00194SGustavo F. Padovan 	case BT_OPEN:
146303a00194SGustavo F. Padovan 	case BT_BOUND:
146403a00194SGustavo F. Padovan 		/* Can connect */
146503a00194SGustavo F. Padovan 		break;
146603a00194SGustavo F. Padovan 
146703a00194SGustavo F. Padovan 	default:
146803a00194SGustavo F. Padovan 		err = -EBADFD;
14696be36555SAndrei Emeltchenko 		release_sock(sk);
147003a00194SGustavo F. Padovan 		goto done;
147103a00194SGustavo F. Padovan 	}
147203a00194SGustavo F. Padovan 
147303a00194SGustavo F. Padovan 	/* Set destination address and psm */
14749219b2a0SGustavo F. Padovan 	bacpy(&bt_sk(sk)->dst, dst);
14756be36555SAndrei Emeltchenko 
14766be36555SAndrei Emeltchenko 	release_sock(sk);
14776be36555SAndrei Emeltchenko 
147803a00194SGustavo F. Padovan 	chan->psm = psm;
147903a00194SGustavo F. Padovan 	chan->dcid = cid;
14800a708f8fSGustavo F. Padovan 
14814343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
14820a708f8fSGustavo F. Padovan 
1483fe4128e0SGustavo F. Padovan 	if (chan->dcid == L2CAP_CID_LE_DATA)
14848e9f9892SAndre Guedes 		hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
14854343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1486acd7d370SVille Tervo 	else
14878e9f9892SAndre Guedes 		hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
14884343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1489acd7d370SVille Tervo 
149030e76272SVille Tervo 	if (IS_ERR(hcon)) {
149130e76272SVille Tervo 		err = PTR_ERR(hcon);
14920a708f8fSGustavo F. Padovan 		goto done;
149330e76272SVille Tervo 	}
14940a708f8fSGustavo F. Padovan 
14950a708f8fSGustavo F. Padovan 	conn = l2cap_conn_add(hcon, 0);
14960a708f8fSGustavo F. Padovan 	if (!conn) {
14970a708f8fSGustavo F. Padovan 		hci_conn_put(hcon);
149830e76272SVille Tervo 		err = -ENOMEM;
14990a708f8fSGustavo F. Padovan 		goto done;
15000a708f8fSGustavo F. Padovan 	}
15010a708f8fSGustavo F. Padovan 
15029f0caeb1SVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
15039f0caeb1SVinicius Costa Gomes 		err = 0;
15049f0caeb1SVinicius Costa Gomes 
15059f0caeb1SVinicius Costa Gomes 		if (!list_empty(&conn->chan_l)) {
15069f0caeb1SVinicius Costa Gomes 			err = -EBUSY;
15079f0caeb1SVinicius Costa Gomes 			hci_conn_put(hcon);
15089f0caeb1SVinicius Costa Gomes 		}
15099f0caeb1SVinicius Costa Gomes 
15109f0caeb1SVinicius Costa Gomes 		if (err)
15119f0caeb1SVinicius Costa Gomes 			goto done;
15129f0caeb1SVinicius Costa Gomes 	}
15139f0caeb1SVinicius Costa Gomes 
15140a708f8fSGustavo F. Padovan 	/* Update source addr of the socket */
15150a708f8fSGustavo F. Padovan 	bacpy(src, conn->src);
15160a708f8fSGustavo F. Padovan 
15176be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
151848454079SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
15196be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
152048454079SGustavo F. Padovan 
15216be36555SAndrei Emeltchenko 	l2cap_state_change(chan, BT_CONNECT);
1522c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
15230a708f8fSGustavo F. Padovan 
15240a708f8fSGustavo F. Padovan 	if (hcon->state == BT_CONNECTED) {
1525715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1526c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
1527d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan))
15286be36555SAndrei Emeltchenko 				l2cap_state_change(chan, BT_CONNECTED);
15290a708f8fSGustavo F. Padovan 		} else
1530fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
15310a708f8fSGustavo F. Padovan 	}
15320a708f8fSGustavo F. Padovan 
153330e76272SVille Tervo 	err = 0;
153430e76272SVille Tervo 
15350a708f8fSGustavo F. Padovan done:
15366be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
153709fd0de5SGustavo F. Padovan 	hci_dev_unlock(hdev);
15380a708f8fSGustavo F. Padovan 	hci_dev_put(hdev);
15390a708f8fSGustavo F. Padovan 	return err;
15400a708f8fSGustavo F. Padovan }
15410a708f8fSGustavo F. Padovan 
1542dcba0dbaSGustavo F. Padovan int __l2cap_wait_ack(struct sock *sk)
15430a708f8fSGustavo F. Padovan {
15448c1d787bSGustavo F. Padovan 	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
15450a708f8fSGustavo F. Padovan 	DECLARE_WAITQUEUE(wait, current);
15460a708f8fSGustavo F. Padovan 	int err = 0;
15470a708f8fSGustavo F. Padovan 	int timeo = HZ/5;
15480a708f8fSGustavo F. Padovan 
15490a708f8fSGustavo F. Padovan 	add_wait_queue(sk_sleep(sk), &wait);
15500a708f8fSGustavo F. Padovan 	set_current_state(TASK_INTERRUPTIBLE);
1551a71a0cf4SPeter Hurley 	while (chan->unacked_frames > 0 && chan->conn) {
15520a708f8fSGustavo F. Padovan 		if (!timeo)
15530a708f8fSGustavo F. Padovan 			timeo = HZ/5;
15540a708f8fSGustavo F. Padovan 
15550a708f8fSGustavo F. Padovan 		if (signal_pending(current)) {
15560a708f8fSGustavo F. Padovan 			err = sock_intr_errno(timeo);
15570a708f8fSGustavo F. Padovan 			break;
15580a708f8fSGustavo F. Padovan 		}
15590a708f8fSGustavo F. Padovan 
15600a708f8fSGustavo F. Padovan 		release_sock(sk);
15610a708f8fSGustavo F. Padovan 		timeo = schedule_timeout(timeo);
15620a708f8fSGustavo F. Padovan 		lock_sock(sk);
1563a71a0cf4SPeter Hurley 		set_current_state(TASK_INTERRUPTIBLE);
15640a708f8fSGustavo F. Padovan 
15650a708f8fSGustavo F. Padovan 		err = sock_error(sk);
15660a708f8fSGustavo F. Padovan 		if (err)
15670a708f8fSGustavo F. Padovan 			break;
15680a708f8fSGustavo F. Padovan 	}
15690a708f8fSGustavo F. Padovan 	set_current_state(TASK_RUNNING);
15700a708f8fSGustavo F. Padovan 	remove_wait_queue(sk_sleep(sk), &wait);
15710a708f8fSGustavo F. Padovan 	return err;
15720a708f8fSGustavo F. Padovan }
15730a708f8fSGustavo F. Padovan 
1574721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work)
15750a708f8fSGustavo F. Padovan {
1576721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1577721c4181SGustavo F. Padovan 							monitor_timer.work);
15780a708f8fSGustavo F. Padovan 
1579525cd185SGustavo F. Padovan 	BT_DBG("chan %p", chan);
15800a708f8fSGustavo F. Padovan 
15816be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
15826be36555SAndrei Emeltchenko 
15832c03a7a4SGustavo F. Padovan 	if (chan->retry_count >= chan->remote_max_tx) {
15848c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
15856be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
15868d7e1c7fSAndrei Emeltchenko 		l2cap_chan_put(chan);
15870a708f8fSGustavo F. Padovan 		return;
15880a708f8fSGustavo F. Padovan 	}
15890a708f8fSGustavo F. Padovan 
15906a026610SGustavo F. Padovan 	chan->retry_count++;
15911a09bcb9SGustavo F. Padovan 	__set_monitor_timer(chan);
15920a708f8fSGustavo F. Padovan 
1593525cd185SGustavo F. Padovan 	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
15946be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
15958d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
15960a708f8fSGustavo F. Padovan }
15970a708f8fSGustavo F. Padovan 
1598721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work)
15990a708f8fSGustavo F. Padovan {
1600721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1601721c4181SGustavo F. Padovan 							retrans_timer.work);
16020a708f8fSGustavo F. Padovan 
160349208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
16040a708f8fSGustavo F. Padovan 
16056be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
16066be36555SAndrei Emeltchenko 
16076a026610SGustavo F. Padovan 	chan->retry_count = 1;
16081a09bcb9SGustavo F. Padovan 	__set_monitor_timer(chan);
16090a708f8fSGustavo F. Padovan 
1610e2ab4353SGustavo F. Padovan 	set_bit(CONN_WAIT_F, &chan->conn_state);
16110a708f8fSGustavo F. Padovan 
1612525cd185SGustavo F. Padovan 	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
16136be36555SAndrei Emeltchenko 
16146be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
16158d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
16160a708f8fSGustavo F. Padovan }
16170a708f8fSGustavo F. Padovan 
161842e5c802SGustavo F. Padovan static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
16190a708f8fSGustavo F. Padovan {
16200a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
16210a708f8fSGustavo F. Padovan 
162258d35f87SGustavo F. Padovan 	while ((skb = skb_peek(&chan->tx_q)) &&
16236a026610SGustavo F. Padovan 			chan->unacked_frames) {
16243ce3514fSMat Martineau 		if (bt_cb(skb)->control.txseq == chan->expected_ack_seq)
16250a708f8fSGustavo F. Padovan 			break;
16260a708f8fSGustavo F. Padovan 
162758d35f87SGustavo F. Padovan 		skb = skb_dequeue(&chan->tx_q);
16280a708f8fSGustavo F. Padovan 		kfree_skb(skb);
16290a708f8fSGustavo F. Padovan 
16306a026610SGustavo F. Padovan 		chan->unacked_frames--;
16310a708f8fSGustavo F. Padovan 	}
16320a708f8fSGustavo F. Padovan 
16336a026610SGustavo F. Padovan 	if (!chan->unacked_frames)
16341a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
16350a708f8fSGustavo F. Padovan }
16360a708f8fSGustavo F. Padovan 
163767c9e840SSzymon Janc static void l2cap_streaming_send(struct l2cap_chan *chan)
16380a708f8fSGustavo F. Padovan {
16390a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
164088843ab0SAndrei Emeltchenko 	u32 control;
164188843ab0SAndrei Emeltchenko 	u16 fcs;
16420a708f8fSGustavo F. Padovan 
164358d35f87SGustavo F. Padovan 	while ((skb = skb_dequeue(&chan->tx_q))) {
164488843ab0SAndrei Emeltchenko 		control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
1645fb45de7dSAndrei Emeltchenko 		control |= __set_txseq(chan, chan->next_tx_seq);
164694122bbeSMat Martineau 		control |= __set_ctrl_sar(chan, bt_cb(skb)->control.sar);
164788843ab0SAndrei Emeltchenko 		__put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
16480a708f8fSGustavo F. Padovan 
164947d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
165003a51213SAndrei Emeltchenko 			fcs = crc16(0, (u8 *)skb->data,
165103a51213SAndrei Emeltchenko 						skb->len - L2CAP_FCS_SIZE);
165203a51213SAndrei Emeltchenko 			put_unaligned_le16(fcs,
165303a51213SAndrei Emeltchenko 					skb->data + skb->len - L2CAP_FCS_SIZE);
16540a708f8fSGustavo F. Padovan 		}
16550a708f8fSGustavo F. Padovan 
16564343478fSGustavo F. Padovan 		l2cap_do_send(chan, skb);
16570a708f8fSGustavo F. Padovan 
1658836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
16590a708f8fSGustavo F. Padovan 	}
16600a708f8fSGustavo F. Padovan }
16610a708f8fSGustavo F. Padovan 
1662fb45de7dSAndrei Emeltchenko static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
16630a708f8fSGustavo F. Padovan {
16640a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
166588843ab0SAndrei Emeltchenko 	u16 fcs;
166688843ab0SAndrei Emeltchenko 	u32 control;
16670a708f8fSGustavo F. Padovan 
166858d35f87SGustavo F. Padovan 	skb = skb_peek(&chan->tx_q);
16690a708f8fSGustavo F. Padovan 	if (!skb)
16700a708f8fSGustavo F. Padovan 		return;
16710a708f8fSGustavo F. Padovan 
16723ce3514fSMat Martineau 	while (bt_cb(skb)->control.txseq != tx_seq) {
167358d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
16740a708f8fSGustavo F. Padovan 			return;
16750a708f8fSGustavo F. Padovan 
1676d1726b6dSSzymon Janc 		skb = skb_queue_next(&chan->tx_q, skb);
1677d1726b6dSSzymon Janc 	}
16780a708f8fSGustavo F. Padovan 
16793ce3514fSMat Martineau 	if (bt_cb(skb)->control.retries == chan->remote_max_tx &&
16803ce3514fSMat Martineau 	    chan->remote_max_tx) {
16818c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
16820a708f8fSGustavo F. Padovan 		return;
16830a708f8fSGustavo F. Padovan 	}
16840a708f8fSGustavo F. Padovan 
16850a708f8fSGustavo F. Padovan 	tx_skb = skb_clone(skb, GFP_ATOMIC);
16863ce3514fSMat Martineau 	bt_cb(skb)->control.retries++;
168788843ab0SAndrei Emeltchenko 
168888843ab0SAndrei Emeltchenko 	control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
16897e0ef6eeSAndrei Emeltchenko 	control &= __get_sar_mask(chan);
16900a708f8fSGustavo F. Padovan 
1691e2ab4353SGustavo F. Padovan 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
169203f6715dSAndrei Emeltchenko 		control |= __set_ctrl_final(chan);
16930a708f8fSGustavo F. Padovan 
16940b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
1695fb45de7dSAndrei Emeltchenko 	control |= __set_txseq(chan, tx_seq);
16960a708f8fSGustavo F. Padovan 
169788843ab0SAndrei Emeltchenko 	__put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
16980a708f8fSGustavo F. Padovan 
169947d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
170003a51213SAndrei Emeltchenko 		fcs = crc16(0, (u8 *)tx_skb->data,
170103a51213SAndrei Emeltchenko 						tx_skb->len - L2CAP_FCS_SIZE);
170203a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs,
170303a51213SAndrei Emeltchenko 				tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
17040a708f8fSGustavo F. Padovan 	}
17050a708f8fSGustavo F. Padovan 
17064343478fSGustavo F. Padovan 	l2cap_do_send(chan, tx_skb);
17070a708f8fSGustavo F. Padovan }
17080a708f8fSGustavo F. Padovan 
170967c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan)
17100a708f8fSGustavo F. Padovan {
17110a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
171288843ab0SAndrei Emeltchenko 	u16 fcs;
171388843ab0SAndrei Emeltchenko 	u32 control;
17140a708f8fSGustavo F. Padovan 	int nsent = 0;
17150a708f8fSGustavo F. Padovan 
171689bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
17170a708f8fSGustavo F. Padovan 		return -ENOTCONN;
17180a708f8fSGustavo F. Padovan 
171994122bbeSMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
172094122bbeSMat Martineau 		return 0;
172194122bbeSMat Martineau 
172258d35f87SGustavo F. Padovan 	while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
17230a708f8fSGustavo F. Padovan 
17243ce3514fSMat Martineau 		if (bt_cb(skb)->control.retries == chan->remote_max_tx &&
17253ce3514fSMat Martineau 		    chan->remote_max_tx) {
17268c1d787bSGustavo F. Padovan 			l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
17270a708f8fSGustavo F. Padovan 			break;
17280a708f8fSGustavo F. Padovan 		}
17290a708f8fSGustavo F. Padovan 
17300a708f8fSGustavo F. Padovan 		tx_skb = skb_clone(skb, GFP_ATOMIC);
17310a708f8fSGustavo F. Padovan 
17323ce3514fSMat Martineau 		bt_cb(skb)->control.retries++;
17330a708f8fSGustavo F. Padovan 
173488843ab0SAndrei Emeltchenko 		control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
17357e0ef6eeSAndrei Emeltchenko 		control &= __get_sar_mask(chan);
17360a708f8fSGustavo F. Padovan 
1737e2ab4353SGustavo F. Padovan 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
173803f6715dSAndrei Emeltchenko 			control |= __set_ctrl_final(chan);
1739e2ab4353SGustavo F. Padovan 
17400b209faeSAndrei Emeltchenko 		control |= __set_reqseq(chan, chan->buffer_seq);
1741fb45de7dSAndrei Emeltchenko 		control |= __set_txseq(chan, chan->next_tx_seq);
174294122bbeSMat Martineau 		control |= __set_ctrl_sar(chan, bt_cb(skb)->control.sar);
17430a708f8fSGustavo F. Padovan 
174488843ab0SAndrei Emeltchenko 		__put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
17450a708f8fSGustavo F. Padovan 
174647d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
174703a51213SAndrei Emeltchenko 			fcs = crc16(0, (u8 *)skb->data,
174803a51213SAndrei Emeltchenko 						tx_skb->len - L2CAP_FCS_SIZE);
174903a51213SAndrei Emeltchenko 			put_unaligned_le16(fcs, skb->data +
175003a51213SAndrei Emeltchenko 						tx_skb->len - L2CAP_FCS_SIZE);
17510a708f8fSGustavo F. Padovan 		}
17520a708f8fSGustavo F. Padovan 
17534343478fSGustavo F. Padovan 		l2cap_do_send(chan, tx_skb);
17540a708f8fSGustavo F. Padovan 
17551a09bcb9SGustavo F. Padovan 		__set_retrans_timer(chan);
17560a708f8fSGustavo F. Padovan 
17573ce3514fSMat Martineau 		bt_cb(skb)->control.txseq = chan->next_tx_seq;
1758836be934SAndrei Emeltchenko 
1759836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
17600a708f8fSGustavo F. Padovan 
17613ce3514fSMat Martineau 		if (bt_cb(skb)->control.retries == 1) {
17626a026610SGustavo F. Padovan 			chan->unacked_frames++;
1763930fa4aeSSzymon Janc 
1764930fa4aeSSzymon Janc 			if (!nsent++)
1765930fa4aeSSzymon Janc 				__clear_ack_timer(chan);
17668ed7a0aeSSzymon Janc 		}
176723e9fde2SSuraj Sumangala 
17686a026610SGustavo F. Padovan 		chan->frames_sent++;
17690a708f8fSGustavo F. Padovan 
177058d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
177158d35f87SGustavo F. Padovan 			chan->tx_send_head = NULL;
17720a708f8fSGustavo F. Padovan 		else
177358d35f87SGustavo F. Padovan 			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
17740a708f8fSGustavo F. Padovan 	}
17750a708f8fSGustavo F. Padovan 
17760a708f8fSGustavo F. Padovan 	return nsent;
17770a708f8fSGustavo F. Padovan }
17780a708f8fSGustavo F. Padovan 
1779525cd185SGustavo F. Padovan static int l2cap_retransmit_frames(struct l2cap_chan *chan)
17800a708f8fSGustavo F. Padovan {
17810a708f8fSGustavo F. Padovan 	int ret;
17820a708f8fSGustavo F. Padovan 
178358d35f87SGustavo F. Padovan 	if (!skb_queue_empty(&chan->tx_q))
178458d35f87SGustavo F. Padovan 		chan->tx_send_head = chan->tx_q.next;
17850a708f8fSGustavo F. Padovan 
178642e5c802SGustavo F. Padovan 	chan->next_tx_seq = chan->expected_ack_seq;
1787525cd185SGustavo F. Padovan 	ret = l2cap_ertm_send(chan);
17880a708f8fSGustavo F. Padovan 	return ret;
17890a708f8fSGustavo F. Padovan }
17900a708f8fSGustavo F. Padovan 
1791b17e73bbSSzymon Janc static void __l2cap_send_ack(struct l2cap_chan *chan)
17920a708f8fSGustavo F. Padovan {
179388843ab0SAndrei Emeltchenko 	u32 control = 0;
17940a708f8fSGustavo F. Padovan 
17950b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
17960a708f8fSGustavo F. Padovan 
1797e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
1798ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
1799e2ab4353SGustavo F. Padovan 		set_bit(CONN_RNR_SENT, &chan->conn_state);
1800525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
18010a708f8fSGustavo F. Padovan 		return;
18020a708f8fSGustavo F. Padovan 	}
18030a708f8fSGustavo F. Padovan 
1804525cd185SGustavo F. Padovan 	if (l2cap_ertm_send(chan) > 0)
18050a708f8fSGustavo F. Padovan 		return;
18060a708f8fSGustavo F. Padovan 
1807ab784b73SAndrei Emeltchenko 	control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
1808525cd185SGustavo F. Padovan 	l2cap_send_sframe(chan, control);
18090a708f8fSGustavo F. Padovan }
18100a708f8fSGustavo F. Padovan 
1811b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan)
1812b17e73bbSSzymon Janc {
1813b17e73bbSSzymon Janc 	__clear_ack_timer(chan);
1814b17e73bbSSzymon Janc 	__l2cap_send_ack(chan);
1815b17e73bbSSzymon Janc }
1816b17e73bbSSzymon Janc 
1817525cd185SGustavo F. Padovan static void l2cap_send_srejtail(struct l2cap_chan *chan)
18180a708f8fSGustavo F. Padovan {
18190a708f8fSGustavo F. Padovan 	struct srej_list *tail;
182088843ab0SAndrei Emeltchenko 	u32 control;
18210a708f8fSGustavo F. Padovan 
1822ab784b73SAndrei Emeltchenko 	control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
182303f6715dSAndrei Emeltchenko 	control |= __set_ctrl_final(chan);
18240a708f8fSGustavo F. Padovan 
182539d5a3eeSGustavo F. Padovan 	tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
18260b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, tail->tx_seq);
18270a708f8fSGustavo F. Padovan 
1828525cd185SGustavo F. Padovan 	l2cap_send_sframe(chan, control);
18290a708f8fSGustavo F. Padovan }
18300a708f8fSGustavo F. Padovan 
183104124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
183204124681SGustavo F. Padovan 					 struct msghdr *msg, int len,
183304124681SGustavo F. Padovan 					 int count, struct sk_buff *skb)
18340a708f8fSGustavo F. Padovan {
18350952a57aSAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
18360a708f8fSGustavo F. Padovan 	struct sk_buff **frag;
183790338947SGustavo Padovan 	int sent = 0;
18380a708f8fSGustavo F. Padovan 
18390a708f8fSGustavo F. Padovan 	if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
18400a708f8fSGustavo F. Padovan 		return -EFAULT;
18410a708f8fSGustavo F. Padovan 
18420a708f8fSGustavo F. Padovan 	sent += count;
18430a708f8fSGustavo F. Padovan 	len  -= count;
18440a708f8fSGustavo F. Padovan 
18450a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
18460a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
18470a708f8fSGustavo F. Padovan 	while (len) {
1848fbe00700SGustavo Padovan 		struct sk_buff *tmp;
1849fbe00700SGustavo Padovan 
18500a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
18510a708f8fSGustavo F. Padovan 
1852fbe00700SGustavo Padovan 		tmp = chan->ops->alloc_skb(chan, count,
185390338947SGustavo Padovan 					   msg->msg_flags & MSG_DONTWAIT);
1854fbe00700SGustavo Padovan 		if (IS_ERR(tmp))
1855fbe00700SGustavo Padovan 			return PTR_ERR(tmp);
18562f7719ceSAndrei Emeltchenko 
1857fbe00700SGustavo Padovan 		*frag = tmp;
1858fbe00700SGustavo Padovan 
18590a708f8fSGustavo F. Padovan 		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
18600a708f8fSGustavo F. Padovan 			return -EFAULT;
18610a708f8fSGustavo F. Padovan 
18625e59b791SLuiz Augusto von Dentz 		(*frag)->priority = skb->priority;
18635e59b791SLuiz Augusto von Dentz 
18640a708f8fSGustavo F. Padovan 		sent += count;
18650a708f8fSGustavo F. Padovan 		len  -= count;
18660a708f8fSGustavo F. Padovan 
18672d0ed3d5SGustavo Padovan 		skb->len += (*frag)->len;
18682d0ed3d5SGustavo Padovan 		skb->data_len += (*frag)->len;
18692d0ed3d5SGustavo Padovan 
18700a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
18710a708f8fSGustavo F. Padovan 	}
18720a708f8fSGustavo F. Padovan 
18730a708f8fSGustavo F. Padovan 	return sent;
18740a708f8fSGustavo F. Padovan }
18750a708f8fSGustavo F. Padovan 
18765e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
18775e59b791SLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
18785e59b791SLuiz Augusto von Dentz 						u32 priority)
18790a708f8fSGustavo F. Padovan {
18808c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
18810a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
188203a51213SAndrei Emeltchenko 	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
18830a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
18840a708f8fSGustavo F. Padovan 
18856d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d priority %u", chan, (int)len, priority);
18860a708f8fSGustavo F. Padovan 
18870a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
18882f7719ceSAndrei Emeltchenko 
18892f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
189090338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
189190338947SGustavo Padovan 	if (IS_ERR(skb))
189290338947SGustavo Padovan 		return skb;
18930a708f8fSGustavo F. Padovan 
18945e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
18955e59b791SLuiz Augusto von Dentz 
18960a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
18970a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1898fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
1899daf6a78cSAndrei Emeltchenko 	lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
1900daf6a78cSAndrei Emeltchenko 	put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE));
19010a708f8fSGustavo F. Padovan 
19020952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
19030a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
19040a708f8fSGustavo F. Padovan 		kfree_skb(skb);
19050a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
19060a708f8fSGustavo F. Padovan 	}
19070a708f8fSGustavo F. Padovan 	return skb;
19080a708f8fSGustavo F. Padovan }
19090a708f8fSGustavo F. Padovan 
19105e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
19115e59b791SLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
19125e59b791SLuiz Augusto von Dentz 						u32 priority)
19130a708f8fSGustavo F. Padovan {
19148c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
19150a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
1916f2ba7faeSGustavo Padovan 	int err, count;
19170a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
19180a708f8fSGustavo F. Padovan 
19196d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d", chan, (int)len);
19200a708f8fSGustavo F. Padovan 
1921f2ba7faeSGustavo Padovan 	count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
19222f7719ceSAndrei Emeltchenko 
1923f2ba7faeSGustavo Padovan 	skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE,
192490338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
192590338947SGustavo Padovan 	if (IS_ERR(skb))
192690338947SGustavo Padovan 		return skb;
19270a708f8fSGustavo F. Padovan 
19285e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
19295e59b791SLuiz Augusto von Dentz 
19300a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
19310a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1932fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
19336ff9b5efSGustavo Padovan 	lh->len = cpu_to_le16(len);
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 	return skb;
19410a708f8fSGustavo F. Padovan }
19420a708f8fSGustavo F. Padovan 
1943ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1944ab0ff76dSLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
194594122bbeSMat Martineau 						u16 sdulen)
19460a708f8fSGustavo F. Padovan {
19478c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
19480a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
1949e4ca6d98SAndrei Emeltchenko 	int err, count, hlen;
19500a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
19510a708f8fSGustavo F. Padovan 
19526d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d", chan, (int)len);
19530a708f8fSGustavo F. Padovan 
19540a708f8fSGustavo F. Padovan 	if (!conn)
19550a708f8fSGustavo F. Padovan 		return ERR_PTR(-ENOTCONN);
19560a708f8fSGustavo F. Padovan 
1957e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1958e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_EXT_HDR_SIZE;
1959e4ca6d98SAndrei Emeltchenko 	else
1960e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_ENH_HDR_SIZE;
1961e4ca6d98SAndrei Emeltchenko 
19620a708f8fSGustavo F. Padovan 	if (sdulen)
196303a51213SAndrei Emeltchenko 		hlen += L2CAP_SDULEN_SIZE;
19640a708f8fSGustavo F. Padovan 
196547d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
196603a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
19670a708f8fSGustavo F. Padovan 
19680a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
19692f7719ceSAndrei Emeltchenko 
19702f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
197190338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
197290338947SGustavo Padovan 	if (IS_ERR(skb))
197390338947SGustavo Padovan 		return skb;
19740a708f8fSGustavo F. Padovan 
19750a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
19760a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1977fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
19780a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
197988843ab0SAndrei Emeltchenko 
198094122bbeSMat Martineau 	__put_control(chan, 0, skb_put(skb, __ctrl_size(chan)));
198188843ab0SAndrei Emeltchenko 
19820a708f8fSGustavo F. Padovan 	if (sdulen)
198303a51213SAndrei Emeltchenko 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
19840a708f8fSGustavo F. Padovan 
19850952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
19860a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
19870a708f8fSGustavo F. Padovan 		kfree_skb(skb);
19880a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
19890a708f8fSGustavo F. Padovan 	}
19900a708f8fSGustavo F. Padovan 
199147d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
199203a51213SAndrei Emeltchenko 		put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
19930a708f8fSGustavo F. Padovan 
19943ce3514fSMat Martineau 	bt_cb(skb)->control.retries = 0;
19950a708f8fSGustavo F. Padovan 	return skb;
19960a708f8fSGustavo F. Padovan }
19970a708f8fSGustavo F. Padovan 
199894122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan,
199994122bbeSMat Martineau 			     struct sk_buff_head *seg_queue,
200094122bbeSMat Martineau 			     struct msghdr *msg, size_t len)
20010a708f8fSGustavo F. Padovan {
20020a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
200394122bbeSMat Martineau 	u16 sdu_len;
200494122bbeSMat Martineau 	size_t pdu_len;
200594122bbeSMat Martineau 	int err = 0;
200694122bbeSMat Martineau 	u8 sar;
20070a708f8fSGustavo F. Padovan 
200894122bbeSMat Martineau 	BT_DBG("chan %p, msg %p, len %d", chan, msg, (int)len);
20090a708f8fSGustavo F. Padovan 
201094122bbeSMat Martineau 	/* It is critical that ERTM PDUs fit in a single HCI fragment,
201194122bbeSMat Martineau 	 * so fragmented skbs are not used.  The HCI layer's handling
201294122bbeSMat Martineau 	 * of fragmented skbs is not compatible with ERTM's queueing.
201394122bbeSMat Martineau 	 */
201494122bbeSMat Martineau 
201594122bbeSMat Martineau 	/* PDU size is derived from the HCI MTU */
201694122bbeSMat Martineau 	pdu_len = chan->conn->mtu;
201794122bbeSMat Martineau 
201894122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
201994122bbeSMat Martineau 
202094122bbeSMat Martineau 	/* Adjust for largest possible L2CAP overhead. */
202194122bbeSMat Martineau 	pdu_len -= L2CAP_EXT_HDR_SIZE + L2CAP_FCS_SIZE;
202294122bbeSMat Martineau 
202394122bbeSMat Martineau 	/* Remote device may have requested smaller PDUs */
202494122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
202594122bbeSMat Martineau 
202694122bbeSMat Martineau 	if (len <= pdu_len) {
202794122bbeSMat Martineau 		sar = L2CAP_SAR_UNSEGMENTED;
202894122bbeSMat Martineau 		sdu_len = 0;
202994122bbeSMat Martineau 		pdu_len = len;
203094122bbeSMat Martineau 	} else {
203194122bbeSMat Martineau 		sar = L2CAP_SAR_START;
203294122bbeSMat Martineau 		sdu_len = len;
203394122bbeSMat Martineau 		pdu_len -= L2CAP_SDULEN_SIZE;
203494122bbeSMat Martineau 	}
20350a708f8fSGustavo F. Padovan 
20360a708f8fSGustavo F. Padovan 	while (len > 0) {
203794122bbeSMat Martineau 		skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
20380a708f8fSGustavo F. Padovan 
20390a708f8fSGustavo F. Padovan 		if (IS_ERR(skb)) {
204094122bbeSMat Martineau 			__skb_queue_purge(seg_queue);
20410a708f8fSGustavo F. Padovan 			return PTR_ERR(skb);
20420a708f8fSGustavo F. Padovan 		}
20430a708f8fSGustavo F. Padovan 
204494122bbeSMat Martineau 		bt_cb(skb)->control.sar = sar;
204594122bbeSMat Martineau 		__skb_queue_tail(seg_queue, skb);
20460a708f8fSGustavo F. Padovan 
204794122bbeSMat Martineau 		len -= pdu_len;
204894122bbeSMat Martineau 		if (sdu_len) {
204994122bbeSMat Martineau 			sdu_len = 0;
205094122bbeSMat Martineau 			pdu_len += L2CAP_SDULEN_SIZE;
205194122bbeSMat Martineau 		}
205294122bbeSMat Martineau 
205394122bbeSMat Martineau 		if (len <= pdu_len) {
205494122bbeSMat Martineau 			sar = L2CAP_SAR_END;
205594122bbeSMat Martineau 			pdu_len = len;
205694122bbeSMat Martineau 		} else {
205794122bbeSMat Martineau 			sar = L2CAP_SAR_CONTINUE;
205894122bbeSMat Martineau 		}
205994122bbeSMat Martineau 	}
206094122bbeSMat Martineau 
206194122bbeSMat Martineau 	return err;
20620a708f8fSGustavo F. Padovan }
20630a708f8fSGustavo F. Padovan 
20645e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
20655e59b791SLuiz Augusto von Dentz 								u32 priority)
20669a91a04aSGustavo F. Padovan {
20679a91a04aSGustavo F. Padovan 	struct sk_buff *skb;
20689a91a04aSGustavo F. Padovan 	int err;
206994122bbeSMat Martineau 	struct sk_buff_head seg_queue;
20709a91a04aSGustavo F. Padovan 
20719a91a04aSGustavo F. Padovan 	/* Connectionless channel */
2072715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
20735e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_connless_pdu(chan, msg, len, priority);
20749a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
20759a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
20769a91a04aSGustavo F. Padovan 
20779a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
20789a91a04aSGustavo F. Padovan 		return len;
20799a91a04aSGustavo F. Padovan 	}
20809a91a04aSGustavo F. Padovan 
20819a91a04aSGustavo F. Padovan 	switch (chan->mode) {
20829a91a04aSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
20839a91a04aSGustavo F. Padovan 		/* Check outgoing MTU */
20849a91a04aSGustavo F. Padovan 		if (len > chan->omtu)
20859a91a04aSGustavo F. Padovan 			return -EMSGSIZE;
20869a91a04aSGustavo F. Padovan 
20879a91a04aSGustavo F. Padovan 		/* Create a basic PDU */
20885e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_basic_pdu(chan, msg, len, priority);
20899a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
20909a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
20919a91a04aSGustavo F. Padovan 
20929a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
20939a91a04aSGustavo F. Padovan 		err = len;
20949a91a04aSGustavo F. Padovan 		break;
20959a91a04aSGustavo F. Padovan 
20969a91a04aSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
20979a91a04aSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
209894122bbeSMat Martineau 		/* Check outgoing MTU */
209994122bbeSMat Martineau 		if (len > chan->omtu) {
210094122bbeSMat Martineau 			err = -EMSGSIZE;
21019a91a04aSGustavo F. Padovan 			break;
21029a91a04aSGustavo F. Padovan 		}
21039a91a04aSGustavo F. Padovan 
210494122bbeSMat Martineau 		__skb_queue_head_init(&seg_queue);
210594122bbeSMat Martineau 
210694122bbeSMat Martineau 		/* Do segmentation before calling in to the state machine,
210794122bbeSMat Martineau 		 * since it's possible to block while waiting for memory
210894122bbeSMat Martineau 		 * allocation.
210994122bbeSMat Martineau 		 */
211094122bbeSMat Martineau 		err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
211194122bbeSMat Martineau 
211294122bbeSMat Martineau 		/* The channel could have been closed while segmenting,
211394122bbeSMat Martineau 		 * check that it is still connected.
211494122bbeSMat Martineau 		 */
211594122bbeSMat Martineau 		if (chan->state != BT_CONNECTED) {
211694122bbeSMat Martineau 			__skb_queue_purge(&seg_queue);
211794122bbeSMat Martineau 			err = -ENOTCONN;
21189a91a04aSGustavo F. Padovan 		}
21199a91a04aSGustavo F. Padovan 
212094122bbeSMat Martineau 		if (err)
212194122bbeSMat Martineau 			break;
212294122bbeSMat Martineau 
2123577cfaebSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM && chan->tx_send_head == NULL)
2124577cfaebSMat Martineau 			chan->tx_send_head = seg_queue.next;
212594122bbeSMat Martineau 		skb_queue_splice_tail_init(&seg_queue, &chan->tx_q);
2126577cfaebSMat Martineau 
212794122bbeSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM)
21289a91a04aSGustavo F. Padovan 			err = l2cap_ertm_send(chan);
212994122bbeSMat Martineau 		else
213094122bbeSMat Martineau 			l2cap_streaming_send(chan);
213194122bbeSMat Martineau 
21329a91a04aSGustavo F. Padovan 		if (err >= 0)
21339a91a04aSGustavo F. Padovan 			err = len;
21349a91a04aSGustavo F. Padovan 
213594122bbeSMat Martineau 		/* If the skbs were not queued for sending, they'll still be in
213694122bbeSMat Martineau 		 * seg_queue and need to be purged.
213794122bbeSMat Martineau 		 */
213894122bbeSMat Martineau 		__skb_queue_purge(&seg_queue);
21399a91a04aSGustavo F. Padovan 		break;
21409a91a04aSGustavo F. Padovan 
21419a91a04aSGustavo F. Padovan 	default:
21429a91a04aSGustavo F. Padovan 		BT_DBG("bad state %1.1x", chan->mode);
21439a91a04aSGustavo F. Padovan 		err = -EBADFD;
21449a91a04aSGustavo F. Padovan 	}
21459a91a04aSGustavo F. Padovan 
21469a91a04aSGustavo F. Padovan 	return err;
21479a91a04aSGustavo F. Padovan }
21489a91a04aSGustavo F. Padovan 
21490a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */
21500a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
21510a708f8fSGustavo F. Padovan {
21520a708f8fSGustavo F. Padovan 	struct sk_buff *nskb;
215348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
21540a708f8fSGustavo F. Padovan 
21550a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
21560a708f8fSGustavo F. Padovan 
21573df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
21583d57dc68SGustavo F. Padovan 
21593df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
216048454079SGustavo F. Padovan 		struct sock *sk = chan->sk;
2161715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_RAW)
21620a708f8fSGustavo F. Padovan 			continue;
21630a708f8fSGustavo F. Padovan 
21640a708f8fSGustavo F. Padovan 		/* Don't send frame to the socket it came from */
21650a708f8fSGustavo F. Padovan 		if (skb->sk == sk)
21660a708f8fSGustavo F. Padovan 			continue;
21670a708f8fSGustavo F. Padovan 		nskb = skb_clone(skb, GFP_ATOMIC);
21680a708f8fSGustavo F. Padovan 		if (!nskb)
21690a708f8fSGustavo F. Padovan 			continue;
21700a708f8fSGustavo F. Padovan 
217123070494SGustavo F. Padovan 		if (chan->ops->recv(chan->data, nskb))
21720a708f8fSGustavo F. Padovan 			kfree_skb(nskb);
21730a708f8fSGustavo F. Padovan 	}
21743d57dc68SGustavo F. Padovan 
21753df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
21760a708f8fSGustavo F. Padovan }
21770a708f8fSGustavo F. Padovan 
21780a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
21790a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
21800a708f8fSGustavo F. Padovan 				u8 code, u8 ident, u16 dlen, void *data)
21810a708f8fSGustavo F. Padovan {
21820a708f8fSGustavo F. Padovan 	struct sk_buff *skb, **frag;
21830a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr *cmd;
21840a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
21850a708f8fSGustavo F. Padovan 	int len, count;
21860a708f8fSGustavo F. Padovan 
21870a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
21880a708f8fSGustavo F. Padovan 			conn, code, ident, dlen);
21890a708f8fSGustavo F. Padovan 
21900a708f8fSGustavo F. Padovan 	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
21910a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, len);
21920a708f8fSGustavo F. Padovan 
21930a708f8fSGustavo F. Padovan 	skb = bt_skb_alloc(count, GFP_ATOMIC);
21940a708f8fSGustavo F. Padovan 	if (!skb)
21950a708f8fSGustavo F. Padovan 		return NULL;
21960a708f8fSGustavo F. Padovan 
21970a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
21980a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
21993300d9a9SClaudio Takahasi 
22003300d9a9SClaudio Takahasi 	if (conn->hcon->type == LE_LINK)
22013300d9a9SClaudio Takahasi 		lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
22023300d9a9SClaudio Takahasi 	else
22030a708f8fSGustavo F. Padovan 		lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
22040a708f8fSGustavo F. Padovan 
22050a708f8fSGustavo F. Padovan 	cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
22060a708f8fSGustavo F. Padovan 	cmd->code  = code;
22070a708f8fSGustavo F. Padovan 	cmd->ident = ident;
22080a708f8fSGustavo F. Padovan 	cmd->len   = cpu_to_le16(dlen);
22090a708f8fSGustavo F. Padovan 
22100a708f8fSGustavo F. Padovan 	if (dlen) {
22110a708f8fSGustavo F. Padovan 		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
22120a708f8fSGustavo F. Padovan 		memcpy(skb_put(skb, count), data, count);
22130a708f8fSGustavo F. Padovan 		data += count;
22140a708f8fSGustavo F. Padovan 	}
22150a708f8fSGustavo F. Padovan 
22160a708f8fSGustavo F. Padovan 	len -= skb->len;
22170a708f8fSGustavo F. Padovan 
22180a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
22190a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
22200a708f8fSGustavo F. Padovan 	while (len) {
22210a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
22220a708f8fSGustavo F. Padovan 
22230a708f8fSGustavo F. Padovan 		*frag = bt_skb_alloc(count, GFP_ATOMIC);
22240a708f8fSGustavo F. Padovan 		if (!*frag)
22250a708f8fSGustavo F. Padovan 			goto fail;
22260a708f8fSGustavo F. Padovan 
22270a708f8fSGustavo F. Padovan 		memcpy(skb_put(*frag, count), data, count);
22280a708f8fSGustavo F. Padovan 
22290a708f8fSGustavo F. Padovan 		len  -= count;
22300a708f8fSGustavo F. Padovan 		data += count;
22310a708f8fSGustavo F. Padovan 
22320a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
22330a708f8fSGustavo F. Padovan 	}
22340a708f8fSGustavo F. Padovan 
22350a708f8fSGustavo F. Padovan 	return skb;
22360a708f8fSGustavo F. Padovan 
22370a708f8fSGustavo F. Padovan fail:
22380a708f8fSGustavo F. Padovan 	kfree_skb(skb);
22390a708f8fSGustavo F. Padovan 	return NULL;
22400a708f8fSGustavo F. Padovan }
22410a708f8fSGustavo F. Padovan 
22420a708f8fSGustavo F. Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
22430a708f8fSGustavo F. Padovan {
22440a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
22450a708f8fSGustavo F. Padovan 	int len;
22460a708f8fSGustavo F. Padovan 
22470a708f8fSGustavo F. Padovan 	len = L2CAP_CONF_OPT_SIZE + opt->len;
22480a708f8fSGustavo F. Padovan 	*ptr += len;
22490a708f8fSGustavo F. Padovan 
22500a708f8fSGustavo F. Padovan 	*type = opt->type;
22510a708f8fSGustavo F. Padovan 	*olen = opt->len;
22520a708f8fSGustavo F. Padovan 
22530a708f8fSGustavo F. Padovan 	switch (opt->len) {
22540a708f8fSGustavo F. Padovan 	case 1:
22550a708f8fSGustavo F. Padovan 		*val = *((u8 *) opt->val);
22560a708f8fSGustavo F. Padovan 		break;
22570a708f8fSGustavo F. Padovan 
22580a708f8fSGustavo F. Padovan 	case 2:
22590a708f8fSGustavo F. Padovan 		*val = get_unaligned_le16(opt->val);
22600a708f8fSGustavo F. Padovan 		break;
22610a708f8fSGustavo F. Padovan 
22620a708f8fSGustavo F. Padovan 	case 4:
22630a708f8fSGustavo F. Padovan 		*val = get_unaligned_le32(opt->val);
22640a708f8fSGustavo F. Padovan 		break;
22650a708f8fSGustavo F. Padovan 
22660a708f8fSGustavo F. Padovan 	default:
22670a708f8fSGustavo F. Padovan 		*val = (unsigned long) opt->val;
22680a708f8fSGustavo F. Padovan 		break;
22690a708f8fSGustavo F. Padovan 	}
22700a708f8fSGustavo F. Padovan 
22710a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
22720a708f8fSGustavo F. Padovan 	return len;
22730a708f8fSGustavo F. Padovan }
22740a708f8fSGustavo F. Padovan 
22750a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
22760a708f8fSGustavo F. Padovan {
22770a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
22780a708f8fSGustavo F. Padovan 
22790a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
22800a708f8fSGustavo F. Padovan 
22810a708f8fSGustavo F. Padovan 	opt->type = type;
22820a708f8fSGustavo F. Padovan 	opt->len  = len;
22830a708f8fSGustavo F. Padovan 
22840a708f8fSGustavo F. Padovan 	switch (len) {
22850a708f8fSGustavo F. Padovan 	case 1:
22860a708f8fSGustavo F. Padovan 		*((u8 *) opt->val)  = val;
22870a708f8fSGustavo F. Padovan 		break;
22880a708f8fSGustavo F. Padovan 
22890a708f8fSGustavo F. Padovan 	case 2:
22900a708f8fSGustavo F. Padovan 		put_unaligned_le16(val, opt->val);
22910a708f8fSGustavo F. Padovan 		break;
22920a708f8fSGustavo F. Padovan 
22930a708f8fSGustavo F. Padovan 	case 4:
22940a708f8fSGustavo F. Padovan 		put_unaligned_le32(val, opt->val);
22950a708f8fSGustavo F. Padovan 		break;
22960a708f8fSGustavo F. Padovan 
22970a708f8fSGustavo F. Padovan 	default:
22980a708f8fSGustavo F. Padovan 		memcpy(opt->val, (void *) val, len);
22990a708f8fSGustavo F. Padovan 		break;
23000a708f8fSGustavo F. Padovan 	}
23010a708f8fSGustavo F. Padovan 
23020a708f8fSGustavo F. Padovan 	*ptr += L2CAP_CONF_OPT_SIZE + len;
23030a708f8fSGustavo F. Padovan }
23040a708f8fSGustavo F. Padovan 
2305f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
2306f89cef09SAndrei Emeltchenko {
2307f89cef09SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
2308f89cef09SAndrei Emeltchenko 
2309f89cef09SAndrei Emeltchenko 	switch (chan->mode) {
2310f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_ERTM:
2311f89cef09SAndrei Emeltchenko 		efs.id		= chan->local_id;
2312f89cef09SAndrei Emeltchenko 		efs.stype	= chan->local_stype;
2313f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
2314f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
2315f89cef09SAndrei Emeltchenko 		efs.acc_lat	= cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
2316f89cef09SAndrei Emeltchenko 		efs.flush_to	= cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
2317f89cef09SAndrei Emeltchenko 		break;
2318f89cef09SAndrei Emeltchenko 
2319f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_STREAMING:
2320f89cef09SAndrei Emeltchenko 		efs.id		= 1;
2321f89cef09SAndrei Emeltchenko 		efs.stype	= L2CAP_SERV_BESTEFFORT;
2322f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
2323f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
2324f89cef09SAndrei Emeltchenko 		efs.acc_lat	= 0;
2325f89cef09SAndrei Emeltchenko 		efs.flush_to	= 0;
2326f89cef09SAndrei Emeltchenko 		break;
2327f89cef09SAndrei Emeltchenko 
2328f89cef09SAndrei Emeltchenko 	default:
2329f89cef09SAndrei Emeltchenko 		return;
2330f89cef09SAndrei Emeltchenko 	}
2331f89cef09SAndrei Emeltchenko 
2332f89cef09SAndrei Emeltchenko 	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
2333f89cef09SAndrei Emeltchenko 							(unsigned long) &efs);
2334f89cef09SAndrei Emeltchenko }
2335f89cef09SAndrei Emeltchenko 
2336721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
23370a708f8fSGustavo F. Padovan {
2338721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2339721c4181SGustavo F. Padovan 							ack_timer.work);
23400a708f8fSGustavo F. Padovan 
23412fb9b3d4SGustavo F. Padovan 	BT_DBG("chan %p", chan);
23422fb9b3d4SGustavo F. Padovan 
23436be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
23446be36555SAndrei Emeltchenko 
2345b17e73bbSSzymon Janc 	__l2cap_send_ack(chan);
23466be36555SAndrei Emeltchenko 
23476be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
234809bfb2eeSSzymon Janc 
234909bfb2eeSSzymon Janc 	l2cap_chan_put(chan);
23500a708f8fSGustavo F. Padovan }
23510a708f8fSGustavo F. Padovan 
23523c588192SMat Martineau static inline int l2cap_ertm_init(struct l2cap_chan *chan)
23530a708f8fSGustavo F. Padovan {
23543c588192SMat Martineau 	int err;
23553c588192SMat Martineau 
2356105bdf9eSMat Martineau 	chan->next_tx_seq = 0;
2357105bdf9eSMat Martineau 	chan->expected_tx_seq = 0;
235842e5c802SGustavo F. Padovan 	chan->expected_ack_seq = 0;
23596a026610SGustavo F. Padovan 	chan->unacked_frames = 0;
236042e5c802SGustavo F. Padovan 	chan->buffer_seq = 0;
23616a026610SGustavo F. Padovan 	chan->num_acked = 0;
23626a026610SGustavo F. Padovan 	chan->frames_sent = 0;
2363105bdf9eSMat Martineau 	chan->last_acked_seq = 0;
2364105bdf9eSMat Martineau 	chan->sdu = NULL;
2365105bdf9eSMat Martineau 	chan->sdu_last_frag = NULL;
2366105bdf9eSMat Martineau 	chan->sdu_len = 0;
2367105bdf9eSMat Martineau 
2368d34c34fbSMat Martineau 	skb_queue_head_init(&chan->tx_q);
2369d34c34fbSMat Martineau 
2370105bdf9eSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
2371105bdf9eSMat Martineau 		return 0;
2372105bdf9eSMat Martineau 
2373105bdf9eSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2374105bdf9eSMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
23750a708f8fSGustavo F. Padovan 
2376721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
2377721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
2378721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
23790a708f8fSGustavo F. Padovan 
2380f1c6775bSGustavo F. Padovan 	skb_queue_head_init(&chan->srej_q);
23810a708f8fSGustavo F. Padovan 
238239d5a3eeSGustavo F. Padovan 	INIT_LIST_HEAD(&chan->srej_l);
23833c588192SMat Martineau 	err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
23843c588192SMat Martineau 	if (err < 0)
23853c588192SMat Martineau 		return err;
23863c588192SMat Martineau 
23879dc9affcSMat Martineau 	err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
23889dc9affcSMat Martineau 	if (err < 0)
23899dc9affcSMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
23909dc9affcSMat Martineau 
23919dc9affcSMat Martineau 	return err;
23920a708f8fSGustavo F. Padovan }
23930a708f8fSGustavo F. Padovan 
23940a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
23950a708f8fSGustavo F. Padovan {
23960a708f8fSGustavo F. Padovan 	switch (mode) {
23970a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
23980a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
23990a708f8fSGustavo F. Padovan 		if (l2cap_mode_supported(mode, remote_feat_mask))
24000a708f8fSGustavo F. Padovan 			return mode;
24010a708f8fSGustavo F. Padovan 		/* fall through */
24020a708f8fSGustavo F. Padovan 	default:
24030a708f8fSGustavo F. Padovan 		return L2CAP_MODE_BASIC;
24040a708f8fSGustavo F. Padovan 	}
24050a708f8fSGustavo F. Padovan }
24060a708f8fSGustavo F. Padovan 
24076327eb98SAndrei Emeltchenko static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
24086327eb98SAndrei Emeltchenko {
24096327eb98SAndrei Emeltchenko 	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
24106327eb98SAndrei Emeltchenko }
24116327eb98SAndrei Emeltchenko 
2412f89cef09SAndrei Emeltchenko static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2413f89cef09SAndrei Emeltchenko {
2414f89cef09SAndrei Emeltchenko 	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2415f89cef09SAndrei Emeltchenko }
2416f89cef09SAndrei Emeltchenko 
24176327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
24186327eb98SAndrei Emeltchenko {
24196327eb98SAndrei Emeltchenko 	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
2420836be934SAndrei Emeltchenko 						__l2cap_ews_supported(chan)) {
24216327eb98SAndrei Emeltchenko 		/* use extended control field */
24226327eb98SAndrei Emeltchenko 		set_bit(FLAG_EXT_CTRL, &chan->flags);
2423836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2424836be934SAndrei Emeltchenko 	} else {
24256327eb98SAndrei Emeltchenko 		chan->tx_win = min_t(u16, chan->tx_win,
24266327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_TX_WINDOW);
2427836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2428836be934SAndrei Emeltchenko 	}
24296327eb98SAndrei Emeltchenko }
24306327eb98SAndrei Emeltchenko 
2431710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
24320a708f8fSGustavo F. Padovan {
24330a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
24340c1bc5c6SGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
24350a708f8fSGustavo F. Padovan 	void *ptr = req->data;
2436c8f79162SAndrei Emeltchenko 	u16 size;
24370a708f8fSGustavo F. Padovan 
243849208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
24390a708f8fSGustavo F. Padovan 
244073ffa904SGustavo F. Padovan 	if (chan->num_conf_req || chan->num_conf_rsp)
24410a708f8fSGustavo F. Padovan 		goto done;
24420a708f8fSGustavo F. Padovan 
24430c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
24440a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
24450a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
2446c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
24470a708f8fSGustavo F. Padovan 			break;
24480a708f8fSGustavo F. Padovan 
2449f89cef09SAndrei Emeltchenko 		if (__l2cap_efs_supported(chan))
2450f89cef09SAndrei Emeltchenko 			set_bit(FLAG_EFS_ENABLE, &chan->flags);
2451f89cef09SAndrei Emeltchenko 
24520a708f8fSGustavo F. Padovan 		/* fall through */
24530a708f8fSGustavo F. Padovan 	default:
24548c1d787bSGustavo F. Padovan 		chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
24550a708f8fSGustavo F. Padovan 		break;
24560a708f8fSGustavo F. Padovan 	}
24570a708f8fSGustavo F. Padovan 
24580a708f8fSGustavo F. Padovan done:
24590c1bc5c6SGustavo F. Padovan 	if (chan->imtu != L2CAP_DEFAULT_MTU)
24600c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
24610a708f8fSGustavo F. Padovan 
24620c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
24630a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
24648c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
24658c1d787bSGustavo F. Padovan 				!(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
24660a708f8fSGustavo F. Padovan 			break;
24670a708f8fSGustavo F. Padovan 
24680a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_BASIC;
24690a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
24700a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
24710a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
24720a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
24730a708f8fSGustavo F. Padovan 		rfc.max_pdu_size    = 0;
24740a708f8fSGustavo F. Padovan 
24750a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
24760a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
24770a708f8fSGustavo F. Padovan 		break;
24780a708f8fSGustavo F. Padovan 
24790a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
24800a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_ERTM;
248147d1ec61SGustavo F. Padovan 		rfc.max_transmit    = chan->max_tx;
24820a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
24830a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
2484c8f79162SAndrei Emeltchenko 
2485c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2486c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2487c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2488c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2489c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
24900a708f8fSGustavo F. Padovan 
24916327eb98SAndrei Emeltchenko 		l2cap_txwin_setup(chan);
24926327eb98SAndrei Emeltchenko 
24936327eb98SAndrei Emeltchenko 		rfc.txwin_size = min_t(u16, chan->tx_win,
24946327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_TX_WINDOW);
24950a708f8fSGustavo F. Padovan 
24960a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
24970a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
24980a708f8fSGustavo F. Padovan 
2499f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2500f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
2501f89cef09SAndrei Emeltchenko 
25028c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
25030a708f8fSGustavo F. Padovan 			break;
25040a708f8fSGustavo F. Padovan 
250547d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_NONE ||
2506c1360a1cSGustavo F. Padovan 				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
250747d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
250847d1ec61SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
25090a708f8fSGustavo F. Padovan 		}
25106327eb98SAndrei Emeltchenko 
25116327eb98SAndrei Emeltchenko 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
25126327eb98SAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
25136327eb98SAndrei Emeltchenko 								chan->tx_win);
25140a708f8fSGustavo F. Padovan 		break;
25150a708f8fSGustavo F. Padovan 
25160a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
25170a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_STREAMING;
25180a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
25190a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
25200a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
25210a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
2522c8f79162SAndrei Emeltchenko 
2523c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2524c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2525c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2526c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2527c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
25280a708f8fSGustavo F. Padovan 
25290a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
25300a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
25310a708f8fSGustavo F. Padovan 
2532f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2533f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
2534f89cef09SAndrei Emeltchenko 
25358c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
25360a708f8fSGustavo F. Padovan 			break;
25370a708f8fSGustavo F. Padovan 
253847d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_NONE ||
2539c1360a1cSGustavo F. Padovan 				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
254047d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
254147d1ec61SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
25420a708f8fSGustavo F. Padovan 		}
25430a708f8fSGustavo F. Padovan 		break;
25440a708f8fSGustavo F. Padovan 	}
25450a708f8fSGustavo F. Padovan 
2546fe4128e0SGustavo F. Padovan 	req->dcid  = cpu_to_le16(chan->dcid);
25470a708f8fSGustavo F. Padovan 	req->flags = cpu_to_le16(0);
25480a708f8fSGustavo F. Padovan 
25490a708f8fSGustavo F. Padovan 	return ptr - data;
25500a708f8fSGustavo F. Padovan }
25510a708f8fSGustavo F. Padovan 
255273ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
25530a708f8fSGustavo F. Padovan {
25540a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
25550a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
255673ffa904SGustavo F. Padovan 	void *req = chan->conf_req;
255773ffa904SGustavo F. Padovan 	int len = chan->conf_len;
25580a708f8fSGustavo F. Padovan 	int type, hint, olen;
25590a708f8fSGustavo F. Padovan 	unsigned long val;
25600a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
256142dceae2SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
256242dceae2SAndrei Emeltchenko 	u8 remote_efs = 0;
25630a708f8fSGustavo F. Padovan 	u16 mtu = L2CAP_DEFAULT_MTU;
25640a708f8fSGustavo F. Padovan 	u16 result = L2CAP_CONF_SUCCESS;
2565c8f79162SAndrei Emeltchenko 	u16 size;
25660a708f8fSGustavo F. Padovan 
256773ffa904SGustavo F. Padovan 	BT_DBG("chan %p", chan);
25680a708f8fSGustavo F. Padovan 
25690a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
25700a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
25710a708f8fSGustavo F. Padovan 
25720a708f8fSGustavo F. Padovan 		hint  = type & L2CAP_CONF_HINT;
25730a708f8fSGustavo F. Padovan 		type &= L2CAP_CONF_MASK;
25740a708f8fSGustavo F. Padovan 
25750a708f8fSGustavo F. Padovan 		switch (type) {
25760a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
25770a708f8fSGustavo F. Padovan 			mtu = val;
25780a708f8fSGustavo F. Padovan 			break;
25790a708f8fSGustavo F. Padovan 
25800a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
25810c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
25820a708f8fSGustavo F. Padovan 			break;
25830a708f8fSGustavo F. Padovan 
25840a708f8fSGustavo F. Padovan 		case L2CAP_CONF_QOS:
25850a708f8fSGustavo F. Padovan 			break;
25860a708f8fSGustavo F. Padovan 
25870a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
25880a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
25890a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *) val, olen);
25900a708f8fSGustavo F. Padovan 			break;
25910a708f8fSGustavo F. Padovan 
25920a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FCS:
25930a708f8fSGustavo F. Padovan 			if (val == L2CAP_FCS_NONE)
2594c1360a1cSGustavo F. Padovan 				set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
259542dceae2SAndrei Emeltchenko 			break;
25960a708f8fSGustavo F. Padovan 
259742dceae2SAndrei Emeltchenko 		case L2CAP_CONF_EFS:
259842dceae2SAndrei Emeltchenko 			remote_efs = 1;
259942dceae2SAndrei Emeltchenko 			if (olen == sizeof(efs))
260042dceae2SAndrei Emeltchenko 				memcpy(&efs, (void *) val, olen);
26010a708f8fSGustavo F. Padovan 			break;
26020a708f8fSGustavo F. Padovan 
26036327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
26046327eb98SAndrei Emeltchenko 			if (!enable_hs)
26056327eb98SAndrei Emeltchenko 				return -ECONNREFUSED;
26066327eb98SAndrei Emeltchenko 
26076327eb98SAndrei Emeltchenko 			set_bit(FLAG_EXT_CTRL, &chan->flags);
26086327eb98SAndrei Emeltchenko 			set_bit(CONF_EWS_RECV, &chan->conf_state);
2609836be934SAndrei Emeltchenko 			chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
26106327eb98SAndrei Emeltchenko 			chan->remote_tx_win = val;
26110a708f8fSGustavo F. Padovan 			break;
26120a708f8fSGustavo F. Padovan 
26130a708f8fSGustavo F. Padovan 		default:
26140a708f8fSGustavo F. Padovan 			if (hint)
26150a708f8fSGustavo F. Padovan 				break;
26160a708f8fSGustavo F. Padovan 
26170a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNKNOWN;
26180a708f8fSGustavo F. Padovan 			*((u8 *) ptr++) = type;
26190a708f8fSGustavo F. Padovan 			break;
26200a708f8fSGustavo F. Padovan 		}
26210a708f8fSGustavo F. Padovan 	}
26220a708f8fSGustavo F. Padovan 
262373ffa904SGustavo F. Padovan 	if (chan->num_conf_rsp || chan->num_conf_req > 1)
26240a708f8fSGustavo F. Padovan 		goto done;
26250a708f8fSGustavo F. Padovan 
26260c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
26270a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
26280a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
2629c1360a1cSGustavo F. Padovan 		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
26300c1bc5c6SGustavo F. Padovan 			chan->mode = l2cap_select_mode(rfc.mode,
26318c1d787bSGustavo F. Padovan 					chan->conn->feat_mask);
26320a708f8fSGustavo F. Padovan 			break;
26330a708f8fSGustavo F. Padovan 		}
26340a708f8fSGustavo F. Padovan 
263542dceae2SAndrei Emeltchenko 		if (remote_efs) {
263642dceae2SAndrei Emeltchenko 			if (__l2cap_efs_supported(chan))
263742dceae2SAndrei Emeltchenko 				set_bit(FLAG_EFS_ENABLE, &chan->flags);
263842dceae2SAndrei Emeltchenko 			else
263942dceae2SAndrei Emeltchenko 				return -ECONNREFUSED;
264042dceae2SAndrei Emeltchenko 		}
264142dceae2SAndrei Emeltchenko 
26420c1bc5c6SGustavo F. Padovan 		if (chan->mode != rfc.mode)
26430a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
26440a708f8fSGustavo F. Padovan 
26450a708f8fSGustavo F. Padovan 		break;
26460a708f8fSGustavo F. Padovan 	}
26470a708f8fSGustavo F. Padovan 
26480a708f8fSGustavo F. Padovan done:
26490c1bc5c6SGustavo F. Padovan 	if (chan->mode != rfc.mode) {
26500a708f8fSGustavo F. Padovan 		result = L2CAP_CONF_UNACCEPT;
26510c1bc5c6SGustavo F. Padovan 		rfc.mode = chan->mode;
26520a708f8fSGustavo F. Padovan 
265373ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp == 1)
26540a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
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 
26600a708f8fSGustavo F. Padovan 	if (result == L2CAP_CONF_SUCCESS) {
26610a708f8fSGustavo F. Padovan 		/* Configure output options and let the other side know
26620a708f8fSGustavo F. Padovan 		 * which ones we don't like. */
26630a708f8fSGustavo F. Padovan 
26640a708f8fSGustavo F. Padovan 		if (mtu < L2CAP_DEFAULT_MIN_MTU)
26650a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
26660a708f8fSGustavo F. Padovan 		else {
26670c1bc5c6SGustavo F. Padovan 			chan->omtu = mtu;
2668c1360a1cSGustavo F. Padovan 			set_bit(CONF_MTU_DONE, &chan->conf_state);
26690a708f8fSGustavo F. Padovan 		}
26700c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
26710a708f8fSGustavo F. Padovan 
267242dceae2SAndrei Emeltchenko 		if (remote_efs) {
267342dceae2SAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
267442dceae2SAndrei Emeltchenko 					efs.stype != L2CAP_SERV_NOTRAFIC &&
267542dceae2SAndrei Emeltchenko 					efs.stype != chan->local_stype) {
267642dceae2SAndrei Emeltchenko 
267742dceae2SAndrei Emeltchenko 				result = L2CAP_CONF_UNACCEPT;
267842dceae2SAndrei Emeltchenko 
267942dceae2SAndrei Emeltchenko 				if (chan->num_conf_req >= 1)
268042dceae2SAndrei Emeltchenko 					return -ECONNREFUSED;
268142dceae2SAndrei Emeltchenko 
268242dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
268342dceae2SAndrei Emeltchenko 							sizeof(efs),
268442dceae2SAndrei Emeltchenko 							(unsigned long) &efs);
26850e8b207eSAndrei Emeltchenko 			} else {
26863e6b3b95SGustavo F. Padovan 				/* Send PENDING Conf Rsp */
26870e8b207eSAndrei Emeltchenko 				result = L2CAP_CONF_PENDING;
26880e8b207eSAndrei Emeltchenko 				set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
268942dceae2SAndrei Emeltchenko 			}
269042dceae2SAndrei Emeltchenko 		}
269142dceae2SAndrei Emeltchenko 
26920a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
26930a708f8fSGustavo F. Padovan 		case L2CAP_MODE_BASIC:
269447d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
2695c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
26960a708f8fSGustavo F. Padovan 			break;
26970a708f8fSGustavo F. Padovan 
26980a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
26996327eb98SAndrei Emeltchenko 			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
27002c03a7a4SGustavo F. Padovan 				chan->remote_tx_win = rfc.txwin_size;
27016327eb98SAndrei Emeltchenko 			else
27026327eb98SAndrei Emeltchenko 				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
27036327eb98SAndrei Emeltchenko 
27042c03a7a4SGustavo F. Padovan 			chan->remote_max_tx = rfc.max_transmit;
27050a708f8fSGustavo F. Padovan 
2706c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2707c8f79162SAndrei Emeltchenko 						chan->conn->mtu -
2708c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2709c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2710c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2711c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
2712c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
27130a708f8fSGustavo F. Padovan 
27140a708f8fSGustavo F. Padovan 			rfc.retrans_timeout =
27154fd21a88SAndrei Emeltchenko 				__constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
27160a708f8fSGustavo F. Padovan 			rfc.monitor_timeout =
27174fd21a88SAndrei Emeltchenko 				__constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
27180a708f8fSGustavo F. Padovan 
2719c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
27200a708f8fSGustavo F. Padovan 
27210a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
27220a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
27230a708f8fSGustavo F. Padovan 
272442dceae2SAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
272542dceae2SAndrei Emeltchenko 				chan->remote_id = efs.id;
272642dceae2SAndrei Emeltchenko 				chan->remote_stype = efs.stype;
272742dceae2SAndrei Emeltchenko 				chan->remote_msdu = le16_to_cpu(efs.msdu);
272842dceae2SAndrei Emeltchenko 				chan->remote_flush_to =
272942dceae2SAndrei Emeltchenko 						le32_to_cpu(efs.flush_to);
273042dceae2SAndrei Emeltchenko 				chan->remote_acc_lat =
273142dceae2SAndrei Emeltchenko 						le32_to_cpu(efs.acc_lat);
273242dceae2SAndrei Emeltchenko 				chan->remote_sdu_itime =
273342dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
273442dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
273542dceae2SAndrei Emeltchenko 					sizeof(efs), (unsigned long) &efs);
273642dceae2SAndrei Emeltchenko 			}
27370a708f8fSGustavo F. Padovan 			break;
27380a708f8fSGustavo F. Padovan 
27390a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
2740c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2741c8f79162SAndrei Emeltchenko 						chan->conn->mtu -
2742c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2743c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2744c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2745c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
2746c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
27470a708f8fSGustavo F. Padovan 
2748c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
27490a708f8fSGustavo F. Padovan 
27500a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
27510a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
27520a708f8fSGustavo F. Padovan 
27530a708f8fSGustavo F. Padovan 			break;
27540a708f8fSGustavo F. Padovan 
27550a708f8fSGustavo F. Padovan 		default:
27560a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
27570a708f8fSGustavo F. Padovan 
27580a708f8fSGustavo F. Padovan 			memset(&rfc, 0, sizeof(rfc));
27590c1bc5c6SGustavo F. Padovan 			rfc.mode = chan->mode;
27600a708f8fSGustavo F. Padovan 		}
27610a708f8fSGustavo F. Padovan 
27620a708f8fSGustavo F. Padovan 		if (result == L2CAP_CONF_SUCCESS)
2763c1360a1cSGustavo F. Padovan 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
27640a708f8fSGustavo F. Padovan 	}
2765fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
27660a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
27670a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(0x0000);
27680a708f8fSGustavo F. Padovan 
27690a708f8fSGustavo F. Padovan 	return ptr - data;
27700a708f8fSGustavo F. Padovan }
27710a708f8fSGustavo F. Padovan 
2772b4450035SGustavo F. Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result)
27730a708f8fSGustavo F. Padovan {
27740a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
27750a708f8fSGustavo F. Padovan 	void *ptr = req->data;
27760a708f8fSGustavo F. Padovan 	int type, olen;
27770a708f8fSGustavo F. Padovan 	unsigned long val;
277836e999a8SMat Martineau 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
277966af7aafSAndrei Emeltchenko 	struct l2cap_conf_efs efs;
27800a708f8fSGustavo F. Padovan 
2781fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
27820a708f8fSGustavo F. Padovan 
27830a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
27840a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
27850a708f8fSGustavo F. Padovan 
27860a708f8fSGustavo F. Padovan 		switch (type) {
27870a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
27880a708f8fSGustavo F. Padovan 			if (val < L2CAP_DEFAULT_MIN_MTU) {
27890a708f8fSGustavo F. Padovan 				*result = L2CAP_CONF_UNACCEPT;
27900c1bc5c6SGustavo F. Padovan 				chan->imtu = L2CAP_DEFAULT_MIN_MTU;
27910a708f8fSGustavo F. Padovan 			} else
27920c1bc5c6SGustavo F. Padovan 				chan->imtu = val;
27930c1bc5c6SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
27940a708f8fSGustavo F. Padovan 			break;
27950a708f8fSGustavo F. Padovan 
27960a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
27970c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
27980a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
27990c1bc5c6SGustavo F. Padovan 							2, chan->flush_to);
28000a708f8fSGustavo F. Padovan 			break;
28010a708f8fSGustavo F. Padovan 
28020a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
28030a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
28040a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
28050a708f8fSGustavo F. Padovan 
2806c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
28070c1bc5c6SGustavo F. Padovan 							rfc.mode != chan->mode)
28080a708f8fSGustavo F. Padovan 				return -ECONNREFUSED;
28090a708f8fSGustavo F. Padovan 
281047d1ec61SGustavo F. Padovan 			chan->fcs = 0;
28110a708f8fSGustavo F. Padovan 
28120a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
28130a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
28140a708f8fSGustavo F. Padovan 			break;
28156327eb98SAndrei Emeltchenko 
28166327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
28176327eb98SAndrei Emeltchenko 			chan->tx_win = min_t(u16, val,
28186327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_EXT_WINDOW);
28193e6b3b95SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
28203e6b3b95SGustavo F. Padovan 							chan->tx_win);
28216327eb98SAndrei Emeltchenko 			break;
282266af7aafSAndrei Emeltchenko 
282366af7aafSAndrei Emeltchenko 		case L2CAP_CONF_EFS:
282466af7aafSAndrei Emeltchenko 			if (olen == sizeof(efs))
282566af7aafSAndrei Emeltchenko 				memcpy(&efs, (void *)val, olen);
282666af7aafSAndrei Emeltchenko 
282766af7aafSAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
282866af7aafSAndrei Emeltchenko 					efs.stype != L2CAP_SERV_NOTRAFIC &&
282966af7aafSAndrei Emeltchenko 					efs.stype != chan->local_stype)
283066af7aafSAndrei Emeltchenko 				return -ECONNREFUSED;
283166af7aafSAndrei Emeltchenko 
283266af7aafSAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
283366af7aafSAndrei Emeltchenko 					sizeof(efs), (unsigned long) &efs);
283466af7aafSAndrei Emeltchenko 			break;
28350a708f8fSGustavo F. Padovan 		}
28360a708f8fSGustavo F. Padovan 	}
28370a708f8fSGustavo F. Padovan 
28380c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
28390a708f8fSGustavo F. Padovan 		return -ECONNREFUSED;
28400a708f8fSGustavo F. Padovan 
28410c1bc5c6SGustavo F. Padovan 	chan->mode = rfc.mode;
28420a708f8fSGustavo F. Padovan 
28430e8b207eSAndrei Emeltchenko 	if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
28440a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
28450a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
284647d1ec61SGustavo F. Padovan 			chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
284747d1ec61SGustavo F. Padovan 			chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
284847d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
284966af7aafSAndrei Emeltchenko 
285066af7aafSAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
285166af7aafSAndrei Emeltchenko 				chan->local_msdu = le16_to_cpu(efs.msdu);
285266af7aafSAndrei Emeltchenko 				chan->local_sdu_itime =
285366af7aafSAndrei Emeltchenko 						le32_to_cpu(efs.sdu_itime);
285466af7aafSAndrei Emeltchenko 				chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
285566af7aafSAndrei Emeltchenko 				chan->local_flush_to =
285666af7aafSAndrei Emeltchenko 						le32_to_cpu(efs.flush_to);
285766af7aafSAndrei Emeltchenko 			}
28580a708f8fSGustavo F. Padovan 			break;
285966af7aafSAndrei Emeltchenko 
28600a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
286147d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
28620a708f8fSGustavo F. Padovan 		}
28630a708f8fSGustavo F. Padovan 	}
28640a708f8fSGustavo F. Padovan 
2865fe4128e0SGustavo F. Padovan 	req->dcid   = cpu_to_le16(chan->dcid);
28660a708f8fSGustavo F. Padovan 	req->flags  = cpu_to_le16(0x0000);
28670a708f8fSGustavo F. Padovan 
28680a708f8fSGustavo F. Padovan 	return ptr - data;
28690a708f8fSGustavo F. Padovan }
28700a708f8fSGustavo F. Padovan 
2871fe4128e0SGustavo F. Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
28720a708f8fSGustavo F. Padovan {
28730a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
28740a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
28750a708f8fSGustavo F. Padovan 
2876fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p", chan);
28770a708f8fSGustavo F. Padovan 
2878fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
28790a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
28800a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(flags);
28810a708f8fSGustavo F. Padovan 
28820a708f8fSGustavo F. Padovan 	return ptr - data;
28830a708f8fSGustavo F. Padovan }
28840a708f8fSGustavo F. Padovan 
28858c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
2886710f9b0aSGustavo F. Padovan {
2887710f9b0aSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
28888c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
2889710f9b0aSGustavo F. Padovan 	u8 buf[128];
2890710f9b0aSGustavo F. Padovan 
2891fe4128e0SGustavo F. Padovan 	rsp.scid   = cpu_to_le16(chan->dcid);
2892fe4128e0SGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(chan->scid);
2893710f9b0aSGustavo F. Padovan 	rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2894710f9b0aSGustavo F. Padovan 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2895710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, chan->ident,
2896710f9b0aSGustavo F. Padovan 				L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2897710f9b0aSGustavo F. Padovan 
2898c1360a1cSGustavo F. Padovan 	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
2899710f9b0aSGustavo F. Padovan 		return;
2900710f9b0aSGustavo F. Padovan 
2901710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2902710f9b0aSGustavo F. Padovan 			l2cap_build_conf_req(chan, buf), buf);
2903710f9b0aSGustavo F. Padovan 	chan->num_conf_req++;
2904710f9b0aSGustavo F. Padovan }
2905710f9b0aSGustavo F. Padovan 
290647d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
29070a708f8fSGustavo F. Padovan {
29080a708f8fSGustavo F. Padovan 	int type, olen;
29090a708f8fSGustavo F. Padovan 	unsigned long val;
29100a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc;
29110a708f8fSGustavo F. Padovan 
291247d1ec61SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
29130a708f8fSGustavo F. Padovan 
29140c1bc5c6SGustavo F. Padovan 	if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
29150a708f8fSGustavo F. Padovan 		return;
29160a708f8fSGustavo F. Padovan 
29170a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
29180a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
29190a708f8fSGustavo F. Padovan 
29200a708f8fSGustavo F. Padovan 		switch (type) {
29210a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
29220a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
29230a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
29240a708f8fSGustavo F. Padovan 			goto done;
29250a708f8fSGustavo F. Padovan 		}
29260a708f8fSGustavo F. Padovan 	}
29270a708f8fSGustavo F. Padovan 
292836e999a8SMat Martineau 	/* Use sane default values in case a misbehaving remote device
292936e999a8SMat Martineau 	 * did not send an RFC option.
293036e999a8SMat Martineau 	 */
293136e999a8SMat Martineau 	rfc.mode = chan->mode;
293236e999a8SMat Martineau 	rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
293336e999a8SMat Martineau 	rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
293436e999a8SMat Martineau 	rfc.max_pdu_size = cpu_to_le16(chan->imtu);
293536e999a8SMat Martineau 
293636e999a8SMat Martineau 	BT_ERR("Expected RFC option was not found, using defaults");
293736e999a8SMat Martineau 
29380a708f8fSGustavo F. Padovan done:
29390a708f8fSGustavo F. Padovan 	switch (rfc.mode) {
29400a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
294147d1ec61SGustavo F. Padovan 		chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
294247d1ec61SGustavo F. Padovan 		chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
294347d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
29440a708f8fSGustavo F. Padovan 		break;
29450a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
294647d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
29470a708f8fSGustavo F. Padovan 	}
29480a708f8fSGustavo F. Padovan }
29490a708f8fSGustavo F. Padovan 
29500a708f8fSGustavo F. Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
29510a708f8fSGustavo F. Padovan {
2952e2fd318eSIlia Kolomisnky 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
29530a708f8fSGustavo F. Padovan 
2954e2fd318eSIlia Kolomisnky 	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
29550a708f8fSGustavo F. Padovan 		return 0;
29560a708f8fSGustavo F. Padovan 
29570a708f8fSGustavo F. Padovan 	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
29580a708f8fSGustavo F. Padovan 					cmd->ident == conn->info_ident) {
295917cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->info_timer);
29600a708f8fSGustavo F. Padovan 
29610a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
29620a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
29630a708f8fSGustavo F. Padovan 
29640a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
29650a708f8fSGustavo F. Padovan 	}
29660a708f8fSGustavo F. Padovan 
29670a708f8fSGustavo F. Padovan 	return 0;
29680a708f8fSGustavo F. Padovan }
29690a708f8fSGustavo F. Padovan 
29700a708f8fSGustavo F. Padovan static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
29710a708f8fSGustavo F. Padovan {
29720a708f8fSGustavo F. Padovan 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
29730a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
297423691d75SGustavo F. Padovan 	struct l2cap_chan *chan = NULL, *pchan;
29750a708f8fSGustavo F. Padovan 	struct sock *parent, *sk = NULL;
29760a708f8fSGustavo F. Padovan 	int result, status = L2CAP_CS_NO_INFO;
29770a708f8fSGustavo F. Padovan 
29780a708f8fSGustavo F. Padovan 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
29790a708f8fSGustavo F. Padovan 	__le16 psm = req->psm;
29800a708f8fSGustavo F. Padovan 
2981097db76cSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
29820a708f8fSGustavo F. Padovan 
29830a708f8fSGustavo F. Padovan 	/* Check if we have socket listening on psm */
2984c2287681SIdo Yariv 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst);
298523691d75SGustavo F. Padovan 	if (!pchan) {
29860a708f8fSGustavo F. Padovan 		result = L2CAP_CR_BAD_PSM;
29870a708f8fSGustavo F. Padovan 		goto sendresp;
29880a708f8fSGustavo F. Padovan 	}
29890a708f8fSGustavo F. Padovan 
299023691d75SGustavo F. Padovan 	parent = pchan->sk;
299123691d75SGustavo F. Padovan 
29923df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
2993aa2ac881SGustavo F. Padovan 	lock_sock(parent);
29940a708f8fSGustavo F. Padovan 
29950a708f8fSGustavo F. Padovan 	/* Check if the ACL is secure enough (if not SDP) */
29960a708f8fSGustavo F. Padovan 	if (psm != cpu_to_le16(0x0001) &&
29970a708f8fSGustavo F. Padovan 				!hci_conn_check_link_mode(conn->hcon)) {
29989f5a0d7bSAndrei Emeltchenko 		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
29990a708f8fSGustavo F. Padovan 		result = L2CAP_CR_SEC_BLOCK;
30000a708f8fSGustavo F. Padovan 		goto response;
30010a708f8fSGustavo F. Padovan 	}
30020a708f8fSGustavo F. Padovan 
30030a708f8fSGustavo F. Padovan 	result = L2CAP_CR_NO_MEM;
30040a708f8fSGustavo F. Padovan 
30050a708f8fSGustavo F. Padovan 	/* Check for backlog size */
30060a708f8fSGustavo F. Padovan 	if (sk_acceptq_is_full(parent)) {
30070a708f8fSGustavo F. Padovan 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
30080a708f8fSGustavo F. Padovan 		goto response;
30090a708f8fSGustavo F. Padovan 	}
30100a708f8fSGustavo F. Padovan 
301180808e43SGustavo F. Padovan 	chan = pchan->ops->new_connection(pchan->data);
301280808e43SGustavo F. Padovan 	if (!chan)
30130a708f8fSGustavo F. Padovan 		goto response;
30140a708f8fSGustavo F. Padovan 
301580808e43SGustavo F. Padovan 	sk = chan->sk;
301680808e43SGustavo F. Padovan 
30170a708f8fSGustavo F. Padovan 	/* Check if we already have channel with that dcid */
3018baa7e1faSGustavo F. Padovan 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
30190a708f8fSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
3020ba3bd0eeSGustavo F. Padovan 		chan->ops->close(chan->data);
30210a708f8fSGustavo F. Padovan 		goto response;
30220a708f8fSGustavo F. Padovan 	}
30230a708f8fSGustavo F. Padovan 
30240a708f8fSGustavo F. Padovan 	hci_conn_hold(conn->hcon);
30250a708f8fSGustavo F. Padovan 
30260a708f8fSGustavo F. Padovan 	bacpy(&bt_sk(sk)->src, conn->src);
30270a708f8fSGustavo F. Padovan 	bacpy(&bt_sk(sk)->dst, conn->dst);
3028fe4128e0SGustavo F. Padovan 	chan->psm  = psm;
3029fe4128e0SGustavo F. Padovan 	chan->dcid = scid;
30300a708f8fSGustavo F. Padovan 
3031d1010240SGustavo F. Padovan 	bt_accept_enqueue(parent, sk);
3032d1010240SGustavo F. Padovan 
30336be36555SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
303448454079SGustavo F. Padovan 
3035fe4128e0SGustavo F. Padovan 	dcid = chan->scid;
30360a708f8fSGustavo F. Padovan 
3037c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
30380a708f8fSGustavo F. Padovan 
3039fc7f8a7eSGustavo F. Padovan 	chan->ident = cmd->ident;
30400a708f8fSGustavo F. Padovan 
30410a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
3042d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan)) {
3043c5daa683SGustavo Padovan 			if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
30440e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_CONNECT2);
30450a708f8fSGustavo F. Padovan 				result = L2CAP_CR_PEND;
30460a708f8fSGustavo F. Padovan 				status = L2CAP_CS_AUTHOR_PEND;
30470a708f8fSGustavo F. Padovan 				parent->sk_data_ready(parent, 0);
30480a708f8fSGustavo F. Padovan 			} else {
30490e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_CONFIG);
30500a708f8fSGustavo F. Padovan 				result = L2CAP_CR_SUCCESS;
30510a708f8fSGustavo F. Padovan 				status = L2CAP_CS_NO_INFO;
30520a708f8fSGustavo F. Padovan 			}
30530a708f8fSGustavo F. Padovan 		} else {
30540e587be7SAndrei Emeltchenko 			__l2cap_state_change(chan, BT_CONNECT2);
30550a708f8fSGustavo F. Padovan 			result = L2CAP_CR_PEND;
30560a708f8fSGustavo F. Padovan 			status = L2CAP_CS_AUTHEN_PEND;
30570a708f8fSGustavo F. Padovan 		}
30580a708f8fSGustavo F. Padovan 	} else {
30590e587be7SAndrei Emeltchenko 		__l2cap_state_change(chan, BT_CONNECT2);
30600a708f8fSGustavo F. Padovan 		result = L2CAP_CR_PEND;
30610a708f8fSGustavo F. Padovan 		status = L2CAP_CS_NO_INFO;
30620a708f8fSGustavo F. Padovan 	}
30630a708f8fSGustavo F. Padovan 
30640a708f8fSGustavo F. Padovan response:
3065aa2ac881SGustavo F. Padovan 	release_sock(parent);
30663df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
30670a708f8fSGustavo F. Padovan 
30680a708f8fSGustavo F. Padovan sendresp:
30690a708f8fSGustavo F. Padovan 	rsp.scid   = cpu_to_le16(scid);
30700a708f8fSGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(dcid);
30710a708f8fSGustavo F. Padovan 	rsp.result = cpu_to_le16(result);
30720a708f8fSGustavo F. Padovan 	rsp.status = cpu_to_le16(status);
30730a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
30740a708f8fSGustavo F. Padovan 
30750a708f8fSGustavo F. Padovan 	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
30760a708f8fSGustavo F. Padovan 		struct l2cap_info_req info;
30770a708f8fSGustavo F. Padovan 		info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
30780a708f8fSGustavo F. Padovan 
30790a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
30800a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
30810a708f8fSGustavo F. Padovan 
3082ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
30830a708f8fSGustavo F. Padovan 
30840a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, conn->info_ident,
30850a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(info), &info);
30860a708f8fSGustavo F. Padovan 	}
30870a708f8fSGustavo F. Padovan 
3088c1360a1cSGustavo F. Padovan 	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
30890a708f8fSGustavo F. Padovan 				result == L2CAP_CR_SUCCESS) {
30900a708f8fSGustavo F. Padovan 		u8 buf[128];
3091c1360a1cSGustavo F. Padovan 		set_bit(CONF_REQ_SENT, &chan->conf_state);
30920a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
309373ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, buf), buf);
309473ffa904SGustavo F. Padovan 		chan->num_conf_req++;
30950a708f8fSGustavo F. Padovan 	}
30960a708f8fSGustavo F. Padovan 
30970a708f8fSGustavo F. Padovan 	return 0;
30980a708f8fSGustavo F. Padovan }
30990a708f8fSGustavo F. Padovan 
31000a708f8fSGustavo F. Padovan static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
31010a708f8fSGustavo F. Padovan {
31020a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
31030a708f8fSGustavo F. Padovan 	u16 scid, dcid, result, status;
310448454079SGustavo F. Padovan 	struct l2cap_chan *chan;
31050a708f8fSGustavo F. Padovan 	u8 req[128];
31063df91ea2SAndrei Emeltchenko 	int err;
31070a708f8fSGustavo F. Padovan 
31080a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
31090a708f8fSGustavo F. Padovan 	dcid   = __le16_to_cpu(rsp->dcid);
31100a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
31110a708f8fSGustavo F. Padovan 	status = __le16_to_cpu(rsp->status);
31120a708f8fSGustavo F. Padovan 
31131b009c98SAndrei Emeltchenko 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
31141b009c98SAndrei Emeltchenko 						dcid, scid, result, status);
31150a708f8fSGustavo F. Padovan 
31163df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
31173df91ea2SAndrei Emeltchenko 
31180a708f8fSGustavo F. Padovan 	if (scid) {
31193df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_scid(conn, scid);
31203df91ea2SAndrei Emeltchenko 		if (!chan) {
31213df91ea2SAndrei Emeltchenko 			err = -EFAULT;
31223df91ea2SAndrei Emeltchenko 			goto unlock;
31233df91ea2SAndrei Emeltchenko 		}
31240a708f8fSGustavo F. Padovan 	} else {
31253df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
31263df91ea2SAndrei Emeltchenko 		if (!chan) {
31273df91ea2SAndrei Emeltchenko 			err = -EFAULT;
31283df91ea2SAndrei Emeltchenko 			goto unlock;
31293df91ea2SAndrei Emeltchenko 		}
31300a708f8fSGustavo F. Padovan 	}
31310a708f8fSGustavo F. Padovan 
31323df91ea2SAndrei Emeltchenko 	err = 0;
31333df91ea2SAndrei Emeltchenko 
31346be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
313548454079SGustavo F. Padovan 
31360a708f8fSGustavo F. Padovan 	switch (result) {
31370a708f8fSGustavo F. Padovan 	case L2CAP_CR_SUCCESS:
313889bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONFIG);
3139fc7f8a7eSGustavo F. Padovan 		chan->ident = 0;
3140fe4128e0SGustavo F. Padovan 		chan->dcid = dcid;
3141c1360a1cSGustavo F. Padovan 		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
31420a708f8fSGustavo F. Padovan 
3143c1360a1cSGustavo F. Padovan 		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
31440a708f8fSGustavo F. Padovan 			break;
31450a708f8fSGustavo F. Padovan 
31460a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
314773ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, req), req);
314873ffa904SGustavo F. Padovan 		chan->num_conf_req++;
31490a708f8fSGustavo F. Padovan 		break;
31500a708f8fSGustavo F. Padovan 
31510a708f8fSGustavo F. Padovan 	case L2CAP_CR_PEND:
3152c1360a1cSGustavo F. Padovan 		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
31530a708f8fSGustavo F. Padovan 		break;
31540a708f8fSGustavo F. Padovan 
31550a708f8fSGustavo F. Padovan 	default:
315648454079SGustavo F. Padovan 		l2cap_chan_del(chan, ECONNREFUSED);
31570a708f8fSGustavo F. Padovan 		break;
31580a708f8fSGustavo F. Padovan 	}
31590a708f8fSGustavo F. Padovan 
31606be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
31613df91ea2SAndrei Emeltchenko 
31623df91ea2SAndrei Emeltchenko unlock:
31633df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
31643df91ea2SAndrei Emeltchenko 
31653df91ea2SAndrei Emeltchenko 	return err;
31660a708f8fSGustavo F. Padovan }
31670a708f8fSGustavo F. Padovan 
316847d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
31690a708f8fSGustavo F. Padovan {
31700a708f8fSGustavo F. Padovan 	/* FCS is enabled only in ERTM or streaming mode, if one or both
31710a708f8fSGustavo F. Padovan 	 * sides request it.
31720a708f8fSGustavo F. Padovan 	 */
31730c1bc5c6SGustavo F. Padovan 	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
317447d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_NONE;
3175c1360a1cSGustavo F. Padovan 	else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
317647d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_CRC16;
31770a708f8fSGustavo F. Padovan }
31780a708f8fSGustavo F. Padovan 
31790a708f8fSGustavo F. Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
31800a708f8fSGustavo F. Padovan {
31810a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
31820a708f8fSGustavo F. Padovan 	u16 dcid, flags;
31830a708f8fSGustavo F. Padovan 	u8 rsp[64];
318448454079SGustavo F. Padovan 	struct l2cap_chan *chan;
31853c588192SMat Martineau 	int len, err = 0;
31860a708f8fSGustavo F. Padovan 
31870a708f8fSGustavo F. Padovan 	dcid  = __le16_to_cpu(req->dcid);
31880a708f8fSGustavo F. Padovan 	flags = __le16_to_cpu(req->flags);
31890a708f8fSGustavo F. Padovan 
31900a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
31910a708f8fSGustavo F. Padovan 
3192baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, dcid);
319348454079SGustavo F. Padovan 	if (!chan)
31940a708f8fSGustavo F. Padovan 		return -ENOENT;
31950a708f8fSGustavo F. Padovan 
3196033b1142SDavid S. Miller 	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
3197e2fd318eSIlia Kolomisnky 		struct l2cap_cmd_rej_cid rej;
31980a708f8fSGustavo F. Padovan 
3199e2fd318eSIlia Kolomisnky 		rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
3200e2fd318eSIlia Kolomisnky 		rej.scid = cpu_to_le16(chan->scid);
3201e2fd318eSIlia Kolomisnky 		rej.dcid = cpu_to_le16(chan->dcid);
3202e2fd318eSIlia Kolomisnky 
32030a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
32040a708f8fSGustavo F. Padovan 				sizeof(rej), &rej);
32050a708f8fSGustavo F. Padovan 		goto unlock;
32060a708f8fSGustavo F. Padovan 	}
32070a708f8fSGustavo F. Padovan 
32080a708f8fSGustavo F. Padovan 	/* Reject if config buffer is too small. */
32090a708f8fSGustavo F. Padovan 	len = cmd_len - sizeof(*req);
32107ac28817SDan Rosenberg 	if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
32110a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3212fe4128e0SGustavo F. Padovan 				l2cap_build_conf_rsp(chan, rsp,
32130a708f8fSGustavo F. Padovan 					L2CAP_CONF_REJECT, flags), rsp);
32140a708f8fSGustavo F. Padovan 		goto unlock;
32150a708f8fSGustavo F. Padovan 	}
32160a708f8fSGustavo F. Padovan 
32170a708f8fSGustavo F. Padovan 	/* Store config. */
321873ffa904SGustavo F. Padovan 	memcpy(chan->conf_req + chan->conf_len, req->data, len);
321973ffa904SGustavo F. Padovan 	chan->conf_len += len;
32200a708f8fSGustavo F. Padovan 
32210a708f8fSGustavo F. Padovan 	if (flags & 0x0001) {
32220a708f8fSGustavo F. Padovan 		/* Incomplete config. Send empty response. */
32230a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3224fe4128e0SGustavo F. Padovan 				l2cap_build_conf_rsp(chan, rsp,
32250a708f8fSGustavo F. Padovan 					L2CAP_CONF_SUCCESS, 0x0001), rsp);
32260a708f8fSGustavo F. Padovan 		goto unlock;
32270a708f8fSGustavo F. Padovan 	}
32280a708f8fSGustavo F. Padovan 
32290a708f8fSGustavo F. Padovan 	/* Complete config. */
323073ffa904SGustavo F. Padovan 	len = l2cap_parse_conf_req(chan, rsp);
32310a708f8fSGustavo F. Padovan 	if (len < 0) {
3232e92c8e70SGustavo F. Padovan 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
32330a708f8fSGustavo F. Padovan 		goto unlock;
32340a708f8fSGustavo F. Padovan 	}
32350a708f8fSGustavo F. Padovan 
32360a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
323773ffa904SGustavo F. Padovan 	chan->num_conf_rsp++;
32380a708f8fSGustavo F. Padovan 
32390a708f8fSGustavo F. Padovan 	/* Reset config buffer. */
324073ffa904SGustavo F. Padovan 	chan->conf_len = 0;
32410a708f8fSGustavo F. Padovan 
3242c1360a1cSGustavo F. Padovan 	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
32430a708f8fSGustavo F. Padovan 		goto unlock;
32440a708f8fSGustavo F. Padovan 
3245c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
324647d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
32470a708f8fSGustavo F. Padovan 
324889bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONNECTED);
32490a708f8fSGustavo F. Padovan 
3250105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
3251105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
32523c588192SMat Martineau 			err = l2cap_ertm_init(chan);
32530a708f8fSGustavo F. Padovan 
32543c588192SMat Martineau 		if (err < 0)
32553c588192SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, -err);
32563c588192SMat Martineau 		else
3257cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
32583c588192SMat Martineau 
32590a708f8fSGustavo F. Padovan 		goto unlock;
32600a708f8fSGustavo F. Padovan 	}
32610a708f8fSGustavo F. Padovan 
3262c1360a1cSGustavo F. Padovan 	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
32630a708f8fSGustavo F. Padovan 		u8 buf[64];
32640a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
326573ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, buf), buf);
326673ffa904SGustavo F. Padovan 		chan->num_conf_req++;
32670a708f8fSGustavo F. Padovan 	}
32680a708f8fSGustavo F. Padovan 
32690e8b207eSAndrei Emeltchenko 	/* Got Conf Rsp PENDING from remote side and asume we sent
32700e8b207eSAndrei Emeltchenko 	   Conf Rsp PENDING in the code above */
32710e8b207eSAndrei Emeltchenko 	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
32720e8b207eSAndrei Emeltchenko 			test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
32730e8b207eSAndrei Emeltchenko 
32740e8b207eSAndrei Emeltchenko 		/* check compatibility */
32750e8b207eSAndrei Emeltchenko 
32760e8b207eSAndrei Emeltchenko 		clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
32770e8b207eSAndrei Emeltchenko 		set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
32780e8b207eSAndrei Emeltchenko 
32790e8b207eSAndrei Emeltchenko 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
32800e8b207eSAndrei Emeltchenko 					l2cap_build_conf_rsp(chan, rsp,
32810e8b207eSAndrei Emeltchenko 					L2CAP_CONF_SUCCESS, 0x0000), rsp);
32820e8b207eSAndrei Emeltchenko 	}
32830e8b207eSAndrei Emeltchenko 
32840a708f8fSGustavo F. Padovan unlock:
32856be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
32863c588192SMat Martineau 	return err;
32870a708f8fSGustavo F. Padovan }
32880a708f8fSGustavo F. Padovan 
32890a708f8fSGustavo F. Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
32900a708f8fSGustavo F. Padovan {
32910a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
32920a708f8fSGustavo F. Padovan 	u16 scid, flags, result;
329348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
329461386cbaSAndrei Emeltchenko 	int len = le16_to_cpu(cmd->len) - sizeof(*rsp);
32953c588192SMat Martineau 	int err = 0;
32960a708f8fSGustavo F. Padovan 
32970a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
32980a708f8fSGustavo F. Padovan 	flags  = __le16_to_cpu(rsp->flags);
32990a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
33000a708f8fSGustavo F. Padovan 
330161386cbaSAndrei Emeltchenko 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
330261386cbaSAndrei Emeltchenko 	       result, len);
33030a708f8fSGustavo F. Padovan 
3304baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, scid);
330548454079SGustavo F. Padovan 	if (!chan)
33060a708f8fSGustavo F. Padovan 		return 0;
33070a708f8fSGustavo F. Padovan 
33080a708f8fSGustavo F. Padovan 	switch (result) {
33090a708f8fSGustavo F. Padovan 	case L2CAP_CONF_SUCCESS:
331047d1ec61SGustavo F. Padovan 		l2cap_conf_rfc_get(chan, rsp->data, len);
33110e8b207eSAndrei Emeltchenko 		clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
33120a708f8fSGustavo F. Padovan 		break;
33130a708f8fSGustavo F. Padovan 
33140e8b207eSAndrei Emeltchenko 	case L2CAP_CONF_PENDING:
33150e8b207eSAndrei Emeltchenko 		set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
33160e8b207eSAndrei Emeltchenko 
33170e8b207eSAndrei Emeltchenko 		if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
33180e8b207eSAndrei Emeltchenko 			char buf[64];
33190e8b207eSAndrei Emeltchenko 
33200e8b207eSAndrei Emeltchenko 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
33210e8b207eSAndrei Emeltchenko 								buf, &result);
33220e8b207eSAndrei Emeltchenko 			if (len < 0) {
33230e8b207eSAndrei Emeltchenko 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
33240e8b207eSAndrei Emeltchenko 				goto done;
33250e8b207eSAndrei Emeltchenko 			}
33260e8b207eSAndrei Emeltchenko 
33270e8b207eSAndrei Emeltchenko 			/* check compatibility */
33280e8b207eSAndrei Emeltchenko 
33290e8b207eSAndrei Emeltchenko 			clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
33300e8b207eSAndrei Emeltchenko 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
33310e8b207eSAndrei Emeltchenko 
33320e8b207eSAndrei Emeltchenko 			l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
33330e8b207eSAndrei Emeltchenko 						l2cap_build_conf_rsp(chan, buf,
33340e8b207eSAndrei Emeltchenko 						L2CAP_CONF_SUCCESS, 0x0000), buf);
33350e8b207eSAndrei Emeltchenko 		}
33360e8b207eSAndrei Emeltchenko 		goto done;
33370e8b207eSAndrei Emeltchenko 
33380a708f8fSGustavo F. Padovan 	case L2CAP_CONF_UNACCEPT:
333973ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
33400a708f8fSGustavo F. Padovan 			char req[64];
33410a708f8fSGustavo F. Padovan 
33420a708f8fSGustavo F. Padovan 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
3343e92c8e70SGustavo F. Padovan 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
33440a708f8fSGustavo F. Padovan 				goto done;
33450a708f8fSGustavo F. Padovan 			}
33460a708f8fSGustavo F. Padovan 
33470a708f8fSGustavo F. Padovan 			/* throw out any old stored conf requests */
33480a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_SUCCESS;
3349b4450035SGustavo F. Padovan 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
3350b4450035SGustavo F. Padovan 								req, &result);
33510a708f8fSGustavo F. Padovan 			if (len < 0) {
3352e92c8e70SGustavo F. Padovan 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
33530a708f8fSGustavo F. Padovan 				goto done;
33540a708f8fSGustavo F. Padovan 			}
33550a708f8fSGustavo F. Padovan 
33560a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn),
33570a708f8fSGustavo F. Padovan 						L2CAP_CONF_REQ, len, req);
335873ffa904SGustavo F. Padovan 			chan->num_conf_req++;
33590a708f8fSGustavo F. Padovan 			if (result != L2CAP_CONF_SUCCESS)
33600a708f8fSGustavo F. Padovan 				goto done;
33610a708f8fSGustavo F. Padovan 			break;
33620a708f8fSGustavo F. Padovan 		}
33630a708f8fSGustavo F. Padovan 
33640a708f8fSGustavo F. Padovan 	default:
33656be36555SAndrei Emeltchenko 		l2cap_chan_set_err(chan, ECONNRESET);
33662e0052e4SAndrei Emeltchenko 
3367ba13ccd9SMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
3368e92c8e70SGustavo F. Padovan 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
33690a708f8fSGustavo F. Padovan 		goto done;
33700a708f8fSGustavo F. Padovan 	}
33710a708f8fSGustavo F. Padovan 
33720a708f8fSGustavo F. Padovan 	if (flags & 0x01)
33730a708f8fSGustavo F. Padovan 		goto done;
33740a708f8fSGustavo F. Padovan 
3375c1360a1cSGustavo F. Padovan 	set_bit(CONF_INPUT_DONE, &chan->conf_state);
33760a708f8fSGustavo F. Padovan 
3377c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
337847d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
33790a708f8fSGustavo F. Padovan 
338089bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONNECTED);
3381105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
3382105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
33833c588192SMat Martineau 			err = l2cap_ertm_init(chan);
33840a708f8fSGustavo F. Padovan 
33853c588192SMat Martineau 		if (err < 0)
33863c588192SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, -err);
33873c588192SMat Martineau 		else
3388cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
33890a708f8fSGustavo F. Padovan 	}
33900a708f8fSGustavo F. Padovan 
33910a708f8fSGustavo F. Padovan done:
33926be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
33933c588192SMat Martineau 	return err;
33940a708f8fSGustavo F. Padovan }
33950a708f8fSGustavo F. Padovan 
33960a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
33970a708f8fSGustavo F. Padovan {
33980a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
33990a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp rsp;
34000a708f8fSGustavo F. Padovan 	u16 dcid, scid;
340148454079SGustavo F. Padovan 	struct l2cap_chan *chan;
34020a708f8fSGustavo F. Padovan 	struct sock *sk;
34030a708f8fSGustavo F. Padovan 
34040a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(req->scid);
34050a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(req->dcid);
34060a708f8fSGustavo F. Padovan 
34070a708f8fSGustavo F. Padovan 	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
34080a708f8fSGustavo F. Padovan 
34093df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
34103df91ea2SAndrei Emeltchenko 
34113df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, dcid);
34123df91ea2SAndrei Emeltchenko 	if (!chan) {
34133df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
34140a708f8fSGustavo F. Padovan 		return 0;
34153df91ea2SAndrei Emeltchenko 	}
34160a708f8fSGustavo F. Padovan 
34176be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
34186be36555SAndrei Emeltchenko 
341948454079SGustavo F. Padovan 	sk = chan->sk;
342048454079SGustavo F. Padovan 
3421fe4128e0SGustavo F. Padovan 	rsp.dcid = cpu_to_le16(chan->scid);
3422fe4128e0SGustavo F. Padovan 	rsp.scid = cpu_to_le16(chan->dcid);
34230a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
34240a708f8fSGustavo F. Padovan 
34256be36555SAndrei Emeltchenko 	lock_sock(sk);
34260a708f8fSGustavo F. Padovan 	sk->sk_shutdown = SHUTDOWN_MASK;
34276be36555SAndrei Emeltchenko 	release_sock(sk);
34280a708f8fSGustavo F. Padovan 
342961d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
343048454079SGustavo F. Padovan 	l2cap_chan_del(chan, ECONNRESET);
34316be36555SAndrei Emeltchenko 
34326be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
34330a708f8fSGustavo F. Padovan 
3434ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
343561d6ef3eSMat Martineau 	l2cap_chan_put(chan);
34363df91ea2SAndrei Emeltchenko 
34373df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
34383df91ea2SAndrei Emeltchenko 
34390a708f8fSGustavo F. Padovan 	return 0;
34400a708f8fSGustavo F. Padovan }
34410a708f8fSGustavo F. Padovan 
34420a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
34430a708f8fSGustavo F. Padovan {
34440a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
34450a708f8fSGustavo F. Padovan 	u16 dcid, scid;
344648454079SGustavo F. Padovan 	struct l2cap_chan *chan;
34470a708f8fSGustavo F. Padovan 
34480a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(rsp->scid);
34490a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(rsp->dcid);
34500a708f8fSGustavo F. Padovan 
34510a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
34520a708f8fSGustavo F. Padovan 
34533df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
34543df91ea2SAndrei Emeltchenko 
34553df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, scid);
34563df91ea2SAndrei Emeltchenko 	if (!chan) {
34573df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
34580a708f8fSGustavo F. Padovan 		return 0;
34593df91ea2SAndrei Emeltchenko 	}
34600a708f8fSGustavo F. Padovan 
34616be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
346248454079SGustavo F. Padovan 
346361d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
346448454079SGustavo F. Padovan 	l2cap_chan_del(chan, 0);
34656be36555SAndrei Emeltchenko 
34666be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
34670a708f8fSGustavo F. Padovan 
3468ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
346961d6ef3eSMat Martineau 	l2cap_chan_put(chan);
34703df91ea2SAndrei Emeltchenko 
34713df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
34723df91ea2SAndrei Emeltchenko 
34730a708f8fSGustavo F. Padovan 	return 0;
34740a708f8fSGustavo F. Padovan }
34750a708f8fSGustavo F. Padovan 
34760a708f8fSGustavo F. Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
34770a708f8fSGustavo F. Padovan {
34780a708f8fSGustavo F. Padovan 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
34790a708f8fSGustavo F. Padovan 	u16 type;
34800a708f8fSGustavo F. Padovan 
34810a708f8fSGustavo F. Padovan 	type = __le16_to_cpu(req->type);
34820a708f8fSGustavo F. Padovan 
34830a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x", type);
34840a708f8fSGustavo F. Padovan 
34850a708f8fSGustavo F. Padovan 	if (type == L2CAP_IT_FEAT_MASK) {
34860a708f8fSGustavo F. Padovan 		u8 buf[8];
34870a708f8fSGustavo F. Padovan 		u32 feat_mask = l2cap_feat_mask;
34880a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
34890a708f8fSGustavo F. Padovan 		rsp->type   = cpu_to_le16(L2CAP_IT_FEAT_MASK);
34900a708f8fSGustavo F. Padovan 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
34910a708f8fSGustavo F. Padovan 		if (!disable_ertm)
34920a708f8fSGustavo F. Padovan 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
34930a708f8fSGustavo F. Padovan 							 | L2CAP_FEAT_FCS;
3494a5fd6f30SAndrei Emeltchenko 		if (enable_hs)
34956327eb98SAndrei Emeltchenko 			feat_mask |= L2CAP_FEAT_EXT_FLOW
34966327eb98SAndrei Emeltchenko 						| L2CAP_FEAT_EXT_WINDOW;
3497a5fd6f30SAndrei Emeltchenko 
34980a708f8fSGustavo F. Padovan 		put_unaligned_le32(feat_mask, rsp->data);
34990a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
35000a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(buf), buf);
35010a708f8fSGustavo F. Padovan 	} else if (type == L2CAP_IT_FIXED_CHAN) {
35020a708f8fSGustavo F. Padovan 		u8 buf[12];
35030a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
350450a147cdSMat Martineau 
350550a147cdSMat Martineau 		if (enable_hs)
350650a147cdSMat Martineau 			l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
350750a147cdSMat Martineau 		else
350850a147cdSMat Martineau 			l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
350950a147cdSMat Martineau 
35100a708f8fSGustavo F. Padovan 		rsp->type   = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
35110a708f8fSGustavo F. Padovan 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
3512c6337ea6SAndrei Emeltchenko 		memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
35130a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
35140a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(buf), buf);
35150a708f8fSGustavo F. Padovan 	} else {
35160a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp rsp;
35170a708f8fSGustavo F. Padovan 		rsp.type   = cpu_to_le16(type);
35180a708f8fSGustavo F. Padovan 		rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
35190a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
35200a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(rsp), &rsp);
35210a708f8fSGustavo F. Padovan 	}
35220a708f8fSGustavo F. Padovan 
35230a708f8fSGustavo F. Padovan 	return 0;
35240a708f8fSGustavo F. Padovan }
35250a708f8fSGustavo F. Padovan 
35260a708f8fSGustavo F. Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
35270a708f8fSGustavo F. Padovan {
35280a708f8fSGustavo F. Padovan 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
35290a708f8fSGustavo F. Padovan 	u16 type, result;
35300a708f8fSGustavo F. Padovan 
35310a708f8fSGustavo F. Padovan 	type   = __le16_to_cpu(rsp->type);
35320a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
35330a708f8fSGustavo F. Padovan 
35340a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
35350a708f8fSGustavo F. Padovan 
3536e90165beSAndrei Emeltchenko 	/* L2CAP Info req/rsp are unbound to channels, add extra checks */
3537e90165beSAndrei Emeltchenko 	if (cmd->ident != conn->info_ident ||
3538e90165beSAndrei Emeltchenko 			conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3539e90165beSAndrei Emeltchenko 		return 0;
3540e90165beSAndrei Emeltchenko 
354117cd3f37SUlisses Furquim 	cancel_delayed_work(&conn->info_timer);
35420a708f8fSGustavo F. Padovan 
35430a708f8fSGustavo F. Padovan 	if (result != L2CAP_IR_SUCCESS) {
35440a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
35450a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
35460a708f8fSGustavo F. Padovan 
35470a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
35480a708f8fSGustavo F. Padovan 
35490a708f8fSGustavo F. Padovan 		return 0;
35500a708f8fSGustavo F. Padovan 	}
35510a708f8fSGustavo F. Padovan 
3552978c93b9SAndrei Emeltchenko 	switch (type) {
3553978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FEAT_MASK:
35540a708f8fSGustavo F. Padovan 		conn->feat_mask = get_unaligned_le32(rsp->data);
35550a708f8fSGustavo F. Padovan 
35560a708f8fSGustavo F. Padovan 		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
35570a708f8fSGustavo F. Padovan 			struct l2cap_info_req req;
35580a708f8fSGustavo F. Padovan 			req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
35590a708f8fSGustavo F. Padovan 
35600a708f8fSGustavo F. Padovan 			conn->info_ident = l2cap_get_ident(conn);
35610a708f8fSGustavo F. Padovan 
35620a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, conn->info_ident,
35630a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(req), &req);
35640a708f8fSGustavo F. Padovan 		} else {
35650a708f8fSGustavo F. Padovan 			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
35660a708f8fSGustavo F. Padovan 			conn->info_ident = 0;
35670a708f8fSGustavo F. Padovan 
35680a708f8fSGustavo F. Padovan 			l2cap_conn_start(conn);
35690a708f8fSGustavo F. Padovan 		}
3570978c93b9SAndrei Emeltchenko 		break;
3571978c93b9SAndrei Emeltchenko 
3572978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FIXED_CHAN:
3573978c93b9SAndrei Emeltchenko 		conn->fixed_chan_mask = rsp->data[0];
35740a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
35750a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
35760a708f8fSGustavo F. Padovan 
35770a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
3578978c93b9SAndrei Emeltchenko 		break;
35790a708f8fSGustavo F. Padovan 	}
35800a708f8fSGustavo F. Padovan 
35810a708f8fSGustavo F. Padovan 	return 0;
35820a708f8fSGustavo F. Padovan }
35830a708f8fSGustavo F. Padovan 
3584f94ff6ffSMat Martineau static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3585f94ff6ffSMat Martineau 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3586f94ff6ffSMat Martineau 					void *data)
3587f94ff6ffSMat Martineau {
3588f94ff6ffSMat Martineau 	struct l2cap_create_chan_req *req = data;
3589f94ff6ffSMat Martineau 	struct l2cap_create_chan_rsp rsp;
3590f94ff6ffSMat Martineau 	u16 psm, scid;
3591f94ff6ffSMat Martineau 
3592f94ff6ffSMat Martineau 	if (cmd_len != sizeof(*req))
3593f94ff6ffSMat Martineau 		return -EPROTO;
3594f94ff6ffSMat Martineau 
3595f94ff6ffSMat Martineau 	if (!enable_hs)
3596f94ff6ffSMat Martineau 		return -EINVAL;
3597f94ff6ffSMat Martineau 
3598f94ff6ffSMat Martineau 	psm = le16_to_cpu(req->psm);
3599f94ff6ffSMat Martineau 	scid = le16_to_cpu(req->scid);
3600f94ff6ffSMat Martineau 
3601f94ff6ffSMat Martineau 	BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3602f94ff6ffSMat Martineau 
3603f94ff6ffSMat Martineau 	/* Placeholder: Always reject */
3604f94ff6ffSMat Martineau 	rsp.dcid = 0;
3605f94ff6ffSMat Martineau 	rsp.scid = cpu_to_le16(scid);
36068ce0c498SAndrei Emeltchenko 	rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
36078ce0c498SAndrei Emeltchenko 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
3608f94ff6ffSMat Martineau 
3609f94ff6ffSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3610f94ff6ffSMat Martineau 		       sizeof(rsp), &rsp);
3611f94ff6ffSMat Martineau 
3612f94ff6ffSMat Martineau 	return 0;
3613f94ff6ffSMat Martineau }
3614f94ff6ffSMat Martineau 
3615f94ff6ffSMat Martineau static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3616f94ff6ffSMat Martineau 					struct l2cap_cmd_hdr *cmd, void *data)
3617f94ff6ffSMat Martineau {
3618f94ff6ffSMat Martineau 	BT_DBG("conn %p", conn);
3619f94ff6ffSMat Martineau 
3620f94ff6ffSMat Martineau 	return l2cap_connect_rsp(conn, cmd, data);
3621f94ff6ffSMat Martineau }
3622f94ff6ffSMat Martineau 
36238d5a04a1SMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
36248d5a04a1SMat Martineau 							u16 icid, u16 result)
36258d5a04a1SMat Martineau {
36268d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp rsp;
36278d5a04a1SMat Martineau 
36288d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
36298d5a04a1SMat Martineau 
36308d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
36318d5a04a1SMat Martineau 	rsp.result = cpu_to_le16(result);
36328d5a04a1SMat Martineau 
36338d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
36348d5a04a1SMat Martineau }
36358d5a04a1SMat Martineau 
36368d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
36378d5a04a1SMat Martineau 				struct l2cap_chan *chan, u16 icid, u16 result)
36388d5a04a1SMat Martineau {
36398d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm cfm;
36408d5a04a1SMat Martineau 	u8 ident;
36418d5a04a1SMat Martineau 
36428d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
36438d5a04a1SMat Martineau 
36448d5a04a1SMat Martineau 	ident = l2cap_get_ident(conn);
36458d5a04a1SMat Martineau 	if (chan)
36468d5a04a1SMat Martineau 		chan->ident = ident;
36478d5a04a1SMat Martineau 
36488d5a04a1SMat Martineau 	cfm.icid = cpu_to_le16(icid);
36498d5a04a1SMat Martineau 	cfm.result = cpu_to_le16(result);
36508d5a04a1SMat Martineau 
36518d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
36528d5a04a1SMat Martineau }
36538d5a04a1SMat Martineau 
36548d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
36558d5a04a1SMat Martineau 								u16 icid)
36568d5a04a1SMat Martineau {
36578d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp rsp;
36588d5a04a1SMat Martineau 
36598d5a04a1SMat Martineau 	BT_DBG("icid %d", icid);
36608d5a04a1SMat Martineau 
36618d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
36628d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
36638d5a04a1SMat Martineau }
36648d5a04a1SMat Martineau 
36658d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
36668d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
36678d5a04a1SMat Martineau {
36688d5a04a1SMat Martineau 	struct l2cap_move_chan_req *req = data;
36698d5a04a1SMat Martineau 	u16 icid = 0;
36708d5a04a1SMat Martineau 	u16 result = L2CAP_MR_NOT_ALLOWED;
36718d5a04a1SMat Martineau 
36728d5a04a1SMat Martineau 	if (cmd_len != sizeof(*req))
36738d5a04a1SMat Martineau 		return -EPROTO;
36748d5a04a1SMat Martineau 
36758d5a04a1SMat Martineau 	icid = le16_to_cpu(req->icid);
36768d5a04a1SMat Martineau 
36778d5a04a1SMat Martineau 	BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
36788d5a04a1SMat Martineau 
36798d5a04a1SMat Martineau 	if (!enable_hs)
36808d5a04a1SMat Martineau 		return -EINVAL;
36818d5a04a1SMat Martineau 
36828d5a04a1SMat Martineau 	/* Placeholder: Always refuse */
36838d5a04a1SMat Martineau 	l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
36848d5a04a1SMat Martineau 
36858d5a04a1SMat Martineau 	return 0;
36868d5a04a1SMat Martineau }
36878d5a04a1SMat Martineau 
36888d5a04a1SMat Martineau static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
36898d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
36908d5a04a1SMat Martineau {
36918d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp *rsp = data;
36928d5a04a1SMat Martineau 	u16 icid, result;
36938d5a04a1SMat Martineau 
36948d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
36958d5a04a1SMat Martineau 		return -EPROTO;
36968d5a04a1SMat Martineau 
36978d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
36988d5a04a1SMat Martineau 	result = le16_to_cpu(rsp->result);
36998d5a04a1SMat Martineau 
37008d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
37018d5a04a1SMat Martineau 
37028d5a04a1SMat Martineau 	/* Placeholder: Always unconfirmed */
37038d5a04a1SMat Martineau 	l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
37048d5a04a1SMat Martineau 
37058d5a04a1SMat Martineau 	return 0;
37068d5a04a1SMat Martineau }
37078d5a04a1SMat Martineau 
37088d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
37098d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
37108d5a04a1SMat Martineau {
37118d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm *cfm = data;
37128d5a04a1SMat Martineau 	u16 icid, result;
37138d5a04a1SMat Martineau 
37148d5a04a1SMat Martineau 	if (cmd_len != sizeof(*cfm))
37158d5a04a1SMat Martineau 		return -EPROTO;
37168d5a04a1SMat Martineau 
37178d5a04a1SMat Martineau 	icid = le16_to_cpu(cfm->icid);
37188d5a04a1SMat Martineau 	result = le16_to_cpu(cfm->result);
37198d5a04a1SMat Martineau 
37208d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
37218d5a04a1SMat Martineau 
37228d5a04a1SMat Martineau 	l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
37238d5a04a1SMat Martineau 
37248d5a04a1SMat Martineau 	return 0;
37258d5a04a1SMat Martineau }
37268d5a04a1SMat Martineau 
37278d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
37288d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
37298d5a04a1SMat Martineau {
37308d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp *rsp = data;
37318d5a04a1SMat Martineau 	u16 icid;
37328d5a04a1SMat Martineau 
37338d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
37348d5a04a1SMat Martineau 		return -EPROTO;
37358d5a04a1SMat Martineau 
37368d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
37378d5a04a1SMat Martineau 
37388d5a04a1SMat Martineau 	BT_DBG("icid %d", icid);
37398d5a04a1SMat Martineau 
37408d5a04a1SMat Martineau 	return 0;
37418d5a04a1SMat Martineau }
37428d5a04a1SMat Martineau 
3743e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
3744de73115aSClaudio Takahasi 							u16 to_multiplier)
3745de73115aSClaudio Takahasi {
3746de73115aSClaudio Takahasi 	u16 max_latency;
3747de73115aSClaudio Takahasi 
3748de73115aSClaudio Takahasi 	if (min > max || min < 6 || max > 3200)
3749de73115aSClaudio Takahasi 		return -EINVAL;
3750de73115aSClaudio Takahasi 
3751de73115aSClaudio Takahasi 	if (to_multiplier < 10 || to_multiplier > 3200)
3752de73115aSClaudio Takahasi 		return -EINVAL;
3753de73115aSClaudio Takahasi 
3754de73115aSClaudio Takahasi 	if (max >= to_multiplier * 8)
3755de73115aSClaudio Takahasi 		return -EINVAL;
3756de73115aSClaudio Takahasi 
3757de73115aSClaudio Takahasi 	max_latency = (to_multiplier * 8 / max) - 1;
3758de73115aSClaudio Takahasi 	if (latency > 499 || latency > max_latency)
3759de73115aSClaudio Takahasi 		return -EINVAL;
3760de73115aSClaudio Takahasi 
3761de73115aSClaudio Takahasi 	return 0;
3762de73115aSClaudio Takahasi }
3763de73115aSClaudio Takahasi 
3764de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3765de73115aSClaudio Takahasi 					struct l2cap_cmd_hdr *cmd, u8 *data)
3766de73115aSClaudio Takahasi {
3767de73115aSClaudio Takahasi 	struct hci_conn *hcon = conn->hcon;
3768de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_req *req;
3769de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_rsp rsp;
3770de73115aSClaudio Takahasi 	u16 min, max, latency, to_multiplier, cmd_len;
37712ce603ebSClaudio Takahasi 	int err;
3772de73115aSClaudio Takahasi 
3773de73115aSClaudio Takahasi 	if (!(hcon->link_mode & HCI_LM_MASTER))
3774de73115aSClaudio Takahasi 		return -EINVAL;
3775de73115aSClaudio Takahasi 
3776de73115aSClaudio Takahasi 	cmd_len = __le16_to_cpu(cmd->len);
3777de73115aSClaudio Takahasi 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3778de73115aSClaudio Takahasi 		return -EPROTO;
3779de73115aSClaudio Takahasi 
3780de73115aSClaudio Takahasi 	req = (struct l2cap_conn_param_update_req *) data;
3781de73115aSClaudio Takahasi 	min		= __le16_to_cpu(req->min);
3782de73115aSClaudio Takahasi 	max		= __le16_to_cpu(req->max);
3783de73115aSClaudio Takahasi 	latency		= __le16_to_cpu(req->latency);
3784de73115aSClaudio Takahasi 	to_multiplier	= __le16_to_cpu(req->to_multiplier);
3785de73115aSClaudio Takahasi 
3786de73115aSClaudio Takahasi 	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3787de73115aSClaudio Takahasi 						min, max, latency, to_multiplier);
3788de73115aSClaudio Takahasi 
3789de73115aSClaudio Takahasi 	memset(&rsp, 0, sizeof(rsp));
37902ce603ebSClaudio Takahasi 
37912ce603ebSClaudio Takahasi 	err = l2cap_check_conn_param(min, max, latency, to_multiplier);
37922ce603ebSClaudio Takahasi 	if (err)
3793de73115aSClaudio Takahasi 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3794de73115aSClaudio Takahasi 	else
3795de73115aSClaudio Takahasi 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3796de73115aSClaudio Takahasi 
3797de73115aSClaudio Takahasi 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3798de73115aSClaudio Takahasi 							sizeof(rsp), &rsp);
3799de73115aSClaudio Takahasi 
38002ce603ebSClaudio Takahasi 	if (!err)
38012ce603ebSClaudio Takahasi 		hci_le_conn_update(hcon, min, max, latency, to_multiplier);
38022ce603ebSClaudio Takahasi 
3803de73115aSClaudio Takahasi 	return 0;
3804de73115aSClaudio Takahasi }
3805de73115aSClaudio Takahasi 
38063300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
38073300d9a9SClaudio Takahasi 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
38083300d9a9SClaudio Takahasi {
38093300d9a9SClaudio Takahasi 	int err = 0;
38103300d9a9SClaudio Takahasi 
38113300d9a9SClaudio Takahasi 	switch (cmd->code) {
38123300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
38133300d9a9SClaudio Takahasi 		l2cap_command_rej(conn, cmd, data);
38143300d9a9SClaudio Takahasi 		break;
38153300d9a9SClaudio Takahasi 
38163300d9a9SClaudio Takahasi 	case L2CAP_CONN_REQ:
38173300d9a9SClaudio Takahasi 		err = l2cap_connect_req(conn, cmd, data);
38183300d9a9SClaudio Takahasi 		break;
38193300d9a9SClaudio Takahasi 
38203300d9a9SClaudio Takahasi 	case L2CAP_CONN_RSP:
38213300d9a9SClaudio Takahasi 		err = l2cap_connect_rsp(conn, cmd, data);
38223300d9a9SClaudio Takahasi 		break;
38233300d9a9SClaudio Takahasi 
38243300d9a9SClaudio Takahasi 	case L2CAP_CONF_REQ:
38253300d9a9SClaudio Takahasi 		err = l2cap_config_req(conn, cmd, cmd_len, data);
38263300d9a9SClaudio Takahasi 		break;
38273300d9a9SClaudio Takahasi 
38283300d9a9SClaudio Takahasi 	case L2CAP_CONF_RSP:
38293300d9a9SClaudio Takahasi 		err = l2cap_config_rsp(conn, cmd, data);
38303300d9a9SClaudio Takahasi 		break;
38313300d9a9SClaudio Takahasi 
38323300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_REQ:
38333300d9a9SClaudio Takahasi 		err = l2cap_disconnect_req(conn, cmd, data);
38343300d9a9SClaudio Takahasi 		break;
38353300d9a9SClaudio Takahasi 
38363300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_RSP:
38373300d9a9SClaudio Takahasi 		err = l2cap_disconnect_rsp(conn, cmd, data);
38383300d9a9SClaudio Takahasi 		break;
38393300d9a9SClaudio Takahasi 
38403300d9a9SClaudio Takahasi 	case L2CAP_ECHO_REQ:
38413300d9a9SClaudio Takahasi 		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
38423300d9a9SClaudio Takahasi 		break;
38433300d9a9SClaudio Takahasi 
38443300d9a9SClaudio Takahasi 	case L2CAP_ECHO_RSP:
38453300d9a9SClaudio Takahasi 		break;
38463300d9a9SClaudio Takahasi 
38473300d9a9SClaudio Takahasi 	case L2CAP_INFO_REQ:
38483300d9a9SClaudio Takahasi 		err = l2cap_information_req(conn, cmd, data);
38493300d9a9SClaudio Takahasi 		break;
38503300d9a9SClaudio Takahasi 
38513300d9a9SClaudio Takahasi 	case L2CAP_INFO_RSP:
38523300d9a9SClaudio Takahasi 		err = l2cap_information_rsp(conn, cmd, data);
38533300d9a9SClaudio Takahasi 		break;
38543300d9a9SClaudio Takahasi 
3855f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_REQ:
3856f94ff6ffSMat Martineau 		err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3857f94ff6ffSMat Martineau 		break;
3858f94ff6ffSMat Martineau 
3859f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_RSP:
3860f94ff6ffSMat Martineau 		err = l2cap_create_channel_rsp(conn, cmd, data);
3861f94ff6ffSMat Martineau 		break;
3862f94ff6ffSMat Martineau 
38638d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_REQ:
38648d5a04a1SMat Martineau 		err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
38658d5a04a1SMat Martineau 		break;
38668d5a04a1SMat Martineau 
38678d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_RSP:
38688d5a04a1SMat Martineau 		err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
38698d5a04a1SMat Martineau 		break;
38708d5a04a1SMat Martineau 
38718d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM:
38728d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
38738d5a04a1SMat Martineau 		break;
38748d5a04a1SMat Martineau 
38758d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM_RSP:
38768d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
38778d5a04a1SMat Martineau 		break;
38788d5a04a1SMat Martineau 
38793300d9a9SClaudio Takahasi 	default:
38803300d9a9SClaudio Takahasi 		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
38813300d9a9SClaudio Takahasi 		err = -EINVAL;
38823300d9a9SClaudio Takahasi 		break;
38833300d9a9SClaudio Takahasi 	}
38843300d9a9SClaudio Takahasi 
38853300d9a9SClaudio Takahasi 	return err;
38863300d9a9SClaudio Takahasi }
38873300d9a9SClaudio Takahasi 
38883300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
38893300d9a9SClaudio Takahasi 					struct l2cap_cmd_hdr *cmd, u8 *data)
38903300d9a9SClaudio Takahasi {
38913300d9a9SClaudio Takahasi 	switch (cmd->code) {
38923300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
38933300d9a9SClaudio Takahasi 		return 0;
38943300d9a9SClaudio Takahasi 
38953300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_REQ:
3896de73115aSClaudio Takahasi 		return l2cap_conn_param_update_req(conn, cmd, data);
38973300d9a9SClaudio Takahasi 
38983300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_RSP:
38993300d9a9SClaudio Takahasi 		return 0;
39003300d9a9SClaudio Takahasi 
39013300d9a9SClaudio Takahasi 	default:
39023300d9a9SClaudio Takahasi 		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
39033300d9a9SClaudio Takahasi 		return -EINVAL;
39043300d9a9SClaudio Takahasi 	}
39053300d9a9SClaudio Takahasi }
39063300d9a9SClaudio Takahasi 
39073300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
39083300d9a9SClaudio Takahasi 							struct sk_buff *skb)
39090a708f8fSGustavo F. Padovan {
39100a708f8fSGustavo F. Padovan 	u8 *data = skb->data;
39110a708f8fSGustavo F. Padovan 	int len = skb->len;
39120a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr cmd;
39133300d9a9SClaudio Takahasi 	int err;
39140a708f8fSGustavo F. Padovan 
39150a708f8fSGustavo F. Padovan 	l2cap_raw_recv(conn, skb);
39160a708f8fSGustavo F. Padovan 
39170a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CMD_HDR_SIZE) {
39180a708f8fSGustavo F. Padovan 		u16 cmd_len;
39190a708f8fSGustavo F. Padovan 		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
39200a708f8fSGustavo F. Padovan 		data += L2CAP_CMD_HDR_SIZE;
39210a708f8fSGustavo F. Padovan 		len  -= L2CAP_CMD_HDR_SIZE;
39220a708f8fSGustavo F. Padovan 
39230a708f8fSGustavo F. Padovan 		cmd_len = le16_to_cpu(cmd.len);
39240a708f8fSGustavo F. Padovan 
39250a708f8fSGustavo F. Padovan 		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident);
39260a708f8fSGustavo F. Padovan 
39270a708f8fSGustavo F. Padovan 		if (cmd_len > len || !cmd.ident) {
39280a708f8fSGustavo F. Padovan 			BT_DBG("corrupted command");
39290a708f8fSGustavo F. Padovan 			break;
39300a708f8fSGustavo F. Padovan 		}
39310a708f8fSGustavo F. Padovan 
39323300d9a9SClaudio Takahasi 		if (conn->hcon->type == LE_LINK)
39333300d9a9SClaudio Takahasi 			err = l2cap_le_sig_cmd(conn, &cmd, data);
39343300d9a9SClaudio Takahasi 		else
39353300d9a9SClaudio Takahasi 			err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
39360a708f8fSGustavo F. Padovan 
39370a708f8fSGustavo F. Padovan 		if (err) {
3938e2fd318eSIlia Kolomisnky 			struct l2cap_cmd_rej_unk rej;
39392c6d1a2eSGustavo F. Padovan 
39402c6d1a2eSGustavo F. Padovan 			BT_ERR("Wrong link type (%d)", err);
39410a708f8fSGustavo F. Padovan 
39420a708f8fSGustavo F. Padovan 			/* FIXME: Map err to a valid reason */
3943e2fd318eSIlia Kolomisnky 			rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
39440a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
39450a708f8fSGustavo F. Padovan 		}
39460a708f8fSGustavo F. Padovan 
39470a708f8fSGustavo F. Padovan 		data += cmd_len;
39480a708f8fSGustavo F. Padovan 		len  -= cmd_len;
39490a708f8fSGustavo F. Padovan 	}
39500a708f8fSGustavo F. Padovan 
39510a708f8fSGustavo F. Padovan 	kfree_skb(skb);
39520a708f8fSGustavo F. Padovan }
39530a708f8fSGustavo F. Padovan 
395447d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
39550a708f8fSGustavo F. Padovan {
39560a708f8fSGustavo F. Padovan 	u16 our_fcs, rcv_fcs;
3957e4ca6d98SAndrei Emeltchenko 	int hdr_size;
3958e4ca6d98SAndrei Emeltchenko 
3959e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3960e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_EXT_HDR_SIZE;
3961e4ca6d98SAndrei Emeltchenko 	else
3962e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_ENH_HDR_SIZE;
39630a708f8fSGustavo F. Padovan 
396447d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
396503a51213SAndrei Emeltchenko 		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
39660a708f8fSGustavo F. Padovan 		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
39670a708f8fSGustavo F. Padovan 		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
39680a708f8fSGustavo F. Padovan 
39690a708f8fSGustavo F. Padovan 		if (our_fcs != rcv_fcs)
39700a708f8fSGustavo F. Padovan 			return -EBADMSG;
39710a708f8fSGustavo F. Padovan 	}
39720a708f8fSGustavo F. Padovan 	return 0;
39730a708f8fSGustavo F. Padovan }
39740a708f8fSGustavo F. Padovan 
3975525cd185SGustavo F. Padovan static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
39760a708f8fSGustavo F. Padovan {
397788843ab0SAndrei Emeltchenko 	u32 control = 0;
39780a708f8fSGustavo F. Padovan 
39796a026610SGustavo F. Padovan 	chan->frames_sent = 0;
39800a708f8fSGustavo F. Padovan 
39810b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
39820a708f8fSGustavo F. Padovan 
3983e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3984ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
3985525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
3986e2ab4353SGustavo F. Padovan 		set_bit(CONN_RNR_SENT, &chan->conn_state);
39870a708f8fSGustavo F. Padovan 	}
39880a708f8fSGustavo F. Padovan 
3989e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
3990525cd185SGustavo F. Padovan 		l2cap_retransmit_frames(chan);
39910a708f8fSGustavo F. Padovan 
3992525cd185SGustavo F. Padovan 	l2cap_ertm_send(chan);
39930a708f8fSGustavo F. Padovan 
3994e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
39956a026610SGustavo F. Padovan 			chan->frames_sent == 0) {
3996ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
3997525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
39980a708f8fSGustavo F. Padovan 	}
39990a708f8fSGustavo F. Padovan }
40000a708f8fSGustavo F. Padovan 
4001fb45de7dSAndrei Emeltchenko static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u16 tx_seq, u8 sar)
40020a708f8fSGustavo F. Padovan {
40030a708f8fSGustavo F. Padovan 	struct sk_buff *next_skb;
40040a708f8fSGustavo F. Padovan 	int tx_seq_offset, next_tx_seq_offset;
40050a708f8fSGustavo F. Padovan 
40063ce3514fSMat Martineau 	bt_cb(skb)->control.txseq = tx_seq;
40073ce3514fSMat Martineau 	bt_cb(skb)->control.sar = sar;
40080a708f8fSGustavo F. Padovan 
4009f1c6775bSGustavo F. Padovan 	next_skb = skb_peek(&chan->srej_q);
40100a708f8fSGustavo F. Padovan 
4011836be934SAndrei Emeltchenko 	tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
40120a708f8fSGustavo F. Padovan 
4013039d9572SSzymon Janc 	while (next_skb) {
40143ce3514fSMat Martineau 		if (bt_cb(next_skb)->control.txseq == tx_seq)
40150a708f8fSGustavo F. Padovan 			return -EINVAL;
40160a708f8fSGustavo F. Padovan 
4017836be934SAndrei Emeltchenko 		next_tx_seq_offset = __seq_offset(chan,
40183ce3514fSMat Martineau 			bt_cb(next_skb)->control.txseq, chan->buffer_seq);
40190a708f8fSGustavo F. Padovan 
40200a708f8fSGustavo F. Padovan 		if (next_tx_seq_offset > tx_seq_offset) {
4021f1c6775bSGustavo F. Padovan 			__skb_queue_before(&chan->srej_q, next_skb, skb);
40220a708f8fSGustavo F. Padovan 			return 0;
40230a708f8fSGustavo F. Padovan 		}
40240a708f8fSGustavo F. Padovan 
4025f1c6775bSGustavo F. Padovan 		if (skb_queue_is_last(&chan->srej_q, next_skb))
4026039d9572SSzymon Janc 			next_skb = NULL;
4027039d9572SSzymon Janc 		else
4028039d9572SSzymon Janc 			next_skb = skb_queue_next(&chan->srej_q, next_skb);
4029039d9572SSzymon Janc 	}
40300a708f8fSGustavo F. Padovan 
4031f1c6775bSGustavo F. Padovan 	__skb_queue_tail(&chan->srej_q, skb);
40320a708f8fSGustavo F. Padovan 
40330a708f8fSGustavo F. Padovan 	return 0;
40340a708f8fSGustavo F. Padovan }
40350a708f8fSGustavo F. Padovan 
403684084a31SMat Martineau static void append_skb_frag(struct sk_buff *skb,
403784084a31SMat Martineau 			struct sk_buff *new_frag, struct sk_buff **last_frag)
40380a708f8fSGustavo F. Padovan {
403984084a31SMat Martineau 	/* skb->len reflects data in skb as well as all fragments
404084084a31SMat Martineau 	 * skb->data_len reflects only data in fragments
404184084a31SMat Martineau 	 */
404284084a31SMat Martineau 	if (!skb_has_frag_list(skb))
404384084a31SMat Martineau 		skb_shinfo(skb)->frag_list = new_frag;
404484084a31SMat Martineau 
404584084a31SMat Martineau 	new_frag->next = NULL;
404684084a31SMat Martineau 
404784084a31SMat Martineau 	(*last_frag)->next = new_frag;
404884084a31SMat Martineau 	*last_frag = new_frag;
404984084a31SMat Martineau 
405084084a31SMat Martineau 	skb->len += new_frag->len;
405184084a31SMat Martineau 	skb->data_len += new_frag->len;
405284084a31SMat Martineau 	skb->truesize += new_frag->truesize;
405384084a31SMat Martineau }
405484084a31SMat Martineau 
405588843ab0SAndrei Emeltchenko static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
405684084a31SMat Martineau {
405784084a31SMat Martineau 	int err = -EINVAL;
40580a708f8fSGustavo F. Padovan 
40597e0ef6eeSAndrei Emeltchenko 	switch (__get_ctrl_sar(chan, control)) {
40607e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_UNSEGMENTED:
406184084a31SMat Martineau 		if (chan->sdu)
406284084a31SMat Martineau 			break;
40630a708f8fSGustavo F. Padovan 
406484084a31SMat Martineau 		err = chan->ops->recv(chan->data, skb);
406584084a31SMat Martineau 		break;
40660a708f8fSGustavo F. Padovan 
40677e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_START:
406884084a31SMat Martineau 		if (chan->sdu)
406984084a31SMat Martineau 			break;
40700a708f8fSGustavo F. Padovan 
40716f61fd47SGustavo F. Padovan 		chan->sdu_len = get_unaligned_le16(skb->data);
407203a51213SAndrei Emeltchenko 		skb_pull(skb, L2CAP_SDULEN_SIZE);
40730a708f8fSGustavo F. Padovan 
407484084a31SMat Martineau 		if (chan->sdu_len > chan->imtu) {
407584084a31SMat Martineau 			err = -EMSGSIZE;
407684084a31SMat Martineau 			break;
407784084a31SMat Martineau 		}
40780a708f8fSGustavo F. Padovan 
407984084a31SMat Martineau 		if (skb->len >= chan->sdu_len)
408084084a31SMat Martineau 			break;
408184084a31SMat Martineau 
408284084a31SMat Martineau 		chan->sdu = skb;
408384084a31SMat Martineau 		chan->sdu_last_frag = skb;
408484084a31SMat Martineau 
408584084a31SMat Martineau 		skb = NULL;
408684084a31SMat Martineau 		err = 0;
40870a708f8fSGustavo F. Padovan 		break;
40880a708f8fSGustavo F. Padovan 
40897e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_CONTINUE:
40906f61fd47SGustavo F. Padovan 		if (!chan->sdu)
409184084a31SMat Martineau 			break;
40920a708f8fSGustavo F. Padovan 
409384084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
409484084a31SMat Martineau 				&chan->sdu_last_frag);
409584084a31SMat Martineau 		skb = NULL;
40960a708f8fSGustavo F. Padovan 
409784084a31SMat Martineau 		if (chan->sdu->len >= chan->sdu_len)
409884084a31SMat Martineau 			break;
40990a708f8fSGustavo F. Padovan 
410084084a31SMat Martineau 		err = 0;
41010a708f8fSGustavo F. Padovan 		break;
41020a708f8fSGustavo F. Padovan 
41037e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_END:
41046f61fd47SGustavo F. Padovan 		if (!chan->sdu)
410584084a31SMat Martineau 			break;
41060a708f8fSGustavo F. Padovan 
410784084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
410884084a31SMat Martineau 				&chan->sdu_last_frag);
410984084a31SMat Martineau 		skb = NULL;
41100a708f8fSGustavo F. Padovan 
411184084a31SMat Martineau 		if (chan->sdu->len != chan->sdu_len)
411284084a31SMat Martineau 			break;
41130a708f8fSGustavo F. Padovan 
411484084a31SMat Martineau 		err = chan->ops->recv(chan->data, chan->sdu);
41150a708f8fSGustavo F. Padovan 
411684084a31SMat Martineau 		if (!err) {
411784084a31SMat Martineau 			/* Reassembly complete */
411884084a31SMat Martineau 			chan->sdu = NULL;
411984084a31SMat Martineau 			chan->sdu_last_frag = NULL;
412084084a31SMat Martineau 			chan->sdu_len = 0;
41210a708f8fSGustavo F. Padovan 		}
41220a708f8fSGustavo F. Padovan 		break;
41230a708f8fSGustavo F. Padovan 	}
41240a708f8fSGustavo F. Padovan 
412584084a31SMat Martineau 	if (err) {
41260a708f8fSGustavo F. Padovan 		kfree_skb(skb);
41276f61fd47SGustavo F. Padovan 		kfree_skb(chan->sdu);
41286f61fd47SGustavo F. Padovan 		chan->sdu = NULL;
412984084a31SMat Martineau 		chan->sdu_last_frag = NULL;
413084084a31SMat Martineau 		chan->sdu_len = 0;
413184084a31SMat Martineau 	}
41320a708f8fSGustavo F. Padovan 
413384084a31SMat Martineau 	return err;
41340a708f8fSGustavo F. Padovan }
41350a708f8fSGustavo F. Padovan 
413626f880d2SMat Martineau static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
41370a708f8fSGustavo F. Padovan {
413826f880d2SMat Martineau 	BT_DBG("chan %p, Enter local busy", chan);
413926f880d2SMat Martineau 
414026f880d2SMat Martineau 	set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
41413c588192SMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
414226f880d2SMat Martineau 
414377f918bcSSzymon Janc 	__set_ack_timer(chan);
41440a708f8fSGustavo F. Padovan }
41450a708f8fSGustavo F. Padovan 
414626f880d2SMat Martineau static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
414726f880d2SMat Martineau {
414888843ab0SAndrei Emeltchenko 	u32 control;
41490a708f8fSGustavo F. Padovan 
4150e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
41510a708f8fSGustavo F. Padovan 		goto done;
41520a708f8fSGustavo F. Padovan 
41530b209faeSAndrei Emeltchenko 	control = __set_reqseq(chan, chan->buffer_seq);
4154e3781735SAndrei Emeltchenko 	control |= __set_ctrl_poll(chan);
4155ab784b73SAndrei Emeltchenko 	control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
4156525cd185SGustavo F. Padovan 	l2cap_send_sframe(chan, control);
41576a026610SGustavo F. Padovan 	chan->retry_count = 1;
41580a708f8fSGustavo F. Padovan 
41591a09bcb9SGustavo F. Padovan 	__clear_retrans_timer(chan);
41601a09bcb9SGustavo F. Padovan 	__set_monitor_timer(chan);
41610a708f8fSGustavo F. Padovan 
4162e2ab4353SGustavo F. Padovan 	set_bit(CONN_WAIT_F, &chan->conn_state);
41630a708f8fSGustavo F. Padovan 
41640a708f8fSGustavo F. Padovan done:
4165e2ab4353SGustavo F. Padovan 	clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
4166e2ab4353SGustavo F. Padovan 	clear_bit(CONN_RNR_SENT, &chan->conn_state);
41670a708f8fSGustavo F. Padovan 
416849208c9cSGustavo F. Padovan 	BT_DBG("chan %p, Exit local busy", chan);
41690a708f8fSGustavo F. Padovan }
41700a708f8fSGustavo F. Padovan 
4171e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
41720a708f8fSGustavo F. Padovan {
4173e328140fSMat Martineau 	if (chan->mode == L2CAP_MODE_ERTM) {
4174e328140fSMat Martineau 		if (busy)
417526f880d2SMat Martineau 			l2cap_ertm_enter_local_busy(chan);
4176e328140fSMat Martineau 		else
4177e328140fSMat Martineau 			l2cap_ertm_exit_local_busy(chan);
41780a708f8fSGustavo F. Padovan 	}
41790a708f8fSGustavo F. Padovan }
41800a708f8fSGustavo F. Padovan 
4181fb45de7dSAndrei Emeltchenko static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
41820a708f8fSGustavo F. Padovan {
41830a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
418488843ab0SAndrei Emeltchenko 	u32 control;
41850a708f8fSGustavo F. Padovan 
4186e328140fSMat Martineau 	while ((skb = skb_peek(&chan->srej_q)) &&
4187e328140fSMat Martineau 			!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4188e328140fSMat Martineau 		int err;
4189e328140fSMat Martineau 
41903ce3514fSMat Martineau 		if (bt_cb(skb)->control.txseq != tx_seq)
41910a708f8fSGustavo F. Padovan 			break;
41920a708f8fSGustavo F. Padovan 
4193f1c6775bSGustavo F. Padovan 		skb = skb_dequeue(&chan->srej_q);
41943ce3514fSMat Martineau 		control = __set_ctrl_sar(chan, bt_cb(skb)->control.sar);
419584084a31SMat Martineau 		err = l2cap_reassemble_sdu(chan, skb, control);
4196e328140fSMat Martineau 
4197e328140fSMat Martineau 		if (err < 0) {
4198e328140fSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4199e328140fSMat Martineau 			break;
4200e328140fSMat Martineau 		}
4201e328140fSMat Martineau 
4202836be934SAndrei Emeltchenko 		chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
4203836be934SAndrei Emeltchenko 		tx_seq = __next_seq(chan, tx_seq);
42040a708f8fSGustavo F. Padovan 	}
42050a708f8fSGustavo F. Padovan }
42060a708f8fSGustavo F. Padovan 
4207fb45de7dSAndrei Emeltchenko static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
42080a708f8fSGustavo F. Padovan {
42090a708f8fSGustavo F. Padovan 	struct srej_list *l, *tmp;
421088843ab0SAndrei Emeltchenko 	u32 control;
42110a708f8fSGustavo F. Padovan 
421239d5a3eeSGustavo F. Padovan 	list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
42130a708f8fSGustavo F. Padovan 		if (l->tx_seq == tx_seq) {
42140a708f8fSGustavo F. Padovan 			list_del(&l->list);
42150a708f8fSGustavo F. Padovan 			kfree(l);
42160a708f8fSGustavo F. Padovan 			return;
42170a708f8fSGustavo F. Padovan 		}
4218ab784b73SAndrei Emeltchenko 		control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
42190b209faeSAndrei Emeltchenko 		control |= __set_reqseq(chan, l->tx_seq);
4220525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
42210a708f8fSGustavo F. Padovan 		list_del(&l->list);
422239d5a3eeSGustavo F. Padovan 		list_add_tail(&l->list, &chan->srej_l);
42230a708f8fSGustavo F. Padovan 	}
42240a708f8fSGustavo F. Padovan }
42250a708f8fSGustavo F. Padovan 
4226aef89f21SSzymon Janc static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
42270a708f8fSGustavo F. Padovan {
42280a708f8fSGustavo F. Padovan 	struct srej_list *new;
422988843ab0SAndrei Emeltchenko 	u32 control;
42300a708f8fSGustavo F. Padovan 
423142e5c802SGustavo F. Padovan 	while (tx_seq != chan->expected_tx_seq) {
4232ab784b73SAndrei Emeltchenko 		control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
42330b209faeSAndrei Emeltchenko 		control |= __set_reqseq(chan, chan->expected_tx_seq);
42343c588192SMat Martineau 		l2cap_seq_list_append(&chan->srej_list, chan->expected_tx_seq);
4235525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
42360a708f8fSGustavo F. Padovan 
42370a708f8fSGustavo F. Padovan 		new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
4238aef89f21SSzymon Janc 		if (!new)
4239aef89f21SSzymon Janc 			return -ENOMEM;
4240aef89f21SSzymon Janc 
424142e5c802SGustavo F. Padovan 		new->tx_seq = chan->expected_tx_seq;
4242836be934SAndrei Emeltchenko 
4243836be934SAndrei Emeltchenko 		chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
4244836be934SAndrei Emeltchenko 
424539d5a3eeSGustavo F. Padovan 		list_add_tail(&new->list, &chan->srej_l);
42460a708f8fSGustavo F. Padovan 	}
4247836be934SAndrei Emeltchenko 
4248836be934SAndrei Emeltchenko 	chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
4249aef89f21SSzymon Janc 
4250aef89f21SSzymon Janc 	return 0;
42510a708f8fSGustavo F. Padovan }
42520a708f8fSGustavo F. Padovan 
425388843ab0SAndrei Emeltchenko static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
42540a708f8fSGustavo F. Padovan {
4255fb45de7dSAndrei Emeltchenko 	u16 tx_seq = __get_txseq(chan, rx_control);
42560b209faeSAndrei Emeltchenko 	u16 req_seq = __get_reqseq(chan, rx_control);
42577e0ef6eeSAndrei Emeltchenko 	u8 sar = __get_ctrl_sar(chan, rx_control);
42580a708f8fSGustavo F. Padovan 	int tx_seq_offset, expected_tx_seq_offset;
425947d1ec61SGustavo F. Padovan 	int num_to_ack = (chan->tx_win/6) + 1;
42600a708f8fSGustavo F. Padovan 	int err = 0;
42610a708f8fSGustavo F. Padovan 
426288843ab0SAndrei Emeltchenko 	BT_DBG("chan %p len %d tx_seq %d rx_control 0x%8.8x", chan, skb->len,
4263525cd185SGustavo F. Padovan 							tx_seq, rx_control);
42640a708f8fSGustavo F. Padovan 
426503f6715dSAndrei Emeltchenko 	if (__is_ctrl_final(chan, rx_control) &&
4266e2ab4353SGustavo F. Padovan 			test_bit(CONN_WAIT_F, &chan->conn_state)) {
42671a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
42686a026610SGustavo F. Padovan 		if (chan->unacked_frames > 0)
42691a09bcb9SGustavo F. Padovan 			__set_retrans_timer(chan);
4270e2ab4353SGustavo F. Padovan 		clear_bit(CONN_WAIT_F, &chan->conn_state);
42710a708f8fSGustavo F. Padovan 	}
42720a708f8fSGustavo F. Padovan 
427342e5c802SGustavo F. Padovan 	chan->expected_ack_seq = req_seq;
427442e5c802SGustavo F. Padovan 	l2cap_drop_acked_frames(chan);
42750a708f8fSGustavo F. Padovan 
4276836be934SAndrei Emeltchenko 	tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
42770a708f8fSGustavo F. Padovan 
42780a708f8fSGustavo F. Padovan 	/* invalid tx_seq */
427947d1ec61SGustavo F. Padovan 	if (tx_seq_offset >= chan->tx_win) {
42808c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
42810a708f8fSGustavo F. Padovan 		goto drop;
42820a708f8fSGustavo F. Padovan 	}
42830a708f8fSGustavo F. Padovan 
428477f918bcSSzymon Janc 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
428577f918bcSSzymon Janc 		if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
428677f918bcSSzymon Janc 			l2cap_send_ack(chan);
42870a708f8fSGustavo F. Padovan 		goto drop;
428877f918bcSSzymon Janc 	}
42890a708f8fSGustavo F. Padovan 
429002f1b641SMat Martineau 	if (tx_seq == chan->expected_tx_seq)
429102f1b641SMat Martineau 		goto expected;
429202f1b641SMat Martineau 
4293e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
42940a708f8fSGustavo F. Padovan 		struct srej_list *first;
42950a708f8fSGustavo F. Padovan 
429639d5a3eeSGustavo F. Padovan 		first = list_first_entry(&chan->srej_l,
42970a708f8fSGustavo F. Padovan 				struct srej_list, list);
42980a708f8fSGustavo F. Padovan 		if (tx_seq == first->tx_seq) {
429942e5c802SGustavo F. Padovan 			l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
4300525cd185SGustavo F. Padovan 			l2cap_check_srej_gap(chan, tx_seq);
43010a708f8fSGustavo F. Padovan 
43020a708f8fSGustavo F. Padovan 			list_del(&first->list);
43030a708f8fSGustavo F. Padovan 			kfree(first);
43040a708f8fSGustavo F. Padovan 
430539d5a3eeSGustavo F. Padovan 			if (list_empty(&chan->srej_l)) {
430642e5c802SGustavo F. Padovan 				chan->buffer_seq = chan->buffer_seq_srej;
4307e2ab4353SGustavo F. Padovan 				clear_bit(CONN_SREJ_SENT, &chan->conn_state);
4308525cd185SGustavo F. Padovan 				l2cap_send_ack(chan);
430949208c9cSGustavo F. Padovan 				BT_DBG("chan %p, Exit SREJ_SENT", chan);
43100a708f8fSGustavo F. Padovan 			}
43110a708f8fSGustavo F. Padovan 		} else {
43120a708f8fSGustavo F. Padovan 			struct srej_list *l;
43130a708f8fSGustavo F. Padovan 
43140a708f8fSGustavo F. Padovan 			/* duplicated tx_seq */
431542e5c802SGustavo F. Padovan 			if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
43160a708f8fSGustavo F. Padovan 				goto drop;
43170a708f8fSGustavo F. Padovan 
431839d5a3eeSGustavo F. Padovan 			list_for_each_entry(l, &chan->srej_l, list) {
43190a708f8fSGustavo F. Padovan 				if (l->tx_seq == tx_seq) {
4320525cd185SGustavo F. Padovan 					l2cap_resend_srejframe(chan, tx_seq);
43210a708f8fSGustavo F. Padovan 					return 0;
43220a708f8fSGustavo F. Padovan 				}
43230a708f8fSGustavo F. Padovan 			}
4324aef89f21SSzymon Janc 
4325aef89f21SSzymon Janc 			err = l2cap_send_srejframe(chan, tx_seq);
4326aef89f21SSzymon Janc 			if (err < 0) {
4327aef89f21SSzymon Janc 				l2cap_send_disconn_req(chan->conn, chan, -err);
4328aef89f21SSzymon Janc 				return err;
4329aef89f21SSzymon Janc 			}
43300a708f8fSGustavo F. Padovan 		}
43310a708f8fSGustavo F. Padovan 	} else {
4332836be934SAndrei Emeltchenko 		expected_tx_seq_offset = __seq_offset(chan,
4333836be934SAndrei Emeltchenko 				chan->expected_tx_seq, chan->buffer_seq);
43340a708f8fSGustavo F. Padovan 
43350a708f8fSGustavo F. Padovan 		/* duplicated tx_seq */
43360a708f8fSGustavo F. Padovan 		if (tx_seq_offset < expected_tx_seq_offset)
43370a708f8fSGustavo F. Padovan 			goto drop;
43380a708f8fSGustavo F. Padovan 
4339e2ab4353SGustavo F. Padovan 		set_bit(CONN_SREJ_SENT, &chan->conn_state);
43400a708f8fSGustavo F. Padovan 
434149208c9cSGustavo F. Padovan 		BT_DBG("chan %p, Enter SREJ", chan);
43420a708f8fSGustavo F. Padovan 
434339d5a3eeSGustavo F. Padovan 		INIT_LIST_HEAD(&chan->srej_l);
434442e5c802SGustavo F. Padovan 		chan->buffer_seq_srej = chan->buffer_seq;
43450a708f8fSGustavo F. Padovan 
4346f1c6775bSGustavo F. Padovan 		__skb_queue_head_init(&chan->srej_q);
434742e5c802SGustavo F. Padovan 		l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
43480a708f8fSGustavo F. Padovan 
43490ef3ef0fSSzymon Janc 		/* Set P-bit only if there are some I-frames to ack. */
43500ef3ef0fSSzymon Janc 		if (__clear_ack_timer(chan))
4351e2ab4353SGustavo F. Padovan 			set_bit(CONN_SEND_PBIT, &chan->conn_state);
43520a708f8fSGustavo F. Padovan 
4353aef89f21SSzymon Janc 		err = l2cap_send_srejframe(chan, tx_seq);
4354aef89f21SSzymon Janc 		if (err < 0) {
4355aef89f21SSzymon Janc 			l2cap_send_disconn_req(chan->conn, chan, -err);
4356aef89f21SSzymon Janc 			return err;
4357aef89f21SSzymon Janc 		}
43580a708f8fSGustavo F. Padovan 	}
43590a708f8fSGustavo F. Padovan 	return 0;
43600a708f8fSGustavo F. Padovan 
43610a708f8fSGustavo F. Padovan expected:
4362836be934SAndrei Emeltchenko 	chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
43630a708f8fSGustavo F. Padovan 
4364e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
43653ce3514fSMat Martineau 		bt_cb(skb)->control.txseq = tx_seq;
43663ce3514fSMat Martineau 		bt_cb(skb)->control.sar = sar;
4367f1c6775bSGustavo F. Padovan 		__skb_queue_tail(&chan->srej_q, skb);
43680a708f8fSGustavo F. Padovan 		return 0;
43690a708f8fSGustavo F. Padovan 	}
43700a708f8fSGustavo F. Padovan 
437184084a31SMat Martineau 	err = l2cap_reassemble_sdu(chan, skb, rx_control);
4372836be934SAndrei Emeltchenko 	chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
4373836be934SAndrei Emeltchenko 
4374e328140fSMat Martineau 	if (err < 0) {
4375e328140fSMat Martineau 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4376e328140fSMat Martineau 		return err;
4377e328140fSMat Martineau 	}
43780a708f8fSGustavo F. Padovan 
437903f6715dSAndrei Emeltchenko 	if (__is_ctrl_final(chan, rx_control)) {
4380e2ab4353SGustavo F. Padovan 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
4381525cd185SGustavo F. Padovan 			l2cap_retransmit_frames(chan);
43820a708f8fSGustavo F. Padovan 	}
43830a708f8fSGustavo F. Padovan 
43840a708f8fSGustavo F. Padovan 
43856a026610SGustavo F. Padovan 	chan->num_acked = (chan->num_acked + 1) % num_to_ack;
43866a026610SGustavo F. Padovan 	if (chan->num_acked == num_to_ack - 1)
4387525cd185SGustavo F. Padovan 		l2cap_send_ack(chan);
43884d611e4dSGustavo F. Padovan 	else
43894d611e4dSGustavo F. Padovan 		__set_ack_timer(chan);
43900a708f8fSGustavo F. Padovan 
43910a708f8fSGustavo F. Padovan 	return 0;
43920a708f8fSGustavo F. Padovan 
43930a708f8fSGustavo F. Padovan drop:
43940a708f8fSGustavo F. Padovan 	kfree_skb(skb);
43950a708f8fSGustavo F. Padovan 	return 0;
43960a708f8fSGustavo F. Padovan }
43970a708f8fSGustavo F. Padovan 
439888843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
43990a708f8fSGustavo F. Padovan {
440088843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
44010b209faeSAndrei Emeltchenko 				__get_reqseq(chan, rx_control), rx_control);
44020a708f8fSGustavo F. Padovan 
44030b209faeSAndrei Emeltchenko 	chan->expected_ack_seq = __get_reqseq(chan, rx_control);
440442e5c802SGustavo F. Padovan 	l2cap_drop_acked_frames(chan);
44050a708f8fSGustavo F. Padovan 
4406e3781735SAndrei Emeltchenko 	if (__is_ctrl_poll(chan, rx_control)) {
4407e2ab4353SGustavo F. Padovan 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
4408e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
4409e2ab4353SGustavo F. Padovan 			if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
44106a026610SGustavo F. Padovan 					(chan->unacked_frames > 0))
44111a09bcb9SGustavo F. Padovan 				__set_retrans_timer(chan);
44120a708f8fSGustavo F. Padovan 
4413e2ab4353SGustavo F. Padovan 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4414525cd185SGustavo F. Padovan 			l2cap_send_srejtail(chan);
44150a708f8fSGustavo F. Padovan 		} else {
4416525cd185SGustavo F. Padovan 			l2cap_send_i_or_rr_or_rnr(chan);
44170a708f8fSGustavo F. Padovan 		}
44180a708f8fSGustavo F. Padovan 
441903f6715dSAndrei Emeltchenko 	} else if (__is_ctrl_final(chan, rx_control)) {
4420e2ab4353SGustavo F. Padovan 		clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
44210a708f8fSGustavo F. Padovan 
4422e2ab4353SGustavo F. Padovan 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
4423525cd185SGustavo F. Padovan 			l2cap_retransmit_frames(chan);
44240a708f8fSGustavo F. Padovan 
44250a708f8fSGustavo F. Padovan 	} else {
4426e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
44276a026610SGustavo F. Padovan 				(chan->unacked_frames > 0))
44281a09bcb9SGustavo F. Padovan 			__set_retrans_timer(chan);
44290a708f8fSGustavo F. Padovan 
4430e2ab4353SGustavo F. Padovan 		clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4431e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
4432525cd185SGustavo F. Padovan 			l2cap_send_ack(chan);
44330a708f8fSGustavo F. Padovan 		else
4434525cd185SGustavo F. Padovan 			l2cap_ertm_send(chan);
44350a708f8fSGustavo F. Padovan 	}
44360a708f8fSGustavo F. Padovan }
44370a708f8fSGustavo F. Padovan 
443888843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
44390a708f8fSGustavo F. Padovan {
44400b209faeSAndrei Emeltchenko 	u16 tx_seq = __get_reqseq(chan, rx_control);
44410a708f8fSGustavo F. Padovan 
444288843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
44430a708f8fSGustavo F. Padovan 
4444e2ab4353SGustavo F. Padovan 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
44450a708f8fSGustavo F. Padovan 
444642e5c802SGustavo F. Padovan 	chan->expected_ack_seq = tx_seq;
444742e5c802SGustavo F. Padovan 	l2cap_drop_acked_frames(chan);
44480a708f8fSGustavo F. Padovan 
444903f6715dSAndrei Emeltchenko 	if (__is_ctrl_final(chan, rx_control)) {
4450e2ab4353SGustavo F. Padovan 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
4451525cd185SGustavo F. Padovan 			l2cap_retransmit_frames(chan);
44520a708f8fSGustavo F. Padovan 	} else {
4453525cd185SGustavo F. Padovan 		l2cap_retransmit_frames(chan);
44540a708f8fSGustavo F. Padovan 
4455e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_WAIT_F, &chan->conn_state))
4456e2ab4353SGustavo F. Padovan 			set_bit(CONN_REJ_ACT, &chan->conn_state);
44570a708f8fSGustavo F. Padovan 	}
44580a708f8fSGustavo F. Padovan }
445988843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
44600a708f8fSGustavo F. Padovan {
44610b209faeSAndrei Emeltchenko 	u16 tx_seq = __get_reqseq(chan, rx_control);
44620a708f8fSGustavo F. Padovan 
446388843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
44640a708f8fSGustavo F. Padovan 
4465e2ab4353SGustavo F. Padovan 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
44660a708f8fSGustavo F. Padovan 
4467e3781735SAndrei Emeltchenko 	if (__is_ctrl_poll(chan, rx_control)) {
446842e5c802SGustavo F. Padovan 		chan->expected_ack_seq = tx_seq;
446942e5c802SGustavo F. Padovan 		l2cap_drop_acked_frames(chan);
44700a708f8fSGustavo F. Padovan 
4471e2ab4353SGustavo F. Padovan 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
4472525cd185SGustavo F. Padovan 		l2cap_retransmit_one_frame(chan, tx_seq);
44730a708f8fSGustavo F. Padovan 
4474525cd185SGustavo F. Padovan 		l2cap_ertm_send(chan);
44750a708f8fSGustavo F. Padovan 
4476e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
44776a026610SGustavo F. Padovan 			chan->srej_save_reqseq = tx_seq;
4478e2ab4353SGustavo F. Padovan 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
44790a708f8fSGustavo F. Padovan 		}
448003f6715dSAndrei Emeltchenko 	} else if (__is_ctrl_final(chan, rx_control)) {
4481e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
44826a026610SGustavo F. Padovan 				chan->srej_save_reqseq == tx_seq)
4483e2ab4353SGustavo F. Padovan 			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
44840a708f8fSGustavo F. Padovan 		else
4485525cd185SGustavo F. Padovan 			l2cap_retransmit_one_frame(chan, tx_seq);
44860a708f8fSGustavo F. Padovan 	} else {
4487525cd185SGustavo F. Padovan 		l2cap_retransmit_one_frame(chan, tx_seq);
4488e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
44896a026610SGustavo F. Padovan 			chan->srej_save_reqseq = tx_seq;
4490e2ab4353SGustavo F. Padovan 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
44910a708f8fSGustavo F. Padovan 		}
44920a708f8fSGustavo F. Padovan 	}
44930a708f8fSGustavo F. Padovan }
44940a708f8fSGustavo F. Padovan 
449588843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
44960a708f8fSGustavo F. Padovan {
44970b209faeSAndrei Emeltchenko 	u16 tx_seq = __get_reqseq(chan, rx_control);
44980a708f8fSGustavo F. Padovan 
449988843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
45000a708f8fSGustavo F. Padovan 
4501e2ab4353SGustavo F. Padovan 	set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
450242e5c802SGustavo F. Padovan 	chan->expected_ack_seq = tx_seq;
450342e5c802SGustavo F. Padovan 	l2cap_drop_acked_frames(chan);
45040a708f8fSGustavo F. Padovan 
4505e3781735SAndrei Emeltchenko 	if (__is_ctrl_poll(chan, rx_control))
4506e2ab4353SGustavo F. Padovan 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
45070a708f8fSGustavo F. Padovan 
4508e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
45091a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
4510e3781735SAndrei Emeltchenko 		if (__is_ctrl_poll(chan, rx_control))
4511525cd185SGustavo F. Padovan 			l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
45120a708f8fSGustavo F. Padovan 		return;
45130a708f8fSGustavo F. Padovan 	}
45140a708f8fSGustavo F. Padovan 
4515e3781735SAndrei Emeltchenko 	if (__is_ctrl_poll(chan, rx_control)) {
4516525cd185SGustavo F. Padovan 		l2cap_send_srejtail(chan);
4517ab784b73SAndrei Emeltchenko 	} else {
4518ab784b73SAndrei Emeltchenko 		rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4519ab784b73SAndrei Emeltchenko 		l2cap_send_sframe(chan, rx_control);
4520ab784b73SAndrei Emeltchenko 	}
45210a708f8fSGustavo F. Padovan }
45220a708f8fSGustavo F. Padovan 
452388843ab0SAndrei Emeltchenko static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
45240a708f8fSGustavo F. Padovan {
452588843ab0SAndrei Emeltchenko 	BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
45260a708f8fSGustavo F. Padovan 
452703f6715dSAndrei Emeltchenko 	if (__is_ctrl_final(chan, rx_control) &&
4528e2ab4353SGustavo F. Padovan 			test_bit(CONN_WAIT_F, &chan->conn_state)) {
45291a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
45306a026610SGustavo F. Padovan 		if (chan->unacked_frames > 0)
45311a09bcb9SGustavo F. Padovan 			__set_retrans_timer(chan);
4532e2ab4353SGustavo F. Padovan 		clear_bit(CONN_WAIT_F, &chan->conn_state);
45330a708f8fSGustavo F. Padovan 	}
45340a708f8fSGustavo F. Padovan 
4535ab784b73SAndrei Emeltchenko 	switch (__get_ctrl_super(chan, rx_control)) {
4536ab784b73SAndrei Emeltchenko 	case L2CAP_SUPER_RR:
4537525cd185SGustavo F. Padovan 		l2cap_data_channel_rrframe(chan, rx_control);
45380a708f8fSGustavo F. Padovan 		break;
45390a708f8fSGustavo F. Padovan 
4540ab784b73SAndrei Emeltchenko 	case L2CAP_SUPER_REJ:
4541525cd185SGustavo F. Padovan 		l2cap_data_channel_rejframe(chan, rx_control);
45420a708f8fSGustavo F. Padovan 		break;
45430a708f8fSGustavo F. Padovan 
4544ab784b73SAndrei Emeltchenko 	case L2CAP_SUPER_SREJ:
4545525cd185SGustavo F. Padovan 		l2cap_data_channel_srejframe(chan, rx_control);
45460a708f8fSGustavo F. Padovan 		break;
45470a708f8fSGustavo F. Padovan 
4548ab784b73SAndrei Emeltchenko 	case L2CAP_SUPER_RNR:
4549525cd185SGustavo F. Padovan 		l2cap_data_channel_rnrframe(chan, rx_control);
45500a708f8fSGustavo F. Padovan 		break;
45510a708f8fSGustavo F. Padovan 	}
45520a708f8fSGustavo F. Padovan 
45530a708f8fSGustavo F. Padovan 	kfree_skb(skb);
45540a708f8fSGustavo F. Padovan 	return 0;
45550a708f8fSGustavo F. Padovan }
45560a708f8fSGustavo F. Padovan 
4557cad8f1d0SSzymon Janc static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
45580a708f8fSGustavo F. Padovan {
455988843ab0SAndrei Emeltchenko 	u32 control;
45600b209faeSAndrei Emeltchenko 	u16 req_seq;
45610a708f8fSGustavo F. Padovan 	int len, next_tx_seq_offset, req_seq_offset;
45620a708f8fSGustavo F. Padovan 
4563b76bbd66SMat Martineau 	__unpack_control(chan, skb);
4564b76bbd66SMat Martineau 
456588843ab0SAndrei Emeltchenko 	control = __get_control(chan, skb->data);
456688843ab0SAndrei Emeltchenko 	skb_pull(skb, __ctrl_size(chan));
45670a708f8fSGustavo F. Padovan 	len = skb->len;
45680a708f8fSGustavo F. Padovan 
45690a708f8fSGustavo F. Padovan 	/*
45700a708f8fSGustavo F. Padovan 	 * We can just drop the corrupted I-frame here.
45710a708f8fSGustavo F. Padovan 	 * Receiver will miss it and start proper recovery
45720a708f8fSGustavo F. Padovan 	 * procedures and ask retransmission.
45730a708f8fSGustavo F. Padovan 	 */
457447d1ec61SGustavo F. Padovan 	if (l2cap_check_fcs(chan, skb))
45750a708f8fSGustavo F. Padovan 		goto drop;
45760a708f8fSGustavo F. Padovan 
4577793c2f1cSAndrei Emeltchenko 	if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
457803a51213SAndrei Emeltchenko 		len -= L2CAP_SDULEN_SIZE;
45790a708f8fSGustavo F. Padovan 
458047d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
458103a51213SAndrei Emeltchenko 		len -= L2CAP_FCS_SIZE;
45820a708f8fSGustavo F. Padovan 
458347d1ec61SGustavo F. Padovan 	if (len > chan->mps) {
45848c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
45850a708f8fSGustavo F. Padovan 		goto drop;
45860a708f8fSGustavo F. Padovan 	}
45870a708f8fSGustavo F. Padovan 
45880b209faeSAndrei Emeltchenko 	req_seq = __get_reqseq(chan, control);
45890a708f8fSGustavo F. Padovan 
4590836be934SAndrei Emeltchenko 	req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
4591836be934SAndrei Emeltchenko 
4592836be934SAndrei Emeltchenko 	next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
4593836be934SAndrei Emeltchenko 						chan->expected_ack_seq);
45940a708f8fSGustavo F. Padovan 
45950a708f8fSGustavo F. Padovan 	/* check for invalid req-seq */
45960a708f8fSGustavo F. Padovan 	if (req_seq_offset > next_tx_seq_offset) {
45978c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
45980a708f8fSGustavo F. Padovan 		goto drop;
45990a708f8fSGustavo F. Padovan 	}
46000a708f8fSGustavo F. Padovan 
4601793c2f1cSAndrei Emeltchenko 	if (!__is_sframe(chan, control)) {
46020a708f8fSGustavo F. Padovan 		if (len < 0) {
46038c1d787bSGustavo F. Padovan 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
46040a708f8fSGustavo F. Padovan 			goto drop;
46050a708f8fSGustavo F. Padovan 		}
46060a708f8fSGustavo F. Padovan 
4607525cd185SGustavo F. Padovan 		l2cap_data_channel_iframe(chan, control, skb);
46080a708f8fSGustavo F. Padovan 	} else {
46090a708f8fSGustavo F. Padovan 		if (len != 0) {
46100a708f8fSGustavo F. Padovan 			BT_ERR("%d", len);
46118c1d787bSGustavo F. Padovan 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
46120a708f8fSGustavo F. Padovan 			goto drop;
46130a708f8fSGustavo F. Padovan 		}
46140a708f8fSGustavo F. Padovan 
4615525cd185SGustavo F. Padovan 		l2cap_data_channel_sframe(chan, control, skb);
46160a708f8fSGustavo F. Padovan 	}
46170a708f8fSGustavo F. Padovan 
46180a708f8fSGustavo F. Padovan 	return 0;
46190a708f8fSGustavo F. Padovan 
46200a708f8fSGustavo F. Padovan drop:
46210a708f8fSGustavo F. Padovan 	kfree_skb(skb);
46220a708f8fSGustavo F. Padovan 	return 0;
46230a708f8fSGustavo F. Padovan }
46240a708f8fSGustavo F. Padovan 
46250a708f8fSGustavo F. Padovan static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
46260a708f8fSGustavo F. Padovan {
462748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
462888843ab0SAndrei Emeltchenko 	u32 control;
4629fb45de7dSAndrei Emeltchenko 	u16 tx_seq;
46300a708f8fSGustavo F. Padovan 	int len;
46310a708f8fSGustavo F. Padovan 
4632baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, cid);
463348454079SGustavo F. Padovan 	if (!chan) {
46340a708f8fSGustavo F. Padovan 		BT_DBG("unknown cid 0x%4.4x", cid);
46356be36555SAndrei Emeltchenko 		/* Drop packet and return */
46363379013bSDan Carpenter 		kfree_skb(skb);
46376be36555SAndrei Emeltchenko 		return 0;
46380a708f8fSGustavo F. Padovan 	}
46390a708f8fSGustavo F. Padovan 
464049208c9cSGustavo F. Padovan 	BT_DBG("chan %p, len %d", chan, skb->len);
46410a708f8fSGustavo F. Padovan 
464289bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
46430a708f8fSGustavo F. Padovan 		goto drop;
46440a708f8fSGustavo F. Padovan 
46450c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
46460a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
46470a708f8fSGustavo F. Padovan 		/* If socket recv buffers overflows we drop data here
46480a708f8fSGustavo F. Padovan 		 * which is *bad* because L2CAP has to be reliable.
46490a708f8fSGustavo F. Padovan 		 * But we don't have any other choice. L2CAP doesn't
46500a708f8fSGustavo F. Padovan 		 * provide flow control mechanism. */
46510a708f8fSGustavo F. Padovan 
46520c1bc5c6SGustavo F. Padovan 		if (chan->imtu < skb->len)
46530a708f8fSGustavo F. Padovan 			goto drop;
46540a708f8fSGustavo F. Padovan 
465523070494SGustavo F. Padovan 		if (!chan->ops->recv(chan->data, skb))
46560a708f8fSGustavo F. Padovan 			goto done;
46570a708f8fSGustavo F. Padovan 		break;
46580a708f8fSGustavo F. Padovan 
46590a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
46605ef8cb9eSAndrei Emeltchenko 		l2cap_ertm_data_rcv(chan, skb);
46610a708f8fSGustavo F. Padovan 
46620a708f8fSGustavo F. Padovan 		goto done;
46630a708f8fSGustavo F. Padovan 
46640a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
466588843ab0SAndrei Emeltchenko 		control = __get_control(chan, skb->data);
466688843ab0SAndrei Emeltchenko 		skb_pull(skb, __ctrl_size(chan));
46670a708f8fSGustavo F. Padovan 		len = skb->len;
46680a708f8fSGustavo F. Padovan 
466947d1ec61SGustavo F. Padovan 		if (l2cap_check_fcs(chan, skb))
46700a708f8fSGustavo F. Padovan 			goto drop;
46710a708f8fSGustavo F. Padovan 
46727e0ef6eeSAndrei Emeltchenko 		if (__is_sar_start(chan, control))
467303a51213SAndrei Emeltchenko 			len -= L2CAP_SDULEN_SIZE;
46740a708f8fSGustavo F. Padovan 
467547d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16)
467603a51213SAndrei Emeltchenko 			len -= L2CAP_FCS_SIZE;
46770a708f8fSGustavo F. Padovan 
4678793c2f1cSAndrei Emeltchenko 		if (len > chan->mps || len < 0 || __is_sframe(chan, control))
46790a708f8fSGustavo F. Padovan 			goto drop;
46800a708f8fSGustavo F. Padovan 
4681fb45de7dSAndrei Emeltchenko 		tx_seq = __get_txseq(chan, control);
46820a708f8fSGustavo F. Padovan 
468384084a31SMat Martineau 		if (chan->expected_tx_seq != tx_seq) {
468484084a31SMat Martineau 			/* Frame(s) missing - must discard partial SDU */
468584084a31SMat Martineau 			kfree_skb(chan->sdu);
468684084a31SMat Martineau 			chan->sdu = NULL;
468784084a31SMat Martineau 			chan->sdu_last_frag = NULL;
468884084a31SMat Martineau 			chan->sdu_len = 0;
468984084a31SMat Martineau 
469084084a31SMat Martineau 			/* TODO: Notify userland of missing data */
469184084a31SMat Martineau 		}
469284084a31SMat Martineau 
4693836be934SAndrei Emeltchenko 		chan->expected_tx_seq = __next_seq(chan, tx_seq);
46940a708f8fSGustavo F. Padovan 
469584084a31SMat Martineau 		if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
469684084a31SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
46970a708f8fSGustavo F. Padovan 
46980a708f8fSGustavo F. Padovan 		goto done;
46990a708f8fSGustavo F. Padovan 
47000a708f8fSGustavo F. Padovan 	default:
47010c1bc5c6SGustavo F. Padovan 		BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
47020a708f8fSGustavo F. Padovan 		break;
47030a708f8fSGustavo F. Padovan 	}
47040a708f8fSGustavo F. Padovan 
47050a708f8fSGustavo F. Padovan drop:
47060a708f8fSGustavo F. Padovan 	kfree_skb(skb);
47070a708f8fSGustavo F. Padovan 
47080a708f8fSGustavo F. Padovan done:
47096be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
47100a708f8fSGustavo F. Padovan 
47110a708f8fSGustavo F. Padovan 	return 0;
47120a708f8fSGustavo F. Padovan }
47130a708f8fSGustavo F. Padovan 
47140a708f8fSGustavo F. Padovan static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
47150a708f8fSGustavo F. Padovan {
471623691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
47170a708f8fSGustavo F. Padovan 
4718c2287681SIdo Yariv 	chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst);
471923691d75SGustavo F. Padovan 	if (!chan)
47200a708f8fSGustavo F. Padovan 		goto drop;
47210a708f8fSGustavo F. Padovan 
47225b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
47230a708f8fSGustavo F. Padovan 
472489bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
47250a708f8fSGustavo F. Padovan 		goto drop;
47260a708f8fSGustavo F. Padovan 
4727e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
47280a708f8fSGustavo F. Padovan 		goto drop;
47290a708f8fSGustavo F. Padovan 
473023070494SGustavo F. Padovan 	if (!chan->ops->recv(chan->data, skb))
47315b4cedaaSAndrei Emeltchenko 		return 0;
47320a708f8fSGustavo F. Padovan 
47330a708f8fSGustavo F. Padovan drop:
47340a708f8fSGustavo F. Padovan 	kfree_skb(skb);
47350a708f8fSGustavo F. Padovan 
47360a708f8fSGustavo F. Padovan 	return 0;
47370a708f8fSGustavo F. Padovan }
47380a708f8fSGustavo F. Padovan 
4739d9b88702SAndrei Emeltchenko static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid,
4740d9b88702SAndrei Emeltchenko 				    struct sk_buff *skb)
47419f69bda6SGustavo F. Padovan {
474223691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
47439f69bda6SGustavo F. Padovan 
4744c2287681SIdo Yariv 	chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst);
474523691d75SGustavo F. Padovan 	if (!chan)
47469f69bda6SGustavo F. Padovan 		goto drop;
47479f69bda6SGustavo F. Padovan 
47485b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
47499f69bda6SGustavo F. Padovan 
475089bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
47519f69bda6SGustavo F. Padovan 		goto drop;
47529f69bda6SGustavo F. Padovan 
4753e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
47549f69bda6SGustavo F. Padovan 		goto drop;
47559f69bda6SGustavo F. Padovan 
475623070494SGustavo F. Padovan 	if (!chan->ops->recv(chan->data, skb))
47575b4cedaaSAndrei Emeltchenko 		return 0;
47589f69bda6SGustavo F. Padovan 
47599f69bda6SGustavo F. Padovan drop:
47609f69bda6SGustavo F. Padovan 	kfree_skb(skb);
47619f69bda6SGustavo F. Padovan 
47629f69bda6SGustavo F. Padovan 	return 0;
47639f69bda6SGustavo F. Padovan }
47649f69bda6SGustavo F. Padovan 
47650a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
47660a708f8fSGustavo F. Padovan {
47670a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh = (void *) skb->data;
47680a708f8fSGustavo F. Padovan 	u16 cid, len;
47690a708f8fSGustavo F. Padovan 	__le16 psm;
47700a708f8fSGustavo F. Padovan 
47710a708f8fSGustavo F. Padovan 	skb_pull(skb, L2CAP_HDR_SIZE);
47720a708f8fSGustavo F. Padovan 	cid = __le16_to_cpu(lh->cid);
47730a708f8fSGustavo F. Padovan 	len = __le16_to_cpu(lh->len);
47740a708f8fSGustavo F. Padovan 
47750a708f8fSGustavo F. Padovan 	if (len != skb->len) {
47760a708f8fSGustavo F. Padovan 		kfree_skb(skb);
47770a708f8fSGustavo F. Padovan 		return;
47780a708f8fSGustavo F. Padovan 	}
47790a708f8fSGustavo F. Padovan 
47800a708f8fSGustavo F. Padovan 	BT_DBG("len %d, cid 0x%4.4x", len, cid);
47810a708f8fSGustavo F. Padovan 
47820a708f8fSGustavo F. Padovan 	switch (cid) {
47833300d9a9SClaudio Takahasi 	case L2CAP_CID_LE_SIGNALING:
47840a708f8fSGustavo F. Padovan 	case L2CAP_CID_SIGNALING:
47850a708f8fSGustavo F. Padovan 		l2cap_sig_channel(conn, skb);
47860a708f8fSGustavo F. Padovan 		break;
47870a708f8fSGustavo F. Padovan 
47880a708f8fSGustavo F. Padovan 	case L2CAP_CID_CONN_LESS:
4789097db76cSAndrei Emeltchenko 		psm = get_unaligned((__le16 *) skb->data);
47900a708f8fSGustavo F. Padovan 		skb_pull(skb, 2);
47910a708f8fSGustavo F. Padovan 		l2cap_conless_channel(conn, psm, skb);
47920a708f8fSGustavo F. Padovan 		break;
47930a708f8fSGustavo F. Padovan 
47949f69bda6SGustavo F. Padovan 	case L2CAP_CID_LE_DATA:
47959f69bda6SGustavo F. Padovan 		l2cap_att_channel(conn, cid, skb);
47969f69bda6SGustavo F. Padovan 		break;
47979f69bda6SGustavo F. Padovan 
4798b501d6a1SAnderson Briglia 	case L2CAP_CID_SMP:
4799b501d6a1SAnderson Briglia 		if (smp_sig_channel(conn, skb))
4800b501d6a1SAnderson Briglia 			l2cap_conn_del(conn->hcon, EACCES);
4801b501d6a1SAnderson Briglia 		break;
4802b501d6a1SAnderson Briglia 
48030a708f8fSGustavo F. Padovan 	default:
48040a708f8fSGustavo F. Padovan 		l2cap_data_channel(conn, cid, skb);
48050a708f8fSGustavo F. Padovan 		break;
48060a708f8fSGustavo F. Padovan 	}
48070a708f8fSGustavo F. Padovan }
48080a708f8fSGustavo F. Padovan 
48090a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
48100a708f8fSGustavo F. Padovan 
4811686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
48120a708f8fSGustavo F. Padovan {
48130a708f8fSGustavo F. Padovan 	int exact = 0, lm1 = 0, lm2 = 0;
481423691d75SGustavo F. Padovan 	struct l2cap_chan *c;
48150a708f8fSGustavo F. Padovan 
48160a708f8fSGustavo F. Padovan 	BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
48170a708f8fSGustavo F. Padovan 
48180a708f8fSGustavo F. Padovan 	/* Find listening sockets and check their link_mode */
481923691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
482023691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
482123691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
48224343478fSGustavo F. Padovan 
482389bc500eSGustavo F. Padovan 		if (c->state != BT_LISTEN)
48240a708f8fSGustavo F. Padovan 			continue;
48250a708f8fSGustavo F. Padovan 
48260a708f8fSGustavo F. Padovan 		if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
48270a708f8fSGustavo F. Padovan 			lm1 |= HCI_LM_ACCEPT;
482843bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
48290a708f8fSGustavo F. Padovan 				lm1 |= HCI_LM_MASTER;
48300a708f8fSGustavo F. Padovan 			exact++;
48310a708f8fSGustavo F. Padovan 		} else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
48320a708f8fSGustavo F. Padovan 			lm2 |= HCI_LM_ACCEPT;
483343bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
48340a708f8fSGustavo F. Padovan 				lm2 |= HCI_LM_MASTER;
48350a708f8fSGustavo F. Padovan 		}
48360a708f8fSGustavo F. Padovan 	}
483723691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
48380a708f8fSGustavo F. Padovan 
48390a708f8fSGustavo F. Padovan 	return exact ? lm1 : lm2;
48400a708f8fSGustavo F. Padovan }
48410a708f8fSGustavo F. Padovan 
4842686ebf28SUlisses Furquim int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
48430a708f8fSGustavo F. Padovan {
48440a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
48450a708f8fSGustavo F. Padovan 
48460a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
48470a708f8fSGustavo F. Padovan 
48480a708f8fSGustavo F. Padovan 	if (!status) {
48490a708f8fSGustavo F. Padovan 		conn = l2cap_conn_add(hcon, status);
48500a708f8fSGustavo F. Padovan 		if (conn)
48510a708f8fSGustavo F. Padovan 			l2cap_conn_ready(conn);
48520a708f8fSGustavo F. Padovan 	} else
4853e175072fSJoe Perches 		l2cap_conn_del(hcon, bt_to_errno(status));
48540a708f8fSGustavo F. Padovan 
48550a708f8fSGustavo F. Padovan 	return 0;
48560a708f8fSGustavo F. Padovan }
48570a708f8fSGustavo F. Padovan 
4858686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
48590a708f8fSGustavo F. Padovan {
48600a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
48610a708f8fSGustavo F. Padovan 
48620a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p", hcon);
48630a708f8fSGustavo F. Padovan 
4864686ebf28SUlisses Furquim 	if (!conn)
48659f5a0d7bSAndrei Emeltchenko 		return HCI_ERROR_REMOTE_USER_TERM;
48660a708f8fSGustavo F. Padovan 	return conn->disc_reason;
48670a708f8fSGustavo F. Padovan }
48680a708f8fSGustavo F. Padovan 
4869686ebf28SUlisses Furquim int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
48700a708f8fSGustavo F. Padovan {
48710a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p reason %d", hcon, reason);
48720a708f8fSGustavo F. Padovan 
4873e175072fSJoe Perches 	l2cap_conn_del(hcon, bt_to_errno(reason));
48740a708f8fSGustavo F. Padovan 	return 0;
48750a708f8fSGustavo F. Padovan }
48760a708f8fSGustavo F. Padovan 
48774343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
48780a708f8fSGustavo F. Padovan {
4879715ec005SGustavo F. Padovan 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
48800a708f8fSGustavo F. Padovan 		return;
48810a708f8fSGustavo F. Padovan 
48820a708f8fSGustavo F. Padovan 	if (encrypt == 0x00) {
48834343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM) {
4884ba13ccd9SMarcel Holtmann 			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
48854343478fSGustavo F. Padovan 		} else if (chan->sec_level == BT_SECURITY_HIGH)
48860f852724SGustavo F. Padovan 			l2cap_chan_close(chan, ECONNREFUSED);
48870a708f8fSGustavo F. Padovan 	} else {
48884343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM)
4889c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
48900a708f8fSGustavo F. Padovan 	}
48910a708f8fSGustavo F. Padovan }
48920a708f8fSGustavo F. Padovan 
4893686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
48940a708f8fSGustavo F. Padovan {
48950a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
489648454079SGustavo F. Padovan 	struct l2cap_chan *chan;
48970a708f8fSGustavo F. Padovan 
48980a708f8fSGustavo F. Padovan 	if (!conn)
48990a708f8fSGustavo F. Padovan 		return 0;
49000a708f8fSGustavo F. Padovan 
49010a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
49020a708f8fSGustavo F. Padovan 
4903160dc6acSVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
490435d4adccSHemant Gupta 		if (!status && encrypt)
4905160dc6acSVinicius Costa Gomes 			smp_distribute_keys(conn, 0);
490617cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->security_timer);
4907160dc6acSVinicius Costa Gomes 	}
4908160dc6acSVinicius Costa Gomes 
49093df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
49100a708f8fSGustavo F. Padovan 
49113df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
49126be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
49130a708f8fSGustavo F. Padovan 
4914f1cb9af5SVinicius Costa Gomes 		BT_DBG("chan->scid %d", chan->scid);
4915f1cb9af5SVinicius Costa Gomes 
4916f1cb9af5SVinicius Costa Gomes 		if (chan->scid == L2CAP_CID_LE_DATA) {
4917f1cb9af5SVinicius Costa Gomes 			if (!status && encrypt) {
4918f1cb9af5SVinicius Costa Gomes 				chan->sec_level = hcon->sec_level;
4919cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
4920f1cb9af5SVinicius Costa Gomes 			}
4921f1cb9af5SVinicius Costa Gomes 
49226be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
4923f1cb9af5SVinicius Costa Gomes 			continue;
4924f1cb9af5SVinicius Costa Gomes 		}
4925f1cb9af5SVinicius Costa Gomes 
4926c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
49276be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
49280a708f8fSGustavo F. Padovan 			continue;
49290a708f8fSGustavo F. Padovan 		}
49300a708f8fSGustavo F. Padovan 
493189bc500eSGustavo F. Padovan 		if (!status && (chan->state == BT_CONNECTED ||
493289bc500eSGustavo F. Padovan 						chan->state == BT_CONFIG)) {
4933a7d7723aSGustavo Padovan 			struct sock *sk = chan->sk;
4934a7d7723aSGustavo Padovan 
4935c5daa683SGustavo Padovan 			clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
4936a7d7723aSGustavo Padovan 			sk->sk_state_change(sk);
4937a7d7723aSGustavo Padovan 
49384343478fSGustavo F. Padovan 			l2cap_check_encryption(chan, encrypt);
49396be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
49400a708f8fSGustavo F. Padovan 			continue;
49410a708f8fSGustavo F. Padovan 		}
49420a708f8fSGustavo F. Padovan 
494389bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
49440a708f8fSGustavo F. Padovan 			if (!status) {
49459b27f350SAndrei Emeltchenko 				l2cap_send_conn_req(chan);
49460a708f8fSGustavo F. Padovan 			} else {
4947ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
49480a708f8fSGustavo F. Padovan 			}
494989bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
49506be36555SAndrei Emeltchenko 			struct sock *sk = chan->sk;
49510a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
4952df3c3931SJohan Hedberg 			__u16 res, stat;
49530a708f8fSGustavo F. Padovan 
49546be36555SAndrei Emeltchenko 			lock_sock(sk);
49556be36555SAndrei Emeltchenko 
49560a708f8fSGustavo F. Padovan 			if (!status) {
4957c5daa683SGustavo Padovan 				if (test_bit(BT_SK_DEFER_SETUP,
4958c5daa683SGustavo Padovan 					     &bt_sk(sk)->flags)) {
4959df3c3931SJohan Hedberg 					struct sock *parent = bt_sk(sk)->parent;
4960df3c3931SJohan Hedberg 					res = L2CAP_CR_PEND;
4961df3c3931SJohan Hedberg 					stat = L2CAP_CS_AUTHOR_PEND;
496205e9a2f6SIlia Kolomisnky 					if (parent)
4963df3c3931SJohan Hedberg 						parent->sk_data_ready(parent, 0);
4964df3c3931SJohan Hedberg 				} else {
49650e587be7SAndrei Emeltchenko 					__l2cap_state_change(chan, BT_CONFIG);
4966df3c3931SJohan Hedberg 					res = L2CAP_CR_SUCCESS;
4967df3c3931SJohan Hedberg 					stat = L2CAP_CS_NO_INFO;
4968df3c3931SJohan Hedberg 				}
49690a708f8fSGustavo F. Padovan 			} else {
49700e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_DISCONN);
4971ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
4972df3c3931SJohan Hedberg 				res = L2CAP_CR_SEC_BLOCK;
4973df3c3931SJohan Hedberg 				stat = L2CAP_CS_NO_INFO;
49740a708f8fSGustavo F. Padovan 			}
49750a708f8fSGustavo F. Padovan 
49766be36555SAndrei Emeltchenko 			release_sock(sk);
49776be36555SAndrei Emeltchenko 
4978fe4128e0SGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
4979fe4128e0SGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
4980df3c3931SJohan Hedberg 			rsp.result = cpu_to_le16(res);
4981df3c3931SJohan Hedberg 			rsp.status = cpu_to_le16(stat);
4982fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4983fc7f8a7eSGustavo F. Padovan 							sizeof(rsp), &rsp);
49840a708f8fSGustavo F. Padovan 		}
49850a708f8fSGustavo F. Padovan 
49866be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
49870a708f8fSGustavo F. Padovan 	}
49880a708f8fSGustavo F. Padovan 
49893df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
49900a708f8fSGustavo F. Padovan 
49910a708f8fSGustavo F. Padovan 	return 0;
49920a708f8fSGustavo F. Padovan }
49930a708f8fSGustavo F. Padovan 
4994686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
49950a708f8fSGustavo F. Padovan {
49960a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
49970a708f8fSGustavo F. Padovan 
49980a708f8fSGustavo F. Padovan 	if (!conn)
49990a708f8fSGustavo F. Padovan 		conn = l2cap_conn_add(hcon, 0);
50000a708f8fSGustavo F. Padovan 
50010a708f8fSGustavo F. Padovan 	if (!conn)
50020a708f8fSGustavo F. Padovan 		goto drop;
50030a708f8fSGustavo F. Padovan 
50040a708f8fSGustavo F. Padovan 	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
50050a708f8fSGustavo F. Padovan 
50060a708f8fSGustavo F. Padovan 	if (!(flags & ACL_CONT)) {
50070a708f8fSGustavo F. Padovan 		struct l2cap_hdr *hdr;
50080a708f8fSGustavo F. Padovan 		int len;
50090a708f8fSGustavo F. Padovan 
50100a708f8fSGustavo F. Padovan 		if (conn->rx_len) {
50110a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected start frame (len %d)", skb->len);
50120a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
50130a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
50140a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
50150a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
50160a708f8fSGustavo F. Padovan 		}
50170a708f8fSGustavo F. Padovan 
50180a708f8fSGustavo F. Padovan 		/* Start fragment always begin with Basic L2CAP header */
50190a708f8fSGustavo F. Padovan 		if (skb->len < L2CAP_HDR_SIZE) {
50200a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too short (len %d)", skb->len);
50210a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
50220a708f8fSGustavo F. Padovan 			goto drop;
50230a708f8fSGustavo F. Padovan 		}
50240a708f8fSGustavo F. Padovan 
50250a708f8fSGustavo F. Padovan 		hdr = (struct l2cap_hdr *) skb->data;
50260a708f8fSGustavo F. Padovan 		len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
50270a708f8fSGustavo F. Padovan 
50280a708f8fSGustavo F. Padovan 		if (len == skb->len) {
50290a708f8fSGustavo F. Padovan 			/* Complete frame received */
50300a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, skb);
50310a708f8fSGustavo F. Padovan 			return 0;
50320a708f8fSGustavo F. Padovan 		}
50330a708f8fSGustavo F. Padovan 
50340a708f8fSGustavo F. Padovan 		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
50350a708f8fSGustavo F. Padovan 
50360a708f8fSGustavo F. Padovan 		if (skb->len > len) {
50370a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too long (len %d, expected len %d)",
50380a708f8fSGustavo F. Padovan 				skb->len, len);
50390a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
50400a708f8fSGustavo F. Padovan 			goto drop;
50410a708f8fSGustavo F. Padovan 		}
50420a708f8fSGustavo F. Padovan 
50430a708f8fSGustavo F. Padovan 		/* Allocate skb for the complete frame (with header) */
50440a708f8fSGustavo F. Padovan 		conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
50450a708f8fSGustavo F. Padovan 		if (!conn->rx_skb)
50460a708f8fSGustavo F. Padovan 			goto drop;
50470a708f8fSGustavo F. Padovan 
50480a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
50490a708f8fSGustavo F. Padovan 								skb->len);
50500a708f8fSGustavo F. Padovan 		conn->rx_len = len - skb->len;
50510a708f8fSGustavo F. Padovan 	} else {
50520a708f8fSGustavo F. Padovan 		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
50530a708f8fSGustavo F. Padovan 
50540a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
50550a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
50560a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
50570a708f8fSGustavo F. Padovan 			goto drop;
50580a708f8fSGustavo F. Padovan 		}
50590a708f8fSGustavo F. Padovan 
50600a708f8fSGustavo F. Padovan 		if (skb->len > conn->rx_len) {
50610a708f8fSGustavo F. Padovan 			BT_ERR("Fragment is too long (len %d, expected %d)",
50620a708f8fSGustavo F. Padovan 					skb->len, conn->rx_len);
50630a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
50640a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
50650a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
50660a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
50670a708f8fSGustavo F. Padovan 			goto drop;
50680a708f8fSGustavo F. Padovan 		}
50690a708f8fSGustavo F. Padovan 
50700a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
50710a708f8fSGustavo F. Padovan 								skb->len);
50720a708f8fSGustavo F. Padovan 		conn->rx_len -= skb->len;
50730a708f8fSGustavo F. Padovan 
50740a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
50750a708f8fSGustavo F. Padovan 			/* Complete frame received */
50760a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, conn->rx_skb);
50770a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
50780a708f8fSGustavo F. Padovan 		}
50790a708f8fSGustavo F. Padovan 	}
50800a708f8fSGustavo F. Padovan 
50810a708f8fSGustavo F. Padovan drop:
50820a708f8fSGustavo F. Padovan 	kfree_skb(skb);
50830a708f8fSGustavo F. Padovan 	return 0;
50840a708f8fSGustavo F. Padovan }
50850a708f8fSGustavo F. Padovan 
50860a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
50870a708f8fSGustavo F. Padovan {
508823691d75SGustavo F. Padovan 	struct l2cap_chan *c;
50890a708f8fSGustavo F. Padovan 
5090333055f2SGustavo F. Padovan 	read_lock(&chan_list_lock);
50910a708f8fSGustavo F. Padovan 
509223691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
509323691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
50940a708f8fSGustavo F. Padovan 
5095903d343eSGustavo F. Padovan 		seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
50960a708f8fSGustavo F. Padovan 					batostr(&bt_sk(sk)->src),
50970a708f8fSGustavo F. Padovan 					batostr(&bt_sk(sk)->dst),
509889bc500eSGustavo F. Padovan 					c->state, __le16_to_cpu(c->psm),
509923691d75SGustavo F. Padovan 					c->scid, c->dcid, c->imtu, c->omtu,
510023691d75SGustavo F. Padovan 					c->sec_level, c->mode);
51010a708f8fSGustavo F. Padovan 	}
51020a708f8fSGustavo F. Padovan 
5103333055f2SGustavo F. Padovan 	read_unlock(&chan_list_lock);
51040a708f8fSGustavo F. Padovan 
51050a708f8fSGustavo F. Padovan 	return 0;
51060a708f8fSGustavo F. Padovan }
51070a708f8fSGustavo F. Padovan 
51080a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file)
51090a708f8fSGustavo F. Padovan {
51100a708f8fSGustavo F. Padovan 	return single_open(file, l2cap_debugfs_show, inode->i_private);
51110a708f8fSGustavo F. Padovan }
51120a708f8fSGustavo F. Padovan 
51130a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = {
51140a708f8fSGustavo F. Padovan 	.open		= l2cap_debugfs_open,
51150a708f8fSGustavo F. Padovan 	.read		= seq_read,
51160a708f8fSGustavo F. Padovan 	.llseek		= seq_lseek,
51170a708f8fSGustavo F. Padovan 	.release	= single_release,
51180a708f8fSGustavo F. Padovan };
51190a708f8fSGustavo F. Padovan 
51200a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
51210a708f8fSGustavo F. Padovan 
512264274518SGustavo F. Padovan int __init l2cap_init(void)
51230a708f8fSGustavo F. Padovan {
51240a708f8fSGustavo F. Padovan 	int err;
51250a708f8fSGustavo F. Padovan 
5126bb58f747SGustavo F. Padovan 	err = l2cap_init_sockets();
51270a708f8fSGustavo F. Padovan 	if (err < 0)
51280a708f8fSGustavo F. Padovan 		return err;
51290a708f8fSGustavo F. Padovan 
51300a708f8fSGustavo F. Padovan 	if (bt_debugfs) {
51310a708f8fSGustavo F. Padovan 		l2cap_debugfs = debugfs_create_file("l2cap", 0444,
51320a708f8fSGustavo F. Padovan 					bt_debugfs, NULL, &l2cap_debugfs_fops);
51330a708f8fSGustavo F. Padovan 		if (!l2cap_debugfs)
51340a708f8fSGustavo F. Padovan 			BT_ERR("Failed to create L2CAP debug file");
51350a708f8fSGustavo F. Padovan 	}
51360a708f8fSGustavo F. Padovan 
51370a708f8fSGustavo F. Padovan 	return 0;
51380a708f8fSGustavo F. Padovan }
51390a708f8fSGustavo F. Padovan 
514064274518SGustavo F. Padovan void l2cap_exit(void)
51410a708f8fSGustavo F. Padovan {
51420a708f8fSGustavo F. Padovan 	debugfs_remove(l2cap_debugfs);
5143bb58f747SGustavo F. Padovan 	l2cap_cleanup_sockets();
51440a708f8fSGustavo F. Padovan }
51450a708f8fSGustavo F. Padovan 
51460a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
51470a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
5148