10a708f8fSGustavo F. Padovan /* 20a708f8fSGustavo F. Padovan BlueZ - Bluetooth protocol stack for Linux 30a708f8fSGustavo F. Padovan Copyright (C) 2000-2001 Qualcomm Incorporated 40a708f8fSGustavo F. Padovan Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org> 50a708f8fSGustavo F. Padovan Copyright (C) 2010 Google Inc. 6590051deSGustavo F. Padovan Copyright (C) 2011 ProFUSION Embedded Systems 7422e925bSMat Martineau Copyright (c) 2012 Code Aurora Forum. All rights reserved. 80a708f8fSGustavo F. Padovan 90a708f8fSGustavo F. Padovan Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> 100a708f8fSGustavo F. Padovan 110a708f8fSGustavo F. Padovan This program is free software; you can redistribute it and/or modify 120a708f8fSGustavo F. Padovan it under the terms of the GNU General Public License version 2 as 130a708f8fSGustavo F. Padovan published by the Free Software Foundation; 140a708f8fSGustavo F. Padovan 150a708f8fSGustavo F. Padovan THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 160a708f8fSGustavo F. Padovan OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 170a708f8fSGustavo F. Padovan FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 180a708f8fSGustavo F. Padovan IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 190a708f8fSGustavo F. Padovan CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 200a708f8fSGustavo F. Padovan WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 210a708f8fSGustavo F. Padovan ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 220a708f8fSGustavo F. Padovan OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 230a708f8fSGustavo F. Padovan 240a708f8fSGustavo F. Padovan ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 250a708f8fSGustavo F. Padovan COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 260a708f8fSGustavo F. Padovan SOFTWARE IS DISCLAIMED. 270a708f8fSGustavo F. Padovan */ 280a708f8fSGustavo F. Padovan 29bb58f747SGustavo F. Padovan /* Bluetooth L2CAP core. */ 300a708f8fSGustavo F. Padovan 310a708f8fSGustavo F. Padovan #include <linux/module.h> 320a708f8fSGustavo F. Padovan 330a708f8fSGustavo F. Padovan #include <linux/debugfs.h> 340a708f8fSGustavo F. Padovan #include <linux/crc16.h> 35dbb50887SDaniel Borkmann #include <linux/filter.h> 360a708f8fSGustavo F. Padovan 370a708f8fSGustavo F. Padovan #include <net/bluetooth/bluetooth.h> 380a708f8fSGustavo F. Padovan #include <net/bluetooth/hci_core.h> 390a708f8fSGustavo F. Padovan #include <net/bluetooth/l2cap.h> 407ef9fbf0SMarcel Holtmann 41ac4b7236SMarcel Holtmann #include "smp.h" 427024728eSMarcel Holtmann #include "a2mp.h" 437ef9fbf0SMarcel Holtmann #include "amp.h" 440a708f8fSGustavo F. Padovan 450f1bfe4eSJohan Hedberg #define LE_FLOWCTL_MAX_CREDITS 65535 460f1bfe4eSJohan Hedberg 47d1de6d46SMat Martineau bool disable_ertm; 480a708f8fSGustavo F. Padovan 49547d1032SMarcel Holtmann static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD; 500a708f8fSGustavo F. Padovan 51b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list); 52b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock); 530a708f8fSGustavo F. Padovan 540a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 550a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data); 564519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 574519de9aSGustavo F. Padovan void *data); 58e860d2c9SBen Seri static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size); 595e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err); 600a708f8fSGustavo F. Padovan 61d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 62608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event); 63608bcc6dSMat Martineau 64a250e048SJohan Hedberg static inline u8 bdaddr_type(u8 link_type, u8 bdaddr_type) 654f1654e0SMarcel Holtmann { 66a250e048SJohan Hedberg if (link_type == LE_LINK) { 67a250e048SJohan Hedberg if (bdaddr_type == ADDR_LE_DEV_PUBLIC) 684f1654e0SMarcel Holtmann return BDADDR_LE_PUBLIC; 694f1654e0SMarcel Holtmann else 704f1654e0SMarcel Holtmann return BDADDR_LE_RANDOM; 714f1654e0SMarcel Holtmann } 724f1654e0SMarcel Holtmann 734f1654e0SMarcel Holtmann return BDADDR_BREDR; 744f1654e0SMarcel Holtmann } 754f1654e0SMarcel Holtmann 76a250e048SJohan Hedberg static inline u8 bdaddr_src_type(struct hci_conn *hcon) 77a250e048SJohan Hedberg { 78a250e048SJohan Hedberg return bdaddr_type(hcon->type, hcon->src_type); 79a250e048SJohan Hedberg } 80a250e048SJohan Hedberg 81a250e048SJohan Hedberg static inline u8 bdaddr_dst_type(struct hci_conn *hcon) 82a250e048SJohan Hedberg { 83a250e048SJohan Hedberg return bdaddr_type(hcon->type, hcon->dst_type); 84a250e048SJohan Hedberg } 85a250e048SJohan Hedberg 860a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */ 8771ba0e56SGustavo F. Padovan 882d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, 892d792818SGustavo Padovan u16 cid) 900a708f8fSGustavo F. Padovan { 913df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 92baa7e1faSGustavo F. Padovan 933df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 943df91ea2SAndrei Emeltchenko if (c->dcid == cid) 953df91ea2SAndrei Emeltchenko return c; 960a708f8fSGustavo F. Padovan } 973df91ea2SAndrei Emeltchenko return NULL; 98baa7e1faSGustavo F. Padovan } 990a708f8fSGustavo F. Padovan 1002d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, 1012d792818SGustavo Padovan u16 cid) 1020a708f8fSGustavo F. Padovan { 1033df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 104baa7e1faSGustavo F. Padovan 1053df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 1063df91ea2SAndrei Emeltchenko if (c->scid == cid) 1073df91ea2SAndrei Emeltchenko return c; 1080a708f8fSGustavo F. Padovan } 1093df91ea2SAndrei Emeltchenko return NULL; 110baa7e1faSGustavo F. Padovan } 1110a708f8fSGustavo F. Padovan 1120a708f8fSGustavo F. Padovan /* Find channel with given SCID. 113ef191adeSMat Martineau * Returns locked channel. */ 1142d792818SGustavo Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, 1152d792818SGustavo Padovan u16 cid) 1160a708f8fSGustavo F. Padovan { 11748454079SGustavo F. Padovan struct l2cap_chan *c; 118baa7e1faSGustavo F. Padovan 1193df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 120baa7e1faSGustavo F. Padovan c = __l2cap_get_chan_by_scid(conn, cid); 121ef191adeSMat Martineau if (c) 122ef191adeSMat Martineau l2cap_chan_lock(c); 1233df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 1243df91ea2SAndrei Emeltchenko 12548454079SGustavo F. Padovan return c; 1260a708f8fSGustavo F. Padovan } 1270a708f8fSGustavo F. Padovan 128b1a130b7SMat Martineau /* Find channel with given DCID. 129b1a130b7SMat Martineau * Returns locked channel. 130b1a130b7SMat Martineau */ 131b1a130b7SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn, 132b1a130b7SMat Martineau u16 cid) 133b1a130b7SMat Martineau { 134b1a130b7SMat Martineau struct l2cap_chan *c; 135b1a130b7SMat Martineau 136b1a130b7SMat Martineau mutex_lock(&conn->chan_lock); 137b1a130b7SMat Martineau c = __l2cap_get_chan_by_dcid(conn, cid); 138b1a130b7SMat Martineau if (c) 139b1a130b7SMat Martineau l2cap_chan_lock(c); 140b1a130b7SMat Martineau mutex_unlock(&conn->chan_lock); 141b1a130b7SMat Martineau 142b1a130b7SMat Martineau return c; 143b1a130b7SMat Martineau } 144b1a130b7SMat Martineau 1452d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, 1462d792818SGustavo Padovan u8 ident) 1470a708f8fSGustavo F. Padovan { 1483df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 149baa7e1faSGustavo F. Padovan 1503df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 1513df91ea2SAndrei Emeltchenko if (c->ident == ident) 1523df91ea2SAndrei Emeltchenko return c; 1530a708f8fSGustavo F. Padovan } 1543df91ea2SAndrei Emeltchenko return NULL; 155baa7e1faSGustavo F. Padovan } 1560a708f8fSGustavo F. Padovan 1575b155ef9SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, 1585b155ef9SMat Martineau u8 ident) 1595b155ef9SMat Martineau { 1605b155ef9SMat Martineau struct l2cap_chan *c; 1615b155ef9SMat Martineau 1625b155ef9SMat Martineau mutex_lock(&conn->chan_lock); 1635b155ef9SMat Martineau c = __l2cap_get_chan_by_ident(conn, ident); 1645b155ef9SMat Martineau if (c) 1655b155ef9SMat Martineau l2cap_chan_lock(c); 1665b155ef9SMat Martineau mutex_unlock(&conn->chan_lock); 1675b155ef9SMat Martineau 1685b155ef9SMat Martineau return c; 1695b155ef9SMat Martineau } 1705b155ef9SMat Martineau 17100f62726SLuiz Augusto von Dentz static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src, 17200f62726SLuiz Augusto von Dentz u8 src_type) 1739e4425ffSGustavo F. Padovan { 17423691d75SGustavo F. Padovan struct l2cap_chan *c; 1759e4425ffSGustavo F. Padovan 17623691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 17700f62726SLuiz Augusto von Dentz if (src_type == BDADDR_BREDR && c->src_type != BDADDR_BREDR) 17800f62726SLuiz Augusto von Dentz continue; 17900f62726SLuiz Augusto von Dentz 18000f62726SLuiz Augusto von Dentz if (src_type != BDADDR_BREDR && c->src_type == BDADDR_BREDR) 18100f62726SLuiz Augusto von Dentz continue; 18200f62726SLuiz Augusto von Dentz 1837eafc59eSMarcel Holtmann if (c->sport == psm && !bacmp(&c->src, src)) 18423691d75SGustavo F. Padovan return c; 1859e4425ffSGustavo F. Padovan } 186250938cbSSzymon Janc return NULL; 187250938cbSSzymon Janc } 1889e4425ffSGustavo F. Padovan 1899e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) 1909e4425ffSGustavo F. Padovan { 19173b2ec18SGustavo F. Padovan int err; 19273b2ec18SGustavo F. Padovan 193333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 1949e4425ffSGustavo F. Padovan 19500f62726SLuiz Augusto von Dentz if (psm && __l2cap_global_chan_by_addr(psm, src, chan->src_type)) { 19673b2ec18SGustavo F. Padovan err = -EADDRINUSE; 19773b2ec18SGustavo F. Padovan goto done; 1989e4425ffSGustavo F. Padovan } 1999e4425ffSGustavo F. Padovan 20073b2ec18SGustavo F. Padovan if (psm) { 2019e4425ffSGustavo F. Padovan chan->psm = psm; 2029e4425ffSGustavo F. Padovan chan->sport = psm; 20373b2ec18SGustavo F. Padovan err = 0; 20473b2ec18SGustavo F. Padovan } else { 20592594a51SJohan Hedberg u16 p, start, end, incr; 20692594a51SJohan Hedberg 20792594a51SJohan Hedberg if (chan->src_type == BDADDR_BREDR) { 20892594a51SJohan Hedberg start = L2CAP_PSM_DYN_START; 20992594a51SJohan Hedberg end = L2CAP_PSM_AUTO_END; 21092594a51SJohan Hedberg incr = 2; 21192594a51SJohan Hedberg } else { 21292594a51SJohan Hedberg start = L2CAP_PSM_LE_DYN_START; 21392594a51SJohan Hedberg end = L2CAP_PSM_LE_DYN_END; 21492594a51SJohan Hedberg incr = 1; 21592594a51SJohan Hedberg } 2169e4425ffSGustavo F. Padovan 21773b2ec18SGustavo F. Padovan err = -EINVAL; 21892594a51SJohan Hedberg for (p = start; p <= end; p += incr) 21900f62726SLuiz Augusto von Dentz if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src, 22000f62726SLuiz Augusto von Dentz chan->src_type)) { 22173b2ec18SGustavo F. Padovan chan->psm = cpu_to_le16(p); 22273b2ec18SGustavo F. Padovan chan->sport = cpu_to_le16(p); 22373b2ec18SGustavo F. Padovan err = 0; 22473b2ec18SGustavo F. Padovan break; 22573b2ec18SGustavo F. Padovan } 22673b2ec18SGustavo F. Padovan } 22773b2ec18SGustavo F. Padovan 22873b2ec18SGustavo F. Padovan done: 229333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 23073b2ec18SGustavo F. Padovan return err; 2319e4425ffSGustavo F. Padovan } 2326b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_add_psm); 2339e4425ffSGustavo F. Padovan 2349e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) 2359e4425ffSGustavo F. Padovan { 236333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 2379e4425ffSGustavo F. Padovan 23814824308SJohan Hedberg /* Override the defaults (which are for conn-oriented) */ 23914824308SJohan Hedberg chan->omtu = L2CAP_DEFAULT_MTU; 24014824308SJohan Hedberg chan->chan_type = L2CAP_CHAN_FIXED; 24114824308SJohan Hedberg 2429e4425ffSGustavo F. Padovan chan->scid = scid; 2439e4425ffSGustavo F. Padovan 244333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 2459e4425ffSGustavo F. Padovan 2469e4425ffSGustavo F. Padovan return 0; 2479e4425ffSGustavo F. Padovan } 2489e4425ffSGustavo F. Padovan 249baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn) 2500a708f8fSGustavo F. Padovan { 251e77af755SJohan Hedberg u16 cid, dyn_end; 2520a708f8fSGustavo F. Padovan 253e77af755SJohan Hedberg if (conn->hcon->type == LE_LINK) 254e77af755SJohan Hedberg dyn_end = L2CAP_CID_LE_DYN_END; 255e77af755SJohan Hedberg else 256e77af755SJohan Hedberg dyn_end = L2CAP_CID_DYN_END; 257e77af755SJohan Hedberg 258ab0c127fSJohan Hedberg for (cid = L2CAP_CID_DYN_START; cid <= dyn_end; cid++) { 259baa7e1faSGustavo F. Padovan if (!__l2cap_get_chan_by_scid(conn, cid)) 2600a708f8fSGustavo F. Padovan return cid; 2610a708f8fSGustavo F. Padovan } 2620a708f8fSGustavo F. Padovan 2630a708f8fSGustavo F. Padovan return 0; 2640a708f8fSGustavo F. Padovan } 2650a708f8fSGustavo F. Padovan 266f93fa273SGustavo Padovan static void l2cap_state_change(struct l2cap_chan *chan, int state) 26789bc500eSGustavo F. Padovan { 26842d2d87cSAndrei Emeltchenko BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state), 269badaaa00SGustavo F. Padovan state_to_string(state)); 270badaaa00SGustavo F. Padovan 27189bc500eSGustavo F. Padovan chan->state = state; 27253f52121SGustavo Padovan chan->ops->state_change(chan, state, 0); 27389bc500eSGustavo F. Padovan } 27489bc500eSGustavo F. Padovan 275f8e73017SGustavo Padovan static inline void l2cap_state_change_and_error(struct l2cap_chan *chan, 276f8e73017SGustavo Padovan int state, int err) 2772e0052e4SAndrei Emeltchenko { 278f8e73017SGustavo Padovan chan->state = state; 27953f52121SGustavo Padovan chan->ops->state_change(chan, chan->state, err); 2802e0052e4SAndrei Emeltchenko } 2812e0052e4SAndrei Emeltchenko 2822e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err) 2832e0052e4SAndrei Emeltchenko { 284f8e73017SGustavo Padovan chan->ops->state_change(chan, chan->state, err); 2852e0052e4SAndrei Emeltchenko } 2862e0052e4SAndrei Emeltchenko 2874239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan) 2884239d16fSMat Martineau { 2894239d16fSMat Martineau if (!delayed_work_pending(&chan->monitor_timer) && 2904239d16fSMat Martineau chan->retrans_timeout) { 2914239d16fSMat Martineau l2cap_set_timer(chan, &chan->retrans_timer, 2924239d16fSMat Martineau msecs_to_jiffies(chan->retrans_timeout)); 2934239d16fSMat Martineau } 2944239d16fSMat Martineau } 2954239d16fSMat Martineau 2964239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan) 2974239d16fSMat Martineau { 2984239d16fSMat Martineau __clear_retrans_timer(chan); 2994239d16fSMat Martineau if (chan->monitor_timeout) { 3004239d16fSMat Martineau l2cap_set_timer(chan, &chan->monitor_timer, 3014239d16fSMat Martineau msecs_to_jiffies(chan->monitor_timeout)); 3024239d16fSMat Martineau } 3034239d16fSMat Martineau } 3044239d16fSMat Martineau 305608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head, 306608bcc6dSMat Martineau u16 seq) 307608bcc6dSMat Martineau { 308608bcc6dSMat Martineau struct sk_buff *skb; 309608bcc6dSMat Martineau 310608bcc6dSMat Martineau skb_queue_walk(head, skb) { 311a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.txseq == seq) 312608bcc6dSMat Martineau return skb; 313608bcc6dSMat Martineau } 314608bcc6dSMat Martineau 315608bcc6dSMat Martineau return NULL; 316608bcc6dSMat Martineau } 317608bcc6dSMat Martineau 3183c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */ 3193c588192SMat Martineau 3203c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for 3213c588192SMat Martineau * SREJ requests that are received and for frames that are to be 3223c588192SMat Martineau * retransmitted. These seq_list functions implement a singly-linked 3233c588192SMat Martineau * list in an array, where membership in the list can also be checked 3243c588192SMat Martineau * in constant time. Items can also be added to the tail of the list 3253c588192SMat Martineau * and removed from the head in constant time, without further memory 3263c588192SMat Martineau * allocs or frees. 3273c588192SMat Martineau */ 3283c588192SMat Martineau 3293c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size) 3303c588192SMat Martineau { 3313c588192SMat Martineau size_t alloc_size, i; 3323c588192SMat Martineau 3333c588192SMat Martineau /* Allocated size is a power of 2 to map sequence numbers 3343c588192SMat Martineau * (which may be up to 14 bits) in to a smaller array that is 3353c588192SMat Martineau * sized for the negotiated ERTM transmit windows. 3363c588192SMat Martineau */ 3373c588192SMat Martineau alloc_size = roundup_pow_of_two(size); 3383c588192SMat Martineau 3396da2ec56SKees Cook seq_list->list = kmalloc_array(alloc_size, sizeof(u16), GFP_KERNEL); 3403c588192SMat Martineau if (!seq_list->list) 3413c588192SMat Martineau return -ENOMEM; 3423c588192SMat Martineau 3433c588192SMat Martineau seq_list->mask = alloc_size - 1; 3443c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3453c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3463c588192SMat Martineau for (i = 0; i < alloc_size; i++) 3473c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 3483c588192SMat Martineau 3493c588192SMat Martineau return 0; 3503c588192SMat Martineau } 3513c588192SMat Martineau 3523c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list) 3533c588192SMat Martineau { 3543c588192SMat Martineau kfree(seq_list->list); 3553c588192SMat Martineau } 3563c588192SMat Martineau 3573c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list, 3583c588192SMat Martineau u16 seq) 3593c588192SMat Martineau { 3603c588192SMat Martineau /* Constant-time check for list membership */ 3613c588192SMat Martineau return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR; 3623c588192SMat Martineau } 3633c588192SMat Martineau 36403a0c5d6SJohan Hedberg static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list) 3653c588192SMat Martineau { 36603a0c5d6SJohan Hedberg u16 seq = seq_list->head; 3673c588192SMat Martineau u16 mask = seq_list->mask; 3683c588192SMat Martineau 3693c588192SMat Martineau seq_list->head = seq_list->list[seq & mask]; 3703c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; 3713c588192SMat Martineau 3723c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_TAIL) { 3733c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3743c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3753c588192SMat Martineau } 3763c588192SMat Martineau 3773c588192SMat Martineau return seq; 3783c588192SMat Martineau } 3793c588192SMat Martineau 3803c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list) 3813c588192SMat Martineau { 3823c588192SMat Martineau u16 i; 383f522ae36SGustavo Padovan 384f522ae36SGustavo Padovan if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) 385f522ae36SGustavo Padovan return; 386f522ae36SGustavo Padovan 3873c588192SMat Martineau for (i = 0; i <= seq_list->mask; i++) 3883c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 3893c588192SMat Martineau 3903c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3913c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3923c588192SMat Martineau } 3933c588192SMat Martineau 3943c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq) 3953c588192SMat Martineau { 3963c588192SMat Martineau u16 mask = seq_list->mask; 3973c588192SMat Martineau 3983c588192SMat Martineau /* All appends happen in constant time */ 3993c588192SMat Martineau 400f522ae36SGustavo Padovan if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR) 401f522ae36SGustavo Padovan return; 402f522ae36SGustavo Padovan 4033c588192SMat Martineau if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR) 4043c588192SMat Martineau seq_list->head = seq; 4053c588192SMat Martineau else 4063c588192SMat Martineau seq_list->list[seq_list->tail & mask] = seq; 4073c588192SMat Martineau 4083c588192SMat Martineau seq_list->tail = seq; 4093c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL; 4103c588192SMat Martineau } 4113c588192SMat Martineau 412721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work) 413ab07801dSGustavo F. Padovan { 414721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 415721c4181SGustavo F. Padovan chan_timer.work); 4163df91ea2SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 417ab07801dSGustavo F. Padovan int reason; 418ab07801dSGustavo F. Padovan 419e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 420ab07801dSGustavo F. Padovan 4213df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 4226be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 423ab07801dSGustavo F. Padovan 42489bc500eSGustavo F. Padovan if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) 425ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 42689bc500eSGustavo F. Padovan else if (chan->state == BT_CONNECT && 427ab07801dSGustavo F. Padovan chan->sec_level != BT_SECURITY_SDP) 428ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 429ab07801dSGustavo F. Padovan else 430ab07801dSGustavo F. Padovan reason = ETIMEDOUT; 431ab07801dSGustavo F. Padovan 4320f852724SGustavo F. Padovan l2cap_chan_close(chan, reason); 433ab07801dSGustavo F. Padovan 4346be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 435ab07801dSGustavo F. Padovan 43680b98027SGustavo Padovan chan->ops->close(chan); 4373df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4383df91ea2SAndrei Emeltchenko 439371fd835SUlisses Furquim l2cap_chan_put(chan); 440ab07801dSGustavo F. Padovan } 441ab07801dSGustavo F. Padovan 442eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void) 4430a708f8fSGustavo F. Padovan { 44448454079SGustavo F. Padovan struct l2cap_chan *chan; 4450a708f8fSGustavo F. Padovan 44648454079SGustavo F. Padovan chan = kzalloc(sizeof(*chan), GFP_ATOMIC); 44748454079SGustavo F. Padovan if (!chan) 44848454079SGustavo F. Padovan return NULL; 4490a708f8fSGustavo F. Padovan 450c03b355eSAndrei Emeltchenko mutex_init(&chan->lock); 451c03b355eSAndrei Emeltchenko 452ff714119SJohan Hedberg /* Set default lock nesting level */ 453ff714119SJohan Hedberg atomic_set(&chan->nesting, L2CAP_NESTING_NORMAL); 454ff714119SJohan Hedberg 455333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 45623691d75SGustavo F. Padovan list_add(&chan->global_l, &chan_list); 457333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 45823691d75SGustavo F. Padovan 459721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout); 460ab07801dSGustavo F. Padovan 46189bc500eSGustavo F. Padovan chan->state = BT_OPEN; 46289bc500eSGustavo F. Padovan 463144ad330SSyam Sidhardhan kref_init(&chan->kref); 46471ba0e56SGustavo F. Padovan 4652827011fSMat Martineau /* This flag is cleared in l2cap_chan_ready() */ 4662827011fSMat Martineau set_bit(CONF_NOT_COMPLETE, &chan->conf_state); 4672827011fSMat Martineau 468eef1d9b6SGustavo Padovan BT_DBG("chan %p", chan); 469abc545b8SSzymon Janc 47048454079SGustavo F. Padovan return chan; 4710a708f8fSGustavo F. Padovan } 4726b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_create); 4730a708f8fSGustavo F. Padovan 474144ad330SSyam Sidhardhan static void l2cap_chan_destroy(struct kref *kref) 4756ff5abbfSGustavo F. Padovan { 476144ad330SSyam Sidhardhan struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref); 477144ad330SSyam Sidhardhan 4784af66c69SJaganath Kanakkassery BT_DBG("chan %p", chan); 4794af66c69SJaganath Kanakkassery 480333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 48123691d75SGustavo F. Padovan list_del(&chan->global_l); 482333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 48323691d75SGustavo F. Padovan 4844af66c69SJaganath Kanakkassery kfree(chan); 4856ff5abbfSGustavo F. Padovan } 4866ff5abbfSGustavo F. Padovan 48730648372SJaganath Kanakkassery void l2cap_chan_hold(struct l2cap_chan *c) 48830648372SJaganath Kanakkassery { 4892c935bc5SPeter Zijlstra BT_DBG("chan %p orig refcnt %d", c, kref_read(&c->kref)); 49030648372SJaganath Kanakkassery 491144ad330SSyam Sidhardhan kref_get(&c->kref); 49230648372SJaganath Kanakkassery } 49330648372SJaganath Kanakkassery 49430648372SJaganath Kanakkassery void l2cap_chan_put(struct l2cap_chan *c) 49530648372SJaganath Kanakkassery { 4962c935bc5SPeter Zijlstra BT_DBG("chan %p orig refcnt %d", c, kref_read(&c->kref)); 49730648372SJaganath Kanakkassery 498144ad330SSyam Sidhardhan kref_put(&c->kref, l2cap_chan_destroy); 49930648372SJaganath Kanakkassery } 5006b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_put); 50130648372SJaganath Kanakkassery 502bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan) 503bd4b1653SAndrei Emeltchenko { 504bd4b1653SAndrei Emeltchenko chan->fcs = L2CAP_FCS_CRC16; 505bd4b1653SAndrei Emeltchenko chan->max_tx = L2CAP_DEFAULT_MAX_TX; 506bd4b1653SAndrei Emeltchenko chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; 507bd4b1653SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 5086a5e8165SJukka Rissanen chan->remote_max_tx = chan->max_tx; 5096a5e8165SJukka Rissanen chan->remote_tx_win = chan->tx_win; 510c20f8e35SMat Martineau chan->ack_win = L2CAP_DEFAULT_TX_WINDOW; 511bd4b1653SAndrei Emeltchenko chan->sec_level = BT_SECURITY_LOW; 5126a5e8165SJukka Rissanen chan->flush_to = L2CAP_DEFAULT_FLUSH_TO; 5136a5e8165SJukka Rissanen chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO; 5146a5e8165SJukka Rissanen chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO; 5156a5e8165SJukka Rissanen chan->conf_state = 0; 516bd4b1653SAndrei Emeltchenko 517bd4b1653SAndrei Emeltchenko set_bit(FLAG_FORCE_ACTIVE, &chan->flags); 518bd4b1653SAndrei Emeltchenko } 5196b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_set_defaults); 520bd4b1653SAndrei Emeltchenko 521ba8f5289SLuiz Augusto von Dentz static void l2cap_le_flowctl_init(struct l2cap_chan *chan, u16 tx_credits) 52238319713SJohan Hedberg { 5230ce43ce6SJohan Hedberg chan->sdu = NULL; 5240ce43ce6SJohan Hedberg chan->sdu_last_frag = NULL; 5250ce43ce6SJohan Hedberg chan->sdu_len = 0; 526ba8f5289SLuiz Augusto von Dentz chan->tx_credits = tx_credits; 527fe149310SLuiz Augusto von Dentz /* Derive MPS from connection MTU to stop HCI fragmentation */ 528fe149310SLuiz Augusto von Dentz chan->mps = min_t(u16, chan->imtu, chan->conn->mtu - L2CAP_HDR_SIZE); 52996cd8eaaSLuiz Augusto von Dentz /* Give enough credits for a full packet */ 53096cd8eaaSLuiz Augusto von Dentz chan->rx_credits = (chan->imtu / chan->mps) + 1; 5310ce43ce6SJohan Hedberg 5320ce43ce6SJohan Hedberg skb_queue_head_init(&chan->tx_q); 53338319713SJohan Hedberg } 53438319713SJohan Hedberg 53593c3e8f5SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 5360a708f8fSGustavo F. Padovan { 5370a708f8fSGustavo F. Padovan BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, 538097db76cSAndrei Emeltchenko __le16_to_cpu(chan->psm), chan->dcid); 5390a708f8fSGustavo F. Padovan 5409f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 5410a708f8fSGustavo F. Padovan 5428c1d787bSGustavo F. Padovan chan->conn = conn; 5430a708f8fSGustavo F. Padovan 5445491120eSAndrei Emeltchenko switch (chan->chan_type) { 5455491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_ORIENTED: 5460a708f8fSGustavo F. Padovan /* Alloc CID for connection-oriented socket */ 547fe4128e0SGustavo F. Padovan chan->scid = l2cap_alloc_cid(conn); 54821626e62SJohan Hedberg if (conn->hcon->type == ACL_LINK) 5490c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 5505491120eSAndrei Emeltchenko break; 5515491120eSAndrei Emeltchenko 5525491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_LESS: 5530a708f8fSGustavo F. Padovan /* Connectionless socket */ 554fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_CONN_LESS; 555fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_CONN_LESS; 5560c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 5575491120eSAndrei Emeltchenko break; 5585491120eSAndrei Emeltchenko 5592338a7e0SJohan Hedberg case L2CAP_CHAN_FIXED: 5602338a7e0SJohan Hedberg /* Caller will set CID and CID specific MTU values */ 561416fa752SAndrei Emeltchenko break; 562416fa752SAndrei Emeltchenko 5635491120eSAndrei Emeltchenko default: 5640a708f8fSGustavo F. Padovan /* Raw socket can send/recv signalling messages only */ 565fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_SIGNALING; 566fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_SIGNALING; 5670c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 5680a708f8fSGustavo F. Padovan } 5690a708f8fSGustavo F. Padovan 5708f7975b1SAndrei Emeltchenko chan->local_id = L2CAP_BESTEFFORT_ID; 5718f7975b1SAndrei Emeltchenko chan->local_stype = L2CAP_SERV_BESTEFFORT; 5728f7975b1SAndrei Emeltchenko chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE; 5738f7975b1SAndrei Emeltchenko chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME; 5748f7975b1SAndrei Emeltchenko chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT; 5758936fa6dSAndrei Emeltchenko chan->local_flush_to = L2CAP_EFS_DEFAULT_FLUSH_TO; 5768f7975b1SAndrei Emeltchenko 577371fd835SUlisses Furquim l2cap_chan_hold(chan); 578baa7e1faSGustavo F. Padovan 579c16900cfSJohan Hedberg /* Only keep a reference for fixed channels if they requested it */ 580c16900cfSJohan Hedberg if (chan->chan_type != L2CAP_CHAN_FIXED || 581c16900cfSJohan Hedberg test_bit(FLAG_HOLD_HCI_CONN, &chan->flags)) 5825ee9891dSJohan Hedberg hci_conn_hold(conn->hcon); 5835ee9891dSJohan Hedberg 5843df91ea2SAndrei Emeltchenko list_add(&chan->list, &conn->chan_l); 585643162a8SAndrei Emeltchenko } 586643162a8SAndrei Emeltchenko 587466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 588643162a8SAndrei Emeltchenko { 589643162a8SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 590643162a8SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 5913df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 5920a708f8fSGustavo F. Padovan } 5930a708f8fSGustavo F. Padovan 594466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err) 5950a708f8fSGustavo F. Padovan { 5968c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 5970a708f8fSGustavo F. Padovan 598c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 5990a708f8fSGustavo F. Padovan 60049d11741SJohan Hedberg BT_DBG("chan %p, conn %p, err %d, state %s", chan, conn, err, 60149d11741SJohan Hedberg state_to_string(chan->state)); 6020a708f8fSGustavo F. Padovan 60372847ce0SJohan Hedberg chan->ops->teardown(chan, err); 60472847ce0SJohan Hedberg 6050a708f8fSGustavo F. Padovan if (conn) { 60656f60984SAndrei Emeltchenko struct amp_mgr *mgr = conn->hcon->amp_mgr; 607baa7e1faSGustavo F. Padovan /* Delete from channel list */ 6083df91ea2SAndrei Emeltchenko list_del(&chan->list); 6093d57dc68SGustavo F. Padovan 610371fd835SUlisses Furquim l2cap_chan_put(chan); 611baa7e1faSGustavo F. Padovan 6128c1d787bSGustavo F. Padovan chan->conn = NULL; 6133cabbfdaSAndrei Emeltchenko 614c16900cfSJohan Hedberg /* Reference was only held for non-fixed channels or 615c16900cfSJohan Hedberg * fixed channels that explicitly requested it using the 616c16900cfSJohan Hedberg * FLAG_HOLD_HCI_CONN flag. 617c16900cfSJohan Hedberg */ 618c16900cfSJohan Hedberg if (chan->chan_type != L2CAP_CHAN_FIXED || 619c16900cfSJohan Hedberg test_bit(FLAG_HOLD_HCI_CONN, &chan->flags)) 62076a68ba0SDavid Herrmann hci_conn_drop(conn->hcon); 62156f60984SAndrei Emeltchenko 62256f60984SAndrei Emeltchenko if (mgr && mgr->bredr_chan == chan) 62356f60984SAndrei Emeltchenko mgr->bredr_chan = NULL; 6240a708f8fSGustavo F. Padovan } 6250a708f8fSGustavo F. Padovan 626419e08c1SAndrei Emeltchenko if (chan->hs_hchan) { 627419e08c1SAndrei Emeltchenko struct hci_chan *hs_hchan = chan->hs_hchan; 628419e08c1SAndrei Emeltchenko 629419e08c1SAndrei Emeltchenko BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan); 630419e08c1SAndrei Emeltchenko amp_disconnect_logical_link(hs_hchan); 631419e08c1SAndrei Emeltchenko } 632419e08c1SAndrei Emeltchenko 6332827011fSMat Martineau if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) 6346ff5abbfSGustavo F. Padovan return; 6352ead70b8SGustavo F. Padovan 636ee556f66SGustavo Padovan switch(chan->mode) { 637ee556f66SGustavo Padovan case L2CAP_MODE_BASIC: 638ee556f66SGustavo Padovan break; 6390a708f8fSGustavo F. Padovan 64038319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 641177f8f2bSJohan Hedberg skb_queue_purge(&chan->tx_q); 64238319713SJohan Hedberg break; 64338319713SJohan Hedberg 644ee556f66SGustavo Padovan case L2CAP_MODE_ERTM: 6451a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 6461a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 6471a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 6480a708f8fSGustavo F. Padovan 649f1c6775bSGustavo F. Padovan skb_queue_purge(&chan->srej_q); 6500a708f8fSGustavo F. Padovan 6513c588192SMat Martineau l2cap_seq_list_free(&chan->srej_list); 6523c588192SMat Martineau l2cap_seq_list_free(&chan->retrans_list); 653ee556f66SGustavo Padovan 654ee556f66SGustavo Padovan /* fall through */ 655ee556f66SGustavo Padovan 656ee556f66SGustavo Padovan case L2CAP_MODE_STREAMING: 657ee556f66SGustavo Padovan skb_queue_purge(&chan->tx_q); 658ee556f66SGustavo Padovan break; 6590a708f8fSGustavo F. Padovan } 660ee556f66SGustavo Padovan 661ee556f66SGustavo Padovan return; 6620a708f8fSGustavo F. Padovan } 6636b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_del); 6640a708f8fSGustavo F. Padovan 665f3d82d0cSJohan Hedberg static void l2cap_conn_update_id_addr(struct work_struct *work) 666387a33e3SJohan Hedberg { 667f3d82d0cSJohan Hedberg struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 668f3d82d0cSJohan Hedberg id_addr_update_work); 669f3d82d0cSJohan Hedberg struct hci_conn *hcon = conn->hcon; 670387a33e3SJohan Hedberg struct l2cap_chan *chan; 671387a33e3SJohan Hedberg 672387a33e3SJohan Hedberg mutex_lock(&conn->chan_lock); 673387a33e3SJohan Hedberg 674387a33e3SJohan Hedberg list_for_each_entry(chan, &conn->chan_l, list) { 675387a33e3SJohan Hedberg l2cap_chan_lock(chan); 676387a33e3SJohan Hedberg bacpy(&chan->dst, &hcon->dst); 677a250e048SJohan Hedberg chan->dst_type = bdaddr_dst_type(hcon); 678387a33e3SJohan Hedberg l2cap_chan_unlock(chan); 679387a33e3SJohan Hedberg } 680387a33e3SJohan Hedberg 681387a33e3SJohan Hedberg mutex_unlock(&conn->chan_lock); 682387a33e3SJohan Hedberg } 683387a33e3SJohan Hedberg 68427e2d4c8SJohan Hedberg static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan) 68527e2d4c8SJohan Hedberg { 68627e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn; 68727e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 68827e2d4c8SJohan Hedberg u16 result; 68927e2d4c8SJohan Hedberg 69027e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 691571f7390SMallikarjun Phulari result = L2CAP_CR_LE_AUTHORIZATION; 69227e2d4c8SJohan Hedberg else 693571f7390SMallikarjun Phulari result = L2CAP_CR_LE_BAD_PSM; 69427e2d4c8SJohan Hedberg 69527e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_DISCONN); 69627e2d4c8SJohan Hedberg 69727e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 69827e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 6993916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps); 7000cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits); 70127e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result); 70227e2d4c8SJohan Hedberg 70327e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), 70427e2d4c8SJohan Hedberg &rsp); 70527e2d4c8SJohan Hedberg } 70627e2d4c8SJohan Hedberg 707791d60f7SJohan Hedberg static void l2cap_chan_connect_reject(struct l2cap_chan *chan) 708791d60f7SJohan Hedberg { 709791d60f7SJohan Hedberg struct l2cap_conn *conn = chan->conn; 710791d60f7SJohan Hedberg struct l2cap_conn_rsp rsp; 711791d60f7SJohan Hedberg u16 result; 712791d60f7SJohan Hedberg 713791d60f7SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 714791d60f7SJohan Hedberg result = L2CAP_CR_SEC_BLOCK; 715791d60f7SJohan Hedberg else 716791d60f7SJohan Hedberg result = L2CAP_CR_BAD_PSM; 717791d60f7SJohan Hedberg 718791d60f7SJohan Hedberg l2cap_state_change(chan, BT_DISCONN); 719791d60f7SJohan Hedberg 720791d60f7SJohan Hedberg rsp.scid = cpu_to_le16(chan->dcid); 721791d60f7SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 722791d60f7SJohan Hedberg rsp.result = cpu_to_le16(result); 723dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 724791d60f7SJohan Hedberg 725791d60f7SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); 726791d60f7SJohan Hedberg } 727791d60f7SJohan Hedberg 7280f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason) 7294519de9aSGustavo F. Padovan { 7304519de9aSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 7314519de9aSGustavo F. Padovan 7327eafc59eSMarcel Holtmann BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 7334519de9aSGustavo F. Padovan 73489bc500eSGustavo F. Padovan switch (chan->state) { 7354519de9aSGustavo F. Padovan case BT_LISTEN: 736c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 7374519de9aSGustavo F. Padovan break; 7384519de9aSGustavo F. Padovan 7394519de9aSGustavo F. Padovan case BT_CONNECTED: 7404519de9aSGustavo F. Padovan case BT_CONFIG: 7417b25c9b3SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) { 7428d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 7435e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, reason); 7444519de9aSGustavo F. Padovan } else 7454519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 7464519de9aSGustavo F. Padovan break; 7474519de9aSGustavo F. Padovan 7484519de9aSGustavo F. Padovan case BT_CONNECT2: 749791d60f7SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) { 750791d60f7SJohan Hedberg if (conn->hcon->type == ACL_LINK) 751791d60f7SJohan Hedberg l2cap_chan_connect_reject(chan); 75227e2d4c8SJohan Hedberg else if (conn->hcon->type == LE_LINK) 75327e2d4c8SJohan Hedberg l2cap_chan_le_connect_reject(chan); 7544519de9aSGustavo F. Padovan } 7554519de9aSGustavo F. Padovan 7564519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 7574519de9aSGustavo F. Padovan break; 7584519de9aSGustavo F. Padovan 7594519de9aSGustavo F. Padovan case BT_CONNECT: 7604519de9aSGustavo F. Padovan case BT_DISCONN: 7614519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 7624519de9aSGustavo F. Padovan break; 7634519de9aSGustavo F. Padovan 7644519de9aSGustavo F. Padovan default: 765c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 7664519de9aSGustavo F. Padovan break; 7674519de9aSGustavo F. Padovan } 7684519de9aSGustavo F. Padovan } 7696b8d4a6aSJukka Rissanen EXPORT_SYMBOL(l2cap_chan_close); 7704519de9aSGustavo F. Padovan 7714343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) 7720a708f8fSGustavo F. Padovan { 7736a974b50SMarcel Holtmann switch (chan->chan_type) { 7746a974b50SMarcel Holtmann case L2CAP_CHAN_RAW: 7754343478fSGustavo F. Padovan switch (chan->sec_level) { 7760a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 7777d513e92SMarcel Holtmann case BT_SECURITY_FIPS: 7780a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING_MITM; 7790a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 7800a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING; 7810a708f8fSGustavo F. Padovan default: 7820a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 7830a708f8fSGustavo F. Padovan } 7846a974b50SMarcel Holtmann break; 7853124b843SMarcel Holtmann case L2CAP_CHAN_CONN_LESS: 786dcf4adbfSJoe Perches if (chan->psm == cpu_to_le16(L2CAP_PSM_3DSP)) { 7873124b843SMarcel Holtmann if (chan->sec_level == BT_SECURITY_LOW) 7883124b843SMarcel Holtmann chan->sec_level = BT_SECURITY_SDP; 7893124b843SMarcel Holtmann } 7907d513e92SMarcel Holtmann if (chan->sec_level == BT_SECURITY_HIGH || 7917d513e92SMarcel Holtmann chan->sec_level == BT_SECURITY_FIPS) 7923124b843SMarcel Holtmann return HCI_AT_NO_BONDING_MITM; 7933124b843SMarcel Holtmann else 7943124b843SMarcel Holtmann return HCI_AT_NO_BONDING; 7953124b843SMarcel Holtmann break; 7966a974b50SMarcel Holtmann case L2CAP_CHAN_CONN_ORIENTED: 797dcf4adbfSJoe Perches if (chan->psm == cpu_to_le16(L2CAP_PSM_SDP)) { 7984343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_LOW) 7994343478fSGustavo F. Padovan chan->sec_level = BT_SECURITY_SDP; 8000a708f8fSGustavo F. Padovan 8017d513e92SMarcel Holtmann if (chan->sec_level == BT_SECURITY_HIGH || 8027d513e92SMarcel Holtmann chan->sec_level == BT_SECURITY_FIPS) 8030a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING_MITM; 8040a708f8fSGustavo F. Padovan else 8050a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 8066a974b50SMarcel Holtmann } 8076a974b50SMarcel Holtmann /* fall through */ 8086a974b50SMarcel Holtmann default: 8094343478fSGustavo F. Padovan switch (chan->sec_level) { 8100a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 8117d513e92SMarcel Holtmann case BT_SECURITY_FIPS: 8120a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING_MITM; 8130a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 8140a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING; 8150a708f8fSGustavo F. Padovan default: 8160a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 8170a708f8fSGustavo F. Padovan } 8186a974b50SMarcel Holtmann break; 8190a708f8fSGustavo F. Padovan } 8200a708f8fSGustavo F. Padovan } 8210a708f8fSGustavo F. Padovan 8220a708f8fSGustavo F. Padovan /* Service level security */ 823e7cafc45SJohan Hedberg int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator) 8240a708f8fSGustavo F. Padovan { 8258c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 8260a708f8fSGustavo F. Padovan __u8 auth_type; 8270a708f8fSGustavo F. Padovan 828a17de2feSJohan Hedberg if (conn->hcon->type == LE_LINK) 829a17de2feSJohan Hedberg return smp_conn_security(conn->hcon, chan->sec_level); 830a17de2feSJohan Hedberg 8314343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 8320a708f8fSGustavo F. Padovan 833e7cafc45SJohan Hedberg return hci_conn_security(conn->hcon, chan->sec_level, auth_type, 834e7cafc45SJohan Hedberg initiator); 8350a708f8fSGustavo F. Padovan } 8360a708f8fSGustavo F. Padovan 837b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn) 8380a708f8fSGustavo F. Padovan { 8390a708f8fSGustavo F. Padovan u8 id; 8400a708f8fSGustavo F. Padovan 8410a708f8fSGustavo F. Padovan /* Get next available identificator. 8420a708f8fSGustavo F. Padovan * 1 - 128 are used by kernel. 8430a708f8fSGustavo F. Padovan * 129 - 199 are reserved. 8440a708f8fSGustavo F. Padovan * 200 - 254 are used by utilities like l2ping, etc. 8450a708f8fSGustavo F. Padovan */ 8460a708f8fSGustavo F. Padovan 8475a54e7c8SMarcel Holtmann mutex_lock(&conn->ident_lock); 8480a708f8fSGustavo F. Padovan 8490a708f8fSGustavo F. Padovan if (++conn->tx_ident > 128) 8500a708f8fSGustavo F. Padovan conn->tx_ident = 1; 8510a708f8fSGustavo F. Padovan 8520a708f8fSGustavo F. Padovan id = conn->tx_ident; 8530a708f8fSGustavo F. Padovan 8545a54e7c8SMarcel Holtmann mutex_unlock(&conn->ident_lock); 8550a708f8fSGustavo F. Padovan 8560a708f8fSGustavo F. Padovan return id; 8570a708f8fSGustavo F. Padovan } 8580a708f8fSGustavo F. Padovan 8592d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 8602d792818SGustavo Padovan void *data) 8610a708f8fSGustavo F. Padovan { 8620a708f8fSGustavo F. Padovan struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); 8630a708f8fSGustavo F. Padovan u8 flags; 8640a708f8fSGustavo F. Padovan 8650a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x", code); 8660a708f8fSGustavo F. Padovan 8670a708f8fSGustavo F. Padovan if (!skb) 8680a708f8fSGustavo F. Padovan return; 8690a708f8fSGustavo F. Padovan 870f6af675eSSteven Walter /* Use NO_FLUSH if supported or we have an LE link (which does 871f6af675eSSteven Walter * not support auto-flushing packets) */ 872f6af675eSSteven Walter if (lmp_no_flush_capable(conn->hcon->hdev) || 873f6af675eSSteven Walter conn->hcon->type == LE_LINK) 8740a708f8fSGustavo F. Padovan flags = ACL_START_NO_FLUSH; 8750a708f8fSGustavo F. Padovan else 8760a708f8fSGustavo F. Padovan flags = ACL_START; 8770a708f8fSGustavo F. Padovan 87814b12d0bSJaikumar Ganesh bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON; 8795e59b791SLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 88014b12d0bSJaikumar Ganesh 88173d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, flags); 8820a708f8fSGustavo F. Padovan } 8830a708f8fSGustavo F. Padovan 88402b0fbb9SMat Martineau static bool __chan_is_moving(struct l2cap_chan *chan) 88502b0fbb9SMat Martineau { 88602b0fbb9SMat Martineau return chan->move_state != L2CAP_MOVE_STABLE && 88702b0fbb9SMat Martineau chan->move_state != L2CAP_MOVE_WAIT_PREPARE; 88802b0fbb9SMat Martineau } 88902b0fbb9SMat Martineau 89073d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) 89173d80debSLuiz Augusto von Dentz { 89273d80debSLuiz Augusto von Dentz struct hci_conn *hcon = chan->conn->hcon; 89373d80debSLuiz Augusto von Dentz u16 flags; 89473d80debSLuiz Augusto von Dentz 89573d80debSLuiz Augusto von Dentz BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, 89673d80debSLuiz Augusto von Dentz skb->priority); 89773d80debSLuiz Augusto von Dentz 898d5f8a75dSMat Martineau if (chan->hs_hcon && !__chan_is_moving(chan)) { 899d5f8a75dSMat Martineau if (chan->hs_hchan) 900d5f8a75dSMat Martineau hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE); 901d5f8a75dSMat Martineau else 902d5f8a75dSMat Martineau kfree_skb(skb); 903d5f8a75dSMat Martineau 904d5f8a75dSMat Martineau return; 905d5f8a75dSMat Martineau } 906d5f8a75dSMat Martineau 907f6af675eSSteven Walter /* Use NO_FLUSH for LE links (where this is the only option) or 908f6af675eSSteven Walter * if the BR/EDR link supports it and flushing has not been 909f6af675eSSteven Walter * explicitly requested (through FLAG_FLUSHABLE). 910f6af675eSSteven Walter */ 911f6af675eSSteven Walter if (hcon->type == LE_LINK || 912f6af675eSSteven Walter (!test_bit(FLAG_FLUSHABLE, &chan->flags) && 913f6af675eSSteven Walter lmp_no_flush_capable(hcon->hdev))) 91473d80debSLuiz Augusto von Dentz flags = ACL_START_NO_FLUSH; 91573d80debSLuiz Augusto von Dentz else 91673d80debSLuiz Augusto von Dentz flags = ACL_START; 91773d80debSLuiz Augusto von Dentz 91873d80debSLuiz Augusto von Dentz bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); 91973d80debSLuiz Augusto von Dentz hci_send_acl(chan->conn->hchan, skb, flags); 9200a708f8fSGustavo F. Padovan } 9210a708f8fSGustavo F. Padovan 922b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control) 923b5c6aaedSMat Martineau { 924b5c6aaedSMat Martineau control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT; 925b5c6aaedSMat Martineau control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT; 926b5c6aaedSMat Martineau 927b5c6aaedSMat Martineau if (enh & L2CAP_CTRL_FRAME_TYPE) { 928b5c6aaedSMat Martineau /* S-Frame */ 929b5c6aaedSMat Martineau control->sframe = 1; 930b5c6aaedSMat Martineau control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT; 931b5c6aaedSMat Martineau control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT; 932b5c6aaedSMat Martineau 933b5c6aaedSMat Martineau control->sar = 0; 934b5c6aaedSMat Martineau control->txseq = 0; 935b5c6aaedSMat Martineau } else { 936b5c6aaedSMat Martineau /* I-Frame */ 937b5c6aaedSMat Martineau control->sframe = 0; 938b5c6aaedSMat Martineau control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT; 939b5c6aaedSMat Martineau control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT; 940b5c6aaedSMat Martineau 941b5c6aaedSMat Martineau control->poll = 0; 942b5c6aaedSMat Martineau control->super = 0; 943b5c6aaedSMat Martineau } 944b5c6aaedSMat Martineau } 945b5c6aaedSMat Martineau 946b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control) 947b5c6aaedSMat Martineau { 948b5c6aaedSMat Martineau control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT; 949b5c6aaedSMat Martineau control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT; 950b5c6aaedSMat Martineau 951b5c6aaedSMat Martineau if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) { 952b5c6aaedSMat Martineau /* S-Frame */ 953b5c6aaedSMat Martineau control->sframe = 1; 954b5c6aaedSMat Martineau control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT; 955b5c6aaedSMat Martineau control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT; 956b5c6aaedSMat Martineau 957b5c6aaedSMat Martineau control->sar = 0; 958b5c6aaedSMat Martineau control->txseq = 0; 959b5c6aaedSMat Martineau } else { 960b5c6aaedSMat Martineau /* I-Frame */ 961b5c6aaedSMat Martineau control->sframe = 0; 962b5c6aaedSMat Martineau control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT; 963b5c6aaedSMat Martineau control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT; 964b5c6aaedSMat Martineau 965b5c6aaedSMat Martineau control->poll = 0; 966b5c6aaedSMat Martineau control->super = 0; 967b5c6aaedSMat Martineau } 968b5c6aaedSMat Martineau } 969b5c6aaedSMat Martineau 970b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan, 971b5c6aaedSMat Martineau struct sk_buff *skb) 972b5c6aaedSMat Martineau { 973b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 974b5c6aaedSMat Martineau __unpack_extended_control(get_unaligned_le32(skb->data), 975a4368ff3SJohan Hedberg &bt_cb(skb)->l2cap); 976cec8ab6eSMat Martineau skb_pull(skb, L2CAP_EXT_CTRL_SIZE); 977b5c6aaedSMat Martineau } else { 978b5c6aaedSMat Martineau __unpack_enhanced_control(get_unaligned_le16(skb->data), 979a4368ff3SJohan Hedberg &bt_cb(skb)->l2cap); 980cec8ab6eSMat Martineau skb_pull(skb, L2CAP_ENH_CTRL_SIZE); 981b5c6aaedSMat Martineau } 982b5c6aaedSMat Martineau } 983b5c6aaedSMat Martineau 984b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control) 985b5c6aaedSMat Martineau { 986b5c6aaedSMat Martineau u32 packed; 987b5c6aaedSMat Martineau 988b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT; 989b5c6aaedSMat Martineau packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT; 990b5c6aaedSMat Martineau 991b5c6aaedSMat Martineau if (control->sframe) { 992b5c6aaedSMat Martineau packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT; 993b5c6aaedSMat Martineau packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT; 994b5c6aaedSMat Martineau packed |= L2CAP_EXT_CTRL_FRAME_TYPE; 995b5c6aaedSMat Martineau } else { 996b5c6aaedSMat Martineau packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT; 997b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT; 998b5c6aaedSMat Martineau } 999b5c6aaedSMat Martineau 1000b5c6aaedSMat Martineau return packed; 1001b5c6aaedSMat Martineau } 1002b5c6aaedSMat Martineau 1003b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control) 1004b5c6aaedSMat Martineau { 1005b5c6aaedSMat Martineau u16 packed; 1006b5c6aaedSMat Martineau 1007b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT; 1008b5c6aaedSMat Martineau packed |= control->final << L2CAP_CTRL_FINAL_SHIFT; 1009b5c6aaedSMat Martineau 1010b5c6aaedSMat Martineau if (control->sframe) { 1011b5c6aaedSMat Martineau packed |= control->poll << L2CAP_CTRL_POLL_SHIFT; 1012b5c6aaedSMat Martineau packed |= control->super << L2CAP_CTRL_SUPER_SHIFT; 1013b5c6aaedSMat Martineau packed |= L2CAP_CTRL_FRAME_TYPE; 1014b5c6aaedSMat Martineau } else { 1015b5c6aaedSMat Martineau packed |= control->sar << L2CAP_CTRL_SAR_SHIFT; 1016b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT; 1017b5c6aaedSMat Martineau } 1018b5c6aaedSMat Martineau 1019b5c6aaedSMat Martineau return packed; 1020b5c6aaedSMat Martineau } 1021b5c6aaedSMat Martineau 1022b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan, 1023b5c6aaedSMat Martineau struct l2cap_ctrl *control, 1024b5c6aaedSMat Martineau struct sk_buff *skb) 1025b5c6aaedSMat Martineau { 1026b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 1027b5c6aaedSMat Martineau put_unaligned_le32(__pack_extended_control(control), 1028b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 1029b5c6aaedSMat Martineau } else { 1030b5c6aaedSMat Martineau put_unaligned_le16(__pack_enhanced_control(control), 1031b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 1032b5c6aaedSMat Martineau } 1033b5c6aaedSMat Martineau } 1034b5c6aaedSMat Martineau 1035ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan) 1036ba7aa64fSGustavo Padovan { 1037ba7aa64fSGustavo Padovan if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1038ba7aa64fSGustavo Padovan return L2CAP_EXT_HDR_SIZE; 1039ba7aa64fSGustavo Padovan else 1040ba7aa64fSGustavo Padovan return L2CAP_ENH_HDR_SIZE; 1041ba7aa64fSGustavo Padovan } 1042ba7aa64fSGustavo Padovan 1043a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan, 1044a67d7f6fSMat Martineau u32 control) 10450a708f8fSGustavo F. Padovan { 10460a708f8fSGustavo F. Padovan struct sk_buff *skb; 10470a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 1048ba7aa64fSGustavo Padovan int hlen = __ertm_hdr_size(chan); 10490a708f8fSGustavo F. Padovan 10500a708f8fSGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 105103a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 10520a708f8fSGustavo F. Padovan 1053a67d7f6fSMat Martineau skb = bt_skb_alloc(hlen, GFP_KERNEL); 10540a708f8fSGustavo F. Padovan 10550a708f8fSGustavo F. Padovan if (!skb) 1056a67d7f6fSMat Martineau return ERR_PTR(-ENOMEM); 10570a708f8fSGustavo F. Padovan 10584df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 10590a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); 1060fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 106188843ab0SAndrei Emeltchenko 1062a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1063a67d7f6fSMat Martineau put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 1064a67d7f6fSMat Martineau else 1065a67d7f6fSMat Martineau put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 10660a708f8fSGustavo F. Padovan 106747d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 1068a67d7f6fSMat Martineau u16 fcs = crc16(0, (u8 *)skb->data, skb->len); 106903a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 10700a708f8fSGustavo F. Padovan } 10710a708f8fSGustavo F. Padovan 107273d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 1073a67d7f6fSMat Martineau return skb; 1074a67d7f6fSMat Martineau } 1075a67d7f6fSMat Martineau 1076a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan, 1077a67d7f6fSMat Martineau struct l2cap_ctrl *control) 1078a67d7f6fSMat Martineau { 1079a67d7f6fSMat Martineau struct sk_buff *skb; 1080a67d7f6fSMat Martineau u32 control_field; 1081a67d7f6fSMat Martineau 1082a67d7f6fSMat Martineau BT_DBG("chan %p, control %p", chan, control); 1083a67d7f6fSMat Martineau 1084a67d7f6fSMat Martineau if (!control->sframe) 1085a67d7f6fSMat Martineau return; 1086a67d7f6fSMat Martineau 1087b99e13adSMat Martineau if (__chan_is_moving(chan)) 1088b99e13adSMat Martineau return; 1089b99e13adSMat Martineau 1090a67d7f6fSMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) && 1091a67d7f6fSMat Martineau !control->poll) 1092a67d7f6fSMat Martineau control->final = 1; 1093a67d7f6fSMat Martineau 1094a67d7f6fSMat Martineau if (control->super == L2CAP_SUPER_RR) 1095a67d7f6fSMat Martineau clear_bit(CONN_RNR_SENT, &chan->conn_state); 1096a67d7f6fSMat Martineau else if (control->super == L2CAP_SUPER_RNR) 1097a67d7f6fSMat Martineau set_bit(CONN_RNR_SENT, &chan->conn_state); 1098a67d7f6fSMat Martineau 1099a67d7f6fSMat Martineau if (control->super != L2CAP_SUPER_SREJ) { 1100a67d7f6fSMat Martineau chan->last_acked_seq = control->reqseq; 1101a67d7f6fSMat Martineau __clear_ack_timer(chan); 1102a67d7f6fSMat Martineau } 1103a67d7f6fSMat Martineau 1104a67d7f6fSMat Martineau BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq, 1105a67d7f6fSMat Martineau control->final, control->poll, control->super); 1106a67d7f6fSMat Martineau 1107a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1108a67d7f6fSMat Martineau control_field = __pack_extended_control(control); 1109a67d7f6fSMat Martineau else 1110a67d7f6fSMat Martineau control_field = __pack_enhanced_control(control); 1111a67d7f6fSMat Martineau 1112a67d7f6fSMat Martineau skb = l2cap_create_sframe_pdu(chan, control_field); 1113a67d7f6fSMat Martineau if (!IS_ERR(skb)) 111473d80debSLuiz Augusto von Dentz l2cap_do_send(chan, skb); 11150a708f8fSGustavo F. Padovan } 11160a708f8fSGustavo F. Padovan 1117c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll) 11180a708f8fSGustavo F. Padovan { 1119c9e3d5e0SMat Martineau struct l2cap_ctrl control; 11200a708f8fSGustavo F. Padovan 1121c9e3d5e0SMat Martineau BT_DBG("chan %p, poll %d", chan, poll); 1122c9e3d5e0SMat Martineau 1123c9e3d5e0SMat Martineau memset(&control, 0, sizeof(control)); 1124c9e3d5e0SMat Martineau control.sframe = 1; 1125c9e3d5e0SMat Martineau control.poll = poll; 1126c9e3d5e0SMat Martineau 1127c9e3d5e0SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 1128c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RNR; 1129c9e3d5e0SMat Martineau else 1130c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RR; 1131c9e3d5e0SMat Martineau 1132c9e3d5e0SMat Martineau control.reqseq = chan->buffer_seq; 1133c9e3d5e0SMat Martineau l2cap_send_sframe(chan, &control); 11340a708f8fSGustavo F. Padovan } 11350a708f8fSGustavo F. Padovan 1136b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) 11370a708f8fSGustavo F. Padovan { 11385ff6f34dSJohan Hedberg if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 11395ff6f34dSJohan Hedberg return true; 11405ff6f34dSJohan Hedberg 1141c1360a1cSGustavo F. Padovan return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); 11420a708f8fSGustavo F. Padovan } 11430a708f8fSGustavo F. Padovan 114493c3e8f5SAndrei Emeltchenko static bool __amp_capable(struct l2cap_chan *chan) 114593c3e8f5SAndrei Emeltchenko { 114693c3e8f5SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 11471df7b17aSMarcel Holtmann struct hci_dev *hdev; 11481df7b17aSMarcel Holtmann bool amp_available = false; 114993c3e8f5SAndrei Emeltchenko 11500bd49fc7SJohan Hedberg if (!(conn->local_fixed_chan & L2CAP_FC_A2MP)) 11511df7b17aSMarcel Holtmann return false; 11521df7b17aSMarcel Holtmann 11530bd49fc7SJohan Hedberg if (!(conn->remote_fixed_chan & L2CAP_FC_A2MP)) 11541df7b17aSMarcel Holtmann return false; 11551df7b17aSMarcel Holtmann 11561df7b17aSMarcel Holtmann read_lock(&hci_dev_list_lock); 11571df7b17aSMarcel Holtmann list_for_each_entry(hdev, &hci_dev_list, list) { 11581df7b17aSMarcel Holtmann if (hdev->amp_type != AMP_TYPE_BREDR && 11591df7b17aSMarcel Holtmann test_bit(HCI_UP, &hdev->flags)) { 11601df7b17aSMarcel Holtmann amp_available = true; 11611df7b17aSMarcel Holtmann break; 11621df7b17aSMarcel Holtmann } 11631df7b17aSMarcel Holtmann } 11641df7b17aSMarcel Holtmann read_unlock(&hci_dev_list_lock); 11651df7b17aSMarcel Holtmann 11661df7b17aSMarcel Holtmann if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED) 11671df7b17aSMarcel Holtmann return amp_available; 1168848566b3SMarcel Holtmann 116993c3e8f5SAndrei Emeltchenko return false; 117093c3e8f5SAndrei Emeltchenko } 117193c3e8f5SAndrei Emeltchenko 11725ce66b59SAndrei Emeltchenko static bool l2cap_check_efs(struct l2cap_chan *chan) 11735ce66b59SAndrei Emeltchenko { 11745ce66b59SAndrei Emeltchenko /* Check EFS parameters */ 11755ce66b59SAndrei Emeltchenko return true; 11765ce66b59SAndrei Emeltchenko } 11775ce66b59SAndrei Emeltchenko 11782766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan) 11799b27f350SAndrei Emeltchenko { 11809b27f350SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 11819b27f350SAndrei Emeltchenko struct l2cap_conn_req req; 11829b27f350SAndrei Emeltchenko 11839b27f350SAndrei Emeltchenko req.scid = cpu_to_le16(chan->scid); 11849b27f350SAndrei Emeltchenko req.psm = chan->psm; 11859b27f350SAndrei Emeltchenko 11869b27f350SAndrei Emeltchenko chan->ident = l2cap_get_ident(conn); 11879b27f350SAndrei Emeltchenko 11889b27f350SAndrei Emeltchenko set_bit(CONF_CONNECT_PEND, &chan->conf_state); 11899b27f350SAndrei Emeltchenko 11909b27f350SAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); 11919b27f350SAndrei Emeltchenko } 11929b27f350SAndrei Emeltchenko 11938eb200bdSMat Martineau static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id) 11948eb200bdSMat Martineau { 11958eb200bdSMat Martineau struct l2cap_create_chan_req req; 11968eb200bdSMat Martineau req.scid = cpu_to_le16(chan->scid); 11978eb200bdSMat Martineau req.psm = chan->psm; 11988eb200bdSMat Martineau req.amp_id = amp_id; 11998eb200bdSMat Martineau 12008eb200bdSMat Martineau chan->ident = l2cap_get_ident(chan->conn); 12018eb200bdSMat Martineau 12028eb200bdSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ, 12038eb200bdSMat Martineau sizeof(req), &req); 12048eb200bdSMat Martineau } 12058eb200bdSMat Martineau 120602b0fbb9SMat Martineau static void l2cap_move_setup(struct l2cap_chan *chan) 120702b0fbb9SMat Martineau { 120802b0fbb9SMat Martineau struct sk_buff *skb; 120902b0fbb9SMat Martineau 121002b0fbb9SMat Martineau BT_DBG("chan %p", chan); 121102b0fbb9SMat Martineau 121202b0fbb9SMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 121302b0fbb9SMat Martineau return; 121402b0fbb9SMat Martineau 121502b0fbb9SMat Martineau __clear_retrans_timer(chan); 121602b0fbb9SMat Martineau __clear_monitor_timer(chan); 121702b0fbb9SMat Martineau __clear_ack_timer(chan); 121802b0fbb9SMat Martineau 121902b0fbb9SMat Martineau chan->retry_count = 0; 122002b0fbb9SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 1221a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.retries) 1222a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 1; 122302b0fbb9SMat Martineau else 122402b0fbb9SMat Martineau break; 122502b0fbb9SMat Martineau } 122602b0fbb9SMat Martineau 122702b0fbb9SMat Martineau chan->expected_tx_seq = chan->buffer_seq; 122802b0fbb9SMat Martineau 122902b0fbb9SMat Martineau clear_bit(CONN_REJ_ACT, &chan->conn_state); 123002b0fbb9SMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 123102b0fbb9SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 123202b0fbb9SMat Martineau l2cap_seq_list_clear(&chan->srej_list); 123302b0fbb9SMat Martineau skb_queue_purge(&chan->srej_q); 123402b0fbb9SMat Martineau 123502b0fbb9SMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 123602b0fbb9SMat Martineau chan->rx_state = L2CAP_RX_STATE_MOVE; 123702b0fbb9SMat Martineau 123802b0fbb9SMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 123902b0fbb9SMat Martineau } 124002b0fbb9SMat Martineau 12415f3847a4SMat Martineau static void l2cap_move_done(struct l2cap_chan *chan) 12425f3847a4SMat Martineau { 12435f3847a4SMat Martineau u8 move_role = chan->move_role; 12445f3847a4SMat Martineau BT_DBG("chan %p", chan); 12455f3847a4SMat Martineau 12465f3847a4SMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 12475f3847a4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 12485f3847a4SMat Martineau 12495f3847a4SMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 12505f3847a4SMat Martineau return; 12515f3847a4SMat Martineau 12525f3847a4SMat Martineau switch (move_role) { 12535f3847a4SMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 12545f3847a4SMat Martineau l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL); 12555f3847a4SMat Martineau chan->rx_state = L2CAP_RX_STATE_WAIT_F; 12565f3847a4SMat Martineau break; 12575f3847a4SMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 12585f3847a4SMat Martineau chan->rx_state = L2CAP_RX_STATE_WAIT_P; 12595f3847a4SMat Martineau break; 12605f3847a4SMat Martineau } 12615f3847a4SMat Martineau } 12625f3847a4SMat Martineau 12639f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan) 12649f0caeb1SVinicius Costa Gomes { 1265315917e0SJohan Hedberg /* The channel may have already been flagged as connected in 1266315917e0SJohan Hedberg * case of receiving data before the L2CAP info req/rsp 1267315917e0SJohan Hedberg * procedure is complete. 1268315917e0SJohan Hedberg */ 1269315917e0SJohan Hedberg if (chan->state == BT_CONNECTED) 1270315917e0SJohan Hedberg return; 1271315917e0SJohan Hedberg 12722827011fSMat Martineau /* This clears all conf flags, including CONF_NOT_COMPLETE */ 12739f0caeb1SVinicius Costa Gomes chan->conf_state = 0; 12749f0caeb1SVinicius Costa Gomes __clear_chan_timer(chan); 12759f0caeb1SVinicius Costa Gomes 12760ce43ce6SJohan Hedberg if (chan->mode == L2CAP_MODE_LE_FLOWCTL && !chan->tx_credits) 12770ce43ce6SJohan Hedberg chan->ops->suspend(chan); 1278177f8f2bSJohan Hedberg 127954a59aa2SAndrei Emeltchenko chan->state = BT_CONNECTED; 12809f0caeb1SVinicius Costa Gomes 128154a59aa2SAndrei Emeltchenko chan->ops->ready(chan); 12829f0caeb1SVinicius Costa Gomes } 12839f0caeb1SVinicius Costa Gomes 1284f1496deeSJohan Hedberg static void l2cap_le_connect(struct l2cap_chan *chan) 1285f1496deeSJohan Hedberg { 1286f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1287f1496deeSJohan Hedberg struct l2cap_le_conn_req req; 1288f1496deeSJohan Hedberg 1289595177f3SJohan Hedberg if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags)) 1290595177f3SJohan Hedberg return; 1291595177f3SJohan Hedberg 1292ba8f5289SLuiz Augusto von Dentz l2cap_le_flowctl_init(chan, 0); 1293fe149310SLuiz Augusto von Dentz 1294f1496deeSJohan Hedberg req.psm = chan->psm; 1295f1496deeSJohan Hedberg req.scid = cpu_to_le16(chan->scid); 1296f1496deeSJohan Hedberg req.mtu = cpu_to_le16(chan->imtu); 12973916aed8SJohan Hedberg req.mps = cpu_to_le16(chan->mps); 12980cd75f7eSJohan Hedberg req.credits = cpu_to_le16(chan->rx_credits); 1299f1496deeSJohan Hedberg 1300f1496deeSJohan Hedberg chan->ident = l2cap_get_ident(conn); 1301f1496deeSJohan Hedberg 1302f1496deeSJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ, 1303f1496deeSJohan Hedberg sizeof(req), &req); 1304f1496deeSJohan Hedberg } 1305f1496deeSJohan Hedberg 1306f1496deeSJohan Hedberg static void l2cap_le_start(struct l2cap_chan *chan) 1307f1496deeSJohan Hedberg { 1308f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1309f1496deeSJohan Hedberg 1310f1496deeSJohan Hedberg if (!smp_conn_security(conn->hcon, chan->sec_level)) 1311f1496deeSJohan Hedberg return; 1312f1496deeSJohan Hedberg 1313f1496deeSJohan Hedberg if (!chan->psm) { 1314f1496deeSJohan Hedberg l2cap_chan_ready(chan); 1315f1496deeSJohan Hedberg return; 1316f1496deeSJohan Hedberg } 1317f1496deeSJohan Hedberg 1318f1496deeSJohan Hedberg if (chan->state == BT_CONNECT) 1319f1496deeSJohan Hedberg l2cap_le_connect(chan); 1320f1496deeSJohan Hedberg } 1321f1496deeSJohan Hedberg 132293c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan) 132393c3e8f5SAndrei Emeltchenko { 132493c3e8f5SAndrei Emeltchenko if (__amp_capable(chan)) { 132593c3e8f5SAndrei Emeltchenko BT_DBG("chan %p AMP capable: discover AMPs", chan); 132693c3e8f5SAndrei Emeltchenko a2mp_discover_amp(chan); 1327f1496deeSJohan Hedberg } else if (chan->conn->hcon->type == LE_LINK) { 1328f1496deeSJohan Hedberg l2cap_le_start(chan); 132993c3e8f5SAndrei Emeltchenko } else { 133093c3e8f5SAndrei Emeltchenko l2cap_send_conn_req(chan); 133193c3e8f5SAndrei Emeltchenko } 133293c3e8f5SAndrei Emeltchenko } 133393c3e8f5SAndrei Emeltchenko 1334aeaeb4bbSJohan Hedberg static void l2cap_request_info(struct l2cap_conn *conn) 13350a708f8fSGustavo F. Padovan { 13360a708f8fSGustavo F. Padovan struct l2cap_info_req req; 1337aeaeb4bbSJohan Hedberg 1338aeaeb4bbSJohan Hedberg if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1339aeaeb4bbSJohan Hedberg return; 1340aeaeb4bbSJohan Hedberg 1341dcf4adbfSJoe Perches req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 13420a708f8fSGustavo F. Padovan 13430a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 13440a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 13450a708f8fSGustavo F. Padovan 1346ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 13470a708f8fSGustavo F. Padovan 13482d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, 13492d792818SGustavo Padovan sizeof(req), &req); 13500a708f8fSGustavo F. Padovan } 1351aeaeb4bbSJohan Hedberg 1352693cd8ceSMarcel Holtmann static bool l2cap_check_enc_key_size(struct hci_conn *hcon) 1353693cd8ceSMarcel Holtmann { 1354693cd8ceSMarcel Holtmann /* The minimum encryption key size needs to be enforced by the 1355693cd8ceSMarcel Holtmann * host stack before establishing any L2CAP connections. The 1356693cd8ceSMarcel Holtmann * specification in theory allows a minimum of 1, but to align 1357693cd8ceSMarcel Holtmann * BR/EDR and LE transports, a minimum of 7 is chosen. 1358693cd8ceSMarcel Holtmann * 1359693cd8ceSMarcel Holtmann * This check might also be called for unencrypted connections 1360693cd8ceSMarcel Holtmann * that have no key size requirements. Ensure that the link is 1361693cd8ceSMarcel Holtmann * actually encrypted before enforcing a key size. 1362693cd8ceSMarcel Holtmann */ 1363693cd8ceSMarcel Holtmann return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) || 136458a96fc3SMarcel Holtmann hcon->enc_key_size >= hcon->hdev->min_enc_key_size); 1365693cd8ceSMarcel Holtmann } 1366693cd8ceSMarcel Holtmann 1367aeaeb4bbSJohan Hedberg static void l2cap_do_start(struct l2cap_chan *chan) 1368aeaeb4bbSJohan Hedberg { 1369aeaeb4bbSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1370aeaeb4bbSJohan Hedberg 1371aeaeb4bbSJohan Hedberg if (conn->hcon->type == LE_LINK) { 1372aeaeb4bbSJohan Hedberg l2cap_le_start(chan); 1373aeaeb4bbSJohan Hedberg return; 1374aeaeb4bbSJohan Hedberg } 1375aeaeb4bbSJohan Hedberg 1376aeaeb4bbSJohan Hedberg if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)) { 1377aeaeb4bbSJohan Hedberg l2cap_request_info(conn); 1378aeaeb4bbSJohan Hedberg return; 1379aeaeb4bbSJohan Hedberg } 1380aeaeb4bbSJohan Hedberg 1381aeaeb4bbSJohan Hedberg if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) 1382aeaeb4bbSJohan Hedberg return; 1383aeaeb4bbSJohan Hedberg 1384693cd8ceSMarcel Holtmann if (!l2cap_chan_check_security(chan, true) || 1385693cd8ceSMarcel Holtmann !__l2cap_no_conn_pending(chan)) 1386693cd8ceSMarcel Holtmann return; 1387693cd8ceSMarcel Holtmann 1388693cd8ceSMarcel Holtmann if (l2cap_check_enc_key_size(conn->hcon)) 1389aeaeb4bbSJohan Hedberg l2cap_start_connection(chan); 1390693cd8ceSMarcel Holtmann else 1391693cd8ceSMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 13920a708f8fSGustavo F. Padovan } 13930a708f8fSGustavo F. Padovan 13940a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) 13950a708f8fSGustavo F. Padovan { 13960a708f8fSGustavo F. Padovan u32 local_feat_mask = l2cap_feat_mask; 13970a708f8fSGustavo F. Padovan if (!disable_ertm) 13980a708f8fSGustavo F. Padovan local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING; 13990a708f8fSGustavo F. Padovan 14000a708f8fSGustavo F. Padovan switch (mode) { 14010a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 14020a708f8fSGustavo F. Padovan return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask; 14030a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 14040a708f8fSGustavo F. Padovan return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask; 14050a708f8fSGustavo F. Padovan default: 14060a708f8fSGustavo F. Padovan return 0x00; 14070a708f8fSGustavo F. Padovan } 14080a708f8fSGustavo F. Padovan } 14090a708f8fSGustavo F. Padovan 14105e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err) 14110a708f8fSGustavo F. Padovan { 14125e4e3972SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 14130a708f8fSGustavo F. Padovan struct l2cap_disconn_req req; 14140a708f8fSGustavo F. Padovan 14150a708f8fSGustavo F. Padovan if (!conn) 14160a708f8fSGustavo F. Padovan return; 14170a708f8fSGustavo F. Padovan 1418aad3d0e3SAndrei Emeltchenko if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) { 14191a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 14201a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 14211a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 14220a708f8fSGustavo F. Padovan } 14230a708f8fSGustavo F. Padovan 14242338a7e0SJohan Hedberg if (chan->scid == L2CAP_CID_A2MP) { 1425d117773cSGustavo Padovan l2cap_state_change(chan, BT_DISCONN); 1426416fa752SAndrei Emeltchenko return; 1427416fa752SAndrei Emeltchenko } 1428416fa752SAndrei Emeltchenko 1429fe4128e0SGustavo F. Padovan req.dcid = cpu_to_le16(chan->dcid); 1430fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 14312d792818SGustavo Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ, 14322d792818SGustavo Padovan sizeof(req), &req); 14330a708f8fSGustavo F. Padovan 1434f8e73017SGustavo Padovan l2cap_state_change_and_error(chan, BT_DISCONN, err); 14350a708f8fSGustavo F. Padovan } 14360a708f8fSGustavo F. Padovan 14370a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */ 14380a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn) 14390a708f8fSGustavo F. Padovan { 14403df91ea2SAndrei Emeltchenko struct l2cap_chan *chan, *tmp; 14410a708f8fSGustavo F. Padovan 14420a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 14430a708f8fSGustavo F. Padovan 14443df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 14450a708f8fSGustavo F. Padovan 14463df91ea2SAndrei Emeltchenko list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 14476be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 14480a708f8fSGustavo F. Padovan 1449715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1450aeaeb4bbSJohan Hedberg l2cap_chan_ready(chan); 14516be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 14520a708f8fSGustavo F. Padovan continue; 14530a708f8fSGustavo F. Padovan } 14540a708f8fSGustavo F. Padovan 145589bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 1456e7cafc45SJohan Hedberg if (!l2cap_chan_check_security(chan, true) || 1457b4450035SGustavo F. Padovan !__l2cap_no_conn_pending(chan)) { 14586be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 14590a708f8fSGustavo F. Padovan continue; 14600a708f8fSGustavo F. Padovan } 14610a708f8fSGustavo F. Padovan 1462c1360a1cSGustavo F. Padovan if (!l2cap_mode_supported(chan->mode, conn->feat_mask) 1463c1360a1cSGustavo F. Padovan && test_bit(CONF_STATE2_DEVICE, 1464c1360a1cSGustavo F. Padovan &chan->conf_state)) { 14650f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 14666be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 14670a708f8fSGustavo F. Padovan continue; 14680a708f8fSGustavo F. Padovan } 14690a708f8fSGustavo F. Padovan 1470693cd8ceSMarcel Holtmann if (l2cap_check_enc_key_size(conn->hcon)) 147193c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 1472693cd8ceSMarcel Holtmann else 1473693cd8ceSMarcel Holtmann l2cap_chan_close(chan, ECONNREFUSED); 14740a708f8fSGustavo F. Padovan 147589bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 14760a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 14770a708f8fSGustavo F. Padovan char buf[128]; 1478fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 1479fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 14800a708f8fSGustavo F. Padovan 1481e7cafc45SJohan Hedberg if (l2cap_chan_check_security(chan, false)) { 1482bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 1483dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_PEND); 1484dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND); 14852dc4e510SGustavo Padovan chan->ops->defer(chan); 14860a708f8fSGustavo F. Padovan 14870a708f8fSGustavo F. Padovan } else { 1488acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 1489dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 1490dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 14910a708f8fSGustavo F. Padovan } 14920a708f8fSGustavo F. Padovan } else { 1493dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_PEND); 1494dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND); 14950a708f8fSGustavo F. Padovan } 14960a708f8fSGustavo F. Padovan 1497fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 1498fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 14990a708f8fSGustavo F. Padovan 1500c1360a1cSGustavo F. Padovan if (test_bit(CONF_REQ_SENT, &chan->conf_state) || 15010a708f8fSGustavo F. Padovan rsp.result != L2CAP_CR_SUCCESS) { 15026be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 15030a708f8fSGustavo F. Padovan continue; 15040a708f8fSGustavo F. Padovan } 15050a708f8fSGustavo F. Padovan 1506c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 15070a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 1508e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); 150973ffa904SGustavo F. Padovan chan->num_conf_req++; 15100a708f8fSGustavo F. Padovan } 15110a708f8fSGustavo F. Padovan 15126be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 15130a708f8fSGustavo F. Padovan } 15140a708f8fSGustavo F. Padovan 15153df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 15160a708f8fSGustavo F. Padovan } 15170a708f8fSGustavo F. Padovan 1518b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn) 1519b62f328bSVille Tervo { 1520cc8dba2bSMarcel Holtmann struct hci_conn *hcon = conn->hcon; 1521dcc36c16SJohan Hedberg struct hci_dev *hdev = hcon->hdev; 1522b62f328bSVille Tervo 1523e760ec12SJohan Hedberg BT_DBG("%s conn %p", hdev->name, conn); 1524b62f328bSVille Tervo 1525e760ec12SJohan Hedberg /* For outgoing pairing which doesn't necessarily have an 1526e760ec12SJohan Hedberg * associated socket (e.g. mgmt_pair_device). 1527e760ec12SJohan Hedberg */ 1528e760ec12SJohan Hedberg if (hcon->out) 1529e760ec12SJohan Hedberg smp_conn_security(hcon, hcon->pending_sec_level); 1530cc8dba2bSMarcel Holtmann 153180afeb6cSMarcel Holtmann /* For LE slave connections, make sure the connection interval 153280afeb6cSMarcel Holtmann * is in the range of the minium and maximum interval that has 153380afeb6cSMarcel Holtmann * been configured for this connection. If not, then trigger 153480afeb6cSMarcel Holtmann * the connection update procedure. 153580afeb6cSMarcel Holtmann */ 153640bef302SJohan Hedberg if (hcon->role == HCI_ROLE_SLAVE && 153780afeb6cSMarcel Holtmann (hcon->le_conn_interval < hcon->le_conn_min_interval || 153880afeb6cSMarcel Holtmann hcon->le_conn_interval > hcon->le_conn_max_interval)) { 153980afeb6cSMarcel Holtmann struct l2cap_conn_param_update_req req; 154080afeb6cSMarcel Holtmann 154180afeb6cSMarcel Holtmann req.min = cpu_to_le16(hcon->le_conn_min_interval); 154280afeb6cSMarcel Holtmann req.max = cpu_to_le16(hcon->le_conn_max_interval); 154380afeb6cSMarcel Holtmann req.latency = cpu_to_le16(hcon->le_conn_latency); 154480afeb6cSMarcel Holtmann req.to_multiplier = cpu_to_le16(hcon->le_supv_timeout); 154580afeb6cSMarcel Holtmann 154680afeb6cSMarcel Holtmann l2cap_send_cmd(conn, l2cap_get_ident(conn), 154780afeb6cSMarcel Holtmann L2CAP_CONN_PARAM_UPDATE_REQ, sizeof(req), &req); 154880afeb6cSMarcel Holtmann } 1549b62f328bSVille Tervo } 1550b62f328bSVille Tervo 15510a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn) 15520a708f8fSGustavo F. Padovan { 155348454079SGustavo F. Padovan struct l2cap_chan *chan; 1554cc110922SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 15550a708f8fSGustavo F. Padovan 15560a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 15570a708f8fSGustavo F. Padovan 1558aeaeb4bbSJohan Hedberg if (hcon->type == ACL_LINK) 1559aeaeb4bbSJohan Hedberg l2cap_request_info(conn); 1560aeaeb4bbSJohan Hedberg 1561e760ec12SJohan Hedberg mutex_lock(&conn->chan_lock); 1562e760ec12SJohan Hedberg 15633df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1564baa7e1faSGustavo F. Padovan 15656be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 15660a708f8fSGustavo F. Padovan 15672338a7e0SJohan Hedberg if (chan->scid == L2CAP_CID_A2MP) { 1568416fa752SAndrei Emeltchenko l2cap_chan_unlock(chan); 1569416fa752SAndrei Emeltchenko continue; 1570416fa752SAndrei Emeltchenko } 1571416fa752SAndrei Emeltchenko 1572cc110922SVinicius Costa Gomes if (hcon->type == LE_LINK) { 1573f1496deeSJohan Hedberg l2cap_le_start(chan); 157463128451SVinicius Costa Gomes } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1575aeaeb4bbSJohan Hedberg if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 157674e75740SGustavo Padovan l2cap_chan_ready(chan); 15771c244f79SGustavo Padovan } else if (chan->state == BT_CONNECT) { 1578fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 15791c244f79SGustavo Padovan } 15800a708f8fSGustavo F. Padovan 15816be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 15820a708f8fSGustavo F. Padovan } 15830a708f8fSGustavo F. Padovan 15843df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 158561a939c6SJohan Hedberg 158679a05727SJohan Hedberg if (hcon->type == LE_LINK) 158779a05727SJohan Hedberg l2cap_le_conn_ready(conn); 158879a05727SJohan Hedberg 158961a939c6SJohan Hedberg queue_work(hcon->hdev->workqueue, &conn->pending_rx_work); 15900a708f8fSGustavo F. Padovan } 15910a708f8fSGustavo F. Padovan 15920a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */ 15930a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) 15940a708f8fSGustavo F. Padovan { 159548454079SGustavo F. Padovan struct l2cap_chan *chan; 15960a708f8fSGustavo F. Padovan 15970a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 15980a708f8fSGustavo F. Padovan 15993df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 16000a708f8fSGustavo F. Padovan 16013df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1602ecf61bdbSAndrei Emeltchenko if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) 16031d8b1fd5SGustavo Padovan l2cap_chan_set_err(chan, err); 16040a708f8fSGustavo F. Padovan } 16050a708f8fSGustavo F. Padovan 16063df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 16070a708f8fSGustavo F. Padovan } 16080a708f8fSGustavo F. Padovan 1609f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work) 16100a708f8fSGustavo F. Padovan { 1611f878fcadSGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 1612030013d8SGustavo F. Padovan info_timer.work); 16130a708f8fSGustavo F. Padovan 16140a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 16150a708f8fSGustavo F. Padovan conn->info_ident = 0; 16160a708f8fSGustavo F. Padovan 16170a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 16180a708f8fSGustavo F. Padovan } 16190a708f8fSGustavo F. Padovan 16202c8e1411SDavid Herrmann /* 16212c8e1411SDavid Herrmann * l2cap_user 16222c8e1411SDavid Herrmann * External modules can register l2cap_user objects on l2cap_conn. The ->probe 16232c8e1411SDavid Herrmann * callback is called during registration. The ->remove callback is called 16242c8e1411SDavid Herrmann * during unregistration. 16252c8e1411SDavid Herrmann * An l2cap_user object can either be explicitly unregistered or when the 16262c8e1411SDavid Herrmann * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon, 16272c8e1411SDavid Herrmann * l2cap->hchan, .. are valid as long as the remove callback hasn't been called. 16282c8e1411SDavid Herrmann * External modules must own a reference to the l2cap_conn object if they intend 16292c8e1411SDavid Herrmann * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at 16302c8e1411SDavid Herrmann * any time if they don't. 16312c8e1411SDavid Herrmann */ 16322c8e1411SDavid Herrmann 16332c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) 16342c8e1411SDavid Herrmann { 16352c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev; 16362c8e1411SDavid Herrmann int ret; 16372c8e1411SDavid Herrmann 16382c8e1411SDavid Herrmann /* We need to check whether l2cap_conn is registered. If it is not, we 16392c8e1411SDavid Herrmann * must not register the l2cap_user. l2cap_conn_del() is unregisters 16402c8e1411SDavid Herrmann * l2cap_conn objects, but doesn't provide its own locking. Instead, it 16412c8e1411SDavid Herrmann * relies on the parent hci_conn object to be locked. This itself relies 16422c8e1411SDavid Herrmann * on the hci_dev object to be locked. So we must lock the hci device 16432c8e1411SDavid Herrmann * here, too. */ 16442c8e1411SDavid Herrmann 16452c8e1411SDavid Herrmann hci_dev_lock(hdev); 16462c8e1411SDavid Herrmann 1647835a6a2fSAlexey Dobriyan if (!list_empty(&user->list)) { 16482c8e1411SDavid Herrmann ret = -EINVAL; 16492c8e1411SDavid Herrmann goto out_unlock; 16502c8e1411SDavid Herrmann } 16512c8e1411SDavid Herrmann 16522c8e1411SDavid Herrmann /* conn->hchan is NULL after l2cap_conn_del() was called */ 16532c8e1411SDavid Herrmann if (!conn->hchan) { 16542c8e1411SDavid Herrmann ret = -ENODEV; 16552c8e1411SDavid Herrmann goto out_unlock; 16562c8e1411SDavid Herrmann } 16572c8e1411SDavid Herrmann 16582c8e1411SDavid Herrmann ret = user->probe(conn, user); 16592c8e1411SDavid Herrmann if (ret) 16602c8e1411SDavid Herrmann goto out_unlock; 16612c8e1411SDavid Herrmann 16622c8e1411SDavid Herrmann list_add(&user->list, &conn->users); 16632c8e1411SDavid Herrmann ret = 0; 16642c8e1411SDavid Herrmann 16652c8e1411SDavid Herrmann out_unlock: 16662c8e1411SDavid Herrmann hci_dev_unlock(hdev); 16672c8e1411SDavid Herrmann return ret; 16682c8e1411SDavid Herrmann } 16692c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user); 16702c8e1411SDavid Herrmann 16712c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) 16722c8e1411SDavid Herrmann { 16732c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev; 16742c8e1411SDavid Herrmann 16752c8e1411SDavid Herrmann hci_dev_lock(hdev); 16762c8e1411SDavid Herrmann 1677835a6a2fSAlexey Dobriyan if (list_empty(&user->list)) 16782c8e1411SDavid Herrmann goto out_unlock; 16792c8e1411SDavid Herrmann 1680ab944c83STedd Ho-Jeong An list_del_init(&user->list); 16812c8e1411SDavid Herrmann user->remove(conn, user); 16822c8e1411SDavid Herrmann 16832c8e1411SDavid Herrmann out_unlock: 16842c8e1411SDavid Herrmann hci_dev_unlock(hdev); 16852c8e1411SDavid Herrmann } 16862c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user); 16872c8e1411SDavid Herrmann 16882c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn) 16892c8e1411SDavid Herrmann { 16902c8e1411SDavid Herrmann struct l2cap_user *user; 16912c8e1411SDavid Herrmann 16922c8e1411SDavid Herrmann while (!list_empty(&conn->users)) { 16932c8e1411SDavid Herrmann user = list_first_entry(&conn->users, struct l2cap_user, list); 1694ab944c83STedd Ho-Jeong An list_del_init(&user->list); 16952c8e1411SDavid Herrmann user->remove(conn, user); 16962c8e1411SDavid Herrmann } 16972c8e1411SDavid Herrmann } 16982c8e1411SDavid Herrmann 16995d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err) 17005d3de7dfSVinicius Costa Gomes { 17015d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 17025d3de7dfSVinicius Costa Gomes struct l2cap_chan *chan, *l; 17035d3de7dfSVinicius Costa Gomes 17045d3de7dfSVinicius Costa Gomes if (!conn) 17055d3de7dfSVinicius Costa Gomes return; 17065d3de7dfSVinicius Costa Gomes 17075d3de7dfSVinicius Costa Gomes BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); 17085d3de7dfSVinicius Costa Gomes 17095d3de7dfSVinicius Costa Gomes kfree_skb(conn->rx_skb); 17105d3de7dfSVinicius Costa Gomes 171161a939c6SJohan Hedberg skb_queue_purge(&conn->pending_rx); 17127ab56c3aSJukka Taimisto 17137ab56c3aSJukka Taimisto /* We can not call flush_work(&conn->pending_rx_work) here since we 17147ab56c3aSJukka Taimisto * might block if we are running on a worker from the same workqueue 17157ab56c3aSJukka Taimisto * pending_rx_work is waiting on. 17167ab56c3aSJukka Taimisto */ 17177ab56c3aSJukka Taimisto if (work_pending(&conn->pending_rx_work)) 17187ab56c3aSJukka Taimisto cancel_work_sync(&conn->pending_rx_work); 171961a939c6SJohan Hedberg 1720f3d82d0cSJohan Hedberg if (work_pending(&conn->id_addr_update_work)) 1721f3d82d0cSJohan Hedberg cancel_work_sync(&conn->id_addr_update_work); 1722f3d82d0cSJohan Hedberg 17232c8e1411SDavid Herrmann l2cap_unregister_all_users(conn); 17242c8e1411SDavid Herrmann 1725e31fb860SJohan Hedberg /* Force the connection to be immediately dropped */ 1726e31fb860SJohan Hedberg hcon->disc_timeout = 0; 1727e31fb860SJohan Hedberg 17283df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 17293df91ea2SAndrei Emeltchenko 17305d3de7dfSVinicius Costa Gomes /* Kill channels */ 17315d3de7dfSVinicius Costa Gomes list_for_each_entry_safe(chan, l, &conn->chan_l, list) { 173261d6ef3eSMat Martineau l2cap_chan_hold(chan); 17336be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 17346be36555SAndrei Emeltchenko 17355d3de7dfSVinicius Costa Gomes l2cap_chan_del(chan, err); 17366be36555SAndrei Emeltchenko 17376be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 17386be36555SAndrei Emeltchenko 173980b98027SGustavo Padovan chan->ops->close(chan); 174061d6ef3eSMat Martineau l2cap_chan_put(chan); 17415d3de7dfSVinicius Costa Gomes } 17425d3de7dfSVinicius Costa Gomes 17433df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 17443df91ea2SAndrei Emeltchenko 174573d80debSLuiz Augusto von Dentz hci_chan_del(conn->hchan); 174673d80debSLuiz Augusto von Dentz 17475d3de7dfSVinicius Costa Gomes if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1748127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->info_timer); 17495d3de7dfSVinicius Costa Gomes 17505d3de7dfSVinicius Costa Gomes hcon->l2cap_data = NULL; 17519c903e37SDavid Herrmann conn->hchan = NULL; 17529c903e37SDavid Herrmann l2cap_conn_put(conn); 17535d3de7dfSVinicius Costa Gomes } 17545d3de7dfSVinicius Costa Gomes 17559c903e37SDavid Herrmann static void l2cap_conn_free(struct kref *ref) 17569c903e37SDavid Herrmann { 17579c903e37SDavid Herrmann struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref); 17589c903e37SDavid Herrmann 17599c903e37SDavid Herrmann hci_conn_put(conn->hcon); 17609c903e37SDavid Herrmann kfree(conn); 17619c903e37SDavid Herrmann } 17629c903e37SDavid Herrmann 176351bb8457SJohan Hedberg struct l2cap_conn *l2cap_conn_get(struct l2cap_conn *conn) 17649c903e37SDavid Herrmann { 17659c903e37SDavid Herrmann kref_get(&conn->ref); 176651bb8457SJohan Hedberg return conn; 17679c903e37SDavid Herrmann } 17689c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_get); 17699c903e37SDavid Herrmann 17709c903e37SDavid Herrmann void l2cap_conn_put(struct l2cap_conn *conn) 17719c903e37SDavid Herrmann { 17729c903e37SDavid Herrmann kref_put(&conn->ref, l2cap_conn_free); 17739c903e37SDavid Herrmann } 17749c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_put); 17759c903e37SDavid Herrmann 17760a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */ 17770a708f8fSGustavo F. Padovan 1778c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr. 17790a708f8fSGustavo F. Padovan * Returns closest match. 17800a708f8fSGustavo F. Padovan */ 1781c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, 1782c2287681SIdo Yariv bdaddr_t *src, 1783bf20fd4eSJohan Hedberg bdaddr_t *dst, 1784bf20fd4eSJohan Hedberg u8 link_type) 17850a708f8fSGustavo F. Padovan { 178623691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 17870a708f8fSGustavo F. Padovan 178823691d75SGustavo F. Padovan read_lock(&chan_list_lock); 17890a708f8fSGustavo F. Padovan 179023691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 179189bc500eSGustavo F. Padovan if (state && c->state != state) 17920a708f8fSGustavo F. Padovan continue; 17930a708f8fSGustavo F. Padovan 1794bf20fd4eSJohan Hedberg if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR) 1795bf20fd4eSJohan Hedberg continue; 1796bf20fd4eSJohan Hedberg 1797bf20fd4eSJohan Hedberg if (link_type == LE_LINK && c->src_type == BDADDR_BREDR) 1798bf20fd4eSJohan Hedberg continue; 1799bf20fd4eSJohan Hedberg 180023691d75SGustavo F. Padovan if (c->psm == psm) { 1801c2287681SIdo Yariv int src_match, dst_match; 1802c2287681SIdo Yariv int src_any, dst_any; 1803c2287681SIdo Yariv 18040a708f8fSGustavo F. Padovan /* Exact match. */ 18057eafc59eSMarcel Holtmann src_match = !bacmp(&c->src, src); 18067eafc59eSMarcel Holtmann dst_match = !bacmp(&c->dst, dst); 1807c2287681SIdo Yariv if (src_match && dst_match) { 1808a24cce14SJohan Hedberg l2cap_chan_hold(c); 1809a7567b20SJohannes Berg read_unlock(&chan_list_lock); 181023691d75SGustavo F. Padovan return c; 181123691d75SGustavo F. Padovan } 18120a708f8fSGustavo F. Padovan 18130a708f8fSGustavo F. Padovan /* Closest match */ 18147eafc59eSMarcel Holtmann src_any = !bacmp(&c->src, BDADDR_ANY); 18157eafc59eSMarcel Holtmann dst_any = !bacmp(&c->dst, BDADDR_ANY); 1816c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1817c2287681SIdo Yariv (src_any && dst_any)) 181823691d75SGustavo F. Padovan c1 = c; 18190a708f8fSGustavo F. Padovan } 18200a708f8fSGustavo F. Padovan } 18210a708f8fSGustavo F. Padovan 1822a24cce14SJohan Hedberg if (c1) 1823a24cce14SJohan Hedberg l2cap_chan_hold(c1); 1824a24cce14SJohan Hedberg 182523691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 18260a708f8fSGustavo F. Padovan 182723691d75SGustavo F. Padovan return c1; 18280a708f8fSGustavo F. Padovan } 18290a708f8fSGustavo F. Padovan 1830721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work) 18310a708f8fSGustavo F. Padovan { 1832721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1833721c4181SGustavo F. Padovan monitor_timer.work); 18340a708f8fSGustavo F. Padovan 1835525cd185SGustavo F. Padovan BT_DBG("chan %p", chan); 18360a708f8fSGustavo F. Padovan 18376be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 18386be36555SAndrei Emeltchenko 183980909e04SMat Martineau if (!chan->conn) { 18406be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 18418d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 18420a708f8fSGustavo F. Padovan return; 18430a708f8fSGustavo F. Padovan } 18440a708f8fSGustavo F. Padovan 1845401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO); 18460a708f8fSGustavo F. Padovan 18476be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 18488d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 18490a708f8fSGustavo F. Padovan } 18500a708f8fSGustavo F. Padovan 1851721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work) 18520a708f8fSGustavo F. Padovan { 1853721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1854721c4181SGustavo F. Padovan retrans_timer.work); 18550a708f8fSGustavo F. Padovan 185649208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 18570a708f8fSGustavo F. Padovan 18586be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 18596be36555SAndrei Emeltchenko 186080909e04SMat Martineau if (!chan->conn) { 186180909e04SMat Martineau l2cap_chan_unlock(chan); 186280909e04SMat Martineau l2cap_chan_put(chan); 186380909e04SMat Martineau return; 186480909e04SMat Martineau } 18650a708f8fSGustavo F. Padovan 1866401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO); 18676be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 18688d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 18690a708f8fSGustavo F. Padovan } 18700a708f8fSGustavo F. Padovan 1871d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan, 18723733937dSMat Martineau struct sk_buff_head *skbs) 18730a708f8fSGustavo F. Padovan { 18740a708f8fSGustavo F. Padovan struct sk_buff *skb; 18753733937dSMat Martineau struct l2cap_ctrl *control; 18760a708f8fSGustavo F. Padovan 18773733937dSMat Martineau BT_DBG("chan %p, skbs %p", chan, skbs); 18783733937dSMat Martineau 1879b99e13adSMat Martineau if (__chan_is_moving(chan)) 1880b99e13adSMat Martineau return; 1881b99e13adSMat Martineau 18823733937dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 18833733937dSMat Martineau 18843733937dSMat Martineau while (!skb_queue_empty(&chan->tx_q)) { 18853733937dSMat Martineau 18863733937dSMat Martineau skb = skb_dequeue(&chan->tx_q); 18873733937dSMat Martineau 1888a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 1; 1889a4368ff3SJohan Hedberg control = &bt_cb(skb)->l2cap; 18903733937dSMat Martineau 18913733937dSMat Martineau control->reqseq = 0; 18923733937dSMat Martineau control->txseq = chan->next_tx_seq; 18933733937dSMat Martineau 18943733937dSMat Martineau __pack_control(chan, control, skb); 18950a708f8fSGustavo F. Padovan 189647d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 18973733937dSMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 18983733937dSMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 18990a708f8fSGustavo F. Padovan } 19000a708f8fSGustavo F. Padovan 19014343478fSGustavo F. Padovan l2cap_do_send(chan, skb); 19020a708f8fSGustavo F. Padovan 1903b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 19043733937dSMat Martineau 1905836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 19063733937dSMat Martineau chan->frames_sent++; 19070a708f8fSGustavo F. Padovan } 19080a708f8fSGustavo F. Padovan } 19090a708f8fSGustavo F. Padovan 191067c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan) 19110a708f8fSGustavo F. Padovan { 19120a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 191318a48e76SMat Martineau struct l2cap_ctrl *control; 191418a48e76SMat Martineau int sent = 0; 191518a48e76SMat Martineau 191618a48e76SMat Martineau BT_DBG("chan %p", chan); 19170a708f8fSGustavo F. Padovan 191889bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 19190a708f8fSGustavo F. Padovan return -ENOTCONN; 19200a708f8fSGustavo F. Padovan 192194122bbeSMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 192294122bbeSMat Martineau return 0; 192394122bbeSMat Martineau 1924b99e13adSMat Martineau if (__chan_is_moving(chan)) 1925b99e13adSMat Martineau return 0; 1926b99e13adSMat Martineau 192718a48e76SMat Martineau while (chan->tx_send_head && 192818a48e76SMat Martineau chan->unacked_frames < chan->remote_tx_win && 192918a48e76SMat Martineau chan->tx_state == L2CAP_TX_STATE_XMIT) { 19300a708f8fSGustavo F. Padovan 193118a48e76SMat Martineau skb = chan->tx_send_head; 19320a708f8fSGustavo F. Padovan 1933a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 1; 1934a4368ff3SJohan Hedberg control = &bt_cb(skb)->l2cap; 19350a708f8fSGustavo F. Padovan 1936e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 193718a48e76SMat Martineau control->final = 1; 1938e2ab4353SGustavo F. Padovan 193918a48e76SMat Martineau control->reqseq = chan->buffer_seq; 194018a48e76SMat Martineau chan->last_acked_seq = chan->buffer_seq; 194118a48e76SMat Martineau control->txseq = chan->next_tx_seq; 19420a708f8fSGustavo F. Padovan 194318a48e76SMat Martineau __pack_control(chan, control, skb); 19440a708f8fSGustavo F. Padovan 194547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 194618a48e76SMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 194718a48e76SMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 19480a708f8fSGustavo F. Padovan } 19490a708f8fSGustavo F. Padovan 195018a48e76SMat Martineau /* Clone after data has been modified. Data is assumed to be 195118a48e76SMat Martineau read-only (for locking purposes) on cloned sk_buffs. 195218a48e76SMat Martineau */ 195318a48e76SMat Martineau tx_skb = skb_clone(skb, GFP_KERNEL); 195418a48e76SMat Martineau 195518a48e76SMat Martineau if (!tx_skb) 195618a48e76SMat Martineau break; 19570a708f8fSGustavo F. Padovan 19581a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 19590a708f8fSGustavo F. Padovan 1960836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 19616a026610SGustavo F. Padovan chan->unacked_frames++; 19626a026610SGustavo F. Padovan chan->frames_sent++; 196318a48e76SMat Martineau sent++; 19640a708f8fSGustavo F. Padovan 196558d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 196658d35f87SGustavo F. Padovan chan->tx_send_head = NULL; 19670a708f8fSGustavo F. Padovan else 196858d35f87SGustavo F. Padovan chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); 196918a48e76SMat Martineau 197018a48e76SMat Martineau l2cap_do_send(chan, tx_skb); 1971b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 19720a708f8fSGustavo F. Padovan } 19730a708f8fSGustavo F. Padovan 1974b4400672SAndrei Emeltchenko BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent, 1975b4400672SAndrei Emeltchenko chan->unacked_frames, skb_queue_len(&chan->tx_q)); 197618a48e76SMat Martineau 197718a48e76SMat Martineau return sent; 19780a708f8fSGustavo F. Padovan } 19790a708f8fSGustavo F. Padovan 1980e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan) 1981e1fbd4c1SMat Martineau { 1982e1fbd4c1SMat Martineau struct l2cap_ctrl control; 1983e1fbd4c1SMat Martineau struct sk_buff *skb; 1984e1fbd4c1SMat Martineau struct sk_buff *tx_skb; 1985e1fbd4c1SMat Martineau u16 seq; 1986e1fbd4c1SMat Martineau 1987e1fbd4c1SMat Martineau BT_DBG("chan %p", chan); 1988e1fbd4c1SMat Martineau 1989e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 1990e1fbd4c1SMat Martineau return; 1991e1fbd4c1SMat Martineau 1992b99e13adSMat Martineau if (__chan_is_moving(chan)) 1993b99e13adSMat Martineau return; 1994b99e13adSMat Martineau 1995e1fbd4c1SMat Martineau while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) { 1996e1fbd4c1SMat Martineau seq = l2cap_seq_list_pop(&chan->retrans_list); 1997e1fbd4c1SMat Martineau 1998e1fbd4c1SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq); 1999e1fbd4c1SMat Martineau if (!skb) { 2000e1fbd4c1SMat Martineau BT_DBG("Error: Can't retransmit seq %d, frame missing", 2001e1fbd4c1SMat Martineau seq); 2002e1fbd4c1SMat Martineau continue; 2003e1fbd4c1SMat Martineau } 2004e1fbd4c1SMat Martineau 2005a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries++; 2006a4368ff3SJohan Hedberg control = bt_cb(skb)->l2cap; 2007e1fbd4c1SMat Martineau 2008e1fbd4c1SMat Martineau if (chan->max_tx != 0 && 2009a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries > chan->max_tx) { 2010e1fbd4c1SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 20115e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 2012e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2013e1fbd4c1SMat Martineau break; 2014e1fbd4c1SMat Martineau } 2015e1fbd4c1SMat Martineau 2016e1fbd4c1SMat Martineau control.reqseq = chan->buffer_seq; 2017e1fbd4c1SMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 2018e1fbd4c1SMat Martineau control.final = 1; 2019e1fbd4c1SMat Martineau else 2020e1fbd4c1SMat Martineau control.final = 0; 2021e1fbd4c1SMat Martineau 2022e1fbd4c1SMat Martineau if (skb_cloned(skb)) { 2023e1fbd4c1SMat Martineau /* Cloned sk_buffs are read-only, so we need a 2024e1fbd4c1SMat Martineau * writeable copy 2025e1fbd4c1SMat Martineau */ 20268bcde1f2SGustavo Padovan tx_skb = skb_copy(skb, GFP_KERNEL); 2027e1fbd4c1SMat Martineau } else { 20288bcde1f2SGustavo Padovan tx_skb = skb_clone(skb, GFP_KERNEL); 2029e1fbd4c1SMat Martineau } 2030e1fbd4c1SMat Martineau 2031e1fbd4c1SMat Martineau if (!tx_skb) { 2032e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2033e1fbd4c1SMat Martineau break; 2034e1fbd4c1SMat Martineau } 2035e1fbd4c1SMat Martineau 2036e1fbd4c1SMat Martineau /* Update skb contents */ 2037e1fbd4c1SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 2038e1fbd4c1SMat Martineau put_unaligned_le32(__pack_extended_control(&control), 2039e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 2040e1fbd4c1SMat Martineau } else { 2041e1fbd4c1SMat Martineau put_unaligned_le16(__pack_enhanced_control(&control), 2042e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 2043e1fbd4c1SMat Martineau } 2044e1fbd4c1SMat Martineau 204513cac152SLukasz Rymanowski /* Update FCS */ 2046e1fbd4c1SMat Martineau if (chan->fcs == L2CAP_FCS_CRC16) { 204713cac152SLukasz Rymanowski u16 fcs = crc16(0, (u8 *) tx_skb->data, 204813cac152SLukasz Rymanowski tx_skb->len - L2CAP_FCS_SIZE); 204913cac152SLukasz Rymanowski put_unaligned_le16(fcs, skb_tail_pointer(tx_skb) - 205013cac152SLukasz Rymanowski L2CAP_FCS_SIZE); 2051e1fbd4c1SMat Martineau } 2052e1fbd4c1SMat Martineau 2053e1fbd4c1SMat Martineau l2cap_do_send(chan, tx_skb); 2054e1fbd4c1SMat Martineau 2055e1fbd4c1SMat Martineau BT_DBG("Resent txseq %d", control.txseq); 2056e1fbd4c1SMat Martineau 2057e1fbd4c1SMat Martineau chan->last_acked_seq = chan->buffer_seq; 2058e1fbd4c1SMat Martineau } 2059e1fbd4c1SMat Martineau } 2060e1fbd4c1SMat Martineau 2061f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan, 2062f80842a8SMat Martineau struct l2cap_ctrl *control) 2063f80842a8SMat Martineau { 2064f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2065f80842a8SMat Martineau 2066f80842a8SMat Martineau l2cap_seq_list_append(&chan->retrans_list, control->reqseq); 2067f80842a8SMat Martineau l2cap_ertm_resend(chan); 2068f80842a8SMat Martineau } 2069f80842a8SMat Martineau 2070d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan, 2071d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 2072d2a7ac5dSMat Martineau { 2073e1fbd4c1SMat Martineau struct sk_buff *skb; 2074e1fbd4c1SMat Martineau 2075e1fbd4c1SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2076e1fbd4c1SMat Martineau 2077e1fbd4c1SMat Martineau if (control->poll) 2078e1fbd4c1SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 2079e1fbd4c1SMat Martineau 2080e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2081e1fbd4c1SMat Martineau 2082e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 2083e1fbd4c1SMat Martineau return; 2084e1fbd4c1SMat Martineau 2085e1fbd4c1SMat Martineau if (chan->unacked_frames) { 2086e1fbd4c1SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 2087a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.txseq == control->reqseq || 2088e1fbd4c1SMat Martineau skb == chan->tx_send_head) 2089e1fbd4c1SMat Martineau break; 2090e1fbd4c1SMat Martineau } 2091e1fbd4c1SMat Martineau 2092e1fbd4c1SMat Martineau skb_queue_walk_from(&chan->tx_q, skb) { 2093e1fbd4c1SMat Martineau if (skb == chan->tx_send_head) 2094e1fbd4c1SMat Martineau break; 2095e1fbd4c1SMat Martineau 2096e1fbd4c1SMat Martineau l2cap_seq_list_append(&chan->retrans_list, 2097a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.txseq); 2098e1fbd4c1SMat Martineau } 2099e1fbd4c1SMat Martineau 2100e1fbd4c1SMat Martineau l2cap_ertm_resend(chan); 2101e1fbd4c1SMat Martineau } 2102d2a7ac5dSMat Martineau } 2103d2a7ac5dSMat Martineau 2104b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan) 2105b17e73bbSSzymon Janc { 21060a0aba42SMat Martineau struct l2cap_ctrl control; 21070a0aba42SMat Martineau u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq, 21080a0aba42SMat Martineau chan->last_acked_seq); 21090a0aba42SMat Martineau int threshold; 21100a0aba42SMat Martineau 21110a0aba42SMat Martineau BT_DBG("chan %p last_acked_seq %d buffer_seq %d", 21120a0aba42SMat Martineau chan, chan->last_acked_seq, chan->buffer_seq); 21130a0aba42SMat Martineau 21140a0aba42SMat Martineau memset(&control, 0, sizeof(control)); 21150a0aba42SMat Martineau control.sframe = 1; 21160a0aba42SMat Martineau 21170a0aba42SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 21180a0aba42SMat Martineau chan->rx_state == L2CAP_RX_STATE_RECV) { 2119b17e73bbSSzymon Janc __clear_ack_timer(chan); 21200a0aba42SMat Martineau control.super = L2CAP_SUPER_RNR; 21210a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 21220a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 21230a0aba42SMat Martineau } else { 21240a0aba42SMat Martineau if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) { 21250a0aba42SMat Martineau l2cap_ertm_send(chan); 21260a0aba42SMat Martineau /* If any i-frames were sent, they included an ack */ 21270a0aba42SMat Martineau if (chan->buffer_seq == chan->last_acked_seq) 21280a0aba42SMat Martineau frames_to_ack = 0; 21290a0aba42SMat Martineau } 21300a0aba42SMat Martineau 2131c20f8e35SMat Martineau /* Ack now if the window is 3/4ths full. 21320a0aba42SMat Martineau * Calculate without mul or div 21330a0aba42SMat Martineau */ 2134c20f8e35SMat Martineau threshold = chan->ack_win; 21350a0aba42SMat Martineau threshold += threshold << 1; 21360a0aba42SMat Martineau threshold >>= 2; 21370a0aba42SMat Martineau 2138b4400672SAndrei Emeltchenko BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack, 21390a0aba42SMat Martineau threshold); 21400a0aba42SMat Martineau 21410a0aba42SMat Martineau if (frames_to_ack >= threshold) { 21420a0aba42SMat Martineau __clear_ack_timer(chan); 21430a0aba42SMat Martineau control.super = L2CAP_SUPER_RR; 21440a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 21450a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 21460a0aba42SMat Martineau frames_to_ack = 0; 21470a0aba42SMat Martineau } 21480a0aba42SMat Martineau 21490a0aba42SMat Martineau if (frames_to_ack) 21500a0aba42SMat Martineau __set_ack_timer(chan); 21510a0aba42SMat Martineau } 2152b17e73bbSSzymon Janc } 2153b17e73bbSSzymon Janc 215404124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, 215504124681SGustavo F. Padovan struct msghdr *msg, int len, 215604124681SGustavo F. Padovan int count, struct sk_buff *skb) 21570a708f8fSGustavo F. Padovan { 21580952a57aSAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 21590a708f8fSGustavo F. Padovan struct sk_buff **frag; 216090338947SGustavo Padovan int sent = 0; 21610a708f8fSGustavo F. Padovan 2162cbbd26b8SAl Viro if (!copy_from_iter_full(skb_put(skb, count), count, &msg->msg_iter)) 21630a708f8fSGustavo F. Padovan return -EFAULT; 21640a708f8fSGustavo F. Padovan 21650a708f8fSGustavo F. Padovan sent += count; 21660a708f8fSGustavo F. Padovan len -= count; 21670a708f8fSGustavo F. Padovan 21680a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 21690a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 21700a708f8fSGustavo F. Padovan while (len) { 2171fbe00700SGustavo Padovan struct sk_buff *tmp; 2172fbe00700SGustavo Padovan 21730a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 21740a708f8fSGustavo F. Padovan 2175d9fbd02bSMarcel Holtmann tmp = chan->ops->alloc_skb(chan, 0, count, 217690338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 2177fbe00700SGustavo Padovan if (IS_ERR(tmp)) 2178fbe00700SGustavo Padovan return PTR_ERR(tmp); 21792f7719ceSAndrei Emeltchenko 2180fbe00700SGustavo Padovan *frag = tmp; 2181fbe00700SGustavo Padovan 2182cbbd26b8SAl Viro if (!copy_from_iter_full(skb_put(*frag, count), count, 2183cbbd26b8SAl Viro &msg->msg_iter)) 21840a708f8fSGustavo F. Padovan return -EFAULT; 21850a708f8fSGustavo F. Padovan 21860a708f8fSGustavo F. Padovan sent += count; 21870a708f8fSGustavo F. Padovan len -= count; 21880a708f8fSGustavo F. Padovan 21892d0ed3d5SGustavo Padovan skb->len += (*frag)->len; 21902d0ed3d5SGustavo Padovan skb->data_len += (*frag)->len; 21912d0ed3d5SGustavo Padovan 21920a708f8fSGustavo F. Padovan frag = &(*frag)->next; 21930a708f8fSGustavo F. Padovan } 21940a708f8fSGustavo F. Padovan 21950a708f8fSGustavo F. Padovan return sent; 21960a708f8fSGustavo F. Padovan } 21970a708f8fSGustavo F. Padovan 21985e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, 21998d46321cSMarcel Holtmann struct msghdr *msg, size_t len) 22000a708f8fSGustavo F. Padovan { 22018c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 22020a708f8fSGustavo F. Padovan struct sk_buff *skb; 220303a51213SAndrei Emeltchenko int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; 22040a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 22050a708f8fSGustavo F. Padovan 22068d46321cSMarcel Holtmann BT_DBG("chan %p psm 0x%2.2x len %zu", chan, 22078d46321cSMarcel Holtmann __le16_to_cpu(chan->psm), len); 22080a708f8fSGustavo F. Padovan 22090a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 22102f7719ceSAndrei Emeltchenko 2211d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, hlen, count, 221290338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 221390338947SGustavo Padovan if (IS_ERR(skb)) 221490338947SGustavo Padovan return skb; 22150a708f8fSGustavo F. Padovan 22160a708f8fSGustavo F. Padovan /* Create L2CAP header */ 22174df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 2218fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 2219daf6a78cSAndrei Emeltchenko lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); 222043b1b8dfSMarcel Holtmann put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE)); 22210a708f8fSGustavo F. Padovan 22220952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 22230a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 22240a708f8fSGustavo F. Padovan kfree_skb(skb); 22250a708f8fSGustavo F. Padovan return ERR_PTR(err); 22260a708f8fSGustavo F. Padovan } 22270a708f8fSGustavo F. Padovan return skb; 22280a708f8fSGustavo F. Padovan } 22290a708f8fSGustavo F. Padovan 22305e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, 22318d46321cSMarcel Holtmann struct msghdr *msg, size_t len) 22320a708f8fSGustavo F. Padovan { 22338c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 22340a708f8fSGustavo F. Padovan struct sk_buff *skb; 2235f2ba7faeSGustavo Padovan int err, count; 22360a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 22370a708f8fSGustavo F. Padovan 2238b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 22390a708f8fSGustavo F. Padovan 2240f2ba7faeSGustavo Padovan count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); 22412f7719ceSAndrei Emeltchenko 2242d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, L2CAP_HDR_SIZE, count, 224390338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 224490338947SGustavo Padovan if (IS_ERR(skb)) 224590338947SGustavo Padovan return skb; 22460a708f8fSGustavo F. Padovan 22470a708f8fSGustavo F. Padovan /* Create L2CAP header */ 22484df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 2249fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 22506ff9b5efSGustavo Padovan lh->len = cpu_to_le16(len); 22510a708f8fSGustavo F. Padovan 22520952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 22530a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 22540a708f8fSGustavo F. Padovan kfree_skb(skb); 22550a708f8fSGustavo F. Padovan return ERR_PTR(err); 22560a708f8fSGustavo F. Padovan } 22570a708f8fSGustavo F. Padovan return skb; 22580a708f8fSGustavo F. Padovan } 22590a708f8fSGustavo F. Padovan 2260ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, 2261ab0ff76dSLuiz Augusto von Dentz struct msghdr *msg, size_t len, 226294122bbeSMat Martineau u16 sdulen) 22630a708f8fSGustavo F. Padovan { 22648c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 22650a708f8fSGustavo F. Padovan struct sk_buff *skb; 2266e4ca6d98SAndrei Emeltchenko int err, count, hlen; 22670a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 22680a708f8fSGustavo F. Padovan 2269b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 22700a708f8fSGustavo F. Padovan 22710a708f8fSGustavo F. Padovan if (!conn) 22720a708f8fSGustavo F. Padovan return ERR_PTR(-ENOTCONN); 22730a708f8fSGustavo F. Padovan 2274ba7aa64fSGustavo Padovan hlen = __ertm_hdr_size(chan); 2275e4ca6d98SAndrei Emeltchenko 22760a708f8fSGustavo F. Padovan if (sdulen) 227703a51213SAndrei Emeltchenko hlen += L2CAP_SDULEN_SIZE; 22780a708f8fSGustavo F. Padovan 227947d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 228003a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 22810a708f8fSGustavo F. Padovan 22820a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 22832f7719ceSAndrei Emeltchenko 2284d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, hlen, count, 228590338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 228690338947SGustavo Padovan if (IS_ERR(skb)) 228790338947SGustavo Padovan return skb; 22880a708f8fSGustavo F. Padovan 22890a708f8fSGustavo F. Padovan /* Create L2CAP header */ 22904df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 2291fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 22920a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 229388843ab0SAndrei Emeltchenko 229418a48e76SMat Martineau /* Control header is populated later */ 229518a48e76SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 229618a48e76SMat Martineau put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 229718a48e76SMat Martineau else 229818a48e76SMat Martineau put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 229988843ab0SAndrei Emeltchenko 23000a708f8fSGustavo F. Padovan if (sdulen) 230103a51213SAndrei Emeltchenko put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 23020a708f8fSGustavo F. Padovan 23030952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 23040a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 23050a708f8fSGustavo F. Padovan kfree_skb(skb); 23060a708f8fSGustavo F. Padovan return ERR_PTR(err); 23070a708f8fSGustavo F. Padovan } 23080a708f8fSGustavo F. Padovan 2309a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.fcs = chan->fcs; 2310a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 0; 23110a708f8fSGustavo F. Padovan return skb; 23120a708f8fSGustavo F. Padovan } 23130a708f8fSGustavo F. Padovan 231494122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan, 231594122bbeSMat Martineau struct sk_buff_head *seg_queue, 231694122bbeSMat Martineau struct msghdr *msg, size_t len) 23170a708f8fSGustavo F. Padovan { 23180a708f8fSGustavo F. Padovan struct sk_buff *skb; 231994122bbeSMat Martineau u16 sdu_len; 232094122bbeSMat Martineau size_t pdu_len; 232194122bbeSMat Martineau u8 sar; 23220a708f8fSGustavo F. Padovan 2323b4400672SAndrei Emeltchenko BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); 23240a708f8fSGustavo F. Padovan 232594122bbeSMat Martineau /* It is critical that ERTM PDUs fit in a single HCI fragment, 232694122bbeSMat Martineau * so fragmented skbs are not used. The HCI layer's handling 232794122bbeSMat Martineau * of fragmented skbs is not compatible with ERTM's queueing. 232894122bbeSMat Martineau */ 232994122bbeSMat Martineau 233094122bbeSMat Martineau /* PDU size is derived from the HCI MTU */ 233194122bbeSMat Martineau pdu_len = chan->conn->mtu; 233294122bbeSMat Martineau 2333a549574dSMat Martineau /* Constrain PDU size for BR/EDR connections */ 2334a549574dSMat Martineau if (!chan->hs_hcon) 233594122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); 233694122bbeSMat Martineau 233794122bbeSMat Martineau /* Adjust for largest possible L2CAP overhead. */ 233835d401dfSGustavo Padovan if (chan->fcs) 233935d401dfSGustavo Padovan pdu_len -= L2CAP_FCS_SIZE; 234035d401dfSGustavo Padovan 2341ba7aa64fSGustavo Padovan pdu_len -= __ertm_hdr_size(chan); 234294122bbeSMat Martineau 234394122bbeSMat Martineau /* Remote device may have requested smaller PDUs */ 234494122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, chan->remote_mps); 234594122bbeSMat Martineau 234694122bbeSMat Martineau if (len <= pdu_len) { 234794122bbeSMat Martineau sar = L2CAP_SAR_UNSEGMENTED; 234894122bbeSMat Martineau sdu_len = 0; 234994122bbeSMat Martineau pdu_len = len; 235094122bbeSMat Martineau } else { 235194122bbeSMat Martineau sar = L2CAP_SAR_START; 235294122bbeSMat Martineau sdu_len = len; 235394122bbeSMat Martineau } 23540a708f8fSGustavo F. Padovan 23550a708f8fSGustavo F. Padovan while (len > 0) { 235694122bbeSMat Martineau skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len); 23570a708f8fSGustavo F. Padovan 23580a708f8fSGustavo F. Padovan if (IS_ERR(skb)) { 235994122bbeSMat Martineau __skb_queue_purge(seg_queue); 23600a708f8fSGustavo F. Padovan return PTR_ERR(skb); 23610a708f8fSGustavo F. Padovan } 23620a708f8fSGustavo F. Padovan 2363a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.sar = sar; 236494122bbeSMat Martineau __skb_queue_tail(seg_queue, skb); 23650a708f8fSGustavo F. Padovan 236694122bbeSMat Martineau len -= pdu_len; 2367069cb270SLukasz Rymanowski if (sdu_len) 236894122bbeSMat Martineau sdu_len = 0; 236994122bbeSMat Martineau 237094122bbeSMat Martineau if (len <= pdu_len) { 237194122bbeSMat Martineau sar = L2CAP_SAR_END; 237294122bbeSMat Martineau pdu_len = len; 237394122bbeSMat Martineau } else { 237494122bbeSMat Martineau sar = L2CAP_SAR_CONTINUE; 237594122bbeSMat Martineau } 237694122bbeSMat Martineau } 237794122bbeSMat Martineau 2378f0f62799SGustavo Padovan return 0; 23790a708f8fSGustavo F. Padovan } 23800a708f8fSGustavo F. Padovan 2381177f8f2bSJohan Hedberg static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan, 2382177f8f2bSJohan Hedberg struct msghdr *msg, 2383177f8f2bSJohan Hedberg size_t len, u16 sdulen) 2384177f8f2bSJohan Hedberg { 2385177f8f2bSJohan Hedberg struct l2cap_conn *conn = chan->conn; 2386177f8f2bSJohan Hedberg struct sk_buff *skb; 2387177f8f2bSJohan Hedberg int err, count, hlen; 2388177f8f2bSJohan Hedberg struct l2cap_hdr *lh; 2389177f8f2bSJohan Hedberg 2390177f8f2bSJohan Hedberg BT_DBG("chan %p len %zu", chan, len); 2391177f8f2bSJohan Hedberg 2392177f8f2bSJohan Hedberg if (!conn) 2393177f8f2bSJohan Hedberg return ERR_PTR(-ENOTCONN); 2394177f8f2bSJohan Hedberg 2395177f8f2bSJohan Hedberg hlen = L2CAP_HDR_SIZE; 2396177f8f2bSJohan Hedberg 2397177f8f2bSJohan Hedberg if (sdulen) 2398177f8f2bSJohan Hedberg hlen += L2CAP_SDULEN_SIZE; 2399177f8f2bSJohan Hedberg 2400177f8f2bSJohan Hedberg count = min_t(unsigned int, (conn->mtu - hlen), len); 2401177f8f2bSJohan Hedberg 2402d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, hlen, count, 2403177f8f2bSJohan Hedberg msg->msg_flags & MSG_DONTWAIT); 2404177f8f2bSJohan Hedberg if (IS_ERR(skb)) 2405177f8f2bSJohan Hedberg return skb; 2406177f8f2bSJohan Hedberg 2407177f8f2bSJohan Hedberg /* Create L2CAP header */ 24084df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 2409177f8f2bSJohan Hedberg lh->cid = cpu_to_le16(chan->dcid); 2410177f8f2bSJohan Hedberg lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 2411177f8f2bSJohan Hedberg 2412177f8f2bSJohan Hedberg if (sdulen) 2413177f8f2bSJohan Hedberg put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 2414177f8f2bSJohan Hedberg 2415177f8f2bSJohan Hedberg err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 2416177f8f2bSJohan Hedberg if (unlikely(err < 0)) { 2417177f8f2bSJohan Hedberg kfree_skb(skb); 2418177f8f2bSJohan Hedberg return ERR_PTR(err); 2419177f8f2bSJohan Hedberg } 2420177f8f2bSJohan Hedberg 2421177f8f2bSJohan Hedberg return skb; 2422177f8f2bSJohan Hedberg } 2423177f8f2bSJohan Hedberg 2424177f8f2bSJohan Hedberg static int l2cap_segment_le_sdu(struct l2cap_chan *chan, 2425177f8f2bSJohan Hedberg struct sk_buff_head *seg_queue, 2426177f8f2bSJohan Hedberg struct msghdr *msg, size_t len) 2427177f8f2bSJohan Hedberg { 2428177f8f2bSJohan Hedberg struct sk_buff *skb; 2429177f8f2bSJohan Hedberg size_t pdu_len; 2430177f8f2bSJohan Hedberg u16 sdu_len; 2431177f8f2bSJohan Hedberg 2432177f8f2bSJohan Hedberg BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); 2433177f8f2bSJohan Hedberg 2434177f8f2bSJohan Hedberg sdu_len = len; 243572c6fb91SJohan Hedberg pdu_len = chan->remote_mps - L2CAP_SDULEN_SIZE; 2436177f8f2bSJohan Hedberg 2437177f8f2bSJohan Hedberg while (len > 0) { 2438177f8f2bSJohan Hedberg if (len <= pdu_len) 2439177f8f2bSJohan Hedberg pdu_len = len; 2440177f8f2bSJohan Hedberg 2441177f8f2bSJohan Hedberg skb = l2cap_create_le_flowctl_pdu(chan, msg, pdu_len, sdu_len); 2442177f8f2bSJohan Hedberg if (IS_ERR(skb)) { 2443177f8f2bSJohan Hedberg __skb_queue_purge(seg_queue); 2444177f8f2bSJohan Hedberg return PTR_ERR(skb); 2445177f8f2bSJohan Hedberg } 2446177f8f2bSJohan Hedberg 2447177f8f2bSJohan Hedberg __skb_queue_tail(seg_queue, skb); 2448177f8f2bSJohan Hedberg 2449177f8f2bSJohan Hedberg len -= pdu_len; 2450177f8f2bSJohan Hedberg 2451177f8f2bSJohan Hedberg if (sdu_len) { 2452177f8f2bSJohan Hedberg sdu_len = 0; 2453177f8f2bSJohan Hedberg pdu_len += L2CAP_SDULEN_SIZE; 2454177f8f2bSJohan Hedberg } 2455177f8f2bSJohan Hedberg } 2456177f8f2bSJohan Hedberg 2457177f8f2bSJohan Hedberg return 0; 2458177f8f2bSJohan Hedberg } 2459177f8f2bSJohan Hedberg 24608a505b7fSLuiz Augusto von Dentz static void l2cap_le_flowctl_send(struct l2cap_chan *chan) 24618a505b7fSLuiz Augusto von Dentz { 24628a505b7fSLuiz Augusto von Dentz int sent = 0; 24638a505b7fSLuiz Augusto von Dentz 24648a505b7fSLuiz Augusto von Dentz BT_DBG("chan %p", chan); 24658a505b7fSLuiz Augusto von Dentz 24668a505b7fSLuiz Augusto von Dentz while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) { 24678a505b7fSLuiz Augusto von Dentz l2cap_do_send(chan, skb_dequeue(&chan->tx_q)); 24688a505b7fSLuiz Augusto von Dentz chan->tx_credits--; 24698a505b7fSLuiz Augusto von Dentz sent++; 24708a505b7fSLuiz Augusto von Dentz } 24718a505b7fSLuiz Augusto von Dentz 24728a505b7fSLuiz Augusto von Dentz BT_DBG("Sent %d credits %u queued %u", sent, chan->tx_credits, 24738a505b7fSLuiz Augusto von Dentz skb_queue_len(&chan->tx_q)); 24748a505b7fSLuiz Augusto von Dentz } 24758a505b7fSLuiz Augusto von Dentz 24768d46321cSMarcel Holtmann int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len) 24779a91a04aSGustavo F. Padovan { 24789a91a04aSGustavo F. Padovan struct sk_buff *skb; 24799a91a04aSGustavo F. Padovan int err; 248094122bbeSMat Martineau struct sk_buff_head seg_queue; 24819a91a04aSGustavo F. Padovan 248231e8ce80SSeung-Woo Kim if (!chan->conn) 248331e8ce80SSeung-Woo Kim return -ENOTCONN; 248431e8ce80SSeung-Woo Kim 24859a91a04aSGustavo F. Padovan /* Connectionless channel */ 2486715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { 24878d46321cSMarcel Holtmann skb = l2cap_create_connless_pdu(chan, msg, len); 24889a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 24899a91a04aSGustavo F. Padovan return PTR_ERR(skb); 24909a91a04aSGustavo F. Padovan 2491ede81a2aSAndrzej Kaczmarek /* Channel lock is released before requesting new skb and then 2492ede81a2aSAndrzej Kaczmarek * reacquired thus we need to recheck channel state. 2493ede81a2aSAndrzej Kaczmarek */ 2494ede81a2aSAndrzej Kaczmarek if (chan->state != BT_CONNECTED) { 2495ede81a2aSAndrzej Kaczmarek kfree_skb(skb); 2496ede81a2aSAndrzej Kaczmarek return -ENOTCONN; 2497ede81a2aSAndrzej Kaczmarek } 2498ede81a2aSAndrzej Kaczmarek 24999a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 25009a91a04aSGustavo F. Padovan return len; 25019a91a04aSGustavo F. Padovan } 25029a91a04aSGustavo F. Padovan 25039a91a04aSGustavo F. Padovan switch (chan->mode) { 250438319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 2505177f8f2bSJohan Hedberg /* Check outgoing MTU */ 2506177f8f2bSJohan Hedberg if (len > chan->omtu) 2507177f8f2bSJohan Hedberg return -EMSGSIZE; 2508177f8f2bSJohan Hedberg 2509177f8f2bSJohan Hedberg __skb_queue_head_init(&seg_queue); 2510177f8f2bSJohan Hedberg 2511177f8f2bSJohan Hedberg err = l2cap_segment_le_sdu(chan, &seg_queue, msg, len); 2512177f8f2bSJohan Hedberg 2513177f8f2bSJohan Hedberg if (chan->state != BT_CONNECTED) { 2514177f8f2bSJohan Hedberg __skb_queue_purge(&seg_queue); 2515177f8f2bSJohan Hedberg err = -ENOTCONN; 2516177f8f2bSJohan Hedberg } 2517177f8f2bSJohan Hedberg 2518177f8f2bSJohan Hedberg if (err) 2519177f8f2bSJohan Hedberg return err; 2520177f8f2bSJohan Hedberg 2521177f8f2bSJohan Hedberg skb_queue_splice_tail_init(&seg_queue, &chan->tx_q); 2522177f8f2bSJohan Hedberg 25238a505b7fSLuiz Augusto von Dentz l2cap_le_flowctl_send(chan); 2524177f8f2bSJohan Hedberg 2525177f8f2bSJohan Hedberg if (!chan->tx_credits) 2526177f8f2bSJohan Hedberg chan->ops->suspend(chan); 2527177f8f2bSJohan Hedberg 2528177f8f2bSJohan Hedberg err = len; 2529177f8f2bSJohan Hedberg 2530177f8f2bSJohan Hedberg break; 2531177f8f2bSJohan Hedberg 2532fad5fc89SJohan Hedberg case L2CAP_MODE_BASIC: 25339a91a04aSGustavo F. Padovan /* Check outgoing MTU */ 25349a91a04aSGustavo F. Padovan if (len > chan->omtu) 25359a91a04aSGustavo F. Padovan return -EMSGSIZE; 25369a91a04aSGustavo F. Padovan 25379a91a04aSGustavo F. Padovan /* Create a basic PDU */ 25388d46321cSMarcel Holtmann skb = l2cap_create_basic_pdu(chan, msg, len); 25399a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 25409a91a04aSGustavo F. Padovan return PTR_ERR(skb); 25419a91a04aSGustavo F. Padovan 2542ede81a2aSAndrzej Kaczmarek /* Channel lock is released before requesting new skb and then 2543ede81a2aSAndrzej Kaczmarek * reacquired thus we need to recheck channel state. 2544ede81a2aSAndrzej Kaczmarek */ 2545ede81a2aSAndrzej Kaczmarek if (chan->state != BT_CONNECTED) { 2546ede81a2aSAndrzej Kaczmarek kfree_skb(skb); 2547ede81a2aSAndrzej Kaczmarek return -ENOTCONN; 2548ede81a2aSAndrzej Kaczmarek } 2549ede81a2aSAndrzej Kaczmarek 25509a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 25519a91a04aSGustavo F. Padovan err = len; 25529a91a04aSGustavo F. Padovan break; 25539a91a04aSGustavo F. Padovan 25549a91a04aSGustavo F. Padovan case L2CAP_MODE_ERTM: 25559a91a04aSGustavo F. Padovan case L2CAP_MODE_STREAMING: 255694122bbeSMat Martineau /* Check outgoing MTU */ 255794122bbeSMat Martineau if (len > chan->omtu) { 255894122bbeSMat Martineau err = -EMSGSIZE; 25599a91a04aSGustavo F. Padovan break; 25609a91a04aSGustavo F. Padovan } 25619a91a04aSGustavo F. Padovan 256294122bbeSMat Martineau __skb_queue_head_init(&seg_queue); 256394122bbeSMat Martineau 256494122bbeSMat Martineau /* Do segmentation before calling in to the state machine, 256594122bbeSMat Martineau * since it's possible to block while waiting for memory 256694122bbeSMat Martineau * allocation. 256794122bbeSMat Martineau */ 256894122bbeSMat Martineau err = l2cap_segment_sdu(chan, &seg_queue, msg, len); 256994122bbeSMat Martineau 257094122bbeSMat Martineau /* The channel could have been closed while segmenting, 257194122bbeSMat Martineau * check that it is still connected. 257294122bbeSMat Martineau */ 257394122bbeSMat Martineau if (chan->state != BT_CONNECTED) { 257494122bbeSMat Martineau __skb_queue_purge(&seg_queue); 257594122bbeSMat Martineau err = -ENOTCONN; 25769a91a04aSGustavo F. Padovan } 25779a91a04aSGustavo F. Padovan 257894122bbeSMat Martineau if (err) 257994122bbeSMat Martineau break; 258094122bbeSMat Martineau 25813733937dSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) 2582d660366dSGustavo Padovan l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST); 25833733937dSMat Martineau else 2584d660366dSGustavo Padovan l2cap_streaming_send(chan, &seg_queue); 258594122bbeSMat Martineau 25869a91a04aSGustavo F. Padovan err = len; 25879a91a04aSGustavo F. Padovan 258894122bbeSMat Martineau /* If the skbs were not queued for sending, they'll still be in 258994122bbeSMat Martineau * seg_queue and need to be purged. 259094122bbeSMat Martineau */ 259194122bbeSMat Martineau __skb_queue_purge(&seg_queue); 25929a91a04aSGustavo F. Padovan break; 25939a91a04aSGustavo F. Padovan 25949a91a04aSGustavo F. Padovan default: 25959a91a04aSGustavo F. Padovan BT_DBG("bad state %1.1x", chan->mode); 25969a91a04aSGustavo F. Padovan err = -EBADFD; 25979a91a04aSGustavo F. Padovan } 25989a91a04aSGustavo F. Padovan 25999a91a04aSGustavo F. Padovan return err; 26009a91a04aSGustavo F. Padovan } 26016b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_send); 26029a91a04aSGustavo F. Padovan 2603d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq) 2604d2a7ac5dSMat Martineau { 2605bed68bdeSMat Martineau struct l2cap_ctrl control; 2606bed68bdeSMat Martineau u16 seq; 2607bed68bdeSMat Martineau 2608b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2609bed68bdeSMat Martineau 2610bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2611bed68bdeSMat Martineau control.sframe = 1; 2612bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2613bed68bdeSMat Martineau 2614bed68bdeSMat Martineau for (seq = chan->expected_tx_seq; seq != txseq; 2615bed68bdeSMat Martineau seq = __next_seq(chan, seq)) { 2616bed68bdeSMat Martineau if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) { 2617bed68bdeSMat Martineau control.reqseq = seq; 2618bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2619bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2620bed68bdeSMat Martineau } 2621bed68bdeSMat Martineau } 2622bed68bdeSMat Martineau 2623bed68bdeSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 2624d2a7ac5dSMat Martineau } 2625d2a7ac5dSMat Martineau 2626d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan) 2627d2a7ac5dSMat Martineau { 2628bed68bdeSMat Martineau struct l2cap_ctrl control; 2629bed68bdeSMat Martineau 2630bed68bdeSMat Martineau BT_DBG("chan %p", chan); 2631bed68bdeSMat Martineau 2632bed68bdeSMat Martineau if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR) 2633bed68bdeSMat Martineau return; 2634bed68bdeSMat Martineau 2635bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2636bed68bdeSMat Martineau control.sframe = 1; 2637bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2638bed68bdeSMat Martineau control.reqseq = chan->srej_list.tail; 2639bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2640d2a7ac5dSMat Martineau } 2641d2a7ac5dSMat Martineau 2642d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq) 2643d2a7ac5dSMat Martineau { 2644bed68bdeSMat Martineau struct l2cap_ctrl control; 2645bed68bdeSMat Martineau u16 initial_head; 2646bed68bdeSMat Martineau u16 seq; 2647bed68bdeSMat Martineau 2648b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2649bed68bdeSMat Martineau 2650bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2651bed68bdeSMat Martineau control.sframe = 1; 2652bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2653bed68bdeSMat Martineau 2654bed68bdeSMat Martineau /* Capture initial list head to allow only one pass through the list. */ 2655bed68bdeSMat Martineau initial_head = chan->srej_list.head; 2656bed68bdeSMat Martineau 2657bed68bdeSMat Martineau do { 2658bed68bdeSMat Martineau seq = l2cap_seq_list_pop(&chan->srej_list); 2659bed68bdeSMat Martineau if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR) 2660bed68bdeSMat Martineau break; 2661bed68bdeSMat Martineau 2662bed68bdeSMat Martineau control.reqseq = seq; 2663bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2664bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2665bed68bdeSMat Martineau } while (chan->srej_list.head != initial_head); 2666d2a7ac5dSMat Martineau } 2667d2a7ac5dSMat Martineau 2668608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq) 2669608bcc6dSMat Martineau { 2670608bcc6dSMat Martineau struct sk_buff *acked_skb; 2671608bcc6dSMat Martineau u16 ackseq; 2672608bcc6dSMat Martineau 2673b4400672SAndrei Emeltchenko BT_DBG("chan %p, reqseq %u", chan, reqseq); 2674608bcc6dSMat Martineau 2675608bcc6dSMat Martineau if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq) 2676608bcc6dSMat Martineau return; 2677608bcc6dSMat Martineau 2678b4400672SAndrei Emeltchenko BT_DBG("expected_ack_seq %u, unacked_frames %u", 2679608bcc6dSMat Martineau chan->expected_ack_seq, chan->unacked_frames); 2680608bcc6dSMat Martineau 2681608bcc6dSMat Martineau for (ackseq = chan->expected_ack_seq; ackseq != reqseq; 2682608bcc6dSMat Martineau ackseq = __next_seq(chan, ackseq)) { 2683608bcc6dSMat Martineau 2684608bcc6dSMat Martineau acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq); 2685608bcc6dSMat Martineau if (acked_skb) { 2686608bcc6dSMat Martineau skb_unlink(acked_skb, &chan->tx_q); 2687608bcc6dSMat Martineau kfree_skb(acked_skb); 2688608bcc6dSMat Martineau chan->unacked_frames--; 2689608bcc6dSMat Martineau } 2690608bcc6dSMat Martineau } 2691608bcc6dSMat Martineau 2692608bcc6dSMat Martineau chan->expected_ack_seq = reqseq; 2693608bcc6dSMat Martineau 2694608bcc6dSMat Martineau if (chan->unacked_frames == 0) 2695608bcc6dSMat Martineau __clear_retrans_timer(chan); 2696608bcc6dSMat Martineau 2697b4400672SAndrei Emeltchenko BT_DBG("unacked_frames %u", chan->unacked_frames); 2698608bcc6dSMat Martineau } 2699608bcc6dSMat Martineau 2700608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan) 2701608bcc6dSMat Martineau { 2702608bcc6dSMat Martineau BT_DBG("chan %p", chan); 2703608bcc6dSMat Martineau 2704608bcc6dSMat Martineau chan->expected_tx_seq = chan->buffer_seq; 2705608bcc6dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 2706608bcc6dSMat Martineau skb_queue_purge(&chan->srej_q); 2707608bcc6dSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2708608bcc6dSMat Martineau } 2709608bcc6dSMat Martineau 2710d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan, 2711608bcc6dSMat Martineau struct l2cap_ctrl *control, 2712608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2713608bcc6dSMat Martineau { 2714608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2715608bcc6dSMat Martineau event); 2716608bcc6dSMat Martineau 2717608bcc6dSMat Martineau switch (event) { 2718608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2719608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2720608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2721608bcc6dSMat Martineau 2722608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2723608bcc6dSMat Martineau l2cap_ertm_send(chan); 2724608bcc6dSMat Martineau break; 2725608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2726608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2727608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2728608bcc6dSMat Martineau 2729608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2730608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2731608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2732608bcc6dSMat Martineau */ 2733608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2734608bcc6dSMat Martineau } 2735608bcc6dSMat Martineau 2736608bcc6dSMat Martineau l2cap_send_ack(chan); 2737608bcc6dSMat Martineau 2738608bcc6dSMat Martineau break; 2739608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2740608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2741608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2742608bcc6dSMat Martineau 2743608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2744608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2745608bcc6dSMat Martineau 2746608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2747608bcc6dSMat Martineau local_control.sframe = 1; 2748608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2749608bcc6dSMat Martineau local_control.poll = 1; 2750608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2751a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2752608bcc6dSMat Martineau 2753608bcc6dSMat Martineau chan->retry_count = 1; 2754608bcc6dSMat Martineau __set_monitor_timer(chan); 2755608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2756608bcc6dSMat Martineau } 2757608bcc6dSMat Martineau break; 2758608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2759608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2760608bcc6dSMat Martineau break; 2761608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2762608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2763608bcc6dSMat Martineau chan->retry_count = 1; 2764608bcc6dSMat Martineau __set_monitor_timer(chan); 2765608bcc6dSMat Martineau __clear_ack_timer(chan); 2766608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2767608bcc6dSMat Martineau break; 2768608bcc6dSMat Martineau case L2CAP_EV_RETRANS_TO: 2769608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2770608bcc6dSMat Martineau chan->retry_count = 1; 2771608bcc6dSMat Martineau __set_monitor_timer(chan); 2772608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2773608bcc6dSMat Martineau break; 2774608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2775608bcc6dSMat Martineau /* Nothing to process */ 2776608bcc6dSMat Martineau break; 2777608bcc6dSMat Martineau default: 2778608bcc6dSMat Martineau break; 2779608bcc6dSMat Martineau } 2780608bcc6dSMat Martineau } 2781608bcc6dSMat Martineau 2782d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan, 2783608bcc6dSMat Martineau struct l2cap_ctrl *control, 2784608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2785608bcc6dSMat Martineau { 2786608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2787608bcc6dSMat Martineau event); 2788608bcc6dSMat Martineau 2789608bcc6dSMat Martineau switch (event) { 2790608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2791608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2792608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2793608bcc6dSMat Martineau /* Queue data, but don't send. */ 2794608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2795608bcc6dSMat Martineau break; 2796608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2797608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2798608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2799608bcc6dSMat Martineau 2800608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2801608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2802608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2803608bcc6dSMat Martineau */ 2804608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2805608bcc6dSMat Martineau } 2806608bcc6dSMat Martineau 2807608bcc6dSMat Martineau l2cap_send_ack(chan); 2808608bcc6dSMat Martineau 2809608bcc6dSMat Martineau break; 2810608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2811608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2812608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2813608bcc6dSMat Martineau 2814608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2815608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2816608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2817608bcc6dSMat Martineau local_control.sframe = 1; 2818608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2819608bcc6dSMat Martineau local_control.poll = 1; 2820608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2821a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2822608bcc6dSMat Martineau 2823608bcc6dSMat Martineau chan->retry_count = 1; 2824608bcc6dSMat Martineau __set_monitor_timer(chan); 2825608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2826608bcc6dSMat Martineau } 2827608bcc6dSMat Martineau break; 2828608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2829608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2830608bcc6dSMat Martineau 2831608bcc6dSMat Martineau /* Fall through */ 2832608bcc6dSMat Martineau 2833608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2834608bcc6dSMat Martineau if (control && control->final) { 2835608bcc6dSMat Martineau __clear_monitor_timer(chan); 2836608bcc6dSMat Martineau if (chan->unacked_frames > 0) 2837608bcc6dSMat Martineau __set_retrans_timer(chan); 2838608bcc6dSMat Martineau chan->retry_count = 0; 2839608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 2840608bcc6dSMat Martineau BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state); 2841608bcc6dSMat Martineau } 2842608bcc6dSMat Martineau break; 2843608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2844608bcc6dSMat Martineau /* Ignore */ 2845608bcc6dSMat Martineau break; 2846608bcc6dSMat Martineau case L2CAP_EV_MONITOR_TO: 2847608bcc6dSMat Martineau if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) { 2848608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2849608bcc6dSMat Martineau __set_monitor_timer(chan); 2850608bcc6dSMat Martineau chan->retry_count++; 2851608bcc6dSMat Martineau } else { 28525e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNABORTED); 2853608bcc6dSMat Martineau } 2854608bcc6dSMat Martineau break; 2855608bcc6dSMat Martineau default: 2856608bcc6dSMat Martineau break; 2857608bcc6dSMat Martineau } 2858608bcc6dSMat Martineau } 2859608bcc6dSMat Martineau 2860d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 2861608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2862608bcc6dSMat Martineau { 2863608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d, state %d", 2864608bcc6dSMat Martineau chan, control, skbs, event, chan->tx_state); 2865608bcc6dSMat Martineau 2866608bcc6dSMat Martineau switch (chan->tx_state) { 2867608bcc6dSMat Martineau case L2CAP_TX_STATE_XMIT: 2868d660366dSGustavo Padovan l2cap_tx_state_xmit(chan, control, skbs, event); 2869608bcc6dSMat Martineau break; 2870608bcc6dSMat Martineau case L2CAP_TX_STATE_WAIT_F: 2871d660366dSGustavo Padovan l2cap_tx_state_wait_f(chan, control, skbs, event); 2872608bcc6dSMat Martineau break; 2873608bcc6dSMat Martineau default: 2874608bcc6dSMat Martineau /* Ignore event */ 2875608bcc6dSMat Martineau break; 2876608bcc6dSMat Martineau } 2877608bcc6dSMat Martineau } 2878608bcc6dSMat Martineau 28794b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan, 28804b51dae9SMat Martineau struct l2cap_ctrl *control) 28814b51dae9SMat Martineau { 28824b51dae9SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2883401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT); 28844b51dae9SMat Martineau } 28854b51dae9SMat Martineau 2886f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan, 2887f80842a8SMat Martineau struct l2cap_ctrl *control) 2888f80842a8SMat Martineau { 2889f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2890401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT); 2891f80842a8SMat Martineau } 2892f80842a8SMat Martineau 28930a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */ 28940a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 28950a708f8fSGustavo F. Padovan { 28960a708f8fSGustavo F. Padovan struct sk_buff *nskb; 289748454079SGustavo F. Padovan struct l2cap_chan *chan; 28980a708f8fSGustavo F. Padovan 28990a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 29000a708f8fSGustavo F. Padovan 29013df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 29023d57dc68SGustavo F. Padovan 29033df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 2904715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW) 29050a708f8fSGustavo F. Padovan continue; 29060a708f8fSGustavo F. Padovan 29077f5396a7SGustavo Padovan /* Don't send frame to the channel it came from */ 2908a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.chan == chan) 29090a708f8fSGustavo F. Padovan continue; 29107f5396a7SGustavo Padovan 29118bcde1f2SGustavo Padovan nskb = skb_clone(skb, GFP_KERNEL); 29120a708f8fSGustavo F. Padovan if (!nskb) 29130a708f8fSGustavo F. Padovan continue; 291480b98027SGustavo Padovan if (chan->ops->recv(chan, nskb)) 29150a708f8fSGustavo F. Padovan kfree_skb(nskb); 29160a708f8fSGustavo F. Padovan } 29173d57dc68SGustavo F. Padovan 29183df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 29190a708f8fSGustavo F. Padovan } 29200a708f8fSGustavo F. Padovan 29210a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */ 2922b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, 2923b4400672SAndrei Emeltchenko u8 ident, u16 dlen, void *data) 29240a708f8fSGustavo F. Padovan { 29250a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag; 29260a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd; 29270a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 29280a708f8fSGustavo F. Padovan int len, count; 29290a708f8fSGustavo F. Padovan 2930b4400672SAndrei Emeltchenko BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u", 29310a708f8fSGustavo F. Padovan conn, code, ident, dlen); 29320a708f8fSGustavo F. Padovan 2933300b962eSAnderson Lizardo if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE) 2934300b962eSAnderson Lizardo return NULL; 2935300b962eSAnderson Lizardo 29360a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; 29370a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 29380a708f8fSGustavo F. Padovan 29398bcde1f2SGustavo Padovan skb = bt_skb_alloc(count, GFP_KERNEL); 29400a708f8fSGustavo F. Padovan if (!skb) 29410a708f8fSGustavo F. Padovan return NULL; 29420a708f8fSGustavo F. Padovan 29434df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 29440a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); 29453300d9a9SClaudio Takahasi 29463300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 2947dcf4adbfSJoe Perches lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING); 29483300d9a9SClaudio Takahasi else 2949dcf4adbfSJoe Perches lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING); 29500a708f8fSGustavo F. Padovan 29514df864c1SJohannes Berg cmd = skb_put(skb, L2CAP_CMD_HDR_SIZE); 29520a708f8fSGustavo F. Padovan cmd->code = code; 29530a708f8fSGustavo F. Padovan cmd->ident = ident; 29540a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen); 29550a708f8fSGustavo F. Padovan 29560a708f8fSGustavo F. Padovan if (dlen) { 29570a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE; 295859ae1d12SJohannes Berg skb_put_data(skb, data, count); 29590a708f8fSGustavo F. Padovan data += count; 29600a708f8fSGustavo F. Padovan } 29610a708f8fSGustavo F. Padovan 29620a708f8fSGustavo F. Padovan len -= skb->len; 29630a708f8fSGustavo F. Padovan 29640a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 29650a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 29660a708f8fSGustavo F. Padovan while (len) { 29670a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 29680a708f8fSGustavo F. Padovan 29698bcde1f2SGustavo Padovan *frag = bt_skb_alloc(count, GFP_KERNEL); 29700a708f8fSGustavo F. Padovan if (!*frag) 29710a708f8fSGustavo F. Padovan goto fail; 29720a708f8fSGustavo F. Padovan 297359ae1d12SJohannes Berg skb_put_data(*frag, data, count); 29740a708f8fSGustavo F. Padovan 29750a708f8fSGustavo F. Padovan len -= count; 29760a708f8fSGustavo F. Padovan data += count; 29770a708f8fSGustavo F. Padovan 29780a708f8fSGustavo F. Padovan frag = &(*frag)->next; 29790a708f8fSGustavo F. Padovan } 29800a708f8fSGustavo F. Padovan 29810a708f8fSGustavo F. Padovan return skb; 29820a708f8fSGustavo F. Padovan 29830a708f8fSGustavo F. Padovan fail: 29840a708f8fSGustavo F. Padovan kfree_skb(skb); 29850a708f8fSGustavo F. Padovan return NULL; 29860a708f8fSGustavo F. Padovan } 29870a708f8fSGustavo F. Padovan 29882d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, 29892d792818SGustavo Padovan unsigned long *val) 29900a708f8fSGustavo F. Padovan { 29910a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 29920a708f8fSGustavo F. Padovan int len; 29930a708f8fSGustavo F. Padovan 29940a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len; 29950a708f8fSGustavo F. Padovan *ptr += len; 29960a708f8fSGustavo F. Padovan 29970a708f8fSGustavo F. Padovan *type = opt->type; 29980a708f8fSGustavo F. Padovan *olen = opt->len; 29990a708f8fSGustavo F. Padovan 30000a708f8fSGustavo F. Padovan switch (opt->len) { 30010a708f8fSGustavo F. Padovan case 1: 30020a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val); 30030a708f8fSGustavo F. Padovan break; 30040a708f8fSGustavo F. Padovan 30050a708f8fSGustavo F. Padovan case 2: 30060a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val); 30070a708f8fSGustavo F. Padovan break; 30080a708f8fSGustavo F. Padovan 30090a708f8fSGustavo F. Padovan case 4: 30100a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val); 30110a708f8fSGustavo F. Padovan break; 30120a708f8fSGustavo F. Padovan 30130a708f8fSGustavo F. Padovan default: 30140a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val; 30150a708f8fSGustavo F. Padovan break; 30160a708f8fSGustavo F. Padovan } 30170a708f8fSGustavo F. Padovan 3018b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val); 30190a708f8fSGustavo F. Padovan return len; 30200a708f8fSGustavo F. Padovan } 30210a708f8fSGustavo F. Padovan 3022e860d2c9SBen Seri static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size) 30230a708f8fSGustavo F. Padovan { 30240a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 30250a708f8fSGustavo F. Padovan 3026b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val); 30270a708f8fSGustavo F. Padovan 3028e860d2c9SBen Seri if (size < L2CAP_CONF_OPT_SIZE + len) 3029e860d2c9SBen Seri return; 3030e860d2c9SBen Seri 30310a708f8fSGustavo F. Padovan opt->type = type; 30320a708f8fSGustavo F. Padovan opt->len = len; 30330a708f8fSGustavo F. Padovan 30340a708f8fSGustavo F. Padovan switch (len) { 30350a708f8fSGustavo F. Padovan case 1: 30360a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val; 30370a708f8fSGustavo F. Padovan break; 30380a708f8fSGustavo F. Padovan 30390a708f8fSGustavo F. Padovan case 2: 30400a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val); 30410a708f8fSGustavo F. Padovan break; 30420a708f8fSGustavo F. Padovan 30430a708f8fSGustavo F. Padovan case 4: 30440a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val); 30450a708f8fSGustavo F. Padovan break; 30460a708f8fSGustavo F. Padovan 30470a708f8fSGustavo F. Padovan default: 30480a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len); 30490a708f8fSGustavo F. Padovan break; 30500a708f8fSGustavo F. Padovan } 30510a708f8fSGustavo F. Padovan 30520a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len; 30530a708f8fSGustavo F. Padovan } 30540a708f8fSGustavo F. Padovan 3055e860d2c9SBen Seri static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan, size_t size) 3056f89cef09SAndrei Emeltchenko { 3057f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs; 3058f89cef09SAndrei Emeltchenko 3059f89cef09SAndrei Emeltchenko switch (chan->mode) { 3060f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM: 3061f89cef09SAndrei Emeltchenko efs.id = chan->local_id; 3062f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype; 3063f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 3064f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 3065dcf4adbfSJoe Perches efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); 3066dcf4adbfSJoe Perches efs.flush_to = cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO); 3067f89cef09SAndrei Emeltchenko break; 3068f89cef09SAndrei Emeltchenko 3069f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING: 3070f89cef09SAndrei Emeltchenko efs.id = 1; 3071f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT; 3072f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 3073f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 3074f89cef09SAndrei Emeltchenko efs.acc_lat = 0; 3075f89cef09SAndrei Emeltchenko efs.flush_to = 0; 3076f89cef09SAndrei Emeltchenko break; 3077f89cef09SAndrei Emeltchenko 3078f89cef09SAndrei Emeltchenko default: 3079f89cef09SAndrei Emeltchenko return; 3080f89cef09SAndrei Emeltchenko } 3081f89cef09SAndrei Emeltchenko 3082f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), 3083e860d2c9SBen Seri (unsigned long) &efs, size); 3084f89cef09SAndrei Emeltchenko } 3085f89cef09SAndrei Emeltchenko 3086721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work) 30870a708f8fSGustavo F. Padovan { 3088721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 3089721c4181SGustavo F. Padovan ack_timer.work); 30900362520bSMat Martineau u16 frames_to_ack; 30910a708f8fSGustavo F. Padovan 30922fb9b3d4SGustavo F. Padovan BT_DBG("chan %p", chan); 30932fb9b3d4SGustavo F. Padovan 30946be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 30956be36555SAndrei Emeltchenko 30960362520bSMat Martineau frames_to_ack = __seq_offset(chan, chan->buffer_seq, 30970362520bSMat Martineau chan->last_acked_seq); 30980362520bSMat Martineau 30990362520bSMat Martineau if (frames_to_ack) 31000362520bSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 31016be36555SAndrei Emeltchenko 31026be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 310309bfb2eeSSzymon Janc l2cap_chan_put(chan); 31040a708f8fSGustavo F. Padovan } 31050a708f8fSGustavo F. Padovan 3106466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan) 31070a708f8fSGustavo F. Padovan { 31083c588192SMat Martineau int err; 31093c588192SMat Martineau 3110105bdf9eSMat Martineau chan->next_tx_seq = 0; 3111105bdf9eSMat Martineau chan->expected_tx_seq = 0; 311242e5c802SGustavo F. Padovan chan->expected_ack_seq = 0; 31136a026610SGustavo F. Padovan chan->unacked_frames = 0; 311442e5c802SGustavo F. Padovan chan->buffer_seq = 0; 31156a026610SGustavo F. Padovan chan->frames_sent = 0; 3116105bdf9eSMat Martineau chan->last_acked_seq = 0; 3117105bdf9eSMat Martineau chan->sdu = NULL; 3118105bdf9eSMat Martineau chan->sdu_last_frag = NULL; 3119105bdf9eSMat Martineau chan->sdu_len = 0; 3120105bdf9eSMat Martineau 3121d34c34fbSMat Martineau skb_queue_head_init(&chan->tx_q); 3122d34c34fbSMat Martineau 31236ed971caSMarcel Holtmann chan->local_amp_id = AMP_ID_BREDR; 31246ed971caSMarcel Holtmann chan->move_id = AMP_ID_BREDR; 312508333283SMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 312608333283SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 312708333283SMat Martineau 3128105bdf9eSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 3129105bdf9eSMat Martineau return 0; 3130105bdf9eSMat Martineau 3131105bdf9eSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 3132105bdf9eSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 31330a708f8fSGustavo F. Padovan 3134721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout); 3135721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout); 3136721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout); 31370a708f8fSGustavo F. Padovan 3138f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q); 31390a708f8fSGustavo F. Padovan 31403c588192SMat Martineau err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win); 31413c588192SMat Martineau if (err < 0) 31423c588192SMat Martineau return err; 31433c588192SMat Martineau 31449dc9affcSMat Martineau err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win); 31459dc9affcSMat Martineau if (err < 0) 31469dc9affcSMat Martineau l2cap_seq_list_free(&chan->srej_list); 31479dc9affcSMat Martineau 31489dc9affcSMat Martineau return err; 31490a708f8fSGustavo F. Padovan } 31500a708f8fSGustavo F. Padovan 31510a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) 31520a708f8fSGustavo F. Padovan { 31530a708f8fSGustavo F. Padovan switch (mode) { 31540a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 31550a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 31560a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask)) 31570a708f8fSGustavo F. Padovan return mode; 31580a708f8fSGustavo F. Padovan /* fall through */ 31590a708f8fSGustavo F. Padovan default: 31600a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC; 31610a708f8fSGustavo F. Padovan } 31620a708f8fSGustavo F. Padovan } 31630a708f8fSGustavo F. Padovan 3164848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn) 31656327eb98SAndrei Emeltchenko { 31660bd49fc7SJohan Hedberg return ((conn->local_fixed_chan & L2CAP_FC_A2MP) && 31670bd49fc7SJohan Hedberg (conn->feat_mask & L2CAP_FEAT_EXT_WINDOW)); 31686327eb98SAndrei Emeltchenko } 31696327eb98SAndrei Emeltchenko 3170848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn) 3171f89cef09SAndrei Emeltchenko { 31720bd49fc7SJohan Hedberg return ((conn->local_fixed_chan & L2CAP_FC_A2MP) && 31730bd49fc7SJohan Hedberg (conn->feat_mask & L2CAP_FEAT_EXT_FLOW)); 3174f89cef09SAndrei Emeltchenko } 3175f89cef09SAndrei Emeltchenko 317636c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan, 317736c86c85SMat Martineau struct l2cap_conf_rfc *rfc) 317836c86c85SMat Martineau { 31796ed971caSMarcel Holtmann if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) { 318036c86c85SMat Martineau u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to; 318136c86c85SMat Martineau 318236c86c85SMat Martineau /* Class 1 devices have must have ERTM timeouts 318336c86c85SMat Martineau * exceeding the Link Supervision Timeout. The 318436c86c85SMat Martineau * default Link Supervision Timeout for AMP 318536c86c85SMat Martineau * controllers is 10 seconds. 318636c86c85SMat Martineau * 318736c86c85SMat Martineau * Class 1 devices use 0xffffffff for their 318836c86c85SMat Martineau * best-effort flush timeout, so the clamping logic 318936c86c85SMat Martineau * will result in a timeout that meets the above 319036c86c85SMat Martineau * requirement. ERTM timeouts are 16-bit values, so 319136c86c85SMat Martineau * the maximum timeout is 65.535 seconds. 319236c86c85SMat Martineau */ 319336c86c85SMat Martineau 319436c86c85SMat Martineau /* Convert timeout to milliseconds and round */ 319536c86c85SMat Martineau ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000); 319636c86c85SMat Martineau 319736c86c85SMat Martineau /* This is the recommended formula for class 2 devices 319836c86c85SMat Martineau * that start ERTM timers when packets are sent to the 319936c86c85SMat Martineau * controller. 320036c86c85SMat Martineau */ 320136c86c85SMat Martineau ertm_to = 3 * ertm_to + 500; 320236c86c85SMat Martineau 320336c86c85SMat Martineau if (ertm_to > 0xffff) 320436c86c85SMat Martineau ertm_to = 0xffff; 320536c86c85SMat Martineau 320636c86c85SMat Martineau rfc->retrans_timeout = cpu_to_le16((u16) ertm_to); 320736c86c85SMat Martineau rfc->monitor_timeout = rfc->retrans_timeout; 320836c86c85SMat Martineau } else { 3209dcf4adbfSJoe Perches rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 3210dcf4adbfSJoe Perches rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 321136c86c85SMat Martineau } 321236c86c85SMat Martineau } 321336c86c85SMat Martineau 32146327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan) 32156327eb98SAndrei Emeltchenko { 32166327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && 3217848566b3SMarcel Holtmann __l2cap_ews_supported(chan->conn)) { 32186327eb98SAndrei Emeltchenko /* use extended control field */ 32196327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 3220836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 3221836be934SAndrei Emeltchenko } else { 32226327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win, 32236327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 3224836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 3225836be934SAndrei Emeltchenko } 3226c20f8e35SMat Martineau chan->ack_win = chan->tx_win; 32276327eb98SAndrei Emeltchenko } 32286327eb98SAndrei Emeltchenko 3229e860d2c9SBen Seri static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size) 32300a708f8fSGustavo F. Padovan { 32310a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 32320c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode }; 32330a708f8fSGustavo F. Padovan void *ptr = req->data; 3234e860d2c9SBen Seri void *endptr = data + data_size; 3235c8f79162SAndrei Emeltchenko u16 size; 32360a708f8fSGustavo F. Padovan 323749208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 32380a708f8fSGustavo F. Padovan 323973ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp) 32400a708f8fSGustavo F. Padovan goto done; 32410a708f8fSGustavo F. Padovan 32420c1bc5c6SGustavo F. Padovan switch (chan->mode) { 32430a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 32440a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3245c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) 32460a708f8fSGustavo F. Padovan break; 32470a708f8fSGustavo F. Padovan 3248848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn)) 3249f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 3250f89cef09SAndrei Emeltchenko 32510a708f8fSGustavo F. Padovan /* fall through */ 32520a708f8fSGustavo F. Padovan default: 32538c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); 32540a708f8fSGustavo F. Padovan break; 32550a708f8fSGustavo F. Padovan } 32560a708f8fSGustavo F. Padovan 32570a708f8fSGustavo F. Padovan done: 32580c1bc5c6SGustavo F. Padovan if (chan->imtu != L2CAP_DEFAULT_MTU) 3259e860d2c9SBen Seri l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, endptr - ptr); 32600a708f8fSGustavo F. Padovan 32610c1bc5c6SGustavo F. Padovan switch (chan->mode) { 32620a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 32636fea7ad1SMarcel Holtmann if (disable_ertm) 32646fea7ad1SMarcel Holtmann break; 32656fea7ad1SMarcel Holtmann 32668c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && 32678c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) 32680a708f8fSGustavo F. Padovan break; 32690a708f8fSGustavo F. Padovan 32700a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC; 32710a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 32720a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 32730a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 32740a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 32750a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0; 32760a708f8fSGustavo F. Padovan 32770a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3278e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr); 32790a708f8fSGustavo F. Padovan break; 32800a708f8fSGustavo F. Padovan 32810a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 32820a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM; 328347d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx; 328436c86c85SMat Martineau 328536c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc); 3286c8f79162SAndrei Emeltchenko 3287c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 32882d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - 3289c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3290c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 32910a708f8fSGustavo F. Padovan 32926327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan); 32936327eb98SAndrei Emeltchenko 32946327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win, 32956327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 32960a708f8fSGustavo F. Padovan 32970a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3298e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr); 32990a708f8fSGustavo F. Padovan 3300f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 3301e860d2c9SBen Seri l2cap_add_opt_efs(&ptr, chan, endptr - ptr); 3302f89cef09SAndrei Emeltchenko 33036327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 33046327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 3305e860d2c9SBen Seri chan->tx_win, endptr - ptr); 330660918918SAndrei Emeltchenko 330760918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS) 330860918918SAndrei Emeltchenko if (chan->fcs == L2CAP_FCS_NONE || 3309f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { 331060918918SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 331160918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, 3312e860d2c9SBen Seri chan->fcs, endptr - ptr); 331360918918SAndrei Emeltchenko } 33140a708f8fSGustavo F. Padovan break; 33150a708f8fSGustavo F. Padovan 33160a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3317273759e2SMat Martineau l2cap_txwin_setup(chan); 33180a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING; 33190a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 33200a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 33210a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 33220a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 3323c8f79162SAndrei Emeltchenko 3324c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 33252d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - 3326c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3327c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 33280a708f8fSGustavo F. Padovan 33290a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3330e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr); 33310a708f8fSGustavo F. Padovan 3332f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 3333e860d2c9SBen Seri l2cap_add_opt_efs(&ptr, chan, endptr - ptr); 3334f89cef09SAndrei Emeltchenko 333560918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS) 333647d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 3337f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { 333847d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 333960918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, 3340e860d2c9SBen Seri chan->fcs, endptr - ptr); 33410a708f8fSGustavo F. Padovan } 33420a708f8fSGustavo F. Padovan break; 33430a708f8fSGustavo F. Padovan } 33440a708f8fSGustavo F. Padovan 3345fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 3346dcf4adbfSJoe Perches req->flags = cpu_to_le16(0); 33470a708f8fSGustavo F. Padovan 33480a708f8fSGustavo F. Padovan return ptr - data; 33490a708f8fSGustavo F. Padovan } 33500a708f8fSGustavo F. Padovan 3351e860d2c9SBen Seri static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data_size) 33520a708f8fSGustavo F. Padovan { 33530a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 33540a708f8fSGustavo F. Padovan void *ptr = rsp->data; 3355e860d2c9SBen Seri void *endptr = data + data_size; 335673ffa904SGustavo F. Padovan void *req = chan->conf_req; 335773ffa904SGustavo F. Padovan int len = chan->conf_len; 33580a708f8fSGustavo F. Padovan int type, hint, olen; 33590a708f8fSGustavo F. Padovan unsigned long val; 33600a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 336142dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs; 336242dceae2SAndrei Emeltchenko u8 remote_efs = 0; 33630a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU; 33640a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS; 3365c8f79162SAndrei Emeltchenko u16 size; 33660a708f8fSGustavo F. Padovan 336773ffa904SGustavo F. Padovan BT_DBG("chan %p", chan); 33680a708f8fSGustavo F. Padovan 33690a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 33700a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val); 33717c9cbd0bSMarcel Holtmann if (len < 0) 33727c9cbd0bSMarcel Holtmann break; 33730a708f8fSGustavo F. Padovan 33740a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT; 33750a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK; 33760a708f8fSGustavo F. Padovan 33770a708f8fSGustavo F. Padovan switch (type) { 33780a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 3379af3d5d1cSMarcel Holtmann if (olen != 2) 3380af3d5d1cSMarcel Holtmann break; 33810a708f8fSGustavo F. Padovan mtu = val; 33820a708f8fSGustavo F. Padovan break; 33830a708f8fSGustavo F. Padovan 33840a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 3385af3d5d1cSMarcel Holtmann if (olen != 2) 3386af3d5d1cSMarcel Holtmann break; 33870c1bc5c6SGustavo F. Padovan chan->flush_to = val; 33880a708f8fSGustavo F. Padovan break; 33890a708f8fSGustavo F. Padovan 33900a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS: 33910a708f8fSGustavo F. Padovan break; 33920a708f8fSGustavo F. Padovan 33930a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 3394af3d5d1cSMarcel Holtmann if (olen != sizeof(rfc)) 3395af3d5d1cSMarcel Holtmann break; 33960a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen); 33970a708f8fSGustavo F. Padovan break; 33980a708f8fSGustavo F. Padovan 33990a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS: 3400af3d5d1cSMarcel Holtmann if (olen != 1) 3401af3d5d1cSMarcel Holtmann break; 34020a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE) 3403f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, &chan->conf_state); 340442dceae2SAndrei Emeltchenko break; 34050a708f8fSGustavo F. Padovan 340642dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS: 3407af3d5d1cSMarcel Holtmann if (olen != sizeof(efs)) 3408af3d5d1cSMarcel Holtmann break; 340942dceae2SAndrei Emeltchenko remote_efs = 1; 341042dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen); 34110a708f8fSGustavo F. Padovan break; 34120a708f8fSGustavo F. Padovan 34136327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 3414af3d5d1cSMarcel Holtmann if (olen != 2) 3415af3d5d1cSMarcel Holtmann break; 34160bd49fc7SJohan Hedberg if (!(chan->conn->local_fixed_chan & L2CAP_FC_A2MP)) 34176327eb98SAndrei Emeltchenko return -ECONNREFUSED; 34186327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 34196327eb98SAndrei Emeltchenko set_bit(CONF_EWS_RECV, &chan->conf_state); 3420836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 34216327eb98SAndrei Emeltchenko chan->remote_tx_win = val; 34220a708f8fSGustavo F. Padovan break; 34230a708f8fSGustavo F. Padovan 34240a708f8fSGustavo F. Padovan default: 34250a708f8fSGustavo F. Padovan if (hint) 34260a708f8fSGustavo F. Padovan break; 34270a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN; 34280a708f8fSGustavo F. Padovan *((u8 *) ptr++) = type; 34290a708f8fSGustavo F. Padovan break; 34300a708f8fSGustavo F. Padovan } 34310a708f8fSGustavo F. Padovan } 34320a708f8fSGustavo F. Padovan 343373ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1) 34340a708f8fSGustavo F. Padovan goto done; 34350a708f8fSGustavo F. Padovan 34360c1bc5c6SGustavo F. Padovan switch (chan->mode) { 34370a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 34380a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3439c1360a1cSGustavo F. Padovan if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { 34400c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, 34418c1d787bSGustavo F. Padovan chan->conn->feat_mask); 34420a708f8fSGustavo F. Padovan break; 34430a708f8fSGustavo F. Padovan } 34440a708f8fSGustavo F. Padovan 344542dceae2SAndrei Emeltchenko if (remote_efs) { 3446848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn)) 344742dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 344842dceae2SAndrei Emeltchenko else 344942dceae2SAndrei Emeltchenko return -ECONNREFUSED; 345042dceae2SAndrei Emeltchenko } 345142dceae2SAndrei Emeltchenko 34520c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) 34530a708f8fSGustavo F. Padovan return -ECONNREFUSED; 34540a708f8fSGustavo F. Padovan 34550a708f8fSGustavo F. Padovan break; 34560a708f8fSGustavo F. Padovan } 34570a708f8fSGustavo F. Padovan 34580a708f8fSGustavo F. Padovan done: 34590c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) { 34600a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 34610c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 34620a708f8fSGustavo F. Padovan 346373ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1) 34640a708f8fSGustavo F. Padovan return -ECONNREFUSED; 34650a708f8fSGustavo F. Padovan 34662d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3467e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr); 34680a708f8fSGustavo F. Padovan } 34690a708f8fSGustavo F. Padovan 34700a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) { 34710a708f8fSGustavo F. Padovan /* Configure output options and let the other side know 34720a708f8fSGustavo F. Padovan * which ones we don't like. */ 34730a708f8fSGustavo F. Padovan 34740a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU) 34750a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 34760a708f8fSGustavo F. Padovan else { 34770c1bc5c6SGustavo F. Padovan chan->omtu = mtu; 3478c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state); 34790a708f8fSGustavo F. Padovan } 3480e860d2c9SBen Seri l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu, endptr - ptr); 34810a708f8fSGustavo F. Padovan 348242dceae2SAndrei Emeltchenko if (remote_efs) { 348342dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 348442dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 348542dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) { 348642dceae2SAndrei Emeltchenko 348742dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT; 348842dceae2SAndrei Emeltchenko 348942dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1) 349042dceae2SAndrei Emeltchenko return -ECONNREFUSED; 349142dceae2SAndrei Emeltchenko 349242dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 349342dceae2SAndrei Emeltchenko sizeof(efs), 3494e860d2c9SBen Seri (unsigned long) &efs, endptr - ptr); 34950e8b207eSAndrei Emeltchenko } else { 34963e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */ 34970e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING; 34980e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 349942dceae2SAndrei Emeltchenko } 350042dceae2SAndrei Emeltchenko } 350142dceae2SAndrei Emeltchenko 35020a708f8fSGustavo F. Padovan switch (rfc.mode) { 35030a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 350447d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3505c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 35060a708f8fSGustavo F. Padovan break; 35070a708f8fSGustavo F. Padovan 35080a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 35096327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state)) 35102c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size; 35116327eb98SAndrei Emeltchenko else 35126327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; 35136327eb98SAndrei Emeltchenko 35142c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit; 35150a708f8fSGustavo F. Padovan 3516c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 35172d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE - 35182d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); 3519c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3520c8f79162SAndrei Emeltchenko chan->remote_mps = size; 35210a708f8fSGustavo F. Padovan 352236c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc); 35230a708f8fSGustavo F. Padovan 3524c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 35250a708f8fSGustavo F. Padovan 35260a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 3527e860d2c9SBen Seri sizeof(rfc), (unsigned long) &rfc, endptr - ptr); 35280a708f8fSGustavo F. Padovan 352942dceae2SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 353042dceae2SAndrei Emeltchenko chan->remote_id = efs.id; 353142dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype; 353242dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu); 353342dceae2SAndrei Emeltchenko chan->remote_flush_to = 353442dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to); 353542dceae2SAndrei Emeltchenko chan->remote_acc_lat = 353642dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat); 353742dceae2SAndrei Emeltchenko chan->remote_sdu_itime = 353842dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 353942dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 35402d792818SGustavo Padovan sizeof(efs), 3541e860d2c9SBen Seri (unsigned long) &efs, endptr - ptr); 354242dceae2SAndrei Emeltchenko } 35430a708f8fSGustavo F. Padovan break; 35440a708f8fSGustavo F. Padovan 35450a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3546c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 35472d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE - 35482d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); 3549c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3550c8f79162SAndrei Emeltchenko chan->remote_mps = size; 35510a708f8fSGustavo F. Padovan 3552c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 35530a708f8fSGustavo F. Padovan 35542d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3555e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr); 35560a708f8fSGustavo F. Padovan 35570a708f8fSGustavo F. Padovan break; 35580a708f8fSGustavo F. Padovan 35590a708f8fSGustavo F. Padovan default: 35600a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 35610a708f8fSGustavo F. Padovan 35620a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc)); 35630c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 35640a708f8fSGustavo F. Padovan } 35650a708f8fSGustavo F. Padovan 35660a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) 3567c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 35680a708f8fSGustavo F. Padovan } 3569fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 35700a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 3571dcf4adbfSJoe Perches rsp->flags = cpu_to_le16(0); 35720a708f8fSGustavo F. Padovan 35730a708f8fSGustavo F. Padovan return ptr - data; 35740a708f8fSGustavo F. Padovan } 35750a708f8fSGustavo F. Padovan 35762d792818SGustavo Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, 3577e860d2c9SBen Seri void *data, size_t size, u16 *result) 35780a708f8fSGustavo F. Padovan { 35790a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 35800a708f8fSGustavo F. Padovan void *ptr = req->data; 3581e860d2c9SBen Seri void *endptr = data + size; 35820a708f8fSGustavo F. Padovan int type, olen; 35830a708f8fSGustavo F. Padovan unsigned long val; 358436e999a8SMat Martineau struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 358566af7aafSAndrei Emeltchenko struct l2cap_conf_efs efs; 35860a708f8fSGustavo F. Padovan 3587fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); 35880a708f8fSGustavo F. Padovan 35890a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 35900a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 35917c9cbd0bSMarcel Holtmann if (len < 0) 35927c9cbd0bSMarcel Holtmann break; 35930a708f8fSGustavo F. Padovan 35940a708f8fSGustavo F. Padovan switch (type) { 35950a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 3596af3d5d1cSMarcel Holtmann if (olen != 2) 3597af3d5d1cSMarcel Holtmann break; 35980a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) { 35990a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT; 36000c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU; 36010a708f8fSGustavo F. Padovan } else 36020c1bc5c6SGustavo F. Padovan chan->imtu = val; 3603af3d5d1cSMarcel Holtmann l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, 3604af3d5d1cSMarcel Holtmann endptr - ptr); 36050a708f8fSGustavo F. Padovan break; 36060a708f8fSGustavo F. Padovan 36070a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 3608af3d5d1cSMarcel Holtmann if (olen != 2) 3609af3d5d1cSMarcel Holtmann break; 36100c1bc5c6SGustavo F. Padovan chan->flush_to = val; 3611af3d5d1cSMarcel Holtmann l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, 3612af3d5d1cSMarcel Holtmann chan->flush_to, endptr - ptr); 36130a708f8fSGustavo F. Padovan break; 36140a708f8fSGustavo F. Padovan 36150a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 3616af3d5d1cSMarcel Holtmann if (olen != sizeof(rfc)) 3617af3d5d1cSMarcel Holtmann break; 36180a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 3619c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && 36200c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode) 36210a708f8fSGustavo F. Padovan return -ECONNREFUSED; 362247d1ec61SGustavo F. Padovan chan->fcs = 0; 3623af3d5d1cSMarcel Holtmann l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3624af3d5d1cSMarcel Holtmann (unsigned long) &rfc, endptr - ptr); 36250a708f8fSGustavo F. Padovan break; 36266327eb98SAndrei Emeltchenko 36276327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 3628af3d5d1cSMarcel Holtmann if (olen != 2) 3629af3d5d1cSMarcel Holtmann break; 3630c20f8e35SMat Martineau chan->ack_win = min_t(u16, val, chan->ack_win); 36313e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 3632e860d2c9SBen Seri chan->tx_win, endptr - ptr); 36336327eb98SAndrei Emeltchenko break; 363466af7aafSAndrei Emeltchenko 363566af7aafSAndrei Emeltchenko case L2CAP_CONF_EFS: 3636af3d5d1cSMarcel Holtmann if (olen != sizeof(efs)) 3637af3d5d1cSMarcel Holtmann break; 363866af7aafSAndrei Emeltchenko memcpy(&efs, (void *)val, olen); 363966af7aafSAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 364066af7aafSAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 364166af7aafSAndrei Emeltchenko efs.stype != chan->local_stype) 364266af7aafSAndrei Emeltchenko return -ECONNREFUSED; 36432d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), 3644e860d2c9SBen Seri (unsigned long) &efs, endptr - ptr); 364566af7aafSAndrei Emeltchenko break; 3646cbabee78SAndrei Emeltchenko 3647cbabee78SAndrei Emeltchenko case L2CAP_CONF_FCS: 3648af3d5d1cSMarcel Holtmann if (olen != 1) 3649af3d5d1cSMarcel Holtmann break; 3650cbabee78SAndrei Emeltchenko if (*result == L2CAP_CONF_PENDING) 3651cbabee78SAndrei Emeltchenko if (val == L2CAP_FCS_NONE) 3652f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, 3653cbabee78SAndrei Emeltchenko &chan->conf_state); 3654cbabee78SAndrei Emeltchenko break; 36550a708f8fSGustavo F. Padovan } 36560a708f8fSGustavo F. Padovan } 36570a708f8fSGustavo F. Padovan 36580c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) 36590a708f8fSGustavo F. Padovan return -ECONNREFUSED; 36600a708f8fSGustavo F. Padovan 36610c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode; 36620a708f8fSGustavo F. Padovan 36630e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) { 36640a708f8fSGustavo F. Padovan switch (rfc.mode) { 36650a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 366647d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 366747d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 366847d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 3669c20f8e35SMat Martineau if (!test_bit(FLAG_EXT_CTRL, &chan->flags)) 3670c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 3671c20f8e35SMat Martineau rfc.txwin_size); 367266af7aafSAndrei Emeltchenko 367366af7aafSAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 367466af7aafSAndrei Emeltchenko chan->local_msdu = le16_to_cpu(efs.msdu); 367566af7aafSAndrei Emeltchenko chan->local_sdu_itime = 367666af7aafSAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 367766af7aafSAndrei Emeltchenko chan->local_acc_lat = le32_to_cpu(efs.acc_lat); 367866af7aafSAndrei Emeltchenko chan->local_flush_to = 367966af7aafSAndrei Emeltchenko le32_to_cpu(efs.flush_to); 368066af7aafSAndrei Emeltchenko } 36810a708f8fSGustavo F. Padovan break; 368266af7aafSAndrei Emeltchenko 36830a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 368447d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 36850a708f8fSGustavo F. Padovan } 36860a708f8fSGustavo F. Padovan } 36870a708f8fSGustavo F. Padovan 3688fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 3689dcf4adbfSJoe Perches req->flags = cpu_to_le16(0); 36900a708f8fSGustavo F. Padovan 36910a708f8fSGustavo F. Padovan return ptr - data; 36920a708f8fSGustavo F. Padovan } 36930a708f8fSGustavo F. Padovan 36942d792818SGustavo Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, 36952d792818SGustavo Padovan u16 result, u16 flags) 36960a708f8fSGustavo F. Padovan { 36970a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 36980a708f8fSGustavo F. Padovan void *ptr = rsp->data; 36990a708f8fSGustavo F. Padovan 3700fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan); 37010a708f8fSGustavo F. Padovan 3702fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 37030a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 37040a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags); 37050a708f8fSGustavo F. Padovan 37060a708f8fSGustavo F. Padovan return ptr - data; 37070a708f8fSGustavo F. Padovan } 37080a708f8fSGustavo F. Padovan 370927e2d4c8SJohan Hedberg void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan) 371027e2d4c8SJohan Hedberg { 371127e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 371227e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn; 371327e2d4c8SJohan Hedberg 371427e2d4c8SJohan Hedberg BT_DBG("chan %p", chan); 371527e2d4c8SJohan Hedberg 371627e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 371727e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 37183916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps); 37190cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits); 3720571f7390SMallikarjun Phulari rsp.result = cpu_to_le16(L2CAP_CR_LE_SUCCESS); 372127e2d4c8SJohan Hedberg 372227e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), 372327e2d4c8SJohan Hedberg &rsp); 372427e2d4c8SJohan Hedberg } 372527e2d4c8SJohan Hedberg 37268c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) 3727710f9b0aSGustavo F. Padovan { 3728710f9b0aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 37298c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 3730710f9b0aSGustavo F. Padovan u8 buf[128]; 3731439f34acSAndrei Emeltchenko u8 rsp_code; 3732710f9b0aSGustavo F. Padovan 3733fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 3734fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3735dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 3736dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 3737439f34acSAndrei Emeltchenko 3738439f34acSAndrei Emeltchenko if (chan->hs_hcon) 3739439f34acSAndrei Emeltchenko rsp_code = L2CAP_CREATE_CHAN_RSP; 3740439f34acSAndrei Emeltchenko else 3741439f34acSAndrei Emeltchenko rsp_code = L2CAP_CONN_RSP; 3742439f34acSAndrei Emeltchenko 3743439f34acSAndrei Emeltchenko BT_DBG("chan %p rsp_code %u", chan, rsp_code); 3744439f34acSAndrei Emeltchenko 3745439f34acSAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp); 3746710f9b0aSGustavo F. Padovan 3747c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 3748710f9b0aSGustavo F. Padovan return; 3749710f9b0aSGustavo F. Padovan 3750710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 3751e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); 3752710f9b0aSGustavo F. Padovan chan->num_conf_req++; 3753710f9b0aSGustavo F. Padovan } 3754710f9b0aSGustavo F. Padovan 375547d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) 37560a708f8fSGustavo F. Padovan { 37570a708f8fSGustavo F. Padovan int type, olen; 37580a708f8fSGustavo F. Padovan unsigned long val; 3759c20f8e35SMat Martineau /* Use sane default values in case a misbehaving remote device 3760c20f8e35SMat Martineau * did not send an RFC or extended window size option. 3761c20f8e35SMat Martineau */ 3762c20f8e35SMat Martineau u16 txwin_ext = chan->ack_win; 3763c20f8e35SMat Martineau struct l2cap_conf_rfc rfc = { 3764c20f8e35SMat Martineau .mode = chan->mode, 3765dcf4adbfSJoe Perches .retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO), 3766dcf4adbfSJoe Perches .monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO), 3767c20f8e35SMat Martineau .max_pdu_size = cpu_to_le16(chan->imtu), 3768c20f8e35SMat Martineau .txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW), 3769c20f8e35SMat Martineau }; 37700a708f8fSGustavo F. Padovan 377147d1ec61SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); 37720a708f8fSGustavo F. Padovan 37730c1bc5c6SGustavo F. Padovan if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) 37740a708f8fSGustavo F. Padovan return; 37750a708f8fSGustavo F. Padovan 37760a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 37770a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 37787c9cbd0bSMarcel Holtmann if (len < 0) 37797c9cbd0bSMarcel Holtmann break; 37800a708f8fSGustavo F. Padovan 3781c20f8e35SMat Martineau switch (type) { 3782c20f8e35SMat Martineau case L2CAP_CONF_RFC: 3783af3d5d1cSMarcel Holtmann if (olen != sizeof(rfc)) 3784af3d5d1cSMarcel Holtmann break; 37850a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 3786c20f8e35SMat Martineau break; 3787c20f8e35SMat Martineau case L2CAP_CONF_EWS: 3788af3d5d1cSMarcel Holtmann if (olen != 2) 3789af3d5d1cSMarcel Holtmann break; 3790c20f8e35SMat Martineau txwin_ext = val; 3791c20f8e35SMat Martineau break; 3792c20f8e35SMat Martineau } 37930a708f8fSGustavo F. Padovan } 37940a708f8fSGustavo F. Padovan 37950a708f8fSGustavo F. Padovan switch (rfc.mode) { 37960a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 379747d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 379847d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 379947d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 3800c20f8e35SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 3801c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, txwin_ext); 3802c20f8e35SMat Martineau else 3803c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 3804c20f8e35SMat Martineau rfc.txwin_size); 38050a708f8fSGustavo F. Padovan break; 38060a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 380747d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 38080a708f8fSGustavo F. Padovan } 38090a708f8fSGustavo F. Padovan } 38100a708f8fSGustavo F. Padovan 38112d792818SGustavo Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, 3812cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 3813cb3b3152SJohan Hedberg u8 *data) 38140a708f8fSGustavo F. Padovan { 3815e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 38160a708f8fSGustavo F. Padovan 3817cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rej)) 3818cb3b3152SJohan Hedberg return -EPROTO; 3819cb3b3152SJohan Hedberg 3820e2fd318eSIlia Kolomisnky if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) 38210a708f8fSGustavo F. Padovan return 0; 38220a708f8fSGustavo F. Padovan 38230a708f8fSGustavo F. Padovan if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && 38240a708f8fSGustavo F. Padovan cmd->ident == conn->info_ident) { 382517cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 38260a708f8fSGustavo F. Padovan 38270a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 38280a708f8fSGustavo F. Padovan conn->info_ident = 0; 38290a708f8fSGustavo F. Padovan 38300a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 38310a708f8fSGustavo F. Padovan } 38320a708f8fSGustavo F. Padovan 38330a708f8fSGustavo F. Padovan return 0; 38340a708f8fSGustavo F. Padovan } 38350a708f8fSGustavo F. Padovan 38361700915fSMat Martineau static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, 38371700915fSMat Martineau struct l2cap_cmd_hdr *cmd, 38384c89b6aaSMat Martineau u8 *data, u8 rsp_code, u8 amp_id) 38390a708f8fSGustavo F. Padovan { 38400a708f8fSGustavo F. Padovan struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 38410a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 384223691d75SGustavo F. Padovan struct l2cap_chan *chan = NULL, *pchan; 38430a708f8fSGustavo F. Padovan int result, status = L2CAP_CS_NO_INFO; 38440a708f8fSGustavo F. Padovan 38450a708f8fSGustavo F. Padovan u16 dcid = 0, scid = __le16_to_cpu(req->scid); 38460a708f8fSGustavo F. Padovan __le16 psm = req->psm; 38470a708f8fSGustavo F. Padovan 3848097db76cSAndrei Emeltchenko BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); 38490a708f8fSGustavo F. Padovan 38500a708f8fSGustavo F. Padovan /* Check if we have socket listening on psm */ 38516f59b904SMarcel Holtmann pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 3852bf20fd4eSJohan Hedberg &conn->hcon->dst, ACL_LINK); 385323691d75SGustavo F. Padovan if (!pchan) { 38540a708f8fSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 38550a708f8fSGustavo F. Padovan goto sendresp; 38560a708f8fSGustavo F. Padovan } 38570a708f8fSGustavo F. Padovan 38583df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 38598ffb9290SGustavo Padovan l2cap_chan_lock(pchan); 38600a708f8fSGustavo F. Padovan 38610a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */ 3862dcf4adbfSJoe Perches if (psm != cpu_to_le16(L2CAP_PSM_SDP) && 38630a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) { 38649f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_AUTH_FAILURE; 38650a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 38660a708f8fSGustavo F. Padovan goto response; 38670a708f8fSGustavo F. Padovan } 38680a708f8fSGustavo F. Padovan 38690a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM; 38700a708f8fSGustavo F. Padovan 3871dd1a8f8aSMallikarjun Phulari /* Check for valid dynamic CID range (as per Erratum 3253) */ 3872dd1a8f8aSMallikarjun Phulari if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_DYN_END) { 3873dd1a8f8aSMallikarjun Phulari result = L2CAP_CR_INVALID_SCID; 38742dfa1003SGustavo Padovan goto response; 3875dd1a8f8aSMallikarjun Phulari } 3876dd1a8f8aSMallikarjun Phulari 3877dd1a8f8aSMallikarjun Phulari /* Check if we already have channel with that dcid */ 3878dd1a8f8aSMallikarjun Phulari if (__l2cap_get_chan_by_dcid(conn, scid)) { 3879dd1a8f8aSMallikarjun Phulari result = L2CAP_CR_SCID_IN_USE; 3880dd1a8f8aSMallikarjun Phulari goto response; 3881dd1a8f8aSMallikarjun Phulari } 38822dfa1003SGustavo Padovan 388380b98027SGustavo Padovan chan = pchan->ops->new_connection(pchan); 388480808e43SGustavo F. Padovan if (!chan) 38850a708f8fSGustavo F. Padovan goto response; 38860a708f8fSGustavo F. Padovan 3887330b6c15SSyam Sidhardhan /* For certain devices (ex: HID mouse), support for authentication, 3888330b6c15SSyam Sidhardhan * pairing and bonding is optional. For such devices, inorder to avoid 3889330b6c15SSyam Sidhardhan * the ACL alive for too long after L2CAP disconnection, reset the ACL 3890330b6c15SSyam Sidhardhan * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect. 3891330b6c15SSyam Sidhardhan */ 3892330b6c15SSyam Sidhardhan conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 3893330b6c15SSyam Sidhardhan 38947eafc59eSMarcel Holtmann bacpy(&chan->src, &conn->hcon->src); 38957eafc59eSMarcel Holtmann bacpy(&chan->dst, &conn->hcon->dst); 3896a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(conn->hcon); 3897a250e048SJohan Hedberg chan->dst_type = bdaddr_dst_type(conn->hcon); 3898fe4128e0SGustavo F. Padovan chan->psm = psm; 3899fe4128e0SGustavo F. Padovan chan->dcid = scid; 39001700915fSMat Martineau chan->local_amp_id = amp_id; 39010a708f8fSGustavo F. Padovan 39026be36555SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 390348454079SGustavo F. Padovan 3904fe4128e0SGustavo F. Padovan dcid = chan->scid; 39050a708f8fSGustavo F. Padovan 39068d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 39070a708f8fSGustavo F. Padovan 3908fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident; 39090a708f8fSGustavo F. Padovan 39100a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { 3911e7cafc45SJohan Hedberg if (l2cap_chan_check_security(chan, false)) { 3912bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 3913f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 39140a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 39150a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND; 39162dc4e510SGustavo Padovan chan->ops->defer(chan); 39170a708f8fSGustavo F. Padovan } else { 39181700915fSMat Martineau /* Force pending result for AMP controllers. 39191700915fSMat Martineau * The connection will succeed after the 39201700915fSMat Martineau * physical link is up. 39211700915fSMat Martineau */ 39226ed971caSMarcel Holtmann if (amp_id == AMP_ID_BREDR) { 3923f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 39240a708f8fSGustavo F. Padovan result = L2CAP_CR_SUCCESS; 39256ed971caSMarcel Holtmann } else { 3926f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 39276ed971caSMarcel Holtmann result = L2CAP_CR_PEND; 39281700915fSMat Martineau } 39290a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 39300a708f8fSGustavo F. Padovan } 39310a708f8fSGustavo F. Padovan } else { 3932f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 39330a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 39340a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND; 39350a708f8fSGustavo F. Padovan } 39360a708f8fSGustavo F. Padovan } else { 3937f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 39380a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 39390a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 39400a708f8fSGustavo F. Padovan } 39410a708f8fSGustavo F. Padovan 39420a708f8fSGustavo F. Padovan response: 39438ffb9290SGustavo Padovan l2cap_chan_unlock(pchan); 39443df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 3945a24cce14SJohan Hedberg l2cap_chan_put(pchan); 39460a708f8fSGustavo F. Padovan 39470a708f8fSGustavo F. Padovan sendresp: 39480a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid); 39490a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid); 39500a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result); 39510a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status); 39524c89b6aaSMat Martineau l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp); 39530a708f8fSGustavo F. Padovan 39540a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { 39550a708f8fSGustavo F. Padovan struct l2cap_info_req info; 3956dcf4adbfSJoe Perches info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 39570a708f8fSGustavo F. Padovan 39580a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 39590a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 39600a708f8fSGustavo F. Padovan 3961ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 39620a708f8fSGustavo F. Padovan 39632d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, 39642d792818SGustavo Padovan sizeof(info), &info); 39650a708f8fSGustavo F. Padovan } 39660a708f8fSGustavo F. Padovan 3967c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && 39680a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) { 39690a708f8fSGustavo F. Padovan u8 buf[128]; 3970c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 39710a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 3972e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); 397373ffa904SGustavo F. Padovan chan->num_conf_req++; 39740a708f8fSGustavo F. Padovan } 39751700915fSMat Martineau 39761700915fSMat Martineau return chan; 39774c89b6aaSMat Martineau } 39780a708f8fSGustavo F. Padovan 39794c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn, 3980cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 39814c89b6aaSMat Martineau { 39827b064edaSJaganath Kanakkassery struct hci_dev *hdev = conn->hcon->hdev; 39837b064edaSJaganath Kanakkassery struct hci_conn *hcon = conn->hcon; 39847b064edaSJaganath Kanakkassery 3985cb3b3152SJohan Hedberg if (cmd_len < sizeof(struct l2cap_conn_req)) 3986cb3b3152SJohan Hedberg return -EPROTO; 3987cb3b3152SJohan Hedberg 39887b064edaSJaganath Kanakkassery hci_dev_lock(hdev); 3989d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_MGMT) && 39907b064edaSJaganath Kanakkassery !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags)) 399148ec92faSAlfonso Acosta mgmt_device_connected(hdev, hcon, 0, NULL, 0); 39927b064edaSJaganath Kanakkassery hci_dev_unlock(hdev); 39937b064edaSJaganath Kanakkassery 3994300229f9SGustavo Padovan l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0); 39950a708f8fSGustavo F. Padovan return 0; 39960a708f8fSGustavo F. Padovan } 39970a708f8fSGustavo F. Padovan 39985909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn, 3999cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4000cb3b3152SJohan Hedberg u8 *data) 40010a708f8fSGustavo F. Padovan { 40020a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; 40030a708f8fSGustavo F. Padovan u16 scid, dcid, result, status; 400448454079SGustavo F. Padovan struct l2cap_chan *chan; 40050a708f8fSGustavo F. Padovan u8 req[128]; 40063df91ea2SAndrei Emeltchenko int err; 40070a708f8fSGustavo F. Padovan 4008cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp)) 4009cb3b3152SJohan Hedberg return -EPROTO; 4010cb3b3152SJohan Hedberg 40110a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 40120a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 40130a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 40140a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status); 40150a708f8fSGustavo F. Padovan 40161b009c98SAndrei Emeltchenko BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", 40171b009c98SAndrei Emeltchenko dcid, scid, result, status); 40180a708f8fSGustavo F. Padovan 40193df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 40203df91ea2SAndrei Emeltchenko 40210a708f8fSGustavo F. Padovan if (scid) { 40223df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 40233df91ea2SAndrei Emeltchenko if (!chan) { 402421870b52SJohan Hedberg err = -EBADSLT; 40253df91ea2SAndrei Emeltchenko goto unlock; 40263df91ea2SAndrei Emeltchenko } 40270a708f8fSGustavo F. Padovan } else { 40283df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 40293df91ea2SAndrei Emeltchenko if (!chan) { 403021870b52SJohan Hedberg err = -EBADSLT; 40313df91ea2SAndrei Emeltchenko goto unlock; 40323df91ea2SAndrei Emeltchenko } 40330a708f8fSGustavo F. Padovan } 40340a708f8fSGustavo F. Padovan 40353df91ea2SAndrei Emeltchenko err = 0; 40363df91ea2SAndrei Emeltchenko 40376be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 403848454079SGustavo F. Padovan 40390a708f8fSGustavo F. Padovan switch (result) { 40400a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS: 404189bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 4042fc7f8a7eSGustavo F. Padovan chan->ident = 0; 4043fe4128e0SGustavo F. Padovan chan->dcid = dcid; 4044c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state); 40450a708f8fSGustavo F. Padovan 4046c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 40470a708f8fSGustavo F. Padovan break; 40480a708f8fSGustavo F. Padovan 40490a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 4050e860d2c9SBen Seri l2cap_build_conf_req(chan, req, sizeof(req)), req); 405173ffa904SGustavo F. Padovan chan->num_conf_req++; 40520a708f8fSGustavo F. Padovan break; 40530a708f8fSGustavo F. Padovan 40540a708f8fSGustavo F. Padovan case L2CAP_CR_PEND: 4055c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 40560a708f8fSGustavo F. Padovan break; 40570a708f8fSGustavo F. Padovan 40580a708f8fSGustavo F. Padovan default: 405948454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED); 40600a708f8fSGustavo F. Padovan break; 40610a708f8fSGustavo F. Padovan } 40620a708f8fSGustavo F. Padovan 40636be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 40643df91ea2SAndrei Emeltchenko 40653df91ea2SAndrei Emeltchenko unlock: 40663df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 40673df91ea2SAndrei Emeltchenko 40683df91ea2SAndrei Emeltchenko return err; 40690a708f8fSGustavo F. Padovan } 40700a708f8fSGustavo F. Padovan 407147d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan) 40720a708f8fSGustavo F. Padovan { 40730a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both 40740a708f8fSGustavo F. Padovan * sides request it. 40750a708f8fSGustavo F. Padovan */ 40760c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) 407747d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 4078f2592d3eSAndrei Emeltchenko else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) 407947d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16; 40800a708f8fSGustavo F. Padovan } 40810a708f8fSGustavo F. Padovan 408229d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data, 408329d8a590SAndrei Emeltchenko u8 ident, u16 flags) 408429d8a590SAndrei Emeltchenko { 408529d8a590SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 408629d8a590SAndrei Emeltchenko 408729d8a590SAndrei Emeltchenko BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident, 408829d8a590SAndrei Emeltchenko flags); 408929d8a590SAndrei Emeltchenko 409029d8a590SAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 409129d8a590SAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 409229d8a590SAndrei Emeltchenko 409329d8a590SAndrei Emeltchenko l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP, 409429d8a590SAndrei Emeltchenko l2cap_build_conf_rsp(chan, data, 409529d8a590SAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), data); 409629d8a590SAndrei Emeltchenko } 409729d8a590SAndrei Emeltchenko 4098662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident, 4099662d652dSJohan Hedberg u16 scid, u16 dcid) 4100662d652dSJohan Hedberg { 4101662d652dSJohan Hedberg struct l2cap_cmd_rej_cid rej; 4102662d652dSJohan Hedberg 4103dcf4adbfSJoe Perches rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID); 4104662d652dSJohan Hedberg rej.scid = __cpu_to_le16(scid); 4105662d652dSJohan Hedberg rej.dcid = __cpu_to_le16(dcid); 4106662d652dSJohan Hedberg 4107662d652dSJohan Hedberg l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); 4108662d652dSJohan Hedberg } 4109662d652dSJohan Hedberg 41102d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, 41112d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len, 41122d792818SGustavo Padovan u8 *data) 41130a708f8fSGustavo F. Padovan { 41140a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; 41150a708f8fSGustavo F. Padovan u16 dcid, flags; 41160a708f8fSGustavo F. Padovan u8 rsp[64]; 411748454079SGustavo F. Padovan struct l2cap_chan *chan; 41183c588192SMat Martineau int len, err = 0; 41190a708f8fSGustavo F. Padovan 4120cb3b3152SJohan Hedberg if (cmd_len < sizeof(*req)) 4121cb3b3152SJohan Hedberg return -EPROTO; 4122cb3b3152SJohan Hedberg 41230a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 41240a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags); 41250a708f8fSGustavo F. Padovan 41260a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); 41270a708f8fSGustavo F. Padovan 4128baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid); 4129662d652dSJohan Hedberg if (!chan) { 4130662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0); 4131662d652dSJohan Hedberg return 0; 4132662d652dSJohan Hedberg } 41330a708f8fSGustavo F. Padovan 4134033b1142SDavid S. Miller if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { 4135662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, 4136662d652dSJohan Hedberg chan->dcid); 41370a708f8fSGustavo F. Padovan goto unlock; 41380a708f8fSGustavo F. Padovan } 41390a708f8fSGustavo F. Padovan 41400a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */ 41410a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req); 4142cb3b3152SJohan Hedberg if (chan->conf_len + len > sizeof(chan->conf_req)) { 41430a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 4144fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 41450a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp); 41460a708f8fSGustavo F. Padovan goto unlock; 41470a708f8fSGustavo F. Padovan } 41480a708f8fSGustavo F. Padovan 41490a708f8fSGustavo F. Padovan /* Store config. */ 415073ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len); 415173ffa904SGustavo F. Padovan chan->conf_len += len; 41520a708f8fSGustavo F. Padovan 415359e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) { 41540a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */ 41550a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 4156fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 41575325e5bbSAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), rsp); 41580a708f8fSGustavo F. Padovan goto unlock; 41590a708f8fSGustavo F. Padovan } 41600a708f8fSGustavo F. Padovan 41610a708f8fSGustavo F. Padovan /* Complete config. */ 4162e860d2c9SBen Seri len = l2cap_parse_conf_req(chan, rsp, sizeof(rsp)); 41630a708f8fSGustavo F. Padovan if (len < 0) { 41645e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 41650a708f8fSGustavo F. Padovan goto unlock; 41660a708f8fSGustavo F. Padovan } 41670a708f8fSGustavo F. Padovan 41681500109bSMat Martineau chan->ident = cmd->ident; 41690a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); 417073ffa904SGustavo F. Padovan chan->num_conf_rsp++; 41710a708f8fSGustavo F. Padovan 41720a708f8fSGustavo F. Padovan /* Reset config buffer. */ 417373ffa904SGustavo F. Padovan chan->conf_len = 0; 41740a708f8fSGustavo F. Padovan 4175c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) 41760a708f8fSGustavo F. Padovan goto unlock; 41770a708f8fSGustavo F. Padovan 4178c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 417947d1ec61SGustavo F. Padovan set_default_fcs(chan); 41800a708f8fSGustavo F. Padovan 4181105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 4182105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 41833c588192SMat Martineau err = l2cap_ertm_init(chan); 41840a708f8fSGustavo F. Padovan 41853c588192SMat Martineau if (err < 0) 41865e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 41873c588192SMat Martineau else 4188cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 41893c588192SMat Martineau 41900a708f8fSGustavo F. Padovan goto unlock; 41910a708f8fSGustavo F. Padovan } 41920a708f8fSGustavo F. Padovan 4193c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { 41940a708f8fSGustavo F. Padovan u8 buf[64]; 41950a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 4196e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); 419773ffa904SGustavo F. Padovan chan->num_conf_req++; 41980a708f8fSGustavo F. Padovan } 41990a708f8fSGustavo F. Padovan 420049c922bbSStephen Hemminger /* Got Conf Rsp PENDING from remote side and assume we sent 42010e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */ 42020e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && 42030e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 42040e8b207eSAndrei Emeltchenko 42050e8b207eSAndrei Emeltchenko /* check compatibility */ 42060e8b207eSAndrei Emeltchenko 420779de886dSAndrei Emeltchenko /* Send rsp for BR/EDR channel */ 4208f351bc72SAndrei Emeltchenko if (!chan->hs_hcon) 420929d8a590SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags); 421079de886dSAndrei Emeltchenko else 421179de886dSAndrei Emeltchenko chan->ident = cmd->ident; 42120e8b207eSAndrei Emeltchenko } 42130e8b207eSAndrei Emeltchenko 42140a708f8fSGustavo F. Padovan unlock: 42156be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 42163c588192SMat Martineau return err; 42170a708f8fSGustavo F. Padovan } 42180a708f8fSGustavo F. Padovan 42192d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, 4220cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4221cb3b3152SJohan Hedberg u8 *data) 42220a708f8fSGustavo F. Padovan { 42230a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; 42240a708f8fSGustavo F. Padovan u16 scid, flags, result; 422548454079SGustavo F. Padovan struct l2cap_chan *chan; 4226cb3b3152SJohan Hedberg int len = cmd_len - sizeof(*rsp); 42273c588192SMat Martineau int err = 0; 42280a708f8fSGustavo F. Padovan 4229cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp)) 4230cb3b3152SJohan Hedberg return -EPROTO; 4231cb3b3152SJohan Hedberg 42320a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 42330a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags); 42340a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 42350a708f8fSGustavo F. Padovan 423661386cbaSAndrei Emeltchenko BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags, 423761386cbaSAndrei Emeltchenko result, len); 42380a708f8fSGustavo F. Padovan 4239baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 424048454079SGustavo F. Padovan if (!chan) 42410a708f8fSGustavo F. Padovan return 0; 42420a708f8fSGustavo F. Padovan 42430a708f8fSGustavo F. Padovan switch (result) { 42440a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS: 424547d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len); 42460e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state); 42470a708f8fSGustavo F. Padovan break; 42480a708f8fSGustavo F. Padovan 42490e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING: 42500e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state); 42510e8b207eSAndrei Emeltchenko 42520e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 42530e8b207eSAndrei Emeltchenko char buf[64]; 42540e8b207eSAndrei Emeltchenko 42550e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len, 4256e860d2c9SBen Seri buf, sizeof(buf), &result); 42570e8b207eSAndrei Emeltchenko if (len < 0) { 42585e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 42590e8b207eSAndrei Emeltchenko goto done; 42600e8b207eSAndrei Emeltchenko } 42610e8b207eSAndrei Emeltchenko 4262f351bc72SAndrei Emeltchenko if (!chan->hs_hcon) { 426379de886dSAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, buf, cmd->ident, 426479de886dSAndrei Emeltchenko 0); 42655ce66b59SAndrei Emeltchenko } else { 42665ce66b59SAndrei Emeltchenko if (l2cap_check_efs(chan)) { 42675ce66b59SAndrei Emeltchenko amp_create_logical_link(chan); 426879de886dSAndrei Emeltchenko chan->ident = cmd->ident; 42690e8b207eSAndrei Emeltchenko } 42705ce66b59SAndrei Emeltchenko } 42715ce66b59SAndrei Emeltchenko } 42720e8b207eSAndrei Emeltchenko goto done; 42730e8b207eSAndrei Emeltchenko 42740a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT: 427573ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { 42760a708f8fSGustavo F. Padovan char req[64]; 42770a708f8fSGustavo F. Padovan 42780a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { 42795e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 42800a708f8fSGustavo F. Padovan goto done; 42810a708f8fSGustavo F. Padovan } 42820a708f8fSGustavo F. Padovan 42830a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */ 42840a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS; 4285b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len, 4286e860d2c9SBen Seri req, sizeof(req), &result); 42870a708f8fSGustavo F. Padovan if (len < 0) { 42885e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 42890a708f8fSGustavo F. Padovan goto done; 42900a708f8fSGustavo F. Padovan } 42910a708f8fSGustavo F. Padovan 42920a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 42930a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req); 429473ffa904SGustavo F. Padovan chan->num_conf_req++; 42950a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS) 42960a708f8fSGustavo F. Padovan goto done; 42970a708f8fSGustavo F. Padovan break; 42980a708f8fSGustavo F. Padovan } 42996317950cSGustavo A. R. Silva /* fall through */ 43000a708f8fSGustavo F. Padovan 43010a708f8fSGustavo F. Padovan default: 43026be36555SAndrei Emeltchenko l2cap_chan_set_err(chan, ECONNRESET); 43032e0052e4SAndrei Emeltchenko 4304ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); 43055e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 43060a708f8fSGustavo F. Padovan goto done; 43070a708f8fSGustavo F. Padovan } 43080a708f8fSGustavo F. Padovan 430959e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) 43100a708f8fSGustavo F. Padovan goto done; 43110a708f8fSGustavo F. Padovan 4312c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state); 43130a708f8fSGustavo F. Padovan 4314c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { 431547d1ec61SGustavo F. Padovan set_default_fcs(chan); 43160a708f8fSGustavo F. Padovan 4317105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 4318105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 43193c588192SMat Martineau err = l2cap_ertm_init(chan); 43200a708f8fSGustavo F. Padovan 43213c588192SMat Martineau if (err < 0) 43225e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 43233c588192SMat Martineau else 4324cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 43250a708f8fSGustavo F. Padovan } 43260a708f8fSGustavo F. Padovan 43270a708f8fSGustavo F. Padovan done: 43286be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 43293c588192SMat Martineau return err; 43300a708f8fSGustavo F. Padovan } 43310a708f8fSGustavo F. Padovan 43322d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, 4333cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4334cb3b3152SJohan Hedberg u8 *data) 43350a708f8fSGustavo F. Padovan { 43360a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; 43370a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp; 43380a708f8fSGustavo F. Padovan u16 dcid, scid; 433948454079SGustavo F. Padovan struct l2cap_chan *chan; 43400a708f8fSGustavo F. Padovan 4341cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req)) 4342cb3b3152SJohan Hedberg return -EPROTO; 4343cb3b3152SJohan Hedberg 43440a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid); 43450a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 43460a708f8fSGustavo F. Padovan 43470a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); 43480a708f8fSGustavo F. Padovan 43493df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 43503df91ea2SAndrei Emeltchenko 43513df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, dcid); 43523df91ea2SAndrei Emeltchenko if (!chan) { 43533df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4354662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid); 4355662d652dSJohan Hedberg return 0; 43563df91ea2SAndrei Emeltchenko } 43570a708f8fSGustavo F. Padovan 43586be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 43596be36555SAndrei Emeltchenko 4360fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 4361fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 43620a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); 43630a708f8fSGustavo F. Padovan 43645ec1bbe5SGustavo Padovan chan->ops->set_shutdown(chan); 43650a708f8fSGustavo F. Padovan 436661d6ef3eSMat Martineau l2cap_chan_hold(chan); 436748454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET); 43686be36555SAndrei Emeltchenko 43696be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 43700a708f8fSGustavo F. Padovan 437180b98027SGustavo Padovan chan->ops->close(chan); 437261d6ef3eSMat Martineau l2cap_chan_put(chan); 43733df91ea2SAndrei Emeltchenko 43743df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 43753df91ea2SAndrei Emeltchenko 43760a708f8fSGustavo F. Padovan return 0; 43770a708f8fSGustavo F. Padovan } 43780a708f8fSGustavo F. Padovan 43792d792818SGustavo Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, 4380cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4381cb3b3152SJohan Hedberg u8 *data) 43820a708f8fSGustavo F. Padovan { 43830a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; 43840a708f8fSGustavo F. Padovan u16 dcid, scid; 438548454079SGustavo F. Padovan struct l2cap_chan *chan; 43860a708f8fSGustavo F. Padovan 4387cb3b3152SJohan Hedberg if (cmd_len != sizeof(*rsp)) 4388cb3b3152SJohan Hedberg return -EPROTO; 4389cb3b3152SJohan Hedberg 43900a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 43910a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 43920a708f8fSGustavo F. Padovan 43930a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); 43940a708f8fSGustavo F. Padovan 43953df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 43963df91ea2SAndrei Emeltchenko 43973df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 43983df91ea2SAndrei Emeltchenko if (!chan) { 43993df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 44000a708f8fSGustavo F. Padovan return 0; 44013df91ea2SAndrei Emeltchenko } 44020a708f8fSGustavo F. Padovan 44036be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 440448454079SGustavo F. Padovan 440528261da8SMatias Karhumaa if (chan->state != BT_DISCONN) { 440628261da8SMatias Karhumaa l2cap_chan_unlock(chan); 440728261da8SMatias Karhumaa mutex_unlock(&conn->chan_lock); 440828261da8SMatias Karhumaa return 0; 440928261da8SMatias Karhumaa } 441028261da8SMatias Karhumaa 441161d6ef3eSMat Martineau l2cap_chan_hold(chan); 441248454079SGustavo F. Padovan l2cap_chan_del(chan, 0); 44136be36555SAndrei Emeltchenko 44146be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 44150a708f8fSGustavo F. Padovan 441680b98027SGustavo Padovan chan->ops->close(chan); 441761d6ef3eSMat Martineau l2cap_chan_put(chan); 44183df91ea2SAndrei Emeltchenko 44193df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 44203df91ea2SAndrei Emeltchenko 44210a708f8fSGustavo F. Padovan return 0; 44220a708f8fSGustavo F. Padovan } 44230a708f8fSGustavo F. Padovan 44242d792818SGustavo Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, 4425cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4426cb3b3152SJohan Hedberg u8 *data) 44270a708f8fSGustavo F. Padovan { 44280a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data; 44290a708f8fSGustavo F. Padovan u16 type; 44300a708f8fSGustavo F. Padovan 4431cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req)) 4432cb3b3152SJohan Hedberg return -EPROTO; 4433cb3b3152SJohan Hedberg 44340a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type); 44350a708f8fSGustavo F. Padovan 44360a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type); 44370a708f8fSGustavo F. Padovan 44380a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) { 44390a708f8fSGustavo F. Padovan u8 buf[8]; 44400a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask; 44410a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 4442dcf4adbfSJoe Perches rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 4443dcf4adbfSJoe Perches rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 44440a708f8fSGustavo F. Padovan if (!disable_ertm) 44450a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING 44460a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS; 44470bd49fc7SJohan Hedberg if (conn->local_fixed_chan & L2CAP_FC_A2MP) 44486327eb98SAndrei Emeltchenko feat_mask |= L2CAP_FEAT_EXT_FLOW 44496327eb98SAndrei Emeltchenko | L2CAP_FEAT_EXT_WINDOW; 4450a5fd6f30SAndrei Emeltchenko 44510a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data); 44522d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), 44532d792818SGustavo Padovan buf); 44540a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) { 44550a708f8fSGustavo F. Padovan u8 buf[12]; 44560a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 445750a147cdSMat Martineau 4458dcf4adbfSJoe Perches rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 4459dcf4adbfSJoe Perches rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 44600bd49fc7SJohan Hedberg rsp->data[0] = conn->local_fixed_chan; 44610bd49fc7SJohan Hedberg memset(rsp->data + 1, 0, 7); 44622d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), 44632d792818SGustavo Padovan buf); 44640a708f8fSGustavo F. Padovan } else { 44650a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp; 44660a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type); 4467dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP); 44682d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), 44692d792818SGustavo Padovan &rsp); 44700a708f8fSGustavo F. Padovan } 44710a708f8fSGustavo F. Padovan 44720a708f8fSGustavo F. Padovan return 0; 44730a708f8fSGustavo F. Padovan } 44740a708f8fSGustavo F. Padovan 44752d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, 4476cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4477cb3b3152SJohan Hedberg u8 *data) 44780a708f8fSGustavo F. Padovan { 44790a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; 44800a708f8fSGustavo F. Padovan u16 type, result; 44810a708f8fSGustavo F. Padovan 44823f6fa3d4SJaganath Kanakkassery if (cmd_len < sizeof(*rsp)) 4483cb3b3152SJohan Hedberg return -EPROTO; 4484cb3b3152SJohan Hedberg 44850a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type); 44860a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 44870a708f8fSGustavo F. Padovan 44880a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); 44890a708f8fSGustavo F. Padovan 4490e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */ 4491e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident || 4492e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 4493e90165beSAndrei Emeltchenko return 0; 4494e90165beSAndrei Emeltchenko 449517cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 44960a708f8fSGustavo F. Padovan 44970a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) { 44980a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 44990a708f8fSGustavo F. Padovan conn->info_ident = 0; 45000a708f8fSGustavo F. Padovan 45010a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 45020a708f8fSGustavo F. Padovan 45030a708f8fSGustavo F. Padovan return 0; 45040a708f8fSGustavo F. Padovan } 45050a708f8fSGustavo F. Padovan 4506978c93b9SAndrei Emeltchenko switch (type) { 4507978c93b9SAndrei Emeltchenko case L2CAP_IT_FEAT_MASK: 45080a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data); 45090a708f8fSGustavo F. Padovan 45100a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { 45110a708f8fSGustavo F. Padovan struct l2cap_info_req req; 4512dcf4adbfSJoe Perches req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 45130a708f8fSGustavo F. Padovan 45140a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 45150a708f8fSGustavo F. Padovan 45160a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 45170a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 45180a708f8fSGustavo F. Padovan } else { 45190a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 45200a708f8fSGustavo F. Padovan conn->info_ident = 0; 45210a708f8fSGustavo F. Padovan 45220a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 45230a708f8fSGustavo F. Padovan } 4524978c93b9SAndrei Emeltchenko break; 4525978c93b9SAndrei Emeltchenko 4526978c93b9SAndrei Emeltchenko case L2CAP_IT_FIXED_CHAN: 45270bd49fc7SJohan Hedberg conn->remote_fixed_chan = rsp->data[0]; 45280a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 45290a708f8fSGustavo F. Padovan conn->info_ident = 0; 45300a708f8fSGustavo F. Padovan 45310a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 4532978c93b9SAndrei Emeltchenko break; 45330a708f8fSGustavo F. Padovan } 45340a708f8fSGustavo F. Padovan 45350a708f8fSGustavo F. Padovan return 0; 45360a708f8fSGustavo F. Padovan } 45370a708f8fSGustavo F. Padovan 45381700915fSMat Martineau static int l2cap_create_channel_req(struct l2cap_conn *conn, 45392d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, 45402d792818SGustavo Padovan u16 cmd_len, void *data) 4541f94ff6ffSMat Martineau { 4542f94ff6ffSMat Martineau struct l2cap_create_chan_req *req = data; 45436e1df6a6SAndrei Emeltchenko struct l2cap_create_chan_rsp rsp; 45441700915fSMat Martineau struct l2cap_chan *chan; 45456e1df6a6SAndrei Emeltchenko struct hci_dev *hdev; 4546f94ff6ffSMat Martineau u16 psm, scid; 4547f94ff6ffSMat Martineau 4548f94ff6ffSMat Martineau if (cmd_len != sizeof(*req)) 4549f94ff6ffSMat Martineau return -EPROTO; 4550f94ff6ffSMat Martineau 45510bd49fc7SJohan Hedberg if (!(conn->local_fixed_chan & L2CAP_FC_A2MP)) 4552f94ff6ffSMat Martineau return -EINVAL; 4553f94ff6ffSMat Martineau 4554f94ff6ffSMat Martineau psm = le16_to_cpu(req->psm); 4555f94ff6ffSMat Martineau scid = le16_to_cpu(req->scid); 4556f94ff6ffSMat Martineau 4557ad0ac6caSAndrei Emeltchenko BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id); 4558f94ff6ffSMat Martineau 45596e1df6a6SAndrei Emeltchenko /* For controller id 0 make BR/EDR connection */ 45606ed971caSMarcel Holtmann if (req->amp_id == AMP_ID_BREDR) { 45616e1df6a6SAndrei Emeltchenko l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, 45626e1df6a6SAndrei Emeltchenko req->amp_id); 45636e1df6a6SAndrei Emeltchenko return 0; 45646e1df6a6SAndrei Emeltchenko } 45651700915fSMat Martineau 45661700915fSMat Martineau /* Validate AMP controller id */ 45671700915fSMat Martineau hdev = hci_dev_get(req->amp_id); 45686e1df6a6SAndrei Emeltchenko if (!hdev) 45696e1df6a6SAndrei Emeltchenko goto error; 45701700915fSMat Martineau 45716e1df6a6SAndrei Emeltchenko if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) { 45726e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 45736e1df6a6SAndrei Emeltchenko goto error; 45746e1df6a6SAndrei Emeltchenko } 45756e1df6a6SAndrei Emeltchenko 45766e1df6a6SAndrei Emeltchenko chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, 45776e1df6a6SAndrei Emeltchenko req->amp_id); 45786e1df6a6SAndrei Emeltchenko if (chan) { 45796e1df6a6SAndrei Emeltchenko struct amp_mgr *mgr = conn->hcon->amp_mgr; 45806e1df6a6SAndrei Emeltchenko struct hci_conn *hs_hcon; 45816e1df6a6SAndrei Emeltchenko 458298e0f7eaSMarcel Holtmann hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, 458398e0f7eaSMarcel Holtmann &conn->hcon->dst); 45846e1df6a6SAndrei Emeltchenko if (!hs_hcon) { 45856e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 4586662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, 4587662d652dSJohan Hedberg chan->dcid); 4588662d652dSJohan Hedberg return 0; 45896e1df6a6SAndrei Emeltchenko } 45906e1df6a6SAndrei Emeltchenko 45916e1df6a6SAndrei Emeltchenko BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon); 45926e1df6a6SAndrei Emeltchenko 45936e1df6a6SAndrei Emeltchenko mgr->bredr_chan = chan; 45946e1df6a6SAndrei Emeltchenko chan->hs_hcon = hs_hcon; 4595fd45bf4cSAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 45966e1df6a6SAndrei Emeltchenko conn->mtu = hdev->block_mtu; 45976e1df6a6SAndrei Emeltchenko } 45986e1df6a6SAndrei Emeltchenko 45996e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 46006e1df6a6SAndrei Emeltchenko 46016e1df6a6SAndrei Emeltchenko return 0; 46026e1df6a6SAndrei Emeltchenko 46036e1df6a6SAndrei Emeltchenko error: 4604f94ff6ffSMat Martineau rsp.dcid = 0; 4605f94ff6ffSMat Martineau rsp.scid = cpu_to_le16(scid); 4606dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_BAD_AMP); 4607dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 4608f94ff6ffSMat Martineau 4609f94ff6ffSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, 4610f94ff6ffSMat Martineau sizeof(rsp), &rsp); 4611f94ff6ffSMat Martineau 4612dc280801SJohan Hedberg return 0; 4613f94ff6ffSMat Martineau } 4614f94ff6ffSMat Martineau 46158eb200bdSMat Martineau static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id) 46168eb200bdSMat Martineau { 46178eb200bdSMat Martineau struct l2cap_move_chan_req req; 46188eb200bdSMat Martineau u8 ident; 46198eb200bdSMat Martineau 46208eb200bdSMat Martineau BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id); 46218eb200bdSMat Martineau 46228eb200bdSMat Martineau ident = l2cap_get_ident(chan->conn); 46238eb200bdSMat Martineau chan->ident = ident; 46248eb200bdSMat Martineau 46258eb200bdSMat Martineau req.icid = cpu_to_le16(chan->scid); 46268eb200bdSMat Martineau req.dest_amp_id = dest_amp_id; 46278eb200bdSMat Martineau 46288eb200bdSMat Martineau l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req), 46298eb200bdSMat Martineau &req); 46308eb200bdSMat Martineau 46318eb200bdSMat Martineau __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); 46328eb200bdSMat Martineau } 46338eb200bdSMat Martineau 46341500109bSMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result) 46358d5a04a1SMat Martineau { 46368d5a04a1SMat Martineau struct l2cap_move_chan_rsp rsp; 46378d5a04a1SMat Martineau 46381500109bSMat Martineau BT_DBG("chan %p, result 0x%4.4x", chan, result); 46398d5a04a1SMat Martineau 46401500109bSMat Martineau rsp.icid = cpu_to_le16(chan->dcid); 46418d5a04a1SMat Martineau rsp.result = cpu_to_le16(result); 46428d5a04a1SMat Martineau 46431500109bSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP, 46441500109bSMat Martineau sizeof(rsp), &rsp); 46458d5a04a1SMat Martineau } 46468d5a04a1SMat Martineau 46475b155ef9SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result) 46488d5a04a1SMat Martineau { 46498d5a04a1SMat Martineau struct l2cap_move_chan_cfm cfm; 46508d5a04a1SMat Martineau 46515b155ef9SMat Martineau BT_DBG("chan %p, result 0x%4.4x", chan, result); 46528d5a04a1SMat Martineau 46535b155ef9SMat Martineau chan->ident = l2cap_get_ident(chan->conn); 46548d5a04a1SMat Martineau 46555b155ef9SMat Martineau cfm.icid = cpu_to_le16(chan->scid); 46568d5a04a1SMat Martineau cfm.result = cpu_to_le16(result); 46578d5a04a1SMat Martineau 46585b155ef9SMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM, 46595b155ef9SMat Martineau sizeof(cfm), &cfm); 46605b155ef9SMat Martineau 46615b155ef9SMat Martineau __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); 46625b155ef9SMat Martineau } 46635b155ef9SMat Martineau 46645b155ef9SMat Martineau static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid) 46655b155ef9SMat Martineau { 46665b155ef9SMat Martineau struct l2cap_move_chan_cfm cfm; 46675b155ef9SMat Martineau 46685b155ef9SMat Martineau BT_DBG("conn %p, icid 0x%4.4x", conn, icid); 46695b155ef9SMat Martineau 46705b155ef9SMat Martineau cfm.icid = cpu_to_le16(icid); 4671dcf4adbfSJoe Perches cfm.result = cpu_to_le16(L2CAP_MC_UNCONFIRMED); 46725b155ef9SMat Martineau 46735b155ef9SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM, 46745b155ef9SMat Martineau sizeof(cfm), &cfm); 46758d5a04a1SMat Martineau } 46768d5a04a1SMat Martineau 46778d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, 46788d5a04a1SMat Martineau u16 icid) 46798d5a04a1SMat Martineau { 46808d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp rsp; 46818d5a04a1SMat Martineau 4682ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 46838d5a04a1SMat Martineau 46848d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 46858d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp); 46868d5a04a1SMat Martineau } 46878d5a04a1SMat Martineau 46885f3847a4SMat Martineau static void __release_logical_link(struct l2cap_chan *chan) 46895f3847a4SMat Martineau { 46905f3847a4SMat Martineau chan->hs_hchan = NULL; 46915f3847a4SMat Martineau chan->hs_hcon = NULL; 46925f3847a4SMat Martineau 46935f3847a4SMat Martineau /* Placeholder - release the logical link */ 46945f3847a4SMat Martineau } 46955f3847a4SMat Martineau 46961500109bSMat Martineau static void l2cap_logical_fail(struct l2cap_chan *chan) 46971500109bSMat Martineau { 46981500109bSMat Martineau /* Logical link setup failed */ 46991500109bSMat Martineau if (chan->state != BT_CONNECTED) { 47001500109bSMat Martineau /* Create channel failure, disconnect */ 47015e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 47021500109bSMat Martineau return; 47031500109bSMat Martineau } 47041500109bSMat Martineau 47051500109bSMat Martineau switch (chan->move_role) { 47061500109bSMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 47071500109bSMat Martineau l2cap_move_done(chan); 47081500109bSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP); 47091500109bSMat Martineau break; 47101500109bSMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 47111500109bSMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP || 47121500109bSMat Martineau chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) { 47131500109bSMat Martineau /* Remote has only sent pending or 47141500109bSMat Martineau * success responses, clean up 47151500109bSMat Martineau */ 47161500109bSMat Martineau l2cap_move_done(chan); 47171500109bSMat Martineau } 47181500109bSMat Martineau 47191500109bSMat Martineau /* Other amp move states imply that the move 47201500109bSMat Martineau * has already aborted 47211500109bSMat Martineau */ 47221500109bSMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 47231500109bSMat Martineau break; 47241500109bSMat Martineau } 47251500109bSMat Martineau } 47261500109bSMat Martineau 47271500109bSMat Martineau static void l2cap_logical_finish_create(struct l2cap_chan *chan, 47281500109bSMat Martineau struct hci_chan *hchan) 47291500109bSMat Martineau { 47301500109bSMat Martineau struct l2cap_conf_rsp rsp; 47311500109bSMat Martineau 4732336178a3SAndrei Emeltchenko chan->hs_hchan = hchan; 47331500109bSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 47341500109bSMat Martineau 473535ba9561SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0); 47361500109bSMat Martineau 47371500109bSMat Martineau if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 4738fe79c6feSAndrei Emeltchenko int err; 47391500109bSMat Martineau 47401500109bSMat Martineau set_default_fcs(chan); 47411500109bSMat Martineau 47421500109bSMat Martineau err = l2cap_ertm_init(chan); 47431500109bSMat Martineau if (err < 0) 47445e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 47451500109bSMat Martineau else 47461500109bSMat Martineau l2cap_chan_ready(chan); 47471500109bSMat Martineau } 47481500109bSMat Martineau } 47491500109bSMat Martineau 47501500109bSMat Martineau static void l2cap_logical_finish_move(struct l2cap_chan *chan, 47511500109bSMat Martineau struct hci_chan *hchan) 47521500109bSMat Martineau { 47531500109bSMat Martineau chan->hs_hcon = hchan->conn; 47541500109bSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 47551500109bSMat Martineau 47561500109bSMat Martineau BT_DBG("move_state %d", chan->move_state); 47571500109bSMat Martineau 47581500109bSMat Martineau switch (chan->move_state) { 47591500109bSMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_COMP: 47601500109bSMat Martineau /* Move confirm will be sent after a success 47611500109bSMat Martineau * response is received 47621500109bSMat Martineau */ 47631500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 47641500109bSMat Martineau break; 47651500109bSMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_CFM: 47661500109bSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 47671500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 47681500109bSMat Martineau } else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { 47691500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; 47701500109bSMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 47711500109bSMat Martineau } else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { 47721500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 47731500109bSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); 47741500109bSMat Martineau } 47751500109bSMat Martineau break; 47761500109bSMat Martineau default: 47771500109bSMat Martineau /* Move was not in expected state, free the channel */ 47781500109bSMat Martineau __release_logical_link(chan); 47791500109bSMat Martineau 47801500109bSMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 47811500109bSMat Martineau } 47821500109bSMat Martineau } 47831500109bSMat Martineau 47841500109bSMat Martineau /* Call with chan locked */ 478527695fb4SAndrei Emeltchenko void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan, 47865b155ef9SMat Martineau u8 status) 47875b155ef9SMat Martineau { 47881500109bSMat Martineau BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status); 47891500109bSMat Martineau 47901500109bSMat Martineau if (status) { 47911500109bSMat Martineau l2cap_logical_fail(chan); 47921500109bSMat Martineau __release_logical_link(chan); 47935b155ef9SMat Martineau return; 47945b155ef9SMat Martineau } 47955b155ef9SMat Martineau 47961500109bSMat Martineau if (chan->state != BT_CONNECTED) { 47971500109bSMat Martineau /* Ignore logical link if channel is on BR/EDR */ 47986ed971caSMarcel Holtmann if (chan->local_amp_id != AMP_ID_BREDR) 47991500109bSMat Martineau l2cap_logical_finish_create(chan, hchan); 48001500109bSMat Martineau } else { 48011500109bSMat Martineau l2cap_logical_finish_move(chan, hchan); 48021500109bSMat Martineau } 48031500109bSMat Martineau } 48041500109bSMat Martineau 48053f7a56c4SMat Martineau void l2cap_move_start(struct l2cap_chan *chan) 48063f7a56c4SMat Martineau { 48073f7a56c4SMat Martineau BT_DBG("chan %p", chan); 48083f7a56c4SMat Martineau 48096ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR) { 48103f7a56c4SMat Martineau if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED) 48113f7a56c4SMat Martineau return; 48123f7a56c4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; 48133f7a56c4SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_PREPARE; 48143f7a56c4SMat Martineau /* Placeholder - start physical link setup */ 48153f7a56c4SMat Martineau } else { 48163f7a56c4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; 48173f7a56c4SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 48183f7a56c4SMat Martineau chan->move_id = 0; 48193f7a56c4SMat Martineau l2cap_move_setup(chan); 48203f7a56c4SMat Martineau l2cap_send_move_chan_req(chan, 0); 48213f7a56c4SMat Martineau } 48223f7a56c4SMat Martineau } 48233f7a56c4SMat Martineau 48248eb200bdSMat Martineau static void l2cap_do_create(struct l2cap_chan *chan, int result, 48258eb200bdSMat Martineau u8 local_amp_id, u8 remote_amp_id) 48268eb200bdSMat Martineau { 482762748ca1SAndrei Emeltchenko BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state), 482862748ca1SAndrei Emeltchenko local_amp_id, remote_amp_id); 482962748ca1SAndrei Emeltchenko 483012d6cc60SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 483112d6cc60SAndrei Emeltchenko 483262748ca1SAndrei Emeltchenko /* Outgoing channel on AMP */ 483362748ca1SAndrei Emeltchenko if (chan->state == BT_CONNECT) { 483462748ca1SAndrei Emeltchenko if (result == L2CAP_CR_SUCCESS) { 483562748ca1SAndrei Emeltchenko chan->local_amp_id = local_amp_id; 483662748ca1SAndrei Emeltchenko l2cap_send_create_chan_req(chan, remote_amp_id); 483762748ca1SAndrei Emeltchenko } else { 483862748ca1SAndrei Emeltchenko /* Revert to BR/EDR connect */ 483962748ca1SAndrei Emeltchenko l2cap_send_conn_req(chan); 484062748ca1SAndrei Emeltchenko } 484162748ca1SAndrei Emeltchenko 484262748ca1SAndrei Emeltchenko return; 484362748ca1SAndrei Emeltchenko } 484462748ca1SAndrei Emeltchenko 484562748ca1SAndrei Emeltchenko /* Incoming channel on AMP */ 484662748ca1SAndrei Emeltchenko if (__l2cap_no_conn_pending(chan)) { 48478eb200bdSMat Martineau struct l2cap_conn_rsp rsp; 48488eb200bdSMat Martineau char buf[128]; 48498eb200bdSMat Martineau rsp.scid = cpu_to_le16(chan->dcid); 48508eb200bdSMat Martineau rsp.dcid = cpu_to_le16(chan->scid); 48518eb200bdSMat Martineau 48528eb200bdSMat Martineau if (result == L2CAP_CR_SUCCESS) { 48538eb200bdSMat Martineau /* Send successful response */ 4854dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 4855dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 48568eb200bdSMat Martineau } else { 48578eb200bdSMat Martineau /* Send negative response */ 4858dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_NO_MEM); 4859dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 48608eb200bdSMat Martineau } 48618eb200bdSMat Martineau 48628eb200bdSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP, 48638eb200bdSMat Martineau sizeof(rsp), &rsp); 48648eb200bdSMat Martineau 48658eb200bdSMat Martineau if (result == L2CAP_CR_SUCCESS) { 4866f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 48678eb200bdSMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 48688eb200bdSMat Martineau l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn), 48698eb200bdSMat Martineau L2CAP_CONF_REQ, 4870e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); 48718eb200bdSMat Martineau chan->num_conf_req++; 48728eb200bdSMat Martineau } 48738eb200bdSMat Martineau } 48748eb200bdSMat Martineau } 48758eb200bdSMat Martineau 48768eb200bdSMat Martineau static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id, 48778eb200bdSMat Martineau u8 remote_amp_id) 48788eb200bdSMat Martineau { 48798eb200bdSMat Martineau l2cap_move_setup(chan); 48808eb200bdSMat Martineau chan->move_id = local_amp_id; 48818eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP; 48828eb200bdSMat Martineau 48838eb200bdSMat Martineau l2cap_send_move_chan_req(chan, remote_amp_id); 48848eb200bdSMat Martineau } 48858eb200bdSMat Martineau 48868eb200bdSMat Martineau static void l2cap_do_move_respond(struct l2cap_chan *chan, int result) 48878eb200bdSMat Martineau { 48888eb200bdSMat Martineau struct hci_chan *hchan = NULL; 48898eb200bdSMat Martineau 48908eb200bdSMat Martineau /* Placeholder - get hci_chan for logical link */ 48918eb200bdSMat Martineau 48928eb200bdSMat Martineau if (hchan) { 48938eb200bdSMat Martineau if (hchan->state == BT_CONNECTED) { 48948eb200bdSMat Martineau /* Logical link is ready to go */ 48958eb200bdSMat Martineau chan->hs_hcon = hchan->conn; 48968eb200bdSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 48978eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 48988eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); 48998eb200bdSMat Martineau 49008eb200bdSMat Martineau l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); 49018eb200bdSMat Martineau } else { 49028eb200bdSMat Martineau /* Wait for logical link to be ready */ 49038eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 49048eb200bdSMat Martineau } 49058eb200bdSMat Martineau } else { 49068eb200bdSMat Martineau /* Logical link not available */ 49078eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED); 49088eb200bdSMat Martineau } 49098eb200bdSMat Martineau } 49108eb200bdSMat Martineau 49118eb200bdSMat Martineau static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result) 49128eb200bdSMat Martineau { 49138eb200bdSMat Martineau if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { 49148eb200bdSMat Martineau u8 rsp_result; 49158eb200bdSMat Martineau if (result == -EINVAL) 49168eb200bdSMat Martineau rsp_result = L2CAP_MR_BAD_ID; 49178eb200bdSMat Martineau else 49188eb200bdSMat Martineau rsp_result = L2CAP_MR_NOT_ALLOWED; 49198eb200bdSMat Martineau 49208eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, rsp_result); 49218eb200bdSMat Martineau } 49228eb200bdSMat Martineau 49238eb200bdSMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 49248eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 49258eb200bdSMat Martineau 49268eb200bdSMat Martineau /* Restart data transmission */ 49278eb200bdSMat Martineau l2cap_ertm_send(chan); 49288eb200bdSMat Martineau } 49298eb200bdSMat Martineau 4930a514b17fSAndrei Emeltchenko /* Invoke with locked chan */ 4931a514b17fSAndrei Emeltchenko void __l2cap_physical_cfm(struct l2cap_chan *chan, int result) 49328eb200bdSMat Martineau { 4933770bfefaSAndrei Emeltchenko u8 local_amp_id = chan->local_amp_id; 4934fffadc08SAndrei Emeltchenko u8 remote_amp_id = chan->remote_amp_id; 4935770bfefaSAndrei Emeltchenko 49368eb200bdSMat Martineau BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d", 49378eb200bdSMat Martineau chan, result, local_amp_id, remote_amp_id); 49388eb200bdSMat Martineau 4939df66499aSDan Carpenter if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) 49408eb200bdSMat Martineau return; 49418eb200bdSMat Martineau 49428eb200bdSMat Martineau if (chan->state != BT_CONNECTED) { 49438eb200bdSMat Martineau l2cap_do_create(chan, result, local_amp_id, remote_amp_id); 49448eb200bdSMat Martineau } else if (result != L2CAP_MR_SUCCESS) { 49458eb200bdSMat Martineau l2cap_do_move_cancel(chan, result); 49468eb200bdSMat Martineau } else { 49478eb200bdSMat Martineau switch (chan->move_role) { 49488eb200bdSMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 49498eb200bdSMat Martineau l2cap_do_move_initiate(chan, local_amp_id, 49508eb200bdSMat Martineau remote_amp_id); 49518eb200bdSMat Martineau break; 49528eb200bdSMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 49538eb200bdSMat Martineau l2cap_do_move_respond(chan, result); 49548eb200bdSMat Martineau break; 49558eb200bdSMat Martineau default: 49568eb200bdSMat Martineau l2cap_do_move_cancel(chan, result); 49578eb200bdSMat Martineau break; 49588eb200bdSMat Martineau } 49598eb200bdSMat Martineau } 49608eb200bdSMat Martineau } 49618eb200bdSMat Martineau 49628d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn, 4963ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 4964ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 49658d5a04a1SMat Martineau { 49668d5a04a1SMat Martineau struct l2cap_move_chan_req *req = data; 49671500109bSMat Martineau struct l2cap_move_chan_rsp rsp; 496802b0fbb9SMat Martineau struct l2cap_chan *chan; 49698d5a04a1SMat Martineau u16 icid = 0; 49708d5a04a1SMat Martineau u16 result = L2CAP_MR_NOT_ALLOWED; 49718d5a04a1SMat Martineau 49728d5a04a1SMat Martineau if (cmd_len != sizeof(*req)) 49738d5a04a1SMat Martineau return -EPROTO; 49748d5a04a1SMat Martineau 49758d5a04a1SMat Martineau icid = le16_to_cpu(req->icid); 49768d5a04a1SMat Martineau 4977ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id); 49788d5a04a1SMat Martineau 49790bd49fc7SJohan Hedberg if (!(conn->local_fixed_chan & L2CAP_FC_A2MP)) 49808d5a04a1SMat Martineau return -EINVAL; 49818d5a04a1SMat Martineau 498202b0fbb9SMat Martineau chan = l2cap_get_chan_by_dcid(conn, icid); 498302b0fbb9SMat Martineau if (!chan) { 49841500109bSMat Martineau rsp.icid = cpu_to_le16(icid); 4985dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_MR_NOT_ALLOWED); 49861500109bSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP, 49871500109bSMat Martineau sizeof(rsp), &rsp); 498802b0fbb9SMat Martineau return 0; 498902b0fbb9SMat Martineau } 499002b0fbb9SMat Martineau 49911500109bSMat Martineau chan->ident = cmd->ident; 49921500109bSMat Martineau 499302b0fbb9SMat Martineau if (chan->scid < L2CAP_CID_DYN_START || 499402b0fbb9SMat Martineau chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY || 499502b0fbb9SMat Martineau (chan->mode != L2CAP_MODE_ERTM && 499602b0fbb9SMat Martineau chan->mode != L2CAP_MODE_STREAMING)) { 499702b0fbb9SMat Martineau result = L2CAP_MR_NOT_ALLOWED; 499802b0fbb9SMat Martineau goto send_move_response; 499902b0fbb9SMat Martineau } 500002b0fbb9SMat Martineau 500102b0fbb9SMat Martineau if (chan->local_amp_id == req->dest_amp_id) { 500202b0fbb9SMat Martineau result = L2CAP_MR_SAME_ID; 500302b0fbb9SMat Martineau goto send_move_response; 500402b0fbb9SMat Martineau } 500502b0fbb9SMat Martineau 50066ed971caSMarcel Holtmann if (req->dest_amp_id != AMP_ID_BREDR) { 500702b0fbb9SMat Martineau struct hci_dev *hdev; 500802b0fbb9SMat Martineau hdev = hci_dev_get(req->dest_amp_id); 500902b0fbb9SMat Martineau if (!hdev || hdev->dev_type != HCI_AMP || 501002b0fbb9SMat Martineau !test_bit(HCI_UP, &hdev->flags)) { 501102b0fbb9SMat Martineau if (hdev) 501202b0fbb9SMat Martineau hci_dev_put(hdev); 501302b0fbb9SMat Martineau 501402b0fbb9SMat Martineau result = L2CAP_MR_BAD_ID; 501502b0fbb9SMat Martineau goto send_move_response; 501602b0fbb9SMat Martineau } 501702b0fbb9SMat Martineau hci_dev_put(hdev); 501802b0fbb9SMat Martineau } 501902b0fbb9SMat Martineau 502002b0fbb9SMat Martineau /* Detect a move collision. Only send a collision response 502102b0fbb9SMat Martineau * if this side has "lost", otherwise proceed with the move. 502202b0fbb9SMat Martineau * The winner has the larger bd_addr. 502302b0fbb9SMat Martineau */ 502402b0fbb9SMat Martineau if ((__chan_is_moving(chan) || 502502b0fbb9SMat Martineau chan->move_role != L2CAP_MOVE_ROLE_NONE) && 50266f59b904SMarcel Holtmann bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) { 502702b0fbb9SMat Martineau result = L2CAP_MR_COLLISION; 502802b0fbb9SMat Martineau goto send_move_response; 502902b0fbb9SMat Martineau } 503002b0fbb9SMat Martineau 503102b0fbb9SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; 503202b0fbb9SMat Martineau l2cap_move_setup(chan); 503302b0fbb9SMat Martineau chan->move_id = req->dest_amp_id; 503402b0fbb9SMat Martineau icid = chan->dcid; 503502b0fbb9SMat Martineau 50366ed971caSMarcel Holtmann if (req->dest_amp_id == AMP_ID_BREDR) { 503702b0fbb9SMat Martineau /* Moving to BR/EDR */ 503802b0fbb9SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 503902b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 504002b0fbb9SMat Martineau result = L2CAP_MR_PEND; 504102b0fbb9SMat Martineau } else { 504202b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 504302b0fbb9SMat Martineau result = L2CAP_MR_SUCCESS; 504402b0fbb9SMat Martineau } 504502b0fbb9SMat Martineau } else { 504602b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_PREPARE; 504702b0fbb9SMat Martineau /* Placeholder - uncomment when amp functions are available */ 504802b0fbb9SMat Martineau /*amp_accept_physical(chan, req->dest_amp_id);*/ 504902b0fbb9SMat Martineau result = L2CAP_MR_PEND; 505002b0fbb9SMat Martineau } 505102b0fbb9SMat Martineau 505202b0fbb9SMat Martineau send_move_response: 50531500109bSMat Martineau l2cap_send_move_chan_rsp(chan, result); 50548d5a04a1SMat Martineau 505502b0fbb9SMat Martineau l2cap_chan_unlock(chan); 505602b0fbb9SMat Martineau 50578d5a04a1SMat Martineau return 0; 50588d5a04a1SMat Martineau } 50598d5a04a1SMat Martineau 50605b155ef9SMat Martineau static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result) 50615b155ef9SMat Martineau { 50625b155ef9SMat Martineau struct l2cap_chan *chan; 50635b155ef9SMat Martineau struct hci_chan *hchan = NULL; 50645b155ef9SMat Martineau 50655b155ef9SMat Martineau chan = l2cap_get_chan_by_scid(conn, icid); 50665b155ef9SMat Martineau if (!chan) { 50675b155ef9SMat Martineau l2cap_send_move_chan_cfm_icid(conn, icid); 50685b155ef9SMat Martineau return; 50695b155ef9SMat Martineau } 50705b155ef9SMat Martineau 50715b155ef9SMat Martineau __clear_chan_timer(chan); 50725b155ef9SMat Martineau if (result == L2CAP_MR_PEND) 50735b155ef9SMat Martineau __set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT); 50745b155ef9SMat Martineau 50755b155ef9SMat Martineau switch (chan->move_state) { 50765b155ef9SMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_COMP: 50775b155ef9SMat Martineau /* Move confirm will be sent when logical link 50785b155ef9SMat Martineau * is complete. 50795b155ef9SMat Martineau */ 50805b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 50815b155ef9SMat Martineau break; 50825b155ef9SMat Martineau case L2CAP_MOVE_WAIT_RSP_SUCCESS: 50835b155ef9SMat Martineau if (result == L2CAP_MR_PEND) { 50845b155ef9SMat Martineau break; 50855b155ef9SMat Martineau } else if (test_bit(CONN_LOCAL_BUSY, 50865b155ef9SMat Martineau &chan->conn_state)) { 50875b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 50885b155ef9SMat Martineau } else { 50895b155ef9SMat Martineau /* Logical link is up or moving to BR/EDR, 50905b155ef9SMat Martineau * proceed with move 50915b155ef9SMat Martineau */ 50925b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; 50935b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 50945b155ef9SMat Martineau } 50955b155ef9SMat Martineau break; 50965b155ef9SMat Martineau case L2CAP_MOVE_WAIT_RSP: 50975b155ef9SMat Martineau /* Moving to AMP */ 50985b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS) { 50995b155ef9SMat Martineau /* Remote is ready, send confirm immediately 51005b155ef9SMat Martineau * after logical link is ready 51015b155ef9SMat Martineau */ 51025b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 51035b155ef9SMat Martineau } else { 51045b155ef9SMat Martineau /* Both logical link and move success 51055b155ef9SMat Martineau * are required to confirm 51065b155ef9SMat Martineau */ 51075b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP; 51085b155ef9SMat Martineau } 51095b155ef9SMat Martineau 51105b155ef9SMat Martineau /* Placeholder - get hci_chan for logical link */ 51115b155ef9SMat Martineau if (!hchan) { 51125b155ef9SMat Martineau /* Logical link not available */ 51135b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 51145b155ef9SMat Martineau break; 51155b155ef9SMat Martineau } 51165b155ef9SMat Martineau 51175b155ef9SMat Martineau /* If the logical link is not yet connected, do not 51185b155ef9SMat Martineau * send confirmation. 51195b155ef9SMat Martineau */ 51205b155ef9SMat Martineau if (hchan->state != BT_CONNECTED) 51215b155ef9SMat Martineau break; 51225b155ef9SMat Martineau 51235b155ef9SMat Martineau /* Logical link is already ready to go */ 51245b155ef9SMat Martineau 51255b155ef9SMat Martineau chan->hs_hcon = hchan->conn; 51265b155ef9SMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 51275b155ef9SMat Martineau 51285b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS) { 51295b155ef9SMat Martineau /* Can confirm now */ 51305b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 51315b155ef9SMat Martineau } else { 51325b155ef9SMat Martineau /* Now only need move success 51335b155ef9SMat Martineau * to confirm 51345b155ef9SMat Martineau */ 51355b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 51365b155ef9SMat Martineau } 51375b155ef9SMat Martineau 51385b155ef9SMat Martineau l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); 51395b155ef9SMat Martineau break; 51405b155ef9SMat Martineau default: 51415b155ef9SMat Martineau /* Any other amp move state means the move failed. */ 51425b155ef9SMat Martineau chan->move_id = chan->local_amp_id; 51435b155ef9SMat Martineau l2cap_move_done(chan); 51445b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 51455b155ef9SMat Martineau } 51465b155ef9SMat Martineau 51475b155ef9SMat Martineau l2cap_chan_unlock(chan); 51485b155ef9SMat Martineau } 51495b155ef9SMat Martineau 51505b155ef9SMat Martineau static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid, 51515b155ef9SMat Martineau u16 result) 51525b155ef9SMat Martineau { 51535b155ef9SMat Martineau struct l2cap_chan *chan; 51545b155ef9SMat Martineau 51555b155ef9SMat Martineau chan = l2cap_get_chan_by_ident(conn, ident); 51565b155ef9SMat Martineau if (!chan) { 51575b155ef9SMat Martineau /* Could not locate channel, icid is best guess */ 51585b155ef9SMat Martineau l2cap_send_move_chan_cfm_icid(conn, icid); 51595b155ef9SMat Martineau return; 51605b155ef9SMat Martineau } 51615b155ef9SMat Martineau 51625b155ef9SMat Martineau __clear_chan_timer(chan); 51635b155ef9SMat Martineau 51645b155ef9SMat Martineau if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { 51655b155ef9SMat Martineau if (result == L2CAP_MR_COLLISION) { 51665b155ef9SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; 51675b155ef9SMat Martineau } else { 51685b155ef9SMat Martineau /* Cleanup - cancel move */ 51695b155ef9SMat Martineau chan->move_id = chan->local_amp_id; 51705b155ef9SMat Martineau l2cap_move_done(chan); 51715b155ef9SMat Martineau } 51725b155ef9SMat Martineau } 51735b155ef9SMat Martineau 51745b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 51755b155ef9SMat Martineau 51765b155ef9SMat Martineau l2cap_chan_unlock(chan); 51775b155ef9SMat Martineau } 51785b155ef9SMat Martineau 51795b155ef9SMat Martineau static int l2cap_move_channel_rsp(struct l2cap_conn *conn, 5180ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5181ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 51828d5a04a1SMat Martineau { 51838d5a04a1SMat Martineau struct l2cap_move_chan_rsp *rsp = data; 51848d5a04a1SMat Martineau u16 icid, result; 51858d5a04a1SMat Martineau 51868d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 51878d5a04a1SMat Martineau return -EPROTO; 51888d5a04a1SMat Martineau 51898d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 51908d5a04a1SMat Martineau result = le16_to_cpu(rsp->result); 51918d5a04a1SMat Martineau 5192ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 51938d5a04a1SMat Martineau 51945b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND) 51955b155ef9SMat Martineau l2cap_move_continue(conn, icid, result); 51965b155ef9SMat Martineau else 51975b155ef9SMat Martineau l2cap_move_fail(conn, cmd->ident, icid, result); 51988d5a04a1SMat Martineau 51998d5a04a1SMat Martineau return 0; 52008d5a04a1SMat Martineau } 52018d5a04a1SMat Martineau 52025f3847a4SMat Martineau static int l2cap_move_channel_confirm(struct l2cap_conn *conn, 5203ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5204ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 52058d5a04a1SMat Martineau { 52068d5a04a1SMat Martineau struct l2cap_move_chan_cfm *cfm = data; 52075f3847a4SMat Martineau struct l2cap_chan *chan; 52088d5a04a1SMat Martineau u16 icid, result; 52098d5a04a1SMat Martineau 52108d5a04a1SMat Martineau if (cmd_len != sizeof(*cfm)) 52118d5a04a1SMat Martineau return -EPROTO; 52128d5a04a1SMat Martineau 52138d5a04a1SMat Martineau icid = le16_to_cpu(cfm->icid); 52148d5a04a1SMat Martineau result = le16_to_cpu(cfm->result); 52158d5a04a1SMat Martineau 5216ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 52178d5a04a1SMat Martineau 52185f3847a4SMat Martineau chan = l2cap_get_chan_by_dcid(conn, icid); 52195f3847a4SMat Martineau if (!chan) { 52205f3847a4SMat Martineau /* Spec requires a response even if the icid was not found */ 52218d5a04a1SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 52225f3847a4SMat Martineau return 0; 52235f3847a4SMat Martineau } 52245f3847a4SMat Martineau 52255f3847a4SMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) { 52265f3847a4SMat Martineau if (result == L2CAP_MC_CONFIRMED) { 52275f3847a4SMat Martineau chan->local_amp_id = chan->move_id; 52286ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR) 52295f3847a4SMat Martineau __release_logical_link(chan); 52305f3847a4SMat Martineau } else { 52315f3847a4SMat Martineau chan->move_id = chan->local_amp_id; 52325f3847a4SMat Martineau } 52335f3847a4SMat Martineau 52345f3847a4SMat Martineau l2cap_move_done(chan); 52355f3847a4SMat Martineau } 52365f3847a4SMat Martineau 52375f3847a4SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 52385f3847a4SMat Martineau 52395f3847a4SMat Martineau l2cap_chan_unlock(chan); 52408d5a04a1SMat Martineau 52418d5a04a1SMat Martineau return 0; 52428d5a04a1SMat Martineau } 52438d5a04a1SMat Martineau 52448d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, 5245ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5246ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 52478d5a04a1SMat Martineau { 52488d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp *rsp = data; 52493fd71a0aSMat Martineau struct l2cap_chan *chan; 52508d5a04a1SMat Martineau u16 icid; 52518d5a04a1SMat Martineau 52528d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 52538d5a04a1SMat Martineau return -EPROTO; 52548d5a04a1SMat Martineau 52558d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 52568d5a04a1SMat Martineau 5257ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 52588d5a04a1SMat Martineau 52593fd71a0aSMat Martineau chan = l2cap_get_chan_by_scid(conn, icid); 52603fd71a0aSMat Martineau if (!chan) 52613fd71a0aSMat Martineau return 0; 52623fd71a0aSMat Martineau 52633fd71a0aSMat Martineau __clear_chan_timer(chan); 52643fd71a0aSMat Martineau 52653fd71a0aSMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) { 52663fd71a0aSMat Martineau chan->local_amp_id = chan->move_id; 52673fd71a0aSMat Martineau 52686ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan) 52693fd71a0aSMat Martineau __release_logical_link(chan); 52703fd71a0aSMat Martineau 52713fd71a0aSMat Martineau l2cap_move_done(chan); 52723fd71a0aSMat Martineau } 52733fd71a0aSMat Martineau 52743fd71a0aSMat Martineau l2cap_chan_unlock(chan); 52753fd71a0aSMat Martineau 52768d5a04a1SMat Martineau return 0; 52778d5a04a1SMat Martineau } 52788d5a04a1SMat Martineau 5279de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, 52802d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, 5281203e639eSJohan Hedberg u16 cmd_len, u8 *data) 5282de73115aSClaudio Takahasi { 5283de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon; 5284de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req; 5285de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp; 5286203e639eSJohan Hedberg u16 min, max, latency, to_multiplier; 52872ce603ebSClaudio Takahasi int err; 5288de73115aSClaudio Takahasi 528940bef302SJohan Hedberg if (hcon->role != HCI_ROLE_MASTER) 5290de73115aSClaudio Takahasi return -EINVAL; 5291de73115aSClaudio Takahasi 5292de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) 5293de73115aSClaudio Takahasi return -EPROTO; 5294de73115aSClaudio Takahasi 5295de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data; 5296de73115aSClaudio Takahasi min = __le16_to_cpu(req->min); 5297de73115aSClaudio Takahasi max = __le16_to_cpu(req->max); 5298de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency); 5299de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier); 5300de73115aSClaudio Takahasi 5301de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", 5302de73115aSClaudio Takahasi min, max, latency, to_multiplier); 5303de73115aSClaudio Takahasi 5304de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp)); 53052ce603ebSClaudio Takahasi 5306d4905f24SAndre Guedes err = hci_check_conn_params(min, max, latency, to_multiplier); 53072ce603ebSClaudio Takahasi if (err) 5308dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); 5309de73115aSClaudio Takahasi else 5310dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); 5311de73115aSClaudio Takahasi 5312de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, 5313de73115aSClaudio Takahasi sizeof(rsp), &rsp); 5314de73115aSClaudio Takahasi 5315ffb5a827SAndre Guedes if (!err) { 5316f4869e2aSJohan Hedberg u8 store_hint; 5317ffb5a827SAndre Guedes 5318f4869e2aSJohan Hedberg store_hint = hci_le_conn_update(hcon, min, max, latency, 5319f4869e2aSJohan Hedberg to_multiplier); 5320f4869e2aSJohan Hedberg mgmt_new_conn_param(hcon->hdev, &hcon->dst, hcon->dst_type, 5321f4869e2aSJohan Hedberg store_hint, min, max, latency, 5322f4869e2aSJohan Hedberg to_multiplier); 5323f4869e2aSJohan Hedberg 5324ffb5a827SAndre Guedes } 53252ce603ebSClaudio Takahasi 5326de73115aSClaudio Takahasi return 0; 5327de73115aSClaudio Takahasi } 5328de73115aSClaudio Takahasi 5329f1496deeSJohan Hedberg static int l2cap_le_connect_rsp(struct l2cap_conn *conn, 5330f1496deeSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5331f1496deeSJohan Hedberg u8 *data) 5332f1496deeSJohan Hedberg { 5333f1496deeSJohan Hedberg struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data; 53343e64b7bdSJohan Hedberg struct hci_conn *hcon = conn->hcon; 5335f1496deeSJohan Hedberg u16 dcid, mtu, mps, credits, result; 5336f1496deeSJohan Hedberg struct l2cap_chan *chan; 53373e64b7bdSJohan Hedberg int err, sec_level; 5338f1496deeSJohan Hedberg 5339f1496deeSJohan Hedberg if (cmd_len < sizeof(*rsp)) 5340f1496deeSJohan Hedberg return -EPROTO; 5341f1496deeSJohan Hedberg 5342f1496deeSJohan Hedberg dcid = __le16_to_cpu(rsp->dcid); 5343f1496deeSJohan Hedberg mtu = __le16_to_cpu(rsp->mtu); 5344f1496deeSJohan Hedberg mps = __le16_to_cpu(rsp->mps); 5345f1496deeSJohan Hedberg credits = __le16_to_cpu(rsp->credits); 5346f1496deeSJohan Hedberg result = __le16_to_cpu(rsp->result); 5347f1496deeSJohan Hedberg 5348571f7390SMallikarjun Phulari if (result == L2CAP_CR_LE_SUCCESS && (mtu < 23 || mps < 23 || 534940624183SJohan Hedberg dcid < L2CAP_CID_DYN_START || 535040624183SJohan Hedberg dcid > L2CAP_CID_LE_DYN_END)) 5351f1496deeSJohan Hedberg return -EPROTO; 5352f1496deeSJohan Hedberg 5353f1496deeSJohan Hedberg BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x", 5354f1496deeSJohan Hedberg dcid, mtu, mps, credits, result); 5355f1496deeSJohan Hedberg 5356f1496deeSJohan Hedberg mutex_lock(&conn->chan_lock); 5357f1496deeSJohan Hedberg 5358f1496deeSJohan Hedberg chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 5359f1496deeSJohan Hedberg if (!chan) { 5360f1496deeSJohan Hedberg err = -EBADSLT; 5361f1496deeSJohan Hedberg goto unlock; 5362f1496deeSJohan Hedberg } 5363f1496deeSJohan Hedberg 5364f1496deeSJohan Hedberg err = 0; 5365f1496deeSJohan Hedberg 5366f1496deeSJohan Hedberg l2cap_chan_lock(chan); 5367f1496deeSJohan Hedberg 5368f1496deeSJohan Hedberg switch (result) { 5369571f7390SMallikarjun Phulari case L2CAP_CR_LE_SUCCESS: 537040624183SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, dcid)) { 537140624183SJohan Hedberg err = -EBADSLT; 537240624183SJohan Hedberg break; 537340624183SJohan Hedberg } 537440624183SJohan Hedberg 5375f1496deeSJohan Hedberg chan->ident = 0; 5376f1496deeSJohan Hedberg chan->dcid = dcid; 5377f1496deeSJohan Hedberg chan->omtu = mtu; 5378f1496deeSJohan Hedberg chan->remote_mps = mps; 53790cd75f7eSJohan Hedberg chan->tx_credits = credits; 5380f1496deeSJohan Hedberg l2cap_chan_ready(chan); 5381f1496deeSJohan Hedberg break; 5382f1496deeSJohan Hedberg 5383571f7390SMallikarjun Phulari case L2CAP_CR_LE_AUTHENTICATION: 5384571f7390SMallikarjun Phulari case L2CAP_CR_LE_ENCRYPTION: 53853e64b7bdSJohan Hedberg /* If we already have MITM protection we can't do 53863e64b7bdSJohan Hedberg * anything. 53873e64b7bdSJohan Hedberg */ 53883e64b7bdSJohan Hedberg if (hcon->sec_level > BT_SECURITY_MEDIUM) { 53893e64b7bdSJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED); 53903e64b7bdSJohan Hedberg break; 53913e64b7bdSJohan Hedberg } 53923e64b7bdSJohan Hedberg 53933e64b7bdSJohan Hedberg sec_level = hcon->sec_level + 1; 53943e64b7bdSJohan Hedberg if (chan->sec_level < sec_level) 53953e64b7bdSJohan Hedberg chan->sec_level = sec_level; 53963e64b7bdSJohan Hedberg 53973e64b7bdSJohan Hedberg /* We'll need to send a new Connect Request */ 53983e64b7bdSJohan Hedberg clear_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags); 53993e64b7bdSJohan Hedberg 54003e64b7bdSJohan Hedberg smp_conn_security(hcon, chan->sec_level); 54013e64b7bdSJohan Hedberg break; 54023e64b7bdSJohan Hedberg 5403f1496deeSJohan Hedberg default: 5404f1496deeSJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED); 5405f1496deeSJohan Hedberg break; 5406f1496deeSJohan Hedberg } 5407f1496deeSJohan Hedberg 5408f1496deeSJohan Hedberg l2cap_chan_unlock(chan); 5409f1496deeSJohan Hedberg 5410f1496deeSJohan Hedberg unlock: 5411f1496deeSJohan Hedberg mutex_unlock(&conn->chan_lock); 5412f1496deeSJohan Hedberg 5413f1496deeSJohan Hedberg return err; 5414f1496deeSJohan Hedberg } 5415f1496deeSJohan Hedberg 54163300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, 54172d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len, 54182d792818SGustavo Padovan u8 *data) 54193300d9a9SClaudio Takahasi { 54203300d9a9SClaudio Takahasi int err = 0; 54213300d9a9SClaudio Takahasi 54223300d9a9SClaudio Takahasi switch (cmd->code) { 54233300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 5424cb3b3152SJohan Hedberg l2cap_command_rej(conn, cmd, cmd_len, data); 54253300d9a9SClaudio Takahasi break; 54263300d9a9SClaudio Takahasi 54273300d9a9SClaudio Takahasi case L2CAP_CONN_REQ: 5428cb3b3152SJohan Hedberg err = l2cap_connect_req(conn, cmd, cmd_len, data); 54293300d9a9SClaudio Takahasi break; 54303300d9a9SClaudio Takahasi 54313300d9a9SClaudio Takahasi case L2CAP_CONN_RSP: 5432f5a2598dSMat Martineau case L2CAP_CREATE_CHAN_RSP: 54339245e737SJohan Hedberg l2cap_connect_create_rsp(conn, cmd, cmd_len, data); 54343300d9a9SClaudio Takahasi break; 54353300d9a9SClaudio Takahasi 54363300d9a9SClaudio Takahasi case L2CAP_CONF_REQ: 54373300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data); 54383300d9a9SClaudio Takahasi break; 54393300d9a9SClaudio Takahasi 54403300d9a9SClaudio Takahasi case L2CAP_CONF_RSP: 54419245e737SJohan Hedberg l2cap_config_rsp(conn, cmd, cmd_len, data); 54423300d9a9SClaudio Takahasi break; 54433300d9a9SClaudio Takahasi 54443300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ: 5445cb3b3152SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data); 54463300d9a9SClaudio Takahasi break; 54473300d9a9SClaudio Takahasi 54483300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP: 54499245e737SJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data); 54503300d9a9SClaudio Takahasi break; 54513300d9a9SClaudio Takahasi 54523300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ: 54533300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data); 54543300d9a9SClaudio Takahasi break; 54553300d9a9SClaudio Takahasi 54563300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP: 54573300d9a9SClaudio Takahasi break; 54583300d9a9SClaudio Takahasi 54593300d9a9SClaudio Takahasi case L2CAP_INFO_REQ: 5460cb3b3152SJohan Hedberg err = l2cap_information_req(conn, cmd, cmd_len, data); 54613300d9a9SClaudio Takahasi break; 54623300d9a9SClaudio Takahasi 54633300d9a9SClaudio Takahasi case L2CAP_INFO_RSP: 54649245e737SJohan Hedberg l2cap_information_rsp(conn, cmd, cmd_len, data); 54653300d9a9SClaudio Takahasi break; 54663300d9a9SClaudio Takahasi 5467f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_REQ: 5468f94ff6ffSMat Martineau err = l2cap_create_channel_req(conn, cmd, cmd_len, data); 5469f94ff6ffSMat Martineau break; 5470f94ff6ffSMat Martineau 54718d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_REQ: 54728d5a04a1SMat Martineau err = l2cap_move_channel_req(conn, cmd, cmd_len, data); 54738d5a04a1SMat Martineau break; 54748d5a04a1SMat Martineau 54758d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_RSP: 54769245e737SJohan Hedberg l2cap_move_channel_rsp(conn, cmd, cmd_len, data); 54778d5a04a1SMat Martineau break; 54788d5a04a1SMat Martineau 54798d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM: 54808d5a04a1SMat Martineau err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data); 54818d5a04a1SMat Martineau break; 54828d5a04a1SMat Martineau 54838d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM_RSP: 54849245e737SJohan Hedberg l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data); 54858d5a04a1SMat Martineau break; 54868d5a04a1SMat Martineau 54873300d9a9SClaudio Takahasi default: 54883300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code); 54893300d9a9SClaudio Takahasi err = -EINVAL; 54903300d9a9SClaudio Takahasi break; 54913300d9a9SClaudio Takahasi } 54923300d9a9SClaudio Takahasi 54933300d9a9SClaudio Takahasi return err; 54943300d9a9SClaudio Takahasi } 54953300d9a9SClaudio Takahasi 549627e2d4c8SJohan Hedberg static int l2cap_le_connect_req(struct l2cap_conn *conn, 549727e2d4c8SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 549827e2d4c8SJohan Hedberg u8 *data) 549927e2d4c8SJohan Hedberg { 550027e2d4c8SJohan Hedberg struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data; 550127e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 550227e2d4c8SJohan Hedberg struct l2cap_chan *chan, *pchan; 55030cd75f7eSJohan Hedberg u16 dcid, scid, credits, mtu, mps; 550427e2d4c8SJohan Hedberg __le16 psm; 550527e2d4c8SJohan Hedberg u8 result; 550627e2d4c8SJohan Hedberg 550727e2d4c8SJohan Hedberg if (cmd_len != sizeof(*req)) 550827e2d4c8SJohan Hedberg return -EPROTO; 550927e2d4c8SJohan Hedberg 551027e2d4c8SJohan Hedberg scid = __le16_to_cpu(req->scid); 551127e2d4c8SJohan Hedberg mtu = __le16_to_cpu(req->mtu); 551227e2d4c8SJohan Hedberg mps = __le16_to_cpu(req->mps); 551327e2d4c8SJohan Hedberg psm = req->psm; 551427e2d4c8SJohan Hedberg dcid = 0; 55150cd75f7eSJohan Hedberg credits = 0; 551627e2d4c8SJohan Hedberg 551727e2d4c8SJohan Hedberg if (mtu < 23 || mps < 23) 551827e2d4c8SJohan Hedberg return -EPROTO; 551927e2d4c8SJohan Hedberg 552027e2d4c8SJohan Hedberg BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm), 552127e2d4c8SJohan Hedberg scid, mtu, mps); 552227e2d4c8SJohan Hedberg 552327e2d4c8SJohan Hedberg /* Check if we have socket listening on psm */ 552427e2d4c8SJohan Hedberg pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 552527e2d4c8SJohan Hedberg &conn->hcon->dst, LE_LINK); 552627e2d4c8SJohan Hedberg if (!pchan) { 5527571f7390SMallikarjun Phulari result = L2CAP_CR_LE_BAD_PSM; 552827e2d4c8SJohan Hedberg chan = NULL; 552927e2d4c8SJohan Hedberg goto response; 553027e2d4c8SJohan Hedberg } 553127e2d4c8SJohan Hedberg 553227e2d4c8SJohan Hedberg mutex_lock(&conn->chan_lock); 553327e2d4c8SJohan Hedberg l2cap_chan_lock(pchan); 553427e2d4c8SJohan Hedberg 553535dc6f83SJohan Hedberg if (!smp_sufficient_security(conn->hcon, pchan->sec_level, 553635dc6f83SJohan Hedberg SMP_ALLOW_STK)) { 5537571f7390SMallikarjun Phulari result = L2CAP_CR_LE_AUTHENTICATION; 553827e2d4c8SJohan Hedberg chan = NULL; 553927e2d4c8SJohan Hedberg goto response_unlock; 554027e2d4c8SJohan Hedberg } 554127e2d4c8SJohan Hedberg 55428a7889ccSJohan Hedberg /* Check for valid dynamic CID range */ 55438a7889ccSJohan Hedberg if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) { 5544571f7390SMallikarjun Phulari result = L2CAP_CR_LE_INVALID_SCID; 55458a7889ccSJohan Hedberg chan = NULL; 55468a7889ccSJohan Hedberg goto response_unlock; 55478a7889ccSJohan Hedberg } 55488a7889ccSJohan Hedberg 554927e2d4c8SJohan Hedberg /* Check if we already have channel with that dcid */ 555027e2d4c8SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, scid)) { 5551571f7390SMallikarjun Phulari result = L2CAP_CR_LE_SCID_IN_USE; 555227e2d4c8SJohan Hedberg chan = NULL; 555327e2d4c8SJohan Hedberg goto response_unlock; 555427e2d4c8SJohan Hedberg } 555527e2d4c8SJohan Hedberg 555627e2d4c8SJohan Hedberg chan = pchan->ops->new_connection(pchan); 555727e2d4c8SJohan Hedberg if (!chan) { 5558571f7390SMallikarjun Phulari result = L2CAP_CR_LE_NO_MEM; 555927e2d4c8SJohan Hedberg goto response_unlock; 556027e2d4c8SJohan Hedberg } 556127e2d4c8SJohan Hedberg 556227e2d4c8SJohan Hedberg bacpy(&chan->src, &conn->hcon->src); 556327e2d4c8SJohan Hedberg bacpy(&chan->dst, &conn->hcon->dst); 5564a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(conn->hcon); 5565a250e048SJohan Hedberg chan->dst_type = bdaddr_dst_type(conn->hcon); 556627e2d4c8SJohan Hedberg chan->psm = psm; 556727e2d4c8SJohan Hedberg chan->dcid = scid; 556827e2d4c8SJohan Hedberg chan->omtu = mtu; 556927e2d4c8SJohan Hedberg chan->remote_mps = mps; 557027e2d4c8SJohan Hedberg 557127e2d4c8SJohan Hedberg __l2cap_chan_add(conn, chan); 5572fe149310SLuiz Augusto von Dentz 5573ba8f5289SLuiz Augusto von Dentz l2cap_le_flowctl_init(chan, __le16_to_cpu(req->credits)); 5574fe149310SLuiz Augusto von Dentz 557527e2d4c8SJohan Hedberg dcid = chan->scid; 55760cd75f7eSJohan Hedberg credits = chan->rx_credits; 557727e2d4c8SJohan Hedberg 557827e2d4c8SJohan Hedberg __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 557927e2d4c8SJohan Hedberg 558027e2d4c8SJohan Hedberg chan->ident = cmd->ident; 558127e2d4c8SJohan Hedberg 558227e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 558327e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_CONNECT2); 5584434714dcSJohan Hedberg /* The following result value is actually not defined 5585434714dcSJohan Hedberg * for LE CoC but we use it to let the function know 5586434714dcSJohan Hedberg * that it should bail out after doing its cleanup 5587434714dcSJohan Hedberg * instead of sending a response. 5588434714dcSJohan Hedberg */ 558927e2d4c8SJohan Hedberg result = L2CAP_CR_PEND; 559027e2d4c8SJohan Hedberg chan->ops->defer(chan); 559127e2d4c8SJohan Hedberg } else { 559227e2d4c8SJohan Hedberg l2cap_chan_ready(chan); 5593571f7390SMallikarjun Phulari result = L2CAP_CR_LE_SUCCESS; 559427e2d4c8SJohan Hedberg } 559527e2d4c8SJohan Hedberg 559627e2d4c8SJohan Hedberg response_unlock: 559727e2d4c8SJohan Hedberg l2cap_chan_unlock(pchan); 559827e2d4c8SJohan Hedberg mutex_unlock(&conn->chan_lock); 5599a24cce14SJohan Hedberg l2cap_chan_put(pchan); 560027e2d4c8SJohan Hedberg 560127e2d4c8SJohan Hedberg if (result == L2CAP_CR_PEND) 560227e2d4c8SJohan Hedberg return 0; 560327e2d4c8SJohan Hedberg 560427e2d4c8SJohan Hedberg response: 560527e2d4c8SJohan Hedberg if (chan) { 560627e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 56073916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps); 560827e2d4c8SJohan Hedberg } else { 560927e2d4c8SJohan Hedberg rsp.mtu = 0; 561027e2d4c8SJohan Hedberg rsp.mps = 0; 561127e2d4c8SJohan Hedberg } 561227e2d4c8SJohan Hedberg 561327e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(dcid); 56140cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(credits); 561527e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result); 561627e2d4c8SJohan Hedberg 561727e2d4c8SJohan Hedberg l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp); 561827e2d4c8SJohan Hedberg 561927e2d4c8SJohan Hedberg return 0; 562027e2d4c8SJohan Hedberg } 562127e2d4c8SJohan Hedberg 5622fad5fc89SJohan Hedberg static inline int l2cap_le_credits(struct l2cap_conn *conn, 5623fad5fc89SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5624fad5fc89SJohan Hedberg u8 *data) 5625fad5fc89SJohan Hedberg { 5626fad5fc89SJohan Hedberg struct l2cap_le_credits *pkt; 5627fad5fc89SJohan Hedberg struct l2cap_chan *chan; 56280f1bfe4eSJohan Hedberg u16 cid, credits, max_credits; 5629fad5fc89SJohan Hedberg 5630fad5fc89SJohan Hedberg if (cmd_len != sizeof(*pkt)) 5631fad5fc89SJohan Hedberg return -EPROTO; 5632fad5fc89SJohan Hedberg 5633fad5fc89SJohan Hedberg pkt = (struct l2cap_le_credits *) data; 5634fad5fc89SJohan Hedberg cid = __le16_to_cpu(pkt->cid); 5635fad5fc89SJohan Hedberg credits = __le16_to_cpu(pkt->credits); 5636fad5fc89SJohan Hedberg 5637fad5fc89SJohan Hedberg BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits); 5638fad5fc89SJohan Hedberg 5639fad5fc89SJohan Hedberg chan = l2cap_get_chan_by_dcid(conn, cid); 5640fad5fc89SJohan Hedberg if (!chan) 5641fad5fc89SJohan Hedberg return -EBADSLT; 5642fad5fc89SJohan Hedberg 56430f1bfe4eSJohan Hedberg max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits; 56440f1bfe4eSJohan Hedberg if (credits > max_credits) { 56450f1bfe4eSJohan Hedberg BT_ERR("LE credits overflow"); 56460f1bfe4eSJohan Hedberg l2cap_send_disconn_req(chan, ECONNRESET); 5647ee93053dSMartin Townsend l2cap_chan_unlock(chan); 56480f1bfe4eSJohan Hedberg 56490f1bfe4eSJohan Hedberg /* Return 0 so that we don't trigger an unnecessary 56500f1bfe4eSJohan Hedberg * command reject packet. 56510f1bfe4eSJohan Hedberg */ 56520f1bfe4eSJohan Hedberg return 0; 56530f1bfe4eSJohan Hedberg } 56540f1bfe4eSJohan Hedberg 5655fad5fc89SJohan Hedberg chan->tx_credits += credits; 5656fad5fc89SJohan Hedberg 56578a505b7fSLuiz Augusto von Dentz /* Resume sending */ 56588a505b7fSLuiz Augusto von Dentz l2cap_le_flowctl_send(chan); 5659fad5fc89SJohan Hedberg 5660fad5fc89SJohan Hedberg if (chan->tx_credits) 5661fad5fc89SJohan Hedberg chan->ops->resume(chan); 5662fad5fc89SJohan Hedberg 5663fad5fc89SJohan Hedberg l2cap_chan_unlock(chan); 5664fad5fc89SJohan Hedberg 5665fad5fc89SJohan Hedberg return 0; 5666fad5fc89SJohan Hedberg } 5667fad5fc89SJohan Hedberg 566871fb4197SJohan Hedberg static inline int l2cap_le_command_rej(struct l2cap_conn *conn, 566971fb4197SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 567071fb4197SJohan Hedberg u8 *data) 567171fb4197SJohan Hedberg { 567271fb4197SJohan Hedberg struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 567371fb4197SJohan Hedberg struct l2cap_chan *chan; 567471fb4197SJohan Hedberg 567571fb4197SJohan Hedberg if (cmd_len < sizeof(*rej)) 567671fb4197SJohan Hedberg return -EPROTO; 567771fb4197SJohan Hedberg 567871fb4197SJohan Hedberg mutex_lock(&conn->chan_lock); 567971fb4197SJohan Hedberg 568071fb4197SJohan Hedberg chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 568171fb4197SJohan Hedberg if (!chan) 568271fb4197SJohan Hedberg goto done; 568371fb4197SJohan Hedberg 568471fb4197SJohan Hedberg l2cap_chan_lock(chan); 568571fb4197SJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED); 568671fb4197SJohan Hedberg l2cap_chan_unlock(chan); 568771fb4197SJohan Hedberg 568871fb4197SJohan Hedberg done: 568971fb4197SJohan Hedberg mutex_unlock(&conn->chan_lock); 569071fb4197SJohan Hedberg return 0; 569171fb4197SJohan Hedberg } 569271fb4197SJohan Hedberg 56933300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, 5694203e639eSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5695203e639eSJohan Hedberg u8 *data) 56963300d9a9SClaudio Takahasi { 5697b5ecba64SJohan Hedberg int err = 0; 5698b5ecba64SJohan Hedberg 56993300d9a9SClaudio Takahasi switch (cmd->code) { 57003300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 570171fb4197SJohan Hedberg l2cap_le_command_rej(conn, cmd, cmd_len, data); 5702b5ecba64SJohan Hedberg break; 57033300d9a9SClaudio Takahasi 57043300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ: 5705b5ecba64SJohan Hedberg err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data); 5706b5ecba64SJohan Hedberg break; 57073300d9a9SClaudio Takahasi 57083300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP: 5709b5ecba64SJohan Hedberg break; 57103300d9a9SClaudio Takahasi 5711f1496deeSJohan Hedberg case L2CAP_LE_CONN_RSP: 5712f1496deeSJohan Hedberg l2cap_le_connect_rsp(conn, cmd, cmd_len, data); 5713b5ecba64SJohan Hedberg break; 5714f1496deeSJohan Hedberg 571527e2d4c8SJohan Hedberg case L2CAP_LE_CONN_REQ: 5716b5ecba64SJohan Hedberg err = l2cap_le_connect_req(conn, cmd, cmd_len, data); 5717b5ecba64SJohan Hedberg break; 571827e2d4c8SJohan Hedberg 5719fad5fc89SJohan Hedberg case L2CAP_LE_CREDITS: 5720fad5fc89SJohan Hedberg err = l2cap_le_credits(conn, cmd, cmd_len, data); 5721fad5fc89SJohan Hedberg break; 5722fad5fc89SJohan Hedberg 57233defe01aSJohan Hedberg case L2CAP_DISCONN_REQ: 5724b5ecba64SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data); 5725b5ecba64SJohan Hedberg break; 57263defe01aSJohan Hedberg 57273defe01aSJohan Hedberg case L2CAP_DISCONN_RSP: 57283defe01aSJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data); 5729b5ecba64SJohan Hedberg break; 57303defe01aSJohan Hedberg 57313300d9a9SClaudio Takahasi default: 57323300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code); 5733b5ecba64SJohan Hedberg err = -EINVAL; 5734b5ecba64SJohan Hedberg break; 57353300d9a9SClaudio Takahasi } 5736b5ecba64SJohan Hedberg 5737b5ecba64SJohan Hedberg return err; 57383300d9a9SClaudio Takahasi } 57393300d9a9SClaudio Takahasi 5740c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn, 5741c5623556SJohan Hedberg struct sk_buff *skb) 5742c5623556SJohan Hedberg { 574369c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon; 57444f3e219dSMarcel Holtmann struct l2cap_cmd_hdr *cmd; 57454f3e219dSMarcel Holtmann u16 len; 5746c5623556SJohan Hedberg int err; 5747c5623556SJohan Hedberg 574869c4e4e8SJohan Hedberg if (hcon->type != LE_LINK) 57493b166295SMarcel Holtmann goto drop; 575069c4e4e8SJohan Hedberg 57514f3e219dSMarcel Holtmann if (skb->len < L2CAP_CMD_HDR_SIZE) 57524f3e219dSMarcel Holtmann goto drop; 5753c5623556SJohan Hedberg 57544f3e219dSMarcel Holtmann cmd = (void *) skb->data; 57554f3e219dSMarcel Holtmann skb_pull(skb, L2CAP_CMD_HDR_SIZE); 5756c5623556SJohan Hedberg 57574f3e219dSMarcel Holtmann len = le16_to_cpu(cmd->len); 5758c5623556SJohan Hedberg 57594f3e219dSMarcel Holtmann BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident); 57604f3e219dSMarcel Holtmann 57614f3e219dSMarcel Holtmann if (len != skb->len || !cmd->ident) { 5762c5623556SJohan Hedberg BT_DBG("corrupted command"); 57634f3e219dSMarcel Holtmann goto drop; 5764c5623556SJohan Hedberg } 5765c5623556SJohan Hedberg 5766203e639eSJohan Hedberg err = l2cap_le_sig_cmd(conn, cmd, len, skb->data); 5767c5623556SJohan Hedberg if (err) { 5768c5623556SJohan Hedberg struct l2cap_cmd_rej_unk rej; 5769c5623556SJohan Hedberg 5770c5623556SJohan Hedberg BT_ERR("Wrong link type (%d)", err); 5771c5623556SJohan Hedberg 5772dcf4adbfSJoe Perches rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 57734f3e219dSMarcel Holtmann l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 5774c5623556SJohan Hedberg sizeof(rej), &rej); 5775c5623556SJohan Hedberg } 5776c5623556SJohan Hedberg 57773b166295SMarcel Holtmann drop: 5778c5623556SJohan Hedberg kfree_skb(skb); 5779c5623556SJohan Hedberg } 5780c5623556SJohan Hedberg 57813300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn, 57823300d9a9SClaudio Takahasi struct sk_buff *skb) 57830a708f8fSGustavo F. Padovan { 578469c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon; 57850a708f8fSGustavo F. Padovan u8 *data = skb->data; 57860a708f8fSGustavo F. Padovan int len = skb->len; 57870a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr cmd; 57883300d9a9SClaudio Takahasi int err; 57890a708f8fSGustavo F. Padovan 57900a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb); 57910a708f8fSGustavo F. Padovan 579269c4e4e8SJohan Hedberg if (hcon->type != ACL_LINK) 57933b166295SMarcel Holtmann goto drop; 579469c4e4e8SJohan Hedberg 57950a708f8fSGustavo F. Padovan while (len >= L2CAP_CMD_HDR_SIZE) { 57960a708f8fSGustavo F. Padovan u16 cmd_len; 57970a708f8fSGustavo F. Padovan memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); 57980a708f8fSGustavo F. Padovan data += L2CAP_CMD_HDR_SIZE; 57990a708f8fSGustavo F. Padovan len -= L2CAP_CMD_HDR_SIZE; 58000a708f8fSGustavo F. Padovan 58010a708f8fSGustavo F. Padovan cmd_len = le16_to_cpu(cmd.len); 58020a708f8fSGustavo F. Padovan 58032d792818SGustavo Padovan BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, 58042d792818SGustavo Padovan cmd.ident); 58050a708f8fSGustavo F. Padovan 58060a708f8fSGustavo F. Padovan if (cmd_len > len || !cmd.ident) { 58070a708f8fSGustavo F. Padovan BT_DBG("corrupted command"); 58080a708f8fSGustavo F. Padovan break; 58090a708f8fSGustavo F. Padovan } 58100a708f8fSGustavo F. Padovan 58113300d9a9SClaudio Takahasi err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data); 58120a708f8fSGustavo F. Padovan if (err) { 5813e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk rej; 58142c6d1a2eSGustavo F. Padovan 58152c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err); 58160a708f8fSGustavo F. Padovan 5817dcf4adbfSJoe Perches rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 58182d792818SGustavo Padovan l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, 58192d792818SGustavo Padovan sizeof(rej), &rej); 58200a708f8fSGustavo F. Padovan } 58210a708f8fSGustavo F. Padovan 58220a708f8fSGustavo F. Padovan data += cmd_len; 58230a708f8fSGustavo F. Padovan len -= cmd_len; 58240a708f8fSGustavo F. Padovan } 58250a708f8fSGustavo F. Padovan 58263b166295SMarcel Holtmann drop: 58270a708f8fSGustavo F. Padovan kfree_skb(skb); 58280a708f8fSGustavo F. Padovan } 58290a708f8fSGustavo F. Padovan 583047d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) 58310a708f8fSGustavo F. Padovan { 58320a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs; 5833e4ca6d98SAndrei Emeltchenko int hdr_size; 5834e4ca6d98SAndrei Emeltchenko 5835e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 5836e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE; 5837e4ca6d98SAndrei Emeltchenko else 5838e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE; 58390a708f8fSGustavo F. Padovan 584047d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 584103a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE); 58420a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len); 58430a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); 58440a708f8fSGustavo F. Padovan 58450a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs) 58460a708f8fSGustavo F. Padovan return -EBADMSG; 58470a708f8fSGustavo F. Padovan } 58480a708f8fSGustavo F. Padovan return 0; 58490a708f8fSGustavo F. Padovan } 58500a708f8fSGustavo F. Padovan 58516ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) 58520a708f8fSGustavo F. Padovan { 5853e31f7633SMat Martineau struct l2cap_ctrl control; 58540a708f8fSGustavo F. Padovan 5855e31f7633SMat Martineau BT_DBG("chan %p", chan); 58560a708f8fSGustavo F. Padovan 5857e31f7633SMat Martineau memset(&control, 0, sizeof(control)); 5858e31f7633SMat Martineau control.sframe = 1; 5859e31f7633SMat Martineau control.final = 1; 5860e31f7633SMat Martineau control.reqseq = chan->buffer_seq; 5861e31f7633SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 58620a708f8fSGustavo F. Padovan 5863e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 5864e31f7633SMat Martineau control.super = L2CAP_SUPER_RNR; 5865e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 58660a708f8fSGustavo F. Padovan } 58670a708f8fSGustavo F. Padovan 5868e31f7633SMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 5869e31f7633SMat Martineau chan->unacked_frames > 0) 5870e31f7633SMat Martineau __set_retrans_timer(chan); 58710a708f8fSGustavo F. Padovan 5872e31f7633SMat Martineau /* Send pending iframes */ 5873525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 58740a708f8fSGustavo F. Padovan 5875e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 5876e31f7633SMat Martineau test_bit(CONN_SEND_FBIT, &chan->conn_state)) { 5877e31f7633SMat Martineau /* F-bit wasn't sent in an s-frame or i-frame yet, so 5878e31f7633SMat Martineau * send it now. 5879e31f7633SMat Martineau */ 5880e31f7633SMat Martineau control.super = L2CAP_SUPER_RR; 5881e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 58820a708f8fSGustavo F. Padovan } 58830a708f8fSGustavo F. Padovan } 58840a708f8fSGustavo F. Padovan 58852d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag, 58862d792818SGustavo Padovan struct sk_buff **last_frag) 58870a708f8fSGustavo F. Padovan { 588884084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments 588984084a31SMat Martineau * skb->data_len reflects only data in fragments 589084084a31SMat Martineau */ 589184084a31SMat Martineau if (!skb_has_frag_list(skb)) 589284084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag; 589384084a31SMat Martineau 589484084a31SMat Martineau new_frag->next = NULL; 589584084a31SMat Martineau 589684084a31SMat Martineau (*last_frag)->next = new_frag; 589784084a31SMat Martineau *last_frag = new_frag; 589884084a31SMat Martineau 589984084a31SMat Martineau skb->len += new_frag->len; 590084084a31SMat Martineau skb->data_len += new_frag->len; 590184084a31SMat Martineau skb->truesize += new_frag->truesize; 590284084a31SMat Martineau } 590384084a31SMat Martineau 59044b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, 59054b51dae9SMat Martineau struct l2cap_ctrl *control) 590684084a31SMat Martineau { 590784084a31SMat Martineau int err = -EINVAL; 59080a708f8fSGustavo F. Padovan 59094b51dae9SMat Martineau switch (control->sar) { 59107e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED: 591184084a31SMat Martineau if (chan->sdu) 591284084a31SMat Martineau break; 59130a708f8fSGustavo F. Padovan 591480b98027SGustavo Padovan err = chan->ops->recv(chan, skb); 591584084a31SMat Martineau break; 59160a708f8fSGustavo F. Padovan 59177e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START: 591884084a31SMat Martineau if (chan->sdu) 591984084a31SMat Martineau break; 59200a708f8fSGustavo F. Padovan 5921dbb50887SDaniel Borkmann if (!pskb_may_pull(skb, L2CAP_SDULEN_SIZE)) 5922dbb50887SDaniel Borkmann break; 5923dbb50887SDaniel Borkmann 59246f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data); 592503a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE); 59260a708f8fSGustavo F. Padovan 592784084a31SMat Martineau if (chan->sdu_len > chan->imtu) { 592884084a31SMat Martineau err = -EMSGSIZE; 592984084a31SMat Martineau break; 593084084a31SMat Martineau } 59310a708f8fSGustavo F. Padovan 593284084a31SMat Martineau if (skb->len >= chan->sdu_len) 593384084a31SMat Martineau break; 593484084a31SMat Martineau 593584084a31SMat Martineau chan->sdu = skb; 593684084a31SMat Martineau chan->sdu_last_frag = skb; 593784084a31SMat Martineau 593884084a31SMat Martineau skb = NULL; 593984084a31SMat Martineau err = 0; 59400a708f8fSGustavo F. Padovan break; 59410a708f8fSGustavo F. Padovan 59427e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE: 59436f61fd47SGustavo F. Padovan if (!chan->sdu) 594484084a31SMat Martineau break; 59450a708f8fSGustavo F. Padovan 594684084a31SMat Martineau append_skb_frag(chan->sdu, skb, 594784084a31SMat Martineau &chan->sdu_last_frag); 594884084a31SMat Martineau skb = NULL; 59490a708f8fSGustavo F. Padovan 595084084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len) 595184084a31SMat Martineau break; 59520a708f8fSGustavo F. Padovan 595384084a31SMat Martineau err = 0; 59540a708f8fSGustavo F. Padovan break; 59550a708f8fSGustavo F. Padovan 59567e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END: 59576f61fd47SGustavo F. Padovan if (!chan->sdu) 595884084a31SMat Martineau break; 59590a708f8fSGustavo F. Padovan 596084084a31SMat Martineau append_skb_frag(chan->sdu, skb, 596184084a31SMat Martineau &chan->sdu_last_frag); 596284084a31SMat Martineau skb = NULL; 59630a708f8fSGustavo F. Padovan 596484084a31SMat Martineau if (chan->sdu->len != chan->sdu_len) 596584084a31SMat Martineau break; 59660a708f8fSGustavo F. Padovan 596780b98027SGustavo Padovan err = chan->ops->recv(chan, chan->sdu); 59680a708f8fSGustavo F. Padovan 596984084a31SMat Martineau if (!err) { 597084084a31SMat Martineau /* Reassembly complete */ 597184084a31SMat Martineau chan->sdu = NULL; 597284084a31SMat Martineau chan->sdu_last_frag = NULL; 597384084a31SMat Martineau chan->sdu_len = 0; 59740a708f8fSGustavo F. Padovan } 59750a708f8fSGustavo F. Padovan break; 59760a708f8fSGustavo F. Padovan } 59770a708f8fSGustavo F. Padovan 597884084a31SMat Martineau if (err) { 59790a708f8fSGustavo F. Padovan kfree_skb(skb); 59806f61fd47SGustavo F. Padovan kfree_skb(chan->sdu); 59816f61fd47SGustavo F. Padovan chan->sdu = NULL; 598284084a31SMat Martineau chan->sdu_last_frag = NULL; 598384084a31SMat Martineau chan->sdu_len = 0; 598484084a31SMat Martineau } 59850a708f8fSGustavo F. Padovan 598684084a31SMat Martineau return err; 59870a708f8fSGustavo F. Padovan } 59880a708f8fSGustavo F. Padovan 598932b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan) 599032b32735SMat Martineau { 599132b32735SMat Martineau /* Placeholder */ 599232b32735SMat Martineau return 0; 599332b32735SMat Martineau } 599432b32735SMat Martineau 5995e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 59960a708f8fSGustavo F. Padovan { 599761aa4f5bSMat Martineau u8 event; 599861aa4f5bSMat Martineau 599961aa4f5bSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 600061aa4f5bSMat Martineau return; 600161aa4f5bSMat Martineau 600261aa4f5bSMat Martineau event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR; 6003401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, event); 60040a708f8fSGustavo F. Padovan } 60050a708f8fSGustavo F. Padovan 6006d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan) 6007d2a7ac5dSMat Martineau { 600863838725SMat Martineau int err = 0; 600963838725SMat Martineau /* Pass sequential frames to l2cap_reassemble_sdu() 601063838725SMat Martineau * until a gap is encountered. 601163838725SMat Martineau */ 601263838725SMat Martineau 601363838725SMat Martineau BT_DBG("chan %p", chan); 601463838725SMat Martineau 601563838725SMat Martineau while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 601663838725SMat Martineau struct sk_buff *skb; 601763838725SMat Martineau BT_DBG("Searching for skb with txseq %d (queue len %d)", 601863838725SMat Martineau chan->buffer_seq, skb_queue_len(&chan->srej_q)); 601963838725SMat Martineau 602063838725SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq); 602163838725SMat Martineau 602263838725SMat Martineau if (!skb) 602363838725SMat Martineau break; 602463838725SMat Martineau 602563838725SMat Martineau skb_unlink(skb, &chan->srej_q); 602663838725SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 6027a4368ff3SJohan Hedberg err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->l2cap); 602863838725SMat Martineau if (err) 602963838725SMat Martineau break; 603063838725SMat Martineau } 603163838725SMat Martineau 603263838725SMat Martineau if (skb_queue_empty(&chan->srej_q)) { 603363838725SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 603463838725SMat Martineau l2cap_send_ack(chan); 603563838725SMat Martineau } 603663838725SMat Martineau 603763838725SMat Martineau return err; 6038d2a7ac5dSMat Martineau } 6039d2a7ac5dSMat Martineau 6040d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan, 6041d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 6042d2a7ac5dSMat Martineau { 6043f80842a8SMat Martineau struct sk_buff *skb; 6044f80842a8SMat Martineau 6045f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 6046f80842a8SMat Martineau 6047f80842a8SMat Martineau if (control->reqseq == chan->next_tx_seq) { 6048f80842a8SMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 60495e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6050f80842a8SMat Martineau return; 6051f80842a8SMat Martineau } 6052f80842a8SMat Martineau 6053f80842a8SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 6054f80842a8SMat Martineau 6055f80842a8SMat Martineau if (skb == NULL) { 6056f80842a8SMat Martineau BT_DBG("Seq %d not available for retransmission", 6057f80842a8SMat Martineau control->reqseq); 6058f80842a8SMat Martineau return; 6059f80842a8SMat Martineau } 6060f80842a8SMat Martineau 6061a4368ff3SJohan Hedberg if (chan->max_tx != 0 && bt_cb(skb)->l2cap.retries >= chan->max_tx) { 6062f80842a8SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 60635e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6064f80842a8SMat Martineau return; 6065f80842a8SMat Martineau } 6066f80842a8SMat Martineau 6067f80842a8SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6068f80842a8SMat Martineau 6069f80842a8SMat Martineau if (control->poll) { 6070f80842a8SMat Martineau l2cap_pass_to_tx(chan, control); 6071f80842a8SMat Martineau 6072f80842a8SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6073f80842a8SMat Martineau l2cap_retransmit(chan, control); 6074f80842a8SMat Martineau l2cap_ertm_send(chan); 6075f80842a8SMat Martineau 6076f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 6077f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 6078f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 6079f80842a8SMat Martineau } 6080f80842a8SMat Martineau } else { 6081f80842a8SMat Martineau l2cap_pass_to_tx_fbit(chan, control); 6082f80842a8SMat Martineau 6083f80842a8SMat Martineau if (control->final) { 6084f80842a8SMat Martineau if (chan->srej_save_reqseq != control->reqseq || 6085f80842a8SMat Martineau !test_and_clear_bit(CONN_SREJ_ACT, 6086f80842a8SMat Martineau &chan->conn_state)) 6087f80842a8SMat Martineau l2cap_retransmit(chan, control); 6088f80842a8SMat Martineau } else { 6089f80842a8SMat Martineau l2cap_retransmit(chan, control); 6090f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 6091f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 6092f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 6093f80842a8SMat Martineau } 6094f80842a8SMat Martineau } 6095f80842a8SMat Martineau } 6096d2a7ac5dSMat Martineau } 6097d2a7ac5dSMat Martineau 6098d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan, 6099d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 6100d2a7ac5dSMat Martineau { 6101fcd289dfSMat Martineau struct sk_buff *skb; 6102fcd289dfSMat Martineau 6103fcd289dfSMat Martineau BT_DBG("chan %p, control %p", chan, control); 6104fcd289dfSMat Martineau 6105fcd289dfSMat Martineau if (control->reqseq == chan->next_tx_seq) { 6106fcd289dfSMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 61075e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6108fcd289dfSMat Martineau return; 6109fcd289dfSMat Martineau } 6110fcd289dfSMat Martineau 6111fcd289dfSMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 6112fcd289dfSMat Martineau 6113fcd289dfSMat Martineau if (chan->max_tx && skb && 6114a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries >= chan->max_tx) { 6115fcd289dfSMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 61165e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6117fcd289dfSMat Martineau return; 6118fcd289dfSMat Martineau } 6119fcd289dfSMat Martineau 6120fcd289dfSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6121fcd289dfSMat Martineau 6122fcd289dfSMat Martineau l2cap_pass_to_tx(chan, control); 6123fcd289dfSMat Martineau 6124fcd289dfSMat Martineau if (control->final) { 6125fcd289dfSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 6126fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 6127fcd289dfSMat Martineau } else { 6128fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 6129fcd289dfSMat Martineau l2cap_ertm_send(chan); 6130fcd289dfSMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) 6131fcd289dfSMat Martineau set_bit(CONN_REJ_ACT, &chan->conn_state); 6132fcd289dfSMat Martineau } 6133d2a7ac5dSMat Martineau } 6134d2a7ac5dSMat Martineau 61354b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) 61364b51dae9SMat Martineau { 61374b51dae9SMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 61384b51dae9SMat Martineau 61394b51dae9SMat Martineau BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq, 61404b51dae9SMat Martineau chan->expected_tx_seq); 61414b51dae9SMat Martineau 61424b51dae9SMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 61434b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 61444b51dae9SMat Martineau chan->tx_win) { 61454b51dae9SMat Martineau /* See notes below regarding "double poll" and 61464b51dae9SMat Martineau * invalid packets. 61474b51dae9SMat Martineau */ 61484b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 61494b51dae9SMat Martineau BT_DBG("Invalid/Ignore - after SREJ"); 61504b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 61514b51dae9SMat Martineau } else { 61524b51dae9SMat Martineau BT_DBG("Invalid - in window after SREJ sent"); 61534b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 61544b51dae9SMat Martineau } 61554b51dae9SMat Martineau } 61564b51dae9SMat Martineau 61574b51dae9SMat Martineau if (chan->srej_list.head == txseq) { 61584b51dae9SMat Martineau BT_DBG("Expected SREJ"); 61594b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED_SREJ; 61604b51dae9SMat Martineau } 61614b51dae9SMat Martineau 61624b51dae9SMat Martineau if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) { 61634b51dae9SMat Martineau BT_DBG("Duplicate SREJ - txseq already stored"); 61644b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE_SREJ; 61654b51dae9SMat Martineau } 61664b51dae9SMat Martineau 61674b51dae9SMat Martineau if (l2cap_seq_list_contains(&chan->srej_list, txseq)) { 61684b51dae9SMat Martineau BT_DBG("Unexpected SREJ - not requested"); 61694b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED_SREJ; 61704b51dae9SMat Martineau } 61714b51dae9SMat Martineau } 61724b51dae9SMat Martineau 61734b51dae9SMat Martineau if (chan->expected_tx_seq == txseq) { 61744b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 61754b51dae9SMat Martineau chan->tx_win) { 61764b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 61774b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 61784b51dae9SMat Martineau } else { 61794b51dae9SMat Martineau BT_DBG("Expected"); 61804b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED; 61814b51dae9SMat Martineau } 61824b51dae9SMat Martineau } 61834b51dae9SMat Martineau 61844b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) < 61852d792818SGustavo Padovan __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) { 61864b51dae9SMat Martineau BT_DBG("Duplicate - expected_tx_seq later than txseq"); 61874b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE; 61884b51dae9SMat Martineau } 61894b51dae9SMat Martineau 61904b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) { 61914b51dae9SMat Martineau /* A source of invalid packets is a "double poll" condition, 61924b51dae9SMat Martineau * where delays cause us to send multiple poll packets. If 61934b51dae9SMat Martineau * the remote stack receives and processes both polls, 61944b51dae9SMat Martineau * sequence numbers can wrap around in such a way that a 61954b51dae9SMat Martineau * resent frame has a sequence number that looks like new data 61964b51dae9SMat Martineau * with a sequence gap. This would trigger an erroneous SREJ 61974b51dae9SMat Martineau * request. 61984b51dae9SMat Martineau * 61994b51dae9SMat Martineau * Fortunately, this is impossible with a tx window that's 62004b51dae9SMat Martineau * less than half of the maximum sequence number, which allows 62014b51dae9SMat Martineau * invalid frames to be safely ignored. 62024b51dae9SMat Martineau * 62034b51dae9SMat Martineau * With tx window sizes greater than half of the tx window 62044b51dae9SMat Martineau * maximum, the frame is invalid and cannot be ignored. This 62054b51dae9SMat Martineau * causes a disconnect. 62064b51dae9SMat Martineau */ 62074b51dae9SMat Martineau 62084b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 62094b51dae9SMat Martineau BT_DBG("Invalid/Ignore - txseq outside tx window"); 62104b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 62114b51dae9SMat Martineau } else { 62124b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 62134b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 62144b51dae9SMat Martineau } 62154b51dae9SMat Martineau } else { 62164b51dae9SMat Martineau BT_DBG("Unexpected - txseq indicates missing frames"); 62174b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED; 62184b51dae9SMat Martineau } 62194b51dae9SMat Martineau } 62204b51dae9SMat Martineau 6221d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan, 6222d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 6223d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 6224d2a7ac5dSMat Martineau { 6225d2a7ac5dSMat Martineau int err = 0; 6226941247f9SPeter Senna Tschudin bool skb_in_use = false; 6227d2a7ac5dSMat Martineau 6228d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 6229d2a7ac5dSMat Martineau event); 6230d2a7ac5dSMat Martineau 6231d2a7ac5dSMat Martineau switch (event) { 6232d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 6233d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, control->txseq)) { 6234d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 6235d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6236d2a7ac5dSMat Martineau 6237d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 6238d2a7ac5dSMat Martineau BT_DBG("Busy, discarding expected seq %d", 6239d2a7ac5dSMat Martineau control->txseq); 6240d2a7ac5dSMat Martineau break; 6241d2a7ac5dSMat Martineau } 6242d2a7ac5dSMat Martineau 6243d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, 6244d2a7ac5dSMat Martineau control->txseq); 6245d2a7ac5dSMat Martineau 6246d2a7ac5dSMat Martineau chan->buffer_seq = chan->expected_tx_seq; 6247941247f9SPeter Senna Tschudin skb_in_use = true; 6248d2a7ac5dSMat Martineau 6249d2a7ac5dSMat Martineau err = l2cap_reassemble_sdu(chan, skb, control); 6250d2a7ac5dSMat Martineau if (err) 6251d2a7ac5dSMat Martineau break; 6252d2a7ac5dSMat Martineau 6253d2a7ac5dSMat Martineau if (control->final) { 6254d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 6255d2a7ac5dSMat Martineau &chan->conn_state)) { 6256d2a7ac5dSMat Martineau control->final = 0; 6257d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6258d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6259d2a7ac5dSMat Martineau } 6260d2a7ac5dSMat Martineau } 6261d2a7ac5dSMat Martineau 6262d2a7ac5dSMat Martineau if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 6263d2a7ac5dSMat Martineau l2cap_send_ack(chan); 6264d2a7ac5dSMat Martineau break; 6265d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 6266d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6267d2a7ac5dSMat Martineau 6268d2a7ac5dSMat Martineau /* Can't issue SREJ frames in the local busy state. 6269d2a7ac5dSMat Martineau * Drop this frame, it will be seen as missing 6270d2a7ac5dSMat Martineau * when local busy is exited. 6271d2a7ac5dSMat Martineau */ 6272d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 6273d2a7ac5dSMat Martineau BT_DBG("Busy, discarding unexpected seq %d", 6274d2a7ac5dSMat Martineau control->txseq); 6275d2a7ac5dSMat Martineau break; 6276d2a7ac5dSMat Martineau } 6277d2a7ac5dSMat Martineau 6278d2a7ac5dSMat Martineau /* There was a gap in the sequence, so an SREJ 6279d2a7ac5dSMat Martineau * must be sent for each missing frame. The 6280d2a7ac5dSMat Martineau * current frame is stored for later use. 6281d2a7ac5dSMat Martineau */ 6282d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6283941247f9SPeter Senna Tschudin skb_in_use = true; 6284d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6285d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6286d2a7ac5dSMat Martineau 6287d2a7ac5dSMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 6288d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 6289d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 6290d2a7ac5dSMat Martineau 6291d2a7ac5dSMat Martineau chan->rx_state = L2CAP_RX_STATE_SREJ_SENT; 6292d2a7ac5dSMat Martineau break; 6293d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 6294d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6295d2a7ac5dSMat Martineau break; 6296d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 6297d2a7ac5dSMat Martineau break; 6298d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 6299d2a7ac5dSMat Martineau default: 63005e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6301d2a7ac5dSMat Martineau break; 6302d2a7ac5dSMat Martineau } 6303d2a7ac5dSMat Martineau break; 6304d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 6305d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6306d2a7ac5dSMat Martineau if (control->final) { 6307d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6308d2a7ac5dSMat Martineau 6309e6a3ee6eSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) && 6310e6a3ee6eSMat Martineau !__chan_is_moving(chan)) { 6311d2a7ac5dSMat Martineau control->final = 0; 6312d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6313d2a7ac5dSMat Martineau } 6314d2a7ac5dSMat Martineau 6315d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6316d2a7ac5dSMat Martineau } else if (control->poll) { 6317d2a7ac5dSMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 6318d2a7ac5dSMat Martineau } else { 6319d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6320d2a7ac5dSMat Martineau &chan->conn_state) && 6321d2a7ac5dSMat Martineau chan->unacked_frames) 6322d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6323d2a7ac5dSMat Martineau 6324d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6325d2a7ac5dSMat Martineau } 6326d2a7ac5dSMat Martineau break; 6327d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 6328d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6329d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6330d2a7ac5dSMat Martineau if (control && control->poll) { 6331d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6332d2a7ac5dSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 6333d2a7ac5dSMat Martineau } 6334d2a7ac5dSMat Martineau __clear_retrans_timer(chan); 6335d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 6336d2a7ac5dSMat Martineau break; 6337d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 6338d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 6339d2a7ac5dSMat Martineau break; 6340d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 6341d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 6342d2a7ac5dSMat Martineau break; 6343d2a7ac5dSMat Martineau default: 6344d2a7ac5dSMat Martineau break; 6345d2a7ac5dSMat Martineau } 6346d2a7ac5dSMat Martineau 6347d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 6348d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 6349d2a7ac5dSMat Martineau kfree_skb(skb); 6350d2a7ac5dSMat Martineau } 6351d2a7ac5dSMat Martineau 6352d2a7ac5dSMat Martineau return err; 6353d2a7ac5dSMat Martineau } 6354d2a7ac5dSMat Martineau 6355d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, 6356d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 6357d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 6358d2a7ac5dSMat Martineau { 6359d2a7ac5dSMat Martineau int err = 0; 6360d2a7ac5dSMat Martineau u16 txseq = control->txseq; 6361941247f9SPeter Senna Tschudin bool skb_in_use = false; 6362d2a7ac5dSMat Martineau 6363d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 6364d2a7ac5dSMat Martineau event); 6365d2a7ac5dSMat Martineau 6366d2a7ac5dSMat Martineau switch (event) { 6367d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 6368d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, txseq)) { 6369d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 6370d2a7ac5dSMat Martineau /* Keep frame for reassembly later */ 6371d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6372d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6373941247f9SPeter Senna Tschudin skb_in_use = true; 6374d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6375d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6376d2a7ac5dSMat Martineau 6377d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 6378d2a7ac5dSMat Martineau break; 6379d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED_SREJ: 6380d2a7ac5dSMat Martineau l2cap_seq_list_pop(&chan->srej_list); 6381d2a7ac5dSMat Martineau 6382d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6383d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6384941247f9SPeter Senna Tschudin skb_in_use = true; 6385d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6386d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6387d2a7ac5dSMat Martineau 6388d2a7ac5dSMat Martineau err = l2cap_rx_queued_iframes(chan); 6389d2a7ac5dSMat Martineau if (err) 6390d2a7ac5dSMat Martineau break; 6391d2a7ac5dSMat Martineau 6392d2a7ac5dSMat Martineau break; 6393d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 6394d2a7ac5dSMat Martineau /* Got a frame that can't be reassembled yet. 6395d2a7ac5dSMat Martineau * Save it for later, and send SREJs to cover 6396d2a7ac5dSMat Martineau * the missing frames. 6397d2a7ac5dSMat Martineau */ 6398d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6399941247f9SPeter Senna Tschudin skb_in_use = true; 6400d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6401d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6402d2a7ac5dSMat Martineau 6403d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6404d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 6405d2a7ac5dSMat Martineau break; 6406d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED_SREJ: 6407d2a7ac5dSMat Martineau /* This frame was requested with an SREJ, but 6408d2a7ac5dSMat Martineau * some expected retransmitted frames are 6409d2a7ac5dSMat Martineau * missing. Request retransmission of missing 6410d2a7ac5dSMat Martineau * SREJ'd frames. 6411d2a7ac5dSMat Martineau */ 6412d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6413941247f9SPeter Senna Tschudin skb_in_use = true; 6414d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6415d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6416d2a7ac5dSMat Martineau 6417d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6418d2a7ac5dSMat Martineau l2cap_send_srej_list(chan, control->txseq); 6419d2a7ac5dSMat Martineau break; 6420d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE_SREJ: 6421d2a7ac5dSMat Martineau /* We've already queued this frame. Drop this copy. */ 6422d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6423d2a7ac5dSMat Martineau break; 6424d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 6425d2a7ac5dSMat Martineau /* Expecting a later sequence number, so this frame 6426d2a7ac5dSMat Martineau * was already received. Ignore it completely. 6427d2a7ac5dSMat Martineau */ 6428d2a7ac5dSMat Martineau break; 6429d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 6430d2a7ac5dSMat Martineau break; 6431d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 6432d2a7ac5dSMat Martineau default: 64335e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6434d2a7ac5dSMat Martineau break; 6435d2a7ac5dSMat Martineau } 6436d2a7ac5dSMat Martineau break; 6437d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 6438d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6439d2a7ac5dSMat Martineau if (control->final) { 6440d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6441d2a7ac5dSMat Martineau 6442d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 6443d2a7ac5dSMat Martineau &chan->conn_state)) { 6444d2a7ac5dSMat Martineau control->final = 0; 6445d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6446d2a7ac5dSMat Martineau } 6447d2a7ac5dSMat Martineau 6448d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6449d2a7ac5dSMat Martineau } else if (control->poll) { 6450d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6451d2a7ac5dSMat Martineau &chan->conn_state) && 6452d2a7ac5dSMat Martineau chan->unacked_frames) { 6453d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6454d2a7ac5dSMat Martineau } 6455d2a7ac5dSMat Martineau 6456d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6457d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 6458d2a7ac5dSMat Martineau } else { 6459d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6460d2a7ac5dSMat Martineau &chan->conn_state) && 6461d2a7ac5dSMat Martineau chan->unacked_frames) 6462d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6463d2a7ac5dSMat Martineau 6464d2a7ac5dSMat Martineau l2cap_send_ack(chan); 6465d2a7ac5dSMat Martineau } 6466d2a7ac5dSMat Martineau break; 6467d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 6468d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6469d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6470d2a7ac5dSMat Martineau if (control->poll) { 6471d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 6472d2a7ac5dSMat Martineau } else { 6473d2a7ac5dSMat Martineau struct l2cap_ctrl rr_control; 6474d2a7ac5dSMat Martineau memset(&rr_control, 0, sizeof(rr_control)); 6475d2a7ac5dSMat Martineau rr_control.sframe = 1; 6476d2a7ac5dSMat Martineau rr_control.super = L2CAP_SUPER_RR; 6477d2a7ac5dSMat Martineau rr_control.reqseq = chan->buffer_seq; 6478d2a7ac5dSMat Martineau l2cap_send_sframe(chan, &rr_control); 6479d2a7ac5dSMat Martineau } 6480d2a7ac5dSMat Martineau 6481d2a7ac5dSMat Martineau break; 6482d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 6483d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 6484d2a7ac5dSMat Martineau break; 6485d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 6486d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 6487d2a7ac5dSMat Martineau break; 6488d2a7ac5dSMat Martineau } 6489d2a7ac5dSMat Martineau 6490d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 6491d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 6492d2a7ac5dSMat Martineau kfree_skb(skb); 6493d2a7ac5dSMat Martineau } 6494d2a7ac5dSMat Martineau 6495d2a7ac5dSMat Martineau return err; 6496d2a7ac5dSMat Martineau } 6497d2a7ac5dSMat Martineau 649832b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan) 649932b32735SMat Martineau { 650032b32735SMat Martineau BT_DBG("chan %p", chan); 650132b32735SMat Martineau 650232b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 650332b32735SMat Martineau 650432b32735SMat Martineau if (chan->hs_hcon) 650532b32735SMat Martineau chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; 650632b32735SMat Martineau else 650732b32735SMat Martineau chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; 650832b32735SMat Martineau 650932b32735SMat Martineau return l2cap_resegment(chan); 651032b32735SMat Martineau } 651132b32735SMat Martineau 651232b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan, 651332b32735SMat Martineau struct l2cap_ctrl *control, 651432b32735SMat Martineau struct sk_buff *skb, u8 event) 651532b32735SMat Martineau { 651632b32735SMat Martineau int err; 651732b32735SMat Martineau 651832b32735SMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 651932b32735SMat Martineau event); 652032b32735SMat Martineau 652132b32735SMat Martineau if (!control->poll) 652232b32735SMat Martineau return -EPROTO; 652332b32735SMat Martineau 652432b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq); 652532b32735SMat Martineau 652632b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q)) 652732b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q); 652832b32735SMat Martineau else 652932b32735SMat Martineau chan->tx_send_head = NULL; 653032b32735SMat Martineau 653132b32735SMat Martineau /* Rewind next_tx_seq to the point expected 653232b32735SMat Martineau * by the receiver. 653332b32735SMat Martineau */ 653432b32735SMat Martineau chan->next_tx_seq = control->reqseq; 653532b32735SMat Martineau chan->unacked_frames = 0; 653632b32735SMat Martineau 653732b32735SMat Martineau err = l2cap_finish_move(chan); 653832b32735SMat Martineau if (err) 653932b32735SMat Martineau return err; 654032b32735SMat Martineau 654132b32735SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 654232b32735SMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 654332b32735SMat Martineau 654432b32735SMat Martineau if (event == L2CAP_EV_RECV_IFRAME) 654532b32735SMat Martineau return -EPROTO; 654632b32735SMat Martineau 654732b32735SMat Martineau return l2cap_rx_state_recv(chan, control, NULL, event); 654832b32735SMat Martineau } 654932b32735SMat Martineau 655032b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan, 655132b32735SMat Martineau struct l2cap_ctrl *control, 655232b32735SMat Martineau struct sk_buff *skb, u8 event) 655332b32735SMat Martineau { 655432b32735SMat Martineau int err; 655532b32735SMat Martineau 655632b32735SMat Martineau if (!control->final) 655732b32735SMat Martineau return -EPROTO; 655832b32735SMat Martineau 655932b32735SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 656032b32735SMat Martineau 656132b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 656232b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq); 656332b32735SMat Martineau 656432b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q)) 656532b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q); 656632b32735SMat Martineau else 656732b32735SMat Martineau chan->tx_send_head = NULL; 656832b32735SMat Martineau 656932b32735SMat Martineau /* Rewind next_tx_seq to the point expected 657032b32735SMat Martineau * by the receiver. 657132b32735SMat Martineau */ 657232b32735SMat Martineau chan->next_tx_seq = control->reqseq; 657332b32735SMat Martineau chan->unacked_frames = 0; 657432b32735SMat Martineau 657532b32735SMat Martineau if (chan->hs_hcon) 657632b32735SMat Martineau chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; 657732b32735SMat Martineau else 657832b32735SMat Martineau chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; 657932b32735SMat Martineau 658032b32735SMat Martineau err = l2cap_resegment(chan); 658132b32735SMat Martineau 658232b32735SMat Martineau if (!err) 658332b32735SMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 658432b32735SMat Martineau 658532b32735SMat Martineau return err; 658632b32735SMat Martineau } 658732b32735SMat Martineau 6588d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq) 6589d2a7ac5dSMat Martineau { 6590d2a7ac5dSMat Martineau /* Make sure reqseq is for a packet that has been sent but not acked */ 6591d2a7ac5dSMat Martineau u16 unacked; 6592d2a7ac5dSMat Martineau 6593d2a7ac5dSMat Martineau unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq); 6594d2a7ac5dSMat Martineau return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked; 6595d2a7ac5dSMat Martineau } 6596d2a7ac5dSMat Martineau 6597cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 6598cec8ab6eSMat Martineau struct sk_buff *skb, u8 event) 65990a708f8fSGustavo F. Padovan { 6600d2a7ac5dSMat Martineau int err = 0; 6601d2a7ac5dSMat Martineau 6602d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan, 6603d2a7ac5dSMat Martineau control, skb, event, chan->rx_state); 6604d2a7ac5dSMat Martineau 6605d2a7ac5dSMat Martineau if (__valid_reqseq(chan, control->reqseq)) { 6606d2a7ac5dSMat Martineau switch (chan->rx_state) { 6607d2a7ac5dSMat Martineau case L2CAP_RX_STATE_RECV: 6608d2a7ac5dSMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 6609d2a7ac5dSMat Martineau break; 6610d2a7ac5dSMat Martineau case L2CAP_RX_STATE_SREJ_SENT: 6611d2a7ac5dSMat Martineau err = l2cap_rx_state_srej_sent(chan, control, skb, 6612d2a7ac5dSMat Martineau event); 6613d2a7ac5dSMat Martineau break; 661432b32735SMat Martineau case L2CAP_RX_STATE_WAIT_P: 661532b32735SMat Martineau err = l2cap_rx_state_wait_p(chan, control, skb, event); 661632b32735SMat Martineau break; 661732b32735SMat Martineau case L2CAP_RX_STATE_WAIT_F: 661832b32735SMat Martineau err = l2cap_rx_state_wait_f(chan, control, skb, event); 661932b32735SMat Martineau break; 6620d2a7ac5dSMat Martineau default: 6621d2a7ac5dSMat Martineau /* shut it down */ 6622d2a7ac5dSMat Martineau break; 6623d2a7ac5dSMat Martineau } 6624d2a7ac5dSMat Martineau } else { 6625d2a7ac5dSMat Martineau BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d", 6626d2a7ac5dSMat Martineau control->reqseq, chan->next_tx_seq, 6627d2a7ac5dSMat Martineau chan->expected_ack_seq); 66285e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6629d2a7ac5dSMat Martineau } 6630d2a7ac5dSMat Martineau 6631d2a7ac5dSMat Martineau return err; 6632cec8ab6eSMat Martineau } 6633cec8ab6eSMat Martineau 6634cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 6635cec8ab6eSMat Martineau struct sk_buff *skb) 6636cec8ab6eSMat Martineau { 66374b51dae9SMat Martineau BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb, 66384b51dae9SMat Martineau chan->rx_state); 66394b51dae9SMat Martineau 66404b51dae9SMat Martineau if (l2cap_classify_txseq(chan, control->txseq) == 66414b51dae9SMat Martineau L2CAP_TXSEQ_EXPECTED) { 66424b51dae9SMat Martineau l2cap_pass_to_tx(chan, control); 66434b51dae9SMat Martineau 66444b51dae9SMat Martineau BT_DBG("buffer_seq %d->%d", chan->buffer_seq, 66454b51dae9SMat Martineau __next_seq(chan, chan->buffer_seq)); 66464b51dae9SMat Martineau 66474b51dae9SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 66484b51dae9SMat Martineau 66494b51dae9SMat Martineau l2cap_reassemble_sdu(chan, skb, control); 66504b51dae9SMat Martineau } else { 66514b51dae9SMat Martineau if (chan->sdu) { 66524b51dae9SMat Martineau kfree_skb(chan->sdu); 66534b51dae9SMat Martineau chan->sdu = NULL; 66544b51dae9SMat Martineau } 66554b51dae9SMat Martineau chan->sdu_last_frag = NULL; 66564b51dae9SMat Martineau chan->sdu_len = 0; 66574b51dae9SMat Martineau 66584b51dae9SMat Martineau if (skb) { 66594b51dae9SMat Martineau BT_DBG("Freeing %p", skb); 66604b51dae9SMat Martineau kfree_skb(skb); 66614b51dae9SMat Martineau } 66624b51dae9SMat Martineau } 66634b51dae9SMat Martineau 66644b51dae9SMat Martineau chan->last_acked_seq = control->txseq; 66654b51dae9SMat Martineau chan->expected_tx_seq = __next_seq(chan, control->txseq); 66664b51dae9SMat Martineau 66679a544210SPrasanna Karthik return 0; 6668cec8ab6eSMat Martineau } 6669cec8ab6eSMat Martineau 6670cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 6671cec8ab6eSMat Martineau { 6672a4368ff3SJohan Hedberg struct l2cap_ctrl *control = &bt_cb(skb)->l2cap; 6673cec8ab6eSMat Martineau u16 len; 6674cec8ab6eSMat Martineau u8 event; 66750a708f8fSGustavo F. Padovan 6676b76bbd66SMat Martineau __unpack_control(chan, skb); 6677b76bbd66SMat Martineau 66780a708f8fSGustavo F. Padovan len = skb->len; 66790a708f8fSGustavo F. Padovan 66800a708f8fSGustavo F. Padovan /* 66810a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here. 66820a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery 6683cec8ab6eSMat Martineau * procedures and ask for retransmission. 66840a708f8fSGustavo F. Padovan */ 668547d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 66860a708f8fSGustavo F. Padovan goto drop; 66870a708f8fSGustavo F. Padovan 6688cec8ab6eSMat Martineau if (!control->sframe && control->sar == L2CAP_SAR_START) 668903a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 66900a708f8fSGustavo F. Padovan 669147d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 669203a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 66930a708f8fSGustavo F. Padovan 669447d1ec61SGustavo F. Padovan if (len > chan->mps) { 66955e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 66960a708f8fSGustavo F. Padovan goto drop; 66970a708f8fSGustavo F. Padovan } 66980a708f8fSGustavo F. Padovan 6699dbb50887SDaniel Borkmann if ((chan->mode == L2CAP_MODE_ERTM || 6700dbb50887SDaniel Borkmann chan->mode == L2CAP_MODE_STREAMING) && sk_filter(chan->data, skb)) 6701dbb50887SDaniel Borkmann goto drop; 6702dbb50887SDaniel Borkmann 6703cec8ab6eSMat Martineau if (!control->sframe) { 6704cec8ab6eSMat Martineau int err; 67050a708f8fSGustavo F. Padovan 6706cec8ab6eSMat Martineau BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d", 6707cec8ab6eSMat Martineau control->sar, control->reqseq, control->final, 6708cec8ab6eSMat Martineau control->txseq); 6709836be934SAndrei Emeltchenko 6710cec8ab6eSMat Martineau /* Validate F-bit - F=0 always valid, F=1 only 6711cec8ab6eSMat Martineau * valid in TX WAIT_F 6712cec8ab6eSMat Martineau */ 6713cec8ab6eSMat Martineau if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F) 67140a708f8fSGustavo F. Padovan goto drop; 67150a708f8fSGustavo F. Padovan 6716cec8ab6eSMat Martineau if (chan->mode != L2CAP_MODE_STREAMING) { 6717cec8ab6eSMat Martineau event = L2CAP_EV_RECV_IFRAME; 6718cec8ab6eSMat Martineau err = l2cap_rx(chan, control, skb, event); 67190a708f8fSGustavo F. Padovan } else { 6720cec8ab6eSMat Martineau err = l2cap_stream_rx(chan, control, skb); 6721cec8ab6eSMat Martineau } 6722cec8ab6eSMat Martineau 6723cec8ab6eSMat Martineau if (err) 67245e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6725cec8ab6eSMat Martineau } else { 6726cec8ab6eSMat Martineau const u8 rx_func_to_event[4] = { 6727cec8ab6eSMat Martineau L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ, 6728cec8ab6eSMat Martineau L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ 6729cec8ab6eSMat Martineau }; 6730cec8ab6eSMat Martineau 6731cec8ab6eSMat Martineau /* Only I-frames are expected in streaming mode */ 6732cec8ab6eSMat Martineau if (chan->mode == L2CAP_MODE_STREAMING) 6733cec8ab6eSMat Martineau goto drop; 6734cec8ab6eSMat Martineau 6735cec8ab6eSMat Martineau BT_DBG("sframe reqseq %d, final %d, poll %d, super %d", 6736cec8ab6eSMat Martineau control->reqseq, control->final, control->poll, 6737cec8ab6eSMat Martineau control->super); 6738cec8ab6eSMat Martineau 67390a708f8fSGustavo F. Padovan if (len != 0) { 67401bb166e6SAndrei Emeltchenko BT_ERR("Trailing bytes: %d in sframe", len); 67415e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 67420a708f8fSGustavo F. Padovan goto drop; 67430a708f8fSGustavo F. Padovan } 67440a708f8fSGustavo F. Padovan 6745cec8ab6eSMat Martineau /* Validate F and P bits */ 6746cec8ab6eSMat Martineau if (control->final && (control->poll || 6747cec8ab6eSMat Martineau chan->tx_state != L2CAP_TX_STATE_WAIT_F)) 6748cec8ab6eSMat Martineau goto drop; 6749cec8ab6eSMat Martineau 6750cec8ab6eSMat Martineau event = rx_func_to_event[control->super]; 6751cec8ab6eSMat Martineau if (l2cap_rx(chan, control, skb, event)) 67525e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 67530a708f8fSGustavo F. Padovan } 67540a708f8fSGustavo F. Padovan 67550a708f8fSGustavo F. Padovan return 0; 67560a708f8fSGustavo F. Padovan 67570a708f8fSGustavo F. Padovan drop: 67580a708f8fSGustavo F. Padovan kfree_skb(skb); 67590a708f8fSGustavo F. Padovan return 0; 67600a708f8fSGustavo F. Padovan } 67610a708f8fSGustavo F. Padovan 6762b1c325c2SJohan Hedberg static void l2cap_chan_le_send_credits(struct l2cap_chan *chan) 6763b1c325c2SJohan Hedberg { 6764b1c325c2SJohan Hedberg struct l2cap_conn *conn = chan->conn; 6765b1c325c2SJohan Hedberg struct l2cap_le_credits pkt; 6766b1c325c2SJohan Hedberg u16 return_credits; 6767b1c325c2SJohan Hedberg 676896cd8eaaSLuiz Augusto von Dentz return_credits = ((chan->imtu / chan->mps) + 1) - chan->rx_credits; 6769b1c325c2SJohan Hedberg 677096cd8eaaSLuiz Augusto von Dentz if (!return_credits) 677196cd8eaaSLuiz Augusto von Dentz return; 6772b1c325c2SJohan Hedberg 6773b1c325c2SJohan Hedberg BT_DBG("chan %p returning %u credits to sender", chan, return_credits); 6774b1c325c2SJohan Hedberg 6775b1c325c2SJohan Hedberg chan->rx_credits += return_credits; 6776b1c325c2SJohan Hedberg 6777b1c325c2SJohan Hedberg pkt.cid = cpu_to_le16(chan->scid); 6778b1c325c2SJohan Hedberg pkt.credits = cpu_to_le16(return_credits); 6779b1c325c2SJohan Hedberg 6780b1c325c2SJohan Hedberg chan->ident = l2cap_get_ident(conn); 6781b1c325c2SJohan Hedberg 6782b1c325c2SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt); 6783b1c325c2SJohan Hedberg } 6784b1c325c2SJohan Hedberg 678596cd8eaaSLuiz Augusto von Dentz static int l2cap_le_recv(struct l2cap_chan *chan, struct sk_buff *skb) 678696cd8eaaSLuiz Augusto von Dentz { 678796cd8eaaSLuiz Augusto von Dentz int err; 678896cd8eaaSLuiz Augusto von Dentz 678996cd8eaaSLuiz Augusto von Dentz BT_DBG("SDU reassemble complete: chan %p skb->len %u", chan, skb->len); 679096cd8eaaSLuiz Augusto von Dentz 679196cd8eaaSLuiz Augusto von Dentz /* Wait recv to confirm reception before updating the credits */ 679296cd8eaaSLuiz Augusto von Dentz err = chan->ops->recv(chan, skb); 679396cd8eaaSLuiz Augusto von Dentz 679496cd8eaaSLuiz Augusto von Dentz /* Update credits whenever an SDU is received */ 679596cd8eaaSLuiz Augusto von Dentz l2cap_chan_le_send_credits(chan); 679696cd8eaaSLuiz Augusto von Dentz 679796cd8eaaSLuiz Augusto von Dentz return err; 679896cd8eaaSLuiz Augusto von Dentz } 679996cd8eaaSLuiz Augusto von Dentz 6800fad5fc89SJohan Hedberg static int l2cap_le_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 6801fad5fc89SJohan Hedberg { 6802aac23bf6SJohan Hedberg int err; 6803fad5fc89SJohan Hedberg 6804aac23bf6SJohan Hedberg if (!chan->rx_credits) { 6805aac23bf6SJohan Hedberg BT_ERR("No credits to receive LE L2CAP data"); 6806dfd9774cSJohan Hedberg l2cap_send_disconn_req(chan, ECONNRESET); 6807fad5fc89SJohan Hedberg return -ENOBUFS; 6808aac23bf6SJohan Hedberg } 6809aac23bf6SJohan Hedberg 6810aac23bf6SJohan Hedberg if (chan->imtu < skb->len) { 6811aac23bf6SJohan Hedberg BT_ERR("Too big LE L2CAP PDU"); 6812aac23bf6SJohan Hedberg return -ENOBUFS; 6813aac23bf6SJohan Hedberg } 6814fad5fc89SJohan Hedberg 6815fad5fc89SJohan Hedberg chan->rx_credits--; 6816fad5fc89SJohan Hedberg BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits); 6817fad5fc89SJohan Hedberg 681896cd8eaaSLuiz Augusto von Dentz /* Update if remote had run out of credits, this should only happens 681996cd8eaaSLuiz Augusto von Dentz * if the remote is not using the entire MPS. 682096cd8eaaSLuiz Augusto von Dentz */ 682196cd8eaaSLuiz Augusto von Dentz if (!chan->rx_credits) 6822fad5fc89SJohan Hedberg l2cap_chan_le_send_credits(chan); 6823fad5fc89SJohan Hedberg 6824aac23bf6SJohan Hedberg err = 0; 6825aac23bf6SJohan Hedberg 6826aac23bf6SJohan Hedberg if (!chan->sdu) { 6827aac23bf6SJohan Hedberg u16 sdu_len; 6828aac23bf6SJohan Hedberg 6829aac23bf6SJohan Hedberg sdu_len = get_unaligned_le16(skb->data); 6830aac23bf6SJohan Hedberg skb_pull(skb, L2CAP_SDULEN_SIZE); 6831aac23bf6SJohan Hedberg 6832aac23bf6SJohan Hedberg BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u", 6833aac23bf6SJohan Hedberg sdu_len, skb->len, chan->imtu); 6834aac23bf6SJohan Hedberg 6835aac23bf6SJohan Hedberg if (sdu_len > chan->imtu) { 6836aac23bf6SJohan Hedberg BT_ERR("Too big LE L2CAP SDU length received"); 6837aac23bf6SJohan Hedberg err = -EMSGSIZE; 6838aac23bf6SJohan Hedberg goto failed; 6839aac23bf6SJohan Hedberg } 6840aac23bf6SJohan Hedberg 6841aac23bf6SJohan Hedberg if (skb->len > sdu_len) { 6842aac23bf6SJohan Hedberg BT_ERR("Too much LE L2CAP data received"); 6843aac23bf6SJohan Hedberg err = -EINVAL; 6844aac23bf6SJohan Hedberg goto failed; 6845aac23bf6SJohan Hedberg } 6846aac23bf6SJohan Hedberg 6847aac23bf6SJohan Hedberg if (skb->len == sdu_len) 684896cd8eaaSLuiz Augusto von Dentz return l2cap_le_recv(chan, skb); 6849aac23bf6SJohan Hedberg 6850aac23bf6SJohan Hedberg chan->sdu = skb; 6851aac23bf6SJohan Hedberg chan->sdu_len = sdu_len; 6852aac23bf6SJohan Hedberg chan->sdu_last_frag = skb; 6853aac23bf6SJohan Hedberg 6854a5c3021bSLuiz Augusto von Dentz /* Detect if remote is not able to use the selected MPS */ 6855a5c3021bSLuiz Augusto von Dentz if (skb->len + L2CAP_SDULEN_SIZE < chan->mps) { 6856a5c3021bSLuiz Augusto von Dentz u16 mps_len = skb->len + L2CAP_SDULEN_SIZE; 6857a5c3021bSLuiz Augusto von Dentz 6858a5c3021bSLuiz Augusto von Dentz /* Adjust the number of credits */ 6859a5c3021bSLuiz Augusto von Dentz BT_DBG("chan->mps %u -> %u", chan->mps, mps_len); 6860a5c3021bSLuiz Augusto von Dentz chan->mps = mps_len; 6861a5c3021bSLuiz Augusto von Dentz l2cap_chan_le_send_credits(chan); 6862a5c3021bSLuiz Augusto von Dentz } 6863a5c3021bSLuiz Augusto von Dentz 6864aac23bf6SJohan Hedberg return 0; 6865aac23bf6SJohan Hedberg } 6866aac23bf6SJohan Hedberg 6867aac23bf6SJohan Hedberg BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u", 6868aac23bf6SJohan Hedberg chan->sdu->len, skb->len, chan->sdu_len); 6869aac23bf6SJohan Hedberg 6870aac23bf6SJohan Hedberg if (chan->sdu->len + skb->len > chan->sdu_len) { 6871aac23bf6SJohan Hedberg BT_ERR("Too much LE L2CAP data received"); 6872aac23bf6SJohan Hedberg err = -EINVAL; 6873aac23bf6SJohan Hedberg goto failed; 6874aac23bf6SJohan Hedberg } 6875aac23bf6SJohan Hedberg 6876aac23bf6SJohan Hedberg append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag); 6877aac23bf6SJohan Hedberg skb = NULL; 6878aac23bf6SJohan Hedberg 6879aac23bf6SJohan Hedberg if (chan->sdu->len == chan->sdu_len) { 688096cd8eaaSLuiz Augusto von Dentz err = l2cap_le_recv(chan, chan->sdu); 6881aac23bf6SJohan Hedberg if (!err) { 6882aac23bf6SJohan Hedberg chan->sdu = NULL; 6883aac23bf6SJohan Hedberg chan->sdu_last_frag = NULL; 6884aac23bf6SJohan Hedberg chan->sdu_len = 0; 6885aac23bf6SJohan Hedberg } 6886aac23bf6SJohan Hedberg } 6887aac23bf6SJohan Hedberg 6888aac23bf6SJohan Hedberg failed: 6889aac23bf6SJohan Hedberg if (err) { 6890aac23bf6SJohan Hedberg kfree_skb(skb); 6891aac23bf6SJohan Hedberg kfree_skb(chan->sdu); 6892aac23bf6SJohan Hedberg chan->sdu = NULL; 6893aac23bf6SJohan Hedberg chan->sdu_last_frag = NULL; 6894aac23bf6SJohan Hedberg chan->sdu_len = 0; 6895aac23bf6SJohan Hedberg } 6896aac23bf6SJohan Hedberg 6897aac23bf6SJohan Hedberg /* We can't return an error here since we took care of the skb 6898aac23bf6SJohan Hedberg * freeing internally. An error return would cause the caller to 6899aac23bf6SJohan Hedberg * do a double-free of the skb. 6900aac23bf6SJohan Hedberg */ 6901aac23bf6SJohan Hedberg return 0; 6902fad5fc89SJohan Hedberg } 6903fad5fc89SJohan Hedberg 690413ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid, 690513ca56e0SAndrei Emeltchenko struct sk_buff *skb) 69060a708f8fSGustavo F. Padovan { 690748454079SGustavo F. Padovan struct l2cap_chan *chan; 69080a708f8fSGustavo F. Padovan 6909baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 691048454079SGustavo F. Padovan if (!chan) { 691197e8e89dSAndrei Emeltchenko if (cid == L2CAP_CID_A2MP) { 691297e8e89dSAndrei Emeltchenko chan = a2mp_channel_create(conn, skb); 691397e8e89dSAndrei Emeltchenko if (!chan) { 691497e8e89dSAndrei Emeltchenko kfree_skb(skb); 691513ca56e0SAndrei Emeltchenko return; 691697e8e89dSAndrei Emeltchenko } 691797e8e89dSAndrei Emeltchenko 691897e8e89dSAndrei Emeltchenko l2cap_chan_lock(chan); 691997e8e89dSAndrei Emeltchenko } else { 69200a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid); 69216be36555SAndrei Emeltchenko /* Drop packet and return */ 69223379013bSDan Carpenter kfree_skb(skb); 692313ca56e0SAndrei Emeltchenko return; 69240a708f8fSGustavo F. Padovan } 692597e8e89dSAndrei Emeltchenko } 69260a708f8fSGustavo F. Padovan 692749208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len); 69280a708f8fSGustavo F. Padovan 6929315917e0SJohan Hedberg /* If we receive data on a fixed channel before the info req/rsp 6930315917e0SJohan Hedberg * procdure is done simply assume that the channel is supported 6931315917e0SJohan Hedberg * and mark it as ready. 6932315917e0SJohan Hedberg */ 6933315917e0SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_FIXED) 6934315917e0SJohan Hedberg l2cap_chan_ready(chan); 6935315917e0SJohan Hedberg 693689bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 69370a708f8fSGustavo F. Padovan goto drop; 69380a708f8fSGustavo F. Padovan 69390c1bc5c6SGustavo F. Padovan switch (chan->mode) { 694038319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 6941fad5fc89SJohan Hedberg if (l2cap_le_data_rcv(chan, skb) < 0) 6942fad5fc89SJohan Hedberg goto drop; 6943fad5fc89SJohan Hedberg 6944fad5fc89SJohan Hedberg goto done; 6945fad5fc89SJohan Hedberg 69460a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 69470a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here 69480a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable. 69490a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't 69500a708f8fSGustavo F. Padovan * provide flow control mechanism. */ 69510a708f8fSGustavo F. Padovan 69522c96e03dSSzymon Janc if (chan->imtu < skb->len) { 69532c96e03dSSzymon Janc BT_ERR("Dropping L2CAP data: receive buffer overflow"); 69540a708f8fSGustavo F. Padovan goto drop; 69552c96e03dSSzymon Janc } 69560a708f8fSGustavo F. Padovan 695780b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 69580a708f8fSGustavo F. Padovan goto done; 69590a708f8fSGustavo F. Padovan break; 69600a708f8fSGustavo F. Padovan 69610a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 69620a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 6963cec8ab6eSMat Martineau l2cap_data_rcv(chan, skb); 69640a708f8fSGustavo F. Padovan goto done; 69650a708f8fSGustavo F. Padovan 69660a708f8fSGustavo F. Padovan default: 69670c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); 69680a708f8fSGustavo F. Padovan break; 69690a708f8fSGustavo F. Padovan } 69700a708f8fSGustavo F. Padovan 69710a708f8fSGustavo F. Padovan drop: 69720a708f8fSGustavo F. Padovan kfree_skb(skb); 69730a708f8fSGustavo F. Padovan 69740a708f8fSGustavo F. Padovan done: 69756be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 69760a708f8fSGustavo F. Padovan } 69770a708f8fSGustavo F. Padovan 697884104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, 697984104b24SAndrei Emeltchenko struct sk_buff *skb) 69800a708f8fSGustavo F. Padovan { 6981ae4fd2d3SMarcel Holtmann struct hci_conn *hcon = conn->hcon; 698223691d75SGustavo F. Padovan struct l2cap_chan *chan; 69830a708f8fSGustavo F. Padovan 6984ae4fd2d3SMarcel Holtmann if (hcon->type != ACL_LINK) 6985a24cce14SJohan Hedberg goto free_skb; 6986ae4fd2d3SMarcel Holtmann 6987bf20fd4eSJohan Hedberg chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst, 6988bf20fd4eSJohan Hedberg ACL_LINK); 698923691d75SGustavo F. Padovan if (!chan) 6990a24cce14SJohan Hedberg goto free_skb; 69910a708f8fSGustavo F. Padovan 69925b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 69930a708f8fSGustavo F. Padovan 699489bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 69950a708f8fSGustavo F. Padovan goto drop; 69960a708f8fSGustavo F. Padovan 6997e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 69980a708f8fSGustavo F. Padovan goto drop; 69990a708f8fSGustavo F. Padovan 70002edf870dSMarcel Holtmann /* Store remote BD_ADDR and PSM for msg_name */ 7001a4368ff3SJohan Hedberg bacpy(&bt_cb(skb)->l2cap.bdaddr, &hcon->dst); 7002a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.psm = psm; 70032edf870dSMarcel Holtmann 7004a24cce14SJohan Hedberg if (!chan->ops->recv(chan, skb)) { 7005a24cce14SJohan Hedberg l2cap_chan_put(chan); 700684104b24SAndrei Emeltchenko return; 7007a24cce14SJohan Hedberg } 70080a708f8fSGustavo F. Padovan 70090a708f8fSGustavo F. Padovan drop: 7010a24cce14SJohan Hedberg l2cap_chan_put(chan); 7011a24cce14SJohan Hedberg free_skb: 70120a708f8fSGustavo F. Padovan kfree_skb(skb); 70130a708f8fSGustavo F. Padovan } 70140a708f8fSGustavo F. Padovan 70150a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) 70160a708f8fSGustavo F. Padovan { 70170a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data; 701861a939c6SJohan Hedberg struct hci_conn *hcon = conn->hcon; 70190a708f8fSGustavo F. Padovan u16 cid, len; 70200a708f8fSGustavo F. Padovan __le16 psm; 70210a708f8fSGustavo F. Padovan 702261a939c6SJohan Hedberg if (hcon->state != BT_CONNECTED) { 702361a939c6SJohan Hedberg BT_DBG("queueing pending rx skb"); 702461a939c6SJohan Hedberg skb_queue_tail(&conn->pending_rx, skb); 702561a939c6SJohan Hedberg return; 702661a939c6SJohan Hedberg } 702761a939c6SJohan Hedberg 70280a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE); 70290a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid); 70300a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len); 70310a708f8fSGustavo F. Padovan 70320a708f8fSGustavo F. Padovan if (len != skb->len) { 70330a708f8fSGustavo F. Padovan kfree_skb(skb); 70340a708f8fSGustavo F. Padovan return; 70350a708f8fSGustavo F. Padovan } 70360a708f8fSGustavo F. Padovan 70379e1d7e15SJohan Hedberg /* Since we can't actively block incoming LE connections we must 70389e1d7e15SJohan Hedberg * at least ensure that we ignore incoming data from them. 70399e1d7e15SJohan Hedberg */ 70409e1d7e15SJohan Hedberg if (hcon->type == LE_LINK && 7041dcc36c16SJohan Hedberg hci_bdaddr_list_lookup(&hcon->hdev->blacklist, &hcon->dst, 7042a250e048SJohan Hedberg bdaddr_dst_type(hcon))) { 7043e493150eSJohan Hedberg kfree_skb(skb); 7044e493150eSJohan Hedberg return; 7045e493150eSJohan Hedberg } 7046e493150eSJohan Hedberg 70470a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid); 70480a708f8fSGustavo F. Padovan 70490a708f8fSGustavo F. Padovan switch (cid) { 70500a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING: 70510a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb); 70520a708f8fSGustavo F. Padovan break; 70530a708f8fSGustavo F. Padovan 70540a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS: 7055097db76cSAndrei Emeltchenko psm = get_unaligned((__le16 *) skb->data); 70560181a70fSAndrei Emeltchenko skb_pull(skb, L2CAP_PSMLEN_SIZE); 70570a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb); 70580a708f8fSGustavo F. Padovan break; 70590a708f8fSGustavo F. Padovan 7060a2877629SMarcel Holtmann case L2CAP_CID_LE_SIGNALING: 7061a2877629SMarcel Holtmann l2cap_le_sig_channel(conn, skb); 7062a2877629SMarcel Holtmann break; 7063a2877629SMarcel Holtmann 70640a708f8fSGustavo F. Padovan default: 70650a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb); 70660a708f8fSGustavo F. Padovan break; 70670a708f8fSGustavo F. Padovan } 70680a708f8fSGustavo F. Padovan } 70690a708f8fSGustavo F. Padovan 707061a939c6SJohan Hedberg static void process_pending_rx(struct work_struct *work) 707161a939c6SJohan Hedberg { 707261a939c6SJohan Hedberg struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 707361a939c6SJohan Hedberg pending_rx_work); 707461a939c6SJohan Hedberg struct sk_buff *skb; 707561a939c6SJohan Hedberg 707661a939c6SJohan Hedberg BT_DBG(""); 707761a939c6SJohan Hedberg 707861a939c6SJohan Hedberg while ((skb = skb_dequeue(&conn->pending_rx))) 707961a939c6SJohan Hedberg l2cap_recv_frame(conn, skb); 708061a939c6SJohan Hedberg } 708161a939c6SJohan Hedberg 7082162b49e7SJohan Hedberg static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) 7083162b49e7SJohan Hedberg { 7084162b49e7SJohan Hedberg struct l2cap_conn *conn = hcon->l2cap_data; 7085162b49e7SJohan Hedberg struct hci_chan *hchan; 7086162b49e7SJohan Hedberg 7087162b49e7SJohan Hedberg if (conn) 7088162b49e7SJohan Hedberg return conn; 7089162b49e7SJohan Hedberg 7090162b49e7SJohan Hedberg hchan = hci_chan_create(hcon); 7091162b49e7SJohan Hedberg if (!hchan) 7092162b49e7SJohan Hedberg return NULL; 7093162b49e7SJohan Hedberg 709427f70f3eSJohan Hedberg conn = kzalloc(sizeof(*conn), GFP_KERNEL); 7095162b49e7SJohan Hedberg if (!conn) { 7096162b49e7SJohan Hedberg hci_chan_del(hchan); 7097162b49e7SJohan Hedberg return NULL; 7098162b49e7SJohan Hedberg } 7099162b49e7SJohan Hedberg 7100162b49e7SJohan Hedberg kref_init(&conn->ref); 7101162b49e7SJohan Hedberg hcon->l2cap_data = conn; 710251bb8457SJohan Hedberg conn->hcon = hci_conn_get(hcon); 7103162b49e7SJohan Hedberg conn->hchan = hchan; 7104162b49e7SJohan Hedberg 7105162b49e7SJohan Hedberg BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); 7106162b49e7SJohan Hedberg 7107162b49e7SJohan Hedberg switch (hcon->type) { 7108162b49e7SJohan Hedberg case LE_LINK: 7109162b49e7SJohan Hedberg if (hcon->hdev->le_mtu) { 7110162b49e7SJohan Hedberg conn->mtu = hcon->hdev->le_mtu; 7111162b49e7SJohan Hedberg break; 7112162b49e7SJohan Hedberg } 7113162b49e7SJohan Hedberg /* fall through */ 7114162b49e7SJohan Hedberg default: 7115162b49e7SJohan Hedberg conn->mtu = hcon->hdev->acl_mtu; 7116162b49e7SJohan Hedberg break; 7117162b49e7SJohan Hedberg } 7118162b49e7SJohan Hedberg 7119162b49e7SJohan Hedberg conn->feat_mask = 0; 7120162b49e7SJohan Hedberg 71210bd49fc7SJohan Hedberg conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS; 71220bd49fc7SJohan Hedberg 71230bd49fc7SJohan Hedberg if (hcon->type == ACL_LINK && 7124d7a5a11dSMarcel Holtmann hci_dev_test_flag(hcon->hdev, HCI_HS_ENABLED)) 71250bd49fc7SJohan Hedberg conn->local_fixed_chan |= L2CAP_FC_A2MP; 7126162b49e7SJohan Hedberg 7127d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED) && 7128f9be9e86SMarcel Holtmann (bredr_sc_enabled(hcon->hdev) || 7129b7cb93e5SMarcel Holtmann hci_dev_test_flag(hcon->hdev, HCI_FORCE_BREDR_SMP))) 7130b5ae344dSJohan Hedberg conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR; 7131b5ae344dSJohan Hedberg 71325a54e7c8SMarcel Holtmann mutex_init(&conn->ident_lock); 7133162b49e7SJohan Hedberg mutex_init(&conn->chan_lock); 7134162b49e7SJohan Hedberg 7135162b49e7SJohan Hedberg INIT_LIST_HEAD(&conn->chan_l); 7136162b49e7SJohan Hedberg INIT_LIST_HEAD(&conn->users); 7137162b49e7SJohan Hedberg 7138162b49e7SJohan Hedberg INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); 7139162b49e7SJohan Hedberg 714061a939c6SJohan Hedberg skb_queue_head_init(&conn->pending_rx); 714161a939c6SJohan Hedberg INIT_WORK(&conn->pending_rx_work, process_pending_rx); 7142f3d82d0cSJohan Hedberg INIT_WORK(&conn->id_addr_update_work, l2cap_conn_update_id_addr); 714361a939c6SJohan Hedberg 7144162b49e7SJohan Hedberg conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 7145162b49e7SJohan Hedberg 7146162b49e7SJohan Hedberg return conn; 7147162b49e7SJohan Hedberg } 7148162b49e7SJohan Hedberg 7149162b49e7SJohan Hedberg static bool is_valid_psm(u16 psm, u8 dst_type) { 7150162b49e7SJohan Hedberg if (!psm) 7151162b49e7SJohan Hedberg return false; 7152162b49e7SJohan Hedberg 7153162b49e7SJohan Hedberg if (bdaddr_type_is_le(dst_type)) 7154162b49e7SJohan Hedberg return (psm <= 0x00ff); 7155162b49e7SJohan Hedberg 7156162b49e7SJohan Hedberg /* PSM must be odd and lsb of upper byte must be 0 */ 7157162b49e7SJohan Hedberg return ((psm & 0x0101) == 0x0001); 7158162b49e7SJohan Hedberg } 7159162b49e7SJohan Hedberg 7160162b49e7SJohan Hedberg int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, 7161162b49e7SJohan Hedberg bdaddr_t *dst, u8 dst_type) 7162162b49e7SJohan Hedberg { 7163162b49e7SJohan Hedberg struct l2cap_conn *conn; 7164162b49e7SJohan Hedberg struct hci_conn *hcon; 7165162b49e7SJohan Hedberg struct hci_dev *hdev; 7166162b49e7SJohan Hedberg int err; 7167162b49e7SJohan Hedberg 7168162b49e7SJohan Hedberg BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst, 7169162b49e7SJohan Hedberg dst_type, __le16_to_cpu(psm)); 7170162b49e7SJohan Hedberg 717139385cb5SJohan Hedberg hdev = hci_get_route(dst, &chan->src, chan->src_type); 7172162b49e7SJohan Hedberg if (!hdev) 7173162b49e7SJohan Hedberg return -EHOSTUNREACH; 7174162b49e7SJohan Hedberg 7175162b49e7SJohan Hedberg hci_dev_lock(hdev); 7176162b49e7SJohan Hedberg 7177162b49e7SJohan Hedberg if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid && 7178162b49e7SJohan Hedberg chan->chan_type != L2CAP_CHAN_RAW) { 7179162b49e7SJohan Hedberg err = -EINVAL; 7180162b49e7SJohan Hedberg goto done; 7181162b49e7SJohan Hedberg } 7182162b49e7SJohan Hedberg 718321626e62SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !psm) { 718421626e62SJohan Hedberg err = -EINVAL; 718521626e62SJohan Hedberg goto done; 718621626e62SJohan Hedberg } 718721626e62SJohan Hedberg 718821626e62SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_FIXED && !cid) { 7189162b49e7SJohan Hedberg err = -EINVAL; 7190162b49e7SJohan Hedberg goto done; 7191162b49e7SJohan Hedberg } 7192162b49e7SJohan Hedberg 7193162b49e7SJohan Hedberg switch (chan->mode) { 7194162b49e7SJohan Hedberg case L2CAP_MODE_BASIC: 7195162b49e7SJohan Hedberg break; 7196162b49e7SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 7197162b49e7SJohan Hedberg break; 7198162b49e7SJohan Hedberg case L2CAP_MODE_ERTM: 7199162b49e7SJohan Hedberg case L2CAP_MODE_STREAMING: 7200162b49e7SJohan Hedberg if (!disable_ertm) 7201162b49e7SJohan Hedberg break; 7202162b49e7SJohan Hedberg /* fall through */ 7203162b49e7SJohan Hedberg default: 7204beb19e4cSJohan Hedberg err = -EOPNOTSUPP; 7205162b49e7SJohan Hedberg goto done; 7206162b49e7SJohan Hedberg } 7207162b49e7SJohan Hedberg 7208162b49e7SJohan Hedberg switch (chan->state) { 7209162b49e7SJohan Hedberg case BT_CONNECT: 7210162b49e7SJohan Hedberg case BT_CONNECT2: 7211162b49e7SJohan Hedberg case BT_CONFIG: 7212162b49e7SJohan Hedberg /* Already connecting */ 7213162b49e7SJohan Hedberg err = 0; 7214162b49e7SJohan Hedberg goto done; 7215162b49e7SJohan Hedberg 7216162b49e7SJohan Hedberg case BT_CONNECTED: 7217162b49e7SJohan Hedberg /* Already connected */ 7218162b49e7SJohan Hedberg err = -EISCONN; 7219162b49e7SJohan Hedberg goto done; 7220162b49e7SJohan Hedberg 7221162b49e7SJohan Hedberg case BT_OPEN: 7222162b49e7SJohan Hedberg case BT_BOUND: 7223162b49e7SJohan Hedberg /* Can connect */ 7224162b49e7SJohan Hedberg break; 7225162b49e7SJohan Hedberg 7226162b49e7SJohan Hedberg default: 7227162b49e7SJohan Hedberg err = -EBADFD; 7228162b49e7SJohan Hedberg goto done; 7229162b49e7SJohan Hedberg } 7230162b49e7SJohan Hedberg 7231162b49e7SJohan Hedberg /* Set destination address and psm */ 7232162b49e7SJohan Hedberg bacpy(&chan->dst, dst); 7233162b49e7SJohan Hedberg chan->dst_type = dst_type; 7234162b49e7SJohan Hedberg 7235162b49e7SJohan Hedberg chan->psm = psm; 7236162b49e7SJohan Hedberg chan->dcid = cid; 7237162b49e7SJohan Hedberg 72386f77d8c7SAndre Guedes if (bdaddr_type_is_le(dst_type)) { 72396f77d8c7SAndre Guedes /* Convert from L2CAP channel address type to HCI address type 72406f77d8c7SAndre Guedes */ 72416f77d8c7SAndre Guedes if (dst_type == BDADDR_LE_PUBLIC) 72426f77d8c7SAndre Guedes dst_type = ADDR_LE_DEV_PUBLIC; 72436f77d8c7SAndre Guedes else 72446f77d8c7SAndre Guedes dst_type = ADDR_LE_DEV_RANDOM; 72456f77d8c7SAndre Guedes 7246d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) 72470ad06aa6SJohan Hedberg hcon = hci_connect_le(hdev, dst, dst_type, 7248fa142220SJakub Pawlowski chan->sec_level, 7249fa142220SJakub Pawlowski HCI_LE_CONN_TIMEOUT, 7250082f2300SSzymon Janc HCI_ROLE_SLAVE, NULL); 72510ad06aa6SJohan Hedberg else 72520ad06aa6SJohan Hedberg hcon = hci_connect_le_scan(hdev, dst, dst_type, 72530ad06aa6SJohan Hedberg chan->sec_level, 72540ad06aa6SJohan Hedberg HCI_LE_CONN_TIMEOUT); 72550ad06aa6SJohan Hedberg 72566f77d8c7SAndre Guedes } else { 7257d93375a8SJohan Hedberg u8 auth_type = l2cap_get_auth_type(chan); 725804a6c589SAndre Guedes hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type); 72596f77d8c7SAndre Guedes } 7260162b49e7SJohan Hedberg 7261162b49e7SJohan Hedberg if (IS_ERR(hcon)) { 7262162b49e7SJohan Hedberg err = PTR_ERR(hcon); 7263162b49e7SJohan Hedberg goto done; 7264162b49e7SJohan Hedberg } 7265162b49e7SJohan Hedberg 7266162b49e7SJohan Hedberg conn = l2cap_conn_add(hcon); 7267162b49e7SJohan Hedberg if (!conn) { 7268162b49e7SJohan Hedberg hci_conn_drop(hcon); 7269162b49e7SJohan Hedberg err = -ENOMEM; 7270162b49e7SJohan Hedberg goto done; 7271162b49e7SJohan Hedberg } 7272162b49e7SJohan Hedberg 727302e246aeSJohan Hedberg mutex_lock(&conn->chan_lock); 727402e246aeSJohan Hedberg l2cap_chan_lock(chan); 727502e246aeSJohan Hedberg 7276162b49e7SJohan Hedberg if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { 7277162b49e7SJohan Hedberg hci_conn_drop(hcon); 7278162b49e7SJohan Hedberg err = -EBUSY; 727902e246aeSJohan Hedberg goto chan_unlock; 7280162b49e7SJohan Hedberg } 7281162b49e7SJohan Hedberg 7282162b49e7SJohan Hedberg /* Update source addr of the socket */ 7283162b49e7SJohan Hedberg bacpy(&chan->src, &hcon->src); 7284a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(hcon); 7285162b49e7SJohan Hedberg 728602e246aeSJohan Hedberg __l2cap_chan_add(conn, chan); 7287162b49e7SJohan Hedberg 7288162b49e7SJohan Hedberg /* l2cap_chan_add takes its own ref so we can drop this one */ 7289162b49e7SJohan Hedberg hci_conn_drop(hcon); 7290162b49e7SJohan Hedberg 7291162b49e7SJohan Hedberg l2cap_state_change(chan, BT_CONNECT); 7292162b49e7SJohan Hedberg __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 7293162b49e7SJohan Hedberg 729461202e4dSJohan Hedberg /* Release chan->sport so that it can be reused by other 729561202e4dSJohan Hedberg * sockets (as it's only used for listening sockets). 729661202e4dSJohan Hedberg */ 729761202e4dSJohan Hedberg write_lock(&chan_list_lock); 729861202e4dSJohan Hedberg chan->sport = 0; 729961202e4dSJohan Hedberg write_unlock(&chan_list_lock); 730061202e4dSJohan Hedberg 7301162b49e7SJohan Hedberg if (hcon->state == BT_CONNECTED) { 7302162b49e7SJohan Hedberg if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 7303162b49e7SJohan Hedberg __clear_chan_timer(chan); 7304e7cafc45SJohan Hedberg if (l2cap_chan_check_security(chan, true)) 7305162b49e7SJohan Hedberg l2cap_state_change(chan, BT_CONNECTED); 7306162b49e7SJohan Hedberg } else 7307162b49e7SJohan Hedberg l2cap_do_start(chan); 7308162b49e7SJohan Hedberg } 7309162b49e7SJohan Hedberg 7310162b49e7SJohan Hedberg err = 0; 7311162b49e7SJohan Hedberg 731202e246aeSJohan Hedberg chan_unlock: 7313162b49e7SJohan Hedberg l2cap_chan_unlock(chan); 731402e246aeSJohan Hedberg mutex_unlock(&conn->chan_lock); 731502e246aeSJohan Hedberg done: 7316162b49e7SJohan Hedberg hci_dev_unlock(hdev); 7317162b49e7SJohan Hedberg hci_dev_put(hdev); 7318162b49e7SJohan Hedberg return err; 7319162b49e7SJohan Hedberg } 73206b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_connect); 7321162b49e7SJohan Hedberg 73220a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */ 73230a708f8fSGustavo F. Padovan 7324686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) 73250a708f8fSGustavo F. Padovan { 73260a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0; 732723691d75SGustavo F. Padovan struct l2cap_chan *c; 73280a708f8fSGustavo F. Padovan 73296ed93dc6SAndrei Emeltchenko BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr); 73300a708f8fSGustavo F. Padovan 73310a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */ 733223691d75SGustavo F. Padovan read_lock(&chan_list_lock); 733323691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 733489bc500eSGustavo F. Padovan if (c->state != BT_LISTEN) 73350a708f8fSGustavo F. Padovan continue; 73360a708f8fSGustavo F. Padovan 73377eafc59eSMarcel Holtmann if (!bacmp(&c->src, &hdev->bdaddr)) { 73380a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT; 733943bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 73400a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER; 73410a708f8fSGustavo F. Padovan exact++; 73427eafc59eSMarcel Holtmann } else if (!bacmp(&c->src, BDADDR_ANY)) { 73430a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT; 734443bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 73450a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER; 73460a708f8fSGustavo F. Padovan } 73470a708f8fSGustavo F. Padovan } 734823691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 73490a708f8fSGustavo F. Padovan 73500a708f8fSGustavo F. Padovan return exact ? lm1 : lm2; 73510a708f8fSGustavo F. Padovan } 73520a708f8fSGustavo F. Padovan 7353e760ec12SJohan Hedberg /* Find the next fixed channel in BT_LISTEN state, continue iteration 7354e760ec12SJohan Hedberg * from an existing channel in the list or from the beginning of the 7355e760ec12SJohan Hedberg * global list (by passing NULL as first parameter). 7356e760ec12SJohan Hedberg */ 7357e760ec12SJohan Hedberg static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c, 7358327a7191SJohan Hedberg struct hci_conn *hcon) 7359e760ec12SJohan Hedberg { 7360327a7191SJohan Hedberg u8 src_type = bdaddr_src_type(hcon); 7361327a7191SJohan Hedberg 7362e760ec12SJohan Hedberg read_lock(&chan_list_lock); 7363e760ec12SJohan Hedberg 7364e760ec12SJohan Hedberg if (c) 7365e760ec12SJohan Hedberg c = list_next_entry(c, global_l); 7366e760ec12SJohan Hedberg else 7367e760ec12SJohan Hedberg c = list_entry(chan_list.next, typeof(*c), global_l); 7368e760ec12SJohan Hedberg 7369e760ec12SJohan Hedberg list_for_each_entry_from(c, &chan_list, global_l) { 7370e760ec12SJohan Hedberg if (c->chan_type != L2CAP_CHAN_FIXED) 7371e760ec12SJohan Hedberg continue; 7372e760ec12SJohan Hedberg if (c->state != BT_LISTEN) 7373e760ec12SJohan Hedberg continue; 7374327a7191SJohan Hedberg if (bacmp(&c->src, &hcon->src) && bacmp(&c->src, BDADDR_ANY)) 7375e760ec12SJohan Hedberg continue; 7376327a7191SJohan Hedberg if (src_type != c->src_type) 737754a1b626SJohan Hedberg continue; 7378e760ec12SJohan Hedberg 7379e760ec12SJohan Hedberg l2cap_chan_hold(c); 7380e760ec12SJohan Hedberg read_unlock(&chan_list_lock); 7381e760ec12SJohan Hedberg return c; 7382e760ec12SJohan Hedberg } 7383e760ec12SJohan Hedberg 7384e760ec12SJohan Hedberg read_unlock(&chan_list_lock); 7385e760ec12SJohan Hedberg 7386e760ec12SJohan Hedberg return NULL; 7387e760ec12SJohan Hedberg } 7388e760ec12SJohan Hedberg 7389539c496dSJohan Hedberg static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) 73900a708f8fSGustavo F. Padovan { 7391e760ec12SJohan Hedberg struct hci_dev *hdev = hcon->hdev; 73920a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 7393e760ec12SJohan Hedberg struct l2cap_chan *pchan; 7394e760ec12SJohan Hedberg u8 dst_type; 73950a708f8fSGustavo F. Padovan 7396539c496dSJohan Hedberg if (hcon->type != ACL_LINK && hcon->type != LE_LINK) 7397539c496dSJohan Hedberg return; 7398539c496dSJohan Hedberg 73996ed93dc6SAndrei Emeltchenko BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status); 74000a708f8fSGustavo F. Padovan 7401dc0f5088SJohan Hedberg if (status) { 7402e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status)); 7403dc0f5088SJohan Hedberg return; 7404ba6fc317SAndrei Emeltchenko } 7405dc0f5088SJohan Hedberg 7406dc0f5088SJohan Hedberg conn = l2cap_conn_add(hcon); 7407dc0f5088SJohan Hedberg if (!conn) 7408dc0f5088SJohan Hedberg return; 7409dc0f5088SJohan Hedberg 7410a250e048SJohan Hedberg dst_type = bdaddr_dst_type(hcon); 7411e760ec12SJohan Hedberg 7412e760ec12SJohan Hedberg /* If device is blocked, do not create channels for it */ 7413e760ec12SJohan Hedberg if (hci_bdaddr_list_lookup(&hdev->blacklist, &hcon->dst, dst_type)) 7414e760ec12SJohan Hedberg return; 7415e760ec12SJohan Hedberg 7416e760ec12SJohan Hedberg /* Find fixed channels and notify them of the new connection. We 7417e760ec12SJohan Hedberg * use multiple individual lookups, continuing each time where 7418e760ec12SJohan Hedberg * we left off, because the list lock would prevent calling the 7419e760ec12SJohan Hedberg * potentially sleeping l2cap_chan_lock() function. 7420e760ec12SJohan Hedberg */ 7421327a7191SJohan Hedberg pchan = l2cap_global_fixed_chan(NULL, hcon); 7422e760ec12SJohan Hedberg while (pchan) { 7423e760ec12SJohan Hedberg struct l2cap_chan *chan, *next; 7424e760ec12SJohan Hedberg 7425e760ec12SJohan Hedberg /* Client fixed channels should override server ones */ 7426e760ec12SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, pchan->scid)) 7427e760ec12SJohan Hedberg goto next; 7428e760ec12SJohan Hedberg 7429e760ec12SJohan Hedberg l2cap_chan_lock(pchan); 7430e760ec12SJohan Hedberg chan = pchan->ops->new_connection(pchan); 7431e760ec12SJohan Hedberg if (chan) { 7432e760ec12SJohan Hedberg bacpy(&chan->src, &hcon->src); 7433e760ec12SJohan Hedberg bacpy(&chan->dst, &hcon->dst); 7434a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(hcon); 7435e760ec12SJohan Hedberg chan->dst_type = dst_type; 7436e760ec12SJohan Hedberg 7437e760ec12SJohan Hedberg __l2cap_chan_add(conn, chan); 7438e760ec12SJohan Hedberg } 7439e760ec12SJohan Hedberg 7440e760ec12SJohan Hedberg l2cap_chan_unlock(pchan); 7441e760ec12SJohan Hedberg next: 7442327a7191SJohan Hedberg next = l2cap_global_fixed_chan(pchan, hcon); 7443e760ec12SJohan Hedberg l2cap_chan_put(pchan); 7444e760ec12SJohan Hedberg pchan = next; 7445e760ec12SJohan Hedberg } 7446e760ec12SJohan Hedberg 7447dc0f5088SJohan Hedberg l2cap_conn_ready(conn); 74480a708f8fSGustavo F. Padovan } 74490a708f8fSGustavo F. Padovan 7450686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon) 74510a708f8fSGustavo F. Padovan { 74520a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 74530a708f8fSGustavo F. Padovan 74540a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon); 74550a708f8fSGustavo F. Padovan 7456686ebf28SUlisses Furquim if (!conn) 74579f5a0d7bSAndrei Emeltchenko return HCI_ERROR_REMOTE_USER_TERM; 74580a708f8fSGustavo F. Padovan return conn->disc_reason; 74590a708f8fSGustavo F. Padovan } 74600a708f8fSGustavo F. Padovan 74613a6d576bSJohan Hedberg static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) 74620a708f8fSGustavo F. Padovan { 74633a6d576bSJohan Hedberg if (hcon->type != ACL_LINK && hcon->type != LE_LINK) 74643a6d576bSJohan Hedberg return; 74653a6d576bSJohan Hedberg 74660a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason); 74670a708f8fSGustavo F. Padovan 7468e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason)); 74690a708f8fSGustavo F. Padovan } 74700a708f8fSGustavo F. Padovan 74714343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) 74720a708f8fSGustavo F. Padovan { 7473715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 74740a708f8fSGustavo F. Padovan return; 74750a708f8fSGustavo F. Padovan 74760a708f8fSGustavo F. Padovan if (encrypt == 0x00) { 74774343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) { 7478ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); 74797d513e92SMarcel Holtmann } else if (chan->sec_level == BT_SECURITY_HIGH || 74807d513e92SMarcel Holtmann chan->sec_level == BT_SECURITY_FIPS) 74810f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED); 74820a708f8fSGustavo F. Padovan } else { 74834343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) 7484c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 74850a708f8fSGustavo F. Padovan } 74860a708f8fSGustavo F. Padovan } 74870a708f8fSGustavo F. Padovan 7488354fe804SJohan Hedberg static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) 74890a708f8fSGustavo F. Padovan { 74900a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 749148454079SGustavo F. Padovan struct l2cap_chan *chan; 74920a708f8fSGustavo F. Padovan 74930a708f8fSGustavo F. Padovan if (!conn) 7494354fe804SJohan Hedberg return; 74950a708f8fSGustavo F. Padovan 749689d8b407SAndrei Emeltchenko BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt); 74970a708f8fSGustavo F. Padovan 74983df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 74990a708f8fSGustavo F. Padovan 75003df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 75016be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 75020a708f8fSGustavo F. Padovan 750389d8b407SAndrei Emeltchenko BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, 750489d8b407SAndrei Emeltchenko state_to_string(chan->state)); 7505f1cb9af5SVinicius Costa Gomes 75062338a7e0SJohan Hedberg if (chan->scid == L2CAP_CID_A2MP) { 750778eb2f98SAndrei Emeltchenko l2cap_chan_unlock(chan); 750878eb2f98SAndrei Emeltchenko continue; 750978eb2f98SAndrei Emeltchenko } 751078eb2f98SAndrei Emeltchenko 7511191eb398SJohan Hedberg if (!status && encrypt) 7512f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level; 7513f1cb9af5SVinicius Costa Gomes 751496eff46eSAndrei Emeltchenko if (!__l2cap_no_conn_pending(chan)) { 75156be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 75160a708f8fSGustavo F. Padovan continue; 75170a708f8fSGustavo F. Padovan } 75180a708f8fSGustavo F. Padovan 751989bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED || 752089bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) { 7521d97c899bSMarcel Holtmann chan->ops->resume(chan); 75224343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt); 75236be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 75240a708f8fSGustavo F. Padovan continue; 75250a708f8fSGustavo F. Padovan } 75260a708f8fSGustavo F. Padovan 752789bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 7528693cd8ceSMarcel Holtmann if (!status && l2cap_check_enc_key_size(hcon)) 752993c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 75306d3c15daSJohan Hedberg else 7531ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 7532fa37c1aaSJohan Hedberg } else if (chan->state == BT_CONNECT2 && 7533fa37c1aaSJohan Hedberg chan->mode != L2CAP_MODE_LE_FLOWCTL) { 75340a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 7535df3c3931SJohan Hedberg __u16 res, stat; 75360a708f8fSGustavo F. Padovan 7537693cd8ceSMarcel Holtmann if (!status && l2cap_check_enc_key_size(hcon)) { 7538bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 7539df3c3931SJohan Hedberg res = L2CAP_CR_PEND; 7540df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND; 75412dc4e510SGustavo Padovan chan->ops->defer(chan); 7542df3c3931SJohan Hedberg } else { 7543acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 7544df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS; 7545df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 7546df3c3931SJohan Hedberg } 75470a708f8fSGustavo F. Padovan } else { 7548acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_DISCONN); 7549ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 7550df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK; 7551df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 75520a708f8fSGustavo F. Padovan } 75530a708f8fSGustavo F. Padovan 7554fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 7555fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 7556df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res); 7557df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat); 7558fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 7559fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 75602d369359SMat Martineau 75612d369359SMat Martineau if (!test_bit(CONF_REQ_SENT, &chan->conf_state) && 75622d369359SMat Martineau res == L2CAP_CR_SUCCESS) { 75632d369359SMat Martineau char buf[128]; 75642d369359SMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 75652d369359SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), 75662d369359SMat Martineau L2CAP_CONF_REQ, 7567e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), 75682d369359SMat Martineau buf); 75692d369359SMat Martineau chan->num_conf_req++; 75702d369359SMat Martineau } 75710a708f8fSGustavo F. Padovan } 75720a708f8fSGustavo F. Padovan 75736be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 75740a708f8fSGustavo F. Padovan } 75750a708f8fSGustavo F. Padovan 75763df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 75770a708f8fSGustavo F. Padovan } 75780a708f8fSGustavo F. Padovan 75799b4c3336SArron Wang void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) 75800a708f8fSGustavo F. Padovan { 75810a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 7582d73a0988SAndrei Emeltchenko struct l2cap_hdr *hdr; 7583d73a0988SAndrei Emeltchenko int len; 75840a708f8fSGustavo F. Padovan 75851d13a254SAndrei Emeltchenko /* For AMP controller do not create l2cap conn */ 7586ca8bee5dSMarcel Holtmann if (!conn && hcon->hdev->dev_type != HCI_PRIMARY) 75871d13a254SAndrei Emeltchenko goto drop; 75880a708f8fSGustavo F. Padovan 75890a708f8fSGustavo F. Padovan if (!conn) 7590baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon); 75910a708f8fSGustavo F. Padovan 75920a708f8fSGustavo F. Padovan if (!conn) 75930a708f8fSGustavo F. Padovan goto drop; 75940a708f8fSGustavo F. Padovan 75950a708f8fSGustavo F. Padovan BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); 75960a708f8fSGustavo F. Padovan 7597d73a0988SAndrei Emeltchenko switch (flags) { 7598d73a0988SAndrei Emeltchenko case ACL_START: 7599d73a0988SAndrei Emeltchenko case ACL_START_NO_FLUSH: 7600d73a0988SAndrei Emeltchenko case ACL_COMPLETE: 76010a708f8fSGustavo F. Padovan if (conn->rx_len) { 76020a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len); 76030a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 76040a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 76050a708f8fSGustavo F. Padovan conn->rx_len = 0; 76060a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 76070a708f8fSGustavo F. Padovan } 76080a708f8fSGustavo F. Padovan 76090a708f8fSGustavo F. Padovan /* Start fragment always begin with Basic L2CAP header */ 76100a708f8fSGustavo F. Padovan if (skb->len < L2CAP_HDR_SIZE) { 76110a708f8fSGustavo F. Padovan BT_ERR("Frame is too short (len %d)", skb->len); 76120a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 76130a708f8fSGustavo F. Padovan goto drop; 76140a708f8fSGustavo F. Padovan } 76150a708f8fSGustavo F. Padovan 76160a708f8fSGustavo F. Padovan hdr = (struct l2cap_hdr *) skb->data; 76170a708f8fSGustavo F. Padovan len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; 76180a708f8fSGustavo F. Padovan 76190a708f8fSGustavo F. Padovan if (len == skb->len) { 76200a708f8fSGustavo F. Padovan /* Complete frame received */ 76210a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb); 76229b4c3336SArron Wang return; 76230a708f8fSGustavo F. Padovan } 76240a708f8fSGustavo F. Padovan 76250a708f8fSGustavo F. Padovan BT_DBG("Start: total len %d, frag len %d", len, skb->len); 76260a708f8fSGustavo F. Padovan 76270a708f8fSGustavo F. Padovan if (skb->len > len) { 76280a708f8fSGustavo F. Padovan BT_ERR("Frame is too long (len %d, expected len %d)", 76290a708f8fSGustavo F. Padovan skb->len, len); 76300a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 76310a708f8fSGustavo F. Padovan goto drop; 76320a708f8fSGustavo F. Padovan } 76330a708f8fSGustavo F. Padovan 76340a708f8fSGustavo F. Padovan /* Allocate skb for the complete frame (with header) */ 76358bcde1f2SGustavo Padovan conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL); 76360a708f8fSGustavo F. Padovan if (!conn->rx_skb) 76370a708f8fSGustavo F. Padovan goto drop; 76380a708f8fSGustavo F. Padovan 76390a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 76400a708f8fSGustavo F. Padovan skb->len); 76410a708f8fSGustavo F. Padovan conn->rx_len = len - skb->len; 7642d73a0988SAndrei Emeltchenko break; 7643d73a0988SAndrei Emeltchenko 7644d73a0988SAndrei Emeltchenko case ACL_CONT: 76450a708f8fSGustavo F. Padovan BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); 76460a708f8fSGustavo F. Padovan 76470a708f8fSGustavo F. Padovan if (!conn->rx_len) { 76480a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len); 76490a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 76500a708f8fSGustavo F. Padovan goto drop; 76510a708f8fSGustavo F. Padovan } 76520a708f8fSGustavo F. Padovan 76530a708f8fSGustavo F. Padovan if (skb->len > conn->rx_len) { 76540a708f8fSGustavo F. Padovan BT_ERR("Fragment is too long (len %d, expected %d)", 76550a708f8fSGustavo F. Padovan skb->len, conn->rx_len); 76560a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 76570a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 76580a708f8fSGustavo F. Padovan conn->rx_len = 0; 76590a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 76600a708f8fSGustavo F. Padovan goto drop; 76610a708f8fSGustavo F. Padovan } 76620a708f8fSGustavo F. Padovan 76630a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 76640a708f8fSGustavo F. Padovan skb->len); 76650a708f8fSGustavo F. Padovan conn->rx_len -= skb->len; 76660a708f8fSGustavo F. Padovan 76670a708f8fSGustavo F. Padovan if (!conn->rx_len) { 7668c4e5bafaSJohan Hedberg /* Complete frame received. l2cap_recv_frame 7669c4e5bafaSJohan Hedberg * takes ownership of the skb so set the global 7670c4e5bafaSJohan Hedberg * rx_skb pointer to NULL first. 7671c4e5bafaSJohan Hedberg */ 7672c4e5bafaSJohan Hedberg struct sk_buff *rx_skb = conn->rx_skb; 76730a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 7674c4e5bafaSJohan Hedberg l2cap_recv_frame(conn, rx_skb); 76750a708f8fSGustavo F. Padovan } 7676d73a0988SAndrei Emeltchenko break; 76770a708f8fSGustavo F. Padovan } 76780a708f8fSGustavo F. Padovan 76790a708f8fSGustavo F. Padovan drop: 76800a708f8fSGustavo F. Padovan kfree_skb(skb); 76810a708f8fSGustavo F. Padovan } 76820a708f8fSGustavo F. Padovan 7683354fe804SJohan Hedberg static struct hci_cb l2cap_cb = { 7684354fe804SJohan Hedberg .name = "L2CAP", 7685539c496dSJohan Hedberg .connect_cfm = l2cap_connect_cfm, 76863a6d576bSJohan Hedberg .disconn_cfm = l2cap_disconn_cfm, 7687354fe804SJohan Hedberg .security_cfm = l2cap_security_cfm, 7688354fe804SJohan Hedberg }; 7689354fe804SJohan Hedberg 76900a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p) 76910a708f8fSGustavo F. Padovan { 769223691d75SGustavo F. Padovan struct l2cap_chan *c; 76930a708f8fSGustavo F. Padovan 7694333055f2SGustavo F. Padovan read_lock(&chan_list_lock); 76950a708f8fSGustavo F. Padovan 769623691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 7697eeb5a067SMarcel Holtmann seq_printf(f, "%pMR (%u) %pMR (%u) %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", 7698eeb5a067SMarcel Holtmann &c->src, c->src_type, &c->dst, c->dst_type, 769989bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm), 770023691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu, 770123691d75SGustavo F. Padovan c->sec_level, c->mode); 77020a708f8fSGustavo F. Padovan } 77030a708f8fSGustavo F. Padovan 7704333055f2SGustavo F. Padovan read_unlock(&chan_list_lock); 77050a708f8fSGustavo F. Padovan 77060a708f8fSGustavo F. Padovan return 0; 77070a708f8fSGustavo F. Padovan } 77080a708f8fSGustavo F. Padovan 77098e2924e3SYangtao Li DEFINE_SHOW_ATTRIBUTE(l2cap_debugfs); 77100a708f8fSGustavo F. Padovan 77110a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs; 77120a708f8fSGustavo F. Padovan 771364274518SGustavo F. Padovan int __init l2cap_init(void) 77140a708f8fSGustavo F. Padovan { 77150a708f8fSGustavo F. Padovan int err; 77160a708f8fSGustavo F. Padovan 7717bb58f747SGustavo F. Padovan err = l2cap_init_sockets(); 77180a708f8fSGustavo F. Padovan if (err < 0) 77190a708f8fSGustavo F. Padovan return err; 77200a708f8fSGustavo F. Padovan 7721354fe804SJohan Hedberg hci_register_cb(&l2cap_cb); 7722354fe804SJohan Hedberg 77231120e4bfSMarcel Holtmann if (IS_ERR_OR_NULL(bt_debugfs)) 77241120e4bfSMarcel Holtmann return 0; 77251120e4bfSMarcel Holtmann 77262d792818SGustavo Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, 77272d792818SGustavo Padovan NULL, &l2cap_debugfs_fops); 77280a708f8fSGustavo F. Padovan 77290a708f8fSGustavo F. Padovan return 0; 77300a708f8fSGustavo F. Padovan } 77310a708f8fSGustavo F. Padovan 773264274518SGustavo F. Padovan void l2cap_exit(void) 77330a708f8fSGustavo F. Padovan { 77340a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs); 7735354fe804SJohan Hedberg hci_unregister_cb(&l2cap_cb); 7736bb58f747SGustavo F. Padovan l2cap_cleanup_sockets(); 77370a708f8fSGustavo F. Padovan } 77380a708f8fSGustavo F. Padovan 77390a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644); 77400a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); 7741