xref: /openbmc/linux/net/bluetooth/l2cap_core.c (revision 61aa4f5b)
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 
76608bcc6dSMat Martineau static int l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
77608bcc6dSMat Martineau 		    struct sk_buff_head *skbs, u8 event);
78608bcc6dSMat Martineau 
790a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */
8071ba0e56SGustavo F. Padovan 
81baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
820a708f8fSGustavo F. Padovan {
833df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
84baa7e1faSGustavo F. Padovan 
853df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
863df91ea2SAndrei Emeltchenko 		if (c->dcid == cid)
873df91ea2SAndrei Emeltchenko 			return c;
880a708f8fSGustavo F. Padovan 	}
893df91ea2SAndrei Emeltchenko 	return NULL;
90baa7e1faSGustavo F. Padovan }
910a708f8fSGustavo F. Padovan 
92baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
930a708f8fSGustavo F. Padovan {
943df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
95baa7e1faSGustavo F. Padovan 
963df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
973df91ea2SAndrei Emeltchenko 		if (c->scid == cid)
983df91ea2SAndrei Emeltchenko 			return c;
990a708f8fSGustavo F. Padovan 	}
1003df91ea2SAndrei Emeltchenko 	return NULL;
101baa7e1faSGustavo F. Padovan }
1020a708f8fSGustavo F. Padovan 
1030a708f8fSGustavo F. Padovan /* Find channel with given SCID.
104ef191adeSMat Martineau  * Returns locked channel. */
105baa7e1faSGustavo F. Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
1060a708f8fSGustavo F. Padovan {
10748454079SGustavo F. Padovan 	struct l2cap_chan *c;
108baa7e1faSGustavo F. Padovan 
1093df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
110baa7e1faSGustavo F. Padovan 	c = __l2cap_get_chan_by_scid(conn, cid);
111ef191adeSMat Martineau 	if (c)
112ef191adeSMat Martineau 		l2cap_chan_lock(c);
1133df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
1143df91ea2SAndrei Emeltchenko 
11548454079SGustavo F. Padovan 	return c;
1160a708f8fSGustavo F. Padovan }
1170a708f8fSGustavo F. Padovan 
118baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
1190a708f8fSGustavo F. Padovan {
1203df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
121baa7e1faSGustavo F. Padovan 
1223df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1233df91ea2SAndrei Emeltchenko 		if (c->ident == ident)
1243df91ea2SAndrei Emeltchenko 			return c;
1250a708f8fSGustavo F. Padovan 	}
1263df91ea2SAndrei Emeltchenko 	return NULL;
127baa7e1faSGustavo F. Padovan }
1280a708f8fSGustavo F. Padovan 
12923691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
1309e4425ffSGustavo F. Padovan {
13123691d75SGustavo F. Padovan 	struct l2cap_chan *c;
1329e4425ffSGustavo F. Padovan 
13323691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
13423691d75SGustavo F. Padovan 		if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
13523691d75SGustavo F. Padovan 			return c;
1369e4425ffSGustavo F. Padovan 	}
137250938cbSSzymon Janc 	return NULL;
138250938cbSSzymon Janc }
1399e4425ffSGustavo F. Padovan 
1409e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
1419e4425ffSGustavo F. Padovan {
14273b2ec18SGustavo F. Padovan 	int err;
14373b2ec18SGustavo F. Padovan 
144333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1459e4425ffSGustavo F. Padovan 
14623691d75SGustavo F. Padovan 	if (psm && __l2cap_global_chan_by_addr(psm, src)) {
14773b2ec18SGustavo F. Padovan 		err = -EADDRINUSE;
14873b2ec18SGustavo F. Padovan 		goto done;
1499e4425ffSGustavo F. Padovan 	}
1509e4425ffSGustavo F. Padovan 
15173b2ec18SGustavo F. Padovan 	if (psm) {
1529e4425ffSGustavo F. Padovan 		chan->psm = psm;
1539e4425ffSGustavo F. Padovan 		chan->sport = psm;
15473b2ec18SGustavo F. Padovan 		err = 0;
15573b2ec18SGustavo F. Padovan 	} else {
15673b2ec18SGustavo F. Padovan 		u16 p;
1579e4425ffSGustavo F. Padovan 
15873b2ec18SGustavo F. Padovan 		err = -EINVAL;
15973b2ec18SGustavo F. Padovan 		for (p = 0x1001; p < 0x1100; p += 2)
16023691d75SGustavo F. Padovan 			if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
16173b2ec18SGustavo F. Padovan 				chan->psm   = cpu_to_le16(p);
16273b2ec18SGustavo F. Padovan 				chan->sport = cpu_to_le16(p);
16373b2ec18SGustavo F. Padovan 				err = 0;
16473b2ec18SGustavo F. Padovan 				break;
16573b2ec18SGustavo F. Padovan 			}
16673b2ec18SGustavo F. Padovan 	}
16773b2ec18SGustavo F. Padovan 
16873b2ec18SGustavo F. Padovan done:
169333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
17073b2ec18SGustavo F. Padovan 	return err;
1719e4425ffSGustavo F. Padovan }
1729e4425ffSGustavo F. Padovan 
1739e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
1749e4425ffSGustavo F. Padovan {
175333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1769e4425ffSGustavo F. Padovan 
1779e4425ffSGustavo F. Padovan 	chan->scid = scid;
1789e4425ffSGustavo F. Padovan 
179333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
1809e4425ffSGustavo F. Padovan 
1819e4425ffSGustavo F. Padovan 	return 0;
1829e4425ffSGustavo F. Padovan }
1839e4425ffSGustavo F. Padovan 
184baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
1850a708f8fSGustavo F. Padovan {
1860a708f8fSGustavo F. Padovan 	u16 cid = L2CAP_CID_DYN_START;
1870a708f8fSGustavo F. Padovan 
1880a708f8fSGustavo F. Padovan 	for (; cid < L2CAP_CID_DYN_END; cid++) {
189baa7e1faSGustavo F. Padovan 		if (!__l2cap_get_chan_by_scid(conn, cid))
1900a708f8fSGustavo F. Padovan 			return cid;
1910a708f8fSGustavo F. Padovan 	}
1920a708f8fSGustavo F. Padovan 
1930a708f8fSGustavo F. Padovan 	return 0;
1940a708f8fSGustavo F. Padovan }
1950a708f8fSGustavo F. Padovan 
1960e587be7SAndrei Emeltchenko static void __l2cap_state_change(struct l2cap_chan *chan, int state)
19789bc500eSGustavo F. Padovan {
19842d2d87cSAndrei Emeltchenko 	BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
199badaaa00SGustavo F. Padovan 						state_to_string(state));
200badaaa00SGustavo F. Padovan 
20189bc500eSGustavo F. Padovan 	chan->state = state;
20289bc500eSGustavo F. Padovan 	chan->ops->state_change(chan->data, state);
20389bc500eSGustavo F. Padovan }
20489bc500eSGustavo F. Padovan 
2050e587be7SAndrei Emeltchenko static void l2cap_state_change(struct l2cap_chan *chan, int state)
2060e587be7SAndrei Emeltchenko {
2070e587be7SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2080e587be7SAndrei Emeltchenko 
2090e587be7SAndrei Emeltchenko 	lock_sock(sk);
2100e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, state);
2110e587be7SAndrei Emeltchenko 	release_sock(sk);
2120e587be7SAndrei Emeltchenko }
2130e587be7SAndrei Emeltchenko 
2142e0052e4SAndrei Emeltchenko static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2152e0052e4SAndrei Emeltchenko {
2162e0052e4SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2172e0052e4SAndrei Emeltchenko 
2182e0052e4SAndrei Emeltchenko 	sk->sk_err = err;
2192e0052e4SAndrei Emeltchenko }
2202e0052e4SAndrei Emeltchenko 
2212e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2222e0052e4SAndrei Emeltchenko {
2232e0052e4SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2242e0052e4SAndrei Emeltchenko 
2252e0052e4SAndrei Emeltchenko 	lock_sock(sk);
2262e0052e4SAndrei Emeltchenko 	__l2cap_chan_set_err(chan, err);
2272e0052e4SAndrei Emeltchenko 	release_sock(sk);
2282e0052e4SAndrei Emeltchenko }
2292e0052e4SAndrei Emeltchenko 
230608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head,
231608bcc6dSMat Martineau 					       u16 seq)
232608bcc6dSMat Martineau {
233608bcc6dSMat Martineau 	struct sk_buff *skb;
234608bcc6dSMat Martineau 
235608bcc6dSMat Martineau 	skb_queue_walk(head, skb) {
236608bcc6dSMat Martineau 		if (bt_cb(skb)->control.txseq == seq)
237608bcc6dSMat Martineau 			return skb;
238608bcc6dSMat Martineau 	}
239608bcc6dSMat Martineau 
240608bcc6dSMat Martineau 	return NULL;
241608bcc6dSMat Martineau }
242608bcc6dSMat Martineau 
2433c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */
2443c588192SMat Martineau 
2453c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for
2463c588192SMat Martineau  * SREJ requests that are received and for frames that are to be
2473c588192SMat Martineau  * retransmitted. These seq_list functions implement a singly-linked
2483c588192SMat Martineau  * list in an array, where membership in the list can also be checked
2493c588192SMat Martineau  * in constant time. Items can also be added to the tail of the list
2503c588192SMat Martineau  * and removed from the head in constant time, without further memory
2513c588192SMat Martineau  * allocs or frees.
2523c588192SMat Martineau  */
2533c588192SMat Martineau 
2543c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
2553c588192SMat Martineau {
2563c588192SMat Martineau 	size_t alloc_size, i;
2573c588192SMat Martineau 
2583c588192SMat Martineau 	/* Allocated size is a power of 2 to map sequence numbers
2593c588192SMat Martineau 	 * (which may be up to 14 bits) in to a smaller array that is
2603c588192SMat Martineau 	 * sized for the negotiated ERTM transmit windows.
2613c588192SMat Martineau 	 */
2623c588192SMat Martineau 	alloc_size = roundup_pow_of_two(size);
2633c588192SMat Martineau 
2643c588192SMat Martineau 	seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL);
2653c588192SMat Martineau 	if (!seq_list->list)
2663c588192SMat Martineau 		return -ENOMEM;
2673c588192SMat Martineau 
2683c588192SMat Martineau 	seq_list->mask = alloc_size - 1;
2693c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
2703c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
2713c588192SMat Martineau 	for (i = 0; i < alloc_size; i++)
2723c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
2733c588192SMat Martineau 
2743c588192SMat Martineau 	return 0;
2753c588192SMat Martineau }
2763c588192SMat Martineau 
2773c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
2783c588192SMat Martineau {
2793c588192SMat Martineau 	kfree(seq_list->list);
2803c588192SMat Martineau }
2813c588192SMat Martineau 
2823c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
2833c588192SMat Martineau 					   u16 seq)
2843c588192SMat Martineau {
2853c588192SMat Martineau 	/* Constant-time check for list membership */
2863c588192SMat Martineau 	return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
2873c588192SMat Martineau }
2883c588192SMat Martineau 
2893c588192SMat Martineau static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq)
2903c588192SMat Martineau {
2913c588192SMat Martineau 	u16 mask = seq_list->mask;
2923c588192SMat Martineau 
2933c588192SMat Martineau 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) {
2943c588192SMat Martineau 		/* In case someone tries to pop the head of an empty list */
2953c588192SMat Martineau 		return L2CAP_SEQ_LIST_CLEAR;
2963c588192SMat Martineau 	} else if (seq_list->head == seq) {
2973c588192SMat Martineau 		/* Head can be removed in constant time */
2983c588192SMat Martineau 		seq_list->head = seq_list->list[seq & mask];
2993c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3003c588192SMat Martineau 
3013c588192SMat Martineau 		if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
3023c588192SMat Martineau 			seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3033c588192SMat Martineau 			seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3043c588192SMat Martineau 		}
3053c588192SMat Martineau 	} else {
3063c588192SMat Martineau 		/* Walk the list to find the sequence number */
3073c588192SMat Martineau 		u16 prev = seq_list->head;
3083c588192SMat Martineau 		while (seq_list->list[prev & mask] != seq) {
3093c588192SMat Martineau 			prev = seq_list->list[prev & mask];
3103c588192SMat Martineau 			if (prev == L2CAP_SEQ_LIST_TAIL)
3113c588192SMat Martineau 				return L2CAP_SEQ_LIST_CLEAR;
3123c588192SMat Martineau 		}
3133c588192SMat Martineau 
3143c588192SMat Martineau 		/* Unlink the number from the list and clear it */
3153c588192SMat Martineau 		seq_list->list[prev & mask] = seq_list->list[seq & mask];
3163c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3173c588192SMat Martineau 		if (seq_list->tail == seq)
3183c588192SMat Martineau 			seq_list->tail = prev;
3193c588192SMat Martineau 	}
3203c588192SMat Martineau 	return seq;
3213c588192SMat Martineau }
3223c588192SMat Martineau 
3233c588192SMat Martineau static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
3243c588192SMat Martineau {
3253c588192SMat Martineau 	/* Remove the head in constant time */
3263c588192SMat Martineau 	return l2cap_seq_list_remove(seq_list, seq_list->head);
3273c588192SMat Martineau }
3283c588192SMat Martineau 
3293c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
3303c588192SMat Martineau {
3313c588192SMat Martineau 	u16 i;
332f522ae36SGustavo Padovan 
333f522ae36SGustavo Padovan 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR)
334f522ae36SGustavo Padovan 		return;
335f522ae36SGustavo Padovan 
3363c588192SMat Martineau 	for (i = 0; i <= seq_list->mask; i++)
3373c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3383c588192SMat Martineau 
3393c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3403c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3413c588192SMat Martineau }
3423c588192SMat Martineau 
3433c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
3443c588192SMat Martineau {
3453c588192SMat Martineau 	u16 mask = seq_list->mask;
3463c588192SMat Martineau 
3473c588192SMat Martineau 	/* All appends happen in constant time */
3483c588192SMat Martineau 
349f522ae36SGustavo Padovan 	if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR)
350f522ae36SGustavo Padovan 		return;
351f522ae36SGustavo Padovan 
3523c588192SMat Martineau 	if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
3533c588192SMat Martineau 		seq_list->head = seq;
3543c588192SMat Martineau 	else
3553c588192SMat Martineau 		seq_list->list[seq_list->tail & mask] = seq;
3563c588192SMat Martineau 
3573c588192SMat Martineau 	seq_list->tail = seq;
3583c588192SMat Martineau 	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
3593c588192SMat Martineau }
3603c588192SMat Martineau 
361721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work)
362ab07801dSGustavo F. Padovan {
363721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
364721c4181SGustavo F. Padovan 							chan_timer.work);
3653df91ea2SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
366ab07801dSGustavo F. Padovan 	int reason;
367ab07801dSGustavo F. Padovan 
368e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
369ab07801dSGustavo F. Padovan 
3703df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
3716be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
372ab07801dSGustavo F. Padovan 
37389bc500eSGustavo F. Padovan 	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
374ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
37589bc500eSGustavo F. Padovan 	else if (chan->state == BT_CONNECT &&
376ab07801dSGustavo F. Padovan 					chan->sec_level != BT_SECURITY_SDP)
377ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
378ab07801dSGustavo F. Padovan 	else
379ab07801dSGustavo F. Padovan 		reason = ETIMEDOUT;
380ab07801dSGustavo F. Padovan 
3810f852724SGustavo F. Padovan 	l2cap_chan_close(chan, reason);
382ab07801dSGustavo F. Padovan 
3836be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
384ab07801dSGustavo F. Padovan 
385ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
3863df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
3873df91ea2SAndrei Emeltchenko 
388371fd835SUlisses Furquim 	l2cap_chan_put(chan);
389ab07801dSGustavo F. Padovan }
390ab07801dSGustavo F. Padovan 
391eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void)
3920a708f8fSGustavo F. Padovan {
39348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
3940a708f8fSGustavo F. Padovan 
39548454079SGustavo F. Padovan 	chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
39648454079SGustavo F. Padovan 	if (!chan)
39748454079SGustavo F. Padovan 		return NULL;
3980a708f8fSGustavo F. Padovan 
399c03b355eSAndrei Emeltchenko 	mutex_init(&chan->lock);
400c03b355eSAndrei Emeltchenko 
401333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
40223691d75SGustavo F. Padovan 	list_add(&chan->global_l, &chan_list);
403333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
40423691d75SGustavo F. Padovan 
405721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
406ab07801dSGustavo F. Padovan 
40789bc500eSGustavo F. Padovan 	chan->state = BT_OPEN;
40889bc500eSGustavo F. Padovan 
40971ba0e56SGustavo F. Padovan 	atomic_set(&chan->refcnt, 1);
41071ba0e56SGustavo F. Padovan 
4112827011fSMat Martineau 	/* This flag is cleared in l2cap_chan_ready() */
4122827011fSMat Martineau 	set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
4132827011fSMat Martineau 
414eef1d9b6SGustavo Padovan 	BT_DBG("chan %p", chan);
415abc545b8SSzymon Janc 
41648454079SGustavo F. Padovan 	return chan;
4170a708f8fSGustavo F. Padovan }
4180a708f8fSGustavo F. Padovan 
41923691d75SGustavo F. Padovan void l2cap_chan_destroy(struct l2cap_chan *chan)
4206ff5abbfSGustavo F. Padovan {
421333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
42223691d75SGustavo F. Padovan 	list_del(&chan->global_l);
423333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
42423691d75SGustavo F. Padovan 
425371fd835SUlisses Furquim 	l2cap_chan_put(chan);
4266ff5abbfSGustavo F. Padovan }
4276ff5abbfSGustavo F. Padovan 
428bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan)
429bd4b1653SAndrei Emeltchenko {
430bd4b1653SAndrei Emeltchenko 	chan->fcs  = L2CAP_FCS_CRC16;
431bd4b1653SAndrei Emeltchenko 	chan->max_tx = L2CAP_DEFAULT_MAX_TX;
432bd4b1653SAndrei Emeltchenko 	chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
433bd4b1653SAndrei Emeltchenko 	chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
434bd4b1653SAndrei Emeltchenko 	chan->sec_level = BT_SECURITY_LOW;
435bd4b1653SAndrei Emeltchenko 
436bd4b1653SAndrei Emeltchenko 	set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
437bd4b1653SAndrei Emeltchenko }
438bd4b1653SAndrei Emeltchenko 
43914a28491SAndrei Emeltchenko static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
4400a708f8fSGustavo F. Padovan {
4410a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
442097db76cSAndrei Emeltchenko 	       __le16_to_cpu(chan->psm), chan->dcid);
4430a708f8fSGustavo F. Padovan 
4449f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
4450a708f8fSGustavo F. Padovan 
4468c1d787bSGustavo F. Padovan 	chan->conn = conn;
4470a708f8fSGustavo F. Padovan 
4485491120eSAndrei Emeltchenko 	switch (chan->chan_type) {
4495491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_ORIENTED:
450b62f328bSVille Tervo 		if (conn->hcon->type == LE_LINK) {
451b62f328bSVille Tervo 			/* LE connection */
4520c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_LE_DEFAULT_MTU;
453fe4128e0SGustavo F. Padovan 			chan->scid = L2CAP_CID_LE_DATA;
454fe4128e0SGustavo F. Padovan 			chan->dcid = L2CAP_CID_LE_DATA;
455b62f328bSVille Tervo 		} else {
4560a708f8fSGustavo F. Padovan 			/* Alloc CID for connection-oriented socket */
457fe4128e0SGustavo F. Padovan 			chan->scid = l2cap_alloc_cid(conn);
4580c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_DEFAULT_MTU;
459b62f328bSVille Tervo 		}
4605491120eSAndrei Emeltchenko 		break;
4615491120eSAndrei Emeltchenko 
4625491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_LESS:
4630a708f8fSGustavo F. Padovan 		/* Connectionless socket */
464fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_CONN_LESS;
465fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_CONN_LESS;
4660c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
4675491120eSAndrei Emeltchenko 		break;
4685491120eSAndrei Emeltchenko 
4695491120eSAndrei Emeltchenko 	default:
4700a708f8fSGustavo F. Padovan 		/* Raw socket can send/recv signalling messages only */
471fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_SIGNALING;
472fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_SIGNALING;
4730c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
4740a708f8fSGustavo F. Padovan 	}
4750a708f8fSGustavo F. Padovan 
4768f7975b1SAndrei Emeltchenko 	chan->local_id		= L2CAP_BESTEFFORT_ID;
4778f7975b1SAndrei Emeltchenko 	chan->local_stype	= L2CAP_SERV_BESTEFFORT;
4788f7975b1SAndrei Emeltchenko 	chan->local_msdu	= L2CAP_DEFAULT_MAX_SDU_SIZE;
4798f7975b1SAndrei Emeltchenko 	chan->local_sdu_itime	= L2CAP_DEFAULT_SDU_ITIME;
4808f7975b1SAndrei Emeltchenko 	chan->local_acc_lat	= L2CAP_DEFAULT_ACC_LAT;
4818f7975b1SAndrei Emeltchenko 	chan->local_flush_to	= L2CAP_DEFAULT_FLUSH_TO;
4828f7975b1SAndrei Emeltchenko 
483371fd835SUlisses Furquim 	l2cap_chan_hold(chan);
484baa7e1faSGustavo F. Padovan 
4853df91ea2SAndrei Emeltchenko 	list_add(&chan->list, &conn->chan_l);
486643162a8SAndrei Emeltchenko }
487643162a8SAndrei Emeltchenko 
48814a28491SAndrei Emeltchenko static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
489643162a8SAndrei Emeltchenko {
490643162a8SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
491643162a8SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
4923df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
4930a708f8fSGustavo F. Padovan }
4940a708f8fSGustavo F. Padovan 
4954519de9aSGustavo F. Padovan static void l2cap_chan_del(struct l2cap_chan *chan, int err)
4960a708f8fSGustavo F. Padovan {
49748454079SGustavo F. Padovan 	struct sock *sk = chan->sk;
4988c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
4990a708f8fSGustavo F. Padovan 	struct sock *parent = bt_sk(sk)->parent;
5000a708f8fSGustavo F. Padovan 
501c9b66675SGustavo F. Padovan 	__clear_chan_timer(chan);
5020a708f8fSGustavo F. Padovan 
50349208c9cSGustavo F. Padovan 	BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
5040a708f8fSGustavo F. Padovan 
5050a708f8fSGustavo F. Padovan 	if (conn) {
506baa7e1faSGustavo F. Padovan 		/* Delete from channel list */
5073df91ea2SAndrei Emeltchenko 		list_del(&chan->list);
5083d57dc68SGustavo F. Padovan 
509371fd835SUlisses Furquim 		l2cap_chan_put(chan);
510baa7e1faSGustavo F. Padovan 
5118c1d787bSGustavo F. Padovan 		chan->conn = NULL;
5120a708f8fSGustavo F. Padovan 		hci_conn_put(conn->hcon);
5130a708f8fSGustavo F. Padovan 	}
5140a708f8fSGustavo F. Padovan 
5156be36555SAndrei Emeltchenko 	lock_sock(sk);
5166be36555SAndrei Emeltchenko 
5170e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_CLOSED);
5180a708f8fSGustavo F. Padovan 	sock_set_flag(sk, SOCK_ZAPPED);
5190a708f8fSGustavo F. Padovan 
5200a708f8fSGustavo F. Padovan 	if (err)
5212e0052e4SAndrei Emeltchenko 		__l2cap_chan_set_err(chan, err);
5220a708f8fSGustavo F. Padovan 
5230a708f8fSGustavo F. Padovan 	if (parent) {
5240a708f8fSGustavo F. Padovan 		bt_accept_unlink(sk);
5250a708f8fSGustavo F. Padovan 		parent->sk_data_ready(parent, 0);
5260a708f8fSGustavo F. Padovan 	} else
5270a708f8fSGustavo F. Padovan 		sk->sk_state_change(sk);
5280a708f8fSGustavo F. Padovan 
5296be36555SAndrei Emeltchenko 	release_sock(sk);
5306be36555SAndrei Emeltchenko 
5312827011fSMat Martineau 	if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
5326ff5abbfSGustavo F. Padovan 		return;
5332ead70b8SGustavo F. Padovan 
53458d35f87SGustavo F. Padovan 	skb_queue_purge(&chan->tx_q);
5350a708f8fSGustavo F. Padovan 
5360c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_ERTM) {
5371a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
5381a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
5391a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
5400a708f8fSGustavo F. Padovan 
541f1c6775bSGustavo F. Padovan 		skb_queue_purge(&chan->srej_q);
5420a708f8fSGustavo F. Padovan 
5433c588192SMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
5443c588192SMat Martineau 		l2cap_seq_list_free(&chan->retrans_list);
5450a708f8fSGustavo F. Padovan 	}
5460a708f8fSGustavo F. Padovan }
5470a708f8fSGustavo F. Padovan 
5484519de9aSGustavo F. Padovan static void l2cap_chan_cleanup_listen(struct sock *parent)
5494519de9aSGustavo F. Padovan {
5504519de9aSGustavo F. Padovan 	struct sock *sk;
5514519de9aSGustavo F. Padovan 
5524519de9aSGustavo F. Padovan 	BT_DBG("parent %p", parent);
5534519de9aSGustavo F. Padovan 
5544519de9aSGustavo F. Padovan 	/* Close not yet accepted channels */
5550f852724SGustavo F. Padovan 	while ((sk = bt_accept_dequeue(parent, NULL))) {
556ba3bd0eeSGustavo F. Padovan 		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
5573df91ea2SAndrei Emeltchenko 
5586be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
559c9b66675SGustavo F. Padovan 		__clear_chan_timer(chan);
560ba3bd0eeSGustavo F. Padovan 		l2cap_chan_close(chan, ECONNRESET);
5616be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
5623df91ea2SAndrei Emeltchenko 
563ba3bd0eeSGustavo F. Padovan 		chan->ops->close(chan->data);
5640f852724SGustavo F. Padovan 	}
5654519de9aSGustavo F. Padovan }
5664519de9aSGustavo F. Padovan 
5670f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason)
5684519de9aSGustavo F. Padovan {
5694519de9aSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
5704519de9aSGustavo F. Padovan 	struct sock *sk = chan->sk;
5714519de9aSGustavo F. Padovan 
572e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s sk %p", chan,
573e05dcc32SAndrei Emeltchenko 					state_to_string(chan->state), sk);
5744519de9aSGustavo F. Padovan 
57589bc500eSGustavo F. Padovan 	switch (chan->state) {
5764519de9aSGustavo F. Padovan 	case BT_LISTEN:
5776be36555SAndrei Emeltchenko 		lock_sock(sk);
5784519de9aSGustavo F. Padovan 		l2cap_chan_cleanup_listen(sk);
57989bc500eSGustavo F. Padovan 
5800e587be7SAndrei Emeltchenko 		__l2cap_state_change(chan, BT_CLOSED);
58189bc500eSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
5826be36555SAndrei Emeltchenko 		release_sock(sk);
5834519de9aSGustavo F. Padovan 		break;
5844519de9aSGustavo F. Padovan 
5854519de9aSGustavo F. Padovan 	case BT_CONNECTED:
5864519de9aSGustavo F. Padovan 	case BT_CONFIG:
587715ec005SGustavo F. Padovan 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
5884519de9aSGustavo F. Padovan 					conn->hcon->type == ACL_LINK) {
589c9b66675SGustavo F. Padovan 			__set_chan_timer(chan, sk->sk_sndtimeo);
5904519de9aSGustavo F. Padovan 			l2cap_send_disconn_req(conn, chan, reason);
5914519de9aSGustavo F. Padovan 		} else
5924519de9aSGustavo F. Padovan 			l2cap_chan_del(chan, reason);
5934519de9aSGustavo F. Padovan 		break;
5944519de9aSGustavo F. Padovan 
5954519de9aSGustavo F. Padovan 	case BT_CONNECT2:
596715ec005SGustavo F. Padovan 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
5974519de9aSGustavo F. Padovan 					conn->hcon->type == ACL_LINK) {
5984519de9aSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
5994519de9aSGustavo F. Padovan 			__u16 result;
6004519de9aSGustavo F. Padovan 
601c5daa683SGustavo Padovan 			if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))
6024519de9aSGustavo F. Padovan 				result = L2CAP_CR_SEC_BLOCK;
6034519de9aSGustavo F. Padovan 			else
6044519de9aSGustavo F. Padovan 				result = L2CAP_CR_BAD_PSM;
60589bc500eSGustavo F. Padovan 			l2cap_state_change(chan, BT_DISCONN);
6064519de9aSGustavo F. Padovan 
6074519de9aSGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
6084519de9aSGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
6094519de9aSGustavo F. Padovan 			rsp.result = cpu_to_le16(result);
6104519de9aSGustavo F. Padovan 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
6114519de9aSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
6124519de9aSGustavo F. Padovan 							sizeof(rsp), &rsp);
6134519de9aSGustavo F. Padovan 		}
6144519de9aSGustavo F. Padovan 
6154519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
6164519de9aSGustavo F. Padovan 		break;
6174519de9aSGustavo F. Padovan 
6184519de9aSGustavo F. Padovan 	case BT_CONNECT:
6194519de9aSGustavo F. Padovan 	case BT_DISCONN:
6204519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
6214519de9aSGustavo F. Padovan 		break;
6224519de9aSGustavo F. Padovan 
6234519de9aSGustavo F. Padovan 	default:
6246be36555SAndrei Emeltchenko 		lock_sock(sk);
6254519de9aSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
6266be36555SAndrei Emeltchenko 		release_sock(sk);
6274519de9aSGustavo F. Padovan 		break;
6284519de9aSGustavo F. Padovan 	}
6294519de9aSGustavo F. Padovan }
6304519de9aSGustavo F. Padovan 
6314343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
6320a708f8fSGustavo F. Padovan {
633715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_RAW) {
6344343478fSGustavo F. Padovan 		switch (chan->sec_level) {
6350a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
6360a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING_MITM;
6370a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
6380a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING;
6390a708f8fSGustavo F. Padovan 		default:
6400a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6410a708f8fSGustavo F. Padovan 		}
642fe4128e0SGustavo F. Padovan 	} else if (chan->psm == cpu_to_le16(0x0001)) {
6434343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_LOW)
6444343478fSGustavo F. Padovan 			chan->sec_level = BT_SECURITY_SDP;
6450a708f8fSGustavo F. Padovan 
6464343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_HIGH)
6470a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING_MITM;
6480a708f8fSGustavo F. Padovan 		else
6490a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6500a708f8fSGustavo F. Padovan 	} else {
6514343478fSGustavo F. Padovan 		switch (chan->sec_level) {
6520a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
6530a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING_MITM;
6540a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
6550a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING;
6560a708f8fSGustavo F. Padovan 		default:
6570a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6580a708f8fSGustavo F. Padovan 		}
6590a708f8fSGustavo F. Padovan 	}
6600a708f8fSGustavo F. Padovan }
6610a708f8fSGustavo F. Padovan 
6620a708f8fSGustavo F. Padovan /* Service level security */
663d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan)
6640a708f8fSGustavo F. Padovan {
6658c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
6660a708f8fSGustavo F. Padovan 	__u8 auth_type;
6670a708f8fSGustavo F. Padovan 
6684343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
6690a708f8fSGustavo F. Padovan 
6704343478fSGustavo F. Padovan 	return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
6710a708f8fSGustavo F. Padovan }
6720a708f8fSGustavo F. Padovan 
673b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn)
6740a708f8fSGustavo F. Padovan {
6750a708f8fSGustavo F. Padovan 	u8 id;
6760a708f8fSGustavo F. Padovan 
6770a708f8fSGustavo F. Padovan 	/* Get next available identificator.
6780a708f8fSGustavo F. Padovan 	 *    1 - 128 are used by kernel.
6790a708f8fSGustavo F. Padovan 	 *  129 - 199 are reserved.
6800a708f8fSGustavo F. Padovan 	 *  200 - 254 are used by utilities like l2ping, etc.
6810a708f8fSGustavo F. Padovan 	 */
6820a708f8fSGustavo F. Padovan 
683333055f2SGustavo F. Padovan 	spin_lock(&conn->lock);
6840a708f8fSGustavo F. Padovan 
6850a708f8fSGustavo F. Padovan 	if (++conn->tx_ident > 128)
6860a708f8fSGustavo F. Padovan 		conn->tx_ident = 1;
6870a708f8fSGustavo F. Padovan 
6880a708f8fSGustavo F. Padovan 	id = conn->tx_ident;
6890a708f8fSGustavo F. Padovan 
690333055f2SGustavo F. Padovan 	spin_unlock(&conn->lock);
6910a708f8fSGustavo F. Padovan 
6920a708f8fSGustavo F. Padovan 	return id;
6930a708f8fSGustavo F. Padovan }
6940a708f8fSGustavo F. Padovan 
6954519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
6960a708f8fSGustavo F. Padovan {
6970a708f8fSGustavo F. Padovan 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
6980a708f8fSGustavo F. Padovan 	u8 flags;
6990a708f8fSGustavo F. Padovan 
7000a708f8fSGustavo F. Padovan 	BT_DBG("code 0x%2.2x", code);
7010a708f8fSGustavo F. Padovan 
7020a708f8fSGustavo F. Padovan 	if (!skb)
7030a708f8fSGustavo F. Padovan 		return;
7040a708f8fSGustavo F. Padovan 
7050a708f8fSGustavo F. Padovan 	if (lmp_no_flush_capable(conn->hcon->hdev))
7060a708f8fSGustavo F. Padovan 		flags = ACL_START_NO_FLUSH;
7070a708f8fSGustavo F. Padovan 	else
7080a708f8fSGustavo F. Padovan 		flags = ACL_START;
7090a708f8fSGustavo F. Padovan 
71014b12d0bSJaikumar Ganesh 	bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
7115e59b791SLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
71214b12d0bSJaikumar Ganesh 
71373d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, flags);
7140a708f8fSGustavo F. Padovan }
7150a708f8fSGustavo F. Padovan 
71673d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
71773d80debSLuiz Augusto von Dentz {
71873d80debSLuiz Augusto von Dentz 	struct hci_conn *hcon = chan->conn->hcon;
71973d80debSLuiz Augusto von Dentz 	u16 flags;
72073d80debSLuiz Augusto von Dentz 
72173d80debSLuiz Augusto von Dentz 	BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
72273d80debSLuiz Augusto von Dentz 							skb->priority);
72373d80debSLuiz Augusto von Dentz 
72473d80debSLuiz Augusto von Dentz 	if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
72573d80debSLuiz Augusto von Dentz 					lmp_no_flush_capable(hcon->hdev))
72673d80debSLuiz Augusto von Dentz 		flags = ACL_START_NO_FLUSH;
72773d80debSLuiz Augusto von Dentz 	else
72873d80debSLuiz Augusto von Dentz 		flags = ACL_START;
72973d80debSLuiz Augusto von Dentz 
73073d80debSLuiz Augusto von Dentz 	bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
73173d80debSLuiz Augusto von Dentz 	hci_send_acl(chan->conn->hchan, skb, flags);
7320a708f8fSGustavo F. Padovan }
7330a708f8fSGustavo F. Padovan 
734b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
735b5c6aaedSMat Martineau {
736b5c6aaedSMat Martineau 	control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
737b5c6aaedSMat Martineau 	control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
738b5c6aaedSMat Martineau 
739b5c6aaedSMat Martineau 	if (enh & L2CAP_CTRL_FRAME_TYPE) {
740b5c6aaedSMat Martineau 		/* S-Frame */
741b5c6aaedSMat Martineau 		control->sframe = 1;
742b5c6aaedSMat Martineau 		control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
743b5c6aaedSMat Martineau 		control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
744b5c6aaedSMat Martineau 
745b5c6aaedSMat Martineau 		control->sar = 0;
746b5c6aaedSMat Martineau 		control->txseq = 0;
747b5c6aaedSMat Martineau 	} else {
748b5c6aaedSMat Martineau 		/* I-Frame */
749b5c6aaedSMat Martineau 		control->sframe = 0;
750b5c6aaedSMat Martineau 		control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
751b5c6aaedSMat Martineau 		control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
752b5c6aaedSMat Martineau 
753b5c6aaedSMat Martineau 		control->poll = 0;
754b5c6aaedSMat Martineau 		control->super = 0;
755b5c6aaedSMat Martineau 	}
756b5c6aaedSMat Martineau }
757b5c6aaedSMat Martineau 
758b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
759b5c6aaedSMat Martineau {
760b5c6aaedSMat Martineau 	control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
761b5c6aaedSMat Martineau 	control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
762b5c6aaedSMat Martineau 
763b5c6aaedSMat Martineau 	if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
764b5c6aaedSMat Martineau 		/* S-Frame */
765b5c6aaedSMat Martineau 		control->sframe = 1;
766b5c6aaedSMat Martineau 		control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
767b5c6aaedSMat Martineau 		control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
768b5c6aaedSMat Martineau 
769b5c6aaedSMat Martineau 		control->sar = 0;
770b5c6aaedSMat Martineau 		control->txseq = 0;
771b5c6aaedSMat Martineau 	} else {
772b5c6aaedSMat Martineau 		/* I-Frame */
773b5c6aaedSMat Martineau 		control->sframe = 0;
774b5c6aaedSMat Martineau 		control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
775b5c6aaedSMat Martineau 		control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
776b5c6aaedSMat Martineau 
777b5c6aaedSMat Martineau 		control->poll = 0;
778b5c6aaedSMat Martineau 		control->super = 0;
779b5c6aaedSMat Martineau 	}
780b5c6aaedSMat Martineau }
781b5c6aaedSMat Martineau 
782b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan,
783b5c6aaedSMat Martineau 				    struct sk_buff *skb)
784b5c6aaedSMat Martineau {
785b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
786b5c6aaedSMat Martineau 		__unpack_extended_control(get_unaligned_le32(skb->data),
787b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
788cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_EXT_CTRL_SIZE);
789b5c6aaedSMat Martineau 	} else {
790b5c6aaedSMat Martineau 		__unpack_enhanced_control(get_unaligned_le16(skb->data),
791b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
792cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_ENH_CTRL_SIZE);
793b5c6aaedSMat Martineau 	}
794b5c6aaedSMat Martineau }
795b5c6aaedSMat Martineau 
796b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control)
797b5c6aaedSMat Martineau {
798b5c6aaedSMat Martineau 	u32 packed;
799b5c6aaedSMat Martineau 
800b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
801b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
802b5c6aaedSMat Martineau 
803b5c6aaedSMat Martineau 	if (control->sframe) {
804b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
805b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
806b5c6aaedSMat Martineau 		packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
807b5c6aaedSMat Martineau 	} else {
808b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
809b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
810b5c6aaedSMat Martineau 	}
811b5c6aaedSMat Martineau 
812b5c6aaedSMat Martineau 	return packed;
813b5c6aaedSMat Martineau }
814b5c6aaedSMat Martineau 
815b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
816b5c6aaedSMat Martineau {
817b5c6aaedSMat Martineau 	u16 packed;
818b5c6aaedSMat Martineau 
819b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
820b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
821b5c6aaedSMat Martineau 
822b5c6aaedSMat Martineau 	if (control->sframe) {
823b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
824b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
825b5c6aaedSMat Martineau 		packed |= L2CAP_CTRL_FRAME_TYPE;
826b5c6aaedSMat Martineau 	} else {
827b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
828b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
829b5c6aaedSMat Martineau 	}
830b5c6aaedSMat Martineau 
831b5c6aaedSMat Martineau 	return packed;
832b5c6aaedSMat Martineau }
833b5c6aaedSMat Martineau 
834b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan,
835b5c6aaedSMat Martineau 				  struct l2cap_ctrl *control,
836b5c6aaedSMat Martineau 				  struct sk_buff *skb)
837b5c6aaedSMat Martineau {
838b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
839b5c6aaedSMat Martineau 		put_unaligned_le32(__pack_extended_control(control),
840b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
841b5c6aaedSMat Martineau 	} else {
842b5c6aaedSMat Martineau 		put_unaligned_le16(__pack_enhanced_control(control),
843b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
844b5c6aaedSMat Martineau 	}
845b5c6aaedSMat Martineau }
846b5c6aaedSMat Martineau 
847a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan,
848a67d7f6fSMat Martineau 					       u32 control)
8490a708f8fSGustavo F. Padovan {
8500a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
8510a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
852a67d7f6fSMat Martineau 	int hlen;
8530a708f8fSGustavo F. Padovan 
854e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
855e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_EXT_HDR_SIZE;
856e4ca6d98SAndrei Emeltchenko 	else
857e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_ENH_HDR_SIZE;
8580a708f8fSGustavo F. Padovan 
8590a708f8fSGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
86003a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
8610a708f8fSGustavo F. Padovan 
862a67d7f6fSMat Martineau 	skb = bt_skb_alloc(hlen, GFP_KERNEL);
8630a708f8fSGustavo F. Padovan 
8640a708f8fSGustavo F. Padovan 	if (!skb)
865a67d7f6fSMat Martineau 		return ERR_PTR(-ENOMEM);
8660a708f8fSGustavo F. Padovan 
8670a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
8680a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
869fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
87088843ab0SAndrei Emeltchenko 
871a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
872a67d7f6fSMat Martineau 		put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
873a67d7f6fSMat Martineau 	else
874a67d7f6fSMat Martineau 		put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
8750a708f8fSGustavo F. Padovan 
87647d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
877a67d7f6fSMat Martineau 		u16 fcs = crc16(0, (u8 *)skb->data, skb->len);
87803a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
8790a708f8fSGustavo F. Padovan 	}
8800a708f8fSGustavo F. Padovan 
88173d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
882a67d7f6fSMat Martineau 	return skb;
883a67d7f6fSMat Martineau }
884a67d7f6fSMat Martineau 
885a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan,
886a67d7f6fSMat Martineau 			      struct l2cap_ctrl *control)
887a67d7f6fSMat Martineau {
888a67d7f6fSMat Martineau 	struct sk_buff *skb;
889a67d7f6fSMat Martineau 	u32 control_field;
890a67d7f6fSMat Martineau 
891a67d7f6fSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
892a67d7f6fSMat Martineau 
893a67d7f6fSMat Martineau 	if (!control->sframe)
894a67d7f6fSMat Martineau 		return;
895a67d7f6fSMat Martineau 
896a67d7f6fSMat Martineau 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
897a67d7f6fSMat Martineau 	    !control->poll)
898a67d7f6fSMat Martineau 		control->final = 1;
899a67d7f6fSMat Martineau 
900a67d7f6fSMat Martineau 	if (control->super == L2CAP_SUPER_RR)
901a67d7f6fSMat Martineau 		clear_bit(CONN_RNR_SENT, &chan->conn_state);
902a67d7f6fSMat Martineau 	else if (control->super == L2CAP_SUPER_RNR)
903a67d7f6fSMat Martineau 		set_bit(CONN_RNR_SENT, &chan->conn_state);
904a67d7f6fSMat Martineau 
905a67d7f6fSMat Martineau 	if (control->super != L2CAP_SUPER_SREJ) {
906a67d7f6fSMat Martineau 		chan->last_acked_seq = control->reqseq;
907a67d7f6fSMat Martineau 		__clear_ack_timer(chan);
908a67d7f6fSMat Martineau 	}
909a67d7f6fSMat Martineau 
910a67d7f6fSMat Martineau 	BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq,
911a67d7f6fSMat Martineau 	       control->final, control->poll, control->super);
912a67d7f6fSMat Martineau 
913a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
914a67d7f6fSMat Martineau 		control_field = __pack_extended_control(control);
915a67d7f6fSMat Martineau 	else
916a67d7f6fSMat Martineau 		control_field = __pack_enhanced_control(control);
917a67d7f6fSMat Martineau 
918a67d7f6fSMat Martineau 	skb = l2cap_create_sframe_pdu(chan, control_field);
919a67d7f6fSMat Martineau 	if (!IS_ERR(skb))
92073d80debSLuiz Augusto von Dentz 		l2cap_do_send(chan, skb);
9210a708f8fSGustavo F. Padovan }
9220a708f8fSGustavo F. Padovan 
92388843ab0SAndrei Emeltchenko static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
9240a708f8fSGustavo F. Padovan {
925e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
926ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
927e2ab4353SGustavo F. Padovan 		set_bit(CONN_RNR_SENT, &chan->conn_state);
9280a708f8fSGustavo F. Padovan 	} else
929ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
9300a708f8fSGustavo F. Padovan 
9310b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
9320a708f8fSGustavo F. Padovan }
9330a708f8fSGustavo F. Padovan 
934b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
9350a708f8fSGustavo F. Padovan {
936c1360a1cSGustavo F. Padovan 	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
9370a708f8fSGustavo F. Padovan }
9380a708f8fSGustavo F. Padovan 
9399b27f350SAndrei Emeltchenko static void l2cap_send_conn_req(struct l2cap_chan *chan)
9409b27f350SAndrei Emeltchenko {
9419b27f350SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
9429b27f350SAndrei Emeltchenko 	struct l2cap_conn_req req;
9439b27f350SAndrei Emeltchenko 
9449b27f350SAndrei Emeltchenko 	req.scid = cpu_to_le16(chan->scid);
9459b27f350SAndrei Emeltchenko 	req.psm  = chan->psm;
9469b27f350SAndrei Emeltchenko 
9479b27f350SAndrei Emeltchenko 	chan->ident = l2cap_get_ident(conn);
9489b27f350SAndrei Emeltchenko 
9499b27f350SAndrei Emeltchenko 	set_bit(CONF_CONNECT_PEND, &chan->conf_state);
9509b27f350SAndrei Emeltchenko 
9519b27f350SAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
9529b27f350SAndrei Emeltchenko }
9539b27f350SAndrei Emeltchenko 
9549f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan)
9559f0caeb1SVinicius Costa Gomes {
9569f0caeb1SVinicius Costa Gomes 	struct sock *sk = chan->sk;
9579f0caeb1SVinicius Costa Gomes 	struct sock *parent;
9589f0caeb1SVinicius Costa Gomes 
9599f0caeb1SVinicius Costa Gomes 	lock_sock(sk);
9609f0caeb1SVinicius Costa Gomes 
9619f0caeb1SVinicius Costa Gomes 	parent = bt_sk(sk)->parent;
9629f0caeb1SVinicius Costa Gomes 
9639f0caeb1SVinicius Costa Gomes 	BT_DBG("sk %p, parent %p", sk, parent);
9649f0caeb1SVinicius Costa Gomes 
9652827011fSMat Martineau 	/* This clears all conf flags, including CONF_NOT_COMPLETE */
9669f0caeb1SVinicius Costa Gomes 	chan->conf_state = 0;
9679f0caeb1SVinicius Costa Gomes 	__clear_chan_timer(chan);
9689f0caeb1SVinicius Costa Gomes 
9699f0caeb1SVinicius Costa Gomes 	__l2cap_state_change(chan, BT_CONNECTED);
9709f0caeb1SVinicius Costa Gomes 	sk->sk_state_change(sk);
9719f0caeb1SVinicius Costa Gomes 
9729f0caeb1SVinicius Costa Gomes 	if (parent)
9739f0caeb1SVinicius Costa Gomes 		parent->sk_data_ready(parent, 0);
9749f0caeb1SVinicius Costa Gomes 
9759f0caeb1SVinicius Costa Gomes 	release_sock(sk);
9769f0caeb1SVinicius Costa Gomes }
9779f0caeb1SVinicius Costa Gomes 
978fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan)
9790a708f8fSGustavo F. Padovan {
9808c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
9810a708f8fSGustavo F. Padovan 
9829f0caeb1SVinicius Costa Gomes 	if (conn->hcon->type == LE_LINK) {
9839f0caeb1SVinicius Costa Gomes 		l2cap_chan_ready(chan);
9849f0caeb1SVinicius Costa Gomes 		return;
9859f0caeb1SVinicius Costa Gomes 	}
9869f0caeb1SVinicius Costa Gomes 
9870a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
9880a708f8fSGustavo F. Padovan 		if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
9890a708f8fSGustavo F. Padovan 			return;
9900a708f8fSGustavo F. Padovan 
991d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan) &&
9929b27f350SAndrei Emeltchenko 				__l2cap_no_conn_pending(chan))
9939b27f350SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
9940a708f8fSGustavo F. Padovan 	} else {
9950a708f8fSGustavo F. Padovan 		struct l2cap_info_req req;
9960a708f8fSGustavo F. Padovan 		req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
9970a708f8fSGustavo F. Padovan 
9980a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
9990a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
10000a708f8fSGustavo F. Padovan 
1001ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
10020a708f8fSGustavo F. Padovan 
10030a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, conn->info_ident,
10040a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(req), &req);
10050a708f8fSGustavo F. Padovan 	}
10060a708f8fSGustavo F. Padovan }
10070a708f8fSGustavo F. Padovan 
10080a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
10090a708f8fSGustavo F. Padovan {
10100a708f8fSGustavo F. Padovan 	u32 local_feat_mask = l2cap_feat_mask;
10110a708f8fSGustavo F. Padovan 	if (!disable_ertm)
10120a708f8fSGustavo F. Padovan 		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
10130a708f8fSGustavo F. Padovan 
10140a708f8fSGustavo F. Padovan 	switch (mode) {
10150a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
10160a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
10170a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
10180a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
10190a708f8fSGustavo F. Padovan 	default:
10200a708f8fSGustavo F. Padovan 		return 0x00;
10210a708f8fSGustavo F. Padovan 	}
10220a708f8fSGustavo F. Padovan }
10230a708f8fSGustavo F. Padovan 
10244519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
10250a708f8fSGustavo F. Padovan {
10266be36555SAndrei Emeltchenko 	struct sock *sk = chan->sk;
10270a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req req;
10280a708f8fSGustavo F. Padovan 
10290a708f8fSGustavo F. Padovan 	if (!conn)
10300a708f8fSGustavo F. Padovan 		return;
10310a708f8fSGustavo F. Padovan 
10320c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_ERTM) {
10331a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
10341a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
10351a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
10360a708f8fSGustavo F. Padovan 	}
10370a708f8fSGustavo F. Padovan 
1038fe4128e0SGustavo F. Padovan 	req.dcid = cpu_to_le16(chan->dcid);
1039fe4128e0SGustavo F. Padovan 	req.scid = cpu_to_le16(chan->scid);
10400a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn),
10410a708f8fSGustavo F. Padovan 			L2CAP_DISCONN_REQ, sizeof(req), &req);
10420a708f8fSGustavo F. Padovan 
10436be36555SAndrei Emeltchenko 	lock_sock(sk);
10440e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_DISCONN);
10452e0052e4SAndrei Emeltchenko 	__l2cap_chan_set_err(chan, err);
10466be36555SAndrei Emeltchenko 	release_sock(sk);
10470a708f8fSGustavo F. Padovan }
10480a708f8fSGustavo F. Padovan 
10490a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
10500a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
10510a708f8fSGustavo F. Padovan {
10523df91ea2SAndrei Emeltchenko 	struct l2cap_chan *chan, *tmp;
10530a708f8fSGustavo F. Padovan 
10540a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
10550a708f8fSGustavo F. Padovan 
10563df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
10570a708f8fSGustavo F. Padovan 
10583df91ea2SAndrei Emeltchenko 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
105948454079SGustavo F. Padovan 		struct sock *sk = chan->sk;
1060baa7e1faSGustavo F. Padovan 
10616be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
10620a708f8fSGustavo F. Padovan 
1063715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
10646be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
10650a708f8fSGustavo F. Padovan 			continue;
10660a708f8fSGustavo F. Padovan 		}
10670a708f8fSGustavo F. Padovan 
106889bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
1069d45fc423SGustavo F. Padovan 			if (!l2cap_chan_check_security(chan) ||
1070b4450035SGustavo F. Padovan 					!__l2cap_no_conn_pending(chan)) {
10716be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10720a708f8fSGustavo F. Padovan 				continue;
10730a708f8fSGustavo F. Padovan 			}
10740a708f8fSGustavo F. Padovan 
1075c1360a1cSGustavo F. Padovan 			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1076c1360a1cSGustavo F. Padovan 					&& test_bit(CONF_STATE2_DEVICE,
1077c1360a1cSGustavo F. Padovan 					&chan->conf_state)) {
10780f852724SGustavo F. Padovan 				l2cap_chan_close(chan, ECONNRESET);
10796be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10800a708f8fSGustavo F. Padovan 				continue;
10810a708f8fSGustavo F. Padovan 			}
10820a708f8fSGustavo F. Padovan 
10839b27f350SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
10840a708f8fSGustavo F. Padovan 
108589bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
10860a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
10870a708f8fSGustavo F. Padovan 			char buf[128];
1088fe4128e0SGustavo F. Padovan 			rsp.scid = cpu_to_le16(chan->dcid);
1089fe4128e0SGustavo F. Padovan 			rsp.dcid = cpu_to_le16(chan->scid);
10900a708f8fSGustavo F. Padovan 
1091d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan)) {
10926be36555SAndrei Emeltchenko 				lock_sock(sk);
1093c5daa683SGustavo Padovan 				if (test_bit(BT_SK_DEFER_SETUP,
1094c5daa683SGustavo Padovan 					     &bt_sk(sk)->flags)) {
10950a708f8fSGustavo F. Padovan 					struct sock *parent = bt_sk(sk)->parent;
10960a708f8fSGustavo F. Padovan 					rsp.result = cpu_to_le16(L2CAP_CR_PEND);
10970a708f8fSGustavo F. Padovan 					rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
109805e9a2f6SIlia Kolomisnky 					if (parent)
10990a708f8fSGustavo F. Padovan 						parent->sk_data_ready(parent, 0);
11000a708f8fSGustavo F. Padovan 
11010a708f8fSGustavo F. Padovan 				} else {
11020e587be7SAndrei Emeltchenko 					__l2cap_state_change(chan, BT_CONFIG);
11030a708f8fSGustavo F. Padovan 					rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
11040a708f8fSGustavo F. Padovan 					rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
11050a708f8fSGustavo F. Padovan 				}
11066be36555SAndrei Emeltchenko 				release_sock(sk);
11070a708f8fSGustavo F. Padovan 			} else {
11080a708f8fSGustavo F. Padovan 				rsp.result = cpu_to_le16(L2CAP_CR_PEND);
11090a708f8fSGustavo F. Padovan 				rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
11100a708f8fSGustavo F. Padovan 			}
11110a708f8fSGustavo F. Padovan 
1112fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1113fc7f8a7eSGustavo F. Padovan 							sizeof(rsp), &rsp);
11140a708f8fSGustavo F. Padovan 
1115c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
11160a708f8fSGustavo F. Padovan 					rsp.result != L2CAP_CR_SUCCESS) {
11176be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
11180a708f8fSGustavo F. Padovan 				continue;
11190a708f8fSGustavo F. Padovan 			}
11200a708f8fSGustavo F. Padovan 
1121c1360a1cSGustavo F. Padovan 			set_bit(CONF_REQ_SENT, &chan->conf_state);
11220a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
112373ffa904SGustavo F. Padovan 						l2cap_build_conf_req(chan, buf), buf);
112473ffa904SGustavo F. Padovan 			chan->num_conf_req++;
11250a708f8fSGustavo F. Padovan 		}
11260a708f8fSGustavo F. Padovan 
11276be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
11280a708f8fSGustavo F. Padovan 	}
11290a708f8fSGustavo F. Padovan 
11303df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
11310a708f8fSGustavo F. Padovan }
11320a708f8fSGustavo F. Padovan 
1133c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr.
1134b62f328bSVille Tervo  * Returns closest match, locked.
1135b62f328bSVille Tervo  */
1136d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
1137c2287681SIdo Yariv 						    bdaddr_t *src,
1138c2287681SIdo Yariv 						    bdaddr_t *dst)
1139b62f328bSVille Tervo {
114023691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
1141b62f328bSVille Tervo 
114223691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
1143b62f328bSVille Tervo 
114423691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
114523691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
1146fe4128e0SGustavo F. Padovan 
114789bc500eSGustavo F. Padovan 		if (state && c->state != state)
1148b62f328bSVille Tervo 			continue;
1149b62f328bSVille Tervo 
115023691d75SGustavo F. Padovan 		if (c->scid == cid) {
1151c2287681SIdo Yariv 			int src_match, dst_match;
1152c2287681SIdo Yariv 			int src_any, dst_any;
1153c2287681SIdo Yariv 
1154b62f328bSVille Tervo 			/* Exact match. */
1155c2287681SIdo Yariv 			src_match = !bacmp(&bt_sk(sk)->src, src);
1156c2287681SIdo Yariv 			dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1157c2287681SIdo Yariv 			if (src_match && dst_match) {
115823691d75SGustavo F. Padovan 				read_unlock(&chan_list_lock);
115923691d75SGustavo F. Padovan 				return c;
116023691d75SGustavo F. Padovan 			}
1161b62f328bSVille Tervo 
1162b62f328bSVille Tervo 			/* Closest match */
1163c2287681SIdo Yariv 			src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1164c2287681SIdo Yariv 			dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1165c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1166c2287681SIdo Yariv 			    (src_any && dst_any))
116723691d75SGustavo F. Padovan 				c1 = c;
1168b62f328bSVille Tervo 		}
1169b62f328bSVille Tervo 	}
1170280f294fSGustavo F. Padovan 
117123691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
1172b62f328bSVille Tervo 
117323691d75SGustavo F. Padovan 	return c1;
1174b62f328bSVille Tervo }
1175b62f328bSVille Tervo 
1176b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1177b62f328bSVille Tervo {
1178c916fbe4SGustavo F. Padovan 	struct sock *parent, *sk;
117923691d75SGustavo F. Padovan 	struct l2cap_chan *chan, *pchan;
1180b62f328bSVille Tervo 
1181b62f328bSVille Tervo 	BT_DBG("");
1182b62f328bSVille Tervo 
1183b62f328bSVille Tervo 	/* Check if we have socket listening on cid */
118423691d75SGustavo F. Padovan 	pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
1185c2287681SIdo Yariv 					  conn->src, conn->dst);
118623691d75SGustavo F. Padovan 	if (!pchan)
1187b62f328bSVille Tervo 		return;
1188b62f328bSVille Tervo 
118923691d75SGustavo F. Padovan 	parent = pchan->sk;
119023691d75SGustavo F. Padovan 
1191aa2ac881SGustavo F. Padovan 	lock_sock(parent);
119262f3a2cfSGustavo F. Padovan 
1193b62f328bSVille Tervo 	/* Check for backlog size */
1194b62f328bSVille Tervo 	if (sk_acceptq_is_full(parent)) {
1195b62f328bSVille Tervo 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
1196b62f328bSVille Tervo 		goto clean;
1197b62f328bSVille Tervo 	}
1198b62f328bSVille Tervo 
119980808e43SGustavo F. Padovan 	chan = pchan->ops->new_connection(pchan->data);
120080808e43SGustavo F. Padovan 	if (!chan)
1201b62f328bSVille Tervo 		goto clean;
1202b62f328bSVille Tervo 
120380808e43SGustavo F. Padovan 	sk = chan->sk;
12045d41ce1dSGustavo F. Padovan 
1205b62f328bSVille Tervo 	hci_conn_hold(conn->hcon);
1206b62f328bSVille Tervo 
1207b62f328bSVille Tervo 	bacpy(&bt_sk(sk)->src, conn->src);
1208b62f328bSVille Tervo 	bacpy(&bt_sk(sk)->dst, conn->dst);
1209b62f328bSVille Tervo 
1210d1010240SGustavo F. Padovan 	bt_accept_enqueue(parent, sk);
1211d1010240SGustavo F. Padovan 
12123d57dc68SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
121348454079SGustavo F. Padovan 
1214c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
1215b62f328bSVille Tervo 
12160e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_CONNECTED);
1217b62f328bSVille Tervo 	parent->sk_data_ready(parent, 0);
1218b62f328bSVille Tervo 
1219b62f328bSVille Tervo clean:
1220aa2ac881SGustavo F. Padovan 	release_sock(parent);
1221b62f328bSVille Tervo }
1222b62f328bSVille Tervo 
12230a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
12240a708f8fSGustavo F. Padovan {
122548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
12260a708f8fSGustavo F. Padovan 
12270a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
12280a708f8fSGustavo F. Padovan 
1229b62f328bSVille Tervo 	if (!conn->hcon->out && conn->hcon->type == LE_LINK)
1230b62f328bSVille Tervo 		l2cap_le_conn_ready(conn);
1231b62f328bSVille Tervo 
1232160dc6acSVinicius Costa Gomes 	if (conn->hcon->out && conn->hcon->type == LE_LINK)
1233160dc6acSVinicius Costa Gomes 		smp_conn_security(conn, conn->hcon->pending_sec_level);
1234160dc6acSVinicius Costa Gomes 
12353df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
12360a708f8fSGustavo F. Padovan 
12373df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1238baa7e1faSGustavo F. Padovan 
12396be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
12400a708f8fSGustavo F. Padovan 
124163128451SVinicius Costa Gomes 		if (conn->hcon->type == LE_LINK) {
1242b501d6a1SAnderson Briglia 			if (smp_conn_security(conn, chan->sec_level))
1243cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
1244acd7d370SVille Tervo 
124563128451SVinicius Costa Gomes 		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
12466be36555SAndrei Emeltchenko 			struct sock *sk = chan->sk;
1247c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
12486be36555SAndrei Emeltchenko 			lock_sock(sk);
12490e587be7SAndrei Emeltchenko 			__l2cap_state_change(chan, BT_CONNECTED);
12500a708f8fSGustavo F. Padovan 			sk->sk_state_change(sk);
12516be36555SAndrei Emeltchenko 			release_sock(sk);
1252b501d6a1SAnderson Briglia 
125389bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT)
1254fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
12550a708f8fSGustavo F. Padovan 
12566be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
12570a708f8fSGustavo F. Padovan 	}
12580a708f8fSGustavo F. Padovan 
12593df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12600a708f8fSGustavo F. Padovan }
12610a708f8fSGustavo F. Padovan 
12620a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
12630a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
12640a708f8fSGustavo F. Padovan {
126548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
12660a708f8fSGustavo F. Padovan 
12670a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
12680a708f8fSGustavo F. Padovan 
12693df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
12700a708f8fSGustavo F. Padovan 
12713df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1272ecf61bdbSAndrei Emeltchenko 		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
12732e0052e4SAndrei Emeltchenko 			__l2cap_chan_set_err(chan, err);
12740a708f8fSGustavo F. Padovan 	}
12750a708f8fSGustavo F. Padovan 
12763df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12770a708f8fSGustavo F. Padovan }
12780a708f8fSGustavo F. Padovan 
1279f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
12800a708f8fSGustavo F. Padovan {
1281f878fcadSGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1282030013d8SGustavo F. Padovan 							info_timer.work);
12830a708f8fSGustavo F. Padovan 
12840a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
12850a708f8fSGustavo F. Padovan 	conn->info_ident = 0;
12860a708f8fSGustavo F. Padovan 
12870a708f8fSGustavo F. Padovan 	l2cap_conn_start(conn);
12880a708f8fSGustavo F. Padovan }
12890a708f8fSGustavo F. Padovan 
12905d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
12915d3de7dfSVinicius Costa Gomes {
12925d3de7dfSVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
12935d3de7dfSVinicius Costa Gomes 	struct l2cap_chan *chan, *l;
12945d3de7dfSVinicius Costa Gomes 
12955d3de7dfSVinicius Costa Gomes 	if (!conn)
12965d3de7dfSVinicius Costa Gomes 		return;
12975d3de7dfSVinicius Costa Gomes 
12985d3de7dfSVinicius Costa Gomes 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
12995d3de7dfSVinicius Costa Gomes 
13005d3de7dfSVinicius Costa Gomes 	kfree_skb(conn->rx_skb);
13015d3de7dfSVinicius Costa Gomes 
13023df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
13033df91ea2SAndrei Emeltchenko 
13045d3de7dfSVinicius Costa Gomes 	/* Kill channels */
13055d3de7dfSVinicius Costa Gomes 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
130661d6ef3eSMat Martineau 		l2cap_chan_hold(chan);
13076be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
13086be36555SAndrei Emeltchenko 
13095d3de7dfSVinicius Costa Gomes 		l2cap_chan_del(chan, err);
13106be36555SAndrei Emeltchenko 
13116be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
13126be36555SAndrei Emeltchenko 
13135d3de7dfSVinicius Costa Gomes 		chan->ops->close(chan->data);
131461d6ef3eSMat Martineau 		l2cap_chan_put(chan);
13155d3de7dfSVinicius Costa Gomes 	}
13165d3de7dfSVinicius Costa Gomes 
13173df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
13183df91ea2SAndrei Emeltchenko 
131973d80debSLuiz Augusto von Dentz 	hci_chan_del(conn->hchan);
132073d80debSLuiz Augusto von Dentz 
13215d3de7dfSVinicius Costa Gomes 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1322127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->info_timer);
13235d3de7dfSVinicius Costa Gomes 
132451a8efd7SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
1325127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->security_timer);
13268aab4757SVinicius Costa Gomes 		smp_chan_destroy(conn);
1327d26a2345SVinicius Costa Gomes 	}
13285d3de7dfSVinicius Costa Gomes 
13295d3de7dfSVinicius Costa Gomes 	hcon->l2cap_data = NULL;
13305d3de7dfSVinicius Costa Gomes 	kfree(conn);
13315d3de7dfSVinicius Costa Gomes }
13325d3de7dfSVinicius Costa Gomes 
13336c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work)
13345d3de7dfSVinicius Costa Gomes {
13356c9d42a1SGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
13366c9d42a1SGustavo F. Padovan 						security_timer.work);
13375d3de7dfSVinicius Costa Gomes 
13385d3de7dfSVinicius Costa Gomes 	l2cap_conn_del(conn->hcon, ETIMEDOUT);
13395d3de7dfSVinicius Costa Gomes }
13405d3de7dfSVinicius Costa Gomes 
13410a708f8fSGustavo F. Padovan static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
13420a708f8fSGustavo F. Padovan {
13430a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
134473d80debSLuiz Augusto von Dentz 	struct hci_chan *hchan;
13450a708f8fSGustavo F. Padovan 
13460a708f8fSGustavo F. Padovan 	if (conn || status)
13470a708f8fSGustavo F. Padovan 		return conn;
13480a708f8fSGustavo F. Padovan 
134973d80debSLuiz Augusto von Dentz 	hchan = hci_chan_create(hcon);
135073d80debSLuiz Augusto von Dentz 	if (!hchan)
13510a708f8fSGustavo F. Padovan 		return NULL;
13520a708f8fSGustavo F. Padovan 
135373d80debSLuiz Augusto von Dentz 	conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
135473d80debSLuiz Augusto von Dentz 	if (!conn) {
135573d80debSLuiz Augusto von Dentz 		hci_chan_del(hchan);
135673d80debSLuiz Augusto von Dentz 		return NULL;
135773d80debSLuiz Augusto von Dentz 	}
135873d80debSLuiz Augusto von Dentz 
13590a708f8fSGustavo F. Padovan 	hcon->l2cap_data = conn;
13600a708f8fSGustavo F. Padovan 	conn->hcon = hcon;
136173d80debSLuiz Augusto von Dentz 	conn->hchan = hchan;
13620a708f8fSGustavo F. Padovan 
136373d80debSLuiz Augusto von Dentz 	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
13640a708f8fSGustavo F. Padovan 
1365acd7d370SVille Tervo 	if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1366acd7d370SVille Tervo 		conn->mtu = hcon->hdev->le_mtu;
1367acd7d370SVille Tervo 	else
13680a708f8fSGustavo F. Padovan 		conn->mtu = hcon->hdev->acl_mtu;
1369acd7d370SVille Tervo 
13700a708f8fSGustavo F. Padovan 	conn->src = &hcon->hdev->bdaddr;
13710a708f8fSGustavo F. Padovan 	conn->dst = &hcon->dst;
13720a708f8fSGustavo F. Padovan 
13730a708f8fSGustavo F. Padovan 	conn->feat_mask = 0;
13740a708f8fSGustavo F. Padovan 
13750a708f8fSGustavo F. Padovan 	spin_lock_init(&conn->lock);
13763df91ea2SAndrei Emeltchenko 	mutex_init(&conn->chan_lock);
1377baa7e1faSGustavo F. Padovan 
1378baa7e1faSGustavo F. Padovan 	INIT_LIST_HEAD(&conn->chan_l);
13790a708f8fSGustavo F. Padovan 
13805d3de7dfSVinicius Costa Gomes 	if (hcon->type == LE_LINK)
13816c9d42a1SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
13825d3de7dfSVinicius Costa Gomes 	else
1383030013d8SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
13840a708f8fSGustavo F. Padovan 
13859f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
13860a708f8fSGustavo F. Padovan 
13870a708f8fSGustavo F. Padovan 	return conn;
13880a708f8fSGustavo F. Padovan }
13890a708f8fSGustavo F. Padovan 
13900a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */
13910a708f8fSGustavo F. Padovan 
1392c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr.
13930a708f8fSGustavo F. Padovan  * Returns closest match.
13940a708f8fSGustavo F. Padovan  */
1395c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1396c2287681SIdo Yariv 						   bdaddr_t *src,
1397c2287681SIdo Yariv 						   bdaddr_t *dst)
13980a708f8fSGustavo F. Padovan {
139923691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
14000a708f8fSGustavo F. Padovan 
140123691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
14020a708f8fSGustavo F. Padovan 
140323691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
140423691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
1405fe4128e0SGustavo F. Padovan 
140689bc500eSGustavo F. Padovan 		if (state && c->state != state)
14070a708f8fSGustavo F. Padovan 			continue;
14080a708f8fSGustavo F. Padovan 
140923691d75SGustavo F. Padovan 		if (c->psm == psm) {
1410c2287681SIdo Yariv 			int src_match, dst_match;
1411c2287681SIdo Yariv 			int src_any, dst_any;
1412c2287681SIdo Yariv 
14130a708f8fSGustavo F. Padovan 			/* Exact match. */
1414c2287681SIdo Yariv 			src_match = !bacmp(&bt_sk(sk)->src, src);
1415c2287681SIdo Yariv 			dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1416c2287681SIdo Yariv 			if (src_match && dst_match) {
1417a7567b20SJohannes Berg 				read_unlock(&chan_list_lock);
141823691d75SGustavo F. Padovan 				return c;
141923691d75SGustavo F. Padovan 			}
14200a708f8fSGustavo F. Padovan 
14210a708f8fSGustavo F. Padovan 			/* Closest match */
1422c2287681SIdo Yariv 			src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1423c2287681SIdo Yariv 			dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1424c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1425c2287681SIdo Yariv 			    (src_any && dst_any))
142623691d75SGustavo F. Padovan 				c1 = c;
14270a708f8fSGustavo F. Padovan 		}
14280a708f8fSGustavo F. Padovan 	}
14290a708f8fSGustavo F. Padovan 
143023691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
14310a708f8fSGustavo F. Padovan 
143223691d75SGustavo F. Padovan 	return c1;
14330a708f8fSGustavo F. Padovan }
14340a708f8fSGustavo F. Padovan 
14358e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
14368e9f9892SAndre Guedes 		       bdaddr_t *dst, u8 dst_type)
14370a708f8fSGustavo F. Padovan {
14385d41ce1dSGustavo F. Padovan 	struct sock *sk = chan->sk;
14390a708f8fSGustavo F. Padovan 	bdaddr_t *src = &bt_sk(sk)->src;
14400a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
14410a708f8fSGustavo F. Padovan 	struct hci_conn *hcon;
14420a708f8fSGustavo F. Padovan 	struct hci_dev *hdev;
14430a708f8fSGustavo F. Padovan 	__u8 auth_type;
14440a708f8fSGustavo F. Padovan 	int err;
14450a708f8fSGustavo F. Padovan 
14468e9f9892SAndre Guedes 	BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst),
14478e9f9892SAndre Guedes 	       dst_type, __le16_to_cpu(chan->psm));
14480a708f8fSGustavo F. Padovan 
14490a708f8fSGustavo F. Padovan 	hdev = hci_get_route(dst, src);
14500a708f8fSGustavo F. Padovan 	if (!hdev)
14510a708f8fSGustavo F. Padovan 		return -EHOSTUNREACH;
14520a708f8fSGustavo F. Padovan 
145309fd0de5SGustavo F. Padovan 	hci_dev_lock(hdev);
14540a708f8fSGustavo F. Padovan 
14556be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
145603a00194SGustavo F. Padovan 
145703a00194SGustavo F. Padovan 	/* PSM must be odd and lsb of upper byte must be 0 */
145803a00194SGustavo F. Padovan 	if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
145903a00194SGustavo F. Padovan 					chan->chan_type != L2CAP_CHAN_RAW) {
146003a00194SGustavo F. Padovan 		err = -EINVAL;
146103a00194SGustavo F. Padovan 		goto done;
146203a00194SGustavo F. Padovan 	}
146303a00194SGustavo F. Padovan 
146403a00194SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
146503a00194SGustavo F. Padovan 		err = -EINVAL;
146603a00194SGustavo F. Padovan 		goto done;
146703a00194SGustavo F. Padovan 	}
146803a00194SGustavo F. Padovan 
146903a00194SGustavo F. Padovan 	switch (chan->mode) {
147003a00194SGustavo F. Padovan 	case L2CAP_MODE_BASIC:
147103a00194SGustavo F. Padovan 		break;
147203a00194SGustavo F. Padovan 	case L2CAP_MODE_ERTM:
147303a00194SGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
147403a00194SGustavo F. Padovan 		if (!disable_ertm)
147503a00194SGustavo F. Padovan 			break;
147603a00194SGustavo F. Padovan 		/* fall through */
147703a00194SGustavo F. Padovan 	default:
147803a00194SGustavo F. Padovan 		err = -ENOTSUPP;
147903a00194SGustavo F. Padovan 		goto done;
148003a00194SGustavo F. Padovan 	}
148103a00194SGustavo F. Padovan 
14826be36555SAndrei Emeltchenko 	lock_sock(sk);
14836be36555SAndrei Emeltchenko 
148403a00194SGustavo F. Padovan 	switch (sk->sk_state) {
148503a00194SGustavo F. Padovan 	case BT_CONNECT:
148603a00194SGustavo F. Padovan 	case BT_CONNECT2:
148703a00194SGustavo F. Padovan 	case BT_CONFIG:
148803a00194SGustavo F. Padovan 		/* Already connecting */
148903a00194SGustavo F. Padovan 		err = 0;
14906be36555SAndrei Emeltchenko 		release_sock(sk);
149103a00194SGustavo F. Padovan 		goto done;
149203a00194SGustavo F. Padovan 
149303a00194SGustavo F. Padovan 	case BT_CONNECTED:
149403a00194SGustavo F. Padovan 		/* Already connected */
149503a00194SGustavo F. Padovan 		err = -EISCONN;
14966be36555SAndrei Emeltchenko 		release_sock(sk);
149703a00194SGustavo F. Padovan 		goto done;
149803a00194SGustavo F. Padovan 
149903a00194SGustavo F. Padovan 	case BT_OPEN:
150003a00194SGustavo F. Padovan 	case BT_BOUND:
150103a00194SGustavo F. Padovan 		/* Can connect */
150203a00194SGustavo F. Padovan 		break;
150303a00194SGustavo F. Padovan 
150403a00194SGustavo F. Padovan 	default:
150503a00194SGustavo F. Padovan 		err = -EBADFD;
15066be36555SAndrei Emeltchenko 		release_sock(sk);
150703a00194SGustavo F. Padovan 		goto done;
150803a00194SGustavo F. Padovan 	}
150903a00194SGustavo F. Padovan 
151003a00194SGustavo F. Padovan 	/* Set destination address and psm */
15119219b2a0SGustavo F. Padovan 	bacpy(&bt_sk(sk)->dst, dst);
15126be36555SAndrei Emeltchenko 
15136be36555SAndrei Emeltchenko 	release_sock(sk);
15146be36555SAndrei Emeltchenko 
151503a00194SGustavo F. Padovan 	chan->psm = psm;
151603a00194SGustavo F. Padovan 	chan->dcid = cid;
15170a708f8fSGustavo F. Padovan 
15184343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
15190a708f8fSGustavo F. Padovan 
1520fe4128e0SGustavo F. Padovan 	if (chan->dcid == L2CAP_CID_LE_DATA)
15218e9f9892SAndre Guedes 		hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
15224343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1523acd7d370SVille Tervo 	else
15248e9f9892SAndre Guedes 		hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
15254343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1526acd7d370SVille Tervo 
152730e76272SVille Tervo 	if (IS_ERR(hcon)) {
152830e76272SVille Tervo 		err = PTR_ERR(hcon);
15290a708f8fSGustavo F. Padovan 		goto done;
153030e76272SVille Tervo 	}
15310a708f8fSGustavo F. Padovan 
15320a708f8fSGustavo F. Padovan 	conn = l2cap_conn_add(hcon, 0);
15330a708f8fSGustavo F. Padovan 	if (!conn) {
15340a708f8fSGustavo F. Padovan 		hci_conn_put(hcon);
153530e76272SVille Tervo 		err = -ENOMEM;
15360a708f8fSGustavo F. Padovan 		goto done;
15370a708f8fSGustavo F. Padovan 	}
15380a708f8fSGustavo F. Padovan 
15399f0caeb1SVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
15409f0caeb1SVinicius Costa Gomes 		err = 0;
15419f0caeb1SVinicius Costa Gomes 
15429f0caeb1SVinicius Costa Gomes 		if (!list_empty(&conn->chan_l)) {
15439f0caeb1SVinicius Costa Gomes 			err = -EBUSY;
15449f0caeb1SVinicius Costa Gomes 			hci_conn_put(hcon);
15459f0caeb1SVinicius Costa Gomes 		}
15469f0caeb1SVinicius Costa Gomes 
15479f0caeb1SVinicius Costa Gomes 		if (err)
15489f0caeb1SVinicius Costa Gomes 			goto done;
15499f0caeb1SVinicius Costa Gomes 	}
15509f0caeb1SVinicius Costa Gomes 
15510a708f8fSGustavo F. Padovan 	/* Update source addr of the socket */
15520a708f8fSGustavo F. Padovan 	bacpy(src, conn->src);
15530a708f8fSGustavo F. Padovan 
15546be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
155548454079SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
15566be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
155748454079SGustavo F. Padovan 
15586be36555SAndrei Emeltchenko 	l2cap_state_change(chan, BT_CONNECT);
1559c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
15600a708f8fSGustavo F. Padovan 
15610a708f8fSGustavo F. Padovan 	if (hcon->state == BT_CONNECTED) {
1562715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1563c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
1564d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan))
15656be36555SAndrei Emeltchenko 				l2cap_state_change(chan, BT_CONNECTED);
15660a708f8fSGustavo F. Padovan 		} else
1567fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
15680a708f8fSGustavo F. Padovan 	}
15690a708f8fSGustavo F. Padovan 
157030e76272SVille Tervo 	err = 0;
157130e76272SVille Tervo 
15720a708f8fSGustavo F. Padovan done:
15736be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
157409fd0de5SGustavo F. Padovan 	hci_dev_unlock(hdev);
15750a708f8fSGustavo F. Padovan 	hci_dev_put(hdev);
15760a708f8fSGustavo F. Padovan 	return err;
15770a708f8fSGustavo F. Padovan }
15780a708f8fSGustavo F. Padovan 
1579dcba0dbaSGustavo F. Padovan int __l2cap_wait_ack(struct sock *sk)
15800a708f8fSGustavo F. Padovan {
15818c1d787bSGustavo F. Padovan 	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
15820a708f8fSGustavo F. Padovan 	DECLARE_WAITQUEUE(wait, current);
15830a708f8fSGustavo F. Padovan 	int err = 0;
15840a708f8fSGustavo F. Padovan 	int timeo = HZ/5;
15850a708f8fSGustavo F. Padovan 
15860a708f8fSGustavo F. Padovan 	add_wait_queue(sk_sleep(sk), &wait);
15870a708f8fSGustavo F. Padovan 	set_current_state(TASK_INTERRUPTIBLE);
1588a71a0cf4SPeter Hurley 	while (chan->unacked_frames > 0 && chan->conn) {
15890a708f8fSGustavo F. Padovan 		if (!timeo)
15900a708f8fSGustavo F. Padovan 			timeo = HZ/5;
15910a708f8fSGustavo F. Padovan 
15920a708f8fSGustavo F. Padovan 		if (signal_pending(current)) {
15930a708f8fSGustavo F. Padovan 			err = sock_intr_errno(timeo);
15940a708f8fSGustavo F. Padovan 			break;
15950a708f8fSGustavo F. Padovan 		}
15960a708f8fSGustavo F. Padovan 
15970a708f8fSGustavo F. Padovan 		release_sock(sk);
15980a708f8fSGustavo F. Padovan 		timeo = schedule_timeout(timeo);
15990a708f8fSGustavo F. Padovan 		lock_sock(sk);
1600a71a0cf4SPeter Hurley 		set_current_state(TASK_INTERRUPTIBLE);
16010a708f8fSGustavo F. Padovan 
16020a708f8fSGustavo F. Padovan 		err = sock_error(sk);
16030a708f8fSGustavo F. Padovan 		if (err)
16040a708f8fSGustavo F. Padovan 			break;
16050a708f8fSGustavo F. Padovan 	}
16060a708f8fSGustavo F. Padovan 	set_current_state(TASK_RUNNING);
16070a708f8fSGustavo F. Padovan 	remove_wait_queue(sk_sleep(sk), &wait);
16080a708f8fSGustavo F. Padovan 	return err;
16090a708f8fSGustavo F. Padovan }
16100a708f8fSGustavo F. Padovan 
1611721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work)
16120a708f8fSGustavo F. Padovan {
1613721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1614721c4181SGustavo F. Padovan 							monitor_timer.work);
16150a708f8fSGustavo F. Padovan 
1616525cd185SGustavo F. Padovan 	BT_DBG("chan %p", chan);
16170a708f8fSGustavo F. Padovan 
16186be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
16196be36555SAndrei Emeltchenko 
16202c03a7a4SGustavo F. Padovan 	if (chan->retry_count >= chan->remote_max_tx) {
16218c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
16226be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
16238d7e1c7fSAndrei Emeltchenko 		l2cap_chan_put(chan);
16240a708f8fSGustavo F. Padovan 		return;
16250a708f8fSGustavo F. Padovan 	}
16260a708f8fSGustavo F. Padovan 
16276a026610SGustavo F. Padovan 	chan->retry_count++;
16281a09bcb9SGustavo F. Padovan 	__set_monitor_timer(chan);
16290a708f8fSGustavo F. Padovan 
1630525cd185SGustavo F. Padovan 	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
16316be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
16328d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
16330a708f8fSGustavo F. Padovan }
16340a708f8fSGustavo F. Padovan 
1635721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work)
16360a708f8fSGustavo F. Padovan {
1637721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1638721c4181SGustavo F. Padovan 							retrans_timer.work);
16390a708f8fSGustavo F. Padovan 
164049208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
16410a708f8fSGustavo F. Padovan 
16426be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
16436be36555SAndrei Emeltchenko 
16446a026610SGustavo F. Padovan 	chan->retry_count = 1;
16451a09bcb9SGustavo F. Padovan 	__set_monitor_timer(chan);
16460a708f8fSGustavo F. Padovan 
1647e2ab4353SGustavo F. Padovan 	set_bit(CONN_WAIT_F, &chan->conn_state);
16480a708f8fSGustavo F. Padovan 
1649525cd185SGustavo F. Padovan 	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
16506be36555SAndrei Emeltchenko 
16516be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
16528d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
16530a708f8fSGustavo F. Padovan }
16540a708f8fSGustavo F. Padovan 
16553733937dSMat Martineau static int l2cap_streaming_send(struct l2cap_chan *chan,
16563733937dSMat Martineau 				struct sk_buff_head *skbs)
16570a708f8fSGustavo F. Padovan {
16580a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
16593733937dSMat Martineau 	struct l2cap_ctrl *control;
16600a708f8fSGustavo F. Padovan 
16613733937dSMat Martineau 	BT_DBG("chan %p, skbs %p", chan, skbs);
16623733937dSMat Martineau 
16633733937dSMat Martineau 	if (chan->state != BT_CONNECTED)
16643733937dSMat Martineau 		return -ENOTCONN;
16653733937dSMat Martineau 
16663733937dSMat Martineau 	skb_queue_splice_tail_init(skbs, &chan->tx_q);
16673733937dSMat Martineau 
16683733937dSMat Martineau 	while (!skb_queue_empty(&chan->tx_q)) {
16693733937dSMat Martineau 
16703733937dSMat Martineau 		skb = skb_dequeue(&chan->tx_q);
16713733937dSMat Martineau 
16723733937dSMat Martineau 		bt_cb(skb)->control.retries = 1;
16733733937dSMat Martineau 		control = &bt_cb(skb)->control;
16743733937dSMat Martineau 
16753733937dSMat Martineau 		control->reqseq = 0;
16763733937dSMat Martineau 		control->txseq = chan->next_tx_seq;
16773733937dSMat Martineau 
16783733937dSMat Martineau 		__pack_control(chan, control, skb);
16790a708f8fSGustavo F. Padovan 
168047d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
16813733937dSMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
16823733937dSMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
16830a708f8fSGustavo F. Padovan 		}
16840a708f8fSGustavo F. Padovan 
16854343478fSGustavo F. Padovan 		l2cap_do_send(chan, skb);
16860a708f8fSGustavo F. Padovan 
16873733937dSMat Martineau 		BT_DBG("Sent txseq %d", (int)control->txseq);
16883733937dSMat Martineau 
1689836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
16903733937dSMat Martineau 		chan->frames_sent++;
16910a708f8fSGustavo F. Padovan 	}
16923733937dSMat Martineau 
16933733937dSMat Martineau 	return 0;
16940a708f8fSGustavo F. Padovan }
16950a708f8fSGustavo F. Padovan 
169667c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan)
16970a708f8fSGustavo F. Padovan {
16980a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
169918a48e76SMat Martineau 	struct l2cap_ctrl *control;
170018a48e76SMat Martineau 	int sent = 0;
170118a48e76SMat Martineau 
170218a48e76SMat Martineau 	BT_DBG("chan %p", chan);
17030a708f8fSGustavo F. Padovan 
170489bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
17050a708f8fSGustavo F. Padovan 		return -ENOTCONN;
17060a708f8fSGustavo F. Padovan 
170794122bbeSMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
170894122bbeSMat Martineau 		return 0;
170994122bbeSMat Martineau 
171018a48e76SMat Martineau 	while (chan->tx_send_head &&
171118a48e76SMat Martineau 	       chan->unacked_frames < chan->remote_tx_win &&
171218a48e76SMat Martineau 	       chan->tx_state == L2CAP_TX_STATE_XMIT) {
17130a708f8fSGustavo F. Padovan 
171418a48e76SMat Martineau 		skb = chan->tx_send_head;
17150a708f8fSGustavo F. Padovan 
171618a48e76SMat Martineau 		bt_cb(skb)->control.retries = 1;
171718a48e76SMat Martineau 		control = &bt_cb(skb)->control;
17180a708f8fSGustavo F. Padovan 
1719e2ab4353SGustavo F. Padovan 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
172018a48e76SMat Martineau 			control->final = 1;
1721e2ab4353SGustavo F. Padovan 
172218a48e76SMat Martineau 		control->reqseq = chan->buffer_seq;
172318a48e76SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
172418a48e76SMat Martineau 		control->txseq = chan->next_tx_seq;
17250a708f8fSGustavo F. Padovan 
172618a48e76SMat Martineau 		__pack_control(chan, control, skb);
17270a708f8fSGustavo F. Padovan 
172847d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
172918a48e76SMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
173018a48e76SMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
17310a708f8fSGustavo F. Padovan 		}
17320a708f8fSGustavo F. Padovan 
173318a48e76SMat Martineau 		/* Clone after data has been modified. Data is assumed to be
173418a48e76SMat Martineau 		   read-only (for locking purposes) on cloned sk_buffs.
173518a48e76SMat Martineau 		 */
173618a48e76SMat Martineau 		tx_skb = skb_clone(skb, GFP_KERNEL);
173718a48e76SMat Martineau 
173818a48e76SMat Martineau 		if (!tx_skb)
173918a48e76SMat Martineau 			break;
17400a708f8fSGustavo F. Padovan 
17411a09bcb9SGustavo F. Padovan 		__set_retrans_timer(chan);
17420a708f8fSGustavo F. Padovan 
1743836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
17446a026610SGustavo F. Padovan 		chan->unacked_frames++;
17456a026610SGustavo F. Padovan 		chan->frames_sent++;
174618a48e76SMat Martineau 		sent++;
17470a708f8fSGustavo F. Padovan 
174858d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
174958d35f87SGustavo F. Padovan 			chan->tx_send_head = NULL;
17500a708f8fSGustavo F. Padovan 		else
175158d35f87SGustavo F. Padovan 			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
175218a48e76SMat Martineau 
175318a48e76SMat Martineau 		l2cap_do_send(chan, tx_skb);
175418a48e76SMat Martineau 		BT_DBG("Sent txseq %d", (int)control->txseq);
17550a708f8fSGustavo F. Padovan 	}
17560a708f8fSGustavo F. Padovan 
175718a48e76SMat Martineau 	BT_DBG("Sent %d, %d unacked, %d in ERTM queue", sent,
175818a48e76SMat Martineau 	       (int) chan->unacked_frames, skb_queue_len(&chan->tx_q));
175918a48e76SMat Martineau 
176018a48e76SMat Martineau 	return sent;
17610a708f8fSGustavo F. Padovan }
17620a708f8fSGustavo F. Padovan 
1763525cd185SGustavo F. Padovan static int l2cap_retransmit_frames(struct l2cap_chan *chan)
17640a708f8fSGustavo F. Padovan {
17650a708f8fSGustavo F. Padovan 	int ret;
17660a708f8fSGustavo F. Padovan 
176758d35f87SGustavo F. Padovan 	if (!skb_queue_empty(&chan->tx_q))
176858d35f87SGustavo F. Padovan 		chan->tx_send_head = chan->tx_q.next;
17690a708f8fSGustavo F. Padovan 
177042e5c802SGustavo F. Padovan 	chan->next_tx_seq = chan->expected_ack_seq;
1771525cd185SGustavo F. Padovan 	ret = l2cap_ertm_send(chan);
17720a708f8fSGustavo F. Padovan 	return ret;
17730a708f8fSGustavo F. Padovan }
17740a708f8fSGustavo F. Padovan 
1775b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan)
1776b17e73bbSSzymon Janc {
17770a0aba42SMat Martineau 	struct l2cap_ctrl control;
17780a0aba42SMat Martineau 	u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq,
17790a0aba42SMat Martineau 					 chan->last_acked_seq);
17800a0aba42SMat Martineau 	int threshold;
17810a0aba42SMat Martineau 
17820a0aba42SMat Martineau 	BT_DBG("chan %p last_acked_seq %d buffer_seq %d",
17830a0aba42SMat Martineau 	       chan, chan->last_acked_seq, chan->buffer_seq);
17840a0aba42SMat Martineau 
17850a0aba42SMat Martineau 	memset(&control, 0, sizeof(control));
17860a0aba42SMat Martineau 	control.sframe = 1;
17870a0aba42SMat Martineau 
17880a0aba42SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
17890a0aba42SMat Martineau 	    chan->rx_state == L2CAP_RX_STATE_RECV) {
1790b17e73bbSSzymon Janc 		__clear_ack_timer(chan);
17910a0aba42SMat Martineau 		control.super = L2CAP_SUPER_RNR;
17920a0aba42SMat Martineau 		control.reqseq = chan->buffer_seq;
17930a0aba42SMat Martineau 		l2cap_send_sframe(chan, &control);
17940a0aba42SMat Martineau 	} else {
17950a0aba42SMat Martineau 		if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) {
17960a0aba42SMat Martineau 			l2cap_ertm_send(chan);
17970a0aba42SMat Martineau 			/* If any i-frames were sent, they included an ack */
17980a0aba42SMat Martineau 			if (chan->buffer_seq == chan->last_acked_seq)
17990a0aba42SMat Martineau 				frames_to_ack = 0;
18000a0aba42SMat Martineau 		}
18010a0aba42SMat Martineau 
18020a0aba42SMat Martineau 		/* Ack now if the tx window is 3/4ths full.
18030a0aba42SMat Martineau 		 * Calculate without mul or div
18040a0aba42SMat Martineau 		 */
18050a0aba42SMat Martineau 		threshold = chan->tx_win;
18060a0aba42SMat Martineau 		threshold += threshold << 1;
18070a0aba42SMat Martineau 		threshold >>= 2;
18080a0aba42SMat Martineau 
18090a0aba42SMat Martineau 		BT_DBG("frames_to_ack %d, threshold %d", (int)frames_to_ack,
18100a0aba42SMat Martineau 		       threshold);
18110a0aba42SMat Martineau 
18120a0aba42SMat Martineau 		if (frames_to_ack >= threshold) {
18130a0aba42SMat Martineau 			__clear_ack_timer(chan);
18140a0aba42SMat Martineau 			control.super = L2CAP_SUPER_RR;
18150a0aba42SMat Martineau 			control.reqseq = chan->buffer_seq;
18160a0aba42SMat Martineau 			l2cap_send_sframe(chan, &control);
18170a0aba42SMat Martineau 			frames_to_ack = 0;
18180a0aba42SMat Martineau 		}
18190a0aba42SMat Martineau 
18200a0aba42SMat Martineau 		if (frames_to_ack)
18210a0aba42SMat Martineau 			__set_ack_timer(chan);
18220a0aba42SMat Martineau 	}
1823b17e73bbSSzymon Janc }
1824b17e73bbSSzymon Janc 
182504124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
182604124681SGustavo F. Padovan 					 struct msghdr *msg, int len,
182704124681SGustavo F. Padovan 					 int count, struct sk_buff *skb)
18280a708f8fSGustavo F. Padovan {
18290952a57aSAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
18300a708f8fSGustavo F. Padovan 	struct sk_buff **frag;
183190338947SGustavo Padovan 	int sent = 0;
18320a708f8fSGustavo F. Padovan 
18330a708f8fSGustavo F. Padovan 	if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
18340a708f8fSGustavo F. Padovan 		return -EFAULT;
18350a708f8fSGustavo F. Padovan 
18360a708f8fSGustavo F. Padovan 	sent += count;
18370a708f8fSGustavo F. Padovan 	len  -= count;
18380a708f8fSGustavo F. Padovan 
18390a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
18400a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
18410a708f8fSGustavo F. Padovan 	while (len) {
1842fbe00700SGustavo Padovan 		struct sk_buff *tmp;
1843fbe00700SGustavo Padovan 
18440a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
18450a708f8fSGustavo F. Padovan 
1846fbe00700SGustavo Padovan 		tmp = chan->ops->alloc_skb(chan, count,
184790338947SGustavo Padovan 					   msg->msg_flags & MSG_DONTWAIT);
1848fbe00700SGustavo Padovan 		if (IS_ERR(tmp))
1849fbe00700SGustavo Padovan 			return PTR_ERR(tmp);
18502f7719ceSAndrei Emeltchenko 
1851fbe00700SGustavo Padovan 		*frag = tmp;
1852fbe00700SGustavo Padovan 
18530a708f8fSGustavo F. Padovan 		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
18540a708f8fSGustavo F. Padovan 			return -EFAULT;
18550a708f8fSGustavo F. Padovan 
18565e59b791SLuiz Augusto von Dentz 		(*frag)->priority = skb->priority;
18575e59b791SLuiz Augusto von Dentz 
18580a708f8fSGustavo F. Padovan 		sent += count;
18590a708f8fSGustavo F. Padovan 		len  -= count;
18600a708f8fSGustavo F. Padovan 
18612d0ed3d5SGustavo Padovan 		skb->len += (*frag)->len;
18622d0ed3d5SGustavo Padovan 		skb->data_len += (*frag)->len;
18632d0ed3d5SGustavo Padovan 
18640a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
18650a708f8fSGustavo F. Padovan 	}
18660a708f8fSGustavo F. Padovan 
18670a708f8fSGustavo F. Padovan 	return sent;
18680a708f8fSGustavo F. Padovan }
18690a708f8fSGustavo F. Padovan 
18705e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
18715e59b791SLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
18725e59b791SLuiz Augusto von Dentz 						u32 priority)
18730a708f8fSGustavo F. Padovan {
18748c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
18750a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
187603a51213SAndrei Emeltchenko 	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
18770a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
18780a708f8fSGustavo F. Padovan 
18796d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d priority %u", chan, (int)len, priority);
18800a708f8fSGustavo F. Padovan 
18810a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
18822f7719ceSAndrei Emeltchenko 
18832f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
188490338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
188590338947SGustavo Padovan 	if (IS_ERR(skb))
188690338947SGustavo Padovan 		return skb;
18870a708f8fSGustavo F. Padovan 
18885e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
18895e59b791SLuiz Augusto von Dentz 
18900a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
18910a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1892fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
1893daf6a78cSAndrei Emeltchenko 	lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
1894daf6a78cSAndrei Emeltchenko 	put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE));
18950a708f8fSGustavo F. Padovan 
18960952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
18970a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
18980a708f8fSGustavo F. Padovan 		kfree_skb(skb);
18990a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
19000a708f8fSGustavo F. Padovan 	}
19010a708f8fSGustavo F. Padovan 	return skb;
19020a708f8fSGustavo F. Padovan }
19030a708f8fSGustavo F. Padovan 
19045e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
19055e59b791SLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
19065e59b791SLuiz Augusto von Dentz 						u32 priority)
19070a708f8fSGustavo F. Padovan {
19088c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
19090a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
1910f2ba7faeSGustavo Padovan 	int err, count;
19110a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
19120a708f8fSGustavo F. Padovan 
19136d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d", chan, (int)len);
19140a708f8fSGustavo F. Padovan 
1915f2ba7faeSGustavo Padovan 	count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
19162f7719ceSAndrei Emeltchenko 
1917f2ba7faeSGustavo Padovan 	skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE,
191890338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
191990338947SGustavo Padovan 	if (IS_ERR(skb))
192090338947SGustavo Padovan 		return skb;
19210a708f8fSGustavo F. Padovan 
19225e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
19235e59b791SLuiz Augusto von Dentz 
19240a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
19250a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1926fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
19276ff9b5efSGustavo Padovan 	lh->len = cpu_to_le16(len);
19280a708f8fSGustavo F. Padovan 
19290952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
19300a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
19310a708f8fSGustavo F. Padovan 		kfree_skb(skb);
19320a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
19330a708f8fSGustavo F. Padovan 	}
19340a708f8fSGustavo F. Padovan 	return skb;
19350a708f8fSGustavo F. Padovan }
19360a708f8fSGustavo F. Padovan 
1937ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1938ab0ff76dSLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
193994122bbeSMat Martineau 						u16 sdulen)
19400a708f8fSGustavo F. Padovan {
19418c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
19420a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
1943e4ca6d98SAndrei Emeltchenko 	int err, count, hlen;
19440a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
19450a708f8fSGustavo F. Padovan 
19466d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d", chan, (int)len);
19470a708f8fSGustavo F. Padovan 
19480a708f8fSGustavo F. Padovan 	if (!conn)
19490a708f8fSGustavo F. Padovan 		return ERR_PTR(-ENOTCONN);
19500a708f8fSGustavo F. Padovan 
1951e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1952e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_EXT_HDR_SIZE;
1953e4ca6d98SAndrei Emeltchenko 	else
1954e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_ENH_HDR_SIZE;
1955e4ca6d98SAndrei Emeltchenko 
19560a708f8fSGustavo F. Padovan 	if (sdulen)
195703a51213SAndrei Emeltchenko 		hlen += L2CAP_SDULEN_SIZE;
19580a708f8fSGustavo F. Padovan 
195947d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
196003a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
19610a708f8fSGustavo F. Padovan 
19620a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
19632f7719ceSAndrei Emeltchenko 
19642f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
196590338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
196690338947SGustavo Padovan 	if (IS_ERR(skb))
196790338947SGustavo Padovan 		return skb;
19680a708f8fSGustavo F. Padovan 
19690a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
19700a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1971fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
19720a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
197388843ab0SAndrei Emeltchenko 
197418a48e76SMat Martineau 	/* Control header is populated later */
197518a48e76SMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
197618a48e76SMat Martineau 		put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
197718a48e76SMat Martineau 	else
197818a48e76SMat Martineau 		put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
197988843ab0SAndrei Emeltchenko 
19800a708f8fSGustavo F. Padovan 	if (sdulen)
198103a51213SAndrei Emeltchenko 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
19820a708f8fSGustavo F. Padovan 
19830952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
19840a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
19850a708f8fSGustavo F. Padovan 		kfree_skb(skb);
19860a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
19870a708f8fSGustavo F. Padovan 	}
19880a708f8fSGustavo F. Padovan 
198918a48e76SMat Martineau 	bt_cb(skb)->control.fcs = chan->fcs;
19903ce3514fSMat Martineau 	bt_cb(skb)->control.retries = 0;
19910a708f8fSGustavo F. Padovan 	return skb;
19920a708f8fSGustavo F. Padovan }
19930a708f8fSGustavo F. Padovan 
199494122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan,
199594122bbeSMat Martineau 			     struct sk_buff_head *seg_queue,
199694122bbeSMat Martineau 			     struct msghdr *msg, size_t len)
19970a708f8fSGustavo F. Padovan {
19980a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
199994122bbeSMat Martineau 	u16 sdu_len;
200094122bbeSMat Martineau 	size_t pdu_len;
200194122bbeSMat Martineau 	int err = 0;
200294122bbeSMat Martineau 	u8 sar;
20030a708f8fSGustavo F. Padovan 
200494122bbeSMat Martineau 	BT_DBG("chan %p, msg %p, len %d", chan, msg, (int)len);
20050a708f8fSGustavo F. Padovan 
200694122bbeSMat Martineau 	/* It is critical that ERTM PDUs fit in a single HCI fragment,
200794122bbeSMat Martineau 	 * so fragmented skbs are not used.  The HCI layer's handling
200894122bbeSMat Martineau 	 * of fragmented skbs is not compatible with ERTM's queueing.
200994122bbeSMat Martineau 	 */
201094122bbeSMat Martineau 
201194122bbeSMat Martineau 	/* PDU size is derived from the HCI MTU */
201294122bbeSMat Martineau 	pdu_len = chan->conn->mtu;
201394122bbeSMat Martineau 
201494122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
201594122bbeSMat Martineau 
201694122bbeSMat Martineau 	/* Adjust for largest possible L2CAP overhead. */
201794122bbeSMat Martineau 	pdu_len -= L2CAP_EXT_HDR_SIZE + L2CAP_FCS_SIZE;
201894122bbeSMat Martineau 
201994122bbeSMat Martineau 	/* Remote device may have requested smaller PDUs */
202094122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
202194122bbeSMat Martineau 
202294122bbeSMat Martineau 	if (len <= pdu_len) {
202394122bbeSMat Martineau 		sar = L2CAP_SAR_UNSEGMENTED;
202494122bbeSMat Martineau 		sdu_len = 0;
202594122bbeSMat Martineau 		pdu_len = len;
202694122bbeSMat Martineau 	} else {
202794122bbeSMat Martineau 		sar = L2CAP_SAR_START;
202894122bbeSMat Martineau 		sdu_len = len;
202994122bbeSMat Martineau 		pdu_len -= L2CAP_SDULEN_SIZE;
203094122bbeSMat Martineau 	}
20310a708f8fSGustavo F. Padovan 
20320a708f8fSGustavo F. Padovan 	while (len > 0) {
203394122bbeSMat Martineau 		skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
20340a708f8fSGustavo F. Padovan 
20350a708f8fSGustavo F. Padovan 		if (IS_ERR(skb)) {
203694122bbeSMat Martineau 			__skb_queue_purge(seg_queue);
20370a708f8fSGustavo F. Padovan 			return PTR_ERR(skb);
20380a708f8fSGustavo F. Padovan 		}
20390a708f8fSGustavo F. Padovan 
204094122bbeSMat Martineau 		bt_cb(skb)->control.sar = sar;
204194122bbeSMat Martineau 		__skb_queue_tail(seg_queue, skb);
20420a708f8fSGustavo F. Padovan 
204394122bbeSMat Martineau 		len -= pdu_len;
204494122bbeSMat Martineau 		if (sdu_len) {
204594122bbeSMat Martineau 			sdu_len = 0;
204694122bbeSMat Martineau 			pdu_len += L2CAP_SDULEN_SIZE;
204794122bbeSMat Martineau 		}
204894122bbeSMat Martineau 
204994122bbeSMat Martineau 		if (len <= pdu_len) {
205094122bbeSMat Martineau 			sar = L2CAP_SAR_END;
205194122bbeSMat Martineau 			pdu_len = len;
205294122bbeSMat Martineau 		} else {
205394122bbeSMat Martineau 			sar = L2CAP_SAR_CONTINUE;
205494122bbeSMat Martineau 		}
205594122bbeSMat Martineau 	}
205694122bbeSMat Martineau 
205794122bbeSMat Martineau 	return err;
20580a708f8fSGustavo F. Padovan }
20590a708f8fSGustavo F. Padovan 
20605e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
20615e59b791SLuiz Augusto von Dentz 								u32 priority)
20629a91a04aSGustavo F. Padovan {
20639a91a04aSGustavo F. Padovan 	struct sk_buff *skb;
20649a91a04aSGustavo F. Padovan 	int err;
206594122bbeSMat Martineau 	struct sk_buff_head seg_queue;
20669a91a04aSGustavo F. Padovan 
20679a91a04aSGustavo F. Padovan 	/* Connectionless channel */
2068715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
20695e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_connless_pdu(chan, msg, len, priority);
20709a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
20719a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
20729a91a04aSGustavo F. Padovan 
20739a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
20749a91a04aSGustavo F. Padovan 		return len;
20759a91a04aSGustavo F. Padovan 	}
20769a91a04aSGustavo F. Padovan 
20779a91a04aSGustavo F. Padovan 	switch (chan->mode) {
20789a91a04aSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
20799a91a04aSGustavo F. Padovan 		/* Check outgoing MTU */
20809a91a04aSGustavo F. Padovan 		if (len > chan->omtu)
20819a91a04aSGustavo F. Padovan 			return -EMSGSIZE;
20829a91a04aSGustavo F. Padovan 
20839a91a04aSGustavo F. Padovan 		/* Create a basic PDU */
20845e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_basic_pdu(chan, msg, len, priority);
20859a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
20869a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
20879a91a04aSGustavo F. Padovan 
20889a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
20899a91a04aSGustavo F. Padovan 		err = len;
20909a91a04aSGustavo F. Padovan 		break;
20919a91a04aSGustavo F. Padovan 
20929a91a04aSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
20939a91a04aSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
209494122bbeSMat Martineau 		/* Check outgoing MTU */
209594122bbeSMat Martineau 		if (len > chan->omtu) {
209694122bbeSMat Martineau 			err = -EMSGSIZE;
20979a91a04aSGustavo F. Padovan 			break;
20989a91a04aSGustavo F. Padovan 		}
20999a91a04aSGustavo F. Padovan 
210094122bbeSMat Martineau 		__skb_queue_head_init(&seg_queue);
210194122bbeSMat Martineau 
210294122bbeSMat Martineau 		/* Do segmentation before calling in to the state machine,
210394122bbeSMat Martineau 		 * since it's possible to block while waiting for memory
210494122bbeSMat Martineau 		 * allocation.
210594122bbeSMat Martineau 		 */
210694122bbeSMat Martineau 		err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
210794122bbeSMat Martineau 
210894122bbeSMat Martineau 		/* The channel could have been closed while segmenting,
210994122bbeSMat Martineau 		 * check that it is still connected.
211094122bbeSMat Martineau 		 */
211194122bbeSMat Martineau 		if (chan->state != BT_CONNECTED) {
211294122bbeSMat Martineau 			__skb_queue_purge(&seg_queue);
211394122bbeSMat Martineau 			err = -ENOTCONN;
21149a91a04aSGustavo F. Padovan 		}
21159a91a04aSGustavo F. Padovan 
211694122bbeSMat Martineau 		if (err)
211794122bbeSMat Martineau 			break;
211894122bbeSMat Martineau 
21193733937dSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM)
2120608bcc6dSMat Martineau 			err = l2cap_tx(chan, 0, &seg_queue,
2121608bcc6dSMat Martineau 				       L2CAP_EV_DATA_REQUEST);
21223733937dSMat Martineau 		else
21233733937dSMat Martineau 			err = l2cap_streaming_send(chan, &seg_queue);
212494122bbeSMat Martineau 
2125608bcc6dSMat Martineau 		if (!err)
21269a91a04aSGustavo F. Padovan 			err = len;
21279a91a04aSGustavo F. Padovan 
212894122bbeSMat Martineau 		/* If the skbs were not queued for sending, they'll still be in
212994122bbeSMat Martineau 		 * seg_queue and need to be purged.
213094122bbeSMat Martineau 		 */
213194122bbeSMat Martineau 		__skb_queue_purge(&seg_queue);
21329a91a04aSGustavo F. Padovan 		break;
21339a91a04aSGustavo F. Padovan 
21349a91a04aSGustavo F. Padovan 	default:
21359a91a04aSGustavo F. Padovan 		BT_DBG("bad state %1.1x", chan->mode);
21369a91a04aSGustavo F. Padovan 		err = -EBADFD;
21379a91a04aSGustavo F. Padovan 	}
21389a91a04aSGustavo F. Padovan 
21399a91a04aSGustavo F. Padovan 	return err;
21409a91a04aSGustavo F. Padovan }
21419a91a04aSGustavo F. Padovan 
2142608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq)
2143608bcc6dSMat Martineau {
2144608bcc6dSMat Martineau 	struct sk_buff *acked_skb;
2145608bcc6dSMat Martineau 	u16 ackseq;
2146608bcc6dSMat Martineau 
2147608bcc6dSMat Martineau 	BT_DBG("chan %p, reqseq %d", chan, reqseq);
2148608bcc6dSMat Martineau 
2149608bcc6dSMat Martineau 	if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq)
2150608bcc6dSMat Martineau 		return;
2151608bcc6dSMat Martineau 
2152608bcc6dSMat Martineau 	BT_DBG("expected_ack_seq %d, unacked_frames %d",
2153608bcc6dSMat Martineau 	       chan->expected_ack_seq, chan->unacked_frames);
2154608bcc6dSMat Martineau 
2155608bcc6dSMat Martineau 	for (ackseq = chan->expected_ack_seq; ackseq != reqseq;
2156608bcc6dSMat Martineau 	     ackseq = __next_seq(chan, ackseq)) {
2157608bcc6dSMat Martineau 
2158608bcc6dSMat Martineau 		acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq);
2159608bcc6dSMat Martineau 		if (acked_skb) {
2160608bcc6dSMat Martineau 			skb_unlink(acked_skb, &chan->tx_q);
2161608bcc6dSMat Martineau 			kfree_skb(acked_skb);
2162608bcc6dSMat Martineau 			chan->unacked_frames--;
2163608bcc6dSMat Martineau 		}
2164608bcc6dSMat Martineau 	}
2165608bcc6dSMat Martineau 
2166608bcc6dSMat Martineau 	chan->expected_ack_seq = reqseq;
2167608bcc6dSMat Martineau 
2168608bcc6dSMat Martineau 	if (chan->unacked_frames == 0)
2169608bcc6dSMat Martineau 		__clear_retrans_timer(chan);
2170608bcc6dSMat Martineau 
2171608bcc6dSMat Martineau 	BT_DBG("unacked_frames %d", (int) chan->unacked_frames);
2172608bcc6dSMat Martineau }
2173608bcc6dSMat Martineau 
2174608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan)
2175608bcc6dSMat Martineau {
2176608bcc6dSMat Martineau 	BT_DBG("chan %p", chan);
2177608bcc6dSMat Martineau 
2178608bcc6dSMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
2179608bcc6dSMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
2180608bcc6dSMat Martineau 	skb_queue_purge(&chan->srej_q);
2181608bcc6dSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2182608bcc6dSMat Martineau }
2183608bcc6dSMat Martineau 
2184608bcc6dSMat Martineau static int l2cap_tx_state_xmit(struct l2cap_chan *chan,
2185608bcc6dSMat Martineau 			       struct l2cap_ctrl *control,
2186608bcc6dSMat Martineau 			       struct sk_buff_head *skbs, u8 event)
2187608bcc6dSMat Martineau {
2188608bcc6dSMat Martineau 	int err = 0;
2189608bcc6dSMat Martineau 
2190608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2191608bcc6dSMat Martineau 	       event);
2192608bcc6dSMat Martineau 
2193608bcc6dSMat Martineau 	switch (event) {
2194608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2195608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2196608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2197608bcc6dSMat Martineau 
2198608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2199608bcc6dSMat Martineau 		l2cap_ertm_send(chan);
2200608bcc6dSMat Martineau 		break;
2201608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2202608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2203608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2204608bcc6dSMat Martineau 
2205608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2206608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2207608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2208608bcc6dSMat Martineau 			 */
2209608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2210608bcc6dSMat Martineau 		}
2211608bcc6dSMat Martineau 
2212608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2213608bcc6dSMat Martineau 
2214608bcc6dSMat Martineau 		break;
2215608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2216608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2217608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2218608bcc6dSMat Martineau 
2219608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2220608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2221608bcc6dSMat Martineau 
2222608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2223608bcc6dSMat Martineau 			local_control.sframe = 1;
2224608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2225608bcc6dSMat Martineau 			local_control.poll = 1;
2226608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2227a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2228608bcc6dSMat Martineau 
2229608bcc6dSMat Martineau 			chan->retry_count = 1;
2230608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2231608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2232608bcc6dSMat Martineau 		}
2233608bcc6dSMat Martineau 		break;
2234608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2235608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2236608bcc6dSMat Martineau 		break;
2237608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2238608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2239608bcc6dSMat Martineau 		chan->retry_count = 1;
2240608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2241608bcc6dSMat Martineau 		__clear_ack_timer(chan);
2242608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2243608bcc6dSMat Martineau 		break;
2244608bcc6dSMat Martineau 	case L2CAP_EV_RETRANS_TO:
2245608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2246608bcc6dSMat Martineau 		chan->retry_count = 1;
2247608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2248608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2249608bcc6dSMat Martineau 		break;
2250608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2251608bcc6dSMat Martineau 		/* Nothing to process */
2252608bcc6dSMat Martineau 		break;
2253608bcc6dSMat Martineau 	default:
2254608bcc6dSMat Martineau 		break;
2255608bcc6dSMat Martineau 	}
2256608bcc6dSMat Martineau 
2257608bcc6dSMat Martineau 	return err;
2258608bcc6dSMat Martineau }
2259608bcc6dSMat Martineau 
2260608bcc6dSMat Martineau static int l2cap_tx_state_wait_f(struct l2cap_chan *chan,
2261608bcc6dSMat Martineau 				 struct l2cap_ctrl *control,
2262608bcc6dSMat Martineau 				 struct sk_buff_head *skbs, u8 event)
2263608bcc6dSMat Martineau {
2264608bcc6dSMat Martineau 	int err = 0;
2265608bcc6dSMat Martineau 
2266608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2267608bcc6dSMat Martineau 	       event);
2268608bcc6dSMat Martineau 
2269608bcc6dSMat Martineau 	switch (event) {
2270608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2271608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2272608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2273608bcc6dSMat Martineau 		/* Queue data, but don't send. */
2274608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2275608bcc6dSMat Martineau 		break;
2276608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2277608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2278608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2279608bcc6dSMat Martineau 
2280608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2281608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2282608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2283608bcc6dSMat Martineau 			 */
2284608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2285608bcc6dSMat Martineau 		}
2286608bcc6dSMat Martineau 
2287608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2288608bcc6dSMat Martineau 
2289608bcc6dSMat Martineau 		break;
2290608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2291608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2292608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2293608bcc6dSMat Martineau 
2294608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2295608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2296608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2297608bcc6dSMat Martineau 			local_control.sframe = 1;
2298608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2299608bcc6dSMat Martineau 			local_control.poll = 1;
2300608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2301a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2302608bcc6dSMat Martineau 
2303608bcc6dSMat Martineau 			chan->retry_count = 1;
2304608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2305608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2306608bcc6dSMat Martineau 		}
2307608bcc6dSMat Martineau 		break;
2308608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2309608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2310608bcc6dSMat Martineau 
2311608bcc6dSMat Martineau 		/* Fall through */
2312608bcc6dSMat Martineau 
2313608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2314608bcc6dSMat Martineau 		if (control && control->final) {
2315608bcc6dSMat Martineau 			__clear_monitor_timer(chan);
2316608bcc6dSMat Martineau 			if (chan->unacked_frames > 0)
2317608bcc6dSMat Martineau 				__set_retrans_timer(chan);
2318608bcc6dSMat Martineau 			chan->retry_count = 0;
2319608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_XMIT;
2320608bcc6dSMat Martineau 			BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state);
2321608bcc6dSMat Martineau 		}
2322608bcc6dSMat Martineau 		break;
2323608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2324608bcc6dSMat Martineau 		/* Ignore */
2325608bcc6dSMat Martineau 		break;
2326608bcc6dSMat Martineau 	case L2CAP_EV_MONITOR_TO:
2327608bcc6dSMat Martineau 		if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) {
2328608bcc6dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 1);
2329608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2330608bcc6dSMat Martineau 			chan->retry_count++;
2331608bcc6dSMat Martineau 		} else {
2332608bcc6dSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
2333608bcc6dSMat Martineau 		}
2334608bcc6dSMat Martineau 		break;
2335608bcc6dSMat Martineau 	default:
2336608bcc6dSMat Martineau 		break;
2337608bcc6dSMat Martineau 	}
2338608bcc6dSMat Martineau 
2339608bcc6dSMat Martineau 	return err;
2340608bcc6dSMat Martineau }
2341608bcc6dSMat Martineau 
2342608bcc6dSMat Martineau static int l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
2343608bcc6dSMat Martineau 		    struct sk_buff_head *skbs, u8 event)
2344608bcc6dSMat Martineau {
2345608bcc6dSMat Martineau 	int err = 0;
2346608bcc6dSMat Martineau 
2347608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d, state %d",
2348608bcc6dSMat Martineau 	       chan, control, skbs, event, chan->tx_state);
2349608bcc6dSMat Martineau 
2350608bcc6dSMat Martineau 	switch (chan->tx_state) {
2351608bcc6dSMat Martineau 	case L2CAP_TX_STATE_XMIT:
2352608bcc6dSMat Martineau 		err = l2cap_tx_state_xmit(chan, control, skbs, event);
2353608bcc6dSMat Martineau 		break;
2354608bcc6dSMat Martineau 	case L2CAP_TX_STATE_WAIT_F:
2355608bcc6dSMat Martineau 		err = l2cap_tx_state_wait_f(chan, control, skbs, event);
2356608bcc6dSMat Martineau 		break;
2357608bcc6dSMat Martineau 	default:
2358608bcc6dSMat Martineau 		/* Ignore event */
2359608bcc6dSMat Martineau 		break;
2360608bcc6dSMat Martineau 	}
2361608bcc6dSMat Martineau 
2362608bcc6dSMat Martineau 	return err;
2363608bcc6dSMat Martineau }
2364608bcc6dSMat Martineau 
23654b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan,
23664b51dae9SMat Martineau 			     struct l2cap_ctrl *control)
23674b51dae9SMat Martineau {
23684b51dae9SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
23694b51dae9SMat Martineau 	l2cap_tx(chan, control, 0, L2CAP_EV_RECV_REQSEQ_AND_FBIT);
23704b51dae9SMat Martineau }
23714b51dae9SMat Martineau 
23720a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */
23730a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
23740a708f8fSGustavo F. Padovan {
23750a708f8fSGustavo F. Padovan 	struct sk_buff *nskb;
237648454079SGustavo F. Padovan 	struct l2cap_chan *chan;
23770a708f8fSGustavo F. Padovan 
23780a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
23790a708f8fSGustavo F. Padovan 
23803df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
23813d57dc68SGustavo F. Padovan 
23823df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
238348454079SGustavo F. Padovan 		struct sock *sk = chan->sk;
2384715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_RAW)
23850a708f8fSGustavo F. Padovan 			continue;
23860a708f8fSGustavo F. Padovan 
23870a708f8fSGustavo F. Padovan 		/* Don't send frame to the socket it came from */
23880a708f8fSGustavo F. Padovan 		if (skb->sk == sk)
23890a708f8fSGustavo F. Padovan 			continue;
23900a708f8fSGustavo F. Padovan 		nskb = skb_clone(skb, GFP_ATOMIC);
23910a708f8fSGustavo F. Padovan 		if (!nskb)
23920a708f8fSGustavo F. Padovan 			continue;
23930a708f8fSGustavo F. Padovan 
239423070494SGustavo F. Padovan 		if (chan->ops->recv(chan->data, nskb))
23950a708f8fSGustavo F. Padovan 			kfree_skb(nskb);
23960a708f8fSGustavo F. Padovan 	}
23973d57dc68SGustavo F. Padovan 
23983df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
23990a708f8fSGustavo F. Padovan }
24000a708f8fSGustavo F. Padovan 
24010a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
24020a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
24030a708f8fSGustavo F. Padovan 				u8 code, u8 ident, u16 dlen, void *data)
24040a708f8fSGustavo F. Padovan {
24050a708f8fSGustavo F. Padovan 	struct sk_buff *skb, **frag;
24060a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr *cmd;
24070a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
24080a708f8fSGustavo F. Padovan 	int len, count;
24090a708f8fSGustavo F. Padovan 
24100a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
24110a708f8fSGustavo F. Padovan 			conn, code, ident, dlen);
24120a708f8fSGustavo F. Padovan 
24130a708f8fSGustavo F. Padovan 	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
24140a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, len);
24150a708f8fSGustavo F. Padovan 
24160a708f8fSGustavo F. Padovan 	skb = bt_skb_alloc(count, GFP_ATOMIC);
24170a708f8fSGustavo F. Padovan 	if (!skb)
24180a708f8fSGustavo F. Padovan 		return NULL;
24190a708f8fSGustavo F. Padovan 
24200a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
24210a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
24223300d9a9SClaudio Takahasi 
24233300d9a9SClaudio Takahasi 	if (conn->hcon->type == LE_LINK)
24243300d9a9SClaudio Takahasi 		lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
24253300d9a9SClaudio Takahasi 	else
24260a708f8fSGustavo F. Padovan 		lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
24270a708f8fSGustavo F. Padovan 
24280a708f8fSGustavo F. Padovan 	cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
24290a708f8fSGustavo F. Padovan 	cmd->code  = code;
24300a708f8fSGustavo F. Padovan 	cmd->ident = ident;
24310a708f8fSGustavo F. Padovan 	cmd->len   = cpu_to_le16(dlen);
24320a708f8fSGustavo F. Padovan 
24330a708f8fSGustavo F. Padovan 	if (dlen) {
24340a708f8fSGustavo F. Padovan 		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
24350a708f8fSGustavo F. Padovan 		memcpy(skb_put(skb, count), data, count);
24360a708f8fSGustavo F. Padovan 		data += count;
24370a708f8fSGustavo F. Padovan 	}
24380a708f8fSGustavo F. Padovan 
24390a708f8fSGustavo F. Padovan 	len -= skb->len;
24400a708f8fSGustavo F. Padovan 
24410a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
24420a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
24430a708f8fSGustavo F. Padovan 	while (len) {
24440a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
24450a708f8fSGustavo F. Padovan 
24460a708f8fSGustavo F. Padovan 		*frag = bt_skb_alloc(count, GFP_ATOMIC);
24470a708f8fSGustavo F. Padovan 		if (!*frag)
24480a708f8fSGustavo F. Padovan 			goto fail;
24490a708f8fSGustavo F. Padovan 
24500a708f8fSGustavo F. Padovan 		memcpy(skb_put(*frag, count), data, count);
24510a708f8fSGustavo F. Padovan 
24520a708f8fSGustavo F. Padovan 		len  -= count;
24530a708f8fSGustavo F. Padovan 		data += count;
24540a708f8fSGustavo F. Padovan 
24550a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
24560a708f8fSGustavo F. Padovan 	}
24570a708f8fSGustavo F. Padovan 
24580a708f8fSGustavo F. Padovan 	return skb;
24590a708f8fSGustavo F. Padovan 
24600a708f8fSGustavo F. Padovan fail:
24610a708f8fSGustavo F. Padovan 	kfree_skb(skb);
24620a708f8fSGustavo F. Padovan 	return NULL;
24630a708f8fSGustavo F. Padovan }
24640a708f8fSGustavo F. Padovan 
24650a708f8fSGustavo F. Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
24660a708f8fSGustavo F. Padovan {
24670a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
24680a708f8fSGustavo F. Padovan 	int len;
24690a708f8fSGustavo F. Padovan 
24700a708f8fSGustavo F. Padovan 	len = L2CAP_CONF_OPT_SIZE + opt->len;
24710a708f8fSGustavo F. Padovan 	*ptr += len;
24720a708f8fSGustavo F. Padovan 
24730a708f8fSGustavo F. Padovan 	*type = opt->type;
24740a708f8fSGustavo F. Padovan 	*olen = opt->len;
24750a708f8fSGustavo F. Padovan 
24760a708f8fSGustavo F. Padovan 	switch (opt->len) {
24770a708f8fSGustavo F. Padovan 	case 1:
24780a708f8fSGustavo F. Padovan 		*val = *((u8 *) opt->val);
24790a708f8fSGustavo F. Padovan 		break;
24800a708f8fSGustavo F. Padovan 
24810a708f8fSGustavo F. Padovan 	case 2:
24820a708f8fSGustavo F. Padovan 		*val = get_unaligned_le16(opt->val);
24830a708f8fSGustavo F. Padovan 		break;
24840a708f8fSGustavo F. Padovan 
24850a708f8fSGustavo F. Padovan 	case 4:
24860a708f8fSGustavo F. Padovan 		*val = get_unaligned_le32(opt->val);
24870a708f8fSGustavo F. Padovan 		break;
24880a708f8fSGustavo F. Padovan 
24890a708f8fSGustavo F. Padovan 	default:
24900a708f8fSGustavo F. Padovan 		*val = (unsigned long) opt->val;
24910a708f8fSGustavo F. Padovan 		break;
24920a708f8fSGustavo F. Padovan 	}
24930a708f8fSGustavo F. Padovan 
24940a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
24950a708f8fSGustavo F. Padovan 	return len;
24960a708f8fSGustavo F. Padovan }
24970a708f8fSGustavo F. Padovan 
24980a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
24990a708f8fSGustavo F. Padovan {
25000a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
25010a708f8fSGustavo F. Padovan 
25020a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
25030a708f8fSGustavo F. Padovan 
25040a708f8fSGustavo F. Padovan 	opt->type = type;
25050a708f8fSGustavo F. Padovan 	opt->len  = len;
25060a708f8fSGustavo F. Padovan 
25070a708f8fSGustavo F. Padovan 	switch (len) {
25080a708f8fSGustavo F. Padovan 	case 1:
25090a708f8fSGustavo F. Padovan 		*((u8 *) opt->val)  = val;
25100a708f8fSGustavo F. Padovan 		break;
25110a708f8fSGustavo F. Padovan 
25120a708f8fSGustavo F. Padovan 	case 2:
25130a708f8fSGustavo F. Padovan 		put_unaligned_le16(val, opt->val);
25140a708f8fSGustavo F. Padovan 		break;
25150a708f8fSGustavo F. Padovan 
25160a708f8fSGustavo F. Padovan 	case 4:
25170a708f8fSGustavo F. Padovan 		put_unaligned_le32(val, opt->val);
25180a708f8fSGustavo F. Padovan 		break;
25190a708f8fSGustavo F. Padovan 
25200a708f8fSGustavo F. Padovan 	default:
25210a708f8fSGustavo F. Padovan 		memcpy(opt->val, (void *) val, len);
25220a708f8fSGustavo F. Padovan 		break;
25230a708f8fSGustavo F. Padovan 	}
25240a708f8fSGustavo F. Padovan 
25250a708f8fSGustavo F. Padovan 	*ptr += L2CAP_CONF_OPT_SIZE + len;
25260a708f8fSGustavo F. Padovan }
25270a708f8fSGustavo F. Padovan 
2528f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
2529f89cef09SAndrei Emeltchenko {
2530f89cef09SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
2531f89cef09SAndrei Emeltchenko 
2532f89cef09SAndrei Emeltchenko 	switch (chan->mode) {
2533f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_ERTM:
2534f89cef09SAndrei Emeltchenko 		efs.id		= chan->local_id;
2535f89cef09SAndrei Emeltchenko 		efs.stype	= chan->local_stype;
2536f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
2537f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
2538f89cef09SAndrei Emeltchenko 		efs.acc_lat	= cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
2539f89cef09SAndrei Emeltchenko 		efs.flush_to	= cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
2540f89cef09SAndrei Emeltchenko 		break;
2541f89cef09SAndrei Emeltchenko 
2542f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_STREAMING:
2543f89cef09SAndrei Emeltchenko 		efs.id		= 1;
2544f89cef09SAndrei Emeltchenko 		efs.stype	= L2CAP_SERV_BESTEFFORT;
2545f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
2546f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
2547f89cef09SAndrei Emeltchenko 		efs.acc_lat	= 0;
2548f89cef09SAndrei Emeltchenko 		efs.flush_to	= 0;
2549f89cef09SAndrei Emeltchenko 		break;
2550f89cef09SAndrei Emeltchenko 
2551f89cef09SAndrei Emeltchenko 	default:
2552f89cef09SAndrei Emeltchenko 		return;
2553f89cef09SAndrei Emeltchenko 	}
2554f89cef09SAndrei Emeltchenko 
2555f89cef09SAndrei Emeltchenko 	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
2556f89cef09SAndrei Emeltchenko 							(unsigned long) &efs);
2557f89cef09SAndrei Emeltchenko }
2558f89cef09SAndrei Emeltchenko 
2559721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
25600a708f8fSGustavo F. Padovan {
2561721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2562721c4181SGustavo F. Padovan 							ack_timer.work);
25630a708f8fSGustavo F. Padovan 
25642fb9b3d4SGustavo F. Padovan 	BT_DBG("chan %p", chan);
25652fb9b3d4SGustavo F. Padovan 
25666be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
25676be36555SAndrei Emeltchenko 
25680a0aba42SMat Martineau 	l2cap_send_ack(chan);
25696be36555SAndrei Emeltchenko 
25706be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
257109bfb2eeSSzymon Janc 
257209bfb2eeSSzymon Janc 	l2cap_chan_put(chan);
25730a708f8fSGustavo F. Padovan }
25740a708f8fSGustavo F. Padovan 
25753c588192SMat Martineau static inline int l2cap_ertm_init(struct l2cap_chan *chan)
25760a708f8fSGustavo F. Padovan {
25773c588192SMat Martineau 	int err;
25783c588192SMat Martineau 
2579105bdf9eSMat Martineau 	chan->next_tx_seq = 0;
2580105bdf9eSMat Martineau 	chan->expected_tx_seq = 0;
258142e5c802SGustavo F. Padovan 	chan->expected_ack_seq = 0;
25826a026610SGustavo F. Padovan 	chan->unacked_frames = 0;
258342e5c802SGustavo F. Padovan 	chan->buffer_seq = 0;
25846a026610SGustavo F. Padovan 	chan->frames_sent = 0;
2585105bdf9eSMat Martineau 	chan->last_acked_seq = 0;
2586105bdf9eSMat Martineau 	chan->sdu = NULL;
2587105bdf9eSMat Martineau 	chan->sdu_last_frag = NULL;
2588105bdf9eSMat Martineau 	chan->sdu_len = 0;
2589105bdf9eSMat Martineau 
2590d34c34fbSMat Martineau 	skb_queue_head_init(&chan->tx_q);
2591d34c34fbSMat Martineau 
2592105bdf9eSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
2593105bdf9eSMat Martineau 		return 0;
2594105bdf9eSMat Martineau 
2595105bdf9eSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2596105bdf9eSMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
25970a708f8fSGustavo F. Padovan 
2598721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
2599721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
2600721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
26010a708f8fSGustavo F. Padovan 
2602f1c6775bSGustavo F. Padovan 	skb_queue_head_init(&chan->srej_q);
26030a708f8fSGustavo F. Padovan 
26043c588192SMat Martineau 	err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
26053c588192SMat Martineau 	if (err < 0)
26063c588192SMat Martineau 		return err;
26073c588192SMat Martineau 
26089dc9affcSMat Martineau 	err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
26099dc9affcSMat Martineau 	if (err < 0)
26109dc9affcSMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
26119dc9affcSMat Martineau 
26129dc9affcSMat Martineau 	return err;
26130a708f8fSGustavo F. Padovan }
26140a708f8fSGustavo F. Padovan 
26150a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
26160a708f8fSGustavo F. Padovan {
26170a708f8fSGustavo F. Padovan 	switch (mode) {
26180a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
26190a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
26200a708f8fSGustavo F. Padovan 		if (l2cap_mode_supported(mode, remote_feat_mask))
26210a708f8fSGustavo F. Padovan 			return mode;
26220a708f8fSGustavo F. Padovan 		/* fall through */
26230a708f8fSGustavo F. Padovan 	default:
26240a708f8fSGustavo F. Padovan 		return L2CAP_MODE_BASIC;
26250a708f8fSGustavo F. Padovan 	}
26260a708f8fSGustavo F. Padovan }
26270a708f8fSGustavo F. Padovan 
26286327eb98SAndrei Emeltchenko static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
26296327eb98SAndrei Emeltchenko {
26306327eb98SAndrei Emeltchenko 	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
26316327eb98SAndrei Emeltchenko }
26326327eb98SAndrei Emeltchenko 
2633f89cef09SAndrei Emeltchenko static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2634f89cef09SAndrei Emeltchenko {
2635f89cef09SAndrei Emeltchenko 	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2636f89cef09SAndrei Emeltchenko }
2637f89cef09SAndrei Emeltchenko 
26386327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
26396327eb98SAndrei Emeltchenko {
26406327eb98SAndrei Emeltchenko 	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
2641836be934SAndrei Emeltchenko 						__l2cap_ews_supported(chan)) {
26426327eb98SAndrei Emeltchenko 		/* use extended control field */
26436327eb98SAndrei Emeltchenko 		set_bit(FLAG_EXT_CTRL, &chan->flags);
2644836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2645836be934SAndrei Emeltchenko 	} else {
26466327eb98SAndrei Emeltchenko 		chan->tx_win = min_t(u16, chan->tx_win,
26476327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_TX_WINDOW);
2648836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2649836be934SAndrei Emeltchenko 	}
26506327eb98SAndrei Emeltchenko }
26516327eb98SAndrei Emeltchenko 
2652710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
26530a708f8fSGustavo F. Padovan {
26540a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
26550c1bc5c6SGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
26560a708f8fSGustavo F. Padovan 	void *ptr = req->data;
2657c8f79162SAndrei Emeltchenko 	u16 size;
26580a708f8fSGustavo F. Padovan 
265949208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
26600a708f8fSGustavo F. Padovan 
266173ffa904SGustavo F. Padovan 	if (chan->num_conf_req || chan->num_conf_rsp)
26620a708f8fSGustavo F. Padovan 		goto done;
26630a708f8fSGustavo F. Padovan 
26640c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
26650a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
26660a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
2667c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
26680a708f8fSGustavo F. Padovan 			break;
26690a708f8fSGustavo F. Padovan 
2670f89cef09SAndrei Emeltchenko 		if (__l2cap_efs_supported(chan))
2671f89cef09SAndrei Emeltchenko 			set_bit(FLAG_EFS_ENABLE, &chan->flags);
2672f89cef09SAndrei Emeltchenko 
26730a708f8fSGustavo F. Padovan 		/* fall through */
26740a708f8fSGustavo F. Padovan 	default:
26758c1d787bSGustavo F. Padovan 		chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
26760a708f8fSGustavo F. Padovan 		break;
26770a708f8fSGustavo F. Padovan 	}
26780a708f8fSGustavo F. Padovan 
26790a708f8fSGustavo F. Padovan done:
26800c1bc5c6SGustavo F. Padovan 	if (chan->imtu != L2CAP_DEFAULT_MTU)
26810c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
26820a708f8fSGustavo F. Padovan 
26830c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
26840a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
26858c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
26868c1d787bSGustavo F. Padovan 				!(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
26870a708f8fSGustavo F. Padovan 			break;
26880a708f8fSGustavo F. Padovan 
26890a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_BASIC;
26900a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
26910a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
26920a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
26930a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
26940a708f8fSGustavo F. Padovan 		rfc.max_pdu_size    = 0;
26950a708f8fSGustavo F. Padovan 
26960a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
26970a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
26980a708f8fSGustavo F. Padovan 		break;
26990a708f8fSGustavo F. Padovan 
27000a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
27010a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_ERTM;
270247d1ec61SGustavo F. Padovan 		rfc.max_transmit    = chan->max_tx;
27030a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
27040a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
2705c8f79162SAndrei Emeltchenko 
2706c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2707c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2708c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2709c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2710c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
27110a708f8fSGustavo F. Padovan 
27126327eb98SAndrei Emeltchenko 		l2cap_txwin_setup(chan);
27136327eb98SAndrei Emeltchenko 
27146327eb98SAndrei Emeltchenko 		rfc.txwin_size = min_t(u16, chan->tx_win,
27156327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_TX_WINDOW);
27160a708f8fSGustavo F. Padovan 
27170a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
27180a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
27190a708f8fSGustavo F. Padovan 
2720f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2721f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
2722f89cef09SAndrei Emeltchenko 
27238c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
27240a708f8fSGustavo F. Padovan 			break;
27250a708f8fSGustavo F. Padovan 
272647d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_NONE ||
2727c1360a1cSGustavo F. Padovan 				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
272847d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
272947d1ec61SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
27300a708f8fSGustavo F. Padovan 		}
27316327eb98SAndrei Emeltchenko 
27326327eb98SAndrei Emeltchenko 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
27336327eb98SAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
27346327eb98SAndrei Emeltchenko 								chan->tx_win);
27350a708f8fSGustavo F. Padovan 		break;
27360a708f8fSGustavo F. Padovan 
27370a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
27380a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_STREAMING;
27390a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
27400a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
27410a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
27420a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
2743c8f79162SAndrei Emeltchenko 
2744c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2745c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2746c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2747c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2748c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
27490a708f8fSGustavo F. Padovan 
27500a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
27510a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
27520a708f8fSGustavo F. Padovan 
2753f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2754f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
2755f89cef09SAndrei Emeltchenko 
27568c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
27570a708f8fSGustavo F. Padovan 			break;
27580a708f8fSGustavo F. Padovan 
275947d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_NONE ||
2760c1360a1cSGustavo F. Padovan 				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
276147d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
276247d1ec61SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
27630a708f8fSGustavo F. Padovan 		}
27640a708f8fSGustavo F. Padovan 		break;
27650a708f8fSGustavo F. Padovan 	}
27660a708f8fSGustavo F. Padovan 
2767fe4128e0SGustavo F. Padovan 	req->dcid  = cpu_to_le16(chan->dcid);
27680a708f8fSGustavo F. Padovan 	req->flags = cpu_to_le16(0);
27690a708f8fSGustavo F. Padovan 
27700a708f8fSGustavo F. Padovan 	return ptr - data;
27710a708f8fSGustavo F. Padovan }
27720a708f8fSGustavo F. Padovan 
277373ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
27740a708f8fSGustavo F. Padovan {
27750a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
27760a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
277773ffa904SGustavo F. Padovan 	void *req = chan->conf_req;
277873ffa904SGustavo F. Padovan 	int len = chan->conf_len;
27790a708f8fSGustavo F. Padovan 	int type, hint, olen;
27800a708f8fSGustavo F. Padovan 	unsigned long val;
27810a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
278242dceae2SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
278342dceae2SAndrei Emeltchenko 	u8 remote_efs = 0;
27840a708f8fSGustavo F. Padovan 	u16 mtu = L2CAP_DEFAULT_MTU;
27850a708f8fSGustavo F. Padovan 	u16 result = L2CAP_CONF_SUCCESS;
2786c8f79162SAndrei Emeltchenko 	u16 size;
27870a708f8fSGustavo F. Padovan 
278873ffa904SGustavo F. Padovan 	BT_DBG("chan %p", chan);
27890a708f8fSGustavo F. Padovan 
27900a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
27910a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
27920a708f8fSGustavo F. Padovan 
27930a708f8fSGustavo F. Padovan 		hint  = type & L2CAP_CONF_HINT;
27940a708f8fSGustavo F. Padovan 		type &= L2CAP_CONF_MASK;
27950a708f8fSGustavo F. Padovan 
27960a708f8fSGustavo F. Padovan 		switch (type) {
27970a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
27980a708f8fSGustavo F. Padovan 			mtu = val;
27990a708f8fSGustavo F. Padovan 			break;
28000a708f8fSGustavo F. Padovan 
28010a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
28020c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
28030a708f8fSGustavo F. Padovan 			break;
28040a708f8fSGustavo F. Padovan 
28050a708f8fSGustavo F. Padovan 		case L2CAP_CONF_QOS:
28060a708f8fSGustavo F. Padovan 			break;
28070a708f8fSGustavo F. Padovan 
28080a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
28090a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
28100a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *) val, olen);
28110a708f8fSGustavo F. Padovan 			break;
28120a708f8fSGustavo F. Padovan 
28130a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FCS:
28140a708f8fSGustavo F. Padovan 			if (val == L2CAP_FCS_NONE)
2815c1360a1cSGustavo F. Padovan 				set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
281642dceae2SAndrei Emeltchenko 			break;
28170a708f8fSGustavo F. Padovan 
281842dceae2SAndrei Emeltchenko 		case L2CAP_CONF_EFS:
281942dceae2SAndrei Emeltchenko 			remote_efs = 1;
282042dceae2SAndrei Emeltchenko 			if (olen == sizeof(efs))
282142dceae2SAndrei Emeltchenko 				memcpy(&efs, (void *) val, olen);
28220a708f8fSGustavo F. Padovan 			break;
28230a708f8fSGustavo F. Padovan 
28246327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
28256327eb98SAndrei Emeltchenko 			if (!enable_hs)
28266327eb98SAndrei Emeltchenko 				return -ECONNREFUSED;
28276327eb98SAndrei Emeltchenko 
28286327eb98SAndrei Emeltchenko 			set_bit(FLAG_EXT_CTRL, &chan->flags);
28296327eb98SAndrei Emeltchenko 			set_bit(CONF_EWS_RECV, &chan->conf_state);
2830836be934SAndrei Emeltchenko 			chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
28316327eb98SAndrei Emeltchenko 			chan->remote_tx_win = val;
28320a708f8fSGustavo F. Padovan 			break;
28330a708f8fSGustavo F. Padovan 
28340a708f8fSGustavo F. Padovan 		default:
28350a708f8fSGustavo F. Padovan 			if (hint)
28360a708f8fSGustavo F. Padovan 				break;
28370a708f8fSGustavo F. Padovan 
28380a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNKNOWN;
28390a708f8fSGustavo F. Padovan 			*((u8 *) ptr++) = type;
28400a708f8fSGustavo F. Padovan 			break;
28410a708f8fSGustavo F. Padovan 		}
28420a708f8fSGustavo F. Padovan 	}
28430a708f8fSGustavo F. Padovan 
284473ffa904SGustavo F. Padovan 	if (chan->num_conf_rsp || chan->num_conf_req > 1)
28450a708f8fSGustavo F. Padovan 		goto done;
28460a708f8fSGustavo F. Padovan 
28470c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
28480a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
28490a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
2850c1360a1cSGustavo F. Padovan 		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
28510c1bc5c6SGustavo F. Padovan 			chan->mode = l2cap_select_mode(rfc.mode,
28528c1d787bSGustavo F. Padovan 					chan->conn->feat_mask);
28530a708f8fSGustavo F. Padovan 			break;
28540a708f8fSGustavo F. Padovan 		}
28550a708f8fSGustavo F. Padovan 
285642dceae2SAndrei Emeltchenko 		if (remote_efs) {
285742dceae2SAndrei Emeltchenko 			if (__l2cap_efs_supported(chan))
285842dceae2SAndrei Emeltchenko 				set_bit(FLAG_EFS_ENABLE, &chan->flags);
285942dceae2SAndrei Emeltchenko 			else
286042dceae2SAndrei Emeltchenko 				return -ECONNREFUSED;
286142dceae2SAndrei Emeltchenko 		}
286242dceae2SAndrei Emeltchenko 
28630c1bc5c6SGustavo F. Padovan 		if (chan->mode != rfc.mode)
28640a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
28650a708f8fSGustavo F. Padovan 
28660a708f8fSGustavo F. Padovan 		break;
28670a708f8fSGustavo F. Padovan 	}
28680a708f8fSGustavo F. Padovan 
28690a708f8fSGustavo F. Padovan done:
28700c1bc5c6SGustavo F. Padovan 	if (chan->mode != rfc.mode) {
28710a708f8fSGustavo F. Padovan 		result = L2CAP_CONF_UNACCEPT;
28720c1bc5c6SGustavo F. Padovan 		rfc.mode = chan->mode;
28730a708f8fSGustavo F. Padovan 
287473ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp == 1)
28750a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
28760a708f8fSGustavo F. Padovan 
28770a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
28780a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
28790a708f8fSGustavo F. Padovan 	}
28800a708f8fSGustavo F. Padovan 
28810a708f8fSGustavo F. Padovan 	if (result == L2CAP_CONF_SUCCESS) {
28820a708f8fSGustavo F. Padovan 		/* Configure output options and let the other side know
28830a708f8fSGustavo F. Padovan 		 * which ones we don't like. */
28840a708f8fSGustavo F. Padovan 
28850a708f8fSGustavo F. Padovan 		if (mtu < L2CAP_DEFAULT_MIN_MTU)
28860a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
28870a708f8fSGustavo F. Padovan 		else {
28880c1bc5c6SGustavo F. Padovan 			chan->omtu = mtu;
2889c1360a1cSGustavo F. Padovan 			set_bit(CONF_MTU_DONE, &chan->conf_state);
28900a708f8fSGustavo F. Padovan 		}
28910c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
28920a708f8fSGustavo F. Padovan 
289342dceae2SAndrei Emeltchenko 		if (remote_efs) {
289442dceae2SAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
289542dceae2SAndrei Emeltchenko 					efs.stype != L2CAP_SERV_NOTRAFIC &&
289642dceae2SAndrei Emeltchenko 					efs.stype != chan->local_stype) {
289742dceae2SAndrei Emeltchenko 
289842dceae2SAndrei Emeltchenko 				result = L2CAP_CONF_UNACCEPT;
289942dceae2SAndrei Emeltchenko 
290042dceae2SAndrei Emeltchenko 				if (chan->num_conf_req >= 1)
290142dceae2SAndrei Emeltchenko 					return -ECONNREFUSED;
290242dceae2SAndrei Emeltchenko 
290342dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
290442dceae2SAndrei Emeltchenko 							sizeof(efs),
290542dceae2SAndrei Emeltchenko 							(unsigned long) &efs);
29060e8b207eSAndrei Emeltchenko 			} else {
29073e6b3b95SGustavo F. Padovan 				/* Send PENDING Conf Rsp */
29080e8b207eSAndrei Emeltchenko 				result = L2CAP_CONF_PENDING;
29090e8b207eSAndrei Emeltchenko 				set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
291042dceae2SAndrei Emeltchenko 			}
291142dceae2SAndrei Emeltchenko 		}
291242dceae2SAndrei Emeltchenko 
29130a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
29140a708f8fSGustavo F. Padovan 		case L2CAP_MODE_BASIC:
291547d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
2916c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
29170a708f8fSGustavo F. Padovan 			break;
29180a708f8fSGustavo F. Padovan 
29190a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
29206327eb98SAndrei Emeltchenko 			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
29212c03a7a4SGustavo F. Padovan 				chan->remote_tx_win = rfc.txwin_size;
29226327eb98SAndrei Emeltchenko 			else
29236327eb98SAndrei Emeltchenko 				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
29246327eb98SAndrei Emeltchenko 
29252c03a7a4SGustavo F. Padovan 			chan->remote_max_tx = rfc.max_transmit;
29260a708f8fSGustavo F. Padovan 
2927c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2928c8f79162SAndrei Emeltchenko 						chan->conn->mtu -
2929c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2930c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2931c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2932c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
2933c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
29340a708f8fSGustavo F. Padovan 
29350a708f8fSGustavo F. Padovan 			rfc.retrans_timeout =
29364fd21a88SAndrei Emeltchenko 				__constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
29370a708f8fSGustavo F. Padovan 			rfc.monitor_timeout =
29384fd21a88SAndrei Emeltchenko 				__constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
29390a708f8fSGustavo F. Padovan 
2940c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
29410a708f8fSGustavo F. Padovan 
29420a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
29430a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
29440a708f8fSGustavo F. Padovan 
294542dceae2SAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
294642dceae2SAndrei Emeltchenko 				chan->remote_id = efs.id;
294742dceae2SAndrei Emeltchenko 				chan->remote_stype = efs.stype;
294842dceae2SAndrei Emeltchenko 				chan->remote_msdu = le16_to_cpu(efs.msdu);
294942dceae2SAndrei Emeltchenko 				chan->remote_flush_to =
295042dceae2SAndrei Emeltchenko 						le32_to_cpu(efs.flush_to);
295142dceae2SAndrei Emeltchenko 				chan->remote_acc_lat =
295242dceae2SAndrei Emeltchenko 						le32_to_cpu(efs.acc_lat);
295342dceae2SAndrei Emeltchenko 				chan->remote_sdu_itime =
295442dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
295542dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
295642dceae2SAndrei Emeltchenko 					sizeof(efs), (unsigned long) &efs);
295742dceae2SAndrei Emeltchenko 			}
29580a708f8fSGustavo F. Padovan 			break;
29590a708f8fSGustavo F. Padovan 
29600a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
2961c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2962c8f79162SAndrei Emeltchenko 						chan->conn->mtu -
2963c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2964c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2965c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2966c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
2967c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
29680a708f8fSGustavo F. Padovan 
2969c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
29700a708f8fSGustavo F. Padovan 
29710a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
29720a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
29730a708f8fSGustavo F. Padovan 
29740a708f8fSGustavo F. Padovan 			break;
29750a708f8fSGustavo F. Padovan 
29760a708f8fSGustavo F. Padovan 		default:
29770a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
29780a708f8fSGustavo F. Padovan 
29790a708f8fSGustavo F. Padovan 			memset(&rfc, 0, sizeof(rfc));
29800c1bc5c6SGustavo F. Padovan 			rfc.mode = chan->mode;
29810a708f8fSGustavo F. Padovan 		}
29820a708f8fSGustavo F. Padovan 
29830a708f8fSGustavo F. Padovan 		if (result == L2CAP_CONF_SUCCESS)
2984c1360a1cSGustavo F. Padovan 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
29850a708f8fSGustavo F. Padovan 	}
2986fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
29870a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
29880a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(0x0000);
29890a708f8fSGustavo F. Padovan 
29900a708f8fSGustavo F. Padovan 	return ptr - data;
29910a708f8fSGustavo F. Padovan }
29920a708f8fSGustavo F. Padovan 
2993b4450035SGustavo F. Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result)
29940a708f8fSGustavo F. Padovan {
29950a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
29960a708f8fSGustavo F. Padovan 	void *ptr = req->data;
29970a708f8fSGustavo F. Padovan 	int type, olen;
29980a708f8fSGustavo F. Padovan 	unsigned long val;
299936e999a8SMat Martineau 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
300066af7aafSAndrei Emeltchenko 	struct l2cap_conf_efs efs;
30010a708f8fSGustavo F. Padovan 
3002fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
30030a708f8fSGustavo F. Padovan 
30040a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
30050a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
30060a708f8fSGustavo F. Padovan 
30070a708f8fSGustavo F. Padovan 		switch (type) {
30080a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
30090a708f8fSGustavo F. Padovan 			if (val < L2CAP_DEFAULT_MIN_MTU) {
30100a708f8fSGustavo F. Padovan 				*result = L2CAP_CONF_UNACCEPT;
30110c1bc5c6SGustavo F. Padovan 				chan->imtu = L2CAP_DEFAULT_MIN_MTU;
30120a708f8fSGustavo F. Padovan 			} else
30130c1bc5c6SGustavo F. Padovan 				chan->imtu = val;
30140c1bc5c6SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
30150a708f8fSGustavo F. Padovan 			break;
30160a708f8fSGustavo F. Padovan 
30170a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
30180c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
30190a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
30200c1bc5c6SGustavo F. Padovan 							2, chan->flush_to);
30210a708f8fSGustavo F. Padovan 			break;
30220a708f8fSGustavo F. Padovan 
30230a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
30240a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
30250a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
30260a708f8fSGustavo F. Padovan 
3027c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
30280c1bc5c6SGustavo F. Padovan 							rfc.mode != chan->mode)
30290a708f8fSGustavo F. Padovan 				return -ECONNREFUSED;
30300a708f8fSGustavo F. Padovan 
303147d1ec61SGustavo F. Padovan 			chan->fcs = 0;
30320a708f8fSGustavo F. Padovan 
30330a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
30340a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
30350a708f8fSGustavo F. Padovan 			break;
30366327eb98SAndrei Emeltchenko 
30376327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
30386327eb98SAndrei Emeltchenko 			chan->tx_win = min_t(u16, val,
30396327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_EXT_WINDOW);
30403e6b3b95SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
30413e6b3b95SGustavo F. Padovan 							chan->tx_win);
30426327eb98SAndrei Emeltchenko 			break;
304366af7aafSAndrei Emeltchenko 
304466af7aafSAndrei Emeltchenko 		case L2CAP_CONF_EFS:
304566af7aafSAndrei Emeltchenko 			if (olen == sizeof(efs))
304666af7aafSAndrei Emeltchenko 				memcpy(&efs, (void *)val, olen);
304766af7aafSAndrei Emeltchenko 
304866af7aafSAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
304966af7aafSAndrei Emeltchenko 					efs.stype != L2CAP_SERV_NOTRAFIC &&
305066af7aafSAndrei Emeltchenko 					efs.stype != chan->local_stype)
305166af7aafSAndrei Emeltchenko 				return -ECONNREFUSED;
305266af7aafSAndrei Emeltchenko 
305366af7aafSAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
305466af7aafSAndrei Emeltchenko 					sizeof(efs), (unsigned long) &efs);
305566af7aafSAndrei Emeltchenko 			break;
30560a708f8fSGustavo F. Padovan 		}
30570a708f8fSGustavo F. Padovan 	}
30580a708f8fSGustavo F. Padovan 
30590c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
30600a708f8fSGustavo F. Padovan 		return -ECONNREFUSED;
30610a708f8fSGustavo F. Padovan 
30620c1bc5c6SGustavo F. Padovan 	chan->mode = rfc.mode;
30630a708f8fSGustavo F. Padovan 
30640e8b207eSAndrei Emeltchenko 	if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
30650a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
30660a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
306747d1ec61SGustavo F. Padovan 			chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
306847d1ec61SGustavo F. Padovan 			chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
306947d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
307066af7aafSAndrei Emeltchenko 
307166af7aafSAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
307266af7aafSAndrei Emeltchenko 				chan->local_msdu = le16_to_cpu(efs.msdu);
307366af7aafSAndrei Emeltchenko 				chan->local_sdu_itime =
307466af7aafSAndrei Emeltchenko 						le32_to_cpu(efs.sdu_itime);
307566af7aafSAndrei Emeltchenko 				chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
307666af7aafSAndrei Emeltchenko 				chan->local_flush_to =
307766af7aafSAndrei Emeltchenko 						le32_to_cpu(efs.flush_to);
307866af7aafSAndrei Emeltchenko 			}
30790a708f8fSGustavo F. Padovan 			break;
308066af7aafSAndrei Emeltchenko 
30810a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
308247d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
30830a708f8fSGustavo F. Padovan 		}
30840a708f8fSGustavo F. Padovan 	}
30850a708f8fSGustavo F. Padovan 
3086fe4128e0SGustavo F. Padovan 	req->dcid   = cpu_to_le16(chan->dcid);
30870a708f8fSGustavo F. Padovan 	req->flags  = cpu_to_le16(0x0000);
30880a708f8fSGustavo F. Padovan 
30890a708f8fSGustavo F. Padovan 	return ptr - data;
30900a708f8fSGustavo F. Padovan }
30910a708f8fSGustavo F. Padovan 
3092fe4128e0SGustavo F. Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
30930a708f8fSGustavo F. Padovan {
30940a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
30950a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
30960a708f8fSGustavo F. Padovan 
3097fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p", chan);
30980a708f8fSGustavo F. Padovan 
3099fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
31000a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
31010a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(flags);
31020a708f8fSGustavo F. Padovan 
31030a708f8fSGustavo F. Padovan 	return ptr - data;
31040a708f8fSGustavo F. Padovan }
31050a708f8fSGustavo F. Padovan 
31068c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
3107710f9b0aSGustavo F. Padovan {
3108710f9b0aSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
31098c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
3110710f9b0aSGustavo F. Padovan 	u8 buf[128];
3111710f9b0aSGustavo F. Padovan 
3112fe4128e0SGustavo F. Padovan 	rsp.scid   = cpu_to_le16(chan->dcid);
3113fe4128e0SGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(chan->scid);
3114710f9b0aSGustavo F. Padovan 	rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
3115710f9b0aSGustavo F. Padovan 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
3116710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, chan->ident,
3117710f9b0aSGustavo F. Padovan 				L2CAP_CONN_RSP, sizeof(rsp), &rsp);
3118710f9b0aSGustavo F. Padovan 
3119c1360a1cSGustavo F. Padovan 	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
3120710f9b0aSGustavo F. Padovan 		return;
3121710f9b0aSGustavo F. Padovan 
3122710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3123710f9b0aSGustavo F. Padovan 			l2cap_build_conf_req(chan, buf), buf);
3124710f9b0aSGustavo F. Padovan 	chan->num_conf_req++;
3125710f9b0aSGustavo F. Padovan }
3126710f9b0aSGustavo F. Padovan 
312747d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
31280a708f8fSGustavo F. Padovan {
31290a708f8fSGustavo F. Padovan 	int type, olen;
31300a708f8fSGustavo F. Padovan 	unsigned long val;
31310a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc;
31320a708f8fSGustavo F. Padovan 
313347d1ec61SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
31340a708f8fSGustavo F. Padovan 
31350c1bc5c6SGustavo F. Padovan 	if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
31360a708f8fSGustavo F. Padovan 		return;
31370a708f8fSGustavo F. Padovan 
31380a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
31390a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
31400a708f8fSGustavo F. Padovan 
31410a708f8fSGustavo F. Padovan 		switch (type) {
31420a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
31430a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
31440a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
31450a708f8fSGustavo F. Padovan 			goto done;
31460a708f8fSGustavo F. Padovan 		}
31470a708f8fSGustavo F. Padovan 	}
31480a708f8fSGustavo F. Padovan 
314936e999a8SMat Martineau 	/* Use sane default values in case a misbehaving remote device
315036e999a8SMat Martineau 	 * did not send an RFC option.
315136e999a8SMat Martineau 	 */
315236e999a8SMat Martineau 	rfc.mode = chan->mode;
315336e999a8SMat Martineau 	rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
315436e999a8SMat Martineau 	rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
315536e999a8SMat Martineau 	rfc.max_pdu_size = cpu_to_le16(chan->imtu);
315636e999a8SMat Martineau 
315736e999a8SMat Martineau 	BT_ERR("Expected RFC option was not found, using defaults");
315836e999a8SMat Martineau 
31590a708f8fSGustavo F. Padovan done:
31600a708f8fSGustavo F. Padovan 	switch (rfc.mode) {
31610a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
316247d1ec61SGustavo F. Padovan 		chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
316347d1ec61SGustavo F. Padovan 		chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
316447d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
31650a708f8fSGustavo F. Padovan 		break;
31660a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
316747d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
31680a708f8fSGustavo F. Padovan 	}
31690a708f8fSGustavo F. Padovan }
31700a708f8fSGustavo F. Padovan 
31710a708f8fSGustavo F. Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
31720a708f8fSGustavo F. Padovan {
3173e2fd318eSIlia Kolomisnky 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
31740a708f8fSGustavo F. Padovan 
3175e2fd318eSIlia Kolomisnky 	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
31760a708f8fSGustavo F. Padovan 		return 0;
31770a708f8fSGustavo F. Padovan 
31780a708f8fSGustavo F. Padovan 	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
31790a708f8fSGustavo F. Padovan 					cmd->ident == conn->info_ident) {
318017cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->info_timer);
31810a708f8fSGustavo F. Padovan 
31820a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
31830a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
31840a708f8fSGustavo F. Padovan 
31850a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
31860a708f8fSGustavo F. Padovan 	}
31870a708f8fSGustavo F. Padovan 
31880a708f8fSGustavo F. Padovan 	return 0;
31890a708f8fSGustavo F. Padovan }
31900a708f8fSGustavo F. Padovan 
31910a708f8fSGustavo F. Padovan static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
31920a708f8fSGustavo F. Padovan {
31930a708f8fSGustavo F. Padovan 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
31940a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
319523691d75SGustavo F. Padovan 	struct l2cap_chan *chan = NULL, *pchan;
31960a708f8fSGustavo F. Padovan 	struct sock *parent, *sk = NULL;
31970a708f8fSGustavo F. Padovan 	int result, status = L2CAP_CS_NO_INFO;
31980a708f8fSGustavo F. Padovan 
31990a708f8fSGustavo F. Padovan 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
32000a708f8fSGustavo F. Padovan 	__le16 psm = req->psm;
32010a708f8fSGustavo F. Padovan 
3202097db76cSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
32030a708f8fSGustavo F. Padovan 
32040a708f8fSGustavo F. Padovan 	/* Check if we have socket listening on psm */
3205c2287681SIdo Yariv 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst);
320623691d75SGustavo F. Padovan 	if (!pchan) {
32070a708f8fSGustavo F. Padovan 		result = L2CAP_CR_BAD_PSM;
32080a708f8fSGustavo F. Padovan 		goto sendresp;
32090a708f8fSGustavo F. Padovan 	}
32100a708f8fSGustavo F. Padovan 
321123691d75SGustavo F. Padovan 	parent = pchan->sk;
321223691d75SGustavo F. Padovan 
32133df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
3214aa2ac881SGustavo F. Padovan 	lock_sock(parent);
32150a708f8fSGustavo F. Padovan 
32160a708f8fSGustavo F. Padovan 	/* Check if the ACL is secure enough (if not SDP) */
32170a708f8fSGustavo F. Padovan 	if (psm != cpu_to_le16(0x0001) &&
32180a708f8fSGustavo F. Padovan 				!hci_conn_check_link_mode(conn->hcon)) {
32199f5a0d7bSAndrei Emeltchenko 		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
32200a708f8fSGustavo F. Padovan 		result = L2CAP_CR_SEC_BLOCK;
32210a708f8fSGustavo F. Padovan 		goto response;
32220a708f8fSGustavo F. Padovan 	}
32230a708f8fSGustavo F. Padovan 
32240a708f8fSGustavo F. Padovan 	result = L2CAP_CR_NO_MEM;
32250a708f8fSGustavo F. Padovan 
32260a708f8fSGustavo F. Padovan 	/* Check for backlog size */
32270a708f8fSGustavo F. Padovan 	if (sk_acceptq_is_full(parent)) {
32280a708f8fSGustavo F. Padovan 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
32290a708f8fSGustavo F. Padovan 		goto response;
32300a708f8fSGustavo F. Padovan 	}
32310a708f8fSGustavo F. Padovan 
323280808e43SGustavo F. Padovan 	chan = pchan->ops->new_connection(pchan->data);
323380808e43SGustavo F. Padovan 	if (!chan)
32340a708f8fSGustavo F. Padovan 		goto response;
32350a708f8fSGustavo F. Padovan 
323680808e43SGustavo F. Padovan 	sk = chan->sk;
323780808e43SGustavo F. Padovan 
32380a708f8fSGustavo F. Padovan 	/* Check if we already have channel with that dcid */
3239baa7e1faSGustavo F. Padovan 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
32400a708f8fSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
3241ba3bd0eeSGustavo F. Padovan 		chan->ops->close(chan->data);
32420a708f8fSGustavo F. Padovan 		goto response;
32430a708f8fSGustavo F. Padovan 	}
32440a708f8fSGustavo F. Padovan 
32450a708f8fSGustavo F. Padovan 	hci_conn_hold(conn->hcon);
32460a708f8fSGustavo F. Padovan 
32470a708f8fSGustavo F. Padovan 	bacpy(&bt_sk(sk)->src, conn->src);
32480a708f8fSGustavo F. Padovan 	bacpy(&bt_sk(sk)->dst, conn->dst);
3249fe4128e0SGustavo F. Padovan 	chan->psm  = psm;
3250fe4128e0SGustavo F. Padovan 	chan->dcid = scid;
32510a708f8fSGustavo F. Padovan 
3252d1010240SGustavo F. Padovan 	bt_accept_enqueue(parent, sk);
3253d1010240SGustavo F. Padovan 
32546be36555SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
325548454079SGustavo F. Padovan 
3256fe4128e0SGustavo F. Padovan 	dcid = chan->scid;
32570a708f8fSGustavo F. Padovan 
3258c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
32590a708f8fSGustavo F. Padovan 
3260fc7f8a7eSGustavo F. Padovan 	chan->ident = cmd->ident;
32610a708f8fSGustavo F. Padovan 
32620a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
3263d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan)) {
3264c5daa683SGustavo Padovan 			if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
32650e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_CONNECT2);
32660a708f8fSGustavo F. Padovan 				result = L2CAP_CR_PEND;
32670a708f8fSGustavo F. Padovan 				status = L2CAP_CS_AUTHOR_PEND;
32680a708f8fSGustavo F. Padovan 				parent->sk_data_ready(parent, 0);
32690a708f8fSGustavo F. Padovan 			} else {
32700e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_CONFIG);
32710a708f8fSGustavo F. Padovan 				result = L2CAP_CR_SUCCESS;
32720a708f8fSGustavo F. Padovan 				status = L2CAP_CS_NO_INFO;
32730a708f8fSGustavo F. Padovan 			}
32740a708f8fSGustavo F. Padovan 		} else {
32750e587be7SAndrei Emeltchenko 			__l2cap_state_change(chan, BT_CONNECT2);
32760a708f8fSGustavo F. Padovan 			result = L2CAP_CR_PEND;
32770a708f8fSGustavo F. Padovan 			status = L2CAP_CS_AUTHEN_PEND;
32780a708f8fSGustavo F. Padovan 		}
32790a708f8fSGustavo F. Padovan 	} else {
32800e587be7SAndrei Emeltchenko 		__l2cap_state_change(chan, BT_CONNECT2);
32810a708f8fSGustavo F. Padovan 		result = L2CAP_CR_PEND;
32820a708f8fSGustavo F. Padovan 		status = L2CAP_CS_NO_INFO;
32830a708f8fSGustavo F. Padovan 	}
32840a708f8fSGustavo F. Padovan 
32850a708f8fSGustavo F. Padovan response:
3286aa2ac881SGustavo F. Padovan 	release_sock(parent);
32873df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
32880a708f8fSGustavo F. Padovan 
32890a708f8fSGustavo F. Padovan sendresp:
32900a708f8fSGustavo F. Padovan 	rsp.scid   = cpu_to_le16(scid);
32910a708f8fSGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(dcid);
32920a708f8fSGustavo F. Padovan 	rsp.result = cpu_to_le16(result);
32930a708f8fSGustavo F. Padovan 	rsp.status = cpu_to_le16(status);
32940a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
32950a708f8fSGustavo F. Padovan 
32960a708f8fSGustavo F. Padovan 	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
32970a708f8fSGustavo F. Padovan 		struct l2cap_info_req info;
32980a708f8fSGustavo F. Padovan 		info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
32990a708f8fSGustavo F. Padovan 
33000a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
33010a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
33020a708f8fSGustavo F. Padovan 
3303ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
33040a708f8fSGustavo F. Padovan 
33050a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, conn->info_ident,
33060a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(info), &info);
33070a708f8fSGustavo F. Padovan 	}
33080a708f8fSGustavo F. Padovan 
3309c1360a1cSGustavo F. Padovan 	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
33100a708f8fSGustavo F. Padovan 				result == L2CAP_CR_SUCCESS) {
33110a708f8fSGustavo F. Padovan 		u8 buf[128];
3312c1360a1cSGustavo F. Padovan 		set_bit(CONF_REQ_SENT, &chan->conf_state);
33130a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
331473ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, buf), buf);
331573ffa904SGustavo F. Padovan 		chan->num_conf_req++;
33160a708f8fSGustavo F. Padovan 	}
33170a708f8fSGustavo F. Padovan 
33180a708f8fSGustavo F. Padovan 	return 0;
33190a708f8fSGustavo F. Padovan }
33200a708f8fSGustavo F. Padovan 
33210a708f8fSGustavo F. Padovan static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
33220a708f8fSGustavo F. Padovan {
33230a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
33240a708f8fSGustavo F. Padovan 	u16 scid, dcid, result, status;
332548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
33260a708f8fSGustavo F. Padovan 	u8 req[128];
33273df91ea2SAndrei Emeltchenko 	int err;
33280a708f8fSGustavo F. Padovan 
33290a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
33300a708f8fSGustavo F. Padovan 	dcid   = __le16_to_cpu(rsp->dcid);
33310a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
33320a708f8fSGustavo F. Padovan 	status = __le16_to_cpu(rsp->status);
33330a708f8fSGustavo F. Padovan 
33341b009c98SAndrei Emeltchenko 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
33351b009c98SAndrei Emeltchenko 						dcid, scid, result, status);
33360a708f8fSGustavo F. Padovan 
33373df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
33383df91ea2SAndrei Emeltchenko 
33390a708f8fSGustavo F. Padovan 	if (scid) {
33403df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_scid(conn, scid);
33413df91ea2SAndrei Emeltchenko 		if (!chan) {
33423df91ea2SAndrei Emeltchenko 			err = -EFAULT;
33433df91ea2SAndrei Emeltchenko 			goto unlock;
33443df91ea2SAndrei Emeltchenko 		}
33450a708f8fSGustavo F. Padovan 	} else {
33463df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
33473df91ea2SAndrei Emeltchenko 		if (!chan) {
33483df91ea2SAndrei Emeltchenko 			err = -EFAULT;
33493df91ea2SAndrei Emeltchenko 			goto unlock;
33503df91ea2SAndrei Emeltchenko 		}
33510a708f8fSGustavo F. Padovan 	}
33520a708f8fSGustavo F. Padovan 
33533df91ea2SAndrei Emeltchenko 	err = 0;
33543df91ea2SAndrei Emeltchenko 
33556be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
335648454079SGustavo F. Padovan 
33570a708f8fSGustavo F. Padovan 	switch (result) {
33580a708f8fSGustavo F. Padovan 	case L2CAP_CR_SUCCESS:
335989bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONFIG);
3360fc7f8a7eSGustavo F. Padovan 		chan->ident = 0;
3361fe4128e0SGustavo F. Padovan 		chan->dcid = dcid;
3362c1360a1cSGustavo F. Padovan 		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
33630a708f8fSGustavo F. Padovan 
3364c1360a1cSGustavo F. Padovan 		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
33650a708f8fSGustavo F. Padovan 			break;
33660a708f8fSGustavo F. Padovan 
33670a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
336873ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, req), req);
336973ffa904SGustavo F. Padovan 		chan->num_conf_req++;
33700a708f8fSGustavo F. Padovan 		break;
33710a708f8fSGustavo F. Padovan 
33720a708f8fSGustavo F. Padovan 	case L2CAP_CR_PEND:
3373c1360a1cSGustavo F. Padovan 		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
33740a708f8fSGustavo F. Padovan 		break;
33750a708f8fSGustavo F. Padovan 
33760a708f8fSGustavo F. Padovan 	default:
337748454079SGustavo F. Padovan 		l2cap_chan_del(chan, ECONNREFUSED);
33780a708f8fSGustavo F. Padovan 		break;
33790a708f8fSGustavo F. Padovan 	}
33800a708f8fSGustavo F. Padovan 
33816be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
33823df91ea2SAndrei Emeltchenko 
33833df91ea2SAndrei Emeltchenko unlock:
33843df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
33853df91ea2SAndrei Emeltchenko 
33863df91ea2SAndrei Emeltchenko 	return err;
33870a708f8fSGustavo F. Padovan }
33880a708f8fSGustavo F. Padovan 
338947d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
33900a708f8fSGustavo F. Padovan {
33910a708f8fSGustavo F. Padovan 	/* FCS is enabled only in ERTM or streaming mode, if one or both
33920a708f8fSGustavo F. Padovan 	 * sides request it.
33930a708f8fSGustavo F. Padovan 	 */
33940c1bc5c6SGustavo F. Padovan 	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
339547d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_NONE;
3396c1360a1cSGustavo F. Padovan 	else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
339747d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_CRC16;
33980a708f8fSGustavo F. Padovan }
33990a708f8fSGustavo F. Padovan 
34000a708f8fSGustavo F. Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
34010a708f8fSGustavo F. Padovan {
34020a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
34030a708f8fSGustavo F. Padovan 	u16 dcid, flags;
34040a708f8fSGustavo F. Padovan 	u8 rsp[64];
340548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
34063c588192SMat Martineau 	int len, err = 0;
34070a708f8fSGustavo F. Padovan 
34080a708f8fSGustavo F. Padovan 	dcid  = __le16_to_cpu(req->dcid);
34090a708f8fSGustavo F. Padovan 	flags = __le16_to_cpu(req->flags);
34100a708f8fSGustavo F. Padovan 
34110a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
34120a708f8fSGustavo F. Padovan 
3413baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, dcid);
341448454079SGustavo F. Padovan 	if (!chan)
34150a708f8fSGustavo F. Padovan 		return -ENOENT;
34160a708f8fSGustavo F. Padovan 
3417033b1142SDavid S. Miller 	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
3418e2fd318eSIlia Kolomisnky 		struct l2cap_cmd_rej_cid rej;
34190a708f8fSGustavo F. Padovan 
3420e2fd318eSIlia Kolomisnky 		rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
3421e2fd318eSIlia Kolomisnky 		rej.scid = cpu_to_le16(chan->scid);
3422e2fd318eSIlia Kolomisnky 		rej.dcid = cpu_to_le16(chan->dcid);
3423e2fd318eSIlia Kolomisnky 
34240a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
34250a708f8fSGustavo F. Padovan 				sizeof(rej), &rej);
34260a708f8fSGustavo F. Padovan 		goto unlock;
34270a708f8fSGustavo F. Padovan 	}
34280a708f8fSGustavo F. Padovan 
34290a708f8fSGustavo F. Padovan 	/* Reject if config buffer is too small. */
34300a708f8fSGustavo F. Padovan 	len = cmd_len - sizeof(*req);
34317ac28817SDan Rosenberg 	if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
34320a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3433fe4128e0SGustavo F. Padovan 				l2cap_build_conf_rsp(chan, rsp,
34340a708f8fSGustavo F. Padovan 					L2CAP_CONF_REJECT, flags), rsp);
34350a708f8fSGustavo F. Padovan 		goto unlock;
34360a708f8fSGustavo F. Padovan 	}
34370a708f8fSGustavo F. Padovan 
34380a708f8fSGustavo F. Padovan 	/* Store config. */
343973ffa904SGustavo F. Padovan 	memcpy(chan->conf_req + chan->conf_len, req->data, len);
344073ffa904SGustavo F. Padovan 	chan->conf_len += len;
34410a708f8fSGustavo F. Padovan 
34420a708f8fSGustavo F. Padovan 	if (flags & 0x0001) {
34430a708f8fSGustavo F. Padovan 		/* Incomplete config. Send empty response. */
34440a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3445fe4128e0SGustavo F. Padovan 				l2cap_build_conf_rsp(chan, rsp,
34460a708f8fSGustavo F. Padovan 					L2CAP_CONF_SUCCESS, 0x0001), rsp);
34470a708f8fSGustavo F. Padovan 		goto unlock;
34480a708f8fSGustavo F. Padovan 	}
34490a708f8fSGustavo F. Padovan 
34500a708f8fSGustavo F. Padovan 	/* Complete config. */
345173ffa904SGustavo F. Padovan 	len = l2cap_parse_conf_req(chan, rsp);
34520a708f8fSGustavo F. Padovan 	if (len < 0) {
3453e92c8e70SGustavo F. Padovan 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
34540a708f8fSGustavo F. Padovan 		goto unlock;
34550a708f8fSGustavo F. Padovan 	}
34560a708f8fSGustavo F. Padovan 
34570a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
345873ffa904SGustavo F. Padovan 	chan->num_conf_rsp++;
34590a708f8fSGustavo F. Padovan 
34600a708f8fSGustavo F. Padovan 	/* Reset config buffer. */
346173ffa904SGustavo F. Padovan 	chan->conf_len = 0;
34620a708f8fSGustavo F. Padovan 
3463c1360a1cSGustavo F. Padovan 	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
34640a708f8fSGustavo F. Padovan 		goto unlock;
34650a708f8fSGustavo F. Padovan 
3466c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
346747d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
34680a708f8fSGustavo F. Padovan 
346989bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONNECTED);
34700a708f8fSGustavo F. Padovan 
3471105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
3472105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
34733c588192SMat Martineau 			err = l2cap_ertm_init(chan);
34740a708f8fSGustavo F. Padovan 
34753c588192SMat Martineau 		if (err < 0)
34763c588192SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, -err);
34773c588192SMat Martineau 		else
3478cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
34793c588192SMat Martineau 
34800a708f8fSGustavo F. Padovan 		goto unlock;
34810a708f8fSGustavo F. Padovan 	}
34820a708f8fSGustavo F. Padovan 
3483c1360a1cSGustavo F. Padovan 	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
34840a708f8fSGustavo F. Padovan 		u8 buf[64];
34850a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
348673ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, buf), buf);
348773ffa904SGustavo F. Padovan 		chan->num_conf_req++;
34880a708f8fSGustavo F. Padovan 	}
34890a708f8fSGustavo F. Padovan 
34900e8b207eSAndrei Emeltchenko 	/* Got Conf Rsp PENDING from remote side and asume we sent
34910e8b207eSAndrei Emeltchenko 	   Conf Rsp PENDING in the code above */
34920e8b207eSAndrei Emeltchenko 	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
34930e8b207eSAndrei Emeltchenko 			test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
34940e8b207eSAndrei Emeltchenko 
34950e8b207eSAndrei Emeltchenko 		/* check compatibility */
34960e8b207eSAndrei Emeltchenko 
34970e8b207eSAndrei Emeltchenko 		clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
34980e8b207eSAndrei Emeltchenko 		set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
34990e8b207eSAndrei Emeltchenko 
35000e8b207eSAndrei Emeltchenko 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
35010e8b207eSAndrei Emeltchenko 					l2cap_build_conf_rsp(chan, rsp,
35020e8b207eSAndrei Emeltchenko 					L2CAP_CONF_SUCCESS, 0x0000), rsp);
35030e8b207eSAndrei Emeltchenko 	}
35040e8b207eSAndrei Emeltchenko 
35050a708f8fSGustavo F. Padovan unlock:
35066be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
35073c588192SMat Martineau 	return err;
35080a708f8fSGustavo F. Padovan }
35090a708f8fSGustavo F. Padovan 
35100a708f8fSGustavo F. Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
35110a708f8fSGustavo F. Padovan {
35120a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
35130a708f8fSGustavo F. Padovan 	u16 scid, flags, result;
351448454079SGustavo F. Padovan 	struct l2cap_chan *chan;
351561386cbaSAndrei Emeltchenko 	int len = le16_to_cpu(cmd->len) - sizeof(*rsp);
35163c588192SMat Martineau 	int err = 0;
35170a708f8fSGustavo F. Padovan 
35180a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
35190a708f8fSGustavo F. Padovan 	flags  = __le16_to_cpu(rsp->flags);
35200a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
35210a708f8fSGustavo F. Padovan 
352261386cbaSAndrei Emeltchenko 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
352361386cbaSAndrei Emeltchenko 	       result, len);
35240a708f8fSGustavo F. Padovan 
3525baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, scid);
352648454079SGustavo F. Padovan 	if (!chan)
35270a708f8fSGustavo F. Padovan 		return 0;
35280a708f8fSGustavo F. Padovan 
35290a708f8fSGustavo F. Padovan 	switch (result) {
35300a708f8fSGustavo F. Padovan 	case L2CAP_CONF_SUCCESS:
353147d1ec61SGustavo F. Padovan 		l2cap_conf_rfc_get(chan, rsp->data, len);
35320e8b207eSAndrei Emeltchenko 		clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
35330a708f8fSGustavo F. Padovan 		break;
35340a708f8fSGustavo F. Padovan 
35350e8b207eSAndrei Emeltchenko 	case L2CAP_CONF_PENDING:
35360e8b207eSAndrei Emeltchenko 		set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
35370e8b207eSAndrei Emeltchenko 
35380e8b207eSAndrei Emeltchenko 		if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
35390e8b207eSAndrei Emeltchenko 			char buf[64];
35400e8b207eSAndrei Emeltchenko 
35410e8b207eSAndrei Emeltchenko 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
35420e8b207eSAndrei Emeltchenko 								buf, &result);
35430e8b207eSAndrei Emeltchenko 			if (len < 0) {
35440e8b207eSAndrei Emeltchenko 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
35450e8b207eSAndrei Emeltchenko 				goto done;
35460e8b207eSAndrei Emeltchenko 			}
35470e8b207eSAndrei Emeltchenko 
35480e8b207eSAndrei Emeltchenko 			/* check compatibility */
35490e8b207eSAndrei Emeltchenko 
35500e8b207eSAndrei Emeltchenko 			clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
35510e8b207eSAndrei Emeltchenko 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
35520e8b207eSAndrei Emeltchenko 
35530e8b207eSAndrei Emeltchenko 			l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
35540e8b207eSAndrei Emeltchenko 						l2cap_build_conf_rsp(chan, buf,
35550e8b207eSAndrei Emeltchenko 						L2CAP_CONF_SUCCESS, 0x0000), buf);
35560e8b207eSAndrei Emeltchenko 		}
35570e8b207eSAndrei Emeltchenko 		goto done;
35580e8b207eSAndrei Emeltchenko 
35590a708f8fSGustavo F. Padovan 	case L2CAP_CONF_UNACCEPT:
356073ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
35610a708f8fSGustavo F. Padovan 			char req[64];
35620a708f8fSGustavo F. Padovan 
35630a708f8fSGustavo F. Padovan 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
3564e92c8e70SGustavo F. Padovan 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
35650a708f8fSGustavo F. Padovan 				goto done;
35660a708f8fSGustavo F. Padovan 			}
35670a708f8fSGustavo F. Padovan 
35680a708f8fSGustavo F. Padovan 			/* throw out any old stored conf requests */
35690a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_SUCCESS;
3570b4450035SGustavo F. Padovan 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
3571b4450035SGustavo F. Padovan 								req, &result);
35720a708f8fSGustavo F. Padovan 			if (len < 0) {
3573e92c8e70SGustavo F. Padovan 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
35740a708f8fSGustavo F. Padovan 				goto done;
35750a708f8fSGustavo F. Padovan 			}
35760a708f8fSGustavo F. Padovan 
35770a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn),
35780a708f8fSGustavo F. Padovan 						L2CAP_CONF_REQ, len, req);
357973ffa904SGustavo F. Padovan 			chan->num_conf_req++;
35800a708f8fSGustavo F. Padovan 			if (result != L2CAP_CONF_SUCCESS)
35810a708f8fSGustavo F. Padovan 				goto done;
35820a708f8fSGustavo F. Padovan 			break;
35830a708f8fSGustavo F. Padovan 		}
35840a708f8fSGustavo F. Padovan 
35850a708f8fSGustavo F. Padovan 	default:
35866be36555SAndrei Emeltchenko 		l2cap_chan_set_err(chan, ECONNRESET);
35872e0052e4SAndrei Emeltchenko 
3588ba13ccd9SMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
3589e92c8e70SGustavo F. Padovan 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
35900a708f8fSGustavo F. Padovan 		goto done;
35910a708f8fSGustavo F. Padovan 	}
35920a708f8fSGustavo F. Padovan 
35930a708f8fSGustavo F. Padovan 	if (flags & 0x01)
35940a708f8fSGustavo F. Padovan 		goto done;
35950a708f8fSGustavo F. Padovan 
3596c1360a1cSGustavo F. Padovan 	set_bit(CONF_INPUT_DONE, &chan->conf_state);
35970a708f8fSGustavo F. Padovan 
3598c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
359947d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
36000a708f8fSGustavo F. Padovan 
360189bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONNECTED);
3602105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
3603105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
36043c588192SMat Martineau 			err = l2cap_ertm_init(chan);
36050a708f8fSGustavo F. Padovan 
36063c588192SMat Martineau 		if (err < 0)
36073c588192SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, -err);
36083c588192SMat Martineau 		else
3609cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
36100a708f8fSGustavo F. Padovan 	}
36110a708f8fSGustavo F. Padovan 
36120a708f8fSGustavo F. Padovan done:
36136be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
36143c588192SMat Martineau 	return err;
36150a708f8fSGustavo F. Padovan }
36160a708f8fSGustavo F. Padovan 
36170a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
36180a708f8fSGustavo F. Padovan {
36190a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
36200a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp rsp;
36210a708f8fSGustavo F. Padovan 	u16 dcid, scid;
362248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
36230a708f8fSGustavo F. Padovan 	struct sock *sk;
36240a708f8fSGustavo F. Padovan 
36250a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(req->scid);
36260a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(req->dcid);
36270a708f8fSGustavo F. Padovan 
36280a708f8fSGustavo F. Padovan 	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
36290a708f8fSGustavo F. Padovan 
36303df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
36313df91ea2SAndrei Emeltchenko 
36323df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, dcid);
36333df91ea2SAndrei Emeltchenko 	if (!chan) {
36343df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
36350a708f8fSGustavo F. Padovan 		return 0;
36363df91ea2SAndrei Emeltchenko 	}
36370a708f8fSGustavo F. Padovan 
36386be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
36396be36555SAndrei Emeltchenko 
364048454079SGustavo F. Padovan 	sk = chan->sk;
364148454079SGustavo F. Padovan 
3642fe4128e0SGustavo F. Padovan 	rsp.dcid = cpu_to_le16(chan->scid);
3643fe4128e0SGustavo F. Padovan 	rsp.scid = cpu_to_le16(chan->dcid);
36440a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
36450a708f8fSGustavo F. Padovan 
36466be36555SAndrei Emeltchenko 	lock_sock(sk);
36470a708f8fSGustavo F. Padovan 	sk->sk_shutdown = SHUTDOWN_MASK;
36486be36555SAndrei Emeltchenko 	release_sock(sk);
36490a708f8fSGustavo F. Padovan 
365061d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
365148454079SGustavo F. Padovan 	l2cap_chan_del(chan, ECONNRESET);
36526be36555SAndrei Emeltchenko 
36536be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
36540a708f8fSGustavo F. Padovan 
3655ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
365661d6ef3eSMat Martineau 	l2cap_chan_put(chan);
36573df91ea2SAndrei Emeltchenko 
36583df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
36593df91ea2SAndrei Emeltchenko 
36600a708f8fSGustavo F. Padovan 	return 0;
36610a708f8fSGustavo F. Padovan }
36620a708f8fSGustavo F. Padovan 
36630a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
36640a708f8fSGustavo F. Padovan {
36650a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
36660a708f8fSGustavo F. Padovan 	u16 dcid, scid;
366748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
36680a708f8fSGustavo F. Padovan 
36690a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(rsp->scid);
36700a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(rsp->dcid);
36710a708f8fSGustavo F. Padovan 
36720a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
36730a708f8fSGustavo F. Padovan 
36743df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
36753df91ea2SAndrei Emeltchenko 
36763df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, scid);
36773df91ea2SAndrei Emeltchenko 	if (!chan) {
36783df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
36790a708f8fSGustavo F. Padovan 		return 0;
36803df91ea2SAndrei Emeltchenko 	}
36810a708f8fSGustavo F. Padovan 
36826be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
368348454079SGustavo F. Padovan 
368461d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
368548454079SGustavo F. Padovan 	l2cap_chan_del(chan, 0);
36866be36555SAndrei Emeltchenko 
36876be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
36880a708f8fSGustavo F. Padovan 
3689ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
369061d6ef3eSMat Martineau 	l2cap_chan_put(chan);
36913df91ea2SAndrei Emeltchenko 
36923df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
36933df91ea2SAndrei Emeltchenko 
36940a708f8fSGustavo F. Padovan 	return 0;
36950a708f8fSGustavo F. Padovan }
36960a708f8fSGustavo F. Padovan 
36970a708f8fSGustavo F. Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
36980a708f8fSGustavo F. Padovan {
36990a708f8fSGustavo F. Padovan 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
37000a708f8fSGustavo F. Padovan 	u16 type;
37010a708f8fSGustavo F. Padovan 
37020a708f8fSGustavo F. Padovan 	type = __le16_to_cpu(req->type);
37030a708f8fSGustavo F. Padovan 
37040a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x", type);
37050a708f8fSGustavo F. Padovan 
37060a708f8fSGustavo F. Padovan 	if (type == L2CAP_IT_FEAT_MASK) {
37070a708f8fSGustavo F. Padovan 		u8 buf[8];
37080a708f8fSGustavo F. Padovan 		u32 feat_mask = l2cap_feat_mask;
37090a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
37100a708f8fSGustavo F. Padovan 		rsp->type   = cpu_to_le16(L2CAP_IT_FEAT_MASK);
37110a708f8fSGustavo F. Padovan 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
37120a708f8fSGustavo F. Padovan 		if (!disable_ertm)
37130a708f8fSGustavo F. Padovan 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
37140a708f8fSGustavo F. Padovan 							 | L2CAP_FEAT_FCS;
3715a5fd6f30SAndrei Emeltchenko 		if (enable_hs)
37166327eb98SAndrei Emeltchenko 			feat_mask |= L2CAP_FEAT_EXT_FLOW
37176327eb98SAndrei Emeltchenko 						| L2CAP_FEAT_EXT_WINDOW;
3718a5fd6f30SAndrei Emeltchenko 
37190a708f8fSGustavo F. Padovan 		put_unaligned_le32(feat_mask, rsp->data);
37200a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
37210a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(buf), buf);
37220a708f8fSGustavo F. Padovan 	} else if (type == L2CAP_IT_FIXED_CHAN) {
37230a708f8fSGustavo F. Padovan 		u8 buf[12];
37240a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
372550a147cdSMat Martineau 
372650a147cdSMat Martineau 		if (enable_hs)
372750a147cdSMat Martineau 			l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
372850a147cdSMat Martineau 		else
372950a147cdSMat Martineau 			l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
373050a147cdSMat Martineau 
37310a708f8fSGustavo F. Padovan 		rsp->type   = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
37320a708f8fSGustavo F. Padovan 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
3733c6337ea6SAndrei Emeltchenko 		memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
37340a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
37350a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(buf), buf);
37360a708f8fSGustavo F. Padovan 	} else {
37370a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp rsp;
37380a708f8fSGustavo F. Padovan 		rsp.type   = cpu_to_le16(type);
37390a708f8fSGustavo F. Padovan 		rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
37400a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
37410a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(rsp), &rsp);
37420a708f8fSGustavo F. Padovan 	}
37430a708f8fSGustavo F. Padovan 
37440a708f8fSGustavo F. Padovan 	return 0;
37450a708f8fSGustavo F. Padovan }
37460a708f8fSGustavo F. Padovan 
37470a708f8fSGustavo F. Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
37480a708f8fSGustavo F. Padovan {
37490a708f8fSGustavo F. Padovan 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
37500a708f8fSGustavo F. Padovan 	u16 type, result;
37510a708f8fSGustavo F. Padovan 
37520a708f8fSGustavo F. Padovan 	type   = __le16_to_cpu(rsp->type);
37530a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
37540a708f8fSGustavo F. Padovan 
37550a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
37560a708f8fSGustavo F. Padovan 
3757e90165beSAndrei Emeltchenko 	/* L2CAP Info req/rsp are unbound to channels, add extra checks */
3758e90165beSAndrei Emeltchenko 	if (cmd->ident != conn->info_ident ||
3759e90165beSAndrei Emeltchenko 			conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3760e90165beSAndrei Emeltchenko 		return 0;
3761e90165beSAndrei Emeltchenko 
376217cd3f37SUlisses Furquim 	cancel_delayed_work(&conn->info_timer);
37630a708f8fSGustavo F. Padovan 
37640a708f8fSGustavo F. Padovan 	if (result != L2CAP_IR_SUCCESS) {
37650a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
37660a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
37670a708f8fSGustavo F. Padovan 
37680a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
37690a708f8fSGustavo F. Padovan 
37700a708f8fSGustavo F. Padovan 		return 0;
37710a708f8fSGustavo F. Padovan 	}
37720a708f8fSGustavo F. Padovan 
3773978c93b9SAndrei Emeltchenko 	switch (type) {
3774978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FEAT_MASK:
37750a708f8fSGustavo F. Padovan 		conn->feat_mask = get_unaligned_le32(rsp->data);
37760a708f8fSGustavo F. Padovan 
37770a708f8fSGustavo F. Padovan 		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
37780a708f8fSGustavo F. Padovan 			struct l2cap_info_req req;
37790a708f8fSGustavo F. Padovan 			req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
37800a708f8fSGustavo F. Padovan 
37810a708f8fSGustavo F. Padovan 			conn->info_ident = l2cap_get_ident(conn);
37820a708f8fSGustavo F. Padovan 
37830a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, conn->info_ident,
37840a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(req), &req);
37850a708f8fSGustavo F. Padovan 		} else {
37860a708f8fSGustavo F. Padovan 			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
37870a708f8fSGustavo F. Padovan 			conn->info_ident = 0;
37880a708f8fSGustavo F. Padovan 
37890a708f8fSGustavo F. Padovan 			l2cap_conn_start(conn);
37900a708f8fSGustavo F. Padovan 		}
3791978c93b9SAndrei Emeltchenko 		break;
3792978c93b9SAndrei Emeltchenko 
3793978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FIXED_CHAN:
3794978c93b9SAndrei Emeltchenko 		conn->fixed_chan_mask = rsp->data[0];
37950a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
37960a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
37970a708f8fSGustavo F. Padovan 
37980a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
3799978c93b9SAndrei Emeltchenko 		break;
38000a708f8fSGustavo F. Padovan 	}
38010a708f8fSGustavo F. Padovan 
38020a708f8fSGustavo F. Padovan 	return 0;
38030a708f8fSGustavo F. Padovan }
38040a708f8fSGustavo F. Padovan 
3805f94ff6ffSMat Martineau static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3806f94ff6ffSMat Martineau 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3807f94ff6ffSMat Martineau 					void *data)
3808f94ff6ffSMat Martineau {
3809f94ff6ffSMat Martineau 	struct l2cap_create_chan_req *req = data;
3810f94ff6ffSMat Martineau 	struct l2cap_create_chan_rsp rsp;
3811f94ff6ffSMat Martineau 	u16 psm, scid;
3812f94ff6ffSMat Martineau 
3813f94ff6ffSMat Martineau 	if (cmd_len != sizeof(*req))
3814f94ff6ffSMat Martineau 		return -EPROTO;
3815f94ff6ffSMat Martineau 
3816f94ff6ffSMat Martineau 	if (!enable_hs)
3817f94ff6ffSMat Martineau 		return -EINVAL;
3818f94ff6ffSMat Martineau 
3819f94ff6ffSMat Martineau 	psm = le16_to_cpu(req->psm);
3820f94ff6ffSMat Martineau 	scid = le16_to_cpu(req->scid);
3821f94ff6ffSMat Martineau 
3822f94ff6ffSMat Martineau 	BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3823f94ff6ffSMat Martineau 
3824f94ff6ffSMat Martineau 	/* Placeholder: Always reject */
3825f94ff6ffSMat Martineau 	rsp.dcid = 0;
3826f94ff6ffSMat Martineau 	rsp.scid = cpu_to_le16(scid);
38278ce0c498SAndrei Emeltchenko 	rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
38288ce0c498SAndrei Emeltchenko 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
3829f94ff6ffSMat Martineau 
3830f94ff6ffSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3831f94ff6ffSMat Martineau 		       sizeof(rsp), &rsp);
3832f94ff6ffSMat Martineau 
3833f94ff6ffSMat Martineau 	return 0;
3834f94ff6ffSMat Martineau }
3835f94ff6ffSMat Martineau 
3836f94ff6ffSMat Martineau static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3837f94ff6ffSMat Martineau 					struct l2cap_cmd_hdr *cmd, void *data)
3838f94ff6ffSMat Martineau {
3839f94ff6ffSMat Martineau 	BT_DBG("conn %p", conn);
3840f94ff6ffSMat Martineau 
3841f94ff6ffSMat Martineau 	return l2cap_connect_rsp(conn, cmd, data);
3842f94ff6ffSMat Martineau }
3843f94ff6ffSMat Martineau 
38448d5a04a1SMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
38458d5a04a1SMat Martineau 							u16 icid, u16 result)
38468d5a04a1SMat Martineau {
38478d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp rsp;
38488d5a04a1SMat Martineau 
38498d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
38508d5a04a1SMat Martineau 
38518d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
38528d5a04a1SMat Martineau 	rsp.result = cpu_to_le16(result);
38538d5a04a1SMat Martineau 
38548d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
38558d5a04a1SMat Martineau }
38568d5a04a1SMat Martineau 
38578d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
38588d5a04a1SMat Martineau 				struct l2cap_chan *chan, u16 icid, u16 result)
38598d5a04a1SMat Martineau {
38608d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm cfm;
38618d5a04a1SMat Martineau 	u8 ident;
38628d5a04a1SMat Martineau 
38638d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
38648d5a04a1SMat Martineau 
38658d5a04a1SMat Martineau 	ident = l2cap_get_ident(conn);
38668d5a04a1SMat Martineau 	if (chan)
38678d5a04a1SMat Martineau 		chan->ident = ident;
38688d5a04a1SMat Martineau 
38698d5a04a1SMat Martineau 	cfm.icid = cpu_to_le16(icid);
38708d5a04a1SMat Martineau 	cfm.result = cpu_to_le16(result);
38718d5a04a1SMat Martineau 
38728d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
38738d5a04a1SMat Martineau }
38748d5a04a1SMat Martineau 
38758d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
38768d5a04a1SMat Martineau 								u16 icid)
38778d5a04a1SMat Martineau {
38788d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp rsp;
38798d5a04a1SMat Martineau 
38808d5a04a1SMat Martineau 	BT_DBG("icid %d", icid);
38818d5a04a1SMat Martineau 
38828d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
38838d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
38848d5a04a1SMat Martineau }
38858d5a04a1SMat Martineau 
38868d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
38878d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
38888d5a04a1SMat Martineau {
38898d5a04a1SMat Martineau 	struct l2cap_move_chan_req *req = data;
38908d5a04a1SMat Martineau 	u16 icid = 0;
38918d5a04a1SMat Martineau 	u16 result = L2CAP_MR_NOT_ALLOWED;
38928d5a04a1SMat Martineau 
38938d5a04a1SMat Martineau 	if (cmd_len != sizeof(*req))
38948d5a04a1SMat Martineau 		return -EPROTO;
38958d5a04a1SMat Martineau 
38968d5a04a1SMat Martineau 	icid = le16_to_cpu(req->icid);
38978d5a04a1SMat Martineau 
38988d5a04a1SMat Martineau 	BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
38998d5a04a1SMat Martineau 
39008d5a04a1SMat Martineau 	if (!enable_hs)
39018d5a04a1SMat Martineau 		return -EINVAL;
39028d5a04a1SMat Martineau 
39038d5a04a1SMat Martineau 	/* Placeholder: Always refuse */
39048d5a04a1SMat Martineau 	l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
39058d5a04a1SMat Martineau 
39068d5a04a1SMat Martineau 	return 0;
39078d5a04a1SMat Martineau }
39088d5a04a1SMat Martineau 
39098d5a04a1SMat Martineau static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
39108d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
39118d5a04a1SMat Martineau {
39128d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp *rsp = data;
39138d5a04a1SMat Martineau 	u16 icid, result;
39148d5a04a1SMat Martineau 
39158d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
39168d5a04a1SMat Martineau 		return -EPROTO;
39178d5a04a1SMat Martineau 
39188d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
39198d5a04a1SMat Martineau 	result = le16_to_cpu(rsp->result);
39208d5a04a1SMat Martineau 
39218d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
39228d5a04a1SMat Martineau 
39238d5a04a1SMat Martineau 	/* Placeholder: Always unconfirmed */
39248d5a04a1SMat Martineau 	l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
39258d5a04a1SMat Martineau 
39268d5a04a1SMat Martineau 	return 0;
39278d5a04a1SMat Martineau }
39288d5a04a1SMat Martineau 
39298d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
39308d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
39318d5a04a1SMat Martineau {
39328d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm *cfm = data;
39338d5a04a1SMat Martineau 	u16 icid, result;
39348d5a04a1SMat Martineau 
39358d5a04a1SMat Martineau 	if (cmd_len != sizeof(*cfm))
39368d5a04a1SMat Martineau 		return -EPROTO;
39378d5a04a1SMat Martineau 
39388d5a04a1SMat Martineau 	icid = le16_to_cpu(cfm->icid);
39398d5a04a1SMat Martineau 	result = le16_to_cpu(cfm->result);
39408d5a04a1SMat Martineau 
39418d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
39428d5a04a1SMat Martineau 
39438d5a04a1SMat Martineau 	l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
39448d5a04a1SMat Martineau 
39458d5a04a1SMat Martineau 	return 0;
39468d5a04a1SMat Martineau }
39478d5a04a1SMat Martineau 
39488d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
39498d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
39508d5a04a1SMat Martineau {
39518d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp *rsp = data;
39528d5a04a1SMat Martineau 	u16 icid;
39538d5a04a1SMat Martineau 
39548d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
39558d5a04a1SMat Martineau 		return -EPROTO;
39568d5a04a1SMat Martineau 
39578d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
39588d5a04a1SMat Martineau 
39598d5a04a1SMat Martineau 	BT_DBG("icid %d", icid);
39608d5a04a1SMat Martineau 
39618d5a04a1SMat Martineau 	return 0;
39628d5a04a1SMat Martineau }
39638d5a04a1SMat Martineau 
3964e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
3965de73115aSClaudio Takahasi 							u16 to_multiplier)
3966de73115aSClaudio Takahasi {
3967de73115aSClaudio Takahasi 	u16 max_latency;
3968de73115aSClaudio Takahasi 
3969de73115aSClaudio Takahasi 	if (min > max || min < 6 || max > 3200)
3970de73115aSClaudio Takahasi 		return -EINVAL;
3971de73115aSClaudio Takahasi 
3972de73115aSClaudio Takahasi 	if (to_multiplier < 10 || to_multiplier > 3200)
3973de73115aSClaudio Takahasi 		return -EINVAL;
3974de73115aSClaudio Takahasi 
3975de73115aSClaudio Takahasi 	if (max >= to_multiplier * 8)
3976de73115aSClaudio Takahasi 		return -EINVAL;
3977de73115aSClaudio Takahasi 
3978de73115aSClaudio Takahasi 	max_latency = (to_multiplier * 8 / max) - 1;
3979de73115aSClaudio Takahasi 	if (latency > 499 || latency > max_latency)
3980de73115aSClaudio Takahasi 		return -EINVAL;
3981de73115aSClaudio Takahasi 
3982de73115aSClaudio Takahasi 	return 0;
3983de73115aSClaudio Takahasi }
3984de73115aSClaudio Takahasi 
3985de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3986de73115aSClaudio Takahasi 					struct l2cap_cmd_hdr *cmd, u8 *data)
3987de73115aSClaudio Takahasi {
3988de73115aSClaudio Takahasi 	struct hci_conn *hcon = conn->hcon;
3989de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_req *req;
3990de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_rsp rsp;
3991de73115aSClaudio Takahasi 	u16 min, max, latency, to_multiplier, cmd_len;
39922ce603ebSClaudio Takahasi 	int err;
3993de73115aSClaudio Takahasi 
3994de73115aSClaudio Takahasi 	if (!(hcon->link_mode & HCI_LM_MASTER))
3995de73115aSClaudio Takahasi 		return -EINVAL;
3996de73115aSClaudio Takahasi 
3997de73115aSClaudio Takahasi 	cmd_len = __le16_to_cpu(cmd->len);
3998de73115aSClaudio Takahasi 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3999de73115aSClaudio Takahasi 		return -EPROTO;
4000de73115aSClaudio Takahasi 
4001de73115aSClaudio Takahasi 	req = (struct l2cap_conn_param_update_req *) data;
4002de73115aSClaudio Takahasi 	min		= __le16_to_cpu(req->min);
4003de73115aSClaudio Takahasi 	max		= __le16_to_cpu(req->max);
4004de73115aSClaudio Takahasi 	latency		= __le16_to_cpu(req->latency);
4005de73115aSClaudio Takahasi 	to_multiplier	= __le16_to_cpu(req->to_multiplier);
4006de73115aSClaudio Takahasi 
4007de73115aSClaudio Takahasi 	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
4008de73115aSClaudio Takahasi 						min, max, latency, to_multiplier);
4009de73115aSClaudio Takahasi 
4010de73115aSClaudio Takahasi 	memset(&rsp, 0, sizeof(rsp));
40112ce603ebSClaudio Takahasi 
40122ce603ebSClaudio Takahasi 	err = l2cap_check_conn_param(min, max, latency, to_multiplier);
40132ce603ebSClaudio Takahasi 	if (err)
4014de73115aSClaudio Takahasi 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
4015de73115aSClaudio Takahasi 	else
4016de73115aSClaudio Takahasi 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
4017de73115aSClaudio Takahasi 
4018de73115aSClaudio Takahasi 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
4019de73115aSClaudio Takahasi 							sizeof(rsp), &rsp);
4020de73115aSClaudio Takahasi 
40212ce603ebSClaudio Takahasi 	if (!err)
40222ce603ebSClaudio Takahasi 		hci_le_conn_update(hcon, min, max, latency, to_multiplier);
40232ce603ebSClaudio Takahasi 
4024de73115aSClaudio Takahasi 	return 0;
4025de73115aSClaudio Takahasi }
4026de73115aSClaudio Takahasi 
40273300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
40283300d9a9SClaudio Takahasi 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
40293300d9a9SClaudio Takahasi {
40303300d9a9SClaudio Takahasi 	int err = 0;
40313300d9a9SClaudio Takahasi 
40323300d9a9SClaudio Takahasi 	switch (cmd->code) {
40333300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
40343300d9a9SClaudio Takahasi 		l2cap_command_rej(conn, cmd, data);
40353300d9a9SClaudio Takahasi 		break;
40363300d9a9SClaudio Takahasi 
40373300d9a9SClaudio Takahasi 	case L2CAP_CONN_REQ:
40383300d9a9SClaudio Takahasi 		err = l2cap_connect_req(conn, cmd, data);
40393300d9a9SClaudio Takahasi 		break;
40403300d9a9SClaudio Takahasi 
40413300d9a9SClaudio Takahasi 	case L2CAP_CONN_RSP:
40423300d9a9SClaudio Takahasi 		err = l2cap_connect_rsp(conn, cmd, data);
40433300d9a9SClaudio Takahasi 		break;
40443300d9a9SClaudio Takahasi 
40453300d9a9SClaudio Takahasi 	case L2CAP_CONF_REQ:
40463300d9a9SClaudio Takahasi 		err = l2cap_config_req(conn, cmd, cmd_len, data);
40473300d9a9SClaudio Takahasi 		break;
40483300d9a9SClaudio Takahasi 
40493300d9a9SClaudio Takahasi 	case L2CAP_CONF_RSP:
40503300d9a9SClaudio Takahasi 		err = l2cap_config_rsp(conn, cmd, data);
40513300d9a9SClaudio Takahasi 		break;
40523300d9a9SClaudio Takahasi 
40533300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_REQ:
40543300d9a9SClaudio Takahasi 		err = l2cap_disconnect_req(conn, cmd, data);
40553300d9a9SClaudio Takahasi 		break;
40563300d9a9SClaudio Takahasi 
40573300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_RSP:
40583300d9a9SClaudio Takahasi 		err = l2cap_disconnect_rsp(conn, cmd, data);
40593300d9a9SClaudio Takahasi 		break;
40603300d9a9SClaudio Takahasi 
40613300d9a9SClaudio Takahasi 	case L2CAP_ECHO_REQ:
40623300d9a9SClaudio Takahasi 		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
40633300d9a9SClaudio Takahasi 		break;
40643300d9a9SClaudio Takahasi 
40653300d9a9SClaudio Takahasi 	case L2CAP_ECHO_RSP:
40663300d9a9SClaudio Takahasi 		break;
40673300d9a9SClaudio Takahasi 
40683300d9a9SClaudio Takahasi 	case L2CAP_INFO_REQ:
40693300d9a9SClaudio Takahasi 		err = l2cap_information_req(conn, cmd, data);
40703300d9a9SClaudio Takahasi 		break;
40713300d9a9SClaudio Takahasi 
40723300d9a9SClaudio Takahasi 	case L2CAP_INFO_RSP:
40733300d9a9SClaudio Takahasi 		err = l2cap_information_rsp(conn, cmd, data);
40743300d9a9SClaudio Takahasi 		break;
40753300d9a9SClaudio Takahasi 
4076f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_REQ:
4077f94ff6ffSMat Martineau 		err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
4078f94ff6ffSMat Martineau 		break;
4079f94ff6ffSMat Martineau 
4080f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_RSP:
4081f94ff6ffSMat Martineau 		err = l2cap_create_channel_rsp(conn, cmd, data);
4082f94ff6ffSMat Martineau 		break;
4083f94ff6ffSMat Martineau 
40848d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_REQ:
40858d5a04a1SMat Martineau 		err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
40868d5a04a1SMat Martineau 		break;
40878d5a04a1SMat Martineau 
40888d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_RSP:
40898d5a04a1SMat Martineau 		err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
40908d5a04a1SMat Martineau 		break;
40918d5a04a1SMat Martineau 
40928d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM:
40938d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
40948d5a04a1SMat Martineau 		break;
40958d5a04a1SMat Martineau 
40968d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM_RSP:
40978d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
40988d5a04a1SMat Martineau 		break;
40998d5a04a1SMat Martineau 
41003300d9a9SClaudio Takahasi 	default:
41013300d9a9SClaudio Takahasi 		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
41023300d9a9SClaudio Takahasi 		err = -EINVAL;
41033300d9a9SClaudio Takahasi 		break;
41043300d9a9SClaudio Takahasi 	}
41053300d9a9SClaudio Takahasi 
41063300d9a9SClaudio Takahasi 	return err;
41073300d9a9SClaudio Takahasi }
41083300d9a9SClaudio Takahasi 
41093300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
41103300d9a9SClaudio Takahasi 					struct l2cap_cmd_hdr *cmd, u8 *data)
41113300d9a9SClaudio Takahasi {
41123300d9a9SClaudio Takahasi 	switch (cmd->code) {
41133300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
41143300d9a9SClaudio Takahasi 		return 0;
41153300d9a9SClaudio Takahasi 
41163300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_REQ:
4117de73115aSClaudio Takahasi 		return l2cap_conn_param_update_req(conn, cmd, data);
41183300d9a9SClaudio Takahasi 
41193300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_RSP:
41203300d9a9SClaudio Takahasi 		return 0;
41213300d9a9SClaudio Takahasi 
41223300d9a9SClaudio Takahasi 	default:
41233300d9a9SClaudio Takahasi 		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
41243300d9a9SClaudio Takahasi 		return -EINVAL;
41253300d9a9SClaudio Takahasi 	}
41263300d9a9SClaudio Takahasi }
41273300d9a9SClaudio Takahasi 
41283300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
41293300d9a9SClaudio Takahasi 							struct sk_buff *skb)
41300a708f8fSGustavo F. Padovan {
41310a708f8fSGustavo F. Padovan 	u8 *data = skb->data;
41320a708f8fSGustavo F. Padovan 	int len = skb->len;
41330a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr cmd;
41343300d9a9SClaudio Takahasi 	int err;
41350a708f8fSGustavo F. Padovan 
41360a708f8fSGustavo F. Padovan 	l2cap_raw_recv(conn, skb);
41370a708f8fSGustavo F. Padovan 
41380a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CMD_HDR_SIZE) {
41390a708f8fSGustavo F. Padovan 		u16 cmd_len;
41400a708f8fSGustavo F. Padovan 		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
41410a708f8fSGustavo F. Padovan 		data += L2CAP_CMD_HDR_SIZE;
41420a708f8fSGustavo F. Padovan 		len  -= L2CAP_CMD_HDR_SIZE;
41430a708f8fSGustavo F. Padovan 
41440a708f8fSGustavo F. Padovan 		cmd_len = le16_to_cpu(cmd.len);
41450a708f8fSGustavo F. Padovan 
41460a708f8fSGustavo F. Padovan 		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident);
41470a708f8fSGustavo F. Padovan 
41480a708f8fSGustavo F. Padovan 		if (cmd_len > len || !cmd.ident) {
41490a708f8fSGustavo F. Padovan 			BT_DBG("corrupted command");
41500a708f8fSGustavo F. Padovan 			break;
41510a708f8fSGustavo F. Padovan 		}
41520a708f8fSGustavo F. Padovan 
41533300d9a9SClaudio Takahasi 		if (conn->hcon->type == LE_LINK)
41543300d9a9SClaudio Takahasi 			err = l2cap_le_sig_cmd(conn, &cmd, data);
41553300d9a9SClaudio Takahasi 		else
41563300d9a9SClaudio Takahasi 			err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
41570a708f8fSGustavo F. Padovan 
41580a708f8fSGustavo F. Padovan 		if (err) {
4159e2fd318eSIlia Kolomisnky 			struct l2cap_cmd_rej_unk rej;
41602c6d1a2eSGustavo F. Padovan 
41612c6d1a2eSGustavo F. Padovan 			BT_ERR("Wrong link type (%d)", err);
41620a708f8fSGustavo F. Padovan 
41630a708f8fSGustavo F. Padovan 			/* FIXME: Map err to a valid reason */
4164e2fd318eSIlia Kolomisnky 			rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
41650a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
41660a708f8fSGustavo F. Padovan 		}
41670a708f8fSGustavo F. Padovan 
41680a708f8fSGustavo F. Padovan 		data += cmd_len;
41690a708f8fSGustavo F. Padovan 		len  -= cmd_len;
41700a708f8fSGustavo F. Padovan 	}
41710a708f8fSGustavo F. Padovan 
41720a708f8fSGustavo F. Padovan 	kfree_skb(skb);
41730a708f8fSGustavo F. Padovan }
41740a708f8fSGustavo F. Padovan 
417547d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
41760a708f8fSGustavo F. Padovan {
41770a708f8fSGustavo F. Padovan 	u16 our_fcs, rcv_fcs;
4178e4ca6d98SAndrei Emeltchenko 	int hdr_size;
4179e4ca6d98SAndrei Emeltchenko 
4180e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
4181e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_EXT_HDR_SIZE;
4182e4ca6d98SAndrei Emeltchenko 	else
4183e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_ENH_HDR_SIZE;
41840a708f8fSGustavo F. Padovan 
418547d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
418603a51213SAndrei Emeltchenko 		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
41870a708f8fSGustavo F. Padovan 		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
41880a708f8fSGustavo F. Padovan 		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
41890a708f8fSGustavo F. Padovan 
41900a708f8fSGustavo F. Padovan 		if (our_fcs != rcv_fcs)
41910a708f8fSGustavo F. Padovan 			return -EBADMSG;
41920a708f8fSGustavo F. Padovan 	}
41930a708f8fSGustavo F. Padovan 	return 0;
41940a708f8fSGustavo F. Padovan }
41950a708f8fSGustavo F. Padovan 
4196525cd185SGustavo F. Padovan static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
41970a708f8fSGustavo F. Padovan {
419888843ab0SAndrei Emeltchenko 	u32 control = 0;
41990a708f8fSGustavo F. Padovan 
42006a026610SGustavo F. Padovan 	chan->frames_sent = 0;
42010a708f8fSGustavo F. Padovan 
42020b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
42030a708f8fSGustavo F. Padovan 
4204e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4205ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
4206e2ab4353SGustavo F. Padovan 		set_bit(CONN_RNR_SENT, &chan->conn_state);
42070a708f8fSGustavo F. Padovan 	}
42080a708f8fSGustavo F. Padovan 
4209e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
4210525cd185SGustavo F. Padovan 		l2cap_retransmit_frames(chan);
42110a708f8fSGustavo F. Padovan 
4212525cd185SGustavo F. Padovan 	l2cap_ertm_send(chan);
42130a708f8fSGustavo F. Padovan 
4214e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
42156a026610SGustavo F. Padovan 			chan->frames_sent == 0) {
4216ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
42170a708f8fSGustavo F. Padovan 	}
42180a708f8fSGustavo F. Padovan }
42190a708f8fSGustavo F. Padovan 
422084084a31SMat Martineau static void append_skb_frag(struct sk_buff *skb,
422184084a31SMat Martineau 			struct sk_buff *new_frag, struct sk_buff **last_frag)
42220a708f8fSGustavo F. Padovan {
422384084a31SMat Martineau 	/* skb->len reflects data in skb as well as all fragments
422484084a31SMat Martineau 	 * skb->data_len reflects only data in fragments
422584084a31SMat Martineau 	 */
422684084a31SMat Martineau 	if (!skb_has_frag_list(skb))
422784084a31SMat Martineau 		skb_shinfo(skb)->frag_list = new_frag;
422884084a31SMat Martineau 
422984084a31SMat Martineau 	new_frag->next = NULL;
423084084a31SMat Martineau 
423184084a31SMat Martineau 	(*last_frag)->next = new_frag;
423284084a31SMat Martineau 	*last_frag = new_frag;
423384084a31SMat Martineau 
423484084a31SMat Martineau 	skb->len += new_frag->len;
423584084a31SMat Martineau 	skb->data_len += new_frag->len;
423684084a31SMat Martineau 	skb->truesize += new_frag->truesize;
423784084a31SMat Martineau }
423884084a31SMat Martineau 
42394b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
42404b51dae9SMat Martineau 				struct l2cap_ctrl *control)
424184084a31SMat Martineau {
424284084a31SMat Martineau 	int err = -EINVAL;
42430a708f8fSGustavo F. Padovan 
42444b51dae9SMat Martineau 	switch (control->sar) {
42457e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_UNSEGMENTED:
424684084a31SMat Martineau 		if (chan->sdu)
424784084a31SMat Martineau 			break;
42480a708f8fSGustavo F. Padovan 
424984084a31SMat Martineau 		err = chan->ops->recv(chan->data, skb);
425084084a31SMat Martineau 		break;
42510a708f8fSGustavo F. Padovan 
42527e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_START:
425384084a31SMat Martineau 		if (chan->sdu)
425484084a31SMat Martineau 			break;
42550a708f8fSGustavo F. Padovan 
42566f61fd47SGustavo F. Padovan 		chan->sdu_len = get_unaligned_le16(skb->data);
425703a51213SAndrei Emeltchenko 		skb_pull(skb, L2CAP_SDULEN_SIZE);
42580a708f8fSGustavo F. Padovan 
425984084a31SMat Martineau 		if (chan->sdu_len > chan->imtu) {
426084084a31SMat Martineau 			err = -EMSGSIZE;
426184084a31SMat Martineau 			break;
426284084a31SMat Martineau 		}
42630a708f8fSGustavo F. Padovan 
426484084a31SMat Martineau 		if (skb->len >= chan->sdu_len)
426584084a31SMat Martineau 			break;
426684084a31SMat Martineau 
426784084a31SMat Martineau 		chan->sdu = skb;
426884084a31SMat Martineau 		chan->sdu_last_frag = skb;
426984084a31SMat Martineau 
427084084a31SMat Martineau 		skb = NULL;
427184084a31SMat Martineau 		err = 0;
42720a708f8fSGustavo F. Padovan 		break;
42730a708f8fSGustavo F. Padovan 
42747e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_CONTINUE:
42756f61fd47SGustavo F. Padovan 		if (!chan->sdu)
427684084a31SMat Martineau 			break;
42770a708f8fSGustavo F. Padovan 
427884084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
427984084a31SMat Martineau 				&chan->sdu_last_frag);
428084084a31SMat Martineau 		skb = NULL;
42810a708f8fSGustavo F. Padovan 
428284084a31SMat Martineau 		if (chan->sdu->len >= chan->sdu_len)
428384084a31SMat Martineau 			break;
42840a708f8fSGustavo F. Padovan 
428584084a31SMat Martineau 		err = 0;
42860a708f8fSGustavo F. Padovan 		break;
42870a708f8fSGustavo F. Padovan 
42887e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_END:
42896f61fd47SGustavo F. Padovan 		if (!chan->sdu)
429084084a31SMat Martineau 			break;
42910a708f8fSGustavo F. Padovan 
429284084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
429384084a31SMat Martineau 				&chan->sdu_last_frag);
429484084a31SMat Martineau 		skb = NULL;
42950a708f8fSGustavo F. Padovan 
429684084a31SMat Martineau 		if (chan->sdu->len != chan->sdu_len)
429784084a31SMat Martineau 			break;
42980a708f8fSGustavo F. Padovan 
429984084a31SMat Martineau 		err = chan->ops->recv(chan->data, chan->sdu);
43000a708f8fSGustavo F. Padovan 
430184084a31SMat Martineau 		if (!err) {
430284084a31SMat Martineau 			/* Reassembly complete */
430384084a31SMat Martineau 			chan->sdu = NULL;
430484084a31SMat Martineau 			chan->sdu_last_frag = NULL;
430584084a31SMat Martineau 			chan->sdu_len = 0;
43060a708f8fSGustavo F. Padovan 		}
43070a708f8fSGustavo F. Padovan 		break;
43080a708f8fSGustavo F. Padovan 	}
43090a708f8fSGustavo F. Padovan 
431084084a31SMat Martineau 	if (err) {
43110a708f8fSGustavo F. Padovan 		kfree_skb(skb);
43126f61fd47SGustavo F. Padovan 		kfree_skb(chan->sdu);
43136f61fd47SGustavo F. Padovan 		chan->sdu = NULL;
431484084a31SMat Martineau 		chan->sdu_last_frag = NULL;
431584084a31SMat Martineau 		chan->sdu_len = 0;
431684084a31SMat Martineau 	}
43170a708f8fSGustavo F. Padovan 
431884084a31SMat Martineau 	return err;
43190a708f8fSGustavo F. Padovan }
43200a708f8fSGustavo F. Padovan 
4321e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
43220a708f8fSGustavo F. Padovan {
432361aa4f5bSMat Martineau 	u8 event;
432461aa4f5bSMat Martineau 
432561aa4f5bSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
432661aa4f5bSMat Martineau 		return;
432761aa4f5bSMat Martineau 
432861aa4f5bSMat Martineau 	event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR;
432961aa4f5bSMat Martineau 	l2cap_tx(chan, 0, 0, event);
43300a708f8fSGustavo F. Padovan }
43310a708f8fSGustavo F. Padovan 
43324b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
43334b51dae9SMat Martineau {
43344b51dae9SMat Martineau 	BT_DBG("chan %p, txseq %d", chan, txseq);
43354b51dae9SMat Martineau 
43364b51dae9SMat Martineau 	BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq,
43374b51dae9SMat Martineau 	       chan->expected_tx_seq);
43384b51dae9SMat Martineau 
43394b51dae9SMat Martineau 	if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
43404b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
43414b51dae9SMat Martineau 								chan->tx_win) {
43424b51dae9SMat Martineau 			/* See notes below regarding "double poll" and
43434b51dae9SMat Martineau 			 * invalid packets.
43444b51dae9SMat Martineau 			 */
43454b51dae9SMat Martineau 			if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
43464b51dae9SMat Martineau 				BT_DBG("Invalid/Ignore - after SREJ");
43474b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID_IGNORE;
43484b51dae9SMat Martineau 			} else {
43494b51dae9SMat Martineau 				BT_DBG("Invalid - in window after SREJ sent");
43504b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID;
43514b51dae9SMat Martineau 			}
43524b51dae9SMat Martineau 		}
43534b51dae9SMat Martineau 
43544b51dae9SMat Martineau 		if (chan->srej_list.head == txseq) {
43554b51dae9SMat Martineau 			BT_DBG("Expected SREJ");
43564b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED_SREJ;
43574b51dae9SMat Martineau 		}
43584b51dae9SMat Martineau 
43594b51dae9SMat Martineau 		if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) {
43604b51dae9SMat Martineau 			BT_DBG("Duplicate SREJ - txseq already stored");
43614b51dae9SMat Martineau 			return L2CAP_TXSEQ_DUPLICATE_SREJ;
43624b51dae9SMat Martineau 		}
43634b51dae9SMat Martineau 
43644b51dae9SMat Martineau 		if (l2cap_seq_list_contains(&chan->srej_list, txseq)) {
43654b51dae9SMat Martineau 			BT_DBG("Unexpected SREJ - not requested");
43664b51dae9SMat Martineau 			return L2CAP_TXSEQ_UNEXPECTED_SREJ;
43674b51dae9SMat Martineau 		}
43684b51dae9SMat Martineau 	}
43694b51dae9SMat Martineau 
43704b51dae9SMat Martineau 	if (chan->expected_tx_seq == txseq) {
43714b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
43724b51dae9SMat Martineau 		    chan->tx_win) {
43734b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
43744b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
43754b51dae9SMat Martineau 		} else {
43764b51dae9SMat Martineau 			BT_DBG("Expected");
43774b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED;
43784b51dae9SMat Martineau 		}
43794b51dae9SMat Martineau 	}
43804b51dae9SMat Martineau 
43814b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) <
43824b51dae9SMat Martineau 		__seq_offset(chan, chan->expected_tx_seq,
43834b51dae9SMat Martineau 			     chan->last_acked_seq)){
43844b51dae9SMat Martineau 		BT_DBG("Duplicate - expected_tx_seq later than txseq");
43854b51dae9SMat Martineau 		return L2CAP_TXSEQ_DUPLICATE;
43864b51dae9SMat Martineau 	}
43874b51dae9SMat Martineau 
43884b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) {
43894b51dae9SMat Martineau 		/* A source of invalid packets is a "double poll" condition,
43904b51dae9SMat Martineau 		 * where delays cause us to send multiple poll packets.  If
43914b51dae9SMat Martineau 		 * the remote stack receives and processes both polls,
43924b51dae9SMat Martineau 		 * sequence numbers can wrap around in such a way that a
43934b51dae9SMat Martineau 		 * resent frame has a sequence number that looks like new data
43944b51dae9SMat Martineau 		 * with a sequence gap.  This would trigger an erroneous SREJ
43954b51dae9SMat Martineau 		 * request.
43964b51dae9SMat Martineau 		 *
43974b51dae9SMat Martineau 		 * Fortunately, this is impossible with a tx window that's
43984b51dae9SMat Martineau 		 * less than half of the maximum sequence number, which allows
43994b51dae9SMat Martineau 		 * invalid frames to be safely ignored.
44004b51dae9SMat Martineau 		 *
44014b51dae9SMat Martineau 		 * With tx window sizes greater than half of the tx window
44024b51dae9SMat Martineau 		 * maximum, the frame is invalid and cannot be ignored.  This
44034b51dae9SMat Martineau 		 * causes a disconnect.
44044b51dae9SMat Martineau 		 */
44054b51dae9SMat Martineau 
44064b51dae9SMat Martineau 		if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
44074b51dae9SMat Martineau 			BT_DBG("Invalid/Ignore - txseq outside tx window");
44084b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID_IGNORE;
44094b51dae9SMat Martineau 		} else {
44104b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
44114b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
44124b51dae9SMat Martineau 		}
44134b51dae9SMat Martineau 	} else {
44144b51dae9SMat Martineau 		BT_DBG("Unexpected - txseq indicates missing frames");
44154b51dae9SMat Martineau 		return L2CAP_TXSEQ_UNEXPECTED;
44164b51dae9SMat Martineau 	}
44174b51dae9SMat Martineau }
44184b51dae9SMat Martineau 
4419cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
4420cec8ab6eSMat Martineau 		    struct sk_buff *skb, u8 event)
44210a708f8fSGustavo F. Padovan {
4422cec8ab6eSMat Martineau 	/* Placeholder */
4423cec8ab6eSMat Martineau 	return -ENOTSUPP;
4424cec8ab6eSMat Martineau }
4425cec8ab6eSMat Martineau 
4426cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
4427cec8ab6eSMat Martineau 			   struct sk_buff *skb)
4428cec8ab6eSMat Martineau {
44294b51dae9SMat Martineau 	int err = 0;
44304b51dae9SMat Martineau 
44314b51dae9SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
44324b51dae9SMat Martineau 	       chan->rx_state);
44334b51dae9SMat Martineau 
44344b51dae9SMat Martineau 	if (l2cap_classify_txseq(chan, control->txseq) ==
44354b51dae9SMat Martineau 	    L2CAP_TXSEQ_EXPECTED) {
44364b51dae9SMat Martineau 		l2cap_pass_to_tx(chan, control);
44374b51dae9SMat Martineau 
44384b51dae9SMat Martineau 		BT_DBG("buffer_seq %d->%d", chan->buffer_seq,
44394b51dae9SMat Martineau 		       __next_seq(chan, chan->buffer_seq));
44404b51dae9SMat Martineau 
44414b51dae9SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
44424b51dae9SMat Martineau 
44434b51dae9SMat Martineau 		l2cap_reassemble_sdu(chan, skb, control);
44444b51dae9SMat Martineau 	} else {
44454b51dae9SMat Martineau 		if (chan->sdu) {
44464b51dae9SMat Martineau 			kfree_skb(chan->sdu);
44474b51dae9SMat Martineau 			chan->sdu = NULL;
44484b51dae9SMat Martineau 		}
44494b51dae9SMat Martineau 		chan->sdu_last_frag = NULL;
44504b51dae9SMat Martineau 		chan->sdu_len = 0;
44514b51dae9SMat Martineau 
44524b51dae9SMat Martineau 		if (skb) {
44534b51dae9SMat Martineau 			BT_DBG("Freeing %p", skb);
44544b51dae9SMat Martineau 			kfree_skb(skb);
44554b51dae9SMat Martineau 		}
44564b51dae9SMat Martineau 	}
44574b51dae9SMat Martineau 
44584b51dae9SMat Martineau 	chan->last_acked_seq = control->txseq;
44594b51dae9SMat Martineau 	chan->expected_tx_seq = __next_seq(chan, control->txseq);
44604b51dae9SMat Martineau 
44614b51dae9SMat Martineau 	return err;
4462cec8ab6eSMat Martineau }
4463cec8ab6eSMat Martineau 
4464cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
4465cec8ab6eSMat Martineau {
4466cec8ab6eSMat Martineau 	struct l2cap_ctrl *control = &bt_cb(skb)->control;
4467cec8ab6eSMat Martineau 	u16 len;
4468cec8ab6eSMat Martineau 	u8 event;
44690a708f8fSGustavo F. Padovan 
4470b76bbd66SMat Martineau 	__unpack_control(chan, skb);
4471b76bbd66SMat Martineau 
44720a708f8fSGustavo F. Padovan 	len = skb->len;
44730a708f8fSGustavo F. Padovan 
44740a708f8fSGustavo F. Padovan 	/*
44750a708f8fSGustavo F. Padovan 	 * We can just drop the corrupted I-frame here.
44760a708f8fSGustavo F. Padovan 	 * Receiver will miss it and start proper recovery
4477cec8ab6eSMat Martineau 	 * procedures and ask for retransmission.
44780a708f8fSGustavo F. Padovan 	 */
447947d1ec61SGustavo F. Padovan 	if (l2cap_check_fcs(chan, skb))
44800a708f8fSGustavo F. Padovan 		goto drop;
44810a708f8fSGustavo F. Padovan 
4482cec8ab6eSMat Martineau 	if (!control->sframe && control->sar == L2CAP_SAR_START)
448303a51213SAndrei Emeltchenko 		len -= L2CAP_SDULEN_SIZE;
44840a708f8fSGustavo F. Padovan 
448547d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
448603a51213SAndrei Emeltchenko 		len -= L2CAP_FCS_SIZE;
44870a708f8fSGustavo F. Padovan 
448847d1ec61SGustavo F. Padovan 	if (len > chan->mps) {
44898c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
44900a708f8fSGustavo F. Padovan 		goto drop;
44910a708f8fSGustavo F. Padovan 	}
44920a708f8fSGustavo F. Padovan 
4493cec8ab6eSMat Martineau 	if (!control->sframe) {
4494cec8ab6eSMat Martineau 		int err;
44950a708f8fSGustavo F. Padovan 
4496cec8ab6eSMat Martineau 		BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d",
4497cec8ab6eSMat Martineau 		       control->sar, control->reqseq, control->final,
4498cec8ab6eSMat Martineau 		       control->txseq);
4499836be934SAndrei Emeltchenko 
4500cec8ab6eSMat Martineau 		/* Validate F-bit - F=0 always valid, F=1 only
4501cec8ab6eSMat Martineau 		 * valid in TX WAIT_F
4502cec8ab6eSMat Martineau 		 */
4503cec8ab6eSMat Martineau 		if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F)
45040a708f8fSGustavo F. Padovan 			goto drop;
45050a708f8fSGustavo F. Padovan 
4506cec8ab6eSMat Martineau 		if (chan->mode != L2CAP_MODE_STREAMING) {
4507cec8ab6eSMat Martineau 			event = L2CAP_EV_RECV_IFRAME;
4508cec8ab6eSMat Martineau 			err = l2cap_rx(chan, control, skb, event);
45090a708f8fSGustavo F. Padovan 		} else {
4510cec8ab6eSMat Martineau 			err = l2cap_stream_rx(chan, control, skb);
4511cec8ab6eSMat Martineau 		}
4512cec8ab6eSMat Martineau 
4513cec8ab6eSMat Martineau 		if (err)
4514cec8ab6eSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan,
4515cec8ab6eSMat Martineau 					       ECONNRESET);
4516cec8ab6eSMat Martineau 	} else {
4517cec8ab6eSMat Martineau 		const u8 rx_func_to_event[4] = {
4518cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
4519cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ
4520cec8ab6eSMat Martineau 		};
4521cec8ab6eSMat Martineau 
4522cec8ab6eSMat Martineau 		/* Only I-frames are expected in streaming mode */
4523cec8ab6eSMat Martineau 		if (chan->mode == L2CAP_MODE_STREAMING)
4524cec8ab6eSMat Martineau 			goto drop;
4525cec8ab6eSMat Martineau 
4526cec8ab6eSMat Martineau 		BT_DBG("sframe reqseq %d, final %d, poll %d, super %d",
4527cec8ab6eSMat Martineau 		       control->reqseq, control->final, control->poll,
4528cec8ab6eSMat Martineau 		       control->super);
4529cec8ab6eSMat Martineau 
45300a708f8fSGustavo F. Padovan 		if (len != 0) {
45310a708f8fSGustavo F. Padovan 			BT_ERR("%d", len);
45328c1d787bSGustavo F. Padovan 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
45330a708f8fSGustavo F. Padovan 			goto drop;
45340a708f8fSGustavo F. Padovan 		}
45350a708f8fSGustavo F. Padovan 
4536cec8ab6eSMat Martineau 		/* Validate F and P bits */
4537cec8ab6eSMat Martineau 		if (control->final && (control->poll ||
4538cec8ab6eSMat Martineau 				       chan->tx_state != L2CAP_TX_STATE_WAIT_F))
4539cec8ab6eSMat Martineau 			goto drop;
4540cec8ab6eSMat Martineau 
4541cec8ab6eSMat Martineau 		event = rx_func_to_event[control->super];
4542cec8ab6eSMat Martineau 		if (l2cap_rx(chan, control, skb, event))
4543cec8ab6eSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
45440a708f8fSGustavo F. Padovan 	}
45450a708f8fSGustavo F. Padovan 
45460a708f8fSGustavo F. Padovan 	return 0;
45470a708f8fSGustavo F. Padovan 
45480a708f8fSGustavo F. Padovan drop:
45490a708f8fSGustavo F. Padovan 	kfree_skb(skb);
45500a708f8fSGustavo F. Padovan 	return 0;
45510a708f8fSGustavo F. Padovan }
45520a708f8fSGustavo F. Padovan 
45530a708f8fSGustavo F. Padovan static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
45540a708f8fSGustavo F. Padovan {
455548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
45560a708f8fSGustavo F. Padovan 
4557baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, cid);
455848454079SGustavo F. Padovan 	if (!chan) {
45590a708f8fSGustavo F. Padovan 		BT_DBG("unknown cid 0x%4.4x", cid);
45606be36555SAndrei Emeltchenko 		/* Drop packet and return */
45613379013bSDan Carpenter 		kfree_skb(skb);
45626be36555SAndrei Emeltchenko 		return 0;
45630a708f8fSGustavo F. Padovan 	}
45640a708f8fSGustavo F. Padovan 
456549208c9cSGustavo F. Padovan 	BT_DBG("chan %p, len %d", chan, skb->len);
45660a708f8fSGustavo F. Padovan 
456789bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
45680a708f8fSGustavo F. Padovan 		goto drop;
45690a708f8fSGustavo F. Padovan 
45700c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
45710a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
45720a708f8fSGustavo F. Padovan 		/* If socket recv buffers overflows we drop data here
45730a708f8fSGustavo F. Padovan 		 * which is *bad* because L2CAP has to be reliable.
45740a708f8fSGustavo F. Padovan 		 * But we don't have any other choice. L2CAP doesn't
45750a708f8fSGustavo F. Padovan 		 * provide flow control mechanism. */
45760a708f8fSGustavo F. Padovan 
45770c1bc5c6SGustavo F. Padovan 		if (chan->imtu < skb->len)
45780a708f8fSGustavo F. Padovan 			goto drop;
45790a708f8fSGustavo F. Padovan 
458023070494SGustavo F. Padovan 		if (!chan->ops->recv(chan->data, skb))
45810a708f8fSGustavo F. Padovan 			goto done;
45820a708f8fSGustavo F. Padovan 		break;
45830a708f8fSGustavo F. Padovan 
45840a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
45850a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
4586cec8ab6eSMat Martineau 		l2cap_data_rcv(chan, skb);
45870a708f8fSGustavo F. Padovan 		goto done;
45880a708f8fSGustavo F. Padovan 
45890a708f8fSGustavo F. Padovan 	default:
45900c1bc5c6SGustavo F. Padovan 		BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
45910a708f8fSGustavo F. Padovan 		break;
45920a708f8fSGustavo F. Padovan 	}
45930a708f8fSGustavo F. Padovan 
45940a708f8fSGustavo F. Padovan drop:
45950a708f8fSGustavo F. Padovan 	kfree_skb(skb);
45960a708f8fSGustavo F. Padovan 
45970a708f8fSGustavo F. Padovan done:
45986be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
45990a708f8fSGustavo F. Padovan 
46000a708f8fSGustavo F. Padovan 	return 0;
46010a708f8fSGustavo F. Padovan }
46020a708f8fSGustavo F. Padovan 
46030a708f8fSGustavo F. Padovan static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
46040a708f8fSGustavo F. Padovan {
460523691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
46060a708f8fSGustavo F. Padovan 
4607c2287681SIdo Yariv 	chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst);
460823691d75SGustavo F. Padovan 	if (!chan)
46090a708f8fSGustavo F. Padovan 		goto drop;
46100a708f8fSGustavo F. Padovan 
46115b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
46120a708f8fSGustavo F. Padovan 
461389bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
46140a708f8fSGustavo F. Padovan 		goto drop;
46150a708f8fSGustavo F. Padovan 
4616e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
46170a708f8fSGustavo F. Padovan 		goto drop;
46180a708f8fSGustavo F. Padovan 
461923070494SGustavo F. Padovan 	if (!chan->ops->recv(chan->data, skb))
46205b4cedaaSAndrei Emeltchenko 		return 0;
46210a708f8fSGustavo F. Padovan 
46220a708f8fSGustavo F. Padovan drop:
46230a708f8fSGustavo F. Padovan 	kfree_skb(skb);
46240a708f8fSGustavo F. Padovan 
46250a708f8fSGustavo F. Padovan 	return 0;
46260a708f8fSGustavo F. Padovan }
46270a708f8fSGustavo F. Padovan 
4628d9b88702SAndrei Emeltchenko static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid,
4629d9b88702SAndrei Emeltchenko 				    struct sk_buff *skb)
46309f69bda6SGustavo F. Padovan {
463123691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
46329f69bda6SGustavo F. Padovan 
4633c2287681SIdo Yariv 	chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst);
463423691d75SGustavo F. Padovan 	if (!chan)
46359f69bda6SGustavo F. Padovan 		goto drop;
46369f69bda6SGustavo F. Padovan 
46375b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
46389f69bda6SGustavo F. Padovan 
463989bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
46409f69bda6SGustavo F. Padovan 		goto drop;
46419f69bda6SGustavo F. Padovan 
4642e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
46439f69bda6SGustavo F. Padovan 		goto drop;
46449f69bda6SGustavo F. Padovan 
464523070494SGustavo F. Padovan 	if (!chan->ops->recv(chan->data, skb))
46465b4cedaaSAndrei Emeltchenko 		return 0;
46479f69bda6SGustavo F. Padovan 
46489f69bda6SGustavo F. Padovan drop:
46499f69bda6SGustavo F. Padovan 	kfree_skb(skb);
46509f69bda6SGustavo F. Padovan 
46519f69bda6SGustavo F. Padovan 	return 0;
46529f69bda6SGustavo F. Padovan }
46539f69bda6SGustavo F. Padovan 
46540a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
46550a708f8fSGustavo F. Padovan {
46560a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh = (void *) skb->data;
46570a708f8fSGustavo F. Padovan 	u16 cid, len;
46580a708f8fSGustavo F. Padovan 	__le16 psm;
46590a708f8fSGustavo F. Padovan 
46600a708f8fSGustavo F. Padovan 	skb_pull(skb, L2CAP_HDR_SIZE);
46610a708f8fSGustavo F. Padovan 	cid = __le16_to_cpu(lh->cid);
46620a708f8fSGustavo F. Padovan 	len = __le16_to_cpu(lh->len);
46630a708f8fSGustavo F. Padovan 
46640a708f8fSGustavo F. Padovan 	if (len != skb->len) {
46650a708f8fSGustavo F. Padovan 		kfree_skb(skb);
46660a708f8fSGustavo F. Padovan 		return;
46670a708f8fSGustavo F. Padovan 	}
46680a708f8fSGustavo F. Padovan 
46690a708f8fSGustavo F. Padovan 	BT_DBG("len %d, cid 0x%4.4x", len, cid);
46700a708f8fSGustavo F. Padovan 
46710a708f8fSGustavo F. Padovan 	switch (cid) {
46723300d9a9SClaudio Takahasi 	case L2CAP_CID_LE_SIGNALING:
46730a708f8fSGustavo F. Padovan 	case L2CAP_CID_SIGNALING:
46740a708f8fSGustavo F. Padovan 		l2cap_sig_channel(conn, skb);
46750a708f8fSGustavo F. Padovan 		break;
46760a708f8fSGustavo F. Padovan 
46770a708f8fSGustavo F. Padovan 	case L2CAP_CID_CONN_LESS:
4678097db76cSAndrei Emeltchenko 		psm = get_unaligned((__le16 *) skb->data);
46790a708f8fSGustavo F. Padovan 		skb_pull(skb, 2);
46800a708f8fSGustavo F. Padovan 		l2cap_conless_channel(conn, psm, skb);
46810a708f8fSGustavo F. Padovan 		break;
46820a708f8fSGustavo F. Padovan 
46839f69bda6SGustavo F. Padovan 	case L2CAP_CID_LE_DATA:
46849f69bda6SGustavo F. Padovan 		l2cap_att_channel(conn, cid, skb);
46859f69bda6SGustavo F. Padovan 		break;
46869f69bda6SGustavo F. Padovan 
4687b501d6a1SAnderson Briglia 	case L2CAP_CID_SMP:
4688b501d6a1SAnderson Briglia 		if (smp_sig_channel(conn, skb))
4689b501d6a1SAnderson Briglia 			l2cap_conn_del(conn->hcon, EACCES);
4690b501d6a1SAnderson Briglia 		break;
4691b501d6a1SAnderson Briglia 
46920a708f8fSGustavo F. Padovan 	default:
46930a708f8fSGustavo F. Padovan 		l2cap_data_channel(conn, cid, skb);
46940a708f8fSGustavo F. Padovan 		break;
46950a708f8fSGustavo F. Padovan 	}
46960a708f8fSGustavo F. Padovan }
46970a708f8fSGustavo F. Padovan 
46980a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
46990a708f8fSGustavo F. Padovan 
4700686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
47010a708f8fSGustavo F. Padovan {
47020a708f8fSGustavo F. Padovan 	int exact = 0, lm1 = 0, lm2 = 0;
470323691d75SGustavo F. Padovan 	struct l2cap_chan *c;
47040a708f8fSGustavo F. Padovan 
47050a708f8fSGustavo F. Padovan 	BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
47060a708f8fSGustavo F. Padovan 
47070a708f8fSGustavo F. Padovan 	/* Find listening sockets and check their link_mode */
470823691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
470923691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
471023691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
47114343478fSGustavo F. Padovan 
471289bc500eSGustavo F. Padovan 		if (c->state != BT_LISTEN)
47130a708f8fSGustavo F. Padovan 			continue;
47140a708f8fSGustavo F. Padovan 
47150a708f8fSGustavo F. Padovan 		if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
47160a708f8fSGustavo F. Padovan 			lm1 |= HCI_LM_ACCEPT;
471743bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
47180a708f8fSGustavo F. Padovan 				lm1 |= HCI_LM_MASTER;
47190a708f8fSGustavo F. Padovan 			exact++;
47200a708f8fSGustavo F. Padovan 		} else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
47210a708f8fSGustavo F. Padovan 			lm2 |= HCI_LM_ACCEPT;
472243bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
47230a708f8fSGustavo F. Padovan 				lm2 |= HCI_LM_MASTER;
47240a708f8fSGustavo F. Padovan 		}
47250a708f8fSGustavo F. Padovan 	}
472623691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
47270a708f8fSGustavo F. Padovan 
47280a708f8fSGustavo F. Padovan 	return exact ? lm1 : lm2;
47290a708f8fSGustavo F. Padovan }
47300a708f8fSGustavo F. Padovan 
4731686ebf28SUlisses Furquim int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
47320a708f8fSGustavo F. Padovan {
47330a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
47340a708f8fSGustavo F. Padovan 
47350a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
47360a708f8fSGustavo F. Padovan 
47370a708f8fSGustavo F. Padovan 	if (!status) {
47380a708f8fSGustavo F. Padovan 		conn = l2cap_conn_add(hcon, status);
47390a708f8fSGustavo F. Padovan 		if (conn)
47400a708f8fSGustavo F. Padovan 			l2cap_conn_ready(conn);
47410a708f8fSGustavo F. Padovan 	} else
4742e175072fSJoe Perches 		l2cap_conn_del(hcon, bt_to_errno(status));
47430a708f8fSGustavo F. Padovan 
47440a708f8fSGustavo F. Padovan 	return 0;
47450a708f8fSGustavo F. Padovan }
47460a708f8fSGustavo F. Padovan 
4747686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
47480a708f8fSGustavo F. Padovan {
47490a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
47500a708f8fSGustavo F. Padovan 
47510a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p", hcon);
47520a708f8fSGustavo F. Padovan 
4753686ebf28SUlisses Furquim 	if (!conn)
47549f5a0d7bSAndrei Emeltchenko 		return HCI_ERROR_REMOTE_USER_TERM;
47550a708f8fSGustavo F. Padovan 	return conn->disc_reason;
47560a708f8fSGustavo F. Padovan }
47570a708f8fSGustavo F. Padovan 
4758686ebf28SUlisses Furquim int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
47590a708f8fSGustavo F. Padovan {
47600a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p reason %d", hcon, reason);
47610a708f8fSGustavo F. Padovan 
4762e175072fSJoe Perches 	l2cap_conn_del(hcon, bt_to_errno(reason));
47630a708f8fSGustavo F. Padovan 	return 0;
47640a708f8fSGustavo F. Padovan }
47650a708f8fSGustavo F. Padovan 
47664343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
47670a708f8fSGustavo F. Padovan {
4768715ec005SGustavo F. Padovan 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
47690a708f8fSGustavo F. Padovan 		return;
47700a708f8fSGustavo F. Padovan 
47710a708f8fSGustavo F. Padovan 	if (encrypt == 0x00) {
47724343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM) {
4773ba13ccd9SMarcel Holtmann 			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
47744343478fSGustavo F. Padovan 		} else if (chan->sec_level == BT_SECURITY_HIGH)
47750f852724SGustavo F. Padovan 			l2cap_chan_close(chan, ECONNREFUSED);
47760a708f8fSGustavo F. Padovan 	} else {
47774343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM)
4778c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
47790a708f8fSGustavo F. Padovan 	}
47800a708f8fSGustavo F. Padovan }
47810a708f8fSGustavo F. Padovan 
4782686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
47830a708f8fSGustavo F. Padovan {
47840a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
478548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
47860a708f8fSGustavo F. Padovan 
47870a708f8fSGustavo F. Padovan 	if (!conn)
47880a708f8fSGustavo F. Padovan 		return 0;
47890a708f8fSGustavo F. Padovan 
47900a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
47910a708f8fSGustavo F. Padovan 
4792160dc6acSVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
479335d4adccSHemant Gupta 		if (!status && encrypt)
4794160dc6acSVinicius Costa Gomes 			smp_distribute_keys(conn, 0);
479517cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->security_timer);
4796160dc6acSVinicius Costa Gomes 	}
4797160dc6acSVinicius Costa Gomes 
47983df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
47990a708f8fSGustavo F. Padovan 
48003df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
48016be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
48020a708f8fSGustavo F. Padovan 
4803f1cb9af5SVinicius Costa Gomes 		BT_DBG("chan->scid %d", chan->scid);
4804f1cb9af5SVinicius Costa Gomes 
4805f1cb9af5SVinicius Costa Gomes 		if (chan->scid == L2CAP_CID_LE_DATA) {
4806f1cb9af5SVinicius Costa Gomes 			if (!status && encrypt) {
4807f1cb9af5SVinicius Costa Gomes 				chan->sec_level = hcon->sec_level;
4808cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
4809f1cb9af5SVinicius Costa Gomes 			}
4810f1cb9af5SVinicius Costa Gomes 
48116be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
4812f1cb9af5SVinicius Costa Gomes 			continue;
4813f1cb9af5SVinicius Costa Gomes 		}
4814f1cb9af5SVinicius Costa Gomes 
4815c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
48166be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
48170a708f8fSGustavo F. Padovan 			continue;
48180a708f8fSGustavo F. Padovan 		}
48190a708f8fSGustavo F. Padovan 
482089bc500eSGustavo F. Padovan 		if (!status && (chan->state == BT_CONNECTED ||
482189bc500eSGustavo F. Padovan 						chan->state == BT_CONFIG)) {
4822a7d7723aSGustavo Padovan 			struct sock *sk = chan->sk;
4823a7d7723aSGustavo Padovan 
4824c5daa683SGustavo Padovan 			clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
4825a7d7723aSGustavo Padovan 			sk->sk_state_change(sk);
4826a7d7723aSGustavo Padovan 
48274343478fSGustavo F. Padovan 			l2cap_check_encryption(chan, encrypt);
48286be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
48290a708f8fSGustavo F. Padovan 			continue;
48300a708f8fSGustavo F. Padovan 		}
48310a708f8fSGustavo F. Padovan 
483289bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
48330a708f8fSGustavo F. Padovan 			if (!status) {
48349b27f350SAndrei Emeltchenko 				l2cap_send_conn_req(chan);
48350a708f8fSGustavo F. Padovan 			} else {
4836ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
48370a708f8fSGustavo F. Padovan 			}
483889bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
48396be36555SAndrei Emeltchenko 			struct sock *sk = chan->sk;
48400a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
4841df3c3931SJohan Hedberg 			__u16 res, stat;
48420a708f8fSGustavo F. Padovan 
48436be36555SAndrei Emeltchenko 			lock_sock(sk);
48446be36555SAndrei Emeltchenko 
48450a708f8fSGustavo F. Padovan 			if (!status) {
4846c5daa683SGustavo Padovan 				if (test_bit(BT_SK_DEFER_SETUP,
4847c5daa683SGustavo Padovan 					     &bt_sk(sk)->flags)) {
4848df3c3931SJohan Hedberg 					struct sock *parent = bt_sk(sk)->parent;
4849df3c3931SJohan Hedberg 					res = L2CAP_CR_PEND;
4850df3c3931SJohan Hedberg 					stat = L2CAP_CS_AUTHOR_PEND;
485105e9a2f6SIlia Kolomisnky 					if (parent)
4852df3c3931SJohan Hedberg 						parent->sk_data_ready(parent, 0);
4853df3c3931SJohan Hedberg 				} else {
48540e587be7SAndrei Emeltchenko 					__l2cap_state_change(chan, BT_CONFIG);
4855df3c3931SJohan Hedberg 					res = L2CAP_CR_SUCCESS;
4856df3c3931SJohan Hedberg 					stat = L2CAP_CS_NO_INFO;
4857df3c3931SJohan Hedberg 				}
48580a708f8fSGustavo F. Padovan 			} else {
48590e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_DISCONN);
4860ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
4861df3c3931SJohan Hedberg 				res = L2CAP_CR_SEC_BLOCK;
4862df3c3931SJohan Hedberg 				stat = L2CAP_CS_NO_INFO;
48630a708f8fSGustavo F. Padovan 			}
48640a708f8fSGustavo F. Padovan 
48656be36555SAndrei Emeltchenko 			release_sock(sk);
48666be36555SAndrei Emeltchenko 
4867fe4128e0SGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
4868fe4128e0SGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
4869df3c3931SJohan Hedberg 			rsp.result = cpu_to_le16(res);
4870df3c3931SJohan Hedberg 			rsp.status = cpu_to_le16(stat);
4871fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4872fc7f8a7eSGustavo F. Padovan 							sizeof(rsp), &rsp);
48730a708f8fSGustavo F. Padovan 		}
48740a708f8fSGustavo F. Padovan 
48756be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
48760a708f8fSGustavo F. Padovan 	}
48770a708f8fSGustavo F. Padovan 
48783df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
48790a708f8fSGustavo F. Padovan 
48800a708f8fSGustavo F. Padovan 	return 0;
48810a708f8fSGustavo F. Padovan }
48820a708f8fSGustavo F. Padovan 
4883686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
48840a708f8fSGustavo F. Padovan {
48850a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
48860a708f8fSGustavo F. Padovan 
48870a708f8fSGustavo F. Padovan 	if (!conn)
48880a708f8fSGustavo F. Padovan 		conn = l2cap_conn_add(hcon, 0);
48890a708f8fSGustavo F. Padovan 
48900a708f8fSGustavo F. Padovan 	if (!conn)
48910a708f8fSGustavo F. Padovan 		goto drop;
48920a708f8fSGustavo F. Padovan 
48930a708f8fSGustavo F. Padovan 	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
48940a708f8fSGustavo F. Padovan 
48950a708f8fSGustavo F. Padovan 	if (!(flags & ACL_CONT)) {
48960a708f8fSGustavo F. Padovan 		struct l2cap_hdr *hdr;
48970a708f8fSGustavo F. Padovan 		int len;
48980a708f8fSGustavo F. Padovan 
48990a708f8fSGustavo F. Padovan 		if (conn->rx_len) {
49000a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected start frame (len %d)", skb->len);
49010a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
49020a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
49030a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
49040a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
49050a708f8fSGustavo F. Padovan 		}
49060a708f8fSGustavo F. Padovan 
49070a708f8fSGustavo F. Padovan 		/* Start fragment always begin with Basic L2CAP header */
49080a708f8fSGustavo F. Padovan 		if (skb->len < L2CAP_HDR_SIZE) {
49090a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too short (len %d)", skb->len);
49100a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
49110a708f8fSGustavo F. Padovan 			goto drop;
49120a708f8fSGustavo F. Padovan 		}
49130a708f8fSGustavo F. Padovan 
49140a708f8fSGustavo F. Padovan 		hdr = (struct l2cap_hdr *) skb->data;
49150a708f8fSGustavo F. Padovan 		len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
49160a708f8fSGustavo F. Padovan 
49170a708f8fSGustavo F. Padovan 		if (len == skb->len) {
49180a708f8fSGustavo F. Padovan 			/* Complete frame received */
49190a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, skb);
49200a708f8fSGustavo F. Padovan 			return 0;
49210a708f8fSGustavo F. Padovan 		}
49220a708f8fSGustavo F. Padovan 
49230a708f8fSGustavo F. Padovan 		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
49240a708f8fSGustavo F. Padovan 
49250a708f8fSGustavo F. Padovan 		if (skb->len > len) {
49260a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too long (len %d, expected len %d)",
49270a708f8fSGustavo F. Padovan 				skb->len, len);
49280a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
49290a708f8fSGustavo F. Padovan 			goto drop;
49300a708f8fSGustavo F. Padovan 		}
49310a708f8fSGustavo F. Padovan 
49320a708f8fSGustavo F. Padovan 		/* Allocate skb for the complete frame (with header) */
49330a708f8fSGustavo F. Padovan 		conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
49340a708f8fSGustavo F. Padovan 		if (!conn->rx_skb)
49350a708f8fSGustavo F. Padovan 			goto drop;
49360a708f8fSGustavo F. Padovan 
49370a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
49380a708f8fSGustavo F. Padovan 								skb->len);
49390a708f8fSGustavo F. Padovan 		conn->rx_len = len - skb->len;
49400a708f8fSGustavo F. Padovan 	} else {
49410a708f8fSGustavo F. Padovan 		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
49420a708f8fSGustavo F. Padovan 
49430a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
49440a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
49450a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
49460a708f8fSGustavo F. Padovan 			goto drop;
49470a708f8fSGustavo F. Padovan 		}
49480a708f8fSGustavo F. Padovan 
49490a708f8fSGustavo F. Padovan 		if (skb->len > conn->rx_len) {
49500a708f8fSGustavo F. Padovan 			BT_ERR("Fragment is too long (len %d, expected %d)",
49510a708f8fSGustavo F. Padovan 					skb->len, conn->rx_len);
49520a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
49530a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
49540a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
49550a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
49560a708f8fSGustavo F. Padovan 			goto drop;
49570a708f8fSGustavo F. Padovan 		}
49580a708f8fSGustavo F. Padovan 
49590a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
49600a708f8fSGustavo F. Padovan 								skb->len);
49610a708f8fSGustavo F. Padovan 		conn->rx_len -= skb->len;
49620a708f8fSGustavo F. Padovan 
49630a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
49640a708f8fSGustavo F. Padovan 			/* Complete frame received */
49650a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, conn->rx_skb);
49660a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
49670a708f8fSGustavo F. Padovan 		}
49680a708f8fSGustavo F. Padovan 	}
49690a708f8fSGustavo F. Padovan 
49700a708f8fSGustavo F. Padovan drop:
49710a708f8fSGustavo F. Padovan 	kfree_skb(skb);
49720a708f8fSGustavo F. Padovan 	return 0;
49730a708f8fSGustavo F. Padovan }
49740a708f8fSGustavo F. Padovan 
49750a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
49760a708f8fSGustavo F. Padovan {
497723691d75SGustavo F. Padovan 	struct l2cap_chan *c;
49780a708f8fSGustavo F. Padovan 
4979333055f2SGustavo F. Padovan 	read_lock(&chan_list_lock);
49800a708f8fSGustavo F. Padovan 
498123691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
498223691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
49830a708f8fSGustavo F. Padovan 
4984903d343eSGustavo F. Padovan 		seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
49850a708f8fSGustavo F. Padovan 					batostr(&bt_sk(sk)->src),
49860a708f8fSGustavo F. Padovan 					batostr(&bt_sk(sk)->dst),
498789bc500eSGustavo F. Padovan 					c->state, __le16_to_cpu(c->psm),
498823691d75SGustavo F. Padovan 					c->scid, c->dcid, c->imtu, c->omtu,
498923691d75SGustavo F. Padovan 					c->sec_level, c->mode);
49900a708f8fSGustavo F. Padovan 	}
49910a708f8fSGustavo F. Padovan 
4992333055f2SGustavo F. Padovan 	read_unlock(&chan_list_lock);
49930a708f8fSGustavo F. Padovan 
49940a708f8fSGustavo F. Padovan 	return 0;
49950a708f8fSGustavo F. Padovan }
49960a708f8fSGustavo F. Padovan 
49970a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file)
49980a708f8fSGustavo F. Padovan {
49990a708f8fSGustavo F. Padovan 	return single_open(file, l2cap_debugfs_show, inode->i_private);
50000a708f8fSGustavo F. Padovan }
50010a708f8fSGustavo F. Padovan 
50020a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = {
50030a708f8fSGustavo F. Padovan 	.open		= l2cap_debugfs_open,
50040a708f8fSGustavo F. Padovan 	.read		= seq_read,
50050a708f8fSGustavo F. Padovan 	.llseek		= seq_lseek,
50060a708f8fSGustavo F. Padovan 	.release	= single_release,
50070a708f8fSGustavo F. Padovan };
50080a708f8fSGustavo F. Padovan 
50090a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
50100a708f8fSGustavo F. Padovan 
501164274518SGustavo F. Padovan int __init l2cap_init(void)
50120a708f8fSGustavo F. Padovan {
50130a708f8fSGustavo F. Padovan 	int err;
50140a708f8fSGustavo F. Padovan 
5015bb58f747SGustavo F. Padovan 	err = l2cap_init_sockets();
50160a708f8fSGustavo F. Padovan 	if (err < 0)
50170a708f8fSGustavo F. Padovan 		return err;
50180a708f8fSGustavo F. Padovan 
50190a708f8fSGustavo F. Padovan 	if (bt_debugfs) {
50200a708f8fSGustavo F. Padovan 		l2cap_debugfs = debugfs_create_file("l2cap", 0444,
50210a708f8fSGustavo F. Padovan 					bt_debugfs, NULL, &l2cap_debugfs_fops);
50220a708f8fSGustavo F. Padovan 		if (!l2cap_debugfs)
50230a708f8fSGustavo F. Padovan 			BT_ERR("Failed to create L2CAP debug file");
50240a708f8fSGustavo F. Padovan 	}
50250a708f8fSGustavo F. Padovan 
50260a708f8fSGustavo F. Padovan 	return 0;
50270a708f8fSGustavo F. Padovan }
50280a708f8fSGustavo F. Padovan 
502964274518SGustavo F. Padovan void l2cap_exit(void)
50300a708f8fSGustavo F. Padovan {
50310a708f8fSGustavo F. Padovan 	debugfs_remove(l2cap_debugfs);
5032bb58f747SGustavo F. Padovan 	l2cap_cleanup_sockets();
50330a708f8fSGustavo F. Padovan }
50340a708f8fSGustavo F. Padovan 
50350a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
50360a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
5037