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; 484be5ca67SLuiz Augusto von Dentz bool enable_ecred; 490a708f8fSGustavo F. Padovan 50547d1032SMarcel Holtmann static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD; 510a708f8fSGustavo F. Padovan 52b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list); 53b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock); 540a708f8fSGustavo F. Padovan 550a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 560a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data); 574519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 584519de9aSGustavo F. Padovan void *data); 59e860d2c9SBen Seri static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size); 605e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err); 610a708f8fSGustavo F. Padovan 62d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 63608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event); 64608bcc6dSMat Martineau 65a250e048SJohan Hedberg static inline u8 bdaddr_type(u8 link_type, u8 bdaddr_type) 664f1654e0SMarcel Holtmann { 67a250e048SJohan Hedberg if (link_type == LE_LINK) { 68a250e048SJohan Hedberg if (bdaddr_type == ADDR_LE_DEV_PUBLIC) 694f1654e0SMarcel Holtmann return BDADDR_LE_PUBLIC; 704f1654e0SMarcel Holtmann else 714f1654e0SMarcel Holtmann return BDADDR_LE_RANDOM; 724f1654e0SMarcel Holtmann } 734f1654e0SMarcel Holtmann 744f1654e0SMarcel Holtmann return BDADDR_BREDR; 754f1654e0SMarcel Holtmann } 764f1654e0SMarcel Holtmann 77a250e048SJohan Hedberg static inline u8 bdaddr_src_type(struct hci_conn *hcon) 78a250e048SJohan Hedberg { 79a250e048SJohan Hedberg return bdaddr_type(hcon->type, hcon->src_type); 80a250e048SJohan Hedberg } 81a250e048SJohan Hedberg 82a250e048SJohan Hedberg static inline u8 bdaddr_dst_type(struct hci_conn *hcon) 83a250e048SJohan Hedberg { 84a250e048SJohan Hedberg return bdaddr_type(hcon->type, hcon->dst_type); 85a250e048SJohan Hedberg } 86a250e048SJohan Hedberg 870a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */ 8871ba0e56SGustavo F. Padovan 892d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, 902d792818SGustavo Padovan u16 cid) 910a708f8fSGustavo F. Padovan { 923df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 93baa7e1faSGustavo F. Padovan 943df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 953df91ea2SAndrei Emeltchenko if (c->dcid == cid) 963df91ea2SAndrei Emeltchenko return c; 970a708f8fSGustavo F. Padovan } 983df91ea2SAndrei Emeltchenko return NULL; 99baa7e1faSGustavo F. Padovan } 1000a708f8fSGustavo F. Padovan 1012d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, 1022d792818SGustavo Padovan u16 cid) 1030a708f8fSGustavo F. Padovan { 1043df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 105baa7e1faSGustavo F. Padovan 1063df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 1073df91ea2SAndrei Emeltchenko if (c->scid == cid) 1083df91ea2SAndrei Emeltchenko return c; 1090a708f8fSGustavo F. Padovan } 1103df91ea2SAndrei Emeltchenko return NULL; 111baa7e1faSGustavo F. Padovan } 1120a708f8fSGustavo F. Padovan 1130a708f8fSGustavo F. Padovan /* Find channel with given SCID. 114ef191adeSMat Martineau * Returns locked channel. */ 1152d792818SGustavo Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, 1162d792818SGustavo Padovan u16 cid) 1170a708f8fSGustavo F. Padovan { 11848454079SGustavo F. Padovan struct l2cap_chan *c; 119baa7e1faSGustavo F. Padovan 1203df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 121baa7e1faSGustavo F. Padovan c = __l2cap_get_chan_by_scid(conn, cid); 122ef191adeSMat Martineau if (c) 123ef191adeSMat Martineau l2cap_chan_lock(c); 1243df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 1253df91ea2SAndrei Emeltchenko 12648454079SGustavo F. Padovan return c; 1270a708f8fSGustavo F. Padovan } 1280a708f8fSGustavo F. Padovan 129b1a130b7SMat Martineau /* Find channel with given DCID. 130b1a130b7SMat Martineau * Returns locked channel. 131b1a130b7SMat Martineau */ 132b1a130b7SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn, 133b1a130b7SMat Martineau u16 cid) 134b1a130b7SMat Martineau { 135b1a130b7SMat Martineau struct l2cap_chan *c; 136b1a130b7SMat Martineau 137b1a130b7SMat Martineau mutex_lock(&conn->chan_lock); 138b1a130b7SMat Martineau c = __l2cap_get_chan_by_dcid(conn, cid); 139b1a130b7SMat Martineau if (c) 140b1a130b7SMat Martineau l2cap_chan_lock(c); 141b1a130b7SMat Martineau mutex_unlock(&conn->chan_lock); 142b1a130b7SMat Martineau 143b1a130b7SMat Martineau return c; 144b1a130b7SMat Martineau } 145b1a130b7SMat Martineau 1462d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, 1472d792818SGustavo Padovan u8 ident) 1480a708f8fSGustavo F. Padovan { 1493df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 150baa7e1faSGustavo F. Padovan 1513df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 1523df91ea2SAndrei Emeltchenko if (c->ident == ident) 1533df91ea2SAndrei Emeltchenko return c; 1540a708f8fSGustavo F. Padovan } 1553df91ea2SAndrei Emeltchenko return NULL; 156baa7e1faSGustavo F. Padovan } 1570a708f8fSGustavo F. Padovan 1585b155ef9SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, 1595b155ef9SMat Martineau u8 ident) 1605b155ef9SMat Martineau { 1615b155ef9SMat Martineau struct l2cap_chan *c; 1625b155ef9SMat Martineau 1635b155ef9SMat Martineau mutex_lock(&conn->chan_lock); 1645b155ef9SMat Martineau c = __l2cap_get_chan_by_ident(conn, ident); 1655b155ef9SMat Martineau if (c) 1665b155ef9SMat Martineau l2cap_chan_lock(c); 1675b155ef9SMat Martineau mutex_unlock(&conn->chan_lock); 1685b155ef9SMat Martineau 1695b155ef9SMat Martineau return c; 1705b155ef9SMat Martineau } 1715b155ef9SMat Martineau 17200f62726SLuiz Augusto von Dentz static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src, 17300f62726SLuiz Augusto von Dentz u8 src_type) 1749e4425ffSGustavo F. Padovan { 17523691d75SGustavo F. Padovan struct l2cap_chan *c; 1769e4425ffSGustavo F. Padovan 17723691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 17800f62726SLuiz Augusto von Dentz if (src_type == BDADDR_BREDR && c->src_type != BDADDR_BREDR) 17900f62726SLuiz Augusto von Dentz continue; 18000f62726SLuiz Augusto von Dentz 18100f62726SLuiz Augusto von Dentz if (src_type != BDADDR_BREDR && c->src_type == BDADDR_BREDR) 18200f62726SLuiz Augusto von Dentz continue; 18300f62726SLuiz Augusto von Dentz 1847eafc59eSMarcel Holtmann if (c->sport == psm && !bacmp(&c->src, src)) 18523691d75SGustavo F. Padovan return c; 1869e4425ffSGustavo F. Padovan } 187250938cbSSzymon Janc return NULL; 188250938cbSSzymon Janc } 1899e4425ffSGustavo F. Padovan 1909e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) 1919e4425ffSGustavo F. Padovan { 19273b2ec18SGustavo F. Padovan int err; 19373b2ec18SGustavo F. Padovan 194333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 1959e4425ffSGustavo F. Padovan 19600f62726SLuiz Augusto von Dentz if (psm && __l2cap_global_chan_by_addr(psm, src, chan->src_type)) { 19773b2ec18SGustavo F. Padovan err = -EADDRINUSE; 19873b2ec18SGustavo F. Padovan goto done; 1999e4425ffSGustavo F. Padovan } 2009e4425ffSGustavo F. Padovan 20173b2ec18SGustavo F. Padovan if (psm) { 2029e4425ffSGustavo F. Padovan chan->psm = psm; 2039e4425ffSGustavo F. Padovan chan->sport = psm; 20473b2ec18SGustavo F. Padovan err = 0; 20573b2ec18SGustavo F. Padovan } else { 20692594a51SJohan Hedberg u16 p, start, end, incr; 20792594a51SJohan Hedberg 20892594a51SJohan Hedberg if (chan->src_type == BDADDR_BREDR) { 20992594a51SJohan Hedberg start = L2CAP_PSM_DYN_START; 21092594a51SJohan Hedberg end = L2CAP_PSM_AUTO_END; 21192594a51SJohan Hedberg incr = 2; 21292594a51SJohan Hedberg } else { 21392594a51SJohan Hedberg start = L2CAP_PSM_LE_DYN_START; 21492594a51SJohan Hedberg end = L2CAP_PSM_LE_DYN_END; 21592594a51SJohan Hedberg incr = 1; 21692594a51SJohan Hedberg } 2179e4425ffSGustavo F. Padovan 21873b2ec18SGustavo F. Padovan err = -EINVAL; 21992594a51SJohan Hedberg for (p = start; p <= end; p += incr) 22000f62726SLuiz Augusto von Dentz if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src, 22100f62726SLuiz Augusto von Dentz chan->src_type)) { 22273b2ec18SGustavo F. Padovan chan->psm = cpu_to_le16(p); 22373b2ec18SGustavo F. Padovan chan->sport = cpu_to_le16(p); 22473b2ec18SGustavo F. Padovan err = 0; 22573b2ec18SGustavo F. Padovan break; 22673b2ec18SGustavo F. Padovan } 22773b2ec18SGustavo F. Padovan } 22873b2ec18SGustavo F. Padovan 22973b2ec18SGustavo F. Padovan done: 230333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 23173b2ec18SGustavo F. Padovan return err; 2329e4425ffSGustavo F. Padovan } 2336b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_add_psm); 2349e4425ffSGustavo F. Padovan 2359e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) 2369e4425ffSGustavo F. Padovan { 237333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 2389e4425ffSGustavo F. Padovan 23914824308SJohan Hedberg /* Override the defaults (which are for conn-oriented) */ 24014824308SJohan Hedberg chan->omtu = L2CAP_DEFAULT_MTU; 24114824308SJohan Hedberg chan->chan_type = L2CAP_CHAN_FIXED; 24214824308SJohan Hedberg 2439e4425ffSGustavo F. Padovan chan->scid = scid; 2449e4425ffSGustavo F. Padovan 245333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 2469e4425ffSGustavo F. Padovan 2479e4425ffSGustavo F. Padovan return 0; 2489e4425ffSGustavo F. Padovan } 2499e4425ffSGustavo F. Padovan 250baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn) 2510a708f8fSGustavo F. Padovan { 252e77af755SJohan Hedberg u16 cid, dyn_end; 2530a708f8fSGustavo F. Padovan 254e77af755SJohan Hedberg if (conn->hcon->type == LE_LINK) 255e77af755SJohan Hedberg dyn_end = L2CAP_CID_LE_DYN_END; 256e77af755SJohan Hedberg else 257e77af755SJohan Hedberg dyn_end = L2CAP_CID_DYN_END; 258e77af755SJohan Hedberg 259ab0c127fSJohan Hedberg for (cid = L2CAP_CID_DYN_START; cid <= dyn_end; cid++) { 260baa7e1faSGustavo F. Padovan if (!__l2cap_get_chan_by_scid(conn, cid)) 2610a708f8fSGustavo F. Padovan return cid; 2620a708f8fSGustavo F. Padovan } 2630a708f8fSGustavo F. Padovan 2640a708f8fSGustavo F. Padovan return 0; 2650a708f8fSGustavo F. Padovan } 2660a708f8fSGustavo F. Padovan 267f93fa273SGustavo Padovan static void l2cap_state_change(struct l2cap_chan *chan, int state) 26889bc500eSGustavo F. Padovan { 26942d2d87cSAndrei Emeltchenko BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state), 270badaaa00SGustavo F. Padovan state_to_string(state)); 271badaaa00SGustavo F. Padovan 27289bc500eSGustavo F. Padovan chan->state = state; 27353f52121SGustavo Padovan chan->ops->state_change(chan, state, 0); 27489bc500eSGustavo F. Padovan } 27589bc500eSGustavo F. Padovan 276f8e73017SGustavo Padovan static inline void l2cap_state_change_and_error(struct l2cap_chan *chan, 277f8e73017SGustavo Padovan int state, int err) 2782e0052e4SAndrei Emeltchenko { 279f8e73017SGustavo Padovan chan->state = state; 28053f52121SGustavo Padovan chan->ops->state_change(chan, chan->state, err); 2812e0052e4SAndrei Emeltchenko } 2822e0052e4SAndrei Emeltchenko 2832e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err) 2842e0052e4SAndrei Emeltchenko { 285f8e73017SGustavo Padovan chan->ops->state_change(chan, chan->state, err); 2862e0052e4SAndrei Emeltchenko } 2872e0052e4SAndrei Emeltchenko 2884239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan) 2894239d16fSMat Martineau { 2904239d16fSMat Martineau if (!delayed_work_pending(&chan->monitor_timer) && 2914239d16fSMat Martineau chan->retrans_timeout) { 2924239d16fSMat Martineau l2cap_set_timer(chan, &chan->retrans_timer, 2934239d16fSMat Martineau msecs_to_jiffies(chan->retrans_timeout)); 2944239d16fSMat Martineau } 2954239d16fSMat Martineau } 2964239d16fSMat Martineau 2974239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan) 2984239d16fSMat Martineau { 2994239d16fSMat Martineau __clear_retrans_timer(chan); 3004239d16fSMat Martineau if (chan->monitor_timeout) { 3014239d16fSMat Martineau l2cap_set_timer(chan, &chan->monitor_timer, 3024239d16fSMat Martineau msecs_to_jiffies(chan->monitor_timeout)); 3034239d16fSMat Martineau } 3044239d16fSMat Martineau } 3054239d16fSMat Martineau 306608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head, 307608bcc6dSMat Martineau u16 seq) 308608bcc6dSMat Martineau { 309608bcc6dSMat Martineau struct sk_buff *skb; 310608bcc6dSMat Martineau 311608bcc6dSMat Martineau skb_queue_walk(head, skb) { 312a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.txseq == seq) 313608bcc6dSMat Martineau return skb; 314608bcc6dSMat Martineau } 315608bcc6dSMat Martineau 316608bcc6dSMat Martineau return NULL; 317608bcc6dSMat Martineau } 318608bcc6dSMat Martineau 3193c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */ 3203c588192SMat Martineau 3213c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for 3223c588192SMat Martineau * SREJ requests that are received and for frames that are to be 3233c588192SMat Martineau * retransmitted. These seq_list functions implement a singly-linked 3243c588192SMat Martineau * list in an array, where membership in the list can also be checked 3253c588192SMat Martineau * in constant time. Items can also be added to the tail of the list 3263c588192SMat Martineau * and removed from the head in constant time, without further memory 3273c588192SMat Martineau * allocs or frees. 3283c588192SMat Martineau */ 3293c588192SMat Martineau 3303c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size) 3313c588192SMat Martineau { 3323c588192SMat Martineau size_t alloc_size, i; 3333c588192SMat Martineau 3343c588192SMat Martineau /* Allocated size is a power of 2 to map sequence numbers 3353c588192SMat Martineau * (which may be up to 14 bits) in to a smaller array that is 3363c588192SMat Martineau * sized for the negotiated ERTM transmit windows. 3373c588192SMat Martineau */ 3383c588192SMat Martineau alloc_size = roundup_pow_of_two(size); 3393c588192SMat Martineau 3406da2ec56SKees Cook seq_list->list = kmalloc_array(alloc_size, sizeof(u16), GFP_KERNEL); 3413c588192SMat Martineau if (!seq_list->list) 3423c588192SMat Martineau return -ENOMEM; 3433c588192SMat Martineau 3443c588192SMat Martineau seq_list->mask = alloc_size - 1; 3453c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3463c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3473c588192SMat Martineau for (i = 0; i < alloc_size; i++) 3483c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 3493c588192SMat Martineau 3503c588192SMat Martineau return 0; 3513c588192SMat Martineau } 3523c588192SMat Martineau 3533c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list) 3543c588192SMat Martineau { 3553c588192SMat Martineau kfree(seq_list->list); 3563c588192SMat Martineau } 3573c588192SMat Martineau 3583c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list, 3593c588192SMat Martineau u16 seq) 3603c588192SMat Martineau { 3613c588192SMat Martineau /* Constant-time check for list membership */ 3623c588192SMat Martineau return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR; 3633c588192SMat Martineau } 3643c588192SMat Martineau 36503a0c5d6SJohan Hedberg static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list) 3663c588192SMat Martineau { 36703a0c5d6SJohan Hedberg u16 seq = seq_list->head; 3683c588192SMat Martineau u16 mask = seq_list->mask; 3693c588192SMat Martineau 3703c588192SMat Martineau seq_list->head = seq_list->list[seq & mask]; 3713c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; 3723c588192SMat Martineau 3733c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_TAIL) { 3743c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3753c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3763c588192SMat Martineau } 3773c588192SMat Martineau 3783c588192SMat Martineau return seq; 3793c588192SMat Martineau } 3803c588192SMat Martineau 3813c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list) 3823c588192SMat Martineau { 3833c588192SMat Martineau u16 i; 384f522ae36SGustavo Padovan 385f522ae36SGustavo Padovan if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) 386f522ae36SGustavo Padovan return; 387f522ae36SGustavo Padovan 3883c588192SMat Martineau for (i = 0; i <= seq_list->mask; i++) 3893c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 3903c588192SMat Martineau 3913c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3923c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3933c588192SMat Martineau } 3943c588192SMat Martineau 3953c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq) 3963c588192SMat Martineau { 3973c588192SMat Martineau u16 mask = seq_list->mask; 3983c588192SMat Martineau 3993c588192SMat Martineau /* All appends happen in constant time */ 4003c588192SMat Martineau 401f522ae36SGustavo Padovan if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR) 402f522ae36SGustavo Padovan return; 403f522ae36SGustavo Padovan 4043c588192SMat Martineau if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR) 4053c588192SMat Martineau seq_list->head = seq; 4063c588192SMat Martineau else 4073c588192SMat Martineau seq_list->list[seq_list->tail & mask] = seq; 4083c588192SMat Martineau 4093c588192SMat Martineau seq_list->tail = seq; 4103c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL; 4113c588192SMat Martineau } 4123c588192SMat Martineau 413721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work) 414ab07801dSGustavo F. Padovan { 415721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 416721c4181SGustavo F. Padovan chan_timer.work); 4173df91ea2SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 418ab07801dSGustavo F. Padovan int reason; 419ab07801dSGustavo F. Padovan 420e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 421ab07801dSGustavo F. Padovan 4223df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 4236c08fc89SManish Mandlik /* __set_chan_timer() calls l2cap_chan_hold(chan) while scheduling 4246c08fc89SManish Mandlik * this work. No need to call l2cap_chan_hold(chan) here again. 4256c08fc89SManish Mandlik */ 4266be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 427ab07801dSGustavo F. Padovan 42889bc500eSGustavo F. Padovan if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) 429ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 43089bc500eSGustavo F. Padovan else if (chan->state == BT_CONNECT && 431ab07801dSGustavo F. Padovan chan->sec_level != BT_SECURITY_SDP) 432ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 433ab07801dSGustavo F. Padovan else 434ab07801dSGustavo F. Padovan reason = ETIMEDOUT; 435ab07801dSGustavo F. Padovan 4360f852724SGustavo F. Padovan l2cap_chan_close(chan, reason); 437ab07801dSGustavo F. Padovan 43880b98027SGustavo Padovan chan->ops->close(chan); 4393df91ea2SAndrei Emeltchenko 4406c08fc89SManish Mandlik l2cap_chan_unlock(chan); 441371fd835SUlisses Furquim l2cap_chan_put(chan); 4426c08fc89SManish Mandlik 4436c08fc89SManish Mandlik mutex_unlock(&conn->chan_lock); 444ab07801dSGustavo F. Padovan } 445ab07801dSGustavo F. Padovan 446eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void) 4470a708f8fSGustavo F. Padovan { 44848454079SGustavo F. Padovan struct l2cap_chan *chan; 4490a708f8fSGustavo F. Padovan 45048454079SGustavo F. Padovan chan = kzalloc(sizeof(*chan), GFP_ATOMIC); 45148454079SGustavo F. Padovan if (!chan) 45248454079SGustavo F. Padovan return NULL; 4530a708f8fSGustavo F. Padovan 454c03b355eSAndrei Emeltchenko mutex_init(&chan->lock); 455c03b355eSAndrei Emeltchenko 456ff714119SJohan Hedberg /* Set default lock nesting level */ 457ff714119SJohan Hedberg atomic_set(&chan->nesting, L2CAP_NESTING_NORMAL); 458ff714119SJohan Hedberg 459333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 46023691d75SGustavo F. Padovan list_add(&chan->global_l, &chan_list); 461333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 46223691d75SGustavo F. Padovan 463721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout); 464ab07801dSGustavo F. Padovan 46589bc500eSGustavo F. Padovan chan->state = BT_OPEN; 46689bc500eSGustavo F. Padovan 467144ad330SSyam Sidhardhan kref_init(&chan->kref); 46871ba0e56SGustavo F. Padovan 4692827011fSMat Martineau /* This flag is cleared in l2cap_chan_ready() */ 4702827011fSMat Martineau set_bit(CONF_NOT_COMPLETE, &chan->conf_state); 4712827011fSMat Martineau 472eef1d9b6SGustavo Padovan BT_DBG("chan %p", chan); 473abc545b8SSzymon Janc 47448454079SGustavo F. Padovan return chan; 4750a708f8fSGustavo F. Padovan } 4766b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_create); 4770a708f8fSGustavo F. Padovan 478144ad330SSyam Sidhardhan static void l2cap_chan_destroy(struct kref *kref) 4796ff5abbfSGustavo F. Padovan { 480144ad330SSyam Sidhardhan struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref); 481144ad330SSyam Sidhardhan 4824af66c69SJaganath Kanakkassery BT_DBG("chan %p", chan); 4834af66c69SJaganath Kanakkassery 484333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 48523691d75SGustavo F. Padovan list_del(&chan->global_l); 486333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 48723691d75SGustavo F. Padovan 4884af66c69SJaganath Kanakkassery kfree(chan); 4896ff5abbfSGustavo F. Padovan } 4906ff5abbfSGustavo F. Padovan 49130648372SJaganath Kanakkassery void l2cap_chan_hold(struct l2cap_chan *c) 49230648372SJaganath Kanakkassery { 4932c935bc5SPeter Zijlstra BT_DBG("chan %p orig refcnt %d", c, kref_read(&c->kref)); 49430648372SJaganath Kanakkassery 495144ad330SSyam Sidhardhan kref_get(&c->kref); 49630648372SJaganath Kanakkassery } 49730648372SJaganath Kanakkassery 49830648372SJaganath Kanakkassery void l2cap_chan_put(struct l2cap_chan *c) 49930648372SJaganath Kanakkassery { 5002c935bc5SPeter Zijlstra BT_DBG("chan %p orig refcnt %d", c, kref_read(&c->kref)); 50130648372SJaganath Kanakkassery 502144ad330SSyam Sidhardhan kref_put(&c->kref, l2cap_chan_destroy); 50330648372SJaganath Kanakkassery } 5046b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_put); 50530648372SJaganath Kanakkassery 506bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan) 507bd4b1653SAndrei Emeltchenko { 508bd4b1653SAndrei Emeltchenko chan->fcs = L2CAP_FCS_CRC16; 509bd4b1653SAndrei Emeltchenko chan->max_tx = L2CAP_DEFAULT_MAX_TX; 510bd4b1653SAndrei Emeltchenko chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; 511bd4b1653SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 5126a5e8165SJukka Rissanen chan->remote_max_tx = chan->max_tx; 5136a5e8165SJukka Rissanen chan->remote_tx_win = chan->tx_win; 514c20f8e35SMat Martineau chan->ack_win = L2CAP_DEFAULT_TX_WINDOW; 515bd4b1653SAndrei Emeltchenko chan->sec_level = BT_SECURITY_LOW; 5166a5e8165SJukka Rissanen chan->flush_to = L2CAP_DEFAULT_FLUSH_TO; 5176a5e8165SJukka Rissanen chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO; 5186a5e8165SJukka Rissanen chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO; 519*3a9d54b1SArchie Pusaka 5206a5e8165SJukka Rissanen chan->conf_state = 0; 521*3a9d54b1SArchie Pusaka set_bit(CONF_NOT_COMPLETE, &chan->conf_state); 522bd4b1653SAndrei Emeltchenko 523bd4b1653SAndrei Emeltchenko set_bit(FLAG_FORCE_ACTIVE, &chan->flags); 524bd4b1653SAndrei Emeltchenko } 5256b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_set_defaults); 526bd4b1653SAndrei Emeltchenko 527ba8f5289SLuiz Augusto von Dentz static void l2cap_le_flowctl_init(struct l2cap_chan *chan, u16 tx_credits) 52838319713SJohan Hedberg { 5290ce43ce6SJohan Hedberg chan->sdu = NULL; 5300ce43ce6SJohan Hedberg chan->sdu_last_frag = NULL; 5310ce43ce6SJohan Hedberg chan->sdu_len = 0; 532ba8f5289SLuiz Augusto von Dentz chan->tx_credits = tx_credits; 533fe149310SLuiz Augusto von Dentz /* Derive MPS from connection MTU to stop HCI fragmentation */ 534fe149310SLuiz Augusto von Dentz chan->mps = min_t(u16, chan->imtu, chan->conn->mtu - L2CAP_HDR_SIZE); 53596cd8eaaSLuiz Augusto von Dentz /* Give enough credits for a full packet */ 53696cd8eaaSLuiz Augusto von Dentz chan->rx_credits = (chan->imtu / chan->mps) + 1; 5370ce43ce6SJohan Hedberg 5380ce43ce6SJohan Hedberg skb_queue_head_init(&chan->tx_q); 53938319713SJohan Hedberg } 54038319713SJohan Hedberg 54115f02b91SLuiz Augusto von Dentz static void l2cap_ecred_init(struct l2cap_chan *chan, u16 tx_credits) 54215f02b91SLuiz Augusto von Dentz { 54315f02b91SLuiz Augusto von Dentz l2cap_le_flowctl_init(chan, tx_credits); 54415f02b91SLuiz Augusto von Dentz 54515f02b91SLuiz Augusto von Dentz /* L2CAP implementations shall support a minimum MPS of 64 octets */ 54615f02b91SLuiz Augusto von Dentz if (chan->mps < L2CAP_ECRED_MIN_MPS) { 54715f02b91SLuiz Augusto von Dentz chan->mps = L2CAP_ECRED_MIN_MPS; 54815f02b91SLuiz Augusto von Dentz chan->rx_credits = (chan->imtu / chan->mps) + 1; 54915f02b91SLuiz Augusto von Dentz } 55015f02b91SLuiz Augusto von Dentz } 55115f02b91SLuiz Augusto von Dentz 55293c3e8f5SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 5530a708f8fSGustavo F. Padovan { 5540a708f8fSGustavo F. Padovan BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, 555097db76cSAndrei Emeltchenko __le16_to_cpu(chan->psm), chan->dcid); 5560a708f8fSGustavo F. Padovan 5579f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 5580a708f8fSGustavo F. Padovan 5598c1d787bSGustavo F. Padovan chan->conn = conn; 5600a708f8fSGustavo F. Padovan 5615491120eSAndrei Emeltchenko switch (chan->chan_type) { 5625491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_ORIENTED: 5630a708f8fSGustavo F. Padovan /* Alloc CID for connection-oriented socket */ 564fe4128e0SGustavo F. Padovan chan->scid = l2cap_alloc_cid(conn); 56521626e62SJohan Hedberg if (conn->hcon->type == ACL_LINK) 5660c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 5675491120eSAndrei Emeltchenko break; 5685491120eSAndrei Emeltchenko 5695491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_LESS: 5700a708f8fSGustavo F. Padovan /* Connectionless socket */ 571fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_CONN_LESS; 572fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_CONN_LESS; 5730c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 5745491120eSAndrei Emeltchenko break; 5755491120eSAndrei Emeltchenko 5762338a7e0SJohan Hedberg case L2CAP_CHAN_FIXED: 5772338a7e0SJohan Hedberg /* Caller will set CID and CID specific MTU values */ 578416fa752SAndrei Emeltchenko break; 579416fa752SAndrei Emeltchenko 5805491120eSAndrei Emeltchenko default: 5810a708f8fSGustavo F. Padovan /* Raw socket can send/recv signalling messages only */ 582fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_SIGNALING; 583fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_SIGNALING; 5840c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 5850a708f8fSGustavo F. Padovan } 5860a708f8fSGustavo F. Padovan 5878f7975b1SAndrei Emeltchenko chan->local_id = L2CAP_BESTEFFORT_ID; 5888f7975b1SAndrei Emeltchenko chan->local_stype = L2CAP_SERV_BESTEFFORT; 5898f7975b1SAndrei Emeltchenko chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE; 5908f7975b1SAndrei Emeltchenko chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME; 5918f7975b1SAndrei Emeltchenko chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT; 5928936fa6dSAndrei Emeltchenko chan->local_flush_to = L2CAP_EFS_DEFAULT_FLUSH_TO; 5938f7975b1SAndrei Emeltchenko 594371fd835SUlisses Furquim l2cap_chan_hold(chan); 595baa7e1faSGustavo F. Padovan 596c16900cfSJohan Hedberg /* Only keep a reference for fixed channels if they requested it */ 597c16900cfSJohan Hedberg if (chan->chan_type != L2CAP_CHAN_FIXED || 598c16900cfSJohan Hedberg test_bit(FLAG_HOLD_HCI_CONN, &chan->flags)) 5995ee9891dSJohan Hedberg hci_conn_hold(conn->hcon); 6005ee9891dSJohan Hedberg 6013df91ea2SAndrei Emeltchenko list_add(&chan->list, &conn->chan_l); 602643162a8SAndrei Emeltchenko } 603643162a8SAndrei Emeltchenko 604466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 605643162a8SAndrei Emeltchenko { 606643162a8SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 607643162a8SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 6083df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 6090a708f8fSGustavo F. Padovan } 6100a708f8fSGustavo F. Padovan 611466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err) 6120a708f8fSGustavo F. Padovan { 6138c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 6140a708f8fSGustavo F. Padovan 615c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 6160a708f8fSGustavo F. Padovan 61749d11741SJohan Hedberg BT_DBG("chan %p, conn %p, err %d, state %s", chan, conn, err, 61849d11741SJohan Hedberg state_to_string(chan->state)); 6190a708f8fSGustavo F. Padovan 62072847ce0SJohan Hedberg chan->ops->teardown(chan, err); 62172847ce0SJohan Hedberg 6220a708f8fSGustavo F. Padovan if (conn) { 62356f60984SAndrei Emeltchenko struct amp_mgr *mgr = conn->hcon->amp_mgr; 624baa7e1faSGustavo F. Padovan /* Delete from channel list */ 6253df91ea2SAndrei Emeltchenko list_del(&chan->list); 6263d57dc68SGustavo F. Padovan 627371fd835SUlisses Furquim l2cap_chan_put(chan); 628baa7e1faSGustavo F. Padovan 6298c1d787bSGustavo F. Padovan chan->conn = NULL; 6303cabbfdaSAndrei Emeltchenko 631c16900cfSJohan Hedberg /* Reference was only held for non-fixed channels or 632c16900cfSJohan Hedberg * fixed channels that explicitly requested it using the 633c16900cfSJohan Hedberg * FLAG_HOLD_HCI_CONN flag. 634c16900cfSJohan Hedberg */ 635c16900cfSJohan Hedberg if (chan->chan_type != L2CAP_CHAN_FIXED || 636c16900cfSJohan Hedberg test_bit(FLAG_HOLD_HCI_CONN, &chan->flags)) 63776a68ba0SDavid Herrmann hci_conn_drop(conn->hcon); 63856f60984SAndrei Emeltchenko 63956f60984SAndrei Emeltchenko if (mgr && mgr->bredr_chan == chan) 64056f60984SAndrei Emeltchenko mgr->bredr_chan = NULL; 6410a708f8fSGustavo F. Padovan } 6420a708f8fSGustavo F. Padovan 643419e08c1SAndrei Emeltchenko if (chan->hs_hchan) { 644419e08c1SAndrei Emeltchenko struct hci_chan *hs_hchan = chan->hs_hchan; 645419e08c1SAndrei Emeltchenko 646419e08c1SAndrei Emeltchenko BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan); 647419e08c1SAndrei Emeltchenko amp_disconnect_logical_link(hs_hchan); 648419e08c1SAndrei Emeltchenko } 649419e08c1SAndrei Emeltchenko 6502827011fSMat Martineau if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) 6516ff5abbfSGustavo F. Padovan return; 6522ead70b8SGustavo F. Padovan 653ee556f66SGustavo Padovan switch(chan->mode) { 654ee556f66SGustavo Padovan case L2CAP_MODE_BASIC: 655ee556f66SGustavo Padovan break; 6560a708f8fSGustavo F. Padovan 65738319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 65815f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL: 659177f8f2bSJohan Hedberg skb_queue_purge(&chan->tx_q); 66038319713SJohan Hedberg break; 66138319713SJohan Hedberg 662ee556f66SGustavo Padovan case L2CAP_MODE_ERTM: 6631a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 6641a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 6651a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 6660a708f8fSGustavo F. Padovan 667f1c6775bSGustavo F. Padovan skb_queue_purge(&chan->srej_q); 6680a708f8fSGustavo F. Padovan 6693c588192SMat Martineau l2cap_seq_list_free(&chan->srej_list); 6703c588192SMat Martineau l2cap_seq_list_free(&chan->retrans_list); 67119186c7bSGustavo A. R. Silva fallthrough; 672ee556f66SGustavo Padovan 673ee556f66SGustavo Padovan case L2CAP_MODE_STREAMING: 674ee556f66SGustavo Padovan skb_queue_purge(&chan->tx_q); 675ee556f66SGustavo Padovan break; 6760a708f8fSGustavo F. Padovan } 677ee556f66SGustavo Padovan 678ee556f66SGustavo Padovan return; 6790a708f8fSGustavo F. Padovan } 6806b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_del); 6810a708f8fSGustavo F. Padovan 682da49b602SLuiz Augusto von Dentz static void __l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func, 683da49b602SLuiz Augusto von Dentz void *data) 684da49b602SLuiz Augusto von Dentz { 685da49b602SLuiz Augusto von Dentz struct l2cap_chan *chan; 686da49b602SLuiz Augusto von Dentz 687da49b602SLuiz Augusto von Dentz list_for_each_entry(chan, &conn->chan_l, list) { 688da49b602SLuiz Augusto von Dentz func(chan, data); 689da49b602SLuiz Augusto von Dentz } 690da49b602SLuiz Augusto von Dentz } 691da49b602SLuiz Augusto von Dentz 692da49b602SLuiz Augusto von Dentz void l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func, 693da49b602SLuiz Augusto von Dentz void *data) 694da49b602SLuiz Augusto von Dentz { 695da49b602SLuiz Augusto von Dentz if (!conn) 696da49b602SLuiz Augusto von Dentz return; 697da49b602SLuiz Augusto von Dentz 698da49b602SLuiz Augusto von Dentz mutex_lock(&conn->chan_lock); 699da49b602SLuiz Augusto von Dentz __l2cap_chan_list(conn, func, data); 700da49b602SLuiz Augusto von Dentz mutex_unlock(&conn->chan_lock); 701da49b602SLuiz Augusto von Dentz } 702da49b602SLuiz Augusto von Dentz 703da49b602SLuiz Augusto von Dentz EXPORT_SYMBOL_GPL(l2cap_chan_list); 704da49b602SLuiz Augusto von Dentz 705f3d82d0cSJohan Hedberg static void l2cap_conn_update_id_addr(struct work_struct *work) 706387a33e3SJohan Hedberg { 707f3d82d0cSJohan Hedberg struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 708f3d82d0cSJohan Hedberg id_addr_update_work); 709f3d82d0cSJohan Hedberg struct hci_conn *hcon = conn->hcon; 710387a33e3SJohan Hedberg struct l2cap_chan *chan; 711387a33e3SJohan Hedberg 712387a33e3SJohan Hedberg mutex_lock(&conn->chan_lock); 713387a33e3SJohan Hedberg 714387a33e3SJohan Hedberg list_for_each_entry(chan, &conn->chan_l, list) { 715387a33e3SJohan Hedberg l2cap_chan_lock(chan); 716387a33e3SJohan Hedberg bacpy(&chan->dst, &hcon->dst); 717a250e048SJohan Hedberg chan->dst_type = bdaddr_dst_type(hcon); 718387a33e3SJohan Hedberg l2cap_chan_unlock(chan); 719387a33e3SJohan Hedberg } 720387a33e3SJohan Hedberg 721387a33e3SJohan Hedberg mutex_unlock(&conn->chan_lock); 722387a33e3SJohan Hedberg } 723387a33e3SJohan Hedberg 72427e2d4c8SJohan Hedberg static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan) 72527e2d4c8SJohan Hedberg { 72627e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn; 72727e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 72827e2d4c8SJohan Hedberg u16 result; 72927e2d4c8SJohan Hedberg 73027e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 731571f7390SMallikarjun Phulari result = L2CAP_CR_LE_AUTHORIZATION; 73227e2d4c8SJohan Hedberg else 733571f7390SMallikarjun Phulari result = L2CAP_CR_LE_BAD_PSM; 73427e2d4c8SJohan Hedberg 73527e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_DISCONN); 73627e2d4c8SJohan Hedberg 73727e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 73827e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 7393916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps); 7400cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits); 74127e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result); 74227e2d4c8SJohan Hedberg 74327e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), 74427e2d4c8SJohan Hedberg &rsp); 74527e2d4c8SJohan Hedberg } 74627e2d4c8SJohan Hedberg 74715f02b91SLuiz Augusto von Dentz static void l2cap_chan_ecred_connect_reject(struct l2cap_chan *chan) 74815f02b91SLuiz Augusto von Dentz { 74915f02b91SLuiz Augusto von Dentz struct l2cap_conn *conn = chan->conn; 75015f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp rsp; 75115f02b91SLuiz Augusto von Dentz u16 result; 75215f02b91SLuiz Augusto von Dentz 75315f02b91SLuiz Augusto von Dentz if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 75415f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_AUTHORIZATION; 75515f02b91SLuiz Augusto von Dentz else 75615f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_BAD_PSM; 75715f02b91SLuiz Augusto von Dentz 75815f02b91SLuiz Augusto von Dentz l2cap_state_change(chan, BT_DISCONN); 75915f02b91SLuiz Augusto von Dentz 76015f02b91SLuiz Augusto von Dentz memset(&rsp, 0, sizeof(rsp)); 76115f02b91SLuiz Augusto von Dentz 76215f02b91SLuiz Augusto von Dentz rsp.result = cpu_to_le16(result); 76315f02b91SLuiz Augusto von Dentz 76415f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), 76515f02b91SLuiz Augusto von Dentz &rsp); 76615f02b91SLuiz Augusto von Dentz } 76715f02b91SLuiz Augusto von Dentz 768791d60f7SJohan Hedberg static void l2cap_chan_connect_reject(struct l2cap_chan *chan) 769791d60f7SJohan Hedberg { 770791d60f7SJohan Hedberg struct l2cap_conn *conn = chan->conn; 771791d60f7SJohan Hedberg struct l2cap_conn_rsp rsp; 772791d60f7SJohan Hedberg u16 result; 773791d60f7SJohan Hedberg 774791d60f7SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 775791d60f7SJohan Hedberg result = L2CAP_CR_SEC_BLOCK; 776791d60f7SJohan Hedberg else 777791d60f7SJohan Hedberg result = L2CAP_CR_BAD_PSM; 778791d60f7SJohan Hedberg 779791d60f7SJohan Hedberg l2cap_state_change(chan, BT_DISCONN); 780791d60f7SJohan Hedberg 781791d60f7SJohan Hedberg rsp.scid = cpu_to_le16(chan->dcid); 782791d60f7SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 783791d60f7SJohan Hedberg rsp.result = cpu_to_le16(result); 784dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 785791d60f7SJohan Hedberg 786791d60f7SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); 787791d60f7SJohan Hedberg } 788791d60f7SJohan Hedberg 7890f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason) 7904519de9aSGustavo F. Padovan { 7914519de9aSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 7924519de9aSGustavo F. Padovan 7937eafc59eSMarcel Holtmann BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 7944519de9aSGustavo F. Padovan 79589bc500eSGustavo F. Padovan switch (chan->state) { 7964519de9aSGustavo F. Padovan case BT_LISTEN: 797c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 7984519de9aSGustavo F. Padovan break; 7994519de9aSGustavo F. Padovan 8004519de9aSGustavo F. Padovan case BT_CONNECTED: 8014519de9aSGustavo F. Padovan case BT_CONFIG: 8027b25c9b3SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) { 8038d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 8045e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, reason); 8054519de9aSGustavo F. Padovan } else 8064519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 8074519de9aSGustavo F. Padovan break; 8084519de9aSGustavo F. Padovan 8094519de9aSGustavo F. Padovan case BT_CONNECT2: 810791d60f7SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) { 811791d60f7SJohan Hedberg if (conn->hcon->type == ACL_LINK) 812791d60f7SJohan Hedberg l2cap_chan_connect_reject(chan); 81315f02b91SLuiz Augusto von Dentz else if (conn->hcon->type == LE_LINK) { 81415f02b91SLuiz Augusto von Dentz switch (chan->mode) { 81515f02b91SLuiz Augusto von Dentz case L2CAP_MODE_LE_FLOWCTL: 81627e2d4c8SJohan Hedberg l2cap_chan_le_connect_reject(chan); 81715f02b91SLuiz Augusto von Dentz break; 81815f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL: 81915f02b91SLuiz Augusto von Dentz l2cap_chan_ecred_connect_reject(chan); 82015f02b91SLuiz Augusto von Dentz break; 82115f02b91SLuiz Augusto von Dentz } 82215f02b91SLuiz Augusto von Dentz } 8234519de9aSGustavo F. Padovan } 8244519de9aSGustavo F. Padovan 8254519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 8264519de9aSGustavo F. Padovan break; 8274519de9aSGustavo F. Padovan 8284519de9aSGustavo F. Padovan case BT_CONNECT: 8294519de9aSGustavo F. Padovan case BT_DISCONN: 8304519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 8314519de9aSGustavo F. Padovan break; 8324519de9aSGustavo F. Padovan 8334519de9aSGustavo F. Padovan default: 834c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 8354519de9aSGustavo F. Padovan break; 8364519de9aSGustavo F. Padovan } 8374519de9aSGustavo F. Padovan } 8386b8d4a6aSJukka Rissanen EXPORT_SYMBOL(l2cap_chan_close); 8394519de9aSGustavo F. Padovan 8404343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) 8410a708f8fSGustavo F. Padovan { 8426a974b50SMarcel Holtmann switch (chan->chan_type) { 8436a974b50SMarcel Holtmann case L2CAP_CHAN_RAW: 8444343478fSGustavo F. Padovan switch (chan->sec_level) { 8450a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 8467d513e92SMarcel Holtmann case BT_SECURITY_FIPS: 8470a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING_MITM; 8480a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 8490a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING; 8500a708f8fSGustavo F. Padovan default: 8510a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 8520a708f8fSGustavo F. Padovan } 8536a974b50SMarcel Holtmann break; 8543124b843SMarcel Holtmann case L2CAP_CHAN_CONN_LESS: 855dcf4adbfSJoe Perches if (chan->psm == cpu_to_le16(L2CAP_PSM_3DSP)) { 8563124b843SMarcel Holtmann if (chan->sec_level == BT_SECURITY_LOW) 8573124b843SMarcel Holtmann chan->sec_level = BT_SECURITY_SDP; 8583124b843SMarcel Holtmann } 8597d513e92SMarcel Holtmann if (chan->sec_level == BT_SECURITY_HIGH || 8607d513e92SMarcel Holtmann chan->sec_level == BT_SECURITY_FIPS) 8613124b843SMarcel Holtmann return HCI_AT_NO_BONDING_MITM; 8623124b843SMarcel Holtmann else 8633124b843SMarcel Holtmann return HCI_AT_NO_BONDING; 8643124b843SMarcel Holtmann break; 8656a974b50SMarcel Holtmann case L2CAP_CHAN_CONN_ORIENTED: 866dcf4adbfSJoe Perches if (chan->psm == cpu_to_le16(L2CAP_PSM_SDP)) { 8674343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_LOW) 8684343478fSGustavo F. Padovan chan->sec_level = BT_SECURITY_SDP; 8690a708f8fSGustavo F. Padovan 8707d513e92SMarcel Holtmann if (chan->sec_level == BT_SECURITY_HIGH || 8717d513e92SMarcel Holtmann chan->sec_level == BT_SECURITY_FIPS) 8720a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING_MITM; 8730a708f8fSGustavo F. Padovan else 8740a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 8756a974b50SMarcel Holtmann } 87619186c7bSGustavo A. R. Silva fallthrough; 87719186c7bSGustavo A. R. Silva 8786a974b50SMarcel Holtmann default: 8794343478fSGustavo F. Padovan switch (chan->sec_level) { 8800a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 8817d513e92SMarcel Holtmann case BT_SECURITY_FIPS: 8820a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING_MITM; 8830a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 8840a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING; 8850a708f8fSGustavo F. Padovan default: 8860a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 8870a708f8fSGustavo F. Padovan } 8886a974b50SMarcel Holtmann break; 8890a708f8fSGustavo F. Padovan } 8900a708f8fSGustavo F. Padovan } 8910a708f8fSGustavo F. Padovan 8920a708f8fSGustavo F. Padovan /* Service level security */ 893e7cafc45SJohan Hedberg int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator) 8940a708f8fSGustavo F. Padovan { 8958c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 8960a708f8fSGustavo F. Padovan __u8 auth_type; 8970a708f8fSGustavo F. Padovan 898a17de2feSJohan Hedberg if (conn->hcon->type == LE_LINK) 899a17de2feSJohan Hedberg return smp_conn_security(conn->hcon, chan->sec_level); 900a17de2feSJohan Hedberg 9014343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 9020a708f8fSGustavo F. Padovan 903e7cafc45SJohan Hedberg return hci_conn_security(conn->hcon, chan->sec_level, auth_type, 904e7cafc45SJohan Hedberg initiator); 9050a708f8fSGustavo F. Padovan } 9060a708f8fSGustavo F. Padovan 907b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn) 9080a708f8fSGustavo F. Padovan { 9090a708f8fSGustavo F. Padovan u8 id; 9100a708f8fSGustavo F. Padovan 9110a708f8fSGustavo F. Padovan /* Get next available identificator. 9120a708f8fSGustavo F. Padovan * 1 - 128 are used by kernel. 9130a708f8fSGustavo F. Padovan * 129 - 199 are reserved. 9140a708f8fSGustavo F. Padovan * 200 - 254 are used by utilities like l2ping, etc. 9150a708f8fSGustavo F. Padovan */ 9160a708f8fSGustavo F. Padovan 9175a54e7c8SMarcel Holtmann mutex_lock(&conn->ident_lock); 9180a708f8fSGustavo F. Padovan 9190a708f8fSGustavo F. Padovan if (++conn->tx_ident > 128) 9200a708f8fSGustavo F. Padovan conn->tx_ident = 1; 9210a708f8fSGustavo F. Padovan 9220a708f8fSGustavo F. Padovan id = conn->tx_ident; 9230a708f8fSGustavo F. Padovan 9245a54e7c8SMarcel Holtmann mutex_unlock(&conn->ident_lock); 9250a708f8fSGustavo F. Padovan 9260a708f8fSGustavo F. Padovan return id; 9270a708f8fSGustavo F. Padovan } 9280a708f8fSGustavo F. Padovan 9292d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 9302d792818SGustavo Padovan void *data) 9310a708f8fSGustavo F. Padovan { 9320a708f8fSGustavo F. Padovan struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); 9330a708f8fSGustavo F. Padovan u8 flags; 9340a708f8fSGustavo F. Padovan 9350a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x", code); 9360a708f8fSGustavo F. Padovan 9370a708f8fSGustavo F. Padovan if (!skb) 9380a708f8fSGustavo F. Padovan return; 9390a708f8fSGustavo F. Padovan 940f6af675eSSteven Walter /* Use NO_FLUSH if supported or we have an LE link (which does 941f6af675eSSteven Walter * not support auto-flushing packets) */ 942f6af675eSSteven Walter if (lmp_no_flush_capable(conn->hcon->hdev) || 943f6af675eSSteven Walter conn->hcon->type == LE_LINK) 9440a708f8fSGustavo F. Padovan flags = ACL_START_NO_FLUSH; 9450a708f8fSGustavo F. Padovan else 9460a708f8fSGustavo F. Padovan flags = ACL_START; 9470a708f8fSGustavo F. Padovan 94814b12d0bSJaikumar Ganesh bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON; 9495e59b791SLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 95014b12d0bSJaikumar Ganesh 95173d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, flags); 9520a708f8fSGustavo F. Padovan } 9530a708f8fSGustavo F. Padovan 95402b0fbb9SMat Martineau static bool __chan_is_moving(struct l2cap_chan *chan) 95502b0fbb9SMat Martineau { 95602b0fbb9SMat Martineau return chan->move_state != L2CAP_MOVE_STABLE && 95702b0fbb9SMat Martineau chan->move_state != L2CAP_MOVE_WAIT_PREPARE; 95802b0fbb9SMat Martineau } 95902b0fbb9SMat Martineau 96073d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) 96173d80debSLuiz Augusto von Dentz { 96273d80debSLuiz Augusto von Dentz struct hci_conn *hcon = chan->conn->hcon; 96373d80debSLuiz Augusto von Dentz u16 flags; 96473d80debSLuiz Augusto von Dentz 96573d80debSLuiz Augusto von Dentz BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, 96673d80debSLuiz Augusto von Dentz skb->priority); 96773d80debSLuiz Augusto von Dentz 968d5f8a75dSMat Martineau if (chan->hs_hcon && !__chan_is_moving(chan)) { 969d5f8a75dSMat Martineau if (chan->hs_hchan) 970d5f8a75dSMat Martineau hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE); 971d5f8a75dSMat Martineau else 972d5f8a75dSMat Martineau kfree_skb(skb); 973d5f8a75dSMat Martineau 974d5f8a75dSMat Martineau return; 975d5f8a75dSMat Martineau } 976d5f8a75dSMat Martineau 977f6af675eSSteven Walter /* Use NO_FLUSH for LE links (where this is the only option) or 978f6af675eSSteven Walter * if the BR/EDR link supports it and flushing has not been 979f6af675eSSteven Walter * explicitly requested (through FLAG_FLUSHABLE). 980f6af675eSSteven Walter */ 981f6af675eSSteven Walter if (hcon->type == LE_LINK || 982f6af675eSSteven Walter (!test_bit(FLAG_FLUSHABLE, &chan->flags) && 983f6af675eSSteven Walter lmp_no_flush_capable(hcon->hdev))) 98473d80debSLuiz Augusto von Dentz flags = ACL_START_NO_FLUSH; 98573d80debSLuiz Augusto von Dentz else 98673d80debSLuiz Augusto von Dentz flags = ACL_START; 98773d80debSLuiz Augusto von Dentz 98873d80debSLuiz Augusto von Dentz bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); 98973d80debSLuiz Augusto von Dentz hci_send_acl(chan->conn->hchan, skb, flags); 9900a708f8fSGustavo F. Padovan } 9910a708f8fSGustavo F. Padovan 992b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control) 993b5c6aaedSMat Martineau { 994b5c6aaedSMat Martineau control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT; 995b5c6aaedSMat Martineau control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT; 996b5c6aaedSMat Martineau 997b5c6aaedSMat Martineau if (enh & L2CAP_CTRL_FRAME_TYPE) { 998b5c6aaedSMat Martineau /* S-Frame */ 999b5c6aaedSMat Martineau control->sframe = 1; 1000b5c6aaedSMat Martineau control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT; 1001b5c6aaedSMat Martineau control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT; 1002b5c6aaedSMat Martineau 1003b5c6aaedSMat Martineau control->sar = 0; 1004b5c6aaedSMat Martineau control->txseq = 0; 1005b5c6aaedSMat Martineau } else { 1006b5c6aaedSMat Martineau /* I-Frame */ 1007b5c6aaedSMat Martineau control->sframe = 0; 1008b5c6aaedSMat Martineau control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT; 1009b5c6aaedSMat Martineau control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT; 1010b5c6aaedSMat Martineau 1011b5c6aaedSMat Martineau control->poll = 0; 1012b5c6aaedSMat Martineau control->super = 0; 1013b5c6aaedSMat Martineau } 1014b5c6aaedSMat Martineau } 1015b5c6aaedSMat Martineau 1016b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control) 1017b5c6aaedSMat Martineau { 1018b5c6aaedSMat Martineau control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT; 1019b5c6aaedSMat Martineau control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT; 1020b5c6aaedSMat Martineau 1021b5c6aaedSMat Martineau if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) { 1022b5c6aaedSMat Martineau /* S-Frame */ 1023b5c6aaedSMat Martineau control->sframe = 1; 1024b5c6aaedSMat Martineau control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT; 1025b5c6aaedSMat Martineau control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT; 1026b5c6aaedSMat Martineau 1027b5c6aaedSMat Martineau control->sar = 0; 1028b5c6aaedSMat Martineau control->txseq = 0; 1029b5c6aaedSMat Martineau } else { 1030b5c6aaedSMat Martineau /* I-Frame */ 1031b5c6aaedSMat Martineau control->sframe = 0; 1032b5c6aaedSMat Martineau control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT; 1033b5c6aaedSMat Martineau control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT; 1034b5c6aaedSMat Martineau 1035b5c6aaedSMat Martineau control->poll = 0; 1036b5c6aaedSMat Martineau control->super = 0; 1037b5c6aaedSMat Martineau } 1038b5c6aaedSMat Martineau } 1039b5c6aaedSMat Martineau 1040b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan, 1041b5c6aaedSMat Martineau struct sk_buff *skb) 1042b5c6aaedSMat Martineau { 1043b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 1044b5c6aaedSMat Martineau __unpack_extended_control(get_unaligned_le32(skb->data), 1045a4368ff3SJohan Hedberg &bt_cb(skb)->l2cap); 1046cec8ab6eSMat Martineau skb_pull(skb, L2CAP_EXT_CTRL_SIZE); 1047b5c6aaedSMat Martineau } else { 1048b5c6aaedSMat Martineau __unpack_enhanced_control(get_unaligned_le16(skb->data), 1049a4368ff3SJohan Hedberg &bt_cb(skb)->l2cap); 1050cec8ab6eSMat Martineau skb_pull(skb, L2CAP_ENH_CTRL_SIZE); 1051b5c6aaedSMat Martineau } 1052b5c6aaedSMat Martineau } 1053b5c6aaedSMat Martineau 1054b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control) 1055b5c6aaedSMat Martineau { 1056b5c6aaedSMat Martineau u32 packed; 1057b5c6aaedSMat Martineau 1058b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT; 1059b5c6aaedSMat Martineau packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT; 1060b5c6aaedSMat Martineau 1061b5c6aaedSMat Martineau if (control->sframe) { 1062b5c6aaedSMat Martineau packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT; 1063b5c6aaedSMat Martineau packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT; 1064b5c6aaedSMat Martineau packed |= L2CAP_EXT_CTRL_FRAME_TYPE; 1065b5c6aaedSMat Martineau } else { 1066b5c6aaedSMat Martineau packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT; 1067b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT; 1068b5c6aaedSMat Martineau } 1069b5c6aaedSMat Martineau 1070b5c6aaedSMat Martineau return packed; 1071b5c6aaedSMat Martineau } 1072b5c6aaedSMat Martineau 1073b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control) 1074b5c6aaedSMat Martineau { 1075b5c6aaedSMat Martineau u16 packed; 1076b5c6aaedSMat Martineau 1077b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT; 1078b5c6aaedSMat Martineau packed |= control->final << L2CAP_CTRL_FINAL_SHIFT; 1079b5c6aaedSMat Martineau 1080b5c6aaedSMat Martineau if (control->sframe) { 1081b5c6aaedSMat Martineau packed |= control->poll << L2CAP_CTRL_POLL_SHIFT; 1082b5c6aaedSMat Martineau packed |= control->super << L2CAP_CTRL_SUPER_SHIFT; 1083b5c6aaedSMat Martineau packed |= L2CAP_CTRL_FRAME_TYPE; 1084b5c6aaedSMat Martineau } else { 1085b5c6aaedSMat Martineau packed |= control->sar << L2CAP_CTRL_SAR_SHIFT; 1086b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT; 1087b5c6aaedSMat Martineau } 1088b5c6aaedSMat Martineau 1089b5c6aaedSMat Martineau return packed; 1090b5c6aaedSMat Martineau } 1091b5c6aaedSMat Martineau 1092b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan, 1093b5c6aaedSMat Martineau struct l2cap_ctrl *control, 1094b5c6aaedSMat Martineau struct sk_buff *skb) 1095b5c6aaedSMat Martineau { 1096b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 1097b5c6aaedSMat Martineau put_unaligned_le32(__pack_extended_control(control), 1098b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 1099b5c6aaedSMat Martineau } else { 1100b5c6aaedSMat Martineau put_unaligned_le16(__pack_enhanced_control(control), 1101b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 1102b5c6aaedSMat Martineau } 1103b5c6aaedSMat Martineau } 1104b5c6aaedSMat Martineau 1105ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan) 1106ba7aa64fSGustavo Padovan { 1107ba7aa64fSGustavo Padovan if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1108ba7aa64fSGustavo Padovan return L2CAP_EXT_HDR_SIZE; 1109ba7aa64fSGustavo Padovan else 1110ba7aa64fSGustavo Padovan return L2CAP_ENH_HDR_SIZE; 1111ba7aa64fSGustavo Padovan } 1112ba7aa64fSGustavo Padovan 1113a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan, 1114a67d7f6fSMat Martineau u32 control) 11150a708f8fSGustavo F. Padovan { 11160a708f8fSGustavo F. Padovan struct sk_buff *skb; 11170a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 1118ba7aa64fSGustavo Padovan int hlen = __ertm_hdr_size(chan); 11190a708f8fSGustavo F. Padovan 11200a708f8fSGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 112103a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 11220a708f8fSGustavo F. Padovan 1123a67d7f6fSMat Martineau skb = bt_skb_alloc(hlen, GFP_KERNEL); 11240a708f8fSGustavo F. Padovan 11250a708f8fSGustavo F. Padovan if (!skb) 1126a67d7f6fSMat Martineau return ERR_PTR(-ENOMEM); 11270a708f8fSGustavo F. Padovan 11284df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 11290a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); 1130fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 113188843ab0SAndrei Emeltchenko 1132a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1133a67d7f6fSMat Martineau put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 1134a67d7f6fSMat Martineau else 1135a67d7f6fSMat Martineau put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 11360a708f8fSGustavo F. Padovan 113747d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 1138a67d7f6fSMat Martineau u16 fcs = crc16(0, (u8 *)skb->data, skb->len); 113903a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 11400a708f8fSGustavo F. Padovan } 11410a708f8fSGustavo F. Padovan 114273d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 1143a67d7f6fSMat Martineau return skb; 1144a67d7f6fSMat Martineau } 1145a67d7f6fSMat Martineau 1146a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan, 1147a67d7f6fSMat Martineau struct l2cap_ctrl *control) 1148a67d7f6fSMat Martineau { 1149a67d7f6fSMat Martineau struct sk_buff *skb; 1150a67d7f6fSMat Martineau u32 control_field; 1151a67d7f6fSMat Martineau 1152a67d7f6fSMat Martineau BT_DBG("chan %p, control %p", chan, control); 1153a67d7f6fSMat Martineau 1154a67d7f6fSMat Martineau if (!control->sframe) 1155a67d7f6fSMat Martineau return; 1156a67d7f6fSMat Martineau 1157b99e13adSMat Martineau if (__chan_is_moving(chan)) 1158b99e13adSMat Martineau return; 1159b99e13adSMat Martineau 1160a67d7f6fSMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) && 1161a67d7f6fSMat Martineau !control->poll) 1162a67d7f6fSMat Martineau control->final = 1; 1163a67d7f6fSMat Martineau 1164a67d7f6fSMat Martineau if (control->super == L2CAP_SUPER_RR) 1165a67d7f6fSMat Martineau clear_bit(CONN_RNR_SENT, &chan->conn_state); 1166a67d7f6fSMat Martineau else if (control->super == L2CAP_SUPER_RNR) 1167a67d7f6fSMat Martineau set_bit(CONN_RNR_SENT, &chan->conn_state); 1168a67d7f6fSMat Martineau 1169a67d7f6fSMat Martineau if (control->super != L2CAP_SUPER_SREJ) { 1170a67d7f6fSMat Martineau chan->last_acked_seq = control->reqseq; 1171a67d7f6fSMat Martineau __clear_ack_timer(chan); 1172a67d7f6fSMat Martineau } 1173a67d7f6fSMat Martineau 1174a67d7f6fSMat Martineau BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq, 1175a67d7f6fSMat Martineau control->final, control->poll, control->super); 1176a67d7f6fSMat Martineau 1177a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1178a67d7f6fSMat Martineau control_field = __pack_extended_control(control); 1179a67d7f6fSMat Martineau else 1180a67d7f6fSMat Martineau control_field = __pack_enhanced_control(control); 1181a67d7f6fSMat Martineau 1182a67d7f6fSMat Martineau skb = l2cap_create_sframe_pdu(chan, control_field); 1183a67d7f6fSMat Martineau if (!IS_ERR(skb)) 118473d80debSLuiz Augusto von Dentz l2cap_do_send(chan, skb); 11850a708f8fSGustavo F. Padovan } 11860a708f8fSGustavo F. Padovan 1187c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll) 11880a708f8fSGustavo F. Padovan { 1189c9e3d5e0SMat Martineau struct l2cap_ctrl control; 11900a708f8fSGustavo F. Padovan 1191c9e3d5e0SMat Martineau BT_DBG("chan %p, poll %d", chan, poll); 1192c9e3d5e0SMat Martineau 1193c9e3d5e0SMat Martineau memset(&control, 0, sizeof(control)); 1194c9e3d5e0SMat Martineau control.sframe = 1; 1195c9e3d5e0SMat Martineau control.poll = poll; 1196c9e3d5e0SMat Martineau 1197c9e3d5e0SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 1198c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RNR; 1199c9e3d5e0SMat Martineau else 1200c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RR; 1201c9e3d5e0SMat Martineau 1202c9e3d5e0SMat Martineau control.reqseq = chan->buffer_seq; 1203c9e3d5e0SMat Martineau l2cap_send_sframe(chan, &control); 12040a708f8fSGustavo F. Padovan } 12050a708f8fSGustavo F. Padovan 1206b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) 12070a708f8fSGustavo F. Padovan { 12085ff6f34dSJohan Hedberg if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 12095ff6f34dSJohan Hedberg return true; 12105ff6f34dSJohan Hedberg 1211c1360a1cSGustavo F. Padovan return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); 12120a708f8fSGustavo F. Padovan } 12130a708f8fSGustavo F. Padovan 121493c3e8f5SAndrei Emeltchenko static bool __amp_capable(struct l2cap_chan *chan) 121593c3e8f5SAndrei Emeltchenko { 121693c3e8f5SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 12171df7b17aSMarcel Holtmann struct hci_dev *hdev; 12181df7b17aSMarcel Holtmann bool amp_available = false; 121993c3e8f5SAndrei Emeltchenko 12200bd49fc7SJohan Hedberg if (!(conn->local_fixed_chan & L2CAP_FC_A2MP)) 12211df7b17aSMarcel Holtmann return false; 12221df7b17aSMarcel Holtmann 12230bd49fc7SJohan Hedberg if (!(conn->remote_fixed_chan & L2CAP_FC_A2MP)) 12241df7b17aSMarcel Holtmann return false; 12251df7b17aSMarcel Holtmann 12261df7b17aSMarcel Holtmann read_lock(&hci_dev_list_lock); 12271df7b17aSMarcel Holtmann list_for_each_entry(hdev, &hci_dev_list, list) { 12281df7b17aSMarcel Holtmann if (hdev->amp_type != AMP_TYPE_BREDR && 12291df7b17aSMarcel Holtmann test_bit(HCI_UP, &hdev->flags)) { 12301df7b17aSMarcel Holtmann amp_available = true; 12311df7b17aSMarcel Holtmann break; 12321df7b17aSMarcel Holtmann } 12331df7b17aSMarcel Holtmann } 12341df7b17aSMarcel Holtmann read_unlock(&hci_dev_list_lock); 12351df7b17aSMarcel Holtmann 12361df7b17aSMarcel Holtmann if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED) 12371df7b17aSMarcel Holtmann return amp_available; 1238848566b3SMarcel Holtmann 123993c3e8f5SAndrei Emeltchenko return false; 124093c3e8f5SAndrei Emeltchenko } 124193c3e8f5SAndrei Emeltchenko 12425ce66b59SAndrei Emeltchenko static bool l2cap_check_efs(struct l2cap_chan *chan) 12435ce66b59SAndrei Emeltchenko { 12445ce66b59SAndrei Emeltchenko /* Check EFS parameters */ 12455ce66b59SAndrei Emeltchenko return true; 12465ce66b59SAndrei Emeltchenko } 12475ce66b59SAndrei Emeltchenko 12482766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan) 12499b27f350SAndrei Emeltchenko { 12509b27f350SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 12519b27f350SAndrei Emeltchenko struct l2cap_conn_req req; 12529b27f350SAndrei Emeltchenko 12539b27f350SAndrei Emeltchenko req.scid = cpu_to_le16(chan->scid); 12549b27f350SAndrei Emeltchenko req.psm = chan->psm; 12559b27f350SAndrei Emeltchenko 12569b27f350SAndrei Emeltchenko chan->ident = l2cap_get_ident(conn); 12579b27f350SAndrei Emeltchenko 12589b27f350SAndrei Emeltchenko set_bit(CONF_CONNECT_PEND, &chan->conf_state); 12599b27f350SAndrei Emeltchenko 12609b27f350SAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); 12619b27f350SAndrei Emeltchenko } 12629b27f350SAndrei Emeltchenko 12638eb200bdSMat Martineau static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id) 12648eb200bdSMat Martineau { 12658eb200bdSMat Martineau struct l2cap_create_chan_req req; 12668eb200bdSMat Martineau req.scid = cpu_to_le16(chan->scid); 12678eb200bdSMat Martineau req.psm = chan->psm; 12688eb200bdSMat Martineau req.amp_id = amp_id; 12698eb200bdSMat Martineau 12708eb200bdSMat Martineau chan->ident = l2cap_get_ident(chan->conn); 12718eb200bdSMat Martineau 12728eb200bdSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ, 12738eb200bdSMat Martineau sizeof(req), &req); 12748eb200bdSMat Martineau } 12758eb200bdSMat Martineau 127602b0fbb9SMat Martineau static void l2cap_move_setup(struct l2cap_chan *chan) 127702b0fbb9SMat Martineau { 127802b0fbb9SMat Martineau struct sk_buff *skb; 127902b0fbb9SMat Martineau 128002b0fbb9SMat Martineau BT_DBG("chan %p", chan); 128102b0fbb9SMat Martineau 128202b0fbb9SMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 128302b0fbb9SMat Martineau return; 128402b0fbb9SMat Martineau 128502b0fbb9SMat Martineau __clear_retrans_timer(chan); 128602b0fbb9SMat Martineau __clear_monitor_timer(chan); 128702b0fbb9SMat Martineau __clear_ack_timer(chan); 128802b0fbb9SMat Martineau 128902b0fbb9SMat Martineau chan->retry_count = 0; 129002b0fbb9SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 1291a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.retries) 1292a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 1; 129302b0fbb9SMat Martineau else 129402b0fbb9SMat Martineau break; 129502b0fbb9SMat Martineau } 129602b0fbb9SMat Martineau 129702b0fbb9SMat Martineau chan->expected_tx_seq = chan->buffer_seq; 129802b0fbb9SMat Martineau 129902b0fbb9SMat Martineau clear_bit(CONN_REJ_ACT, &chan->conn_state); 130002b0fbb9SMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 130102b0fbb9SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 130202b0fbb9SMat Martineau l2cap_seq_list_clear(&chan->srej_list); 130302b0fbb9SMat Martineau skb_queue_purge(&chan->srej_q); 130402b0fbb9SMat Martineau 130502b0fbb9SMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 130602b0fbb9SMat Martineau chan->rx_state = L2CAP_RX_STATE_MOVE; 130702b0fbb9SMat Martineau 130802b0fbb9SMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 130902b0fbb9SMat Martineau } 131002b0fbb9SMat Martineau 13115f3847a4SMat Martineau static void l2cap_move_done(struct l2cap_chan *chan) 13125f3847a4SMat Martineau { 13135f3847a4SMat Martineau u8 move_role = chan->move_role; 13145f3847a4SMat Martineau BT_DBG("chan %p", chan); 13155f3847a4SMat Martineau 13165f3847a4SMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 13175f3847a4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 13185f3847a4SMat Martineau 13195f3847a4SMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 13205f3847a4SMat Martineau return; 13215f3847a4SMat Martineau 13225f3847a4SMat Martineau switch (move_role) { 13235f3847a4SMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 13245f3847a4SMat Martineau l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL); 13255f3847a4SMat Martineau chan->rx_state = L2CAP_RX_STATE_WAIT_F; 13265f3847a4SMat Martineau break; 13275f3847a4SMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 13285f3847a4SMat Martineau chan->rx_state = L2CAP_RX_STATE_WAIT_P; 13295f3847a4SMat Martineau break; 13305f3847a4SMat Martineau } 13315f3847a4SMat Martineau } 13325f3847a4SMat Martineau 13339f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan) 13349f0caeb1SVinicius Costa Gomes { 1335315917e0SJohan Hedberg /* The channel may have already been flagged as connected in 1336315917e0SJohan Hedberg * case of receiving data before the L2CAP info req/rsp 1337315917e0SJohan Hedberg * procedure is complete. 1338315917e0SJohan Hedberg */ 1339315917e0SJohan Hedberg if (chan->state == BT_CONNECTED) 1340315917e0SJohan Hedberg return; 1341315917e0SJohan Hedberg 13422827011fSMat Martineau /* This clears all conf flags, including CONF_NOT_COMPLETE */ 13439f0caeb1SVinicius Costa Gomes chan->conf_state = 0; 13449f0caeb1SVinicius Costa Gomes __clear_chan_timer(chan); 13459f0caeb1SVinicius Costa Gomes 134615f02b91SLuiz Augusto von Dentz switch (chan->mode) { 134715f02b91SLuiz Augusto von Dentz case L2CAP_MODE_LE_FLOWCTL: 134815f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL: 134915f02b91SLuiz Augusto von Dentz if (!chan->tx_credits) 13500ce43ce6SJohan Hedberg chan->ops->suspend(chan); 135115f02b91SLuiz Augusto von Dentz break; 135215f02b91SLuiz Augusto von Dentz } 1353177f8f2bSJohan Hedberg 135454a59aa2SAndrei Emeltchenko chan->state = BT_CONNECTED; 13559f0caeb1SVinicius Costa Gomes 135654a59aa2SAndrei Emeltchenko chan->ops->ready(chan); 13579f0caeb1SVinicius Costa Gomes } 13589f0caeb1SVinicius Costa Gomes 1359f1496deeSJohan Hedberg static void l2cap_le_connect(struct l2cap_chan *chan) 1360f1496deeSJohan Hedberg { 1361f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1362f1496deeSJohan Hedberg struct l2cap_le_conn_req req; 1363f1496deeSJohan Hedberg 1364595177f3SJohan Hedberg if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags)) 1365595177f3SJohan Hedberg return; 1366595177f3SJohan Hedberg 13674b6e228eSLuiz Augusto von Dentz if (!chan->imtu) 13684b6e228eSLuiz Augusto von Dentz chan->imtu = chan->conn->mtu; 13694b6e228eSLuiz Augusto von Dentz 1370ba8f5289SLuiz Augusto von Dentz l2cap_le_flowctl_init(chan, 0); 1371fe149310SLuiz Augusto von Dentz 1372f1496deeSJohan Hedberg req.psm = chan->psm; 1373f1496deeSJohan Hedberg req.scid = cpu_to_le16(chan->scid); 1374f1496deeSJohan Hedberg req.mtu = cpu_to_le16(chan->imtu); 13753916aed8SJohan Hedberg req.mps = cpu_to_le16(chan->mps); 13760cd75f7eSJohan Hedberg req.credits = cpu_to_le16(chan->rx_credits); 1377f1496deeSJohan Hedberg 1378f1496deeSJohan Hedberg chan->ident = l2cap_get_ident(conn); 1379f1496deeSJohan Hedberg 1380f1496deeSJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ, 1381f1496deeSJohan Hedberg sizeof(req), &req); 1382f1496deeSJohan Hedberg } 1383f1496deeSJohan Hedberg 1384da49b602SLuiz Augusto von Dentz struct l2cap_ecred_conn_data { 138515f02b91SLuiz Augusto von Dentz struct { 138615f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_req req; 1387da49b602SLuiz Augusto von Dentz __le16 scid[5]; 138815f02b91SLuiz Augusto von Dentz } __packed pdu; 1389da49b602SLuiz Augusto von Dentz struct l2cap_chan *chan; 1390da49b602SLuiz Augusto von Dentz struct pid *pid; 1391da49b602SLuiz Augusto von Dentz int count; 1392da49b602SLuiz Augusto von Dentz }; 1393da49b602SLuiz Augusto von Dentz 1394da49b602SLuiz Augusto von Dentz static void l2cap_ecred_defer_connect(struct l2cap_chan *chan, void *data) 1395da49b602SLuiz Augusto von Dentz { 1396da49b602SLuiz Augusto von Dentz struct l2cap_ecred_conn_data *conn = data; 1397da49b602SLuiz Augusto von Dentz struct pid *pid; 1398da49b602SLuiz Augusto von Dentz 1399da49b602SLuiz Augusto von Dentz if (chan == conn->chan) 1400da49b602SLuiz Augusto von Dentz return; 1401da49b602SLuiz Augusto von Dentz 1402da49b602SLuiz Augusto von Dentz if (!test_and_clear_bit(FLAG_DEFER_SETUP, &chan->flags)) 1403da49b602SLuiz Augusto von Dentz return; 1404da49b602SLuiz Augusto von Dentz 1405da49b602SLuiz Augusto von Dentz pid = chan->ops->get_peer_pid(chan); 1406da49b602SLuiz Augusto von Dentz 1407da49b602SLuiz Augusto von Dentz /* Only add deferred channels with the same PID/PSM */ 1408da49b602SLuiz Augusto von Dentz if (conn->pid != pid || chan->psm != conn->chan->psm || chan->ident || 1409da49b602SLuiz Augusto von Dentz chan->mode != L2CAP_MODE_EXT_FLOWCTL || chan->state != BT_CONNECT) 1410da49b602SLuiz Augusto von Dentz return; 141115f02b91SLuiz Augusto von Dentz 141215f02b91SLuiz Augusto von Dentz if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags)) 141315f02b91SLuiz Augusto von Dentz return; 141415f02b91SLuiz Augusto von Dentz 141515f02b91SLuiz Augusto von Dentz l2cap_ecred_init(chan, 0); 141615f02b91SLuiz Augusto von Dentz 1417da49b602SLuiz Augusto von Dentz /* Set the same ident so we can match on the rsp */ 1418da49b602SLuiz Augusto von Dentz chan->ident = conn->chan->ident; 1419da49b602SLuiz Augusto von Dentz 1420da49b602SLuiz Augusto von Dentz /* Include all channels deferred */ 1421da49b602SLuiz Augusto von Dentz conn->pdu.scid[conn->count] = cpu_to_le16(chan->scid); 1422da49b602SLuiz Augusto von Dentz 1423da49b602SLuiz Augusto von Dentz conn->count++; 1424da49b602SLuiz Augusto von Dentz } 1425da49b602SLuiz Augusto von Dentz 1426da49b602SLuiz Augusto von Dentz static void l2cap_ecred_connect(struct l2cap_chan *chan) 1427da49b602SLuiz Augusto von Dentz { 1428da49b602SLuiz Augusto von Dentz struct l2cap_conn *conn = chan->conn; 1429da49b602SLuiz Augusto von Dentz struct l2cap_ecred_conn_data data; 1430da49b602SLuiz Augusto von Dentz 1431da49b602SLuiz Augusto von Dentz if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 1432da49b602SLuiz Augusto von Dentz return; 1433da49b602SLuiz Augusto von Dentz 1434da49b602SLuiz Augusto von Dentz if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags)) 1435da49b602SLuiz Augusto von Dentz return; 1436da49b602SLuiz Augusto von Dentz 1437da49b602SLuiz Augusto von Dentz l2cap_ecred_init(chan, 0); 1438da49b602SLuiz Augusto von Dentz 1439da49b602SLuiz Augusto von Dentz data.pdu.req.psm = chan->psm; 1440da49b602SLuiz Augusto von Dentz data.pdu.req.mtu = cpu_to_le16(chan->imtu); 1441da49b602SLuiz Augusto von Dentz data.pdu.req.mps = cpu_to_le16(chan->mps); 1442da49b602SLuiz Augusto von Dentz data.pdu.req.credits = cpu_to_le16(chan->rx_credits); 1443da49b602SLuiz Augusto von Dentz data.pdu.scid[0] = cpu_to_le16(chan->scid); 144415f02b91SLuiz Augusto von Dentz 144515f02b91SLuiz Augusto von Dentz chan->ident = l2cap_get_ident(conn); 1446da49b602SLuiz Augusto von Dentz data.pid = chan->ops->get_peer_pid(chan); 1447da49b602SLuiz Augusto von Dentz 1448da49b602SLuiz Augusto von Dentz data.count = 1; 1449da49b602SLuiz Augusto von Dentz data.chan = chan; 1450da49b602SLuiz Augusto von Dentz data.pid = chan->ops->get_peer_pid(chan); 1451da49b602SLuiz Augusto von Dentz 1452da49b602SLuiz Augusto von Dentz __l2cap_chan_list(conn, l2cap_ecred_defer_connect, &data); 145315f02b91SLuiz Augusto von Dentz 145415f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_CONN_REQ, 1455da49b602SLuiz Augusto von Dentz sizeof(data.pdu.req) + data.count * sizeof(__le16), 1456da49b602SLuiz Augusto von Dentz &data.pdu); 145715f02b91SLuiz Augusto von Dentz } 145815f02b91SLuiz Augusto von Dentz 1459f1496deeSJohan Hedberg static void l2cap_le_start(struct l2cap_chan *chan) 1460f1496deeSJohan Hedberg { 1461f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1462f1496deeSJohan Hedberg 1463f1496deeSJohan Hedberg if (!smp_conn_security(conn->hcon, chan->sec_level)) 1464f1496deeSJohan Hedberg return; 1465f1496deeSJohan Hedberg 1466f1496deeSJohan Hedberg if (!chan->psm) { 1467f1496deeSJohan Hedberg l2cap_chan_ready(chan); 1468f1496deeSJohan Hedberg return; 1469f1496deeSJohan Hedberg } 1470f1496deeSJohan Hedberg 147115f02b91SLuiz Augusto von Dentz if (chan->state == BT_CONNECT) { 147215f02b91SLuiz Augusto von Dentz if (chan->mode == L2CAP_MODE_EXT_FLOWCTL) 147315f02b91SLuiz Augusto von Dentz l2cap_ecred_connect(chan); 147415f02b91SLuiz Augusto von Dentz else 1475f1496deeSJohan Hedberg l2cap_le_connect(chan); 1476f1496deeSJohan Hedberg } 147715f02b91SLuiz Augusto von Dentz } 1478f1496deeSJohan Hedberg 147993c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan) 148093c3e8f5SAndrei Emeltchenko { 148193c3e8f5SAndrei Emeltchenko if (__amp_capable(chan)) { 148293c3e8f5SAndrei Emeltchenko BT_DBG("chan %p AMP capable: discover AMPs", chan); 148393c3e8f5SAndrei Emeltchenko a2mp_discover_amp(chan); 1484f1496deeSJohan Hedberg } else if (chan->conn->hcon->type == LE_LINK) { 1485f1496deeSJohan Hedberg l2cap_le_start(chan); 148693c3e8f5SAndrei Emeltchenko } else { 148793c3e8f5SAndrei Emeltchenko l2cap_send_conn_req(chan); 148893c3e8f5SAndrei Emeltchenko } 148993c3e8f5SAndrei Emeltchenko } 149093c3e8f5SAndrei Emeltchenko 1491aeaeb4bbSJohan Hedberg static void l2cap_request_info(struct l2cap_conn *conn) 14920a708f8fSGustavo F. Padovan { 14930a708f8fSGustavo F. Padovan struct l2cap_info_req req; 1494aeaeb4bbSJohan Hedberg 1495aeaeb4bbSJohan Hedberg if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1496aeaeb4bbSJohan Hedberg return; 1497aeaeb4bbSJohan Hedberg 1498dcf4adbfSJoe Perches req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 14990a708f8fSGustavo F. Padovan 15000a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 15010a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 15020a708f8fSGustavo F. Padovan 1503ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 15040a708f8fSGustavo F. Padovan 15052d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, 15062d792818SGustavo Padovan sizeof(req), &req); 15070a708f8fSGustavo F. Padovan } 1508aeaeb4bbSJohan Hedberg 1509693cd8ceSMarcel Holtmann static bool l2cap_check_enc_key_size(struct hci_conn *hcon) 1510693cd8ceSMarcel Holtmann { 1511693cd8ceSMarcel Holtmann /* The minimum encryption key size needs to be enforced by the 1512693cd8ceSMarcel Holtmann * host stack before establishing any L2CAP connections. The 1513693cd8ceSMarcel Holtmann * specification in theory allows a minimum of 1, but to align 1514693cd8ceSMarcel Holtmann * BR/EDR and LE transports, a minimum of 7 is chosen. 1515693cd8ceSMarcel Holtmann * 1516693cd8ceSMarcel Holtmann * This check might also be called for unencrypted connections 1517693cd8ceSMarcel Holtmann * that have no key size requirements. Ensure that the link is 1518693cd8ceSMarcel Holtmann * actually encrypted before enforcing a key size. 1519693cd8ceSMarcel Holtmann */ 1520288c0697SArchie Pusaka int min_key_size = hcon->hdev->min_enc_key_size; 1521288c0697SArchie Pusaka 1522288c0697SArchie Pusaka /* On FIPS security level, key size must be 16 bytes */ 1523288c0697SArchie Pusaka if (hcon->sec_level == BT_SECURITY_FIPS) 1524288c0697SArchie Pusaka min_key_size = 16; 1525288c0697SArchie Pusaka 1526693cd8ceSMarcel Holtmann return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) || 1527288c0697SArchie Pusaka hcon->enc_key_size >= min_key_size); 1528693cd8ceSMarcel Holtmann } 1529693cd8ceSMarcel Holtmann 1530aeaeb4bbSJohan Hedberg static void l2cap_do_start(struct l2cap_chan *chan) 1531aeaeb4bbSJohan Hedberg { 1532aeaeb4bbSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1533aeaeb4bbSJohan Hedberg 1534aeaeb4bbSJohan Hedberg if (conn->hcon->type == LE_LINK) { 1535aeaeb4bbSJohan Hedberg l2cap_le_start(chan); 1536aeaeb4bbSJohan Hedberg return; 1537aeaeb4bbSJohan Hedberg } 1538aeaeb4bbSJohan Hedberg 1539aeaeb4bbSJohan Hedberg if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)) { 1540aeaeb4bbSJohan Hedberg l2cap_request_info(conn); 1541aeaeb4bbSJohan Hedberg return; 1542aeaeb4bbSJohan Hedberg } 1543aeaeb4bbSJohan Hedberg 1544aeaeb4bbSJohan Hedberg if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) 1545aeaeb4bbSJohan Hedberg return; 1546aeaeb4bbSJohan Hedberg 1547693cd8ceSMarcel Holtmann if (!l2cap_chan_check_security(chan, true) || 1548693cd8ceSMarcel Holtmann !__l2cap_no_conn_pending(chan)) 1549693cd8ceSMarcel Holtmann return; 1550693cd8ceSMarcel Holtmann 1551693cd8ceSMarcel Holtmann if (l2cap_check_enc_key_size(conn->hcon)) 1552aeaeb4bbSJohan Hedberg l2cap_start_connection(chan); 1553693cd8ceSMarcel Holtmann else 1554693cd8ceSMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 15550a708f8fSGustavo F. Padovan } 15560a708f8fSGustavo F. Padovan 15570a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) 15580a708f8fSGustavo F. Padovan { 15590a708f8fSGustavo F. Padovan u32 local_feat_mask = l2cap_feat_mask; 15600a708f8fSGustavo F. Padovan if (!disable_ertm) 15610a708f8fSGustavo F. Padovan local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING; 15620a708f8fSGustavo F. Padovan 15630a708f8fSGustavo F. Padovan switch (mode) { 15640a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 15650a708f8fSGustavo F. Padovan return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask; 15660a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 15670a708f8fSGustavo F. Padovan return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask; 15680a708f8fSGustavo F. Padovan default: 15690a708f8fSGustavo F. Padovan return 0x00; 15700a708f8fSGustavo F. Padovan } 15710a708f8fSGustavo F. Padovan } 15720a708f8fSGustavo F. Padovan 15735e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err) 15740a708f8fSGustavo F. Padovan { 15755e4e3972SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 15760a708f8fSGustavo F. Padovan struct l2cap_disconn_req req; 15770a708f8fSGustavo F. Padovan 15780a708f8fSGustavo F. Padovan if (!conn) 15790a708f8fSGustavo F. Padovan return; 15800a708f8fSGustavo F. Padovan 1581aad3d0e3SAndrei Emeltchenko if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) { 15821a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 15831a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 15841a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 15850a708f8fSGustavo F. Padovan } 15860a708f8fSGustavo F. Padovan 15872338a7e0SJohan Hedberg if (chan->scid == L2CAP_CID_A2MP) { 1588d117773cSGustavo Padovan l2cap_state_change(chan, BT_DISCONN); 1589416fa752SAndrei Emeltchenko return; 1590416fa752SAndrei Emeltchenko } 1591416fa752SAndrei Emeltchenko 1592fe4128e0SGustavo F. Padovan req.dcid = cpu_to_le16(chan->dcid); 1593fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 15942d792818SGustavo Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ, 15952d792818SGustavo Padovan sizeof(req), &req); 15960a708f8fSGustavo F. Padovan 1597f8e73017SGustavo Padovan l2cap_state_change_and_error(chan, BT_DISCONN, err); 15980a708f8fSGustavo F. Padovan } 15990a708f8fSGustavo F. Padovan 16000a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */ 16010a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn) 16020a708f8fSGustavo F. Padovan { 16033df91ea2SAndrei Emeltchenko struct l2cap_chan *chan, *tmp; 16040a708f8fSGustavo F. Padovan 16050a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 16060a708f8fSGustavo F. Padovan 16073df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 16080a708f8fSGustavo F. Padovan 16093df91ea2SAndrei Emeltchenko list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 16106be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 16110a708f8fSGustavo F. Padovan 1612715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1613aeaeb4bbSJohan Hedberg l2cap_chan_ready(chan); 16146be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16150a708f8fSGustavo F. Padovan continue; 16160a708f8fSGustavo F. Padovan } 16170a708f8fSGustavo F. Padovan 161889bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 1619e7cafc45SJohan Hedberg if (!l2cap_chan_check_security(chan, true) || 1620b4450035SGustavo F. Padovan !__l2cap_no_conn_pending(chan)) { 16216be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16220a708f8fSGustavo F. Padovan continue; 16230a708f8fSGustavo F. Padovan } 16240a708f8fSGustavo F. Padovan 1625c1360a1cSGustavo F. Padovan if (!l2cap_mode_supported(chan->mode, conn->feat_mask) 1626c1360a1cSGustavo F. Padovan && test_bit(CONF_STATE2_DEVICE, 1627c1360a1cSGustavo F. Padovan &chan->conf_state)) { 16280f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 16296be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16300a708f8fSGustavo F. Padovan continue; 16310a708f8fSGustavo F. Padovan } 16320a708f8fSGustavo F. Padovan 1633693cd8ceSMarcel Holtmann if (l2cap_check_enc_key_size(conn->hcon)) 163493c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 1635693cd8ceSMarcel Holtmann else 1636693cd8ceSMarcel Holtmann l2cap_chan_close(chan, ECONNREFUSED); 16370a708f8fSGustavo F. Padovan 163889bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 16390a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 16400a708f8fSGustavo F. Padovan char buf[128]; 1641fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 1642fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 16430a708f8fSGustavo F. Padovan 1644e7cafc45SJohan Hedberg if (l2cap_chan_check_security(chan, false)) { 1645bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 1646dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_PEND); 1647dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND); 16482dc4e510SGustavo Padovan chan->ops->defer(chan); 16490a708f8fSGustavo F. Padovan 16500a708f8fSGustavo F. Padovan } else { 1651acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 1652dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 1653dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 16540a708f8fSGustavo F. Padovan } 16550a708f8fSGustavo F. Padovan } else { 1656dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_PEND); 1657dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND); 16580a708f8fSGustavo F. Padovan } 16590a708f8fSGustavo F. Padovan 1660fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 1661fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 16620a708f8fSGustavo F. Padovan 1663c1360a1cSGustavo F. Padovan if (test_bit(CONF_REQ_SENT, &chan->conf_state) || 16640a708f8fSGustavo F. Padovan rsp.result != L2CAP_CR_SUCCESS) { 16656be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16660a708f8fSGustavo F. Padovan continue; 16670a708f8fSGustavo F. Padovan } 16680a708f8fSGustavo F. Padovan 1669c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 16700a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 1671e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); 167273ffa904SGustavo F. Padovan chan->num_conf_req++; 16730a708f8fSGustavo F. Padovan } 16740a708f8fSGustavo F. Padovan 16756be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16760a708f8fSGustavo F. Padovan } 16770a708f8fSGustavo F. Padovan 16783df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 16790a708f8fSGustavo F. Padovan } 16800a708f8fSGustavo F. Padovan 1681b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn) 1682b62f328bSVille Tervo { 1683cc8dba2bSMarcel Holtmann struct hci_conn *hcon = conn->hcon; 1684dcc36c16SJohan Hedberg struct hci_dev *hdev = hcon->hdev; 1685b62f328bSVille Tervo 1686e760ec12SJohan Hedberg BT_DBG("%s conn %p", hdev->name, conn); 1687b62f328bSVille Tervo 1688e760ec12SJohan Hedberg /* For outgoing pairing which doesn't necessarily have an 1689e760ec12SJohan Hedberg * associated socket (e.g. mgmt_pair_device). 1690e760ec12SJohan Hedberg */ 1691e760ec12SJohan Hedberg if (hcon->out) 1692e760ec12SJohan Hedberg smp_conn_security(hcon, hcon->pending_sec_level); 1693cc8dba2bSMarcel Holtmann 169480afeb6cSMarcel Holtmann /* For LE slave connections, make sure the connection interval 169580afeb6cSMarcel Holtmann * is in the range of the minium and maximum interval that has 169680afeb6cSMarcel Holtmann * been configured for this connection. If not, then trigger 169780afeb6cSMarcel Holtmann * the connection update procedure. 169880afeb6cSMarcel Holtmann */ 169940bef302SJohan Hedberg if (hcon->role == HCI_ROLE_SLAVE && 170080afeb6cSMarcel Holtmann (hcon->le_conn_interval < hcon->le_conn_min_interval || 170180afeb6cSMarcel Holtmann hcon->le_conn_interval > hcon->le_conn_max_interval)) { 170280afeb6cSMarcel Holtmann struct l2cap_conn_param_update_req req; 170380afeb6cSMarcel Holtmann 170480afeb6cSMarcel Holtmann req.min = cpu_to_le16(hcon->le_conn_min_interval); 170580afeb6cSMarcel Holtmann req.max = cpu_to_le16(hcon->le_conn_max_interval); 170680afeb6cSMarcel Holtmann req.latency = cpu_to_le16(hcon->le_conn_latency); 170780afeb6cSMarcel Holtmann req.to_multiplier = cpu_to_le16(hcon->le_supv_timeout); 170880afeb6cSMarcel Holtmann 170980afeb6cSMarcel Holtmann l2cap_send_cmd(conn, l2cap_get_ident(conn), 171080afeb6cSMarcel Holtmann L2CAP_CONN_PARAM_UPDATE_REQ, sizeof(req), &req); 171180afeb6cSMarcel Holtmann } 1712b62f328bSVille Tervo } 1713b62f328bSVille Tervo 17140a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn) 17150a708f8fSGustavo F. Padovan { 171648454079SGustavo F. Padovan struct l2cap_chan *chan; 1717cc110922SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 17180a708f8fSGustavo F. Padovan 17190a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 17200a708f8fSGustavo F. Padovan 1721aeaeb4bbSJohan Hedberg if (hcon->type == ACL_LINK) 1722aeaeb4bbSJohan Hedberg l2cap_request_info(conn); 1723aeaeb4bbSJohan Hedberg 1724e760ec12SJohan Hedberg mutex_lock(&conn->chan_lock); 1725e760ec12SJohan Hedberg 17263df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1727baa7e1faSGustavo F. Padovan 17286be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 17290a708f8fSGustavo F. Padovan 17302338a7e0SJohan Hedberg if (chan->scid == L2CAP_CID_A2MP) { 1731416fa752SAndrei Emeltchenko l2cap_chan_unlock(chan); 1732416fa752SAndrei Emeltchenko continue; 1733416fa752SAndrei Emeltchenko } 1734416fa752SAndrei Emeltchenko 1735cc110922SVinicius Costa Gomes if (hcon->type == LE_LINK) { 1736f1496deeSJohan Hedberg l2cap_le_start(chan); 173763128451SVinicius Costa Gomes } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1738aeaeb4bbSJohan Hedberg if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 173974e75740SGustavo Padovan l2cap_chan_ready(chan); 17401c244f79SGustavo Padovan } else if (chan->state == BT_CONNECT) { 1741fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 17421c244f79SGustavo Padovan } 17430a708f8fSGustavo F. Padovan 17446be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 17450a708f8fSGustavo F. Padovan } 17460a708f8fSGustavo F. Padovan 17473df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 174861a939c6SJohan Hedberg 174979a05727SJohan Hedberg if (hcon->type == LE_LINK) 175079a05727SJohan Hedberg l2cap_le_conn_ready(conn); 175179a05727SJohan Hedberg 175261a939c6SJohan Hedberg queue_work(hcon->hdev->workqueue, &conn->pending_rx_work); 17530a708f8fSGustavo F. Padovan } 17540a708f8fSGustavo F. Padovan 17550a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */ 17560a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) 17570a708f8fSGustavo F. Padovan { 175848454079SGustavo F. Padovan struct l2cap_chan *chan; 17590a708f8fSGustavo F. Padovan 17600a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 17610a708f8fSGustavo F. Padovan 17623df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 17630a708f8fSGustavo F. Padovan 17643df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1765ecf61bdbSAndrei Emeltchenko if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) 17661d8b1fd5SGustavo Padovan l2cap_chan_set_err(chan, err); 17670a708f8fSGustavo F. Padovan } 17680a708f8fSGustavo F. Padovan 17693df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 17700a708f8fSGustavo F. Padovan } 17710a708f8fSGustavo F. Padovan 1772f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work) 17730a708f8fSGustavo F. Padovan { 1774f878fcadSGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 1775030013d8SGustavo F. Padovan info_timer.work); 17760a708f8fSGustavo F. Padovan 17770a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 17780a708f8fSGustavo F. Padovan conn->info_ident = 0; 17790a708f8fSGustavo F. Padovan 17800a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 17810a708f8fSGustavo F. Padovan } 17820a708f8fSGustavo F. Padovan 17832c8e1411SDavid Herrmann /* 17842c8e1411SDavid Herrmann * l2cap_user 17852c8e1411SDavid Herrmann * External modules can register l2cap_user objects on l2cap_conn. The ->probe 17862c8e1411SDavid Herrmann * callback is called during registration. The ->remove callback is called 17872c8e1411SDavid Herrmann * during unregistration. 17882c8e1411SDavid Herrmann * An l2cap_user object can either be explicitly unregistered or when the 17892c8e1411SDavid Herrmann * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon, 17902c8e1411SDavid Herrmann * l2cap->hchan, .. are valid as long as the remove callback hasn't been called. 17912c8e1411SDavid Herrmann * External modules must own a reference to the l2cap_conn object if they intend 17922c8e1411SDavid Herrmann * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at 17932c8e1411SDavid Herrmann * any time if they don't. 17942c8e1411SDavid Herrmann */ 17952c8e1411SDavid Herrmann 17962c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) 17972c8e1411SDavid Herrmann { 17982c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev; 17992c8e1411SDavid Herrmann int ret; 18002c8e1411SDavid Herrmann 18012c8e1411SDavid Herrmann /* We need to check whether l2cap_conn is registered. If it is not, we 18022c8e1411SDavid Herrmann * must not register the l2cap_user. l2cap_conn_del() is unregisters 18032c8e1411SDavid Herrmann * l2cap_conn objects, but doesn't provide its own locking. Instead, it 18042c8e1411SDavid Herrmann * relies on the parent hci_conn object to be locked. This itself relies 18052c8e1411SDavid Herrmann * on the hci_dev object to be locked. So we must lock the hci device 18062c8e1411SDavid Herrmann * here, too. */ 18072c8e1411SDavid Herrmann 18082c8e1411SDavid Herrmann hci_dev_lock(hdev); 18092c8e1411SDavid Herrmann 1810835a6a2fSAlexey Dobriyan if (!list_empty(&user->list)) { 18112c8e1411SDavid Herrmann ret = -EINVAL; 18122c8e1411SDavid Herrmann goto out_unlock; 18132c8e1411SDavid Herrmann } 18142c8e1411SDavid Herrmann 18152c8e1411SDavid Herrmann /* conn->hchan is NULL after l2cap_conn_del() was called */ 18162c8e1411SDavid Herrmann if (!conn->hchan) { 18172c8e1411SDavid Herrmann ret = -ENODEV; 18182c8e1411SDavid Herrmann goto out_unlock; 18192c8e1411SDavid Herrmann } 18202c8e1411SDavid Herrmann 18212c8e1411SDavid Herrmann ret = user->probe(conn, user); 18222c8e1411SDavid Herrmann if (ret) 18232c8e1411SDavid Herrmann goto out_unlock; 18242c8e1411SDavid Herrmann 18252c8e1411SDavid Herrmann list_add(&user->list, &conn->users); 18262c8e1411SDavid Herrmann ret = 0; 18272c8e1411SDavid Herrmann 18282c8e1411SDavid Herrmann out_unlock: 18292c8e1411SDavid Herrmann hci_dev_unlock(hdev); 18302c8e1411SDavid Herrmann return ret; 18312c8e1411SDavid Herrmann } 18322c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user); 18332c8e1411SDavid Herrmann 18342c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) 18352c8e1411SDavid Herrmann { 18362c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev; 18372c8e1411SDavid Herrmann 18382c8e1411SDavid Herrmann hci_dev_lock(hdev); 18392c8e1411SDavid Herrmann 1840835a6a2fSAlexey Dobriyan if (list_empty(&user->list)) 18412c8e1411SDavid Herrmann goto out_unlock; 18422c8e1411SDavid Herrmann 1843ab944c83STedd Ho-Jeong An list_del_init(&user->list); 18442c8e1411SDavid Herrmann user->remove(conn, user); 18452c8e1411SDavid Herrmann 18462c8e1411SDavid Herrmann out_unlock: 18472c8e1411SDavid Herrmann hci_dev_unlock(hdev); 18482c8e1411SDavid Herrmann } 18492c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user); 18502c8e1411SDavid Herrmann 18512c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn) 18522c8e1411SDavid Herrmann { 18532c8e1411SDavid Herrmann struct l2cap_user *user; 18542c8e1411SDavid Herrmann 18552c8e1411SDavid Herrmann while (!list_empty(&conn->users)) { 18562c8e1411SDavid Herrmann user = list_first_entry(&conn->users, struct l2cap_user, list); 1857ab944c83STedd Ho-Jeong An list_del_init(&user->list); 18582c8e1411SDavid Herrmann user->remove(conn, user); 18592c8e1411SDavid Herrmann } 18602c8e1411SDavid Herrmann } 18612c8e1411SDavid Herrmann 18625d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err) 18635d3de7dfSVinicius Costa Gomes { 18645d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 18655d3de7dfSVinicius Costa Gomes struct l2cap_chan *chan, *l; 18665d3de7dfSVinicius Costa Gomes 18675d3de7dfSVinicius Costa Gomes if (!conn) 18685d3de7dfSVinicius Costa Gomes return; 18695d3de7dfSVinicius Costa Gomes 18705d3de7dfSVinicius Costa Gomes BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); 18715d3de7dfSVinicius Costa Gomes 18725d3de7dfSVinicius Costa Gomes kfree_skb(conn->rx_skb); 18735d3de7dfSVinicius Costa Gomes 187461a939c6SJohan Hedberg skb_queue_purge(&conn->pending_rx); 18757ab56c3aSJukka Taimisto 18767ab56c3aSJukka Taimisto /* We can not call flush_work(&conn->pending_rx_work) here since we 18777ab56c3aSJukka Taimisto * might block if we are running on a worker from the same workqueue 18787ab56c3aSJukka Taimisto * pending_rx_work is waiting on. 18797ab56c3aSJukka Taimisto */ 18807ab56c3aSJukka Taimisto if (work_pending(&conn->pending_rx_work)) 18817ab56c3aSJukka Taimisto cancel_work_sync(&conn->pending_rx_work); 188261a939c6SJohan Hedberg 1883f3d82d0cSJohan Hedberg if (work_pending(&conn->id_addr_update_work)) 1884f3d82d0cSJohan Hedberg cancel_work_sync(&conn->id_addr_update_work); 1885f3d82d0cSJohan Hedberg 18862c8e1411SDavid Herrmann l2cap_unregister_all_users(conn); 18872c8e1411SDavid Herrmann 1888e31fb860SJohan Hedberg /* Force the connection to be immediately dropped */ 1889e31fb860SJohan Hedberg hcon->disc_timeout = 0; 1890e31fb860SJohan Hedberg 18913df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 18923df91ea2SAndrei Emeltchenko 18935d3de7dfSVinicius Costa Gomes /* Kill channels */ 18945d3de7dfSVinicius Costa Gomes list_for_each_entry_safe(chan, l, &conn->chan_l, list) { 189561d6ef3eSMat Martineau l2cap_chan_hold(chan); 18966be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 18976be36555SAndrei Emeltchenko 18985d3de7dfSVinicius Costa Gomes l2cap_chan_del(chan, err); 18996be36555SAndrei Emeltchenko 190080b98027SGustavo Padovan chan->ops->close(chan); 19016c08fc89SManish Mandlik 19026c08fc89SManish Mandlik l2cap_chan_unlock(chan); 190361d6ef3eSMat Martineau l2cap_chan_put(chan); 19045d3de7dfSVinicius Costa Gomes } 19055d3de7dfSVinicius Costa Gomes 19063df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 19073df91ea2SAndrei Emeltchenko 190873d80debSLuiz Augusto von Dentz hci_chan_del(conn->hchan); 190973d80debSLuiz Augusto von Dentz 19105d3de7dfSVinicius Costa Gomes if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1911127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->info_timer); 19125d3de7dfSVinicius Costa Gomes 19135d3de7dfSVinicius Costa Gomes hcon->l2cap_data = NULL; 19149c903e37SDavid Herrmann conn->hchan = NULL; 19159c903e37SDavid Herrmann l2cap_conn_put(conn); 19165d3de7dfSVinicius Costa Gomes } 19175d3de7dfSVinicius Costa Gomes 19189c903e37SDavid Herrmann static void l2cap_conn_free(struct kref *ref) 19199c903e37SDavid Herrmann { 19209c903e37SDavid Herrmann struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref); 19219c903e37SDavid Herrmann 19229c903e37SDavid Herrmann hci_conn_put(conn->hcon); 19239c903e37SDavid Herrmann kfree(conn); 19249c903e37SDavid Herrmann } 19259c903e37SDavid Herrmann 192651bb8457SJohan Hedberg struct l2cap_conn *l2cap_conn_get(struct l2cap_conn *conn) 19279c903e37SDavid Herrmann { 19289c903e37SDavid Herrmann kref_get(&conn->ref); 192951bb8457SJohan Hedberg return conn; 19309c903e37SDavid Herrmann } 19319c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_get); 19329c903e37SDavid Herrmann 19339c903e37SDavid Herrmann void l2cap_conn_put(struct l2cap_conn *conn) 19349c903e37SDavid Herrmann { 19359c903e37SDavid Herrmann kref_put(&conn->ref, l2cap_conn_free); 19369c903e37SDavid Herrmann } 19379c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_put); 19389c903e37SDavid Herrmann 19390a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */ 19400a708f8fSGustavo F. Padovan 1941c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr. 19420a708f8fSGustavo F. Padovan * Returns closest match. 19430a708f8fSGustavo F. Padovan */ 1944c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, 1945c2287681SIdo Yariv bdaddr_t *src, 1946bf20fd4eSJohan Hedberg bdaddr_t *dst, 1947bf20fd4eSJohan Hedberg u8 link_type) 19480a708f8fSGustavo F. Padovan { 194923691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 19500a708f8fSGustavo F. Padovan 195123691d75SGustavo F. Padovan read_lock(&chan_list_lock); 19520a708f8fSGustavo F. Padovan 195323691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 195489bc500eSGustavo F. Padovan if (state && c->state != state) 19550a708f8fSGustavo F. Padovan continue; 19560a708f8fSGustavo F. Padovan 1957bf20fd4eSJohan Hedberg if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR) 1958bf20fd4eSJohan Hedberg continue; 1959bf20fd4eSJohan Hedberg 1960bf20fd4eSJohan Hedberg if (link_type == LE_LINK && c->src_type == BDADDR_BREDR) 1961bf20fd4eSJohan Hedberg continue; 1962bf20fd4eSJohan Hedberg 196323691d75SGustavo F. Padovan if (c->psm == psm) { 1964c2287681SIdo Yariv int src_match, dst_match; 1965c2287681SIdo Yariv int src_any, dst_any; 1966c2287681SIdo Yariv 19670a708f8fSGustavo F. Padovan /* Exact match. */ 19687eafc59eSMarcel Holtmann src_match = !bacmp(&c->src, src); 19697eafc59eSMarcel Holtmann dst_match = !bacmp(&c->dst, dst); 1970c2287681SIdo Yariv if (src_match && dst_match) { 1971a24cce14SJohan Hedberg l2cap_chan_hold(c); 1972a7567b20SJohannes Berg read_unlock(&chan_list_lock); 197323691d75SGustavo F. Padovan return c; 197423691d75SGustavo F. Padovan } 19750a708f8fSGustavo F. Padovan 19760a708f8fSGustavo F. Padovan /* Closest match */ 19777eafc59eSMarcel Holtmann src_any = !bacmp(&c->src, BDADDR_ANY); 19787eafc59eSMarcel Holtmann dst_any = !bacmp(&c->dst, BDADDR_ANY); 1979c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1980c2287681SIdo Yariv (src_any && dst_any)) 198123691d75SGustavo F. Padovan c1 = c; 19820a708f8fSGustavo F. Padovan } 19830a708f8fSGustavo F. Padovan } 19840a708f8fSGustavo F. Padovan 1985a24cce14SJohan Hedberg if (c1) 1986a24cce14SJohan Hedberg l2cap_chan_hold(c1); 1987a24cce14SJohan Hedberg 198823691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 19890a708f8fSGustavo F. Padovan 199023691d75SGustavo F. Padovan return c1; 19910a708f8fSGustavo F. Padovan } 19920a708f8fSGustavo F. Padovan 1993721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work) 19940a708f8fSGustavo F. Padovan { 1995721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1996721c4181SGustavo F. Padovan monitor_timer.work); 19970a708f8fSGustavo F. Padovan 1998525cd185SGustavo F. Padovan BT_DBG("chan %p", chan); 19990a708f8fSGustavo F. Padovan 20006be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 20016be36555SAndrei Emeltchenko 200280909e04SMat Martineau if (!chan->conn) { 20036be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 20048d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 20050a708f8fSGustavo F. Padovan return; 20060a708f8fSGustavo F. Padovan } 20070a708f8fSGustavo F. Padovan 2008401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO); 20090a708f8fSGustavo F. Padovan 20106be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 20118d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 20120a708f8fSGustavo F. Padovan } 20130a708f8fSGustavo F. Padovan 2014721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work) 20150a708f8fSGustavo F. Padovan { 2016721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 2017721c4181SGustavo F. Padovan retrans_timer.work); 20180a708f8fSGustavo F. Padovan 201949208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 20200a708f8fSGustavo F. Padovan 20216be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 20226be36555SAndrei Emeltchenko 202380909e04SMat Martineau if (!chan->conn) { 202480909e04SMat Martineau l2cap_chan_unlock(chan); 202580909e04SMat Martineau l2cap_chan_put(chan); 202680909e04SMat Martineau return; 202780909e04SMat Martineau } 20280a708f8fSGustavo F. Padovan 2029401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO); 20306be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 20318d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 20320a708f8fSGustavo F. Padovan } 20330a708f8fSGustavo F. Padovan 2034d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan, 20353733937dSMat Martineau struct sk_buff_head *skbs) 20360a708f8fSGustavo F. Padovan { 20370a708f8fSGustavo F. Padovan struct sk_buff *skb; 20383733937dSMat Martineau struct l2cap_ctrl *control; 20390a708f8fSGustavo F. Padovan 20403733937dSMat Martineau BT_DBG("chan %p, skbs %p", chan, skbs); 20413733937dSMat Martineau 2042b99e13adSMat Martineau if (__chan_is_moving(chan)) 2043b99e13adSMat Martineau return; 2044b99e13adSMat Martineau 20453733937dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 20463733937dSMat Martineau 20473733937dSMat Martineau while (!skb_queue_empty(&chan->tx_q)) { 20483733937dSMat Martineau 20493733937dSMat Martineau skb = skb_dequeue(&chan->tx_q); 20503733937dSMat Martineau 2051a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 1; 2052a4368ff3SJohan Hedberg control = &bt_cb(skb)->l2cap; 20533733937dSMat Martineau 20543733937dSMat Martineau control->reqseq = 0; 20553733937dSMat Martineau control->txseq = chan->next_tx_seq; 20563733937dSMat Martineau 20573733937dSMat Martineau __pack_control(chan, control, skb); 20580a708f8fSGustavo F. Padovan 205947d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 20603733937dSMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 20613733937dSMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 20620a708f8fSGustavo F. Padovan } 20630a708f8fSGustavo F. Padovan 20644343478fSGustavo F. Padovan l2cap_do_send(chan, skb); 20650a708f8fSGustavo F. Padovan 2066b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 20673733937dSMat Martineau 2068836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 20693733937dSMat Martineau chan->frames_sent++; 20700a708f8fSGustavo F. Padovan } 20710a708f8fSGustavo F. Padovan } 20720a708f8fSGustavo F. Padovan 207367c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan) 20740a708f8fSGustavo F. Padovan { 20750a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 207618a48e76SMat Martineau struct l2cap_ctrl *control; 207718a48e76SMat Martineau int sent = 0; 207818a48e76SMat Martineau 207918a48e76SMat Martineau BT_DBG("chan %p", chan); 20800a708f8fSGustavo F. Padovan 208189bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 20820a708f8fSGustavo F. Padovan return -ENOTCONN; 20830a708f8fSGustavo F. Padovan 208494122bbeSMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 208594122bbeSMat Martineau return 0; 208694122bbeSMat Martineau 2087b99e13adSMat Martineau if (__chan_is_moving(chan)) 2088b99e13adSMat Martineau return 0; 2089b99e13adSMat Martineau 209018a48e76SMat Martineau while (chan->tx_send_head && 209118a48e76SMat Martineau chan->unacked_frames < chan->remote_tx_win && 209218a48e76SMat Martineau chan->tx_state == L2CAP_TX_STATE_XMIT) { 20930a708f8fSGustavo F. Padovan 209418a48e76SMat Martineau skb = chan->tx_send_head; 20950a708f8fSGustavo F. Padovan 2096a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 1; 2097a4368ff3SJohan Hedberg control = &bt_cb(skb)->l2cap; 20980a708f8fSGustavo F. Padovan 2099e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 210018a48e76SMat Martineau control->final = 1; 2101e2ab4353SGustavo F. Padovan 210218a48e76SMat Martineau control->reqseq = chan->buffer_seq; 210318a48e76SMat Martineau chan->last_acked_seq = chan->buffer_seq; 210418a48e76SMat Martineau control->txseq = chan->next_tx_seq; 21050a708f8fSGustavo F. Padovan 210618a48e76SMat Martineau __pack_control(chan, control, skb); 21070a708f8fSGustavo F. Padovan 210847d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 210918a48e76SMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 211018a48e76SMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 21110a708f8fSGustavo F. Padovan } 21120a708f8fSGustavo F. Padovan 211318a48e76SMat Martineau /* Clone after data has been modified. Data is assumed to be 211418a48e76SMat Martineau read-only (for locking purposes) on cloned sk_buffs. 211518a48e76SMat Martineau */ 211618a48e76SMat Martineau tx_skb = skb_clone(skb, GFP_KERNEL); 211718a48e76SMat Martineau 211818a48e76SMat Martineau if (!tx_skb) 211918a48e76SMat Martineau break; 21200a708f8fSGustavo F. Padovan 21211a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 21220a708f8fSGustavo F. Padovan 2123836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 21246a026610SGustavo F. Padovan chan->unacked_frames++; 21256a026610SGustavo F. Padovan chan->frames_sent++; 212618a48e76SMat Martineau sent++; 21270a708f8fSGustavo F. Padovan 212858d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 212958d35f87SGustavo F. Padovan chan->tx_send_head = NULL; 21300a708f8fSGustavo F. Padovan else 213158d35f87SGustavo F. Padovan chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); 213218a48e76SMat Martineau 213318a48e76SMat Martineau l2cap_do_send(chan, tx_skb); 2134b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 21350a708f8fSGustavo F. Padovan } 21360a708f8fSGustavo F. Padovan 2137b4400672SAndrei Emeltchenko BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent, 2138b4400672SAndrei Emeltchenko chan->unacked_frames, skb_queue_len(&chan->tx_q)); 213918a48e76SMat Martineau 214018a48e76SMat Martineau return sent; 21410a708f8fSGustavo F. Padovan } 21420a708f8fSGustavo F. Padovan 2143e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan) 2144e1fbd4c1SMat Martineau { 2145e1fbd4c1SMat Martineau struct l2cap_ctrl control; 2146e1fbd4c1SMat Martineau struct sk_buff *skb; 2147e1fbd4c1SMat Martineau struct sk_buff *tx_skb; 2148e1fbd4c1SMat Martineau u16 seq; 2149e1fbd4c1SMat Martineau 2150e1fbd4c1SMat Martineau BT_DBG("chan %p", chan); 2151e1fbd4c1SMat Martineau 2152e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 2153e1fbd4c1SMat Martineau return; 2154e1fbd4c1SMat Martineau 2155b99e13adSMat Martineau if (__chan_is_moving(chan)) 2156b99e13adSMat Martineau return; 2157b99e13adSMat Martineau 2158e1fbd4c1SMat Martineau while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) { 2159e1fbd4c1SMat Martineau seq = l2cap_seq_list_pop(&chan->retrans_list); 2160e1fbd4c1SMat Martineau 2161e1fbd4c1SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq); 2162e1fbd4c1SMat Martineau if (!skb) { 2163e1fbd4c1SMat Martineau BT_DBG("Error: Can't retransmit seq %d, frame missing", 2164e1fbd4c1SMat Martineau seq); 2165e1fbd4c1SMat Martineau continue; 2166e1fbd4c1SMat Martineau } 2167e1fbd4c1SMat Martineau 2168a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries++; 2169a4368ff3SJohan Hedberg control = bt_cb(skb)->l2cap; 2170e1fbd4c1SMat Martineau 2171e1fbd4c1SMat Martineau if (chan->max_tx != 0 && 2172a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries > chan->max_tx) { 2173e1fbd4c1SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 21745e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 2175e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2176e1fbd4c1SMat Martineau break; 2177e1fbd4c1SMat Martineau } 2178e1fbd4c1SMat Martineau 2179e1fbd4c1SMat Martineau control.reqseq = chan->buffer_seq; 2180e1fbd4c1SMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 2181e1fbd4c1SMat Martineau control.final = 1; 2182e1fbd4c1SMat Martineau else 2183e1fbd4c1SMat Martineau control.final = 0; 2184e1fbd4c1SMat Martineau 2185e1fbd4c1SMat Martineau if (skb_cloned(skb)) { 2186e1fbd4c1SMat Martineau /* Cloned sk_buffs are read-only, so we need a 2187e1fbd4c1SMat Martineau * writeable copy 2188e1fbd4c1SMat Martineau */ 21898bcde1f2SGustavo Padovan tx_skb = skb_copy(skb, GFP_KERNEL); 2190e1fbd4c1SMat Martineau } else { 21918bcde1f2SGustavo Padovan tx_skb = skb_clone(skb, GFP_KERNEL); 2192e1fbd4c1SMat Martineau } 2193e1fbd4c1SMat Martineau 2194e1fbd4c1SMat Martineau if (!tx_skb) { 2195e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2196e1fbd4c1SMat Martineau break; 2197e1fbd4c1SMat Martineau } 2198e1fbd4c1SMat Martineau 2199e1fbd4c1SMat Martineau /* Update skb contents */ 2200e1fbd4c1SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 2201e1fbd4c1SMat Martineau put_unaligned_le32(__pack_extended_control(&control), 2202e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 2203e1fbd4c1SMat Martineau } else { 2204e1fbd4c1SMat Martineau put_unaligned_le16(__pack_enhanced_control(&control), 2205e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 2206e1fbd4c1SMat Martineau } 2207e1fbd4c1SMat Martineau 220813cac152SLukasz Rymanowski /* Update FCS */ 2209e1fbd4c1SMat Martineau if (chan->fcs == L2CAP_FCS_CRC16) { 221013cac152SLukasz Rymanowski u16 fcs = crc16(0, (u8 *) tx_skb->data, 221113cac152SLukasz Rymanowski tx_skb->len - L2CAP_FCS_SIZE); 221213cac152SLukasz Rymanowski put_unaligned_le16(fcs, skb_tail_pointer(tx_skb) - 221313cac152SLukasz Rymanowski L2CAP_FCS_SIZE); 2214e1fbd4c1SMat Martineau } 2215e1fbd4c1SMat Martineau 2216e1fbd4c1SMat Martineau l2cap_do_send(chan, tx_skb); 2217e1fbd4c1SMat Martineau 2218e1fbd4c1SMat Martineau BT_DBG("Resent txseq %d", control.txseq); 2219e1fbd4c1SMat Martineau 2220e1fbd4c1SMat Martineau chan->last_acked_seq = chan->buffer_seq; 2221e1fbd4c1SMat Martineau } 2222e1fbd4c1SMat Martineau } 2223e1fbd4c1SMat Martineau 2224f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan, 2225f80842a8SMat Martineau struct l2cap_ctrl *control) 2226f80842a8SMat Martineau { 2227f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2228f80842a8SMat Martineau 2229f80842a8SMat Martineau l2cap_seq_list_append(&chan->retrans_list, control->reqseq); 2230f80842a8SMat Martineau l2cap_ertm_resend(chan); 2231f80842a8SMat Martineau } 2232f80842a8SMat Martineau 2233d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan, 2234d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 2235d2a7ac5dSMat Martineau { 2236e1fbd4c1SMat Martineau struct sk_buff *skb; 2237e1fbd4c1SMat Martineau 2238e1fbd4c1SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2239e1fbd4c1SMat Martineau 2240e1fbd4c1SMat Martineau if (control->poll) 2241e1fbd4c1SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 2242e1fbd4c1SMat Martineau 2243e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2244e1fbd4c1SMat Martineau 2245e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 2246e1fbd4c1SMat Martineau return; 2247e1fbd4c1SMat Martineau 2248e1fbd4c1SMat Martineau if (chan->unacked_frames) { 2249e1fbd4c1SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 2250a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.txseq == control->reqseq || 2251e1fbd4c1SMat Martineau skb == chan->tx_send_head) 2252e1fbd4c1SMat Martineau break; 2253e1fbd4c1SMat Martineau } 2254e1fbd4c1SMat Martineau 2255e1fbd4c1SMat Martineau skb_queue_walk_from(&chan->tx_q, skb) { 2256e1fbd4c1SMat Martineau if (skb == chan->tx_send_head) 2257e1fbd4c1SMat Martineau break; 2258e1fbd4c1SMat Martineau 2259e1fbd4c1SMat Martineau l2cap_seq_list_append(&chan->retrans_list, 2260a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.txseq); 2261e1fbd4c1SMat Martineau } 2262e1fbd4c1SMat Martineau 2263e1fbd4c1SMat Martineau l2cap_ertm_resend(chan); 2264e1fbd4c1SMat Martineau } 2265d2a7ac5dSMat Martineau } 2266d2a7ac5dSMat Martineau 2267b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan) 2268b17e73bbSSzymon Janc { 22690a0aba42SMat Martineau struct l2cap_ctrl control; 22700a0aba42SMat Martineau u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq, 22710a0aba42SMat Martineau chan->last_acked_seq); 22720a0aba42SMat Martineau int threshold; 22730a0aba42SMat Martineau 22740a0aba42SMat Martineau BT_DBG("chan %p last_acked_seq %d buffer_seq %d", 22750a0aba42SMat Martineau chan, chan->last_acked_seq, chan->buffer_seq); 22760a0aba42SMat Martineau 22770a0aba42SMat Martineau memset(&control, 0, sizeof(control)); 22780a0aba42SMat Martineau control.sframe = 1; 22790a0aba42SMat Martineau 22800a0aba42SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 22810a0aba42SMat Martineau chan->rx_state == L2CAP_RX_STATE_RECV) { 2282b17e73bbSSzymon Janc __clear_ack_timer(chan); 22830a0aba42SMat Martineau control.super = L2CAP_SUPER_RNR; 22840a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 22850a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 22860a0aba42SMat Martineau } else { 22870a0aba42SMat Martineau if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) { 22880a0aba42SMat Martineau l2cap_ertm_send(chan); 22890a0aba42SMat Martineau /* If any i-frames were sent, they included an ack */ 22900a0aba42SMat Martineau if (chan->buffer_seq == chan->last_acked_seq) 22910a0aba42SMat Martineau frames_to_ack = 0; 22920a0aba42SMat Martineau } 22930a0aba42SMat Martineau 2294c20f8e35SMat Martineau /* Ack now if the window is 3/4ths full. 22950a0aba42SMat Martineau * Calculate without mul or div 22960a0aba42SMat Martineau */ 2297c20f8e35SMat Martineau threshold = chan->ack_win; 22980a0aba42SMat Martineau threshold += threshold << 1; 22990a0aba42SMat Martineau threshold >>= 2; 23000a0aba42SMat Martineau 2301b4400672SAndrei Emeltchenko BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack, 23020a0aba42SMat Martineau threshold); 23030a0aba42SMat Martineau 23040a0aba42SMat Martineau if (frames_to_ack >= threshold) { 23050a0aba42SMat Martineau __clear_ack_timer(chan); 23060a0aba42SMat Martineau control.super = L2CAP_SUPER_RR; 23070a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 23080a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 23090a0aba42SMat Martineau frames_to_ack = 0; 23100a0aba42SMat Martineau } 23110a0aba42SMat Martineau 23120a0aba42SMat Martineau if (frames_to_ack) 23130a0aba42SMat Martineau __set_ack_timer(chan); 23140a0aba42SMat Martineau } 2315b17e73bbSSzymon Janc } 2316b17e73bbSSzymon Janc 231704124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, 231804124681SGustavo F. Padovan struct msghdr *msg, int len, 231904124681SGustavo F. Padovan int count, struct sk_buff *skb) 23200a708f8fSGustavo F. Padovan { 23210952a57aSAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 23220a708f8fSGustavo F. Padovan struct sk_buff **frag; 232390338947SGustavo Padovan int sent = 0; 23240a708f8fSGustavo F. Padovan 2325cbbd26b8SAl Viro if (!copy_from_iter_full(skb_put(skb, count), count, &msg->msg_iter)) 23260a708f8fSGustavo F. Padovan return -EFAULT; 23270a708f8fSGustavo F. Padovan 23280a708f8fSGustavo F. Padovan sent += count; 23290a708f8fSGustavo F. Padovan len -= count; 23300a708f8fSGustavo F. Padovan 23310a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 23320a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 23330a708f8fSGustavo F. Padovan while (len) { 2334fbe00700SGustavo Padovan struct sk_buff *tmp; 2335fbe00700SGustavo Padovan 23360a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 23370a708f8fSGustavo F. Padovan 2338d9fbd02bSMarcel Holtmann tmp = chan->ops->alloc_skb(chan, 0, count, 233990338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 2340fbe00700SGustavo Padovan if (IS_ERR(tmp)) 2341fbe00700SGustavo Padovan return PTR_ERR(tmp); 23422f7719ceSAndrei Emeltchenko 2343fbe00700SGustavo Padovan *frag = tmp; 2344fbe00700SGustavo Padovan 2345cbbd26b8SAl Viro if (!copy_from_iter_full(skb_put(*frag, count), count, 2346cbbd26b8SAl Viro &msg->msg_iter)) 23470a708f8fSGustavo F. Padovan return -EFAULT; 23480a708f8fSGustavo F. Padovan 23490a708f8fSGustavo F. Padovan sent += count; 23500a708f8fSGustavo F. Padovan len -= count; 23510a708f8fSGustavo F. Padovan 23522d0ed3d5SGustavo Padovan skb->len += (*frag)->len; 23532d0ed3d5SGustavo Padovan skb->data_len += (*frag)->len; 23542d0ed3d5SGustavo Padovan 23550a708f8fSGustavo F. Padovan frag = &(*frag)->next; 23560a708f8fSGustavo F. Padovan } 23570a708f8fSGustavo F. Padovan 23580a708f8fSGustavo F. Padovan return sent; 23590a708f8fSGustavo F. Padovan } 23600a708f8fSGustavo F. Padovan 23615e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, 23628d46321cSMarcel Holtmann struct msghdr *msg, size_t len) 23630a708f8fSGustavo F. Padovan { 23648c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 23650a708f8fSGustavo F. Padovan struct sk_buff *skb; 236603a51213SAndrei Emeltchenko int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; 23670a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 23680a708f8fSGustavo F. Padovan 23698d46321cSMarcel Holtmann BT_DBG("chan %p psm 0x%2.2x len %zu", chan, 23708d46321cSMarcel Holtmann __le16_to_cpu(chan->psm), len); 23710a708f8fSGustavo F. Padovan 23720a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 23732f7719ceSAndrei Emeltchenko 2374d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, hlen, count, 237590338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 237690338947SGustavo Padovan if (IS_ERR(skb)) 237790338947SGustavo Padovan return skb; 23780a708f8fSGustavo F. Padovan 23790a708f8fSGustavo F. Padovan /* Create L2CAP header */ 23804df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 2381fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 2382daf6a78cSAndrei Emeltchenko lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); 238343b1b8dfSMarcel Holtmann put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE)); 23840a708f8fSGustavo F. Padovan 23850952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 23860a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 23870a708f8fSGustavo F. Padovan kfree_skb(skb); 23880a708f8fSGustavo F. Padovan return ERR_PTR(err); 23890a708f8fSGustavo F. Padovan } 23900a708f8fSGustavo F. Padovan return skb; 23910a708f8fSGustavo F. Padovan } 23920a708f8fSGustavo F. Padovan 23935e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, 23948d46321cSMarcel Holtmann struct msghdr *msg, size_t len) 23950a708f8fSGustavo F. Padovan { 23968c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 23970a708f8fSGustavo F. Padovan struct sk_buff *skb; 2398f2ba7faeSGustavo Padovan int err, count; 23990a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 24000a708f8fSGustavo F. Padovan 2401b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 24020a708f8fSGustavo F. Padovan 2403f2ba7faeSGustavo Padovan count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); 24042f7719ceSAndrei Emeltchenko 2405d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, L2CAP_HDR_SIZE, count, 240690338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 240790338947SGustavo Padovan if (IS_ERR(skb)) 240890338947SGustavo Padovan return skb; 24090a708f8fSGustavo F. Padovan 24100a708f8fSGustavo F. Padovan /* Create L2CAP header */ 24114df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 2412fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 24136ff9b5efSGustavo Padovan lh->len = cpu_to_le16(len); 24140a708f8fSGustavo F. Padovan 24150952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 24160a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 24170a708f8fSGustavo F. Padovan kfree_skb(skb); 24180a708f8fSGustavo F. Padovan return ERR_PTR(err); 24190a708f8fSGustavo F. Padovan } 24200a708f8fSGustavo F. Padovan return skb; 24210a708f8fSGustavo F. Padovan } 24220a708f8fSGustavo F. Padovan 2423ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, 2424ab0ff76dSLuiz Augusto von Dentz struct msghdr *msg, size_t len, 242594122bbeSMat Martineau u16 sdulen) 24260a708f8fSGustavo F. Padovan { 24278c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 24280a708f8fSGustavo F. Padovan struct sk_buff *skb; 2429e4ca6d98SAndrei Emeltchenko int err, count, hlen; 24300a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 24310a708f8fSGustavo F. Padovan 2432b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 24330a708f8fSGustavo F. Padovan 24340a708f8fSGustavo F. Padovan if (!conn) 24350a708f8fSGustavo F. Padovan return ERR_PTR(-ENOTCONN); 24360a708f8fSGustavo F. Padovan 2437ba7aa64fSGustavo Padovan hlen = __ertm_hdr_size(chan); 2438e4ca6d98SAndrei Emeltchenko 24390a708f8fSGustavo F. Padovan if (sdulen) 244003a51213SAndrei Emeltchenko hlen += L2CAP_SDULEN_SIZE; 24410a708f8fSGustavo F. Padovan 244247d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 244303a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 24440a708f8fSGustavo F. Padovan 24450a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 24462f7719ceSAndrei Emeltchenko 2447d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, hlen, count, 244890338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 244990338947SGustavo Padovan if (IS_ERR(skb)) 245090338947SGustavo Padovan return skb; 24510a708f8fSGustavo F. Padovan 24520a708f8fSGustavo F. Padovan /* Create L2CAP header */ 24534df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 2454fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 24550a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 245688843ab0SAndrei Emeltchenko 245718a48e76SMat Martineau /* Control header is populated later */ 245818a48e76SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 245918a48e76SMat Martineau put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 246018a48e76SMat Martineau else 246118a48e76SMat Martineau put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 246288843ab0SAndrei Emeltchenko 24630a708f8fSGustavo F. Padovan if (sdulen) 246403a51213SAndrei Emeltchenko put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 24650a708f8fSGustavo F. Padovan 24660952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 24670a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 24680a708f8fSGustavo F. Padovan kfree_skb(skb); 24690a708f8fSGustavo F. Padovan return ERR_PTR(err); 24700a708f8fSGustavo F. Padovan } 24710a708f8fSGustavo F. Padovan 2472a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.fcs = chan->fcs; 2473a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 0; 24740a708f8fSGustavo F. Padovan return skb; 24750a708f8fSGustavo F. Padovan } 24760a708f8fSGustavo F. Padovan 247794122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan, 247894122bbeSMat Martineau struct sk_buff_head *seg_queue, 247994122bbeSMat Martineau struct msghdr *msg, size_t len) 24800a708f8fSGustavo F. Padovan { 24810a708f8fSGustavo F. Padovan struct sk_buff *skb; 248294122bbeSMat Martineau u16 sdu_len; 248394122bbeSMat Martineau size_t pdu_len; 248494122bbeSMat Martineau u8 sar; 24850a708f8fSGustavo F. Padovan 2486b4400672SAndrei Emeltchenko BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); 24870a708f8fSGustavo F. Padovan 248894122bbeSMat Martineau /* It is critical that ERTM PDUs fit in a single HCI fragment, 248994122bbeSMat Martineau * so fragmented skbs are not used. The HCI layer's handling 249094122bbeSMat Martineau * of fragmented skbs is not compatible with ERTM's queueing. 249194122bbeSMat Martineau */ 249294122bbeSMat Martineau 249394122bbeSMat Martineau /* PDU size is derived from the HCI MTU */ 249494122bbeSMat Martineau pdu_len = chan->conn->mtu; 249594122bbeSMat Martineau 2496a549574dSMat Martineau /* Constrain PDU size for BR/EDR connections */ 2497a549574dSMat Martineau if (!chan->hs_hcon) 249894122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); 249994122bbeSMat Martineau 250094122bbeSMat Martineau /* Adjust for largest possible L2CAP overhead. */ 250135d401dfSGustavo Padovan if (chan->fcs) 250235d401dfSGustavo Padovan pdu_len -= L2CAP_FCS_SIZE; 250335d401dfSGustavo Padovan 2504ba7aa64fSGustavo Padovan pdu_len -= __ertm_hdr_size(chan); 250594122bbeSMat Martineau 250694122bbeSMat Martineau /* Remote device may have requested smaller PDUs */ 250794122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, chan->remote_mps); 250894122bbeSMat Martineau 250994122bbeSMat Martineau if (len <= pdu_len) { 251094122bbeSMat Martineau sar = L2CAP_SAR_UNSEGMENTED; 251194122bbeSMat Martineau sdu_len = 0; 251294122bbeSMat Martineau pdu_len = len; 251394122bbeSMat Martineau } else { 251494122bbeSMat Martineau sar = L2CAP_SAR_START; 251594122bbeSMat Martineau sdu_len = len; 251694122bbeSMat Martineau } 25170a708f8fSGustavo F. Padovan 25180a708f8fSGustavo F. Padovan while (len > 0) { 251994122bbeSMat Martineau skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len); 25200a708f8fSGustavo F. Padovan 25210a708f8fSGustavo F. Padovan if (IS_ERR(skb)) { 252294122bbeSMat Martineau __skb_queue_purge(seg_queue); 25230a708f8fSGustavo F. Padovan return PTR_ERR(skb); 25240a708f8fSGustavo F. Padovan } 25250a708f8fSGustavo F. Padovan 2526a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.sar = sar; 252794122bbeSMat Martineau __skb_queue_tail(seg_queue, skb); 25280a708f8fSGustavo F. Padovan 252994122bbeSMat Martineau len -= pdu_len; 2530069cb270SLukasz Rymanowski if (sdu_len) 253194122bbeSMat Martineau sdu_len = 0; 253294122bbeSMat Martineau 253394122bbeSMat Martineau if (len <= pdu_len) { 253494122bbeSMat Martineau sar = L2CAP_SAR_END; 253594122bbeSMat Martineau pdu_len = len; 253694122bbeSMat Martineau } else { 253794122bbeSMat Martineau sar = L2CAP_SAR_CONTINUE; 253894122bbeSMat Martineau } 253994122bbeSMat Martineau } 254094122bbeSMat Martineau 2541f0f62799SGustavo Padovan return 0; 25420a708f8fSGustavo F. Padovan } 25430a708f8fSGustavo F. Padovan 2544177f8f2bSJohan Hedberg static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan, 2545177f8f2bSJohan Hedberg struct msghdr *msg, 2546177f8f2bSJohan Hedberg size_t len, u16 sdulen) 2547177f8f2bSJohan Hedberg { 2548177f8f2bSJohan Hedberg struct l2cap_conn *conn = chan->conn; 2549177f8f2bSJohan Hedberg struct sk_buff *skb; 2550177f8f2bSJohan Hedberg int err, count, hlen; 2551177f8f2bSJohan Hedberg struct l2cap_hdr *lh; 2552177f8f2bSJohan Hedberg 2553177f8f2bSJohan Hedberg BT_DBG("chan %p len %zu", chan, len); 2554177f8f2bSJohan Hedberg 2555177f8f2bSJohan Hedberg if (!conn) 2556177f8f2bSJohan Hedberg return ERR_PTR(-ENOTCONN); 2557177f8f2bSJohan Hedberg 2558177f8f2bSJohan Hedberg hlen = L2CAP_HDR_SIZE; 2559177f8f2bSJohan Hedberg 2560177f8f2bSJohan Hedberg if (sdulen) 2561177f8f2bSJohan Hedberg hlen += L2CAP_SDULEN_SIZE; 2562177f8f2bSJohan Hedberg 2563177f8f2bSJohan Hedberg count = min_t(unsigned int, (conn->mtu - hlen), len); 2564177f8f2bSJohan Hedberg 2565d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, hlen, count, 2566177f8f2bSJohan Hedberg msg->msg_flags & MSG_DONTWAIT); 2567177f8f2bSJohan Hedberg if (IS_ERR(skb)) 2568177f8f2bSJohan Hedberg return skb; 2569177f8f2bSJohan Hedberg 2570177f8f2bSJohan Hedberg /* Create L2CAP header */ 25714df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 2572177f8f2bSJohan Hedberg lh->cid = cpu_to_le16(chan->dcid); 2573177f8f2bSJohan Hedberg lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 2574177f8f2bSJohan Hedberg 2575177f8f2bSJohan Hedberg if (sdulen) 2576177f8f2bSJohan Hedberg put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 2577177f8f2bSJohan Hedberg 2578177f8f2bSJohan Hedberg err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 2579177f8f2bSJohan Hedberg if (unlikely(err < 0)) { 2580177f8f2bSJohan Hedberg kfree_skb(skb); 2581177f8f2bSJohan Hedberg return ERR_PTR(err); 2582177f8f2bSJohan Hedberg } 2583177f8f2bSJohan Hedberg 2584177f8f2bSJohan Hedberg return skb; 2585177f8f2bSJohan Hedberg } 2586177f8f2bSJohan Hedberg 2587177f8f2bSJohan Hedberg static int l2cap_segment_le_sdu(struct l2cap_chan *chan, 2588177f8f2bSJohan Hedberg struct sk_buff_head *seg_queue, 2589177f8f2bSJohan Hedberg struct msghdr *msg, size_t len) 2590177f8f2bSJohan Hedberg { 2591177f8f2bSJohan Hedberg struct sk_buff *skb; 2592177f8f2bSJohan Hedberg size_t pdu_len; 2593177f8f2bSJohan Hedberg u16 sdu_len; 2594177f8f2bSJohan Hedberg 2595177f8f2bSJohan Hedberg BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); 2596177f8f2bSJohan Hedberg 2597177f8f2bSJohan Hedberg sdu_len = len; 259872c6fb91SJohan Hedberg pdu_len = chan->remote_mps - L2CAP_SDULEN_SIZE; 2599177f8f2bSJohan Hedberg 2600177f8f2bSJohan Hedberg while (len > 0) { 2601177f8f2bSJohan Hedberg if (len <= pdu_len) 2602177f8f2bSJohan Hedberg pdu_len = len; 2603177f8f2bSJohan Hedberg 2604177f8f2bSJohan Hedberg skb = l2cap_create_le_flowctl_pdu(chan, msg, pdu_len, sdu_len); 2605177f8f2bSJohan Hedberg if (IS_ERR(skb)) { 2606177f8f2bSJohan Hedberg __skb_queue_purge(seg_queue); 2607177f8f2bSJohan Hedberg return PTR_ERR(skb); 2608177f8f2bSJohan Hedberg } 2609177f8f2bSJohan Hedberg 2610177f8f2bSJohan Hedberg __skb_queue_tail(seg_queue, skb); 2611177f8f2bSJohan Hedberg 2612177f8f2bSJohan Hedberg len -= pdu_len; 2613177f8f2bSJohan Hedberg 2614177f8f2bSJohan Hedberg if (sdu_len) { 2615177f8f2bSJohan Hedberg sdu_len = 0; 2616177f8f2bSJohan Hedberg pdu_len += L2CAP_SDULEN_SIZE; 2617177f8f2bSJohan Hedberg } 2618177f8f2bSJohan Hedberg } 2619177f8f2bSJohan Hedberg 2620177f8f2bSJohan Hedberg return 0; 2621177f8f2bSJohan Hedberg } 2622177f8f2bSJohan Hedberg 26238a505b7fSLuiz Augusto von Dentz static void l2cap_le_flowctl_send(struct l2cap_chan *chan) 26248a505b7fSLuiz Augusto von Dentz { 26258a505b7fSLuiz Augusto von Dentz int sent = 0; 26268a505b7fSLuiz Augusto von Dentz 26278a505b7fSLuiz Augusto von Dentz BT_DBG("chan %p", chan); 26288a505b7fSLuiz Augusto von Dentz 26298a505b7fSLuiz Augusto von Dentz while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) { 26308a505b7fSLuiz Augusto von Dentz l2cap_do_send(chan, skb_dequeue(&chan->tx_q)); 26318a505b7fSLuiz Augusto von Dentz chan->tx_credits--; 26328a505b7fSLuiz Augusto von Dentz sent++; 26338a505b7fSLuiz Augusto von Dentz } 26348a505b7fSLuiz Augusto von Dentz 26358a505b7fSLuiz Augusto von Dentz BT_DBG("Sent %d credits %u queued %u", sent, chan->tx_credits, 26368a505b7fSLuiz Augusto von Dentz skb_queue_len(&chan->tx_q)); 26378a505b7fSLuiz Augusto von Dentz } 26388a505b7fSLuiz Augusto von Dentz 26398d46321cSMarcel Holtmann int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len) 26409a91a04aSGustavo F. Padovan { 26419a91a04aSGustavo F. Padovan struct sk_buff *skb; 26429a91a04aSGustavo F. Padovan int err; 264394122bbeSMat Martineau struct sk_buff_head seg_queue; 26449a91a04aSGustavo F. Padovan 264531e8ce80SSeung-Woo Kim if (!chan->conn) 264631e8ce80SSeung-Woo Kim return -ENOTCONN; 264731e8ce80SSeung-Woo Kim 26489a91a04aSGustavo F. Padovan /* Connectionless channel */ 2649715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { 26508d46321cSMarcel Holtmann skb = l2cap_create_connless_pdu(chan, msg, len); 26519a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 26529a91a04aSGustavo F. Padovan return PTR_ERR(skb); 26539a91a04aSGustavo F. Padovan 2654ede81a2aSAndrzej Kaczmarek /* Channel lock is released before requesting new skb and then 2655ede81a2aSAndrzej Kaczmarek * reacquired thus we need to recheck channel state. 2656ede81a2aSAndrzej Kaczmarek */ 2657ede81a2aSAndrzej Kaczmarek if (chan->state != BT_CONNECTED) { 2658ede81a2aSAndrzej Kaczmarek kfree_skb(skb); 2659ede81a2aSAndrzej Kaczmarek return -ENOTCONN; 2660ede81a2aSAndrzej Kaczmarek } 2661ede81a2aSAndrzej Kaczmarek 26629a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 26639a91a04aSGustavo F. Padovan return len; 26649a91a04aSGustavo F. Padovan } 26659a91a04aSGustavo F. Padovan 26669a91a04aSGustavo F. Padovan switch (chan->mode) { 266738319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 266815f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL: 2669177f8f2bSJohan Hedberg /* Check outgoing MTU */ 2670177f8f2bSJohan Hedberg if (len > chan->omtu) 2671177f8f2bSJohan Hedberg return -EMSGSIZE; 2672177f8f2bSJohan Hedberg 2673177f8f2bSJohan Hedberg __skb_queue_head_init(&seg_queue); 2674177f8f2bSJohan Hedberg 2675177f8f2bSJohan Hedberg err = l2cap_segment_le_sdu(chan, &seg_queue, msg, len); 2676177f8f2bSJohan Hedberg 2677177f8f2bSJohan Hedberg if (chan->state != BT_CONNECTED) { 2678177f8f2bSJohan Hedberg __skb_queue_purge(&seg_queue); 2679177f8f2bSJohan Hedberg err = -ENOTCONN; 2680177f8f2bSJohan Hedberg } 2681177f8f2bSJohan Hedberg 2682177f8f2bSJohan Hedberg if (err) 2683177f8f2bSJohan Hedberg return err; 2684177f8f2bSJohan Hedberg 2685177f8f2bSJohan Hedberg skb_queue_splice_tail_init(&seg_queue, &chan->tx_q); 2686177f8f2bSJohan Hedberg 26878a505b7fSLuiz Augusto von Dentz l2cap_le_flowctl_send(chan); 2688177f8f2bSJohan Hedberg 2689177f8f2bSJohan Hedberg if (!chan->tx_credits) 2690177f8f2bSJohan Hedberg chan->ops->suspend(chan); 2691177f8f2bSJohan Hedberg 2692177f8f2bSJohan Hedberg err = len; 2693177f8f2bSJohan Hedberg 2694177f8f2bSJohan Hedberg break; 2695177f8f2bSJohan Hedberg 2696fad5fc89SJohan Hedberg case L2CAP_MODE_BASIC: 26979a91a04aSGustavo F. Padovan /* Check outgoing MTU */ 26989a91a04aSGustavo F. Padovan if (len > chan->omtu) 26999a91a04aSGustavo F. Padovan return -EMSGSIZE; 27009a91a04aSGustavo F. Padovan 27019a91a04aSGustavo F. Padovan /* Create a basic PDU */ 27028d46321cSMarcel Holtmann skb = l2cap_create_basic_pdu(chan, msg, len); 27039a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 27049a91a04aSGustavo F. Padovan return PTR_ERR(skb); 27059a91a04aSGustavo F. Padovan 2706ede81a2aSAndrzej Kaczmarek /* Channel lock is released before requesting new skb and then 2707ede81a2aSAndrzej Kaczmarek * reacquired thus we need to recheck channel state. 2708ede81a2aSAndrzej Kaczmarek */ 2709ede81a2aSAndrzej Kaczmarek if (chan->state != BT_CONNECTED) { 2710ede81a2aSAndrzej Kaczmarek kfree_skb(skb); 2711ede81a2aSAndrzej Kaczmarek return -ENOTCONN; 2712ede81a2aSAndrzej Kaczmarek } 2713ede81a2aSAndrzej Kaczmarek 27149a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 27159a91a04aSGustavo F. Padovan err = len; 27169a91a04aSGustavo F. Padovan break; 27179a91a04aSGustavo F. Padovan 27189a91a04aSGustavo F. Padovan case L2CAP_MODE_ERTM: 27199a91a04aSGustavo F. Padovan case L2CAP_MODE_STREAMING: 272094122bbeSMat Martineau /* Check outgoing MTU */ 272194122bbeSMat Martineau if (len > chan->omtu) { 272294122bbeSMat Martineau err = -EMSGSIZE; 27239a91a04aSGustavo F. Padovan break; 27249a91a04aSGustavo F. Padovan } 27259a91a04aSGustavo F. Padovan 272694122bbeSMat Martineau __skb_queue_head_init(&seg_queue); 272794122bbeSMat Martineau 272894122bbeSMat Martineau /* Do segmentation before calling in to the state machine, 272994122bbeSMat Martineau * since it's possible to block while waiting for memory 273094122bbeSMat Martineau * allocation. 273194122bbeSMat Martineau */ 273294122bbeSMat Martineau err = l2cap_segment_sdu(chan, &seg_queue, msg, len); 273394122bbeSMat Martineau 273494122bbeSMat Martineau /* The channel could have been closed while segmenting, 273594122bbeSMat Martineau * check that it is still connected. 273694122bbeSMat Martineau */ 273794122bbeSMat Martineau if (chan->state != BT_CONNECTED) { 273894122bbeSMat Martineau __skb_queue_purge(&seg_queue); 273994122bbeSMat Martineau err = -ENOTCONN; 27409a91a04aSGustavo F. Padovan } 27419a91a04aSGustavo F. Padovan 274294122bbeSMat Martineau if (err) 274394122bbeSMat Martineau break; 274494122bbeSMat Martineau 27453733937dSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) 2746d660366dSGustavo Padovan l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST); 27473733937dSMat Martineau else 2748d660366dSGustavo Padovan l2cap_streaming_send(chan, &seg_queue); 274994122bbeSMat Martineau 27509a91a04aSGustavo F. Padovan err = len; 27519a91a04aSGustavo F. Padovan 275294122bbeSMat Martineau /* If the skbs were not queued for sending, they'll still be in 275394122bbeSMat Martineau * seg_queue and need to be purged. 275494122bbeSMat Martineau */ 275594122bbeSMat Martineau __skb_queue_purge(&seg_queue); 27569a91a04aSGustavo F. Padovan break; 27579a91a04aSGustavo F. Padovan 27589a91a04aSGustavo F. Padovan default: 27599a91a04aSGustavo F. Padovan BT_DBG("bad state %1.1x", chan->mode); 27609a91a04aSGustavo F. Padovan err = -EBADFD; 27619a91a04aSGustavo F. Padovan } 27629a91a04aSGustavo F. Padovan 27639a91a04aSGustavo F. Padovan return err; 27649a91a04aSGustavo F. Padovan } 27656b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_send); 27669a91a04aSGustavo F. Padovan 2767d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq) 2768d2a7ac5dSMat Martineau { 2769bed68bdeSMat Martineau struct l2cap_ctrl control; 2770bed68bdeSMat Martineau u16 seq; 2771bed68bdeSMat Martineau 2772b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2773bed68bdeSMat Martineau 2774bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2775bed68bdeSMat Martineau control.sframe = 1; 2776bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2777bed68bdeSMat Martineau 2778bed68bdeSMat Martineau for (seq = chan->expected_tx_seq; seq != txseq; 2779bed68bdeSMat Martineau seq = __next_seq(chan, seq)) { 2780bed68bdeSMat Martineau if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) { 2781bed68bdeSMat Martineau control.reqseq = seq; 2782bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2783bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2784bed68bdeSMat Martineau } 2785bed68bdeSMat Martineau } 2786bed68bdeSMat Martineau 2787bed68bdeSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 2788d2a7ac5dSMat Martineau } 2789d2a7ac5dSMat Martineau 2790d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan) 2791d2a7ac5dSMat Martineau { 2792bed68bdeSMat Martineau struct l2cap_ctrl control; 2793bed68bdeSMat Martineau 2794bed68bdeSMat Martineau BT_DBG("chan %p", chan); 2795bed68bdeSMat Martineau 2796bed68bdeSMat Martineau if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR) 2797bed68bdeSMat Martineau return; 2798bed68bdeSMat Martineau 2799bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2800bed68bdeSMat Martineau control.sframe = 1; 2801bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2802bed68bdeSMat Martineau control.reqseq = chan->srej_list.tail; 2803bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2804d2a7ac5dSMat Martineau } 2805d2a7ac5dSMat Martineau 2806d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq) 2807d2a7ac5dSMat Martineau { 2808bed68bdeSMat Martineau struct l2cap_ctrl control; 2809bed68bdeSMat Martineau u16 initial_head; 2810bed68bdeSMat Martineau u16 seq; 2811bed68bdeSMat Martineau 2812b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2813bed68bdeSMat Martineau 2814bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2815bed68bdeSMat Martineau control.sframe = 1; 2816bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2817bed68bdeSMat Martineau 2818bed68bdeSMat Martineau /* Capture initial list head to allow only one pass through the list. */ 2819bed68bdeSMat Martineau initial_head = chan->srej_list.head; 2820bed68bdeSMat Martineau 2821bed68bdeSMat Martineau do { 2822bed68bdeSMat Martineau seq = l2cap_seq_list_pop(&chan->srej_list); 2823bed68bdeSMat Martineau if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR) 2824bed68bdeSMat Martineau break; 2825bed68bdeSMat Martineau 2826bed68bdeSMat Martineau control.reqseq = seq; 2827bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2828bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2829bed68bdeSMat Martineau } while (chan->srej_list.head != initial_head); 2830d2a7ac5dSMat Martineau } 2831d2a7ac5dSMat Martineau 2832608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq) 2833608bcc6dSMat Martineau { 2834608bcc6dSMat Martineau struct sk_buff *acked_skb; 2835608bcc6dSMat Martineau u16 ackseq; 2836608bcc6dSMat Martineau 2837b4400672SAndrei Emeltchenko BT_DBG("chan %p, reqseq %u", chan, reqseq); 2838608bcc6dSMat Martineau 2839608bcc6dSMat Martineau if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq) 2840608bcc6dSMat Martineau return; 2841608bcc6dSMat Martineau 2842b4400672SAndrei Emeltchenko BT_DBG("expected_ack_seq %u, unacked_frames %u", 2843608bcc6dSMat Martineau chan->expected_ack_seq, chan->unacked_frames); 2844608bcc6dSMat Martineau 2845608bcc6dSMat Martineau for (ackseq = chan->expected_ack_seq; ackseq != reqseq; 2846608bcc6dSMat Martineau ackseq = __next_seq(chan, ackseq)) { 2847608bcc6dSMat Martineau 2848608bcc6dSMat Martineau acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq); 2849608bcc6dSMat Martineau if (acked_skb) { 2850608bcc6dSMat Martineau skb_unlink(acked_skb, &chan->tx_q); 2851608bcc6dSMat Martineau kfree_skb(acked_skb); 2852608bcc6dSMat Martineau chan->unacked_frames--; 2853608bcc6dSMat Martineau } 2854608bcc6dSMat Martineau } 2855608bcc6dSMat Martineau 2856608bcc6dSMat Martineau chan->expected_ack_seq = reqseq; 2857608bcc6dSMat Martineau 2858608bcc6dSMat Martineau if (chan->unacked_frames == 0) 2859608bcc6dSMat Martineau __clear_retrans_timer(chan); 2860608bcc6dSMat Martineau 2861b4400672SAndrei Emeltchenko BT_DBG("unacked_frames %u", chan->unacked_frames); 2862608bcc6dSMat Martineau } 2863608bcc6dSMat Martineau 2864608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan) 2865608bcc6dSMat Martineau { 2866608bcc6dSMat Martineau BT_DBG("chan %p", chan); 2867608bcc6dSMat Martineau 2868608bcc6dSMat Martineau chan->expected_tx_seq = chan->buffer_seq; 2869608bcc6dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 2870608bcc6dSMat Martineau skb_queue_purge(&chan->srej_q); 2871608bcc6dSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2872608bcc6dSMat Martineau } 2873608bcc6dSMat Martineau 2874d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan, 2875608bcc6dSMat Martineau struct l2cap_ctrl *control, 2876608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2877608bcc6dSMat Martineau { 2878608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2879608bcc6dSMat Martineau event); 2880608bcc6dSMat Martineau 2881608bcc6dSMat Martineau switch (event) { 2882608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2883608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2884608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2885608bcc6dSMat Martineau 2886608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2887608bcc6dSMat Martineau l2cap_ertm_send(chan); 2888608bcc6dSMat Martineau break; 2889608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2890608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2891608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2892608bcc6dSMat Martineau 2893608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2894608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2895608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2896608bcc6dSMat Martineau */ 2897608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2898608bcc6dSMat Martineau } 2899608bcc6dSMat Martineau 2900608bcc6dSMat Martineau l2cap_send_ack(chan); 2901608bcc6dSMat Martineau 2902608bcc6dSMat Martineau break; 2903608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2904608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2905608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2906608bcc6dSMat Martineau 2907608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2908608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2909608bcc6dSMat Martineau 2910608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2911608bcc6dSMat Martineau local_control.sframe = 1; 2912608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2913608bcc6dSMat Martineau local_control.poll = 1; 2914608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2915a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2916608bcc6dSMat Martineau 2917608bcc6dSMat Martineau chan->retry_count = 1; 2918608bcc6dSMat Martineau __set_monitor_timer(chan); 2919608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2920608bcc6dSMat Martineau } 2921608bcc6dSMat Martineau break; 2922608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2923608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2924608bcc6dSMat Martineau break; 2925608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2926608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2927608bcc6dSMat Martineau chan->retry_count = 1; 2928608bcc6dSMat Martineau __set_monitor_timer(chan); 2929608bcc6dSMat Martineau __clear_ack_timer(chan); 2930608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2931608bcc6dSMat Martineau break; 2932608bcc6dSMat Martineau case L2CAP_EV_RETRANS_TO: 2933608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2934608bcc6dSMat Martineau chan->retry_count = 1; 2935608bcc6dSMat Martineau __set_monitor_timer(chan); 2936608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2937608bcc6dSMat Martineau break; 2938608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2939608bcc6dSMat Martineau /* Nothing to process */ 2940608bcc6dSMat Martineau break; 2941608bcc6dSMat Martineau default: 2942608bcc6dSMat Martineau break; 2943608bcc6dSMat Martineau } 2944608bcc6dSMat Martineau } 2945608bcc6dSMat Martineau 2946d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan, 2947608bcc6dSMat Martineau struct l2cap_ctrl *control, 2948608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2949608bcc6dSMat Martineau { 2950608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2951608bcc6dSMat Martineau event); 2952608bcc6dSMat Martineau 2953608bcc6dSMat Martineau switch (event) { 2954608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2955608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2956608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2957608bcc6dSMat Martineau /* Queue data, but don't send. */ 2958608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2959608bcc6dSMat Martineau break; 2960608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2961608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2962608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2963608bcc6dSMat Martineau 2964608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2965608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2966608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2967608bcc6dSMat Martineau */ 2968608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2969608bcc6dSMat Martineau } 2970608bcc6dSMat Martineau 2971608bcc6dSMat Martineau l2cap_send_ack(chan); 2972608bcc6dSMat Martineau 2973608bcc6dSMat Martineau break; 2974608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2975608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2976608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2977608bcc6dSMat Martineau 2978608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2979608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2980608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2981608bcc6dSMat Martineau local_control.sframe = 1; 2982608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2983608bcc6dSMat Martineau local_control.poll = 1; 2984608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2985a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2986608bcc6dSMat Martineau 2987608bcc6dSMat Martineau chan->retry_count = 1; 2988608bcc6dSMat Martineau __set_monitor_timer(chan); 2989608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2990608bcc6dSMat Martineau } 2991608bcc6dSMat Martineau break; 2992608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2993608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 299419186c7bSGustavo A. R. Silva fallthrough; 2995608bcc6dSMat Martineau 2996608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2997608bcc6dSMat Martineau if (control && control->final) { 2998608bcc6dSMat Martineau __clear_monitor_timer(chan); 2999608bcc6dSMat Martineau if (chan->unacked_frames > 0) 3000608bcc6dSMat Martineau __set_retrans_timer(chan); 3001608bcc6dSMat Martineau chan->retry_count = 0; 3002608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 3003608bcc6dSMat Martineau BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state); 3004608bcc6dSMat Martineau } 3005608bcc6dSMat Martineau break; 3006608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 3007608bcc6dSMat Martineau /* Ignore */ 3008608bcc6dSMat Martineau break; 3009608bcc6dSMat Martineau case L2CAP_EV_MONITOR_TO: 3010608bcc6dSMat Martineau if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) { 3011608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 3012608bcc6dSMat Martineau __set_monitor_timer(chan); 3013608bcc6dSMat Martineau chan->retry_count++; 3014608bcc6dSMat Martineau } else { 30155e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNABORTED); 3016608bcc6dSMat Martineau } 3017608bcc6dSMat Martineau break; 3018608bcc6dSMat Martineau default: 3019608bcc6dSMat Martineau break; 3020608bcc6dSMat Martineau } 3021608bcc6dSMat Martineau } 3022608bcc6dSMat Martineau 3023d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 3024608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 3025608bcc6dSMat Martineau { 3026608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d, state %d", 3027608bcc6dSMat Martineau chan, control, skbs, event, chan->tx_state); 3028608bcc6dSMat Martineau 3029608bcc6dSMat Martineau switch (chan->tx_state) { 3030608bcc6dSMat Martineau case L2CAP_TX_STATE_XMIT: 3031d660366dSGustavo Padovan l2cap_tx_state_xmit(chan, control, skbs, event); 3032608bcc6dSMat Martineau break; 3033608bcc6dSMat Martineau case L2CAP_TX_STATE_WAIT_F: 3034d660366dSGustavo Padovan l2cap_tx_state_wait_f(chan, control, skbs, event); 3035608bcc6dSMat Martineau break; 3036608bcc6dSMat Martineau default: 3037608bcc6dSMat Martineau /* Ignore event */ 3038608bcc6dSMat Martineau break; 3039608bcc6dSMat Martineau } 3040608bcc6dSMat Martineau } 3041608bcc6dSMat Martineau 30424b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan, 30434b51dae9SMat Martineau struct l2cap_ctrl *control) 30444b51dae9SMat Martineau { 30454b51dae9SMat Martineau BT_DBG("chan %p, control %p", chan, control); 3046401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT); 30474b51dae9SMat Martineau } 30484b51dae9SMat Martineau 3049f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan, 3050f80842a8SMat Martineau struct l2cap_ctrl *control) 3051f80842a8SMat Martineau { 3052f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 3053401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT); 3054f80842a8SMat Martineau } 3055f80842a8SMat Martineau 30560a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */ 30570a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 30580a708f8fSGustavo F. Padovan { 30590a708f8fSGustavo F. Padovan struct sk_buff *nskb; 306048454079SGustavo F. Padovan struct l2cap_chan *chan; 30610a708f8fSGustavo F. Padovan 30620a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 30630a708f8fSGustavo F. Padovan 30643df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 30653d57dc68SGustavo F. Padovan 30663df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 3067715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW) 30680a708f8fSGustavo F. Padovan continue; 30690a708f8fSGustavo F. Padovan 30707f5396a7SGustavo Padovan /* Don't send frame to the channel it came from */ 3071a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.chan == chan) 30720a708f8fSGustavo F. Padovan continue; 30737f5396a7SGustavo Padovan 30748bcde1f2SGustavo Padovan nskb = skb_clone(skb, GFP_KERNEL); 30750a708f8fSGustavo F. Padovan if (!nskb) 30760a708f8fSGustavo F. Padovan continue; 307780b98027SGustavo Padovan if (chan->ops->recv(chan, nskb)) 30780a708f8fSGustavo F. Padovan kfree_skb(nskb); 30790a708f8fSGustavo F. Padovan } 30803d57dc68SGustavo F. Padovan 30813df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 30820a708f8fSGustavo F. Padovan } 30830a708f8fSGustavo F. Padovan 30840a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */ 3085b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, 3086b4400672SAndrei Emeltchenko u8 ident, u16 dlen, void *data) 30870a708f8fSGustavo F. Padovan { 30880a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag; 30890a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd; 30900a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 30910a708f8fSGustavo F. Padovan int len, count; 30920a708f8fSGustavo F. Padovan 3093b4400672SAndrei Emeltchenko BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u", 30940a708f8fSGustavo F. Padovan conn, code, ident, dlen); 30950a708f8fSGustavo F. Padovan 3096300b962eSAnderson Lizardo if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE) 3097300b962eSAnderson Lizardo return NULL; 3098300b962eSAnderson Lizardo 30990a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; 31000a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 31010a708f8fSGustavo F. Padovan 31028bcde1f2SGustavo Padovan skb = bt_skb_alloc(count, GFP_KERNEL); 31030a708f8fSGustavo F. Padovan if (!skb) 31040a708f8fSGustavo F. Padovan return NULL; 31050a708f8fSGustavo F. Padovan 31064df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 31070a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); 31083300d9a9SClaudio Takahasi 31093300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 3110dcf4adbfSJoe Perches lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING); 31113300d9a9SClaudio Takahasi else 3112dcf4adbfSJoe Perches lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING); 31130a708f8fSGustavo F. Padovan 31144df864c1SJohannes Berg cmd = skb_put(skb, L2CAP_CMD_HDR_SIZE); 31150a708f8fSGustavo F. Padovan cmd->code = code; 31160a708f8fSGustavo F. Padovan cmd->ident = ident; 31170a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen); 31180a708f8fSGustavo F. Padovan 31190a708f8fSGustavo F. Padovan if (dlen) { 31200a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE; 312159ae1d12SJohannes Berg skb_put_data(skb, data, count); 31220a708f8fSGustavo F. Padovan data += count; 31230a708f8fSGustavo F. Padovan } 31240a708f8fSGustavo F. Padovan 31250a708f8fSGustavo F. Padovan len -= skb->len; 31260a708f8fSGustavo F. Padovan 31270a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 31280a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 31290a708f8fSGustavo F. Padovan while (len) { 31300a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 31310a708f8fSGustavo F. Padovan 31328bcde1f2SGustavo Padovan *frag = bt_skb_alloc(count, GFP_KERNEL); 31330a708f8fSGustavo F. Padovan if (!*frag) 31340a708f8fSGustavo F. Padovan goto fail; 31350a708f8fSGustavo F. Padovan 313659ae1d12SJohannes Berg skb_put_data(*frag, data, count); 31370a708f8fSGustavo F. Padovan 31380a708f8fSGustavo F. Padovan len -= count; 31390a708f8fSGustavo F. Padovan data += count; 31400a708f8fSGustavo F. Padovan 31410a708f8fSGustavo F. Padovan frag = &(*frag)->next; 31420a708f8fSGustavo F. Padovan } 31430a708f8fSGustavo F. Padovan 31440a708f8fSGustavo F. Padovan return skb; 31450a708f8fSGustavo F. Padovan 31460a708f8fSGustavo F. Padovan fail: 31470a708f8fSGustavo F. Padovan kfree_skb(skb); 31480a708f8fSGustavo F. Padovan return NULL; 31490a708f8fSGustavo F. Padovan } 31500a708f8fSGustavo F. Padovan 31512d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, 31522d792818SGustavo Padovan unsigned long *val) 31530a708f8fSGustavo F. Padovan { 31540a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 31550a708f8fSGustavo F. Padovan int len; 31560a708f8fSGustavo F. Padovan 31570a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len; 31580a708f8fSGustavo F. Padovan *ptr += len; 31590a708f8fSGustavo F. Padovan 31600a708f8fSGustavo F. Padovan *type = opt->type; 31610a708f8fSGustavo F. Padovan *olen = opt->len; 31620a708f8fSGustavo F. Padovan 31630a708f8fSGustavo F. Padovan switch (opt->len) { 31640a708f8fSGustavo F. Padovan case 1: 31650a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val); 31660a708f8fSGustavo F. Padovan break; 31670a708f8fSGustavo F. Padovan 31680a708f8fSGustavo F. Padovan case 2: 31690a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val); 31700a708f8fSGustavo F. Padovan break; 31710a708f8fSGustavo F. Padovan 31720a708f8fSGustavo F. Padovan case 4: 31730a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val); 31740a708f8fSGustavo F. Padovan break; 31750a708f8fSGustavo F. Padovan 31760a708f8fSGustavo F. Padovan default: 31770a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val; 31780a708f8fSGustavo F. Padovan break; 31790a708f8fSGustavo F. Padovan } 31800a708f8fSGustavo F. Padovan 3181b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val); 31820a708f8fSGustavo F. Padovan return len; 31830a708f8fSGustavo F. Padovan } 31840a708f8fSGustavo F. Padovan 3185e860d2c9SBen Seri static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size) 31860a708f8fSGustavo F. Padovan { 31870a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 31880a708f8fSGustavo F. Padovan 3189b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val); 31900a708f8fSGustavo F. Padovan 3191e860d2c9SBen Seri if (size < L2CAP_CONF_OPT_SIZE + len) 3192e860d2c9SBen Seri return; 3193e860d2c9SBen Seri 31940a708f8fSGustavo F. Padovan opt->type = type; 31950a708f8fSGustavo F. Padovan opt->len = len; 31960a708f8fSGustavo F. Padovan 31970a708f8fSGustavo F. Padovan switch (len) { 31980a708f8fSGustavo F. Padovan case 1: 31990a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val; 32000a708f8fSGustavo F. Padovan break; 32010a708f8fSGustavo F. Padovan 32020a708f8fSGustavo F. Padovan case 2: 32030a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val); 32040a708f8fSGustavo F. Padovan break; 32050a708f8fSGustavo F. Padovan 32060a708f8fSGustavo F. Padovan case 4: 32070a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val); 32080a708f8fSGustavo F. Padovan break; 32090a708f8fSGustavo F. Padovan 32100a708f8fSGustavo F. Padovan default: 32110a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len); 32120a708f8fSGustavo F. Padovan break; 32130a708f8fSGustavo F. Padovan } 32140a708f8fSGustavo F. Padovan 32150a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len; 32160a708f8fSGustavo F. Padovan } 32170a708f8fSGustavo F. Padovan 3218e860d2c9SBen Seri static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan, size_t size) 3219f89cef09SAndrei Emeltchenko { 3220f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs; 3221f89cef09SAndrei Emeltchenko 3222f89cef09SAndrei Emeltchenko switch (chan->mode) { 3223f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM: 3224f89cef09SAndrei Emeltchenko efs.id = chan->local_id; 3225f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype; 3226f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 3227f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 3228dcf4adbfSJoe Perches efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); 3229dcf4adbfSJoe Perches efs.flush_to = cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO); 3230f89cef09SAndrei Emeltchenko break; 3231f89cef09SAndrei Emeltchenko 3232f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING: 3233f89cef09SAndrei Emeltchenko efs.id = 1; 3234f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT; 3235f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 3236f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 3237f89cef09SAndrei Emeltchenko efs.acc_lat = 0; 3238f89cef09SAndrei Emeltchenko efs.flush_to = 0; 3239f89cef09SAndrei Emeltchenko break; 3240f89cef09SAndrei Emeltchenko 3241f89cef09SAndrei Emeltchenko default: 3242f89cef09SAndrei Emeltchenko return; 3243f89cef09SAndrei Emeltchenko } 3244f89cef09SAndrei Emeltchenko 3245f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), 3246e860d2c9SBen Seri (unsigned long) &efs, size); 3247f89cef09SAndrei Emeltchenko } 3248f89cef09SAndrei Emeltchenko 3249721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work) 32500a708f8fSGustavo F. Padovan { 3251721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 3252721c4181SGustavo F. Padovan ack_timer.work); 32530362520bSMat Martineau u16 frames_to_ack; 32540a708f8fSGustavo F. Padovan 32552fb9b3d4SGustavo F. Padovan BT_DBG("chan %p", chan); 32562fb9b3d4SGustavo F. Padovan 32576be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 32586be36555SAndrei Emeltchenko 32590362520bSMat Martineau frames_to_ack = __seq_offset(chan, chan->buffer_seq, 32600362520bSMat Martineau chan->last_acked_seq); 32610362520bSMat Martineau 32620362520bSMat Martineau if (frames_to_ack) 32630362520bSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 32646be36555SAndrei Emeltchenko 32656be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 326609bfb2eeSSzymon Janc l2cap_chan_put(chan); 32670a708f8fSGustavo F. Padovan } 32680a708f8fSGustavo F. Padovan 3269466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan) 32700a708f8fSGustavo F. Padovan { 32713c588192SMat Martineau int err; 32723c588192SMat Martineau 3273105bdf9eSMat Martineau chan->next_tx_seq = 0; 3274105bdf9eSMat Martineau chan->expected_tx_seq = 0; 327542e5c802SGustavo F. Padovan chan->expected_ack_seq = 0; 32766a026610SGustavo F. Padovan chan->unacked_frames = 0; 327742e5c802SGustavo F. Padovan chan->buffer_seq = 0; 32786a026610SGustavo F. Padovan chan->frames_sent = 0; 3279105bdf9eSMat Martineau chan->last_acked_seq = 0; 3280105bdf9eSMat Martineau chan->sdu = NULL; 3281105bdf9eSMat Martineau chan->sdu_last_frag = NULL; 3282105bdf9eSMat Martineau chan->sdu_len = 0; 3283105bdf9eSMat Martineau 3284d34c34fbSMat Martineau skb_queue_head_init(&chan->tx_q); 3285d34c34fbSMat Martineau 32866ed971caSMarcel Holtmann chan->local_amp_id = AMP_ID_BREDR; 32876ed971caSMarcel Holtmann chan->move_id = AMP_ID_BREDR; 328808333283SMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 328908333283SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 329008333283SMat Martineau 3291105bdf9eSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 3292105bdf9eSMat Martineau return 0; 3293105bdf9eSMat Martineau 3294105bdf9eSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 3295105bdf9eSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 32960a708f8fSGustavo F. Padovan 3297721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout); 3298721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout); 3299721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout); 33000a708f8fSGustavo F. Padovan 3301f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q); 33020a708f8fSGustavo F. Padovan 33033c588192SMat Martineau err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win); 33043c588192SMat Martineau if (err < 0) 33053c588192SMat Martineau return err; 33063c588192SMat Martineau 33079dc9affcSMat Martineau err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win); 33089dc9affcSMat Martineau if (err < 0) 33099dc9affcSMat Martineau l2cap_seq_list_free(&chan->srej_list); 33109dc9affcSMat Martineau 33119dc9affcSMat Martineau return err; 33120a708f8fSGustavo F. Padovan } 33130a708f8fSGustavo F. Padovan 33140a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) 33150a708f8fSGustavo F. Padovan { 33160a708f8fSGustavo F. Padovan switch (mode) { 33170a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 33180a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 33190a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask)) 33200a708f8fSGustavo F. Padovan return mode; 332119186c7bSGustavo A. R. Silva fallthrough; 33220a708f8fSGustavo F. Padovan default: 33230a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC; 33240a708f8fSGustavo F. Padovan } 33250a708f8fSGustavo F. Padovan } 33260a708f8fSGustavo F. Padovan 3327848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn) 33286327eb98SAndrei Emeltchenko { 33290bd49fc7SJohan Hedberg return ((conn->local_fixed_chan & L2CAP_FC_A2MP) && 33300bd49fc7SJohan Hedberg (conn->feat_mask & L2CAP_FEAT_EXT_WINDOW)); 33316327eb98SAndrei Emeltchenko } 33326327eb98SAndrei Emeltchenko 3333848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn) 3334f89cef09SAndrei Emeltchenko { 33350bd49fc7SJohan Hedberg return ((conn->local_fixed_chan & L2CAP_FC_A2MP) && 33360bd49fc7SJohan Hedberg (conn->feat_mask & L2CAP_FEAT_EXT_FLOW)); 3337f89cef09SAndrei Emeltchenko } 3338f89cef09SAndrei Emeltchenko 333936c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan, 334036c86c85SMat Martineau struct l2cap_conf_rfc *rfc) 334136c86c85SMat Martineau { 33426ed971caSMarcel Holtmann if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) { 334336c86c85SMat Martineau u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to; 334436c86c85SMat Martineau 334536c86c85SMat Martineau /* Class 1 devices have must have ERTM timeouts 334636c86c85SMat Martineau * exceeding the Link Supervision Timeout. The 334736c86c85SMat Martineau * default Link Supervision Timeout for AMP 334836c86c85SMat Martineau * controllers is 10 seconds. 334936c86c85SMat Martineau * 335036c86c85SMat Martineau * Class 1 devices use 0xffffffff for their 335136c86c85SMat Martineau * best-effort flush timeout, so the clamping logic 335236c86c85SMat Martineau * will result in a timeout that meets the above 335336c86c85SMat Martineau * requirement. ERTM timeouts are 16-bit values, so 335436c86c85SMat Martineau * the maximum timeout is 65.535 seconds. 335536c86c85SMat Martineau */ 335636c86c85SMat Martineau 335736c86c85SMat Martineau /* Convert timeout to milliseconds and round */ 335836c86c85SMat Martineau ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000); 335936c86c85SMat Martineau 336036c86c85SMat Martineau /* This is the recommended formula for class 2 devices 336136c86c85SMat Martineau * that start ERTM timers when packets are sent to the 336236c86c85SMat Martineau * controller. 336336c86c85SMat Martineau */ 336436c86c85SMat Martineau ertm_to = 3 * ertm_to + 500; 336536c86c85SMat Martineau 336636c86c85SMat Martineau if (ertm_to > 0xffff) 336736c86c85SMat Martineau ertm_to = 0xffff; 336836c86c85SMat Martineau 336936c86c85SMat Martineau rfc->retrans_timeout = cpu_to_le16((u16) ertm_to); 337036c86c85SMat Martineau rfc->monitor_timeout = rfc->retrans_timeout; 337136c86c85SMat Martineau } else { 3372dcf4adbfSJoe Perches rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 3373dcf4adbfSJoe Perches rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 337436c86c85SMat Martineau } 337536c86c85SMat Martineau } 337636c86c85SMat Martineau 33776327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan) 33786327eb98SAndrei Emeltchenko { 33796327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && 3380848566b3SMarcel Holtmann __l2cap_ews_supported(chan->conn)) { 33816327eb98SAndrei Emeltchenko /* use extended control field */ 33826327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 3383836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 3384836be934SAndrei Emeltchenko } else { 33856327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win, 33866327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 3387836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 3388836be934SAndrei Emeltchenko } 3389c20f8e35SMat Martineau chan->ack_win = chan->tx_win; 33906327eb98SAndrei Emeltchenko } 33916327eb98SAndrei Emeltchenko 33924b6e228eSLuiz Augusto von Dentz static void l2cap_mtu_auto(struct l2cap_chan *chan) 33934b6e228eSLuiz Augusto von Dentz { 33944b6e228eSLuiz Augusto von Dentz struct hci_conn *conn = chan->conn->hcon; 33954b6e228eSLuiz Augusto von Dentz 33964b6e228eSLuiz Augusto von Dentz chan->imtu = L2CAP_DEFAULT_MIN_MTU; 33974b6e228eSLuiz Augusto von Dentz 33984b6e228eSLuiz Augusto von Dentz /* The 2-DH1 packet has between 2 and 56 information bytes 33994b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header) 34004b6e228eSLuiz Augusto von Dentz */ 34014b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_2DH1)) 34024b6e228eSLuiz Augusto von Dentz chan->imtu = 54; 34034b6e228eSLuiz Augusto von Dentz 34044b6e228eSLuiz Augusto von Dentz /* The 3-DH1 packet has between 2 and 85 information bytes 34054b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header) 34064b6e228eSLuiz Augusto von Dentz */ 34074b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_3DH1)) 34084b6e228eSLuiz Augusto von Dentz chan->imtu = 83; 34094b6e228eSLuiz Augusto von Dentz 34104b6e228eSLuiz Augusto von Dentz /* The 2-DH3 packet has between 2 and 369 information bytes 34114b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header) 34124b6e228eSLuiz Augusto von Dentz */ 34134b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_2DH3)) 34144b6e228eSLuiz Augusto von Dentz chan->imtu = 367; 34154b6e228eSLuiz Augusto von Dentz 34164b6e228eSLuiz Augusto von Dentz /* The 3-DH3 packet has between 2 and 554 information bytes 34174b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header) 34184b6e228eSLuiz Augusto von Dentz */ 34194b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_3DH3)) 34204b6e228eSLuiz Augusto von Dentz chan->imtu = 552; 34214b6e228eSLuiz Augusto von Dentz 34224b6e228eSLuiz Augusto von Dentz /* The 2-DH5 packet has between 2 and 681 information bytes 34234b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header) 34244b6e228eSLuiz Augusto von Dentz */ 34254b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_2DH5)) 34264b6e228eSLuiz Augusto von Dentz chan->imtu = 679; 34274b6e228eSLuiz Augusto von Dentz 34284b6e228eSLuiz Augusto von Dentz /* The 3-DH5 packet has between 2 and 1023 information bytes 34294b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header) 34304b6e228eSLuiz Augusto von Dentz */ 34314b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_3DH5)) 34324b6e228eSLuiz Augusto von Dentz chan->imtu = 1021; 34334b6e228eSLuiz Augusto von Dentz } 34344b6e228eSLuiz Augusto von Dentz 3435e860d2c9SBen Seri static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size) 34360a708f8fSGustavo F. Padovan { 34370a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 34380c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode }; 34390a708f8fSGustavo F. Padovan void *ptr = req->data; 3440e860d2c9SBen Seri void *endptr = data + data_size; 3441c8f79162SAndrei Emeltchenko u16 size; 34420a708f8fSGustavo F. Padovan 344349208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 34440a708f8fSGustavo F. Padovan 344573ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp) 34460a708f8fSGustavo F. Padovan goto done; 34470a708f8fSGustavo F. Padovan 34480c1bc5c6SGustavo F. Padovan switch (chan->mode) { 34490a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 34500a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3451c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) 34520a708f8fSGustavo F. Padovan break; 34530a708f8fSGustavo F. Padovan 3454848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn)) 3455f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 3456f89cef09SAndrei Emeltchenko 345719186c7bSGustavo A. R. Silva fallthrough; 34580a708f8fSGustavo F. Padovan default: 34598c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); 34600a708f8fSGustavo F. Padovan break; 34610a708f8fSGustavo F. Padovan } 34620a708f8fSGustavo F. Padovan 34630a708f8fSGustavo F. Padovan done: 34644b6e228eSLuiz Augusto von Dentz if (chan->imtu != L2CAP_DEFAULT_MTU) { 34654b6e228eSLuiz Augusto von Dentz if (!chan->imtu) 34664b6e228eSLuiz Augusto von Dentz l2cap_mtu_auto(chan); 34674b6e228eSLuiz Augusto von Dentz l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, 34684b6e228eSLuiz Augusto von Dentz endptr - ptr); 34694b6e228eSLuiz Augusto von Dentz } 34700a708f8fSGustavo F. Padovan 34710c1bc5c6SGustavo F. Padovan switch (chan->mode) { 34720a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 34736fea7ad1SMarcel Holtmann if (disable_ertm) 34746fea7ad1SMarcel Holtmann break; 34756fea7ad1SMarcel Holtmann 34768c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && 34778c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) 34780a708f8fSGustavo F. Padovan break; 34790a708f8fSGustavo F. Padovan 34800a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC; 34810a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 34820a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 34830a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 34840a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 34850a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0; 34860a708f8fSGustavo F. Padovan 34870a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3488e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr); 34890a708f8fSGustavo F. Padovan break; 34900a708f8fSGustavo F. Padovan 34910a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 34920a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM; 349347d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx; 349436c86c85SMat Martineau 349536c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc); 3496c8f79162SAndrei Emeltchenko 3497c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 34982d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - 3499c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3500c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 35010a708f8fSGustavo F. Padovan 35026327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan); 35036327eb98SAndrei Emeltchenko 35046327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win, 35056327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 35060a708f8fSGustavo F. Padovan 35070a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3508e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr); 35090a708f8fSGustavo F. Padovan 3510f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 3511e860d2c9SBen Seri l2cap_add_opt_efs(&ptr, chan, endptr - ptr); 3512f89cef09SAndrei Emeltchenko 35136327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 35146327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 3515e860d2c9SBen Seri chan->tx_win, endptr - ptr); 351660918918SAndrei Emeltchenko 351760918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS) 351860918918SAndrei Emeltchenko if (chan->fcs == L2CAP_FCS_NONE || 3519f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { 352060918918SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 352160918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, 3522e860d2c9SBen Seri chan->fcs, endptr - ptr); 352360918918SAndrei Emeltchenko } 35240a708f8fSGustavo F. Padovan break; 35250a708f8fSGustavo F. Padovan 35260a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3527273759e2SMat Martineau l2cap_txwin_setup(chan); 35280a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING; 35290a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 35300a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 35310a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 35320a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 3533c8f79162SAndrei Emeltchenko 3534c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 35352d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - 3536c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3537c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 35380a708f8fSGustavo F. Padovan 35390a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3540e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr); 35410a708f8fSGustavo F. Padovan 3542f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 3543e860d2c9SBen Seri l2cap_add_opt_efs(&ptr, chan, endptr - ptr); 3544f89cef09SAndrei Emeltchenko 354560918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS) 354647d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 3547f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { 354847d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 354960918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, 3550e860d2c9SBen Seri chan->fcs, endptr - ptr); 35510a708f8fSGustavo F. Padovan } 35520a708f8fSGustavo F. Padovan break; 35530a708f8fSGustavo F. Padovan } 35540a708f8fSGustavo F. Padovan 3555fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 3556dcf4adbfSJoe Perches req->flags = cpu_to_le16(0); 35570a708f8fSGustavo F. Padovan 35580a708f8fSGustavo F. Padovan return ptr - data; 35590a708f8fSGustavo F. Padovan } 35600a708f8fSGustavo F. Padovan 3561e860d2c9SBen Seri static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data_size) 35620a708f8fSGustavo F. Padovan { 35630a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 35640a708f8fSGustavo F. Padovan void *ptr = rsp->data; 3565e860d2c9SBen Seri void *endptr = data + data_size; 356673ffa904SGustavo F. Padovan void *req = chan->conf_req; 356773ffa904SGustavo F. Padovan int len = chan->conf_len; 35680a708f8fSGustavo F. Padovan int type, hint, olen; 35690a708f8fSGustavo F. Padovan unsigned long val; 35700a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 357142dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs; 357242dceae2SAndrei Emeltchenko u8 remote_efs = 0; 35730a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU; 35740a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS; 3575c8f79162SAndrei Emeltchenko u16 size; 35760a708f8fSGustavo F. Padovan 357773ffa904SGustavo F. Padovan BT_DBG("chan %p", chan); 35780a708f8fSGustavo F. Padovan 35790a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 35800a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val); 35817c9cbd0bSMarcel Holtmann if (len < 0) 35827c9cbd0bSMarcel Holtmann break; 35830a708f8fSGustavo F. Padovan 35840a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT; 35850a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK; 35860a708f8fSGustavo F. Padovan 35870a708f8fSGustavo F. Padovan switch (type) { 35880a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 3589af3d5d1cSMarcel Holtmann if (olen != 2) 3590af3d5d1cSMarcel Holtmann break; 35910a708f8fSGustavo F. Padovan mtu = val; 35920a708f8fSGustavo F. Padovan break; 35930a708f8fSGustavo F. Padovan 35940a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 3595af3d5d1cSMarcel Holtmann if (olen != 2) 3596af3d5d1cSMarcel Holtmann break; 35970c1bc5c6SGustavo F. Padovan chan->flush_to = val; 35980a708f8fSGustavo F. Padovan break; 35990a708f8fSGustavo F. Padovan 36000a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS: 36010a708f8fSGustavo F. Padovan break; 36020a708f8fSGustavo F. Padovan 36030a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 3604af3d5d1cSMarcel Holtmann if (olen != sizeof(rfc)) 3605af3d5d1cSMarcel Holtmann break; 36060a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen); 36070a708f8fSGustavo F. Padovan break; 36080a708f8fSGustavo F. Padovan 36090a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS: 3610af3d5d1cSMarcel Holtmann if (olen != 1) 3611af3d5d1cSMarcel Holtmann break; 36120a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE) 3613f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, &chan->conf_state); 361442dceae2SAndrei Emeltchenko break; 36150a708f8fSGustavo F. Padovan 361642dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS: 3617af3d5d1cSMarcel Holtmann if (olen != sizeof(efs)) 3618af3d5d1cSMarcel Holtmann break; 361942dceae2SAndrei Emeltchenko remote_efs = 1; 362042dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen); 36210a708f8fSGustavo F. Padovan break; 36220a708f8fSGustavo F. Padovan 36236327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 3624af3d5d1cSMarcel Holtmann if (olen != 2) 3625af3d5d1cSMarcel Holtmann break; 36260bd49fc7SJohan Hedberg if (!(chan->conn->local_fixed_chan & L2CAP_FC_A2MP)) 36276327eb98SAndrei Emeltchenko return -ECONNREFUSED; 36286327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 36296327eb98SAndrei Emeltchenko set_bit(CONF_EWS_RECV, &chan->conf_state); 3630836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 36316327eb98SAndrei Emeltchenko chan->remote_tx_win = val; 36320a708f8fSGustavo F. Padovan break; 36330a708f8fSGustavo F. Padovan 36340a708f8fSGustavo F. Padovan default: 36350a708f8fSGustavo F. Padovan if (hint) 36360a708f8fSGustavo F. Padovan break; 36370a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN; 36385b8ec15dSJimmy Wahlberg l2cap_add_conf_opt(&ptr, (u8)type, sizeof(u8), type, endptr - ptr); 36390a708f8fSGustavo F. Padovan break; 36400a708f8fSGustavo F. Padovan } 36410a708f8fSGustavo F. Padovan } 36420a708f8fSGustavo F. Padovan 364373ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1) 36440a708f8fSGustavo F. Padovan goto done; 36450a708f8fSGustavo F. Padovan 36460c1bc5c6SGustavo F. Padovan switch (chan->mode) { 36470a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 36480a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3649c1360a1cSGustavo F. Padovan if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { 36500c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, 36518c1d787bSGustavo F. Padovan chan->conn->feat_mask); 36520a708f8fSGustavo F. Padovan break; 36530a708f8fSGustavo F. Padovan } 36540a708f8fSGustavo F. Padovan 365542dceae2SAndrei Emeltchenko if (remote_efs) { 3656848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn)) 365742dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 365842dceae2SAndrei Emeltchenko else 365942dceae2SAndrei Emeltchenko return -ECONNREFUSED; 366042dceae2SAndrei Emeltchenko } 366142dceae2SAndrei Emeltchenko 36620c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) 36630a708f8fSGustavo F. Padovan return -ECONNREFUSED; 36640a708f8fSGustavo F. Padovan 36650a708f8fSGustavo F. Padovan break; 36660a708f8fSGustavo F. Padovan } 36670a708f8fSGustavo F. Padovan 36680a708f8fSGustavo F. Padovan done: 36690c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) { 36700a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 36710c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 36720a708f8fSGustavo F. Padovan 367373ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1) 36740a708f8fSGustavo F. Padovan return -ECONNREFUSED; 36750a708f8fSGustavo F. Padovan 36762d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3677e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr); 36780a708f8fSGustavo F. Padovan } 36790a708f8fSGustavo F. Padovan 36800a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) { 36810a708f8fSGustavo F. Padovan /* Configure output options and let the other side know 36820a708f8fSGustavo F. Padovan * which ones we don't like. */ 36830a708f8fSGustavo F. Padovan 36840a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU) 36850a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 36860a708f8fSGustavo F. Padovan else { 36870c1bc5c6SGustavo F. Padovan chan->omtu = mtu; 3688c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state); 36890a708f8fSGustavo F. Padovan } 3690e860d2c9SBen Seri l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu, endptr - ptr); 36910a708f8fSGustavo F. Padovan 369242dceae2SAndrei Emeltchenko if (remote_efs) { 369342dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 369442dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 369542dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) { 369642dceae2SAndrei Emeltchenko 369742dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT; 369842dceae2SAndrei Emeltchenko 369942dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1) 370042dceae2SAndrei Emeltchenko return -ECONNREFUSED; 370142dceae2SAndrei Emeltchenko 370242dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 370342dceae2SAndrei Emeltchenko sizeof(efs), 3704e860d2c9SBen Seri (unsigned long) &efs, endptr - ptr); 37050e8b207eSAndrei Emeltchenko } else { 37063e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */ 37070e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING; 37080e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 370942dceae2SAndrei Emeltchenko } 371042dceae2SAndrei Emeltchenko } 371142dceae2SAndrei Emeltchenko 37120a708f8fSGustavo F. Padovan switch (rfc.mode) { 37130a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 371447d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3715c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 37160a708f8fSGustavo F. Padovan break; 37170a708f8fSGustavo F. Padovan 37180a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 37196327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state)) 37202c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size; 37216327eb98SAndrei Emeltchenko else 37226327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; 37236327eb98SAndrei Emeltchenko 37242c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit; 37250a708f8fSGustavo F. Padovan 3726c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 37272d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE - 37282d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); 3729c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3730c8f79162SAndrei Emeltchenko chan->remote_mps = size; 37310a708f8fSGustavo F. Padovan 373236c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc); 37330a708f8fSGustavo F. Padovan 3734c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 37350a708f8fSGustavo F. Padovan 37360a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 3737e860d2c9SBen Seri sizeof(rfc), (unsigned long) &rfc, endptr - ptr); 37380a708f8fSGustavo F. Padovan 373942dceae2SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 374042dceae2SAndrei Emeltchenko chan->remote_id = efs.id; 374142dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype; 374242dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu); 374342dceae2SAndrei Emeltchenko chan->remote_flush_to = 374442dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to); 374542dceae2SAndrei Emeltchenko chan->remote_acc_lat = 374642dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat); 374742dceae2SAndrei Emeltchenko chan->remote_sdu_itime = 374842dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 374942dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 37502d792818SGustavo Padovan sizeof(efs), 3751e860d2c9SBen Seri (unsigned long) &efs, endptr - ptr); 375242dceae2SAndrei Emeltchenko } 37530a708f8fSGustavo F. Padovan break; 37540a708f8fSGustavo F. Padovan 37550a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3756c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 37572d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE - 37582d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); 3759c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3760c8f79162SAndrei Emeltchenko chan->remote_mps = size; 37610a708f8fSGustavo F. Padovan 3762c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 37630a708f8fSGustavo F. Padovan 37642d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3765e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr); 37660a708f8fSGustavo F. Padovan 37670a708f8fSGustavo F. Padovan break; 37680a708f8fSGustavo F. Padovan 37690a708f8fSGustavo F. Padovan default: 37700a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 37710a708f8fSGustavo F. Padovan 37720a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc)); 37730c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 37740a708f8fSGustavo F. Padovan } 37750a708f8fSGustavo F. Padovan 37760a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) 3777c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 37780a708f8fSGustavo F. Padovan } 3779fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 37800a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 3781dcf4adbfSJoe Perches rsp->flags = cpu_to_le16(0); 37820a708f8fSGustavo F. Padovan 37830a708f8fSGustavo F. Padovan return ptr - data; 37840a708f8fSGustavo F. Padovan } 37850a708f8fSGustavo F. Padovan 37862d792818SGustavo Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, 3787e860d2c9SBen Seri void *data, size_t size, u16 *result) 37880a708f8fSGustavo F. Padovan { 37890a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 37900a708f8fSGustavo F. Padovan void *ptr = req->data; 3791e860d2c9SBen Seri void *endptr = data + size; 37920a708f8fSGustavo F. Padovan int type, olen; 37930a708f8fSGustavo F. Padovan unsigned long val; 379436e999a8SMat Martineau struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 379566af7aafSAndrei Emeltchenko struct l2cap_conf_efs efs; 37960a708f8fSGustavo F. Padovan 3797fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); 37980a708f8fSGustavo F. Padovan 37990a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 38000a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 38017c9cbd0bSMarcel Holtmann if (len < 0) 38027c9cbd0bSMarcel Holtmann break; 38030a708f8fSGustavo F. Padovan 38040a708f8fSGustavo F. Padovan switch (type) { 38050a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 3806af3d5d1cSMarcel Holtmann if (olen != 2) 3807af3d5d1cSMarcel Holtmann break; 38080a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) { 38090a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT; 38100c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU; 38110a708f8fSGustavo F. Padovan } else 38120c1bc5c6SGustavo F. Padovan chan->imtu = val; 3813af3d5d1cSMarcel Holtmann l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, 3814af3d5d1cSMarcel Holtmann endptr - ptr); 38150a708f8fSGustavo F. Padovan break; 38160a708f8fSGustavo F. Padovan 38170a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 3818af3d5d1cSMarcel Holtmann if (olen != 2) 3819af3d5d1cSMarcel Holtmann break; 38200c1bc5c6SGustavo F. Padovan chan->flush_to = val; 3821af3d5d1cSMarcel Holtmann l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, 3822af3d5d1cSMarcel Holtmann chan->flush_to, endptr - ptr); 38230a708f8fSGustavo F. Padovan break; 38240a708f8fSGustavo F. Padovan 38250a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 3826af3d5d1cSMarcel Holtmann if (olen != sizeof(rfc)) 3827af3d5d1cSMarcel Holtmann break; 38280a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 3829c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && 38300c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode) 38310a708f8fSGustavo F. Padovan return -ECONNREFUSED; 383247d1ec61SGustavo F. Padovan chan->fcs = 0; 3833af3d5d1cSMarcel Holtmann l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3834af3d5d1cSMarcel Holtmann (unsigned long) &rfc, endptr - ptr); 38350a708f8fSGustavo F. Padovan break; 38366327eb98SAndrei Emeltchenko 38376327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 3838af3d5d1cSMarcel Holtmann if (olen != 2) 3839af3d5d1cSMarcel Holtmann break; 3840c20f8e35SMat Martineau chan->ack_win = min_t(u16, val, chan->ack_win); 38413e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 3842e860d2c9SBen Seri chan->tx_win, endptr - ptr); 38436327eb98SAndrei Emeltchenko break; 384466af7aafSAndrei Emeltchenko 384566af7aafSAndrei Emeltchenko case L2CAP_CONF_EFS: 3846af3d5d1cSMarcel Holtmann if (olen != sizeof(efs)) 3847af3d5d1cSMarcel Holtmann break; 384866af7aafSAndrei Emeltchenko memcpy(&efs, (void *)val, olen); 384966af7aafSAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 385066af7aafSAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 385166af7aafSAndrei Emeltchenko efs.stype != chan->local_stype) 385266af7aafSAndrei Emeltchenko return -ECONNREFUSED; 38532d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), 3854e860d2c9SBen Seri (unsigned long) &efs, endptr - ptr); 385566af7aafSAndrei Emeltchenko break; 3856cbabee78SAndrei Emeltchenko 3857cbabee78SAndrei Emeltchenko case L2CAP_CONF_FCS: 3858af3d5d1cSMarcel Holtmann if (olen != 1) 3859af3d5d1cSMarcel Holtmann break; 3860cbabee78SAndrei Emeltchenko if (*result == L2CAP_CONF_PENDING) 3861cbabee78SAndrei Emeltchenko if (val == L2CAP_FCS_NONE) 3862f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, 3863cbabee78SAndrei Emeltchenko &chan->conf_state); 3864cbabee78SAndrei Emeltchenko break; 38650a708f8fSGustavo F. Padovan } 38660a708f8fSGustavo F. Padovan } 38670a708f8fSGustavo F. Padovan 38680c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) 38690a708f8fSGustavo F. Padovan return -ECONNREFUSED; 38700a708f8fSGustavo F. Padovan 38710c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode; 38720a708f8fSGustavo F. Padovan 38730e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) { 38740a708f8fSGustavo F. Padovan switch (rfc.mode) { 38750a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 387647d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 387747d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 387847d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 3879c20f8e35SMat Martineau if (!test_bit(FLAG_EXT_CTRL, &chan->flags)) 3880c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 3881c20f8e35SMat Martineau rfc.txwin_size); 388266af7aafSAndrei Emeltchenko 388366af7aafSAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 388466af7aafSAndrei Emeltchenko chan->local_msdu = le16_to_cpu(efs.msdu); 388566af7aafSAndrei Emeltchenko chan->local_sdu_itime = 388666af7aafSAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 388766af7aafSAndrei Emeltchenko chan->local_acc_lat = le32_to_cpu(efs.acc_lat); 388866af7aafSAndrei Emeltchenko chan->local_flush_to = 388966af7aafSAndrei Emeltchenko le32_to_cpu(efs.flush_to); 389066af7aafSAndrei Emeltchenko } 38910a708f8fSGustavo F. Padovan break; 389266af7aafSAndrei Emeltchenko 38930a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 389447d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 38950a708f8fSGustavo F. Padovan } 38960a708f8fSGustavo F. Padovan } 38970a708f8fSGustavo F. Padovan 3898fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 3899dcf4adbfSJoe Perches req->flags = cpu_to_le16(0); 39000a708f8fSGustavo F. Padovan 39010a708f8fSGustavo F. Padovan return ptr - data; 39020a708f8fSGustavo F. Padovan } 39030a708f8fSGustavo F. Padovan 39042d792818SGustavo Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, 39052d792818SGustavo Padovan u16 result, u16 flags) 39060a708f8fSGustavo F. Padovan { 39070a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 39080a708f8fSGustavo F. Padovan void *ptr = rsp->data; 39090a708f8fSGustavo F. Padovan 3910fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan); 39110a708f8fSGustavo F. Padovan 3912fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 39130a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 39140a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags); 39150a708f8fSGustavo F. Padovan 39160a708f8fSGustavo F. Padovan return ptr - data; 39170a708f8fSGustavo F. Padovan } 39180a708f8fSGustavo F. Padovan 391927e2d4c8SJohan Hedberg void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan) 392027e2d4c8SJohan Hedberg { 392127e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 392227e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn; 392327e2d4c8SJohan Hedberg 392427e2d4c8SJohan Hedberg BT_DBG("chan %p", chan); 392527e2d4c8SJohan Hedberg 392627e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 392727e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 39283916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps); 39290cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits); 3930571f7390SMallikarjun Phulari rsp.result = cpu_to_le16(L2CAP_CR_LE_SUCCESS); 393127e2d4c8SJohan Hedberg 393227e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), 393327e2d4c8SJohan Hedberg &rsp); 393427e2d4c8SJohan Hedberg } 393527e2d4c8SJohan Hedberg 393615f02b91SLuiz Augusto von Dentz void __l2cap_ecred_conn_rsp_defer(struct l2cap_chan *chan) 393715f02b91SLuiz Augusto von Dentz { 393815f02b91SLuiz Augusto von Dentz struct { 393915f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp rsp; 394015f02b91SLuiz Augusto von Dentz __le16 dcid[5]; 394115f02b91SLuiz Augusto von Dentz } __packed pdu; 394215f02b91SLuiz Augusto von Dentz struct l2cap_conn *conn = chan->conn; 394315f02b91SLuiz Augusto von Dentz u16 ident = chan->ident; 394415f02b91SLuiz Augusto von Dentz int i = 0; 394515f02b91SLuiz Augusto von Dentz 394615f02b91SLuiz Augusto von Dentz if (!ident) 394715f02b91SLuiz Augusto von Dentz return; 394815f02b91SLuiz Augusto von Dentz 394915f02b91SLuiz Augusto von Dentz BT_DBG("chan %p ident %d", chan, ident); 395015f02b91SLuiz Augusto von Dentz 395115f02b91SLuiz Augusto von Dentz pdu.rsp.mtu = cpu_to_le16(chan->imtu); 395215f02b91SLuiz Augusto von Dentz pdu.rsp.mps = cpu_to_le16(chan->mps); 395315f02b91SLuiz Augusto von Dentz pdu.rsp.credits = cpu_to_le16(chan->rx_credits); 395415f02b91SLuiz Augusto von Dentz pdu.rsp.result = cpu_to_le16(L2CAP_CR_LE_SUCCESS); 395515f02b91SLuiz Augusto von Dentz 395615f02b91SLuiz Augusto von Dentz mutex_lock(&conn->chan_lock); 395715f02b91SLuiz Augusto von Dentz 395815f02b91SLuiz Augusto von Dentz list_for_each_entry(chan, &conn->chan_l, list) { 395915f02b91SLuiz Augusto von Dentz if (chan->ident != ident) 396015f02b91SLuiz Augusto von Dentz continue; 396115f02b91SLuiz Augusto von Dentz 396215f02b91SLuiz Augusto von Dentz /* Reset ident so only one response is sent */ 396315f02b91SLuiz Augusto von Dentz chan->ident = 0; 396415f02b91SLuiz Augusto von Dentz 396515f02b91SLuiz Augusto von Dentz /* Include all channels pending with the same ident */ 396615f02b91SLuiz Augusto von Dentz pdu.dcid[i++] = cpu_to_le16(chan->scid); 396715f02b91SLuiz Augusto von Dentz } 396815f02b91SLuiz Augusto von Dentz 396915f02b91SLuiz Augusto von Dentz mutex_unlock(&conn->chan_lock); 397015f02b91SLuiz Augusto von Dentz 397115f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, ident, L2CAP_ECRED_CONN_RSP, 397215f02b91SLuiz Augusto von Dentz sizeof(pdu.rsp) + i * sizeof(__le16), &pdu); 397315f02b91SLuiz Augusto von Dentz } 397415f02b91SLuiz Augusto von Dentz 39758c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) 3976710f9b0aSGustavo F. Padovan { 3977710f9b0aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 39788c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 3979710f9b0aSGustavo F. Padovan u8 buf[128]; 3980439f34acSAndrei Emeltchenko u8 rsp_code; 3981710f9b0aSGustavo F. Padovan 3982fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 3983fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3984dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 3985dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 3986439f34acSAndrei Emeltchenko 3987439f34acSAndrei Emeltchenko if (chan->hs_hcon) 3988439f34acSAndrei Emeltchenko rsp_code = L2CAP_CREATE_CHAN_RSP; 3989439f34acSAndrei Emeltchenko else 3990439f34acSAndrei Emeltchenko rsp_code = L2CAP_CONN_RSP; 3991439f34acSAndrei Emeltchenko 3992439f34acSAndrei Emeltchenko BT_DBG("chan %p rsp_code %u", chan, rsp_code); 3993439f34acSAndrei Emeltchenko 3994439f34acSAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp); 3995710f9b0aSGustavo F. Padovan 3996c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 3997710f9b0aSGustavo F. Padovan return; 3998710f9b0aSGustavo F. Padovan 3999710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 4000e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); 4001710f9b0aSGustavo F. Padovan chan->num_conf_req++; 4002710f9b0aSGustavo F. Padovan } 4003710f9b0aSGustavo F. Padovan 400447d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) 40050a708f8fSGustavo F. Padovan { 40060a708f8fSGustavo F. Padovan int type, olen; 40070a708f8fSGustavo F. Padovan unsigned long val; 4008c20f8e35SMat Martineau /* Use sane default values in case a misbehaving remote device 4009c20f8e35SMat Martineau * did not send an RFC or extended window size option. 4010c20f8e35SMat Martineau */ 4011c20f8e35SMat Martineau u16 txwin_ext = chan->ack_win; 4012c20f8e35SMat Martineau struct l2cap_conf_rfc rfc = { 4013c20f8e35SMat Martineau .mode = chan->mode, 4014dcf4adbfSJoe Perches .retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO), 4015dcf4adbfSJoe Perches .monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO), 4016c20f8e35SMat Martineau .max_pdu_size = cpu_to_le16(chan->imtu), 4017c20f8e35SMat Martineau .txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW), 4018c20f8e35SMat Martineau }; 40190a708f8fSGustavo F. Padovan 402047d1ec61SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); 40210a708f8fSGustavo F. Padovan 40220c1bc5c6SGustavo F. Padovan if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) 40230a708f8fSGustavo F. Padovan return; 40240a708f8fSGustavo F. Padovan 40250a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 40260a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 40277c9cbd0bSMarcel Holtmann if (len < 0) 40287c9cbd0bSMarcel Holtmann break; 40290a708f8fSGustavo F. Padovan 4030c20f8e35SMat Martineau switch (type) { 4031c20f8e35SMat Martineau case L2CAP_CONF_RFC: 4032af3d5d1cSMarcel Holtmann if (olen != sizeof(rfc)) 4033af3d5d1cSMarcel Holtmann break; 40340a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 4035c20f8e35SMat Martineau break; 4036c20f8e35SMat Martineau case L2CAP_CONF_EWS: 4037af3d5d1cSMarcel Holtmann if (olen != 2) 4038af3d5d1cSMarcel Holtmann break; 4039c20f8e35SMat Martineau txwin_ext = val; 4040c20f8e35SMat Martineau break; 4041c20f8e35SMat Martineau } 40420a708f8fSGustavo F. Padovan } 40430a708f8fSGustavo F. Padovan 40440a708f8fSGustavo F. Padovan switch (rfc.mode) { 40450a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 404647d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 404747d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 404847d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 4049c20f8e35SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 4050c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, txwin_ext); 4051c20f8e35SMat Martineau else 4052c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 4053c20f8e35SMat Martineau rfc.txwin_size); 40540a708f8fSGustavo F. Padovan break; 40550a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 405647d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 40570a708f8fSGustavo F. Padovan } 40580a708f8fSGustavo F. Padovan } 40590a708f8fSGustavo F. Padovan 40602d792818SGustavo Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, 4061cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4062cb3b3152SJohan Hedberg u8 *data) 40630a708f8fSGustavo F. Padovan { 4064e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 40650a708f8fSGustavo F. Padovan 4066cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rej)) 4067cb3b3152SJohan Hedberg return -EPROTO; 4068cb3b3152SJohan Hedberg 4069e2fd318eSIlia Kolomisnky if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) 40700a708f8fSGustavo F. Padovan return 0; 40710a708f8fSGustavo F. Padovan 40720a708f8fSGustavo F. Padovan if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && 40730a708f8fSGustavo F. Padovan cmd->ident == conn->info_ident) { 407417cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 40750a708f8fSGustavo F. Padovan 40760a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 40770a708f8fSGustavo F. Padovan conn->info_ident = 0; 40780a708f8fSGustavo F. Padovan 40790a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 40800a708f8fSGustavo F. Padovan } 40810a708f8fSGustavo F. Padovan 40820a708f8fSGustavo F. Padovan return 0; 40830a708f8fSGustavo F. Padovan } 40840a708f8fSGustavo F. Padovan 40851700915fSMat Martineau static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, 40861700915fSMat Martineau struct l2cap_cmd_hdr *cmd, 40874c89b6aaSMat Martineau u8 *data, u8 rsp_code, u8 amp_id) 40880a708f8fSGustavo F. Padovan { 40890a708f8fSGustavo F. Padovan struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 40900a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 409123691d75SGustavo F. Padovan struct l2cap_chan *chan = NULL, *pchan; 40920a708f8fSGustavo F. Padovan int result, status = L2CAP_CS_NO_INFO; 40930a708f8fSGustavo F. Padovan 40940a708f8fSGustavo F. Padovan u16 dcid = 0, scid = __le16_to_cpu(req->scid); 40950a708f8fSGustavo F. Padovan __le16 psm = req->psm; 40960a708f8fSGustavo F. Padovan 4097097db76cSAndrei Emeltchenko BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); 40980a708f8fSGustavo F. Padovan 40990a708f8fSGustavo F. Padovan /* Check if we have socket listening on psm */ 41006f59b904SMarcel Holtmann pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 4101bf20fd4eSJohan Hedberg &conn->hcon->dst, ACL_LINK); 410223691d75SGustavo F. Padovan if (!pchan) { 41030a708f8fSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 41040a708f8fSGustavo F. Padovan goto sendresp; 41050a708f8fSGustavo F. Padovan } 41060a708f8fSGustavo F. Padovan 41073df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 41088ffb9290SGustavo Padovan l2cap_chan_lock(pchan); 41090a708f8fSGustavo F. Padovan 41100a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */ 4111dcf4adbfSJoe Perches if (psm != cpu_to_le16(L2CAP_PSM_SDP) && 41120a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) { 41139f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_AUTH_FAILURE; 41140a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 41150a708f8fSGustavo F. Padovan goto response; 41160a708f8fSGustavo F. Padovan } 41170a708f8fSGustavo F. Padovan 41180a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM; 41190a708f8fSGustavo F. Padovan 4120dd1a8f8aSMallikarjun Phulari /* Check for valid dynamic CID range (as per Erratum 3253) */ 4121dd1a8f8aSMallikarjun Phulari if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_DYN_END) { 4122dd1a8f8aSMallikarjun Phulari result = L2CAP_CR_INVALID_SCID; 41232dfa1003SGustavo Padovan goto response; 4124dd1a8f8aSMallikarjun Phulari } 4125dd1a8f8aSMallikarjun Phulari 4126dd1a8f8aSMallikarjun Phulari /* Check if we already have channel with that dcid */ 4127dd1a8f8aSMallikarjun Phulari if (__l2cap_get_chan_by_dcid(conn, scid)) { 4128dd1a8f8aSMallikarjun Phulari result = L2CAP_CR_SCID_IN_USE; 4129dd1a8f8aSMallikarjun Phulari goto response; 4130dd1a8f8aSMallikarjun Phulari } 41312dfa1003SGustavo Padovan 413280b98027SGustavo Padovan chan = pchan->ops->new_connection(pchan); 413380808e43SGustavo F. Padovan if (!chan) 41340a708f8fSGustavo F. Padovan goto response; 41350a708f8fSGustavo F. Padovan 4136330b6c15SSyam Sidhardhan /* For certain devices (ex: HID mouse), support for authentication, 4137330b6c15SSyam Sidhardhan * pairing and bonding is optional. For such devices, inorder to avoid 4138330b6c15SSyam Sidhardhan * the ACL alive for too long after L2CAP disconnection, reset the ACL 4139330b6c15SSyam Sidhardhan * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect. 4140330b6c15SSyam Sidhardhan */ 4141330b6c15SSyam Sidhardhan conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 4142330b6c15SSyam Sidhardhan 41437eafc59eSMarcel Holtmann bacpy(&chan->src, &conn->hcon->src); 41447eafc59eSMarcel Holtmann bacpy(&chan->dst, &conn->hcon->dst); 4145a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(conn->hcon); 4146a250e048SJohan Hedberg chan->dst_type = bdaddr_dst_type(conn->hcon); 4147fe4128e0SGustavo F. Padovan chan->psm = psm; 4148fe4128e0SGustavo F. Padovan chan->dcid = scid; 41491700915fSMat Martineau chan->local_amp_id = amp_id; 41500a708f8fSGustavo F. Padovan 41516be36555SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 415248454079SGustavo F. Padovan 4153fe4128e0SGustavo F. Padovan dcid = chan->scid; 41540a708f8fSGustavo F. Padovan 41558d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 41560a708f8fSGustavo F. Padovan 4157fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident; 41580a708f8fSGustavo F. Padovan 41590a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { 4160e7cafc45SJohan Hedberg if (l2cap_chan_check_security(chan, false)) { 4161bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 4162f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 41630a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 41640a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND; 41652dc4e510SGustavo Padovan chan->ops->defer(chan); 41660a708f8fSGustavo F. Padovan } else { 41671700915fSMat Martineau /* Force pending result for AMP controllers. 41681700915fSMat Martineau * The connection will succeed after the 41691700915fSMat Martineau * physical link is up. 41701700915fSMat Martineau */ 41716ed971caSMarcel Holtmann if (amp_id == AMP_ID_BREDR) { 4172f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 41730a708f8fSGustavo F. Padovan result = L2CAP_CR_SUCCESS; 41746ed971caSMarcel Holtmann } else { 4175f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 41766ed971caSMarcel Holtmann result = L2CAP_CR_PEND; 41771700915fSMat Martineau } 41780a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 41790a708f8fSGustavo F. Padovan } 41800a708f8fSGustavo F. Padovan } else { 4181f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 41820a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 41830a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND; 41840a708f8fSGustavo F. Padovan } 41850a708f8fSGustavo F. Padovan } else { 4186f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 41870a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 41880a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 41890a708f8fSGustavo F. Padovan } 41900a708f8fSGustavo F. Padovan 41910a708f8fSGustavo F. Padovan response: 41928ffb9290SGustavo Padovan l2cap_chan_unlock(pchan); 41933df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4194a24cce14SJohan Hedberg l2cap_chan_put(pchan); 41950a708f8fSGustavo F. Padovan 41960a708f8fSGustavo F. Padovan sendresp: 41970a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid); 41980a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid); 41990a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result); 42000a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status); 42014c89b6aaSMat Martineau l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp); 42020a708f8fSGustavo F. Padovan 42030a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { 42040a708f8fSGustavo F. Padovan struct l2cap_info_req info; 4205dcf4adbfSJoe Perches info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 42060a708f8fSGustavo F. Padovan 42070a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 42080a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 42090a708f8fSGustavo F. Padovan 4210ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 42110a708f8fSGustavo F. Padovan 42122d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, 42132d792818SGustavo Padovan sizeof(info), &info); 42140a708f8fSGustavo F. Padovan } 42150a708f8fSGustavo F. Padovan 4216c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && 42170a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) { 42180a708f8fSGustavo F. Padovan u8 buf[128]; 4219c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 42200a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 4221e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); 422273ffa904SGustavo F. Padovan chan->num_conf_req++; 42230a708f8fSGustavo F. Padovan } 42241700915fSMat Martineau 42251700915fSMat Martineau return chan; 42264c89b6aaSMat Martineau } 42270a708f8fSGustavo F. Padovan 42284c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn, 4229cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 42304c89b6aaSMat Martineau { 42317b064edaSJaganath Kanakkassery struct hci_dev *hdev = conn->hcon->hdev; 42327b064edaSJaganath Kanakkassery struct hci_conn *hcon = conn->hcon; 42337b064edaSJaganath Kanakkassery 4234cb3b3152SJohan Hedberg if (cmd_len < sizeof(struct l2cap_conn_req)) 4235cb3b3152SJohan Hedberg return -EPROTO; 4236cb3b3152SJohan Hedberg 42377b064edaSJaganath Kanakkassery hci_dev_lock(hdev); 4238d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_MGMT) && 42397b064edaSJaganath Kanakkassery !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags)) 424048ec92faSAlfonso Acosta mgmt_device_connected(hdev, hcon, 0, NULL, 0); 42417b064edaSJaganath Kanakkassery hci_dev_unlock(hdev); 42427b064edaSJaganath Kanakkassery 4243300229f9SGustavo Padovan l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0); 42440a708f8fSGustavo F. Padovan return 0; 42450a708f8fSGustavo F. Padovan } 42460a708f8fSGustavo F. Padovan 42475909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn, 4248cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4249cb3b3152SJohan Hedberg u8 *data) 42500a708f8fSGustavo F. Padovan { 42510a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; 42520a708f8fSGustavo F. Padovan u16 scid, dcid, result, status; 425348454079SGustavo F. Padovan struct l2cap_chan *chan; 42540a708f8fSGustavo F. Padovan u8 req[128]; 42553df91ea2SAndrei Emeltchenko int err; 42560a708f8fSGustavo F. Padovan 4257cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp)) 4258cb3b3152SJohan Hedberg return -EPROTO; 4259cb3b3152SJohan Hedberg 42600a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 42610a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 42620a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 42630a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status); 42640a708f8fSGustavo F. Padovan 42651b009c98SAndrei Emeltchenko BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", 42661b009c98SAndrei Emeltchenko dcid, scid, result, status); 42670a708f8fSGustavo F. Padovan 42683df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 42693df91ea2SAndrei Emeltchenko 42700a708f8fSGustavo F. Padovan if (scid) { 42713df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 42723df91ea2SAndrei Emeltchenko if (!chan) { 427321870b52SJohan Hedberg err = -EBADSLT; 42743df91ea2SAndrei Emeltchenko goto unlock; 42753df91ea2SAndrei Emeltchenko } 42760a708f8fSGustavo F. Padovan } else { 42773df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 42783df91ea2SAndrei Emeltchenko if (!chan) { 427921870b52SJohan Hedberg err = -EBADSLT; 42803df91ea2SAndrei Emeltchenko goto unlock; 42813df91ea2SAndrei Emeltchenko } 42820a708f8fSGustavo F. Padovan } 42830a708f8fSGustavo F. Padovan 42843df91ea2SAndrei Emeltchenko err = 0; 42853df91ea2SAndrei Emeltchenko 42866be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 428748454079SGustavo F. Padovan 42880a708f8fSGustavo F. Padovan switch (result) { 42890a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS: 429089bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 4291fc7f8a7eSGustavo F. Padovan chan->ident = 0; 4292fe4128e0SGustavo F. Padovan chan->dcid = dcid; 4293c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state); 42940a708f8fSGustavo F. Padovan 4295c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 42960a708f8fSGustavo F. Padovan break; 42970a708f8fSGustavo F. Padovan 42980a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 4299e860d2c9SBen Seri l2cap_build_conf_req(chan, req, sizeof(req)), req); 430073ffa904SGustavo F. Padovan chan->num_conf_req++; 43010a708f8fSGustavo F. Padovan break; 43020a708f8fSGustavo F. Padovan 43030a708f8fSGustavo F. Padovan case L2CAP_CR_PEND: 4304c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 43050a708f8fSGustavo F. Padovan break; 43060a708f8fSGustavo F. Padovan 43070a708f8fSGustavo F. Padovan default: 430848454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED); 43090a708f8fSGustavo F. Padovan break; 43100a708f8fSGustavo F. Padovan } 43110a708f8fSGustavo F. Padovan 43126be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 43133df91ea2SAndrei Emeltchenko 43143df91ea2SAndrei Emeltchenko unlock: 43153df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 43163df91ea2SAndrei Emeltchenko 43173df91ea2SAndrei Emeltchenko return err; 43180a708f8fSGustavo F. Padovan } 43190a708f8fSGustavo F. Padovan 432047d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan) 43210a708f8fSGustavo F. Padovan { 43220a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both 43230a708f8fSGustavo F. Padovan * sides request it. 43240a708f8fSGustavo F. Padovan */ 43250c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) 432647d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 4327f2592d3eSAndrei Emeltchenko else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) 432847d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16; 43290a708f8fSGustavo F. Padovan } 43300a708f8fSGustavo F. Padovan 433129d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data, 433229d8a590SAndrei Emeltchenko u8 ident, u16 flags) 433329d8a590SAndrei Emeltchenko { 433429d8a590SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 433529d8a590SAndrei Emeltchenko 433629d8a590SAndrei Emeltchenko BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident, 433729d8a590SAndrei Emeltchenko flags); 433829d8a590SAndrei Emeltchenko 433929d8a590SAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 434029d8a590SAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 434129d8a590SAndrei Emeltchenko 434229d8a590SAndrei Emeltchenko l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP, 434329d8a590SAndrei Emeltchenko l2cap_build_conf_rsp(chan, data, 434429d8a590SAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), data); 434529d8a590SAndrei Emeltchenko } 434629d8a590SAndrei Emeltchenko 4347662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident, 4348662d652dSJohan Hedberg u16 scid, u16 dcid) 4349662d652dSJohan Hedberg { 4350662d652dSJohan Hedberg struct l2cap_cmd_rej_cid rej; 4351662d652dSJohan Hedberg 4352dcf4adbfSJoe Perches rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID); 4353662d652dSJohan Hedberg rej.scid = __cpu_to_le16(scid); 4354662d652dSJohan Hedberg rej.dcid = __cpu_to_le16(dcid); 4355662d652dSJohan Hedberg 4356662d652dSJohan Hedberg l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); 4357662d652dSJohan Hedberg } 4358662d652dSJohan Hedberg 43592d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, 43602d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len, 43612d792818SGustavo Padovan u8 *data) 43620a708f8fSGustavo F. Padovan { 43630a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; 43640a708f8fSGustavo F. Padovan u16 dcid, flags; 43650a708f8fSGustavo F. Padovan u8 rsp[64]; 436648454079SGustavo F. Padovan struct l2cap_chan *chan; 43673c588192SMat Martineau int len, err = 0; 43680a708f8fSGustavo F. Padovan 4369cb3b3152SJohan Hedberg if (cmd_len < sizeof(*req)) 4370cb3b3152SJohan Hedberg return -EPROTO; 4371cb3b3152SJohan Hedberg 43720a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 43730a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags); 43740a708f8fSGustavo F. Padovan 43750a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); 43760a708f8fSGustavo F. Padovan 4377baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid); 4378662d652dSJohan Hedberg if (!chan) { 4379662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0); 4380662d652dSJohan Hedberg return 0; 4381662d652dSJohan Hedberg } 43820a708f8fSGustavo F. Padovan 438396298f64SHoward Chung if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2 && 438496298f64SHoward Chung chan->state != BT_CONNECTED) { 4385662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, 4386662d652dSJohan Hedberg chan->dcid); 43870a708f8fSGustavo F. Padovan goto unlock; 43880a708f8fSGustavo F. Padovan } 43890a708f8fSGustavo F. Padovan 43900a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */ 43910a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req); 4392cb3b3152SJohan Hedberg if (chan->conf_len + len > sizeof(chan->conf_req)) { 43930a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 4394fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 43950a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp); 43960a708f8fSGustavo F. Padovan goto unlock; 43970a708f8fSGustavo F. Padovan } 43980a708f8fSGustavo F. Padovan 43990a708f8fSGustavo F. Padovan /* Store config. */ 440073ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len); 440173ffa904SGustavo F. Padovan chan->conf_len += len; 44020a708f8fSGustavo F. Padovan 440359e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) { 44040a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */ 44050a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 4406fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 44075325e5bbSAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), rsp); 44080a708f8fSGustavo F. Padovan goto unlock; 44090a708f8fSGustavo F. Padovan } 44100a708f8fSGustavo F. Padovan 44110a708f8fSGustavo F. Padovan /* Complete config. */ 4412e860d2c9SBen Seri len = l2cap_parse_conf_req(chan, rsp, sizeof(rsp)); 44130a708f8fSGustavo F. Padovan if (len < 0) { 44145e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 44150a708f8fSGustavo F. Padovan goto unlock; 44160a708f8fSGustavo F. Padovan } 44170a708f8fSGustavo F. Padovan 44181500109bSMat Martineau chan->ident = cmd->ident; 44190a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); 442073ffa904SGustavo F. Padovan chan->num_conf_rsp++; 44210a708f8fSGustavo F. Padovan 44220a708f8fSGustavo F. Padovan /* Reset config buffer. */ 442373ffa904SGustavo F. Padovan chan->conf_len = 0; 44240a708f8fSGustavo F. Padovan 4425c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) 44260a708f8fSGustavo F. Padovan goto unlock; 44270a708f8fSGustavo F. Padovan 4428c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 442947d1ec61SGustavo F. Padovan set_default_fcs(chan); 44300a708f8fSGustavo F. Padovan 4431105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 4432105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 44333c588192SMat Martineau err = l2cap_ertm_init(chan); 44340a708f8fSGustavo F. Padovan 44353c588192SMat Martineau if (err < 0) 44365e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 44373c588192SMat Martineau else 4438cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 44393c588192SMat Martineau 44400a708f8fSGustavo F. Padovan goto unlock; 44410a708f8fSGustavo F. Padovan } 44420a708f8fSGustavo F. Padovan 4443c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { 44440a708f8fSGustavo F. Padovan u8 buf[64]; 44450a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 4446e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); 444773ffa904SGustavo F. Padovan chan->num_conf_req++; 44480a708f8fSGustavo F. Padovan } 44490a708f8fSGustavo F. Padovan 445049c922bbSStephen Hemminger /* Got Conf Rsp PENDING from remote side and assume we sent 44510e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */ 44520e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && 44530e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 44540e8b207eSAndrei Emeltchenko 44550e8b207eSAndrei Emeltchenko /* check compatibility */ 44560e8b207eSAndrei Emeltchenko 445779de886dSAndrei Emeltchenko /* Send rsp for BR/EDR channel */ 4458f351bc72SAndrei Emeltchenko if (!chan->hs_hcon) 445929d8a590SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags); 446079de886dSAndrei Emeltchenko else 446179de886dSAndrei Emeltchenko chan->ident = cmd->ident; 44620e8b207eSAndrei Emeltchenko } 44630e8b207eSAndrei Emeltchenko 44640a708f8fSGustavo F. Padovan unlock: 44656be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 44663c588192SMat Martineau return err; 44670a708f8fSGustavo F. Padovan } 44680a708f8fSGustavo F. Padovan 44692d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, 4470cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4471cb3b3152SJohan Hedberg u8 *data) 44720a708f8fSGustavo F. Padovan { 44730a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; 44740a708f8fSGustavo F. Padovan u16 scid, flags, result; 447548454079SGustavo F. Padovan struct l2cap_chan *chan; 4476cb3b3152SJohan Hedberg int len = cmd_len - sizeof(*rsp); 44773c588192SMat Martineau int err = 0; 44780a708f8fSGustavo F. Padovan 4479cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp)) 4480cb3b3152SJohan Hedberg return -EPROTO; 4481cb3b3152SJohan Hedberg 44820a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 44830a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags); 44840a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 44850a708f8fSGustavo F. Padovan 448661386cbaSAndrei Emeltchenko BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags, 448761386cbaSAndrei Emeltchenko result, len); 44880a708f8fSGustavo F. Padovan 4489baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 449048454079SGustavo F. Padovan if (!chan) 44910a708f8fSGustavo F. Padovan return 0; 44920a708f8fSGustavo F. Padovan 44930a708f8fSGustavo F. Padovan switch (result) { 44940a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS: 449547d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len); 44960e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state); 44970a708f8fSGustavo F. Padovan break; 44980a708f8fSGustavo F. Padovan 44990e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING: 45000e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state); 45010e8b207eSAndrei Emeltchenko 45020e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 45030e8b207eSAndrei Emeltchenko char buf[64]; 45040e8b207eSAndrei Emeltchenko 45050e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len, 4506e860d2c9SBen Seri buf, sizeof(buf), &result); 45070e8b207eSAndrei Emeltchenko if (len < 0) { 45085e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 45090e8b207eSAndrei Emeltchenko goto done; 45100e8b207eSAndrei Emeltchenko } 45110e8b207eSAndrei Emeltchenko 4512f351bc72SAndrei Emeltchenko if (!chan->hs_hcon) { 451379de886dSAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, buf, cmd->ident, 451479de886dSAndrei Emeltchenko 0); 45155ce66b59SAndrei Emeltchenko } else { 45165ce66b59SAndrei Emeltchenko if (l2cap_check_efs(chan)) { 45175ce66b59SAndrei Emeltchenko amp_create_logical_link(chan); 451879de886dSAndrei Emeltchenko chan->ident = cmd->ident; 45190e8b207eSAndrei Emeltchenko } 45205ce66b59SAndrei Emeltchenko } 45215ce66b59SAndrei Emeltchenko } 45220e8b207eSAndrei Emeltchenko goto done; 45230e8b207eSAndrei Emeltchenko 452498d2c3e1SBastien Nocera case L2CAP_CONF_UNKNOWN: 45250a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT: 452673ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { 45270a708f8fSGustavo F. Padovan char req[64]; 45280a708f8fSGustavo F. Padovan 45290a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { 45305e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 45310a708f8fSGustavo F. Padovan goto done; 45320a708f8fSGustavo F. Padovan } 45330a708f8fSGustavo F. Padovan 45340a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */ 45350a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS; 4536b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len, 4537e860d2c9SBen Seri req, sizeof(req), &result); 45380a708f8fSGustavo F. Padovan if (len < 0) { 45395e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 45400a708f8fSGustavo F. Padovan goto done; 45410a708f8fSGustavo F. Padovan } 45420a708f8fSGustavo F. Padovan 45430a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 45440a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req); 454573ffa904SGustavo F. Padovan chan->num_conf_req++; 45460a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS) 45470a708f8fSGustavo F. Padovan goto done; 45480a708f8fSGustavo F. Padovan break; 45490a708f8fSGustavo F. Padovan } 455019186c7bSGustavo A. R. Silva fallthrough; 45510a708f8fSGustavo F. Padovan 45520a708f8fSGustavo F. Padovan default: 45536be36555SAndrei Emeltchenko l2cap_chan_set_err(chan, ECONNRESET); 45542e0052e4SAndrei Emeltchenko 4555ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); 45565e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 45570a708f8fSGustavo F. Padovan goto done; 45580a708f8fSGustavo F. Padovan } 45590a708f8fSGustavo F. Padovan 456059e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) 45610a708f8fSGustavo F. Padovan goto done; 45620a708f8fSGustavo F. Padovan 4563c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state); 45640a708f8fSGustavo F. Padovan 4565c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { 456647d1ec61SGustavo F. Padovan set_default_fcs(chan); 45670a708f8fSGustavo F. Padovan 4568105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 4569105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 45703c588192SMat Martineau err = l2cap_ertm_init(chan); 45710a708f8fSGustavo F. Padovan 45723c588192SMat Martineau if (err < 0) 45735e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 45743c588192SMat Martineau else 4575cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 45760a708f8fSGustavo F. Padovan } 45770a708f8fSGustavo F. Padovan 45780a708f8fSGustavo F. Padovan done: 45796be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 45803c588192SMat Martineau return err; 45810a708f8fSGustavo F. Padovan } 45820a708f8fSGustavo F. Padovan 45832d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, 4584cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4585cb3b3152SJohan Hedberg u8 *data) 45860a708f8fSGustavo F. Padovan { 45870a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; 45880a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp; 45890a708f8fSGustavo F. Padovan u16 dcid, scid; 459048454079SGustavo F. Padovan struct l2cap_chan *chan; 45910a708f8fSGustavo F. Padovan 4592cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req)) 4593cb3b3152SJohan Hedberg return -EPROTO; 4594cb3b3152SJohan Hedberg 45950a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid); 45960a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 45970a708f8fSGustavo F. Padovan 45980a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); 45990a708f8fSGustavo F. Padovan 46003df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 46013df91ea2SAndrei Emeltchenko 46023df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, dcid); 46033df91ea2SAndrei Emeltchenko if (!chan) { 46043df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4605662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid); 4606662d652dSJohan Hedberg return 0; 46073df91ea2SAndrei Emeltchenko } 46080a708f8fSGustavo F. Padovan 46096c08fc89SManish Mandlik l2cap_chan_hold(chan); 46106be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 46116be36555SAndrei Emeltchenko 4612fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 4613fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 46140a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); 46150a708f8fSGustavo F. Padovan 46165ec1bbe5SGustavo Padovan chan->ops->set_shutdown(chan); 46170a708f8fSGustavo F. Padovan 461848454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET); 46196be36555SAndrei Emeltchenko 462080b98027SGustavo Padovan chan->ops->close(chan); 46216c08fc89SManish Mandlik 46226c08fc89SManish Mandlik l2cap_chan_unlock(chan); 462361d6ef3eSMat Martineau l2cap_chan_put(chan); 46243df91ea2SAndrei Emeltchenko 46253df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 46263df91ea2SAndrei Emeltchenko 46270a708f8fSGustavo F. Padovan return 0; 46280a708f8fSGustavo F. Padovan } 46290a708f8fSGustavo F. Padovan 46302d792818SGustavo Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, 4631cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4632cb3b3152SJohan Hedberg u8 *data) 46330a708f8fSGustavo F. Padovan { 46340a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; 46350a708f8fSGustavo F. Padovan u16 dcid, scid; 463648454079SGustavo F. Padovan struct l2cap_chan *chan; 46370a708f8fSGustavo F. Padovan 4638cb3b3152SJohan Hedberg if (cmd_len != sizeof(*rsp)) 4639cb3b3152SJohan Hedberg return -EPROTO; 4640cb3b3152SJohan Hedberg 46410a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 46420a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 46430a708f8fSGustavo F. Padovan 46440a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); 46450a708f8fSGustavo F. Padovan 46463df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 46473df91ea2SAndrei Emeltchenko 46483df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 46493df91ea2SAndrei Emeltchenko if (!chan) { 46503df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 46510a708f8fSGustavo F. Padovan return 0; 46523df91ea2SAndrei Emeltchenko } 46530a708f8fSGustavo F. Padovan 46546c08fc89SManish Mandlik l2cap_chan_hold(chan); 46556be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 465648454079SGustavo F. Padovan 465728261da8SMatias Karhumaa if (chan->state != BT_DISCONN) { 465828261da8SMatias Karhumaa l2cap_chan_unlock(chan); 46596c08fc89SManish Mandlik l2cap_chan_put(chan); 466028261da8SMatias Karhumaa mutex_unlock(&conn->chan_lock); 466128261da8SMatias Karhumaa return 0; 466228261da8SMatias Karhumaa } 466328261da8SMatias Karhumaa 466448454079SGustavo F. Padovan l2cap_chan_del(chan, 0); 46656be36555SAndrei Emeltchenko 466680b98027SGustavo Padovan chan->ops->close(chan); 46676c08fc89SManish Mandlik 46686c08fc89SManish Mandlik l2cap_chan_unlock(chan); 466961d6ef3eSMat Martineau l2cap_chan_put(chan); 46703df91ea2SAndrei Emeltchenko 46713df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 46723df91ea2SAndrei Emeltchenko 46730a708f8fSGustavo F. Padovan return 0; 46740a708f8fSGustavo F. Padovan } 46750a708f8fSGustavo F. Padovan 46762d792818SGustavo Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, 4677cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4678cb3b3152SJohan Hedberg u8 *data) 46790a708f8fSGustavo F. Padovan { 46800a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data; 46810a708f8fSGustavo F. Padovan u16 type; 46820a708f8fSGustavo F. Padovan 4683cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req)) 4684cb3b3152SJohan Hedberg return -EPROTO; 4685cb3b3152SJohan Hedberg 46860a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type); 46870a708f8fSGustavo F. Padovan 46880a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type); 46890a708f8fSGustavo F. Padovan 46900a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) { 46910a708f8fSGustavo F. Padovan u8 buf[8]; 46920a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask; 46930a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 4694dcf4adbfSJoe Perches rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 4695dcf4adbfSJoe Perches rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 46960a708f8fSGustavo F. Padovan if (!disable_ertm) 46970a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING 46980a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS; 46990bd49fc7SJohan Hedberg if (conn->local_fixed_chan & L2CAP_FC_A2MP) 47006327eb98SAndrei Emeltchenko feat_mask |= L2CAP_FEAT_EXT_FLOW 47016327eb98SAndrei Emeltchenko | L2CAP_FEAT_EXT_WINDOW; 4702a5fd6f30SAndrei Emeltchenko 47030a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data); 47042d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), 47052d792818SGustavo Padovan buf); 47060a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) { 47070a708f8fSGustavo F. Padovan u8 buf[12]; 47080a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 470950a147cdSMat Martineau 4710dcf4adbfSJoe Perches rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 4711dcf4adbfSJoe Perches rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 47120bd49fc7SJohan Hedberg rsp->data[0] = conn->local_fixed_chan; 47130bd49fc7SJohan Hedberg memset(rsp->data + 1, 0, 7); 47142d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), 47152d792818SGustavo Padovan buf); 47160a708f8fSGustavo F. Padovan } else { 47170a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp; 47180a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type); 4719dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP); 47202d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), 47212d792818SGustavo Padovan &rsp); 47220a708f8fSGustavo F. Padovan } 47230a708f8fSGustavo F. Padovan 47240a708f8fSGustavo F. Padovan return 0; 47250a708f8fSGustavo F. Padovan } 47260a708f8fSGustavo F. Padovan 47272d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, 4728cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4729cb3b3152SJohan Hedberg u8 *data) 47300a708f8fSGustavo F. Padovan { 47310a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; 47320a708f8fSGustavo F. Padovan u16 type, result; 47330a708f8fSGustavo F. Padovan 47343f6fa3d4SJaganath Kanakkassery if (cmd_len < sizeof(*rsp)) 4735cb3b3152SJohan Hedberg return -EPROTO; 4736cb3b3152SJohan Hedberg 47370a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type); 47380a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 47390a708f8fSGustavo F. Padovan 47400a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); 47410a708f8fSGustavo F. Padovan 4742e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */ 4743e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident || 4744e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 4745e90165beSAndrei Emeltchenko return 0; 4746e90165beSAndrei Emeltchenko 474717cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 47480a708f8fSGustavo F. Padovan 47490a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) { 47500a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 47510a708f8fSGustavo F. Padovan conn->info_ident = 0; 47520a708f8fSGustavo F. Padovan 47530a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 47540a708f8fSGustavo F. Padovan 47550a708f8fSGustavo F. Padovan return 0; 47560a708f8fSGustavo F. Padovan } 47570a708f8fSGustavo F. Padovan 4758978c93b9SAndrei Emeltchenko switch (type) { 4759978c93b9SAndrei Emeltchenko case L2CAP_IT_FEAT_MASK: 47600a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data); 47610a708f8fSGustavo F. Padovan 47620a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { 47630a708f8fSGustavo F. Padovan struct l2cap_info_req req; 4764dcf4adbfSJoe Perches req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 47650a708f8fSGustavo F. Padovan 47660a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 47670a708f8fSGustavo F. Padovan 47680a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 47690a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 47700a708f8fSGustavo F. Padovan } else { 47710a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 47720a708f8fSGustavo F. Padovan conn->info_ident = 0; 47730a708f8fSGustavo F. Padovan 47740a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 47750a708f8fSGustavo F. Padovan } 4776978c93b9SAndrei Emeltchenko break; 4777978c93b9SAndrei Emeltchenko 4778978c93b9SAndrei Emeltchenko case L2CAP_IT_FIXED_CHAN: 47790bd49fc7SJohan Hedberg conn->remote_fixed_chan = rsp->data[0]; 47800a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 47810a708f8fSGustavo F. Padovan conn->info_ident = 0; 47820a708f8fSGustavo F. Padovan 47830a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 4784978c93b9SAndrei Emeltchenko break; 47850a708f8fSGustavo F. Padovan } 47860a708f8fSGustavo F. Padovan 47870a708f8fSGustavo F. Padovan return 0; 47880a708f8fSGustavo F. Padovan } 47890a708f8fSGustavo F. Padovan 47901700915fSMat Martineau static int l2cap_create_channel_req(struct l2cap_conn *conn, 47912d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, 47922d792818SGustavo Padovan u16 cmd_len, void *data) 4793f94ff6ffSMat Martineau { 4794f94ff6ffSMat Martineau struct l2cap_create_chan_req *req = data; 47956e1df6a6SAndrei Emeltchenko struct l2cap_create_chan_rsp rsp; 47961700915fSMat Martineau struct l2cap_chan *chan; 47976e1df6a6SAndrei Emeltchenko struct hci_dev *hdev; 4798f94ff6ffSMat Martineau u16 psm, scid; 4799f94ff6ffSMat Martineau 4800f94ff6ffSMat Martineau if (cmd_len != sizeof(*req)) 4801f94ff6ffSMat Martineau return -EPROTO; 4802f94ff6ffSMat Martineau 48030bd49fc7SJohan Hedberg if (!(conn->local_fixed_chan & L2CAP_FC_A2MP)) 4804f94ff6ffSMat Martineau return -EINVAL; 4805f94ff6ffSMat Martineau 4806f94ff6ffSMat Martineau psm = le16_to_cpu(req->psm); 4807f94ff6ffSMat Martineau scid = le16_to_cpu(req->scid); 4808f94ff6ffSMat Martineau 4809ad0ac6caSAndrei Emeltchenko BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id); 4810f94ff6ffSMat Martineau 48116e1df6a6SAndrei Emeltchenko /* For controller id 0 make BR/EDR connection */ 48126ed971caSMarcel Holtmann if (req->amp_id == AMP_ID_BREDR) { 48136e1df6a6SAndrei Emeltchenko l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, 48146e1df6a6SAndrei Emeltchenko req->amp_id); 48156e1df6a6SAndrei Emeltchenko return 0; 48166e1df6a6SAndrei Emeltchenko } 48171700915fSMat Martineau 48181700915fSMat Martineau /* Validate AMP controller id */ 48191700915fSMat Martineau hdev = hci_dev_get(req->amp_id); 48206e1df6a6SAndrei Emeltchenko if (!hdev) 48216e1df6a6SAndrei Emeltchenko goto error; 48221700915fSMat Martineau 48236e1df6a6SAndrei Emeltchenko if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) { 48246e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 48256e1df6a6SAndrei Emeltchenko goto error; 48266e1df6a6SAndrei Emeltchenko } 48276e1df6a6SAndrei Emeltchenko 48286e1df6a6SAndrei Emeltchenko chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, 48296e1df6a6SAndrei Emeltchenko req->amp_id); 48306e1df6a6SAndrei Emeltchenko if (chan) { 48316e1df6a6SAndrei Emeltchenko struct amp_mgr *mgr = conn->hcon->amp_mgr; 48326e1df6a6SAndrei Emeltchenko struct hci_conn *hs_hcon; 48336e1df6a6SAndrei Emeltchenko 483498e0f7eaSMarcel Holtmann hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, 483598e0f7eaSMarcel Holtmann &conn->hcon->dst); 48366e1df6a6SAndrei Emeltchenko if (!hs_hcon) { 48376e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 4838662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, 4839662d652dSJohan Hedberg chan->dcid); 4840662d652dSJohan Hedberg return 0; 48416e1df6a6SAndrei Emeltchenko } 48426e1df6a6SAndrei Emeltchenko 48436e1df6a6SAndrei Emeltchenko BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon); 48446e1df6a6SAndrei Emeltchenko 48456e1df6a6SAndrei Emeltchenko mgr->bredr_chan = chan; 48466e1df6a6SAndrei Emeltchenko chan->hs_hcon = hs_hcon; 4847fd45bf4cSAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 48486e1df6a6SAndrei Emeltchenko conn->mtu = hdev->block_mtu; 48496e1df6a6SAndrei Emeltchenko } 48506e1df6a6SAndrei Emeltchenko 48516e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 48526e1df6a6SAndrei Emeltchenko 48536e1df6a6SAndrei Emeltchenko return 0; 48546e1df6a6SAndrei Emeltchenko 48556e1df6a6SAndrei Emeltchenko error: 4856f94ff6ffSMat Martineau rsp.dcid = 0; 4857f94ff6ffSMat Martineau rsp.scid = cpu_to_le16(scid); 4858dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_BAD_AMP); 4859dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 4860f94ff6ffSMat Martineau 4861f94ff6ffSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, 4862f94ff6ffSMat Martineau sizeof(rsp), &rsp); 4863f94ff6ffSMat Martineau 4864dc280801SJohan Hedberg return 0; 4865f94ff6ffSMat Martineau } 4866f94ff6ffSMat Martineau 48678eb200bdSMat Martineau static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id) 48688eb200bdSMat Martineau { 48698eb200bdSMat Martineau struct l2cap_move_chan_req req; 48708eb200bdSMat Martineau u8 ident; 48718eb200bdSMat Martineau 48728eb200bdSMat Martineau BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id); 48738eb200bdSMat Martineau 48748eb200bdSMat Martineau ident = l2cap_get_ident(chan->conn); 48758eb200bdSMat Martineau chan->ident = ident; 48768eb200bdSMat Martineau 48778eb200bdSMat Martineau req.icid = cpu_to_le16(chan->scid); 48788eb200bdSMat Martineau req.dest_amp_id = dest_amp_id; 48798eb200bdSMat Martineau 48808eb200bdSMat Martineau l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req), 48818eb200bdSMat Martineau &req); 48828eb200bdSMat Martineau 48838eb200bdSMat Martineau __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); 48848eb200bdSMat Martineau } 48858eb200bdSMat Martineau 48861500109bSMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result) 48878d5a04a1SMat Martineau { 48888d5a04a1SMat Martineau struct l2cap_move_chan_rsp rsp; 48898d5a04a1SMat Martineau 48901500109bSMat Martineau BT_DBG("chan %p, result 0x%4.4x", chan, result); 48918d5a04a1SMat Martineau 48921500109bSMat Martineau rsp.icid = cpu_to_le16(chan->dcid); 48938d5a04a1SMat Martineau rsp.result = cpu_to_le16(result); 48948d5a04a1SMat Martineau 48951500109bSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP, 48961500109bSMat Martineau sizeof(rsp), &rsp); 48978d5a04a1SMat Martineau } 48988d5a04a1SMat Martineau 48995b155ef9SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result) 49008d5a04a1SMat Martineau { 49018d5a04a1SMat Martineau struct l2cap_move_chan_cfm cfm; 49028d5a04a1SMat Martineau 49035b155ef9SMat Martineau BT_DBG("chan %p, result 0x%4.4x", chan, result); 49048d5a04a1SMat Martineau 49055b155ef9SMat Martineau chan->ident = l2cap_get_ident(chan->conn); 49068d5a04a1SMat Martineau 49075b155ef9SMat Martineau cfm.icid = cpu_to_le16(chan->scid); 49088d5a04a1SMat Martineau cfm.result = cpu_to_le16(result); 49098d5a04a1SMat Martineau 49105b155ef9SMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM, 49115b155ef9SMat Martineau sizeof(cfm), &cfm); 49125b155ef9SMat Martineau 49135b155ef9SMat Martineau __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); 49145b155ef9SMat Martineau } 49155b155ef9SMat Martineau 49165b155ef9SMat Martineau static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid) 49175b155ef9SMat Martineau { 49185b155ef9SMat Martineau struct l2cap_move_chan_cfm cfm; 49195b155ef9SMat Martineau 49205b155ef9SMat Martineau BT_DBG("conn %p, icid 0x%4.4x", conn, icid); 49215b155ef9SMat Martineau 49225b155ef9SMat Martineau cfm.icid = cpu_to_le16(icid); 4923dcf4adbfSJoe Perches cfm.result = cpu_to_le16(L2CAP_MC_UNCONFIRMED); 49245b155ef9SMat Martineau 49255b155ef9SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM, 49265b155ef9SMat Martineau sizeof(cfm), &cfm); 49278d5a04a1SMat Martineau } 49288d5a04a1SMat Martineau 49298d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, 49308d5a04a1SMat Martineau u16 icid) 49318d5a04a1SMat Martineau { 49328d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp rsp; 49338d5a04a1SMat Martineau 4934ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 49358d5a04a1SMat Martineau 49368d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 49378d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp); 49388d5a04a1SMat Martineau } 49398d5a04a1SMat Martineau 49405f3847a4SMat Martineau static void __release_logical_link(struct l2cap_chan *chan) 49415f3847a4SMat Martineau { 49425f3847a4SMat Martineau chan->hs_hchan = NULL; 49435f3847a4SMat Martineau chan->hs_hcon = NULL; 49445f3847a4SMat Martineau 49455f3847a4SMat Martineau /* Placeholder - release the logical link */ 49465f3847a4SMat Martineau } 49475f3847a4SMat Martineau 49481500109bSMat Martineau static void l2cap_logical_fail(struct l2cap_chan *chan) 49491500109bSMat Martineau { 49501500109bSMat Martineau /* Logical link setup failed */ 49511500109bSMat Martineau if (chan->state != BT_CONNECTED) { 49521500109bSMat Martineau /* Create channel failure, disconnect */ 49535e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 49541500109bSMat Martineau return; 49551500109bSMat Martineau } 49561500109bSMat Martineau 49571500109bSMat Martineau switch (chan->move_role) { 49581500109bSMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 49591500109bSMat Martineau l2cap_move_done(chan); 49601500109bSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP); 49611500109bSMat Martineau break; 49621500109bSMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 49631500109bSMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP || 49641500109bSMat Martineau chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) { 49651500109bSMat Martineau /* Remote has only sent pending or 49661500109bSMat Martineau * success responses, clean up 49671500109bSMat Martineau */ 49681500109bSMat Martineau l2cap_move_done(chan); 49691500109bSMat Martineau } 49701500109bSMat Martineau 49711500109bSMat Martineau /* Other amp move states imply that the move 49721500109bSMat Martineau * has already aborted 49731500109bSMat Martineau */ 49741500109bSMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 49751500109bSMat Martineau break; 49761500109bSMat Martineau } 49771500109bSMat Martineau } 49781500109bSMat Martineau 49791500109bSMat Martineau static void l2cap_logical_finish_create(struct l2cap_chan *chan, 49801500109bSMat Martineau struct hci_chan *hchan) 49811500109bSMat Martineau { 49821500109bSMat Martineau struct l2cap_conf_rsp rsp; 49831500109bSMat Martineau 4984336178a3SAndrei Emeltchenko chan->hs_hchan = hchan; 49851500109bSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 49861500109bSMat Martineau 498735ba9561SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0); 49881500109bSMat Martineau 49891500109bSMat Martineau if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 4990fe79c6feSAndrei Emeltchenko int err; 49911500109bSMat Martineau 49921500109bSMat Martineau set_default_fcs(chan); 49931500109bSMat Martineau 49941500109bSMat Martineau err = l2cap_ertm_init(chan); 49951500109bSMat Martineau if (err < 0) 49965e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 49971500109bSMat Martineau else 49981500109bSMat Martineau l2cap_chan_ready(chan); 49991500109bSMat Martineau } 50001500109bSMat Martineau } 50011500109bSMat Martineau 50021500109bSMat Martineau static void l2cap_logical_finish_move(struct l2cap_chan *chan, 50031500109bSMat Martineau struct hci_chan *hchan) 50041500109bSMat Martineau { 50051500109bSMat Martineau chan->hs_hcon = hchan->conn; 50061500109bSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 50071500109bSMat Martineau 50081500109bSMat Martineau BT_DBG("move_state %d", chan->move_state); 50091500109bSMat Martineau 50101500109bSMat Martineau switch (chan->move_state) { 50111500109bSMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_COMP: 50121500109bSMat Martineau /* Move confirm will be sent after a success 50131500109bSMat Martineau * response is received 50141500109bSMat Martineau */ 50151500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 50161500109bSMat Martineau break; 50171500109bSMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_CFM: 50181500109bSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 50191500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 50201500109bSMat Martineau } else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { 50211500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; 50221500109bSMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 50231500109bSMat Martineau } else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { 50241500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 50251500109bSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); 50261500109bSMat Martineau } 50271500109bSMat Martineau break; 50281500109bSMat Martineau default: 50291500109bSMat Martineau /* Move was not in expected state, free the channel */ 50301500109bSMat Martineau __release_logical_link(chan); 50311500109bSMat Martineau 50321500109bSMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 50331500109bSMat Martineau } 50341500109bSMat Martineau } 50351500109bSMat Martineau 50361500109bSMat Martineau /* Call with chan locked */ 503727695fb4SAndrei Emeltchenko void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan, 50385b155ef9SMat Martineau u8 status) 50395b155ef9SMat Martineau { 50401500109bSMat Martineau BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status); 50411500109bSMat Martineau 50421500109bSMat Martineau if (status) { 50431500109bSMat Martineau l2cap_logical_fail(chan); 50441500109bSMat Martineau __release_logical_link(chan); 50455b155ef9SMat Martineau return; 50465b155ef9SMat Martineau } 50475b155ef9SMat Martineau 50481500109bSMat Martineau if (chan->state != BT_CONNECTED) { 50491500109bSMat Martineau /* Ignore logical link if channel is on BR/EDR */ 50506ed971caSMarcel Holtmann if (chan->local_amp_id != AMP_ID_BREDR) 50511500109bSMat Martineau l2cap_logical_finish_create(chan, hchan); 50521500109bSMat Martineau } else { 50531500109bSMat Martineau l2cap_logical_finish_move(chan, hchan); 50541500109bSMat Martineau } 50551500109bSMat Martineau } 50561500109bSMat Martineau 50573f7a56c4SMat Martineau void l2cap_move_start(struct l2cap_chan *chan) 50583f7a56c4SMat Martineau { 50593f7a56c4SMat Martineau BT_DBG("chan %p", chan); 50603f7a56c4SMat Martineau 50616ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR) { 50623f7a56c4SMat Martineau if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED) 50633f7a56c4SMat Martineau return; 50643f7a56c4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; 50653f7a56c4SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_PREPARE; 50663f7a56c4SMat Martineau /* Placeholder - start physical link setup */ 50673f7a56c4SMat Martineau } else { 50683f7a56c4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; 50693f7a56c4SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 50703f7a56c4SMat Martineau chan->move_id = 0; 50713f7a56c4SMat Martineau l2cap_move_setup(chan); 50723f7a56c4SMat Martineau l2cap_send_move_chan_req(chan, 0); 50733f7a56c4SMat Martineau } 50743f7a56c4SMat Martineau } 50753f7a56c4SMat Martineau 50768eb200bdSMat Martineau static void l2cap_do_create(struct l2cap_chan *chan, int result, 50778eb200bdSMat Martineau u8 local_amp_id, u8 remote_amp_id) 50788eb200bdSMat Martineau { 507962748ca1SAndrei Emeltchenko BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state), 508062748ca1SAndrei Emeltchenko local_amp_id, remote_amp_id); 508162748ca1SAndrei Emeltchenko 508212d6cc60SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 508312d6cc60SAndrei Emeltchenko 508462748ca1SAndrei Emeltchenko /* Outgoing channel on AMP */ 508562748ca1SAndrei Emeltchenko if (chan->state == BT_CONNECT) { 508662748ca1SAndrei Emeltchenko if (result == L2CAP_CR_SUCCESS) { 508762748ca1SAndrei Emeltchenko chan->local_amp_id = local_amp_id; 508862748ca1SAndrei Emeltchenko l2cap_send_create_chan_req(chan, remote_amp_id); 508962748ca1SAndrei Emeltchenko } else { 509062748ca1SAndrei Emeltchenko /* Revert to BR/EDR connect */ 509162748ca1SAndrei Emeltchenko l2cap_send_conn_req(chan); 509262748ca1SAndrei Emeltchenko } 509362748ca1SAndrei Emeltchenko 509462748ca1SAndrei Emeltchenko return; 509562748ca1SAndrei Emeltchenko } 509662748ca1SAndrei Emeltchenko 509762748ca1SAndrei Emeltchenko /* Incoming channel on AMP */ 509862748ca1SAndrei Emeltchenko if (__l2cap_no_conn_pending(chan)) { 50998eb200bdSMat Martineau struct l2cap_conn_rsp rsp; 51008eb200bdSMat Martineau char buf[128]; 51018eb200bdSMat Martineau rsp.scid = cpu_to_le16(chan->dcid); 51028eb200bdSMat Martineau rsp.dcid = cpu_to_le16(chan->scid); 51038eb200bdSMat Martineau 51048eb200bdSMat Martineau if (result == L2CAP_CR_SUCCESS) { 51058eb200bdSMat Martineau /* Send successful response */ 5106dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 5107dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 51088eb200bdSMat Martineau } else { 51098eb200bdSMat Martineau /* Send negative response */ 5110dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_NO_MEM); 5111dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 51128eb200bdSMat Martineau } 51138eb200bdSMat Martineau 51148eb200bdSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP, 51158eb200bdSMat Martineau sizeof(rsp), &rsp); 51168eb200bdSMat Martineau 51178eb200bdSMat Martineau if (result == L2CAP_CR_SUCCESS) { 5118f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 51198eb200bdSMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 51208eb200bdSMat Martineau l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn), 51218eb200bdSMat Martineau L2CAP_CONF_REQ, 5122e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); 51238eb200bdSMat Martineau chan->num_conf_req++; 51248eb200bdSMat Martineau } 51258eb200bdSMat Martineau } 51268eb200bdSMat Martineau } 51278eb200bdSMat Martineau 51288eb200bdSMat Martineau static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id, 51298eb200bdSMat Martineau u8 remote_amp_id) 51308eb200bdSMat Martineau { 51318eb200bdSMat Martineau l2cap_move_setup(chan); 51328eb200bdSMat Martineau chan->move_id = local_amp_id; 51338eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP; 51348eb200bdSMat Martineau 51358eb200bdSMat Martineau l2cap_send_move_chan_req(chan, remote_amp_id); 51368eb200bdSMat Martineau } 51378eb200bdSMat Martineau 51388eb200bdSMat Martineau static void l2cap_do_move_respond(struct l2cap_chan *chan, int result) 51398eb200bdSMat Martineau { 51408eb200bdSMat Martineau struct hci_chan *hchan = NULL; 51418eb200bdSMat Martineau 51428eb200bdSMat Martineau /* Placeholder - get hci_chan for logical link */ 51438eb200bdSMat Martineau 51448eb200bdSMat Martineau if (hchan) { 51458eb200bdSMat Martineau if (hchan->state == BT_CONNECTED) { 51468eb200bdSMat Martineau /* Logical link is ready to go */ 51478eb200bdSMat Martineau chan->hs_hcon = hchan->conn; 51488eb200bdSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 51498eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 51508eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); 51518eb200bdSMat Martineau 51528eb200bdSMat Martineau l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); 51538eb200bdSMat Martineau } else { 51548eb200bdSMat Martineau /* Wait for logical link to be ready */ 51558eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 51568eb200bdSMat Martineau } 51578eb200bdSMat Martineau } else { 51588eb200bdSMat Martineau /* Logical link not available */ 51598eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED); 51608eb200bdSMat Martineau } 51618eb200bdSMat Martineau } 51628eb200bdSMat Martineau 51638eb200bdSMat Martineau static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result) 51648eb200bdSMat Martineau { 51658eb200bdSMat Martineau if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { 51668eb200bdSMat Martineau u8 rsp_result; 51678eb200bdSMat Martineau if (result == -EINVAL) 51688eb200bdSMat Martineau rsp_result = L2CAP_MR_BAD_ID; 51698eb200bdSMat Martineau else 51708eb200bdSMat Martineau rsp_result = L2CAP_MR_NOT_ALLOWED; 51718eb200bdSMat Martineau 51728eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, rsp_result); 51738eb200bdSMat Martineau } 51748eb200bdSMat Martineau 51758eb200bdSMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 51768eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 51778eb200bdSMat Martineau 51788eb200bdSMat Martineau /* Restart data transmission */ 51798eb200bdSMat Martineau l2cap_ertm_send(chan); 51808eb200bdSMat Martineau } 51818eb200bdSMat Martineau 5182a514b17fSAndrei Emeltchenko /* Invoke with locked chan */ 5183a514b17fSAndrei Emeltchenko void __l2cap_physical_cfm(struct l2cap_chan *chan, int result) 51848eb200bdSMat Martineau { 5185770bfefaSAndrei Emeltchenko u8 local_amp_id = chan->local_amp_id; 5186fffadc08SAndrei Emeltchenko u8 remote_amp_id = chan->remote_amp_id; 5187770bfefaSAndrei Emeltchenko 51888eb200bdSMat Martineau BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d", 51898eb200bdSMat Martineau chan, result, local_amp_id, remote_amp_id); 51908eb200bdSMat Martineau 5191df66499aSDan Carpenter if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) 51928eb200bdSMat Martineau return; 51938eb200bdSMat Martineau 51948eb200bdSMat Martineau if (chan->state != BT_CONNECTED) { 51958eb200bdSMat Martineau l2cap_do_create(chan, result, local_amp_id, remote_amp_id); 51968eb200bdSMat Martineau } else if (result != L2CAP_MR_SUCCESS) { 51978eb200bdSMat Martineau l2cap_do_move_cancel(chan, result); 51988eb200bdSMat Martineau } else { 51998eb200bdSMat Martineau switch (chan->move_role) { 52008eb200bdSMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 52018eb200bdSMat Martineau l2cap_do_move_initiate(chan, local_amp_id, 52028eb200bdSMat Martineau remote_amp_id); 52038eb200bdSMat Martineau break; 52048eb200bdSMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 52058eb200bdSMat Martineau l2cap_do_move_respond(chan, result); 52068eb200bdSMat Martineau break; 52078eb200bdSMat Martineau default: 52088eb200bdSMat Martineau l2cap_do_move_cancel(chan, result); 52098eb200bdSMat Martineau break; 52108eb200bdSMat Martineau } 52118eb200bdSMat Martineau } 52128eb200bdSMat Martineau } 52138eb200bdSMat Martineau 52148d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn, 5215ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5216ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 52178d5a04a1SMat Martineau { 52188d5a04a1SMat Martineau struct l2cap_move_chan_req *req = data; 52191500109bSMat Martineau struct l2cap_move_chan_rsp rsp; 522002b0fbb9SMat Martineau struct l2cap_chan *chan; 52218d5a04a1SMat Martineau u16 icid = 0; 52228d5a04a1SMat Martineau u16 result = L2CAP_MR_NOT_ALLOWED; 52238d5a04a1SMat Martineau 52248d5a04a1SMat Martineau if (cmd_len != sizeof(*req)) 52258d5a04a1SMat Martineau return -EPROTO; 52268d5a04a1SMat Martineau 52278d5a04a1SMat Martineau icid = le16_to_cpu(req->icid); 52288d5a04a1SMat Martineau 5229ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id); 52308d5a04a1SMat Martineau 52310bd49fc7SJohan Hedberg if (!(conn->local_fixed_chan & L2CAP_FC_A2MP)) 52328d5a04a1SMat Martineau return -EINVAL; 52338d5a04a1SMat Martineau 523402b0fbb9SMat Martineau chan = l2cap_get_chan_by_dcid(conn, icid); 523502b0fbb9SMat Martineau if (!chan) { 52361500109bSMat Martineau rsp.icid = cpu_to_le16(icid); 5237dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_MR_NOT_ALLOWED); 52381500109bSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP, 52391500109bSMat Martineau sizeof(rsp), &rsp); 524002b0fbb9SMat Martineau return 0; 524102b0fbb9SMat Martineau } 524202b0fbb9SMat Martineau 52431500109bSMat Martineau chan->ident = cmd->ident; 52441500109bSMat Martineau 524502b0fbb9SMat Martineau if (chan->scid < L2CAP_CID_DYN_START || 524602b0fbb9SMat Martineau chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY || 524702b0fbb9SMat Martineau (chan->mode != L2CAP_MODE_ERTM && 524802b0fbb9SMat Martineau chan->mode != L2CAP_MODE_STREAMING)) { 524902b0fbb9SMat Martineau result = L2CAP_MR_NOT_ALLOWED; 525002b0fbb9SMat Martineau goto send_move_response; 525102b0fbb9SMat Martineau } 525202b0fbb9SMat Martineau 525302b0fbb9SMat Martineau if (chan->local_amp_id == req->dest_amp_id) { 525402b0fbb9SMat Martineau result = L2CAP_MR_SAME_ID; 525502b0fbb9SMat Martineau goto send_move_response; 525602b0fbb9SMat Martineau } 525702b0fbb9SMat Martineau 52586ed971caSMarcel Holtmann if (req->dest_amp_id != AMP_ID_BREDR) { 525902b0fbb9SMat Martineau struct hci_dev *hdev; 526002b0fbb9SMat Martineau hdev = hci_dev_get(req->dest_amp_id); 526102b0fbb9SMat Martineau if (!hdev || hdev->dev_type != HCI_AMP || 526202b0fbb9SMat Martineau !test_bit(HCI_UP, &hdev->flags)) { 526302b0fbb9SMat Martineau if (hdev) 526402b0fbb9SMat Martineau hci_dev_put(hdev); 526502b0fbb9SMat Martineau 526602b0fbb9SMat Martineau result = L2CAP_MR_BAD_ID; 526702b0fbb9SMat Martineau goto send_move_response; 526802b0fbb9SMat Martineau } 526902b0fbb9SMat Martineau hci_dev_put(hdev); 527002b0fbb9SMat Martineau } 527102b0fbb9SMat Martineau 527202b0fbb9SMat Martineau /* Detect a move collision. Only send a collision response 527302b0fbb9SMat Martineau * if this side has "lost", otherwise proceed with the move. 527402b0fbb9SMat Martineau * The winner has the larger bd_addr. 527502b0fbb9SMat Martineau */ 527602b0fbb9SMat Martineau if ((__chan_is_moving(chan) || 527702b0fbb9SMat Martineau chan->move_role != L2CAP_MOVE_ROLE_NONE) && 52786f59b904SMarcel Holtmann bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) { 527902b0fbb9SMat Martineau result = L2CAP_MR_COLLISION; 528002b0fbb9SMat Martineau goto send_move_response; 528102b0fbb9SMat Martineau } 528202b0fbb9SMat Martineau 528302b0fbb9SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; 528402b0fbb9SMat Martineau l2cap_move_setup(chan); 528502b0fbb9SMat Martineau chan->move_id = req->dest_amp_id; 528602b0fbb9SMat Martineau 52876ed971caSMarcel Holtmann if (req->dest_amp_id == AMP_ID_BREDR) { 528802b0fbb9SMat Martineau /* Moving to BR/EDR */ 528902b0fbb9SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 529002b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 529102b0fbb9SMat Martineau result = L2CAP_MR_PEND; 529202b0fbb9SMat Martineau } else { 529302b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 529402b0fbb9SMat Martineau result = L2CAP_MR_SUCCESS; 529502b0fbb9SMat Martineau } 529602b0fbb9SMat Martineau } else { 529702b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_PREPARE; 529802b0fbb9SMat Martineau /* Placeholder - uncomment when amp functions are available */ 529902b0fbb9SMat Martineau /*amp_accept_physical(chan, req->dest_amp_id);*/ 530002b0fbb9SMat Martineau result = L2CAP_MR_PEND; 530102b0fbb9SMat Martineau } 530202b0fbb9SMat Martineau 530302b0fbb9SMat Martineau send_move_response: 53041500109bSMat Martineau l2cap_send_move_chan_rsp(chan, result); 53058d5a04a1SMat Martineau 530602b0fbb9SMat Martineau l2cap_chan_unlock(chan); 530702b0fbb9SMat Martineau 53088d5a04a1SMat Martineau return 0; 53098d5a04a1SMat Martineau } 53108d5a04a1SMat Martineau 53115b155ef9SMat Martineau static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result) 53125b155ef9SMat Martineau { 53135b155ef9SMat Martineau struct l2cap_chan *chan; 53145b155ef9SMat Martineau struct hci_chan *hchan = NULL; 53155b155ef9SMat Martineau 53165b155ef9SMat Martineau chan = l2cap_get_chan_by_scid(conn, icid); 53175b155ef9SMat Martineau if (!chan) { 53185b155ef9SMat Martineau l2cap_send_move_chan_cfm_icid(conn, icid); 53195b155ef9SMat Martineau return; 53205b155ef9SMat Martineau } 53215b155ef9SMat Martineau 53225b155ef9SMat Martineau __clear_chan_timer(chan); 53235b155ef9SMat Martineau if (result == L2CAP_MR_PEND) 53245b155ef9SMat Martineau __set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT); 53255b155ef9SMat Martineau 53265b155ef9SMat Martineau switch (chan->move_state) { 53275b155ef9SMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_COMP: 53285b155ef9SMat Martineau /* Move confirm will be sent when logical link 53295b155ef9SMat Martineau * is complete. 53305b155ef9SMat Martineau */ 53315b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 53325b155ef9SMat Martineau break; 53335b155ef9SMat Martineau case L2CAP_MOVE_WAIT_RSP_SUCCESS: 53345b155ef9SMat Martineau if (result == L2CAP_MR_PEND) { 53355b155ef9SMat Martineau break; 53365b155ef9SMat Martineau } else if (test_bit(CONN_LOCAL_BUSY, 53375b155ef9SMat Martineau &chan->conn_state)) { 53385b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 53395b155ef9SMat Martineau } else { 53405b155ef9SMat Martineau /* Logical link is up or moving to BR/EDR, 53415b155ef9SMat Martineau * proceed with move 53425b155ef9SMat Martineau */ 53435b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; 53445b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 53455b155ef9SMat Martineau } 53465b155ef9SMat Martineau break; 53475b155ef9SMat Martineau case L2CAP_MOVE_WAIT_RSP: 53485b155ef9SMat Martineau /* Moving to AMP */ 53495b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS) { 53505b155ef9SMat Martineau /* Remote is ready, send confirm immediately 53515b155ef9SMat Martineau * after logical link is ready 53525b155ef9SMat Martineau */ 53535b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 53545b155ef9SMat Martineau } else { 53555b155ef9SMat Martineau /* Both logical link and move success 53565b155ef9SMat Martineau * are required to confirm 53575b155ef9SMat Martineau */ 53585b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP; 53595b155ef9SMat Martineau } 53605b155ef9SMat Martineau 53615b155ef9SMat Martineau /* Placeholder - get hci_chan for logical link */ 53625b155ef9SMat Martineau if (!hchan) { 53635b155ef9SMat Martineau /* Logical link not available */ 53645b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 53655b155ef9SMat Martineau break; 53665b155ef9SMat Martineau } 53675b155ef9SMat Martineau 53685b155ef9SMat Martineau /* If the logical link is not yet connected, do not 53695b155ef9SMat Martineau * send confirmation. 53705b155ef9SMat Martineau */ 53715b155ef9SMat Martineau if (hchan->state != BT_CONNECTED) 53725b155ef9SMat Martineau break; 53735b155ef9SMat Martineau 53745b155ef9SMat Martineau /* Logical link is already ready to go */ 53755b155ef9SMat Martineau 53765b155ef9SMat Martineau chan->hs_hcon = hchan->conn; 53775b155ef9SMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 53785b155ef9SMat Martineau 53795b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS) { 53805b155ef9SMat Martineau /* Can confirm now */ 53815b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 53825b155ef9SMat Martineau } else { 53835b155ef9SMat Martineau /* Now only need move success 53845b155ef9SMat Martineau * to confirm 53855b155ef9SMat Martineau */ 53865b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 53875b155ef9SMat Martineau } 53885b155ef9SMat Martineau 53895b155ef9SMat Martineau l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); 53905b155ef9SMat Martineau break; 53915b155ef9SMat Martineau default: 53925b155ef9SMat Martineau /* Any other amp move state means the move failed. */ 53935b155ef9SMat Martineau chan->move_id = chan->local_amp_id; 53945b155ef9SMat Martineau l2cap_move_done(chan); 53955b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 53965b155ef9SMat Martineau } 53975b155ef9SMat Martineau 53985b155ef9SMat Martineau l2cap_chan_unlock(chan); 53995b155ef9SMat Martineau } 54005b155ef9SMat Martineau 54015b155ef9SMat Martineau static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid, 54025b155ef9SMat Martineau u16 result) 54035b155ef9SMat Martineau { 54045b155ef9SMat Martineau struct l2cap_chan *chan; 54055b155ef9SMat Martineau 54065b155ef9SMat Martineau chan = l2cap_get_chan_by_ident(conn, ident); 54075b155ef9SMat Martineau if (!chan) { 54085b155ef9SMat Martineau /* Could not locate channel, icid is best guess */ 54095b155ef9SMat Martineau l2cap_send_move_chan_cfm_icid(conn, icid); 54105b155ef9SMat Martineau return; 54115b155ef9SMat Martineau } 54125b155ef9SMat Martineau 54135b155ef9SMat Martineau __clear_chan_timer(chan); 54145b155ef9SMat Martineau 54155b155ef9SMat Martineau if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { 54165b155ef9SMat Martineau if (result == L2CAP_MR_COLLISION) { 54175b155ef9SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; 54185b155ef9SMat Martineau } else { 54195b155ef9SMat Martineau /* Cleanup - cancel move */ 54205b155ef9SMat Martineau chan->move_id = chan->local_amp_id; 54215b155ef9SMat Martineau l2cap_move_done(chan); 54225b155ef9SMat Martineau } 54235b155ef9SMat Martineau } 54245b155ef9SMat Martineau 54255b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 54265b155ef9SMat Martineau 54275b155ef9SMat Martineau l2cap_chan_unlock(chan); 54285b155ef9SMat Martineau } 54295b155ef9SMat Martineau 54305b155ef9SMat Martineau static int l2cap_move_channel_rsp(struct l2cap_conn *conn, 5431ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5432ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 54338d5a04a1SMat Martineau { 54348d5a04a1SMat Martineau struct l2cap_move_chan_rsp *rsp = data; 54358d5a04a1SMat Martineau u16 icid, result; 54368d5a04a1SMat Martineau 54378d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 54388d5a04a1SMat Martineau return -EPROTO; 54398d5a04a1SMat Martineau 54408d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 54418d5a04a1SMat Martineau result = le16_to_cpu(rsp->result); 54428d5a04a1SMat Martineau 5443ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 54448d5a04a1SMat Martineau 54455b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND) 54465b155ef9SMat Martineau l2cap_move_continue(conn, icid, result); 54475b155ef9SMat Martineau else 54485b155ef9SMat Martineau l2cap_move_fail(conn, cmd->ident, icid, result); 54498d5a04a1SMat Martineau 54508d5a04a1SMat Martineau return 0; 54518d5a04a1SMat Martineau } 54528d5a04a1SMat Martineau 54535f3847a4SMat Martineau static int l2cap_move_channel_confirm(struct l2cap_conn *conn, 5454ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5455ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 54568d5a04a1SMat Martineau { 54578d5a04a1SMat Martineau struct l2cap_move_chan_cfm *cfm = data; 54585f3847a4SMat Martineau struct l2cap_chan *chan; 54598d5a04a1SMat Martineau u16 icid, result; 54608d5a04a1SMat Martineau 54618d5a04a1SMat Martineau if (cmd_len != sizeof(*cfm)) 54628d5a04a1SMat Martineau return -EPROTO; 54638d5a04a1SMat Martineau 54648d5a04a1SMat Martineau icid = le16_to_cpu(cfm->icid); 54658d5a04a1SMat Martineau result = le16_to_cpu(cfm->result); 54668d5a04a1SMat Martineau 5467ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 54688d5a04a1SMat Martineau 54695f3847a4SMat Martineau chan = l2cap_get_chan_by_dcid(conn, icid); 54705f3847a4SMat Martineau if (!chan) { 54715f3847a4SMat Martineau /* Spec requires a response even if the icid was not found */ 54728d5a04a1SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 54735f3847a4SMat Martineau return 0; 54745f3847a4SMat Martineau } 54755f3847a4SMat Martineau 54765f3847a4SMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) { 54775f3847a4SMat Martineau if (result == L2CAP_MC_CONFIRMED) { 54785f3847a4SMat Martineau chan->local_amp_id = chan->move_id; 54796ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR) 54805f3847a4SMat Martineau __release_logical_link(chan); 54815f3847a4SMat Martineau } else { 54825f3847a4SMat Martineau chan->move_id = chan->local_amp_id; 54835f3847a4SMat Martineau } 54845f3847a4SMat Martineau 54855f3847a4SMat Martineau l2cap_move_done(chan); 54865f3847a4SMat Martineau } 54875f3847a4SMat Martineau 54885f3847a4SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 54895f3847a4SMat Martineau 54905f3847a4SMat Martineau l2cap_chan_unlock(chan); 54918d5a04a1SMat Martineau 54928d5a04a1SMat Martineau return 0; 54938d5a04a1SMat Martineau } 54948d5a04a1SMat Martineau 54958d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, 5496ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5497ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 54988d5a04a1SMat Martineau { 54998d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp *rsp = data; 55003fd71a0aSMat Martineau struct l2cap_chan *chan; 55018d5a04a1SMat Martineau u16 icid; 55028d5a04a1SMat Martineau 55038d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 55048d5a04a1SMat Martineau return -EPROTO; 55058d5a04a1SMat Martineau 55068d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 55078d5a04a1SMat Martineau 5508ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 55098d5a04a1SMat Martineau 55103fd71a0aSMat Martineau chan = l2cap_get_chan_by_scid(conn, icid); 55113fd71a0aSMat Martineau if (!chan) 55123fd71a0aSMat Martineau return 0; 55133fd71a0aSMat Martineau 55143fd71a0aSMat Martineau __clear_chan_timer(chan); 55153fd71a0aSMat Martineau 55163fd71a0aSMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) { 55173fd71a0aSMat Martineau chan->local_amp_id = chan->move_id; 55183fd71a0aSMat Martineau 55196ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan) 55203fd71a0aSMat Martineau __release_logical_link(chan); 55213fd71a0aSMat Martineau 55223fd71a0aSMat Martineau l2cap_move_done(chan); 55233fd71a0aSMat Martineau } 55243fd71a0aSMat Martineau 55253fd71a0aSMat Martineau l2cap_chan_unlock(chan); 55263fd71a0aSMat Martineau 55278d5a04a1SMat Martineau return 0; 55288d5a04a1SMat Martineau } 55298d5a04a1SMat Martineau 5530de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, 55312d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, 5532203e639eSJohan Hedberg u16 cmd_len, u8 *data) 5533de73115aSClaudio Takahasi { 5534de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon; 5535de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req; 5536de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp; 5537203e639eSJohan Hedberg u16 min, max, latency, to_multiplier; 55382ce603ebSClaudio Takahasi int err; 5539de73115aSClaudio Takahasi 554040bef302SJohan Hedberg if (hcon->role != HCI_ROLE_MASTER) 5541de73115aSClaudio Takahasi return -EINVAL; 5542de73115aSClaudio Takahasi 5543de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) 5544de73115aSClaudio Takahasi return -EPROTO; 5545de73115aSClaudio Takahasi 5546de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data; 5547de73115aSClaudio Takahasi min = __le16_to_cpu(req->min); 5548de73115aSClaudio Takahasi max = __le16_to_cpu(req->max); 5549de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency); 5550de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier); 5551de73115aSClaudio Takahasi 5552de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", 5553de73115aSClaudio Takahasi min, max, latency, to_multiplier); 5554de73115aSClaudio Takahasi 5555de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp)); 55562ce603ebSClaudio Takahasi 5557d4905f24SAndre Guedes err = hci_check_conn_params(min, max, latency, to_multiplier); 55582ce603ebSClaudio Takahasi if (err) 5559dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); 5560de73115aSClaudio Takahasi else 5561dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); 5562de73115aSClaudio Takahasi 5563de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, 5564de73115aSClaudio Takahasi sizeof(rsp), &rsp); 5565de73115aSClaudio Takahasi 5566ffb5a827SAndre Guedes if (!err) { 5567f4869e2aSJohan Hedberg u8 store_hint; 5568ffb5a827SAndre Guedes 5569f4869e2aSJohan Hedberg store_hint = hci_le_conn_update(hcon, min, max, latency, 5570f4869e2aSJohan Hedberg to_multiplier); 5571f4869e2aSJohan Hedberg mgmt_new_conn_param(hcon->hdev, &hcon->dst, hcon->dst_type, 5572f4869e2aSJohan Hedberg store_hint, min, max, latency, 5573f4869e2aSJohan Hedberg to_multiplier); 5574f4869e2aSJohan Hedberg 5575ffb5a827SAndre Guedes } 55762ce603ebSClaudio Takahasi 5577de73115aSClaudio Takahasi return 0; 5578de73115aSClaudio Takahasi } 5579de73115aSClaudio Takahasi 5580f1496deeSJohan Hedberg static int l2cap_le_connect_rsp(struct l2cap_conn *conn, 5581f1496deeSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5582f1496deeSJohan Hedberg u8 *data) 5583f1496deeSJohan Hedberg { 5584f1496deeSJohan Hedberg struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data; 55853e64b7bdSJohan Hedberg struct hci_conn *hcon = conn->hcon; 5586f1496deeSJohan Hedberg u16 dcid, mtu, mps, credits, result; 5587f1496deeSJohan Hedberg struct l2cap_chan *chan; 55883e64b7bdSJohan Hedberg int err, sec_level; 5589f1496deeSJohan Hedberg 5590f1496deeSJohan Hedberg if (cmd_len < sizeof(*rsp)) 5591f1496deeSJohan Hedberg return -EPROTO; 5592f1496deeSJohan Hedberg 5593f1496deeSJohan Hedberg dcid = __le16_to_cpu(rsp->dcid); 5594f1496deeSJohan Hedberg mtu = __le16_to_cpu(rsp->mtu); 5595f1496deeSJohan Hedberg mps = __le16_to_cpu(rsp->mps); 5596f1496deeSJohan Hedberg credits = __le16_to_cpu(rsp->credits); 5597f1496deeSJohan Hedberg result = __le16_to_cpu(rsp->result); 5598f1496deeSJohan Hedberg 5599571f7390SMallikarjun Phulari if (result == L2CAP_CR_LE_SUCCESS && (mtu < 23 || mps < 23 || 560040624183SJohan Hedberg dcid < L2CAP_CID_DYN_START || 560140624183SJohan Hedberg dcid > L2CAP_CID_LE_DYN_END)) 5602f1496deeSJohan Hedberg return -EPROTO; 5603f1496deeSJohan Hedberg 5604f1496deeSJohan Hedberg BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x", 5605f1496deeSJohan Hedberg dcid, mtu, mps, credits, result); 5606f1496deeSJohan Hedberg 5607f1496deeSJohan Hedberg mutex_lock(&conn->chan_lock); 5608f1496deeSJohan Hedberg 5609f1496deeSJohan Hedberg chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 5610f1496deeSJohan Hedberg if (!chan) { 5611f1496deeSJohan Hedberg err = -EBADSLT; 5612f1496deeSJohan Hedberg goto unlock; 5613f1496deeSJohan Hedberg } 5614f1496deeSJohan Hedberg 5615f1496deeSJohan Hedberg err = 0; 5616f1496deeSJohan Hedberg 5617f1496deeSJohan Hedberg l2cap_chan_lock(chan); 5618f1496deeSJohan Hedberg 5619f1496deeSJohan Hedberg switch (result) { 5620571f7390SMallikarjun Phulari case L2CAP_CR_LE_SUCCESS: 562140624183SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, dcid)) { 562240624183SJohan Hedberg err = -EBADSLT; 562340624183SJohan Hedberg break; 562440624183SJohan Hedberg } 562540624183SJohan Hedberg 5626f1496deeSJohan Hedberg chan->ident = 0; 5627f1496deeSJohan Hedberg chan->dcid = dcid; 5628f1496deeSJohan Hedberg chan->omtu = mtu; 5629f1496deeSJohan Hedberg chan->remote_mps = mps; 56300cd75f7eSJohan Hedberg chan->tx_credits = credits; 5631f1496deeSJohan Hedberg l2cap_chan_ready(chan); 5632f1496deeSJohan Hedberg break; 5633f1496deeSJohan Hedberg 5634571f7390SMallikarjun Phulari case L2CAP_CR_LE_AUTHENTICATION: 5635571f7390SMallikarjun Phulari case L2CAP_CR_LE_ENCRYPTION: 56363e64b7bdSJohan Hedberg /* If we already have MITM protection we can't do 56373e64b7bdSJohan Hedberg * anything. 56383e64b7bdSJohan Hedberg */ 56393e64b7bdSJohan Hedberg if (hcon->sec_level > BT_SECURITY_MEDIUM) { 56403e64b7bdSJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED); 56413e64b7bdSJohan Hedberg break; 56423e64b7bdSJohan Hedberg } 56433e64b7bdSJohan Hedberg 56443e64b7bdSJohan Hedberg sec_level = hcon->sec_level + 1; 56453e64b7bdSJohan Hedberg if (chan->sec_level < sec_level) 56463e64b7bdSJohan Hedberg chan->sec_level = sec_level; 56473e64b7bdSJohan Hedberg 56483e64b7bdSJohan Hedberg /* We'll need to send a new Connect Request */ 56493e64b7bdSJohan Hedberg clear_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags); 56503e64b7bdSJohan Hedberg 56513e64b7bdSJohan Hedberg smp_conn_security(hcon, chan->sec_level); 56523e64b7bdSJohan Hedberg break; 56533e64b7bdSJohan Hedberg 5654f1496deeSJohan Hedberg default: 5655f1496deeSJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED); 5656f1496deeSJohan Hedberg break; 5657f1496deeSJohan Hedberg } 5658f1496deeSJohan Hedberg 5659f1496deeSJohan Hedberg l2cap_chan_unlock(chan); 5660f1496deeSJohan Hedberg 5661f1496deeSJohan Hedberg unlock: 5662f1496deeSJohan Hedberg mutex_unlock(&conn->chan_lock); 5663f1496deeSJohan Hedberg 5664f1496deeSJohan Hedberg return err; 5665f1496deeSJohan Hedberg } 5666f1496deeSJohan Hedberg 56673300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, 56682d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len, 56692d792818SGustavo Padovan u8 *data) 56703300d9a9SClaudio Takahasi { 56713300d9a9SClaudio Takahasi int err = 0; 56723300d9a9SClaudio Takahasi 56733300d9a9SClaudio Takahasi switch (cmd->code) { 56743300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 5675cb3b3152SJohan Hedberg l2cap_command_rej(conn, cmd, cmd_len, data); 56763300d9a9SClaudio Takahasi break; 56773300d9a9SClaudio Takahasi 56783300d9a9SClaudio Takahasi case L2CAP_CONN_REQ: 5679cb3b3152SJohan Hedberg err = l2cap_connect_req(conn, cmd, cmd_len, data); 56803300d9a9SClaudio Takahasi break; 56813300d9a9SClaudio Takahasi 56823300d9a9SClaudio Takahasi case L2CAP_CONN_RSP: 5683f5a2598dSMat Martineau case L2CAP_CREATE_CHAN_RSP: 56849245e737SJohan Hedberg l2cap_connect_create_rsp(conn, cmd, cmd_len, data); 56853300d9a9SClaudio Takahasi break; 56863300d9a9SClaudio Takahasi 56873300d9a9SClaudio Takahasi case L2CAP_CONF_REQ: 56883300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data); 56893300d9a9SClaudio Takahasi break; 56903300d9a9SClaudio Takahasi 56913300d9a9SClaudio Takahasi case L2CAP_CONF_RSP: 56929245e737SJohan Hedberg l2cap_config_rsp(conn, cmd, cmd_len, data); 56933300d9a9SClaudio Takahasi break; 56943300d9a9SClaudio Takahasi 56953300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ: 5696cb3b3152SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data); 56973300d9a9SClaudio Takahasi break; 56983300d9a9SClaudio Takahasi 56993300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP: 57009245e737SJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data); 57013300d9a9SClaudio Takahasi break; 57023300d9a9SClaudio Takahasi 57033300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ: 57043300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data); 57053300d9a9SClaudio Takahasi break; 57063300d9a9SClaudio Takahasi 57073300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP: 57083300d9a9SClaudio Takahasi break; 57093300d9a9SClaudio Takahasi 57103300d9a9SClaudio Takahasi case L2CAP_INFO_REQ: 5711cb3b3152SJohan Hedberg err = l2cap_information_req(conn, cmd, cmd_len, data); 57123300d9a9SClaudio Takahasi break; 57133300d9a9SClaudio Takahasi 57143300d9a9SClaudio Takahasi case L2CAP_INFO_RSP: 57159245e737SJohan Hedberg l2cap_information_rsp(conn, cmd, cmd_len, data); 57163300d9a9SClaudio Takahasi break; 57173300d9a9SClaudio Takahasi 5718f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_REQ: 5719f94ff6ffSMat Martineau err = l2cap_create_channel_req(conn, cmd, cmd_len, data); 5720f94ff6ffSMat Martineau break; 5721f94ff6ffSMat Martineau 57228d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_REQ: 57238d5a04a1SMat Martineau err = l2cap_move_channel_req(conn, cmd, cmd_len, data); 57248d5a04a1SMat Martineau break; 57258d5a04a1SMat Martineau 57268d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_RSP: 57279245e737SJohan Hedberg l2cap_move_channel_rsp(conn, cmd, cmd_len, data); 57288d5a04a1SMat Martineau break; 57298d5a04a1SMat Martineau 57308d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM: 57318d5a04a1SMat Martineau err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data); 57328d5a04a1SMat Martineau break; 57338d5a04a1SMat Martineau 57348d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM_RSP: 57359245e737SJohan Hedberg l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data); 57368d5a04a1SMat Martineau break; 57378d5a04a1SMat Martineau 57383300d9a9SClaudio Takahasi default: 57393300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code); 57403300d9a9SClaudio Takahasi err = -EINVAL; 57413300d9a9SClaudio Takahasi break; 57423300d9a9SClaudio Takahasi } 57433300d9a9SClaudio Takahasi 57443300d9a9SClaudio Takahasi return err; 57453300d9a9SClaudio Takahasi } 57463300d9a9SClaudio Takahasi 574727e2d4c8SJohan Hedberg static int l2cap_le_connect_req(struct l2cap_conn *conn, 574827e2d4c8SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 574927e2d4c8SJohan Hedberg u8 *data) 575027e2d4c8SJohan Hedberg { 575127e2d4c8SJohan Hedberg struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data; 575227e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 575327e2d4c8SJohan Hedberg struct l2cap_chan *chan, *pchan; 57540cd75f7eSJohan Hedberg u16 dcid, scid, credits, mtu, mps; 575527e2d4c8SJohan Hedberg __le16 psm; 575627e2d4c8SJohan Hedberg u8 result; 575727e2d4c8SJohan Hedberg 575827e2d4c8SJohan Hedberg if (cmd_len != sizeof(*req)) 575927e2d4c8SJohan Hedberg return -EPROTO; 576027e2d4c8SJohan Hedberg 576127e2d4c8SJohan Hedberg scid = __le16_to_cpu(req->scid); 576227e2d4c8SJohan Hedberg mtu = __le16_to_cpu(req->mtu); 576327e2d4c8SJohan Hedberg mps = __le16_to_cpu(req->mps); 576427e2d4c8SJohan Hedberg psm = req->psm; 576527e2d4c8SJohan Hedberg dcid = 0; 57660cd75f7eSJohan Hedberg credits = 0; 576727e2d4c8SJohan Hedberg 576827e2d4c8SJohan Hedberg if (mtu < 23 || mps < 23) 576927e2d4c8SJohan Hedberg return -EPROTO; 577027e2d4c8SJohan Hedberg 577127e2d4c8SJohan Hedberg BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm), 577227e2d4c8SJohan Hedberg scid, mtu, mps); 577327e2d4c8SJohan Hedberg 577427e2d4c8SJohan Hedberg /* Check if we have socket listening on psm */ 577527e2d4c8SJohan Hedberg pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 577627e2d4c8SJohan Hedberg &conn->hcon->dst, LE_LINK); 577727e2d4c8SJohan Hedberg if (!pchan) { 5778571f7390SMallikarjun Phulari result = L2CAP_CR_LE_BAD_PSM; 577927e2d4c8SJohan Hedberg chan = NULL; 578027e2d4c8SJohan Hedberg goto response; 578127e2d4c8SJohan Hedberg } 578227e2d4c8SJohan Hedberg 578327e2d4c8SJohan Hedberg mutex_lock(&conn->chan_lock); 578427e2d4c8SJohan Hedberg l2cap_chan_lock(pchan); 578527e2d4c8SJohan Hedberg 578635dc6f83SJohan Hedberg if (!smp_sufficient_security(conn->hcon, pchan->sec_level, 578735dc6f83SJohan Hedberg SMP_ALLOW_STK)) { 5788571f7390SMallikarjun Phulari result = L2CAP_CR_LE_AUTHENTICATION; 578927e2d4c8SJohan Hedberg chan = NULL; 579027e2d4c8SJohan Hedberg goto response_unlock; 579127e2d4c8SJohan Hedberg } 579227e2d4c8SJohan Hedberg 57938a7889ccSJohan Hedberg /* Check for valid dynamic CID range */ 57948a7889ccSJohan Hedberg if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) { 5795571f7390SMallikarjun Phulari result = L2CAP_CR_LE_INVALID_SCID; 57968a7889ccSJohan Hedberg chan = NULL; 57978a7889ccSJohan Hedberg goto response_unlock; 57988a7889ccSJohan Hedberg } 57998a7889ccSJohan Hedberg 580027e2d4c8SJohan Hedberg /* Check if we already have channel with that dcid */ 580127e2d4c8SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, scid)) { 5802571f7390SMallikarjun Phulari result = L2CAP_CR_LE_SCID_IN_USE; 580327e2d4c8SJohan Hedberg chan = NULL; 580427e2d4c8SJohan Hedberg goto response_unlock; 580527e2d4c8SJohan Hedberg } 580627e2d4c8SJohan Hedberg 580727e2d4c8SJohan Hedberg chan = pchan->ops->new_connection(pchan); 580827e2d4c8SJohan Hedberg if (!chan) { 5809571f7390SMallikarjun Phulari result = L2CAP_CR_LE_NO_MEM; 581027e2d4c8SJohan Hedberg goto response_unlock; 581127e2d4c8SJohan Hedberg } 581227e2d4c8SJohan Hedberg 581327e2d4c8SJohan Hedberg bacpy(&chan->src, &conn->hcon->src); 581427e2d4c8SJohan Hedberg bacpy(&chan->dst, &conn->hcon->dst); 5815a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(conn->hcon); 5816a250e048SJohan Hedberg chan->dst_type = bdaddr_dst_type(conn->hcon); 581727e2d4c8SJohan Hedberg chan->psm = psm; 581827e2d4c8SJohan Hedberg chan->dcid = scid; 581927e2d4c8SJohan Hedberg chan->omtu = mtu; 582027e2d4c8SJohan Hedberg chan->remote_mps = mps; 582127e2d4c8SJohan Hedberg 582227e2d4c8SJohan Hedberg __l2cap_chan_add(conn, chan); 5823fe149310SLuiz Augusto von Dentz 5824ba8f5289SLuiz Augusto von Dentz l2cap_le_flowctl_init(chan, __le16_to_cpu(req->credits)); 5825fe149310SLuiz Augusto von Dentz 582627e2d4c8SJohan Hedberg dcid = chan->scid; 58270cd75f7eSJohan Hedberg credits = chan->rx_credits; 582827e2d4c8SJohan Hedberg 582927e2d4c8SJohan Hedberg __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 583027e2d4c8SJohan Hedberg 583127e2d4c8SJohan Hedberg chan->ident = cmd->ident; 583227e2d4c8SJohan Hedberg 583327e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 583427e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_CONNECT2); 5835434714dcSJohan Hedberg /* The following result value is actually not defined 5836434714dcSJohan Hedberg * for LE CoC but we use it to let the function know 5837434714dcSJohan Hedberg * that it should bail out after doing its cleanup 5838434714dcSJohan Hedberg * instead of sending a response. 5839434714dcSJohan Hedberg */ 584027e2d4c8SJohan Hedberg result = L2CAP_CR_PEND; 584127e2d4c8SJohan Hedberg chan->ops->defer(chan); 584227e2d4c8SJohan Hedberg } else { 584327e2d4c8SJohan Hedberg l2cap_chan_ready(chan); 5844571f7390SMallikarjun Phulari result = L2CAP_CR_LE_SUCCESS; 584527e2d4c8SJohan Hedberg } 584627e2d4c8SJohan Hedberg 584727e2d4c8SJohan Hedberg response_unlock: 584827e2d4c8SJohan Hedberg l2cap_chan_unlock(pchan); 584927e2d4c8SJohan Hedberg mutex_unlock(&conn->chan_lock); 5850a24cce14SJohan Hedberg l2cap_chan_put(pchan); 585127e2d4c8SJohan Hedberg 585227e2d4c8SJohan Hedberg if (result == L2CAP_CR_PEND) 585327e2d4c8SJohan Hedberg return 0; 585427e2d4c8SJohan Hedberg 585527e2d4c8SJohan Hedberg response: 585627e2d4c8SJohan Hedberg if (chan) { 585727e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 58583916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps); 585927e2d4c8SJohan Hedberg } else { 586027e2d4c8SJohan Hedberg rsp.mtu = 0; 586127e2d4c8SJohan Hedberg rsp.mps = 0; 586227e2d4c8SJohan Hedberg } 586327e2d4c8SJohan Hedberg 586427e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(dcid); 58650cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(credits); 586627e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result); 586727e2d4c8SJohan Hedberg 586827e2d4c8SJohan Hedberg l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp); 586927e2d4c8SJohan Hedberg 587027e2d4c8SJohan Hedberg return 0; 587127e2d4c8SJohan Hedberg } 587227e2d4c8SJohan Hedberg 5873fad5fc89SJohan Hedberg static inline int l2cap_le_credits(struct l2cap_conn *conn, 5874fad5fc89SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5875fad5fc89SJohan Hedberg u8 *data) 5876fad5fc89SJohan Hedberg { 5877fad5fc89SJohan Hedberg struct l2cap_le_credits *pkt; 5878fad5fc89SJohan Hedberg struct l2cap_chan *chan; 58790f1bfe4eSJohan Hedberg u16 cid, credits, max_credits; 5880fad5fc89SJohan Hedberg 5881fad5fc89SJohan Hedberg if (cmd_len != sizeof(*pkt)) 5882fad5fc89SJohan Hedberg return -EPROTO; 5883fad5fc89SJohan Hedberg 5884fad5fc89SJohan Hedberg pkt = (struct l2cap_le_credits *) data; 5885fad5fc89SJohan Hedberg cid = __le16_to_cpu(pkt->cid); 5886fad5fc89SJohan Hedberg credits = __le16_to_cpu(pkt->credits); 5887fad5fc89SJohan Hedberg 5888fad5fc89SJohan Hedberg BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits); 5889fad5fc89SJohan Hedberg 5890fad5fc89SJohan Hedberg chan = l2cap_get_chan_by_dcid(conn, cid); 5891fad5fc89SJohan Hedberg if (!chan) 5892fad5fc89SJohan Hedberg return -EBADSLT; 5893fad5fc89SJohan Hedberg 58940f1bfe4eSJohan Hedberg max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits; 58950f1bfe4eSJohan Hedberg if (credits > max_credits) { 58960f1bfe4eSJohan Hedberg BT_ERR("LE credits overflow"); 58970f1bfe4eSJohan Hedberg l2cap_send_disconn_req(chan, ECONNRESET); 5898ee93053dSMartin Townsend l2cap_chan_unlock(chan); 58990f1bfe4eSJohan Hedberg 59000f1bfe4eSJohan Hedberg /* Return 0 so that we don't trigger an unnecessary 59010f1bfe4eSJohan Hedberg * command reject packet. 59020f1bfe4eSJohan Hedberg */ 59030f1bfe4eSJohan Hedberg return 0; 59040f1bfe4eSJohan Hedberg } 59050f1bfe4eSJohan Hedberg 5906fad5fc89SJohan Hedberg chan->tx_credits += credits; 5907fad5fc89SJohan Hedberg 59088a505b7fSLuiz Augusto von Dentz /* Resume sending */ 59098a505b7fSLuiz Augusto von Dentz l2cap_le_flowctl_send(chan); 5910fad5fc89SJohan Hedberg 5911fad5fc89SJohan Hedberg if (chan->tx_credits) 5912fad5fc89SJohan Hedberg chan->ops->resume(chan); 5913fad5fc89SJohan Hedberg 5914fad5fc89SJohan Hedberg l2cap_chan_unlock(chan); 5915fad5fc89SJohan Hedberg 5916fad5fc89SJohan Hedberg return 0; 5917fad5fc89SJohan Hedberg } 5918fad5fc89SJohan Hedberg 591915f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn, 592015f02b91SLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd, u16 cmd_len, 592115f02b91SLuiz Augusto von Dentz u8 *data) 592215f02b91SLuiz Augusto von Dentz { 592315f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_req *req = (void *) data; 592415f02b91SLuiz Augusto von Dentz struct { 592515f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp rsp; 59267cf3b1ddSLuiz Augusto von Dentz __le16 dcid[L2CAP_ECRED_MAX_CID]; 592715f02b91SLuiz Augusto von Dentz } __packed pdu; 592815f02b91SLuiz Augusto von Dentz struct l2cap_chan *chan, *pchan; 5929965995b7SYueHaibing u16 mtu, mps; 593015f02b91SLuiz Augusto von Dentz __le16 psm; 593115f02b91SLuiz Augusto von Dentz u8 result, len = 0; 593215f02b91SLuiz Augusto von Dentz int i, num_scid; 593315f02b91SLuiz Augusto von Dentz bool defer = false; 593415f02b91SLuiz Augusto von Dentz 59354be5ca67SLuiz Augusto von Dentz if (!enable_ecred) 59364be5ca67SLuiz Augusto von Dentz return -EINVAL; 59374be5ca67SLuiz Augusto von Dentz 593869d67b46SKonstantin Forostyan if (cmd_len < sizeof(*req) || (cmd_len - sizeof(*req)) % sizeof(u16)) { 593915f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_INVALID_PARAMS; 594015f02b91SLuiz Augusto von Dentz goto response; 594115f02b91SLuiz Augusto von Dentz } 594215f02b91SLuiz Augusto von Dentz 59437cf3b1ddSLuiz Augusto von Dentz cmd_len -= sizeof(*req); 59447cf3b1ddSLuiz Augusto von Dentz num_scid = cmd_len / sizeof(u16); 59457cf3b1ddSLuiz Augusto von Dentz 59467cf3b1ddSLuiz Augusto von Dentz if (num_scid > ARRAY_SIZE(pdu.dcid)) { 59477cf3b1ddSLuiz Augusto von Dentz result = L2CAP_CR_LE_INVALID_PARAMS; 59487cf3b1ddSLuiz Augusto von Dentz goto response; 59497cf3b1ddSLuiz Augusto von Dentz } 59507cf3b1ddSLuiz Augusto von Dentz 595115f02b91SLuiz Augusto von Dentz mtu = __le16_to_cpu(req->mtu); 595215f02b91SLuiz Augusto von Dentz mps = __le16_to_cpu(req->mps); 595315f02b91SLuiz Augusto von Dentz 595415f02b91SLuiz Augusto von Dentz if (mtu < L2CAP_ECRED_MIN_MTU || mps < L2CAP_ECRED_MIN_MPS) { 595515f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_UNACCEPT_PARAMS; 595615f02b91SLuiz Augusto von Dentz goto response; 595715f02b91SLuiz Augusto von Dentz } 595815f02b91SLuiz Augusto von Dentz 595915f02b91SLuiz Augusto von Dentz psm = req->psm; 596015f02b91SLuiz Augusto von Dentz 596115f02b91SLuiz Augusto von Dentz BT_DBG("psm 0x%2.2x mtu %u mps %u", __le16_to_cpu(psm), mtu, mps); 596215f02b91SLuiz Augusto von Dentz 596315f02b91SLuiz Augusto von Dentz memset(&pdu, 0, sizeof(pdu)); 596415f02b91SLuiz Augusto von Dentz 596515f02b91SLuiz Augusto von Dentz /* Check if we have socket listening on psm */ 596615f02b91SLuiz Augusto von Dentz pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 596715f02b91SLuiz Augusto von Dentz &conn->hcon->dst, LE_LINK); 596815f02b91SLuiz Augusto von Dentz if (!pchan) { 596915f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_BAD_PSM; 597015f02b91SLuiz Augusto von Dentz goto response; 597115f02b91SLuiz Augusto von Dentz } 597215f02b91SLuiz Augusto von Dentz 597315f02b91SLuiz Augusto von Dentz mutex_lock(&conn->chan_lock); 597415f02b91SLuiz Augusto von Dentz l2cap_chan_lock(pchan); 597515f02b91SLuiz Augusto von Dentz 597615f02b91SLuiz Augusto von Dentz if (!smp_sufficient_security(conn->hcon, pchan->sec_level, 597715f02b91SLuiz Augusto von Dentz SMP_ALLOW_STK)) { 597815f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_AUTHENTICATION; 597915f02b91SLuiz Augusto von Dentz goto unlock; 598015f02b91SLuiz Augusto von Dentz } 598115f02b91SLuiz Augusto von Dentz 598215f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_SUCCESS; 598315f02b91SLuiz Augusto von Dentz 598415f02b91SLuiz Augusto von Dentz for (i = 0; i < num_scid; i++) { 598515f02b91SLuiz Augusto von Dentz u16 scid = __le16_to_cpu(req->scid[i]); 598615f02b91SLuiz Augusto von Dentz 598715f02b91SLuiz Augusto von Dentz BT_DBG("scid[%d] 0x%4.4x", i, scid); 598815f02b91SLuiz Augusto von Dentz 598915f02b91SLuiz Augusto von Dentz pdu.dcid[i] = 0x0000; 599015f02b91SLuiz Augusto von Dentz len += sizeof(*pdu.dcid); 599115f02b91SLuiz Augusto von Dentz 599215f02b91SLuiz Augusto von Dentz /* Check for valid dynamic CID range */ 599315f02b91SLuiz Augusto von Dentz if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) { 599415f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_INVALID_SCID; 599515f02b91SLuiz Augusto von Dentz continue; 599615f02b91SLuiz Augusto von Dentz } 599715f02b91SLuiz Augusto von Dentz 599815f02b91SLuiz Augusto von Dentz /* Check if we already have channel with that dcid */ 599915f02b91SLuiz Augusto von Dentz if (__l2cap_get_chan_by_dcid(conn, scid)) { 600015f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_SCID_IN_USE; 600115f02b91SLuiz Augusto von Dentz continue; 600215f02b91SLuiz Augusto von Dentz } 600315f02b91SLuiz Augusto von Dentz 600415f02b91SLuiz Augusto von Dentz chan = pchan->ops->new_connection(pchan); 600515f02b91SLuiz Augusto von Dentz if (!chan) { 600615f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_NO_MEM; 600715f02b91SLuiz Augusto von Dentz continue; 600815f02b91SLuiz Augusto von Dentz } 600915f02b91SLuiz Augusto von Dentz 601015f02b91SLuiz Augusto von Dentz bacpy(&chan->src, &conn->hcon->src); 601115f02b91SLuiz Augusto von Dentz bacpy(&chan->dst, &conn->hcon->dst); 601215f02b91SLuiz Augusto von Dentz chan->src_type = bdaddr_src_type(conn->hcon); 601315f02b91SLuiz Augusto von Dentz chan->dst_type = bdaddr_dst_type(conn->hcon); 601415f02b91SLuiz Augusto von Dentz chan->psm = psm; 601515f02b91SLuiz Augusto von Dentz chan->dcid = scid; 601615f02b91SLuiz Augusto von Dentz chan->omtu = mtu; 601715f02b91SLuiz Augusto von Dentz chan->remote_mps = mps; 601815f02b91SLuiz Augusto von Dentz 601915f02b91SLuiz Augusto von Dentz __l2cap_chan_add(conn, chan); 602015f02b91SLuiz Augusto von Dentz 602115f02b91SLuiz Augusto von Dentz l2cap_ecred_init(chan, __le16_to_cpu(req->credits)); 602215f02b91SLuiz Augusto von Dentz 602315f02b91SLuiz Augusto von Dentz /* Init response */ 602415f02b91SLuiz Augusto von Dentz if (!pdu.rsp.credits) { 602515f02b91SLuiz Augusto von Dentz pdu.rsp.mtu = cpu_to_le16(chan->imtu); 602615f02b91SLuiz Augusto von Dentz pdu.rsp.mps = cpu_to_le16(chan->mps); 602715f02b91SLuiz Augusto von Dentz pdu.rsp.credits = cpu_to_le16(chan->rx_credits); 602815f02b91SLuiz Augusto von Dentz } 602915f02b91SLuiz Augusto von Dentz 603015f02b91SLuiz Augusto von Dentz pdu.dcid[i] = cpu_to_le16(chan->scid); 603115f02b91SLuiz Augusto von Dentz 603215f02b91SLuiz Augusto von Dentz __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 603315f02b91SLuiz Augusto von Dentz 603415f02b91SLuiz Augusto von Dentz chan->ident = cmd->ident; 603515f02b91SLuiz Augusto von Dentz 603615f02b91SLuiz Augusto von Dentz if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 603715f02b91SLuiz Augusto von Dentz l2cap_state_change(chan, BT_CONNECT2); 603815f02b91SLuiz Augusto von Dentz defer = true; 603915f02b91SLuiz Augusto von Dentz chan->ops->defer(chan); 604015f02b91SLuiz Augusto von Dentz } else { 604115f02b91SLuiz Augusto von Dentz l2cap_chan_ready(chan); 604215f02b91SLuiz Augusto von Dentz } 604315f02b91SLuiz Augusto von Dentz } 604415f02b91SLuiz Augusto von Dentz 604515f02b91SLuiz Augusto von Dentz unlock: 604615f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(pchan); 604715f02b91SLuiz Augusto von Dentz mutex_unlock(&conn->chan_lock); 604815f02b91SLuiz Augusto von Dentz l2cap_chan_put(pchan); 604915f02b91SLuiz Augusto von Dentz 605015f02b91SLuiz Augusto von Dentz response: 605115f02b91SLuiz Augusto von Dentz pdu.rsp.result = cpu_to_le16(result); 605215f02b91SLuiz Augusto von Dentz 605315f02b91SLuiz Augusto von Dentz if (defer) 605415f02b91SLuiz Augusto von Dentz return 0; 605515f02b91SLuiz Augusto von Dentz 605615f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, cmd->ident, L2CAP_ECRED_CONN_RSP, 605715f02b91SLuiz Augusto von Dentz sizeof(pdu.rsp) + len, &pdu); 605815f02b91SLuiz Augusto von Dentz 605915f02b91SLuiz Augusto von Dentz return 0; 606015f02b91SLuiz Augusto von Dentz } 606115f02b91SLuiz Augusto von Dentz 606215f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn, 606315f02b91SLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd, u16 cmd_len, 606415f02b91SLuiz Augusto von Dentz u8 *data) 606515f02b91SLuiz Augusto von Dentz { 606615f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp *rsp = (void *) data; 606715f02b91SLuiz Augusto von Dentz struct hci_conn *hcon = conn->hcon; 606815f02b91SLuiz Augusto von Dentz u16 mtu, mps, credits, result; 606915f02b91SLuiz Augusto von Dentz struct l2cap_chan *chan; 607015f02b91SLuiz Augusto von Dentz int err = 0, sec_level; 607115f02b91SLuiz Augusto von Dentz int i = 0; 607215f02b91SLuiz Augusto von Dentz 607315f02b91SLuiz Augusto von Dentz if (cmd_len < sizeof(*rsp)) 607415f02b91SLuiz Augusto von Dentz return -EPROTO; 607515f02b91SLuiz Augusto von Dentz 607615f02b91SLuiz Augusto von Dentz mtu = __le16_to_cpu(rsp->mtu); 607715f02b91SLuiz Augusto von Dentz mps = __le16_to_cpu(rsp->mps); 607815f02b91SLuiz Augusto von Dentz credits = __le16_to_cpu(rsp->credits); 607915f02b91SLuiz Augusto von Dentz result = __le16_to_cpu(rsp->result); 608015f02b91SLuiz Augusto von Dentz 608115f02b91SLuiz Augusto von Dentz BT_DBG("mtu %u mps %u credits %u result 0x%4.4x", mtu, mps, credits, 608215f02b91SLuiz Augusto von Dentz result); 608315f02b91SLuiz Augusto von Dentz 608415f02b91SLuiz Augusto von Dentz mutex_lock(&conn->chan_lock); 608515f02b91SLuiz Augusto von Dentz 608615f02b91SLuiz Augusto von Dentz cmd_len -= sizeof(*rsp); 608715f02b91SLuiz Augusto von Dentz 608815f02b91SLuiz Augusto von Dentz list_for_each_entry(chan, &conn->chan_l, list) { 608915f02b91SLuiz Augusto von Dentz u16 dcid; 609015f02b91SLuiz Augusto von Dentz 609115f02b91SLuiz Augusto von Dentz if (chan->ident != cmd->ident || 609215f02b91SLuiz Augusto von Dentz chan->mode != L2CAP_MODE_EXT_FLOWCTL || 609315f02b91SLuiz Augusto von Dentz chan->state == BT_CONNECTED) 609415f02b91SLuiz Augusto von Dentz continue; 609515f02b91SLuiz Augusto von Dentz 609615f02b91SLuiz Augusto von Dentz l2cap_chan_lock(chan); 609715f02b91SLuiz Augusto von Dentz 609815f02b91SLuiz Augusto von Dentz /* Check that there is a dcid for each pending channel */ 609915f02b91SLuiz Augusto von Dentz if (cmd_len < sizeof(dcid)) { 610015f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED); 610115f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(chan); 610215f02b91SLuiz Augusto von Dentz continue; 610315f02b91SLuiz Augusto von Dentz } 610415f02b91SLuiz Augusto von Dentz 610515f02b91SLuiz Augusto von Dentz dcid = __le16_to_cpu(rsp->dcid[i++]); 610615f02b91SLuiz Augusto von Dentz cmd_len -= sizeof(u16); 610715f02b91SLuiz Augusto von Dentz 610815f02b91SLuiz Augusto von Dentz BT_DBG("dcid[%d] 0x%4.4x", i, dcid); 610915f02b91SLuiz Augusto von Dentz 611015f02b91SLuiz Augusto von Dentz /* Check if dcid is already in use */ 611115f02b91SLuiz Augusto von Dentz if (dcid && __l2cap_get_chan_by_dcid(conn, dcid)) { 611215f02b91SLuiz Augusto von Dentz /* If a device receives a 611315f02b91SLuiz Augusto von Dentz * L2CAP_CREDIT_BASED_CONNECTION_RSP packet with an 611415f02b91SLuiz Augusto von Dentz * already-assigned Destination CID, then both the 611515f02b91SLuiz Augusto von Dentz * original channel and the new channel shall be 611615f02b91SLuiz Augusto von Dentz * immediately discarded and not used. 611715f02b91SLuiz Augusto von Dentz */ 611815f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED); 611915f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(chan); 612015f02b91SLuiz Augusto von Dentz chan = __l2cap_get_chan_by_dcid(conn, dcid); 612115f02b91SLuiz Augusto von Dentz l2cap_chan_lock(chan); 612215f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNRESET); 612315f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(chan); 612415f02b91SLuiz Augusto von Dentz continue; 612515f02b91SLuiz Augusto von Dentz } 612615f02b91SLuiz Augusto von Dentz 612715f02b91SLuiz Augusto von Dentz switch (result) { 612815f02b91SLuiz Augusto von Dentz case L2CAP_CR_LE_AUTHENTICATION: 612915f02b91SLuiz Augusto von Dentz case L2CAP_CR_LE_ENCRYPTION: 613015f02b91SLuiz Augusto von Dentz /* If we already have MITM protection we can't do 613115f02b91SLuiz Augusto von Dentz * anything. 613215f02b91SLuiz Augusto von Dentz */ 613315f02b91SLuiz Augusto von Dentz if (hcon->sec_level > BT_SECURITY_MEDIUM) { 613415f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED); 613515f02b91SLuiz Augusto von Dentz break; 613615f02b91SLuiz Augusto von Dentz } 613715f02b91SLuiz Augusto von Dentz 613815f02b91SLuiz Augusto von Dentz sec_level = hcon->sec_level + 1; 613915f02b91SLuiz Augusto von Dentz if (chan->sec_level < sec_level) 614015f02b91SLuiz Augusto von Dentz chan->sec_level = sec_level; 614115f02b91SLuiz Augusto von Dentz 614215f02b91SLuiz Augusto von Dentz /* We'll need to send a new Connect Request */ 614315f02b91SLuiz Augusto von Dentz clear_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags); 614415f02b91SLuiz Augusto von Dentz 614515f02b91SLuiz Augusto von Dentz smp_conn_security(hcon, chan->sec_level); 614615f02b91SLuiz Augusto von Dentz break; 614715f02b91SLuiz Augusto von Dentz 614815f02b91SLuiz Augusto von Dentz case L2CAP_CR_LE_BAD_PSM: 614915f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED); 615015f02b91SLuiz Augusto von Dentz break; 615115f02b91SLuiz Augusto von Dentz 615215f02b91SLuiz Augusto von Dentz default: 615315f02b91SLuiz Augusto von Dentz /* If dcid was not set it means channels was refused */ 615415f02b91SLuiz Augusto von Dentz if (!dcid) { 615515f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED); 615615f02b91SLuiz Augusto von Dentz break; 615715f02b91SLuiz Augusto von Dentz } 615815f02b91SLuiz Augusto von Dentz 615915f02b91SLuiz Augusto von Dentz chan->ident = 0; 616015f02b91SLuiz Augusto von Dentz chan->dcid = dcid; 616115f02b91SLuiz Augusto von Dentz chan->omtu = mtu; 616215f02b91SLuiz Augusto von Dentz chan->remote_mps = mps; 616315f02b91SLuiz Augusto von Dentz chan->tx_credits = credits; 616415f02b91SLuiz Augusto von Dentz l2cap_chan_ready(chan); 616515f02b91SLuiz Augusto von Dentz break; 616615f02b91SLuiz Augusto von Dentz } 616715f02b91SLuiz Augusto von Dentz 616815f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(chan); 616915f02b91SLuiz Augusto von Dentz } 617015f02b91SLuiz Augusto von Dentz 617115f02b91SLuiz Augusto von Dentz mutex_unlock(&conn->chan_lock); 617215f02b91SLuiz Augusto von Dentz 617315f02b91SLuiz Augusto von Dentz return err; 617415f02b91SLuiz Augusto von Dentz } 617515f02b91SLuiz Augusto von Dentz 617615f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_reconf_req(struct l2cap_conn *conn, 617715f02b91SLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd, u16 cmd_len, 617815f02b91SLuiz Augusto von Dentz u8 *data) 617915f02b91SLuiz Augusto von Dentz { 618015f02b91SLuiz Augusto von Dentz struct l2cap_ecred_reconf_req *req = (void *) data; 618115f02b91SLuiz Augusto von Dentz struct l2cap_ecred_reconf_rsp rsp; 618215f02b91SLuiz Augusto von Dentz u16 mtu, mps, result; 618315f02b91SLuiz Augusto von Dentz struct l2cap_chan *chan; 618415f02b91SLuiz Augusto von Dentz int i, num_scid; 618515f02b91SLuiz Augusto von Dentz 61864be5ca67SLuiz Augusto von Dentz if (!enable_ecred) 61874be5ca67SLuiz Augusto von Dentz return -EINVAL; 61884be5ca67SLuiz Augusto von Dentz 618915f02b91SLuiz Augusto von Dentz if (cmd_len < sizeof(*req) || cmd_len - sizeof(*req) % sizeof(u16)) { 619015f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_INVALID_PARAMS; 619115f02b91SLuiz Augusto von Dentz goto respond; 619215f02b91SLuiz Augusto von Dentz } 619315f02b91SLuiz Augusto von Dentz 619415f02b91SLuiz Augusto von Dentz mtu = __le16_to_cpu(req->mtu); 619515f02b91SLuiz Augusto von Dentz mps = __le16_to_cpu(req->mps); 619615f02b91SLuiz Augusto von Dentz 619715f02b91SLuiz Augusto von Dentz BT_DBG("mtu %u mps %u", mtu, mps); 619815f02b91SLuiz Augusto von Dentz 619915f02b91SLuiz Augusto von Dentz if (mtu < L2CAP_ECRED_MIN_MTU) { 620015f02b91SLuiz Augusto von Dentz result = L2CAP_RECONF_INVALID_MTU; 620115f02b91SLuiz Augusto von Dentz goto respond; 620215f02b91SLuiz Augusto von Dentz } 620315f02b91SLuiz Augusto von Dentz 620415f02b91SLuiz Augusto von Dentz if (mps < L2CAP_ECRED_MIN_MPS) { 620515f02b91SLuiz Augusto von Dentz result = L2CAP_RECONF_INVALID_MPS; 620615f02b91SLuiz Augusto von Dentz goto respond; 620715f02b91SLuiz Augusto von Dentz } 620815f02b91SLuiz Augusto von Dentz 620915f02b91SLuiz Augusto von Dentz cmd_len -= sizeof(*req); 621015f02b91SLuiz Augusto von Dentz num_scid = cmd_len / sizeof(u16); 621115f02b91SLuiz Augusto von Dentz result = L2CAP_RECONF_SUCCESS; 621215f02b91SLuiz Augusto von Dentz 621315f02b91SLuiz Augusto von Dentz for (i = 0; i < num_scid; i++) { 621415f02b91SLuiz Augusto von Dentz u16 scid; 621515f02b91SLuiz Augusto von Dentz 621615f02b91SLuiz Augusto von Dentz scid = __le16_to_cpu(req->scid[i]); 621715f02b91SLuiz Augusto von Dentz if (!scid) 621815f02b91SLuiz Augusto von Dentz return -EPROTO; 621915f02b91SLuiz Augusto von Dentz 622015f02b91SLuiz Augusto von Dentz chan = __l2cap_get_chan_by_dcid(conn, scid); 622115f02b91SLuiz Augusto von Dentz if (!chan) 622215f02b91SLuiz Augusto von Dentz continue; 622315f02b91SLuiz Augusto von Dentz 622415f02b91SLuiz Augusto von Dentz /* If the MTU value is decreased for any of the included 622515f02b91SLuiz Augusto von Dentz * channels, then the receiver shall disconnect all 622615f02b91SLuiz Augusto von Dentz * included channels. 622715f02b91SLuiz Augusto von Dentz */ 622815f02b91SLuiz Augusto von Dentz if (chan->omtu > mtu) { 622915f02b91SLuiz Augusto von Dentz BT_ERR("chan %p decreased MTU %u -> %u", chan, 623015f02b91SLuiz Augusto von Dentz chan->omtu, mtu); 623115f02b91SLuiz Augusto von Dentz result = L2CAP_RECONF_INVALID_MTU; 623215f02b91SLuiz Augusto von Dentz } 623315f02b91SLuiz Augusto von Dentz 623415f02b91SLuiz Augusto von Dentz chan->omtu = mtu; 623515f02b91SLuiz Augusto von Dentz chan->remote_mps = mps; 623615f02b91SLuiz Augusto von Dentz } 623715f02b91SLuiz Augusto von Dentz 623815f02b91SLuiz Augusto von Dentz respond: 623915f02b91SLuiz Augusto von Dentz rsp.result = cpu_to_le16(result); 624015f02b91SLuiz Augusto von Dentz 624115f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, cmd->ident, L2CAP_ECRED_RECONF_RSP, sizeof(rsp), 624215f02b91SLuiz Augusto von Dentz &rsp); 624315f02b91SLuiz Augusto von Dentz 624415f02b91SLuiz Augusto von Dentz return 0; 624515f02b91SLuiz Augusto von Dentz } 624615f02b91SLuiz Augusto von Dentz 624715f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn, 624815f02b91SLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd, u16 cmd_len, 624915f02b91SLuiz Augusto von Dentz u8 *data) 625015f02b91SLuiz Augusto von Dentz { 625115f02b91SLuiz Augusto von Dentz struct l2cap_chan *chan; 625215f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp *rsp = (void *) data; 625315f02b91SLuiz Augusto von Dentz u16 result; 625415f02b91SLuiz Augusto von Dentz 625515f02b91SLuiz Augusto von Dentz if (cmd_len < sizeof(*rsp)) 625615f02b91SLuiz Augusto von Dentz return -EPROTO; 625715f02b91SLuiz Augusto von Dentz 625815f02b91SLuiz Augusto von Dentz result = __le16_to_cpu(rsp->result); 625915f02b91SLuiz Augusto von Dentz 626015f02b91SLuiz Augusto von Dentz BT_DBG("result 0x%4.4x", rsp->result); 626115f02b91SLuiz Augusto von Dentz 626215f02b91SLuiz Augusto von Dentz if (!result) 626315f02b91SLuiz Augusto von Dentz return 0; 626415f02b91SLuiz Augusto von Dentz 626515f02b91SLuiz Augusto von Dentz list_for_each_entry(chan, &conn->chan_l, list) { 626615f02b91SLuiz Augusto von Dentz if (chan->ident != cmd->ident) 626715f02b91SLuiz Augusto von Dentz continue; 626815f02b91SLuiz Augusto von Dentz 626915f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNRESET); 627015f02b91SLuiz Augusto von Dentz } 627115f02b91SLuiz Augusto von Dentz 627215f02b91SLuiz Augusto von Dentz return 0; 627315f02b91SLuiz Augusto von Dentz } 627415f02b91SLuiz Augusto von Dentz 627571fb4197SJohan Hedberg static inline int l2cap_le_command_rej(struct l2cap_conn *conn, 627671fb4197SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 627771fb4197SJohan Hedberg u8 *data) 627871fb4197SJohan Hedberg { 627971fb4197SJohan Hedberg struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 628071fb4197SJohan Hedberg struct l2cap_chan *chan; 628171fb4197SJohan Hedberg 628271fb4197SJohan Hedberg if (cmd_len < sizeof(*rej)) 628371fb4197SJohan Hedberg return -EPROTO; 628471fb4197SJohan Hedberg 628571fb4197SJohan Hedberg mutex_lock(&conn->chan_lock); 628671fb4197SJohan Hedberg 628771fb4197SJohan Hedberg chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 628871fb4197SJohan Hedberg if (!chan) 628971fb4197SJohan Hedberg goto done; 629071fb4197SJohan Hedberg 629171fb4197SJohan Hedberg l2cap_chan_lock(chan); 629271fb4197SJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED); 629371fb4197SJohan Hedberg l2cap_chan_unlock(chan); 629471fb4197SJohan Hedberg 629571fb4197SJohan Hedberg done: 629671fb4197SJohan Hedberg mutex_unlock(&conn->chan_lock); 629771fb4197SJohan Hedberg return 0; 629871fb4197SJohan Hedberg } 629971fb4197SJohan Hedberg 63003300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, 6301203e639eSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 6302203e639eSJohan Hedberg u8 *data) 63033300d9a9SClaudio Takahasi { 6304b5ecba64SJohan Hedberg int err = 0; 6305b5ecba64SJohan Hedberg 63063300d9a9SClaudio Takahasi switch (cmd->code) { 63073300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 630871fb4197SJohan Hedberg l2cap_le_command_rej(conn, cmd, cmd_len, data); 6309b5ecba64SJohan Hedberg break; 63103300d9a9SClaudio Takahasi 63113300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ: 6312b5ecba64SJohan Hedberg err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data); 6313b5ecba64SJohan Hedberg break; 63143300d9a9SClaudio Takahasi 63153300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP: 6316b5ecba64SJohan Hedberg break; 63173300d9a9SClaudio Takahasi 6318f1496deeSJohan Hedberg case L2CAP_LE_CONN_RSP: 6319f1496deeSJohan Hedberg l2cap_le_connect_rsp(conn, cmd, cmd_len, data); 6320b5ecba64SJohan Hedberg break; 6321f1496deeSJohan Hedberg 632227e2d4c8SJohan Hedberg case L2CAP_LE_CONN_REQ: 6323b5ecba64SJohan Hedberg err = l2cap_le_connect_req(conn, cmd, cmd_len, data); 6324b5ecba64SJohan Hedberg break; 632527e2d4c8SJohan Hedberg 6326fad5fc89SJohan Hedberg case L2CAP_LE_CREDITS: 6327fad5fc89SJohan Hedberg err = l2cap_le_credits(conn, cmd, cmd_len, data); 6328fad5fc89SJohan Hedberg break; 6329fad5fc89SJohan Hedberg 633015f02b91SLuiz Augusto von Dentz case L2CAP_ECRED_CONN_REQ: 633115f02b91SLuiz Augusto von Dentz err = l2cap_ecred_conn_req(conn, cmd, cmd_len, data); 633215f02b91SLuiz Augusto von Dentz break; 633315f02b91SLuiz Augusto von Dentz 633415f02b91SLuiz Augusto von Dentz case L2CAP_ECRED_CONN_RSP: 633515f02b91SLuiz Augusto von Dentz err = l2cap_ecred_conn_rsp(conn, cmd, cmd_len, data); 633615f02b91SLuiz Augusto von Dentz break; 633715f02b91SLuiz Augusto von Dentz 633815f02b91SLuiz Augusto von Dentz case L2CAP_ECRED_RECONF_REQ: 633915f02b91SLuiz Augusto von Dentz err = l2cap_ecred_reconf_req(conn, cmd, cmd_len, data); 634015f02b91SLuiz Augusto von Dentz break; 634115f02b91SLuiz Augusto von Dentz 634215f02b91SLuiz Augusto von Dentz case L2CAP_ECRED_RECONF_RSP: 634315f02b91SLuiz Augusto von Dentz err = l2cap_ecred_reconf_rsp(conn, cmd, cmd_len, data); 634415f02b91SLuiz Augusto von Dentz break; 634515f02b91SLuiz Augusto von Dentz 63463defe01aSJohan Hedberg case L2CAP_DISCONN_REQ: 6347b5ecba64SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data); 6348b5ecba64SJohan Hedberg break; 63493defe01aSJohan Hedberg 63503defe01aSJohan Hedberg case L2CAP_DISCONN_RSP: 63513defe01aSJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data); 6352b5ecba64SJohan Hedberg break; 63533defe01aSJohan Hedberg 63543300d9a9SClaudio Takahasi default: 63553300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code); 6356b5ecba64SJohan Hedberg err = -EINVAL; 6357b5ecba64SJohan Hedberg break; 63583300d9a9SClaudio Takahasi } 6359b5ecba64SJohan Hedberg 6360b5ecba64SJohan Hedberg return err; 63613300d9a9SClaudio Takahasi } 63623300d9a9SClaudio Takahasi 6363c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn, 6364c5623556SJohan Hedberg struct sk_buff *skb) 6365c5623556SJohan Hedberg { 636669c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon; 63674f3e219dSMarcel Holtmann struct l2cap_cmd_hdr *cmd; 63684f3e219dSMarcel Holtmann u16 len; 6369c5623556SJohan Hedberg int err; 6370c5623556SJohan Hedberg 637169c4e4e8SJohan Hedberg if (hcon->type != LE_LINK) 63723b166295SMarcel Holtmann goto drop; 637369c4e4e8SJohan Hedberg 63744f3e219dSMarcel Holtmann if (skb->len < L2CAP_CMD_HDR_SIZE) 63754f3e219dSMarcel Holtmann goto drop; 6376c5623556SJohan Hedberg 63774f3e219dSMarcel Holtmann cmd = (void *) skb->data; 63784f3e219dSMarcel Holtmann skb_pull(skb, L2CAP_CMD_HDR_SIZE); 6379c5623556SJohan Hedberg 63804f3e219dSMarcel Holtmann len = le16_to_cpu(cmd->len); 6381c5623556SJohan Hedberg 63824f3e219dSMarcel Holtmann BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident); 63834f3e219dSMarcel Holtmann 63844f3e219dSMarcel Holtmann if (len != skb->len || !cmd->ident) { 6385c5623556SJohan Hedberg BT_DBG("corrupted command"); 63864f3e219dSMarcel Holtmann goto drop; 6387c5623556SJohan Hedberg } 6388c5623556SJohan Hedberg 6389203e639eSJohan Hedberg err = l2cap_le_sig_cmd(conn, cmd, len, skb->data); 6390c5623556SJohan Hedberg if (err) { 6391c5623556SJohan Hedberg struct l2cap_cmd_rej_unk rej; 6392c5623556SJohan Hedberg 6393c5623556SJohan Hedberg BT_ERR("Wrong link type (%d)", err); 6394c5623556SJohan Hedberg 6395dcf4adbfSJoe Perches rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 63964f3e219dSMarcel Holtmann l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 6397c5623556SJohan Hedberg sizeof(rej), &rej); 6398c5623556SJohan Hedberg } 6399c5623556SJohan Hedberg 64003b166295SMarcel Holtmann drop: 6401c5623556SJohan Hedberg kfree_skb(skb); 6402c5623556SJohan Hedberg } 6403c5623556SJohan Hedberg 64043300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn, 64053300d9a9SClaudio Takahasi struct sk_buff *skb) 64060a708f8fSGustavo F. Padovan { 640769c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon; 640855cee73eSLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd; 64093300d9a9SClaudio Takahasi int err; 64100a708f8fSGustavo F. Padovan 64110a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb); 64120a708f8fSGustavo F. Padovan 641369c4e4e8SJohan Hedberg if (hcon->type != ACL_LINK) 64143b166295SMarcel Holtmann goto drop; 641569c4e4e8SJohan Hedberg 641655cee73eSLuiz Augusto von Dentz while (skb->len >= L2CAP_CMD_HDR_SIZE) { 641755cee73eSLuiz Augusto von Dentz u16 len; 64180a708f8fSGustavo F. Padovan 641955cee73eSLuiz Augusto von Dentz cmd = (void *) skb->data; 642055cee73eSLuiz Augusto von Dentz skb_pull(skb, L2CAP_CMD_HDR_SIZE); 64210a708f8fSGustavo F. Padovan 642255cee73eSLuiz Augusto von Dentz len = le16_to_cpu(cmd->len); 64230a708f8fSGustavo F. Padovan 642455cee73eSLuiz Augusto von Dentz BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, 642555cee73eSLuiz Augusto von Dentz cmd->ident); 642655cee73eSLuiz Augusto von Dentz 642755cee73eSLuiz Augusto von Dentz if (len > skb->len || !cmd->ident) { 64280a708f8fSGustavo F. Padovan BT_DBG("corrupted command"); 64290a708f8fSGustavo F. Padovan break; 64300a708f8fSGustavo F. Padovan } 64310a708f8fSGustavo F. Padovan 643255cee73eSLuiz Augusto von Dentz err = l2cap_bredr_sig_cmd(conn, cmd, len, skb->data); 64330a708f8fSGustavo F. Padovan if (err) { 6434e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk rej; 64352c6d1a2eSGustavo F. Padovan 64362c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err); 64370a708f8fSGustavo F. Padovan 6438dcf4adbfSJoe Perches rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 643955cee73eSLuiz Augusto von Dentz l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 64402d792818SGustavo Padovan sizeof(rej), &rej); 64410a708f8fSGustavo F. Padovan } 64420a708f8fSGustavo F. Padovan 644355cee73eSLuiz Augusto von Dentz skb_pull(skb, len); 64440a708f8fSGustavo F. Padovan } 64450a708f8fSGustavo F. Padovan 64463b166295SMarcel Holtmann drop: 64470a708f8fSGustavo F. Padovan kfree_skb(skb); 64480a708f8fSGustavo F. Padovan } 64490a708f8fSGustavo F. Padovan 645047d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) 64510a708f8fSGustavo F. Padovan { 64520a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs; 6453e4ca6d98SAndrei Emeltchenko int hdr_size; 6454e4ca6d98SAndrei Emeltchenko 6455e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 6456e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE; 6457e4ca6d98SAndrei Emeltchenko else 6458e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE; 64590a708f8fSGustavo F. Padovan 646047d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 646103a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE); 64620a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len); 64630a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); 64640a708f8fSGustavo F. Padovan 64650a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs) 64660a708f8fSGustavo F. Padovan return -EBADMSG; 64670a708f8fSGustavo F. Padovan } 64680a708f8fSGustavo F. Padovan return 0; 64690a708f8fSGustavo F. Padovan } 64700a708f8fSGustavo F. Padovan 64716ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) 64720a708f8fSGustavo F. Padovan { 6473e31f7633SMat Martineau struct l2cap_ctrl control; 64740a708f8fSGustavo F. Padovan 6475e31f7633SMat Martineau BT_DBG("chan %p", chan); 64760a708f8fSGustavo F. Padovan 6477e31f7633SMat Martineau memset(&control, 0, sizeof(control)); 6478e31f7633SMat Martineau control.sframe = 1; 6479e31f7633SMat Martineau control.final = 1; 6480e31f7633SMat Martineau control.reqseq = chan->buffer_seq; 6481e31f7633SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 64820a708f8fSGustavo F. Padovan 6483e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 6484e31f7633SMat Martineau control.super = L2CAP_SUPER_RNR; 6485e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 64860a708f8fSGustavo F. Padovan } 64870a708f8fSGustavo F. Padovan 6488e31f7633SMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 6489e31f7633SMat Martineau chan->unacked_frames > 0) 6490e31f7633SMat Martineau __set_retrans_timer(chan); 64910a708f8fSGustavo F. Padovan 6492e31f7633SMat Martineau /* Send pending iframes */ 6493525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 64940a708f8fSGustavo F. Padovan 6495e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 6496e31f7633SMat Martineau test_bit(CONN_SEND_FBIT, &chan->conn_state)) { 6497e31f7633SMat Martineau /* F-bit wasn't sent in an s-frame or i-frame yet, so 6498e31f7633SMat Martineau * send it now. 6499e31f7633SMat Martineau */ 6500e31f7633SMat Martineau control.super = L2CAP_SUPER_RR; 6501e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 65020a708f8fSGustavo F. Padovan } 65030a708f8fSGustavo F. Padovan } 65040a708f8fSGustavo F. Padovan 65052d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag, 65062d792818SGustavo Padovan struct sk_buff **last_frag) 65070a708f8fSGustavo F. Padovan { 650884084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments 650984084a31SMat Martineau * skb->data_len reflects only data in fragments 651084084a31SMat Martineau */ 651184084a31SMat Martineau if (!skb_has_frag_list(skb)) 651284084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag; 651384084a31SMat Martineau 651484084a31SMat Martineau new_frag->next = NULL; 651584084a31SMat Martineau 651684084a31SMat Martineau (*last_frag)->next = new_frag; 651784084a31SMat Martineau *last_frag = new_frag; 651884084a31SMat Martineau 651984084a31SMat Martineau skb->len += new_frag->len; 652084084a31SMat Martineau skb->data_len += new_frag->len; 652184084a31SMat Martineau skb->truesize += new_frag->truesize; 652284084a31SMat Martineau } 652384084a31SMat Martineau 65244b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, 65254b51dae9SMat Martineau struct l2cap_ctrl *control) 652684084a31SMat Martineau { 652784084a31SMat Martineau int err = -EINVAL; 65280a708f8fSGustavo F. Padovan 65294b51dae9SMat Martineau switch (control->sar) { 65307e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED: 653184084a31SMat Martineau if (chan->sdu) 653284084a31SMat Martineau break; 65330a708f8fSGustavo F. Padovan 653480b98027SGustavo Padovan err = chan->ops->recv(chan, skb); 653584084a31SMat Martineau break; 65360a708f8fSGustavo F. Padovan 65377e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START: 653884084a31SMat Martineau if (chan->sdu) 653984084a31SMat Martineau break; 65400a708f8fSGustavo F. Padovan 6541dbb50887SDaniel Borkmann if (!pskb_may_pull(skb, L2CAP_SDULEN_SIZE)) 6542dbb50887SDaniel Borkmann break; 6543dbb50887SDaniel Borkmann 65446f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data); 654503a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE); 65460a708f8fSGustavo F. Padovan 654784084a31SMat Martineau if (chan->sdu_len > chan->imtu) { 654884084a31SMat Martineau err = -EMSGSIZE; 654984084a31SMat Martineau break; 655084084a31SMat Martineau } 65510a708f8fSGustavo F. Padovan 655284084a31SMat Martineau if (skb->len >= chan->sdu_len) 655384084a31SMat Martineau break; 655484084a31SMat Martineau 655584084a31SMat Martineau chan->sdu = skb; 655684084a31SMat Martineau chan->sdu_last_frag = skb; 655784084a31SMat Martineau 655884084a31SMat Martineau skb = NULL; 655984084a31SMat Martineau err = 0; 65600a708f8fSGustavo F. Padovan break; 65610a708f8fSGustavo F. Padovan 65627e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE: 65636f61fd47SGustavo F. Padovan if (!chan->sdu) 656484084a31SMat Martineau break; 65650a708f8fSGustavo F. Padovan 656684084a31SMat Martineau append_skb_frag(chan->sdu, skb, 656784084a31SMat Martineau &chan->sdu_last_frag); 656884084a31SMat Martineau skb = NULL; 65690a708f8fSGustavo F. Padovan 657084084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len) 657184084a31SMat Martineau break; 65720a708f8fSGustavo F. Padovan 657384084a31SMat Martineau err = 0; 65740a708f8fSGustavo F. Padovan break; 65750a708f8fSGustavo F. Padovan 65767e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END: 65776f61fd47SGustavo F. Padovan if (!chan->sdu) 657884084a31SMat Martineau break; 65790a708f8fSGustavo F. Padovan 658084084a31SMat Martineau append_skb_frag(chan->sdu, skb, 658184084a31SMat Martineau &chan->sdu_last_frag); 658284084a31SMat Martineau skb = NULL; 65830a708f8fSGustavo F. Padovan 658484084a31SMat Martineau if (chan->sdu->len != chan->sdu_len) 658584084a31SMat Martineau break; 65860a708f8fSGustavo F. Padovan 658780b98027SGustavo Padovan err = chan->ops->recv(chan, chan->sdu); 65880a708f8fSGustavo F. Padovan 658984084a31SMat Martineau if (!err) { 659084084a31SMat Martineau /* Reassembly complete */ 659184084a31SMat Martineau chan->sdu = NULL; 659284084a31SMat Martineau chan->sdu_last_frag = NULL; 659384084a31SMat Martineau chan->sdu_len = 0; 65940a708f8fSGustavo F. Padovan } 65950a708f8fSGustavo F. Padovan break; 65960a708f8fSGustavo F. Padovan } 65970a708f8fSGustavo F. Padovan 659884084a31SMat Martineau if (err) { 65990a708f8fSGustavo F. Padovan kfree_skb(skb); 66006f61fd47SGustavo F. Padovan kfree_skb(chan->sdu); 66016f61fd47SGustavo F. Padovan chan->sdu = NULL; 660284084a31SMat Martineau chan->sdu_last_frag = NULL; 660384084a31SMat Martineau chan->sdu_len = 0; 660484084a31SMat Martineau } 66050a708f8fSGustavo F. Padovan 660684084a31SMat Martineau return err; 66070a708f8fSGustavo F. Padovan } 66080a708f8fSGustavo F. Padovan 660932b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan) 661032b32735SMat Martineau { 661132b32735SMat Martineau /* Placeholder */ 661232b32735SMat Martineau return 0; 661332b32735SMat Martineau } 661432b32735SMat Martineau 6615e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 66160a708f8fSGustavo F. Padovan { 661761aa4f5bSMat Martineau u8 event; 661861aa4f5bSMat Martineau 661961aa4f5bSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 662061aa4f5bSMat Martineau return; 662161aa4f5bSMat Martineau 662261aa4f5bSMat Martineau event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR; 6623401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, event); 66240a708f8fSGustavo F. Padovan } 66250a708f8fSGustavo F. Padovan 6626d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan) 6627d2a7ac5dSMat Martineau { 662863838725SMat Martineau int err = 0; 662963838725SMat Martineau /* Pass sequential frames to l2cap_reassemble_sdu() 663063838725SMat Martineau * until a gap is encountered. 663163838725SMat Martineau */ 663263838725SMat Martineau 663363838725SMat Martineau BT_DBG("chan %p", chan); 663463838725SMat Martineau 663563838725SMat Martineau while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 663663838725SMat Martineau struct sk_buff *skb; 663763838725SMat Martineau BT_DBG("Searching for skb with txseq %d (queue len %d)", 663863838725SMat Martineau chan->buffer_seq, skb_queue_len(&chan->srej_q)); 663963838725SMat Martineau 664063838725SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq); 664163838725SMat Martineau 664263838725SMat Martineau if (!skb) 664363838725SMat Martineau break; 664463838725SMat Martineau 664563838725SMat Martineau skb_unlink(skb, &chan->srej_q); 664663838725SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 6647a4368ff3SJohan Hedberg err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->l2cap); 664863838725SMat Martineau if (err) 664963838725SMat Martineau break; 665063838725SMat Martineau } 665163838725SMat Martineau 665263838725SMat Martineau if (skb_queue_empty(&chan->srej_q)) { 665363838725SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 665463838725SMat Martineau l2cap_send_ack(chan); 665563838725SMat Martineau } 665663838725SMat Martineau 665763838725SMat Martineau return err; 6658d2a7ac5dSMat Martineau } 6659d2a7ac5dSMat Martineau 6660d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan, 6661d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 6662d2a7ac5dSMat Martineau { 6663f80842a8SMat Martineau struct sk_buff *skb; 6664f80842a8SMat Martineau 6665f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 6666f80842a8SMat Martineau 6667f80842a8SMat Martineau if (control->reqseq == chan->next_tx_seq) { 6668f80842a8SMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 66695e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6670f80842a8SMat Martineau return; 6671f80842a8SMat Martineau } 6672f80842a8SMat Martineau 6673f80842a8SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 6674f80842a8SMat Martineau 6675f80842a8SMat Martineau if (skb == NULL) { 6676f80842a8SMat Martineau BT_DBG("Seq %d not available for retransmission", 6677f80842a8SMat Martineau control->reqseq); 6678f80842a8SMat Martineau return; 6679f80842a8SMat Martineau } 6680f80842a8SMat Martineau 6681a4368ff3SJohan Hedberg if (chan->max_tx != 0 && bt_cb(skb)->l2cap.retries >= chan->max_tx) { 6682f80842a8SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 66835e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6684f80842a8SMat Martineau return; 6685f80842a8SMat Martineau } 6686f80842a8SMat Martineau 6687f80842a8SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6688f80842a8SMat Martineau 6689f80842a8SMat Martineau if (control->poll) { 6690f80842a8SMat Martineau l2cap_pass_to_tx(chan, control); 6691f80842a8SMat Martineau 6692f80842a8SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6693f80842a8SMat Martineau l2cap_retransmit(chan, control); 6694f80842a8SMat Martineau l2cap_ertm_send(chan); 6695f80842a8SMat Martineau 6696f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 6697f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 6698f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 6699f80842a8SMat Martineau } 6700f80842a8SMat Martineau } else { 6701f80842a8SMat Martineau l2cap_pass_to_tx_fbit(chan, control); 6702f80842a8SMat Martineau 6703f80842a8SMat Martineau if (control->final) { 6704f80842a8SMat Martineau if (chan->srej_save_reqseq != control->reqseq || 6705f80842a8SMat Martineau !test_and_clear_bit(CONN_SREJ_ACT, 6706f80842a8SMat Martineau &chan->conn_state)) 6707f80842a8SMat Martineau l2cap_retransmit(chan, control); 6708f80842a8SMat Martineau } else { 6709f80842a8SMat Martineau l2cap_retransmit(chan, control); 6710f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 6711f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 6712f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 6713f80842a8SMat Martineau } 6714f80842a8SMat Martineau } 6715f80842a8SMat Martineau } 6716d2a7ac5dSMat Martineau } 6717d2a7ac5dSMat Martineau 6718d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan, 6719d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 6720d2a7ac5dSMat Martineau { 6721fcd289dfSMat Martineau struct sk_buff *skb; 6722fcd289dfSMat Martineau 6723fcd289dfSMat Martineau BT_DBG("chan %p, control %p", chan, control); 6724fcd289dfSMat Martineau 6725fcd289dfSMat Martineau if (control->reqseq == chan->next_tx_seq) { 6726fcd289dfSMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 67275e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6728fcd289dfSMat Martineau return; 6729fcd289dfSMat Martineau } 6730fcd289dfSMat Martineau 6731fcd289dfSMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 6732fcd289dfSMat Martineau 6733fcd289dfSMat Martineau if (chan->max_tx && skb && 6734a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries >= chan->max_tx) { 6735fcd289dfSMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 67365e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6737fcd289dfSMat Martineau return; 6738fcd289dfSMat Martineau } 6739fcd289dfSMat Martineau 6740fcd289dfSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6741fcd289dfSMat Martineau 6742fcd289dfSMat Martineau l2cap_pass_to_tx(chan, control); 6743fcd289dfSMat Martineau 6744fcd289dfSMat Martineau if (control->final) { 6745fcd289dfSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 6746fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 6747fcd289dfSMat Martineau } else { 6748fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 6749fcd289dfSMat Martineau l2cap_ertm_send(chan); 6750fcd289dfSMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) 6751fcd289dfSMat Martineau set_bit(CONN_REJ_ACT, &chan->conn_state); 6752fcd289dfSMat Martineau } 6753d2a7ac5dSMat Martineau } 6754d2a7ac5dSMat Martineau 67554b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) 67564b51dae9SMat Martineau { 67574b51dae9SMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 67584b51dae9SMat Martineau 67594b51dae9SMat Martineau BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq, 67604b51dae9SMat Martineau chan->expected_tx_seq); 67614b51dae9SMat Martineau 67624b51dae9SMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 67634b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 67644b51dae9SMat Martineau chan->tx_win) { 67654b51dae9SMat Martineau /* See notes below regarding "double poll" and 67664b51dae9SMat Martineau * invalid packets. 67674b51dae9SMat Martineau */ 67684b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 67694b51dae9SMat Martineau BT_DBG("Invalid/Ignore - after SREJ"); 67704b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 67714b51dae9SMat Martineau } else { 67724b51dae9SMat Martineau BT_DBG("Invalid - in window after SREJ sent"); 67734b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 67744b51dae9SMat Martineau } 67754b51dae9SMat Martineau } 67764b51dae9SMat Martineau 67774b51dae9SMat Martineau if (chan->srej_list.head == txseq) { 67784b51dae9SMat Martineau BT_DBG("Expected SREJ"); 67794b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED_SREJ; 67804b51dae9SMat Martineau } 67814b51dae9SMat Martineau 67824b51dae9SMat Martineau if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) { 67834b51dae9SMat Martineau BT_DBG("Duplicate SREJ - txseq already stored"); 67844b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE_SREJ; 67854b51dae9SMat Martineau } 67864b51dae9SMat Martineau 67874b51dae9SMat Martineau if (l2cap_seq_list_contains(&chan->srej_list, txseq)) { 67884b51dae9SMat Martineau BT_DBG("Unexpected SREJ - not requested"); 67894b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED_SREJ; 67904b51dae9SMat Martineau } 67914b51dae9SMat Martineau } 67924b51dae9SMat Martineau 67934b51dae9SMat Martineau if (chan->expected_tx_seq == txseq) { 67944b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 67954b51dae9SMat Martineau chan->tx_win) { 67964b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 67974b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 67984b51dae9SMat Martineau } else { 67994b51dae9SMat Martineau BT_DBG("Expected"); 68004b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED; 68014b51dae9SMat Martineau } 68024b51dae9SMat Martineau } 68034b51dae9SMat Martineau 68044b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) < 68052d792818SGustavo Padovan __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) { 68064b51dae9SMat Martineau BT_DBG("Duplicate - expected_tx_seq later than txseq"); 68074b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE; 68084b51dae9SMat Martineau } 68094b51dae9SMat Martineau 68104b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) { 68114b51dae9SMat Martineau /* A source of invalid packets is a "double poll" condition, 68124b51dae9SMat Martineau * where delays cause us to send multiple poll packets. If 68134b51dae9SMat Martineau * the remote stack receives and processes both polls, 68144b51dae9SMat Martineau * sequence numbers can wrap around in such a way that a 68154b51dae9SMat Martineau * resent frame has a sequence number that looks like new data 68164b51dae9SMat Martineau * with a sequence gap. This would trigger an erroneous SREJ 68174b51dae9SMat Martineau * request. 68184b51dae9SMat Martineau * 68194b51dae9SMat Martineau * Fortunately, this is impossible with a tx window that's 68204b51dae9SMat Martineau * less than half of the maximum sequence number, which allows 68214b51dae9SMat Martineau * invalid frames to be safely ignored. 68224b51dae9SMat Martineau * 68234b51dae9SMat Martineau * With tx window sizes greater than half of the tx window 68244b51dae9SMat Martineau * maximum, the frame is invalid and cannot be ignored. This 68254b51dae9SMat Martineau * causes a disconnect. 68264b51dae9SMat Martineau */ 68274b51dae9SMat Martineau 68284b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 68294b51dae9SMat Martineau BT_DBG("Invalid/Ignore - txseq outside tx window"); 68304b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 68314b51dae9SMat Martineau } else { 68324b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 68334b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 68344b51dae9SMat Martineau } 68354b51dae9SMat Martineau } else { 68364b51dae9SMat Martineau BT_DBG("Unexpected - txseq indicates missing frames"); 68374b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED; 68384b51dae9SMat Martineau } 68394b51dae9SMat Martineau } 68404b51dae9SMat Martineau 6841d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan, 6842d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 6843d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 6844d2a7ac5dSMat Martineau { 6845d2a7ac5dSMat Martineau int err = 0; 6846941247f9SPeter Senna Tschudin bool skb_in_use = false; 6847d2a7ac5dSMat Martineau 6848d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 6849d2a7ac5dSMat Martineau event); 6850d2a7ac5dSMat Martineau 6851d2a7ac5dSMat Martineau switch (event) { 6852d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 6853d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, control->txseq)) { 6854d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 6855d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6856d2a7ac5dSMat Martineau 6857d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 6858d2a7ac5dSMat Martineau BT_DBG("Busy, discarding expected seq %d", 6859d2a7ac5dSMat Martineau control->txseq); 6860d2a7ac5dSMat Martineau break; 6861d2a7ac5dSMat Martineau } 6862d2a7ac5dSMat Martineau 6863d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, 6864d2a7ac5dSMat Martineau control->txseq); 6865d2a7ac5dSMat Martineau 6866d2a7ac5dSMat Martineau chan->buffer_seq = chan->expected_tx_seq; 6867941247f9SPeter Senna Tschudin skb_in_use = true; 6868d2a7ac5dSMat Martineau 6869d2a7ac5dSMat Martineau err = l2cap_reassemble_sdu(chan, skb, control); 6870d2a7ac5dSMat Martineau if (err) 6871d2a7ac5dSMat Martineau break; 6872d2a7ac5dSMat Martineau 6873d2a7ac5dSMat Martineau if (control->final) { 6874d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 6875d2a7ac5dSMat Martineau &chan->conn_state)) { 6876d2a7ac5dSMat Martineau control->final = 0; 6877d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6878d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6879d2a7ac5dSMat Martineau } 6880d2a7ac5dSMat Martineau } 6881d2a7ac5dSMat Martineau 6882d2a7ac5dSMat Martineau if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 6883d2a7ac5dSMat Martineau l2cap_send_ack(chan); 6884d2a7ac5dSMat Martineau break; 6885d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 6886d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6887d2a7ac5dSMat Martineau 6888d2a7ac5dSMat Martineau /* Can't issue SREJ frames in the local busy state. 6889d2a7ac5dSMat Martineau * Drop this frame, it will be seen as missing 6890d2a7ac5dSMat Martineau * when local busy is exited. 6891d2a7ac5dSMat Martineau */ 6892d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 6893d2a7ac5dSMat Martineau BT_DBG("Busy, discarding unexpected seq %d", 6894d2a7ac5dSMat Martineau control->txseq); 6895d2a7ac5dSMat Martineau break; 6896d2a7ac5dSMat Martineau } 6897d2a7ac5dSMat Martineau 6898d2a7ac5dSMat Martineau /* There was a gap in the sequence, so an SREJ 6899d2a7ac5dSMat Martineau * must be sent for each missing frame. The 6900d2a7ac5dSMat Martineau * current frame is stored for later use. 6901d2a7ac5dSMat Martineau */ 6902d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6903941247f9SPeter Senna Tschudin skb_in_use = true; 6904d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6905d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6906d2a7ac5dSMat Martineau 6907d2a7ac5dSMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 6908d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 6909d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 6910d2a7ac5dSMat Martineau 6911d2a7ac5dSMat Martineau chan->rx_state = L2CAP_RX_STATE_SREJ_SENT; 6912d2a7ac5dSMat Martineau break; 6913d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 6914d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6915d2a7ac5dSMat Martineau break; 6916d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 6917d2a7ac5dSMat Martineau break; 6918d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 6919d2a7ac5dSMat Martineau default: 69205e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6921d2a7ac5dSMat Martineau break; 6922d2a7ac5dSMat Martineau } 6923d2a7ac5dSMat Martineau break; 6924d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 6925d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6926d2a7ac5dSMat Martineau if (control->final) { 6927d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6928d2a7ac5dSMat Martineau 6929e6a3ee6eSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) && 6930e6a3ee6eSMat Martineau !__chan_is_moving(chan)) { 6931d2a7ac5dSMat Martineau control->final = 0; 6932d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6933d2a7ac5dSMat Martineau } 6934d2a7ac5dSMat Martineau 6935d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6936d2a7ac5dSMat Martineau } else if (control->poll) { 6937d2a7ac5dSMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 6938d2a7ac5dSMat Martineau } else { 6939d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6940d2a7ac5dSMat Martineau &chan->conn_state) && 6941d2a7ac5dSMat Martineau chan->unacked_frames) 6942d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6943d2a7ac5dSMat Martineau 6944d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6945d2a7ac5dSMat Martineau } 6946d2a7ac5dSMat Martineau break; 6947d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 6948d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6949d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6950d2a7ac5dSMat Martineau if (control && control->poll) { 6951d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6952d2a7ac5dSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 6953d2a7ac5dSMat Martineau } 6954d2a7ac5dSMat Martineau __clear_retrans_timer(chan); 6955d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 6956d2a7ac5dSMat Martineau break; 6957d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 6958d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 6959d2a7ac5dSMat Martineau break; 6960d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 6961d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 6962d2a7ac5dSMat Martineau break; 6963d2a7ac5dSMat Martineau default: 6964d2a7ac5dSMat Martineau break; 6965d2a7ac5dSMat Martineau } 6966d2a7ac5dSMat Martineau 6967d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 6968d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 6969d2a7ac5dSMat Martineau kfree_skb(skb); 6970d2a7ac5dSMat Martineau } 6971d2a7ac5dSMat Martineau 6972d2a7ac5dSMat Martineau return err; 6973d2a7ac5dSMat Martineau } 6974d2a7ac5dSMat Martineau 6975d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, 6976d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 6977d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 6978d2a7ac5dSMat Martineau { 6979d2a7ac5dSMat Martineau int err = 0; 6980d2a7ac5dSMat Martineau u16 txseq = control->txseq; 6981941247f9SPeter Senna Tschudin bool skb_in_use = false; 6982d2a7ac5dSMat Martineau 6983d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 6984d2a7ac5dSMat Martineau event); 6985d2a7ac5dSMat Martineau 6986d2a7ac5dSMat Martineau switch (event) { 6987d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 6988d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, txseq)) { 6989d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 6990d2a7ac5dSMat Martineau /* Keep frame for reassembly later */ 6991d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6992d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6993941247f9SPeter Senna Tschudin skb_in_use = true; 6994d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6995d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6996d2a7ac5dSMat Martineau 6997d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 6998d2a7ac5dSMat Martineau break; 6999d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED_SREJ: 7000d2a7ac5dSMat Martineau l2cap_seq_list_pop(&chan->srej_list); 7001d2a7ac5dSMat Martineau 7002d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7003d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 7004941247f9SPeter Senna Tschudin skb_in_use = true; 7005d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 7006d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 7007d2a7ac5dSMat Martineau 7008d2a7ac5dSMat Martineau err = l2cap_rx_queued_iframes(chan); 7009d2a7ac5dSMat Martineau if (err) 7010d2a7ac5dSMat Martineau break; 7011d2a7ac5dSMat Martineau 7012d2a7ac5dSMat Martineau break; 7013d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 7014d2a7ac5dSMat Martineau /* Got a frame that can't be reassembled yet. 7015d2a7ac5dSMat Martineau * Save it for later, and send SREJs to cover 7016d2a7ac5dSMat Martineau * the missing frames. 7017d2a7ac5dSMat Martineau */ 7018d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 7019941247f9SPeter Senna Tschudin skb_in_use = true; 7020d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 7021d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 7022d2a7ac5dSMat Martineau 7023d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7024d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 7025d2a7ac5dSMat Martineau break; 7026d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED_SREJ: 7027d2a7ac5dSMat Martineau /* This frame was requested with an SREJ, but 7028d2a7ac5dSMat Martineau * some expected retransmitted frames are 7029d2a7ac5dSMat Martineau * missing. Request retransmission of missing 7030d2a7ac5dSMat Martineau * SREJ'd frames. 7031d2a7ac5dSMat Martineau */ 7032d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 7033941247f9SPeter Senna Tschudin skb_in_use = true; 7034d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 7035d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 7036d2a7ac5dSMat Martineau 7037d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7038d2a7ac5dSMat Martineau l2cap_send_srej_list(chan, control->txseq); 7039d2a7ac5dSMat Martineau break; 7040d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE_SREJ: 7041d2a7ac5dSMat Martineau /* We've already queued this frame. Drop this copy. */ 7042d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7043d2a7ac5dSMat Martineau break; 7044d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 7045d2a7ac5dSMat Martineau /* Expecting a later sequence number, so this frame 7046d2a7ac5dSMat Martineau * was already received. Ignore it completely. 7047d2a7ac5dSMat Martineau */ 7048d2a7ac5dSMat Martineau break; 7049d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 7050d2a7ac5dSMat Martineau break; 7051d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 7052d2a7ac5dSMat Martineau default: 70535e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 7054d2a7ac5dSMat Martineau break; 7055d2a7ac5dSMat Martineau } 7056d2a7ac5dSMat Martineau break; 7057d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 7058d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7059d2a7ac5dSMat Martineau if (control->final) { 7060d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 7061d2a7ac5dSMat Martineau 7062d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 7063d2a7ac5dSMat Martineau &chan->conn_state)) { 7064d2a7ac5dSMat Martineau control->final = 0; 7065d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 7066d2a7ac5dSMat Martineau } 7067d2a7ac5dSMat Martineau 7068d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 7069d2a7ac5dSMat Martineau } else if (control->poll) { 7070d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 7071d2a7ac5dSMat Martineau &chan->conn_state) && 7072d2a7ac5dSMat Martineau chan->unacked_frames) { 7073d2a7ac5dSMat Martineau __set_retrans_timer(chan); 7074d2a7ac5dSMat Martineau } 7075d2a7ac5dSMat Martineau 7076d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 7077d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 7078d2a7ac5dSMat Martineau } else { 7079d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 7080d2a7ac5dSMat Martineau &chan->conn_state) && 7081d2a7ac5dSMat Martineau chan->unacked_frames) 7082d2a7ac5dSMat Martineau __set_retrans_timer(chan); 7083d2a7ac5dSMat Martineau 7084d2a7ac5dSMat Martineau l2cap_send_ack(chan); 7085d2a7ac5dSMat Martineau } 7086d2a7ac5dSMat Martineau break; 7087d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 7088d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 7089d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7090d2a7ac5dSMat Martineau if (control->poll) { 7091d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 7092d2a7ac5dSMat Martineau } else { 7093d2a7ac5dSMat Martineau struct l2cap_ctrl rr_control; 7094d2a7ac5dSMat Martineau memset(&rr_control, 0, sizeof(rr_control)); 7095d2a7ac5dSMat Martineau rr_control.sframe = 1; 7096d2a7ac5dSMat Martineau rr_control.super = L2CAP_SUPER_RR; 7097d2a7ac5dSMat Martineau rr_control.reqseq = chan->buffer_seq; 7098d2a7ac5dSMat Martineau l2cap_send_sframe(chan, &rr_control); 7099d2a7ac5dSMat Martineau } 7100d2a7ac5dSMat Martineau 7101d2a7ac5dSMat Martineau break; 7102d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 7103d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 7104d2a7ac5dSMat Martineau break; 7105d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 7106d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 7107d2a7ac5dSMat Martineau break; 7108d2a7ac5dSMat Martineau } 7109d2a7ac5dSMat Martineau 7110d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 7111d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 7112d2a7ac5dSMat Martineau kfree_skb(skb); 7113d2a7ac5dSMat Martineau } 7114d2a7ac5dSMat Martineau 7115d2a7ac5dSMat Martineau return err; 7116d2a7ac5dSMat Martineau } 7117d2a7ac5dSMat Martineau 711832b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan) 711932b32735SMat Martineau { 712032b32735SMat Martineau BT_DBG("chan %p", chan); 712132b32735SMat Martineau 712232b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 712332b32735SMat Martineau 712432b32735SMat Martineau if (chan->hs_hcon) 712532b32735SMat Martineau chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; 712632b32735SMat Martineau else 712732b32735SMat Martineau chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; 712832b32735SMat Martineau 712932b32735SMat Martineau return l2cap_resegment(chan); 713032b32735SMat Martineau } 713132b32735SMat Martineau 713232b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan, 713332b32735SMat Martineau struct l2cap_ctrl *control, 713432b32735SMat Martineau struct sk_buff *skb, u8 event) 713532b32735SMat Martineau { 713632b32735SMat Martineau int err; 713732b32735SMat Martineau 713832b32735SMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 713932b32735SMat Martineau event); 714032b32735SMat Martineau 714132b32735SMat Martineau if (!control->poll) 714232b32735SMat Martineau return -EPROTO; 714332b32735SMat Martineau 714432b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq); 714532b32735SMat Martineau 714632b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q)) 714732b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q); 714832b32735SMat Martineau else 714932b32735SMat Martineau chan->tx_send_head = NULL; 715032b32735SMat Martineau 715132b32735SMat Martineau /* Rewind next_tx_seq to the point expected 715232b32735SMat Martineau * by the receiver. 715332b32735SMat Martineau */ 715432b32735SMat Martineau chan->next_tx_seq = control->reqseq; 715532b32735SMat Martineau chan->unacked_frames = 0; 715632b32735SMat Martineau 715732b32735SMat Martineau err = l2cap_finish_move(chan); 715832b32735SMat Martineau if (err) 715932b32735SMat Martineau return err; 716032b32735SMat Martineau 716132b32735SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 716232b32735SMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 716332b32735SMat Martineau 716432b32735SMat Martineau if (event == L2CAP_EV_RECV_IFRAME) 716532b32735SMat Martineau return -EPROTO; 716632b32735SMat Martineau 716732b32735SMat Martineau return l2cap_rx_state_recv(chan, control, NULL, event); 716832b32735SMat Martineau } 716932b32735SMat Martineau 717032b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan, 717132b32735SMat Martineau struct l2cap_ctrl *control, 717232b32735SMat Martineau struct sk_buff *skb, u8 event) 717332b32735SMat Martineau { 717432b32735SMat Martineau int err; 717532b32735SMat Martineau 717632b32735SMat Martineau if (!control->final) 717732b32735SMat Martineau return -EPROTO; 717832b32735SMat Martineau 717932b32735SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 718032b32735SMat Martineau 718132b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 718232b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq); 718332b32735SMat Martineau 718432b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q)) 718532b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q); 718632b32735SMat Martineau else 718732b32735SMat Martineau chan->tx_send_head = NULL; 718832b32735SMat Martineau 718932b32735SMat Martineau /* Rewind next_tx_seq to the point expected 719032b32735SMat Martineau * by the receiver. 719132b32735SMat Martineau */ 719232b32735SMat Martineau chan->next_tx_seq = control->reqseq; 719332b32735SMat Martineau chan->unacked_frames = 0; 719432b32735SMat Martineau 719532b32735SMat Martineau if (chan->hs_hcon) 719632b32735SMat Martineau chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; 719732b32735SMat Martineau else 719832b32735SMat Martineau chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; 719932b32735SMat Martineau 720032b32735SMat Martineau err = l2cap_resegment(chan); 720132b32735SMat Martineau 720232b32735SMat Martineau if (!err) 720332b32735SMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 720432b32735SMat Martineau 720532b32735SMat Martineau return err; 720632b32735SMat Martineau } 720732b32735SMat Martineau 7208d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq) 7209d2a7ac5dSMat Martineau { 7210d2a7ac5dSMat Martineau /* Make sure reqseq is for a packet that has been sent but not acked */ 7211d2a7ac5dSMat Martineau u16 unacked; 7212d2a7ac5dSMat Martineau 7213d2a7ac5dSMat Martineau unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq); 7214d2a7ac5dSMat Martineau return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked; 7215d2a7ac5dSMat Martineau } 7216d2a7ac5dSMat Martineau 7217cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 7218cec8ab6eSMat Martineau struct sk_buff *skb, u8 event) 72190a708f8fSGustavo F. Padovan { 7220d2a7ac5dSMat Martineau int err = 0; 7221d2a7ac5dSMat Martineau 7222d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan, 7223d2a7ac5dSMat Martineau control, skb, event, chan->rx_state); 7224d2a7ac5dSMat Martineau 7225d2a7ac5dSMat Martineau if (__valid_reqseq(chan, control->reqseq)) { 7226d2a7ac5dSMat Martineau switch (chan->rx_state) { 7227d2a7ac5dSMat Martineau case L2CAP_RX_STATE_RECV: 7228d2a7ac5dSMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 7229d2a7ac5dSMat Martineau break; 7230d2a7ac5dSMat Martineau case L2CAP_RX_STATE_SREJ_SENT: 7231d2a7ac5dSMat Martineau err = l2cap_rx_state_srej_sent(chan, control, skb, 7232d2a7ac5dSMat Martineau event); 7233d2a7ac5dSMat Martineau break; 723432b32735SMat Martineau case L2CAP_RX_STATE_WAIT_P: 723532b32735SMat Martineau err = l2cap_rx_state_wait_p(chan, control, skb, event); 723632b32735SMat Martineau break; 723732b32735SMat Martineau case L2CAP_RX_STATE_WAIT_F: 723832b32735SMat Martineau err = l2cap_rx_state_wait_f(chan, control, skb, event); 723932b32735SMat Martineau break; 7240d2a7ac5dSMat Martineau default: 7241d2a7ac5dSMat Martineau /* shut it down */ 7242d2a7ac5dSMat Martineau break; 7243d2a7ac5dSMat Martineau } 7244d2a7ac5dSMat Martineau } else { 7245d2a7ac5dSMat Martineau BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d", 7246d2a7ac5dSMat Martineau control->reqseq, chan->next_tx_seq, 7247d2a7ac5dSMat Martineau chan->expected_ack_seq); 72485e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 7249d2a7ac5dSMat Martineau } 7250d2a7ac5dSMat Martineau 7251d2a7ac5dSMat Martineau return err; 7252cec8ab6eSMat Martineau } 7253cec8ab6eSMat Martineau 7254cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 7255cec8ab6eSMat Martineau struct sk_buff *skb) 7256cec8ab6eSMat Martineau { 72574b51dae9SMat Martineau BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb, 72584b51dae9SMat Martineau chan->rx_state); 72594b51dae9SMat Martineau 72604b51dae9SMat Martineau if (l2cap_classify_txseq(chan, control->txseq) == 72614b51dae9SMat Martineau L2CAP_TXSEQ_EXPECTED) { 72624b51dae9SMat Martineau l2cap_pass_to_tx(chan, control); 72634b51dae9SMat Martineau 72644b51dae9SMat Martineau BT_DBG("buffer_seq %d->%d", chan->buffer_seq, 72654b51dae9SMat Martineau __next_seq(chan, chan->buffer_seq)); 72664b51dae9SMat Martineau 72674b51dae9SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 72684b51dae9SMat Martineau 72694b51dae9SMat Martineau l2cap_reassemble_sdu(chan, skb, control); 72704b51dae9SMat Martineau } else { 72714b51dae9SMat Martineau if (chan->sdu) { 72724b51dae9SMat Martineau kfree_skb(chan->sdu); 72734b51dae9SMat Martineau chan->sdu = NULL; 72744b51dae9SMat Martineau } 72754b51dae9SMat Martineau chan->sdu_last_frag = NULL; 72764b51dae9SMat Martineau chan->sdu_len = 0; 72774b51dae9SMat Martineau 72784b51dae9SMat Martineau if (skb) { 72794b51dae9SMat Martineau BT_DBG("Freeing %p", skb); 72804b51dae9SMat Martineau kfree_skb(skb); 72814b51dae9SMat Martineau } 72824b51dae9SMat Martineau } 72834b51dae9SMat Martineau 72844b51dae9SMat Martineau chan->last_acked_seq = control->txseq; 72854b51dae9SMat Martineau chan->expected_tx_seq = __next_seq(chan, control->txseq); 72864b51dae9SMat Martineau 72879a544210SPrasanna Karthik return 0; 7288cec8ab6eSMat Martineau } 7289cec8ab6eSMat Martineau 7290cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 7291cec8ab6eSMat Martineau { 7292a4368ff3SJohan Hedberg struct l2cap_ctrl *control = &bt_cb(skb)->l2cap; 7293cec8ab6eSMat Martineau u16 len; 7294cec8ab6eSMat Martineau u8 event; 72950a708f8fSGustavo F. Padovan 7296b76bbd66SMat Martineau __unpack_control(chan, skb); 7297b76bbd66SMat Martineau 72980a708f8fSGustavo F. Padovan len = skb->len; 72990a708f8fSGustavo F. Padovan 73000a708f8fSGustavo F. Padovan /* 73010a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here. 73020a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery 7303cec8ab6eSMat Martineau * procedures and ask for retransmission. 73040a708f8fSGustavo F. Padovan */ 730547d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 73060a708f8fSGustavo F. Padovan goto drop; 73070a708f8fSGustavo F. Padovan 7308cec8ab6eSMat Martineau if (!control->sframe && control->sar == L2CAP_SAR_START) 730903a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 73100a708f8fSGustavo F. Padovan 731147d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 731203a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 73130a708f8fSGustavo F. Padovan 731447d1ec61SGustavo F. Padovan if (len > chan->mps) { 73155e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 73160a708f8fSGustavo F. Padovan goto drop; 73170a708f8fSGustavo F. Padovan } 73180a708f8fSGustavo F. Padovan 7319f1942564SLuiz Augusto von Dentz if (chan->ops->filter) { 7320f1942564SLuiz Augusto von Dentz if (chan->ops->filter(chan, skb)) 7321dbb50887SDaniel Borkmann goto drop; 7322f1942564SLuiz Augusto von Dentz } 7323dbb50887SDaniel Borkmann 7324cec8ab6eSMat Martineau if (!control->sframe) { 7325cec8ab6eSMat Martineau int err; 73260a708f8fSGustavo F. Padovan 7327cec8ab6eSMat Martineau BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d", 7328cec8ab6eSMat Martineau control->sar, control->reqseq, control->final, 7329cec8ab6eSMat Martineau control->txseq); 7330836be934SAndrei Emeltchenko 7331cec8ab6eSMat Martineau /* Validate F-bit - F=0 always valid, F=1 only 7332cec8ab6eSMat Martineau * valid in TX WAIT_F 7333cec8ab6eSMat Martineau */ 7334cec8ab6eSMat Martineau if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F) 73350a708f8fSGustavo F. Padovan goto drop; 73360a708f8fSGustavo F. Padovan 7337cec8ab6eSMat Martineau if (chan->mode != L2CAP_MODE_STREAMING) { 7338cec8ab6eSMat Martineau event = L2CAP_EV_RECV_IFRAME; 7339cec8ab6eSMat Martineau err = l2cap_rx(chan, control, skb, event); 73400a708f8fSGustavo F. Padovan } else { 7341cec8ab6eSMat Martineau err = l2cap_stream_rx(chan, control, skb); 7342cec8ab6eSMat Martineau } 7343cec8ab6eSMat Martineau 7344cec8ab6eSMat Martineau if (err) 73455e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 7346cec8ab6eSMat Martineau } else { 7347cec8ab6eSMat Martineau const u8 rx_func_to_event[4] = { 7348cec8ab6eSMat Martineau L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ, 7349cec8ab6eSMat Martineau L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ 7350cec8ab6eSMat Martineau }; 7351cec8ab6eSMat Martineau 7352cec8ab6eSMat Martineau /* Only I-frames are expected in streaming mode */ 7353cec8ab6eSMat Martineau if (chan->mode == L2CAP_MODE_STREAMING) 7354cec8ab6eSMat Martineau goto drop; 7355cec8ab6eSMat Martineau 7356cec8ab6eSMat Martineau BT_DBG("sframe reqseq %d, final %d, poll %d, super %d", 7357cec8ab6eSMat Martineau control->reqseq, control->final, control->poll, 7358cec8ab6eSMat Martineau control->super); 7359cec8ab6eSMat Martineau 73600a708f8fSGustavo F. Padovan if (len != 0) { 73611bb166e6SAndrei Emeltchenko BT_ERR("Trailing bytes: %d in sframe", len); 73625e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 73630a708f8fSGustavo F. Padovan goto drop; 73640a708f8fSGustavo F. Padovan } 73650a708f8fSGustavo F. Padovan 7366cec8ab6eSMat Martineau /* Validate F and P bits */ 7367cec8ab6eSMat Martineau if (control->final && (control->poll || 7368cec8ab6eSMat Martineau chan->tx_state != L2CAP_TX_STATE_WAIT_F)) 7369cec8ab6eSMat Martineau goto drop; 7370cec8ab6eSMat Martineau 7371cec8ab6eSMat Martineau event = rx_func_to_event[control->super]; 7372cec8ab6eSMat Martineau if (l2cap_rx(chan, control, skb, event)) 73735e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 73740a708f8fSGustavo F. Padovan } 73750a708f8fSGustavo F. Padovan 73760a708f8fSGustavo F. Padovan return 0; 73770a708f8fSGustavo F. Padovan 73780a708f8fSGustavo F. Padovan drop: 73790a708f8fSGustavo F. Padovan kfree_skb(skb); 73800a708f8fSGustavo F. Padovan return 0; 73810a708f8fSGustavo F. Padovan } 73820a708f8fSGustavo F. Padovan 7383b1c325c2SJohan Hedberg static void l2cap_chan_le_send_credits(struct l2cap_chan *chan) 7384b1c325c2SJohan Hedberg { 7385b1c325c2SJohan Hedberg struct l2cap_conn *conn = chan->conn; 7386b1c325c2SJohan Hedberg struct l2cap_le_credits pkt; 7387b1c325c2SJohan Hedberg u16 return_credits; 7388b1c325c2SJohan Hedberg 738915f02b91SLuiz Augusto von Dentz return_credits = (chan->imtu / chan->mps) + 1; 7390b1c325c2SJohan Hedberg 739115f02b91SLuiz Augusto von Dentz if (chan->rx_credits >= return_credits) 739296cd8eaaSLuiz Augusto von Dentz return; 7393b1c325c2SJohan Hedberg 739415f02b91SLuiz Augusto von Dentz return_credits -= chan->rx_credits; 739515f02b91SLuiz Augusto von Dentz 7396b1c325c2SJohan Hedberg BT_DBG("chan %p returning %u credits to sender", chan, return_credits); 7397b1c325c2SJohan Hedberg 7398b1c325c2SJohan Hedberg chan->rx_credits += return_credits; 7399b1c325c2SJohan Hedberg 7400b1c325c2SJohan Hedberg pkt.cid = cpu_to_le16(chan->scid); 7401b1c325c2SJohan Hedberg pkt.credits = cpu_to_le16(return_credits); 7402b1c325c2SJohan Hedberg 7403b1c325c2SJohan Hedberg chan->ident = l2cap_get_ident(conn); 7404b1c325c2SJohan Hedberg 7405b1c325c2SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt); 7406b1c325c2SJohan Hedberg } 7407b1c325c2SJohan Hedberg 740815f02b91SLuiz Augusto von Dentz static int l2cap_ecred_recv(struct l2cap_chan *chan, struct sk_buff *skb) 740996cd8eaaSLuiz Augusto von Dentz { 741096cd8eaaSLuiz Augusto von Dentz int err; 741196cd8eaaSLuiz Augusto von Dentz 741296cd8eaaSLuiz Augusto von Dentz BT_DBG("SDU reassemble complete: chan %p skb->len %u", chan, skb->len); 741396cd8eaaSLuiz Augusto von Dentz 741496cd8eaaSLuiz Augusto von Dentz /* Wait recv to confirm reception before updating the credits */ 741596cd8eaaSLuiz Augusto von Dentz err = chan->ops->recv(chan, skb); 741696cd8eaaSLuiz Augusto von Dentz 741796cd8eaaSLuiz Augusto von Dentz /* Update credits whenever an SDU is received */ 741896cd8eaaSLuiz Augusto von Dentz l2cap_chan_le_send_credits(chan); 741996cd8eaaSLuiz Augusto von Dentz 742096cd8eaaSLuiz Augusto von Dentz return err; 742196cd8eaaSLuiz Augusto von Dentz } 742296cd8eaaSLuiz Augusto von Dentz 742315f02b91SLuiz Augusto von Dentz static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 7424fad5fc89SJohan Hedberg { 7425aac23bf6SJohan Hedberg int err; 7426fad5fc89SJohan Hedberg 7427aac23bf6SJohan Hedberg if (!chan->rx_credits) { 7428aac23bf6SJohan Hedberg BT_ERR("No credits to receive LE L2CAP data"); 7429dfd9774cSJohan Hedberg l2cap_send_disconn_req(chan, ECONNRESET); 7430fad5fc89SJohan Hedberg return -ENOBUFS; 7431aac23bf6SJohan Hedberg } 7432aac23bf6SJohan Hedberg 7433aac23bf6SJohan Hedberg if (chan->imtu < skb->len) { 7434aac23bf6SJohan Hedberg BT_ERR("Too big LE L2CAP PDU"); 7435aac23bf6SJohan Hedberg return -ENOBUFS; 7436aac23bf6SJohan Hedberg } 7437fad5fc89SJohan Hedberg 7438fad5fc89SJohan Hedberg chan->rx_credits--; 7439fad5fc89SJohan Hedberg BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits); 7440fad5fc89SJohan Hedberg 744196cd8eaaSLuiz Augusto von Dentz /* Update if remote had run out of credits, this should only happens 744296cd8eaaSLuiz Augusto von Dentz * if the remote is not using the entire MPS. 744396cd8eaaSLuiz Augusto von Dentz */ 744496cd8eaaSLuiz Augusto von Dentz if (!chan->rx_credits) 7445fad5fc89SJohan Hedberg l2cap_chan_le_send_credits(chan); 7446fad5fc89SJohan Hedberg 7447aac23bf6SJohan Hedberg err = 0; 7448aac23bf6SJohan Hedberg 7449aac23bf6SJohan Hedberg if (!chan->sdu) { 7450aac23bf6SJohan Hedberg u16 sdu_len; 7451aac23bf6SJohan Hedberg 7452aac23bf6SJohan Hedberg sdu_len = get_unaligned_le16(skb->data); 7453aac23bf6SJohan Hedberg skb_pull(skb, L2CAP_SDULEN_SIZE); 7454aac23bf6SJohan Hedberg 7455aac23bf6SJohan Hedberg BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u", 7456aac23bf6SJohan Hedberg sdu_len, skb->len, chan->imtu); 7457aac23bf6SJohan Hedberg 7458aac23bf6SJohan Hedberg if (sdu_len > chan->imtu) { 7459aac23bf6SJohan Hedberg BT_ERR("Too big LE L2CAP SDU length received"); 7460aac23bf6SJohan Hedberg err = -EMSGSIZE; 7461aac23bf6SJohan Hedberg goto failed; 7462aac23bf6SJohan Hedberg } 7463aac23bf6SJohan Hedberg 7464aac23bf6SJohan Hedberg if (skb->len > sdu_len) { 7465aac23bf6SJohan Hedberg BT_ERR("Too much LE L2CAP data received"); 7466aac23bf6SJohan Hedberg err = -EINVAL; 7467aac23bf6SJohan Hedberg goto failed; 7468aac23bf6SJohan Hedberg } 7469aac23bf6SJohan Hedberg 7470aac23bf6SJohan Hedberg if (skb->len == sdu_len) 747115f02b91SLuiz Augusto von Dentz return l2cap_ecred_recv(chan, skb); 7472aac23bf6SJohan Hedberg 7473aac23bf6SJohan Hedberg chan->sdu = skb; 7474aac23bf6SJohan Hedberg chan->sdu_len = sdu_len; 7475aac23bf6SJohan Hedberg chan->sdu_last_frag = skb; 7476aac23bf6SJohan Hedberg 7477a5c3021bSLuiz Augusto von Dentz /* Detect if remote is not able to use the selected MPS */ 7478a5c3021bSLuiz Augusto von Dentz if (skb->len + L2CAP_SDULEN_SIZE < chan->mps) { 7479a5c3021bSLuiz Augusto von Dentz u16 mps_len = skb->len + L2CAP_SDULEN_SIZE; 7480a5c3021bSLuiz Augusto von Dentz 7481a5c3021bSLuiz Augusto von Dentz /* Adjust the number of credits */ 7482a5c3021bSLuiz Augusto von Dentz BT_DBG("chan->mps %u -> %u", chan->mps, mps_len); 7483a5c3021bSLuiz Augusto von Dentz chan->mps = mps_len; 7484a5c3021bSLuiz Augusto von Dentz l2cap_chan_le_send_credits(chan); 7485a5c3021bSLuiz Augusto von Dentz } 7486a5c3021bSLuiz Augusto von Dentz 7487aac23bf6SJohan Hedberg return 0; 7488aac23bf6SJohan Hedberg } 7489aac23bf6SJohan Hedberg 7490aac23bf6SJohan Hedberg BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u", 7491aac23bf6SJohan Hedberg chan->sdu->len, skb->len, chan->sdu_len); 7492aac23bf6SJohan Hedberg 7493aac23bf6SJohan Hedberg if (chan->sdu->len + skb->len > chan->sdu_len) { 7494aac23bf6SJohan Hedberg BT_ERR("Too much LE L2CAP data received"); 7495aac23bf6SJohan Hedberg err = -EINVAL; 7496aac23bf6SJohan Hedberg goto failed; 7497aac23bf6SJohan Hedberg } 7498aac23bf6SJohan Hedberg 7499aac23bf6SJohan Hedberg append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag); 7500aac23bf6SJohan Hedberg skb = NULL; 7501aac23bf6SJohan Hedberg 7502aac23bf6SJohan Hedberg if (chan->sdu->len == chan->sdu_len) { 750315f02b91SLuiz Augusto von Dentz err = l2cap_ecred_recv(chan, chan->sdu); 7504aac23bf6SJohan Hedberg if (!err) { 7505aac23bf6SJohan Hedberg chan->sdu = NULL; 7506aac23bf6SJohan Hedberg chan->sdu_last_frag = NULL; 7507aac23bf6SJohan Hedberg chan->sdu_len = 0; 7508aac23bf6SJohan Hedberg } 7509aac23bf6SJohan Hedberg } 7510aac23bf6SJohan Hedberg 7511aac23bf6SJohan Hedberg failed: 7512aac23bf6SJohan Hedberg if (err) { 7513aac23bf6SJohan Hedberg kfree_skb(skb); 7514aac23bf6SJohan Hedberg kfree_skb(chan->sdu); 7515aac23bf6SJohan Hedberg chan->sdu = NULL; 7516aac23bf6SJohan Hedberg chan->sdu_last_frag = NULL; 7517aac23bf6SJohan Hedberg chan->sdu_len = 0; 7518aac23bf6SJohan Hedberg } 7519aac23bf6SJohan Hedberg 7520aac23bf6SJohan Hedberg /* We can't return an error here since we took care of the skb 7521aac23bf6SJohan Hedberg * freeing internally. An error return would cause the caller to 7522aac23bf6SJohan Hedberg * do a double-free of the skb. 7523aac23bf6SJohan Hedberg */ 7524aac23bf6SJohan Hedberg return 0; 7525fad5fc89SJohan Hedberg } 7526fad5fc89SJohan Hedberg 752713ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid, 752813ca56e0SAndrei Emeltchenko struct sk_buff *skb) 75290a708f8fSGustavo F. Padovan { 753048454079SGustavo F. Padovan struct l2cap_chan *chan; 75310a708f8fSGustavo F. Padovan 7532baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 753348454079SGustavo F. Padovan if (!chan) { 753497e8e89dSAndrei Emeltchenko if (cid == L2CAP_CID_A2MP) { 753597e8e89dSAndrei Emeltchenko chan = a2mp_channel_create(conn, skb); 753697e8e89dSAndrei Emeltchenko if (!chan) { 753797e8e89dSAndrei Emeltchenko kfree_skb(skb); 753813ca56e0SAndrei Emeltchenko return; 753997e8e89dSAndrei Emeltchenko } 754097e8e89dSAndrei Emeltchenko 754197e8e89dSAndrei Emeltchenko l2cap_chan_lock(chan); 754297e8e89dSAndrei Emeltchenko } else { 75430a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid); 75446be36555SAndrei Emeltchenko /* Drop packet and return */ 75453379013bSDan Carpenter kfree_skb(skb); 754613ca56e0SAndrei Emeltchenko return; 75470a708f8fSGustavo F. Padovan } 754897e8e89dSAndrei Emeltchenko } 75490a708f8fSGustavo F. Padovan 755049208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len); 75510a708f8fSGustavo F. Padovan 7552315917e0SJohan Hedberg /* If we receive data on a fixed channel before the info req/rsp 7553315917e0SJohan Hedberg * procdure is done simply assume that the channel is supported 7554315917e0SJohan Hedberg * and mark it as ready. 7555315917e0SJohan Hedberg */ 7556315917e0SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_FIXED) 7557315917e0SJohan Hedberg l2cap_chan_ready(chan); 7558315917e0SJohan Hedberg 755989bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 75600a708f8fSGustavo F. Padovan goto drop; 75610a708f8fSGustavo F. Padovan 75620c1bc5c6SGustavo F. Padovan switch (chan->mode) { 756338319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 756415f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL: 756515f02b91SLuiz Augusto von Dentz if (l2cap_ecred_data_rcv(chan, skb) < 0) 7566fad5fc89SJohan Hedberg goto drop; 7567fad5fc89SJohan Hedberg 7568fad5fc89SJohan Hedberg goto done; 7569fad5fc89SJohan Hedberg 75700a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 75710a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here 75720a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable. 75730a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't 75740a708f8fSGustavo F. Padovan * provide flow control mechanism. */ 75750a708f8fSGustavo F. Padovan 75762c96e03dSSzymon Janc if (chan->imtu < skb->len) { 75772c96e03dSSzymon Janc BT_ERR("Dropping L2CAP data: receive buffer overflow"); 75780a708f8fSGustavo F. Padovan goto drop; 75792c96e03dSSzymon Janc } 75800a708f8fSGustavo F. Padovan 758180b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 75820a708f8fSGustavo F. Padovan goto done; 75830a708f8fSGustavo F. Padovan break; 75840a708f8fSGustavo F. Padovan 75850a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 75860a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 7587cec8ab6eSMat Martineau l2cap_data_rcv(chan, skb); 75880a708f8fSGustavo F. Padovan goto done; 75890a708f8fSGustavo F. Padovan 75900a708f8fSGustavo F. Padovan default: 75910c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); 75920a708f8fSGustavo F. Padovan break; 75930a708f8fSGustavo F. Padovan } 75940a708f8fSGustavo F. Padovan 75950a708f8fSGustavo F. Padovan drop: 75960a708f8fSGustavo F. Padovan kfree_skb(skb); 75970a708f8fSGustavo F. Padovan 75980a708f8fSGustavo F. Padovan done: 75996be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 76000a708f8fSGustavo F. Padovan } 76010a708f8fSGustavo F. Padovan 760284104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, 760384104b24SAndrei Emeltchenko struct sk_buff *skb) 76040a708f8fSGustavo F. Padovan { 7605ae4fd2d3SMarcel Holtmann struct hci_conn *hcon = conn->hcon; 760623691d75SGustavo F. Padovan struct l2cap_chan *chan; 76070a708f8fSGustavo F. Padovan 7608ae4fd2d3SMarcel Holtmann if (hcon->type != ACL_LINK) 7609a24cce14SJohan Hedberg goto free_skb; 7610ae4fd2d3SMarcel Holtmann 7611bf20fd4eSJohan Hedberg chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst, 7612bf20fd4eSJohan Hedberg ACL_LINK); 761323691d75SGustavo F. Padovan if (!chan) 7614a24cce14SJohan Hedberg goto free_skb; 76150a708f8fSGustavo F. Padovan 76165b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 76170a708f8fSGustavo F. Padovan 761889bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 76190a708f8fSGustavo F. Padovan goto drop; 76200a708f8fSGustavo F. Padovan 7621e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 76220a708f8fSGustavo F. Padovan goto drop; 76230a708f8fSGustavo F. Padovan 76242edf870dSMarcel Holtmann /* Store remote BD_ADDR and PSM for msg_name */ 7625a4368ff3SJohan Hedberg bacpy(&bt_cb(skb)->l2cap.bdaddr, &hcon->dst); 7626a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.psm = psm; 76272edf870dSMarcel Holtmann 7628a24cce14SJohan Hedberg if (!chan->ops->recv(chan, skb)) { 7629a24cce14SJohan Hedberg l2cap_chan_put(chan); 763084104b24SAndrei Emeltchenko return; 7631a24cce14SJohan Hedberg } 76320a708f8fSGustavo F. Padovan 76330a708f8fSGustavo F. Padovan drop: 7634a24cce14SJohan Hedberg l2cap_chan_put(chan); 7635a24cce14SJohan Hedberg free_skb: 76360a708f8fSGustavo F. Padovan kfree_skb(skb); 76370a708f8fSGustavo F. Padovan } 76380a708f8fSGustavo F. Padovan 76390a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) 76400a708f8fSGustavo F. Padovan { 76410a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data; 764261a939c6SJohan Hedberg struct hci_conn *hcon = conn->hcon; 76430a708f8fSGustavo F. Padovan u16 cid, len; 76440a708f8fSGustavo F. Padovan __le16 psm; 76450a708f8fSGustavo F. Padovan 764661a939c6SJohan Hedberg if (hcon->state != BT_CONNECTED) { 764761a939c6SJohan Hedberg BT_DBG("queueing pending rx skb"); 764861a939c6SJohan Hedberg skb_queue_tail(&conn->pending_rx, skb); 764961a939c6SJohan Hedberg return; 765061a939c6SJohan Hedberg } 765161a939c6SJohan Hedberg 76520a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE); 76530a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid); 76540a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len); 76550a708f8fSGustavo F. Padovan 76560a708f8fSGustavo F. Padovan if (len != skb->len) { 76570a708f8fSGustavo F. Padovan kfree_skb(skb); 76580a708f8fSGustavo F. Padovan return; 76590a708f8fSGustavo F. Padovan } 76600a708f8fSGustavo F. Padovan 76619e1d7e15SJohan Hedberg /* Since we can't actively block incoming LE connections we must 76629e1d7e15SJohan Hedberg * at least ensure that we ignore incoming data from them. 76639e1d7e15SJohan Hedberg */ 76649e1d7e15SJohan Hedberg if (hcon->type == LE_LINK && 7665dcc36c16SJohan Hedberg hci_bdaddr_list_lookup(&hcon->hdev->blacklist, &hcon->dst, 7666a250e048SJohan Hedberg bdaddr_dst_type(hcon))) { 7667e493150eSJohan Hedberg kfree_skb(skb); 7668e493150eSJohan Hedberg return; 7669e493150eSJohan Hedberg } 7670e493150eSJohan Hedberg 76710a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid); 76720a708f8fSGustavo F. Padovan 76730a708f8fSGustavo F. Padovan switch (cid) { 76740a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING: 76750a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb); 76760a708f8fSGustavo F. Padovan break; 76770a708f8fSGustavo F. Padovan 76780a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS: 7679097db76cSAndrei Emeltchenko psm = get_unaligned((__le16 *) skb->data); 76800181a70fSAndrei Emeltchenko skb_pull(skb, L2CAP_PSMLEN_SIZE); 76810a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb); 76820a708f8fSGustavo F. Padovan break; 76830a708f8fSGustavo F. Padovan 7684a2877629SMarcel Holtmann case L2CAP_CID_LE_SIGNALING: 7685a2877629SMarcel Holtmann l2cap_le_sig_channel(conn, skb); 7686a2877629SMarcel Holtmann break; 7687a2877629SMarcel Holtmann 76880a708f8fSGustavo F. Padovan default: 76890a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb); 76900a708f8fSGustavo F. Padovan break; 76910a708f8fSGustavo F. Padovan } 76920a708f8fSGustavo F. Padovan } 76930a708f8fSGustavo F. Padovan 769461a939c6SJohan Hedberg static void process_pending_rx(struct work_struct *work) 769561a939c6SJohan Hedberg { 769661a939c6SJohan Hedberg struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 769761a939c6SJohan Hedberg pending_rx_work); 769861a939c6SJohan Hedberg struct sk_buff *skb; 769961a939c6SJohan Hedberg 770061a939c6SJohan Hedberg BT_DBG(""); 770161a939c6SJohan Hedberg 770261a939c6SJohan Hedberg while ((skb = skb_dequeue(&conn->pending_rx))) 770361a939c6SJohan Hedberg l2cap_recv_frame(conn, skb); 770461a939c6SJohan Hedberg } 770561a939c6SJohan Hedberg 7706162b49e7SJohan Hedberg static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) 7707162b49e7SJohan Hedberg { 7708162b49e7SJohan Hedberg struct l2cap_conn *conn = hcon->l2cap_data; 7709162b49e7SJohan Hedberg struct hci_chan *hchan; 7710162b49e7SJohan Hedberg 7711162b49e7SJohan Hedberg if (conn) 7712162b49e7SJohan Hedberg return conn; 7713162b49e7SJohan Hedberg 7714162b49e7SJohan Hedberg hchan = hci_chan_create(hcon); 7715162b49e7SJohan Hedberg if (!hchan) 7716162b49e7SJohan Hedberg return NULL; 7717162b49e7SJohan Hedberg 771827f70f3eSJohan Hedberg conn = kzalloc(sizeof(*conn), GFP_KERNEL); 7719162b49e7SJohan Hedberg if (!conn) { 7720162b49e7SJohan Hedberg hci_chan_del(hchan); 7721162b49e7SJohan Hedberg return NULL; 7722162b49e7SJohan Hedberg } 7723162b49e7SJohan Hedberg 7724162b49e7SJohan Hedberg kref_init(&conn->ref); 7725162b49e7SJohan Hedberg hcon->l2cap_data = conn; 772651bb8457SJohan Hedberg conn->hcon = hci_conn_get(hcon); 7727162b49e7SJohan Hedberg conn->hchan = hchan; 7728162b49e7SJohan Hedberg 7729162b49e7SJohan Hedberg BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); 7730162b49e7SJohan Hedberg 7731162b49e7SJohan Hedberg switch (hcon->type) { 7732162b49e7SJohan Hedberg case LE_LINK: 7733162b49e7SJohan Hedberg if (hcon->hdev->le_mtu) { 7734162b49e7SJohan Hedberg conn->mtu = hcon->hdev->le_mtu; 7735162b49e7SJohan Hedberg break; 7736162b49e7SJohan Hedberg } 773719186c7bSGustavo A. R. Silva fallthrough; 7738162b49e7SJohan Hedberg default: 7739162b49e7SJohan Hedberg conn->mtu = hcon->hdev->acl_mtu; 7740162b49e7SJohan Hedberg break; 7741162b49e7SJohan Hedberg } 7742162b49e7SJohan Hedberg 7743162b49e7SJohan Hedberg conn->feat_mask = 0; 7744162b49e7SJohan Hedberg 77450bd49fc7SJohan Hedberg conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS; 77460bd49fc7SJohan Hedberg 77470bd49fc7SJohan Hedberg if (hcon->type == ACL_LINK && 7748d7a5a11dSMarcel Holtmann hci_dev_test_flag(hcon->hdev, HCI_HS_ENABLED)) 77490bd49fc7SJohan Hedberg conn->local_fixed_chan |= L2CAP_FC_A2MP; 7750162b49e7SJohan Hedberg 7751d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED) && 7752f9be9e86SMarcel Holtmann (bredr_sc_enabled(hcon->hdev) || 7753b7cb93e5SMarcel Holtmann hci_dev_test_flag(hcon->hdev, HCI_FORCE_BREDR_SMP))) 7754b5ae344dSJohan Hedberg conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR; 7755b5ae344dSJohan Hedberg 77565a54e7c8SMarcel Holtmann mutex_init(&conn->ident_lock); 7757162b49e7SJohan Hedberg mutex_init(&conn->chan_lock); 7758162b49e7SJohan Hedberg 7759162b49e7SJohan Hedberg INIT_LIST_HEAD(&conn->chan_l); 7760162b49e7SJohan Hedberg INIT_LIST_HEAD(&conn->users); 7761162b49e7SJohan Hedberg 7762162b49e7SJohan Hedberg INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); 7763162b49e7SJohan Hedberg 776461a939c6SJohan Hedberg skb_queue_head_init(&conn->pending_rx); 776561a939c6SJohan Hedberg INIT_WORK(&conn->pending_rx_work, process_pending_rx); 7766f3d82d0cSJohan Hedberg INIT_WORK(&conn->id_addr_update_work, l2cap_conn_update_id_addr); 776761a939c6SJohan Hedberg 7768162b49e7SJohan Hedberg conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 7769162b49e7SJohan Hedberg 7770162b49e7SJohan Hedberg return conn; 7771162b49e7SJohan Hedberg } 7772162b49e7SJohan Hedberg 7773162b49e7SJohan Hedberg static bool is_valid_psm(u16 psm, u8 dst_type) { 7774162b49e7SJohan Hedberg if (!psm) 7775162b49e7SJohan Hedberg return false; 7776162b49e7SJohan Hedberg 7777162b49e7SJohan Hedberg if (bdaddr_type_is_le(dst_type)) 7778162b49e7SJohan Hedberg return (psm <= 0x00ff); 7779162b49e7SJohan Hedberg 7780162b49e7SJohan Hedberg /* PSM must be odd and lsb of upper byte must be 0 */ 7781162b49e7SJohan Hedberg return ((psm & 0x0101) == 0x0001); 7782162b49e7SJohan Hedberg } 7783162b49e7SJohan Hedberg 7784da49b602SLuiz Augusto von Dentz struct l2cap_chan_data { 7785da49b602SLuiz Augusto von Dentz struct l2cap_chan *chan; 7786da49b602SLuiz Augusto von Dentz struct pid *pid; 7787da49b602SLuiz Augusto von Dentz int count; 7788da49b602SLuiz Augusto von Dentz }; 7789da49b602SLuiz Augusto von Dentz 7790da49b602SLuiz Augusto von Dentz static void l2cap_chan_by_pid(struct l2cap_chan *chan, void *data) 7791da49b602SLuiz Augusto von Dentz { 7792da49b602SLuiz Augusto von Dentz struct l2cap_chan_data *d = data; 7793da49b602SLuiz Augusto von Dentz struct pid *pid; 7794da49b602SLuiz Augusto von Dentz 7795da49b602SLuiz Augusto von Dentz if (chan == d->chan) 7796da49b602SLuiz Augusto von Dentz return; 7797da49b602SLuiz Augusto von Dentz 7798da49b602SLuiz Augusto von Dentz if (!test_bit(FLAG_DEFER_SETUP, &chan->flags)) 7799da49b602SLuiz Augusto von Dentz return; 7800da49b602SLuiz Augusto von Dentz 7801da49b602SLuiz Augusto von Dentz pid = chan->ops->get_peer_pid(chan); 7802da49b602SLuiz Augusto von Dentz 7803da49b602SLuiz Augusto von Dentz /* Only count deferred channels with the same PID/PSM */ 7804da49b602SLuiz Augusto von Dentz if (d->pid != pid || chan->psm != d->chan->psm || chan->ident || 7805da49b602SLuiz Augusto von Dentz chan->mode != L2CAP_MODE_EXT_FLOWCTL || chan->state != BT_CONNECT) 7806da49b602SLuiz Augusto von Dentz return; 7807da49b602SLuiz Augusto von Dentz 7808da49b602SLuiz Augusto von Dentz d->count++; 7809da49b602SLuiz Augusto von Dentz } 7810da49b602SLuiz Augusto von Dentz 7811162b49e7SJohan Hedberg int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, 7812162b49e7SJohan Hedberg bdaddr_t *dst, u8 dst_type) 7813162b49e7SJohan Hedberg { 7814162b49e7SJohan Hedberg struct l2cap_conn *conn; 7815162b49e7SJohan Hedberg struct hci_conn *hcon; 7816162b49e7SJohan Hedberg struct hci_dev *hdev; 7817162b49e7SJohan Hedberg int err; 7818162b49e7SJohan Hedberg 781915f02b91SLuiz Augusto von Dentz BT_DBG("%pMR -> %pMR (type %u) psm 0x%4.4x mode 0x%2.2x", &chan->src, 782015f02b91SLuiz Augusto von Dentz dst, dst_type, __le16_to_cpu(psm), chan->mode); 7821162b49e7SJohan Hedberg 782239385cb5SJohan Hedberg hdev = hci_get_route(dst, &chan->src, chan->src_type); 7823162b49e7SJohan Hedberg if (!hdev) 7824162b49e7SJohan Hedberg return -EHOSTUNREACH; 7825162b49e7SJohan Hedberg 7826162b49e7SJohan Hedberg hci_dev_lock(hdev); 7827162b49e7SJohan Hedberg 7828162b49e7SJohan Hedberg if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid && 7829162b49e7SJohan Hedberg chan->chan_type != L2CAP_CHAN_RAW) { 7830162b49e7SJohan Hedberg err = -EINVAL; 7831162b49e7SJohan Hedberg goto done; 7832162b49e7SJohan Hedberg } 7833162b49e7SJohan Hedberg 783421626e62SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !psm) { 783521626e62SJohan Hedberg err = -EINVAL; 783621626e62SJohan Hedberg goto done; 783721626e62SJohan Hedberg } 783821626e62SJohan Hedberg 783921626e62SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_FIXED && !cid) { 7840162b49e7SJohan Hedberg err = -EINVAL; 7841162b49e7SJohan Hedberg goto done; 7842162b49e7SJohan Hedberg } 7843162b49e7SJohan Hedberg 7844162b49e7SJohan Hedberg switch (chan->mode) { 7845162b49e7SJohan Hedberg case L2CAP_MODE_BASIC: 7846162b49e7SJohan Hedberg break; 7847162b49e7SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 78484be5ca67SLuiz Augusto von Dentz break; 784915f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL: 78504be5ca67SLuiz Augusto von Dentz if (!enable_ecred) { 78514be5ca67SLuiz Augusto von Dentz err = -EOPNOTSUPP; 78524be5ca67SLuiz Augusto von Dentz goto done; 78534be5ca67SLuiz Augusto von Dentz } 7854162b49e7SJohan Hedberg break; 7855162b49e7SJohan Hedberg case L2CAP_MODE_ERTM: 7856162b49e7SJohan Hedberg case L2CAP_MODE_STREAMING: 7857162b49e7SJohan Hedberg if (!disable_ertm) 7858162b49e7SJohan Hedberg break; 785919186c7bSGustavo A. R. Silva fallthrough; 7860162b49e7SJohan Hedberg default: 7861beb19e4cSJohan Hedberg err = -EOPNOTSUPP; 7862162b49e7SJohan Hedberg goto done; 7863162b49e7SJohan Hedberg } 7864162b49e7SJohan Hedberg 7865162b49e7SJohan Hedberg switch (chan->state) { 7866162b49e7SJohan Hedberg case BT_CONNECT: 7867162b49e7SJohan Hedberg case BT_CONNECT2: 7868162b49e7SJohan Hedberg case BT_CONFIG: 7869162b49e7SJohan Hedberg /* Already connecting */ 7870162b49e7SJohan Hedberg err = 0; 7871162b49e7SJohan Hedberg goto done; 7872162b49e7SJohan Hedberg 7873162b49e7SJohan Hedberg case BT_CONNECTED: 7874162b49e7SJohan Hedberg /* Already connected */ 7875162b49e7SJohan Hedberg err = -EISCONN; 7876162b49e7SJohan Hedberg goto done; 7877162b49e7SJohan Hedberg 7878162b49e7SJohan Hedberg case BT_OPEN: 7879162b49e7SJohan Hedberg case BT_BOUND: 7880162b49e7SJohan Hedberg /* Can connect */ 7881162b49e7SJohan Hedberg break; 7882162b49e7SJohan Hedberg 7883162b49e7SJohan Hedberg default: 7884162b49e7SJohan Hedberg err = -EBADFD; 7885162b49e7SJohan Hedberg goto done; 7886162b49e7SJohan Hedberg } 7887162b49e7SJohan Hedberg 7888162b49e7SJohan Hedberg /* Set destination address and psm */ 7889162b49e7SJohan Hedberg bacpy(&chan->dst, dst); 7890162b49e7SJohan Hedberg chan->dst_type = dst_type; 7891162b49e7SJohan Hedberg 7892162b49e7SJohan Hedberg chan->psm = psm; 7893162b49e7SJohan Hedberg chan->dcid = cid; 7894162b49e7SJohan Hedberg 78956f77d8c7SAndre Guedes if (bdaddr_type_is_le(dst_type)) { 78966f77d8c7SAndre Guedes /* Convert from L2CAP channel address type to HCI address type 78976f77d8c7SAndre Guedes */ 78986f77d8c7SAndre Guedes if (dst_type == BDADDR_LE_PUBLIC) 78996f77d8c7SAndre Guedes dst_type = ADDR_LE_DEV_PUBLIC; 79006f77d8c7SAndre Guedes else 79016f77d8c7SAndre Guedes dst_type = ADDR_LE_DEV_RANDOM; 79026f77d8c7SAndre Guedes 7903d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) 79040ad06aa6SJohan Hedberg hcon = hci_connect_le(hdev, dst, dst_type, 7905fa142220SJakub Pawlowski chan->sec_level, 7906fa142220SJakub Pawlowski HCI_LE_CONN_TIMEOUT, 7907082f2300SSzymon Janc HCI_ROLE_SLAVE, NULL); 79080ad06aa6SJohan Hedberg else 79090ad06aa6SJohan Hedberg hcon = hci_connect_le_scan(hdev, dst, dst_type, 79100ad06aa6SJohan Hedberg chan->sec_level, 791176b13996SManish Mandlik HCI_LE_CONN_TIMEOUT, 791276b13996SManish Mandlik CONN_REASON_L2CAP_CHAN); 79130ad06aa6SJohan Hedberg 79146f77d8c7SAndre Guedes } else { 7915d93375a8SJohan Hedberg u8 auth_type = l2cap_get_auth_type(chan); 791676b13996SManish Mandlik hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type, 791776b13996SManish Mandlik CONN_REASON_L2CAP_CHAN); 79186f77d8c7SAndre Guedes } 7919162b49e7SJohan Hedberg 7920162b49e7SJohan Hedberg if (IS_ERR(hcon)) { 7921162b49e7SJohan Hedberg err = PTR_ERR(hcon); 7922162b49e7SJohan Hedberg goto done; 7923162b49e7SJohan Hedberg } 7924162b49e7SJohan Hedberg 7925162b49e7SJohan Hedberg conn = l2cap_conn_add(hcon); 7926162b49e7SJohan Hedberg if (!conn) { 7927162b49e7SJohan Hedberg hci_conn_drop(hcon); 7928162b49e7SJohan Hedberg err = -ENOMEM; 7929162b49e7SJohan Hedberg goto done; 7930162b49e7SJohan Hedberg } 7931162b49e7SJohan Hedberg 7932da49b602SLuiz Augusto von Dentz if (chan->mode == L2CAP_MODE_EXT_FLOWCTL) { 7933da49b602SLuiz Augusto von Dentz struct l2cap_chan_data data; 7934da49b602SLuiz Augusto von Dentz 7935da49b602SLuiz Augusto von Dentz data.chan = chan; 7936da49b602SLuiz Augusto von Dentz data.pid = chan->ops->get_peer_pid(chan); 7937da49b602SLuiz Augusto von Dentz data.count = 1; 7938da49b602SLuiz Augusto von Dentz 7939da49b602SLuiz Augusto von Dentz l2cap_chan_list(conn, l2cap_chan_by_pid, &data); 7940da49b602SLuiz Augusto von Dentz 7941da49b602SLuiz Augusto von Dentz /* Check if there isn't too many channels being connected */ 7942da49b602SLuiz Augusto von Dentz if (data.count > L2CAP_ECRED_CONN_SCID_MAX) { 7943da49b602SLuiz Augusto von Dentz hci_conn_drop(hcon); 7944da49b602SLuiz Augusto von Dentz err = -EPROTO; 7945da49b602SLuiz Augusto von Dentz goto done; 7946da49b602SLuiz Augusto von Dentz } 7947da49b602SLuiz Augusto von Dentz } 7948da49b602SLuiz Augusto von Dentz 794902e246aeSJohan Hedberg mutex_lock(&conn->chan_lock); 795002e246aeSJohan Hedberg l2cap_chan_lock(chan); 795102e246aeSJohan Hedberg 7952162b49e7SJohan Hedberg if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { 7953162b49e7SJohan Hedberg hci_conn_drop(hcon); 7954162b49e7SJohan Hedberg err = -EBUSY; 795502e246aeSJohan Hedberg goto chan_unlock; 7956162b49e7SJohan Hedberg } 7957162b49e7SJohan Hedberg 7958162b49e7SJohan Hedberg /* Update source addr of the socket */ 7959162b49e7SJohan Hedberg bacpy(&chan->src, &hcon->src); 7960a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(hcon); 7961162b49e7SJohan Hedberg 796202e246aeSJohan Hedberg __l2cap_chan_add(conn, chan); 7963162b49e7SJohan Hedberg 7964162b49e7SJohan Hedberg /* l2cap_chan_add takes its own ref so we can drop this one */ 7965162b49e7SJohan Hedberg hci_conn_drop(hcon); 7966162b49e7SJohan Hedberg 7967162b49e7SJohan Hedberg l2cap_state_change(chan, BT_CONNECT); 7968162b49e7SJohan Hedberg __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 7969162b49e7SJohan Hedberg 797061202e4dSJohan Hedberg /* Release chan->sport so that it can be reused by other 797161202e4dSJohan Hedberg * sockets (as it's only used for listening sockets). 797261202e4dSJohan Hedberg */ 797361202e4dSJohan Hedberg write_lock(&chan_list_lock); 797461202e4dSJohan Hedberg chan->sport = 0; 797561202e4dSJohan Hedberg write_unlock(&chan_list_lock); 797661202e4dSJohan Hedberg 7977162b49e7SJohan Hedberg if (hcon->state == BT_CONNECTED) { 7978162b49e7SJohan Hedberg if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 7979162b49e7SJohan Hedberg __clear_chan_timer(chan); 7980e7cafc45SJohan Hedberg if (l2cap_chan_check_security(chan, true)) 7981162b49e7SJohan Hedberg l2cap_state_change(chan, BT_CONNECTED); 7982162b49e7SJohan Hedberg } else 7983162b49e7SJohan Hedberg l2cap_do_start(chan); 7984162b49e7SJohan Hedberg } 7985162b49e7SJohan Hedberg 7986162b49e7SJohan Hedberg err = 0; 7987162b49e7SJohan Hedberg 798802e246aeSJohan Hedberg chan_unlock: 7989162b49e7SJohan Hedberg l2cap_chan_unlock(chan); 799002e246aeSJohan Hedberg mutex_unlock(&conn->chan_lock); 799102e246aeSJohan Hedberg done: 7992162b49e7SJohan Hedberg hci_dev_unlock(hdev); 7993162b49e7SJohan Hedberg hci_dev_put(hdev); 7994162b49e7SJohan Hedberg return err; 7995162b49e7SJohan Hedberg } 79966b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_connect); 7997162b49e7SJohan Hedberg 799815f02b91SLuiz Augusto von Dentz static void l2cap_ecred_reconfigure(struct l2cap_chan *chan) 799915f02b91SLuiz Augusto von Dentz { 800015f02b91SLuiz Augusto von Dentz struct l2cap_conn *conn = chan->conn; 800115f02b91SLuiz Augusto von Dentz struct { 800215f02b91SLuiz Augusto von Dentz struct l2cap_ecred_reconf_req req; 800315f02b91SLuiz Augusto von Dentz __le16 scid; 800415f02b91SLuiz Augusto von Dentz } pdu; 800515f02b91SLuiz Augusto von Dentz 800615f02b91SLuiz Augusto von Dentz pdu.req.mtu = cpu_to_le16(chan->imtu); 800715f02b91SLuiz Augusto von Dentz pdu.req.mps = cpu_to_le16(chan->mps); 800815f02b91SLuiz Augusto von Dentz pdu.scid = cpu_to_le16(chan->scid); 800915f02b91SLuiz Augusto von Dentz 801015f02b91SLuiz Augusto von Dentz chan->ident = l2cap_get_ident(conn); 801115f02b91SLuiz Augusto von Dentz 801215f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_RECONF_REQ, 801315f02b91SLuiz Augusto von Dentz sizeof(pdu), &pdu); 801415f02b91SLuiz Augusto von Dentz } 801515f02b91SLuiz Augusto von Dentz 801615f02b91SLuiz Augusto von Dentz int l2cap_chan_reconfigure(struct l2cap_chan *chan, __u16 mtu) 801715f02b91SLuiz Augusto von Dentz { 801815f02b91SLuiz Augusto von Dentz if (chan->imtu > mtu) 801915f02b91SLuiz Augusto von Dentz return -EINVAL; 802015f02b91SLuiz Augusto von Dentz 802115f02b91SLuiz Augusto von Dentz BT_DBG("chan %p mtu 0x%4.4x", chan, mtu); 802215f02b91SLuiz Augusto von Dentz 802315f02b91SLuiz Augusto von Dentz chan->imtu = mtu; 802415f02b91SLuiz Augusto von Dentz 802515f02b91SLuiz Augusto von Dentz l2cap_ecred_reconfigure(chan); 802615f02b91SLuiz Augusto von Dentz 802715f02b91SLuiz Augusto von Dentz return 0; 802815f02b91SLuiz Augusto von Dentz } 802915f02b91SLuiz Augusto von Dentz 80300a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */ 80310a708f8fSGustavo F. Padovan 8032686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) 80330a708f8fSGustavo F. Padovan { 80340a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0; 803523691d75SGustavo F. Padovan struct l2cap_chan *c; 80360a708f8fSGustavo F. Padovan 80376ed93dc6SAndrei Emeltchenko BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr); 80380a708f8fSGustavo F. Padovan 80390a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */ 804023691d75SGustavo F. Padovan read_lock(&chan_list_lock); 804123691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 804289bc500eSGustavo F. Padovan if (c->state != BT_LISTEN) 80430a708f8fSGustavo F. Padovan continue; 80440a708f8fSGustavo F. Padovan 80457eafc59eSMarcel Holtmann if (!bacmp(&c->src, &hdev->bdaddr)) { 80460a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT; 804743bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 80480a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER; 80490a708f8fSGustavo F. Padovan exact++; 80507eafc59eSMarcel Holtmann } else if (!bacmp(&c->src, BDADDR_ANY)) { 80510a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT; 805243bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 80530a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER; 80540a708f8fSGustavo F. Padovan } 80550a708f8fSGustavo F. Padovan } 805623691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 80570a708f8fSGustavo F. Padovan 80580a708f8fSGustavo F. Padovan return exact ? lm1 : lm2; 80590a708f8fSGustavo F. Padovan } 80600a708f8fSGustavo F. Padovan 8061e760ec12SJohan Hedberg /* Find the next fixed channel in BT_LISTEN state, continue iteration 8062e760ec12SJohan Hedberg * from an existing channel in the list or from the beginning of the 8063e760ec12SJohan Hedberg * global list (by passing NULL as first parameter). 8064e760ec12SJohan Hedberg */ 8065e760ec12SJohan Hedberg static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c, 8066327a7191SJohan Hedberg struct hci_conn *hcon) 8067e760ec12SJohan Hedberg { 8068327a7191SJohan Hedberg u8 src_type = bdaddr_src_type(hcon); 8069327a7191SJohan Hedberg 8070e760ec12SJohan Hedberg read_lock(&chan_list_lock); 8071e760ec12SJohan Hedberg 8072e760ec12SJohan Hedberg if (c) 8073e760ec12SJohan Hedberg c = list_next_entry(c, global_l); 8074e760ec12SJohan Hedberg else 8075e760ec12SJohan Hedberg c = list_entry(chan_list.next, typeof(*c), global_l); 8076e760ec12SJohan Hedberg 8077e760ec12SJohan Hedberg list_for_each_entry_from(c, &chan_list, global_l) { 8078e760ec12SJohan Hedberg if (c->chan_type != L2CAP_CHAN_FIXED) 8079e760ec12SJohan Hedberg continue; 8080e760ec12SJohan Hedberg if (c->state != BT_LISTEN) 8081e760ec12SJohan Hedberg continue; 8082327a7191SJohan Hedberg if (bacmp(&c->src, &hcon->src) && bacmp(&c->src, BDADDR_ANY)) 8083e760ec12SJohan Hedberg continue; 8084327a7191SJohan Hedberg if (src_type != c->src_type) 808554a1b626SJohan Hedberg continue; 8086e760ec12SJohan Hedberg 8087e760ec12SJohan Hedberg l2cap_chan_hold(c); 8088e760ec12SJohan Hedberg read_unlock(&chan_list_lock); 8089e760ec12SJohan Hedberg return c; 8090e760ec12SJohan Hedberg } 8091e760ec12SJohan Hedberg 8092e760ec12SJohan Hedberg read_unlock(&chan_list_lock); 8093e760ec12SJohan Hedberg 8094e760ec12SJohan Hedberg return NULL; 8095e760ec12SJohan Hedberg } 8096e760ec12SJohan Hedberg 8097539c496dSJohan Hedberg static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) 80980a708f8fSGustavo F. Padovan { 8099e760ec12SJohan Hedberg struct hci_dev *hdev = hcon->hdev; 81000a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 8101e760ec12SJohan Hedberg struct l2cap_chan *pchan; 8102e760ec12SJohan Hedberg u8 dst_type; 81030a708f8fSGustavo F. Padovan 8104539c496dSJohan Hedberg if (hcon->type != ACL_LINK && hcon->type != LE_LINK) 8105539c496dSJohan Hedberg return; 8106539c496dSJohan Hedberg 81076ed93dc6SAndrei Emeltchenko BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status); 81080a708f8fSGustavo F. Padovan 8109dc0f5088SJohan Hedberg if (status) { 8110e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status)); 8111dc0f5088SJohan Hedberg return; 8112ba6fc317SAndrei Emeltchenko } 8113dc0f5088SJohan Hedberg 8114dc0f5088SJohan Hedberg conn = l2cap_conn_add(hcon); 8115dc0f5088SJohan Hedberg if (!conn) 8116dc0f5088SJohan Hedberg return; 8117dc0f5088SJohan Hedberg 8118a250e048SJohan Hedberg dst_type = bdaddr_dst_type(hcon); 8119e760ec12SJohan Hedberg 8120e760ec12SJohan Hedberg /* If device is blocked, do not create channels for it */ 8121e760ec12SJohan Hedberg if (hci_bdaddr_list_lookup(&hdev->blacklist, &hcon->dst, dst_type)) 8122e760ec12SJohan Hedberg return; 8123e760ec12SJohan Hedberg 8124e760ec12SJohan Hedberg /* Find fixed channels and notify them of the new connection. We 8125e760ec12SJohan Hedberg * use multiple individual lookups, continuing each time where 8126e760ec12SJohan Hedberg * we left off, because the list lock would prevent calling the 8127e760ec12SJohan Hedberg * potentially sleeping l2cap_chan_lock() function. 8128e760ec12SJohan Hedberg */ 8129327a7191SJohan Hedberg pchan = l2cap_global_fixed_chan(NULL, hcon); 8130e760ec12SJohan Hedberg while (pchan) { 8131e760ec12SJohan Hedberg struct l2cap_chan *chan, *next; 8132e760ec12SJohan Hedberg 8133e760ec12SJohan Hedberg /* Client fixed channels should override server ones */ 8134e760ec12SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, pchan->scid)) 8135e760ec12SJohan Hedberg goto next; 8136e760ec12SJohan Hedberg 8137e760ec12SJohan Hedberg l2cap_chan_lock(pchan); 8138e760ec12SJohan Hedberg chan = pchan->ops->new_connection(pchan); 8139e760ec12SJohan Hedberg if (chan) { 8140e760ec12SJohan Hedberg bacpy(&chan->src, &hcon->src); 8141e760ec12SJohan Hedberg bacpy(&chan->dst, &hcon->dst); 8142a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(hcon); 8143e760ec12SJohan Hedberg chan->dst_type = dst_type; 8144e760ec12SJohan Hedberg 8145e760ec12SJohan Hedberg __l2cap_chan_add(conn, chan); 8146e760ec12SJohan Hedberg } 8147e760ec12SJohan Hedberg 8148e760ec12SJohan Hedberg l2cap_chan_unlock(pchan); 8149e760ec12SJohan Hedberg next: 8150327a7191SJohan Hedberg next = l2cap_global_fixed_chan(pchan, hcon); 8151e760ec12SJohan Hedberg l2cap_chan_put(pchan); 8152e760ec12SJohan Hedberg pchan = next; 8153e760ec12SJohan Hedberg } 8154e760ec12SJohan Hedberg 8155dc0f5088SJohan Hedberg l2cap_conn_ready(conn); 81560a708f8fSGustavo F. Padovan } 81570a708f8fSGustavo F. Padovan 8158686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon) 81590a708f8fSGustavo F. Padovan { 81600a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 81610a708f8fSGustavo F. Padovan 81620a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon); 81630a708f8fSGustavo F. Padovan 8164686ebf28SUlisses Furquim if (!conn) 81659f5a0d7bSAndrei Emeltchenko return HCI_ERROR_REMOTE_USER_TERM; 81660a708f8fSGustavo F. Padovan return conn->disc_reason; 81670a708f8fSGustavo F. Padovan } 81680a708f8fSGustavo F. Padovan 81693a6d576bSJohan Hedberg static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) 81700a708f8fSGustavo F. Padovan { 81713a6d576bSJohan Hedberg if (hcon->type != ACL_LINK && hcon->type != LE_LINK) 81723a6d576bSJohan Hedberg return; 81733a6d576bSJohan Hedberg 81740a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason); 81750a708f8fSGustavo F. Padovan 8176e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason)); 81770a708f8fSGustavo F. Padovan } 81780a708f8fSGustavo F. Padovan 81794343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) 81800a708f8fSGustavo F. Padovan { 8181715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 81820a708f8fSGustavo F. Padovan return; 81830a708f8fSGustavo F. Padovan 81840a708f8fSGustavo F. Padovan if (encrypt == 0x00) { 81854343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) { 8186ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); 81877d513e92SMarcel Holtmann } else if (chan->sec_level == BT_SECURITY_HIGH || 81887d513e92SMarcel Holtmann chan->sec_level == BT_SECURITY_FIPS) 81890f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED); 81900a708f8fSGustavo F. Padovan } else { 81914343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) 8192c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 81930a708f8fSGustavo F. Padovan } 81940a708f8fSGustavo F. Padovan } 81950a708f8fSGustavo F. Padovan 8196354fe804SJohan Hedberg static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) 81970a708f8fSGustavo F. Padovan { 81980a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 819948454079SGustavo F. Padovan struct l2cap_chan *chan; 82000a708f8fSGustavo F. Padovan 82010a708f8fSGustavo F. Padovan if (!conn) 8202354fe804SJohan Hedberg return; 82030a708f8fSGustavo F. Padovan 820489d8b407SAndrei Emeltchenko BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt); 82050a708f8fSGustavo F. Padovan 82063df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 82070a708f8fSGustavo F. Padovan 82083df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 82096be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 82100a708f8fSGustavo F. Padovan 821189d8b407SAndrei Emeltchenko BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, 821289d8b407SAndrei Emeltchenko state_to_string(chan->state)); 8213f1cb9af5SVinicius Costa Gomes 82142338a7e0SJohan Hedberg if (chan->scid == L2CAP_CID_A2MP) { 821578eb2f98SAndrei Emeltchenko l2cap_chan_unlock(chan); 821678eb2f98SAndrei Emeltchenko continue; 821778eb2f98SAndrei Emeltchenko } 821878eb2f98SAndrei Emeltchenko 8219191eb398SJohan Hedberg if (!status && encrypt) 8220f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level; 8221f1cb9af5SVinicius Costa Gomes 822296eff46eSAndrei Emeltchenko if (!__l2cap_no_conn_pending(chan)) { 82236be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 82240a708f8fSGustavo F. Padovan continue; 82250a708f8fSGustavo F. Padovan } 82260a708f8fSGustavo F. Padovan 822789bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED || 822889bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) { 8229d97c899bSMarcel Holtmann chan->ops->resume(chan); 82304343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt); 82316be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 82320a708f8fSGustavo F. Padovan continue; 82330a708f8fSGustavo F. Padovan } 82340a708f8fSGustavo F. Padovan 823589bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 8236693cd8ceSMarcel Holtmann if (!status && l2cap_check_enc_key_size(hcon)) 823793c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 82386d3c15daSJohan Hedberg else 8239ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 8240fa37c1aaSJohan Hedberg } else if (chan->state == BT_CONNECT2 && 824115f02b91SLuiz Augusto von Dentz !(chan->mode == L2CAP_MODE_EXT_FLOWCTL || 824215f02b91SLuiz Augusto von Dentz chan->mode == L2CAP_MODE_LE_FLOWCTL)) { 82430a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 8244df3c3931SJohan Hedberg __u16 res, stat; 82450a708f8fSGustavo F. Padovan 8246693cd8ceSMarcel Holtmann if (!status && l2cap_check_enc_key_size(hcon)) { 8247bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 8248df3c3931SJohan Hedberg res = L2CAP_CR_PEND; 8249df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND; 82502dc4e510SGustavo Padovan chan->ops->defer(chan); 8251df3c3931SJohan Hedberg } else { 8252acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 8253df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS; 8254df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 8255df3c3931SJohan Hedberg } 82560a708f8fSGustavo F. Padovan } else { 8257acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_DISCONN); 8258ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 8259df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK; 8260df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 82610a708f8fSGustavo F. Padovan } 82620a708f8fSGustavo F. Padovan 8263fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 8264fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 8265df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res); 8266df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat); 8267fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 8268fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 82692d369359SMat Martineau 82702d369359SMat Martineau if (!test_bit(CONF_REQ_SENT, &chan->conf_state) && 82712d369359SMat Martineau res == L2CAP_CR_SUCCESS) { 82722d369359SMat Martineau char buf[128]; 82732d369359SMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 82742d369359SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), 82752d369359SMat Martineau L2CAP_CONF_REQ, 8276e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), 82772d369359SMat Martineau buf); 82782d369359SMat Martineau chan->num_conf_req++; 82792d369359SMat Martineau } 82800a708f8fSGustavo F. Padovan } 82810a708f8fSGustavo F. Padovan 82826be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 82830a708f8fSGustavo F. Padovan } 82840a708f8fSGustavo F. Padovan 82853df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 82860a708f8fSGustavo F. Padovan } 82870a708f8fSGustavo F. Padovan 82884d7ea8eeSLuiz Augusto von Dentz /* Append fragment into frame respecting the maximum len of rx_skb */ 82894d7ea8eeSLuiz Augusto von Dentz static int l2cap_recv_frag(struct l2cap_conn *conn, struct sk_buff *skb, 82904d7ea8eeSLuiz Augusto von Dentz u16 len) 82914d7ea8eeSLuiz Augusto von Dentz { 82924d7ea8eeSLuiz Augusto von Dentz if (!conn->rx_skb) { 82934d7ea8eeSLuiz Augusto von Dentz /* Allocate skb for the complete frame (with header) */ 82944d7ea8eeSLuiz Augusto von Dentz conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL); 82954d7ea8eeSLuiz Augusto von Dentz if (!conn->rx_skb) 82964d7ea8eeSLuiz Augusto von Dentz return -ENOMEM; 82974d7ea8eeSLuiz Augusto von Dentz /* Init rx_len */ 82984d7ea8eeSLuiz Augusto von Dentz conn->rx_len = len; 82994d7ea8eeSLuiz Augusto von Dentz } 83004d7ea8eeSLuiz Augusto von Dentz 83014d7ea8eeSLuiz Augusto von Dentz /* Copy as much as the rx_skb can hold */ 83024d7ea8eeSLuiz Augusto von Dentz len = min_t(u16, len, skb->len); 83034d7ea8eeSLuiz Augusto von Dentz skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, len), len); 83044d7ea8eeSLuiz Augusto von Dentz skb_pull(skb, len); 83054d7ea8eeSLuiz Augusto von Dentz conn->rx_len -= len; 83064d7ea8eeSLuiz Augusto von Dentz 83074d7ea8eeSLuiz Augusto von Dentz return len; 83084d7ea8eeSLuiz Augusto von Dentz } 83094d7ea8eeSLuiz Augusto von Dentz 83104d7ea8eeSLuiz Augusto von Dentz static int l2cap_recv_len(struct l2cap_conn *conn, struct sk_buff *skb) 83114d7ea8eeSLuiz Augusto von Dentz { 83124d7ea8eeSLuiz Augusto von Dentz struct sk_buff *rx_skb; 83134d7ea8eeSLuiz Augusto von Dentz int len; 83144d7ea8eeSLuiz Augusto von Dentz 83154d7ea8eeSLuiz Augusto von Dentz /* Append just enough to complete the header */ 83164d7ea8eeSLuiz Augusto von Dentz len = l2cap_recv_frag(conn, skb, L2CAP_LEN_SIZE - conn->rx_skb->len); 83174d7ea8eeSLuiz Augusto von Dentz 83184d7ea8eeSLuiz Augusto von Dentz /* If header could not be read just continue */ 83194d7ea8eeSLuiz Augusto von Dentz if (len < 0 || conn->rx_skb->len < L2CAP_LEN_SIZE) 83204d7ea8eeSLuiz Augusto von Dentz return len; 83214d7ea8eeSLuiz Augusto von Dentz 83224d7ea8eeSLuiz Augusto von Dentz rx_skb = conn->rx_skb; 83234d7ea8eeSLuiz Augusto von Dentz len = get_unaligned_le16(rx_skb->data); 83244d7ea8eeSLuiz Augusto von Dentz 83254d7ea8eeSLuiz Augusto von Dentz /* Check if rx_skb has enough space to received all fragments */ 83264d7ea8eeSLuiz Augusto von Dentz if (len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE) <= skb_tailroom(rx_skb)) { 83274d7ea8eeSLuiz Augusto von Dentz /* Update expected len */ 83284d7ea8eeSLuiz Augusto von Dentz conn->rx_len = len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE); 83294d7ea8eeSLuiz Augusto von Dentz return L2CAP_LEN_SIZE; 83304d7ea8eeSLuiz Augusto von Dentz } 83314d7ea8eeSLuiz Augusto von Dentz 83324d7ea8eeSLuiz Augusto von Dentz /* Reset conn->rx_skb since it will need to be reallocated in order to 83334d7ea8eeSLuiz Augusto von Dentz * fit all fragments. 83344d7ea8eeSLuiz Augusto von Dentz */ 83354d7ea8eeSLuiz Augusto von Dentz conn->rx_skb = NULL; 83364d7ea8eeSLuiz Augusto von Dentz 83374d7ea8eeSLuiz Augusto von Dentz /* Reallocates rx_skb using the exact expected length */ 83384d7ea8eeSLuiz Augusto von Dentz len = l2cap_recv_frag(conn, rx_skb, 83394d7ea8eeSLuiz Augusto von Dentz len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE)); 83404d7ea8eeSLuiz Augusto von Dentz kfree_skb(rx_skb); 83414d7ea8eeSLuiz Augusto von Dentz 83424d7ea8eeSLuiz Augusto von Dentz return len; 83434d7ea8eeSLuiz Augusto von Dentz } 83444d7ea8eeSLuiz Augusto von Dentz 83454d7ea8eeSLuiz Augusto von Dentz static void l2cap_recv_reset(struct l2cap_conn *conn) 83464d7ea8eeSLuiz Augusto von Dentz { 83474d7ea8eeSLuiz Augusto von Dentz kfree_skb(conn->rx_skb); 83484d7ea8eeSLuiz Augusto von Dentz conn->rx_skb = NULL; 83494d7ea8eeSLuiz Augusto von Dentz conn->rx_len = 0; 83504d7ea8eeSLuiz Augusto von Dentz } 83514d7ea8eeSLuiz Augusto von Dentz 83529b4c3336SArron Wang void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) 83530a708f8fSGustavo F. Padovan { 83540a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 8355d73a0988SAndrei Emeltchenko int len; 83560a708f8fSGustavo F. Padovan 83571d13a254SAndrei Emeltchenko /* For AMP controller do not create l2cap conn */ 8358ca8bee5dSMarcel Holtmann if (!conn && hcon->hdev->dev_type != HCI_PRIMARY) 83591d13a254SAndrei Emeltchenko goto drop; 83600a708f8fSGustavo F. Padovan 83610a708f8fSGustavo F. Padovan if (!conn) 8362baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon); 83630a708f8fSGustavo F. Padovan 83640a708f8fSGustavo F. Padovan if (!conn) 83650a708f8fSGustavo F. Padovan goto drop; 83660a708f8fSGustavo F. Padovan 83670a708f8fSGustavo F. Padovan BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); 83680a708f8fSGustavo F. Padovan 8369d73a0988SAndrei Emeltchenko switch (flags) { 8370d73a0988SAndrei Emeltchenko case ACL_START: 8371d73a0988SAndrei Emeltchenko case ACL_START_NO_FLUSH: 8372d73a0988SAndrei Emeltchenko case ACL_COMPLETE: 83734d7ea8eeSLuiz Augusto von Dentz if (conn->rx_skb) { 83740a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len); 83754d7ea8eeSLuiz Augusto von Dentz l2cap_recv_reset(conn); 83760a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 83770a708f8fSGustavo F. Padovan } 83780a708f8fSGustavo F. Padovan 83794d7ea8eeSLuiz Augusto von Dentz /* Start fragment may not contain the L2CAP length so just 83804d7ea8eeSLuiz Augusto von Dentz * copy the initial byte when that happens and use conn->mtu as 83814d7ea8eeSLuiz Augusto von Dentz * expected length. 83824d7ea8eeSLuiz Augusto von Dentz */ 83834d7ea8eeSLuiz Augusto von Dentz if (skb->len < L2CAP_LEN_SIZE) { 83844d7ea8eeSLuiz Augusto von Dentz if (l2cap_recv_frag(conn, skb, conn->mtu) < 0) 83850a708f8fSGustavo F. Padovan goto drop; 83864d7ea8eeSLuiz Augusto von Dentz return; 83870a708f8fSGustavo F. Padovan } 83880a708f8fSGustavo F. Padovan 83894d7ea8eeSLuiz Augusto von Dentz len = get_unaligned_le16(skb->data) + L2CAP_HDR_SIZE; 83900a708f8fSGustavo F. Padovan 83910a708f8fSGustavo F. Padovan if (len == skb->len) { 83920a708f8fSGustavo F. Padovan /* Complete frame received */ 83930a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb); 83949b4c3336SArron Wang return; 83950a708f8fSGustavo F. Padovan } 83960a708f8fSGustavo F. Padovan 83970a708f8fSGustavo F. Padovan BT_DBG("Start: total len %d, frag len %d", len, skb->len); 83980a708f8fSGustavo F. Padovan 83990a708f8fSGustavo F. Padovan if (skb->len > len) { 84000a708f8fSGustavo F. Padovan BT_ERR("Frame is too long (len %d, expected len %d)", 84010a708f8fSGustavo F. Padovan skb->len, len); 84020a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 84030a708f8fSGustavo F. Padovan goto drop; 84040a708f8fSGustavo F. Padovan } 84050a708f8fSGustavo F. Padovan 84064d7ea8eeSLuiz Augusto von Dentz /* Append fragment into frame (with header) */ 84074d7ea8eeSLuiz Augusto von Dentz if (l2cap_recv_frag(conn, skb, len) < 0) 84080a708f8fSGustavo F. Padovan goto drop; 84090a708f8fSGustavo F. Padovan 8410d73a0988SAndrei Emeltchenko break; 8411d73a0988SAndrei Emeltchenko 8412d73a0988SAndrei Emeltchenko case ACL_CONT: 84130a708f8fSGustavo F. Padovan BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); 84140a708f8fSGustavo F. Padovan 84154d7ea8eeSLuiz Augusto von Dentz if (!conn->rx_skb) { 84160a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len); 84170a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 84180a708f8fSGustavo F. Padovan goto drop; 84190a708f8fSGustavo F. Padovan } 84200a708f8fSGustavo F. Padovan 84214d7ea8eeSLuiz Augusto von Dentz /* Complete the L2CAP length if it has not been read */ 84224d7ea8eeSLuiz Augusto von Dentz if (conn->rx_skb->len < L2CAP_LEN_SIZE) { 84234d7ea8eeSLuiz Augusto von Dentz if (l2cap_recv_len(conn, skb) < 0) { 84240a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 84250a708f8fSGustavo F. Padovan goto drop; 84260a708f8fSGustavo F. Padovan } 84270a708f8fSGustavo F. Padovan 84284d7ea8eeSLuiz Augusto von Dentz /* Header still could not be read just continue */ 84294d7ea8eeSLuiz Augusto von Dentz if (conn->rx_skb->len < L2CAP_LEN_SIZE) 84304d7ea8eeSLuiz Augusto von Dentz return; 84314d7ea8eeSLuiz Augusto von Dentz } 84324d7ea8eeSLuiz Augusto von Dentz 84334d7ea8eeSLuiz Augusto von Dentz if (skb->len > conn->rx_len) { 84344d7ea8eeSLuiz Augusto von Dentz BT_ERR("Fragment is too long (len %d, expected %d)", 84354d7ea8eeSLuiz Augusto von Dentz skb->len, conn->rx_len); 84364d7ea8eeSLuiz Augusto von Dentz l2cap_recv_reset(conn); 84374d7ea8eeSLuiz Augusto von Dentz l2cap_conn_unreliable(conn, ECOMM); 84384d7ea8eeSLuiz Augusto von Dentz goto drop; 84394d7ea8eeSLuiz Augusto von Dentz } 84404d7ea8eeSLuiz Augusto von Dentz 84414d7ea8eeSLuiz Augusto von Dentz /* Append fragment into frame (with header) */ 84424d7ea8eeSLuiz Augusto von Dentz l2cap_recv_frag(conn, skb, skb->len); 84430a708f8fSGustavo F. Padovan 84440a708f8fSGustavo F. Padovan if (!conn->rx_len) { 8445c4e5bafaSJohan Hedberg /* Complete frame received. l2cap_recv_frame 8446c4e5bafaSJohan Hedberg * takes ownership of the skb so set the global 8447c4e5bafaSJohan Hedberg * rx_skb pointer to NULL first. 8448c4e5bafaSJohan Hedberg */ 8449c4e5bafaSJohan Hedberg struct sk_buff *rx_skb = conn->rx_skb; 84500a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 8451c4e5bafaSJohan Hedberg l2cap_recv_frame(conn, rx_skb); 84520a708f8fSGustavo F. Padovan } 8453d73a0988SAndrei Emeltchenko break; 84540a708f8fSGustavo F. Padovan } 84550a708f8fSGustavo F. Padovan 84560a708f8fSGustavo F. Padovan drop: 84570a708f8fSGustavo F. Padovan kfree_skb(skb); 84580a708f8fSGustavo F. Padovan } 84590a708f8fSGustavo F. Padovan 8460354fe804SJohan Hedberg static struct hci_cb l2cap_cb = { 8461354fe804SJohan Hedberg .name = "L2CAP", 8462539c496dSJohan Hedberg .connect_cfm = l2cap_connect_cfm, 84633a6d576bSJohan Hedberg .disconn_cfm = l2cap_disconn_cfm, 8464354fe804SJohan Hedberg .security_cfm = l2cap_security_cfm, 8465354fe804SJohan Hedberg }; 8466354fe804SJohan Hedberg 84670a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p) 84680a708f8fSGustavo F. Padovan { 846923691d75SGustavo F. Padovan struct l2cap_chan *c; 84700a708f8fSGustavo F. Padovan 8471333055f2SGustavo F. Padovan read_lock(&chan_list_lock); 84720a708f8fSGustavo F. Padovan 847323691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 8474eeb5a067SMarcel Holtmann seq_printf(f, "%pMR (%u) %pMR (%u) %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", 8475eeb5a067SMarcel Holtmann &c->src, c->src_type, &c->dst, c->dst_type, 847689bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm), 847723691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu, 847823691d75SGustavo F. Padovan c->sec_level, c->mode); 84790a708f8fSGustavo F. Padovan } 84800a708f8fSGustavo F. Padovan 8481333055f2SGustavo F. Padovan read_unlock(&chan_list_lock); 84820a708f8fSGustavo F. Padovan 84830a708f8fSGustavo F. Padovan return 0; 84840a708f8fSGustavo F. Padovan } 84850a708f8fSGustavo F. Padovan 84868e2924e3SYangtao Li DEFINE_SHOW_ATTRIBUTE(l2cap_debugfs); 84870a708f8fSGustavo F. Padovan 84880a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs; 84890a708f8fSGustavo F. Padovan 849064274518SGustavo F. Padovan int __init l2cap_init(void) 84910a708f8fSGustavo F. Padovan { 84920a708f8fSGustavo F. Padovan int err; 84930a708f8fSGustavo F. Padovan 8494bb58f747SGustavo F. Padovan err = l2cap_init_sockets(); 84950a708f8fSGustavo F. Padovan if (err < 0) 84960a708f8fSGustavo F. Padovan return err; 84970a708f8fSGustavo F. Padovan 8498354fe804SJohan Hedberg hci_register_cb(&l2cap_cb); 8499354fe804SJohan Hedberg 85001120e4bfSMarcel Holtmann if (IS_ERR_OR_NULL(bt_debugfs)) 85011120e4bfSMarcel Holtmann return 0; 85021120e4bfSMarcel Holtmann 85032d792818SGustavo Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, 85042d792818SGustavo Padovan NULL, &l2cap_debugfs_fops); 85050a708f8fSGustavo F. Padovan 85060a708f8fSGustavo F. Padovan return 0; 85070a708f8fSGustavo F. Padovan } 85080a708f8fSGustavo F. Padovan 850964274518SGustavo F. Padovan void l2cap_exit(void) 85100a708f8fSGustavo F. Padovan { 85110a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs); 8512354fe804SJohan Hedberg hci_unregister_cb(&l2cap_cb); 8513bb58f747SGustavo F. Padovan l2cap_cleanup_sockets(); 85140a708f8fSGustavo F. Padovan } 85150a708f8fSGustavo F. Padovan 85160a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644); 85170a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); 85184be5ca67SLuiz Augusto von Dentz 85194be5ca67SLuiz Augusto von Dentz module_param(enable_ecred, bool, 0644); 85204be5ca67SLuiz Augusto von Dentz MODULE_PARM_DESC(enable_ecred, "Enable enhanced credit flow control mode"); 8521