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 454*be859723STetsuo Handa skb_queue_head_init(&chan->tx_q); 455*be859723STetsuo Handa skb_queue_head_init(&chan->srej_q); 456c03b355eSAndrei Emeltchenko mutex_init(&chan->lock); 457c03b355eSAndrei Emeltchenko 458ff714119SJohan Hedberg /* Set default lock nesting level */ 459ff714119SJohan Hedberg atomic_set(&chan->nesting, L2CAP_NESTING_NORMAL); 460ff714119SJohan Hedberg 461333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 46223691d75SGustavo F. Padovan list_add(&chan->global_l, &chan_list); 463333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 46423691d75SGustavo F. Padovan 465721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout); 466ab07801dSGustavo F. Padovan 46789bc500eSGustavo F. Padovan chan->state = BT_OPEN; 46889bc500eSGustavo F. Padovan 469144ad330SSyam Sidhardhan kref_init(&chan->kref); 47071ba0e56SGustavo F. Padovan 4712827011fSMat Martineau /* This flag is cleared in l2cap_chan_ready() */ 4722827011fSMat Martineau set_bit(CONF_NOT_COMPLETE, &chan->conf_state); 4732827011fSMat Martineau 474eef1d9b6SGustavo Padovan BT_DBG("chan %p", chan); 475abc545b8SSzymon Janc 47648454079SGustavo F. Padovan return chan; 4770a708f8fSGustavo F. Padovan } 4786b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_create); 4790a708f8fSGustavo F. Padovan 480144ad330SSyam Sidhardhan static void l2cap_chan_destroy(struct kref *kref) 4816ff5abbfSGustavo F. Padovan { 482144ad330SSyam Sidhardhan struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref); 483144ad330SSyam Sidhardhan 4844af66c69SJaganath Kanakkassery BT_DBG("chan %p", chan); 4854af66c69SJaganath Kanakkassery 486333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 48723691d75SGustavo F. Padovan list_del(&chan->global_l); 488333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 48923691d75SGustavo F. Padovan 4904af66c69SJaganath Kanakkassery kfree(chan); 4916ff5abbfSGustavo F. Padovan } 4926ff5abbfSGustavo F. Padovan 49330648372SJaganath Kanakkassery void l2cap_chan_hold(struct l2cap_chan *c) 49430648372SJaganath Kanakkassery { 4952c935bc5SPeter Zijlstra BT_DBG("chan %p orig refcnt %d", c, kref_read(&c->kref)); 49630648372SJaganath Kanakkassery 497144ad330SSyam Sidhardhan kref_get(&c->kref); 49830648372SJaganath Kanakkassery } 49930648372SJaganath Kanakkassery 50030648372SJaganath Kanakkassery void l2cap_chan_put(struct l2cap_chan *c) 50130648372SJaganath Kanakkassery { 5022c935bc5SPeter Zijlstra BT_DBG("chan %p orig refcnt %d", c, kref_read(&c->kref)); 50330648372SJaganath Kanakkassery 504144ad330SSyam Sidhardhan kref_put(&c->kref, l2cap_chan_destroy); 50530648372SJaganath Kanakkassery } 5066b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_put); 50730648372SJaganath Kanakkassery 508bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan) 509bd4b1653SAndrei Emeltchenko { 510bd4b1653SAndrei Emeltchenko chan->fcs = L2CAP_FCS_CRC16; 511bd4b1653SAndrei Emeltchenko chan->max_tx = L2CAP_DEFAULT_MAX_TX; 512bd4b1653SAndrei Emeltchenko chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; 513bd4b1653SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 5146a5e8165SJukka Rissanen chan->remote_max_tx = chan->max_tx; 5156a5e8165SJukka Rissanen chan->remote_tx_win = chan->tx_win; 516c20f8e35SMat Martineau chan->ack_win = L2CAP_DEFAULT_TX_WINDOW; 517bd4b1653SAndrei Emeltchenko chan->sec_level = BT_SECURITY_LOW; 5186a5e8165SJukka Rissanen chan->flush_to = L2CAP_DEFAULT_FLUSH_TO; 5196a5e8165SJukka Rissanen chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO; 5206a5e8165SJukka Rissanen chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO; 5213a9d54b1SArchie Pusaka 5226a5e8165SJukka Rissanen chan->conf_state = 0; 5233a9d54b1SArchie Pusaka set_bit(CONF_NOT_COMPLETE, &chan->conf_state); 524bd4b1653SAndrei Emeltchenko 525bd4b1653SAndrei Emeltchenko set_bit(FLAG_FORCE_ACTIVE, &chan->flags); 526bd4b1653SAndrei Emeltchenko } 5276b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_set_defaults); 528bd4b1653SAndrei Emeltchenko 529ba8f5289SLuiz Augusto von Dentz static void l2cap_le_flowctl_init(struct l2cap_chan *chan, u16 tx_credits) 53038319713SJohan Hedberg { 5310ce43ce6SJohan Hedberg chan->sdu = NULL; 5320ce43ce6SJohan Hedberg chan->sdu_last_frag = NULL; 5330ce43ce6SJohan Hedberg chan->sdu_len = 0; 534ba8f5289SLuiz Augusto von Dentz chan->tx_credits = tx_credits; 535fe149310SLuiz Augusto von Dentz /* Derive MPS from connection MTU to stop HCI fragmentation */ 536fe149310SLuiz Augusto von Dentz chan->mps = min_t(u16, chan->imtu, chan->conn->mtu - L2CAP_HDR_SIZE); 53796cd8eaaSLuiz Augusto von Dentz /* Give enough credits for a full packet */ 53896cd8eaaSLuiz Augusto von Dentz chan->rx_credits = (chan->imtu / chan->mps) + 1; 5390ce43ce6SJohan Hedberg 5400ce43ce6SJohan Hedberg skb_queue_head_init(&chan->tx_q); 54138319713SJohan Hedberg } 54238319713SJohan Hedberg 54315f02b91SLuiz Augusto von Dentz static void l2cap_ecred_init(struct l2cap_chan *chan, u16 tx_credits) 54415f02b91SLuiz Augusto von Dentz { 54515f02b91SLuiz Augusto von Dentz l2cap_le_flowctl_init(chan, tx_credits); 54615f02b91SLuiz Augusto von Dentz 54715f02b91SLuiz Augusto von Dentz /* L2CAP implementations shall support a minimum MPS of 64 octets */ 54815f02b91SLuiz Augusto von Dentz if (chan->mps < L2CAP_ECRED_MIN_MPS) { 54915f02b91SLuiz Augusto von Dentz chan->mps = L2CAP_ECRED_MIN_MPS; 55015f02b91SLuiz Augusto von Dentz chan->rx_credits = (chan->imtu / chan->mps) + 1; 55115f02b91SLuiz Augusto von Dentz } 55215f02b91SLuiz Augusto von Dentz } 55315f02b91SLuiz Augusto von Dentz 55493c3e8f5SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 5550a708f8fSGustavo F. Padovan { 5560a708f8fSGustavo F. Padovan BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, 557097db76cSAndrei Emeltchenko __le16_to_cpu(chan->psm), chan->dcid); 5580a708f8fSGustavo F. Padovan 5599f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 5600a708f8fSGustavo F. Padovan 5618c1d787bSGustavo F. Padovan chan->conn = conn; 5620a708f8fSGustavo F. Padovan 5635491120eSAndrei Emeltchenko switch (chan->chan_type) { 5645491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_ORIENTED: 5650a708f8fSGustavo F. Padovan /* Alloc CID for connection-oriented socket */ 566fe4128e0SGustavo F. Padovan chan->scid = l2cap_alloc_cid(conn); 56721626e62SJohan Hedberg if (conn->hcon->type == ACL_LINK) 5680c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 5695491120eSAndrei Emeltchenko break; 5705491120eSAndrei Emeltchenko 5715491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_LESS: 5720a708f8fSGustavo F. Padovan /* Connectionless socket */ 573fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_CONN_LESS; 574fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_CONN_LESS; 5750c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 5765491120eSAndrei Emeltchenko break; 5775491120eSAndrei Emeltchenko 5782338a7e0SJohan Hedberg case L2CAP_CHAN_FIXED: 5792338a7e0SJohan Hedberg /* Caller will set CID and CID specific MTU values */ 580416fa752SAndrei Emeltchenko break; 581416fa752SAndrei Emeltchenko 5825491120eSAndrei Emeltchenko default: 5830a708f8fSGustavo F. Padovan /* Raw socket can send/recv signalling messages only */ 584fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_SIGNALING; 585fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_SIGNALING; 5860c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 5870a708f8fSGustavo F. Padovan } 5880a708f8fSGustavo F. Padovan 5898f7975b1SAndrei Emeltchenko chan->local_id = L2CAP_BESTEFFORT_ID; 5908f7975b1SAndrei Emeltchenko chan->local_stype = L2CAP_SERV_BESTEFFORT; 5918f7975b1SAndrei Emeltchenko chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE; 5928f7975b1SAndrei Emeltchenko chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME; 5938f7975b1SAndrei Emeltchenko chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT; 5948936fa6dSAndrei Emeltchenko chan->local_flush_to = L2CAP_EFS_DEFAULT_FLUSH_TO; 5958f7975b1SAndrei Emeltchenko 596371fd835SUlisses Furquim l2cap_chan_hold(chan); 597baa7e1faSGustavo F. Padovan 598c16900cfSJohan Hedberg /* Only keep a reference for fixed channels if they requested it */ 599c16900cfSJohan Hedberg if (chan->chan_type != L2CAP_CHAN_FIXED || 600c16900cfSJohan Hedberg test_bit(FLAG_HOLD_HCI_CONN, &chan->flags)) 6015ee9891dSJohan Hedberg hci_conn_hold(conn->hcon); 6025ee9891dSJohan Hedberg 6033df91ea2SAndrei Emeltchenko list_add(&chan->list, &conn->chan_l); 604643162a8SAndrei Emeltchenko } 605643162a8SAndrei Emeltchenko 606466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 607643162a8SAndrei Emeltchenko { 608643162a8SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 609643162a8SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 6103df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 6110a708f8fSGustavo F. Padovan } 6120a708f8fSGustavo F. Padovan 613466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err) 6140a708f8fSGustavo F. Padovan { 6158c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 6160a708f8fSGustavo F. Padovan 617c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 6180a708f8fSGustavo F. Padovan 61949d11741SJohan Hedberg BT_DBG("chan %p, conn %p, err %d, state %s", chan, conn, err, 62049d11741SJohan Hedberg state_to_string(chan->state)); 6210a708f8fSGustavo F. Padovan 62272847ce0SJohan Hedberg chan->ops->teardown(chan, err); 62372847ce0SJohan Hedberg 6240a708f8fSGustavo F. Padovan if (conn) { 62556f60984SAndrei Emeltchenko struct amp_mgr *mgr = conn->hcon->amp_mgr; 626baa7e1faSGustavo F. Padovan /* Delete from channel list */ 6273df91ea2SAndrei Emeltchenko list_del(&chan->list); 6283d57dc68SGustavo F. Padovan 629371fd835SUlisses Furquim l2cap_chan_put(chan); 630baa7e1faSGustavo F. Padovan 6318c1d787bSGustavo F. Padovan chan->conn = NULL; 6323cabbfdaSAndrei Emeltchenko 633c16900cfSJohan Hedberg /* Reference was only held for non-fixed channels or 634c16900cfSJohan Hedberg * fixed channels that explicitly requested it using the 635c16900cfSJohan Hedberg * FLAG_HOLD_HCI_CONN flag. 636c16900cfSJohan Hedberg */ 637c16900cfSJohan Hedberg if (chan->chan_type != L2CAP_CHAN_FIXED || 638c16900cfSJohan Hedberg test_bit(FLAG_HOLD_HCI_CONN, &chan->flags)) 63976a68ba0SDavid Herrmann hci_conn_drop(conn->hcon); 64056f60984SAndrei Emeltchenko 64156f60984SAndrei Emeltchenko if (mgr && mgr->bredr_chan == chan) 64256f60984SAndrei Emeltchenko mgr->bredr_chan = NULL; 6430a708f8fSGustavo F. Padovan } 6440a708f8fSGustavo F. Padovan 645419e08c1SAndrei Emeltchenko if (chan->hs_hchan) { 646419e08c1SAndrei Emeltchenko struct hci_chan *hs_hchan = chan->hs_hchan; 647419e08c1SAndrei Emeltchenko 648419e08c1SAndrei Emeltchenko BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan); 649419e08c1SAndrei Emeltchenko amp_disconnect_logical_link(hs_hchan); 650419e08c1SAndrei Emeltchenko } 651419e08c1SAndrei Emeltchenko 6522827011fSMat Martineau if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) 6536ff5abbfSGustavo F. Padovan return; 6542ead70b8SGustavo F. Padovan 655ee556f66SGustavo Padovan switch(chan->mode) { 656ee556f66SGustavo Padovan case L2CAP_MODE_BASIC: 657ee556f66SGustavo Padovan break; 6580a708f8fSGustavo F. Padovan 65938319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 66015f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL: 661177f8f2bSJohan Hedberg skb_queue_purge(&chan->tx_q); 66238319713SJohan Hedberg break; 66338319713SJohan Hedberg 664ee556f66SGustavo Padovan case L2CAP_MODE_ERTM: 6651a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 6661a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 6671a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 6680a708f8fSGustavo F. Padovan 669f1c6775bSGustavo F. Padovan skb_queue_purge(&chan->srej_q); 6700a708f8fSGustavo F. Padovan 6713c588192SMat Martineau l2cap_seq_list_free(&chan->srej_list); 6723c588192SMat Martineau l2cap_seq_list_free(&chan->retrans_list); 67319186c7bSGustavo A. R. Silva fallthrough; 674ee556f66SGustavo Padovan 675ee556f66SGustavo Padovan case L2CAP_MODE_STREAMING: 676ee556f66SGustavo Padovan skb_queue_purge(&chan->tx_q); 677ee556f66SGustavo Padovan break; 6780a708f8fSGustavo F. Padovan } 679ee556f66SGustavo Padovan 680ee556f66SGustavo Padovan return; 6810a708f8fSGustavo F. Padovan } 6826b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_del); 6830a708f8fSGustavo F. Padovan 684da49b602SLuiz Augusto von Dentz static void __l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func, 685da49b602SLuiz Augusto von Dentz void *data) 686da49b602SLuiz Augusto von Dentz { 687da49b602SLuiz Augusto von Dentz struct l2cap_chan *chan; 688da49b602SLuiz Augusto von Dentz 689da49b602SLuiz Augusto von Dentz list_for_each_entry(chan, &conn->chan_l, list) { 690da49b602SLuiz Augusto von Dentz func(chan, data); 691da49b602SLuiz Augusto von Dentz } 692da49b602SLuiz Augusto von Dentz } 693da49b602SLuiz Augusto von Dentz 694da49b602SLuiz Augusto von Dentz void l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func, 695da49b602SLuiz Augusto von Dentz void *data) 696da49b602SLuiz Augusto von Dentz { 697da49b602SLuiz Augusto von Dentz if (!conn) 698da49b602SLuiz Augusto von Dentz return; 699da49b602SLuiz Augusto von Dentz 700da49b602SLuiz Augusto von Dentz mutex_lock(&conn->chan_lock); 701da49b602SLuiz Augusto von Dentz __l2cap_chan_list(conn, func, data); 702da49b602SLuiz Augusto von Dentz mutex_unlock(&conn->chan_lock); 703da49b602SLuiz Augusto von Dentz } 704da49b602SLuiz Augusto von Dentz 705da49b602SLuiz Augusto von Dentz EXPORT_SYMBOL_GPL(l2cap_chan_list); 706da49b602SLuiz Augusto von Dentz 707f3d82d0cSJohan Hedberg static void l2cap_conn_update_id_addr(struct work_struct *work) 708387a33e3SJohan Hedberg { 709f3d82d0cSJohan Hedberg struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 710f3d82d0cSJohan Hedberg id_addr_update_work); 711f3d82d0cSJohan Hedberg struct hci_conn *hcon = conn->hcon; 712387a33e3SJohan Hedberg struct l2cap_chan *chan; 713387a33e3SJohan Hedberg 714387a33e3SJohan Hedberg mutex_lock(&conn->chan_lock); 715387a33e3SJohan Hedberg 716387a33e3SJohan Hedberg list_for_each_entry(chan, &conn->chan_l, list) { 717387a33e3SJohan Hedberg l2cap_chan_lock(chan); 718387a33e3SJohan Hedberg bacpy(&chan->dst, &hcon->dst); 719a250e048SJohan Hedberg chan->dst_type = bdaddr_dst_type(hcon); 720387a33e3SJohan Hedberg l2cap_chan_unlock(chan); 721387a33e3SJohan Hedberg } 722387a33e3SJohan Hedberg 723387a33e3SJohan Hedberg mutex_unlock(&conn->chan_lock); 724387a33e3SJohan Hedberg } 725387a33e3SJohan Hedberg 72627e2d4c8SJohan Hedberg static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan) 72727e2d4c8SJohan Hedberg { 72827e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn; 72927e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 73027e2d4c8SJohan Hedberg u16 result; 73127e2d4c8SJohan Hedberg 73227e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 733571f7390SMallikarjun Phulari result = L2CAP_CR_LE_AUTHORIZATION; 73427e2d4c8SJohan Hedberg else 735571f7390SMallikarjun Phulari result = L2CAP_CR_LE_BAD_PSM; 73627e2d4c8SJohan Hedberg 73727e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_DISCONN); 73827e2d4c8SJohan Hedberg 73927e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 74027e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 7413916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps); 7420cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits); 74327e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result); 74427e2d4c8SJohan Hedberg 74527e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), 74627e2d4c8SJohan Hedberg &rsp); 74727e2d4c8SJohan Hedberg } 74827e2d4c8SJohan Hedberg 74915f02b91SLuiz Augusto von Dentz static void l2cap_chan_ecred_connect_reject(struct l2cap_chan *chan) 75015f02b91SLuiz Augusto von Dentz { 75115f02b91SLuiz Augusto von Dentz struct l2cap_conn *conn = chan->conn; 75215f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp rsp; 75315f02b91SLuiz Augusto von Dentz u16 result; 75415f02b91SLuiz Augusto von Dentz 75515f02b91SLuiz Augusto von Dentz if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 75615f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_AUTHORIZATION; 75715f02b91SLuiz Augusto von Dentz else 75815f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_BAD_PSM; 75915f02b91SLuiz Augusto von Dentz 76015f02b91SLuiz Augusto von Dentz l2cap_state_change(chan, BT_DISCONN); 76115f02b91SLuiz Augusto von Dentz 76215f02b91SLuiz Augusto von Dentz memset(&rsp, 0, sizeof(rsp)); 76315f02b91SLuiz Augusto von Dentz 76415f02b91SLuiz Augusto von Dentz rsp.result = cpu_to_le16(result); 76515f02b91SLuiz Augusto von Dentz 76615f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), 76715f02b91SLuiz Augusto von Dentz &rsp); 76815f02b91SLuiz Augusto von Dentz } 76915f02b91SLuiz Augusto von Dentz 770791d60f7SJohan Hedberg static void l2cap_chan_connect_reject(struct l2cap_chan *chan) 771791d60f7SJohan Hedberg { 772791d60f7SJohan Hedberg struct l2cap_conn *conn = chan->conn; 773791d60f7SJohan Hedberg struct l2cap_conn_rsp rsp; 774791d60f7SJohan Hedberg u16 result; 775791d60f7SJohan Hedberg 776791d60f7SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 777791d60f7SJohan Hedberg result = L2CAP_CR_SEC_BLOCK; 778791d60f7SJohan Hedberg else 779791d60f7SJohan Hedberg result = L2CAP_CR_BAD_PSM; 780791d60f7SJohan Hedberg 781791d60f7SJohan Hedberg l2cap_state_change(chan, BT_DISCONN); 782791d60f7SJohan Hedberg 783791d60f7SJohan Hedberg rsp.scid = cpu_to_le16(chan->dcid); 784791d60f7SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 785791d60f7SJohan Hedberg rsp.result = cpu_to_le16(result); 786dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 787791d60f7SJohan Hedberg 788791d60f7SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); 789791d60f7SJohan Hedberg } 790791d60f7SJohan Hedberg 7910f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason) 7924519de9aSGustavo F. Padovan { 7934519de9aSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 7944519de9aSGustavo F. Padovan 7957eafc59eSMarcel Holtmann BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 7964519de9aSGustavo F. Padovan 79789bc500eSGustavo F. Padovan switch (chan->state) { 7984519de9aSGustavo F. Padovan case BT_LISTEN: 799c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 8004519de9aSGustavo F. Padovan break; 8014519de9aSGustavo F. Padovan 8024519de9aSGustavo F. Padovan case BT_CONNECTED: 8034519de9aSGustavo F. Padovan case BT_CONFIG: 8047b25c9b3SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) { 8058d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 8065e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, reason); 8074519de9aSGustavo F. Padovan } else 8084519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 8094519de9aSGustavo F. Padovan break; 8104519de9aSGustavo F. Padovan 8114519de9aSGustavo F. Padovan case BT_CONNECT2: 812791d60f7SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) { 813791d60f7SJohan Hedberg if (conn->hcon->type == ACL_LINK) 814791d60f7SJohan Hedberg l2cap_chan_connect_reject(chan); 81515f02b91SLuiz Augusto von Dentz else if (conn->hcon->type == LE_LINK) { 81615f02b91SLuiz Augusto von Dentz switch (chan->mode) { 81715f02b91SLuiz Augusto von Dentz case L2CAP_MODE_LE_FLOWCTL: 81827e2d4c8SJohan Hedberg l2cap_chan_le_connect_reject(chan); 81915f02b91SLuiz Augusto von Dentz break; 82015f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL: 82115f02b91SLuiz Augusto von Dentz l2cap_chan_ecred_connect_reject(chan); 82215f02b91SLuiz Augusto von Dentz break; 82315f02b91SLuiz Augusto von Dentz } 82415f02b91SLuiz Augusto von Dentz } 8254519de9aSGustavo F. Padovan } 8264519de9aSGustavo F. Padovan 8274519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 8284519de9aSGustavo F. Padovan break; 8294519de9aSGustavo F. Padovan 8304519de9aSGustavo F. Padovan case BT_CONNECT: 8314519de9aSGustavo F. Padovan case BT_DISCONN: 8324519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 8334519de9aSGustavo F. Padovan break; 8344519de9aSGustavo F. Padovan 8354519de9aSGustavo F. Padovan default: 836c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 8374519de9aSGustavo F. Padovan break; 8384519de9aSGustavo F. Padovan } 8394519de9aSGustavo F. Padovan } 8406b8d4a6aSJukka Rissanen EXPORT_SYMBOL(l2cap_chan_close); 8414519de9aSGustavo F. Padovan 8424343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) 8430a708f8fSGustavo F. Padovan { 8446a974b50SMarcel Holtmann switch (chan->chan_type) { 8456a974b50SMarcel Holtmann case L2CAP_CHAN_RAW: 8464343478fSGustavo F. Padovan switch (chan->sec_level) { 8470a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 8487d513e92SMarcel Holtmann case BT_SECURITY_FIPS: 8490a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING_MITM; 8500a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 8510a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING; 8520a708f8fSGustavo F. Padovan default: 8530a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 8540a708f8fSGustavo F. Padovan } 8556a974b50SMarcel Holtmann break; 8563124b843SMarcel Holtmann case L2CAP_CHAN_CONN_LESS: 857dcf4adbfSJoe Perches if (chan->psm == cpu_to_le16(L2CAP_PSM_3DSP)) { 8583124b843SMarcel Holtmann if (chan->sec_level == BT_SECURITY_LOW) 8593124b843SMarcel Holtmann chan->sec_level = BT_SECURITY_SDP; 8603124b843SMarcel Holtmann } 8617d513e92SMarcel Holtmann if (chan->sec_level == BT_SECURITY_HIGH || 8627d513e92SMarcel Holtmann chan->sec_level == BT_SECURITY_FIPS) 8633124b843SMarcel Holtmann return HCI_AT_NO_BONDING_MITM; 8643124b843SMarcel Holtmann else 8653124b843SMarcel Holtmann return HCI_AT_NO_BONDING; 8663124b843SMarcel Holtmann break; 8676a974b50SMarcel Holtmann case L2CAP_CHAN_CONN_ORIENTED: 868dcf4adbfSJoe Perches if (chan->psm == cpu_to_le16(L2CAP_PSM_SDP)) { 8694343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_LOW) 8704343478fSGustavo F. Padovan chan->sec_level = BT_SECURITY_SDP; 8710a708f8fSGustavo F. Padovan 8727d513e92SMarcel Holtmann if (chan->sec_level == BT_SECURITY_HIGH || 8737d513e92SMarcel Holtmann chan->sec_level == BT_SECURITY_FIPS) 8740a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING_MITM; 8750a708f8fSGustavo F. Padovan else 8760a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 8776a974b50SMarcel Holtmann } 87819186c7bSGustavo A. R. Silva fallthrough; 87919186c7bSGustavo A. R. Silva 8806a974b50SMarcel Holtmann default: 8814343478fSGustavo F. Padovan switch (chan->sec_level) { 8820a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 8837d513e92SMarcel Holtmann case BT_SECURITY_FIPS: 8840a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING_MITM; 8850a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 8860a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING; 8870a708f8fSGustavo F. Padovan default: 8880a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 8890a708f8fSGustavo F. Padovan } 8906a974b50SMarcel Holtmann break; 8910a708f8fSGustavo F. Padovan } 8920a708f8fSGustavo F. Padovan } 8930a708f8fSGustavo F. Padovan 8940a708f8fSGustavo F. Padovan /* Service level security */ 895e7cafc45SJohan Hedberg int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator) 8960a708f8fSGustavo F. Padovan { 8978c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 8980a708f8fSGustavo F. Padovan __u8 auth_type; 8990a708f8fSGustavo F. Padovan 900a17de2feSJohan Hedberg if (conn->hcon->type == LE_LINK) 901a17de2feSJohan Hedberg return smp_conn_security(conn->hcon, chan->sec_level); 902a17de2feSJohan Hedberg 9034343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 9040a708f8fSGustavo F. Padovan 905e7cafc45SJohan Hedberg return hci_conn_security(conn->hcon, chan->sec_level, auth_type, 906e7cafc45SJohan Hedberg initiator); 9070a708f8fSGustavo F. Padovan } 9080a708f8fSGustavo F. Padovan 909b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn) 9100a708f8fSGustavo F. Padovan { 9110a708f8fSGustavo F. Padovan u8 id; 9120a708f8fSGustavo F. Padovan 9130a708f8fSGustavo F. Padovan /* Get next available identificator. 9140a708f8fSGustavo F. Padovan * 1 - 128 are used by kernel. 9150a708f8fSGustavo F. Padovan * 129 - 199 are reserved. 9160a708f8fSGustavo F. Padovan * 200 - 254 are used by utilities like l2ping, etc. 9170a708f8fSGustavo F. Padovan */ 9180a708f8fSGustavo F. Padovan 9195a54e7c8SMarcel Holtmann mutex_lock(&conn->ident_lock); 9200a708f8fSGustavo F. Padovan 9210a708f8fSGustavo F. Padovan if (++conn->tx_ident > 128) 9220a708f8fSGustavo F. Padovan conn->tx_ident = 1; 9230a708f8fSGustavo F. Padovan 9240a708f8fSGustavo F. Padovan id = conn->tx_ident; 9250a708f8fSGustavo F. Padovan 9265a54e7c8SMarcel Holtmann mutex_unlock(&conn->ident_lock); 9270a708f8fSGustavo F. Padovan 9280a708f8fSGustavo F. Padovan return id; 9290a708f8fSGustavo F. Padovan } 9300a708f8fSGustavo F. Padovan 9312d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 9322d792818SGustavo Padovan void *data) 9330a708f8fSGustavo F. Padovan { 9340a708f8fSGustavo F. Padovan struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); 9350a708f8fSGustavo F. Padovan u8 flags; 9360a708f8fSGustavo F. Padovan 9370a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x", code); 9380a708f8fSGustavo F. Padovan 9390a708f8fSGustavo F. Padovan if (!skb) 9400a708f8fSGustavo F. Padovan return; 9410a708f8fSGustavo F. Padovan 942f6af675eSSteven Walter /* Use NO_FLUSH if supported or we have an LE link (which does 943f6af675eSSteven Walter * not support auto-flushing packets) */ 944f6af675eSSteven Walter if (lmp_no_flush_capable(conn->hcon->hdev) || 945f6af675eSSteven Walter conn->hcon->type == LE_LINK) 9460a708f8fSGustavo F. Padovan flags = ACL_START_NO_FLUSH; 9470a708f8fSGustavo F. Padovan else 9480a708f8fSGustavo F. Padovan flags = ACL_START; 9490a708f8fSGustavo F. Padovan 95014b12d0bSJaikumar Ganesh bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON; 9515e59b791SLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 95214b12d0bSJaikumar Ganesh 95373d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, flags); 9540a708f8fSGustavo F. Padovan } 9550a708f8fSGustavo F. Padovan 95602b0fbb9SMat Martineau static bool __chan_is_moving(struct l2cap_chan *chan) 95702b0fbb9SMat Martineau { 95802b0fbb9SMat Martineau return chan->move_state != L2CAP_MOVE_STABLE && 95902b0fbb9SMat Martineau chan->move_state != L2CAP_MOVE_WAIT_PREPARE; 96002b0fbb9SMat Martineau } 96102b0fbb9SMat Martineau 96273d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) 96373d80debSLuiz Augusto von Dentz { 96473d80debSLuiz Augusto von Dentz struct hci_conn *hcon = chan->conn->hcon; 96573d80debSLuiz Augusto von Dentz u16 flags; 96673d80debSLuiz Augusto von Dentz 96773d80debSLuiz Augusto von Dentz BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, 96873d80debSLuiz Augusto von Dentz skb->priority); 96973d80debSLuiz Augusto von Dentz 970d5f8a75dSMat Martineau if (chan->hs_hcon && !__chan_is_moving(chan)) { 971d5f8a75dSMat Martineau if (chan->hs_hchan) 972d5f8a75dSMat Martineau hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE); 973d5f8a75dSMat Martineau else 974d5f8a75dSMat Martineau kfree_skb(skb); 975d5f8a75dSMat Martineau 976d5f8a75dSMat Martineau return; 977d5f8a75dSMat Martineau } 978d5f8a75dSMat Martineau 979f6af675eSSteven Walter /* Use NO_FLUSH for LE links (where this is the only option) or 980f6af675eSSteven Walter * if the BR/EDR link supports it and flushing has not been 981f6af675eSSteven Walter * explicitly requested (through FLAG_FLUSHABLE). 982f6af675eSSteven Walter */ 983f6af675eSSteven Walter if (hcon->type == LE_LINK || 984f6af675eSSteven Walter (!test_bit(FLAG_FLUSHABLE, &chan->flags) && 985f6af675eSSteven Walter lmp_no_flush_capable(hcon->hdev))) 98673d80debSLuiz Augusto von Dentz flags = ACL_START_NO_FLUSH; 98773d80debSLuiz Augusto von Dentz else 98873d80debSLuiz Augusto von Dentz flags = ACL_START; 98973d80debSLuiz Augusto von Dentz 99073d80debSLuiz Augusto von Dentz bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); 99173d80debSLuiz Augusto von Dentz hci_send_acl(chan->conn->hchan, skb, flags); 9920a708f8fSGustavo F. Padovan } 9930a708f8fSGustavo F. Padovan 994b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control) 995b5c6aaedSMat Martineau { 996b5c6aaedSMat Martineau control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT; 997b5c6aaedSMat Martineau control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT; 998b5c6aaedSMat Martineau 999b5c6aaedSMat Martineau if (enh & L2CAP_CTRL_FRAME_TYPE) { 1000b5c6aaedSMat Martineau /* S-Frame */ 1001b5c6aaedSMat Martineau control->sframe = 1; 1002b5c6aaedSMat Martineau control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT; 1003b5c6aaedSMat Martineau control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT; 1004b5c6aaedSMat Martineau 1005b5c6aaedSMat Martineau control->sar = 0; 1006b5c6aaedSMat Martineau control->txseq = 0; 1007b5c6aaedSMat Martineau } else { 1008b5c6aaedSMat Martineau /* I-Frame */ 1009b5c6aaedSMat Martineau control->sframe = 0; 1010b5c6aaedSMat Martineau control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT; 1011b5c6aaedSMat Martineau control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT; 1012b5c6aaedSMat Martineau 1013b5c6aaedSMat Martineau control->poll = 0; 1014b5c6aaedSMat Martineau control->super = 0; 1015b5c6aaedSMat Martineau } 1016b5c6aaedSMat Martineau } 1017b5c6aaedSMat Martineau 1018b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control) 1019b5c6aaedSMat Martineau { 1020b5c6aaedSMat Martineau control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT; 1021b5c6aaedSMat Martineau control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT; 1022b5c6aaedSMat Martineau 1023b5c6aaedSMat Martineau if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) { 1024b5c6aaedSMat Martineau /* S-Frame */ 1025b5c6aaedSMat Martineau control->sframe = 1; 1026b5c6aaedSMat Martineau control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT; 1027b5c6aaedSMat Martineau control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT; 1028b5c6aaedSMat Martineau 1029b5c6aaedSMat Martineau control->sar = 0; 1030b5c6aaedSMat Martineau control->txseq = 0; 1031b5c6aaedSMat Martineau } else { 1032b5c6aaedSMat Martineau /* I-Frame */ 1033b5c6aaedSMat Martineau control->sframe = 0; 1034b5c6aaedSMat Martineau control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT; 1035b5c6aaedSMat Martineau control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT; 1036b5c6aaedSMat Martineau 1037b5c6aaedSMat Martineau control->poll = 0; 1038b5c6aaedSMat Martineau control->super = 0; 1039b5c6aaedSMat Martineau } 1040b5c6aaedSMat Martineau } 1041b5c6aaedSMat Martineau 1042b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan, 1043b5c6aaedSMat Martineau struct sk_buff *skb) 1044b5c6aaedSMat Martineau { 1045b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 1046b5c6aaedSMat Martineau __unpack_extended_control(get_unaligned_le32(skb->data), 1047a4368ff3SJohan Hedberg &bt_cb(skb)->l2cap); 1048cec8ab6eSMat Martineau skb_pull(skb, L2CAP_EXT_CTRL_SIZE); 1049b5c6aaedSMat Martineau } else { 1050b5c6aaedSMat Martineau __unpack_enhanced_control(get_unaligned_le16(skb->data), 1051a4368ff3SJohan Hedberg &bt_cb(skb)->l2cap); 1052cec8ab6eSMat Martineau skb_pull(skb, L2CAP_ENH_CTRL_SIZE); 1053b5c6aaedSMat Martineau } 1054b5c6aaedSMat Martineau } 1055b5c6aaedSMat Martineau 1056b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control) 1057b5c6aaedSMat Martineau { 1058b5c6aaedSMat Martineau u32 packed; 1059b5c6aaedSMat Martineau 1060b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT; 1061b5c6aaedSMat Martineau packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT; 1062b5c6aaedSMat Martineau 1063b5c6aaedSMat Martineau if (control->sframe) { 1064b5c6aaedSMat Martineau packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT; 1065b5c6aaedSMat Martineau packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT; 1066b5c6aaedSMat Martineau packed |= L2CAP_EXT_CTRL_FRAME_TYPE; 1067b5c6aaedSMat Martineau } else { 1068b5c6aaedSMat Martineau packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT; 1069b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT; 1070b5c6aaedSMat Martineau } 1071b5c6aaedSMat Martineau 1072b5c6aaedSMat Martineau return packed; 1073b5c6aaedSMat Martineau } 1074b5c6aaedSMat Martineau 1075b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control) 1076b5c6aaedSMat Martineau { 1077b5c6aaedSMat Martineau u16 packed; 1078b5c6aaedSMat Martineau 1079b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT; 1080b5c6aaedSMat Martineau packed |= control->final << L2CAP_CTRL_FINAL_SHIFT; 1081b5c6aaedSMat Martineau 1082b5c6aaedSMat Martineau if (control->sframe) { 1083b5c6aaedSMat Martineau packed |= control->poll << L2CAP_CTRL_POLL_SHIFT; 1084b5c6aaedSMat Martineau packed |= control->super << L2CAP_CTRL_SUPER_SHIFT; 1085b5c6aaedSMat Martineau packed |= L2CAP_CTRL_FRAME_TYPE; 1086b5c6aaedSMat Martineau } else { 1087b5c6aaedSMat Martineau packed |= control->sar << L2CAP_CTRL_SAR_SHIFT; 1088b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT; 1089b5c6aaedSMat Martineau } 1090b5c6aaedSMat Martineau 1091b5c6aaedSMat Martineau return packed; 1092b5c6aaedSMat Martineau } 1093b5c6aaedSMat Martineau 1094b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan, 1095b5c6aaedSMat Martineau struct l2cap_ctrl *control, 1096b5c6aaedSMat Martineau struct sk_buff *skb) 1097b5c6aaedSMat Martineau { 1098b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 1099b5c6aaedSMat Martineau put_unaligned_le32(__pack_extended_control(control), 1100b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 1101b5c6aaedSMat Martineau } else { 1102b5c6aaedSMat Martineau put_unaligned_le16(__pack_enhanced_control(control), 1103b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 1104b5c6aaedSMat Martineau } 1105b5c6aaedSMat Martineau } 1106b5c6aaedSMat Martineau 1107ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan) 1108ba7aa64fSGustavo Padovan { 1109ba7aa64fSGustavo Padovan if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1110ba7aa64fSGustavo Padovan return L2CAP_EXT_HDR_SIZE; 1111ba7aa64fSGustavo Padovan else 1112ba7aa64fSGustavo Padovan return L2CAP_ENH_HDR_SIZE; 1113ba7aa64fSGustavo Padovan } 1114ba7aa64fSGustavo Padovan 1115a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan, 1116a67d7f6fSMat Martineau u32 control) 11170a708f8fSGustavo F. Padovan { 11180a708f8fSGustavo F. Padovan struct sk_buff *skb; 11190a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 1120ba7aa64fSGustavo Padovan int hlen = __ertm_hdr_size(chan); 11210a708f8fSGustavo F. Padovan 11220a708f8fSGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 112303a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 11240a708f8fSGustavo F. Padovan 1125a67d7f6fSMat Martineau skb = bt_skb_alloc(hlen, GFP_KERNEL); 11260a708f8fSGustavo F. Padovan 11270a708f8fSGustavo F. Padovan if (!skb) 1128a67d7f6fSMat Martineau return ERR_PTR(-ENOMEM); 11290a708f8fSGustavo F. Padovan 11304df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 11310a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); 1132fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 113388843ab0SAndrei Emeltchenko 1134a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1135a67d7f6fSMat Martineau put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 1136a67d7f6fSMat Martineau else 1137a67d7f6fSMat Martineau put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 11380a708f8fSGustavo F. Padovan 113947d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 1140a67d7f6fSMat Martineau u16 fcs = crc16(0, (u8 *)skb->data, skb->len); 114103a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 11420a708f8fSGustavo F. Padovan } 11430a708f8fSGustavo F. Padovan 114473d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 1145a67d7f6fSMat Martineau return skb; 1146a67d7f6fSMat Martineau } 1147a67d7f6fSMat Martineau 1148a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan, 1149a67d7f6fSMat Martineau struct l2cap_ctrl *control) 1150a67d7f6fSMat Martineau { 1151a67d7f6fSMat Martineau struct sk_buff *skb; 1152a67d7f6fSMat Martineau u32 control_field; 1153a67d7f6fSMat Martineau 1154a67d7f6fSMat Martineau BT_DBG("chan %p, control %p", chan, control); 1155a67d7f6fSMat Martineau 1156a67d7f6fSMat Martineau if (!control->sframe) 1157a67d7f6fSMat Martineau return; 1158a67d7f6fSMat Martineau 1159b99e13adSMat Martineau if (__chan_is_moving(chan)) 1160b99e13adSMat Martineau return; 1161b99e13adSMat Martineau 1162a67d7f6fSMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) && 1163a67d7f6fSMat Martineau !control->poll) 1164a67d7f6fSMat Martineau control->final = 1; 1165a67d7f6fSMat Martineau 1166a67d7f6fSMat Martineau if (control->super == L2CAP_SUPER_RR) 1167a67d7f6fSMat Martineau clear_bit(CONN_RNR_SENT, &chan->conn_state); 1168a67d7f6fSMat Martineau else if (control->super == L2CAP_SUPER_RNR) 1169a67d7f6fSMat Martineau set_bit(CONN_RNR_SENT, &chan->conn_state); 1170a67d7f6fSMat Martineau 1171a67d7f6fSMat Martineau if (control->super != L2CAP_SUPER_SREJ) { 1172a67d7f6fSMat Martineau chan->last_acked_seq = control->reqseq; 1173a67d7f6fSMat Martineau __clear_ack_timer(chan); 1174a67d7f6fSMat Martineau } 1175a67d7f6fSMat Martineau 1176a67d7f6fSMat Martineau BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq, 1177a67d7f6fSMat Martineau control->final, control->poll, control->super); 1178a67d7f6fSMat Martineau 1179a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1180a67d7f6fSMat Martineau control_field = __pack_extended_control(control); 1181a67d7f6fSMat Martineau else 1182a67d7f6fSMat Martineau control_field = __pack_enhanced_control(control); 1183a67d7f6fSMat Martineau 1184a67d7f6fSMat Martineau skb = l2cap_create_sframe_pdu(chan, control_field); 1185a67d7f6fSMat Martineau if (!IS_ERR(skb)) 118673d80debSLuiz Augusto von Dentz l2cap_do_send(chan, skb); 11870a708f8fSGustavo F. Padovan } 11880a708f8fSGustavo F. Padovan 1189c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll) 11900a708f8fSGustavo F. Padovan { 1191c9e3d5e0SMat Martineau struct l2cap_ctrl control; 11920a708f8fSGustavo F. Padovan 1193c9e3d5e0SMat Martineau BT_DBG("chan %p, poll %d", chan, poll); 1194c9e3d5e0SMat Martineau 1195c9e3d5e0SMat Martineau memset(&control, 0, sizeof(control)); 1196c9e3d5e0SMat Martineau control.sframe = 1; 1197c9e3d5e0SMat Martineau control.poll = poll; 1198c9e3d5e0SMat Martineau 1199c9e3d5e0SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 1200c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RNR; 1201c9e3d5e0SMat Martineau else 1202c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RR; 1203c9e3d5e0SMat Martineau 1204c9e3d5e0SMat Martineau control.reqseq = chan->buffer_seq; 1205c9e3d5e0SMat Martineau l2cap_send_sframe(chan, &control); 12060a708f8fSGustavo F. Padovan } 12070a708f8fSGustavo F. Padovan 1208b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) 12090a708f8fSGustavo F. Padovan { 12105ff6f34dSJohan Hedberg if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 12115ff6f34dSJohan Hedberg return true; 12125ff6f34dSJohan Hedberg 1213c1360a1cSGustavo F. Padovan return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); 12140a708f8fSGustavo F. Padovan } 12150a708f8fSGustavo F. Padovan 121693c3e8f5SAndrei Emeltchenko static bool __amp_capable(struct l2cap_chan *chan) 121793c3e8f5SAndrei Emeltchenko { 121893c3e8f5SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 12191df7b17aSMarcel Holtmann struct hci_dev *hdev; 12201df7b17aSMarcel Holtmann bool amp_available = false; 122193c3e8f5SAndrei Emeltchenko 12220bd49fc7SJohan Hedberg if (!(conn->local_fixed_chan & L2CAP_FC_A2MP)) 12231df7b17aSMarcel Holtmann return false; 12241df7b17aSMarcel Holtmann 12250bd49fc7SJohan Hedberg if (!(conn->remote_fixed_chan & L2CAP_FC_A2MP)) 12261df7b17aSMarcel Holtmann return false; 12271df7b17aSMarcel Holtmann 12281df7b17aSMarcel Holtmann read_lock(&hci_dev_list_lock); 12291df7b17aSMarcel Holtmann list_for_each_entry(hdev, &hci_dev_list, list) { 12301df7b17aSMarcel Holtmann if (hdev->amp_type != AMP_TYPE_BREDR && 12311df7b17aSMarcel Holtmann test_bit(HCI_UP, &hdev->flags)) { 12321df7b17aSMarcel Holtmann amp_available = true; 12331df7b17aSMarcel Holtmann break; 12341df7b17aSMarcel Holtmann } 12351df7b17aSMarcel Holtmann } 12361df7b17aSMarcel Holtmann read_unlock(&hci_dev_list_lock); 12371df7b17aSMarcel Holtmann 12381df7b17aSMarcel Holtmann if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED) 12391df7b17aSMarcel Holtmann return amp_available; 1240848566b3SMarcel Holtmann 124193c3e8f5SAndrei Emeltchenko return false; 124293c3e8f5SAndrei Emeltchenko } 124393c3e8f5SAndrei Emeltchenko 12445ce66b59SAndrei Emeltchenko static bool l2cap_check_efs(struct l2cap_chan *chan) 12455ce66b59SAndrei Emeltchenko { 12465ce66b59SAndrei Emeltchenko /* Check EFS parameters */ 12475ce66b59SAndrei Emeltchenko return true; 12485ce66b59SAndrei Emeltchenko } 12495ce66b59SAndrei Emeltchenko 12502766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan) 12519b27f350SAndrei Emeltchenko { 12529b27f350SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 12539b27f350SAndrei Emeltchenko struct l2cap_conn_req req; 12549b27f350SAndrei Emeltchenko 12559b27f350SAndrei Emeltchenko req.scid = cpu_to_le16(chan->scid); 12569b27f350SAndrei Emeltchenko req.psm = chan->psm; 12579b27f350SAndrei Emeltchenko 12589b27f350SAndrei Emeltchenko chan->ident = l2cap_get_ident(conn); 12599b27f350SAndrei Emeltchenko 12609b27f350SAndrei Emeltchenko set_bit(CONF_CONNECT_PEND, &chan->conf_state); 12619b27f350SAndrei Emeltchenko 12629b27f350SAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); 12639b27f350SAndrei Emeltchenko } 12649b27f350SAndrei Emeltchenko 12658eb200bdSMat Martineau static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id) 12668eb200bdSMat Martineau { 12678eb200bdSMat Martineau struct l2cap_create_chan_req req; 12688eb200bdSMat Martineau req.scid = cpu_to_le16(chan->scid); 12698eb200bdSMat Martineau req.psm = chan->psm; 12708eb200bdSMat Martineau req.amp_id = amp_id; 12718eb200bdSMat Martineau 12728eb200bdSMat Martineau chan->ident = l2cap_get_ident(chan->conn); 12738eb200bdSMat Martineau 12748eb200bdSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ, 12758eb200bdSMat Martineau sizeof(req), &req); 12768eb200bdSMat Martineau } 12778eb200bdSMat Martineau 127802b0fbb9SMat Martineau static void l2cap_move_setup(struct l2cap_chan *chan) 127902b0fbb9SMat Martineau { 128002b0fbb9SMat Martineau struct sk_buff *skb; 128102b0fbb9SMat Martineau 128202b0fbb9SMat Martineau BT_DBG("chan %p", chan); 128302b0fbb9SMat Martineau 128402b0fbb9SMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 128502b0fbb9SMat Martineau return; 128602b0fbb9SMat Martineau 128702b0fbb9SMat Martineau __clear_retrans_timer(chan); 128802b0fbb9SMat Martineau __clear_monitor_timer(chan); 128902b0fbb9SMat Martineau __clear_ack_timer(chan); 129002b0fbb9SMat Martineau 129102b0fbb9SMat Martineau chan->retry_count = 0; 129202b0fbb9SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 1293a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.retries) 1294a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 1; 129502b0fbb9SMat Martineau else 129602b0fbb9SMat Martineau break; 129702b0fbb9SMat Martineau } 129802b0fbb9SMat Martineau 129902b0fbb9SMat Martineau chan->expected_tx_seq = chan->buffer_seq; 130002b0fbb9SMat Martineau 130102b0fbb9SMat Martineau clear_bit(CONN_REJ_ACT, &chan->conn_state); 130202b0fbb9SMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 130302b0fbb9SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 130402b0fbb9SMat Martineau l2cap_seq_list_clear(&chan->srej_list); 130502b0fbb9SMat Martineau skb_queue_purge(&chan->srej_q); 130602b0fbb9SMat Martineau 130702b0fbb9SMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 130802b0fbb9SMat Martineau chan->rx_state = L2CAP_RX_STATE_MOVE; 130902b0fbb9SMat Martineau 131002b0fbb9SMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 131102b0fbb9SMat Martineau } 131202b0fbb9SMat Martineau 13135f3847a4SMat Martineau static void l2cap_move_done(struct l2cap_chan *chan) 13145f3847a4SMat Martineau { 13155f3847a4SMat Martineau u8 move_role = chan->move_role; 13165f3847a4SMat Martineau BT_DBG("chan %p", chan); 13175f3847a4SMat Martineau 13185f3847a4SMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 13195f3847a4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 13205f3847a4SMat Martineau 13215f3847a4SMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 13225f3847a4SMat Martineau return; 13235f3847a4SMat Martineau 13245f3847a4SMat Martineau switch (move_role) { 13255f3847a4SMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 13265f3847a4SMat Martineau l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL); 13275f3847a4SMat Martineau chan->rx_state = L2CAP_RX_STATE_WAIT_F; 13285f3847a4SMat Martineau break; 13295f3847a4SMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 13305f3847a4SMat Martineau chan->rx_state = L2CAP_RX_STATE_WAIT_P; 13315f3847a4SMat Martineau break; 13325f3847a4SMat Martineau } 13335f3847a4SMat Martineau } 13345f3847a4SMat Martineau 13359f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan) 13369f0caeb1SVinicius Costa Gomes { 1337315917e0SJohan Hedberg /* The channel may have already been flagged as connected in 1338315917e0SJohan Hedberg * case of receiving data before the L2CAP info req/rsp 1339315917e0SJohan Hedberg * procedure is complete. 1340315917e0SJohan Hedberg */ 1341315917e0SJohan Hedberg if (chan->state == BT_CONNECTED) 1342315917e0SJohan Hedberg return; 1343315917e0SJohan Hedberg 13442827011fSMat Martineau /* This clears all conf flags, including CONF_NOT_COMPLETE */ 13459f0caeb1SVinicius Costa Gomes chan->conf_state = 0; 13469f0caeb1SVinicius Costa Gomes __clear_chan_timer(chan); 13479f0caeb1SVinicius Costa Gomes 134815f02b91SLuiz Augusto von Dentz switch (chan->mode) { 134915f02b91SLuiz Augusto von Dentz case L2CAP_MODE_LE_FLOWCTL: 135015f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL: 135115f02b91SLuiz Augusto von Dentz if (!chan->tx_credits) 13520ce43ce6SJohan Hedberg chan->ops->suspend(chan); 135315f02b91SLuiz Augusto von Dentz break; 135415f02b91SLuiz Augusto von Dentz } 1355177f8f2bSJohan Hedberg 135654a59aa2SAndrei Emeltchenko chan->state = BT_CONNECTED; 13579f0caeb1SVinicius Costa Gomes 135854a59aa2SAndrei Emeltchenko chan->ops->ready(chan); 13599f0caeb1SVinicius Costa Gomes } 13609f0caeb1SVinicius Costa Gomes 1361f1496deeSJohan Hedberg static void l2cap_le_connect(struct l2cap_chan *chan) 1362f1496deeSJohan Hedberg { 1363f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1364f1496deeSJohan Hedberg struct l2cap_le_conn_req req; 1365f1496deeSJohan Hedberg 1366595177f3SJohan Hedberg if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags)) 1367595177f3SJohan Hedberg return; 1368595177f3SJohan Hedberg 13694b6e228eSLuiz Augusto von Dentz if (!chan->imtu) 13704b6e228eSLuiz Augusto von Dentz chan->imtu = chan->conn->mtu; 13714b6e228eSLuiz Augusto von Dentz 1372ba8f5289SLuiz Augusto von Dentz l2cap_le_flowctl_init(chan, 0); 1373fe149310SLuiz Augusto von Dentz 1374f1496deeSJohan Hedberg req.psm = chan->psm; 1375f1496deeSJohan Hedberg req.scid = cpu_to_le16(chan->scid); 1376f1496deeSJohan Hedberg req.mtu = cpu_to_le16(chan->imtu); 13773916aed8SJohan Hedberg req.mps = cpu_to_le16(chan->mps); 13780cd75f7eSJohan Hedberg req.credits = cpu_to_le16(chan->rx_credits); 1379f1496deeSJohan Hedberg 1380f1496deeSJohan Hedberg chan->ident = l2cap_get_ident(conn); 1381f1496deeSJohan Hedberg 1382f1496deeSJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ, 1383f1496deeSJohan Hedberg sizeof(req), &req); 1384f1496deeSJohan Hedberg } 1385f1496deeSJohan Hedberg 1386da49b602SLuiz Augusto von Dentz struct l2cap_ecred_conn_data { 138715f02b91SLuiz Augusto von Dentz struct { 138815f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_req req; 1389da49b602SLuiz Augusto von Dentz __le16 scid[5]; 139015f02b91SLuiz Augusto von Dentz } __packed pdu; 1391da49b602SLuiz Augusto von Dentz struct l2cap_chan *chan; 1392da49b602SLuiz Augusto von Dentz struct pid *pid; 1393da49b602SLuiz Augusto von Dentz int count; 1394da49b602SLuiz Augusto von Dentz }; 1395da49b602SLuiz Augusto von Dentz 1396da49b602SLuiz Augusto von Dentz static void l2cap_ecred_defer_connect(struct l2cap_chan *chan, void *data) 1397da49b602SLuiz Augusto von Dentz { 1398da49b602SLuiz Augusto von Dentz struct l2cap_ecred_conn_data *conn = data; 1399da49b602SLuiz Augusto von Dentz struct pid *pid; 1400da49b602SLuiz Augusto von Dentz 1401da49b602SLuiz Augusto von Dentz if (chan == conn->chan) 1402da49b602SLuiz Augusto von Dentz return; 1403da49b602SLuiz Augusto von Dentz 1404da49b602SLuiz Augusto von Dentz if (!test_and_clear_bit(FLAG_DEFER_SETUP, &chan->flags)) 1405da49b602SLuiz Augusto von Dentz return; 1406da49b602SLuiz Augusto von Dentz 1407da49b602SLuiz Augusto von Dentz pid = chan->ops->get_peer_pid(chan); 1408da49b602SLuiz Augusto von Dentz 1409da49b602SLuiz Augusto von Dentz /* Only add deferred channels with the same PID/PSM */ 1410da49b602SLuiz Augusto von Dentz if (conn->pid != pid || chan->psm != conn->chan->psm || chan->ident || 1411da49b602SLuiz Augusto von Dentz chan->mode != L2CAP_MODE_EXT_FLOWCTL || chan->state != BT_CONNECT) 1412da49b602SLuiz Augusto von Dentz return; 141315f02b91SLuiz Augusto von Dentz 141415f02b91SLuiz Augusto von Dentz if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags)) 141515f02b91SLuiz Augusto von Dentz return; 141615f02b91SLuiz Augusto von Dentz 141715f02b91SLuiz Augusto von Dentz l2cap_ecred_init(chan, 0); 141815f02b91SLuiz Augusto von Dentz 1419da49b602SLuiz Augusto von Dentz /* Set the same ident so we can match on the rsp */ 1420da49b602SLuiz Augusto von Dentz chan->ident = conn->chan->ident; 1421da49b602SLuiz Augusto von Dentz 1422da49b602SLuiz Augusto von Dentz /* Include all channels deferred */ 1423da49b602SLuiz Augusto von Dentz conn->pdu.scid[conn->count] = cpu_to_le16(chan->scid); 1424da49b602SLuiz Augusto von Dentz 1425da49b602SLuiz Augusto von Dentz conn->count++; 1426da49b602SLuiz Augusto von Dentz } 1427da49b602SLuiz Augusto von Dentz 1428da49b602SLuiz Augusto von Dentz static void l2cap_ecred_connect(struct l2cap_chan *chan) 1429da49b602SLuiz Augusto von Dentz { 1430da49b602SLuiz Augusto von Dentz struct l2cap_conn *conn = chan->conn; 1431da49b602SLuiz Augusto von Dentz struct l2cap_ecred_conn_data data; 1432da49b602SLuiz Augusto von Dentz 1433da49b602SLuiz Augusto von Dentz if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 1434da49b602SLuiz Augusto von Dentz return; 1435da49b602SLuiz Augusto von Dentz 1436da49b602SLuiz Augusto von Dentz if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags)) 1437da49b602SLuiz Augusto von Dentz return; 1438da49b602SLuiz Augusto von Dentz 1439da49b602SLuiz Augusto von Dentz l2cap_ecred_init(chan, 0); 1440da49b602SLuiz Augusto von Dentz 1441da49b602SLuiz Augusto von Dentz data.pdu.req.psm = chan->psm; 1442da49b602SLuiz Augusto von Dentz data.pdu.req.mtu = cpu_to_le16(chan->imtu); 1443da49b602SLuiz Augusto von Dentz data.pdu.req.mps = cpu_to_le16(chan->mps); 1444da49b602SLuiz Augusto von Dentz data.pdu.req.credits = cpu_to_le16(chan->rx_credits); 1445da49b602SLuiz Augusto von Dentz data.pdu.scid[0] = cpu_to_le16(chan->scid); 144615f02b91SLuiz Augusto von Dentz 144715f02b91SLuiz Augusto von Dentz chan->ident = l2cap_get_ident(conn); 1448da49b602SLuiz Augusto von Dentz data.pid = chan->ops->get_peer_pid(chan); 1449da49b602SLuiz Augusto von Dentz 1450da49b602SLuiz Augusto von Dentz data.count = 1; 1451da49b602SLuiz Augusto von Dentz data.chan = chan; 1452da49b602SLuiz Augusto von Dentz data.pid = chan->ops->get_peer_pid(chan); 1453da49b602SLuiz Augusto von Dentz 1454da49b602SLuiz Augusto von Dentz __l2cap_chan_list(conn, l2cap_ecred_defer_connect, &data); 145515f02b91SLuiz Augusto von Dentz 145615f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_CONN_REQ, 1457da49b602SLuiz Augusto von Dentz sizeof(data.pdu.req) + data.count * sizeof(__le16), 1458da49b602SLuiz Augusto von Dentz &data.pdu); 145915f02b91SLuiz Augusto von Dentz } 146015f02b91SLuiz Augusto von Dentz 1461f1496deeSJohan Hedberg static void l2cap_le_start(struct l2cap_chan *chan) 1462f1496deeSJohan Hedberg { 1463f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1464f1496deeSJohan Hedberg 1465f1496deeSJohan Hedberg if (!smp_conn_security(conn->hcon, chan->sec_level)) 1466f1496deeSJohan Hedberg return; 1467f1496deeSJohan Hedberg 1468f1496deeSJohan Hedberg if (!chan->psm) { 1469f1496deeSJohan Hedberg l2cap_chan_ready(chan); 1470f1496deeSJohan Hedberg return; 1471f1496deeSJohan Hedberg } 1472f1496deeSJohan Hedberg 147315f02b91SLuiz Augusto von Dentz if (chan->state == BT_CONNECT) { 147415f02b91SLuiz Augusto von Dentz if (chan->mode == L2CAP_MODE_EXT_FLOWCTL) 147515f02b91SLuiz Augusto von Dentz l2cap_ecred_connect(chan); 147615f02b91SLuiz Augusto von Dentz else 1477f1496deeSJohan Hedberg l2cap_le_connect(chan); 1478f1496deeSJohan Hedberg } 147915f02b91SLuiz Augusto von Dentz } 1480f1496deeSJohan Hedberg 148193c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan) 148293c3e8f5SAndrei Emeltchenko { 148393c3e8f5SAndrei Emeltchenko if (__amp_capable(chan)) { 148493c3e8f5SAndrei Emeltchenko BT_DBG("chan %p AMP capable: discover AMPs", chan); 148593c3e8f5SAndrei Emeltchenko a2mp_discover_amp(chan); 1486f1496deeSJohan Hedberg } else if (chan->conn->hcon->type == LE_LINK) { 1487f1496deeSJohan Hedberg l2cap_le_start(chan); 148893c3e8f5SAndrei Emeltchenko } else { 148993c3e8f5SAndrei Emeltchenko l2cap_send_conn_req(chan); 149093c3e8f5SAndrei Emeltchenko } 149193c3e8f5SAndrei Emeltchenko } 149293c3e8f5SAndrei Emeltchenko 1493aeaeb4bbSJohan Hedberg static void l2cap_request_info(struct l2cap_conn *conn) 14940a708f8fSGustavo F. Padovan { 14950a708f8fSGustavo F. Padovan struct l2cap_info_req req; 1496aeaeb4bbSJohan Hedberg 1497aeaeb4bbSJohan Hedberg if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1498aeaeb4bbSJohan Hedberg return; 1499aeaeb4bbSJohan Hedberg 1500dcf4adbfSJoe Perches req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 15010a708f8fSGustavo F. Padovan 15020a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 15030a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 15040a708f8fSGustavo F. Padovan 1505ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 15060a708f8fSGustavo F. Padovan 15072d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, 15082d792818SGustavo Padovan sizeof(req), &req); 15090a708f8fSGustavo F. Padovan } 1510aeaeb4bbSJohan Hedberg 1511693cd8ceSMarcel Holtmann static bool l2cap_check_enc_key_size(struct hci_conn *hcon) 1512693cd8ceSMarcel Holtmann { 1513693cd8ceSMarcel Holtmann /* The minimum encryption key size needs to be enforced by the 1514693cd8ceSMarcel Holtmann * host stack before establishing any L2CAP connections. The 1515693cd8ceSMarcel Holtmann * specification in theory allows a minimum of 1, but to align 1516693cd8ceSMarcel Holtmann * BR/EDR and LE transports, a minimum of 7 is chosen. 1517693cd8ceSMarcel Holtmann * 1518693cd8ceSMarcel Holtmann * This check might also be called for unencrypted connections 1519693cd8ceSMarcel Holtmann * that have no key size requirements. Ensure that the link is 1520693cd8ceSMarcel Holtmann * actually encrypted before enforcing a key size. 1521693cd8ceSMarcel Holtmann */ 1522288c0697SArchie Pusaka int min_key_size = hcon->hdev->min_enc_key_size; 1523288c0697SArchie Pusaka 1524288c0697SArchie Pusaka /* On FIPS security level, key size must be 16 bytes */ 1525288c0697SArchie Pusaka if (hcon->sec_level == BT_SECURITY_FIPS) 1526288c0697SArchie Pusaka min_key_size = 16; 1527288c0697SArchie Pusaka 1528693cd8ceSMarcel Holtmann return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) || 1529288c0697SArchie Pusaka hcon->enc_key_size >= min_key_size); 1530693cd8ceSMarcel Holtmann } 1531693cd8ceSMarcel Holtmann 1532aeaeb4bbSJohan Hedberg static void l2cap_do_start(struct l2cap_chan *chan) 1533aeaeb4bbSJohan Hedberg { 1534aeaeb4bbSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1535aeaeb4bbSJohan Hedberg 1536aeaeb4bbSJohan Hedberg if (conn->hcon->type == LE_LINK) { 1537aeaeb4bbSJohan Hedberg l2cap_le_start(chan); 1538aeaeb4bbSJohan Hedberg return; 1539aeaeb4bbSJohan Hedberg } 1540aeaeb4bbSJohan Hedberg 1541aeaeb4bbSJohan Hedberg if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)) { 1542aeaeb4bbSJohan Hedberg l2cap_request_info(conn); 1543aeaeb4bbSJohan Hedberg return; 1544aeaeb4bbSJohan Hedberg } 1545aeaeb4bbSJohan Hedberg 1546aeaeb4bbSJohan Hedberg if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) 1547aeaeb4bbSJohan Hedberg return; 1548aeaeb4bbSJohan Hedberg 1549693cd8ceSMarcel Holtmann if (!l2cap_chan_check_security(chan, true) || 1550693cd8ceSMarcel Holtmann !__l2cap_no_conn_pending(chan)) 1551693cd8ceSMarcel Holtmann return; 1552693cd8ceSMarcel Holtmann 1553693cd8ceSMarcel Holtmann if (l2cap_check_enc_key_size(conn->hcon)) 1554aeaeb4bbSJohan Hedberg l2cap_start_connection(chan); 1555693cd8ceSMarcel Holtmann else 1556693cd8ceSMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 15570a708f8fSGustavo F. Padovan } 15580a708f8fSGustavo F. Padovan 15590a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) 15600a708f8fSGustavo F. Padovan { 15610a708f8fSGustavo F. Padovan u32 local_feat_mask = l2cap_feat_mask; 15620a708f8fSGustavo F. Padovan if (!disable_ertm) 15630a708f8fSGustavo F. Padovan local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING; 15640a708f8fSGustavo F. Padovan 15650a708f8fSGustavo F. Padovan switch (mode) { 15660a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 15670a708f8fSGustavo F. Padovan return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask; 15680a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 15690a708f8fSGustavo F. Padovan return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask; 15700a708f8fSGustavo F. Padovan default: 15710a708f8fSGustavo F. Padovan return 0x00; 15720a708f8fSGustavo F. Padovan } 15730a708f8fSGustavo F. Padovan } 15740a708f8fSGustavo F. Padovan 15755e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err) 15760a708f8fSGustavo F. Padovan { 15775e4e3972SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 15780a708f8fSGustavo F. Padovan struct l2cap_disconn_req req; 15790a708f8fSGustavo F. Padovan 15800a708f8fSGustavo F. Padovan if (!conn) 15810a708f8fSGustavo F. Padovan return; 15820a708f8fSGustavo F. Padovan 1583aad3d0e3SAndrei Emeltchenko if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) { 15841a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 15851a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 15861a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 15870a708f8fSGustavo F. Padovan } 15880a708f8fSGustavo F. Padovan 15892338a7e0SJohan Hedberg if (chan->scid == L2CAP_CID_A2MP) { 1590d117773cSGustavo Padovan l2cap_state_change(chan, BT_DISCONN); 1591416fa752SAndrei Emeltchenko return; 1592416fa752SAndrei Emeltchenko } 1593416fa752SAndrei Emeltchenko 1594fe4128e0SGustavo F. Padovan req.dcid = cpu_to_le16(chan->dcid); 1595fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 15962d792818SGustavo Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ, 15972d792818SGustavo Padovan sizeof(req), &req); 15980a708f8fSGustavo F. Padovan 1599f8e73017SGustavo Padovan l2cap_state_change_and_error(chan, BT_DISCONN, err); 16000a708f8fSGustavo F. Padovan } 16010a708f8fSGustavo F. Padovan 16020a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */ 16030a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn) 16040a708f8fSGustavo F. Padovan { 16053df91ea2SAndrei Emeltchenko struct l2cap_chan *chan, *tmp; 16060a708f8fSGustavo F. Padovan 16070a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 16080a708f8fSGustavo F. Padovan 16093df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 16100a708f8fSGustavo F. Padovan 16113df91ea2SAndrei Emeltchenko list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 16126be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 16130a708f8fSGustavo F. Padovan 1614715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1615aeaeb4bbSJohan Hedberg l2cap_chan_ready(chan); 16166be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16170a708f8fSGustavo F. Padovan continue; 16180a708f8fSGustavo F. Padovan } 16190a708f8fSGustavo F. Padovan 162089bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 1621e7cafc45SJohan Hedberg if (!l2cap_chan_check_security(chan, true) || 1622b4450035SGustavo F. Padovan !__l2cap_no_conn_pending(chan)) { 16236be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16240a708f8fSGustavo F. Padovan continue; 16250a708f8fSGustavo F. Padovan } 16260a708f8fSGustavo F. Padovan 1627c1360a1cSGustavo F. Padovan if (!l2cap_mode_supported(chan->mode, conn->feat_mask) 1628c1360a1cSGustavo F. Padovan && test_bit(CONF_STATE2_DEVICE, 1629c1360a1cSGustavo F. Padovan &chan->conf_state)) { 16300f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 16316be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16320a708f8fSGustavo F. Padovan continue; 16330a708f8fSGustavo F. Padovan } 16340a708f8fSGustavo F. Padovan 1635693cd8ceSMarcel Holtmann if (l2cap_check_enc_key_size(conn->hcon)) 163693c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 1637693cd8ceSMarcel Holtmann else 1638693cd8ceSMarcel Holtmann l2cap_chan_close(chan, ECONNREFUSED); 16390a708f8fSGustavo F. Padovan 164089bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 16410a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 16420a708f8fSGustavo F. Padovan char buf[128]; 1643fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 1644fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 16450a708f8fSGustavo F. Padovan 1646e7cafc45SJohan Hedberg if (l2cap_chan_check_security(chan, false)) { 1647bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 1648dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_PEND); 1649dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND); 16502dc4e510SGustavo Padovan chan->ops->defer(chan); 16510a708f8fSGustavo F. Padovan 16520a708f8fSGustavo F. Padovan } else { 1653acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 1654dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 1655dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 16560a708f8fSGustavo F. Padovan } 16570a708f8fSGustavo F. Padovan } else { 1658dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_PEND); 1659dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND); 16600a708f8fSGustavo F. Padovan } 16610a708f8fSGustavo F. Padovan 1662fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 1663fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 16640a708f8fSGustavo F. Padovan 1665c1360a1cSGustavo F. Padovan if (test_bit(CONF_REQ_SENT, &chan->conf_state) || 16660a708f8fSGustavo F. Padovan rsp.result != L2CAP_CR_SUCCESS) { 16676be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16680a708f8fSGustavo F. Padovan continue; 16690a708f8fSGustavo F. Padovan } 16700a708f8fSGustavo F. Padovan 1671c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 16720a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 1673e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); 167473ffa904SGustavo F. Padovan chan->num_conf_req++; 16750a708f8fSGustavo F. Padovan } 16760a708f8fSGustavo F. Padovan 16776be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16780a708f8fSGustavo F. Padovan } 16790a708f8fSGustavo F. Padovan 16803df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 16810a708f8fSGustavo F. Padovan } 16820a708f8fSGustavo F. Padovan 1683b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn) 1684b62f328bSVille Tervo { 1685cc8dba2bSMarcel Holtmann struct hci_conn *hcon = conn->hcon; 1686dcc36c16SJohan Hedberg struct hci_dev *hdev = hcon->hdev; 1687b62f328bSVille Tervo 1688e760ec12SJohan Hedberg BT_DBG("%s conn %p", hdev->name, conn); 1689b62f328bSVille Tervo 1690e760ec12SJohan Hedberg /* For outgoing pairing which doesn't necessarily have an 1691e760ec12SJohan Hedberg * associated socket (e.g. mgmt_pair_device). 1692e760ec12SJohan Hedberg */ 1693e760ec12SJohan Hedberg if (hcon->out) 1694e760ec12SJohan Hedberg smp_conn_security(hcon, hcon->pending_sec_level); 1695cc8dba2bSMarcel Holtmann 169680afeb6cSMarcel Holtmann /* For LE slave connections, make sure the connection interval 169780afeb6cSMarcel Holtmann * is in the range of the minium and maximum interval that has 169880afeb6cSMarcel Holtmann * been configured for this connection. If not, then trigger 169980afeb6cSMarcel Holtmann * the connection update procedure. 170080afeb6cSMarcel Holtmann */ 170140bef302SJohan Hedberg if (hcon->role == HCI_ROLE_SLAVE && 170280afeb6cSMarcel Holtmann (hcon->le_conn_interval < hcon->le_conn_min_interval || 170380afeb6cSMarcel Holtmann hcon->le_conn_interval > hcon->le_conn_max_interval)) { 170480afeb6cSMarcel Holtmann struct l2cap_conn_param_update_req req; 170580afeb6cSMarcel Holtmann 170680afeb6cSMarcel Holtmann req.min = cpu_to_le16(hcon->le_conn_min_interval); 170780afeb6cSMarcel Holtmann req.max = cpu_to_le16(hcon->le_conn_max_interval); 170880afeb6cSMarcel Holtmann req.latency = cpu_to_le16(hcon->le_conn_latency); 170980afeb6cSMarcel Holtmann req.to_multiplier = cpu_to_le16(hcon->le_supv_timeout); 171080afeb6cSMarcel Holtmann 171180afeb6cSMarcel Holtmann l2cap_send_cmd(conn, l2cap_get_ident(conn), 171280afeb6cSMarcel Holtmann L2CAP_CONN_PARAM_UPDATE_REQ, sizeof(req), &req); 171380afeb6cSMarcel Holtmann } 1714b62f328bSVille Tervo } 1715b62f328bSVille Tervo 17160a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn) 17170a708f8fSGustavo F. Padovan { 171848454079SGustavo F. Padovan struct l2cap_chan *chan; 1719cc110922SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 17200a708f8fSGustavo F. Padovan 17210a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 17220a708f8fSGustavo F. Padovan 1723aeaeb4bbSJohan Hedberg if (hcon->type == ACL_LINK) 1724aeaeb4bbSJohan Hedberg l2cap_request_info(conn); 1725aeaeb4bbSJohan Hedberg 1726e760ec12SJohan Hedberg mutex_lock(&conn->chan_lock); 1727e760ec12SJohan Hedberg 17283df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1729baa7e1faSGustavo F. Padovan 17306be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 17310a708f8fSGustavo F. Padovan 17322338a7e0SJohan Hedberg if (chan->scid == L2CAP_CID_A2MP) { 1733416fa752SAndrei Emeltchenko l2cap_chan_unlock(chan); 1734416fa752SAndrei Emeltchenko continue; 1735416fa752SAndrei Emeltchenko } 1736416fa752SAndrei Emeltchenko 1737cc110922SVinicius Costa Gomes if (hcon->type == LE_LINK) { 1738f1496deeSJohan Hedberg l2cap_le_start(chan); 173963128451SVinicius Costa Gomes } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1740aeaeb4bbSJohan Hedberg if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 174174e75740SGustavo Padovan l2cap_chan_ready(chan); 17421c244f79SGustavo Padovan } else if (chan->state == BT_CONNECT) { 1743fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 17441c244f79SGustavo Padovan } 17450a708f8fSGustavo F. Padovan 17466be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 17470a708f8fSGustavo F. Padovan } 17480a708f8fSGustavo F. Padovan 17493df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 175061a939c6SJohan Hedberg 175179a05727SJohan Hedberg if (hcon->type == LE_LINK) 175279a05727SJohan Hedberg l2cap_le_conn_ready(conn); 175379a05727SJohan Hedberg 175461a939c6SJohan Hedberg queue_work(hcon->hdev->workqueue, &conn->pending_rx_work); 17550a708f8fSGustavo F. Padovan } 17560a708f8fSGustavo F. Padovan 17570a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */ 17580a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) 17590a708f8fSGustavo F. Padovan { 176048454079SGustavo F. Padovan struct l2cap_chan *chan; 17610a708f8fSGustavo F. Padovan 17620a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 17630a708f8fSGustavo F. Padovan 17643df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 17650a708f8fSGustavo F. Padovan 17663df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1767ecf61bdbSAndrei Emeltchenko if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) 17681d8b1fd5SGustavo Padovan l2cap_chan_set_err(chan, err); 17690a708f8fSGustavo F. Padovan } 17700a708f8fSGustavo F. Padovan 17713df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 17720a708f8fSGustavo F. Padovan } 17730a708f8fSGustavo F. Padovan 1774f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work) 17750a708f8fSGustavo F. Padovan { 1776f878fcadSGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 1777030013d8SGustavo F. Padovan info_timer.work); 17780a708f8fSGustavo F. Padovan 17790a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 17800a708f8fSGustavo F. Padovan conn->info_ident = 0; 17810a708f8fSGustavo F. Padovan 17820a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 17830a708f8fSGustavo F. Padovan } 17840a708f8fSGustavo F. Padovan 17852c8e1411SDavid Herrmann /* 17862c8e1411SDavid Herrmann * l2cap_user 17872c8e1411SDavid Herrmann * External modules can register l2cap_user objects on l2cap_conn. The ->probe 17882c8e1411SDavid Herrmann * callback is called during registration. The ->remove callback is called 17892c8e1411SDavid Herrmann * during unregistration. 17902c8e1411SDavid Herrmann * An l2cap_user object can either be explicitly unregistered or when the 17912c8e1411SDavid Herrmann * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon, 17922c8e1411SDavid Herrmann * l2cap->hchan, .. are valid as long as the remove callback hasn't been called. 17932c8e1411SDavid Herrmann * External modules must own a reference to the l2cap_conn object if they intend 17942c8e1411SDavid Herrmann * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at 17952c8e1411SDavid Herrmann * any time if they don't. 17962c8e1411SDavid Herrmann */ 17972c8e1411SDavid Herrmann 17982c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) 17992c8e1411SDavid Herrmann { 18002c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev; 18012c8e1411SDavid Herrmann int ret; 18022c8e1411SDavid Herrmann 18032c8e1411SDavid Herrmann /* We need to check whether l2cap_conn is registered. If it is not, we 18042c8e1411SDavid Herrmann * must not register the l2cap_user. l2cap_conn_del() is unregisters 18052c8e1411SDavid Herrmann * l2cap_conn objects, but doesn't provide its own locking. Instead, it 18062c8e1411SDavid Herrmann * relies on the parent hci_conn object to be locked. This itself relies 18072c8e1411SDavid Herrmann * on the hci_dev object to be locked. So we must lock the hci device 18082c8e1411SDavid Herrmann * here, too. */ 18092c8e1411SDavid Herrmann 18102c8e1411SDavid Herrmann hci_dev_lock(hdev); 18112c8e1411SDavid Herrmann 1812835a6a2fSAlexey Dobriyan if (!list_empty(&user->list)) { 18132c8e1411SDavid Herrmann ret = -EINVAL; 18142c8e1411SDavid Herrmann goto out_unlock; 18152c8e1411SDavid Herrmann } 18162c8e1411SDavid Herrmann 18172c8e1411SDavid Herrmann /* conn->hchan is NULL after l2cap_conn_del() was called */ 18182c8e1411SDavid Herrmann if (!conn->hchan) { 18192c8e1411SDavid Herrmann ret = -ENODEV; 18202c8e1411SDavid Herrmann goto out_unlock; 18212c8e1411SDavid Herrmann } 18222c8e1411SDavid Herrmann 18232c8e1411SDavid Herrmann ret = user->probe(conn, user); 18242c8e1411SDavid Herrmann if (ret) 18252c8e1411SDavid Herrmann goto out_unlock; 18262c8e1411SDavid Herrmann 18272c8e1411SDavid Herrmann list_add(&user->list, &conn->users); 18282c8e1411SDavid Herrmann ret = 0; 18292c8e1411SDavid Herrmann 18302c8e1411SDavid Herrmann out_unlock: 18312c8e1411SDavid Herrmann hci_dev_unlock(hdev); 18322c8e1411SDavid Herrmann return ret; 18332c8e1411SDavid Herrmann } 18342c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user); 18352c8e1411SDavid Herrmann 18362c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) 18372c8e1411SDavid Herrmann { 18382c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev; 18392c8e1411SDavid Herrmann 18402c8e1411SDavid Herrmann hci_dev_lock(hdev); 18412c8e1411SDavid Herrmann 1842835a6a2fSAlexey Dobriyan if (list_empty(&user->list)) 18432c8e1411SDavid Herrmann goto out_unlock; 18442c8e1411SDavid Herrmann 1845ab944c83STedd Ho-Jeong An list_del_init(&user->list); 18462c8e1411SDavid Herrmann user->remove(conn, user); 18472c8e1411SDavid Herrmann 18482c8e1411SDavid Herrmann out_unlock: 18492c8e1411SDavid Herrmann hci_dev_unlock(hdev); 18502c8e1411SDavid Herrmann } 18512c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user); 18522c8e1411SDavid Herrmann 18532c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn) 18542c8e1411SDavid Herrmann { 18552c8e1411SDavid Herrmann struct l2cap_user *user; 18562c8e1411SDavid Herrmann 18572c8e1411SDavid Herrmann while (!list_empty(&conn->users)) { 18582c8e1411SDavid Herrmann user = list_first_entry(&conn->users, struct l2cap_user, list); 1859ab944c83STedd Ho-Jeong An list_del_init(&user->list); 18602c8e1411SDavid Herrmann user->remove(conn, user); 18612c8e1411SDavid Herrmann } 18622c8e1411SDavid Herrmann } 18632c8e1411SDavid Herrmann 18645d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err) 18655d3de7dfSVinicius Costa Gomes { 18665d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 18675d3de7dfSVinicius Costa Gomes struct l2cap_chan *chan, *l; 18685d3de7dfSVinicius Costa Gomes 18695d3de7dfSVinicius Costa Gomes if (!conn) 18705d3de7dfSVinicius Costa Gomes return; 18715d3de7dfSVinicius Costa Gomes 18725d3de7dfSVinicius Costa Gomes BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); 18735d3de7dfSVinicius Costa Gomes 18745d3de7dfSVinicius Costa Gomes kfree_skb(conn->rx_skb); 18755d3de7dfSVinicius Costa Gomes 187661a939c6SJohan Hedberg skb_queue_purge(&conn->pending_rx); 18777ab56c3aSJukka Taimisto 18787ab56c3aSJukka Taimisto /* We can not call flush_work(&conn->pending_rx_work) here since we 18797ab56c3aSJukka Taimisto * might block if we are running on a worker from the same workqueue 18807ab56c3aSJukka Taimisto * pending_rx_work is waiting on. 18817ab56c3aSJukka Taimisto */ 18827ab56c3aSJukka Taimisto if (work_pending(&conn->pending_rx_work)) 18837ab56c3aSJukka Taimisto cancel_work_sync(&conn->pending_rx_work); 188461a939c6SJohan Hedberg 1885f3d82d0cSJohan Hedberg if (work_pending(&conn->id_addr_update_work)) 1886f3d82d0cSJohan Hedberg cancel_work_sync(&conn->id_addr_update_work); 1887f3d82d0cSJohan Hedberg 18882c8e1411SDavid Herrmann l2cap_unregister_all_users(conn); 18892c8e1411SDavid Herrmann 1890e31fb860SJohan Hedberg /* Force the connection to be immediately dropped */ 1891e31fb860SJohan Hedberg hcon->disc_timeout = 0; 1892e31fb860SJohan Hedberg 18933df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 18943df91ea2SAndrei Emeltchenko 18955d3de7dfSVinicius Costa Gomes /* Kill channels */ 18965d3de7dfSVinicius Costa Gomes list_for_each_entry_safe(chan, l, &conn->chan_l, list) { 189761d6ef3eSMat Martineau l2cap_chan_hold(chan); 18986be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 18996be36555SAndrei Emeltchenko 19005d3de7dfSVinicius Costa Gomes l2cap_chan_del(chan, err); 19016be36555SAndrei Emeltchenko 190280b98027SGustavo Padovan chan->ops->close(chan); 19036c08fc89SManish Mandlik 19046c08fc89SManish Mandlik l2cap_chan_unlock(chan); 190561d6ef3eSMat Martineau l2cap_chan_put(chan); 19065d3de7dfSVinicius Costa Gomes } 19075d3de7dfSVinicius Costa Gomes 19083df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 19093df91ea2SAndrei Emeltchenko 191073d80debSLuiz Augusto von Dentz hci_chan_del(conn->hchan); 191173d80debSLuiz Augusto von Dentz 19125d3de7dfSVinicius Costa Gomes if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1913127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->info_timer); 19145d3de7dfSVinicius Costa Gomes 19155d3de7dfSVinicius Costa Gomes hcon->l2cap_data = NULL; 19169c903e37SDavid Herrmann conn->hchan = NULL; 19179c903e37SDavid Herrmann l2cap_conn_put(conn); 19185d3de7dfSVinicius Costa Gomes } 19195d3de7dfSVinicius Costa Gomes 19209c903e37SDavid Herrmann static void l2cap_conn_free(struct kref *ref) 19219c903e37SDavid Herrmann { 19229c903e37SDavid Herrmann struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref); 19239c903e37SDavid Herrmann 19249c903e37SDavid Herrmann hci_conn_put(conn->hcon); 19259c903e37SDavid Herrmann kfree(conn); 19269c903e37SDavid Herrmann } 19279c903e37SDavid Herrmann 192851bb8457SJohan Hedberg struct l2cap_conn *l2cap_conn_get(struct l2cap_conn *conn) 19299c903e37SDavid Herrmann { 19309c903e37SDavid Herrmann kref_get(&conn->ref); 193151bb8457SJohan Hedberg return conn; 19329c903e37SDavid Herrmann } 19339c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_get); 19349c903e37SDavid Herrmann 19359c903e37SDavid Herrmann void l2cap_conn_put(struct l2cap_conn *conn) 19369c903e37SDavid Herrmann { 19379c903e37SDavid Herrmann kref_put(&conn->ref, l2cap_conn_free); 19389c903e37SDavid Herrmann } 19399c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_put); 19409c903e37SDavid Herrmann 19410a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */ 19420a708f8fSGustavo F. Padovan 1943c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr. 19440a708f8fSGustavo F. Padovan * Returns closest match. 19450a708f8fSGustavo F. Padovan */ 1946c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, 1947c2287681SIdo Yariv bdaddr_t *src, 1948bf20fd4eSJohan Hedberg bdaddr_t *dst, 1949bf20fd4eSJohan Hedberg u8 link_type) 19500a708f8fSGustavo F. Padovan { 195123691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 19520a708f8fSGustavo F. Padovan 195323691d75SGustavo F. Padovan read_lock(&chan_list_lock); 19540a708f8fSGustavo F. Padovan 195523691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 195689bc500eSGustavo F. Padovan if (state && c->state != state) 19570a708f8fSGustavo F. Padovan continue; 19580a708f8fSGustavo F. Padovan 1959bf20fd4eSJohan Hedberg if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR) 1960bf20fd4eSJohan Hedberg continue; 1961bf20fd4eSJohan Hedberg 1962bf20fd4eSJohan Hedberg if (link_type == LE_LINK && c->src_type == BDADDR_BREDR) 1963bf20fd4eSJohan Hedberg continue; 1964bf20fd4eSJohan Hedberg 196523691d75SGustavo F. Padovan if (c->psm == psm) { 1966c2287681SIdo Yariv int src_match, dst_match; 1967c2287681SIdo Yariv int src_any, dst_any; 1968c2287681SIdo Yariv 19690a708f8fSGustavo F. Padovan /* Exact match. */ 19707eafc59eSMarcel Holtmann src_match = !bacmp(&c->src, src); 19717eafc59eSMarcel Holtmann dst_match = !bacmp(&c->dst, dst); 1972c2287681SIdo Yariv if (src_match && dst_match) { 1973a24cce14SJohan Hedberg l2cap_chan_hold(c); 1974a7567b20SJohannes Berg read_unlock(&chan_list_lock); 197523691d75SGustavo F. Padovan return c; 197623691d75SGustavo F. Padovan } 19770a708f8fSGustavo F. Padovan 19780a708f8fSGustavo F. Padovan /* Closest match */ 19797eafc59eSMarcel Holtmann src_any = !bacmp(&c->src, BDADDR_ANY); 19807eafc59eSMarcel Holtmann dst_any = !bacmp(&c->dst, BDADDR_ANY); 1981c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1982c2287681SIdo Yariv (src_any && dst_any)) 198323691d75SGustavo F. Padovan c1 = c; 19840a708f8fSGustavo F. Padovan } 19850a708f8fSGustavo F. Padovan } 19860a708f8fSGustavo F. Padovan 1987a24cce14SJohan Hedberg if (c1) 1988a24cce14SJohan Hedberg l2cap_chan_hold(c1); 1989a24cce14SJohan Hedberg 199023691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 19910a708f8fSGustavo F. Padovan 199223691d75SGustavo F. Padovan return c1; 19930a708f8fSGustavo F. Padovan } 19940a708f8fSGustavo F. Padovan 1995721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work) 19960a708f8fSGustavo F. Padovan { 1997721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1998721c4181SGustavo F. Padovan monitor_timer.work); 19990a708f8fSGustavo F. Padovan 2000525cd185SGustavo F. Padovan BT_DBG("chan %p", chan); 20010a708f8fSGustavo F. Padovan 20026be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 20036be36555SAndrei Emeltchenko 200480909e04SMat Martineau if (!chan->conn) { 20056be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 20068d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 20070a708f8fSGustavo F. Padovan return; 20080a708f8fSGustavo F. Padovan } 20090a708f8fSGustavo F. Padovan 2010401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO); 20110a708f8fSGustavo F. Padovan 20126be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 20138d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 20140a708f8fSGustavo F. Padovan } 20150a708f8fSGustavo F. Padovan 2016721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work) 20170a708f8fSGustavo F. Padovan { 2018721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 2019721c4181SGustavo F. Padovan retrans_timer.work); 20200a708f8fSGustavo F. Padovan 202149208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 20220a708f8fSGustavo F. Padovan 20236be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 20246be36555SAndrei Emeltchenko 202580909e04SMat Martineau if (!chan->conn) { 202680909e04SMat Martineau l2cap_chan_unlock(chan); 202780909e04SMat Martineau l2cap_chan_put(chan); 202880909e04SMat Martineau return; 202980909e04SMat Martineau } 20300a708f8fSGustavo F. Padovan 2031401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO); 20326be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 20338d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 20340a708f8fSGustavo F. Padovan } 20350a708f8fSGustavo F. Padovan 2036d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan, 20373733937dSMat Martineau struct sk_buff_head *skbs) 20380a708f8fSGustavo F. Padovan { 20390a708f8fSGustavo F. Padovan struct sk_buff *skb; 20403733937dSMat Martineau struct l2cap_ctrl *control; 20410a708f8fSGustavo F. Padovan 20423733937dSMat Martineau BT_DBG("chan %p, skbs %p", chan, skbs); 20433733937dSMat Martineau 2044b99e13adSMat Martineau if (__chan_is_moving(chan)) 2045b99e13adSMat Martineau return; 2046b99e13adSMat Martineau 20473733937dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 20483733937dSMat Martineau 20493733937dSMat Martineau while (!skb_queue_empty(&chan->tx_q)) { 20503733937dSMat Martineau 20513733937dSMat Martineau skb = skb_dequeue(&chan->tx_q); 20523733937dSMat Martineau 2053a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 1; 2054a4368ff3SJohan Hedberg control = &bt_cb(skb)->l2cap; 20553733937dSMat Martineau 20563733937dSMat Martineau control->reqseq = 0; 20573733937dSMat Martineau control->txseq = chan->next_tx_seq; 20583733937dSMat Martineau 20593733937dSMat Martineau __pack_control(chan, control, skb); 20600a708f8fSGustavo F. Padovan 206147d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 20623733937dSMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 20633733937dSMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 20640a708f8fSGustavo F. Padovan } 20650a708f8fSGustavo F. Padovan 20664343478fSGustavo F. Padovan l2cap_do_send(chan, skb); 20670a708f8fSGustavo F. Padovan 2068b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 20693733937dSMat Martineau 2070836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 20713733937dSMat Martineau chan->frames_sent++; 20720a708f8fSGustavo F. Padovan } 20730a708f8fSGustavo F. Padovan } 20740a708f8fSGustavo F. Padovan 207567c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan) 20760a708f8fSGustavo F. Padovan { 20770a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 207818a48e76SMat Martineau struct l2cap_ctrl *control; 207918a48e76SMat Martineau int sent = 0; 208018a48e76SMat Martineau 208118a48e76SMat Martineau BT_DBG("chan %p", chan); 20820a708f8fSGustavo F. Padovan 208389bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 20840a708f8fSGustavo F. Padovan return -ENOTCONN; 20850a708f8fSGustavo F. Padovan 208694122bbeSMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 208794122bbeSMat Martineau return 0; 208894122bbeSMat Martineau 2089b99e13adSMat Martineau if (__chan_is_moving(chan)) 2090b99e13adSMat Martineau return 0; 2091b99e13adSMat Martineau 209218a48e76SMat Martineau while (chan->tx_send_head && 209318a48e76SMat Martineau chan->unacked_frames < chan->remote_tx_win && 209418a48e76SMat Martineau chan->tx_state == L2CAP_TX_STATE_XMIT) { 20950a708f8fSGustavo F. Padovan 209618a48e76SMat Martineau skb = chan->tx_send_head; 20970a708f8fSGustavo F. Padovan 2098a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 1; 2099a4368ff3SJohan Hedberg control = &bt_cb(skb)->l2cap; 21000a708f8fSGustavo F. Padovan 2101e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 210218a48e76SMat Martineau control->final = 1; 2103e2ab4353SGustavo F. Padovan 210418a48e76SMat Martineau control->reqseq = chan->buffer_seq; 210518a48e76SMat Martineau chan->last_acked_seq = chan->buffer_seq; 210618a48e76SMat Martineau control->txseq = chan->next_tx_seq; 21070a708f8fSGustavo F. Padovan 210818a48e76SMat Martineau __pack_control(chan, control, skb); 21090a708f8fSGustavo F. Padovan 211047d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 211118a48e76SMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 211218a48e76SMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 21130a708f8fSGustavo F. Padovan } 21140a708f8fSGustavo F. Padovan 211518a48e76SMat Martineau /* Clone after data has been modified. Data is assumed to be 211618a48e76SMat Martineau read-only (for locking purposes) on cloned sk_buffs. 211718a48e76SMat Martineau */ 211818a48e76SMat Martineau tx_skb = skb_clone(skb, GFP_KERNEL); 211918a48e76SMat Martineau 212018a48e76SMat Martineau if (!tx_skb) 212118a48e76SMat Martineau break; 21220a708f8fSGustavo F. Padovan 21231a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 21240a708f8fSGustavo F. Padovan 2125836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 21266a026610SGustavo F. Padovan chan->unacked_frames++; 21276a026610SGustavo F. Padovan chan->frames_sent++; 212818a48e76SMat Martineau sent++; 21290a708f8fSGustavo F. Padovan 213058d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 213158d35f87SGustavo F. Padovan chan->tx_send_head = NULL; 21320a708f8fSGustavo F. Padovan else 213358d35f87SGustavo F. Padovan chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); 213418a48e76SMat Martineau 213518a48e76SMat Martineau l2cap_do_send(chan, tx_skb); 2136b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 21370a708f8fSGustavo F. Padovan } 21380a708f8fSGustavo F. Padovan 2139b4400672SAndrei Emeltchenko BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent, 2140b4400672SAndrei Emeltchenko chan->unacked_frames, skb_queue_len(&chan->tx_q)); 214118a48e76SMat Martineau 214218a48e76SMat Martineau return sent; 21430a708f8fSGustavo F. Padovan } 21440a708f8fSGustavo F. Padovan 2145e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan) 2146e1fbd4c1SMat Martineau { 2147e1fbd4c1SMat Martineau struct l2cap_ctrl control; 2148e1fbd4c1SMat Martineau struct sk_buff *skb; 2149e1fbd4c1SMat Martineau struct sk_buff *tx_skb; 2150e1fbd4c1SMat Martineau u16 seq; 2151e1fbd4c1SMat Martineau 2152e1fbd4c1SMat Martineau BT_DBG("chan %p", chan); 2153e1fbd4c1SMat Martineau 2154e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 2155e1fbd4c1SMat Martineau return; 2156e1fbd4c1SMat Martineau 2157b99e13adSMat Martineau if (__chan_is_moving(chan)) 2158b99e13adSMat Martineau return; 2159b99e13adSMat Martineau 2160e1fbd4c1SMat Martineau while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) { 2161e1fbd4c1SMat Martineau seq = l2cap_seq_list_pop(&chan->retrans_list); 2162e1fbd4c1SMat Martineau 2163e1fbd4c1SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq); 2164e1fbd4c1SMat Martineau if (!skb) { 2165e1fbd4c1SMat Martineau BT_DBG("Error: Can't retransmit seq %d, frame missing", 2166e1fbd4c1SMat Martineau seq); 2167e1fbd4c1SMat Martineau continue; 2168e1fbd4c1SMat Martineau } 2169e1fbd4c1SMat Martineau 2170a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries++; 2171a4368ff3SJohan Hedberg control = bt_cb(skb)->l2cap; 2172e1fbd4c1SMat Martineau 2173e1fbd4c1SMat Martineau if (chan->max_tx != 0 && 2174a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries > chan->max_tx) { 2175e1fbd4c1SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 21765e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 2177e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2178e1fbd4c1SMat Martineau break; 2179e1fbd4c1SMat Martineau } 2180e1fbd4c1SMat Martineau 2181e1fbd4c1SMat Martineau control.reqseq = chan->buffer_seq; 2182e1fbd4c1SMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 2183e1fbd4c1SMat Martineau control.final = 1; 2184e1fbd4c1SMat Martineau else 2185e1fbd4c1SMat Martineau control.final = 0; 2186e1fbd4c1SMat Martineau 2187e1fbd4c1SMat Martineau if (skb_cloned(skb)) { 2188e1fbd4c1SMat Martineau /* Cloned sk_buffs are read-only, so we need a 2189e1fbd4c1SMat Martineau * writeable copy 2190e1fbd4c1SMat Martineau */ 21918bcde1f2SGustavo Padovan tx_skb = skb_copy(skb, GFP_KERNEL); 2192e1fbd4c1SMat Martineau } else { 21938bcde1f2SGustavo Padovan tx_skb = skb_clone(skb, GFP_KERNEL); 2194e1fbd4c1SMat Martineau } 2195e1fbd4c1SMat Martineau 2196e1fbd4c1SMat Martineau if (!tx_skb) { 2197e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2198e1fbd4c1SMat Martineau break; 2199e1fbd4c1SMat Martineau } 2200e1fbd4c1SMat Martineau 2201e1fbd4c1SMat Martineau /* Update skb contents */ 2202e1fbd4c1SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 2203e1fbd4c1SMat Martineau put_unaligned_le32(__pack_extended_control(&control), 2204e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 2205e1fbd4c1SMat Martineau } else { 2206e1fbd4c1SMat Martineau put_unaligned_le16(__pack_enhanced_control(&control), 2207e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 2208e1fbd4c1SMat Martineau } 2209e1fbd4c1SMat Martineau 221013cac152SLukasz Rymanowski /* Update FCS */ 2211e1fbd4c1SMat Martineau if (chan->fcs == L2CAP_FCS_CRC16) { 221213cac152SLukasz Rymanowski u16 fcs = crc16(0, (u8 *) tx_skb->data, 221313cac152SLukasz Rymanowski tx_skb->len - L2CAP_FCS_SIZE); 221413cac152SLukasz Rymanowski put_unaligned_le16(fcs, skb_tail_pointer(tx_skb) - 221513cac152SLukasz Rymanowski L2CAP_FCS_SIZE); 2216e1fbd4c1SMat Martineau } 2217e1fbd4c1SMat Martineau 2218e1fbd4c1SMat Martineau l2cap_do_send(chan, tx_skb); 2219e1fbd4c1SMat Martineau 2220e1fbd4c1SMat Martineau BT_DBG("Resent txseq %d", control.txseq); 2221e1fbd4c1SMat Martineau 2222e1fbd4c1SMat Martineau chan->last_acked_seq = chan->buffer_seq; 2223e1fbd4c1SMat Martineau } 2224e1fbd4c1SMat Martineau } 2225e1fbd4c1SMat Martineau 2226f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan, 2227f80842a8SMat Martineau struct l2cap_ctrl *control) 2228f80842a8SMat Martineau { 2229f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2230f80842a8SMat Martineau 2231f80842a8SMat Martineau l2cap_seq_list_append(&chan->retrans_list, control->reqseq); 2232f80842a8SMat Martineau l2cap_ertm_resend(chan); 2233f80842a8SMat Martineau } 2234f80842a8SMat Martineau 2235d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan, 2236d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 2237d2a7ac5dSMat Martineau { 2238e1fbd4c1SMat Martineau struct sk_buff *skb; 2239e1fbd4c1SMat Martineau 2240e1fbd4c1SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2241e1fbd4c1SMat Martineau 2242e1fbd4c1SMat Martineau if (control->poll) 2243e1fbd4c1SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 2244e1fbd4c1SMat Martineau 2245e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2246e1fbd4c1SMat Martineau 2247e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 2248e1fbd4c1SMat Martineau return; 2249e1fbd4c1SMat Martineau 2250e1fbd4c1SMat Martineau if (chan->unacked_frames) { 2251e1fbd4c1SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 2252a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.txseq == control->reqseq || 2253e1fbd4c1SMat Martineau skb == chan->tx_send_head) 2254e1fbd4c1SMat Martineau break; 2255e1fbd4c1SMat Martineau } 2256e1fbd4c1SMat Martineau 2257e1fbd4c1SMat Martineau skb_queue_walk_from(&chan->tx_q, skb) { 2258e1fbd4c1SMat Martineau if (skb == chan->tx_send_head) 2259e1fbd4c1SMat Martineau break; 2260e1fbd4c1SMat Martineau 2261e1fbd4c1SMat Martineau l2cap_seq_list_append(&chan->retrans_list, 2262a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.txseq); 2263e1fbd4c1SMat Martineau } 2264e1fbd4c1SMat Martineau 2265e1fbd4c1SMat Martineau l2cap_ertm_resend(chan); 2266e1fbd4c1SMat Martineau } 2267d2a7ac5dSMat Martineau } 2268d2a7ac5dSMat Martineau 2269b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan) 2270b17e73bbSSzymon Janc { 22710a0aba42SMat Martineau struct l2cap_ctrl control; 22720a0aba42SMat Martineau u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq, 22730a0aba42SMat Martineau chan->last_acked_seq); 22740a0aba42SMat Martineau int threshold; 22750a0aba42SMat Martineau 22760a0aba42SMat Martineau BT_DBG("chan %p last_acked_seq %d buffer_seq %d", 22770a0aba42SMat Martineau chan, chan->last_acked_seq, chan->buffer_seq); 22780a0aba42SMat Martineau 22790a0aba42SMat Martineau memset(&control, 0, sizeof(control)); 22800a0aba42SMat Martineau control.sframe = 1; 22810a0aba42SMat Martineau 22820a0aba42SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 22830a0aba42SMat Martineau chan->rx_state == L2CAP_RX_STATE_RECV) { 2284b17e73bbSSzymon Janc __clear_ack_timer(chan); 22850a0aba42SMat Martineau control.super = L2CAP_SUPER_RNR; 22860a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 22870a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 22880a0aba42SMat Martineau } else { 22890a0aba42SMat Martineau if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) { 22900a0aba42SMat Martineau l2cap_ertm_send(chan); 22910a0aba42SMat Martineau /* If any i-frames were sent, they included an ack */ 22920a0aba42SMat Martineau if (chan->buffer_seq == chan->last_acked_seq) 22930a0aba42SMat Martineau frames_to_ack = 0; 22940a0aba42SMat Martineau } 22950a0aba42SMat Martineau 2296c20f8e35SMat Martineau /* Ack now if the window is 3/4ths full. 22970a0aba42SMat Martineau * Calculate without mul or div 22980a0aba42SMat Martineau */ 2299c20f8e35SMat Martineau threshold = chan->ack_win; 23000a0aba42SMat Martineau threshold += threshold << 1; 23010a0aba42SMat Martineau threshold >>= 2; 23020a0aba42SMat Martineau 2303b4400672SAndrei Emeltchenko BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack, 23040a0aba42SMat Martineau threshold); 23050a0aba42SMat Martineau 23060a0aba42SMat Martineau if (frames_to_ack >= threshold) { 23070a0aba42SMat Martineau __clear_ack_timer(chan); 23080a0aba42SMat Martineau control.super = L2CAP_SUPER_RR; 23090a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 23100a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 23110a0aba42SMat Martineau frames_to_ack = 0; 23120a0aba42SMat Martineau } 23130a0aba42SMat Martineau 23140a0aba42SMat Martineau if (frames_to_ack) 23150a0aba42SMat Martineau __set_ack_timer(chan); 23160a0aba42SMat Martineau } 2317b17e73bbSSzymon Janc } 2318b17e73bbSSzymon Janc 231904124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, 232004124681SGustavo F. Padovan struct msghdr *msg, int len, 232104124681SGustavo F. Padovan int count, struct sk_buff *skb) 23220a708f8fSGustavo F. Padovan { 23230952a57aSAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 23240a708f8fSGustavo F. Padovan struct sk_buff **frag; 232590338947SGustavo Padovan int sent = 0; 23260a708f8fSGustavo F. Padovan 2327cbbd26b8SAl Viro if (!copy_from_iter_full(skb_put(skb, count), count, &msg->msg_iter)) 23280a708f8fSGustavo F. Padovan return -EFAULT; 23290a708f8fSGustavo F. Padovan 23300a708f8fSGustavo F. Padovan sent += count; 23310a708f8fSGustavo F. Padovan len -= count; 23320a708f8fSGustavo F. Padovan 23330a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 23340a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 23350a708f8fSGustavo F. Padovan while (len) { 2336fbe00700SGustavo Padovan struct sk_buff *tmp; 2337fbe00700SGustavo Padovan 23380a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 23390a708f8fSGustavo F. Padovan 2340d9fbd02bSMarcel Holtmann tmp = chan->ops->alloc_skb(chan, 0, count, 234190338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 2342fbe00700SGustavo Padovan if (IS_ERR(tmp)) 2343fbe00700SGustavo Padovan return PTR_ERR(tmp); 23442f7719ceSAndrei Emeltchenko 2345fbe00700SGustavo Padovan *frag = tmp; 2346fbe00700SGustavo Padovan 2347cbbd26b8SAl Viro if (!copy_from_iter_full(skb_put(*frag, count), count, 2348cbbd26b8SAl Viro &msg->msg_iter)) 23490a708f8fSGustavo F. Padovan return -EFAULT; 23500a708f8fSGustavo F. Padovan 23510a708f8fSGustavo F. Padovan sent += count; 23520a708f8fSGustavo F. Padovan len -= count; 23530a708f8fSGustavo F. Padovan 23542d0ed3d5SGustavo Padovan skb->len += (*frag)->len; 23552d0ed3d5SGustavo Padovan skb->data_len += (*frag)->len; 23562d0ed3d5SGustavo Padovan 23570a708f8fSGustavo F. Padovan frag = &(*frag)->next; 23580a708f8fSGustavo F. Padovan } 23590a708f8fSGustavo F. Padovan 23600a708f8fSGustavo F. Padovan return sent; 23610a708f8fSGustavo F. Padovan } 23620a708f8fSGustavo F. Padovan 23635e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, 23648d46321cSMarcel Holtmann struct msghdr *msg, size_t len) 23650a708f8fSGustavo F. Padovan { 23668c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 23670a708f8fSGustavo F. Padovan struct sk_buff *skb; 236803a51213SAndrei Emeltchenko int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; 23690a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 23700a708f8fSGustavo F. Padovan 23718d46321cSMarcel Holtmann BT_DBG("chan %p psm 0x%2.2x len %zu", chan, 23728d46321cSMarcel Holtmann __le16_to_cpu(chan->psm), len); 23730a708f8fSGustavo F. Padovan 23740a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 23752f7719ceSAndrei Emeltchenko 2376d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, hlen, count, 237790338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 237890338947SGustavo Padovan if (IS_ERR(skb)) 237990338947SGustavo Padovan return skb; 23800a708f8fSGustavo F. Padovan 23810a708f8fSGustavo F. Padovan /* Create L2CAP header */ 23824df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 2383fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 2384daf6a78cSAndrei Emeltchenko lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); 238543b1b8dfSMarcel Holtmann put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE)); 23860a708f8fSGustavo F. Padovan 23870952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 23880a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 23890a708f8fSGustavo F. Padovan kfree_skb(skb); 23900a708f8fSGustavo F. Padovan return ERR_PTR(err); 23910a708f8fSGustavo F. Padovan } 23920a708f8fSGustavo F. Padovan return skb; 23930a708f8fSGustavo F. Padovan } 23940a708f8fSGustavo F. Padovan 23955e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, 23968d46321cSMarcel Holtmann struct msghdr *msg, size_t len) 23970a708f8fSGustavo F. Padovan { 23988c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 23990a708f8fSGustavo F. Padovan struct sk_buff *skb; 2400f2ba7faeSGustavo Padovan int err, count; 24010a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 24020a708f8fSGustavo F. Padovan 2403b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 24040a708f8fSGustavo F. Padovan 2405f2ba7faeSGustavo Padovan count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); 24062f7719ceSAndrei Emeltchenko 2407d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, L2CAP_HDR_SIZE, count, 240890338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 240990338947SGustavo Padovan if (IS_ERR(skb)) 241090338947SGustavo Padovan return skb; 24110a708f8fSGustavo F. Padovan 24120a708f8fSGustavo F. Padovan /* Create L2CAP header */ 24134df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 2414fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 24156ff9b5efSGustavo Padovan lh->len = cpu_to_le16(len); 24160a708f8fSGustavo F. Padovan 24170952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 24180a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 24190a708f8fSGustavo F. Padovan kfree_skb(skb); 24200a708f8fSGustavo F. Padovan return ERR_PTR(err); 24210a708f8fSGustavo F. Padovan } 24220a708f8fSGustavo F. Padovan return skb; 24230a708f8fSGustavo F. Padovan } 24240a708f8fSGustavo F. Padovan 2425ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, 2426ab0ff76dSLuiz Augusto von Dentz struct msghdr *msg, size_t len, 242794122bbeSMat Martineau u16 sdulen) 24280a708f8fSGustavo F. Padovan { 24298c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 24300a708f8fSGustavo F. Padovan struct sk_buff *skb; 2431e4ca6d98SAndrei Emeltchenko int err, count, hlen; 24320a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 24330a708f8fSGustavo F. Padovan 2434b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 24350a708f8fSGustavo F. Padovan 24360a708f8fSGustavo F. Padovan if (!conn) 24370a708f8fSGustavo F. Padovan return ERR_PTR(-ENOTCONN); 24380a708f8fSGustavo F. Padovan 2439ba7aa64fSGustavo Padovan hlen = __ertm_hdr_size(chan); 2440e4ca6d98SAndrei Emeltchenko 24410a708f8fSGustavo F. Padovan if (sdulen) 244203a51213SAndrei Emeltchenko hlen += L2CAP_SDULEN_SIZE; 24430a708f8fSGustavo F. Padovan 244447d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 244503a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 24460a708f8fSGustavo F. Padovan 24470a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 24482f7719ceSAndrei Emeltchenko 2449d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, hlen, count, 245090338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 245190338947SGustavo Padovan if (IS_ERR(skb)) 245290338947SGustavo Padovan return skb; 24530a708f8fSGustavo F. Padovan 24540a708f8fSGustavo F. Padovan /* Create L2CAP header */ 24554df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 2456fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 24570a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 245888843ab0SAndrei Emeltchenko 245918a48e76SMat Martineau /* Control header is populated later */ 246018a48e76SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 246118a48e76SMat Martineau put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 246218a48e76SMat Martineau else 246318a48e76SMat Martineau put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 246488843ab0SAndrei Emeltchenko 24650a708f8fSGustavo F. Padovan if (sdulen) 246603a51213SAndrei Emeltchenko put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 24670a708f8fSGustavo F. Padovan 24680952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 24690a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 24700a708f8fSGustavo F. Padovan kfree_skb(skb); 24710a708f8fSGustavo F. Padovan return ERR_PTR(err); 24720a708f8fSGustavo F. Padovan } 24730a708f8fSGustavo F. Padovan 2474a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.fcs = chan->fcs; 2475a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 0; 24760a708f8fSGustavo F. Padovan return skb; 24770a708f8fSGustavo F. Padovan } 24780a708f8fSGustavo F. Padovan 247994122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan, 248094122bbeSMat Martineau struct sk_buff_head *seg_queue, 248194122bbeSMat Martineau struct msghdr *msg, size_t len) 24820a708f8fSGustavo F. Padovan { 24830a708f8fSGustavo F. Padovan struct sk_buff *skb; 248494122bbeSMat Martineau u16 sdu_len; 248594122bbeSMat Martineau size_t pdu_len; 248694122bbeSMat Martineau u8 sar; 24870a708f8fSGustavo F. Padovan 2488b4400672SAndrei Emeltchenko BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); 24890a708f8fSGustavo F. Padovan 249094122bbeSMat Martineau /* It is critical that ERTM PDUs fit in a single HCI fragment, 249194122bbeSMat Martineau * so fragmented skbs are not used. The HCI layer's handling 249294122bbeSMat Martineau * of fragmented skbs is not compatible with ERTM's queueing. 249394122bbeSMat Martineau */ 249494122bbeSMat Martineau 249594122bbeSMat Martineau /* PDU size is derived from the HCI MTU */ 249694122bbeSMat Martineau pdu_len = chan->conn->mtu; 249794122bbeSMat Martineau 2498a549574dSMat Martineau /* Constrain PDU size for BR/EDR connections */ 2499a549574dSMat Martineau if (!chan->hs_hcon) 250094122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); 250194122bbeSMat Martineau 250294122bbeSMat Martineau /* Adjust for largest possible L2CAP overhead. */ 250335d401dfSGustavo Padovan if (chan->fcs) 250435d401dfSGustavo Padovan pdu_len -= L2CAP_FCS_SIZE; 250535d401dfSGustavo Padovan 2506ba7aa64fSGustavo Padovan pdu_len -= __ertm_hdr_size(chan); 250794122bbeSMat Martineau 250894122bbeSMat Martineau /* Remote device may have requested smaller PDUs */ 250994122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, chan->remote_mps); 251094122bbeSMat Martineau 251194122bbeSMat Martineau if (len <= pdu_len) { 251294122bbeSMat Martineau sar = L2CAP_SAR_UNSEGMENTED; 251394122bbeSMat Martineau sdu_len = 0; 251494122bbeSMat Martineau pdu_len = len; 251594122bbeSMat Martineau } else { 251694122bbeSMat Martineau sar = L2CAP_SAR_START; 251794122bbeSMat Martineau sdu_len = len; 251894122bbeSMat Martineau } 25190a708f8fSGustavo F. Padovan 25200a708f8fSGustavo F. Padovan while (len > 0) { 252194122bbeSMat Martineau skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len); 25220a708f8fSGustavo F. Padovan 25230a708f8fSGustavo F. Padovan if (IS_ERR(skb)) { 252494122bbeSMat Martineau __skb_queue_purge(seg_queue); 25250a708f8fSGustavo F. Padovan return PTR_ERR(skb); 25260a708f8fSGustavo F. Padovan } 25270a708f8fSGustavo F. Padovan 2528a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.sar = sar; 252994122bbeSMat Martineau __skb_queue_tail(seg_queue, skb); 25300a708f8fSGustavo F. Padovan 253194122bbeSMat Martineau len -= pdu_len; 2532069cb270SLukasz Rymanowski if (sdu_len) 253394122bbeSMat Martineau sdu_len = 0; 253494122bbeSMat Martineau 253594122bbeSMat Martineau if (len <= pdu_len) { 253694122bbeSMat Martineau sar = L2CAP_SAR_END; 253794122bbeSMat Martineau pdu_len = len; 253894122bbeSMat Martineau } else { 253994122bbeSMat Martineau sar = L2CAP_SAR_CONTINUE; 254094122bbeSMat Martineau } 254194122bbeSMat Martineau } 254294122bbeSMat Martineau 2543f0f62799SGustavo Padovan return 0; 25440a708f8fSGustavo F. Padovan } 25450a708f8fSGustavo F. Padovan 2546177f8f2bSJohan Hedberg static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan, 2547177f8f2bSJohan Hedberg struct msghdr *msg, 2548177f8f2bSJohan Hedberg size_t len, u16 sdulen) 2549177f8f2bSJohan Hedberg { 2550177f8f2bSJohan Hedberg struct l2cap_conn *conn = chan->conn; 2551177f8f2bSJohan Hedberg struct sk_buff *skb; 2552177f8f2bSJohan Hedberg int err, count, hlen; 2553177f8f2bSJohan Hedberg struct l2cap_hdr *lh; 2554177f8f2bSJohan Hedberg 2555177f8f2bSJohan Hedberg BT_DBG("chan %p len %zu", chan, len); 2556177f8f2bSJohan Hedberg 2557177f8f2bSJohan Hedberg if (!conn) 2558177f8f2bSJohan Hedberg return ERR_PTR(-ENOTCONN); 2559177f8f2bSJohan Hedberg 2560177f8f2bSJohan Hedberg hlen = L2CAP_HDR_SIZE; 2561177f8f2bSJohan Hedberg 2562177f8f2bSJohan Hedberg if (sdulen) 2563177f8f2bSJohan Hedberg hlen += L2CAP_SDULEN_SIZE; 2564177f8f2bSJohan Hedberg 2565177f8f2bSJohan Hedberg count = min_t(unsigned int, (conn->mtu - hlen), len); 2566177f8f2bSJohan Hedberg 2567d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, hlen, count, 2568177f8f2bSJohan Hedberg msg->msg_flags & MSG_DONTWAIT); 2569177f8f2bSJohan Hedberg if (IS_ERR(skb)) 2570177f8f2bSJohan Hedberg return skb; 2571177f8f2bSJohan Hedberg 2572177f8f2bSJohan Hedberg /* Create L2CAP header */ 25734df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 2574177f8f2bSJohan Hedberg lh->cid = cpu_to_le16(chan->dcid); 2575177f8f2bSJohan Hedberg lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 2576177f8f2bSJohan Hedberg 2577177f8f2bSJohan Hedberg if (sdulen) 2578177f8f2bSJohan Hedberg put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 2579177f8f2bSJohan Hedberg 2580177f8f2bSJohan Hedberg err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 2581177f8f2bSJohan Hedberg if (unlikely(err < 0)) { 2582177f8f2bSJohan Hedberg kfree_skb(skb); 2583177f8f2bSJohan Hedberg return ERR_PTR(err); 2584177f8f2bSJohan Hedberg } 2585177f8f2bSJohan Hedberg 2586177f8f2bSJohan Hedberg return skb; 2587177f8f2bSJohan Hedberg } 2588177f8f2bSJohan Hedberg 2589177f8f2bSJohan Hedberg static int l2cap_segment_le_sdu(struct l2cap_chan *chan, 2590177f8f2bSJohan Hedberg struct sk_buff_head *seg_queue, 2591177f8f2bSJohan Hedberg struct msghdr *msg, size_t len) 2592177f8f2bSJohan Hedberg { 2593177f8f2bSJohan Hedberg struct sk_buff *skb; 2594177f8f2bSJohan Hedberg size_t pdu_len; 2595177f8f2bSJohan Hedberg u16 sdu_len; 2596177f8f2bSJohan Hedberg 2597177f8f2bSJohan Hedberg BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); 2598177f8f2bSJohan Hedberg 2599177f8f2bSJohan Hedberg sdu_len = len; 260072c6fb91SJohan Hedberg pdu_len = chan->remote_mps - L2CAP_SDULEN_SIZE; 2601177f8f2bSJohan Hedberg 2602177f8f2bSJohan Hedberg while (len > 0) { 2603177f8f2bSJohan Hedberg if (len <= pdu_len) 2604177f8f2bSJohan Hedberg pdu_len = len; 2605177f8f2bSJohan Hedberg 2606177f8f2bSJohan Hedberg skb = l2cap_create_le_flowctl_pdu(chan, msg, pdu_len, sdu_len); 2607177f8f2bSJohan Hedberg if (IS_ERR(skb)) { 2608177f8f2bSJohan Hedberg __skb_queue_purge(seg_queue); 2609177f8f2bSJohan Hedberg return PTR_ERR(skb); 2610177f8f2bSJohan Hedberg } 2611177f8f2bSJohan Hedberg 2612177f8f2bSJohan Hedberg __skb_queue_tail(seg_queue, skb); 2613177f8f2bSJohan Hedberg 2614177f8f2bSJohan Hedberg len -= pdu_len; 2615177f8f2bSJohan Hedberg 2616177f8f2bSJohan Hedberg if (sdu_len) { 2617177f8f2bSJohan Hedberg sdu_len = 0; 2618177f8f2bSJohan Hedberg pdu_len += L2CAP_SDULEN_SIZE; 2619177f8f2bSJohan Hedberg } 2620177f8f2bSJohan Hedberg } 2621177f8f2bSJohan Hedberg 2622177f8f2bSJohan Hedberg return 0; 2623177f8f2bSJohan Hedberg } 2624177f8f2bSJohan Hedberg 26258a505b7fSLuiz Augusto von Dentz static void l2cap_le_flowctl_send(struct l2cap_chan *chan) 26268a505b7fSLuiz Augusto von Dentz { 26278a505b7fSLuiz Augusto von Dentz int sent = 0; 26288a505b7fSLuiz Augusto von Dentz 26298a505b7fSLuiz Augusto von Dentz BT_DBG("chan %p", chan); 26308a505b7fSLuiz Augusto von Dentz 26318a505b7fSLuiz Augusto von Dentz while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) { 26328a505b7fSLuiz Augusto von Dentz l2cap_do_send(chan, skb_dequeue(&chan->tx_q)); 26338a505b7fSLuiz Augusto von Dentz chan->tx_credits--; 26348a505b7fSLuiz Augusto von Dentz sent++; 26358a505b7fSLuiz Augusto von Dentz } 26368a505b7fSLuiz Augusto von Dentz 26378a505b7fSLuiz Augusto von Dentz BT_DBG("Sent %d credits %u queued %u", sent, chan->tx_credits, 26388a505b7fSLuiz Augusto von Dentz skb_queue_len(&chan->tx_q)); 26398a505b7fSLuiz Augusto von Dentz } 26408a505b7fSLuiz Augusto von Dentz 26418d46321cSMarcel Holtmann int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len) 26429a91a04aSGustavo F. Padovan { 26439a91a04aSGustavo F. Padovan struct sk_buff *skb; 26449a91a04aSGustavo F. Padovan int err; 264594122bbeSMat Martineau struct sk_buff_head seg_queue; 26469a91a04aSGustavo F. Padovan 264731e8ce80SSeung-Woo Kim if (!chan->conn) 264831e8ce80SSeung-Woo Kim return -ENOTCONN; 264931e8ce80SSeung-Woo Kim 26509a91a04aSGustavo F. Padovan /* Connectionless channel */ 2651715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { 26528d46321cSMarcel Holtmann skb = l2cap_create_connless_pdu(chan, msg, len); 26539a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 26549a91a04aSGustavo F. Padovan return PTR_ERR(skb); 26559a91a04aSGustavo F. Padovan 2656ede81a2aSAndrzej Kaczmarek /* Channel lock is released before requesting new skb and then 2657ede81a2aSAndrzej Kaczmarek * reacquired thus we need to recheck channel state. 2658ede81a2aSAndrzej Kaczmarek */ 2659ede81a2aSAndrzej Kaczmarek if (chan->state != BT_CONNECTED) { 2660ede81a2aSAndrzej Kaczmarek kfree_skb(skb); 2661ede81a2aSAndrzej Kaczmarek return -ENOTCONN; 2662ede81a2aSAndrzej Kaczmarek } 2663ede81a2aSAndrzej Kaczmarek 26649a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 26659a91a04aSGustavo F. Padovan return len; 26669a91a04aSGustavo F. Padovan } 26679a91a04aSGustavo F. Padovan 26689a91a04aSGustavo F. Padovan switch (chan->mode) { 266938319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 267015f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL: 2671177f8f2bSJohan Hedberg /* Check outgoing MTU */ 2672177f8f2bSJohan Hedberg if (len > chan->omtu) 2673177f8f2bSJohan Hedberg return -EMSGSIZE; 2674177f8f2bSJohan Hedberg 2675177f8f2bSJohan Hedberg __skb_queue_head_init(&seg_queue); 2676177f8f2bSJohan Hedberg 2677177f8f2bSJohan Hedberg err = l2cap_segment_le_sdu(chan, &seg_queue, msg, len); 2678177f8f2bSJohan Hedberg 2679177f8f2bSJohan Hedberg if (chan->state != BT_CONNECTED) { 2680177f8f2bSJohan Hedberg __skb_queue_purge(&seg_queue); 2681177f8f2bSJohan Hedberg err = -ENOTCONN; 2682177f8f2bSJohan Hedberg } 2683177f8f2bSJohan Hedberg 2684177f8f2bSJohan Hedberg if (err) 2685177f8f2bSJohan Hedberg return err; 2686177f8f2bSJohan Hedberg 2687177f8f2bSJohan Hedberg skb_queue_splice_tail_init(&seg_queue, &chan->tx_q); 2688177f8f2bSJohan Hedberg 26898a505b7fSLuiz Augusto von Dentz l2cap_le_flowctl_send(chan); 2690177f8f2bSJohan Hedberg 2691177f8f2bSJohan Hedberg if (!chan->tx_credits) 2692177f8f2bSJohan Hedberg chan->ops->suspend(chan); 2693177f8f2bSJohan Hedberg 2694177f8f2bSJohan Hedberg err = len; 2695177f8f2bSJohan Hedberg 2696177f8f2bSJohan Hedberg break; 2697177f8f2bSJohan Hedberg 2698fad5fc89SJohan Hedberg case L2CAP_MODE_BASIC: 26999a91a04aSGustavo F. Padovan /* Check outgoing MTU */ 27009a91a04aSGustavo F. Padovan if (len > chan->omtu) 27019a91a04aSGustavo F. Padovan return -EMSGSIZE; 27029a91a04aSGustavo F. Padovan 27039a91a04aSGustavo F. Padovan /* Create a basic PDU */ 27048d46321cSMarcel Holtmann skb = l2cap_create_basic_pdu(chan, msg, len); 27059a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 27069a91a04aSGustavo F. Padovan return PTR_ERR(skb); 27079a91a04aSGustavo F. Padovan 2708ede81a2aSAndrzej Kaczmarek /* Channel lock is released before requesting new skb and then 2709ede81a2aSAndrzej Kaczmarek * reacquired thus we need to recheck channel state. 2710ede81a2aSAndrzej Kaczmarek */ 2711ede81a2aSAndrzej Kaczmarek if (chan->state != BT_CONNECTED) { 2712ede81a2aSAndrzej Kaczmarek kfree_skb(skb); 2713ede81a2aSAndrzej Kaczmarek return -ENOTCONN; 2714ede81a2aSAndrzej Kaczmarek } 2715ede81a2aSAndrzej Kaczmarek 27169a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 27179a91a04aSGustavo F. Padovan err = len; 27189a91a04aSGustavo F. Padovan break; 27199a91a04aSGustavo F. Padovan 27209a91a04aSGustavo F. Padovan case L2CAP_MODE_ERTM: 27219a91a04aSGustavo F. Padovan case L2CAP_MODE_STREAMING: 272294122bbeSMat Martineau /* Check outgoing MTU */ 272394122bbeSMat Martineau if (len > chan->omtu) { 272494122bbeSMat Martineau err = -EMSGSIZE; 27259a91a04aSGustavo F. Padovan break; 27269a91a04aSGustavo F. Padovan } 27279a91a04aSGustavo F. Padovan 272894122bbeSMat Martineau __skb_queue_head_init(&seg_queue); 272994122bbeSMat Martineau 273094122bbeSMat Martineau /* Do segmentation before calling in to the state machine, 273194122bbeSMat Martineau * since it's possible to block while waiting for memory 273294122bbeSMat Martineau * allocation. 273394122bbeSMat Martineau */ 273494122bbeSMat Martineau err = l2cap_segment_sdu(chan, &seg_queue, msg, len); 273594122bbeSMat Martineau 273694122bbeSMat Martineau /* The channel could have been closed while segmenting, 273794122bbeSMat Martineau * check that it is still connected. 273894122bbeSMat Martineau */ 273994122bbeSMat Martineau if (chan->state != BT_CONNECTED) { 274094122bbeSMat Martineau __skb_queue_purge(&seg_queue); 274194122bbeSMat Martineau err = -ENOTCONN; 27429a91a04aSGustavo F. Padovan } 27439a91a04aSGustavo F. Padovan 274494122bbeSMat Martineau if (err) 274594122bbeSMat Martineau break; 274694122bbeSMat Martineau 27473733937dSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) 2748d660366dSGustavo Padovan l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST); 27493733937dSMat Martineau else 2750d660366dSGustavo Padovan l2cap_streaming_send(chan, &seg_queue); 275194122bbeSMat Martineau 27529a91a04aSGustavo F. Padovan err = len; 27539a91a04aSGustavo F. Padovan 275494122bbeSMat Martineau /* If the skbs were not queued for sending, they'll still be in 275594122bbeSMat Martineau * seg_queue and need to be purged. 275694122bbeSMat Martineau */ 275794122bbeSMat Martineau __skb_queue_purge(&seg_queue); 27589a91a04aSGustavo F. Padovan break; 27599a91a04aSGustavo F. Padovan 27609a91a04aSGustavo F. Padovan default: 27619a91a04aSGustavo F. Padovan BT_DBG("bad state %1.1x", chan->mode); 27629a91a04aSGustavo F. Padovan err = -EBADFD; 27639a91a04aSGustavo F. Padovan } 27649a91a04aSGustavo F. Padovan 27659a91a04aSGustavo F. Padovan return err; 27669a91a04aSGustavo F. Padovan } 27676b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_send); 27689a91a04aSGustavo F. Padovan 2769d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq) 2770d2a7ac5dSMat Martineau { 2771bed68bdeSMat Martineau struct l2cap_ctrl control; 2772bed68bdeSMat Martineau u16 seq; 2773bed68bdeSMat Martineau 2774b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2775bed68bdeSMat Martineau 2776bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2777bed68bdeSMat Martineau control.sframe = 1; 2778bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2779bed68bdeSMat Martineau 2780bed68bdeSMat Martineau for (seq = chan->expected_tx_seq; seq != txseq; 2781bed68bdeSMat Martineau seq = __next_seq(chan, seq)) { 2782bed68bdeSMat Martineau if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) { 2783bed68bdeSMat Martineau control.reqseq = seq; 2784bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2785bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2786bed68bdeSMat Martineau } 2787bed68bdeSMat Martineau } 2788bed68bdeSMat Martineau 2789bed68bdeSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 2790d2a7ac5dSMat Martineau } 2791d2a7ac5dSMat Martineau 2792d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan) 2793d2a7ac5dSMat Martineau { 2794bed68bdeSMat Martineau struct l2cap_ctrl control; 2795bed68bdeSMat Martineau 2796bed68bdeSMat Martineau BT_DBG("chan %p", chan); 2797bed68bdeSMat Martineau 2798bed68bdeSMat Martineau if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR) 2799bed68bdeSMat Martineau return; 2800bed68bdeSMat Martineau 2801bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2802bed68bdeSMat Martineau control.sframe = 1; 2803bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2804bed68bdeSMat Martineau control.reqseq = chan->srej_list.tail; 2805bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2806d2a7ac5dSMat Martineau } 2807d2a7ac5dSMat Martineau 2808d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq) 2809d2a7ac5dSMat Martineau { 2810bed68bdeSMat Martineau struct l2cap_ctrl control; 2811bed68bdeSMat Martineau u16 initial_head; 2812bed68bdeSMat Martineau u16 seq; 2813bed68bdeSMat Martineau 2814b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2815bed68bdeSMat Martineau 2816bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2817bed68bdeSMat Martineau control.sframe = 1; 2818bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2819bed68bdeSMat Martineau 2820bed68bdeSMat Martineau /* Capture initial list head to allow only one pass through the list. */ 2821bed68bdeSMat Martineau initial_head = chan->srej_list.head; 2822bed68bdeSMat Martineau 2823bed68bdeSMat Martineau do { 2824bed68bdeSMat Martineau seq = l2cap_seq_list_pop(&chan->srej_list); 2825bed68bdeSMat Martineau if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR) 2826bed68bdeSMat Martineau break; 2827bed68bdeSMat Martineau 2828bed68bdeSMat Martineau control.reqseq = seq; 2829bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2830bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2831bed68bdeSMat Martineau } while (chan->srej_list.head != initial_head); 2832d2a7ac5dSMat Martineau } 2833d2a7ac5dSMat Martineau 2834608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq) 2835608bcc6dSMat Martineau { 2836608bcc6dSMat Martineau struct sk_buff *acked_skb; 2837608bcc6dSMat Martineau u16 ackseq; 2838608bcc6dSMat Martineau 2839b4400672SAndrei Emeltchenko BT_DBG("chan %p, reqseq %u", chan, reqseq); 2840608bcc6dSMat Martineau 2841608bcc6dSMat Martineau if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq) 2842608bcc6dSMat Martineau return; 2843608bcc6dSMat Martineau 2844b4400672SAndrei Emeltchenko BT_DBG("expected_ack_seq %u, unacked_frames %u", 2845608bcc6dSMat Martineau chan->expected_ack_seq, chan->unacked_frames); 2846608bcc6dSMat Martineau 2847608bcc6dSMat Martineau for (ackseq = chan->expected_ack_seq; ackseq != reqseq; 2848608bcc6dSMat Martineau ackseq = __next_seq(chan, ackseq)) { 2849608bcc6dSMat Martineau 2850608bcc6dSMat Martineau acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq); 2851608bcc6dSMat Martineau if (acked_skb) { 2852608bcc6dSMat Martineau skb_unlink(acked_skb, &chan->tx_q); 2853608bcc6dSMat Martineau kfree_skb(acked_skb); 2854608bcc6dSMat Martineau chan->unacked_frames--; 2855608bcc6dSMat Martineau } 2856608bcc6dSMat Martineau } 2857608bcc6dSMat Martineau 2858608bcc6dSMat Martineau chan->expected_ack_seq = reqseq; 2859608bcc6dSMat Martineau 2860608bcc6dSMat Martineau if (chan->unacked_frames == 0) 2861608bcc6dSMat Martineau __clear_retrans_timer(chan); 2862608bcc6dSMat Martineau 2863b4400672SAndrei Emeltchenko BT_DBG("unacked_frames %u", chan->unacked_frames); 2864608bcc6dSMat Martineau } 2865608bcc6dSMat Martineau 2866608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan) 2867608bcc6dSMat Martineau { 2868608bcc6dSMat Martineau BT_DBG("chan %p", chan); 2869608bcc6dSMat Martineau 2870608bcc6dSMat Martineau chan->expected_tx_seq = chan->buffer_seq; 2871608bcc6dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 2872608bcc6dSMat Martineau skb_queue_purge(&chan->srej_q); 2873608bcc6dSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2874608bcc6dSMat Martineau } 2875608bcc6dSMat Martineau 2876d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan, 2877608bcc6dSMat Martineau struct l2cap_ctrl *control, 2878608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2879608bcc6dSMat Martineau { 2880608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2881608bcc6dSMat Martineau event); 2882608bcc6dSMat Martineau 2883608bcc6dSMat Martineau switch (event) { 2884608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2885608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2886608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2887608bcc6dSMat Martineau 2888608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2889608bcc6dSMat Martineau l2cap_ertm_send(chan); 2890608bcc6dSMat Martineau break; 2891608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2892608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2893608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2894608bcc6dSMat Martineau 2895608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2896608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2897608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2898608bcc6dSMat Martineau */ 2899608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2900608bcc6dSMat Martineau } 2901608bcc6dSMat Martineau 2902608bcc6dSMat Martineau l2cap_send_ack(chan); 2903608bcc6dSMat Martineau 2904608bcc6dSMat Martineau break; 2905608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2906608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2907608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2908608bcc6dSMat Martineau 2909608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2910608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2911608bcc6dSMat Martineau 2912608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2913608bcc6dSMat Martineau local_control.sframe = 1; 2914608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2915608bcc6dSMat Martineau local_control.poll = 1; 2916608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2917a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2918608bcc6dSMat Martineau 2919608bcc6dSMat Martineau chan->retry_count = 1; 2920608bcc6dSMat Martineau __set_monitor_timer(chan); 2921608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2922608bcc6dSMat Martineau } 2923608bcc6dSMat Martineau break; 2924608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2925608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2926608bcc6dSMat Martineau break; 2927608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2928608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2929608bcc6dSMat Martineau chan->retry_count = 1; 2930608bcc6dSMat Martineau __set_monitor_timer(chan); 2931608bcc6dSMat Martineau __clear_ack_timer(chan); 2932608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2933608bcc6dSMat Martineau break; 2934608bcc6dSMat Martineau case L2CAP_EV_RETRANS_TO: 2935608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2936608bcc6dSMat Martineau chan->retry_count = 1; 2937608bcc6dSMat Martineau __set_monitor_timer(chan); 2938608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2939608bcc6dSMat Martineau break; 2940608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2941608bcc6dSMat Martineau /* Nothing to process */ 2942608bcc6dSMat Martineau break; 2943608bcc6dSMat Martineau default: 2944608bcc6dSMat Martineau break; 2945608bcc6dSMat Martineau } 2946608bcc6dSMat Martineau } 2947608bcc6dSMat Martineau 2948d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan, 2949608bcc6dSMat Martineau struct l2cap_ctrl *control, 2950608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2951608bcc6dSMat Martineau { 2952608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2953608bcc6dSMat Martineau event); 2954608bcc6dSMat Martineau 2955608bcc6dSMat Martineau switch (event) { 2956608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2957608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2958608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2959608bcc6dSMat Martineau /* Queue data, but don't send. */ 2960608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2961608bcc6dSMat Martineau break; 2962608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2963608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2964608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2965608bcc6dSMat Martineau 2966608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2967608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2968608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2969608bcc6dSMat Martineau */ 2970608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2971608bcc6dSMat Martineau } 2972608bcc6dSMat Martineau 2973608bcc6dSMat Martineau l2cap_send_ack(chan); 2974608bcc6dSMat Martineau 2975608bcc6dSMat Martineau break; 2976608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2977608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2978608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2979608bcc6dSMat Martineau 2980608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2981608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2982608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2983608bcc6dSMat Martineau local_control.sframe = 1; 2984608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2985608bcc6dSMat Martineau local_control.poll = 1; 2986608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2987a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2988608bcc6dSMat Martineau 2989608bcc6dSMat Martineau chan->retry_count = 1; 2990608bcc6dSMat Martineau __set_monitor_timer(chan); 2991608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2992608bcc6dSMat Martineau } 2993608bcc6dSMat Martineau break; 2994608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2995608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 299619186c7bSGustavo A. R. Silva fallthrough; 2997608bcc6dSMat Martineau 2998608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2999608bcc6dSMat Martineau if (control && control->final) { 3000608bcc6dSMat Martineau __clear_monitor_timer(chan); 3001608bcc6dSMat Martineau if (chan->unacked_frames > 0) 3002608bcc6dSMat Martineau __set_retrans_timer(chan); 3003608bcc6dSMat Martineau chan->retry_count = 0; 3004608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 3005608bcc6dSMat Martineau BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state); 3006608bcc6dSMat Martineau } 3007608bcc6dSMat Martineau break; 3008608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 3009608bcc6dSMat Martineau /* Ignore */ 3010608bcc6dSMat Martineau break; 3011608bcc6dSMat Martineau case L2CAP_EV_MONITOR_TO: 3012608bcc6dSMat Martineau if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) { 3013608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 3014608bcc6dSMat Martineau __set_monitor_timer(chan); 3015608bcc6dSMat Martineau chan->retry_count++; 3016608bcc6dSMat Martineau } else { 30175e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNABORTED); 3018608bcc6dSMat Martineau } 3019608bcc6dSMat Martineau break; 3020608bcc6dSMat Martineau default: 3021608bcc6dSMat Martineau break; 3022608bcc6dSMat Martineau } 3023608bcc6dSMat Martineau } 3024608bcc6dSMat Martineau 3025d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 3026608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 3027608bcc6dSMat Martineau { 3028608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d, state %d", 3029608bcc6dSMat Martineau chan, control, skbs, event, chan->tx_state); 3030608bcc6dSMat Martineau 3031608bcc6dSMat Martineau switch (chan->tx_state) { 3032608bcc6dSMat Martineau case L2CAP_TX_STATE_XMIT: 3033d660366dSGustavo Padovan l2cap_tx_state_xmit(chan, control, skbs, event); 3034608bcc6dSMat Martineau break; 3035608bcc6dSMat Martineau case L2CAP_TX_STATE_WAIT_F: 3036d660366dSGustavo Padovan l2cap_tx_state_wait_f(chan, control, skbs, event); 3037608bcc6dSMat Martineau break; 3038608bcc6dSMat Martineau default: 3039608bcc6dSMat Martineau /* Ignore event */ 3040608bcc6dSMat Martineau break; 3041608bcc6dSMat Martineau } 3042608bcc6dSMat Martineau } 3043608bcc6dSMat Martineau 30444b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan, 30454b51dae9SMat Martineau struct l2cap_ctrl *control) 30464b51dae9SMat Martineau { 30474b51dae9SMat Martineau BT_DBG("chan %p, control %p", chan, control); 3048401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT); 30494b51dae9SMat Martineau } 30504b51dae9SMat Martineau 3051f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan, 3052f80842a8SMat Martineau struct l2cap_ctrl *control) 3053f80842a8SMat Martineau { 3054f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 3055401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT); 3056f80842a8SMat Martineau } 3057f80842a8SMat Martineau 30580a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */ 30590a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 30600a708f8fSGustavo F. Padovan { 30610a708f8fSGustavo F. Padovan struct sk_buff *nskb; 306248454079SGustavo F. Padovan struct l2cap_chan *chan; 30630a708f8fSGustavo F. Padovan 30640a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 30650a708f8fSGustavo F. Padovan 30663df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 30673d57dc68SGustavo F. Padovan 30683df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 3069715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW) 30700a708f8fSGustavo F. Padovan continue; 30710a708f8fSGustavo F. Padovan 30727f5396a7SGustavo Padovan /* Don't send frame to the channel it came from */ 3073a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.chan == chan) 30740a708f8fSGustavo F. Padovan continue; 30757f5396a7SGustavo Padovan 30768bcde1f2SGustavo Padovan nskb = skb_clone(skb, GFP_KERNEL); 30770a708f8fSGustavo F. Padovan if (!nskb) 30780a708f8fSGustavo F. Padovan continue; 307980b98027SGustavo Padovan if (chan->ops->recv(chan, nskb)) 30800a708f8fSGustavo F. Padovan kfree_skb(nskb); 30810a708f8fSGustavo F. Padovan } 30823d57dc68SGustavo F. Padovan 30833df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 30840a708f8fSGustavo F. Padovan } 30850a708f8fSGustavo F. Padovan 30860a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */ 3087b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, 3088b4400672SAndrei Emeltchenko u8 ident, u16 dlen, void *data) 30890a708f8fSGustavo F. Padovan { 30900a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag; 30910a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd; 30920a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 30930a708f8fSGustavo F. Padovan int len, count; 30940a708f8fSGustavo F. Padovan 3095b4400672SAndrei Emeltchenko BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u", 30960a708f8fSGustavo F. Padovan conn, code, ident, dlen); 30970a708f8fSGustavo F. Padovan 3098300b962eSAnderson Lizardo if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE) 3099300b962eSAnderson Lizardo return NULL; 3100300b962eSAnderson Lizardo 31010a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; 31020a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 31030a708f8fSGustavo F. Padovan 31048bcde1f2SGustavo Padovan skb = bt_skb_alloc(count, GFP_KERNEL); 31050a708f8fSGustavo F. Padovan if (!skb) 31060a708f8fSGustavo F. Padovan return NULL; 31070a708f8fSGustavo F. Padovan 31084df864c1SJohannes Berg lh = skb_put(skb, L2CAP_HDR_SIZE); 31090a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); 31103300d9a9SClaudio Takahasi 31113300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 3112dcf4adbfSJoe Perches lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING); 31133300d9a9SClaudio Takahasi else 3114dcf4adbfSJoe Perches lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING); 31150a708f8fSGustavo F. Padovan 31164df864c1SJohannes Berg cmd = skb_put(skb, L2CAP_CMD_HDR_SIZE); 31170a708f8fSGustavo F. Padovan cmd->code = code; 31180a708f8fSGustavo F. Padovan cmd->ident = ident; 31190a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen); 31200a708f8fSGustavo F. Padovan 31210a708f8fSGustavo F. Padovan if (dlen) { 31220a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE; 312359ae1d12SJohannes Berg skb_put_data(skb, data, count); 31240a708f8fSGustavo F. Padovan data += count; 31250a708f8fSGustavo F. Padovan } 31260a708f8fSGustavo F. Padovan 31270a708f8fSGustavo F. Padovan len -= skb->len; 31280a708f8fSGustavo F. Padovan 31290a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 31300a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 31310a708f8fSGustavo F. Padovan while (len) { 31320a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 31330a708f8fSGustavo F. Padovan 31348bcde1f2SGustavo Padovan *frag = bt_skb_alloc(count, GFP_KERNEL); 31350a708f8fSGustavo F. Padovan if (!*frag) 31360a708f8fSGustavo F. Padovan goto fail; 31370a708f8fSGustavo F. Padovan 313859ae1d12SJohannes Berg skb_put_data(*frag, data, count); 31390a708f8fSGustavo F. Padovan 31400a708f8fSGustavo F. Padovan len -= count; 31410a708f8fSGustavo F. Padovan data += count; 31420a708f8fSGustavo F. Padovan 31430a708f8fSGustavo F. Padovan frag = &(*frag)->next; 31440a708f8fSGustavo F. Padovan } 31450a708f8fSGustavo F. Padovan 31460a708f8fSGustavo F. Padovan return skb; 31470a708f8fSGustavo F. Padovan 31480a708f8fSGustavo F. Padovan fail: 31490a708f8fSGustavo F. Padovan kfree_skb(skb); 31500a708f8fSGustavo F. Padovan return NULL; 31510a708f8fSGustavo F. Padovan } 31520a708f8fSGustavo F. Padovan 31532d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, 31542d792818SGustavo Padovan unsigned long *val) 31550a708f8fSGustavo F. Padovan { 31560a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 31570a708f8fSGustavo F. Padovan int len; 31580a708f8fSGustavo F. Padovan 31590a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len; 31600a708f8fSGustavo F. Padovan *ptr += len; 31610a708f8fSGustavo F. Padovan 31620a708f8fSGustavo F. Padovan *type = opt->type; 31630a708f8fSGustavo F. Padovan *olen = opt->len; 31640a708f8fSGustavo F. Padovan 31650a708f8fSGustavo F. Padovan switch (opt->len) { 31660a708f8fSGustavo F. Padovan case 1: 31670a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val); 31680a708f8fSGustavo F. Padovan break; 31690a708f8fSGustavo F. Padovan 31700a708f8fSGustavo F. Padovan case 2: 31710a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val); 31720a708f8fSGustavo F. Padovan break; 31730a708f8fSGustavo F. Padovan 31740a708f8fSGustavo F. Padovan case 4: 31750a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val); 31760a708f8fSGustavo F. Padovan break; 31770a708f8fSGustavo F. Padovan 31780a708f8fSGustavo F. Padovan default: 31790a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val; 31800a708f8fSGustavo F. Padovan break; 31810a708f8fSGustavo F. Padovan } 31820a708f8fSGustavo F. Padovan 3183b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val); 31840a708f8fSGustavo F. Padovan return len; 31850a708f8fSGustavo F. Padovan } 31860a708f8fSGustavo F. Padovan 3187e860d2c9SBen Seri static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size) 31880a708f8fSGustavo F. Padovan { 31890a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 31900a708f8fSGustavo F. Padovan 3191b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val); 31920a708f8fSGustavo F. Padovan 3193e860d2c9SBen Seri if (size < L2CAP_CONF_OPT_SIZE + len) 3194e860d2c9SBen Seri return; 3195e860d2c9SBen Seri 31960a708f8fSGustavo F. Padovan opt->type = type; 31970a708f8fSGustavo F. Padovan opt->len = len; 31980a708f8fSGustavo F. Padovan 31990a708f8fSGustavo F. Padovan switch (len) { 32000a708f8fSGustavo F. Padovan case 1: 32010a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val; 32020a708f8fSGustavo F. Padovan break; 32030a708f8fSGustavo F. Padovan 32040a708f8fSGustavo F. Padovan case 2: 32050a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val); 32060a708f8fSGustavo F. Padovan break; 32070a708f8fSGustavo F. Padovan 32080a708f8fSGustavo F. Padovan case 4: 32090a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val); 32100a708f8fSGustavo F. Padovan break; 32110a708f8fSGustavo F. Padovan 32120a708f8fSGustavo F. Padovan default: 32130a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len); 32140a708f8fSGustavo F. Padovan break; 32150a708f8fSGustavo F. Padovan } 32160a708f8fSGustavo F. Padovan 32170a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len; 32180a708f8fSGustavo F. Padovan } 32190a708f8fSGustavo F. Padovan 3220e860d2c9SBen Seri static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan, size_t size) 3221f89cef09SAndrei Emeltchenko { 3222f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs; 3223f89cef09SAndrei Emeltchenko 3224f89cef09SAndrei Emeltchenko switch (chan->mode) { 3225f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM: 3226f89cef09SAndrei Emeltchenko efs.id = chan->local_id; 3227f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype; 3228f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 3229f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 3230dcf4adbfSJoe Perches efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); 3231dcf4adbfSJoe Perches efs.flush_to = cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO); 3232f89cef09SAndrei Emeltchenko break; 3233f89cef09SAndrei Emeltchenko 3234f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING: 3235f89cef09SAndrei Emeltchenko efs.id = 1; 3236f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT; 3237f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 3238f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 3239f89cef09SAndrei Emeltchenko efs.acc_lat = 0; 3240f89cef09SAndrei Emeltchenko efs.flush_to = 0; 3241f89cef09SAndrei Emeltchenko break; 3242f89cef09SAndrei Emeltchenko 3243f89cef09SAndrei Emeltchenko default: 3244f89cef09SAndrei Emeltchenko return; 3245f89cef09SAndrei Emeltchenko } 3246f89cef09SAndrei Emeltchenko 3247f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), 3248e860d2c9SBen Seri (unsigned long) &efs, size); 3249f89cef09SAndrei Emeltchenko } 3250f89cef09SAndrei Emeltchenko 3251721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work) 32520a708f8fSGustavo F. Padovan { 3253721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 3254721c4181SGustavo F. Padovan ack_timer.work); 32550362520bSMat Martineau u16 frames_to_ack; 32560a708f8fSGustavo F. Padovan 32572fb9b3d4SGustavo F. Padovan BT_DBG("chan %p", chan); 32582fb9b3d4SGustavo F. Padovan 32596be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 32606be36555SAndrei Emeltchenko 32610362520bSMat Martineau frames_to_ack = __seq_offset(chan, chan->buffer_seq, 32620362520bSMat Martineau chan->last_acked_seq); 32630362520bSMat Martineau 32640362520bSMat Martineau if (frames_to_ack) 32650362520bSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 32666be36555SAndrei Emeltchenko 32676be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 326809bfb2eeSSzymon Janc l2cap_chan_put(chan); 32690a708f8fSGustavo F. Padovan } 32700a708f8fSGustavo F. Padovan 3271466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan) 32720a708f8fSGustavo F. Padovan { 32733c588192SMat Martineau int err; 32743c588192SMat Martineau 3275105bdf9eSMat Martineau chan->next_tx_seq = 0; 3276105bdf9eSMat Martineau chan->expected_tx_seq = 0; 327742e5c802SGustavo F. Padovan chan->expected_ack_seq = 0; 32786a026610SGustavo F. Padovan chan->unacked_frames = 0; 327942e5c802SGustavo F. Padovan chan->buffer_seq = 0; 32806a026610SGustavo F. Padovan chan->frames_sent = 0; 3281105bdf9eSMat Martineau chan->last_acked_seq = 0; 3282105bdf9eSMat Martineau chan->sdu = NULL; 3283105bdf9eSMat Martineau chan->sdu_last_frag = NULL; 3284105bdf9eSMat Martineau chan->sdu_len = 0; 3285105bdf9eSMat Martineau 3286d34c34fbSMat Martineau skb_queue_head_init(&chan->tx_q); 3287d34c34fbSMat Martineau 32886ed971caSMarcel Holtmann chan->local_amp_id = AMP_ID_BREDR; 32896ed971caSMarcel Holtmann chan->move_id = AMP_ID_BREDR; 329008333283SMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 329108333283SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 329208333283SMat Martineau 3293105bdf9eSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 3294105bdf9eSMat Martineau return 0; 3295105bdf9eSMat Martineau 3296105bdf9eSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 3297105bdf9eSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 32980a708f8fSGustavo F. Padovan 3299721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout); 3300721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout); 3301721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout); 33020a708f8fSGustavo F. Padovan 3303f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q); 33040a708f8fSGustavo F. Padovan 33053c588192SMat Martineau err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win); 33063c588192SMat Martineau if (err < 0) 33073c588192SMat Martineau return err; 33083c588192SMat Martineau 33099dc9affcSMat Martineau err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win); 33109dc9affcSMat Martineau if (err < 0) 33119dc9affcSMat Martineau l2cap_seq_list_free(&chan->srej_list); 33129dc9affcSMat Martineau 33139dc9affcSMat Martineau return err; 33140a708f8fSGustavo F. Padovan } 33150a708f8fSGustavo F. Padovan 33160a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) 33170a708f8fSGustavo F. Padovan { 33180a708f8fSGustavo F. Padovan switch (mode) { 33190a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 33200a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 33210a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask)) 33220a708f8fSGustavo F. Padovan return mode; 332319186c7bSGustavo A. R. Silva fallthrough; 33240a708f8fSGustavo F. Padovan default: 33250a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC; 33260a708f8fSGustavo F. Padovan } 33270a708f8fSGustavo F. Padovan } 33280a708f8fSGustavo F. Padovan 3329848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn) 33306327eb98SAndrei Emeltchenko { 33310bd49fc7SJohan Hedberg return ((conn->local_fixed_chan & L2CAP_FC_A2MP) && 33320bd49fc7SJohan Hedberg (conn->feat_mask & L2CAP_FEAT_EXT_WINDOW)); 33336327eb98SAndrei Emeltchenko } 33346327eb98SAndrei Emeltchenko 3335848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn) 3336f89cef09SAndrei Emeltchenko { 33370bd49fc7SJohan Hedberg return ((conn->local_fixed_chan & L2CAP_FC_A2MP) && 33380bd49fc7SJohan Hedberg (conn->feat_mask & L2CAP_FEAT_EXT_FLOW)); 3339f89cef09SAndrei Emeltchenko } 3340f89cef09SAndrei Emeltchenko 334136c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan, 334236c86c85SMat Martineau struct l2cap_conf_rfc *rfc) 334336c86c85SMat Martineau { 33446ed971caSMarcel Holtmann if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) { 334536c86c85SMat Martineau u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to; 334636c86c85SMat Martineau 334736c86c85SMat Martineau /* Class 1 devices have must have ERTM timeouts 334836c86c85SMat Martineau * exceeding the Link Supervision Timeout. The 334936c86c85SMat Martineau * default Link Supervision Timeout for AMP 335036c86c85SMat Martineau * controllers is 10 seconds. 335136c86c85SMat Martineau * 335236c86c85SMat Martineau * Class 1 devices use 0xffffffff for their 335336c86c85SMat Martineau * best-effort flush timeout, so the clamping logic 335436c86c85SMat Martineau * will result in a timeout that meets the above 335536c86c85SMat Martineau * requirement. ERTM timeouts are 16-bit values, so 335636c86c85SMat Martineau * the maximum timeout is 65.535 seconds. 335736c86c85SMat Martineau */ 335836c86c85SMat Martineau 335936c86c85SMat Martineau /* Convert timeout to milliseconds and round */ 336036c86c85SMat Martineau ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000); 336136c86c85SMat Martineau 336236c86c85SMat Martineau /* This is the recommended formula for class 2 devices 336336c86c85SMat Martineau * that start ERTM timers when packets are sent to the 336436c86c85SMat Martineau * controller. 336536c86c85SMat Martineau */ 336636c86c85SMat Martineau ertm_to = 3 * ertm_to + 500; 336736c86c85SMat Martineau 336836c86c85SMat Martineau if (ertm_to > 0xffff) 336936c86c85SMat Martineau ertm_to = 0xffff; 337036c86c85SMat Martineau 337136c86c85SMat Martineau rfc->retrans_timeout = cpu_to_le16((u16) ertm_to); 337236c86c85SMat Martineau rfc->monitor_timeout = rfc->retrans_timeout; 337336c86c85SMat Martineau } else { 3374dcf4adbfSJoe Perches rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 3375dcf4adbfSJoe Perches rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 337636c86c85SMat Martineau } 337736c86c85SMat Martineau } 337836c86c85SMat Martineau 33796327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan) 33806327eb98SAndrei Emeltchenko { 33816327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && 3382848566b3SMarcel Holtmann __l2cap_ews_supported(chan->conn)) { 33836327eb98SAndrei Emeltchenko /* use extended control field */ 33846327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 3385836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 3386836be934SAndrei Emeltchenko } else { 33876327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win, 33886327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 3389836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 3390836be934SAndrei Emeltchenko } 3391c20f8e35SMat Martineau chan->ack_win = chan->tx_win; 33926327eb98SAndrei Emeltchenko } 33936327eb98SAndrei Emeltchenko 33944b6e228eSLuiz Augusto von Dentz static void l2cap_mtu_auto(struct l2cap_chan *chan) 33954b6e228eSLuiz Augusto von Dentz { 33964b6e228eSLuiz Augusto von Dentz struct hci_conn *conn = chan->conn->hcon; 33974b6e228eSLuiz Augusto von Dentz 33984b6e228eSLuiz Augusto von Dentz chan->imtu = L2CAP_DEFAULT_MIN_MTU; 33994b6e228eSLuiz Augusto von Dentz 34004b6e228eSLuiz Augusto von Dentz /* The 2-DH1 packet has between 2 and 56 information bytes 34014b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header) 34024b6e228eSLuiz Augusto von Dentz */ 34034b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_2DH1)) 34044b6e228eSLuiz Augusto von Dentz chan->imtu = 54; 34054b6e228eSLuiz Augusto von Dentz 34064b6e228eSLuiz Augusto von Dentz /* The 3-DH1 packet has between 2 and 85 information bytes 34074b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header) 34084b6e228eSLuiz Augusto von Dentz */ 34094b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_3DH1)) 34104b6e228eSLuiz Augusto von Dentz chan->imtu = 83; 34114b6e228eSLuiz Augusto von Dentz 34124b6e228eSLuiz Augusto von Dentz /* The 2-DH3 packet has between 2 and 369 information bytes 34134b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header) 34144b6e228eSLuiz Augusto von Dentz */ 34154b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_2DH3)) 34164b6e228eSLuiz Augusto von Dentz chan->imtu = 367; 34174b6e228eSLuiz Augusto von Dentz 34184b6e228eSLuiz Augusto von Dentz /* The 3-DH3 packet has between 2 and 554 information bytes 34194b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header) 34204b6e228eSLuiz Augusto von Dentz */ 34214b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_3DH3)) 34224b6e228eSLuiz Augusto von Dentz chan->imtu = 552; 34234b6e228eSLuiz Augusto von Dentz 34244b6e228eSLuiz Augusto von Dentz /* The 2-DH5 packet has between 2 and 681 information bytes 34254b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header) 34264b6e228eSLuiz Augusto von Dentz */ 34274b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_2DH5)) 34284b6e228eSLuiz Augusto von Dentz chan->imtu = 679; 34294b6e228eSLuiz Augusto von Dentz 34304b6e228eSLuiz Augusto von Dentz /* The 3-DH5 packet has between 2 and 1023 information bytes 34314b6e228eSLuiz Augusto von Dentz * (including the 2-byte payload header) 34324b6e228eSLuiz Augusto von Dentz */ 34334b6e228eSLuiz Augusto von Dentz if (!(conn->pkt_type & HCI_3DH5)) 34344b6e228eSLuiz Augusto von Dentz chan->imtu = 1021; 34354b6e228eSLuiz Augusto von Dentz } 34364b6e228eSLuiz Augusto von Dentz 3437e860d2c9SBen Seri static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size) 34380a708f8fSGustavo F. Padovan { 34390a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 34400c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode }; 34410a708f8fSGustavo F. Padovan void *ptr = req->data; 3442e860d2c9SBen Seri void *endptr = data + data_size; 3443c8f79162SAndrei Emeltchenko u16 size; 34440a708f8fSGustavo F. Padovan 344549208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 34460a708f8fSGustavo F. Padovan 344773ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp) 34480a708f8fSGustavo F. Padovan goto done; 34490a708f8fSGustavo F. Padovan 34500c1bc5c6SGustavo F. Padovan switch (chan->mode) { 34510a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 34520a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3453c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) 34540a708f8fSGustavo F. Padovan break; 34550a708f8fSGustavo F. Padovan 3456848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn)) 3457f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 3458f89cef09SAndrei Emeltchenko 345919186c7bSGustavo A. R. Silva fallthrough; 34600a708f8fSGustavo F. Padovan default: 34618c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); 34620a708f8fSGustavo F. Padovan break; 34630a708f8fSGustavo F. Padovan } 34640a708f8fSGustavo F. Padovan 34650a708f8fSGustavo F. Padovan done: 34664b6e228eSLuiz Augusto von Dentz if (chan->imtu != L2CAP_DEFAULT_MTU) { 34674b6e228eSLuiz Augusto von Dentz if (!chan->imtu) 34684b6e228eSLuiz Augusto von Dentz l2cap_mtu_auto(chan); 34694b6e228eSLuiz Augusto von Dentz l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, 34704b6e228eSLuiz Augusto von Dentz endptr - ptr); 34714b6e228eSLuiz Augusto von Dentz } 34720a708f8fSGustavo F. Padovan 34730c1bc5c6SGustavo F. Padovan switch (chan->mode) { 34740a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 34756fea7ad1SMarcel Holtmann if (disable_ertm) 34766fea7ad1SMarcel Holtmann break; 34776fea7ad1SMarcel Holtmann 34788c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && 34798c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) 34800a708f8fSGustavo F. Padovan break; 34810a708f8fSGustavo F. Padovan 34820a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC; 34830a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 34840a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 34850a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 34860a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 34870a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0; 34880a708f8fSGustavo F. Padovan 34890a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3490e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr); 34910a708f8fSGustavo F. Padovan break; 34920a708f8fSGustavo F. Padovan 34930a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 34940a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM; 349547d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx; 349636c86c85SMat Martineau 349736c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc); 3498c8f79162SAndrei Emeltchenko 3499c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 35002d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - 3501c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3502c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 35030a708f8fSGustavo F. Padovan 35046327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan); 35056327eb98SAndrei Emeltchenko 35066327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win, 35076327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 35080a708f8fSGustavo F. Padovan 35090a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3510e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr); 35110a708f8fSGustavo F. Padovan 3512f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 3513e860d2c9SBen Seri l2cap_add_opt_efs(&ptr, chan, endptr - ptr); 3514f89cef09SAndrei Emeltchenko 35156327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 35166327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 3517e860d2c9SBen Seri chan->tx_win, endptr - ptr); 351860918918SAndrei Emeltchenko 351960918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS) 352060918918SAndrei Emeltchenko if (chan->fcs == L2CAP_FCS_NONE || 3521f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { 352260918918SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 352360918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, 3524e860d2c9SBen Seri chan->fcs, endptr - ptr); 352560918918SAndrei Emeltchenko } 35260a708f8fSGustavo F. Padovan break; 35270a708f8fSGustavo F. Padovan 35280a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3529273759e2SMat Martineau l2cap_txwin_setup(chan); 35300a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING; 35310a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 35320a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 35330a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 35340a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 3535c8f79162SAndrei Emeltchenko 3536c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 35372d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - 3538c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3539c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 35400a708f8fSGustavo F. Padovan 35410a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3542e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr); 35430a708f8fSGustavo F. Padovan 3544f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 3545e860d2c9SBen Seri l2cap_add_opt_efs(&ptr, chan, endptr - ptr); 3546f89cef09SAndrei Emeltchenko 354760918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS) 354847d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 3549f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { 355047d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 355160918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, 3552e860d2c9SBen Seri chan->fcs, endptr - ptr); 35530a708f8fSGustavo F. Padovan } 35540a708f8fSGustavo F. Padovan break; 35550a708f8fSGustavo F. Padovan } 35560a708f8fSGustavo F. Padovan 3557fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 3558dcf4adbfSJoe Perches req->flags = cpu_to_le16(0); 35590a708f8fSGustavo F. Padovan 35600a708f8fSGustavo F. Padovan return ptr - data; 35610a708f8fSGustavo F. Padovan } 35620a708f8fSGustavo F. Padovan 3563e860d2c9SBen Seri static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data_size) 35640a708f8fSGustavo F. Padovan { 35650a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 35660a708f8fSGustavo F. Padovan void *ptr = rsp->data; 3567e860d2c9SBen Seri void *endptr = data + data_size; 356873ffa904SGustavo F. Padovan void *req = chan->conf_req; 356973ffa904SGustavo F. Padovan int len = chan->conf_len; 35700a708f8fSGustavo F. Padovan int type, hint, olen; 35710a708f8fSGustavo F. Padovan unsigned long val; 35720a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 357342dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs; 357442dceae2SAndrei Emeltchenko u8 remote_efs = 0; 35750a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU; 35760a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS; 3577c8f79162SAndrei Emeltchenko u16 size; 35780a708f8fSGustavo F. Padovan 357973ffa904SGustavo F. Padovan BT_DBG("chan %p", chan); 35800a708f8fSGustavo F. Padovan 35810a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 35820a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val); 35837c9cbd0bSMarcel Holtmann if (len < 0) 35847c9cbd0bSMarcel Holtmann break; 35850a708f8fSGustavo F. Padovan 35860a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT; 35870a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK; 35880a708f8fSGustavo F. Padovan 35890a708f8fSGustavo F. Padovan switch (type) { 35900a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 3591af3d5d1cSMarcel Holtmann if (olen != 2) 3592af3d5d1cSMarcel Holtmann break; 35930a708f8fSGustavo F. Padovan mtu = val; 35940a708f8fSGustavo F. Padovan break; 35950a708f8fSGustavo F. Padovan 35960a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 3597af3d5d1cSMarcel Holtmann if (olen != 2) 3598af3d5d1cSMarcel Holtmann break; 35990c1bc5c6SGustavo F. Padovan chan->flush_to = val; 36000a708f8fSGustavo F. Padovan break; 36010a708f8fSGustavo F. Padovan 36020a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS: 36030a708f8fSGustavo F. Padovan break; 36040a708f8fSGustavo F. Padovan 36050a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 3606af3d5d1cSMarcel Holtmann if (olen != sizeof(rfc)) 3607af3d5d1cSMarcel Holtmann break; 36080a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen); 36090a708f8fSGustavo F. Padovan break; 36100a708f8fSGustavo F. Padovan 36110a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS: 3612af3d5d1cSMarcel Holtmann if (olen != 1) 3613af3d5d1cSMarcel Holtmann break; 36140a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE) 3615f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, &chan->conf_state); 361642dceae2SAndrei Emeltchenko break; 36170a708f8fSGustavo F. Padovan 361842dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS: 3619af3d5d1cSMarcel Holtmann if (olen != sizeof(efs)) 3620af3d5d1cSMarcel Holtmann break; 362142dceae2SAndrei Emeltchenko remote_efs = 1; 362242dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen); 36230a708f8fSGustavo F. Padovan break; 36240a708f8fSGustavo F. Padovan 36256327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 3626af3d5d1cSMarcel Holtmann if (olen != 2) 3627af3d5d1cSMarcel Holtmann break; 36280bd49fc7SJohan Hedberg if (!(chan->conn->local_fixed_chan & L2CAP_FC_A2MP)) 36296327eb98SAndrei Emeltchenko return -ECONNREFUSED; 36306327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 36316327eb98SAndrei Emeltchenko set_bit(CONF_EWS_RECV, &chan->conf_state); 3632836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 36336327eb98SAndrei Emeltchenko chan->remote_tx_win = val; 36340a708f8fSGustavo F. Padovan break; 36350a708f8fSGustavo F. Padovan 36360a708f8fSGustavo F. Padovan default: 36370a708f8fSGustavo F. Padovan if (hint) 36380a708f8fSGustavo F. Padovan break; 36390a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN; 36405b8ec15dSJimmy Wahlberg l2cap_add_conf_opt(&ptr, (u8)type, sizeof(u8), type, endptr - ptr); 36410a708f8fSGustavo F. Padovan break; 36420a708f8fSGustavo F. Padovan } 36430a708f8fSGustavo F. Padovan } 36440a708f8fSGustavo F. Padovan 364573ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1) 36460a708f8fSGustavo F. Padovan goto done; 36470a708f8fSGustavo F. Padovan 36480c1bc5c6SGustavo F. Padovan switch (chan->mode) { 36490a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 36500a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3651c1360a1cSGustavo F. Padovan if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { 36520c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, 36538c1d787bSGustavo F. Padovan chan->conn->feat_mask); 36540a708f8fSGustavo F. Padovan break; 36550a708f8fSGustavo F. Padovan } 36560a708f8fSGustavo F. Padovan 365742dceae2SAndrei Emeltchenko if (remote_efs) { 3658848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn)) 365942dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 366042dceae2SAndrei Emeltchenko else 366142dceae2SAndrei Emeltchenko return -ECONNREFUSED; 366242dceae2SAndrei Emeltchenko } 366342dceae2SAndrei Emeltchenko 36640c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) 36650a708f8fSGustavo F. Padovan return -ECONNREFUSED; 36660a708f8fSGustavo F. Padovan 36670a708f8fSGustavo F. Padovan break; 36680a708f8fSGustavo F. Padovan } 36690a708f8fSGustavo F. Padovan 36700a708f8fSGustavo F. Padovan done: 36710c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) { 36720a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 36730c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 36740a708f8fSGustavo F. Padovan 367573ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1) 36760a708f8fSGustavo F. Padovan return -ECONNREFUSED; 36770a708f8fSGustavo F. Padovan 36782d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3679e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr); 36800a708f8fSGustavo F. Padovan } 36810a708f8fSGustavo F. Padovan 36820a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) { 36830a708f8fSGustavo F. Padovan /* Configure output options and let the other side know 36840a708f8fSGustavo F. Padovan * which ones we don't like. */ 36850a708f8fSGustavo F. Padovan 36860a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU) 36870a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 36880a708f8fSGustavo F. Padovan else { 36890c1bc5c6SGustavo F. Padovan chan->omtu = mtu; 3690c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state); 36910a708f8fSGustavo F. Padovan } 3692e860d2c9SBen Seri l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu, endptr - ptr); 36930a708f8fSGustavo F. Padovan 369442dceae2SAndrei Emeltchenko if (remote_efs) { 369542dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 369642dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 369742dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) { 369842dceae2SAndrei Emeltchenko 369942dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT; 370042dceae2SAndrei Emeltchenko 370142dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1) 370242dceae2SAndrei Emeltchenko return -ECONNREFUSED; 370342dceae2SAndrei Emeltchenko 370442dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 370542dceae2SAndrei Emeltchenko sizeof(efs), 3706e860d2c9SBen Seri (unsigned long) &efs, endptr - ptr); 37070e8b207eSAndrei Emeltchenko } else { 37083e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */ 37090e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING; 37100e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 371142dceae2SAndrei Emeltchenko } 371242dceae2SAndrei Emeltchenko } 371342dceae2SAndrei Emeltchenko 37140a708f8fSGustavo F. Padovan switch (rfc.mode) { 37150a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 371647d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3717c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 37180a708f8fSGustavo F. Padovan break; 37190a708f8fSGustavo F. Padovan 37200a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 37216327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state)) 37222c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size; 37236327eb98SAndrei Emeltchenko else 37246327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; 37256327eb98SAndrei Emeltchenko 37262c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit; 37270a708f8fSGustavo F. Padovan 3728c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 37292d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE - 37302d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); 3731c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3732c8f79162SAndrei Emeltchenko chan->remote_mps = size; 37330a708f8fSGustavo F. Padovan 373436c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc); 37350a708f8fSGustavo F. Padovan 3736c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 37370a708f8fSGustavo F. Padovan 37380a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 3739e860d2c9SBen Seri sizeof(rfc), (unsigned long) &rfc, endptr - ptr); 37400a708f8fSGustavo F. Padovan 374142dceae2SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 374242dceae2SAndrei Emeltchenko chan->remote_id = efs.id; 374342dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype; 374442dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu); 374542dceae2SAndrei Emeltchenko chan->remote_flush_to = 374642dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to); 374742dceae2SAndrei Emeltchenko chan->remote_acc_lat = 374842dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat); 374942dceae2SAndrei Emeltchenko chan->remote_sdu_itime = 375042dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 375142dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 37522d792818SGustavo Padovan sizeof(efs), 3753e860d2c9SBen Seri (unsigned long) &efs, endptr - ptr); 375442dceae2SAndrei Emeltchenko } 37550a708f8fSGustavo F. Padovan break; 37560a708f8fSGustavo F. Padovan 37570a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3758c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 37592d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE - 37602d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); 3761c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3762c8f79162SAndrei Emeltchenko chan->remote_mps = size; 37630a708f8fSGustavo F. Padovan 3764c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 37650a708f8fSGustavo F. Padovan 37662d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3767e860d2c9SBen Seri (unsigned long) &rfc, endptr - ptr); 37680a708f8fSGustavo F. Padovan 37690a708f8fSGustavo F. Padovan break; 37700a708f8fSGustavo F. Padovan 37710a708f8fSGustavo F. Padovan default: 37720a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 37730a708f8fSGustavo F. Padovan 37740a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc)); 37750c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 37760a708f8fSGustavo F. Padovan } 37770a708f8fSGustavo F. Padovan 37780a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) 3779c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 37800a708f8fSGustavo F. Padovan } 3781fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 37820a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 3783dcf4adbfSJoe Perches rsp->flags = cpu_to_le16(0); 37840a708f8fSGustavo F. Padovan 37850a708f8fSGustavo F. Padovan return ptr - data; 37860a708f8fSGustavo F. Padovan } 37870a708f8fSGustavo F. Padovan 37882d792818SGustavo Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, 3789e860d2c9SBen Seri void *data, size_t size, u16 *result) 37900a708f8fSGustavo F. Padovan { 37910a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 37920a708f8fSGustavo F. Padovan void *ptr = req->data; 3793e860d2c9SBen Seri void *endptr = data + size; 37940a708f8fSGustavo F. Padovan int type, olen; 37950a708f8fSGustavo F. Padovan unsigned long val; 379636e999a8SMat Martineau struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 379766af7aafSAndrei Emeltchenko struct l2cap_conf_efs efs; 37980a708f8fSGustavo F. Padovan 3799fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); 38000a708f8fSGustavo F. Padovan 38010a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 38020a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 38037c9cbd0bSMarcel Holtmann if (len < 0) 38047c9cbd0bSMarcel Holtmann break; 38050a708f8fSGustavo F. Padovan 38060a708f8fSGustavo F. Padovan switch (type) { 38070a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 3808af3d5d1cSMarcel Holtmann if (olen != 2) 3809af3d5d1cSMarcel Holtmann break; 38100a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) { 38110a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT; 38120c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU; 38130a708f8fSGustavo F. Padovan } else 38140c1bc5c6SGustavo F. Padovan chan->imtu = val; 3815af3d5d1cSMarcel Holtmann l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, 3816af3d5d1cSMarcel Holtmann endptr - ptr); 38170a708f8fSGustavo F. Padovan break; 38180a708f8fSGustavo F. Padovan 38190a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 3820af3d5d1cSMarcel Holtmann if (olen != 2) 3821af3d5d1cSMarcel Holtmann break; 38220c1bc5c6SGustavo F. Padovan chan->flush_to = val; 3823af3d5d1cSMarcel Holtmann l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, 3824af3d5d1cSMarcel Holtmann chan->flush_to, endptr - ptr); 38250a708f8fSGustavo F. Padovan break; 38260a708f8fSGustavo F. Padovan 38270a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 3828af3d5d1cSMarcel Holtmann if (olen != sizeof(rfc)) 3829af3d5d1cSMarcel Holtmann break; 38300a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 3831c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && 38320c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode) 38330a708f8fSGustavo F. Padovan return -ECONNREFUSED; 383447d1ec61SGustavo F. Padovan chan->fcs = 0; 3835af3d5d1cSMarcel Holtmann l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 3836af3d5d1cSMarcel Holtmann (unsigned long) &rfc, endptr - ptr); 38370a708f8fSGustavo F. Padovan break; 38386327eb98SAndrei Emeltchenko 38396327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 3840af3d5d1cSMarcel Holtmann if (olen != 2) 3841af3d5d1cSMarcel Holtmann break; 3842c20f8e35SMat Martineau chan->ack_win = min_t(u16, val, chan->ack_win); 38433e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 3844e860d2c9SBen Seri chan->tx_win, endptr - ptr); 38456327eb98SAndrei Emeltchenko break; 384666af7aafSAndrei Emeltchenko 384766af7aafSAndrei Emeltchenko case L2CAP_CONF_EFS: 3848af3d5d1cSMarcel Holtmann if (olen != sizeof(efs)) 3849af3d5d1cSMarcel Holtmann break; 385066af7aafSAndrei Emeltchenko memcpy(&efs, (void *)val, olen); 385166af7aafSAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 385266af7aafSAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 385366af7aafSAndrei Emeltchenko efs.stype != chan->local_stype) 385466af7aafSAndrei Emeltchenko return -ECONNREFUSED; 38552d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), 3856e860d2c9SBen Seri (unsigned long) &efs, endptr - ptr); 385766af7aafSAndrei Emeltchenko break; 3858cbabee78SAndrei Emeltchenko 3859cbabee78SAndrei Emeltchenko case L2CAP_CONF_FCS: 3860af3d5d1cSMarcel Holtmann if (olen != 1) 3861af3d5d1cSMarcel Holtmann break; 3862cbabee78SAndrei Emeltchenko if (*result == L2CAP_CONF_PENDING) 3863cbabee78SAndrei Emeltchenko if (val == L2CAP_FCS_NONE) 3864f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, 3865cbabee78SAndrei Emeltchenko &chan->conf_state); 3866cbabee78SAndrei Emeltchenko break; 38670a708f8fSGustavo F. Padovan } 38680a708f8fSGustavo F. Padovan } 38690a708f8fSGustavo F. Padovan 38700c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) 38710a708f8fSGustavo F. Padovan return -ECONNREFUSED; 38720a708f8fSGustavo F. Padovan 38730c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode; 38740a708f8fSGustavo F. Padovan 38750e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) { 38760a708f8fSGustavo F. Padovan switch (rfc.mode) { 38770a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 387847d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 387947d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 388047d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 3881c20f8e35SMat Martineau if (!test_bit(FLAG_EXT_CTRL, &chan->flags)) 3882c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 3883c20f8e35SMat Martineau rfc.txwin_size); 388466af7aafSAndrei Emeltchenko 388566af7aafSAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 388666af7aafSAndrei Emeltchenko chan->local_msdu = le16_to_cpu(efs.msdu); 388766af7aafSAndrei Emeltchenko chan->local_sdu_itime = 388866af7aafSAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 388966af7aafSAndrei Emeltchenko chan->local_acc_lat = le32_to_cpu(efs.acc_lat); 389066af7aafSAndrei Emeltchenko chan->local_flush_to = 389166af7aafSAndrei Emeltchenko le32_to_cpu(efs.flush_to); 389266af7aafSAndrei Emeltchenko } 38930a708f8fSGustavo F. Padovan break; 389466af7aafSAndrei Emeltchenko 38950a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 389647d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 38970a708f8fSGustavo F. Padovan } 38980a708f8fSGustavo F. Padovan } 38990a708f8fSGustavo F. Padovan 3900fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 3901dcf4adbfSJoe Perches req->flags = cpu_to_le16(0); 39020a708f8fSGustavo F. Padovan 39030a708f8fSGustavo F. Padovan return ptr - data; 39040a708f8fSGustavo F. Padovan } 39050a708f8fSGustavo F. Padovan 39062d792818SGustavo Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, 39072d792818SGustavo Padovan u16 result, u16 flags) 39080a708f8fSGustavo F. Padovan { 39090a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 39100a708f8fSGustavo F. Padovan void *ptr = rsp->data; 39110a708f8fSGustavo F. Padovan 3912fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan); 39130a708f8fSGustavo F. Padovan 3914fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 39150a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 39160a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags); 39170a708f8fSGustavo F. Padovan 39180a708f8fSGustavo F. Padovan return ptr - data; 39190a708f8fSGustavo F. Padovan } 39200a708f8fSGustavo F. Padovan 392127e2d4c8SJohan Hedberg void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan) 392227e2d4c8SJohan Hedberg { 392327e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 392427e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn; 392527e2d4c8SJohan Hedberg 392627e2d4c8SJohan Hedberg BT_DBG("chan %p", chan); 392727e2d4c8SJohan Hedberg 392827e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 392927e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 39303916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps); 39310cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits); 3932571f7390SMallikarjun Phulari rsp.result = cpu_to_le16(L2CAP_CR_LE_SUCCESS); 393327e2d4c8SJohan Hedberg 393427e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), 393527e2d4c8SJohan Hedberg &rsp); 393627e2d4c8SJohan Hedberg } 393727e2d4c8SJohan Hedberg 393815f02b91SLuiz Augusto von Dentz void __l2cap_ecred_conn_rsp_defer(struct l2cap_chan *chan) 393915f02b91SLuiz Augusto von Dentz { 394015f02b91SLuiz Augusto von Dentz struct { 394115f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp rsp; 394215f02b91SLuiz Augusto von Dentz __le16 dcid[5]; 394315f02b91SLuiz Augusto von Dentz } __packed pdu; 394415f02b91SLuiz Augusto von Dentz struct l2cap_conn *conn = chan->conn; 394515f02b91SLuiz Augusto von Dentz u16 ident = chan->ident; 394615f02b91SLuiz Augusto von Dentz int i = 0; 394715f02b91SLuiz Augusto von Dentz 394815f02b91SLuiz Augusto von Dentz if (!ident) 394915f02b91SLuiz Augusto von Dentz return; 395015f02b91SLuiz Augusto von Dentz 395115f02b91SLuiz Augusto von Dentz BT_DBG("chan %p ident %d", chan, ident); 395215f02b91SLuiz Augusto von Dentz 395315f02b91SLuiz Augusto von Dentz pdu.rsp.mtu = cpu_to_le16(chan->imtu); 395415f02b91SLuiz Augusto von Dentz pdu.rsp.mps = cpu_to_le16(chan->mps); 395515f02b91SLuiz Augusto von Dentz pdu.rsp.credits = cpu_to_le16(chan->rx_credits); 395615f02b91SLuiz Augusto von Dentz pdu.rsp.result = cpu_to_le16(L2CAP_CR_LE_SUCCESS); 395715f02b91SLuiz Augusto von Dentz 395815f02b91SLuiz Augusto von Dentz mutex_lock(&conn->chan_lock); 395915f02b91SLuiz Augusto von Dentz 396015f02b91SLuiz Augusto von Dentz list_for_each_entry(chan, &conn->chan_l, list) { 396115f02b91SLuiz Augusto von Dentz if (chan->ident != ident) 396215f02b91SLuiz Augusto von Dentz continue; 396315f02b91SLuiz Augusto von Dentz 396415f02b91SLuiz Augusto von Dentz /* Reset ident so only one response is sent */ 396515f02b91SLuiz Augusto von Dentz chan->ident = 0; 396615f02b91SLuiz Augusto von Dentz 396715f02b91SLuiz Augusto von Dentz /* Include all channels pending with the same ident */ 396815f02b91SLuiz Augusto von Dentz pdu.dcid[i++] = cpu_to_le16(chan->scid); 396915f02b91SLuiz Augusto von Dentz } 397015f02b91SLuiz Augusto von Dentz 397115f02b91SLuiz Augusto von Dentz mutex_unlock(&conn->chan_lock); 397215f02b91SLuiz Augusto von Dentz 397315f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, ident, L2CAP_ECRED_CONN_RSP, 397415f02b91SLuiz Augusto von Dentz sizeof(pdu.rsp) + i * sizeof(__le16), &pdu); 397515f02b91SLuiz Augusto von Dentz } 397615f02b91SLuiz Augusto von Dentz 39778c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) 3978710f9b0aSGustavo F. Padovan { 3979710f9b0aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 39808c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 3981710f9b0aSGustavo F. Padovan u8 buf[128]; 3982439f34acSAndrei Emeltchenko u8 rsp_code; 3983710f9b0aSGustavo F. Padovan 3984fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 3985fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3986dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 3987dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 3988439f34acSAndrei Emeltchenko 3989439f34acSAndrei Emeltchenko if (chan->hs_hcon) 3990439f34acSAndrei Emeltchenko rsp_code = L2CAP_CREATE_CHAN_RSP; 3991439f34acSAndrei Emeltchenko else 3992439f34acSAndrei Emeltchenko rsp_code = L2CAP_CONN_RSP; 3993439f34acSAndrei Emeltchenko 3994439f34acSAndrei Emeltchenko BT_DBG("chan %p rsp_code %u", chan, rsp_code); 3995439f34acSAndrei Emeltchenko 3996439f34acSAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp); 3997710f9b0aSGustavo F. Padovan 3998c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 3999710f9b0aSGustavo F. Padovan return; 4000710f9b0aSGustavo F. Padovan 4001710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 4002e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); 4003710f9b0aSGustavo F. Padovan chan->num_conf_req++; 4004710f9b0aSGustavo F. Padovan } 4005710f9b0aSGustavo F. Padovan 400647d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) 40070a708f8fSGustavo F. Padovan { 40080a708f8fSGustavo F. Padovan int type, olen; 40090a708f8fSGustavo F. Padovan unsigned long val; 4010c20f8e35SMat Martineau /* Use sane default values in case a misbehaving remote device 4011c20f8e35SMat Martineau * did not send an RFC or extended window size option. 4012c20f8e35SMat Martineau */ 4013c20f8e35SMat Martineau u16 txwin_ext = chan->ack_win; 4014c20f8e35SMat Martineau struct l2cap_conf_rfc rfc = { 4015c20f8e35SMat Martineau .mode = chan->mode, 4016dcf4adbfSJoe Perches .retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO), 4017dcf4adbfSJoe Perches .monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO), 4018c20f8e35SMat Martineau .max_pdu_size = cpu_to_le16(chan->imtu), 4019c20f8e35SMat Martineau .txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW), 4020c20f8e35SMat Martineau }; 40210a708f8fSGustavo F. Padovan 402247d1ec61SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); 40230a708f8fSGustavo F. Padovan 40240c1bc5c6SGustavo F. Padovan if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) 40250a708f8fSGustavo F. Padovan return; 40260a708f8fSGustavo F. Padovan 40270a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 40280a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 40297c9cbd0bSMarcel Holtmann if (len < 0) 40307c9cbd0bSMarcel Holtmann break; 40310a708f8fSGustavo F. Padovan 4032c20f8e35SMat Martineau switch (type) { 4033c20f8e35SMat Martineau case L2CAP_CONF_RFC: 4034af3d5d1cSMarcel Holtmann if (olen != sizeof(rfc)) 4035af3d5d1cSMarcel Holtmann break; 40360a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 4037c20f8e35SMat Martineau break; 4038c20f8e35SMat Martineau case L2CAP_CONF_EWS: 4039af3d5d1cSMarcel Holtmann if (olen != 2) 4040af3d5d1cSMarcel Holtmann break; 4041c20f8e35SMat Martineau txwin_ext = val; 4042c20f8e35SMat Martineau break; 4043c20f8e35SMat Martineau } 40440a708f8fSGustavo F. Padovan } 40450a708f8fSGustavo F. Padovan 40460a708f8fSGustavo F. Padovan switch (rfc.mode) { 40470a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 404847d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 404947d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 405047d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 4051c20f8e35SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 4052c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, txwin_ext); 4053c20f8e35SMat Martineau else 4054c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 4055c20f8e35SMat Martineau rfc.txwin_size); 40560a708f8fSGustavo F. Padovan break; 40570a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 405847d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 40590a708f8fSGustavo F. Padovan } 40600a708f8fSGustavo F. Padovan } 40610a708f8fSGustavo F. Padovan 40622d792818SGustavo Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, 4063cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4064cb3b3152SJohan Hedberg u8 *data) 40650a708f8fSGustavo F. Padovan { 4066e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 40670a708f8fSGustavo F. Padovan 4068cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rej)) 4069cb3b3152SJohan Hedberg return -EPROTO; 4070cb3b3152SJohan Hedberg 4071e2fd318eSIlia Kolomisnky if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) 40720a708f8fSGustavo F. Padovan return 0; 40730a708f8fSGustavo F. Padovan 40740a708f8fSGustavo F. Padovan if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && 40750a708f8fSGustavo F. Padovan cmd->ident == conn->info_ident) { 407617cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 40770a708f8fSGustavo F. Padovan 40780a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 40790a708f8fSGustavo F. Padovan conn->info_ident = 0; 40800a708f8fSGustavo F. Padovan 40810a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 40820a708f8fSGustavo F. Padovan } 40830a708f8fSGustavo F. Padovan 40840a708f8fSGustavo F. Padovan return 0; 40850a708f8fSGustavo F. Padovan } 40860a708f8fSGustavo F. Padovan 40871700915fSMat Martineau static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, 40881700915fSMat Martineau struct l2cap_cmd_hdr *cmd, 40894c89b6aaSMat Martineau u8 *data, u8 rsp_code, u8 amp_id) 40900a708f8fSGustavo F. Padovan { 40910a708f8fSGustavo F. Padovan struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 40920a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 409323691d75SGustavo F. Padovan struct l2cap_chan *chan = NULL, *pchan; 40940a708f8fSGustavo F. Padovan int result, status = L2CAP_CS_NO_INFO; 40950a708f8fSGustavo F. Padovan 40960a708f8fSGustavo F. Padovan u16 dcid = 0, scid = __le16_to_cpu(req->scid); 40970a708f8fSGustavo F. Padovan __le16 psm = req->psm; 40980a708f8fSGustavo F. Padovan 4099097db76cSAndrei Emeltchenko BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); 41000a708f8fSGustavo F. Padovan 41010a708f8fSGustavo F. Padovan /* Check if we have socket listening on psm */ 41026f59b904SMarcel Holtmann pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 4103bf20fd4eSJohan Hedberg &conn->hcon->dst, ACL_LINK); 410423691d75SGustavo F. Padovan if (!pchan) { 41050a708f8fSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 41060a708f8fSGustavo F. Padovan goto sendresp; 41070a708f8fSGustavo F. Padovan } 41080a708f8fSGustavo F. Padovan 41093df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 41108ffb9290SGustavo Padovan l2cap_chan_lock(pchan); 41110a708f8fSGustavo F. Padovan 41120a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */ 4113dcf4adbfSJoe Perches if (psm != cpu_to_le16(L2CAP_PSM_SDP) && 41140a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) { 41159f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_AUTH_FAILURE; 41160a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 41170a708f8fSGustavo F. Padovan goto response; 41180a708f8fSGustavo F. Padovan } 41190a708f8fSGustavo F. Padovan 41200a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM; 41210a708f8fSGustavo F. Padovan 4122dd1a8f8aSMallikarjun Phulari /* Check for valid dynamic CID range (as per Erratum 3253) */ 4123dd1a8f8aSMallikarjun Phulari if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_DYN_END) { 4124dd1a8f8aSMallikarjun Phulari result = L2CAP_CR_INVALID_SCID; 41252dfa1003SGustavo Padovan goto response; 4126dd1a8f8aSMallikarjun Phulari } 4127dd1a8f8aSMallikarjun Phulari 4128dd1a8f8aSMallikarjun Phulari /* Check if we already have channel with that dcid */ 4129dd1a8f8aSMallikarjun Phulari if (__l2cap_get_chan_by_dcid(conn, scid)) { 4130dd1a8f8aSMallikarjun Phulari result = L2CAP_CR_SCID_IN_USE; 4131dd1a8f8aSMallikarjun Phulari goto response; 4132dd1a8f8aSMallikarjun Phulari } 41332dfa1003SGustavo Padovan 413480b98027SGustavo Padovan chan = pchan->ops->new_connection(pchan); 413580808e43SGustavo F. Padovan if (!chan) 41360a708f8fSGustavo F. Padovan goto response; 41370a708f8fSGustavo F. Padovan 4138330b6c15SSyam Sidhardhan /* For certain devices (ex: HID mouse), support for authentication, 4139330b6c15SSyam Sidhardhan * pairing and bonding is optional. For such devices, inorder to avoid 4140330b6c15SSyam Sidhardhan * the ACL alive for too long after L2CAP disconnection, reset the ACL 4141330b6c15SSyam Sidhardhan * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect. 4142330b6c15SSyam Sidhardhan */ 4143330b6c15SSyam Sidhardhan conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 4144330b6c15SSyam Sidhardhan 41457eafc59eSMarcel Holtmann bacpy(&chan->src, &conn->hcon->src); 41467eafc59eSMarcel Holtmann bacpy(&chan->dst, &conn->hcon->dst); 4147a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(conn->hcon); 4148a250e048SJohan Hedberg chan->dst_type = bdaddr_dst_type(conn->hcon); 4149fe4128e0SGustavo F. Padovan chan->psm = psm; 4150fe4128e0SGustavo F. Padovan chan->dcid = scid; 41511700915fSMat Martineau chan->local_amp_id = amp_id; 41520a708f8fSGustavo F. Padovan 41536be36555SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 415448454079SGustavo F. Padovan 4155fe4128e0SGustavo F. Padovan dcid = chan->scid; 41560a708f8fSGustavo F. Padovan 41578d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 41580a708f8fSGustavo F. Padovan 4159fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident; 41600a708f8fSGustavo F. Padovan 41610a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { 4162e7cafc45SJohan Hedberg if (l2cap_chan_check_security(chan, false)) { 4163bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 4164f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 41650a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 41660a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND; 41672dc4e510SGustavo Padovan chan->ops->defer(chan); 41680a708f8fSGustavo F. Padovan } else { 41691700915fSMat Martineau /* Force pending result for AMP controllers. 41701700915fSMat Martineau * The connection will succeed after the 41711700915fSMat Martineau * physical link is up. 41721700915fSMat Martineau */ 41736ed971caSMarcel Holtmann if (amp_id == AMP_ID_BREDR) { 4174f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 41750a708f8fSGustavo F. Padovan result = L2CAP_CR_SUCCESS; 41766ed971caSMarcel Holtmann } else { 4177f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 41786ed971caSMarcel Holtmann result = L2CAP_CR_PEND; 41791700915fSMat Martineau } 41800a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 41810a708f8fSGustavo F. Padovan } 41820a708f8fSGustavo F. Padovan } else { 4183f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 41840a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 41850a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND; 41860a708f8fSGustavo F. Padovan } 41870a708f8fSGustavo F. Padovan } else { 4188f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 41890a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 41900a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 41910a708f8fSGustavo F. Padovan } 41920a708f8fSGustavo F. Padovan 41930a708f8fSGustavo F. Padovan response: 41948ffb9290SGustavo Padovan l2cap_chan_unlock(pchan); 41953df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4196a24cce14SJohan Hedberg l2cap_chan_put(pchan); 41970a708f8fSGustavo F. Padovan 41980a708f8fSGustavo F. Padovan sendresp: 41990a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid); 42000a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid); 42010a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result); 42020a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status); 42034c89b6aaSMat Martineau l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp); 42040a708f8fSGustavo F. Padovan 42050a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { 42060a708f8fSGustavo F. Padovan struct l2cap_info_req info; 4207dcf4adbfSJoe Perches info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 42080a708f8fSGustavo F. Padovan 42090a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 42100a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 42110a708f8fSGustavo F. Padovan 4212ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 42130a708f8fSGustavo F. Padovan 42142d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, 42152d792818SGustavo Padovan sizeof(info), &info); 42160a708f8fSGustavo F. Padovan } 42170a708f8fSGustavo F. Padovan 4218c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && 42190a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) { 42200a708f8fSGustavo F. Padovan u8 buf[128]; 4221c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 42220a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 4223e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); 422473ffa904SGustavo F. Padovan chan->num_conf_req++; 42250a708f8fSGustavo F. Padovan } 42261700915fSMat Martineau 42271700915fSMat Martineau return chan; 42284c89b6aaSMat Martineau } 42290a708f8fSGustavo F. Padovan 42304c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn, 4231cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 42324c89b6aaSMat Martineau { 42337b064edaSJaganath Kanakkassery struct hci_dev *hdev = conn->hcon->hdev; 42347b064edaSJaganath Kanakkassery struct hci_conn *hcon = conn->hcon; 42357b064edaSJaganath Kanakkassery 4236cb3b3152SJohan Hedberg if (cmd_len < sizeof(struct l2cap_conn_req)) 4237cb3b3152SJohan Hedberg return -EPROTO; 4238cb3b3152SJohan Hedberg 42397b064edaSJaganath Kanakkassery hci_dev_lock(hdev); 4240d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_MGMT) && 42417b064edaSJaganath Kanakkassery !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags)) 424248ec92faSAlfonso Acosta mgmt_device_connected(hdev, hcon, 0, NULL, 0); 42437b064edaSJaganath Kanakkassery hci_dev_unlock(hdev); 42447b064edaSJaganath Kanakkassery 4245300229f9SGustavo Padovan l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0); 42460a708f8fSGustavo F. Padovan return 0; 42470a708f8fSGustavo F. Padovan } 42480a708f8fSGustavo F. Padovan 42495909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn, 4250cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4251cb3b3152SJohan Hedberg u8 *data) 42520a708f8fSGustavo F. Padovan { 42530a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; 42540a708f8fSGustavo F. Padovan u16 scid, dcid, result, status; 425548454079SGustavo F. Padovan struct l2cap_chan *chan; 42560a708f8fSGustavo F. Padovan u8 req[128]; 42573df91ea2SAndrei Emeltchenko int err; 42580a708f8fSGustavo F. Padovan 4259cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp)) 4260cb3b3152SJohan Hedberg return -EPROTO; 4261cb3b3152SJohan Hedberg 42620a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 42630a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 42640a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 42650a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status); 42660a708f8fSGustavo F. Padovan 42671b009c98SAndrei Emeltchenko BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", 42681b009c98SAndrei Emeltchenko dcid, scid, result, status); 42690a708f8fSGustavo F. Padovan 42703df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 42713df91ea2SAndrei Emeltchenko 42720a708f8fSGustavo F. Padovan if (scid) { 42733df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 42743df91ea2SAndrei Emeltchenko if (!chan) { 427521870b52SJohan Hedberg err = -EBADSLT; 42763df91ea2SAndrei Emeltchenko goto unlock; 42773df91ea2SAndrei Emeltchenko } 42780a708f8fSGustavo F. Padovan } else { 42793df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 42803df91ea2SAndrei Emeltchenko if (!chan) { 428121870b52SJohan Hedberg err = -EBADSLT; 42823df91ea2SAndrei Emeltchenko goto unlock; 42833df91ea2SAndrei Emeltchenko } 42840a708f8fSGustavo F. Padovan } 42850a708f8fSGustavo F. Padovan 42863df91ea2SAndrei Emeltchenko err = 0; 42873df91ea2SAndrei Emeltchenko 42886be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 428948454079SGustavo F. Padovan 42900a708f8fSGustavo F. Padovan switch (result) { 42910a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS: 429289bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 4293fc7f8a7eSGustavo F. Padovan chan->ident = 0; 4294fe4128e0SGustavo F. Padovan chan->dcid = dcid; 4295c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state); 42960a708f8fSGustavo F. Padovan 4297c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 42980a708f8fSGustavo F. Padovan break; 42990a708f8fSGustavo F. Padovan 43000a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 4301e860d2c9SBen Seri l2cap_build_conf_req(chan, req, sizeof(req)), req); 430273ffa904SGustavo F. Padovan chan->num_conf_req++; 43030a708f8fSGustavo F. Padovan break; 43040a708f8fSGustavo F. Padovan 43050a708f8fSGustavo F. Padovan case L2CAP_CR_PEND: 4306c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 43070a708f8fSGustavo F. Padovan break; 43080a708f8fSGustavo F. Padovan 43090a708f8fSGustavo F. Padovan default: 431048454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED); 43110a708f8fSGustavo F. Padovan break; 43120a708f8fSGustavo F. Padovan } 43130a708f8fSGustavo F. Padovan 43146be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 43153df91ea2SAndrei Emeltchenko 43163df91ea2SAndrei Emeltchenko unlock: 43173df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 43183df91ea2SAndrei Emeltchenko 43193df91ea2SAndrei Emeltchenko return err; 43200a708f8fSGustavo F. Padovan } 43210a708f8fSGustavo F. Padovan 432247d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan) 43230a708f8fSGustavo F. Padovan { 43240a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both 43250a708f8fSGustavo F. Padovan * sides request it. 43260a708f8fSGustavo F. Padovan */ 43270c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) 432847d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 4329f2592d3eSAndrei Emeltchenko else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) 433047d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16; 43310a708f8fSGustavo F. Padovan } 43320a708f8fSGustavo F. Padovan 433329d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data, 433429d8a590SAndrei Emeltchenko u8 ident, u16 flags) 433529d8a590SAndrei Emeltchenko { 433629d8a590SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 433729d8a590SAndrei Emeltchenko 433829d8a590SAndrei Emeltchenko BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident, 433929d8a590SAndrei Emeltchenko flags); 434029d8a590SAndrei Emeltchenko 434129d8a590SAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 434229d8a590SAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 434329d8a590SAndrei Emeltchenko 434429d8a590SAndrei Emeltchenko l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP, 434529d8a590SAndrei Emeltchenko l2cap_build_conf_rsp(chan, data, 434629d8a590SAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), data); 434729d8a590SAndrei Emeltchenko } 434829d8a590SAndrei Emeltchenko 4349662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident, 4350662d652dSJohan Hedberg u16 scid, u16 dcid) 4351662d652dSJohan Hedberg { 4352662d652dSJohan Hedberg struct l2cap_cmd_rej_cid rej; 4353662d652dSJohan Hedberg 4354dcf4adbfSJoe Perches rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID); 4355662d652dSJohan Hedberg rej.scid = __cpu_to_le16(scid); 4356662d652dSJohan Hedberg rej.dcid = __cpu_to_le16(dcid); 4357662d652dSJohan Hedberg 4358662d652dSJohan Hedberg l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); 4359662d652dSJohan Hedberg } 4360662d652dSJohan Hedberg 43612d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, 43622d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len, 43632d792818SGustavo Padovan u8 *data) 43640a708f8fSGustavo F. Padovan { 43650a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; 43660a708f8fSGustavo F. Padovan u16 dcid, flags; 43670a708f8fSGustavo F. Padovan u8 rsp[64]; 436848454079SGustavo F. Padovan struct l2cap_chan *chan; 43693c588192SMat Martineau int len, err = 0; 43700a708f8fSGustavo F. Padovan 4371cb3b3152SJohan Hedberg if (cmd_len < sizeof(*req)) 4372cb3b3152SJohan Hedberg return -EPROTO; 4373cb3b3152SJohan Hedberg 43740a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 43750a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags); 43760a708f8fSGustavo F. Padovan 43770a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); 43780a708f8fSGustavo F. Padovan 4379baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid); 4380662d652dSJohan Hedberg if (!chan) { 4381662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0); 4382662d652dSJohan Hedberg return 0; 4383662d652dSJohan Hedberg } 43840a708f8fSGustavo F. Padovan 438596298f64SHoward Chung if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2 && 438696298f64SHoward Chung chan->state != BT_CONNECTED) { 4387662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, 4388662d652dSJohan Hedberg chan->dcid); 43890a708f8fSGustavo F. Padovan goto unlock; 43900a708f8fSGustavo F. Padovan } 43910a708f8fSGustavo F. Padovan 43920a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */ 43930a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req); 4394cb3b3152SJohan Hedberg if (chan->conf_len + len > sizeof(chan->conf_req)) { 43950a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 4396fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 43970a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp); 43980a708f8fSGustavo F. Padovan goto unlock; 43990a708f8fSGustavo F. Padovan } 44000a708f8fSGustavo F. Padovan 44010a708f8fSGustavo F. Padovan /* Store config. */ 440273ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len); 440373ffa904SGustavo F. Padovan chan->conf_len += len; 44040a708f8fSGustavo F. Padovan 440559e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) { 44060a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */ 44070a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 4408fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 44095325e5bbSAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), rsp); 44100a708f8fSGustavo F. Padovan goto unlock; 44110a708f8fSGustavo F. Padovan } 44120a708f8fSGustavo F. Padovan 44130a708f8fSGustavo F. Padovan /* Complete config. */ 4414e860d2c9SBen Seri len = l2cap_parse_conf_req(chan, rsp, sizeof(rsp)); 44150a708f8fSGustavo F. Padovan if (len < 0) { 44165e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 44170a708f8fSGustavo F. Padovan goto unlock; 44180a708f8fSGustavo F. Padovan } 44190a708f8fSGustavo F. Padovan 44201500109bSMat Martineau chan->ident = cmd->ident; 44210a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); 442273ffa904SGustavo F. Padovan chan->num_conf_rsp++; 44230a708f8fSGustavo F. Padovan 44240a708f8fSGustavo F. Padovan /* Reset config buffer. */ 442573ffa904SGustavo F. Padovan chan->conf_len = 0; 44260a708f8fSGustavo F. Padovan 4427c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) 44280a708f8fSGustavo F. Padovan goto unlock; 44290a708f8fSGustavo F. Padovan 4430c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 443147d1ec61SGustavo F. Padovan set_default_fcs(chan); 44320a708f8fSGustavo F. Padovan 4433105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 4434105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 44353c588192SMat Martineau err = l2cap_ertm_init(chan); 44360a708f8fSGustavo F. Padovan 44373c588192SMat Martineau if (err < 0) 44385e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 44393c588192SMat Martineau else 4440cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 44413c588192SMat Martineau 44420a708f8fSGustavo F. Padovan goto unlock; 44430a708f8fSGustavo F. Padovan } 44440a708f8fSGustavo F. Padovan 4445c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { 44460a708f8fSGustavo F. Padovan u8 buf[64]; 44470a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 4448e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); 444973ffa904SGustavo F. Padovan chan->num_conf_req++; 44500a708f8fSGustavo F. Padovan } 44510a708f8fSGustavo F. Padovan 445249c922bbSStephen Hemminger /* Got Conf Rsp PENDING from remote side and assume we sent 44530e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */ 44540e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && 44550e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 44560e8b207eSAndrei Emeltchenko 44570e8b207eSAndrei Emeltchenko /* check compatibility */ 44580e8b207eSAndrei Emeltchenko 445979de886dSAndrei Emeltchenko /* Send rsp for BR/EDR channel */ 4460f351bc72SAndrei Emeltchenko if (!chan->hs_hcon) 446129d8a590SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags); 446279de886dSAndrei Emeltchenko else 446379de886dSAndrei Emeltchenko chan->ident = cmd->ident; 44640e8b207eSAndrei Emeltchenko } 44650e8b207eSAndrei Emeltchenko 44660a708f8fSGustavo F. Padovan unlock: 44676be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 44683c588192SMat Martineau return err; 44690a708f8fSGustavo F. Padovan } 44700a708f8fSGustavo F. Padovan 44712d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, 4472cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4473cb3b3152SJohan Hedberg u8 *data) 44740a708f8fSGustavo F. Padovan { 44750a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; 44760a708f8fSGustavo F. Padovan u16 scid, flags, result; 447748454079SGustavo F. Padovan struct l2cap_chan *chan; 4478cb3b3152SJohan Hedberg int len = cmd_len - sizeof(*rsp); 44793c588192SMat Martineau int err = 0; 44800a708f8fSGustavo F. Padovan 4481cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp)) 4482cb3b3152SJohan Hedberg return -EPROTO; 4483cb3b3152SJohan Hedberg 44840a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 44850a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags); 44860a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 44870a708f8fSGustavo F. Padovan 448861386cbaSAndrei Emeltchenko BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags, 448961386cbaSAndrei Emeltchenko result, len); 44900a708f8fSGustavo F. Padovan 4491baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 449248454079SGustavo F. Padovan if (!chan) 44930a708f8fSGustavo F. Padovan return 0; 44940a708f8fSGustavo F. Padovan 44950a708f8fSGustavo F. Padovan switch (result) { 44960a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS: 449747d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len); 44980e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state); 44990a708f8fSGustavo F. Padovan break; 45000a708f8fSGustavo F. Padovan 45010e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING: 45020e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state); 45030e8b207eSAndrei Emeltchenko 45040e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 45050e8b207eSAndrei Emeltchenko char buf[64]; 45060e8b207eSAndrei Emeltchenko 45070e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len, 4508e860d2c9SBen Seri buf, sizeof(buf), &result); 45090e8b207eSAndrei Emeltchenko if (len < 0) { 45105e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 45110e8b207eSAndrei Emeltchenko goto done; 45120e8b207eSAndrei Emeltchenko } 45130e8b207eSAndrei Emeltchenko 4514f351bc72SAndrei Emeltchenko if (!chan->hs_hcon) { 451579de886dSAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, buf, cmd->ident, 451679de886dSAndrei Emeltchenko 0); 45175ce66b59SAndrei Emeltchenko } else { 45185ce66b59SAndrei Emeltchenko if (l2cap_check_efs(chan)) { 45195ce66b59SAndrei Emeltchenko amp_create_logical_link(chan); 452079de886dSAndrei Emeltchenko chan->ident = cmd->ident; 45210e8b207eSAndrei Emeltchenko } 45225ce66b59SAndrei Emeltchenko } 45235ce66b59SAndrei Emeltchenko } 45240e8b207eSAndrei Emeltchenko goto done; 45250e8b207eSAndrei Emeltchenko 452698d2c3e1SBastien Nocera case L2CAP_CONF_UNKNOWN: 45270a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT: 452873ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { 45290a708f8fSGustavo F. Padovan char req[64]; 45300a708f8fSGustavo F. Padovan 45310a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { 45325e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 45330a708f8fSGustavo F. Padovan goto done; 45340a708f8fSGustavo F. Padovan } 45350a708f8fSGustavo F. Padovan 45360a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */ 45370a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS; 4538b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len, 4539e860d2c9SBen Seri req, sizeof(req), &result); 45400a708f8fSGustavo F. Padovan if (len < 0) { 45415e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 45420a708f8fSGustavo F. Padovan goto done; 45430a708f8fSGustavo F. Padovan } 45440a708f8fSGustavo F. Padovan 45450a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 45460a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req); 454773ffa904SGustavo F. Padovan chan->num_conf_req++; 45480a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS) 45490a708f8fSGustavo F. Padovan goto done; 45500a708f8fSGustavo F. Padovan break; 45510a708f8fSGustavo F. Padovan } 455219186c7bSGustavo A. R. Silva fallthrough; 45530a708f8fSGustavo F. Padovan 45540a708f8fSGustavo F. Padovan default: 45556be36555SAndrei Emeltchenko l2cap_chan_set_err(chan, ECONNRESET); 45562e0052e4SAndrei Emeltchenko 4557ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); 45585e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 45590a708f8fSGustavo F. Padovan goto done; 45600a708f8fSGustavo F. Padovan } 45610a708f8fSGustavo F. Padovan 456259e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) 45630a708f8fSGustavo F. Padovan goto done; 45640a708f8fSGustavo F. Padovan 4565c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state); 45660a708f8fSGustavo F. Padovan 4567c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { 456847d1ec61SGustavo F. Padovan set_default_fcs(chan); 45690a708f8fSGustavo F. Padovan 4570105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 4571105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 45723c588192SMat Martineau err = l2cap_ertm_init(chan); 45730a708f8fSGustavo F. Padovan 45743c588192SMat Martineau if (err < 0) 45755e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 45763c588192SMat Martineau else 4577cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 45780a708f8fSGustavo F. Padovan } 45790a708f8fSGustavo F. Padovan 45800a708f8fSGustavo F. Padovan done: 45816be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 45823c588192SMat Martineau return err; 45830a708f8fSGustavo F. Padovan } 45840a708f8fSGustavo F. Padovan 45852d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, 4586cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4587cb3b3152SJohan Hedberg u8 *data) 45880a708f8fSGustavo F. Padovan { 45890a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; 45900a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp; 45910a708f8fSGustavo F. Padovan u16 dcid, scid; 459248454079SGustavo F. Padovan struct l2cap_chan *chan; 45930a708f8fSGustavo F. Padovan 4594cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req)) 4595cb3b3152SJohan Hedberg return -EPROTO; 4596cb3b3152SJohan Hedberg 45970a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid); 45980a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 45990a708f8fSGustavo F. Padovan 46000a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); 46010a708f8fSGustavo F. Padovan 46023df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 46033df91ea2SAndrei Emeltchenko 46043df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, dcid); 46053df91ea2SAndrei Emeltchenko if (!chan) { 46063df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4607662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid); 4608662d652dSJohan Hedberg return 0; 46093df91ea2SAndrei Emeltchenko } 46100a708f8fSGustavo F. Padovan 46116c08fc89SManish Mandlik l2cap_chan_hold(chan); 46126be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 46136be36555SAndrei Emeltchenko 4614fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 4615fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 46160a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); 46170a708f8fSGustavo F. Padovan 46185ec1bbe5SGustavo Padovan chan->ops->set_shutdown(chan); 46190a708f8fSGustavo F. Padovan 462048454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET); 46216be36555SAndrei Emeltchenko 462280b98027SGustavo Padovan chan->ops->close(chan); 46236c08fc89SManish Mandlik 46246c08fc89SManish Mandlik l2cap_chan_unlock(chan); 462561d6ef3eSMat Martineau l2cap_chan_put(chan); 46263df91ea2SAndrei Emeltchenko 46273df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 46283df91ea2SAndrei Emeltchenko 46290a708f8fSGustavo F. Padovan return 0; 46300a708f8fSGustavo F. Padovan } 46310a708f8fSGustavo F. Padovan 46322d792818SGustavo Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, 4633cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4634cb3b3152SJohan Hedberg u8 *data) 46350a708f8fSGustavo F. Padovan { 46360a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; 46370a708f8fSGustavo F. Padovan u16 dcid, scid; 463848454079SGustavo F. Padovan struct l2cap_chan *chan; 46390a708f8fSGustavo F. Padovan 4640cb3b3152SJohan Hedberg if (cmd_len != sizeof(*rsp)) 4641cb3b3152SJohan Hedberg return -EPROTO; 4642cb3b3152SJohan Hedberg 46430a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 46440a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 46450a708f8fSGustavo F. Padovan 46460a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); 46470a708f8fSGustavo F. Padovan 46483df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 46493df91ea2SAndrei Emeltchenko 46503df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 46513df91ea2SAndrei Emeltchenko if (!chan) { 46523df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 46530a708f8fSGustavo F. Padovan return 0; 46543df91ea2SAndrei Emeltchenko } 46550a708f8fSGustavo F. Padovan 46566c08fc89SManish Mandlik l2cap_chan_hold(chan); 46576be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 465848454079SGustavo F. Padovan 465928261da8SMatias Karhumaa if (chan->state != BT_DISCONN) { 466028261da8SMatias Karhumaa l2cap_chan_unlock(chan); 46616c08fc89SManish Mandlik l2cap_chan_put(chan); 466228261da8SMatias Karhumaa mutex_unlock(&conn->chan_lock); 466328261da8SMatias Karhumaa return 0; 466428261da8SMatias Karhumaa } 466528261da8SMatias Karhumaa 466648454079SGustavo F. Padovan l2cap_chan_del(chan, 0); 46676be36555SAndrei Emeltchenko 466880b98027SGustavo Padovan chan->ops->close(chan); 46696c08fc89SManish Mandlik 46706c08fc89SManish Mandlik l2cap_chan_unlock(chan); 467161d6ef3eSMat Martineau l2cap_chan_put(chan); 46723df91ea2SAndrei Emeltchenko 46733df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 46743df91ea2SAndrei Emeltchenko 46750a708f8fSGustavo F. Padovan return 0; 46760a708f8fSGustavo F. Padovan } 46770a708f8fSGustavo F. Padovan 46782d792818SGustavo Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, 4679cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4680cb3b3152SJohan Hedberg u8 *data) 46810a708f8fSGustavo F. Padovan { 46820a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data; 46830a708f8fSGustavo F. Padovan u16 type; 46840a708f8fSGustavo F. Padovan 4685cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req)) 4686cb3b3152SJohan Hedberg return -EPROTO; 4687cb3b3152SJohan Hedberg 46880a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type); 46890a708f8fSGustavo F. Padovan 46900a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type); 46910a708f8fSGustavo F. Padovan 46920a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) { 46930a708f8fSGustavo F. Padovan u8 buf[8]; 46940a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask; 46950a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 4696dcf4adbfSJoe Perches rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 4697dcf4adbfSJoe Perches rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 46980a708f8fSGustavo F. Padovan if (!disable_ertm) 46990a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING 47000a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS; 47010bd49fc7SJohan Hedberg if (conn->local_fixed_chan & L2CAP_FC_A2MP) 47026327eb98SAndrei Emeltchenko feat_mask |= L2CAP_FEAT_EXT_FLOW 47036327eb98SAndrei Emeltchenko | L2CAP_FEAT_EXT_WINDOW; 4704a5fd6f30SAndrei Emeltchenko 47050a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data); 47062d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), 47072d792818SGustavo Padovan buf); 47080a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) { 47090a708f8fSGustavo F. Padovan u8 buf[12]; 47100a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 471150a147cdSMat Martineau 4712dcf4adbfSJoe Perches rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 4713dcf4adbfSJoe Perches rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 47140bd49fc7SJohan Hedberg rsp->data[0] = conn->local_fixed_chan; 47150bd49fc7SJohan Hedberg memset(rsp->data + 1, 0, 7); 47162d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), 47172d792818SGustavo Padovan buf); 47180a708f8fSGustavo F. Padovan } else { 47190a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp; 47200a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type); 4721dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP); 47222d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), 47232d792818SGustavo Padovan &rsp); 47240a708f8fSGustavo F. Padovan } 47250a708f8fSGustavo F. Padovan 47260a708f8fSGustavo F. Padovan return 0; 47270a708f8fSGustavo F. Padovan } 47280a708f8fSGustavo F. Padovan 47292d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, 4730cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4731cb3b3152SJohan Hedberg u8 *data) 47320a708f8fSGustavo F. Padovan { 47330a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; 47340a708f8fSGustavo F. Padovan u16 type, result; 47350a708f8fSGustavo F. Padovan 47363f6fa3d4SJaganath Kanakkassery if (cmd_len < sizeof(*rsp)) 4737cb3b3152SJohan Hedberg return -EPROTO; 4738cb3b3152SJohan Hedberg 47390a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type); 47400a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 47410a708f8fSGustavo F. Padovan 47420a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); 47430a708f8fSGustavo F. Padovan 4744e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */ 4745e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident || 4746e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 4747e90165beSAndrei Emeltchenko return 0; 4748e90165beSAndrei Emeltchenko 474917cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 47500a708f8fSGustavo F. Padovan 47510a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) { 47520a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 47530a708f8fSGustavo F. Padovan conn->info_ident = 0; 47540a708f8fSGustavo F. Padovan 47550a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 47560a708f8fSGustavo F. Padovan 47570a708f8fSGustavo F. Padovan return 0; 47580a708f8fSGustavo F. Padovan } 47590a708f8fSGustavo F. Padovan 4760978c93b9SAndrei Emeltchenko switch (type) { 4761978c93b9SAndrei Emeltchenko case L2CAP_IT_FEAT_MASK: 47620a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data); 47630a708f8fSGustavo F. Padovan 47640a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { 47650a708f8fSGustavo F. Padovan struct l2cap_info_req req; 4766dcf4adbfSJoe Perches req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 47670a708f8fSGustavo F. Padovan 47680a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 47690a708f8fSGustavo F. Padovan 47700a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 47710a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 47720a708f8fSGustavo F. Padovan } else { 47730a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 47740a708f8fSGustavo F. Padovan conn->info_ident = 0; 47750a708f8fSGustavo F. Padovan 47760a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 47770a708f8fSGustavo F. Padovan } 4778978c93b9SAndrei Emeltchenko break; 4779978c93b9SAndrei Emeltchenko 4780978c93b9SAndrei Emeltchenko case L2CAP_IT_FIXED_CHAN: 47810bd49fc7SJohan Hedberg conn->remote_fixed_chan = rsp->data[0]; 47820a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 47830a708f8fSGustavo F. Padovan conn->info_ident = 0; 47840a708f8fSGustavo F. Padovan 47850a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 4786978c93b9SAndrei Emeltchenko break; 47870a708f8fSGustavo F. Padovan } 47880a708f8fSGustavo F. Padovan 47890a708f8fSGustavo F. Padovan return 0; 47900a708f8fSGustavo F. Padovan } 47910a708f8fSGustavo F. Padovan 47921700915fSMat Martineau static int l2cap_create_channel_req(struct l2cap_conn *conn, 47932d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, 47942d792818SGustavo Padovan u16 cmd_len, void *data) 4795f94ff6ffSMat Martineau { 4796f94ff6ffSMat Martineau struct l2cap_create_chan_req *req = data; 47976e1df6a6SAndrei Emeltchenko struct l2cap_create_chan_rsp rsp; 47981700915fSMat Martineau struct l2cap_chan *chan; 47996e1df6a6SAndrei Emeltchenko struct hci_dev *hdev; 4800f94ff6ffSMat Martineau u16 psm, scid; 4801f94ff6ffSMat Martineau 4802f94ff6ffSMat Martineau if (cmd_len != sizeof(*req)) 4803f94ff6ffSMat Martineau return -EPROTO; 4804f94ff6ffSMat Martineau 48050bd49fc7SJohan Hedberg if (!(conn->local_fixed_chan & L2CAP_FC_A2MP)) 4806f94ff6ffSMat Martineau return -EINVAL; 4807f94ff6ffSMat Martineau 4808f94ff6ffSMat Martineau psm = le16_to_cpu(req->psm); 4809f94ff6ffSMat Martineau scid = le16_to_cpu(req->scid); 4810f94ff6ffSMat Martineau 4811ad0ac6caSAndrei Emeltchenko BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id); 4812f94ff6ffSMat Martineau 48136e1df6a6SAndrei Emeltchenko /* For controller id 0 make BR/EDR connection */ 48146ed971caSMarcel Holtmann if (req->amp_id == AMP_ID_BREDR) { 48156e1df6a6SAndrei Emeltchenko l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, 48166e1df6a6SAndrei Emeltchenko req->amp_id); 48176e1df6a6SAndrei Emeltchenko return 0; 48186e1df6a6SAndrei Emeltchenko } 48191700915fSMat Martineau 48201700915fSMat Martineau /* Validate AMP controller id */ 48211700915fSMat Martineau hdev = hci_dev_get(req->amp_id); 48226e1df6a6SAndrei Emeltchenko if (!hdev) 48236e1df6a6SAndrei Emeltchenko goto error; 48241700915fSMat Martineau 48256e1df6a6SAndrei Emeltchenko if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) { 48266e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 48276e1df6a6SAndrei Emeltchenko goto error; 48286e1df6a6SAndrei Emeltchenko } 48296e1df6a6SAndrei Emeltchenko 48306e1df6a6SAndrei Emeltchenko chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, 48316e1df6a6SAndrei Emeltchenko req->amp_id); 48326e1df6a6SAndrei Emeltchenko if (chan) { 48336e1df6a6SAndrei Emeltchenko struct amp_mgr *mgr = conn->hcon->amp_mgr; 48346e1df6a6SAndrei Emeltchenko struct hci_conn *hs_hcon; 48356e1df6a6SAndrei Emeltchenko 483698e0f7eaSMarcel Holtmann hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, 483798e0f7eaSMarcel Holtmann &conn->hcon->dst); 48386e1df6a6SAndrei Emeltchenko if (!hs_hcon) { 48396e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 4840662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, 4841662d652dSJohan Hedberg chan->dcid); 4842662d652dSJohan Hedberg return 0; 48436e1df6a6SAndrei Emeltchenko } 48446e1df6a6SAndrei Emeltchenko 48456e1df6a6SAndrei Emeltchenko BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon); 48466e1df6a6SAndrei Emeltchenko 48476e1df6a6SAndrei Emeltchenko mgr->bredr_chan = chan; 48486e1df6a6SAndrei Emeltchenko chan->hs_hcon = hs_hcon; 4849fd45bf4cSAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 48506e1df6a6SAndrei Emeltchenko conn->mtu = hdev->block_mtu; 48516e1df6a6SAndrei Emeltchenko } 48526e1df6a6SAndrei Emeltchenko 48536e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 48546e1df6a6SAndrei Emeltchenko 48556e1df6a6SAndrei Emeltchenko return 0; 48566e1df6a6SAndrei Emeltchenko 48576e1df6a6SAndrei Emeltchenko error: 4858f94ff6ffSMat Martineau rsp.dcid = 0; 4859f94ff6ffSMat Martineau rsp.scid = cpu_to_le16(scid); 4860dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_BAD_AMP); 4861dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 4862f94ff6ffSMat Martineau 4863f94ff6ffSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, 4864f94ff6ffSMat Martineau sizeof(rsp), &rsp); 4865f94ff6ffSMat Martineau 4866dc280801SJohan Hedberg return 0; 4867f94ff6ffSMat Martineau } 4868f94ff6ffSMat Martineau 48698eb200bdSMat Martineau static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id) 48708eb200bdSMat Martineau { 48718eb200bdSMat Martineau struct l2cap_move_chan_req req; 48728eb200bdSMat Martineau u8 ident; 48738eb200bdSMat Martineau 48748eb200bdSMat Martineau BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id); 48758eb200bdSMat Martineau 48768eb200bdSMat Martineau ident = l2cap_get_ident(chan->conn); 48778eb200bdSMat Martineau chan->ident = ident; 48788eb200bdSMat Martineau 48798eb200bdSMat Martineau req.icid = cpu_to_le16(chan->scid); 48808eb200bdSMat Martineau req.dest_amp_id = dest_amp_id; 48818eb200bdSMat Martineau 48828eb200bdSMat Martineau l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req), 48838eb200bdSMat Martineau &req); 48848eb200bdSMat Martineau 48858eb200bdSMat Martineau __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); 48868eb200bdSMat Martineau } 48878eb200bdSMat Martineau 48881500109bSMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result) 48898d5a04a1SMat Martineau { 48908d5a04a1SMat Martineau struct l2cap_move_chan_rsp rsp; 48918d5a04a1SMat Martineau 48921500109bSMat Martineau BT_DBG("chan %p, result 0x%4.4x", chan, result); 48938d5a04a1SMat Martineau 48941500109bSMat Martineau rsp.icid = cpu_to_le16(chan->dcid); 48958d5a04a1SMat Martineau rsp.result = cpu_to_le16(result); 48968d5a04a1SMat Martineau 48971500109bSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP, 48981500109bSMat Martineau sizeof(rsp), &rsp); 48998d5a04a1SMat Martineau } 49008d5a04a1SMat Martineau 49015b155ef9SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result) 49028d5a04a1SMat Martineau { 49038d5a04a1SMat Martineau struct l2cap_move_chan_cfm cfm; 49048d5a04a1SMat Martineau 49055b155ef9SMat Martineau BT_DBG("chan %p, result 0x%4.4x", chan, result); 49068d5a04a1SMat Martineau 49075b155ef9SMat Martineau chan->ident = l2cap_get_ident(chan->conn); 49088d5a04a1SMat Martineau 49095b155ef9SMat Martineau cfm.icid = cpu_to_le16(chan->scid); 49108d5a04a1SMat Martineau cfm.result = cpu_to_le16(result); 49118d5a04a1SMat Martineau 49125b155ef9SMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM, 49135b155ef9SMat Martineau sizeof(cfm), &cfm); 49145b155ef9SMat Martineau 49155b155ef9SMat Martineau __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); 49165b155ef9SMat Martineau } 49175b155ef9SMat Martineau 49185b155ef9SMat Martineau static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid) 49195b155ef9SMat Martineau { 49205b155ef9SMat Martineau struct l2cap_move_chan_cfm cfm; 49215b155ef9SMat Martineau 49225b155ef9SMat Martineau BT_DBG("conn %p, icid 0x%4.4x", conn, icid); 49235b155ef9SMat Martineau 49245b155ef9SMat Martineau cfm.icid = cpu_to_le16(icid); 4925dcf4adbfSJoe Perches cfm.result = cpu_to_le16(L2CAP_MC_UNCONFIRMED); 49265b155ef9SMat Martineau 49275b155ef9SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM, 49285b155ef9SMat Martineau sizeof(cfm), &cfm); 49298d5a04a1SMat Martineau } 49308d5a04a1SMat Martineau 49318d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, 49328d5a04a1SMat Martineau u16 icid) 49338d5a04a1SMat Martineau { 49348d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp rsp; 49358d5a04a1SMat Martineau 4936ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 49378d5a04a1SMat Martineau 49388d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 49398d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp); 49408d5a04a1SMat Martineau } 49418d5a04a1SMat Martineau 49425f3847a4SMat Martineau static void __release_logical_link(struct l2cap_chan *chan) 49435f3847a4SMat Martineau { 49445f3847a4SMat Martineau chan->hs_hchan = NULL; 49455f3847a4SMat Martineau chan->hs_hcon = NULL; 49465f3847a4SMat Martineau 49475f3847a4SMat Martineau /* Placeholder - release the logical link */ 49485f3847a4SMat Martineau } 49495f3847a4SMat Martineau 49501500109bSMat Martineau static void l2cap_logical_fail(struct l2cap_chan *chan) 49511500109bSMat Martineau { 49521500109bSMat Martineau /* Logical link setup failed */ 49531500109bSMat Martineau if (chan->state != BT_CONNECTED) { 49541500109bSMat Martineau /* Create channel failure, disconnect */ 49555e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 49561500109bSMat Martineau return; 49571500109bSMat Martineau } 49581500109bSMat Martineau 49591500109bSMat Martineau switch (chan->move_role) { 49601500109bSMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 49611500109bSMat Martineau l2cap_move_done(chan); 49621500109bSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP); 49631500109bSMat Martineau break; 49641500109bSMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 49651500109bSMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP || 49661500109bSMat Martineau chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) { 49671500109bSMat Martineau /* Remote has only sent pending or 49681500109bSMat Martineau * success responses, clean up 49691500109bSMat Martineau */ 49701500109bSMat Martineau l2cap_move_done(chan); 49711500109bSMat Martineau } 49721500109bSMat Martineau 49731500109bSMat Martineau /* Other amp move states imply that the move 49741500109bSMat Martineau * has already aborted 49751500109bSMat Martineau */ 49761500109bSMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 49771500109bSMat Martineau break; 49781500109bSMat Martineau } 49791500109bSMat Martineau } 49801500109bSMat Martineau 49811500109bSMat Martineau static void l2cap_logical_finish_create(struct l2cap_chan *chan, 49821500109bSMat Martineau struct hci_chan *hchan) 49831500109bSMat Martineau { 49841500109bSMat Martineau struct l2cap_conf_rsp rsp; 49851500109bSMat Martineau 4986336178a3SAndrei Emeltchenko chan->hs_hchan = hchan; 49871500109bSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 49881500109bSMat Martineau 498935ba9561SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0); 49901500109bSMat Martineau 49911500109bSMat Martineau if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 4992fe79c6feSAndrei Emeltchenko int err; 49931500109bSMat Martineau 49941500109bSMat Martineau set_default_fcs(chan); 49951500109bSMat Martineau 49961500109bSMat Martineau err = l2cap_ertm_init(chan); 49971500109bSMat Martineau if (err < 0) 49985e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 49991500109bSMat Martineau else 50001500109bSMat Martineau l2cap_chan_ready(chan); 50011500109bSMat Martineau } 50021500109bSMat Martineau } 50031500109bSMat Martineau 50041500109bSMat Martineau static void l2cap_logical_finish_move(struct l2cap_chan *chan, 50051500109bSMat Martineau struct hci_chan *hchan) 50061500109bSMat Martineau { 50071500109bSMat Martineau chan->hs_hcon = hchan->conn; 50081500109bSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 50091500109bSMat Martineau 50101500109bSMat Martineau BT_DBG("move_state %d", chan->move_state); 50111500109bSMat Martineau 50121500109bSMat Martineau switch (chan->move_state) { 50131500109bSMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_COMP: 50141500109bSMat Martineau /* Move confirm will be sent after a success 50151500109bSMat Martineau * response is received 50161500109bSMat Martineau */ 50171500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 50181500109bSMat Martineau break; 50191500109bSMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_CFM: 50201500109bSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 50211500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 50221500109bSMat Martineau } else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { 50231500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; 50241500109bSMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 50251500109bSMat Martineau } else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { 50261500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 50271500109bSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); 50281500109bSMat Martineau } 50291500109bSMat Martineau break; 50301500109bSMat Martineau default: 50311500109bSMat Martineau /* Move was not in expected state, free the channel */ 50321500109bSMat Martineau __release_logical_link(chan); 50331500109bSMat Martineau 50341500109bSMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 50351500109bSMat Martineau } 50361500109bSMat Martineau } 50371500109bSMat Martineau 50381500109bSMat Martineau /* Call with chan locked */ 503927695fb4SAndrei Emeltchenko void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan, 50405b155ef9SMat Martineau u8 status) 50415b155ef9SMat Martineau { 50421500109bSMat Martineau BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status); 50431500109bSMat Martineau 50441500109bSMat Martineau if (status) { 50451500109bSMat Martineau l2cap_logical_fail(chan); 50461500109bSMat Martineau __release_logical_link(chan); 50475b155ef9SMat Martineau return; 50485b155ef9SMat Martineau } 50495b155ef9SMat Martineau 50501500109bSMat Martineau if (chan->state != BT_CONNECTED) { 50511500109bSMat Martineau /* Ignore logical link if channel is on BR/EDR */ 50526ed971caSMarcel Holtmann if (chan->local_amp_id != AMP_ID_BREDR) 50531500109bSMat Martineau l2cap_logical_finish_create(chan, hchan); 50541500109bSMat Martineau } else { 50551500109bSMat Martineau l2cap_logical_finish_move(chan, hchan); 50561500109bSMat Martineau } 50571500109bSMat Martineau } 50581500109bSMat Martineau 50593f7a56c4SMat Martineau void l2cap_move_start(struct l2cap_chan *chan) 50603f7a56c4SMat Martineau { 50613f7a56c4SMat Martineau BT_DBG("chan %p", chan); 50623f7a56c4SMat Martineau 50636ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR) { 50643f7a56c4SMat Martineau if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED) 50653f7a56c4SMat Martineau return; 50663f7a56c4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; 50673f7a56c4SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_PREPARE; 50683f7a56c4SMat Martineau /* Placeholder - start physical link setup */ 50693f7a56c4SMat Martineau } else { 50703f7a56c4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; 50713f7a56c4SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 50723f7a56c4SMat Martineau chan->move_id = 0; 50733f7a56c4SMat Martineau l2cap_move_setup(chan); 50743f7a56c4SMat Martineau l2cap_send_move_chan_req(chan, 0); 50753f7a56c4SMat Martineau } 50763f7a56c4SMat Martineau } 50773f7a56c4SMat Martineau 50788eb200bdSMat Martineau static void l2cap_do_create(struct l2cap_chan *chan, int result, 50798eb200bdSMat Martineau u8 local_amp_id, u8 remote_amp_id) 50808eb200bdSMat Martineau { 508162748ca1SAndrei Emeltchenko BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state), 508262748ca1SAndrei Emeltchenko local_amp_id, remote_amp_id); 508362748ca1SAndrei Emeltchenko 508412d6cc60SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 508512d6cc60SAndrei Emeltchenko 508662748ca1SAndrei Emeltchenko /* Outgoing channel on AMP */ 508762748ca1SAndrei Emeltchenko if (chan->state == BT_CONNECT) { 508862748ca1SAndrei Emeltchenko if (result == L2CAP_CR_SUCCESS) { 508962748ca1SAndrei Emeltchenko chan->local_amp_id = local_amp_id; 509062748ca1SAndrei Emeltchenko l2cap_send_create_chan_req(chan, remote_amp_id); 509162748ca1SAndrei Emeltchenko } else { 509262748ca1SAndrei Emeltchenko /* Revert to BR/EDR connect */ 509362748ca1SAndrei Emeltchenko l2cap_send_conn_req(chan); 509462748ca1SAndrei Emeltchenko } 509562748ca1SAndrei Emeltchenko 509662748ca1SAndrei Emeltchenko return; 509762748ca1SAndrei Emeltchenko } 509862748ca1SAndrei Emeltchenko 509962748ca1SAndrei Emeltchenko /* Incoming channel on AMP */ 510062748ca1SAndrei Emeltchenko if (__l2cap_no_conn_pending(chan)) { 51018eb200bdSMat Martineau struct l2cap_conn_rsp rsp; 51028eb200bdSMat Martineau char buf[128]; 51038eb200bdSMat Martineau rsp.scid = cpu_to_le16(chan->dcid); 51048eb200bdSMat Martineau rsp.dcid = cpu_to_le16(chan->scid); 51058eb200bdSMat Martineau 51068eb200bdSMat Martineau if (result == L2CAP_CR_SUCCESS) { 51078eb200bdSMat Martineau /* Send successful response */ 5108dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 5109dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 51108eb200bdSMat Martineau } else { 51118eb200bdSMat Martineau /* Send negative response */ 5112dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_NO_MEM); 5113dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 51148eb200bdSMat Martineau } 51158eb200bdSMat Martineau 51168eb200bdSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP, 51178eb200bdSMat Martineau sizeof(rsp), &rsp); 51188eb200bdSMat Martineau 51198eb200bdSMat Martineau if (result == L2CAP_CR_SUCCESS) { 5120f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 51218eb200bdSMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 51228eb200bdSMat Martineau l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn), 51238eb200bdSMat Martineau L2CAP_CONF_REQ, 5124e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); 51258eb200bdSMat Martineau chan->num_conf_req++; 51268eb200bdSMat Martineau } 51278eb200bdSMat Martineau } 51288eb200bdSMat Martineau } 51298eb200bdSMat Martineau 51308eb200bdSMat Martineau static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id, 51318eb200bdSMat Martineau u8 remote_amp_id) 51328eb200bdSMat Martineau { 51338eb200bdSMat Martineau l2cap_move_setup(chan); 51348eb200bdSMat Martineau chan->move_id = local_amp_id; 51358eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP; 51368eb200bdSMat Martineau 51378eb200bdSMat Martineau l2cap_send_move_chan_req(chan, remote_amp_id); 51388eb200bdSMat Martineau } 51398eb200bdSMat Martineau 51408eb200bdSMat Martineau static void l2cap_do_move_respond(struct l2cap_chan *chan, int result) 51418eb200bdSMat Martineau { 51428eb200bdSMat Martineau struct hci_chan *hchan = NULL; 51438eb200bdSMat Martineau 51448eb200bdSMat Martineau /* Placeholder - get hci_chan for logical link */ 51458eb200bdSMat Martineau 51468eb200bdSMat Martineau if (hchan) { 51478eb200bdSMat Martineau if (hchan->state == BT_CONNECTED) { 51488eb200bdSMat Martineau /* Logical link is ready to go */ 51498eb200bdSMat Martineau chan->hs_hcon = hchan->conn; 51508eb200bdSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 51518eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 51528eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); 51538eb200bdSMat Martineau 51548eb200bdSMat Martineau l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); 51558eb200bdSMat Martineau } else { 51568eb200bdSMat Martineau /* Wait for logical link to be ready */ 51578eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 51588eb200bdSMat Martineau } 51598eb200bdSMat Martineau } else { 51608eb200bdSMat Martineau /* Logical link not available */ 51618eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED); 51628eb200bdSMat Martineau } 51638eb200bdSMat Martineau } 51648eb200bdSMat Martineau 51658eb200bdSMat Martineau static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result) 51668eb200bdSMat Martineau { 51678eb200bdSMat Martineau if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { 51688eb200bdSMat Martineau u8 rsp_result; 51698eb200bdSMat Martineau if (result == -EINVAL) 51708eb200bdSMat Martineau rsp_result = L2CAP_MR_BAD_ID; 51718eb200bdSMat Martineau else 51728eb200bdSMat Martineau rsp_result = L2CAP_MR_NOT_ALLOWED; 51738eb200bdSMat Martineau 51748eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, rsp_result); 51758eb200bdSMat Martineau } 51768eb200bdSMat Martineau 51778eb200bdSMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 51788eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 51798eb200bdSMat Martineau 51808eb200bdSMat Martineau /* Restart data transmission */ 51818eb200bdSMat Martineau l2cap_ertm_send(chan); 51828eb200bdSMat Martineau } 51838eb200bdSMat Martineau 5184a514b17fSAndrei Emeltchenko /* Invoke with locked chan */ 5185a514b17fSAndrei Emeltchenko void __l2cap_physical_cfm(struct l2cap_chan *chan, int result) 51868eb200bdSMat Martineau { 5187770bfefaSAndrei Emeltchenko u8 local_amp_id = chan->local_amp_id; 5188fffadc08SAndrei Emeltchenko u8 remote_amp_id = chan->remote_amp_id; 5189770bfefaSAndrei Emeltchenko 51908eb200bdSMat Martineau BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d", 51918eb200bdSMat Martineau chan, result, local_amp_id, remote_amp_id); 51928eb200bdSMat Martineau 5193df66499aSDan Carpenter if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) 51948eb200bdSMat Martineau return; 51958eb200bdSMat Martineau 51968eb200bdSMat Martineau if (chan->state != BT_CONNECTED) { 51978eb200bdSMat Martineau l2cap_do_create(chan, result, local_amp_id, remote_amp_id); 51988eb200bdSMat Martineau } else if (result != L2CAP_MR_SUCCESS) { 51998eb200bdSMat Martineau l2cap_do_move_cancel(chan, result); 52008eb200bdSMat Martineau } else { 52018eb200bdSMat Martineau switch (chan->move_role) { 52028eb200bdSMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 52038eb200bdSMat Martineau l2cap_do_move_initiate(chan, local_amp_id, 52048eb200bdSMat Martineau remote_amp_id); 52058eb200bdSMat Martineau break; 52068eb200bdSMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 52078eb200bdSMat Martineau l2cap_do_move_respond(chan, result); 52088eb200bdSMat Martineau break; 52098eb200bdSMat Martineau default: 52108eb200bdSMat Martineau l2cap_do_move_cancel(chan, result); 52118eb200bdSMat Martineau break; 52128eb200bdSMat Martineau } 52138eb200bdSMat Martineau } 52148eb200bdSMat Martineau } 52158eb200bdSMat Martineau 52168d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn, 5217ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5218ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 52198d5a04a1SMat Martineau { 52208d5a04a1SMat Martineau struct l2cap_move_chan_req *req = data; 52211500109bSMat Martineau struct l2cap_move_chan_rsp rsp; 522202b0fbb9SMat Martineau struct l2cap_chan *chan; 52238d5a04a1SMat Martineau u16 icid = 0; 52248d5a04a1SMat Martineau u16 result = L2CAP_MR_NOT_ALLOWED; 52258d5a04a1SMat Martineau 52268d5a04a1SMat Martineau if (cmd_len != sizeof(*req)) 52278d5a04a1SMat Martineau return -EPROTO; 52288d5a04a1SMat Martineau 52298d5a04a1SMat Martineau icid = le16_to_cpu(req->icid); 52308d5a04a1SMat Martineau 5231ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id); 52328d5a04a1SMat Martineau 52330bd49fc7SJohan Hedberg if (!(conn->local_fixed_chan & L2CAP_FC_A2MP)) 52348d5a04a1SMat Martineau return -EINVAL; 52358d5a04a1SMat Martineau 523602b0fbb9SMat Martineau chan = l2cap_get_chan_by_dcid(conn, icid); 523702b0fbb9SMat Martineau if (!chan) { 52381500109bSMat Martineau rsp.icid = cpu_to_le16(icid); 5239dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_MR_NOT_ALLOWED); 52401500109bSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP, 52411500109bSMat Martineau sizeof(rsp), &rsp); 524202b0fbb9SMat Martineau return 0; 524302b0fbb9SMat Martineau } 524402b0fbb9SMat Martineau 52451500109bSMat Martineau chan->ident = cmd->ident; 52461500109bSMat Martineau 524702b0fbb9SMat Martineau if (chan->scid < L2CAP_CID_DYN_START || 524802b0fbb9SMat Martineau chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY || 524902b0fbb9SMat Martineau (chan->mode != L2CAP_MODE_ERTM && 525002b0fbb9SMat Martineau chan->mode != L2CAP_MODE_STREAMING)) { 525102b0fbb9SMat Martineau result = L2CAP_MR_NOT_ALLOWED; 525202b0fbb9SMat Martineau goto send_move_response; 525302b0fbb9SMat Martineau } 525402b0fbb9SMat Martineau 525502b0fbb9SMat Martineau if (chan->local_amp_id == req->dest_amp_id) { 525602b0fbb9SMat Martineau result = L2CAP_MR_SAME_ID; 525702b0fbb9SMat Martineau goto send_move_response; 525802b0fbb9SMat Martineau } 525902b0fbb9SMat Martineau 52606ed971caSMarcel Holtmann if (req->dest_amp_id != AMP_ID_BREDR) { 526102b0fbb9SMat Martineau struct hci_dev *hdev; 526202b0fbb9SMat Martineau hdev = hci_dev_get(req->dest_amp_id); 526302b0fbb9SMat Martineau if (!hdev || hdev->dev_type != HCI_AMP || 526402b0fbb9SMat Martineau !test_bit(HCI_UP, &hdev->flags)) { 526502b0fbb9SMat Martineau if (hdev) 526602b0fbb9SMat Martineau hci_dev_put(hdev); 526702b0fbb9SMat Martineau 526802b0fbb9SMat Martineau result = L2CAP_MR_BAD_ID; 526902b0fbb9SMat Martineau goto send_move_response; 527002b0fbb9SMat Martineau } 527102b0fbb9SMat Martineau hci_dev_put(hdev); 527202b0fbb9SMat Martineau } 527302b0fbb9SMat Martineau 527402b0fbb9SMat Martineau /* Detect a move collision. Only send a collision response 527502b0fbb9SMat Martineau * if this side has "lost", otherwise proceed with the move. 527602b0fbb9SMat Martineau * The winner has the larger bd_addr. 527702b0fbb9SMat Martineau */ 527802b0fbb9SMat Martineau if ((__chan_is_moving(chan) || 527902b0fbb9SMat Martineau chan->move_role != L2CAP_MOVE_ROLE_NONE) && 52806f59b904SMarcel Holtmann bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) { 528102b0fbb9SMat Martineau result = L2CAP_MR_COLLISION; 528202b0fbb9SMat Martineau goto send_move_response; 528302b0fbb9SMat Martineau } 528402b0fbb9SMat Martineau 528502b0fbb9SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; 528602b0fbb9SMat Martineau l2cap_move_setup(chan); 528702b0fbb9SMat Martineau chan->move_id = req->dest_amp_id; 528802b0fbb9SMat Martineau 52896ed971caSMarcel Holtmann if (req->dest_amp_id == AMP_ID_BREDR) { 529002b0fbb9SMat Martineau /* Moving to BR/EDR */ 529102b0fbb9SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 529202b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 529302b0fbb9SMat Martineau result = L2CAP_MR_PEND; 529402b0fbb9SMat Martineau } else { 529502b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 529602b0fbb9SMat Martineau result = L2CAP_MR_SUCCESS; 529702b0fbb9SMat Martineau } 529802b0fbb9SMat Martineau } else { 529902b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_PREPARE; 530002b0fbb9SMat Martineau /* Placeholder - uncomment when amp functions are available */ 530102b0fbb9SMat Martineau /*amp_accept_physical(chan, req->dest_amp_id);*/ 530202b0fbb9SMat Martineau result = L2CAP_MR_PEND; 530302b0fbb9SMat Martineau } 530402b0fbb9SMat Martineau 530502b0fbb9SMat Martineau send_move_response: 53061500109bSMat Martineau l2cap_send_move_chan_rsp(chan, result); 53078d5a04a1SMat Martineau 530802b0fbb9SMat Martineau l2cap_chan_unlock(chan); 530902b0fbb9SMat Martineau 53108d5a04a1SMat Martineau return 0; 53118d5a04a1SMat Martineau } 53128d5a04a1SMat Martineau 53135b155ef9SMat Martineau static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result) 53145b155ef9SMat Martineau { 53155b155ef9SMat Martineau struct l2cap_chan *chan; 53165b155ef9SMat Martineau struct hci_chan *hchan = NULL; 53175b155ef9SMat Martineau 53185b155ef9SMat Martineau chan = l2cap_get_chan_by_scid(conn, icid); 53195b155ef9SMat Martineau if (!chan) { 53205b155ef9SMat Martineau l2cap_send_move_chan_cfm_icid(conn, icid); 53215b155ef9SMat Martineau return; 53225b155ef9SMat Martineau } 53235b155ef9SMat Martineau 53245b155ef9SMat Martineau __clear_chan_timer(chan); 53255b155ef9SMat Martineau if (result == L2CAP_MR_PEND) 53265b155ef9SMat Martineau __set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT); 53275b155ef9SMat Martineau 53285b155ef9SMat Martineau switch (chan->move_state) { 53295b155ef9SMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_COMP: 53305b155ef9SMat Martineau /* Move confirm will be sent when logical link 53315b155ef9SMat Martineau * is complete. 53325b155ef9SMat Martineau */ 53335b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 53345b155ef9SMat Martineau break; 53355b155ef9SMat Martineau case L2CAP_MOVE_WAIT_RSP_SUCCESS: 53365b155ef9SMat Martineau if (result == L2CAP_MR_PEND) { 53375b155ef9SMat Martineau break; 53385b155ef9SMat Martineau } else if (test_bit(CONN_LOCAL_BUSY, 53395b155ef9SMat Martineau &chan->conn_state)) { 53405b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 53415b155ef9SMat Martineau } else { 53425b155ef9SMat Martineau /* Logical link is up or moving to BR/EDR, 53435b155ef9SMat Martineau * proceed with move 53445b155ef9SMat Martineau */ 53455b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; 53465b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 53475b155ef9SMat Martineau } 53485b155ef9SMat Martineau break; 53495b155ef9SMat Martineau case L2CAP_MOVE_WAIT_RSP: 53505b155ef9SMat Martineau /* Moving to AMP */ 53515b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS) { 53525b155ef9SMat Martineau /* Remote is ready, send confirm immediately 53535b155ef9SMat Martineau * after logical link is ready 53545b155ef9SMat Martineau */ 53555b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 53565b155ef9SMat Martineau } else { 53575b155ef9SMat Martineau /* Both logical link and move success 53585b155ef9SMat Martineau * are required to confirm 53595b155ef9SMat Martineau */ 53605b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP; 53615b155ef9SMat Martineau } 53625b155ef9SMat Martineau 53635b155ef9SMat Martineau /* Placeholder - get hci_chan for logical link */ 53645b155ef9SMat Martineau if (!hchan) { 53655b155ef9SMat Martineau /* Logical link not available */ 53665b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 53675b155ef9SMat Martineau break; 53685b155ef9SMat Martineau } 53695b155ef9SMat Martineau 53705b155ef9SMat Martineau /* If the logical link is not yet connected, do not 53715b155ef9SMat Martineau * send confirmation. 53725b155ef9SMat Martineau */ 53735b155ef9SMat Martineau if (hchan->state != BT_CONNECTED) 53745b155ef9SMat Martineau break; 53755b155ef9SMat Martineau 53765b155ef9SMat Martineau /* Logical link is already ready to go */ 53775b155ef9SMat Martineau 53785b155ef9SMat Martineau chan->hs_hcon = hchan->conn; 53795b155ef9SMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 53805b155ef9SMat Martineau 53815b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS) { 53825b155ef9SMat Martineau /* Can confirm now */ 53835b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 53845b155ef9SMat Martineau } else { 53855b155ef9SMat Martineau /* Now only need move success 53865b155ef9SMat Martineau * to confirm 53875b155ef9SMat Martineau */ 53885b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 53895b155ef9SMat Martineau } 53905b155ef9SMat Martineau 53915b155ef9SMat Martineau l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); 53925b155ef9SMat Martineau break; 53935b155ef9SMat Martineau default: 53945b155ef9SMat Martineau /* Any other amp move state means the move failed. */ 53955b155ef9SMat Martineau chan->move_id = chan->local_amp_id; 53965b155ef9SMat Martineau l2cap_move_done(chan); 53975b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 53985b155ef9SMat Martineau } 53995b155ef9SMat Martineau 54005b155ef9SMat Martineau l2cap_chan_unlock(chan); 54015b155ef9SMat Martineau } 54025b155ef9SMat Martineau 54035b155ef9SMat Martineau static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid, 54045b155ef9SMat Martineau u16 result) 54055b155ef9SMat Martineau { 54065b155ef9SMat Martineau struct l2cap_chan *chan; 54075b155ef9SMat Martineau 54085b155ef9SMat Martineau chan = l2cap_get_chan_by_ident(conn, ident); 54095b155ef9SMat Martineau if (!chan) { 54105b155ef9SMat Martineau /* Could not locate channel, icid is best guess */ 54115b155ef9SMat Martineau l2cap_send_move_chan_cfm_icid(conn, icid); 54125b155ef9SMat Martineau return; 54135b155ef9SMat Martineau } 54145b155ef9SMat Martineau 54155b155ef9SMat Martineau __clear_chan_timer(chan); 54165b155ef9SMat Martineau 54175b155ef9SMat Martineau if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { 54185b155ef9SMat Martineau if (result == L2CAP_MR_COLLISION) { 54195b155ef9SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; 54205b155ef9SMat Martineau } else { 54215b155ef9SMat Martineau /* Cleanup - cancel move */ 54225b155ef9SMat Martineau chan->move_id = chan->local_amp_id; 54235b155ef9SMat Martineau l2cap_move_done(chan); 54245b155ef9SMat Martineau } 54255b155ef9SMat Martineau } 54265b155ef9SMat Martineau 54275b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 54285b155ef9SMat Martineau 54295b155ef9SMat Martineau l2cap_chan_unlock(chan); 54305b155ef9SMat Martineau } 54315b155ef9SMat Martineau 54325b155ef9SMat Martineau static int l2cap_move_channel_rsp(struct l2cap_conn *conn, 5433ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5434ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 54358d5a04a1SMat Martineau { 54368d5a04a1SMat Martineau struct l2cap_move_chan_rsp *rsp = data; 54378d5a04a1SMat Martineau u16 icid, result; 54388d5a04a1SMat Martineau 54398d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 54408d5a04a1SMat Martineau return -EPROTO; 54418d5a04a1SMat Martineau 54428d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 54438d5a04a1SMat Martineau result = le16_to_cpu(rsp->result); 54448d5a04a1SMat Martineau 5445ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 54468d5a04a1SMat Martineau 54475b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND) 54485b155ef9SMat Martineau l2cap_move_continue(conn, icid, result); 54495b155ef9SMat Martineau else 54505b155ef9SMat Martineau l2cap_move_fail(conn, cmd->ident, icid, result); 54518d5a04a1SMat Martineau 54528d5a04a1SMat Martineau return 0; 54538d5a04a1SMat Martineau } 54548d5a04a1SMat Martineau 54555f3847a4SMat Martineau static int l2cap_move_channel_confirm(struct l2cap_conn *conn, 5456ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5457ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 54588d5a04a1SMat Martineau { 54598d5a04a1SMat Martineau struct l2cap_move_chan_cfm *cfm = data; 54605f3847a4SMat Martineau struct l2cap_chan *chan; 54618d5a04a1SMat Martineau u16 icid, result; 54628d5a04a1SMat Martineau 54638d5a04a1SMat Martineau if (cmd_len != sizeof(*cfm)) 54648d5a04a1SMat Martineau return -EPROTO; 54658d5a04a1SMat Martineau 54668d5a04a1SMat Martineau icid = le16_to_cpu(cfm->icid); 54678d5a04a1SMat Martineau result = le16_to_cpu(cfm->result); 54688d5a04a1SMat Martineau 5469ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 54708d5a04a1SMat Martineau 54715f3847a4SMat Martineau chan = l2cap_get_chan_by_dcid(conn, icid); 54725f3847a4SMat Martineau if (!chan) { 54735f3847a4SMat Martineau /* Spec requires a response even if the icid was not found */ 54748d5a04a1SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 54755f3847a4SMat Martineau return 0; 54765f3847a4SMat Martineau } 54775f3847a4SMat Martineau 54785f3847a4SMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) { 54795f3847a4SMat Martineau if (result == L2CAP_MC_CONFIRMED) { 54805f3847a4SMat Martineau chan->local_amp_id = chan->move_id; 54816ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR) 54825f3847a4SMat Martineau __release_logical_link(chan); 54835f3847a4SMat Martineau } else { 54845f3847a4SMat Martineau chan->move_id = chan->local_amp_id; 54855f3847a4SMat Martineau } 54865f3847a4SMat Martineau 54875f3847a4SMat Martineau l2cap_move_done(chan); 54885f3847a4SMat Martineau } 54895f3847a4SMat Martineau 54905f3847a4SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 54915f3847a4SMat Martineau 54925f3847a4SMat Martineau l2cap_chan_unlock(chan); 54938d5a04a1SMat Martineau 54948d5a04a1SMat Martineau return 0; 54958d5a04a1SMat Martineau } 54968d5a04a1SMat Martineau 54978d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, 5498ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5499ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 55008d5a04a1SMat Martineau { 55018d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp *rsp = data; 55023fd71a0aSMat Martineau struct l2cap_chan *chan; 55038d5a04a1SMat Martineau u16 icid; 55048d5a04a1SMat Martineau 55058d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 55068d5a04a1SMat Martineau return -EPROTO; 55078d5a04a1SMat Martineau 55088d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 55098d5a04a1SMat Martineau 5510ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 55118d5a04a1SMat Martineau 55123fd71a0aSMat Martineau chan = l2cap_get_chan_by_scid(conn, icid); 55133fd71a0aSMat Martineau if (!chan) 55143fd71a0aSMat Martineau return 0; 55153fd71a0aSMat Martineau 55163fd71a0aSMat Martineau __clear_chan_timer(chan); 55173fd71a0aSMat Martineau 55183fd71a0aSMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) { 55193fd71a0aSMat Martineau chan->local_amp_id = chan->move_id; 55203fd71a0aSMat Martineau 55216ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan) 55223fd71a0aSMat Martineau __release_logical_link(chan); 55233fd71a0aSMat Martineau 55243fd71a0aSMat Martineau l2cap_move_done(chan); 55253fd71a0aSMat Martineau } 55263fd71a0aSMat Martineau 55273fd71a0aSMat Martineau l2cap_chan_unlock(chan); 55283fd71a0aSMat Martineau 55298d5a04a1SMat Martineau return 0; 55308d5a04a1SMat Martineau } 55318d5a04a1SMat Martineau 5532de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, 55332d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, 5534203e639eSJohan Hedberg u16 cmd_len, u8 *data) 5535de73115aSClaudio Takahasi { 5536de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon; 5537de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req; 5538de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp; 5539203e639eSJohan Hedberg u16 min, max, latency, to_multiplier; 55402ce603ebSClaudio Takahasi int err; 5541de73115aSClaudio Takahasi 554240bef302SJohan Hedberg if (hcon->role != HCI_ROLE_MASTER) 5543de73115aSClaudio Takahasi return -EINVAL; 5544de73115aSClaudio Takahasi 5545de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) 5546de73115aSClaudio Takahasi return -EPROTO; 5547de73115aSClaudio Takahasi 5548de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data; 5549de73115aSClaudio Takahasi min = __le16_to_cpu(req->min); 5550de73115aSClaudio Takahasi max = __le16_to_cpu(req->max); 5551de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency); 5552de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier); 5553de73115aSClaudio Takahasi 5554de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", 5555de73115aSClaudio Takahasi min, max, latency, to_multiplier); 5556de73115aSClaudio Takahasi 5557de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp)); 55582ce603ebSClaudio Takahasi 5559d4905f24SAndre Guedes err = hci_check_conn_params(min, max, latency, to_multiplier); 55602ce603ebSClaudio Takahasi if (err) 5561dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); 5562de73115aSClaudio Takahasi else 5563dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); 5564de73115aSClaudio Takahasi 5565de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, 5566de73115aSClaudio Takahasi sizeof(rsp), &rsp); 5567de73115aSClaudio Takahasi 5568ffb5a827SAndre Guedes if (!err) { 5569f4869e2aSJohan Hedberg u8 store_hint; 5570ffb5a827SAndre Guedes 5571f4869e2aSJohan Hedberg store_hint = hci_le_conn_update(hcon, min, max, latency, 5572f4869e2aSJohan Hedberg to_multiplier); 5573f4869e2aSJohan Hedberg mgmt_new_conn_param(hcon->hdev, &hcon->dst, hcon->dst_type, 5574f4869e2aSJohan Hedberg store_hint, min, max, latency, 5575f4869e2aSJohan Hedberg to_multiplier); 5576f4869e2aSJohan Hedberg 5577ffb5a827SAndre Guedes } 55782ce603ebSClaudio Takahasi 5579de73115aSClaudio Takahasi return 0; 5580de73115aSClaudio Takahasi } 5581de73115aSClaudio Takahasi 5582f1496deeSJohan Hedberg static int l2cap_le_connect_rsp(struct l2cap_conn *conn, 5583f1496deeSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5584f1496deeSJohan Hedberg u8 *data) 5585f1496deeSJohan Hedberg { 5586f1496deeSJohan Hedberg struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data; 55873e64b7bdSJohan Hedberg struct hci_conn *hcon = conn->hcon; 5588f1496deeSJohan Hedberg u16 dcid, mtu, mps, credits, result; 5589f1496deeSJohan Hedberg struct l2cap_chan *chan; 55903e64b7bdSJohan Hedberg int err, sec_level; 5591f1496deeSJohan Hedberg 5592f1496deeSJohan Hedberg if (cmd_len < sizeof(*rsp)) 5593f1496deeSJohan Hedberg return -EPROTO; 5594f1496deeSJohan Hedberg 5595f1496deeSJohan Hedberg dcid = __le16_to_cpu(rsp->dcid); 5596f1496deeSJohan Hedberg mtu = __le16_to_cpu(rsp->mtu); 5597f1496deeSJohan Hedberg mps = __le16_to_cpu(rsp->mps); 5598f1496deeSJohan Hedberg credits = __le16_to_cpu(rsp->credits); 5599f1496deeSJohan Hedberg result = __le16_to_cpu(rsp->result); 5600f1496deeSJohan Hedberg 5601571f7390SMallikarjun Phulari if (result == L2CAP_CR_LE_SUCCESS && (mtu < 23 || mps < 23 || 560240624183SJohan Hedberg dcid < L2CAP_CID_DYN_START || 560340624183SJohan Hedberg dcid > L2CAP_CID_LE_DYN_END)) 5604f1496deeSJohan Hedberg return -EPROTO; 5605f1496deeSJohan Hedberg 5606f1496deeSJohan Hedberg BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x", 5607f1496deeSJohan Hedberg dcid, mtu, mps, credits, result); 5608f1496deeSJohan Hedberg 5609f1496deeSJohan Hedberg mutex_lock(&conn->chan_lock); 5610f1496deeSJohan Hedberg 5611f1496deeSJohan Hedberg chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 5612f1496deeSJohan Hedberg if (!chan) { 5613f1496deeSJohan Hedberg err = -EBADSLT; 5614f1496deeSJohan Hedberg goto unlock; 5615f1496deeSJohan Hedberg } 5616f1496deeSJohan Hedberg 5617f1496deeSJohan Hedberg err = 0; 5618f1496deeSJohan Hedberg 5619f1496deeSJohan Hedberg l2cap_chan_lock(chan); 5620f1496deeSJohan Hedberg 5621f1496deeSJohan Hedberg switch (result) { 5622571f7390SMallikarjun Phulari case L2CAP_CR_LE_SUCCESS: 562340624183SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, dcid)) { 562440624183SJohan Hedberg err = -EBADSLT; 562540624183SJohan Hedberg break; 562640624183SJohan Hedberg } 562740624183SJohan Hedberg 5628f1496deeSJohan Hedberg chan->ident = 0; 5629f1496deeSJohan Hedberg chan->dcid = dcid; 5630f1496deeSJohan Hedberg chan->omtu = mtu; 5631f1496deeSJohan Hedberg chan->remote_mps = mps; 56320cd75f7eSJohan Hedberg chan->tx_credits = credits; 5633f1496deeSJohan Hedberg l2cap_chan_ready(chan); 5634f1496deeSJohan Hedberg break; 5635f1496deeSJohan Hedberg 5636571f7390SMallikarjun Phulari case L2CAP_CR_LE_AUTHENTICATION: 5637571f7390SMallikarjun Phulari case L2CAP_CR_LE_ENCRYPTION: 56383e64b7bdSJohan Hedberg /* If we already have MITM protection we can't do 56393e64b7bdSJohan Hedberg * anything. 56403e64b7bdSJohan Hedberg */ 56413e64b7bdSJohan Hedberg if (hcon->sec_level > BT_SECURITY_MEDIUM) { 56423e64b7bdSJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED); 56433e64b7bdSJohan Hedberg break; 56443e64b7bdSJohan Hedberg } 56453e64b7bdSJohan Hedberg 56463e64b7bdSJohan Hedberg sec_level = hcon->sec_level + 1; 56473e64b7bdSJohan Hedberg if (chan->sec_level < sec_level) 56483e64b7bdSJohan Hedberg chan->sec_level = sec_level; 56493e64b7bdSJohan Hedberg 56503e64b7bdSJohan Hedberg /* We'll need to send a new Connect Request */ 56513e64b7bdSJohan Hedberg clear_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags); 56523e64b7bdSJohan Hedberg 56533e64b7bdSJohan Hedberg smp_conn_security(hcon, chan->sec_level); 56543e64b7bdSJohan Hedberg break; 56553e64b7bdSJohan Hedberg 5656f1496deeSJohan Hedberg default: 5657f1496deeSJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED); 5658f1496deeSJohan Hedberg break; 5659f1496deeSJohan Hedberg } 5660f1496deeSJohan Hedberg 5661f1496deeSJohan Hedberg l2cap_chan_unlock(chan); 5662f1496deeSJohan Hedberg 5663f1496deeSJohan Hedberg unlock: 5664f1496deeSJohan Hedberg mutex_unlock(&conn->chan_lock); 5665f1496deeSJohan Hedberg 5666f1496deeSJohan Hedberg return err; 5667f1496deeSJohan Hedberg } 5668f1496deeSJohan Hedberg 56693300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, 56702d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len, 56712d792818SGustavo Padovan u8 *data) 56723300d9a9SClaudio Takahasi { 56733300d9a9SClaudio Takahasi int err = 0; 56743300d9a9SClaudio Takahasi 56753300d9a9SClaudio Takahasi switch (cmd->code) { 56763300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 5677cb3b3152SJohan Hedberg l2cap_command_rej(conn, cmd, cmd_len, data); 56783300d9a9SClaudio Takahasi break; 56793300d9a9SClaudio Takahasi 56803300d9a9SClaudio Takahasi case L2CAP_CONN_REQ: 5681cb3b3152SJohan Hedberg err = l2cap_connect_req(conn, cmd, cmd_len, data); 56823300d9a9SClaudio Takahasi break; 56833300d9a9SClaudio Takahasi 56843300d9a9SClaudio Takahasi case L2CAP_CONN_RSP: 5685f5a2598dSMat Martineau case L2CAP_CREATE_CHAN_RSP: 56869245e737SJohan Hedberg l2cap_connect_create_rsp(conn, cmd, cmd_len, data); 56873300d9a9SClaudio Takahasi break; 56883300d9a9SClaudio Takahasi 56893300d9a9SClaudio Takahasi case L2CAP_CONF_REQ: 56903300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data); 56913300d9a9SClaudio Takahasi break; 56923300d9a9SClaudio Takahasi 56933300d9a9SClaudio Takahasi case L2CAP_CONF_RSP: 56949245e737SJohan Hedberg l2cap_config_rsp(conn, cmd, cmd_len, data); 56953300d9a9SClaudio Takahasi break; 56963300d9a9SClaudio Takahasi 56973300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ: 5698cb3b3152SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data); 56993300d9a9SClaudio Takahasi break; 57003300d9a9SClaudio Takahasi 57013300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP: 57029245e737SJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data); 57033300d9a9SClaudio Takahasi break; 57043300d9a9SClaudio Takahasi 57053300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ: 57063300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data); 57073300d9a9SClaudio Takahasi break; 57083300d9a9SClaudio Takahasi 57093300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP: 57103300d9a9SClaudio Takahasi break; 57113300d9a9SClaudio Takahasi 57123300d9a9SClaudio Takahasi case L2CAP_INFO_REQ: 5713cb3b3152SJohan Hedberg err = l2cap_information_req(conn, cmd, cmd_len, data); 57143300d9a9SClaudio Takahasi break; 57153300d9a9SClaudio Takahasi 57163300d9a9SClaudio Takahasi case L2CAP_INFO_RSP: 57179245e737SJohan Hedberg l2cap_information_rsp(conn, cmd, cmd_len, data); 57183300d9a9SClaudio Takahasi break; 57193300d9a9SClaudio Takahasi 5720f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_REQ: 5721f94ff6ffSMat Martineau err = l2cap_create_channel_req(conn, cmd, cmd_len, data); 5722f94ff6ffSMat Martineau break; 5723f94ff6ffSMat Martineau 57248d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_REQ: 57258d5a04a1SMat Martineau err = l2cap_move_channel_req(conn, cmd, cmd_len, data); 57268d5a04a1SMat Martineau break; 57278d5a04a1SMat Martineau 57288d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_RSP: 57299245e737SJohan Hedberg l2cap_move_channel_rsp(conn, cmd, cmd_len, data); 57308d5a04a1SMat Martineau break; 57318d5a04a1SMat Martineau 57328d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM: 57338d5a04a1SMat Martineau err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data); 57348d5a04a1SMat Martineau break; 57358d5a04a1SMat Martineau 57368d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM_RSP: 57379245e737SJohan Hedberg l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data); 57388d5a04a1SMat Martineau break; 57398d5a04a1SMat Martineau 57403300d9a9SClaudio Takahasi default: 57413300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code); 57423300d9a9SClaudio Takahasi err = -EINVAL; 57433300d9a9SClaudio Takahasi break; 57443300d9a9SClaudio Takahasi } 57453300d9a9SClaudio Takahasi 57463300d9a9SClaudio Takahasi return err; 57473300d9a9SClaudio Takahasi } 57483300d9a9SClaudio Takahasi 574927e2d4c8SJohan Hedberg static int l2cap_le_connect_req(struct l2cap_conn *conn, 575027e2d4c8SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 575127e2d4c8SJohan Hedberg u8 *data) 575227e2d4c8SJohan Hedberg { 575327e2d4c8SJohan Hedberg struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data; 575427e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 575527e2d4c8SJohan Hedberg struct l2cap_chan *chan, *pchan; 57560cd75f7eSJohan Hedberg u16 dcid, scid, credits, mtu, mps; 575727e2d4c8SJohan Hedberg __le16 psm; 575827e2d4c8SJohan Hedberg u8 result; 575927e2d4c8SJohan Hedberg 576027e2d4c8SJohan Hedberg if (cmd_len != sizeof(*req)) 576127e2d4c8SJohan Hedberg return -EPROTO; 576227e2d4c8SJohan Hedberg 576327e2d4c8SJohan Hedberg scid = __le16_to_cpu(req->scid); 576427e2d4c8SJohan Hedberg mtu = __le16_to_cpu(req->mtu); 576527e2d4c8SJohan Hedberg mps = __le16_to_cpu(req->mps); 576627e2d4c8SJohan Hedberg psm = req->psm; 576727e2d4c8SJohan Hedberg dcid = 0; 57680cd75f7eSJohan Hedberg credits = 0; 576927e2d4c8SJohan Hedberg 577027e2d4c8SJohan Hedberg if (mtu < 23 || mps < 23) 577127e2d4c8SJohan Hedberg return -EPROTO; 577227e2d4c8SJohan Hedberg 577327e2d4c8SJohan Hedberg BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm), 577427e2d4c8SJohan Hedberg scid, mtu, mps); 577527e2d4c8SJohan Hedberg 577627e2d4c8SJohan Hedberg /* Check if we have socket listening on psm */ 577727e2d4c8SJohan Hedberg pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 577827e2d4c8SJohan Hedberg &conn->hcon->dst, LE_LINK); 577927e2d4c8SJohan Hedberg if (!pchan) { 5780571f7390SMallikarjun Phulari result = L2CAP_CR_LE_BAD_PSM; 578127e2d4c8SJohan Hedberg chan = NULL; 578227e2d4c8SJohan Hedberg goto response; 578327e2d4c8SJohan Hedberg } 578427e2d4c8SJohan Hedberg 578527e2d4c8SJohan Hedberg mutex_lock(&conn->chan_lock); 578627e2d4c8SJohan Hedberg l2cap_chan_lock(pchan); 578727e2d4c8SJohan Hedberg 578835dc6f83SJohan Hedberg if (!smp_sufficient_security(conn->hcon, pchan->sec_level, 578935dc6f83SJohan Hedberg SMP_ALLOW_STK)) { 5790571f7390SMallikarjun Phulari result = L2CAP_CR_LE_AUTHENTICATION; 579127e2d4c8SJohan Hedberg chan = NULL; 579227e2d4c8SJohan Hedberg goto response_unlock; 579327e2d4c8SJohan Hedberg } 579427e2d4c8SJohan Hedberg 57958a7889ccSJohan Hedberg /* Check for valid dynamic CID range */ 57968a7889ccSJohan Hedberg if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) { 5797571f7390SMallikarjun Phulari result = L2CAP_CR_LE_INVALID_SCID; 57988a7889ccSJohan Hedberg chan = NULL; 57998a7889ccSJohan Hedberg goto response_unlock; 58008a7889ccSJohan Hedberg } 58018a7889ccSJohan Hedberg 580227e2d4c8SJohan Hedberg /* Check if we already have channel with that dcid */ 580327e2d4c8SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, scid)) { 5804571f7390SMallikarjun Phulari result = L2CAP_CR_LE_SCID_IN_USE; 580527e2d4c8SJohan Hedberg chan = NULL; 580627e2d4c8SJohan Hedberg goto response_unlock; 580727e2d4c8SJohan Hedberg } 580827e2d4c8SJohan Hedberg 580927e2d4c8SJohan Hedberg chan = pchan->ops->new_connection(pchan); 581027e2d4c8SJohan Hedberg if (!chan) { 5811571f7390SMallikarjun Phulari result = L2CAP_CR_LE_NO_MEM; 581227e2d4c8SJohan Hedberg goto response_unlock; 581327e2d4c8SJohan Hedberg } 581427e2d4c8SJohan Hedberg 581527e2d4c8SJohan Hedberg bacpy(&chan->src, &conn->hcon->src); 581627e2d4c8SJohan Hedberg bacpy(&chan->dst, &conn->hcon->dst); 5817a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(conn->hcon); 5818a250e048SJohan Hedberg chan->dst_type = bdaddr_dst_type(conn->hcon); 581927e2d4c8SJohan Hedberg chan->psm = psm; 582027e2d4c8SJohan Hedberg chan->dcid = scid; 582127e2d4c8SJohan Hedberg chan->omtu = mtu; 582227e2d4c8SJohan Hedberg chan->remote_mps = mps; 582327e2d4c8SJohan Hedberg 582427e2d4c8SJohan Hedberg __l2cap_chan_add(conn, chan); 5825fe149310SLuiz Augusto von Dentz 5826ba8f5289SLuiz Augusto von Dentz l2cap_le_flowctl_init(chan, __le16_to_cpu(req->credits)); 5827fe149310SLuiz Augusto von Dentz 582827e2d4c8SJohan Hedberg dcid = chan->scid; 58290cd75f7eSJohan Hedberg credits = chan->rx_credits; 583027e2d4c8SJohan Hedberg 583127e2d4c8SJohan Hedberg __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 583227e2d4c8SJohan Hedberg 583327e2d4c8SJohan Hedberg chan->ident = cmd->ident; 583427e2d4c8SJohan Hedberg 583527e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 583627e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_CONNECT2); 5837434714dcSJohan Hedberg /* The following result value is actually not defined 5838434714dcSJohan Hedberg * for LE CoC but we use it to let the function know 5839434714dcSJohan Hedberg * that it should bail out after doing its cleanup 5840434714dcSJohan Hedberg * instead of sending a response. 5841434714dcSJohan Hedberg */ 584227e2d4c8SJohan Hedberg result = L2CAP_CR_PEND; 584327e2d4c8SJohan Hedberg chan->ops->defer(chan); 584427e2d4c8SJohan Hedberg } else { 584527e2d4c8SJohan Hedberg l2cap_chan_ready(chan); 5846571f7390SMallikarjun Phulari result = L2CAP_CR_LE_SUCCESS; 584727e2d4c8SJohan Hedberg } 584827e2d4c8SJohan Hedberg 584927e2d4c8SJohan Hedberg response_unlock: 585027e2d4c8SJohan Hedberg l2cap_chan_unlock(pchan); 585127e2d4c8SJohan Hedberg mutex_unlock(&conn->chan_lock); 5852a24cce14SJohan Hedberg l2cap_chan_put(pchan); 585327e2d4c8SJohan Hedberg 585427e2d4c8SJohan Hedberg if (result == L2CAP_CR_PEND) 585527e2d4c8SJohan Hedberg return 0; 585627e2d4c8SJohan Hedberg 585727e2d4c8SJohan Hedberg response: 585827e2d4c8SJohan Hedberg if (chan) { 585927e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 58603916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps); 586127e2d4c8SJohan Hedberg } else { 586227e2d4c8SJohan Hedberg rsp.mtu = 0; 586327e2d4c8SJohan Hedberg rsp.mps = 0; 586427e2d4c8SJohan Hedberg } 586527e2d4c8SJohan Hedberg 586627e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(dcid); 58670cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(credits); 586827e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result); 586927e2d4c8SJohan Hedberg 587027e2d4c8SJohan Hedberg l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp); 587127e2d4c8SJohan Hedberg 587227e2d4c8SJohan Hedberg return 0; 587327e2d4c8SJohan Hedberg } 587427e2d4c8SJohan Hedberg 5875fad5fc89SJohan Hedberg static inline int l2cap_le_credits(struct l2cap_conn *conn, 5876fad5fc89SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5877fad5fc89SJohan Hedberg u8 *data) 5878fad5fc89SJohan Hedberg { 5879fad5fc89SJohan Hedberg struct l2cap_le_credits *pkt; 5880fad5fc89SJohan Hedberg struct l2cap_chan *chan; 58810f1bfe4eSJohan Hedberg u16 cid, credits, max_credits; 5882fad5fc89SJohan Hedberg 5883fad5fc89SJohan Hedberg if (cmd_len != sizeof(*pkt)) 5884fad5fc89SJohan Hedberg return -EPROTO; 5885fad5fc89SJohan Hedberg 5886fad5fc89SJohan Hedberg pkt = (struct l2cap_le_credits *) data; 5887fad5fc89SJohan Hedberg cid = __le16_to_cpu(pkt->cid); 5888fad5fc89SJohan Hedberg credits = __le16_to_cpu(pkt->credits); 5889fad5fc89SJohan Hedberg 5890fad5fc89SJohan Hedberg BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits); 5891fad5fc89SJohan Hedberg 5892fad5fc89SJohan Hedberg chan = l2cap_get_chan_by_dcid(conn, cid); 5893fad5fc89SJohan Hedberg if (!chan) 5894fad5fc89SJohan Hedberg return -EBADSLT; 5895fad5fc89SJohan Hedberg 58960f1bfe4eSJohan Hedberg max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits; 58970f1bfe4eSJohan Hedberg if (credits > max_credits) { 58980f1bfe4eSJohan Hedberg BT_ERR("LE credits overflow"); 58990f1bfe4eSJohan Hedberg l2cap_send_disconn_req(chan, ECONNRESET); 5900ee93053dSMartin Townsend l2cap_chan_unlock(chan); 59010f1bfe4eSJohan Hedberg 59020f1bfe4eSJohan Hedberg /* Return 0 so that we don't trigger an unnecessary 59030f1bfe4eSJohan Hedberg * command reject packet. 59040f1bfe4eSJohan Hedberg */ 59050f1bfe4eSJohan Hedberg return 0; 59060f1bfe4eSJohan Hedberg } 59070f1bfe4eSJohan Hedberg 5908fad5fc89SJohan Hedberg chan->tx_credits += credits; 5909fad5fc89SJohan Hedberg 59108a505b7fSLuiz Augusto von Dentz /* Resume sending */ 59118a505b7fSLuiz Augusto von Dentz l2cap_le_flowctl_send(chan); 5912fad5fc89SJohan Hedberg 5913fad5fc89SJohan Hedberg if (chan->tx_credits) 5914fad5fc89SJohan Hedberg chan->ops->resume(chan); 5915fad5fc89SJohan Hedberg 5916fad5fc89SJohan Hedberg l2cap_chan_unlock(chan); 5917fad5fc89SJohan Hedberg 5918fad5fc89SJohan Hedberg return 0; 5919fad5fc89SJohan Hedberg } 5920fad5fc89SJohan Hedberg 592115f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn, 592215f02b91SLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd, u16 cmd_len, 592315f02b91SLuiz Augusto von Dentz u8 *data) 592415f02b91SLuiz Augusto von Dentz { 592515f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_req *req = (void *) data; 592615f02b91SLuiz Augusto von Dentz struct { 592715f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp rsp; 59287cf3b1ddSLuiz Augusto von Dentz __le16 dcid[L2CAP_ECRED_MAX_CID]; 592915f02b91SLuiz Augusto von Dentz } __packed pdu; 593015f02b91SLuiz Augusto von Dentz struct l2cap_chan *chan, *pchan; 5931965995b7SYueHaibing u16 mtu, mps; 593215f02b91SLuiz Augusto von Dentz __le16 psm; 593315f02b91SLuiz Augusto von Dentz u8 result, len = 0; 593415f02b91SLuiz Augusto von Dentz int i, num_scid; 593515f02b91SLuiz Augusto von Dentz bool defer = false; 593615f02b91SLuiz Augusto von Dentz 59374be5ca67SLuiz Augusto von Dentz if (!enable_ecred) 59384be5ca67SLuiz Augusto von Dentz return -EINVAL; 59394be5ca67SLuiz Augusto von Dentz 594069d67b46SKonstantin Forostyan if (cmd_len < sizeof(*req) || (cmd_len - sizeof(*req)) % sizeof(u16)) { 594115f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_INVALID_PARAMS; 594215f02b91SLuiz Augusto von Dentz goto response; 594315f02b91SLuiz Augusto von Dentz } 594415f02b91SLuiz Augusto von Dentz 59457cf3b1ddSLuiz Augusto von Dentz cmd_len -= sizeof(*req); 59467cf3b1ddSLuiz Augusto von Dentz num_scid = cmd_len / sizeof(u16); 59477cf3b1ddSLuiz Augusto von Dentz 59487cf3b1ddSLuiz Augusto von Dentz if (num_scid > ARRAY_SIZE(pdu.dcid)) { 59497cf3b1ddSLuiz Augusto von Dentz result = L2CAP_CR_LE_INVALID_PARAMS; 59507cf3b1ddSLuiz Augusto von Dentz goto response; 59517cf3b1ddSLuiz Augusto von Dentz } 59527cf3b1ddSLuiz Augusto von Dentz 595315f02b91SLuiz Augusto von Dentz mtu = __le16_to_cpu(req->mtu); 595415f02b91SLuiz Augusto von Dentz mps = __le16_to_cpu(req->mps); 595515f02b91SLuiz Augusto von Dentz 595615f02b91SLuiz Augusto von Dentz if (mtu < L2CAP_ECRED_MIN_MTU || mps < L2CAP_ECRED_MIN_MPS) { 595715f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_UNACCEPT_PARAMS; 595815f02b91SLuiz Augusto von Dentz goto response; 595915f02b91SLuiz Augusto von Dentz } 596015f02b91SLuiz Augusto von Dentz 596115f02b91SLuiz Augusto von Dentz psm = req->psm; 596215f02b91SLuiz Augusto von Dentz 596315f02b91SLuiz Augusto von Dentz BT_DBG("psm 0x%2.2x mtu %u mps %u", __le16_to_cpu(psm), mtu, mps); 596415f02b91SLuiz Augusto von Dentz 596515f02b91SLuiz Augusto von Dentz memset(&pdu, 0, sizeof(pdu)); 596615f02b91SLuiz Augusto von Dentz 596715f02b91SLuiz Augusto von Dentz /* Check if we have socket listening on psm */ 596815f02b91SLuiz Augusto von Dentz pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 596915f02b91SLuiz Augusto von Dentz &conn->hcon->dst, LE_LINK); 597015f02b91SLuiz Augusto von Dentz if (!pchan) { 597115f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_BAD_PSM; 597215f02b91SLuiz Augusto von Dentz goto response; 597315f02b91SLuiz Augusto von Dentz } 597415f02b91SLuiz Augusto von Dentz 597515f02b91SLuiz Augusto von Dentz mutex_lock(&conn->chan_lock); 597615f02b91SLuiz Augusto von Dentz l2cap_chan_lock(pchan); 597715f02b91SLuiz Augusto von Dentz 597815f02b91SLuiz Augusto von Dentz if (!smp_sufficient_security(conn->hcon, pchan->sec_level, 597915f02b91SLuiz Augusto von Dentz SMP_ALLOW_STK)) { 598015f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_AUTHENTICATION; 598115f02b91SLuiz Augusto von Dentz goto unlock; 598215f02b91SLuiz Augusto von Dentz } 598315f02b91SLuiz Augusto von Dentz 598415f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_SUCCESS; 598515f02b91SLuiz Augusto von Dentz 598615f02b91SLuiz Augusto von Dentz for (i = 0; i < num_scid; i++) { 598715f02b91SLuiz Augusto von Dentz u16 scid = __le16_to_cpu(req->scid[i]); 598815f02b91SLuiz Augusto von Dentz 598915f02b91SLuiz Augusto von Dentz BT_DBG("scid[%d] 0x%4.4x", i, scid); 599015f02b91SLuiz Augusto von Dentz 599115f02b91SLuiz Augusto von Dentz pdu.dcid[i] = 0x0000; 599215f02b91SLuiz Augusto von Dentz len += sizeof(*pdu.dcid); 599315f02b91SLuiz Augusto von Dentz 599415f02b91SLuiz Augusto von Dentz /* Check for valid dynamic CID range */ 599515f02b91SLuiz Augusto von Dentz if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) { 599615f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_INVALID_SCID; 599715f02b91SLuiz Augusto von Dentz continue; 599815f02b91SLuiz Augusto von Dentz } 599915f02b91SLuiz Augusto von Dentz 600015f02b91SLuiz Augusto von Dentz /* Check if we already have channel with that dcid */ 600115f02b91SLuiz Augusto von Dentz if (__l2cap_get_chan_by_dcid(conn, scid)) { 600215f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_SCID_IN_USE; 600315f02b91SLuiz Augusto von Dentz continue; 600415f02b91SLuiz Augusto von Dentz } 600515f02b91SLuiz Augusto von Dentz 600615f02b91SLuiz Augusto von Dentz chan = pchan->ops->new_connection(pchan); 600715f02b91SLuiz Augusto von Dentz if (!chan) { 600815f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_NO_MEM; 600915f02b91SLuiz Augusto von Dentz continue; 601015f02b91SLuiz Augusto von Dentz } 601115f02b91SLuiz Augusto von Dentz 601215f02b91SLuiz Augusto von Dentz bacpy(&chan->src, &conn->hcon->src); 601315f02b91SLuiz Augusto von Dentz bacpy(&chan->dst, &conn->hcon->dst); 601415f02b91SLuiz Augusto von Dentz chan->src_type = bdaddr_src_type(conn->hcon); 601515f02b91SLuiz Augusto von Dentz chan->dst_type = bdaddr_dst_type(conn->hcon); 601615f02b91SLuiz Augusto von Dentz chan->psm = psm; 601715f02b91SLuiz Augusto von Dentz chan->dcid = scid; 601815f02b91SLuiz Augusto von Dentz chan->omtu = mtu; 601915f02b91SLuiz Augusto von Dentz chan->remote_mps = mps; 602015f02b91SLuiz Augusto von Dentz 602115f02b91SLuiz Augusto von Dentz __l2cap_chan_add(conn, chan); 602215f02b91SLuiz Augusto von Dentz 602315f02b91SLuiz Augusto von Dentz l2cap_ecred_init(chan, __le16_to_cpu(req->credits)); 602415f02b91SLuiz Augusto von Dentz 602515f02b91SLuiz Augusto von Dentz /* Init response */ 602615f02b91SLuiz Augusto von Dentz if (!pdu.rsp.credits) { 602715f02b91SLuiz Augusto von Dentz pdu.rsp.mtu = cpu_to_le16(chan->imtu); 602815f02b91SLuiz Augusto von Dentz pdu.rsp.mps = cpu_to_le16(chan->mps); 602915f02b91SLuiz Augusto von Dentz pdu.rsp.credits = cpu_to_le16(chan->rx_credits); 603015f02b91SLuiz Augusto von Dentz } 603115f02b91SLuiz Augusto von Dentz 603215f02b91SLuiz Augusto von Dentz pdu.dcid[i] = cpu_to_le16(chan->scid); 603315f02b91SLuiz Augusto von Dentz 603415f02b91SLuiz Augusto von Dentz __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 603515f02b91SLuiz Augusto von Dentz 603615f02b91SLuiz Augusto von Dentz chan->ident = cmd->ident; 603715f02b91SLuiz Augusto von Dentz 603815f02b91SLuiz Augusto von Dentz if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 603915f02b91SLuiz Augusto von Dentz l2cap_state_change(chan, BT_CONNECT2); 604015f02b91SLuiz Augusto von Dentz defer = true; 604115f02b91SLuiz Augusto von Dentz chan->ops->defer(chan); 604215f02b91SLuiz Augusto von Dentz } else { 604315f02b91SLuiz Augusto von Dentz l2cap_chan_ready(chan); 604415f02b91SLuiz Augusto von Dentz } 604515f02b91SLuiz Augusto von Dentz } 604615f02b91SLuiz Augusto von Dentz 604715f02b91SLuiz Augusto von Dentz unlock: 604815f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(pchan); 604915f02b91SLuiz Augusto von Dentz mutex_unlock(&conn->chan_lock); 605015f02b91SLuiz Augusto von Dentz l2cap_chan_put(pchan); 605115f02b91SLuiz Augusto von Dentz 605215f02b91SLuiz Augusto von Dentz response: 605315f02b91SLuiz Augusto von Dentz pdu.rsp.result = cpu_to_le16(result); 605415f02b91SLuiz Augusto von Dentz 605515f02b91SLuiz Augusto von Dentz if (defer) 605615f02b91SLuiz Augusto von Dentz return 0; 605715f02b91SLuiz Augusto von Dentz 605815f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, cmd->ident, L2CAP_ECRED_CONN_RSP, 605915f02b91SLuiz Augusto von Dentz sizeof(pdu.rsp) + len, &pdu); 606015f02b91SLuiz Augusto von Dentz 606115f02b91SLuiz Augusto von Dentz return 0; 606215f02b91SLuiz Augusto von Dentz } 606315f02b91SLuiz Augusto von Dentz 606415f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn, 606515f02b91SLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd, u16 cmd_len, 606615f02b91SLuiz Augusto von Dentz u8 *data) 606715f02b91SLuiz Augusto von Dentz { 606815f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp *rsp = (void *) data; 606915f02b91SLuiz Augusto von Dentz struct hci_conn *hcon = conn->hcon; 607015f02b91SLuiz Augusto von Dentz u16 mtu, mps, credits, result; 607115f02b91SLuiz Augusto von Dentz struct l2cap_chan *chan; 607215f02b91SLuiz Augusto von Dentz int err = 0, sec_level; 607315f02b91SLuiz Augusto von Dentz int i = 0; 607415f02b91SLuiz Augusto von Dentz 607515f02b91SLuiz Augusto von Dentz if (cmd_len < sizeof(*rsp)) 607615f02b91SLuiz Augusto von Dentz return -EPROTO; 607715f02b91SLuiz Augusto von Dentz 607815f02b91SLuiz Augusto von Dentz mtu = __le16_to_cpu(rsp->mtu); 607915f02b91SLuiz Augusto von Dentz mps = __le16_to_cpu(rsp->mps); 608015f02b91SLuiz Augusto von Dentz credits = __le16_to_cpu(rsp->credits); 608115f02b91SLuiz Augusto von Dentz result = __le16_to_cpu(rsp->result); 608215f02b91SLuiz Augusto von Dentz 608315f02b91SLuiz Augusto von Dentz BT_DBG("mtu %u mps %u credits %u result 0x%4.4x", mtu, mps, credits, 608415f02b91SLuiz Augusto von Dentz result); 608515f02b91SLuiz Augusto von Dentz 608615f02b91SLuiz Augusto von Dentz mutex_lock(&conn->chan_lock); 608715f02b91SLuiz Augusto von Dentz 608815f02b91SLuiz Augusto von Dentz cmd_len -= sizeof(*rsp); 608915f02b91SLuiz Augusto von Dentz 609015f02b91SLuiz Augusto von Dentz list_for_each_entry(chan, &conn->chan_l, list) { 609115f02b91SLuiz Augusto von Dentz u16 dcid; 609215f02b91SLuiz Augusto von Dentz 609315f02b91SLuiz Augusto von Dentz if (chan->ident != cmd->ident || 609415f02b91SLuiz Augusto von Dentz chan->mode != L2CAP_MODE_EXT_FLOWCTL || 609515f02b91SLuiz Augusto von Dentz chan->state == BT_CONNECTED) 609615f02b91SLuiz Augusto von Dentz continue; 609715f02b91SLuiz Augusto von Dentz 609815f02b91SLuiz Augusto von Dentz l2cap_chan_lock(chan); 609915f02b91SLuiz Augusto von Dentz 610015f02b91SLuiz Augusto von Dentz /* Check that there is a dcid for each pending channel */ 610115f02b91SLuiz Augusto von Dentz if (cmd_len < sizeof(dcid)) { 610215f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED); 610315f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(chan); 610415f02b91SLuiz Augusto von Dentz continue; 610515f02b91SLuiz Augusto von Dentz } 610615f02b91SLuiz Augusto von Dentz 610715f02b91SLuiz Augusto von Dentz dcid = __le16_to_cpu(rsp->dcid[i++]); 610815f02b91SLuiz Augusto von Dentz cmd_len -= sizeof(u16); 610915f02b91SLuiz Augusto von Dentz 611015f02b91SLuiz Augusto von Dentz BT_DBG("dcid[%d] 0x%4.4x", i, dcid); 611115f02b91SLuiz Augusto von Dentz 611215f02b91SLuiz Augusto von Dentz /* Check if dcid is already in use */ 611315f02b91SLuiz Augusto von Dentz if (dcid && __l2cap_get_chan_by_dcid(conn, dcid)) { 611415f02b91SLuiz Augusto von Dentz /* If a device receives a 611515f02b91SLuiz Augusto von Dentz * L2CAP_CREDIT_BASED_CONNECTION_RSP packet with an 611615f02b91SLuiz Augusto von Dentz * already-assigned Destination CID, then both the 611715f02b91SLuiz Augusto von Dentz * original channel and the new channel shall be 611815f02b91SLuiz Augusto von Dentz * immediately discarded and not used. 611915f02b91SLuiz Augusto von Dentz */ 612015f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED); 612115f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(chan); 612215f02b91SLuiz Augusto von Dentz chan = __l2cap_get_chan_by_dcid(conn, dcid); 612315f02b91SLuiz Augusto von Dentz l2cap_chan_lock(chan); 612415f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNRESET); 612515f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(chan); 612615f02b91SLuiz Augusto von Dentz continue; 612715f02b91SLuiz Augusto von Dentz } 612815f02b91SLuiz Augusto von Dentz 612915f02b91SLuiz Augusto von Dentz switch (result) { 613015f02b91SLuiz Augusto von Dentz case L2CAP_CR_LE_AUTHENTICATION: 613115f02b91SLuiz Augusto von Dentz case L2CAP_CR_LE_ENCRYPTION: 613215f02b91SLuiz Augusto von Dentz /* If we already have MITM protection we can't do 613315f02b91SLuiz Augusto von Dentz * anything. 613415f02b91SLuiz Augusto von Dentz */ 613515f02b91SLuiz Augusto von Dentz if (hcon->sec_level > BT_SECURITY_MEDIUM) { 613615f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED); 613715f02b91SLuiz Augusto von Dentz break; 613815f02b91SLuiz Augusto von Dentz } 613915f02b91SLuiz Augusto von Dentz 614015f02b91SLuiz Augusto von Dentz sec_level = hcon->sec_level + 1; 614115f02b91SLuiz Augusto von Dentz if (chan->sec_level < sec_level) 614215f02b91SLuiz Augusto von Dentz chan->sec_level = sec_level; 614315f02b91SLuiz Augusto von Dentz 614415f02b91SLuiz Augusto von Dentz /* We'll need to send a new Connect Request */ 614515f02b91SLuiz Augusto von Dentz clear_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags); 614615f02b91SLuiz Augusto von Dentz 614715f02b91SLuiz Augusto von Dentz smp_conn_security(hcon, chan->sec_level); 614815f02b91SLuiz Augusto von Dentz break; 614915f02b91SLuiz Augusto von Dentz 615015f02b91SLuiz Augusto von Dentz case L2CAP_CR_LE_BAD_PSM: 615115f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED); 615215f02b91SLuiz Augusto von Dentz break; 615315f02b91SLuiz Augusto von Dentz 615415f02b91SLuiz Augusto von Dentz default: 615515f02b91SLuiz Augusto von Dentz /* If dcid was not set it means channels was refused */ 615615f02b91SLuiz Augusto von Dentz if (!dcid) { 615715f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNREFUSED); 615815f02b91SLuiz Augusto von Dentz break; 615915f02b91SLuiz Augusto von Dentz } 616015f02b91SLuiz Augusto von Dentz 616115f02b91SLuiz Augusto von Dentz chan->ident = 0; 616215f02b91SLuiz Augusto von Dentz chan->dcid = dcid; 616315f02b91SLuiz Augusto von Dentz chan->omtu = mtu; 616415f02b91SLuiz Augusto von Dentz chan->remote_mps = mps; 616515f02b91SLuiz Augusto von Dentz chan->tx_credits = credits; 616615f02b91SLuiz Augusto von Dentz l2cap_chan_ready(chan); 616715f02b91SLuiz Augusto von Dentz break; 616815f02b91SLuiz Augusto von Dentz } 616915f02b91SLuiz Augusto von Dentz 617015f02b91SLuiz Augusto von Dentz l2cap_chan_unlock(chan); 617115f02b91SLuiz Augusto von Dentz } 617215f02b91SLuiz Augusto von Dentz 617315f02b91SLuiz Augusto von Dentz mutex_unlock(&conn->chan_lock); 617415f02b91SLuiz Augusto von Dentz 617515f02b91SLuiz Augusto von Dentz return err; 617615f02b91SLuiz Augusto von Dentz } 617715f02b91SLuiz Augusto von Dentz 617815f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_reconf_req(struct l2cap_conn *conn, 617915f02b91SLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd, u16 cmd_len, 618015f02b91SLuiz Augusto von Dentz u8 *data) 618115f02b91SLuiz Augusto von Dentz { 618215f02b91SLuiz Augusto von Dentz struct l2cap_ecred_reconf_req *req = (void *) data; 618315f02b91SLuiz Augusto von Dentz struct l2cap_ecred_reconf_rsp rsp; 618415f02b91SLuiz Augusto von Dentz u16 mtu, mps, result; 618515f02b91SLuiz Augusto von Dentz struct l2cap_chan *chan; 618615f02b91SLuiz Augusto von Dentz int i, num_scid; 618715f02b91SLuiz Augusto von Dentz 61884be5ca67SLuiz Augusto von Dentz if (!enable_ecred) 61894be5ca67SLuiz Augusto von Dentz return -EINVAL; 61904be5ca67SLuiz Augusto von Dentz 619115f02b91SLuiz Augusto von Dentz if (cmd_len < sizeof(*req) || cmd_len - sizeof(*req) % sizeof(u16)) { 619215f02b91SLuiz Augusto von Dentz result = L2CAP_CR_LE_INVALID_PARAMS; 619315f02b91SLuiz Augusto von Dentz goto respond; 619415f02b91SLuiz Augusto von Dentz } 619515f02b91SLuiz Augusto von Dentz 619615f02b91SLuiz Augusto von Dentz mtu = __le16_to_cpu(req->mtu); 619715f02b91SLuiz Augusto von Dentz mps = __le16_to_cpu(req->mps); 619815f02b91SLuiz Augusto von Dentz 619915f02b91SLuiz Augusto von Dentz BT_DBG("mtu %u mps %u", mtu, mps); 620015f02b91SLuiz Augusto von Dentz 620115f02b91SLuiz Augusto von Dentz if (mtu < L2CAP_ECRED_MIN_MTU) { 620215f02b91SLuiz Augusto von Dentz result = L2CAP_RECONF_INVALID_MTU; 620315f02b91SLuiz Augusto von Dentz goto respond; 620415f02b91SLuiz Augusto von Dentz } 620515f02b91SLuiz Augusto von Dentz 620615f02b91SLuiz Augusto von Dentz if (mps < L2CAP_ECRED_MIN_MPS) { 620715f02b91SLuiz Augusto von Dentz result = L2CAP_RECONF_INVALID_MPS; 620815f02b91SLuiz Augusto von Dentz goto respond; 620915f02b91SLuiz Augusto von Dentz } 621015f02b91SLuiz Augusto von Dentz 621115f02b91SLuiz Augusto von Dentz cmd_len -= sizeof(*req); 621215f02b91SLuiz Augusto von Dentz num_scid = cmd_len / sizeof(u16); 621315f02b91SLuiz Augusto von Dentz result = L2CAP_RECONF_SUCCESS; 621415f02b91SLuiz Augusto von Dentz 621515f02b91SLuiz Augusto von Dentz for (i = 0; i < num_scid; i++) { 621615f02b91SLuiz Augusto von Dentz u16 scid; 621715f02b91SLuiz Augusto von Dentz 621815f02b91SLuiz Augusto von Dentz scid = __le16_to_cpu(req->scid[i]); 621915f02b91SLuiz Augusto von Dentz if (!scid) 622015f02b91SLuiz Augusto von Dentz return -EPROTO; 622115f02b91SLuiz Augusto von Dentz 622215f02b91SLuiz Augusto von Dentz chan = __l2cap_get_chan_by_dcid(conn, scid); 622315f02b91SLuiz Augusto von Dentz if (!chan) 622415f02b91SLuiz Augusto von Dentz continue; 622515f02b91SLuiz Augusto von Dentz 622615f02b91SLuiz Augusto von Dentz /* If the MTU value is decreased for any of the included 622715f02b91SLuiz Augusto von Dentz * channels, then the receiver shall disconnect all 622815f02b91SLuiz Augusto von Dentz * included channels. 622915f02b91SLuiz Augusto von Dentz */ 623015f02b91SLuiz Augusto von Dentz if (chan->omtu > mtu) { 623115f02b91SLuiz Augusto von Dentz BT_ERR("chan %p decreased MTU %u -> %u", chan, 623215f02b91SLuiz Augusto von Dentz chan->omtu, mtu); 623315f02b91SLuiz Augusto von Dentz result = L2CAP_RECONF_INVALID_MTU; 623415f02b91SLuiz Augusto von Dentz } 623515f02b91SLuiz Augusto von Dentz 623615f02b91SLuiz Augusto von Dentz chan->omtu = mtu; 623715f02b91SLuiz Augusto von Dentz chan->remote_mps = mps; 623815f02b91SLuiz Augusto von Dentz } 623915f02b91SLuiz Augusto von Dentz 624015f02b91SLuiz Augusto von Dentz respond: 624115f02b91SLuiz Augusto von Dentz rsp.result = cpu_to_le16(result); 624215f02b91SLuiz Augusto von Dentz 624315f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, cmd->ident, L2CAP_ECRED_RECONF_RSP, sizeof(rsp), 624415f02b91SLuiz Augusto von Dentz &rsp); 624515f02b91SLuiz Augusto von Dentz 624615f02b91SLuiz Augusto von Dentz return 0; 624715f02b91SLuiz Augusto von Dentz } 624815f02b91SLuiz Augusto von Dentz 624915f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn, 625015f02b91SLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd, u16 cmd_len, 625115f02b91SLuiz Augusto von Dentz u8 *data) 625215f02b91SLuiz Augusto von Dentz { 625315f02b91SLuiz Augusto von Dentz struct l2cap_chan *chan; 625415f02b91SLuiz Augusto von Dentz struct l2cap_ecred_conn_rsp *rsp = (void *) data; 625515f02b91SLuiz Augusto von Dentz u16 result; 625615f02b91SLuiz Augusto von Dentz 625715f02b91SLuiz Augusto von Dentz if (cmd_len < sizeof(*rsp)) 625815f02b91SLuiz Augusto von Dentz return -EPROTO; 625915f02b91SLuiz Augusto von Dentz 626015f02b91SLuiz Augusto von Dentz result = __le16_to_cpu(rsp->result); 626115f02b91SLuiz Augusto von Dentz 626215f02b91SLuiz Augusto von Dentz BT_DBG("result 0x%4.4x", rsp->result); 626315f02b91SLuiz Augusto von Dentz 626415f02b91SLuiz Augusto von Dentz if (!result) 626515f02b91SLuiz Augusto von Dentz return 0; 626615f02b91SLuiz Augusto von Dentz 626715f02b91SLuiz Augusto von Dentz list_for_each_entry(chan, &conn->chan_l, list) { 626815f02b91SLuiz Augusto von Dentz if (chan->ident != cmd->ident) 626915f02b91SLuiz Augusto von Dentz continue; 627015f02b91SLuiz Augusto von Dentz 627115f02b91SLuiz Augusto von Dentz l2cap_chan_del(chan, ECONNRESET); 627215f02b91SLuiz Augusto von Dentz } 627315f02b91SLuiz Augusto von Dentz 627415f02b91SLuiz Augusto von Dentz return 0; 627515f02b91SLuiz Augusto von Dentz } 627615f02b91SLuiz Augusto von Dentz 627771fb4197SJohan Hedberg static inline int l2cap_le_command_rej(struct l2cap_conn *conn, 627871fb4197SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 627971fb4197SJohan Hedberg u8 *data) 628071fb4197SJohan Hedberg { 628171fb4197SJohan Hedberg struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 628271fb4197SJohan Hedberg struct l2cap_chan *chan; 628371fb4197SJohan Hedberg 628471fb4197SJohan Hedberg if (cmd_len < sizeof(*rej)) 628571fb4197SJohan Hedberg return -EPROTO; 628671fb4197SJohan Hedberg 628771fb4197SJohan Hedberg mutex_lock(&conn->chan_lock); 628871fb4197SJohan Hedberg 628971fb4197SJohan Hedberg chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 629071fb4197SJohan Hedberg if (!chan) 629171fb4197SJohan Hedberg goto done; 629271fb4197SJohan Hedberg 629371fb4197SJohan Hedberg l2cap_chan_lock(chan); 629471fb4197SJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED); 629571fb4197SJohan Hedberg l2cap_chan_unlock(chan); 629671fb4197SJohan Hedberg 629771fb4197SJohan Hedberg done: 629871fb4197SJohan Hedberg mutex_unlock(&conn->chan_lock); 629971fb4197SJohan Hedberg return 0; 630071fb4197SJohan Hedberg } 630171fb4197SJohan Hedberg 63023300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, 6303203e639eSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 6304203e639eSJohan Hedberg u8 *data) 63053300d9a9SClaudio Takahasi { 6306b5ecba64SJohan Hedberg int err = 0; 6307b5ecba64SJohan Hedberg 63083300d9a9SClaudio Takahasi switch (cmd->code) { 63093300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 631071fb4197SJohan Hedberg l2cap_le_command_rej(conn, cmd, cmd_len, data); 6311b5ecba64SJohan Hedberg break; 63123300d9a9SClaudio Takahasi 63133300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ: 6314b5ecba64SJohan Hedberg err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data); 6315b5ecba64SJohan Hedberg break; 63163300d9a9SClaudio Takahasi 63173300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP: 6318b5ecba64SJohan Hedberg break; 63193300d9a9SClaudio Takahasi 6320f1496deeSJohan Hedberg case L2CAP_LE_CONN_RSP: 6321f1496deeSJohan Hedberg l2cap_le_connect_rsp(conn, cmd, cmd_len, data); 6322b5ecba64SJohan Hedberg break; 6323f1496deeSJohan Hedberg 632427e2d4c8SJohan Hedberg case L2CAP_LE_CONN_REQ: 6325b5ecba64SJohan Hedberg err = l2cap_le_connect_req(conn, cmd, cmd_len, data); 6326b5ecba64SJohan Hedberg break; 632727e2d4c8SJohan Hedberg 6328fad5fc89SJohan Hedberg case L2CAP_LE_CREDITS: 6329fad5fc89SJohan Hedberg err = l2cap_le_credits(conn, cmd, cmd_len, data); 6330fad5fc89SJohan Hedberg break; 6331fad5fc89SJohan Hedberg 633215f02b91SLuiz Augusto von Dentz case L2CAP_ECRED_CONN_REQ: 633315f02b91SLuiz Augusto von Dentz err = l2cap_ecred_conn_req(conn, cmd, cmd_len, data); 633415f02b91SLuiz Augusto von Dentz break; 633515f02b91SLuiz Augusto von Dentz 633615f02b91SLuiz Augusto von Dentz case L2CAP_ECRED_CONN_RSP: 633715f02b91SLuiz Augusto von Dentz err = l2cap_ecred_conn_rsp(conn, cmd, cmd_len, data); 633815f02b91SLuiz Augusto von Dentz break; 633915f02b91SLuiz Augusto von Dentz 634015f02b91SLuiz Augusto von Dentz case L2CAP_ECRED_RECONF_REQ: 634115f02b91SLuiz Augusto von Dentz err = l2cap_ecred_reconf_req(conn, cmd, cmd_len, data); 634215f02b91SLuiz Augusto von Dentz break; 634315f02b91SLuiz Augusto von Dentz 634415f02b91SLuiz Augusto von Dentz case L2CAP_ECRED_RECONF_RSP: 634515f02b91SLuiz Augusto von Dentz err = l2cap_ecred_reconf_rsp(conn, cmd, cmd_len, data); 634615f02b91SLuiz Augusto von Dentz break; 634715f02b91SLuiz Augusto von Dentz 63483defe01aSJohan Hedberg case L2CAP_DISCONN_REQ: 6349b5ecba64SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data); 6350b5ecba64SJohan Hedberg break; 63513defe01aSJohan Hedberg 63523defe01aSJohan Hedberg case L2CAP_DISCONN_RSP: 63533defe01aSJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data); 6354b5ecba64SJohan Hedberg break; 63553defe01aSJohan Hedberg 63563300d9a9SClaudio Takahasi default: 63573300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code); 6358b5ecba64SJohan Hedberg err = -EINVAL; 6359b5ecba64SJohan Hedberg break; 63603300d9a9SClaudio Takahasi } 6361b5ecba64SJohan Hedberg 6362b5ecba64SJohan Hedberg return err; 63633300d9a9SClaudio Takahasi } 63643300d9a9SClaudio Takahasi 6365c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn, 6366c5623556SJohan Hedberg struct sk_buff *skb) 6367c5623556SJohan Hedberg { 636869c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon; 63694f3e219dSMarcel Holtmann struct l2cap_cmd_hdr *cmd; 63704f3e219dSMarcel Holtmann u16 len; 6371c5623556SJohan Hedberg int err; 6372c5623556SJohan Hedberg 637369c4e4e8SJohan Hedberg if (hcon->type != LE_LINK) 63743b166295SMarcel Holtmann goto drop; 637569c4e4e8SJohan Hedberg 63764f3e219dSMarcel Holtmann if (skb->len < L2CAP_CMD_HDR_SIZE) 63774f3e219dSMarcel Holtmann goto drop; 6378c5623556SJohan Hedberg 63794f3e219dSMarcel Holtmann cmd = (void *) skb->data; 63804f3e219dSMarcel Holtmann skb_pull(skb, L2CAP_CMD_HDR_SIZE); 6381c5623556SJohan Hedberg 63824f3e219dSMarcel Holtmann len = le16_to_cpu(cmd->len); 6383c5623556SJohan Hedberg 63844f3e219dSMarcel Holtmann BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident); 63854f3e219dSMarcel Holtmann 63864f3e219dSMarcel Holtmann if (len != skb->len || !cmd->ident) { 6387c5623556SJohan Hedberg BT_DBG("corrupted command"); 63884f3e219dSMarcel Holtmann goto drop; 6389c5623556SJohan Hedberg } 6390c5623556SJohan Hedberg 6391203e639eSJohan Hedberg err = l2cap_le_sig_cmd(conn, cmd, len, skb->data); 6392c5623556SJohan Hedberg if (err) { 6393c5623556SJohan Hedberg struct l2cap_cmd_rej_unk rej; 6394c5623556SJohan Hedberg 6395c5623556SJohan Hedberg BT_ERR("Wrong link type (%d)", err); 6396c5623556SJohan Hedberg 6397dcf4adbfSJoe Perches rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 63984f3e219dSMarcel Holtmann l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 6399c5623556SJohan Hedberg sizeof(rej), &rej); 6400c5623556SJohan Hedberg } 6401c5623556SJohan Hedberg 64023b166295SMarcel Holtmann drop: 6403c5623556SJohan Hedberg kfree_skb(skb); 6404c5623556SJohan Hedberg } 6405c5623556SJohan Hedberg 64063300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn, 64073300d9a9SClaudio Takahasi struct sk_buff *skb) 64080a708f8fSGustavo F. Padovan { 640969c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon; 641055cee73eSLuiz Augusto von Dentz struct l2cap_cmd_hdr *cmd; 64113300d9a9SClaudio Takahasi int err; 64120a708f8fSGustavo F. Padovan 64130a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb); 64140a708f8fSGustavo F. Padovan 641569c4e4e8SJohan Hedberg if (hcon->type != ACL_LINK) 64163b166295SMarcel Holtmann goto drop; 641769c4e4e8SJohan Hedberg 641855cee73eSLuiz Augusto von Dentz while (skb->len >= L2CAP_CMD_HDR_SIZE) { 641955cee73eSLuiz Augusto von Dentz u16 len; 64200a708f8fSGustavo F. Padovan 642155cee73eSLuiz Augusto von Dentz cmd = (void *) skb->data; 642255cee73eSLuiz Augusto von Dentz skb_pull(skb, L2CAP_CMD_HDR_SIZE); 64230a708f8fSGustavo F. Padovan 642455cee73eSLuiz Augusto von Dentz len = le16_to_cpu(cmd->len); 64250a708f8fSGustavo F. Padovan 642655cee73eSLuiz Augusto von Dentz BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, 642755cee73eSLuiz Augusto von Dentz cmd->ident); 642855cee73eSLuiz Augusto von Dentz 642955cee73eSLuiz Augusto von Dentz if (len > skb->len || !cmd->ident) { 64300a708f8fSGustavo F. Padovan BT_DBG("corrupted command"); 64310a708f8fSGustavo F. Padovan break; 64320a708f8fSGustavo F. Padovan } 64330a708f8fSGustavo F. Padovan 643455cee73eSLuiz Augusto von Dentz err = l2cap_bredr_sig_cmd(conn, cmd, len, skb->data); 64350a708f8fSGustavo F. Padovan if (err) { 6436e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk rej; 64372c6d1a2eSGustavo F. Padovan 64382c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err); 64390a708f8fSGustavo F. Padovan 6440dcf4adbfSJoe Perches rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 644155cee73eSLuiz Augusto von Dentz l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 64422d792818SGustavo Padovan sizeof(rej), &rej); 64430a708f8fSGustavo F. Padovan } 64440a708f8fSGustavo F. Padovan 644555cee73eSLuiz Augusto von Dentz skb_pull(skb, len); 64460a708f8fSGustavo F. Padovan } 64470a708f8fSGustavo F. Padovan 64483b166295SMarcel Holtmann drop: 64490a708f8fSGustavo F. Padovan kfree_skb(skb); 64500a708f8fSGustavo F. Padovan } 64510a708f8fSGustavo F. Padovan 645247d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) 64530a708f8fSGustavo F. Padovan { 64540a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs; 6455e4ca6d98SAndrei Emeltchenko int hdr_size; 6456e4ca6d98SAndrei Emeltchenko 6457e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 6458e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE; 6459e4ca6d98SAndrei Emeltchenko else 6460e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE; 64610a708f8fSGustavo F. Padovan 646247d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 646303a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE); 64640a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len); 64650a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); 64660a708f8fSGustavo F. Padovan 64670a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs) 64680a708f8fSGustavo F. Padovan return -EBADMSG; 64690a708f8fSGustavo F. Padovan } 64700a708f8fSGustavo F. Padovan return 0; 64710a708f8fSGustavo F. Padovan } 64720a708f8fSGustavo F. Padovan 64736ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) 64740a708f8fSGustavo F. Padovan { 6475e31f7633SMat Martineau struct l2cap_ctrl control; 64760a708f8fSGustavo F. Padovan 6477e31f7633SMat Martineau BT_DBG("chan %p", chan); 64780a708f8fSGustavo F. Padovan 6479e31f7633SMat Martineau memset(&control, 0, sizeof(control)); 6480e31f7633SMat Martineau control.sframe = 1; 6481e31f7633SMat Martineau control.final = 1; 6482e31f7633SMat Martineau control.reqseq = chan->buffer_seq; 6483e31f7633SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 64840a708f8fSGustavo F. Padovan 6485e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 6486e31f7633SMat Martineau control.super = L2CAP_SUPER_RNR; 6487e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 64880a708f8fSGustavo F. Padovan } 64890a708f8fSGustavo F. Padovan 6490e31f7633SMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 6491e31f7633SMat Martineau chan->unacked_frames > 0) 6492e31f7633SMat Martineau __set_retrans_timer(chan); 64930a708f8fSGustavo F. Padovan 6494e31f7633SMat Martineau /* Send pending iframes */ 6495525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 64960a708f8fSGustavo F. Padovan 6497e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 6498e31f7633SMat Martineau test_bit(CONN_SEND_FBIT, &chan->conn_state)) { 6499e31f7633SMat Martineau /* F-bit wasn't sent in an s-frame or i-frame yet, so 6500e31f7633SMat Martineau * send it now. 6501e31f7633SMat Martineau */ 6502e31f7633SMat Martineau control.super = L2CAP_SUPER_RR; 6503e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 65040a708f8fSGustavo F. Padovan } 65050a708f8fSGustavo F. Padovan } 65060a708f8fSGustavo F. Padovan 65072d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag, 65082d792818SGustavo Padovan struct sk_buff **last_frag) 65090a708f8fSGustavo F. Padovan { 651084084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments 651184084a31SMat Martineau * skb->data_len reflects only data in fragments 651284084a31SMat Martineau */ 651384084a31SMat Martineau if (!skb_has_frag_list(skb)) 651484084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag; 651584084a31SMat Martineau 651684084a31SMat Martineau new_frag->next = NULL; 651784084a31SMat Martineau 651884084a31SMat Martineau (*last_frag)->next = new_frag; 651984084a31SMat Martineau *last_frag = new_frag; 652084084a31SMat Martineau 652184084a31SMat Martineau skb->len += new_frag->len; 652284084a31SMat Martineau skb->data_len += new_frag->len; 652384084a31SMat Martineau skb->truesize += new_frag->truesize; 652484084a31SMat Martineau } 652584084a31SMat Martineau 65264b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, 65274b51dae9SMat Martineau struct l2cap_ctrl *control) 652884084a31SMat Martineau { 652984084a31SMat Martineau int err = -EINVAL; 65300a708f8fSGustavo F. Padovan 65314b51dae9SMat Martineau switch (control->sar) { 65327e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED: 653384084a31SMat Martineau if (chan->sdu) 653484084a31SMat Martineau break; 65350a708f8fSGustavo F. Padovan 653680b98027SGustavo Padovan err = chan->ops->recv(chan, skb); 653784084a31SMat Martineau break; 65380a708f8fSGustavo F. Padovan 65397e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START: 654084084a31SMat Martineau if (chan->sdu) 654184084a31SMat Martineau break; 65420a708f8fSGustavo F. Padovan 6543dbb50887SDaniel Borkmann if (!pskb_may_pull(skb, L2CAP_SDULEN_SIZE)) 6544dbb50887SDaniel Borkmann break; 6545dbb50887SDaniel Borkmann 65466f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data); 654703a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE); 65480a708f8fSGustavo F. Padovan 654984084a31SMat Martineau if (chan->sdu_len > chan->imtu) { 655084084a31SMat Martineau err = -EMSGSIZE; 655184084a31SMat Martineau break; 655284084a31SMat Martineau } 65530a708f8fSGustavo F. Padovan 655484084a31SMat Martineau if (skb->len >= chan->sdu_len) 655584084a31SMat Martineau break; 655684084a31SMat Martineau 655784084a31SMat Martineau chan->sdu = skb; 655884084a31SMat Martineau chan->sdu_last_frag = skb; 655984084a31SMat Martineau 656084084a31SMat Martineau skb = NULL; 656184084a31SMat Martineau err = 0; 65620a708f8fSGustavo F. Padovan break; 65630a708f8fSGustavo F. Padovan 65647e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE: 65656f61fd47SGustavo F. Padovan if (!chan->sdu) 656684084a31SMat Martineau break; 65670a708f8fSGustavo F. Padovan 656884084a31SMat Martineau append_skb_frag(chan->sdu, skb, 656984084a31SMat Martineau &chan->sdu_last_frag); 657084084a31SMat Martineau skb = NULL; 65710a708f8fSGustavo F. Padovan 657284084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len) 657384084a31SMat Martineau break; 65740a708f8fSGustavo F. Padovan 657584084a31SMat Martineau err = 0; 65760a708f8fSGustavo F. Padovan break; 65770a708f8fSGustavo F. Padovan 65787e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END: 65796f61fd47SGustavo F. Padovan if (!chan->sdu) 658084084a31SMat Martineau break; 65810a708f8fSGustavo F. Padovan 658284084a31SMat Martineau append_skb_frag(chan->sdu, skb, 658384084a31SMat Martineau &chan->sdu_last_frag); 658484084a31SMat Martineau skb = NULL; 65850a708f8fSGustavo F. Padovan 658684084a31SMat Martineau if (chan->sdu->len != chan->sdu_len) 658784084a31SMat Martineau break; 65880a708f8fSGustavo F. Padovan 658980b98027SGustavo Padovan err = chan->ops->recv(chan, chan->sdu); 65900a708f8fSGustavo F. Padovan 659184084a31SMat Martineau if (!err) { 659284084a31SMat Martineau /* Reassembly complete */ 659384084a31SMat Martineau chan->sdu = NULL; 659484084a31SMat Martineau chan->sdu_last_frag = NULL; 659584084a31SMat Martineau chan->sdu_len = 0; 65960a708f8fSGustavo F. Padovan } 65970a708f8fSGustavo F. Padovan break; 65980a708f8fSGustavo F. Padovan } 65990a708f8fSGustavo F. Padovan 660084084a31SMat Martineau if (err) { 66010a708f8fSGustavo F. Padovan kfree_skb(skb); 66026f61fd47SGustavo F. Padovan kfree_skb(chan->sdu); 66036f61fd47SGustavo F. Padovan chan->sdu = NULL; 660484084a31SMat Martineau chan->sdu_last_frag = NULL; 660584084a31SMat Martineau chan->sdu_len = 0; 660684084a31SMat Martineau } 66070a708f8fSGustavo F. Padovan 660884084a31SMat Martineau return err; 66090a708f8fSGustavo F. Padovan } 66100a708f8fSGustavo F. Padovan 661132b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan) 661232b32735SMat Martineau { 661332b32735SMat Martineau /* Placeholder */ 661432b32735SMat Martineau return 0; 661532b32735SMat Martineau } 661632b32735SMat Martineau 6617e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 66180a708f8fSGustavo F. Padovan { 661961aa4f5bSMat Martineau u8 event; 662061aa4f5bSMat Martineau 662161aa4f5bSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 662261aa4f5bSMat Martineau return; 662361aa4f5bSMat Martineau 662461aa4f5bSMat Martineau event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR; 6625401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, event); 66260a708f8fSGustavo F. Padovan } 66270a708f8fSGustavo F. Padovan 6628d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan) 6629d2a7ac5dSMat Martineau { 663063838725SMat Martineau int err = 0; 663163838725SMat Martineau /* Pass sequential frames to l2cap_reassemble_sdu() 663263838725SMat Martineau * until a gap is encountered. 663363838725SMat Martineau */ 663463838725SMat Martineau 663563838725SMat Martineau BT_DBG("chan %p", chan); 663663838725SMat Martineau 663763838725SMat Martineau while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 663863838725SMat Martineau struct sk_buff *skb; 663963838725SMat Martineau BT_DBG("Searching for skb with txseq %d (queue len %d)", 664063838725SMat Martineau chan->buffer_seq, skb_queue_len(&chan->srej_q)); 664163838725SMat Martineau 664263838725SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq); 664363838725SMat Martineau 664463838725SMat Martineau if (!skb) 664563838725SMat Martineau break; 664663838725SMat Martineau 664763838725SMat Martineau skb_unlink(skb, &chan->srej_q); 664863838725SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 6649a4368ff3SJohan Hedberg err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->l2cap); 665063838725SMat Martineau if (err) 665163838725SMat Martineau break; 665263838725SMat Martineau } 665363838725SMat Martineau 665463838725SMat Martineau if (skb_queue_empty(&chan->srej_q)) { 665563838725SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 665663838725SMat Martineau l2cap_send_ack(chan); 665763838725SMat Martineau } 665863838725SMat Martineau 665963838725SMat Martineau return err; 6660d2a7ac5dSMat Martineau } 6661d2a7ac5dSMat Martineau 6662d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan, 6663d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 6664d2a7ac5dSMat Martineau { 6665f80842a8SMat Martineau struct sk_buff *skb; 6666f80842a8SMat Martineau 6667f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 6668f80842a8SMat Martineau 6669f80842a8SMat Martineau if (control->reqseq == chan->next_tx_seq) { 6670f80842a8SMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 66715e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6672f80842a8SMat Martineau return; 6673f80842a8SMat Martineau } 6674f80842a8SMat Martineau 6675f80842a8SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 6676f80842a8SMat Martineau 6677f80842a8SMat Martineau if (skb == NULL) { 6678f80842a8SMat Martineau BT_DBG("Seq %d not available for retransmission", 6679f80842a8SMat Martineau control->reqseq); 6680f80842a8SMat Martineau return; 6681f80842a8SMat Martineau } 6682f80842a8SMat Martineau 6683a4368ff3SJohan Hedberg if (chan->max_tx != 0 && bt_cb(skb)->l2cap.retries >= chan->max_tx) { 6684f80842a8SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 66855e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6686f80842a8SMat Martineau return; 6687f80842a8SMat Martineau } 6688f80842a8SMat Martineau 6689f80842a8SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6690f80842a8SMat Martineau 6691f80842a8SMat Martineau if (control->poll) { 6692f80842a8SMat Martineau l2cap_pass_to_tx(chan, control); 6693f80842a8SMat Martineau 6694f80842a8SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6695f80842a8SMat Martineau l2cap_retransmit(chan, control); 6696f80842a8SMat Martineau l2cap_ertm_send(chan); 6697f80842a8SMat Martineau 6698f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 6699f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 6700f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 6701f80842a8SMat Martineau } 6702f80842a8SMat Martineau } else { 6703f80842a8SMat Martineau l2cap_pass_to_tx_fbit(chan, control); 6704f80842a8SMat Martineau 6705f80842a8SMat Martineau if (control->final) { 6706f80842a8SMat Martineau if (chan->srej_save_reqseq != control->reqseq || 6707f80842a8SMat Martineau !test_and_clear_bit(CONN_SREJ_ACT, 6708f80842a8SMat Martineau &chan->conn_state)) 6709f80842a8SMat Martineau l2cap_retransmit(chan, control); 6710f80842a8SMat Martineau } else { 6711f80842a8SMat Martineau l2cap_retransmit(chan, control); 6712f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 6713f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 6714f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 6715f80842a8SMat Martineau } 6716f80842a8SMat Martineau } 6717f80842a8SMat Martineau } 6718d2a7ac5dSMat Martineau } 6719d2a7ac5dSMat Martineau 6720d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan, 6721d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 6722d2a7ac5dSMat Martineau { 6723fcd289dfSMat Martineau struct sk_buff *skb; 6724fcd289dfSMat Martineau 6725fcd289dfSMat Martineau BT_DBG("chan %p, control %p", chan, control); 6726fcd289dfSMat Martineau 6727fcd289dfSMat Martineau if (control->reqseq == chan->next_tx_seq) { 6728fcd289dfSMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 67295e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6730fcd289dfSMat Martineau return; 6731fcd289dfSMat Martineau } 6732fcd289dfSMat Martineau 6733fcd289dfSMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 6734fcd289dfSMat Martineau 6735fcd289dfSMat Martineau if (chan->max_tx && skb && 6736a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries >= chan->max_tx) { 6737fcd289dfSMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 67385e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6739fcd289dfSMat Martineau return; 6740fcd289dfSMat Martineau } 6741fcd289dfSMat Martineau 6742fcd289dfSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6743fcd289dfSMat Martineau 6744fcd289dfSMat Martineau l2cap_pass_to_tx(chan, control); 6745fcd289dfSMat Martineau 6746fcd289dfSMat Martineau if (control->final) { 6747fcd289dfSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 6748fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 6749fcd289dfSMat Martineau } else { 6750fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 6751fcd289dfSMat Martineau l2cap_ertm_send(chan); 6752fcd289dfSMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) 6753fcd289dfSMat Martineau set_bit(CONN_REJ_ACT, &chan->conn_state); 6754fcd289dfSMat Martineau } 6755d2a7ac5dSMat Martineau } 6756d2a7ac5dSMat Martineau 67574b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) 67584b51dae9SMat Martineau { 67594b51dae9SMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 67604b51dae9SMat Martineau 67614b51dae9SMat Martineau BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq, 67624b51dae9SMat Martineau chan->expected_tx_seq); 67634b51dae9SMat Martineau 67644b51dae9SMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 67654b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 67664b51dae9SMat Martineau chan->tx_win) { 67674b51dae9SMat Martineau /* See notes below regarding "double poll" and 67684b51dae9SMat Martineau * invalid packets. 67694b51dae9SMat Martineau */ 67704b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 67714b51dae9SMat Martineau BT_DBG("Invalid/Ignore - after SREJ"); 67724b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 67734b51dae9SMat Martineau } else { 67744b51dae9SMat Martineau BT_DBG("Invalid - in window after SREJ sent"); 67754b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 67764b51dae9SMat Martineau } 67774b51dae9SMat Martineau } 67784b51dae9SMat Martineau 67794b51dae9SMat Martineau if (chan->srej_list.head == txseq) { 67804b51dae9SMat Martineau BT_DBG("Expected SREJ"); 67814b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED_SREJ; 67824b51dae9SMat Martineau } 67834b51dae9SMat Martineau 67844b51dae9SMat Martineau if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) { 67854b51dae9SMat Martineau BT_DBG("Duplicate SREJ - txseq already stored"); 67864b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE_SREJ; 67874b51dae9SMat Martineau } 67884b51dae9SMat Martineau 67894b51dae9SMat Martineau if (l2cap_seq_list_contains(&chan->srej_list, txseq)) { 67904b51dae9SMat Martineau BT_DBG("Unexpected SREJ - not requested"); 67914b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED_SREJ; 67924b51dae9SMat Martineau } 67934b51dae9SMat Martineau } 67944b51dae9SMat Martineau 67954b51dae9SMat Martineau if (chan->expected_tx_seq == txseq) { 67964b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 67974b51dae9SMat Martineau chan->tx_win) { 67984b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 67994b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 68004b51dae9SMat Martineau } else { 68014b51dae9SMat Martineau BT_DBG("Expected"); 68024b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED; 68034b51dae9SMat Martineau } 68044b51dae9SMat Martineau } 68054b51dae9SMat Martineau 68064b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) < 68072d792818SGustavo Padovan __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) { 68084b51dae9SMat Martineau BT_DBG("Duplicate - expected_tx_seq later than txseq"); 68094b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE; 68104b51dae9SMat Martineau } 68114b51dae9SMat Martineau 68124b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) { 68134b51dae9SMat Martineau /* A source of invalid packets is a "double poll" condition, 68144b51dae9SMat Martineau * where delays cause us to send multiple poll packets. If 68154b51dae9SMat Martineau * the remote stack receives and processes both polls, 68164b51dae9SMat Martineau * sequence numbers can wrap around in such a way that a 68174b51dae9SMat Martineau * resent frame has a sequence number that looks like new data 68184b51dae9SMat Martineau * with a sequence gap. This would trigger an erroneous SREJ 68194b51dae9SMat Martineau * request. 68204b51dae9SMat Martineau * 68214b51dae9SMat Martineau * Fortunately, this is impossible with a tx window that's 68224b51dae9SMat Martineau * less than half of the maximum sequence number, which allows 68234b51dae9SMat Martineau * invalid frames to be safely ignored. 68244b51dae9SMat Martineau * 68254b51dae9SMat Martineau * With tx window sizes greater than half of the tx window 68264b51dae9SMat Martineau * maximum, the frame is invalid and cannot be ignored. This 68274b51dae9SMat Martineau * causes a disconnect. 68284b51dae9SMat Martineau */ 68294b51dae9SMat Martineau 68304b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 68314b51dae9SMat Martineau BT_DBG("Invalid/Ignore - txseq outside tx window"); 68324b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 68334b51dae9SMat Martineau } else { 68344b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 68354b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 68364b51dae9SMat Martineau } 68374b51dae9SMat Martineau } else { 68384b51dae9SMat Martineau BT_DBG("Unexpected - txseq indicates missing frames"); 68394b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED; 68404b51dae9SMat Martineau } 68414b51dae9SMat Martineau } 68424b51dae9SMat Martineau 6843d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan, 6844d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 6845d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 6846d2a7ac5dSMat Martineau { 6847d2a7ac5dSMat Martineau int err = 0; 6848941247f9SPeter Senna Tschudin bool skb_in_use = false; 6849d2a7ac5dSMat Martineau 6850d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 6851d2a7ac5dSMat Martineau event); 6852d2a7ac5dSMat Martineau 6853d2a7ac5dSMat Martineau switch (event) { 6854d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 6855d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, control->txseq)) { 6856d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 6857d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6858d2a7ac5dSMat Martineau 6859d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 6860d2a7ac5dSMat Martineau BT_DBG("Busy, discarding expected seq %d", 6861d2a7ac5dSMat Martineau control->txseq); 6862d2a7ac5dSMat Martineau break; 6863d2a7ac5dSMat Martineau } 6864d2a7ac5dSMat Martineau 6865d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, 6866d2a7ac5dSMat Martineau control->txseq); 6867d2a7ac5dSMat Martineau 6868d2a7ac5dSMat Martineau chan->buffer_seq = chan->expected_tx_seq; 6869941247f9SPeter Senna Tschudin skb_in_use = true; 6870d2a7ac5dSMat Martineau 6871d2a7ac5dSMat Martineau err = l2cap_reassemble_sdu(chan, skb, control); 6872d2a7ac5dSMat Martineau if (err) 6873d2a7ac5dSMat Martineau break; 6874d2a7ac5dSMat Martineau 6875d2a7ac5dSMat Martineau if (control->final) { 6876d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 6877d2a7ac5dSMat Martineau &chan->conn_state)) { 6878d2a7ac5dSMat Martineau control->final = 0; 6879d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6880d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6881d2a7ac5dSMat Martineau } 6882d2a7ac5dSMat Martineau } 6883d2a7ac5dSMat Martineau 6884d2a7ac5dSMat Martineau if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 6885d2a7ac5dSMat Martineau l2cap_send_ack(chan); 6886d2a7ac5dSMat Martineau break; 6887d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 6888d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6889d2a7ac5dSMat Martineau 6890d2a7ac5dSMat Martineau /* Can't issue SREJ frames in the local busy state. 6891d2a7ac5dSMat Martineau * Drop this frame, it will be seen as missing 6892d2a7ac5dSMat Martineau * when local busy is exited. 6893d2a7ac5dSMat Martineau */ 6894d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 6895d2a7ac5dSMat Martineau BT_DBG("Busy, discarding unexpected seq %d", 6896d2a7ac5dSMat Martineau control->txseq); 6897d2a7ac5dSMat Martineau break; 6898d2a7ac5dSMat Martineau } 6899d2a7ac5dSMat Martineau 6900d2a7ac5dSMat Martineau /* There was a gap in the sequence, so an SREJ 6901d2a7ac5dSMat Martineau * must be sent for each missing frame. The 6902d2a7ac5dSMat Martineau * current frame is stored for later use. 6903d2a7ac5dSMat Martineau */ 6904d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6905941247f9SPeter Senna Tschudin skb_in_use = true; 6906d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6907d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6908d2a7ac5dSMat Martineau 6909d2a7ac5dSMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 6910d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 6911d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 6912d2a7ac5dSMat Martineau 6913d2a7ac5dSMat Martineau chan->rx_state = L2CAP_RX_STATE_SREJ_SENT; 6914d2a7ac5dSMat Martineau break; 6915d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 6916d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6917d2a7ac5dSMat Martineau break; 6918d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 6919d2a7ac5dSMat Martineau break; 6920d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 6921d2a7ac5dSMat Martineau default: 69225e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6923d2a7ac5dSMat Martineau break; 6924d2a7ac5dSMat Martineau } 6925d2a7ac5dSMat Martineau break; 6926d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 6927d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6928d2a7ac5dSMat Martineau if (control->final) { 6929d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6930d2a7ac5dSMat Martineau 6931e6a3ee6eSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) && 6932e6a3ee6eSMat Martineau !__chan_is_moving(chan)) { 6933d2a7ac5dSMat Martineau control->final = 0; 6934d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6935d2a7ac5dSMat Martineau } 6936d2a7ac5dSMat Martineau 6937d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6938d2a7ac5dSMat Martineau } else if (control->poll) { 6939d2a7ac5dSMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 6940d2a7ac5dSMat Martineau } else { 6941d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6942d2a7ac5dSMat Martineau &chan->conn_state) && 6943d2a7ac5dSMat Martineau chan->unacked_frames) 6944d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6945d2a7ac5dSMat Martineau 6946d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6947d2a7ac5dSMat Martineau } 6948d2a7ac5dSMat Martineau break; 6949d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 6950d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6951d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6952d2a7ac5dSMat Martineau if (control && control->poll) { 6953d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6954d2a7ac5dSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 6955d2a7ac5dSMat Martineau } 6956d2a7ac5dSMat Martineau __clear_retrans_timer(chan); 6957d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 6958d2a7ac5dSMat Martineau break; 6959d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 6960d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 6961d2a7ac5dSMat Martineau break; 6962d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 6963d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 6964d2a7ac5dSMat Martineau break; 6965d2a7ac5dSMat Martineau default: 6966d2a7ac5dSMat Martineau break; 6967d2a7ac5dSMat Martineau } 6968d2a7ac5dSMat Martineau 6969d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 6970d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 6971d2a7ac5dSMat Martineau kfree_skb(skb); 6972d2a7ac5dSMat Martineau } 6973d2a7ac5dSMat Martineau 6974d2a7ac5dSMat Martineau return err; 6975d2a7ac5dSMat Martineau } 6976d2a7ac5dSMat Martineau 6977d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, 6978d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 6979d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 6980d2a7ac5dSMat Martineau { 6981d2a7ac5dSMat Martineau int err = 0; 6982d2a7ac5dSMat Martineau u16 txseq = control->txseq; 6983941247f9SPeter Senna Tschudin bool skb_in_use = false; 6984d2a7ac5dSMat Martineau 6985d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 6986d2a7ac5dSMat Martineau event); 6987d2a7ac5dSMat Martineau 6988d2a7ac5dSMat Martineau switch (event) { 6989d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 6990d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, txseq)) { 6991d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 6992d2a7ac5dSMat Martineau /* Keep frame for reassembly later */ 6993d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6994d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6995941247f9SPeter Senna Tschudin skb_in_use = true; 6996d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6997d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6998d2a7ac5dSMat Martineau 6999d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 7000d2a7ac5dSMat Martineau break; 7001d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED_SREJ: 7002d2a7ac5dSMat Martineau l2cap_seq_list_pop(&chan->srej_list); 7003d2a7ac5dSMat Martineau 7004d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7005d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 7006941247f9SPeter Senna Tschudin skb_in_use = true; 7007d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 7008d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 7009d2a7ac5dSMat Martineau 7010d2a7ac5dSMat Martineau err = l2cap_rx_queued_iframes(chan); 7011d2a7ac5dSMat Martineau if (err) 7012d2a7ac5dSMat Martineau break; 7013d2a7ac5dSMat Martineau 7014d2a7ac5dSMat Martineau break; 7015d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 7016d2a7ac5dSMat Martineau /* Got a frame that can't be reassembled yet. 7017d2a7ac5dSMat Martineau * Save it for later, and send SREJs to cover 7018d2a7ac5dSMat Martineau * the missing frames. 7019d2a7ac5dSMat Martineau */ 7020d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 7021941247f9SPeter Senna Tschudin skb_in_use = true; 7022d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 7023d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 7024d2a7ac5dSMat Martineau 7025d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7026d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 7027d2a7ac5dSMat Martineau break; 7028d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED_SREJ: 7029d2a7ac5dSMat Martineau /* This frame was requested with an SREJ, but 7030d2a7ac5dSMat Martineau * some expected retransmitted frames are 7031d2a7ac5dSMat Martineau * missing. Request retransmission of missing 7032d2a7ac5dSMat Martineau * SREJ'd frames. 7033d2a7ac5dSMat Martineau */ 7034d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 7035941247f9SPeter Senna Tschudin skb_in_use = true; 7036d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 7037d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 7038d2a7ac5dSMat Martineau 7039d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7040d2a7ac5dSMat Martineau l2cap_send_srej_list(chan, control->txseq); 7041d2a7ac5dSMat Martineau break; 7042d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE_SREJ: 7043d2a7ac5dSMat Martineau /* We've already queued this frame. Drop this copy. */ 7044d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7045d2a7ac5dSMat Martineau break; 7046d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 7047d2a7ac5dSMat Martineau /* Expecting a later sequence number, so this frame 7048d2a7ac5dSMat Martineau * was already received. Ignore it completely. 7049d2a7ac5dSMat Martineau */ 7050d2a7ac5dSMat Martineau break; 7051d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 7052d2a7ac5dSMat Martineau break; 7053d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 7054d2a7ac5dSMat Martineau default: 70555e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 7056d2a7ac5dSMat Martineau break; 7057d2a7ac5dSMat Martineau } 7058d2a7ac5dSMat Martineau break; 7059d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 7060d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7061d2a7ac5dSMat Martineau if (control->final) { 7062d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 7063d2a7ac5dSMat Martineau 7064d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 7065d2a7ac5dSMat Martineau &chan->conn_state)) { 7066d2a7ac5dSMat Martineau control->final = 0; 7067d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 7068d2a7ac5dSMat Martineau } 7069d2a7ac5dSMat Martineau 7070d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 7071d2a7ac5dSMat Martineau } else if (control->poll) { 7072d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 7073d2a7ac5dSMat Martineau &chan->conn_state) && 7074d2a7ac5dSMat Martineau chan->unacked_frames) { 7075d2a7ac5dSMat Martineau __set_retrans_timer(chan); 7076d2a7ac5dSMat Martineau } 7077d2a7ac5dSMat Martineau 7078d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 7079d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 7080d2a7ac5dSMat Martineau } else { 7081d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 7082d2a7ac5dSMat Martineau &chan->conn_state) && 7083d2a7ac5dSMat Martineau chan->unacked_frames) 7084d2a7ac5dSMat Martineau __set_retrans_timer(chan); 7085d2a7ac5dSMat Martineau 7086d2a7ac5dSMat Martineau l2cap_send_ack(chan); 7087d2a7ac5dSMat Martineau } 7088d2a7ac5dSMat Martineau break; 7089d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 7090d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 7091d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 7092d2a7ac5dSMat Martineau if (control->poll) { 7093d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 7094d2a7ac5dSMat Martineau } else { 7095d2a7ac5dSMat Martineau struct l2cap_ctrl rr_control; 7096d2a7ac5dSMat Martineau memset(&rr_control, 0, sizeof(rr_control)); 7097d2a7ac5dSMat Martineau rr_control.sframe = 1; 7098d2a7ac5dSMat Martineau rr_control.super = L2CAP_SUPER_RR; 7099d2a7ac5dSMat Martineau rr_control.reqseq = chan->buffer_seq; 7100d2a7ac5dSMat Martineau l2cap_send_sframe(chan, &rr_control); 7101d2a7ac5dSMat Martineau } 7102d2a7ac5dSMat Martineau 7103d2a7ac5dSMat Martineau break; 7104d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 7105d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 7106d2a7ac5dSMat Martineau break; 7107d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 7108d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 7109d2a7ac5dSMat Martineau break; 7110d2a7ac5dSMat Martineau } 7111d2a7ac5dSMat Martineau 7112d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 7113d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 7114d2a7ac5dSMat Martineau kfree_skb(skb); 7115d2a7ac5dSMat Martineau } 7116d2a7ac5dSMat Martineau 7117d2a7ac5dSMat Martineau return err; 7118d2a7ac5dSMat Martineau } 7119d2a7ac5dSMat Martineau 712032b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan) 712132b32735SMat Martineau { 712232b32735SMat Martineau BT_DBG("chan %p", chan); 712332b32735SMat Martineau 712432b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 712532b32735SMat Martineau 712632b32735SMat Martineau if (chan->hs_hcon) 712732b32735SMat Martineau chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; 712832b32735SMat Martineau else 712932b32735SMat Martineau chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; 713032b32735SMat Martineau 713132b32735SMat Martineau return l2cap_resegment(chan); 713232b32735SMat Martineau } 713332b32735SMat Martineau 713432b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan, 713532b32735SMat Martineau struct l2cap_ctrl *control, 713632b32735SMat Martineau struct sk_buff *skb, u8 event) 713732b32735SMat Martineau { 713832b32735SMat Martineau int err; 713932b32735SMat Martineau 714032b32735SMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 714132b32735SMat Martineau event); 714232b32735SMat Martineau 714332b32735SMat Martineau if (!control->poll) 714432b32735SMat Martineau return -EPROTO; 714532b32735SMat Martineau 714632b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq); 714732b32735SMat Martineau 714832b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q)) 714932b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q); 715032b32735SMat Martineau else 715132b32735SMat Martineau chan->tx_send_head = NULL; 715232b32735SMat Martineau 715332b32735SMat Martineau /* Rewind next_tx_seq to the point expected 715432b32735SMat Martineau * by the receiver. 715532b32735SMat Martineau */ 715632b32735SMat Martineau chan->next_tx_seq = control->reqseq; 715732b32735SMat Martineau chan->unacked_frames = 0; 715832b32735SMat Martineau 715932b32735SMat Martineau err = l2cap_finish_move(chan); 716032b32735SMat Martineau if (err) 716132b32735SMat Martineau return err; 716232b32735SMat Martineau 716332b32735SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 716432b32735SMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 716532b32735SMat Martineau 716632b32735SMat Martineau if (event == L2CAP_EV_RECV_IFRAME) 716732b32735SMat Martineau return -EPROTO; 716832b32735SMat Martineau 716932b32735SMat Martineau return l2cap_rx_state_recv(chan, control, NULL, event); 717032b32735SMat Martineau } 717132b32735SMat Martineau 717232b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan, 717332b32735SMat Martineau struct l2cap_ctrl *control, 717432b32735SMat Martineau struct sk_buff *skb, u8 event) 717532b32735SMat Martineau { 717632b32735SMat Martineau int err; 717732b32735SMat Martineau 717832b32735SMat Martineau if (!control->final) 717932b32735SMat Martineau return -EPROTO; 718032b32735SMat Martineau 718132b32735SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 718232b32735SMat Martineau 718332b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 718432b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq); 718532b32735SMat Martineau 718632b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q)) 718732b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q); 718832b32735SMat Martineau else 718932b32735SMat Martineau chan->tx_send_head = NULL; 719032b32735SMat Martineau 719132b32735SMat Martineau /* Rewind next_tx_seq to the point expected 719232b32735SMat Martineau * by the receiver. 719332b32735SMat Martineau */ 719432b32735SMat Martineau chan->next_tx_seq = control->reqseq; 719532b32735SMat Martineau chan->unacked_frames = 0; 719632b32735SMat Martineau 719732b32735SMat Martineau if (chan->hs_hcon) 719832b32735SMat Martineau chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; 719932b32735SMat Martineau else 720032b32735SMat Martineau chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; 720132b32735SMat Martineau 720232b32735SMat Martineau err = l2cap_resegment(chan); 720332b32735SMat Martineau 720432b32735SMat Martineau if (!err) 720532b32735SMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 720632b32735SMat Martineau 720732b32735SMat Martineau return err; 720832b32735SMat Martineau } 720932b32735SMat Martineau 7210d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq) 7211d2a7ac5dSMat Martineau { 7212d2a7ac5dSMat Martineau /* Make sure reqseq is for a packet that has been sent but not acked */ 7213d2a7ac5dSMat Martineau u16 unacked; 7214d2a7ac5dSMat Martineau 7215d2a7ac5dSMat Martineau unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq); 7216d2a7ac5dSMat Martineau return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked; 7217d2a7ac5dSMat Martineau } 7218d2a7ac5dSMat Martineau 7219cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 7220cec8ab6eSMat Martineau struct sk_buff *skb, u8 event) 72210a708f8fSGustavo F. Padovan { 7222d2a7ac5dSMat Martineau int err = 0; 7223d2a7ac5dSMat Martineau 7224d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan, 7225d2a7ac5dSMat Martineau control, skb, event, chan->rx_state); 7226d2a7ac5dSMat Martineau 7227d2a7ac5dSMat Martineau if (__valid_reqseq(chan, control->reqseq)) { 7228d2a7ac5dSMat Martineau switch (chan->rx_state) { 7229d2a7ac5dSMat Martineau case L2CAP_RX_STATE_RECV: 7230d2a7ac5dSMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 7231d2a7ac5dSMat Martineau break; 7232d2a7ac5dSMat Martineau case L2CAP_RX_STATE_SREJ_SENT: 7233d2a7ac5dSMat Martineau err = l2cap_rx_state_srej_sent(chan, control, skb, 7234d2a7ac5dSMat Martineau event); 7235d2a7ac5dSMat Martineau break; 723632b32735SMat Martineau case L2CAP_RX_STATE_WAIT_P: 723732b32735SMat Martineau err = l2cap_rx_state_wait_p(chan, control, skb, event); 723832b32735SMat Martineau break; 723932b32735SMat Martineau case L2CAP_RX_STATE_WAIT_F: 724032b32735SMat Martineau err = l2cap_rx_state_wait_f(chan, control, skb, event); 724132b32735SMat Martineau break; 7242d2a7ac5dSMat Martineau default: 7243d2a7ac5dSMat Martineau /* shut it down */ 7244d2a7ac5dSMat Martineau break; 7245d2a7ac5dSMat Martineau } 7246d2a7ac5dSMat Martineau } else { 7247d2a7ac5dSMat Martineau BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d", 7248d2a7ac5dSMat Martineau control->reqseq, chan->next_tx_seq, 7249d2a7ac5dSMat Martineau chan->expected_ack_seq); 72505e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 7251d2a7ac5dSMat Martineau } 7252d2a7ac5dSMat Martineau 7253d2a7ac5dSMat Martineau return err; 7254cec8ab6eSMat Martineau } 7255cec8ab6eSMat Martineau 7256cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 7257cec8ab6eSMat Martineau struct sk_buff *skb) 7258cec8ab6eSMat Martineau { 72594b51dae9SMat Martineau BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb, 72604b51dae9SMat Martineau chan->rx_state); 72614b51dae9SMat Martineau 72624b51dae9SMat Martineau if (l2cap_classify_txseq(chan, control->txseq) == 72634b51dae9SMat Martineau L2CAP_TXSEQ_EXPECTED) { 72644b51dae9SMat Martineau l2cap_pass_to_tx(chan, control); 72654b51dae9SMat Martineau 72664b51dae9SMat Martineau BT_DBG("buffer_seq %d->%d", chan->buffer_seq, 72674b51dae9SMat Martineau __next_seq(chan, chan->buffer_seq)); 72684b51dae9SMat Martineau 72694b51dae9SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 72704b51dae9SMat Martineau 72714b51dae9SMat Martineau l2cap_reassemble_sdu(chan, skb, control); 72724b51dae9SMat Martineau } else { 72734b51dae9SMat Martineau if (chan->sdu) { 72744b51dae9SMat Martineau kfree_skb(chan->sdu); 72754b51dae9SMat Martineau chan->sdu = NULL; 72764b51dae9SMat Martineau } 72774b51dae9SMat Martineau chan->sdu_last_frag = NULL; 72784b51dae9SMat Martineau chan->sdu_len = 0; 72794b51dae9SMat Martineau 72804b51dae9SMat Martineau if (skb) { 72814b51dae9SMat Martineau BT_DBG("Freeing %p", skb); 72824b51dae9SMat Martineau kfree_skb(skb); 72834b51dae9SMat Martineau } 72844b51dae9SMat Martineau } 72854b51dae9SMat Martineau 72864b51dae9SMat Martineau chan->last_acked_seq = control->txseq; 72874b51dae9SMat Martineau chan->expected_tx_seq = __next_seq(chan, control->txseq); 72884b51dae9SMat Martineau 72899a544210SPrasanna Karthik return 0; 7290cec8ab6eSMat Martineau } 7291cec8ab6eSMat Martineau 7292cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 7293cec8ab6eSMat Martineau { 7294a4368ff3SJohan Hedberg struct l2cap_ctrl *control = &bt_cb(skb)->l2cap; 7295cec8ab6eSMat Martineau u16 len; 7296cec8ab6eSMat Martineau u8 event; 72970a708f8fSGustavo F. Padovan 7298b76bbd66SMat Martineau __unpack_control(chan, skb); 7299b76bbd66SMat Martineau 73000a708f8fSGustavo F. Padovan len = skb->len; 73010a708f8fSGustavo F. Padovan 73020a708f8fSGustavo F. Padovan /* 73030a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here. 73040a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery 7305cec8ab6eSMat Martineau * procedures and ask for retransmission. 73060a708f8fSGustavo F. Padovan */ 730747d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 73080a708f8fSGustavo F. Padovan goto drop; 73090a708f8fSGustavo F. Padovan 7310cec8ab6eSMat Martineau if (!control->sframe && control->sar == L2CAP_SAR_START) 731103a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 73120a708f8fSGustavo F. Padovan 731347d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 731403a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 73150a708f8fSGustavo F. Padovan 731647d1ec61SGustavo F. Padovan if (len > chan->mps) { 73175e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 73180a708f8fSGustavo F. Padovan goto drop; 73190a708f8fSGustavo F. Padovan } 73200a708f8fSGustavo F. Padovan 7321f1942564SLuiz Augusto von Dentz if (chan->ops->filter) { 7322f1942564SLuiz Augusto von Dentz if (chan->ops->filter(chan, skb)) 7323dbb50887SDaniel Borkmann goto drop; 7324f1942564SLuiz Augusto von Dentz } 7325dbb50887SDaniel Borkmann 7326cec8ab6eSMat Martineau if (!control->sframe) { 7327cec8ab6eSMat Martineau int err; 73280a708f8fSGustavo F. Padovan 7329cec8ab6eSMat Martineau BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d", 7330cec8ab6eSMat Martineau control->sar, control->reqseq, control->final, 7331cec8ab6eSMat Martineau control->txseq); 7332836be934SAndrei Emeltchenko 7333cec8ab6eSMat Martineau /* Validate F-bit - F=0 always valid, F=1 only 7334cec8ab6eSMat Martineau * valid in TX WAIT_F 7335cec8ab6eSMat Martineau */ 7336cec8ab6eSMat Martineau if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F) 73370a708f8fSGustavo F. Padovan goto drop; 73380a708f8fSGustavo F. Padovan 7339cec8ab6eSMat Martineau if (chan->mode != L2CAP_MODE_STREAMING) { 7340cec8ab6eSMat Martineau event = L2CAP_EV_RECV_IFRAME; 7341cec8ab6eSMat Martineau err = l2cap_rx(chan, control, skb, event); 73420a708f8fSGustavo F. Padovan } else { 7343cec8ab6eSMat Martineau err = l2cap_stream_rx(chan, control, skb); 7344cec8ab6eSMat Martineau } 7345cec8ab6eSMat Martineau 7346cec8ab6eSMat Martineau if (err) 73475e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 7348cec8ab6eSMat Martineau } else { 7349cec8ab6eSMat Martineau const u8 rx_func_to_event[4] = { 7350cec8ab6eSMat Martineau L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ, 7351cec8ab6eSMat Martineau L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ 7352cec8ab6eSMat Martineau }; 7353cec8ab6eSMat Martineau 7354cec8ab6eSMat Martineau /* Only I-frames are expected in streaming mode */ 7355cec8ab6eSMat Martineau if (chan->mode == L2CAP_MODE_STREAMING) 7356cec8ab6eSMat Martineau goto drop; 7357cec8ab6eSMat Martineau 7358cec8ab6eSMat Martineau BT_DBG("sframe reqseq %d, final %d, poll %d, super %d", 7359cec8ab6eSMat Martineau control->reqseq, control->final, control->poll, 7360cec8ab6eSMat Martineau control->super); 7361cec8ab6eSMat Martineau 73620a708f8fSGustavo F. Padovan if (len != 0) { 73631bb166e6SAndrei Emeltchenko BT_ERR("Trailing bytes: %d in sframe", len); 73645e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 73650a708f8fSGustavo F. Padovan goto drop; 73660a708f8fSGustavo F. Padovan } 73670a708f8fSGustavo F. Padovan 7368cec8ab6eSMat Martineau /* Validate F and P bits */ 7369cec8ab6eSMat Martineau if (control->final && (control->poll || 7370cec8ab6eSMat Martineau chan->tx_state != L2CAP_TX_STATE_WAIT_F)) 7371cec8ab6eSMat Martineau goto drop; 7372cec8ab6eSMat Martineau 7373cec8ab6eSMat Martineau event = rx_func_to_event[control->super]; 7374cec8ab6eSMat Martineau if (l2cap_rx(chan, control, skb, event)) 73755e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 73760a708f8fSGustavo F. Padovan } 73770a708f8fSGustavo F. Padovan 73780a708f8fSGustavo F. Padovan return 0; 73790a708f8fSGustavo F. Padovan 73800a708f8fSGustavo F. Padovan drop: 73810a708f8fSGustavo F. Padovan kfree_skb(skb); 73820a708f8fSGustavo F. Padovan return 0; 73830a708f8fSGustavo F. Padovan } 73840a708f8fSGustavo F. Padovan 7385b1c325c2SJohan Hedberg static void l2cap_chan_le_send_credits(struct l2cap_chan *chan) 7386b1c325c2SJohan Hedberg { 7387b1c325c2SJohan Hedberg struct l2cap_conn *conn = chan->conn; 7388b1c325c2SJohan Hedberg struct l2cap_le_credits pkt; 7389b1c325c2SJohan Hedberg u16 return_credits; 7390b1c325c2SJohan Hedberg 739115f02b91SLuiz Augusto von Dentz return_credits = (chan->imtu / chan->mps) + 1; 7392b1c325c2SJohan Hedberg 739315f02b91SLuiz Augusto von Dentz if (chan->rx_credits >= return_credits) 739496cd8eaaSLuiz Augusto von Dentz return; 7395b1c325c2SJohan Hedberg 739615f02b91SLuiz Augusto von Dentz return_credits -= chan->rx_credits; 739715f02b91SLuiz Augusto von Dentz 7398b1c325c2SJohan Hedberg BT_DBG("chan %p returning %u credits to sender", chan, return_credits); 7399b1c325c2SJohan Hedberg 7400b1c325c2SJohan Hedberg chan->rx_credits += return_credits; 7401b1c325c2SJohan Hedberg 7402b1c325c2SJohan Hedberg pkt.cid = cpu_to_le16(chan->scid); 7403b1c325c2SJohan Hedberg pkt.credits = cpu_to_le16(return_credits); 7404b1c325c2SJohan Hedberg 7405b1c325c2SJohan Hedberg chan->ident = l2cap_get_ident(conn); 7406b1c325c2SJohan Hedberg 7407b1c325c2SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt); 7408b1c325c2SJohan Hedberg } 7409b1c325c2SJohan Hedberg 741015f02b91SLuiz Augusto von Dentz static int l2cap_ecred_recv(struct l2cap_chan *chan, struct sk_buff *skb) 741196cd8eaaSLuiz Augusto von Dentz { 741296cd8eaaSLuiz Augusto von Dentz int err; 741396cd8eaaSLuiz Augusto von Dentz 741496cd8eaaSLuiz Augusto von Dentz BT_DBG("SDU reassemble complete: chan %p skb->len %u", chan, skb->len); 741596cd8eaaSLuiz Augusto von Dentz 741696cd8eaaSLuiz Augusto von Dentz /* Wait recv to confirm reception before updating the credits */ 741796cd8eaaSLuiz Augusto von Dentz err = chan->ops->recv(chan, skb); 741896cd8eaaSLuiz Augusto von Dentz 741996cd8eaaSLuiz Augusto von Dentz /* Update credits whenever an SDU is received */ 742096cd8eaaSLuiz Augusto von Dentz l2cap_chan_le_send_credits(chan); 742196cd8eaaSLuiz Augusto von Dentz 742296cd8eaaSLuiz Augusto von Dentz return err; 742396cd8eaaSLuiz Augusto von Dentz } 742496cd8eaaSLuiz Augusto von Dentz 742515f02b91SLuiz Augusto von Dentz static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 7426fad5fc89SJohan Hedberg { 7427aac23bf6SJohan Hedberg int err; 7428fad5fc89SJohan Hedberg 7429aac23bf6SJohan Hedberg if (!chan->rx_credits) { 7430aac23bf6SJohan Hedberg BT_ERR("No credits to receive LE L2CAP data"); 7431dfd9774cSJohan Hedberg l2cap_send_disconn_req(chan, ECONNRESET); 7432fad5fc89SJohan Hedberg return -ENOBUFS; 7433aac23bf6SJohan Hedberg } 7434aac23bf6SJohan Hedberg 7435aac23bf6SJohan Hedberg if (chan->imtu < skb->len) { 7436aac23bf6SJohan Hedberg BT_ERR("Too big LE L2CAP PDU"); 7437aac23bf6SJohan Hedberg return -ENOBUFS; 7438aac23bf6SJohan Hedberg } 7439fad5fc89SJohan Hedberg 7440fad5fc89SJohan Hedberg chan->rx_credits--; 7441fad5fc89SJohan Hedberg BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits); 7442fad5fc89SJohan Hedberg 744396cd8eaaSLuiz Augusto von Dentz /* Update if remote had run out of credits, this should only happens 744496cd8eaaSLuiz Augusto von Dentz * if the remote is not using the entire MPS. 744596cd8eaaSLuiz Augusto von Dentz */ 744696cd8eaaSLuiz Augusto von Dentz if (!chan->rx_credits) 7447fad5fc89SJohan Hedberg l2cap_chan_le_send_credits(chan); 7448fad5fc89SJohan Hedberg 7449aac23bf6SJohan Hedberg err = 0; 7450aac23bf6SJohan Hedberg 7451aac23bf6SJohan Hedberg if (!chan->sdu) { 7452aac23bf6SJohan Hedberg u16 sdu_len; 7453aac23bf6SJohan Hedberg 7454aac23bf6SJohan Hedberg sdu_len = get_unaligned_le16(skb->data); 7455aac23bf6SJohan Hedberg skb_pull(skb, L2CAP_SDULEN_SIZE); 7456aac23bf6SJohan Hedberg 7457aac23bf6SJohan Hedberg BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u", 7458aac23bf6SJohan Hedberg sdu_len, skb->len, chan->imtu); 7459aac23bf6SJohan Hedberg 7460aac23bf6SJohan Hedberg if (sdu_len > chan->imtu) { 7461aac23bf6SJohan Hedberg BT_ERR("Too big LE L2CAP SDU length received"); 7462aac23bf6SJohan Hedberg err = -EMSGSIZE; 7463aac23bf6SJohan Hedberg goto failed; 7464aac23bf6SJohan Hedberg } 7465aac23bf6SJohan Hedberg 7466aac23bf6SJohan Hedberg if (skb->len > sdu_len) { 7467aac23bf6SJohan Hedberg BT_ERR("Too much LE L2CAP data received"); 7468aac23bf6SJohan Hedberg err = -EINVAL; 7469aac23bf6SJohan Hedberg goto failed; 7470aac23bf6SJohan Hedberg } 7471aac23bf6SJohan Hedberg 7472aac23bf6SJohan Hedberg if (skb->len == sdu_len) 747315f02b91SLuiz Augusto von Dentz return l2cap_ecred_recv(chan, skb); 7474aac23bf6SJohan Hedberg 7475aac23bf6SJohan Hedberg chan->sdu = skb; 7476aac23bf6SJohan Hedberg chan->sdu_len = sdu_len; 7477aac23bf6SJohan Hedberg chan->sdu_last_frag = skb; 7478aac23bf6SJohan Hedberg 7479a5c3021bSLuiz Augusto von Dentz /* Detect if remote is not able to use the selected MPS */ 7480a5c3021bSLuiz Augusto von Dentz if (skb->len + L2CAP_SDULEN_SIZE < chan->mps) { 7481a5c3021bSLuiz Augusto von Dentz u16 mps_len = skb->len + L2CAP_SDULEN_SIZE; 7482a5c3021bSLuiz Augusto von Dentz 7483a5c3021bSLuiz Augusto von Dentz /* Adjust the number of credits */ 7484a5c3021bSLuiz Augusto von Dentz BT_DBG("chan->mps %u -> %u", chan->mps, mps_len); 7485a5c3021bSLuiz Augusto von Dentz chan->mps = mps_len; 7486a5c3021bSLuiz Augusto von Dentz l2cap_chan_le_send_credits(chan); 7487a5c3021bSLuiz Augusto von Dentz } 7488a5c3021bSLuiz Augusto von Dentz 7489aac23bf6SJohan Hedberg return 0; 7490aac23bf6SJohan Hedberg } 7491aac23bf6SJohan Hedberg 7492aac23bf6SJohan Hedberg BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u", 7493aac23bf6SJohan Hedberg chan->sdu->len, skb->len, chan->sdu_len); 7494aac23bf6SJohan Hedberg 7495aac23bf6SJohan Hedberg if (chan->sdu->len + skb->len > chan->sdu_len) { 7496aac23bf6SJohan Hedberg BT_ERR("Too much LE L2CAP data received"); 7497aac23bf6SJohan Hedberg err = -EINVAL; 7498aac23bf6SJohan Hedberg goto failed; 7499aac23bf6SJohan Hedberg } 7500aac23bf6SJohan Hedberg 7501aac23bf6SJohan Hedberg append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag); 7502aac23bf6SJohan Hedberg skb = NULL; 7503aac23bf6SJohan Hedberg 7504aac23bf6SJohan Hedberg if (chan->sdu->len == chan->sdu_len) { 750515f02b91SLuiz Augusto von Dentz err = l2cap_ecred_recv(chan, chan->sdu); 7506aac23bf6SJohan Hedberg if (!err) { 7507aac23bf6SJohan Hedberg chan->sdu = NULL; 7508aac23bf6SJohan Hedberg chan->sdu_last_frag = NULL; 7509aac23bf6SJohan Hedberg chan->sdu_len = 0; 7510aac23bf6SJohan Hedberg } 7511aac23bf6SJohan Hedberg } 7512aac23bf6SJohan Hedberg 7513aac23bf6SJohan Hedberg failed: 7514aac23bf6SJohan Hedberg if (err) { 7515aac23bf6SJohan Hedberg kfree_skb(skb); 7516aac23bf6SJohan Hedberg kfree_skb(chan->sdu); 7517aac23bf6SJohan Hedberg chan->sdu = NULL; 7518aac23bf6SJohan Hedberg chan->sdu_last_frag = NULL; 7519aac23bf6SJohan Hedberg chan->sdu_len = 0; 7520aac23bf6SJohan Hedberg } 7521aac23bf6SJohan Hedberg 7522aac23bf6SJohan Hedberg /* We can't return an error here since we took care of the skb 7523aac23bf6SJohan Hedberg * freeing internally. An error return would cause the caller to 7524aac23bf6SJohan Hedberg * do a double-free of the skb. 7525aac23bf6SJohan Hedberg */ 7526aac23bf6SJohan Hedberg return 0; 7527fad5fc89SJohan Hedberg } 7528fad5fc89SJohan Hedberg 752913ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid, 753013ca56e0SAndrei Emeltchenko struct sk_buff *skb) 75310a708f8fSGustavo F. Padovan { 753248454079SGustavo F. Padovan struct l2cap_chan *chan; 75330a708f8fSGustavo F. Padovan 7534baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 753548454079SGustavo F. Padovan if (!chan) { 753697e8e89dSAndrei Emeltchenko if (cid == L2CAP_CID_A2MP) { 753797e8e89dSAndrei Emeltchenko chan = a2mp_channel_create(conn, skb); 753897e8e89dSAndrei Emeltchenko if (!chan) { 753997e8e89dSAndrei Emeltchenko kfree_skb(skb); 754013ca56e0SAndrei Emeltchenko return; 754197e8e89dSAndrei Emeltchenko } 754297e8e89dSAndrei Emeltchenko 754397e8e89dSAndrei Emeltchenko l2cap_chan_lock(chan); 754497e8e89dSAndrei Emeltchenko } else { 75450a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid); 75466be36555SAndrei Emeltchenko /* Drop packet and return */ 75473379013bSDan Carpenter kfree_skb(skb); 754813ca56e0SAndrei Emeltchenko return; 75490a708f8fSGustavo F. Padovan } 755097e8e89dSAndrei Emeltchenko } 75510a708f8fSGustavo F. Padovan 755249208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len); 75530a708f8fSGustavo F. Padovan 7554315917e0SJohan Hedberg /* If we receive data on a fixed channel before the info req/rsp 7555315917e0SJohan Hedberg * procdure is done simply assume that the channel is supported 7556315917e0SJohan Hedberg * and mark it as ready. 7557315917e0SJohan Hedberg */ 7558315917e0SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_FIXED) 7559315917e0SJohan Hedberg l2cap_chan_ready(chan); 7560315917e0SJohan Hedberg 756189bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 75620a708f8fSGustavo F. Padovan goto drop; 75630a708f8fSGustavo F. Padovan 75640c1bc5c6SGustavo F. Padovan switch (chan->mode) { 756538319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 756615f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL: 756715f02b91SLuiz Augusto von Dentz if (l2cap_ecred_data_rcv(chan, skb) < 0) 7568fad5fc89SJohan Hedberg goto drop; 7569fad5fc89SJohan Hedberg 7570fad5fc89SJohan Hedberg goto done; 7571fad5fc89SJohan Hedberg 75720a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 75730a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here 75740a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable. 75750a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't 75760a708f8fSGustavo F. Padovan * provide flow control mechanism. */ 75770a708f8fSGustavo F. Padovan 75782c96e03dSSzymon Janc if (chan->imtu < skb->len) { 75792c96e03dSSzymon Janc BT_ERR("Dropping L2CAP data: receive buffer overflow"); 75800a708f8fSGustavo F. Padovan goto drop; 75812c96e03dSSzymon Janc } 75820a708f8fSGustavo F. Padovan 758380b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 75840a708f8fSGustavo F. Padovan goto done; 75850a708f8fSGustavo F. Padovan break; 75860a708f8fSGustavo F. Padovan 75870a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 75880a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 7589cec8ab6eSMat Martineau l2cap_data_rcv(chan, skb); 75900a708f8fSGustavo F. Padovan goto done; 75910a708f8fSGustavo F. Padovan 75920a708f8fSGustavo F. Padovan default: 75930c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); 75940a708f8fSGustavo F. Padovan break; 75950a708f8fSGustavo F. Padovan } 75960a708f8fSGustavo F. Padovan 75970a708f8fSGustavo F. Padovan drop: 75980a708f8fSGustavo F. Padovan kfree_skb(skb); 75990a708f8fSGustavo F. Padovan 76000a708f8fSGustavo F. Padovan done: 76016be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 76020a708f8fSGustavo F. Padovan } 76030a708f8fSGustavo F. Padovan 760484104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, 760584104b24SAndrei Emeltchenko struct sk_buff *skb) 76060a708f8fSGustavo F. Padovan { 7607ae4fd2d3SMarcel Holtmann struct hci_conn *hcon = conn->hcon; 760823691d75SGustavo F. Padovan struct l2cap_chan *chan; 76090a708f8fSGustavo F. Padovan 7610ae4fd2d3SMarcel Holtmann if (hcon->type != ACL_LINK) 7611a24cce14SJohan Hedberg goto free_skb; 7612ae4fd2d3SMarcel Holtmann 7613bf20fd4eSJohan Hedberg chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst, 7614bf20fd4eSJohan Hedberg ACL_LINK); 761523691d75SGustavo F. Padovan if (!chan) 7616a24cce14SJohan Hedberg goto free_skb; 76170a708f8fSGustavo F. Padovan 76185b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 76190a708f8fSGustavo F. Padovan 762089bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 76210a708f8fSGustavo F. Padovan goto drop; 76220a708f8fSGustavo F. Padovan 7623e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 76240a708f8fSGustavo F. Padovan goto drop; 76250a708f8fSGustavo F. Padovan 76262edf870dSMarcel Holtmann /* Store remote BD_ADDR and PSM for msg_name */ 7627a4368ff3SJohan Hedberg bacpy(&bt_cb(skb)->l2cap.bdaddr, &hcon->dst); 7628a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.psm = psm; 76292edf870dSMarcel Holtmann 7630a24cce14SJohan Hedberg if (!chan->ops->recv(chan, skb)) { 7631a24cce14SJohan Hedberg l2cap_chan_put(chan); 763284104b24SAndrei Emeltchenko return; 7633a24cce14SJohan Hedberg } 76340a708f8fSGustavo F. Padovan 76350a708f8fSGustavo F. Padovan drop: 7636a24cce14SJohan Hedberg l2cap_chan_put(chan); 7637a24cce14SJohan Hedberg free_skb: 76380a708f8fSGustavo F. Padovan kfree_skb(skb); 76390a708f8fSGustavo F. Padovan } 76400a708f8fSGustavo F. Padovan 76410a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) 76420a708f8fSGustavo F. Padovan { 76430a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data; 764461a939c6SJohan Hedberg struct hci_conn *hcon = conn->hcon; 76450a708f8fSGustavo F. Padovan u16 cid, len; 76460a708f8fSGustavo F. Padovan __le16 psm; 76470a708f8fSGustavo F. Padovan 764861a939c6SJohan Hedberg if (hcon->state != BT_CONNECTED) { 764961a939c6SJohan Hedberg BT_DBG("queueing pending rx skb"); 765061a939c6SJohan Hedberg skb_queue_tail(&conn->pending_rx, skb); 765161a939c6SJohan Hedberg return; 765261a939c6SJohan Hedberg } 765361a939c6SJohan Hedberg 76540a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE); 76550a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid); 76560a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len); 76570a708f8fSGustavo F. Padovan 76580a708f8fSGustavo F. Padovan if (len != skb->len) { 76590a708f8fSGustavo F. Padovan kfree_skb(skb); 76600a708f8fSGustavo F. Padovan return; 76610a708f8fSGustavo F. Padovan } 76620a708f8fSGustavo F. Padovan 76639e1d7e15SJohan Hedberg /* Since we can't actively block incoming LE connections we must 76649e1d7e15SJohan Hedberg * at least ensure that we ignore incoming data from them. 76659e1d7e15SJohan Hedberg */ 76669e1d7e15SJohan Hedberg if (hcon->type == LE_LINK && 7667dcc36c16SJohan Hedberg hci_bdaddr_list_lookup(&hcon->hdev->blacklist, &hcon->dst, 7668a250e048SJohan Hedberg bdaddr_dst_type(hcon))) { 7669e493150eSJohan Hedberg kfree_skb(skb); 7670e493150eSJohan Hedberg return; 7671e493150eSJohan Hedberg } 7672e493150eSJohan Hedberg 76730a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid); 76740a708f8fSGustavo F. Padovan 76750a708f8fSGustavo F. Padovan switch (cid) { 76760a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING: 76770a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb); 76780a708f8fSGustavo F. Padovan break; 76790a708f8fSGustavo F. Padovan 76800a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS: 7681097db76cSAndrei Emeltchenko psm = get_unaligned((__le16 *) skb->data); 76820181a70fSAndrei Emeltchenko skb_pull(skb, L2CAP_PSMLEN_SIZE); 76830a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb); 76840a708f8fSGustavo F. Padovan break; 76850a708f8fSGustavo F. Padovan 7686a2877629SMarcel Holtmann case L2CAP_CID_LE_SIGNALING: 7687a2877629SMarcel Holtmann l2cap_le_sig_channel(conn, skb); 7688a2877629SMarcel Holtmann break; 7689a2877629SMarcel Holtmann 76900a708f8fSGustavo F. Padovan default: 76910a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb); 76920a708f8fSGustavo F. Padovan break; 76930a708f8fSGustavo F. Padovan } 76940a708f8fSGustavo F. Padovan } 76950a708f8fSGustavo F. Padovan 769661a939c6SJohan Hedberg static void process_pending_rx(struct work_struct *work) 769761a939c6SJohan Hedberg { 769861a939c6SJohan Hedberg struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 769961a939c6SJohan Hedberg pending_rx_work); 770061a939c6SJohan Hedberg struct sk_buff *skb; 770161a939c6SJohan Hedberg 770261a939c6SJohan Hedberg BT_DBG(""); 770361a939c6SJohan Hedberg 770461a939c6SJohan Hedberg while ((skb = skb_dequeue(&conn->pending_rx))) 770561a939c6SJohan Hedberg l2cap_recv_frame(conn, skb); 770661a939c6SJohan Hedberg } 770761a939c6SJohan Hedberg 7708162b49e7SJohan Hedberg static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) 7709162b49e7SJohan Hedberg { 7710162b49e7SJohan Hedberg struct l2cap_conn *conn = hcon->l2cap_data; 7711162b49e7SJohan Hedberg struct hci_chan *hchan; 7712162b49e7SJohan Hedberg 7713162b49e7SJohan Hedberg if (conn) 7714162b49e7SJohan Hedberg return conn; 7715162b49e7SJohan Hedberg 7716162b49e7SJohan Hedberg hchan = hci_chan_create(hcon); 7717162b49e7SJohan Hedberg if (!hchan) 7718162b49e7SJohan Hedberg return NULL; 7719162b49e7SJohan Hedberg 772027f70f3eSJohan Hedberg conn = kzalloc(sizeof(*conn), GFP_KERNEL); 7721162b49e7SJohan Hedberg if (!conn) { 7722162b49e7SJohan Hedberg hci_chan_del(hchan); 7723162b49e7SJohan Hedberg return NULL; 7724162b49e7SJohan Hedberg } 7725162b49e7SJohan Hedberg 7726162b49e7SJohan Hedberg kref_init(&conn->ref); 7727162b49e7SJohan Hedberg hcon->l2cap_data = conn; 772851bb8457SJohan Hedberg conn->hcon = hci_conn_get(hcon); 7729162b49e7SJohan Hedberg conn->hchan = hchan; 7730162b49e7SJohan Hedberg 7731162b49e7SJohan Hedberg BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); 7732162b49e7SJohan Hedberg 7733162b49e7SJohan Hedberg switch (hcon->type) { 7734162b49e7SJohan Hedberg case LE_LINK: 7735162b49e7SJohan Hedberg if (hcon->hdev->le_mtu) { 7736162b49e7SJohan Hedberg conn->mtu = hcon->hdev->le_mtu; 7737162b49e7SJohan Hedberg break; 7738162b49e7SJohan Hedberg } 773919186c7bSGustavo A. R. Silva fallthrough; 7740162b49e7SJohan Hedberg default: 7741162b49e7SJohan Hedberg conn->mtu = hcon->hdev->acl_mtu; 7742162b49e7SJohan Hedberg break; 7743162b49e7SJohan Hedberg } 7744162b49e7SJohan Hedberg 7745162b49e7SJohan Hedberg conn->feat_mask = 0; 7746162b49e7SJohan Hedberg 77470bd49fc7SJohan Hedberg conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS; 77480bd49fc7SJohan Hedberg 77490bd49fc7SJohan Hedberg if (hcon->type == ACL_LINK && 7750d7a5a11dSMarcel Holtmann hci_dev_test_flag(hcon->hdev, HCI_HS_ENABLED)) 77510bd49fc7SJohan Hedberg conn->local_fixed_chan |= L2CAP_FC_A2MP; 7752162b49e7SJohan Hedberg 7753d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED) && 7754f9be9e86SMarcel Holtmann (bredr_sc_enabled(hcon->hdev) || 7755b7cb93e5SMarcel Holtmann hci_dev_test_flag(hcon->hdev, HCI_FORCE_BREDR_SMP))) 7756b5ae344dSJohan Hedberg conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR; 7757b5ae344dSJohan Hedberg 77585a54e7c8SMarcel Holtmann mutex_init(&conn->ident_lock); 7759162b49e7SJohan Hedberg mutex_init(&conn->chan_lock); 7760162b49e7SJohan Hedberg 7761162b49e7SJohan Hedberg INIT_LIST_HEAD(&conn->chan_l); 7762162b49e7SJohan Hedberg INIT_LIST_HEAD(&conn->users); 7763162b49e7SJohan Hedberg 7764162b49e7SJohan Hedberg INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); 7765162b49e7SJohan Hedberg 776661a939c6SJohan Hedberg skb_queue_head_init(&conn->pending_rx); 776761a939c6SJohan Hedberg INIT_WORK(&conn->pending_rx_work, process_pending_rx); 7768f3d82d0cSJohan Hedberg INIT_WORK(&conn->id_addr_update_work, l2cap_conn_update_id_addr); 776961a939c6SJohan Hedberg 7770162b49e7SJohan Hedberg conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 7771162b49e7SJohan Hedberg 7772162b49e7SJohan Hedberg return conn; 7773162b49e7SJohan Hedberg } 7774162b49e7SJohan Hedberg 7775162b49e7SJohan Hedberg static bool is_valid_psm(u16 psm, u8 dst_type) { 7776162b49e7SJohan Hedberg if (!psm) 7777162b49e7SJohan Hedberg return false; 7778162b49e7SJohan Hedberg 7779162b49e7SJohan Hedberg if (bdaddr_type_is_le(dst_type)) 7780162b49e7SJohan Hedberg return (psm <= 0x00ff); 7781162b49e7SJohan Hedberg 7782162b49e7SJohan Hedberg /* PSM must be odd and lsb of upper byte must be 0 */ 7783162b49e7SJohan Hedberg return ((psm & 0x0101) == 0x0001); 7784162b49e7SJohan Hedberg } 7785162b49e7SJohan Hedberg 7786da49b602SLuiz Augusto von Dentz struct l2cap_chan_data { 7787da49b602SLuiz Augusto von Dentz struct l2cap_chan *chan; 7788da49b602SLuiz Augusto von Dentz struct pid *pid; 7789da49b602SLuiz Augusto von Dentz int count; 7790da49b602SLuiz Augusto von Dentz }; 7791da49b602SLuiz Augusto von Dentz 7792da49b602SLuiz Augusto von Dentz static void l2cap_chan_by_pid(struct l2cap_chan *chan, void *data) 7793da49b602SLuiz Augusto von Dentz { 7794da49b602SLuiz Augusto von Dentz struct l2cap_chan_data *d = data; 7795da49b602SLuiz Augusto von Dentz struct pid *pid; 7796da49b602SLuiz Augusto von Dentz 7797da49b602SLuiz Augusto von Dentz if (chan == d->chan) 7798da49b602SLuiz Augusto von Dentz return; 7799da49b602SLuiz Augusto von Dentz 7800da49b602SLuiz Augusto von Dentz if (!test_bit(FLAG_DEFER_SETUP, &chan->flags)) 7801da49b602SLuiz Augusto von Dentz return; 7802da49b602SLuiz Augusto von Dentz 7803da49b602SLuiz Augusto von Dentz pid = chan->ops->get_peer_pid(chan); 7804da49b602SLuiz Augusto von Dentz 7805da49b602SLuiz Augusto von Dentz /* Only count deferred channels with the same PID/PSM */ 7806da49b602SLuiz Augusto von Dentz if (d->pid != pid || chan->psm != d->chan->psm || chan->ident || 7807da49b602SLuiz Augusto von Dentz chan->mode != L2CAP_MODE_EXT_FLOWCTL || chan->state != BT_CONNECT) 7808da49b602SLuiz Augusto von Dentz return; 7809da49b602SLuiz Augusto von Dentz 7810da49b602SLuiz Augusto von Dentz d->count++; 7811da49b602SLuiz Augusto von Dentz } 7812da49b602SLuiz Augusto von Dentz 7813162b49e7SJohan Hedberg int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, 7814162b49e7SJohan Hedberg bdaddr_t *dst, u8 dst_type) 7815162b49e7SJohan Hedberg { 7816162b49e7SJohan Hedberg struct l2cap_conn *conn; 7817162b49e7SJohan Hedberg struct hci_conn *hcon; 7818162b49e7SJohan Hedberg struct hci_dev *hdev; 7819162b49e7SJohan Hedberg int err; 7820162b49e7SJohan Hedberg 782115f02b91SLuiz Augusto von Dentz BT_DBG("%pMR -> %pMR (type %u) psm 0x%4.4x mode 0x%2.2x", &chan->src, 782215f02b91SLuiz Augusto von Dentz dst, dst_type, __le16_to_cpu(psm), chan->mode); 7823162b49e7SJohan Hedberg 782439385cb5SJohan Hedberg hdev = hci_get_route(dst, &chan->src, chan->src_type); 7825162b49e7SJohan Hedberg if (!hdev) 7826162b49e7SJohan Hedberg return -EHOSTUNREACH; 7827162b49e7SJohan Hedberg 7828162b49e7SJohan Hedberg hci_dev_lock(hdev); 7829162b49e7SJohan Hedberg 7830162b49e7SJohan Hedberg if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid && 7831162b49e7SJohan Hedberg chan->chan_type != L2CAP_CHAN_RAW) { 7832162b49e7SJohan Hedberg err = -EINVAL; 7833162b49e7SJohan Hedberg goto done; 7834162b49e7SJohan Hedberg } 7835162b49e7SJohan Hedberg 783621626e62SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !psm) { 783721626e62SJohan Hedberg err = -EINVAL; 783821626e62SJohan Hedberg goto done; 783921626e62SJohan Hedberg } 784021626e62SJohan Hedberg 784121626e62SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_FIXED && !cid) { 7842162b49e7SJohan Hedberg err = -EINVAL; 7843162b49e7SJohan Hedberg goto done; 7844162b49e7SJohan Hedberg } 7845162b49e7SJohan Hedberg 7846162b49e7SJohan Hedberg switch (chan->mode) { 7847162b49e7SJohan Hedberg case L2CAP_MODE_BASIC: 7848162b49e7SJohan Hedberg break; 7849162b49e7SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 78504be5ca67SLuiz Augusto von Dentz break; 785115f02b91SLuiz Augusto von Dentz case L2CAP_MODE_EXT_FLOWCTL: 78524be5ca67SLuiz Augusto von Dentz if (!enable_ecred) { 78534be5ca67SLuiz Augusto von Dentz err = -EOPNOTSUPP; 78544be5ca67SLuiz Augusto von Dentz goto done; 78554be5ca67SLuiz Augusto von Dentz } 7856162b49e7SJohan Hedberg break; 7857162b49e7SJohan Hedberg case L2CAP_MODE_ERTM: 7858162b49e7SJohan Hedberg case L2CAP_MODE_STREAMING: 7859162b49e7SJohan Hedberg if (!disable_ertm) 7860162b49e7SJohan Hedberg break; 786119186c7bSGustavo A. R. Silva fallthrough; 7862162b49e7SJohan Hedberg default: 7863beb19e4cSJohan Hedberg err = -EOPNOTSUPP; 7864162b49e7SJohan Hedberg goto done; 7865162b49e7SJohan Hedberg } 7866162b49e7SJohan Hedberg 7867162b49e7SJohan Hedberg switch (chan->state) { 7868162b49e7SJohan Hedberg case BT_CONNECT: 7869162b49e7SJohan Hedberg case BT_CONNECT2: 7870162b49e7SJohan Hedberg case BT_CONFIG: 7871162b49e7SJohan Hedberg /* Already connecting */ 7872162b49e7SJohan Hedberg err = 0; 7873162b49e7SJohan Hedberg goto done; 7874162b49e7SJohan Hedberg 7875162b49e7SJohan Hedberg case BT_CONNECTED: 7876162b49e7SJohan Hedberg /* Already connected */ 7877162b49e7SJohan Hedberg err = -EISCONN; 7878162b49e7SJohan Hedberg goto done; 7879162b49e7SJohan Hedberg 7880162b49e7SJohan Hedberg case BT_OPEN: 7881162b49e7SJohan Hedberg case BT_BOUND: 7882162b49e7SJohan Hedberg /* Can connect */ 7883162b49e7SJohan Hedberg break; 7884162b49e7SJohan Hedberg 7885162b49e7SJohan Hedberg default: 7886162b49e7SJohan Hedberg err = -EBADFD; 7887162b49e7SJohan Hedberg goto done; 7888162b49e7SJohan Hedberg } 7889162b49e7SJohan Hedberg 7890162b49e7SJohan Hedberg /* Set destination address and psm */ 7891162b49e7SJohan Hedberg bacpy(&chan->dst, dst); 7892162b49e7SJohan Hedberg chan->dst_type = dst_type; 7893162b49e7SJohan Hedberg 7894162b49e7SJohan Hedberg chan->psm = psm; 7895162b49e7SJohan Hedberg chan->dcid = cid; 7896162b49e7SJohan Hedberg 78976f77d8c7SAndre Guedes if (bdaddr_type_is_le(dst_type)) { 78986f77d8c7SAndre Guedes /* Convert from L2CAP channel address type to HCI address type 78996f77d8c7SAndre Guedes */ 79006f77d8c7SAndre Guedes if (dst_type == BDADDR_LE_PUBLIC) 79016f77d8c7SAndre Guedes dst_type = ADDR_LE_DEV_PUBLIC; 79026f77d8c7SAndre Guedes else 79036f77d8c7SAndre Guedes dst_type = ADDR_LE_DEV_RANDOM; 79046f77d8c7SAndre Guedes 7905d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) 79060ad06aa6SJohan Hedberg hcon = hci_connect_le(hdev, dst, dst_type, 7907fa142220SJakub Pawlowski chan->sec_level, 7908fa142220SJakub Pawlowski HCI_LE_CONN_TIMEOUT, 7909082f2300SSzymon Janc HCI_ROLE_SLAVE, NULL); 79100ad06aa6SJohan Hedberg else 79110ad06aa6SJohan Hedberg hcon = hci_connect_le_scan(hdev, dst, dst_type, 79120ad06aa6SJohan Hedberg chan->sec_level, 791376b13996SManish Mandlik HCI_LE_CONN_TIMEOUT, 791476b13996SManish Mandlik CONN_REASON_L2CAP_CHAN); 79150ad06aa6SJohan Hedberg 79166f77d8c7SAndre Guedes } else { 7917d93375a8SJohan Hedberg u8 auth_type = l2cap_get_auth_type(chan); 791876b13996SManish Mandlik hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type, 791976b13996SManish Mandlik CONN_REASON_L2CAP_CHAN); 79206f77d8c7SAndre Guedes } 7921162b49e7SJohan Hedberg 7922162b49e7SJohan Hedberg if (IS_ERR(hcon)) { 7923162b49e7SJohan Hedberg err = PTR_ERR(hcon); 7924162b49e7SJohan Hedberg goto done; 7925162b49e7SJohan Hedberg } 7926162b49e7SJohan Hedberg 7927162b49e7SJohan Hedberg conn = l2cap_conn_add(hcon); 7928162b49e7SJohan Hedberg if (!conn) { 7929162b49e7SJohan Hedberg hci_conn_drop(hcon); 7930162b49e7SJohan Hedberg err = -ENOMEM; 7931162b49e7SJohan Hedberg goto done; 7932162b49e7SJohan Hedberg } 7933162b49e7SJohan Hedberg 7934da49b602SLuiz Augusto von Dentz if (chan->mode == L2CAP_MODE_EXT_FLOWCTL) { 7935da49b602SLuiz Augusto von Dentz struct l2cap_chan_data data; 7936da49b602SLuiz Augusto von Dentz 7937da49b602SLuiz Augusto von Dentz data.chan = chan; 7938da49b602SLuiz Augusto von Dentz data.pid = chan->ops->get_peer_pid(chan); 7939da49b602SLuiz Augusto von Dentz data.count = 1; 7940da49b602SLuiz Augusto von Dentz 7941da49b602SLuiz Augusto von Dentz l2cap_chan_list(conn, l2cap_chan_by_pid, &data); 7942da49b602SLuiz Augusto von Dentz 7943da49b602SLuiz Augusto von Dentz /* Check if there isn't too many channels being connected */ 7944da49b602SLuiz Augusto von Dentz if (data.count > L2CAP_ECRED_CONN_SCID_MAX) { 7945da49b602SLuiz Augusto von Dentz hci_conn_drop(hcon); 7946da49b602SLuiz Augusto von Dentz err = -EPROTO; 7947da49b602SLuiz Augusto von Dentz goto done; 7948da49b602SLuiz Augusto von Dentz } 7949da49b602SLuiz Augusto von Dentz } 7950da49b602SLuiz Augusto von Dentz 795102e246aeSJohan Hedberg mutex_lock(&conn->chan_lock); 795202e246aeSJohan Hedberg l2cap_chan_lock(chan); 795302e246aeSJohan Hedberg 7954162b49e7SJohan Hedberg if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { 7955162b49e7SJohan Hedberg hci_conn_drop(hcon); 7956162b49e7SJohan Hedberg err = -EBUSY; 795702e246aeSJohan Hedberg goto chan_unlock; 7958162b49e7SJohan Hedberg } 7959162b49e7SJohan Hedberg 7960162b49e7SJohan Hedberg /* Update source addr of the socket */ 7961162b49e7SJohan Hedberg bacpy(&chan->src, &hcon->src); 7962a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(hcon); 7963162b49e7SJohan Hedberg 796402e246aeSJohan Hedberg __l2cap_chan_add(conn, chan); 7965162b49e7SJohan Hedberg 7966162b49e7SJohan Hedberg /* l2cap_chan_add takes its own ref so we can drop this one */ 7967162b49e7SJohan Hedberg hci_conn_drop(hcon); 7968162b49e7SJohan Hedberg 7969162b49e7SJohan Hedberg l2cap_state_change(chan, BT_CONNECT); 7970162b49e7SJohan Hedberg __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 7971162b49e7SJohan Hedberg 797261202e4dSJohan Hedberg /* Release chan->sport so that it can be reused by other 797361202e4dSJohan Hedberg * sockets (as it's only used for listening sockets). 797461202e4dSJohan Hedberg */ 797561202e4dSJohan Hedberg write_lock(&chan_list_lock); 797661202e4dSJohan Hedberg chan->sport = 0; 797761202e4dSJohan Hedberg write_unlock(&chan_list_lock); 797861202e4dSJohan Hedberg 7979162b49e7SJohan Hedberg if (hcon->state == BT_CONNECTED) { 7980162b49e7SJohan Hedberg if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 7981162b49e7SJohan Hedberg __clear_chan_timer(chan); 7982e7cafc45SJohan Hedberg if (l2cap_chan_check_security(chan, true)) 7983162b49e7SJohan Hedberg l2cap_state_change(chan, BT_CONNECTED); 7984162b49e7SJohan Hedberg } else 7985162b49e7SJohan Hedberg l2cap_do_start(chan); 7986162b49e7SJohan Hedberg } 7987162b49e7SJohan Hedberg 7988162b49e7SJohan Hedberg err = 0; 7989162b49e7SJohan Hedberg 799002e246aeSJohan Hedberg chan_unlock: 7991162b49e7SJohan Hedberg l2cap_chan_unlock(chan); 799202e246aeSJohan Hedberg mutex_unlock(&conn->chan_lock); 799302e246aeSJohan Hedberg done: 7994162b49e7SJohan Hedberg hci_dev_unlock(hdev); 7995162b49e7SJohan Hedberg hci_dev_put(hdev); 7996162b49e7SJohan Hedberg return err; 7997162b49e7SJohan Hedberg } 79986b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_connect); 7999162b49e7SJohan Hedberg 800015f02b91SLuiz Augusto von Dentz static void l2cap_ecred_reconfigure(struct l2cap_chan *chan) 800115f02b91SLuiz Augusto von Dentz { 800215f02b91SLuiz Augusto von Dentz struct l2cap_conn *conn = chan->conn; 800315f02b91SLuiz Augusto von Dentz struct { 800415f02b91SLuiz Augusto von Dentz struct l2cap_ecred_reconf_req req; 800515f02b91SLuiz Augusto von Dentz __le16 scid; 800615f02b91SLuiz Augusto von Dentz } pdu; 800715f02b91SLuiz Augusto von Dentz 800815f02b91SLuiz Augusto von Dentz pdu.req.mtu = cpu_to_le16(chan->imtu); 800915f02b91SLuiz Augusto von Dentz pdu.req.mps = cpu_to_le16(chan->mps); 801015f02b91SLuiz Augusto von Dentz pdu.scid = cpu_to_le16(chan->scid); 801115f02b91SLuiz Augusto von Dentz 801215f02b91SLuiz Augusto von Dentz chan->ident = l2cap_get_ident(conn); 801315f02b91SLuiz Augusto von Dentz 801415f02b91SLuiz Augusto von Dentz l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_RECONF_REQ, 801515f02b91SLuiz Augusto von Dentz sizeof(pdu), &pdu); 801615f02b91SLuiz Augusto von Dentz } 801715f02b91SLuiz Augusto von Dentz 801815f02b91SLuiz Augusto von Dentz int l2cap_chan_reconfigure(struct l2cap_chan *chan, __u16 mtu) 801915f02b91SLuiz Augusto von Dentz { 802015f02b91SLuiz Augusto von Dentz if (chan->imtu > mtu) 802115f02b91SLuiz Augusto von Dentz return -EINVAL; 802215f02b91SLuiz Augusto von Dentz 802315f02b91SLuiz Augusto von Dentz BT_DBG("chan %p mtu 0x%4.4x", chan, mtu); 802415f02b91SLuiz Augusto von Dentz 802515f02b91SLuiz Augusto von Dentz chan->imtu = mtu; 802615f02b91SLuiz Augusto von Dentz 802715f02b91SLuiz Augusto von Dentz l2cap_ecred_reconfigure(chan); 802815f02b91SLuiz Augusto von Dentz 802915f02b91SLuiz Augusto von Dentz return 0; 803015f02b91SLuiz Augusto von Dentz } 803115f02b91SLuiz Augusto von Dentz 80320a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */ 80330a708f8fSGustavo F. Padovan 8034686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) 80350a708f8fSGustavo F. Padovan { 80360a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0; 803723691d75SGustavo F. Padovan struct l2cap_chan *c; 80380a708f8fSGustavo F. Padovan 80396ed93dc6SAndrei Emeltchenko BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr); 80400a708f8fSGustavo F. Padovan 80410a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */ 804223691d75SGustavo F. Padovan read_lock(&chan_list_lock); 804323691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 804489bc500eSGustavo F. Padovan if (c->state != BT_LISTEN) 80450a708f8fSGustavo F. Padovan continue; 80460a708f8fSGustavo F. Padovan 80477eafc59eSMarcel Holtmann if (!bacmp(&c->src, &hdev->bdaddr)) { 80480a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT; 804943bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 80500a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER; 80510a708f8fSGustavo F. Padovan exact++; 80527eafc59eSMarcel Holtmann } else if (!bacmp(&c->src, BDADDR_ANY)) { 80530a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT; 805443bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 80550a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER; 80560a708f8fSGustavo F. Padovan } 80570a708f8fSGustavo F. Padovan } 805823691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 80590a708f8fSGustavo F. Padovan 80600a708f8fSGustavo F. Padovan return exact ? lm1 : lm2; 80610a708f8fSGustavo F. Padovan } 80620a708f8fSGustavo F. Padovan 8063e760ec12SJohan Hedberg /* Find the next fixed channel in BT_LISTEN state, continue iteration 8064e760ec12SJohan Hedberg * from an existing channel in the list or from the beginning of the 8065e760ec12SJohan Hedberg * global list (by passing NULL as first parameter). 8066e760ec12SJohan Hedberg */ 8067e760ec12SJohan Hedberg static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c, 8068327a7191SJohan Hedberg struct hci_conn *hcon) 8069e760ec12SJohan Hedberg { 8070327a7191SJohan Hedberg u8 src_type = bdaddr_src_type(hcon); 8071327a7191SJohan Hedberg 8072e760ec12SJohan Hedberg read_lock(&chan_list_lock); 8073e760ec12SJohan Hedberg 8074e760ec12SJohan Hedberg if (c) 8075e760ec12SJohan Hedberg c = list_next_entry(c, global_l); 8076e760ec12SJohan Hedberg else 8077e760ec12SJohan Hedberg c = list_entry(chan_list.next, typeof(*c), global_l); 8078e760ec12SJohan Hedberg 8079e760ec12SJohan Hedberg list_for_each_entry_from(c, &chan_list, global_l) { 8080e760ec12SJohan Hedberg if (c->chan_type != L2CAP_CHAN_FIXED) 8081e760ec12SJohan Hedberg continue; 8082e760ec12SJohan Hedberg if (c->state != BT_LISTEN) 8083e760ec12SJohan Hedberg continue; 8084327a7191SJohan Hedberg if (bacmp(&c->src, &hcon->src) && bacmp(&c->src, BDADDR_ANY)) 8085e760ec12SJohan Hedberg continue; 8086327a7191SJohan Hedberg if (src_type != c->src_type) 808754a1b626SJohan Hedberg continue; 8088e760ec12SJohan Hedberg 8089e760ec12SJohan Hedberg l2cap_chan_hold(c); 8090e760ec12SJohan Hedberg read_unlock(&chan_list_lock); 8091e760ec12SJohan Hedberg return c; 8092e760ec12SJohan Hedberg } 8093e760ec12SJohan Hedberg 8094e760ec12SJohan Hedberg read_unlock(&chan_list_lock); 8095e760ec12SJohan Hedberg 8096e760ec12SJohan Hedberg return NULL; 8097e760ec12SJohan Hedberg } 8098e760ec12SJohan Hedberg 8099539c496dSJohan Hedberg static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) 81000a708f8fSGustavo F. Padovan { 8101e760ec12SJohan Hedberg struct hci_dev *hdev = hcon->hdev; 81020a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 8103e760ec12SJohan Hedberg struct l2cap_chan *pchan; 8104e760ec12SJohan Hedberg u8 dst_type; 81050a708f8fSGustavo F. Padovan 8106539c496dSJohan Hedberg if (hcon->type != ACL_LINK && hcon->type != LE_LINK) 8107539c496dSJohan Hedberg return; 8108539c496dSJohan Hedberg 81096ed93dc6SAndrei Emeltchenko BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status); 81100a708f8fSGustavo F. Padovan 8111dc0f5088SJohan Hedberg if (status) { 8112e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status)); 8113dc0f5088SJohan Hedberg return; 8114ba6fc317SAndrei Emeltchenko } 8115dc0f5088SJohan Hedberg 8116dc0f5088SJohan Hedberg conn = l2cap_conn_add(hcon); 8117dc0f5088SJohan Hedberg if (!conn) 8118dc0f5088SJohan Hedberg return; 8119dc0f5088SJohan Hedberg 8120a250e048SJohan Hedberg dst_type = bdaddr_dst_type(hcon); 8121e760ec12SJohan Hedberg 8122e760ec12SJohan Hedberg /* If device is blocked, do not create channels for it */ 8123e760ec12SJohan Hedberg if (hci_bdaddr_list_lookup(&hdev->blacklist, &hcon->dst, dst_type)) 8124e760ec12SJohan Hedberg return; 8125e760ec12SJohan Hedberg 8126e760ec12SJohan Hedberg /* Find fixed channels and notify them of the new connection. We 8127e760ec12SJohan Hedberg * use multiple individual lookups, continuing each time where 8128e760ec12SJohan Hedberg * we left off, because the list lock would prevent calling the 8129e760ec12SJohan Hedberg * potentially sleeping l2cap_chan_lock() function. 8130e760ec12SJohan Hedberg */ 8131327a7191SJohan Hedberg pchan = l2cap_global_fixed_chan(NULL, hcon); 8132e760ec12SJohan Hedberg while (pchan) { 8133e760ec12SJohan Hedberg struct l2cap_chan *chan, *next; 8134e760ec12SJohan Hedberg 8135e760ec12SJohan Hedberg /* Client fixed channels should override server ones */ 8136e760ec12SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, pchan->scid)) 8137e760ec12SJohan Hedberg goto next; 8138e760ec12SJohan Hedberg 8139e760ec12SJohan Hedberg l2cap_chan_lock(pchan); 8140e760ec12SJohan Hedberg chan = pchan->ops->new_connection(pchan); 8141e760ec12SJohan Hedberg if (chan) { 8142e760ec12SJohan Hedberg bacpy(&chan->src, &hcon->src); 8143e760ec12SJohan Hedberg bacpy(&chan->dst, &hcon->dst); 8144a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(hcon); 8145e760ec12SJohan Hedberg chan->dst_type = dst_type; 8146e760ec12SJohan Hedberg 8147e760ec12SJohan Hedberg __l2cap_chan_add(conn, chan); 8148e760ec12SJohan Hedberg } 8149e760ec12SJohan Hedberg 8150e760ec12SJohan Hedberg l2cap_chan_unlock(pchan); 8151e760ec12SJohan Hedberg next: 8152327a7191SJohan Hedberg next = l2cap_global_fixed_chan(pchan, hcon); 8153e760ec12SJohan Hedberg l2cap_chan_put(pchan); 8154e760ec12SJohan Hedberg pchan = next; 8155e760ec12SJohan Hedberg } 8156e760ec12SJohan Hedberg 8157dc0f5088SJohan Hedberg l2cap_conn_ready(conn); 81580a708f8fSGustavo F. Padovan } 81590a708f8fSGustavo F. Padovan 8160686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon) 81610a708f8fSGustavo F. Padovan { 81620a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 81630a708f8fSGustavo F. Padovan 81640a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon); 81650a708f8fSGustavo F. Padovan 8166686ebf28SUlisses Furquim if (!conn) 81679f5a0d7bSAndrei Emeltchenko return HCI_ERROR_REMOTE_USER_TERM; 81680a708f8fSGustavo F. Padovan return conn->disc_reason; 81690a708f8fSGustavo F. Padovan } 81700a708f8fSGustavo F. Padovan 81713a6d576bSJohan Hedberg static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) 81720a708f8fSGustavo F. Padovan { 81733a6d576bSJohan Hedberg if (hcon->type != ACL_LINK && hcon->type != LE_LINK) 81743a6d576bSJohan Hedberg return; 81753a6d576bSJohan Hedberg 81760a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason); 81770a708f8fSGustavo F. Padovan 8178e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason)); 81790a708f8fSGustavo F. Padovan } 81800a708f8fSGustavo F. Padovan 81814343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) 81820a708f8fSGustavo F. Padovan { 8183715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 81840a708f8fSGustavo F. Padovan return; 81850a708f8fSGustavo F. Padovan 81860a708f8fSGustavo F. Padovan if (encrypt == 0x00) { 81874343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) { 8188ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); 81897d513e92SMarcel Holtmann } else if (chan->sec_level == BT_SECURITY_HIGH || 81907d513e92SMarcel Holtmann chan->sec_level == BT_SECURITY_FIPS) 81910f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED); 81920a708f8fSGustavo F. Padovan } else { 81934343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) 8194c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 81950a708f8fSGustavo F. Padovan } 81960a708f8fSGustavo F. Padovan } 81970a708f8fSGustavo F. Padovan 8198354fe804SJohan Hedberg static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) 81990a708f8fSGustavo F. Padovan { 82000a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 820148454079SGustavo F. Padovan struct l2cap_chan *chan; 82020a708f8fSGustavo F. Padovan 82030a708f8fSGustavo F. Padovan if (!conn) 8204354fe804SJohan Hedberg return; 82050a708f8fSGustavo F. Padovan 820689d8b407SAndrei Emeltchenko BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt); 82070a708f8fSGustavo F. Padovan 82083df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 82090a708f8fSGustavo F. Padovan 82103df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 82116be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 82120a708f8fSGustavo F. Padovan 821389d8b407SAndrei Emeltchenko BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, 821489d8b407SAndrei Emeltchenko state_to_string(chan->state)); 8215f1cb9af5SVinicius Costa Gomes 82162338a7e0SJohan Hedberg if (chan->scid == L2CAP_CID_A2MP) { 821778eb2f98SAndrei Emeltchenko l2cap_chan_unlock(chan); 821878eb2f98SAndrei Emeltchenko continue; 821978eb2f98SAndrei Emeltchenko } 822078eb2f98SAndrei Emeltchenko 8221191eb398SJohan Hedberg if (!status && encrypt) 8222f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level; 8223f1cb9af5SVinicius Costa Gomes 822496eff46eSAndrei Emeltchenko if (!__l2cap_no_conn_pending(chan)) { 82256be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 82260a708f8fSGustavo F. Padovan continue; 82270a708f8fSGustavo F. Padovan } 82280a708f8fSGustavo F. Padovan 822989bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED || 823089bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) { 8231d97c899bSMarcel Holtmann chan->ops->resume(chan); 82324343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt); 82336be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 82340a708f8fSGustavo F. Padovan continue; 82350a708f8fSGustavo F. Padovan } 82360a708f8fSGustavo F. Padovan 823789bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 8238693cd8ceSMarcel Holtmann if (!status && l2cap_check_enc_key_size(hcon)) 823993c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 82406d3c15daSJohan Hedberg else 8241ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 8242fa37c1aaSJohan Hedberg } else if (chan->state == BT_CONNECT2 && 824315f02b91SLuiz Augusto von Dentz !(chan->mode == L2CAP_MODE_EXT_FLOWCTL || 824415f02b91SLuiz Augusto von Dentz chan->mode == L2CAP_MODE_LE_FLOWCTL)) { 82450a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 8246df3c3931SJohan Hedberg __u16 res, stat; 82470a708f8fSGustavo F. Padovan 8248693cd8ceSMarcel Holtmann if (!status && l2cap_check_enc_key_size(hcon)) { 8249bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 8250df3c3931SJohan Hedberg res = L2CAP_CR_PEND; 8251df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND; 82522dc4e510SGustavo Padovan chan->ops->defer(chan); 8253df3c3931SJohan Hedberg } else { 8254acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 8255df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS; 8256df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 8257df3c3931SJohan Hedberg } 82580a708f8fSGustavo F. Padovan } else { 8259acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_DISCONN); 8260ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 8261df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK; 8262df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 82630a708f8fSGustavo F. Padovan } 82640a708f8fSGustavo F. Padovan 8265fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 8266fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 8267df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res); 8268df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat); 8269fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 8270fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 82712d369359SMat Martineau 82722d369359SMat Martineau if (!test_bit(CONF_REQ_SENT, &chan->conf_state) && 82732d369359SMat Martineau res == L2CAP_CR_SUCCESS) { 82742d369359SMat Martineau char buf[128]; 82752d369359SMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 82762d369359SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), 82772d369359SMat Martineau L2CAP_CONF_REQ, 8278e860d2c9SBen Seri l2cap_build_conf_req(chan, buf, sizeof(buf)), 82792d369359SMat Martineau buf); 82802d369359SMat Martineau chan->num_conf_req++; 82812d369359SMat Martineau } 82820a708f8fSGustavo F. Padovan } 82830a708f8fSGustavo F. Padovan 82846be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 82850a708f8fSGustavo F. Padovan } 82860a708f8fSGustavo F. Padovan 82873df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 82880a708f8fSGustavo F. Padovan } 82890a708f8fSGustavo F. Padovan 82904d7ea8eeSLuiz Augusto von Dentz /* Append fragment into frame respecting the maximum len of rx_skb */ 82914d7ea8eeSLuiz Augusto von Dentz static int l2cap_recv_frag(struct l2cap_conn *conn, struct sk_buff *skb, 82924d7ea8eeSLuiz Augusto von Dentz u16 len) 82934d7ea8eeSLuiz Augusto von Dentz { 82944d7ea8eeSLuiz Augusto von Dentz if (!conn->rx_skb) { 82954d7ea8eeSLuiz Augusto von Dentz /* Allocate skb for the complete frame (with header) */ 82964d7ea8eeSLuiz Augusto von Dentz conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL); 82974d7ea8eeSLuiz Augusto von Dentz if (!conn->rx_skb) 82984d7ea8eeSLuiz Augusto von Dentz return -ENOMEM; 82994d7ea8eeSLuiz Augusto von Dentz /* Init rx_len */ 83004d7ea8eeSLuiz Augusto von Dentz conn->rx_len = len; 83014d7ea8eeSLuiz Augusto von Dentz } 83024d7ea8eeSLuiz Augusto von Dentz 83034d7ea8eeSLuiz Augusto von Dentz /* Copy as much as the rx_skb can hold */ 83044d7ea8eeSLuiz Augusto von Dentz len = min_t(u16, len, skb->len); 83054d7ea8eeSLuiz Augusto von Dentz skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, len), len); 83064d7ea8eeSLuiz Augusto von Dentz skb_pull(skb, len); 83074d7ea8eeSLuiz Augusto von Dentz conn->rx_len -= len; 83084d7ea8eeSLuiz Augusto von Dentz 83094d7ea8eeSLuiz Augusto von Dentz return len; 83104d7ea8eeSLuiz Augusto von Dentz } 83114d7ea8eeSLuiz Augusto von Dentz 83124d7ea8eeSLuiz Augusto von Dentz static int l2cap_recv_len(struct l2cap_conn *conn, struct sk_buff *skb) 83134d7ea8eeSLuiz Augusto von Dentz { 83144d7ea8eeSLuiz Augusto von Dentz struct sk_buff *rx_skb; 83154d7ea8eeSLuiz Augusto von Dentz int len; 83164d7ea8eeSLuiz Augusto von Dentz 83174d7ea8eeSLuiz Augusto von Dentz /* Append just enough to complete the header */ 83184d7ea8eeSLuiz Augusto von Dentz len = l2cap_recv_frag(conn, skb, L2CAP_LEN_SIZE - conn->rx_skb->len); 83194d7ea8eeSLuiz Augusto von Dentz 83204d7ea8eeSLuiz Augusto von Dentz /* If header could not be read just continue */ 83214d7ea8eeSLuiz Augusto von Dentz if (len < 0 || conn->rx_skb->len < L2CAP_LEN_SIZE) 83224d7ea8eeSLuiz Augusto von Dentz return len; 83234d7ea8eeSLuiz Augusto von Dentz 83244d7ea8eeSLuiz Augusto von Dentz rx_skb = conn->rx_skb; 83254d7ea8eeSLuiz Augusto von Dentz len = get_unaligned_le16(rx_skb->data); 83264d7ea8eeSLuiz Augusto von Dentz 83274d7ea8eeSLuiz Augusto von Dentz /* Check if rx_skb has enough space to received all fragments */ 83284d7ea8eeSLuiz Augusto von Dentz if (len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE) <= skb_tailroom(rx_skb)) { 83294d7ea8eeSLuiz Augusto von Dentz /* Update expected len */ 83304d7ea8eeSLuiz Augusto von Dentz conn->rx_len = len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE); 83314d7ea8eeSLuiz Augusto von Dentz return L2CAP_LEN_SIZE; 83324d7ea8eeSLuiz Augusto von Dentz } 83334d7ea8eeSLuiz Augusto von Dentz 83344d7ea8eeSLuiz Augusto von Dentz /* Reset conn->rx_skb since it will need to be reallocated in order to 83354d7ea8eeSLuiz Augusto von Dentz * fit all fragments. 83364d7ea8eeSLuiz Augusto von Dentz */ 83374d7ea8eeSLuiz Augusto von Dentz conn->rx_skb = NULL; 83384d7ea8eeSLuiz Augusto von Dentz 83394d7ea8eeSLuiz Augusto von Dentz /* Reallocates rx_skb using the exact expected length */ 83404d7ea8eeSLuiz Augusto von Dentz len = l2cap_recv_frag(conn, rx_skb, 83414d7ea8eeSLuiz Augusto von Dentz len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE)); 83424d7ea8eeSLuiz Augusto von Dentz kfree_skb(rx_skb); 83434d7ea8eeSLuiz Augusto von Dentz 83444d7ea8eeSLuiz Augusto von Dentz return len; 83454d7ea8eeSLuiz Augusto von Dentz } 83464d7ea8eeSLuiz Augusto von Dentz 83474d7ea8eeSLuiz Augusto von Dentz static void l2cap_recv_reset(struct l2cap_conn *conn) 83484d7ea8eeSLuiz Augusto von Dentz { 83494d7ea8eeSLuiz Augusto von Dentz kfree_skb(conn->rx_skb); 83504d7ea8eeSLuiz Augusto von Dentz conn->rx_skb = NULL; 83514d7ea8eeSLuiz Augusto von Dentz conn->rx_len = 0; 83524d7ea8eeSLuiz Augusto von Dentz } 83534d7ea8eeSLuiz Augusto von Dentz 83549b4c3336SArron Wang void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) 83550a708f8fSGustavo F. Padovan { 83560a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 8357d73a0988SAndrei Emeltchenko int len; 83580a708f8fSGustavo F. Padovan 83591d13a254SAndrei Emeltchenko /* For AMP controller do not create l2cap conn */ 8360ca8bee5dSMarcel Holtmann if (!conn && hcon->hdev->dev_type != HCI_PRIMARY) 83611d13a254SAndrei Emeltchenko goto drop; 83620a708f8fSGustavo F. Padovan 83630a708f8fSGustavo F. Padovan if (!conn) 8364baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon); 83650a708f8fSGustavo F. Padovan 83660a708f8fSGustavo F. Padovan if (!conn) 83670a708f8fSGustavo F. Padovan goto drop; 83680a708f8fSGustavo F. Padovan 83690a708f8fSGustavo F. Padovan BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); 83700a708f8fSGustavo F. Padovan 8371d73a0988SAndrei Emeltchenko switch (flags) { 8372d73a0988SAndrei Emeltchenko case ACL_START: 8373d73a0988SAndrei Emeltchenko case ACL_START_NO_FLUSH: 8374d73a0988SAndrei Emeltchenko case ACL_COMPLETE: 83754d7ea8eeSLuiz Augusto von Dentz if (conn->rx_skb) { 83760a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len); 83774d7ea8eeSLuiz Augusto von Dentz l2cap_recv_reset(conn); 83780a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 83790a708f8fSGustavo F. Padovan } 83800a708f8fSGustavo F. Padovan 83814d7ea8eeSLuiz Augusto von Dentz /* Start fragment may not contain the L2CAP length so just 83824d7ea8eeSLuiz Augusto von Dentz * copy the initial byte when that happens and use conn->mtu as 83834d7ea8eeSLuiz Augusto von Dentz * expected length. 83844d7ea8eeSLuiz Augusto von Dentz */ 83854d7ea8eeSLuiz Augusto von Dentz if (skb->len < L2CAP_LEN_SIZE) { 83864d7ea8eeSLuiz Augusto von Dentz if (l2cap_recv_frag(conn, skb, conn->mtu) < 0) 83870a708f8fSGustavo F. Padovan goto drop; 83884d7ea8eeSLuiz Augusto von Dentz return; 83890a708f8fSGustavo F. Padovan } 83900a708f8fSGustavo F. Padovan 83914d7ea8eeSLuiz Augusto von Dentz len = get_unaligned_le16(skb->data) + L2CAP_HDR_SIZE; 83920a708f8fSGustavo F. Padovan 83930a708f8fSGustavo F. Padovan if (len == skb->len) { 83940a708f8fSGustavo F. Padovan /* Complete frame received */ 83950a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb); 83969b4c3336SArron Wang return; 83970a708f8fSGustavo F. Padovan } 83980a708f8fSGustavo F. Padovan 83990a708f8fSGustavo F. Padovan BT_DBG("Start: total len %d, frag len %d", len, skb->len); 84000a708f8fSGustavo F. Padovan 84010a708f8fSGustavo F. Padovan if (skb->len > len) { 84020a708f8fSGustavo F. Padovan BT_ERR("Frame is too long (len %d, expected len %d)", 84030a708f8fSGustavo F. Padovan skb->len, len); 84040a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 84050a708f8fSGustavo F. Padovan goto drop; 84060a708f8fSGustavo F. Padovan } 84070a708f8fSGustavo F. Padovan 84084d7ea8eeSLuiz Augusto von Dentz /* Append fragment into frame (with header) */ 84094d7ea8eeSLuiz Augusto von Dentz if (l2cap_recv_frag(conn, skb, len) < 0) 84100a708f8fSGustavo F. Padovan goto drop; 84110a708f8fSGustavo F. Padovan 8412d73a0988SAndrei Emeltchenko break; 8413d73a0988SAndrei Emeltchenko 8414d73a0988SAndrei Emeltchenko case ACL_CONT: 84150a708f8fSGustavo F. Padovan BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); 84160a708f8fSGustavo F. Padovan 84174d7ea8eeSLuiz Augusto von Dentz if (!conn->rx_skb) { 84180a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len); 84190a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 84200a708f8fSGustavo F. Padovan goto drop; 84210a708f8fSGustavo F. Padovan } 84220a708f8fSGustavo F. Padovan 84234d7ea8eeSLuiz Augusto von Dentz /* Complete the L2CAP length if it has not been read */ 84244d7ea8eeSLuiz Augusto von Dentz if (conn->rx_skb->len < L2CAP_LEN_SIZE) { 84254d7ea8eeSLuiz Augusto von Dentz if (l2cap_recv_len(conn, skb) < 0) { 84260a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 84270a708f8fSGustavo F. Padovan goto drop; 84280a708f8fSGustavo F. Padovan } 84290a708f8fSGustavo F. Padovan 84304d7ea8eeSLuiz Augusto von Dentz /* Header still could not be read just continue */ 84314d7ea8eeSLuiz Augusto von Dentz if (conn->rx_skb->len < L2CAP_LEN_SIZE) 84324d7ea8eeSLuiz Augusto von Dentz return; 84334d7ea8eeSLuiz Augusto von Dentz } 84344d7ea8eeSLuiz Augusto von Dentz 84354d7ea8eeSLuiz Augusto von Dentz if (skb->len > conn->rx_len) { 84364d7ea8eeSLuiz Augusto von Dentz BT_ERR("Fragment is too long (len %d, expected %d)", 84374d7ea8eeSLuiz Augusto von Dentz skb->len, conn->rx_len); 84384d7ea8eeSLuiz Augusto von Dentz l2cap_recv_reset(conn); 84394d7ea8eeSLuiz Augusto von Dentz l2cap_conn_unreliable(conn, ECOMM); 84404d7ea8eeSLuiz Augusto von Dentz goto drop; 84414d7ea8eeSLuiz Augusto von Dentz } 84424d7ea8eeSLuiz Augusto von Dentz 84434d7ea8eeSLuiz Augusto von Dentz /* Append fragment into frame (with header) */ 84444d7ea8eeSLuiz Augusto von Dentz l2cap_recv_frag(conn, skb, skb->len); 84450a708f8fSGustavo F. Padovan 84460a708f8fSGustavo F. Padovan if (!conn->rx_len) { 8447c4e5bafaSJohan Hedberg /* Complete frame received. l2cap_recv_frame 8448c4e5bafaSJohan Hedberg * takes ownership of the skb so set the global 8449c4e5bafaSJohan Hedberg * rx_skb pointer to NULL first. 8450c4e5bafaSJohan Hedberg */ 8451c4e5bafaSJohan Hedberg struct sk_buff *rx_skb = conn->rx_skb; 84520a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 8453c4e5bafaSJohan Hedberg l2cap_recv_frame(conn, rx_skb); 84540a708f8fSGustavo F. Padovan } 8455d73a0988SAndrei Emeltchenko break; 84560a708f8fSGustavo F. Padovan } 84570a708f8fSGustavo F. Padovan 84580a708f8fSGustavo F. Padovan drop: 84590a708f8fSGustavo F. Padovan kfree_skb(skb); 84600a708f8fSGustavo F. Padovan } 84610a708f8fSGustavo F. Padovan 8462354fe804SJohan Hedberg static struct hci_cb l2cap_cb = { 8463354fe804SJohan Hedberg .name = "L2CAP", 8464539c496dSJohan Hedberg .connect_cfm = l2cap_connect_cfm, 84653a6d576bSJohan Hedberg .disconn_cfm = l2cap_disconn_cfm, 8466354fe804SJohan Hedberg .security_cfm = l2cap_security_cfm, 8467354fe804SJohan Hedberg }; 8468354fe804SJohan Hedberg 84690a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p) 84700a708f8fSGustavo F. Padovan { 847123691d75SGustavo F. Padovan struct l2cap_chan *c; 84720a708f8fSGustavo F. Padovan 8473333055f2SGustavo F. Padovan read_lock(&chan_list_lock); 84740a708f8fSGustavo F. Padovan 847523691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 8476eeb5a067SMarcel Holtmann seq_printf(f, "%pMR (%u) %pMR (%u) %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", 8477eeb5a067SMarcel Holtmann &c->src, c->src_type, &c->dst, c->dst_type, 847889bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm), 847923691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu, 848023691d75SGustavo F. Padovan c->sec_level, c->mode); 84810a708f8fSGustavo F. Padovan } 84820a708f8fSGustavo F. Padovan 8483333055f2SGustavo F. Padovan read_unlock(&chan_list_lock); 84840a708f8fSGustavo F. Padovan 84850a708f8fSGustavo F. Padovan return 0; 84860a708f8fSGustavo F. Padovan } 84870a708f8fSGustavo F. Padovan 84888e2924e3SYangtao Li DEFINE_SHOW_ATTRIBUTE(l2cap_debugfs); 84890a708f8fSGustavo F. Padovan 84900a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs; 84910a708f8fSGustavo F. Padovan 849264274518SGustavo F. Padovan int __init l2cap_init(void) 84930a708f8fSGustavo F. Padovan { 84940a708f8fSGustavo F. Padovan int err; 84950a708f8fSGustavo F. Padovan 8496bb58f747SGustavo F. Padovan err = l2cap_init_sockets(); 84970a708f8fSGustavo F. Padovan if (err < 0) 84980a708f8fSGustavo F. Padovan return err; 84990a708f8fSGustavo F. Padovan 8500354fe804SJohan Hedberg hci_register_cb(&l2cap_cb); 8501354fe804SJohan Hedberg 85021120e4bfSMarcel Holtmann if (IS_ERR_OR_NULL(bt_debugfs)) 85031120e4bfSMarcel Holtmann return 0; 85041120e4bfSMarcel Holtmann 85052d792818SGustavo Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, 85062d792818SGustavo Padovan NULL, &l2cap_debugfs_fops); 85070a708f8fSGustavo F. Padovan 85080a708f8fSGustavo F. Padovan return 0; 85090a708f8fSGustavo F. Padovan } 85100a708f8fSGustavo F. Padovan 851164274518SGustavo F. Padovan void l2cap_exit(void) 85120a708f8fSGustavo F. Padovan { 85130a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs); 8514354fe804SJohan Hedberg hci_unregister_cb(&l2cap_cb); 8515bb58f747SGustavo F. Padovan l2cap_cleanup_sockets(); 85160a708f8fSGustavo F. Padovan } 85170a708f8fSGustavo F. Padovan 85180a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644); 85190a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); 85204be5ca67SLuiz Augusto von Dentz 85214be5ca67SLuiz Augusto von Dentz module_param(enable_ecred, bool, 0644); 85224be5ca67SLuiz Augusto von Dentz MODULE_PARM_DESC(enable_ecred, "Enable enhanced credit flow control mode"); 8523