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> 350a708f8fSGustavo F. Padovan 360a708f8fSGustavo F. Padovan #include <net/bluetooth/bluetooth.h> 370a708f8fSGustavo F. Padovan #include <net/bluetooth/hci_core.h> 380a708f8fSGustavo F. Padovan #include <net/bluetooth/l2cap.h> 397ef9fbf0SMarcel Holtmann 40ac4b7236SMarcel Holtmann #include "smp.h" 417024728eSMarcel Holtmann #include "a2mp.h" 427ef9fbf0SMarcel Holtmann #include "amp.h" 430a708f8fSGustavo F. Padovan 440f1bfe4eSJohan Hedberg #define LE_FLOWCTL_MAX_CREDITS 65535 450f1bfe4eSJohan Hedberg 46d1de6d46SMat Martineau bool disable_ertm; 470a708f8fSGustavo F. Padovan 48547d1032SMarcel Holtmann static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD; 490a708f8fSGustavo F. Padovan 50b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list); 51b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock); 520a708f8fSGustavo F. Padovan 53f15b8ecfSJohan Hedberg static u16 le_max_credits = L2CAP_LE_MAX_CREDITS; 54f15b8ecfSJohan Hedberg static u16 le_default_mps = L2CAP_LE_DEFAULT_MPS; 55f15b8ecfSJohan Hedberg 560a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 570a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data); 584519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 594519de9aSGustavo F. Padovan void *data); 60710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); 615e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err); 620a708f8fSGustavo F. Padovan 63d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 64608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event); 65608bcc6dSMat Martineau 66a250e048SJohan Hedberg static inline u8 bdaddr_type(u8 link_type, u8 bdaddr_type) 674f1654e0SMarcel Holtmann { 68a250e048SJohan Hedberg if (link_type == LE_LINK) { 69a250e048SJohan Hedberg if (bdaddr_type == ADDR_LE_DEV_PUBLIC) 704f1654e0SMarcel Holtmann return BDADDR_LE_PUBLIC; 714f1654e0SMarcel Holtmann else 724f1654e0SMarcel Holtmann return BDADDR_LE_RANDOM; 734f1654e0SMarcel Holtmann } 744f1654e0SMarcel Holtmann 754f1654e0SMarcel Holtmann return BDADDR_BREDR; 764f1654e0SMarcel Holtmann } 774f1654e0SMarcel Holtmann 78a250e048SJohan Hedberg static inline u8 bdaddr_src_type(struct hci_conn *hcon) 79a250e048SJohan Hedberg { 80a250e048SJohan Hedberg return bdaddr_type(hcon->type, hcon->src_type); 81a250e048SJohan Hedberg } 82a250e048SJohan Hedberg 83a250e048SJohan Hedberg static inline u8 bdaddr_dst_type(struct hci_conn *hcon) 84a250e048SJohan Hedberg { 85a250e048SJohan Hedberg return bdaddr_type(hcon->type, hcon->dst_type); 86a250e048SJohan Hedberg } 87a250e048SJohan Hedberg 880a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */ 8971ba0e56SGustavo F. Padovan 902d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, 912d792818SGustavo Padovan u16 cid) 920a708f8fSGustavo F. Padovan { 933df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 94baa7e1faSGustavo F. Padovan 953df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 963df91ea2SAndrei Emeltchenko if (c->dcid == cid) 973df91ea2SAndrei Emeltchenko return c; 980a708f8fSGustavo F. Padovan } 993df91ea2SAndrei Emeltchenko return NULL; 100baa7e1faSGustavo F. Padovan } 1010a708f8fSGustavo F. Padovan 1022d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, 1032d792818SGustavo Padovan u16 cid) 1040a708f8fSGustavo F. Padovan { 1053df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 106baa7e1faSGustavo F. Padovan 1073df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 1083df91ea2SAndrei Emeltchenko if (c->scid == cid) 1093df91ea2SAndrei Emeltchenko return c; 1100a708f8fSGustavo F. Padovan } 1113df91ea2SAndrei Emeltchenko return NULL; 112baa7e1faSGustavo F. Padovan } 1130a708f8fSGustavo F. Padovan 1140a708f8fSGustavo F. Padovan /* Find channel with given SCID. 115ef191adeSMat Martineau * Returns locked channel. */ 1162d792818SGustavo Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, 1172d792818SGustavo Padovan u16 cid) 1180a708f8fSGustavo F. Padovan { 11948454079SGustavo F. Padovan struct l2cap_chan *c; 120baa7e1faSGustavo F. Padovan 1213df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 122baa7e1faSGustavo F. Padovan c = __l2cap_get_chan_by_scid(conn, cid); 123ef191adeSMat Martineau if (c) 124ef191adeSMat Martineau l2cap_chan_lock(c); 1253df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 1263df91ea2SAndrei Emeltchenko 12748454079SGustavo F. Padovan return c; 1280a708f8fSGustavo F. Padovan } 1290a708f8fSGustavo F. Padovan 130b1a130b7SMat Martineau /* Find channel with given DCID. 131b1a130b7SMat Martineau * Returns locked channel. 132b1a130b7SMat Martineau */ 133b1a130b7SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn, 134b1a130b7SMat Martineau u16 cid) 135b1a130b7SMat Martineau { 136b1a130b7SMat Martineau struct l2cap_chan *c; 137b1a130b7SMat Martineau 138b1a130b7SMat Martineau mutex_lock(&conn->chan_lock); 139b1a130b7SMat Martineau c = __l2cap_get_chan_by_dcid(conn, cid); 140b1a130b7SMat Martineau if (c) 141b1a130b7SMat Martineau l2cap_chan_lock(c); 142b1a130b7SMat Martineau mutex_unlock(&conn->chan_lock); 143b1a130b7SMat Martineau 144b1a130b7SMat Martineau return c; 145b1a130b7SMat Martineau } 146b1a130b7SMat Martineau 1472d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, 1482d792818SGustavo Padovan u8 ident) 1490a708f8fSGustavo F. Padovan { 1503df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 151baa7e1faSGustavo F. Padovan 1523df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 1533df91ea2SAndrei Emeltchenko if (c->ident == ident) 1543df91ea2SAndrei Emeltchenko return c; 1550a708f8fSGustavo F. Padovan } 1563df91ea2SAndrei Emeltchenko return NULL; 157baa7e1faSGustavo F. Padovan } 1580a708f8fSGustavo F. Padovan 1595b155ef9SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, 1605b155ef9SMat Martineau u8 ident) 1615b155ef9SMat Martineau { 1625b155ef9SMat Martineau struct l2cap_chan *c; 1635b155ef9SMat Martineau 1645b155ef9SMat Martineau mutex_lock(&conn->chan_lock); 1655b155ef9SMat Martineau c = __l2cap_get_chan_by_ident(conn, ident); 1665b155ef9SMat Martineau if (c) 1675b155ef9SMat Martineau l2cap_chan_lock(c); 1685b155ef9SMat Martineau mutex_unlock(&conn->chan_lock); 1695b155ef9SMat Martineau 1705b155ef9SMat Martineau return c; 1715b155ef9SMat Martineau } 1725b155ef9SMat Martineau 17323691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src) 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) { 1787eafc59eSMarcel Holtmann if (c->sport == psm && !bacmp(&c->src, src)) 17923691d75SGustavo F. Padovan return c; 1809e4425ffSGustavo F. Padovan } 181250938cbSSzymon Janc return NULL; 182250938cbSSzymon Janc } 1839e4425ffSGustavo F. Padovan 1849e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) 1859e4425ffSGustavo F. Padovan { 18673b2ec18SGustavo F. Padovan int err; 18773b2ec18SGustavo F. Padovan 188333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 1899e4425ffSGustavo F. Padovan 19023691d75SGustavo F. Padovan if (psm && __l2cap_global_chan_by_addr(psm, src)) { 19173b2ec18SGustavo F. Padovan err = -EADDRINUSE; 19273b2ec18SGustavo F. Padovan goto done; 1939e4425ffSGustavo F. Padovan } 1949e4425ffSGustavo F. Padovan 19573b2ec18SGustavo F. Padovan if (psm) { 1969e4425ffSGustavo F. Padovan chan->psm = psm; 1979e4425ffSGustavo F. Padovan chan->sport = psm; 19873b2ec18SGustavo F. Padovan err = 0; 19973b2ec18SGustavo F. Padovan } else { 20073b2ec18SGustavo F. Padovan u16 p; 2019e4425ffSGustavo F. Padovan 20273b2ec18SGustavo F. Padovan err = -EINVAL; 20373b2ec18SGustavo F. Padovan for (p = 0x1001; p < 0x1100; p += 2) 20423691d75SGustavo F. Padovan if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) { 20573b2ec18SGustavo F. Padovan chan->psm = cpu_to_le16(p); 20673b2ec18SGustavo F. Padovan chan->sport = cpu_to_le16(p); 20773b2ec18SGustavo F. Padovan err = 0; 20873b2ec18SGustavo F. Padovan break; 20973b2ec18SGustavo F. Padovan } 21073b2ec18SGustavo F. Padovan } 21173b2ec18SGustavo F. Padovan 21273b2ec18SGustavo F. Padovan done: 213333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 21473b2ec18SGustavo F. Padovan return err; 2159e4425ffSGustavo F. Padovan } 2166b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_add_psm); 2179e4425ffSGustavo F. Padovan 2189e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) 2199e4425ffSGustavo F. Padovan { 220333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 2219e4425ffSGustavo F. Padovan 22214824308SJohan Hedberg /* Override the defaults (which are for conn-oriented) */ 22314824308SJohan Hedberg chan->omtu = L2CAP_DEFAULT_MTU; 22414824308SJohan Hedberg chan->chan_type = L2CAP_CHAN_FIXED; 22514824308SJohan Hedberg 2269e4425ffSGustavo F. Padovan chan->scid = scid; 2279e4425ffSGustavo F. Padovan 228333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 2299e4425ffSGustavo F. Padovan 2309e4425ffSGustavo F. Padovan return 0; 2319e4425ffSGustavo F. Padovan } 2329e4425ffSGustavo F. Padovan 233baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn) 2340a708f8fSGustavo F. Padovan { 235e77af755SJohan Hedberg u16 cid, dyn_end; 2360a708f8fSGustavo F. Padovan 237e77af755SJohan Hedberg if (conn->hcon->type == LE_LINK) 238e77af755SJohan Hedberg dyn_end = L2CAP_CID_LE_DYN_END; 239e77af755SJohan Hedberg else 240e77af755SJohan Hedberg dyn_end = L2CAP_CID_DYN_END; 241e77af755SJohan Hedberg 242e77af755SJohan Hedberg for (cid = L2CAP_CID_DYN_START; cid < dyn_end; cid++) { 243baa7e1faSGustavo F. Padovan if (!__l2cap_get_chan_by_scid(conn, cid)) 2440a708f8fSGustavo F. Padovan return cid; 2450a708f8fSGustavo F. Padovan } 2460a708f8fSGustavo F. Padovan 2470a708f8fSGustavo F. Padovan return 0; 2480a708f8fSGustavo F. Padovan } 2490a708f8fSGustavo F. Padovan 250f93fa273SGustavo Padovan static void l2cap_state_change(struct l2cap_chan *chan, int state) 25189bc500eSGustavo F. Padovan { 25242d2d87cSAndrei Emeltchenko BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state), 253badaaa00SGustavo F. Padovan state_to_string(state)); 254badaaa00SGustavo F. Padovan 25589bc500eSGustavo F. Padovan chan->state = state; 25653f52121SGustavo Padovan chan->ops->state_change(chan, state, 0); 25789bc500eSGustavo F. Padovan } 25889bc500eSGustavo F. Padovan 259f8e73017SGustavo Padovan static inline void l2cap_state_change_and_error(struct l2cap_chan *chan, 260f8e73017SGustavo Padovan int state, int err) 2612e0052e4SAndrei Emeltchenko { 262f8e73017SGustavo Padovan chan->state = state; 26353f52121SGustavo Padovan chan->ops->state_change(chan, chan->state, err); 2642e0052e4SAndrei Emeltchenko } 2652e0052e4SAndrei Emeltchenko 2662e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err) 2672e0052e4SAndrei Emeltchenko { 268f8e73017SGustavo Padovan chan->ops->state_change(chan, chan->state, err); 2692e0052e4SAndrei Emeltchenko } 2702e0052e4SAndrei Emeltchenko 2714239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan) 2724239d16fSMat Martineau { 2734239d16fSMat Martineau if (!delayed_work_pending(&chan->monitor_timer) && 2744239d16fSMat Martineau chan->retrans_timeout) { 2754239d16fSMat Martineau l2cap_set_timer(chan, &chan->retrans_timer, 2764239d16fSMat Martineau msecs_to_jiffies(chan->retrans_timeout)); 2774239d16fSMat Martineau } 2784239d16fSMat Martineau } 2794239d16fSMat Martineau 2804239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan) 2814239d16fSMat Martineau { 2824239d16fSMat Martineau __clear_retrans_timer(chan); 2834239d16fSMat Martineau if (chan->monitor_timeout) { 2844239d16fSMat Martineau l2cap_set_timer(chan, &chan->monitor_timer, 2854239d16fSMat Martineau msecs_to_jiffies(chan->monitor_timeout)); 2864239d16fSMat Martineau } 2874239d16fSMat Martineau } 2884239d16fSMat Martineau 289608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head, 290608bcc6dSMat Martineau u16 seq) 291608bcc6dSMat Martineau { 292608bcc6dSMat Martineau struct sk_buff *skb; 293608bcc6dSMat Martineau 294608bcc6dSMat Martineau skb_queue_walk(head, skb) { 295a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.txseq == seq) 296608bcc6dSMat Martineau return skb; 297608bcc6dSMat Martineau } 298608bcc6dSMat Martineau 299608bcc6dSMat Martineau return NULL; 300608bcc6dSMat Martineau } 301608bcc6dSMat Martineau 3023c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */ 3033c588192SMat Martineau 3043c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for 3053c588192SMat Martineau * SREJ requests that are received and for frames that are to be 3063c588192SMat Martineau * retransmitted. These seq_list functions implement a singly-linked 3073c588192SMat Martineau * list in an array, where membership in the list can also be checked 3083c588192SMat Martineau * in constant time. Items can also be added to the tail of the list 3093c588192SMat Martineau * and removed from the head in constant time, without further memory 3103c588192SMat Martineau * allocs or frees. 3113c588192SMat Martineau */ 3123c588192SMat Martineau 3133c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size) 3143c588192SMat Martineau { 3153c588192SMat Martineau size_t alloc_size, i; 3163c588192SMat Martineau 3173c588192SMat Martineau /* Allocated size is a power of 2 to map sequence numbers 3183c588192SMat Martineau * (which may be up to 14 bits) in to a smaller array that is 3193c588192SMat Martineau * sized for the negotiated ERTM transmit windows. 3203c588192SMat Martineau */ 3213c588192SMat Martineau alloc_size = roundup_pow_of_two(size); 3223c588192SMat Martineau 3233c588192SMat Martineau seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL); 3243c588192SMat Martineau if (!seq_list->list) 3253c588192SMat Martineau return -ENOMEM; 3263c588192SMat Martineau 3273c588192SMat Martineau seq_list->mask = alloc_size - 1; 3283c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3293c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3303c588192SMat Martineau for (i = 0; i < alloc_size; i++) 3313c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 3323c588192SMat Martineau 3333c588192SMat Martineau return 0; 3343c588192SMat Martineau } 3353c588192SMat Martineau 3363c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list) 3373c588192SMat Martineau { 3383c588192SMat Martineau kfree(seq_list->list); 3393c588192SMat Martineau } 3403c588192SMat Martineau 3413c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list, 3423c588192SMat Martineau u16 seq) 3433c588192SMat Martineau { 3443c588192SMat Martineau /* Constant-time check for list membership */ 3453c588192SMat Martineau return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR; 3463c588192SMat Martineau } 3473c588192SMat Martineau 34803a0c5d6SJohan Hedberg static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list) 3493c588192SMat Martineau { 35003a0c5d6SJohan Hedberg u16 seq = seq_list->head; 3513c588192SMat Martineau u16 mask = seq_list->mask; 3523c588192SMat Martineau 3533c588192SMat Martineau seq_list->head = seq_list->list[seq & mask]; 3543c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; 3553c588192SMat Martineau 3563c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_TAIL) { 3573c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3583c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3593c588192SMat Martineau } 3603c588192SMat Martineau 3613c588192SMat Martineau return seq; 3623c588192SMat Martineau } 3633c588192SMat Martineau 3643c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list) 3653c588192SMat Martineau { 3663c588192SMat Martineau u16 i; 367f522ae36SGustavo Padovan 368f522ae36SGustavo Padovan if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) 369f522ae36SGustavo Padovan return; 370f522ae36SGustavo Padovan 3713c588192SMat Martineau for (i = 0; i <= seq_list->mask; i++) 3723c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 3733c588192SMat Martineau 3743c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3753c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3763c588192SMat Martineau } 3773c588192SMat Martineau 3783c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq) 3793c588192SMat Martineau { 3803c588192SMat Martineau u16 mask = seq_list->mask; 3813c588192SMat Martineau 3823c588192SMat Martineau /* All appends happen in constant time */ 3833c588192SMat Martineau 384f522ae36SGustavo Padovan if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR) 385f522ae36SGustavo Padovan return; 386f522ae36SGustavo Padovan 3873c588192SMat Martineau if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR) 3883c588192SMat Martineau seq_list->head = seq; 3893c588192SMat Martineau else 3903c588192SMat Martineau seq_list->list[seq_list->tail & mask] = seq; 3913c588192SMat Martineau 3923c588192SMat Martineau seq_list->tail = seq; 3933c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL; 3943c588192SMat Martineau } 3953c588192SMat Martineau 396721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work) 397ab07801dSGustavo F. Padovan { 398721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 399721c4181SGustavo F. Padovan chan_timer.work); 4003df91ea2SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 401ab07801dSGustavo F. Padovan int reason; 402ab07801dSGustavo F. Padovan 403e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 404ab07801dSGustavo F. Padovan 4053df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 4066be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 407ab07801dSGustavo F. Padovan 40889bc500eSGustavo F. Padovan if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) 409ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 41089bc500eSGustavo F. Padovan else if (chan->state == BT_CONNECT && 411ab07801dSGustavo F. Padovan chan->sec_level != BT_SECURITY_SDP) 412ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 413ab07801dSGustavo F. Padovan else 414ab07801dSGustavo F. Padovan reason = ETIMEDOUT; 415ab07801dSGustavo F. Padovan 4160f852724SGustavo F. Padovan l2cap_chan_close(chan, reason); 417ab07801dSGustavo F. Padovan 4186be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 419ab07801dSGustavo F. Padovan 42080b98027SGustavo Padovan chan->ops->close(chan); 4213df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4223df91ea2SAndrei Emeltchenko 423371fd835SUlisses Furquim l2cap_chan_put(chan); 424ab07801dSGustavo F. Padovan } 425ab07801dSGustavo F. Padovan 426eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void) 4270a708f8fSGustavo F. Padovan { 42848454079SGustavo F. Padovan struct l2cap_chan *chan; 4290a708f8fSGustavo F. Padovan 43048454079SGustavo F. Padovan chan = kzalloc(sizeof(*chan), GFP_ATOMIC); 43148454079SGustavo F. Padovan if (!chan) 43248454079SGustavo F. Padovan return NULL; 4330a708f8fSGustavo F. Padovan 434c03b355eSAndrei Emeltchenko mutex_init(&chan->lock); 435c03b355eSAndrei Emeltchenko 436ff714119SJohan Hedberg /* Set default lock nesting level */ 437ff714119SJohan Hedberg atomic_set(&chan->nesting, L2CAP_NESTING_NORMAL); 438ff714119SJohan Hedberg 439333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 44023691d75SGustavo F. Padovan list_add(&chan->global_l, &chan_list); 441333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 44223691d75SGustavo F. Padovan 443721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout); 444ab07801dSGustavo F. Padovan 44589bc500eSGustavo F. Padovan chan->state = BT_OPEN; 44689bc500eSGustavo F. Padovan 447144ad330SSyam Sidhardhan kref_init(&chan->kref); 44871ba0e56SGustavo F. Padovan 4492827011fSMat Martineau /* This flag is cleared in l2cap_chan_ready() */ 4502827011fSMat Martineau set_bit(CONF_NOT_COMPLETE, &chan->conf_state); 4512827011fSMat Martineau 452eef1d9b6SGustavo Padovan BT_DBG("chan %p", chan); 453abc545b8SSzymon Janc 45448454079SGustavo F. Padovan return chan; 4550a708f8fSGustavo F. Padovan } 4566b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_create); 4570a708f8fSGustavo F. Padovan 458144ad330SSyam Sidhardhan static void l2cap_chan_destroy(struct kref *kref) 4596ff5abbfSGustavo F. Padovan { 460144ad330SSyam Sidhardhan struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref); 461144ad330SSyam Sidhardhan 4624af66c69SJaganath Kanakkassery BT_DBG("chan %p", chan); 4634af66c69SJaganath Kanakkassery 464333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 46523691d75SGustavo F. Padovan list_del(&chan->global_l); 466333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 46723691d75SGustavo F. Padovan 4684af66c69SJaganath Kanakkassery kfree(chan); 4696ff5abbfSGustavo F. Padovan } 4706ff5abbfSGustavo F. Padovan 47130648372SJaganath Kanakkassery void l2cap_chan_hold(struct l2cap_chan *c) 47230648372SJaganath Kanakkassery { 473144ad330SSyam Sidhardhan BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount)); 47430648372SJaganath Kanakkassery 475144ad330SSyam Sidhardhan kref_get(&c->kref); 47630648372SJaganath Kanakkassery } 47730648372SJaganath Kanakkassery 47830648372SJaganath Kanakkassery void l2cap_chan_put(struct l2cap_chan *c) 47930648372SJaganath Kanakkassery { 480144ad330SSyam Sidhardhan BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount)); 48130648372SJaganath Kanakkassery 482144ad330SSyam Sidhardhan kref_put(&c->kref, l2cap_chan_destroy); 48330648372SJaganath Kanakkassery } 4846b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_put); 48530648372SJaganath Kanakkassery 486bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan) 487bd4b1653SAndrei Emeltchenko { 488bd4b1653SAndrei Emeltchenko chan->fcs = L2CAP_FCS_CRC16; 489bd4b1653SAndrei Emeltchenko chan->max_tx = L2CAP_DEFAULT_MAX_TX; 490bd4b1653SAndrei Emeltchenko chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; 491bd4b1653SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 4926a5e8165SJukka Rissanen chan->remote_max_tx = chan->max_tx; 4936a5e8165SJukka Rissanen chan->remote_tx_win = chan->tx_win; 494c20f8e35SMat Martineau chan->ack_win = L2CAP_DEFAULT_TX_WINDOW; 495bd4b1653SAndrei Emeltchenko chan->sec_level = BT_SECURITY_LOW; 4966a5e8165SJukka Rissanen chan->flush_to = L2CAP_DEFAULT_FLUSH_TO; 4976a5e8165SJukka Rissanen chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO; 4986a5e8165SJukka Rissanen chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO; 4996a5e8165SJukka Rissanen chan->conf_state = 0; 500bd4b1653SAndrei Emeltchenko 501bd4b1653SAndrei Emeltchenko set_bit(FLAG_FORCE_ACTIVE, &chan->flags); 502bd4b1653SAndrei Emeltchenko } 5036b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_set_defaults); 504bd4b1653SAndrei Emeltchenko 5050ce43ce6SJohan Hedberg static void l2cap_le_flowctl_init(struct l2cap_chan *chan) 50638319713SJohan Hedberg { 5070ce43ce6SJohan Hedberg chan->sdu = NULL; 5080ce43ce6SJohan Hedberg chan->sdu_last_frag = NULL; 5090ce43ce6SJohan Hedberg chan->sdu_len = 0; 5100cd75f7eSJohan Hedberg chan->tx_credits = 0; 511f15b8ecfSJohan Hedberg chan->rx_credits = le_max_credits; 512d1d79413SJohan Hedberg chan->mps = min_t(u16, chan->imtu, le_default_mps); 5130ce43ce6SJohan Hedberg 5140ce43ce6SJohan Hedberg skb_queue_head_init(&chan->tx_q); 51538319713SJohan Hedberg } 51638319713SJohan Hedberg 51793c3e8f5SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 5180a708f8fSGustavo F. Padovan { 5190a708f8fSGustavo F. Padovan BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, 520097db76cSAndrei Emeltchenko __le16_to_cpu(chan->psm), chan->dcid); 5210a708f8fSGustavo F. Padovan 5229f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 5230a708f8fSGustavo F. Padovan 5248c1d787bSGustavo F. Padovan chan->conn = conn; 5250a708f8fSGustavo F. Padovan 5265491120eSAndrei Emeltchenko switch (chan->chan_type) { 5275491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_ORIENTED: 5280a708f8fSGustavo F. Padovan /* Alloc CID for connection-oriented socket */ 529fe4128e0SGustavo F. Padovan chan->scid = l2cap_alloc_cid(conn); 53021626e62SJohan Hedberg if (conn->hcon->type == ACL_LINK) 5310c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 5325491120eSAndrei Emeltchenko break; 5335491120eSAndrei Emeltchenko 5345491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_LESS: 5350a708f8fSGustavo F. Padovan /* Connectionless socket */ 536fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_CONN_LESS; 537fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_CONN_LESS; 5380c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 5395491120eSAndrei Emeltchenko break; 5405491120eSAndrei Emeltchenko 5412338a7e0SJohan Hedberg case L2CAP_CHAN_FIXED: 5422338a7e0SJohan Hedberg /* Caller will set CID and CID specific MTU values */ 543416fa752SAndrei Emeltchenko break; 544416fa752SAndrei Emeltchenko 5455491120eSAndrei Emeltchenko default: 5460a708f8fSGustavo F. Padovan /* Raw socket can send/recv signalling messages only */ 547fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_SIGNALING; 548fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_SIGNALING; 5490c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 5500a708f8fSGustavo F. Padovan } 5510a708f8fSGustavo F. Padovan 5528f7975b1SAndrei Emeltchenko chan->local_id = L2CAP_BESTEFFORT_ID; 5538f7975b1SAndrei Emeltchenko chan->local_stype = L2CAP_SERV_BESTEFFORT; 5548f7975b1SAndrei Emeltchenko chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE; 5558f7975b1SAndrei Emeltchenko chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME; 5568f7975b1SAndrei Emeltchenko chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT; 5578936fa6dSAndrei Emeltchenko chan->local_flush_to = L2CAP_EFS_DEFAULT_FLUSH_TO; 5588f7975b1SAndrei Emeltchenko 559371fd835SUlisses Furquim l2cap_chan_hold(chan); 560baa7e1faSGustavo F. Padovan 561c16900cfSJohan Hedberg /* Only keep a reference for fixed channels if they requested it */ 562c16900cfSJohan Hedberg if (chan->chan_type != L2CAP_CHAN_FIXED || 563c16900cfSJohan Hedberg test_bit(FLAG_HOLD_HCI_CONN, &chan->flags)) 5645ee9891dSJohan Hedberg hci_conn_hold(conn->hcon); 5655ee9891dSJohan Hedberg 5663df91ea2SAndrei Emeltchenko list_add(&chan->list, &conn->chan_l); 567643162a8SAndrei Emeltchenko } 568643162a8SAndrei Emeltchenko 569466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 570643162a8SAndrei Emeltchenko { 571643162a8SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 572643162a8SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 5733df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 5740a708f8fSGustavo F. Padovan } 5750a708f8fSGustavo F. Padovan 576466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err) 5770a708f8fSGustavo F. Padovan { 5788c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 5790a708f8fSGustavo F. Padovan 580c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 5810a708f8fSGustavo F. Padovan 58249d11741SJohan Hedberg BT_DBG("chan %p, conn %p, err %d, state %s", chan, conn, err, 58349d11741SJohan Hedberg state_to_string(chan->state)); 5840a708f8fSGustavo F. Padovan 58572847ce0SJohan Hedberg chan->ops->teardown(chan, err); 58672847ce0SJohan Hedberg 5870a708f8fSGustavo F. Padovan if (conn) { 58856f60984SAndrei Emeltchenko struct amp_mgr *mgr = conn->hcon->amp_mgr; 589baa7e1faSGustavo F. Padovan /* Delete from channel list */ 5903df91ea2SAndrei Emeltchenko list_del(&chan->list); 5913d57dc68SGustavo F. Padovan 592371fd835SUlisses Furquim l2cap_chan_put(chan); 593baa7e1faSGustavo F. Padovan 5948c1d787bSGustavo F. Padovan chan->conn = NULL; 5953cabbfdaSAndrei Emeltchenko 596c16900cfSJohan Hedberg /* Reference was only held for non-fixed channels or 597c16900cfSJohan Hedberg * fixed channels that explicitly requested it using the 598c16900cfSJohan Hedberg * FLAG_HOLD_HCI_CONN flag. 599c16900cfSJohan Hedberg */ 600c16900cfSJohan Hedberg if (chan->chan_type != L2CAP_CHAN_FIXED || 601c16900cfSJohan Hedberg test_bit(FLAG_HOLD_HCI_CONN, &chan->flags)) 60276a68ba0SDavid Herrmann hci_conn_drop(conn->hcon); 60356f60984SAndrei Emeltchenko 60456f60984SAndrei Emeltchenko if (mgr && mgr->bredr_chan == chan) 60556f60984SAndrei Emeltchenko mgr->bredr_chan = NULL; 6060a708f8fSGustavo F. Padovan } 6070a708f8fSGustavo F. Padovan 608419e08c1SAndrei Emeltchenko if (chan->hs_hchan) { 609419e08c1SAndrei Emeltchenko struct hci_chan *hs_hchan = chan->hs_hchan; 610419e08c1SAndrei Emeltchenko 611419e08c1SAndrei Emeltchenko BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan); 612419e08c1SAndrei Emeltchenko amp_disconnect_logical_link(hs_hchan); 613419e08c1SAndrei Emeltchenko } 614419e08c1SAndrei Emeltchenko 6152827011fSMat Martineau if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) 6166ff5abbfSGustavo F. Padovan return; 6172ead70b8SGustavo F. Padovan 618ee556f66SGustavo Padovan switch(chan->mode) { 619ee556f66SGustavo Padovan case L2CAP_MODE_BASIC: 620ee556f66SGustavo Padovan break; 6210a708f8fSGustavo F. Padovan 62238319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 623177f8f2bSJohan Hedberg skb_queue_purge(&chan->tx_q); 62438319713SJohan Hedberg break; 62538319713SJohan Hedberg 626ee556f66SGustavo Padovan case L2CAP_MODE_ERTM: 6271a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 6281a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 6291a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 6300a708f8fSGustavo F. Padovan 631f1c6775bSGustavo F. Padovan skb_queue_purge(&chan->srej_q); 6320a708f8fSGustavo F. Padovan 6333c588192SMat Martineau l2cap_seq_list_free(&chan->srej_list); 6343c588192SMat Martineau l2cap_seq_list_free(&chan->retrans_list); 635ee556f66SGustavo Padovan 636ee556f66SGustavo Padovan /* fall through */ 637ee556f66SGustavo Padovan 638ee556f66SGustavo Padovan case L2CAP_MODE_STREAMING: 639ee556f66SGustavo Padovan skb_queue_purge(&chan->tx_q); 640ee556f66SGustavo Padovan break; 6410a708f8fSGustavo F. Padovan } 642ee556f66SGustavo Padovan 643ee556f66SGustavo Padovan return; 6440a708f8fSGustavo F. Padovan } 6456b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_del); 6460a708f8fSGustavo F. Padovan 647f3d82d0cSJohan Hedberg static void l2cap_conn_update_id_addr(struct work_struct *work) 648387a33e3SJohan Hedberg { 649f3d82d0cSJohan Hedberg struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 650f3d82d0cSJohan Hedberg id_addr_update_work); 651f3d82d0cSJohan Hedberg struct hci_conn *hcon = conn->hcon; 652387a33e3SJohan Hedberg struct l2cap_chan *chan; 653387a33e3SJohan Hedberg 654387a33e3SJohan Hedberg mutex_lock(&conn->chan_lock); 655387a33e3SJohan Hedberg 656387a33e3SJohan Hedberg list_for_each_entry(chan, &conn->chan_l, list) { 657387a33e3SJohan Hedberg l2cap_chan_lock(chan); 658387a33e3SJohan Hedberg bacpy(&chan->dst, &hcon->dst); 659a250e048SJohan Hedberg chan->dst_type = bdaddr_dst_type(hcon); 660387a33e3SJohan Hedberg l2cap_chan_unlock(chan); 661387a33e3SJohan Hedberg } 662387a33e3SJohan Hedberg 663387a33e3SJohan Hedberg mutex_unlock(&conn->chan_lock); 664387a33e3SJohan Hedberg } 665387a33e3SJohan Hedberg 66627e2d4c8SJohan Hedberg static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan) 66727e2d4c8SJohan Hedberg { 66827e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn; 66927e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 67027e2d4c8SJohan Hedberg u16 result; 67127e2d4c8SJohan Hedberg 67227e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 67327e2d4c8SJohan Hedberg result = L2CAP_CR_AUTHORIZATION; 67427e2d4c8SJohan Hedberg else 67527e2d4c8SJohan Hedberg result = L2CAP_CR_BAD_PSM; 67627e2d4c8SJohan Hedberg 67727e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_DISCONN); 67827e2d4c8SJohan Hedberg 67927e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 68027e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 6813916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps); 6820cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits); 68327e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result); 68427e2d4c8SJohan Hedberg 68527e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), 68627e2d4c8SJohan Hedberg &rsp); 68727e2d4c8SJohan Hedberg } 68827e2d4c8SJohan Hedberg 689791d60f7SJohan Hedberg static void l2cap_chan_connect_reject(struct l2cap_chan *chan) 690791d60f7SJohan Hedberg { 691791d60f7SJohan Hedberg struct l2cap_conn *conn = chan->conn; 692791d60f7SJohan Hedberg struct l2cap_conn_rsp rsp; 693791d60f7SJohan Hedberg u16 result; 694791d60f7SJohan Hedberg 695791d60f7SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 696791d60f7SJohan Hedberg result = L2CAP_CR_SEC_BLOCK; 697791d60f7SJohan Hedberg else 698791d60f7SJohan Hedberg result = L2CAP_CR_BAD_PSM; 699791d60f7SJohan Hedberg 700791d60f7SJohan Hedberg l2cap_state_change(chan, BT_DISCONN); 701791d60f7SJohan Hedberg 702791d60f7SJohan Hedberg rsp.scid = cpu_to_le16(chan->dcid); 703791d60f7SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 704791d60f7SJohan Hedberg rsp.result = cpu_to_le16(result); 705dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 706791d60f7SJohan Hedberg 707791d60f7SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); 708791d60f7SJohan Hedberg } 709791d60f7SJohan Hedberg 7100f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason) 7114519de9aSGustavo F. Padovan { 7124519de9aSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 7134519de9aSGustavo F. Padovan 7147eafc59eSMarcel Holtmann BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 7154519de9aSGustavo F. Padovan 71689bc500eSGustavo F. Padovan switch (chan->state) { 7174519de9aSGustavo F. Padovan case BT_LISTEN: 718c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 7194519de9aSGustavo F. Padovan break; 7204519de9aSGustavo F. Padovan 7214519de9aSGustavo F. Padovan case BT_CONNECTED: 7224519de9aSGustavo F. Padovan case BT_CONFIG: 7237b25c9b3SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) { 7248d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 7255e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, reason); 7264519de9aSGustavo F. Padovan } else 7274519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 7284519de9aSGustavo F. Padovan break; 7294519de9aSGustavo F. Padovan 7304519de9aSGustavo F. Padovan case BT_CONNECT2: 731791d60f7SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) { 732791d60f7SJohan Hedberg if (conn->hcon->type == ACL_LINK) 733791d60f7SJohan Hedberg l2cap_chan_connect_reject(chan); 73427e2d4c8SJohan Hedberg else if (conn->hcon->type == LE_LINK) 73527e2d4c8SJohan Hedberg l2cap_chan_le_connect_reject(chan); 7364519de9aSGustavo F. Padovan } 7374519de9aSGustavo F. Padovan 7384519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 7394519de9aSGustavo F. Padovan break; 7404519de9aSGustavo F. Padovan 7414519de9aSGustavo F. Padovan case BT_CONNECT: 7424519de9aSGustavo F. Padovan case BT_DISCONN: 7434519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 7444519de9aSGustavo F. Padovan break; 7454519de9aSGustavo F. Padovan 7464519de9aSGustavo F. Padovan default: 747c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 7484519de9aSGustavo F. Padovan break; 7494519de9aSGustavo F. Padovan } 7504519de9aSGustavo F. Padovan } 7516b8d4a6aSJukka Rissanen EXPORT_SYMBOL(l2cap_chan_close); 7524519de9aSGustavo F. Padovan 7534343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) 7540a708f8fSGustavo F. Padovan { 7556a974b50SMarcel Holtmann switch (chan->chan_type) { 7566a974b50SMarcel Holtmann case L2CAP_CHAN_RAW: 7574343478fSGustavo F. Padovan switch (chan->sec_level) { 7580a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 7597d513e92SMarcel Holtmann case BT_SECURITY_FIPS: 7600a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING_MITM; 7610a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 7620a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING; 7630a708f8fSGustavo F. Padovan default: 7640a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 7650a708f8fSGustavo F. Padovan } 7666a974b50SMarcel Holtmann break; 7673124b843SMarcel Holtmann case L2CAP_CHAN_CONN_LESS: 768dcf4adbfSJoe Perches if (chan->psm == cpu_to_le16(L2CAP_PSM_3DSP)) { 7693124b843SMarcel Holtmann if (chan->sec_level == BT_SECURITY_LOW) 7703124b843SMarcel Holtmann chan->sec_level = BT_SECURITY_SDP; 7713124b843SMarcel Holtmann } 7727d513e92SMarcel Holtmann if (chan->sec_level == BT_SECURITY_HIGH || 7737d513e92SMarcel Holtmann chan->sec_level == BT_SECURITY_FIPS) 7743124b843SMarcel Holtmann return HCI_AT_NO_BONDING_MITM; 7753124b843SMarcel Holtmann else 7763124b843SMarcel Holtmann return HCI_AT_NO_BONDING; 7773124b843SMarcel Holtmann break; 7786a974b50SMarcel Holtmann case L2CAP_CHAN_CONN_ORIENTED: 779dcf4adbfSJoe Perches if (chan->psm == cpu_to_le16(L2CAP_PSM_SDP)) { 7804343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_LOW) 7814343478fSGustavo F. Padovan chan->sec_level = BT_SECURITY_SDP; 7820a708f8fSGustavo F. Padovan 7837d513e92SMarcel Holtmann if (chan->sec_level == BT_SECURITY_HIGH || 7847d513e92SMarcel Holtmann chan->sec_level == BT_SECURITY_FIPS) 7850a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING_MITM; 7860a708f8fSGustavo F. Padovan else 7870a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 7886a974b50SMarcel Holtmann } 7896a974b50SMarcel Holtmann /* fall through */ 7906a974b50SMarcel Holtmann default: 7914343478fSGustavo F. Padovan switch (chan->sec_level) { 7920a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 7937d513e92SMarcel Holtmann case BT_SECURITY_FIPS: 7940a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING_MITM; 7950a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 7960a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING; 7970a708f8fSGustavo F. Padovan default: 7980a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 7990a708f8fSGustavo F. Padovan } 8006a974b50SMarcel Holtmann break; 8010a708f8fSGustavo F. Padovan } 8020a708f8fSGustavo F. Padovan } 8030a708f8fSGustavo F. Padovan 8040a708f8fSGustavo F. Padovan /* Service level security */ 805e7cafc45SJohan Hedberg int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator) 8060a708f8fSGustavo F. Padovan { 8078c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 8080a708f8fSGustavo F. Padovan __u8 auth_type; 8090a708f8fSGustavo F. Padovan 810a17de2feSJohan Hedberg if (conn->hcon->type == LE_LINK) 811a17de2feSJohan Hedberg return smp_conn_security(conn->hcon, chan->sec_level); 812a17de2feSJohan Hedberg 8134343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 8140a708f8fSGustavo F. Padovan 815e7cafc45SJohan Hedberg return hci_conn_security(conn->hcon, chan->sec_level, auth_type, 816e7cafc45SJohan Hedberg initiator); 8170a708f8fSGustavo F. Padovan } 8180a708f8fSGustavo F. Padovan 819b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn) 8200a708f8fSGustavo F. Padovan { 8210a708f8fSGustavo F. Padovan u8 id; 8220a708f8fSGustavo F. Padovan 8230a708f8fSGustavo F. Padovan /* Get next available identificator. 8240a708f8fSGustavo F. Padovan * 1 - 128 are used by kernel. 8250a708f8fSGustavo F. Padovan * 129 - 199 are reserved. 8260a708f8fSGustavo F. Padovan * 200 - 254 are used by utilities like l2ping, etc. 8270a708f8fSGustavo F. Padovan */ 8280a708f8fSGustavo F. Padovan 8295a54e7c8SMarcel Holtmann mutex_lock(&conn->ident_lock); 8300a708f8fSGustavo F. Padovan 8310a708f8fSGustavo F. Padovan if (++conn->tx_ident > 128) 8320a708f8fSGustavo F. Padovan conn->tx_ident = 1; 8330a708f8fSGustavo F. Padovan 8340a708f8fSGustavo F. Padovan id = conn->tx_ident; 8350a708f8fSGustavo F. Padovan 8365a54e7c8SMarcel Holtmann mutex_unlock(&conn->ident_lock); 8370a708f8fSGustavo F. Padovan 8380a708f8fSGustavo F. Padovan return id; 8390a708f8fSGustavo F. Padovan } 8400a708f8fSGustavo F. Padovan 8412d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 8422d792818SGustavo Padovan void *data) 8430a708f8fSGustavo F. Padovan { 8440a708f8fSGustavo F. Padovan struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); 8450a708f8fSGustavo F. Padovan u8 flags; 8460a708f8fSGustavo F. Padovan 8470a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x", code); 8480a708f8fSGustavo F. Padovan 8490a708f8fSGustavo F. Padovan if (!skb) 8500a708f8fSGustavo F. Padovan return; 8510a708f8fSGustavo F. Padovan 852f6af675eSSteven Walter /* Use NO_FLUSH if supported or we have an LE link (which does 853f6af675eSSteven Walter * not support auto-flushing packets) */ 854f6af675eSSteven Walter if (lmp_no_flush_capable(conn->hcon->hdev) || 855f6af675eSSteven Walter conn->hcon->type == LE_LINK) 8560a708f8fSGustavo F. Padovan flags = ACL_START_NO_FLUSH; 8570a708f8fSGustavo F. Padovan else 8580a708f8fSGustavo F. Padovan flags = ACL_START; 8590a708f8fSGustavo F. Padovan 86014b12d0bSJaikumar Ganesh bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON; 8615e59b791SLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 86214b12d0bSJaikumar Ganesh 86373d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, flags); 8640a708f8fSGustavo F. Padovan } 8650a708f8fSGustavo F. Padovan 86602b0fbb9SMat Martineau static bool __chan_is_moving(struct l2cap_chan *chan) 86702b0fbb9SMat Martineau { 86802b0fbb9SMat Martineau return chan->move_state != L2CAP_MOVE_STABLE && 86902b0fbb9SMat Martineau chan->move_state != L2CAP_MOVE_WAIT_PREPARE; 87002b0fbb9SMat Martineau } 87102b0fbb9SMat Martineau 87273d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) 87373d80debSLuiz Augusto von Dentz { 87473d80debSLuiz Augusto von Dentz struct hci_conn *hcon = chan->conn->hcon; 87573d80debSLuiz Augusto von Dentz u16 flags; 87673d80debSLuiz Augusto von Dentz 87773d80debSLuiz Augusto von Dentz BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, 87873d80debSLuiz Augusto von Dentz skb->priority); 87973d80debSLuiz Augusto von Dentz 880d5f8a75dSMat Martineau if (chan->hs_hcon && !__chan_is_moving(chan)) { 881d5f8a75dSMat Martineau if (chan->hs_hchan) 882d5f8a75dSMat Martineau hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE); 883d5f8a75dSMat Martineau else 884d5f8a75dSMat Martineau kfree_skb(skb); 885d5f8a75dSMat Martineau 886d5f8a75dSMat Martineau return; 887d5f8a75dSMat Martineau } 888d5f8a75dSMat Martineau 889f6af675eSSteven Walter /* Use NO_FLUSH for LE links (where this is the only option) or 890f6af675eSSteven Walter * if the BR/EDR link supports it and flushing has not been 891f6af675eSSteven Walter * explicitly requested (through FLAG_FLUSHABLE). 892f6af675eSSteven Walter */ 893f6af675eSSteven Walter if (hcon->type == LE_LINK || 894f6af675eSSteven Walter (!test_bit(FLAG_FLUSHABLE, &chan->flags) && 895f6af675eSSteven Walter lmp_no_flush_capable(hcon->hdev))) 89673d80debSLuiz Augusto von Dentz flags = ACL_START_NO_FLUSH; 89773d80debSLuiz Augusto von Dentz else 89873d80debSLuiz Augusto von Dentz flags = ACL_START; 89973d80debSLuiz Augusto von Dentz 90073d80debSLuiz Augusto von Dentz bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); 90173d80debSLuiz Augusto von Dentz hci_send_acl(chan->conn->hchan, skb, flags); 9020a708f8fSGustavo F. Padovan } 9030a708f8fSGustavo F. Padovan 904b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control) 905b5c6aaedSMat Martineau { 906b5c6aaedSMat Martineau control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT; 907b5c6aaedSMat Martineau control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT; 908b5c6aaedSMat Martineau 909b5c6aaedSMat Martineau if (enh & L2CAP_CTRL_FRAME_TYPE) { 910b5c6aaedSMat Martineau /* S-Frame */ 911b5c6aaedSMat Martineau control->sframe = 1; 912b5c6aaedSMat Martineau control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT; 913b5c6aaedSMat Martineau control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT; 914b5c6aaedSMat Martineau 915b5c6aaedSMat Martineau control->sar = 0; 916b5c6aaedSMat Martineau control->txseq = 0; 917b5c6aaedSMat Martineau } else { 918b5c6aaedSMat Martineau /* I-Frame */ 919b5c6aaedSMat Martineau control->sframe = 0; 920b5c6aaedSMat Martineau control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT; 921b5c6aaedSMat Martineau control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT; 922b5c6aaedSMat Martineau 923b5c6aaedSMat Martineau control->poll = 0; 924b5c6aaedSMat Martineau control->super = 0; 925b5c6aaedSMat Martineau } 926b5c6aaedSMat Martineau } 927b5c6aaedSMat Martineau 928b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control) 929b5c6aaedSMat Martineau { 930b5c6aaedSMat Martineau control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT; 931b5c6aaedSMat Martineau control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT; 932b5c6aaedSMat Martineau 933b5c6aaedSMat Martineau if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) { 934b5c6aaedSMat Martineau /* S-Frame */ 935b5c6aaedSMat Martineau control->sframe = 1; 936b5c6aaedSMat Martineau control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT; 937b5c6aaedSMat Martineau control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT; 938b5c6aaedSMat Martineau 939b5c6aaedSMat Martineau control->sar = 0; 940b5c6aaedSMat Martineau control->txseq = 0; 941b5c6aaedSMat Martineau } else { 942b5c6aaedSMat Martineau /* I-Frame */ 943b5c6aaedSMat Martineau control->sframe = 0; 944b5c6aaedSMat Martineau control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT; 945b5c6aaedSMat Martineau control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT; 946b5c6aaedSMat Martineau 947b5c6aaedSMat Martineau control->poll = 0; 948b5c6aaedSMat Martineau control->super = 0; 949b5c6aaedSMat Martineau } 950b5c6aaedSMat Martineau } 951b5c6aaedSMat Martineau 952b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan, 953b5c6aaedSMat Martineau struct sk_buff *skb) 954b5c6aaedSMat Martineau { 955b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 956b5c6aaedSMat Martineau __unpack_extended_control(get_unaligned_le32(skb->data), 957a4368ff3SJohan Hedberg &bt_cb(skb)->l2cap); 958cec8ab6eSMat Martineau skb_pull(skb, L2CAP_EXT_CTRL_SIZE); 959b5c6aaedSMat Martineau } else { 960b5c6aaedSMat Martineau __unpack_enhanced_control(get_unaligned_le16(skb->data), 961a4368ff3SJohan Hedberg &bt_cb(skb)->l2cap); 962cec8ab6eSMat Martineau skb_pull(skb, L2CAP_ENH_CTRL_SIZE); 963b5c6aaedSMat Martineau } 964b5c6aaedSMat Martineau } 965b5c6aaedSMat Martineau 966b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control) 967b5c6aaedSMat Martineau { 968b5c6aaedSMat Martineau u32 packed; 969b5c6aaedSMat Martineau 970b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT; 971b5c6aaedSMat Martineau packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT; 972b5c6aaedSMat Martineau 973b5c6aaedSMat Martineau if (control->sframe) { 974b5c6aaedSMat Martineau packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT; 975b5c6aaedSMat Martineau packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT; 976b5c6aaedSMat Martineau packed |= L2CAP_EXT_CTRL_FRAME_TYPE; 977b5c6aaedSMat Martineau } else { 978b5c6aaedSMat Martineau packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT; 979b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT; 980b5c6aaedSMat Martineau } 981b5c6aaedSMat Martineau 982b5c6aaedSMat Martineau return packed; 983b5c6aaedSMat Martineau } 984b5c6aaedSMat Martineau 985b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control) 986b5c6aaedSMat Martineau { 987b5c6aaedSMat Martineau u16 packed; 988b5c6aaedSMat Martineau 989b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT; 990b5c6aaedSMat Martineau packed |= control->final << L2CAP_CTRL_FINAL_SHIFT; 991b5c6aaedSMat Martineau 992b5c6aaedSMat Martineau if (control->sframe) { 993b5c6aaedSMat Martineau packed |= control->poll << L2CAP_CTRL_POLL_SHIFT; 994b5c6aaedSMat Martineau packed |= control->super << L2CAP_CTRL_SUPER_SHIFT; 995b5c6aaedSMat Martineau packed |= L2CAP_CTRL_FRAME_TYPE; 996b5c6aaedSMat Martineau } else { 997b5c6aaedSMat Martineau packed |= control->sar << L2CAP_CTRL_SAR_SHIFT; 998b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT; 999b5c6aaedSMat Martineau } 1000b5c6aaedSMat Martineau 1001b5c6aaedSMat Martineau return packed; 1002b5c6aaedSMat Martineau } 1003b5c6aaedSMat Martineau 1004b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan, 1005b5c6aaedSMat Martineau struct l2cap_ctrl *control, 1006b5c6aaedSMat Martineau struct sk_buff *skb) 1007b5c6aaedSMat Martineau { 1008b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 1009b5c6aaedSMat Martineau put_unaligned_le32(__pack_extended_control(control), 1010b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 1011b5c6aaedSMat Martineau } else { 1012b5c6aaedSMat Martineau put_unaligned_le16(__pack_enhanced_control(control), 1013b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 1014b5c6aaedSMat Martineau } 1015b5c6aaedSMat Martineau } 1016b5c6aaedSMat Martineau 1017ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan) 1018ba7aa64fSGustavo Padovan { 1019ba7aa64fSGustavo Padovan if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1020ba7aa64fSGustavo Padovan return L2CAP_EXT_HDR_SIZE; 1021ba7aa64fSGustavo Padovan else 1022ba7aa64fSGustavo Padovan return L2CAP_ENH_HDR_SIZE; 1023ba7aa64fSGustavo Padovan } 1024ba7aa64fSGustavo Padovan 1025a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan, 1026a67d7f6fSMat Martineau u32 control) 10270a708f8fSGustavo F. Padovan { 10280a708f8fSGustavo F. Padovan struct sk_buff *skb; 10290a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 1030ba7aa64fSGustavo Padovan int hlen = __ertm_hdr_size(chan); 10310a708f8fSGustavo F. Padovan 10320a708f8fSGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 103303a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 10340a708f8fSGustavo F. Padovan 1035a67d7f6fSMat Martineau skb = bt_skb_alloc(hlen, GFP_KERNEL); 10360a708f8fSGustavo F. Padovan 10370a708f8fSGustavo F. Padovan if (!skb) 1038a67d7f6fSMat Martineau return ERR_PTR(-ENOMEM); 10390a708f8fSGustavo F. Padovan 10400a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 10410a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); 1042fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 104388843ab0SAndrei Emeltchenko 1044a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1045a67d7f6fSMat Martineau put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 1046a67d7f6fSMat Martineau else 1047a67d7f6fSMat Martineau put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 10480a708f8fSGustavo F. Padovan 104947d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 1050a67d7f6fSMat Martineau u16 fcs = crc16(0, (u8 *)skb->data, skb->len); 105103a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 10520a708f8fSGustavo F. Padovan } 10530a708f8fSGustavo F. Padovan 105473d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 1055a67d7f6fSMat Martineau return skb; 1056a67d7f6fSMat Martineau } 1057a67d7f6fSMat Martineau 1058a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan, 1059a67d7f6fSMat Martineau struct l2cap_ctrl *control) 1060a67d7f6fSMat Martineau { 1061a67d7f6fSMat Martineau struct sk_buff *skb; 1062a67d7f6fSMat Martineau u32 control_field; 1063a67d7f6fSMat Martineau 1064a67d7f6fSMat Martineau BT_DBG("chan %p, control %p", chan, control); 1065a67d7f6fSMat Martineau 1066a67d7f6fSMat Martineau if (!control->sframe) 1067a67d7f6fSMat Martineau return; 1068a67d7f6fSMat Martineau 1069b99e13adSMat Martineau if (__chan_is_moving(chan)) 1070b99e13adSMat Martineau return; 1071b99e13adSMat Martineau 1072a67d7f6fSMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) && 1073a67d7f6fSMat Martineau !control->poll) 1074a67d7f6fSMat Martineau control->final = 1; 1075a67d7f6fSMat Martineau 1076a67d7f6fSMat Martineau if (control->super == L2CAP_SUPER_RR) 1077a67d7f6fSMat Martineau clear_bit(CONN_RNR_SENT, &chan->conn_state); 1078a67d7f6fSMat Martineau else if (control->super == L2CAP_SUPER_RNR) 1079a67d7f6fSMat Martineau set_bit(CONN_RNR_SENT, &chan->conn_state); 1080a67d7f6fSMat Martineau 1081a67d7f6fSMat Martineau if (control->super != L2CAP_SUPER_SREJ) { 1082a67d7f6fSMat Martineau chan->last_acked_seq = control->reqseq; 1083a67d7f6fSMat Martineau __clear_ack_timer(chan); 1084a67d7f6fSMat Martineau } 1085a67d7f6fSMat Martineau 1086a67d7f6fSMat Martineau BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq, 1087a67d7f6fSMat Martineau control->final, control->poll, control->super); 1088a67d7f6fSMat Martineau 1089a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1090a67d7f6fSMat Martineau control_field = __pack_extended_control(control); 1091a67d7f6fSMat Martineau else 1092a67d7f6fSMat Martineau control_field = __pack_enhanced_control(control); 1093a67d7f6fSMat Martineau 1094a67d7f6fSMat Martineau skb = l2cap_create_sframe_pdu(chan, control_field); 1095a67d7f6fSMat Martineau if (!IS_ERR(skb)) 109673d80debSLuiz Augusto von Dentz l2cap_do_send(chan, skb); 10970a708f8fSGustavo F. Padovan } 10980a708f8fSGustavo F. Padovan 1099c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll) 11000a708f8fSGustavo F. Padovan { 1101c9e3d5e0SMat Martineau struct l2cap_ctrl control; 11020a708f8fSGustavo F. Padovan 1103c9e3d5e0SMat Martineau BT_DBG("chan %p, poll %d", chan, poll); 1104c9e3d5e0SMat Martineau 1105c9e3d5e0SMat Martineau memset(&control, 0, sizeof(control)); 1106c9e3d5e0SMat Martineau control.sframe = 1; 1107c9e3d5e0SMat Martineau control.poll = poll; 1108c9e3d5e0SMat Martineau 1109c9e3d5e0SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 1110c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RNR; 1111c9e3d5e0SMat Martineau else 1112c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RR; 1113c9e3d5e0SMat Martineau 1114c9e3d5e0SMat Martineau control.reqseq = chan->buffer_seq; 1115c9e3d5e0SMat Martineau l2cap_send_sframe(chan, &control); 11160a708f8fSGustavo F. Padovan } 11170a708f8fSGustavo F. Padovan 1118b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) 11190a708f8fSGustavo F. Padovan { 11205ff6f34dSJohan Hedberg if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 11215ff6f34dSJohan Hedberg return true; 11225ff6f34dSJohan Hedberg 1123c1360a1cSGustavo F. Padovan return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); 11240a708f8fSGustavo F. Padovan } 11250a708f8fSGustavo F. Padovan 112693c3e8f5SAndrei Emeltchenko static bool __amp_capable(struct l2cap_chan *chan) 112793c3e8f5SAndrei Emeltchenko { 112893c3e8f5SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 11291df7b17aSMarcel Holtmann struct hci_dev *hdev; 11301df7b17aSMarcel Holtmann bool amp_available = false; 113193c3e8f5SAndrei Emeltchenko 11320bd49fc7SJohan Hedberg if (!(conn->local_fixed_chan & L2CAP_FC_A2MP)) 11331df7b17aSMarcel Holtmann return false; 11341df7b17aSMarcel Holtmann 11350bd49fc7SJohan Hedberg if (!(conn->remote_fixed_chan & L2CAP_FC_A2MP)) 11361df7b17aSMarcel Holtmann return false; 11371df7b17aSMarcel Holtmann 11381df7b17aSMarcel Holtmann read_lock(&hci_dev_list_lock); 11391df7b17aSMarcel Holtmann list_for_each_entry(hdev, &hci_dev_list, list) { 11401df7b17aSMarcel Holtmann if (hdev->amp_type != AMP_TYPE_BREDR && 11411df7b17aSMarcel Holtmann test_bit(HCI_UP, &hdev->flags)) { 11421df7b17aSMarcel Holtmann amp_available = true; 11431df7b17aSMarcel Holtmann break; 11441df7b17aSMarcel Holtmann } 11451df7b17aSMarcel Holtmann } 11461df7b17aSMarcel Holtmann read_unlock(&hci_dev_list_lock); 11471df7b17aSMarcel Holtmann 11481df7b17aSMarcel Holtmann if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED) 11491df7b17aSMarcel Holtmann return amp_available; 1150848566b3SMarcel Holtmann 115193c3e8f5SAndrei Emeltchenko return false; 115293c3e8f5SAndrei Emeltchenko } 115393c3e8f5SAndrei Emeltchenko 11545ce66b59SAndrei Emeltchenko static bool l2cap_check_efs(struct l2cap_chan *chan) 11555ce66b59SAndrei Emeltchenko { 11565ce66b59SAndrei Emeltchenko /* Check EFS parameters */ 11575ce66b59SAndrei Emeltchenko return true; 11585ce66b59SAndrei Emeltchenko } 11595ce66b59SAndrei Emeltchenko 11602766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan) 11619b27f350SAndrei Emeltchenko { 11629b27f350SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 11639b27f350SAndrei Emeltchenko struct l2cap_conn_req req; 11649b27f350SAndrei Emeltchenko 11659b27f350SAndrei Emeltchenko req.scid = cpu_to_le16(chan->scid); 11669b27f350SAndrei Emeltchenko req.psm = chan->psm; 11679b27f350SAndrei Emeltchenko 11689b27f350SAndrei Emeltchenko chan->ident = l2cap_get_ident(conn); 11699b27f350SAndrei Emeltchenko 11709b27f350SAndrei Emeltchenko set_bit(CONF_CONNECT_PEND, &chan->conf_state); 11719b27f350SAndrei Emeltchenko 11729b27f350SAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); 11739b27f350SAndrei Emeltchenko } 11749b27f350SAndrei Emeltchenko 11758eb200bdSMat Martineau static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id) 11768eb200bdSMat Martineau { 11778eb200bdSMat Martineau struct l2cap_create_chan_req req; 11788eb200bdSMat Martineau req.scid = cpu_to_le16(chan->scid); 11798eb200bdSMat Martineau req.psm = chan->psm; 11808eb200bdSMat Martineau req.amp_id = amp_id; 11818eb200bdSMat Martineau 11828eb200bdSMat Martineau chan->ident = l2cap_get_ident(chan->conn); 11838eb200bdSMat Martineau 11848eb200bdSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ, 11858eb200bdSMat Martineau sizeof(req), &req); 11868eb200bdSMat Martineau } 11878eb200bdSMat Martineau 118802b0fbb9SMat Martineau static void l2cap_move_setup(struct l2cap_chan *chan) 118902b0fbb9SMat Martineau { 119002b0fbb9SMat Martineau struct sk_buff *skb; 119102b0fbb9SMat Martineau 119202b0fbb9SMat Martineau BT_DBG("chan %p", chan); 119302b0fbb9SMat Martineau 119402b0fbb9SMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 119502b0fbb9SMat Martineau return; 119602b0fbb9SMat Martineau 119702b0fbb9SMat Martineau __clear_retrans_timer(chan); 119802b0fbb9SMat Martineau __clear_monitor_timer(chan); 119902b0fbb9SMat Martineau __clear_ack_timer(chan); 120002b0fbb9SMat Martineau 120102b0fbb9SMat Martineau chan->retry_count = 0; 120202b0fbb9SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 1203a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.retries) 1204a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 1; 120502b0fbb9SMat Martineau else 120602b0fbb9SMat Martineau break; 120702b0fbb9SMat Martineau } 120802b0fbb9SMat Martineau 120902b0fbb9SMat Martineau chan->expected_tx_seq = chan->buffer_seq; 121002b0fbb9SMat Martineau 121102b0fbb9SMat Martineau clear_bit(CONN_REJ_ACT, &chan->conn_state); 121202b0fbb9SMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 121302b0fbb9SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 121402b0fbb9SMat Martineau l2cap_seq_list_clear(&chan->srej_list); 121502b0fbb9SMat Martineau skb_queue_purge(&chan->srej_q); 121602b0fbb9SMat Martineau 121702b0fbb9SMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 121802b0fbb9SMat Martineau chan->rx_state = L2CAP_RX_STATE_MOVE; 121902b0fbb9SMat Martineau 122002b0fbb9SMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 122102b0fbb9SMat Martineau } 122202b0fbb9SMat Martineau 12235f3847a4SMat Martineau static void l2cap_move_done(struct l2cap_chan *chan) 12245f3847a4SMat Martineau { 12255f3847a4SMat Martineau u8 move_role = chan->move_role; 12265f3847a4SMat Martineau BT_DBG("chan %p", chan); 12275f3847a4SMat Martineau 12285f3847a4SMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 12295f3847a4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 12305f3847a4SMat Martineau 12315f3847a4SMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 12325f3847a4SMat Martineau return; 12335f3847a4SMat Martineau 12345f3847a4SMat Martineau switch (move_role) { 12355f3847a4SMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 12365f3847a4SMat Martineau l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL); 12375f3847a4SMat Martineau chan->rx_state = L2CAP_RX_STATE_WAIT_F; 12385f3847a4SMat Martineau break; 12395f3847a4SMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 12405f3847a4SMat Martineau chan->rx_state = L2CAP_RX_STATE_WAIT_P; 12415f3847a4SMat Martineau break; 12425f3847a4SMat Martineau } 12435f3847a4SMat Martineau } 12445f3847a4SMat Martineau 12459f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan) 12469f0caeb1SVinicius Costa Gomes { 1247315917e0SJohan Hedberg /* The channel may have already been flagged as connected in 1248315917e0SJohan Hedberg * case of receiving data before the L2CAP info req/rsp 1249315917e0SJohan Hedberg * procedure is complete. 1250315917e0SJohan Hedberg */ 1251315917e0SJohan Hedberg if (chan->state == BT_CONNECTED) 1252315917e0SJohan Hedberg return; 1253315917e0SJohan Hedberg 12542827011fSMat Martineau /* This clears all conf flags, including CONF_NOT_COMPLETE */ 12559f0caeb1SVinicius Costa Gomes chan->conf_state = 0; 12569f0caeb1SVinicius Costa Gomes __clear_chan_timer(chan); 12579f0caeb1SVinicius Costa Gomes 12580ce43ce6SJohan Hedberg if (chan->mode == L2CAP_MODE_LE_FLOWCTL && !chan->tx_credits) 12590ce43ce6SJohan Hedberg chan->ops->suspend(chan); 1260177f8f2bSJohan Hedberg 126154a59aa2SAndrei Emeltchenko chan->state = BT_CONNECTED; 12629f0caeb1SVinicius Costa Gomes 126354a59aa2SAndrei Emeltchenko chan->ops->ready(chan); 12649f0caeb1SVinicius Costa Gomes } 12659f0caeb1SVinicius Costa Gomes 1266f1496deeSJohan Hedberg static void l2cap_le_connect(struct l2cap_chan *chan) 1267f1496deeSJohan Hedberg { 1268f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1269f1496deeSJohan Hedberg struct l2cap_le_conn_req req; 1270f1496deeSJohan Hedberg 1271595177f3SJohan Hedberg if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags)) 1272595177f3SJohan Hedberg return; 1273595177f3SJohan Hedberg 1274f1496deeSJohan Hedberg req.psm = chan->psm; 1275f1496deeSJohan Hedberg req.scid = cpu_to_le16(chan->scid); 1276f1496deeSJohan Hedberg req.mtu = cpu_to_le16(chan->imtu); 12773916aed8SJohan Hedberg req.mps = cpu_to_le16(chan->mps); 12780cd75f7eSJohan Hedberg req.credits = cpu_to_le16(chan->rx_credits); 1279f1496deeSJohan Hedberg 1280f1496deeSJohan Hedberg chan->ident = l2cap_get_ident(conn); 1281f1496deeSJohan Hedberg 1282f1496deeSJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ, 1283f1496deeSJohan Hedberg sizeof(req), &req); 1284f1496deeSJohan Hedberg } 1285f1496deeSJohan Hedberg 1286f1496deeSJohan Hedberg static void l2cap_le_start(struct l2cap_chan *chan) 1287f1496deeSJohan Hedberg { 1288f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1289f1496deeSJohan Hedberg 1290f1496deeSJohan Hedberg if (!smp_conn_security(conn->hcon, chan->sec_level)) 1291f1496deeSJohan Hedberg return; 1292f1496deeSJohan Hedberg 1293f1496deeSJohan Hedberg if (!chan->psm) { 1294f1496deeSJohan Hedberg l2cap_chan_ready(chan); 1295f1496deeSJohan Hedberg return; 1296f1496deeSJohan Hedberg } 1297f1496deeSJohan Hedberg 1298f1496deeSJohan Hedberg if (chan->state == BT_CONNECT) 1299f1496deeSJohan Hedberg l2cap_le_connect(chan); 1300f1496deeSJohan Hedberg } 1301f1496deeSJohan Hedberg 130293c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan) 130393c3e8f5SAndrei Emeltchenko { 130493c3e8f5SAndrei Emeltchenko if (__amp_capable(chan)) { 130593c3e8f5SAndrei Emeltchenko BT_DBG("chan %p AMP capable: discover AMPs", chan); 130693c3e8f5SAndrei Emeltchenko a2mp_discover_amp(chan); 1307f1496deeSJohan Hedberg } else if (chan->conn->hcon->type == LE_LINK) { 1308f1496deeSJohan Hedberg l2cap_le_start(chan); 130993c3e8f5SAndrei Emeltchenko } else { 131093c3e8f5SAndrei Emeltchenko l2cap_send_conn_req(chan); 131193c3e8f5SAndrei Emeltchenko } 131293c3e8f5SAndrei Emeltchenko } 131393c3e8f5SAndrei Emeltchenko 1314aeaeb4bbSJohan Hedberg static void l2cap_request_info(struct l2cap_conn *conn) 13150a708f8fSGustavo F. Padovan { 13160a708f8fSGustavo F. Padovan struct l2cap_info_req req; 1317aeaeb4bbSJohan Hedberg 1318aeaeb4bbSJohan Hedberg if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1319aeaeb4bbSJohan Hedberg return; 1320aeaeb4bbSJohan Hedberg 1321dcf4adbfSJoe Perches req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 13220a708f8fSGustavo F. Padovan 13230a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 13240a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 13250a708f8fSGustavo F. Padovan 1326ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 13270a708f8fSGustavo F. Padovan 13282d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, 13292d792818SGustavo Padovan sizeof(req), &req); 13300a708f8fSGustavo F. Padovan } 1331aeaeb4bbSJohan Hedberg 1332aeaeb4bbSJohan Hedberg static void l2cap_do_start(struct l2cap_chan *chan) 1333aeaeb4bbSJohan Hedberg { 1334aeaeb4bbSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1335aeaeb4bbSJohan Hedberg 1336aeaeb4bbSJohan Hedberg if (conn->hcon->type == LE_LINK) { 1337aeaeb4bbSJohan Hedberg l2cap_le_start(chan); 1338aeaeb4bbSJohan Hedberg return; 1339aeaeb4bbSJohan Hedberg } 1340aeaeb4bbSJohan Hedberg 1341aeaeb4bbSJohan Hedberg if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)) { 1342aeaeb4bbSJohan Hedberg l2cap_request_info(conn); 1343aeaeb4bbSJohan Hedberg return; 1344aeaeb4bbSJohan Hedberg } 1345aeaeb4bbSJohan Hedberg 1346aeaeb4bbSJohan Hedberg if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) 1347aeaeb4bbSJohan Hedberg return; 1348aeaeb4bbSJohan Hedberg 1349aeaeb4bbSJohan Hedberg if (l2cap_chan_check_security(chan, true) && 1350aeaeb4bbSJohan Hedberg __l2cap_no_conn_pending(chan)) 1351aeaeb4bbSJohan Hedberg l2cap_start_connection(chan); 13520a708f8fSGustavo F. Padovan } 13530a708f8fSGustavo F. Padovan 13540a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) 13550a708f8fSGustavo F. Padovan { 13560a708f8fSGustavo F. Padovan u32 local_feat_mask = l2cap_feat_mask; 13570a708f8fSGustavo F. Padovan if (!disable_ertm) 13580a708f8fSGustavo F. Padovan local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING; 13590a708f8fSGustavo F. Padovan 13600a708f8fSGustavo F. Padovan switch (mode) { 13610a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 13620a708f8fSGustavo F. Padovan return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask; 13630a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 13640a708f8fSGustavo F. Padovan return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask; 13650a708f8fSGustavo F. Padovan default: 13660a708f8fSGustavo F. Padovan return 0x00; 13670a708f8fSGustavo F. Padovan } 13680a708f8fSGustavo F. Padovan } 13690a708f8fSGustavo F. Padovan 13705e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err) 13710a708f8fSGustavo F. Padovan { 13725e4e3972SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 13730a708f8fSGustavo F. Padovan struct l2cap_disconn_req req; 13740a708f8fSGustavo F. Padovan 13750a708f8fSGustavo F. Padovan if (!conn) 13760a708f8fSGustavo F. Padovan return; 13770a708f8fSGustavo F. Padovan 1378aad3d0e3SAndrei Emeltchenko if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) { 13791a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 13801a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 13811a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 13820a708f8fSGustavo F. Padovan } 13830a708f8fSGustavo F. Padovan 13842338a7e0SJohan Hedberg if (chan->scid == L2CAP_CID_A2MP) { 1385d117773cSGustavo Padovan l2cap_state_change(chan, BT_DISCONN); 1386416fa752SAndrei Emeltchenko return; 1387416fa752SAndrei Emeltchenko } 1388416fa752SAndrei Emeltchenko 1389fe4128e0SGustavo F. Padovan req.dcid = cpu_to_le16(chan->dcid); 1390fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 13912d792818SGustavo Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ, 13922d792818SGustavo Padovan sizeof(req), &req); 13930a708f8fSGustavo F. Padovan 1394f8e73017SGustavo Padovan l2cap_state_change_and_error(chan, BT_DISCONN, err); 13950a708f8fSGustavo F. Padovan } 13960a708f8fSGustavo F. Padovan 13970a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */ 13980a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn) 13990a708f8fSGustavo F. Padovan { 14003df91ea2SAndrei Emeltchenko struct l2cap_chan *chan, *tmp; 14010a708f8fSGustavo F. Padovan 14020a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 14030a708f8fSGustavo F. Padovan 14043df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 14050a708f8fSGustavo F. Padovan 14063df91ea2SAndrei Emeltchenko list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 14076be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 14080a708f8fSGustavo F. Padovan 1409715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1410aeaeb4bbSJohan Hedberg l2cap_chan_ready(chan); 14116be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 14120a708f8fSGustavo F. Padovan continue; 14130a708f8fSGustavo F. Padovan } 14140a708f8fSGustavo F. Padovan 141589bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 1416e7cafc45SJohan Hedberg if (!l2cap_chan_check_security(chan, true) || 1417b4450035SGustavo F. Padovan !__l2cap_no_conn_pending(chan)) { 14186be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 14190a708f8fSGustavo F. Padovan continue; 14200a708f8fSGustavo F. Padovan } 14210a708f8fSGustavo F. Padovan 1422c1360a1cSGustavo F. Padovan if (!l2cap_mode_supported(chan->mode, conn->feat_mask) 1423c1360a1cSGustavo F. Padovan && test_bit(CONF_STATE2_DEVICE, 1424c1360a1cSGustavo F. Padovan &chan->conf_state)) { 14250f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 14266be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 14270a708f8fSGustavo F. Padovan continue; 14280a708f8fSGustavo F. Padovan } 14290a708f8fSGustavo F. Padovan 143093c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 14310a708f8fSGustavo F. Padovan 143289bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 14330a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 14340a708f8fSGustavo F. Padovan char buf[128]; 1435fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 1436fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 14370a708f8fSGustavo F. Padovan 1438e7cafc45SJohan Hedberg if (l2cap_chan_check_security(chan, false)) { 1439bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 1440dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_PEND); 1441dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND); 14422dc4e510SGustavo Padovan chan->ops->defer(chan); 14430a708f8fSGustavo F. Padovan 14440a708f8fSGustavo F. Padovan } else { 1445acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 1446dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 1447dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 14480a708f8fSGustavo F. Padovan } 14490a708f8fSGustavo F. Padovan } else { 1450dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_PEND); 1451dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND); 14520a708f8fSGustavo F. Padovan } 14530a708f8fSGustavo F. Padovan 1454fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 1455fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 14560a708f8fSGustavo F. Padovan 1457c1360a1cSGustavo F. Padovan if (test_bit(CONF_REQ_SENT, &chan->conf_state) || 14580a708f8fSGustavo F. Padovan rsp.result != L2CAP_CR_SUCCESS) { 14596be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 14600a708f8fSGustavo F. Padovan continue; 14610a708f8fSGustavo F. Padovan } 14620a708f8fSGustavo F. Padovan 1463c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 14640a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 146573ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 146673ffa904SGustavo F. Padovan chan->num_conf_req++; 14670a708f8fSGustavo F. Padovan } 14680a708f8fSGustavo F. Padovan 14696be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 14700a708f8fSGustavo F. Padovan } 14710a708f8fSGustavo F. Padovan 14723df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 14730a708f8fSGustavo F. Padovan } 14740a708f8fSGustavo F. Padovan 1475b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn) 1476b62f328bSVille Tervo { 1477cc8dba2bSMarcel Holtmann struct hci_conn *hcon = conn->hcon; 1478dcc36c16SJohan Hedberg struct hci_dev *hdev = hcon->hdev; 1479b62f328bSVille Tervo 1480e760ec12SJohan Hedberg BT_DBG("%s conn %p", hdev->name, conn); 1481b62f328bSVille Tervo 1482e760ec12SJohan Hedberg /* For outgoing pairing which doesn't necessarily have an 1483e760ec12SJohan Hedberg * associated socket (e.g. mgmt_pair_device). 1484e760ec12SJohan Hedberg */ 1485e760ec12SJohan Hedberg if (hcon->out) 1486e760ec12SJohan Hedberg smp_conn_security(hcon, hcon->pending_sec_level); 1487cc8dba2bSMarcel Holtmann 148880afeb6cSMarcel Holtmann /* For LE slave connections, make sure the connection interval 148980afeb6cSMarcel Holtmann * is in the range of the minium and maximum interval that has 149080afeb6cSMarcel Holtmann * been configured for this connection. If not, then trigger 149180afeb6cSMarcel Holtmann * the connection update procedure. 149280afeb6cSMarcel Holtmann */ 149340bef302SJohan Hedberg if (hcon->role == HCI_ROLE_SLAVE && 149480afeb6cSMarcel Holtmann (hcon->le_conn_interval < hcon->le_conn_min_interval || 149580afeb6cSMarcel Holtmann hcon->le_conn_interval > hcon->le_conn_max_interval)) { 149680afeb6cSMarcel Holtmann struct l2cap_conn_param_update_req req; 149780afeb6cSMarcel Holtmann 149880afeb6cSMarcel Holtmann req.min = cpu_to_le16(hcon->le_conn_min_interval); 149980afeb6cSMarcel Holtmann req.max = cpu_to_le16(hcon->le_conn_max_interval); 150080afeb6cSMarcel Holtmann req.latency = cpu_to_le16(hcon->le_conn_latency); 150180afeb6cSMarcel Holtmann req.to_multiplier = cpu_to_le16(hcon->le_supv_timeout); 150280afeb6cSMarcel Holtmann 150380afeb6cSMarcel Holtmann l2cap_send_cmd(conn, l2cap_get_ident(conn), 150480afeb6cSMarcel Holtmann L2CAP_CONN_PARAM_UPDATE_REQ, sizeof(req), &req); 150580afeb6cSMarcel Holtmann } 1506b62f328bSVille Tervo } 1507b62f328bSVille Tervo 15080a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn) 15090a708f8fSGustavo F. Padovan { 151048454079SGustavo F. Padovan struct l2cap_chan *chan; 1511cc110922SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 15120a708f8fSGustavo F. Padovan 15130a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 15140a708f8fSGustavo F. Padovan 1515aeaeb4bbSJohan Hedberg if (hcon->type == ACL_LINK) 1516aeaeb4bbSJohan Hedberg l2cap_request_info(conn); 1517aeaeb4bbSJohan Hedberg 1518e760ec12SJohan Hedberg mutex_lock(&conn->chan_lock); 1519e760ec12SJohan Hedberg 15203df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1521baa7e1faSGustavo F. Padovan 15226be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 15230a708f8fSGustavo F. Padovan 15242338a7e0SJohan Hedberg if (chan->scid == L2CAP_CID_A2MP) { 1525416fa752SAndrei Emeltchenko l2cap_chan_unlock(chan); 1526416fa752SAndrei Emeltchenko continue; 1527416fa752SAndrei Emeltchenko } 1528416fa752SAndrei Emeltchenko 1529cc110922SVinicius Costa Gomes if (hcon->type == LE_LINK) { 1530f1496deeSJohan Hedberg l2cap_le_start(chan); 153163128451SVinicius Costa Gomes } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1532aeaeb4bbSJohan Hedberg if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 153374e75740SGustavo Padovan l2cap_chan_ready(chan); 15341c244f79SGustavo Padovan } else if (chan->state == BT_CONNECT) { 1535fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 15361c244f79SGustavo Padovan } 15370a708f8fSGustavo F. Padovan 15386be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 15390a708f8fSGustavo F. Padovan } 15400a708f8fSGustavo F. Padovan 15413df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 154261a939c6SJohan Hedberg 154379a05727SJohan Hedberg if (hcon->type == LE_LINK) 154479a05727SJohan Hedberg l2cap_le_conn_ready(conn); 154579a05727SJohan Hedberg 154661a939c6SJohan Hedberg queue_work(hcon->hdev->workqueue, &conn->pending_rx_work); 15470a708f8fSGustavo F. Padovan } 15480a708f8fSGustavo F. Padovan 15490a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */ 15500a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) 15510a708f8fSGustavo F. Padovan { 155248454079SGustavo F. Padovan struct l2cap_chan *chan; 15530a708f8fSGustavo F. Padovan 15540a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 15550a708f8fSGustavo F. Padovan 15563df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 15570a708f8fSGustavo F. Padovan 15583df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1559ecf61bdbSAndrei Emeltchenko if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) 15601d8b1fd5SGustavo Padovan l2cap_chan_set_err(chan, err); 15610a708f8fSGustavo F. Padovan } 15620a708f8fSGustavo F. Padovan 15633df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 15640a708f8fSGustavo F. Padovan } 15650a708f8fSGustavo F. Padovan 1566f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work) 15670a708f8fSGustavo F. Padovan { 1568f878fcadSGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 1569030013d8SGustavo F. Padovan info_timer.work); 15700a708f8fSGustavo F. Padovan 15710a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 15720a708f8fSGustavo F. Padovan conn->info_ident = 0; 15730a708f8fSGustavo F. Padovan 15740a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 15750a708f8fSGustavo F. Padovan } 15760a708f8fSGustavo F. Padovan 15772c8e1411SDavid Herrmann /* 15782c8e1411SDavid Herrmann * l2cap_user 15792c8e1411SDavid Herrmann * External modules can register l2cap_user objects on l2cap_conn. The ->probe 15802c8e1411SDavid Herrmann * callback is called during registration. The ->remove callback is called 15812c8e1411SDavid Herrmann * during unregistration. 15822c8e1411SDavid Herrmann * An l2cap_user object can either be explicitly unregistered or when the 15832c8e1411SDavid Herrmann * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon, 15842c8e1411SDavid Herrmann * l2cap->hchan, .. are valid as long as the remove callback hasn't been called. 15852c8e1411SDavid Herrmann * External modules must own a reference to the l2cap_conn object if they intend 15862c8e1411SDavid Herrmann * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at 15872c8e1411SDavid Herrmann * any time if they don't. 15882c8e1411SDavid Herrmann */ 15892c8e1411SDavid Herrmann 15902c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) 15912c8e1411SDavid Herrmann { 15922c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev; 15932c8e1411SDavid Herrmann int ret; 15942c8e1411SDavid Herrmann 15952c8e1411SDavid Herrmann /* We need to check whether l2cap_conn is registered. If it is not, we 15962c8e1411SDavid Herrmann * must not register the l2cap_user. l2cap_conn_del() is unregisters 15972c8e1411SDavid Herrmann * l2cap_conn objects, but doesn't provide its own locking. Instead, it 15982c8e1411SDavid Herrmann * relies on the parent hci_conn object to be locked. This itself relies 15992c8e1411SDavid Herrmann * on the hci_dev object to be locked. So we must lock the hci device 16002c8e1411SDavid Herrmann * here, too. */ 16012c8e1411SDavid Herrmann 16022c8e1411SDavid Herrmann hci_dev_lock(hdev); 16032c8e1411SDavid Herrmann 1604835a6a2fSAlexey Dobriyan if (!list_empty(&user->list)) { 16052c8e1411SDavid Herrmann ret = -EINVAL; 16062c8e1411SDavid Herrmann goto out_unlock; 16072c8e1411SDavid Herrmann } 16082c8e1411SDavid Herrmann 16092c8e1411SDavid Herrmann /* conn->hchan is NULL after l2cap_conn_del() was called */ 16102c8e1411SDavid Herrmann if (!conn->hchan) { 16112c8e1411SDavid Herrmann ret = -ENODEV; 16122c8e1411SDavid Herrmann goto out_unlock; 16132c8e1411SDavid Herrmann } 16142c8e1411SDavid Herrmann 16152c8e1411SDavid Herrmann ret = user->probe(conn, user); 16162c8e1411SDavid Herrmann if (ret) 16172c8e1411SDavid Herrmann goto out_unlock; 16182c8e1411SDavid Herrmann 16192c8e1411SDavid Herrmann list_add(&user->list, &conn->users); 16202c8e1411SDavid Herrmann ret = 0; 16212c8e1411SDavid Herrmann 16222c8e1411SDavid Herrmann out_unlock: 16232c8e1411SDavid Herrmann hci_dev_unlock(hdev); 16242c8e1411SDavid Herrmann return ret; 16252c8e1411SDavid Herrmann } 16262c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user); 16272c8e1411SDavid Herrmann 16282c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) 16292c8e1411SDavid Herrmann { 16302c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev; 16312c8e1411SDavid Herrmann 16322c8e1411SDavid Herrmann hci_dev_lock(hdev); 16332c8e1411SDavid Herrmann 1634835a6a2fSAlexey Dobriyan if (list_empty(&user->list)) 16352c8e1411SDavid Herrmann goto out_unlock; 16362c8e1411SDavid Herrmann 1637*ab944c83STedd Ho-Jeong An list_del_init(&user->list); 16382c8e1411SDavid Herrmann user->remove(conn, user); 16392c8e1411SDavid Herrmann 16402c8e1411SDavid Herrmann out_unlock: 16412c8e1411SDavid Herrmann hci_dev_unlock(hdev); 16422c8e1411SDavid Herrmann } 16432c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user); 16442c8e1411SDavid Herrmann 16452c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn) 16462c8e1411SDavid Herrmann { 16472c8e1411SDavid Herrmann struct l2cap_user *user; 16482c8e1411SDavid Herrmann 16492c8e1411SDavid Herrmann while (!list_empty(&conn->users)) { 16502c8e1411SDavid Herrmann user = list_first_entry(&conn->users, struct l2cap_user, list); 1651*ab944c83STedd Ho-Jeong An list_del_init(&user->list); 16522c8e1411SDavid Herrmann user->remove(conn, user); 16532c8e1411SDavid Herrmann } 16542c8e1411SDavid Herrmann } 16552c8e1411SDavid Herrmann 16565d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err) 16575d3de7dfSVinicius Costa Gomes { 16585d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 16595d3de7dfSVinicius Costa Gomes struct l2cap_chan *chan, *l; 16605d3de7dfSVinicius Costa Gomes 16615d3de7dfSVinicius Costa Gomes if (!conn) 16625d3de7dfSVinicius Costa Gomes return; 16635d3de7dfSVinicius Costa Gomes 16645d3de7dfSVinicius Costa Gomes BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); 16655d3de7dfSVinicius Costa Gomes 16665d3de7dfSVinicius Costa Gomes kfree_skb(conn->rx_skb); 16675d3de7dfSVinicius Costa Gomes 166861a939c6SJohan Hedberg skb_queue_purge(&conn->pending_rx); 16697ab56c3aSJukka Taimisto 16707ab56c3aSJukka Taimisto /* We can not call flush_work(&conn->pending_rx_work) here since we 16717ab56c3aSJukka Taimisto * might block if we are running on a worker from the same workqueue 16727ab56c3aSJukka Taimisto * pending_rx_work is waiting on. 16737ab56c3aSJukka Taimisto */ 16747ab56c3aSJukka Taimisto if (work_pending(&conn->pending_rx_work)) 16757ab56c3aSJukka Taimisto cancel_work_sync(&conn->pending_rx_work); 167661a939c6SJohan Hedberg 1677f3d82d0cSJohan Hedberg if (work_pending(&conn->id_addr_update_work)) 1678f3d82d0cSJohan Hedberg cancel_work_sync(&conn->id_addr_update_work); 1679f3d82d0cSJohan Hedberg 16802c8e1411SDavid Herrmann l2cap_unregister_all_users(conn); 16812c8e1411SDavid Herrmann 1682e31fb860SJohan Hedberg /* Force the connection to be immediately dropped */ 1683e31fb860SJohan Hedberg hcon->disc_timeout = 0; 1684e31fb860SJohan Hedberg 16853df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 16863df91ea2SAndrei Emeltchenko 16875d3de7dfSVinicius Costa Gomes /* Kill channels */ 16885d3de7dfSVinicius Costa Gomes list_for_each_entry_safe(chan, l, &conn->chan_l, list) { 168961d6ef3eSMat Martineau l2cap_chan_hold(chan); 16906be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 16916be36555SAndrei Emeltchenko 16925d3de7dfSVinicius Costa Gomes l2cap_chan_del(chan, err); 16936be36555SAndrei Emeltchenko 16946be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16956be36555SAndrei Emeltchenko 169680b98027SGustavo Padovan chan->ops->close(chan); 169761d6ef3eSMat Martineau l2cap_chan_put(chan); 16985d3de7dfSVinicius Costa Gomes } 16995d3de7dfSVinicius Costa Gomes 17003df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 17013df91ea2SAndrei Emeltchenko 170273d80debSLuiz Augusto von Dentz hci_chan_del(conn->hchan); 170373d80debSLuiz Augusto von Dentz 17045d3de7dfSVinicius Costa Gomes if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1705127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->info_timer); 17065d3de7dfSVinicius Costa Gomes 17075d3de7dfSVinicius Costa Gomes hcon->l2cap_data = NULL; 17089c903e37SDavid Herrmann conn->hchan = NULL; 17099c903e37SDavid Herrmann l2cap_conn_put(conn); 17105d3de7dfSVinicius Costa Gomes } 17115d3de7dfSVinicius Costa Gomes 17129c903e37SDavid Herrmann static void l2cap_conn_free(struct kref *ref) 17139c903e37SDavid Herrmann { 17149c903e37SDavid Herrmann struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref); 17159c903e37SDavid Herrmann 17169c903e37SDavid Herrmann hci_conn_put(conn->hcon); 17179c903e37SDavid Herrmann kfree(conn); 17189c903e37SDavid Herrmann } 17199c903e37SDavid Herrmann 172051bb8457SJohan Hedberg struct l2cap_conn *l2cap_conn_get(struct l2cap_conn *conn) 17219c903e37SDavid Herrmann { 17229c903e37SDavid Herrmann kref_get(&conn->ref); 172351bb8457SJohan Hedberg return conn; 17249c903e37SDavid Herrmann } 17259c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_get); 17269c903e37SDavid Herrmann 17279c903e37SDavid Herrmann void l2cap_conn_put(struct l2cap_conn *conn) 17289c903e37SDavid Herrmann { 17299c903e37SDavid Herrmann kref_put(&conn->ref, l2cap_conn_free); 17309c903e37SDavid Herrmann } 17319c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_put); 17329c903e37SDavid Herrmann 17330a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */ 17340a708f8fSGustavo F. Padovan 1735c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr. 17360a708f8fSGustavo F. Padovan * Returns closest match. 17370a708f8fSGustavo F. Padovan */ 1738c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, 1739c2287681SIdo Yariv bdaddr_t *src, 1740bf20fd4eSJohan Hedberg bdaddr_t *dst, 1741bf20fd4eSJohan Hedberg u8 link_type) 17420a708f8fSGustavo F. Padovan { 174323691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 17440a708f8fSGustavo F. Padovan 174523691d75SGustavo F. Padovan read_lock(&chan_list_lock); 17460a708f8fSGustavo F. Padovan 174723691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 174889bc500eSGustavo F. Padovan if (state && c->state != state) 17490a708f8fSGustavo F. Padovan continue; 17500a708f8fSGustavo F. Padovan 1751bf20fd4eSJohan Hedberg if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR) 1752bf20fd4eSJohan Hedberg continue; 1753bf20fd4eSJohan Hedberg 1754bf20fd4eSJohan Hedberg if (link_type == LE_LINK && c->src_type == BDADDR_BREDR) 1755bf20fd4eSJohan Hedberg continue; 1756bf20fd4eSJohan Hedberg 175723691d75SGustavo F. Padovan if (c->psm == psm) { 1758c2287681SIdo Yariv int src_match, dst_match; 1759c2287681SIdo Yariv int src_any, dst_any; 1760c2287681SIdo Yariv 17610a708f8fSGustavo F. Padovan /* Exact match. */ 17627eafc59eSMarcel Holtmann src_match = !bacmp(&c->src, src); 17637eafc59eSMarcel Holtmann dst_match = !bacmp(&c->dst, dst); 1764c2287681SIdo Yariv if (src_match && dst_match) { 1765a24cce14SJohan Hedberg l2cap_chan_hold(c); 1766a7567b20SJohannes Berg read_unlock(&chan_list_lock); 176723691d75SGustavo F. Padovan return c; 176823691d75SGustavo F. Padovan } 17690a708f8fSGustavo F. Padovan 17700a708f8fSGustavo F. Padovan /* Closest match */ 17717eafc59eSMarcel Holtmann src_any = !bacmp(&c->src, BDADDR_ANY); 17727eafc59eSMarcel Holtmann dst_any = !bacmp(&c->dst, BDADDR_ANY); 1773c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1774c2287681SIdo Yariv (src_any && dst_any)) 177523691d75SGustavo F. Padovan c1 = c; 17760a708f8fSGustavo F. Padovan } 17770a708f8fSGustavo F. Padovan } 17780a708f8fSGustavo F. Padovan 1779a24cce14SJohan Hedberg if (c1) 1780a24cce14SJohan Hedberg l2cap_chan_hold(c1); 1781a24cce14SJohan Hedberg 178223691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 17830a708f8fSGustavo F. Padovan 178423691d75SGustavo F. Padovan return c1; 17850a708f8fSGustavo F. Padovan } 17860a708f8fSGustavo F. Padovan 1787721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work) 17880a708f8fSGustavo F. Padovan { 1789721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1790721c4181SGustavo F. Padovan monitor_timer.work); 17910a708f8fSGustavo F. Padovan 1792525cd185SGustavo F. Padovan BT_DBG("chan %p", chan); 17930a708f8fSGustavo F. Padovan 17946be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 17956be36555SAndrei Emeltchenko 179680909e04SMat Martineau if (!chan->conn) { 17976be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 17988d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 17990a708f8fSGustavo F. Padovan return; 18000a708f8fSGustavo F. Padovan } 18010a708f8fSGustavo F. Padovan 1802401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO); 18030a708f8fSGustavo F. Padovan 18046be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 18058d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 18060a708f8fSGustavo F. Padovan } 18070a708f8fSGustavo F. Padovan 1808721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work) 18090a708f8fSGustavo F. Padovan { 1810721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1811721c4181SGustavo F. Padovan retrans_timer.work); 18120a708f8fSGustavo F. Padovan 181349208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 18140a708f8fSGustavo F. Padovan 18156be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 18166be36555SAndrei Emeltchenko 181780909e04SMat Martineau if (!chan->conn) { 181880909e04SMat Martineau l2cap_chan_unlock(chan); 181980909e04SMat Martineau l2cap_chan_put(chan); 182080909e04SMat Martineau return; 182180909e04SMat Martineau } 18220a708f8fSGustavo F. Padovan 1823401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO); 18246be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 18258d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 18260a708f8fSGustavo F. Padovan } 18270a708f8fSGustavo F. Padovan 1828d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan, 18293733937dSMat Martineau struct sk_buff_head *skbs) 18300a708f8fSGustavo F. Padovan { 18310a708f8fSGustavo F. Padovan struct sk_buff *skb; 18323733937dSMat Martineau struct l2cap_ctrl *control; 18330a708f8fSGustavo F. Padovan 18343733937dSMat Martineau BT_DBG("chan %p, skbs %p", chan, skbs); 18353733937dSMat Martineau 1836b99e13adSMat Martineau if (__chan_is_moving(chan)) 1837b99e13adSMat Martineau return; 1838b99e13adSMat Martineau 18393733937dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 18403733937dSMat Martineau 18413733937dSMat Martineau while (!skb_queue_empty(&chan->tx_q)) { 18423733937dSMat Martineau 18433733937dSMat Martineau skb = skb_dequeue(&chan->tx_q); 18443733937dSMat Martineau 1845a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 1; 1846a4368ff3SJohan Hedberg control = &bt_cb(skb)->l2cap; 18473733937dSMat Martineau 18483733937dSMat Martineau control->reqseq = 0; 18493733937dSMat Martineau control->txseq = chan->next_tx_seq; 18503733937dSMat Martineau 18513733937dSMat Martineau __pack_control(chan, control, skb); 18520a708f8fSGustavo F. Padovan 185347d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 18543733937dSMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 18553733937dSMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 18560a708f8fSGustavo F. Padovan } 18570a708f8fSGustavo F. Padovan 18584343478fSGustavo F. Padovan l2cap_do_send(chan, skb); 18590a708f8fSGustavo F. Padovan 1860b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 18613733937dSMat Martineau 1862836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 18633733937dSMat Martineau chan->frames_sent++; 18640a708f8fSGustavo F. Padovan } 18650a708f8fSGustavo F. Padovan } 18660a708f8fSGustavo F. Padovan 186767c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan) 18680a708f8fSGustavo F. Padovan { 18690a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 187018a48e76SMat Martineau struct l2cap_ctrl *control; 187118a48e76SMat Martineau int sent = 0; 187218a48e76SMat Martineau 187318a48e76SMat Martineau BT_DBG("chan %p", chan); 18740a708f8fSGustavo F. Padovan 187589bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 18760a708f8fSGustavo F. Padovan return -ENOTCONN; 18770a708f8fSGustavo F. Padovan 187894122bbeSMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 187994122bbeSMat Martineau return 0; 188094122bbeSMat Martineau 1881b99e13adSMat Martineau if (__chan_is_moving(chan)) 1882b99e13adSMat Martineau return 0; 1883b99e13adSMat Martineau 188418a48e76SMat Martineau while (chan->tx_send_head && 188518a48e76SMat Martineau chan->unacked_frames < chan->remote_tx_win && 188618a48e76SMat Martineau chan->tx_state == L2CAP_TX_STATE_XMIT) { 18870a708f8fSGustavo F. Padovan 188818a48e76SMat Martineau skb = chan->tx_send_head; 18890a708f8fSGustavo F. Padovan 1890a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 1; 1891a4368ff3SJohan Hedberg control = &bt_cb(skb)->l2cap; 18920a708f8fSGustavo F. Padovan 1893e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 189418a48e76SMat Martineau control->final = 1; 1895e2ab4353SGustavo F. Padovan 189618a48e76SMat Martineau control->reqseq = chan->buffer_seq; 189718a48e76SMat Martineau chan->last_acked_seq = chan->buffer_seq; 189818a48e76SMat Martineau control->txseq = chan->next_tx_seq; 18990a708f8fSGustavo F. Padovan 190018a48e76SMat Martineau __pack_control(chan, control, skb); 19010a708f8fSGustavo F. Padovan 190247d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 190318a48e76SMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 190418a48e76SMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 19050a708f8fSGustavo F. Padovan } 19060a708f8fSGustavo F. Padovan 190718a48e76SMat Martineau /* Clone after data has been modified. Data is assumed to be 190818a48e76SMat Martineau read-only (for locking purposes) on cloned sk_buffs. 190918a48e76SMat Martineau */ 191018a48e76SMat Martineau tx_skb = skb_clone(skb, GFP_KERNEL); 191118a48e76SMat Martineau 191218a48e76SMat Martineau if (!tx_skb) 191318a48e76SMat Martineau break; 19140a708f8fSGustavo F. Padovan 19151a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 19160a708f8fSGustavo F. Padovan 1917836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 19186a026610SGustavo F. Padovan chan->unacked_frames++; 19196a026610SGustavo F. Padovan chan->frames_sent++; 192018a48e76SMat Martineau sent++; 19210a708f8fSGustavo F. Padovan 192258d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 192358d35f87SGustavo F. Padovan chan->tx_send_head = NULL; 19240a708f8fSGustavo F. Padovan else 192558d35f87SGustavo F. Padovan chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); 192618a48e76SMat Martineau 192718a48e76SMat Martineau l2cap_do_send(chan, tx_skb); 1928b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 19290a708f8fSGustavo F. Padovan } 19300a708f8fSGustavo F. Padovan 1931b4400672SAndrei Emeltchenko BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent, 1932b4400672SAndrei Emeltchenko chan->unacked_frames, skb_queue_len(&chan->tx_q)); 193318a48e76SMat Martineau 193418a48e76SMat Martineau return sent; 19350a708f8fSGustavo F. Padovan } 19360a708f8fSGustavo F. Padovan 1937e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan) 1938e1fbd4c1SMat Martineau { 1939e1fbd4c1SMat Martineau struct l2cap_ctrl control; 1940e1fbd4c1SMat Martineau struct sk_buff *skb; 1941e1fbd4c1SMat Martineau struct sk_buff *tx_skb; 1942e1fbd4c1SMat Martineau u16 seq; 1943e1fbd4c1SMat Martineau 1944e1fbd4c1SMat Martineau BT_DBG("chan %p", chan); 1945e1fbd4c1SMat Martineau 1946e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 1947e1fbd4c1SMat Martineau return; 1948e1fbd4c1SMat Martineau 1949b99e13adSMat Martineau if (__chan_is_moving(chan)) 1950b99e13adSMat Martineau return; 1951b99e13adSMat Martineau 1952e1fbd4c1SMat Martineau while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) { 1953e1fbd4c1SMat Martineau seq = l2cap_seq_list_pop(&chan->retrans_list); 1954e1fbd4c1SMat Martineau 1955e1fbd4c1SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq); 1956e1fbd4c1SMat Martineau if (!skb) { 1957e1fbd4c1SMat Martineau BT_DBG("Error: Can't retransmit seq %d, frame missing", 1958e1fbd4c1SMat Martineau seq); 1959e1fbd4c1SMat Martineau continue; 1960e1fbd4c1SMat Martineau } 1961e1fbd4c1SMat Martineau 1962a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries++; 1963a4368ff3SJohan Hedberg control = bt_cb(skb)->l2cap; 1964e1fbd4c1SMat Martineau 1965e1fbd4c1SMat Martineau if (chan->max_tx != 0 && 1966a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries > chan->max_tx) { 1967e1fbd4c1SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 19685e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 1969e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 1970e1fbd4c1SMat Martineau break; 1971e1fbd4c1SMat Martineau } 1972e1fbd4c1SMat Martineau 1973e1fbd4c1SMat Martineau control.reqseq = chan->buffer_seq; 1974e1fbd4c1SMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 1975e1fbd4c1SMat Martineau control.final = 1; 1976e1fbd4c1SMat Martineau else 1977e1fbd4c1SMat Martineau control.final = 0; 1978e1fbd4c1SMat Martineau 1979e1fbd4c1SMat Martineau if (skb_cloned(skb)) { 1980e1fbd4c1SMat Martineau /* Cloned sk_buffs are read-only, so we need a 1981e1fbd4c1SMat Martineau * writeable copy 1982e1fbd4c1SMat Martineau */ 19838bcde1f2SGustavo Padovan tx_skb = skb_copy(skb, GFP_KERNEL); 1984e1fbd4c1SMat Martineau } else { 19858bcde1f2SGustavo Padovan tx_skb = skb_clone(skb, GFP_KERNEL); 1986e1fbd4c1SMat Martineau } 1987e1fbd4c1SMat Martineau 1988e1fbd4c1SMat Martineau if (!tx_skb) { 1989e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 1990e1fbd4c1SMat Martineau break; 1991e1fbd4c1SMat Martineau } 1992e1fbd4c1SMat Martineau 1993e1fbd4c1SMat Martineau /* Update skb contents */ 1994e1fbd4c1SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 1995e1fbd4c1SMat Martineau put_unaligned_le32(__pack_extended_control(&control), 1996e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 1997e1fbd4c1SMat Martineau } else { 1998e1fbd4c1SMat Martineau put_unaligned_le16(__pack_enhanced_control(&control), 1999e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 2000e1fbd4c1SMat Martineau } 2001e1fbd4c1SMat Martineau 200213cac152SLukasz Rymanowski /* Update FCS */ 2003e1fbd4c1SMat Martineau if (chan->fcs == L2CAP_FCS_CRC16) { 200413cac152SLukasz Rymanowski u16 fcs = crc16(0, (u8 *) tx_skb->data, 200513cac152SLukasz Rymanowski tx_skb->len - L2CAP_FCS_SIZE); 200613cac152SLukasz Rymanowski put_unaligned_le16(fcs, skb_tail_pointer(tx_skb) - 200713cac152SLukasz Rymanowski L2CAP_FCS_SIZE); 2008e1fbd4c1SMat Martineau } 2009e1fbd4c1SMat Martineau 2010e1fbd4c1SMat Martineau l2cap_do_send(chan, tx_skb); 2011e1fbd4c1SMat Martineau 2012e1fbd4c1SMat Martineau BT_DBG("Resent txseq %d", control.txseq); 2013e1fbd4c1SMat Martineau 2014e1fbd4c1SMat Martineau chan->last_acked_seq = chan->buffer_seq; 2015e1fbd4c1SMat Martineau } 2016e1fbd4c1SMat Martineau } 2017e1fbd4c1SMat Martineau 2018f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan, 2019f80842a8SMat Martineau struct l2cap_ctrl *control) 2020f80842a8SMat Martineau { 2021f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2022f80842a8SMat Martineau 2023f80842a8SMat Martineau l2cap_seq_list_append(&chan->retrans_list, control->reqseq); 2024f80842a8SMat Martineau l2cap_ertm_resend(chan); 2025f80842a8SMat Martineau } 2026f80842a8SMat Martineau 2027d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan, 2028d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 2029d2a7ac5dSMat Martineau { 2030e1fbd4c1SMat Martineau struct sk_buff *skb; 2031e1fbd4c1SMat Martineau 2032e1fbd4c1SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2033e1fbd4c1SMat Martineau 2034e1fbd4c1SMat Martineau if (control->poll) 2035e1fbd4c1SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 2036e1fbd4c1SMat Martineau 2037e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2038e1fbd4c1SMat Martineau 2039e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 2040e1fbd4c1SMat Martineau return; 2041e1fbd4c1SMat Martineau 2042e1fbd4c1SMat Martineau if (chan->unacked_frames) { 2043e1fbd4c1SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 2044a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.txseq == control->reqseq || 2045e1fbd4c1SMat Martineau skb == chan->tx_send_head) 2046e1fbd4c1SMat Martineau break; 2047e1fbd4c1SMat Martineau } 2048e1fbd4c1SMat Martineau 2049e1fbd4c1SMat Martineau skb_queue_walk_from(&chan->tx_q, skb) { 2050e1fbd4c1SMat Martineau if (skb == chan->tx_send_head) 2051e1fbd4c1SMat Martineau break; 2052e1fbd4c1SMat Martineau 2053e1fbd4c1SMat Martineau l2cap_seq_list_append(&chan->retrans_list, 2054a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.txseq); 2055e1fbd4c1SMat Martineau } 2056e1fbd4c1SMat Martineau 2057e1fbd4c1SMat Martineau l2cap_ertm_resend(chan); 2058e1fbd4c1SMat Martineau } 2059d2a7ac5dSMat Martineau } 2060d2a7ac5dSMat Martineau 2061b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan) 2062b17e73bbSSzymon Janc { 20630a0aba42SMat Martineau struct l2cap_ctrl control; 20640a0aba42SMat Martineau u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq, 20650a0aba42SMat Martineau chan->last_acked_seq); 20660a0aba42SMat Martineau int threshold; 20670a0aba42SMat Martineau 20680a0aba42SMat Martineau BT_DBG("chan %p last_acked_seq %d buffer_seq %d", 20690a0aba42SMat Martineau chan, chan->last_acked_seq, chan->buffer_seq); 20700a0aba42SMat Martineau 20710a0aba42SMat Martineau memset(&control, 0, sizeof(control)); 20720a0aba42SMat Martineau control.sframe = 1; 20730a0aba42SMat Martineau 20740a0aba42SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 20750a0aba42SMat Martineau chan->rx_state == L2CAP_RX_STATE_RECV) { 2076b17e73bbSSzymon Janc __clear_ack_timer(chan); 20770a0aba42SMat Martineau control.super = L2CAP_SUPER_RNR; 20780a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 20790a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 20800a0aba42SMat Martineau } else { 20810a0aba42SMat Martineau if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) { 20820a0aba42SMat Martineau l2cap_ertm_send(chan); 20830a0aba42SMat Martineau /* If any i-frames were sent, they included an ack */ 20840a0aba42SMat Martineau if (chan->buffer_seq == chan->last_acked_seq) 20850a0aba42SMat Martineau frames_to_ack = 0; 20860a0aba42SMat Martineau } 20870a0aba42SMat Martineau 2088c20f8e35SMat Martineau /* Ack now if the window is 3/4ths full. 20890a0aba42SMat Martineau * Calculate without mul or div 20900a0aba42SMat Martineau */ 2091c20f8e35SMat Martineau threshold = chan->ack_win; 20920a0aba42SMat Martineau threshold += threshold << 1; 20930a0aba42SMat Martineau threshold >>= 2; 20940a0aba42SMat Martineau 2095b4400672SAndrei Emeltchenko BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack, 20960a0aba42SMat Martineau threshold); 20970a0aba42SMat Martineau 20980a0aba42SMat Martineau if (frames_to_ack >= threshold) { 20990a0aba42SMat Martineau __clear_ack_timer(chan); 21000a0aba42SMat Martineau control.super = L2CAP_SUPER_RR; 21010a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 21020a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 21030a0aba42SMat Martineau frames_to_ack = 0; 21040a0aba42SMat Martineau } 21050a0aba42SMat Martineau 21060a0aba42SMat Martineau if (frames_to_ack) 21070a0aba42SMat Martineau __set_ack_timer(chan); 21080a0aba42SMat Martineau } 2109b17e73bbSSzymon Janc } 2110b17e73bbSSzymon Janc 211104124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, 211204124681SGustavo F. Padovan struct msghdr *msg, int len, 211304124681SGustavo F. Padovan int count, struct sk_buff *skb) 21140a708f8fSGustavo F. Padovan { 21150952a57aSAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 21160a708f8fSGustavo F. Padovan struct sk_buff **frag; 211790338947SGustavo Padovan int sent = 0; 21180a708f8fSGustavo F. Padovan 211917836394SAl Viro if (copy_from_iter(skb_put(skb, count), count, &msg->msg_iter) != count) 21200a708f8fSGustavo F. Padovan return -EFAULT; 21210a708f8fSGustavo F. Padovan 21220a708f8fSGustavo F. Padovan sent += count; 21230a708f8fSGustavo F. Padovan len -= count; 21240a708f8fSGustavo F. Padovan 21250a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 21260a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 21270a708f8fSGustavo F. Padovan while (len) { 2128fbe00700SGustavo Padovan struct sk_buff *tmp; 2129fbe00700SGustavo Padovan 21300a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 21310a708f8fSGustavo F. Padovan 2132d9fbd02bSMarcel Holtmann tmp = chan->ops->alloc_skb(chan, 0, count, 213390338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 2134fbe00700SGustavo Padovan if (IS_ERR(tmp)) 2135fbe00700SGustavo Padovan return PTR_ERR(tmp); 21362f7719ceSAndrei Emeltchenko 2137fbe00700SGustavo Padovan *frag = tmp; 2138fbe00700SGustavo Padovan 213917836394SAl Viro if (copy_from_iter(skb_put(*frag, count), count, 214017836394SAl Viro &msg->msg_iter) != count) 21410a708f8fSGustavo F. Padovan return -EFAULT; 21420a708f8fSGustavo F. Padovan 21430a708f8fSGustavo F. Padovan sent += count; 21440a708f8fSGustavo F. Padovan len -= count; 21450a708f8fSGustavo F. Padovan 21462d0ed3d5SGustavo Padovan skb->len += (*frag)->len; 21472d0ed3d5SGustavo Padovan skb->data_len += (*frag)->len; 21482d0ed3d5SGustavo Padovan 21490a708f8fSGustavo F. Padovan frag = &(*frag)->next; 21500a708f8fSGustavo F. Padovan } 21510a708f8fSGustavo F. Padovan 21520a708f8fSGustavo F. Padovan return sent; 21530a708f8fSGustavo F. Padovan } 21540a708f8fSGustavo F. Padovan 21555e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, 21568d46321cSMarcel Holtmann struct msghdr *msg, size_t len) 21570a708f8fSGustavo F. Padovan { 21588c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 21590a708f8fSGustavo F. Padovan struct sk_buff *skb; 216003a51213SAndrei Emeltchenko int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; 21610a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 21620a708f8fSGustavo F. Padovan 21638d46321cSMarcel Holtmann BT_DBG("chan %p psm 0x%2.2x len %zu", chan, 21648d46321cSMarcel Holtmann __le16_to_cpu(chan->psm), len); 21650a708f8fSGustavo F. Padovan 21660a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 21672f7719ceSAndrei Emeltchenko 2168d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, hlen, count, 216990338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 217090338947SGustavo Padovan if (IS_ERR(skb)) 217190338947SGustavo Padovan return skb; 21720a708f8fSGustavo F. Padovan 21730a708f8fSGustavo F. Padovan /* Create L2CAP header */ 21740a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2175fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 2176daf6a78cSAndrei Emeltchenko lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); 217743b1b8dfSMarcel Holtmann put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE)); 21780a708f8fSGustavo F. Padovan 21790952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 21800a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 21810a708f8fSGustavo F. Padovan kfree_skb(skb); 21820a708f8fSGustavo F. Padovan return ERR_PTR(err); 21830a708f8fSGustavo F. Padovan } 21840a708f8fSGustavo F. Padovan return skb; 21850a708f8fSGustavo F. Padovan } 21860a708f8fSGustavo F. Padovan 21875e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, 21888d46321cSMarcel Holtmann struct msghdr *msg, size_t len) 21890a708f8fSGustavo F. Padovan { 21908c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 21910a708f8fSGustavo F. Padovan struct sk_buff *skb; 2192f2ba7faeSGustavo Padovan int err, count; 21930a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 21940a708f8fSGustavo F. Padovan 2195b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 21960a708f8fSGustavo F. Padovan 2197f2ba7faeSGustavo Padovan count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); 21982f7719ceSAndrei Emeltchenko 2199d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, L2CAP_HDR_SIZE, count, 220090338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 220190338947SGustavo Padovan if (IS_ERR(skb)) 220290338947SGustavo Padovan return skb; 22030a708f8fSGustavo F. Padovan 22040a708f8fSGustavo F. Padovan /* Create L2CAP header */ 22050a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2206fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 22076ff9b5efSGustavo Padovan lh->len = cpu_to_le16(len); 22080a708f8fSGustavo F. Padovan 22090952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 22100a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 22110a708f8fSGustavo F. Padovan kfree_skb(skb); 22120a708f8fSGustavo F. Padovan return ERR_PTR(err); 22130a708f8fSGustavo F. Padovan } 22140a708f8fSGustavo F. Padovan return skb; 22150a708f8fSGustavo F. Padovan } 22160a708f8fSGustavo F. Padovan 2217ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, 2218ab0ff76dSLuiz Augusto von Dentz struct msghdr *msg, size_t len, 221994122bbeSMat Martineau u16 sdulen) 22200a708f8fSGustavo F. Padovan { 22218c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 22220a708f8fSGustavo F. Padovan struct sk_buff *skb; 2223e4ca6d98SAndrei Emeltchenko int err, count, hlen; 22240a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 22250a708f8fSGustavo F. Padovan 2226b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 22270a708f8fSGustavo F. Padovan 22280a708f8fSGustavo F. Padovan if (!conn) 22290a708f8fSGustavo F. Padovan return ERR_PTR(-ENOTCONN); 22300a708f8fSGustavo F. Padovan 2231ba7aa64fSGustavo Padovan hlen = __ertm_hdr_size(chan); 2232e4ca6d98SAndrei Emeltchenko 22330a708f8fSGustavo F. Padovan if (sdulen) 223403a51213SAndrei Emeltchenko hlen += L2CAP_SDULEN_SIZE; 22350a708f8fSGustavo F. Padovan 223647d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 223703a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 22380a708f8fSGustavo F. Padovan 22390a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 22402f7719ceSAndrei Emeltchenko 2241d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, hlen, count, 224290338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 224390338947SGustavo Padovan if (IS_ERR(skb)) 224490338947SGustavo Padovan return skb; 22450a708f8fSGustavo F. Padovan 22460a708f8fSGustavo F. Padovan /* Create L2CAP header */ 22470a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2248fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 22490a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 225088843ab0SAndrei Emeltchenko 225118a48e76SMat Martineau /* Control header is populated later */ 225218a48e76SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 225318a48e76SMat Martineau put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 225418a48e76SMat Martineau else 225518a48e76SMat Martineau put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 225688843ab0SAndrei Emeltchenko 22570a708f8fSGustavo F. Padovan if (sdulen) 225803a51213SAndrei Emeltchenko put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 22590a708f8fSGustavo F. Padovan 22600952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 22610a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 22620a708f8fSGustavo F. Padovan kfree_skb(skb); 22630a708f8fSGustavo F. Padovan return ERR_PTR(err); 22640a708f8fSGustavo F. Padovan } 22650a708f8fSGustavo F. Padovan 2266a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.fcs = chan->fcs; 2267a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries = 0; 22680a708f8fSGustavo F. Padovan return skb; 22690a708f8fSGustavo F. Padovan } 22700a708f8fSGustavo F. Padovan 227194122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan, 227294122bbeSMat Martineau struct sk_buff_head *seg_queue, 227394122bbeSMat Martineau struct msghdr *msg, size_t len) 22740a708f8fSGustavo F. Padovan { 22750a708f8fSGustavo F. Padovan struct sk_buff *skb; 227694122bbeSMat Martineau u16 sdu_len; 227794122bbeSMat Martineau size_t pdu_len; 227894122bbeSMat Martineau u8 sar; 22790a708f8fSGustavo F. Padovan 2280b4400672SAndrei Emeltchenko BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); 22810a708f8fSGustavo F. Padovan 228294122bbeSMat Martineau /* It is critical that ERTM PDUs fit in a single HCI fragment, 228394122bbeSMat Martineau * so fragmented skbs are not used. The HCI layer's handling 228494122bbeSMat Martineau * of fragmented skbs is not compatible with ERTM's queueing. 228594122bbeSMat Martineau */ 228694122bbeSMat Martineau 228794122bbeSMat Martineau /* PDU size is derived from the HCI MTU */ 228894122bbeSMat Martineau pdu_len = chan->conn->mtu; 228994122bbeSMat Martineau 2290a549574dSMat Martineau /* Constrain PDU size for BR/EDR connections */ 2291a549574dSMat Martineau if (!chan->hs_hcon) 229294122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); 229394122bbeSMat Martineau 229494122bbeSMat Martineau /* Adjust for largest possible L2CAP overhead. */ 229535d401dfSGustavo Padovan if (chan->fcs) 229635d401dfSGustavo Padovan pdu_len -= L2CAP_FCS_SIZE; 229735d401dfSGustavo Padovan 2298ba7aa64fSGustavo Padovan pdu_len -= __ertm_hdr_size(chan); 229994122bbeSMat Martineau 230094122bbeSMat Martineau /* Remote device may have requested smaller PDUs */ 230194122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, chan->remote_mps); 230294122bbeSMat Martineau 230394122bbeSMat Martineau if (len <= pdu_len) { 230494122bbeSMat Martineau sar = L2CAP_SAR_UNSEGMENTED; 230594122bbeSMat Martineau sdu_len = 0; 230694122bbeSMat Martineau pdu_len = len; 230794122bbeSMat Martineau } else { 230894122bbeSMat Martineau sar = L2CAP_SAR_START; 230994122bbeSMat Martineau sdu_len = len; 231094122bbeSMat Martineau } 23110a708f8fSGustavo F. Padovan 23120a708f8fSGustavo F. Padovan while (len > 0) { 231394122bbeSMat Martineau skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len); 23140a708f8fSGustavo F. Padovan 23150a708f8fSGustavo F. Padovan if (IS_ERR(skb)) { 231694122bbeSMat Martineau __skb_queue_purge(seg_queue); 23170a708f8fSGustavo F. Padovan return PTR_ERR(skb); 23180a708f8fSGustavo F. Padovan } 23190a708f8fSGustavo F. Padovan 2320a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.sar = sar; 232194122bbeSMat Martineau __skb_queue_tail(seg_queue, skb); 23220a708f8fSGustavo F. Padovan 232394122bbeSMat Martineau len -= pdu_len; 2324069cb270SLukasz Rymanowski if (sdu_len) 232594122bbeSMat Martineau sdu_len = 0; 232694122bbeSMat Martineau 232794122bbeSMat Martineau if (len <= pdu_len) { 232894122bbeSMat Martineau sar = L2CAP_SAR_END; 232994122bbeSMat Martineau pdu_len = len; 233094122bbeSMat Martineau } else { 233194122bbeSMat Martineau sar = L2CAP_SAR_CONTINUE; 233294122bbeSMat Martineau } 233394122bbeSMat Martineau } 233494122bbeSMat Martineau 2335f0f62799SGustavo Padovan return 0; 23360a708f8fSGustavo F. Padovan } 23370a708f8fSGustavo F. Padovan 2338177f8f2bSJohan Hedberg static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan, 2339177f8f2bSJohan Hedberg struct msghdr *msg, 2340177f8f2bSJohan Hedberg size_t len, u16 sdulen) 2341177f8f2bSJohan Hedberg { 2342177f8f2bSJohan Hedberg struct l2cap_conn *conn = chan->conn; 2343177f8f2bSJohan Hedberg struct sk_buff *skb; 2344177f8f2bSJohan Hedberg int err, count, hlen; 2345177f8f2bSJohan Hedberg struct l2cap_hdr *lh; 2346177f8f2bSJohan Hedberg 2347177f8f2bSJohan Hedberg BT_DBG("chan %p len %zu", chan, len); 2348177f8f2bSJohan Hedberg 2349177f8f2bSJohan Hedberg if (!conn) 2350177f8f2bSJohan Hedberg return ERR_PTR(-ENOTCONN); 2351177f8f2bSJohan Hedberg 2352177f8f2bSJohan Hedberg hlen = L2CAP_HDR_SIZE; 2353177f8f2bSJohan Hedberg 2354177f8f2bSJohan Hedberg if (sdulen) 2355177f8f2bSJohan Hedberg hlen += L2CAP_SDULEN_SIZE; 2356177f8f2bSJohan Hedberg 2357177f8f2bSJohan Hedberg count = min_t(unsigned int, (conn->mtu - hlen), len); 2358177f8f2bSJohan Hedberg 2359d9fbd02bSMarcel Holtmann skb = chan->ops->alloc_skb(chan, hlen, count, 2360177f8f2bSJohan Hedberg msg->msg_flags & MSG_DONTWAIT); 2361177f8f2bSJohan Hedberg if (IS_ERR(skb)) 2362177f8f2bSJohan Hedberg return skb; 2363177f8f2bSJohan Hedberg 2364177f8f2bSJohan Hedberg /* Create L2CAP header */ 2365177f8f2bSJohan Hedberg lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2366177f8f2bSJohan Hedberg lh->cid = cpu_to_le16(chan->dcid); 2367177f8f2bSJohan Hedberg lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 2368177f8f2bSJohan Hedberg 2369177f8f2bSJohan Hedberg if (sdulen) 2370177f8f2bSJohan Hedberg put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 2371177f8f2bSJohan Hedberg 2372177f8f2bSJohan Hedberg err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 2373177f8f2bSJohan Hedberg if (unlikely(err < 0)) { 2374177f8f2bSJohan Hedberg kfree_skb(skb); 2375177f8f2bSJohan Hedberg return ERR_PTR(err); 2376177f8f2bSJohan Hedberg } 2377177f8f2bSJohan Hedberg 2378177f8f2bSJohan Hedberg return skb; 2379177f8f2bSJohan Hedberg } 2380177f8f2bSJohan Hedberg 2381177f8f2bSJohan Hedberg static int l2cap_segment_le_sdu(struct l2cap_chan *chan, 2382177f8f2bSJohan Hedberg struct sk_buff_head *seg_queue, 2383177f8f2bSJohan Hedberg struct msghdr *msg, size_t len) 2384177f8f2bSJohan Hedberg { 2385177f8f2bSJohan Hedberg struct sk_buff *skb; 2386177f8f2bSJohan Hedberg size_t pdu_len; 2387177f8f2bSJohan Hedberg u16 sdu_len; 2388177f8f2bSJohan Hedberg 2389177f8f2bSJohan Hedberg BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); 2390177f8f2bSJohan Hedberg 2391177f8f2bSJohan Hedberg sdu_len = len; 239272c6fb91SJohan Hedberg pdu_len = chan->remote_mps - L2CAP_SDULEN_SIZE; 2393177f8f2bSJohan Hedberg 2394177f8f2bSJohan Hedberg while (len > 0) { 2395177f8f2bSJohan Hedberg if (len <= pdu_len) 2396177f8f2bSJohan Hedberg pdu_len = len; 2397177f8f2bSJohan Hedberg 2398177f8f2bSJohan Hedberg skb = l2cap_create_le_flowctl_pdu(chan, msg, pdu_len, sdu_len); 2399177f8f2bSJohan Hedberg if (IS_ERR(skb)) { 2400177f8f2bSJohan Hedberg __skb_queue_purge(seg_queue); 2401177f8f2bSJohan Hedberg return PTR_ERR(skb); 2402177f8f2bSJohan Hedberg } 2403177f8f2bSJohan Hedberg 2404177f8f2bSJohan Hedberg __skb_queue_tail(seg_queue, skb); 2405177f8f2bSJohan Hedberg 2406177f8f2bSJohan Hedberg len -= pdu_len; 2407177f8f2bSJohan Hedberg 2408177f8f2bSJohan Hedberg if (sdu_len) { 2409177f8f2bSJohan Hedberg sdu_len = 0; 2410177f8f2bSJohan Hedberg pdu_len += L2CAP_SDULEN_SIZE; 2411177f8f2bSJohan Hedberg } 2412177f8f2bSJohan Hedberg } 2413177f8f2bSJohan Hedberg 2414177f8f2bSJohan Hedberg return 0; 2415177f8f2bSJohan Hedberg } 2416177f8f2bSJohan Hedberg 24178d46321cSMarcel Holtmann int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len) 24189a91a04aSGustavo F. Padovan { 24199a91a04aSGustavo F. Padovan struct sk_buff *skb; 24209a91a04aSGustavo F. Padovan int err; 242194122bbeSMat Martineau struct sk_buff_head seg_queue; 24229a91a04aSGustavo F. Padovan 242331e8ce80SSeung-Woo Kim if (!chan->conn) 242431e8ce80SSeung-Woo Kim return -ENOTCONN; 242531e8ce80SSeung-Woo Kim 24269a91a04aSGustavo F. Padovan /* Connectionless channel */ 2427715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { 24288d46321cSMarcel Holtmann skb = l2cap_create_connless_pdu(chan, msg, len); 24299a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 24309a91a04aSGustavo F. Padovan return PTR_ERR(skb); 24319a91a04aSGustavo F. Padovan 2432ede81a2aSAndrzej Kaczmarek /* Channel lock is released before requesting new skb and then 2433ede81a2aSAndrzej Kaczmarek * reacquired thus we need to recheck channel state. 2434ede81a2aSAndrzej Kaczmarek */ 2435ede81a2aSAndrzej Kaczmarek if (chan->state != BT_CONNECTED) { 2436ede81a2aSAndrzej Kaczmarek kfree_skb(skb); 2437ede81a2aSAndrzej Kaczmarek return -ENOTCONN; 2438ede81a2aSAndrzej Kaczmarek } 2439ede81a2aSAndrzej Kaczmarek 24409a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 24419a91a04aSGustavo F. Padovan return len; 24429a91a04aSGustavo F. Padovan } 24439a91a04aSGustavo F. Padovan 24449a91a04aSGustavo F. Padovan switch (chan->mode) { 244538319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 2446177f8f2bSJohan Hedberg /* Check outgoing MTU */ 2447177f8f2bSJohan Hedberg if (len > chan->omtu) 2448177f8f2bSJohan Hedberg return -EMSGSIZE; 2449177f8f2bSJohan Hedberg 2450fad5fc89SJohan Hedberg if (!chan->tx_credits) 2451fad5fc89SJohan Hedberg return -EAGAIN; 2452fad5fc89SJohan Hedberg 2453177f8f2bSJohan Hedberg __skb_queue_head_init(&seg_queue); 2454177f8f2bSJohan Hedberg 2455177f8f2bSJohan Hedberg err = l2cap_segment_le_sdu(chan, &seg_queue, msg, len); 2456177f8f2bSJohan Hedberg 2457177f8f2bSJohan Hedberg if (chan->state != BT_CONNECTED) { 2458177f8f2bSJohan Hedberg __skb_queue_purge(&seg_queue); 2459177f8f2bSJohan Hedberg err = -ENOTCONN; 2460177f8f2bSJohan Hedberg } 2461177f8f2bSJohan Hedberg 2462177f8f2bSJohan Hedberg if (err) 2463177f8f2bSJohan Hedberg return err; 2464177f8f2bSJohan Hedberg 2465177f8f2bSJohan Hedberg skb_queue_splice_tail_init(&seg_queue, &chan->tx_q); 2466177f8f2bSJohan Hedberg 2467177f8f2bSJohan Hedberg while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) { 2468177f8f2bSJohan Hedberg l2cap_do_send(chan, skb_dequeue(&chan->tx_q)); 2469177f8f2bSJohan Hedberg chan->tx_credits--; 2470177f8f2bSJohan Hedberg } 2471177f8f2bSJohan Hedberg 2472177f8f2bSJohan Hedberg if (!chan->tx_credits) 2473177f8f2bSJohan Hedberg chan->ops->suspend(chan); 2474177f8f2bSJohan Hedberg 2475177f8f2bSJohan Hedberg err = len; 2476177f8f2bSJohan Hedberg 2477177f8f2bSJohan Hedberg break; 2478177f8f2bSJohan Hedberg 2479fad5fc89SJohan Hedberg case L2CAP_MODE_BASIC: 24809a91a04aSGustavo F. Padovan /* Check outgoing MTU */ 24819a91a04aSGustavo F. Padovan if (len > chan->omtu) 24829a91a04aSGustavo F. Padovan return -EMSGSIZE; 24839a91a04aSGustavo F. Padovan 24849a91a04aSGustavo F. Padovan /* Create a basic PDU */ 24858d46321cSMarcel Holtmann skb = l2cap_create_basic_pdu(chan, msg, len); 24869a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 24879a91a04aSGustavo F. Padovan return PTR_ERR(skb); 24889a91a04aSGustavo F. Padovan 2489ede81a2aSAndrzej Kaczmarek /* Channel lock is released before requesting new skb and then 2490ede81a2aSAndrzej Kaczmarek * reacquired thus we need to recheck channel state. 2491ede81a2aSAndrzej Kaczmarek */ 2492ede81a2aSAndrzej Kaczmarek if (chan->state != BT_CONNECTED) { 2493ede81a2aSAndrzej Kaczmarek kfree_skb(skb); 2494ede81a2aSAndrzej Kaczmarek return -ENOTCONN; 2495ede81a2aSAndrzej Kaczmarek } 2496ede81a2aSAndrzej Kaczmarek 24979a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 24989a91a04aSGustavo F. Padovan err = len; 24999a91a04aSGustavo F. Padovan break; 25009a91a04aSGustavo F. Padovan 25019a91a04aSGustavo F. Padovan case L2CAP_MODE_ERTM: 25029a91a04aSGustavo F. Padovan case L2CAP_MODE_STREAMING: 250394122bbeSMat Martineau /* Check outgoing MTU */ 250494122bbeSMat Martineau if (len > chan->omtu) { 250594122bbeSMat Martineau err = -EMSGSIZE; 25069a91a04aSGustavo F. Padovan break; 25079a91a04aSGustavo F. Padovan } 25089a91a04aSGustavo F. Padovan 250994122bbeSMat Martineau __skb_queue_head_init(&seg_queue); 251094122bbeSMat Martineau 251194122bbeSMat Martineau /* Do segmentation before calling in to the state machine, 251294122bbeSMat Martineau * since it's possible to block while waiting for memory 251394122bbeSMat Martineau * allocation. 251494122bbeSMat Martineau */ 251594122bbeSMat Martineau err = l2cap_segment_sdu(chan, &seg_queue, msg, len); 251694122bbeSMat Martineau 251794122bbeSMat Martineau /* The channel could have been closed while segmenting, 251894122bbeSMat Martineau * check that it is still connected. 251994122bbeSMat Martineau */ 252094122bbeSMat Martineau if (chan->state != BT_CONNECTED) { 252194122bbeSMat Martineau __skb_queue_purge(&seg_queue); 252294122bbeSMat Martineau err = -ENOTCONN; 25239a91a04aSGustavo F. Padovan } 25249a91a04aSGustavo F. Padovan 252594122bbeSMat Martineau if (err) 252694122bbeSMat Martineau break; 252794122bbeSMat Martineau 25283733937dSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) 2529d660366dSGustavo Padovan l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST); 25303733937dSMat Martineau else 2531d660366dSGustavo Padovan l2cap_streaming_send(chan, &seg_queue); 253294122bbeSMat Martineau 25339a91a04aSGustavo F. Padovan err = len; 25349a91a04aSGustavo F. Padovan 253594122bbeSMat Martineau /* If the skbs were not queued for sending, they'll still be in 253694122bbeSMat Martineau * seg_queue and need to be purged. 253794122bbeSMat Martineau */ 253894122bbeSMat Martineau __skb_queue_purge(&seg_queue); 25399a91a04aSGustavo F. Padovan break; 25409a91a04aSGustavo F. Padovan 25419a91a04aSGustavo F. Padovan default: 25429a91a04aSGustavo F. Padovan BT_DBG("bad state %1.1x", chan->mode); 25439a91a04aSGustavo F. Padovan err = -EBADFD; 25449a91a04aSGustavo F. Padovan } 25459a91a04aSGustavo F. Padovan 25469a91a04aSGustavo F. Padovan return err; 25479a91a04aSGustavo F. Padovan } 25486b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_send); 25499a91a04aSGustavo F. Padovan 2550d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq) 2551d2a7ac5dSMat Martineau { 2552bed68bdeSMat Martineau struct l2cap_ctrl control; 2553bed68bdeSMat Martineau u16 seq; 2554bed68bdeSMat Martineau 2555b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2556bed68bdeSMat Martineau 2557bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2558bed68bdeSMat Martineau control.sframe = 1; 2559bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2560bed68bdeSMat Martineau 2561bed68bdeSMat Martineau for (seq = chan->expected_tx_seq; seq != txseq; 2562bed68bdeSMat Martineau seq = __next_seq(chan, seq)) { 2563bed68bdeSMat Martineau if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) { 2564bed68bdeSMat Martineau control.reqseq = seq; 2565bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2566bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2567bed68bdeSMat Martineau } 2568bed68bdeSMat Martineau } 2569bed68bdeSMat Martineau 2570bed68bdeSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 2571d2a7ac5dSMat Martineau } 2572d2a7ac5dSMat Martineau 2573d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan) 2574d2a7ac5dSMat Martineau { 2575bed68bdeSMat Martineau struct l2cap_ctrl control; 2576bed68bdeSMat Martineau 2577bed68bdeSMat Martineau BT_DBG("chan %p", chan); 2578bed68bdeSMat Martineau 2579bed68bdeSMat Martineau if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR) 2580bed68bdeSMat Martineau return; 2581bed68bdeSMat Martineau 2582bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2583bed68bdeSMat Martineau control.sframe = 1; 2584bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2585bed68bdeSMat Martineau control.reqseq = chan->srej_list.tail; 2586bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2587d2a7ac5dSMat Martineau } 2588d2a7ac5dSMat Martineau 2589d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq) 2590d2a7ac5dSMat Martineau { 2591bed68bdeSMat Martineau struct l2cap_ctrl control; 2592bed68bdeSMat Martineau u16 initial_head; 2593bed68bdeSMat Martineau u16 seq; 2594bed68bdeSMat Martineau 2595b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2596bed68bdeSMat Martineau 2597bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2598bed68bdeSMat Martineau control.sframe = 1; 2599bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2600bed68bdeSMat Martineau 2601bed68bdeSMat Martineau /* Capture initial list head to allow only one pass through the list. */ 2602bed68bdeSMat Martineau initial_head = chan->srej_list.head; 2603bed68bdeSMat Martineau 2604bed68bdeSMat Martineau do { 2605bed68bdeSMat Martineau seq = l2cap_seq_list_pop(&chan->srej_list); 2606bed68bdeSMat Martineau if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR) 2607bed68bdeSMat Martineau break; 2608bed68bdeSMat Martineau 2609bed68bdeSMat Martineau control.reqseq = seq; 2610bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2611bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2612bed68bdeSMat Martineau } while (chan->srej_list.head != initial_head); 2613d2a7ac5dSMat Martineau } 2614d2a7ac5dSMat Martineau 2615608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq) 2616608bcc6dSMat Martineau { 2617608bcc6dSMat Martineau struct sk_buff *acked_skb; 2618608bcc6dSMat Martineau u16 ackseq; 2619608bcc6dSMat Martineau 2620b4400672SAndrei Emeltchenko BT_DBG("chan %p, reqseq %u", chan, reqseq); 2621608bcc6dSMat Martineau 2622608bcc6dSMat Martineau if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq) 2623608bcc6dSMat Martineau return; 2624608bcc6dSMat Martineau 2625b4400672SAndrei Emeltchenko BT_DBG("expected_ack_seq %u, unacked_frames %u", 2626608bcc6dSMat Martineau chan->expected_ack_seq, chan->unacked_frames); 2627608bcc6dSMat Martineau 2628608bcc6dSMat Martineau for (ackseq = chan->expected_ack_seq; ackseq != reqseq; 2629608bcc6dSMat Martineau ackseq = __next_seq(chan, ackseq)) { 2630608bcc6dSMat Martineau 2631608bcc6dSMat Martineau acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq); 2632608bcc6dSMat Martineau if (acked_skb) { 2633608bcc6dSMat Martineau skb_unlink(acked_skb, &chan->tx_q); 2634608bcc6dSMat Martineau kfree_skb(acked_skb); 2635608bcc6dSMat Martineau chan->unacked_frames--; 2636608bcc6dSMat Martineau } 2637608bcc6dSMat Martineau } 2638608bcc6dSMat Martineau 2639608bcc6dSMat Martineau chan->expected_ack_seq = reqseq; 2640608bcc6dSMat Martineau 2641608bcc6dSMat Martineau if (chan->unacked_frames == 0) 2642608bcc6dSMat Martineau __clear_retrans_timer(chan); 2643608bcc6dSMat Martineau 2644b4400672SAndrei Emeltchenko BT_DBG("unacked_frames %u", chan->unacked_frames); 2645608bcc6dSMat Martineau } 2646608bcc6dSMat Martineau 2647608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan) 2648608bcc6dSMat Martineau { 2649608bcc6dSMat Martineau BT_DBG("chan %p", chan); 2650608bcc6dSMat Martineau 2651608bcc6dSMat Martineau chan->expected_tx_seq = chan->buffer_seq; 2652608bcc6dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 2653608bcc6dSMat Martineau skb_queue_purge(&chan->srej_q); 2654608bcc6dSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2655608bcc6dSMat Martineau } 2656608bcc6dSMat Martineau 2657d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan, 2658608bcc6dSMat Martineau struct l2cap_ctrl *control, 2659608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2660608bcc6dSMat Martineau { 2661608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2662608bcc6dSMat Martineau event); 2663608bcc6dSMat Martineau 2664608bcc6dSMat Martineau switch (event) { 2665608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2666608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2667608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2668608bcc6dSMat Martineau 2669608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2670608bcc6dSMat Martineau l2cap_ertm_send(chan); 2671608bcc6dSMat Martineau break; 2672608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2673608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2674608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2675608bcc6dSMat Martineau 2676608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2677608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2678608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2679608bcc6dSMat Martineau */ 2680608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2681608bcc6dSMat Martineau } 2682608bcc6dSMat Martineau 2683608bcc6dSMat Martineau l2cap_send_ack(chan); 2684608bcc6dSMat Martineau 2685608bcc6dSMat Martineau break; 2686608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2687608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2688608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2689608bcc6dSMat Martineau 2690608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2691608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2692608bcc6dSMat Martineau 2693608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2694608bcc6dSMat Martineau local_control.sframe = 1; 2695608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2696608bcc6dSMat Martineau local_control.poll = 1; 2697608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2698a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2699608bcc6dSMat Martineau 2700608bcc6dSMat Martineau chan->retry_count = 1; 2701608bcc6dSMat Martineau __set_monitor_timer(chan); 2702608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2703608bcc6dSMat Martineau } 2704608bcc6dSMat Martineau break; 2705608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2706608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2707608bcc6dSMat Martineau break; 2708608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2709608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2710608bcc6dSMat Martineau chan->retry_count = 1; 2711608bcc6dSMat Martineau __set_monitor_timer(chan); 2712608bcc6dSMat Martineau __clear_ack_timer(chan); 2713608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2714608bcc6dSMat Martineau break; 2715608bcc6dSMat Martineau case L2CAP_EV_RETRANS_TO: 2716608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2717608bcc6dSMat Martineau chan->retry_count = 1; 2718608bcc6dSMat Martineau __set_monitor_timer(chan); 2719608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2720608bcc6dSMat Martineau break; 2721608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2722608bcc6dSMat Martineau /* Nothing to process */ 2723608bcc6dSMat Martineau break; 2724608bcc6dSMat Martineau default: 2725608bcc6dSMat Martineau break; 2726608bcc6dSMat Martineau } 2727608bcc6dSMat Martineau } 2728608bcc6dSMat Martineau 2729d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan, 2730608bcc6dSMat Martineau struct l2cap_ctrl *control, 2731608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2732608bcc6dSMat Martineau { 2733608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2734608bcc6dSMat Martineau event); 2735608bcc6dSMat Martineau 2736608bcc6dSMat Martineau switch (event) { 2737608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2738608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2739608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2740608bcc6dSMat Martineau /* Queue data, but don't send. */ 2741608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2742608bcc6dSMat Martineau break; 2743608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2744608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2745608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2746608bcc6dSMat Martineau 2747608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2748608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2749608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2750608bcc6dSMat Martineau */ 2751608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2752608bcc6dSMat Martineau } 2753608bcc6dSMat Martineau 2754608bcc6dSMat Martineau l2cap_send_ack(chan); 2755608bcc6dSMat Martineau 2756608bcc6dSMat Martineau break; 2757608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2758608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2759608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2760608bcc6dSMat Martineau 2761608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2762608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2763608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2764608bcc6dSMat Martineau local_control.sframe = 1; 2765608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2766608bcc6dSMat Martineau local_control.poll = 1; 2767608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2768a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2769608bcc6dSMat Martineau 2770608bcc6dSMat Martineau chan->retry_count = 1; 2771608bcc6dSMat Martineau __set_monitor_timer(chan); 2772608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2773608bcc6dSMat Martineau } 2774608bcc6dSMat Martineau break; 2775608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2776608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2777608bcc6dSMat Martineau 2778608bcc6dSMat Martineau /* Fall through */ 2779608bcc6dSMat Martineau 2780608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2781608bcc6dSMat Martineau if (control && control->final) { 2782608bcc6dSMat Martineau __clear_monitor_timer(chan); 2783608bcc6dSMat Martineau if (chan->unacked_frames > 0) 2784608bcc6dSMat Martineau __set_retrans_timer(chan); 2785608bcc6dSMat Martineau chan->retry_count = 0; 2786608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 2787608bcc6dSMat Martineau BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state); 2788608bcc6dSMat Martineau } 2789608bcc6dSMat Martineau break; 2790608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2791608bcc6dSMat Martineau /* Ignore */ 2792608bcc6dSMat Martineau break; 2793608bcc6dSMat Martineau case L2CAP_EV_MONITOR_TO: 2794608bcc6dSMat Martineau if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) { 2795608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2796608bcc6dSMat Martineau __set_monitor_timer(chan); 2797608bcc6dSMat Martineau chan->retry_count++; 2798608bcc6dSMat Martineau } else { 27995e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNABORTED); 2800608bcc6dSMat Martineau } 2801608bcc6dSMat Martineau break; 2802608bcc6dSMat Martineau default: 2803608bcc6dSMat Martineau break; 2804608bcc6dSMat Martineau } 2805608bcc6dSMat Martineau } 2806608bcc6dSMat Martineau 2807d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 2808608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2809608bcc6dSMat Martineau { 2810608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d, state %d", 2811608bcc6dSMat Martineau chan, control, skbs, event, chan->tx_state); 2812608bcc6dSMat Martineau 2813608bcc6dSMat Martineau switch (chan->tx_state) { 2814608bcc6dSMat Martineau case L2CAP_TX_STATE_XMIT: 2815d660366dSGustavo Padovan l2cap_tx_state_xmit(chan, control, skbs, event); 2816608bcc6dSMat Martineau break; 2817608bcc6dSMat Martineau case L2CAP_TX_STATE_WAIT_F: 2818d660366dSGustavo Padovan l2cap_tx_state_wait_f(chan, control, skbs, event); 2819608bcc6dSMat Martineau break; 2820608bcc6dSMat Martineau default: 2821608bcc6dSMat Martineau /* Ignore event */ 2822608bcc6dSMat Martineau break; 2823608bcc6dSMat Martineau } 2824608bcc6dSMat Martineau } 2825608bcc6dSMat Martineau 28264b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan, 28274b51dae9SMat Martineau struct l2cap_ctrl *control) 28284b51dae9SMat Martineau { 28294b51dae9SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2830401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT); 28314b51dae9SMat Martineau } 28324b51dae9SMat Martineau 2833f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan, 2834f80842a8SMat Martineau struct l2cap_ctrl *control) 2835f80842a8SMat Martineau { 2836f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2837401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT); 2838f80842a8SMat Martineau } 2839f80842a8SMat Martineau 28400a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */ 28410a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 28420a708f8fSGustavo F. Padovan { 28430a708f8fSGustavo F. Padovan struct sk_buff *nskb; 284448454079SGustavo F. Padovan struct l2cap_chan *chan; 28450a708f8fSGustavo F. Padovan 28460a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 28470a708f8fSGustavo F. Padovan 28483df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 28493d57dc68SGustavo F. Padovan 28503df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 2851715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW) 28520a708f8fSGustavo F. Padovan continue; 28530a708f8fSGustavo F. Padovan 28547f5396a7SGustavo Padovan /* Don't send frame to the channel it came from */ 2855a4368ff3SJohan Hedberg if (bt_cb(skb)->l2cap.chan == chan) 28560a708f8fSGustavo F. Padovan continue; 28577f5396a7SGustavo Padovan 28588bcde1f2SGustavo Padovan nskb = skb_clone(skb, GFP_KERNEL); 28590a708f8fSGustavo F. Padovan if (!nskb) 28600a708f8fSGustavo F. Padovan continue; 286180b98027SGustavo Padovan if (chan->ops->recv(chan, nskb)) 28620a708f8fSGustavo F. Padovan kfree_skb(nskb); 28630a708f8fSGustavo F. Padovan } 28643d57dc68SGustavo F. Padovan 28653df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 28660a708f8fSGustavo F. Padovan } 28670a708f8fSGustavo F. Padovan 28680a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */ 2869b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, 2870b4400672SAndrei Emeltchenko u8 ident, u16 dlen, void *data) 28710a708f8fSGustavo F. Padovan { 28720a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag; 28730a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd; 28740a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 28750a708f8fSGustavo F. Padovan int len, count; 28760a708f8fSGustavo F. Padovan 2877b4400672SAndrei Emeltchenko BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u", 28780a708f8fSGustavo F. Padovan conn, code, ident, dlen); 28790a708f8fSGustavo F. Padovan 2880300b962eSAnderson Lizardo if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE) 2881300b962eSAnderson Lizardo return NULL; 2882300b962eSAnderson Lizardo 28830a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; 28840a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 28850a708f8fSGustavo F. Padovan 28868bcde1f2SGustavo Padovan skb = bt_skb_alloc(count, GFP_KERNEL); 28870a708f8fSGustavo F. Padovan if (!skb) 28880a708f8fSGustavo F. Padovan return NULL; 28890a708f8fSGustavo F. Padovan 28900a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 28910a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); 28923300d9a9SClaudio Takahasi 28933300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 2894dcf4adbfSJoe Perches lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING); 28953300d9a9SClaudio Takahasi else 2896dcf4adbfSJoe Perches lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING); 28970a708f8fSGustavo F. Padovan 28980a708f8fSGustavo F. Padovan cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); 28990a708f8fSGustavo F. Padovan cmd->code = code; 29000a708f8fSGustavo F. Padovan cmd->ident = ident; 29010a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen); 29020a708f8fSGustavo F. Padovan 29030a708f8fSGustavo F. Padovan if (dlen) { 29040a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE; 29050a708f8fSGustavo F. Padovan memcpy(skb_put(skb, count), data, count); 29060a708f8fSGustavo F. Padovan data += count; 29070a708f8fSGustavo F. Padovan } 29080a708f8fSGustavo F. Padovan 29090a708f8fSGustavo F. Padovan len -= skb->len; 29100a708f8fSGustavo F. Padovan 29110a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 29120a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 29130a708f8fSGustavo F. Padovan while (len) { 29140a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 29150a708f8fSGustavo F. Padovan 29168bcde1f2SGustavo Padovan *frag = bt_skb_alloc(count, GFP_KERNEL); 29170a708f8fSGustavo F. Padovan if (!*frag) 29180a708f8fSGustavo F. Padovan goto fail; 29190a708f8fSGustavo F. Padovan 29200a708f8fSGustavo F. Padovan memcpy(skb_put(*frag, count), data, count); 29210a708f8fSGustavo F. Padovan 29220a708f8fSGustavo F. Padovan len -= count; 29230a708f8fSGustavo F. Padovan data += count; 29240a708f8fSGustavo F. Padovan 29250a708f8fSGustavo F. Padovan frag = &(*frag)->next; 29260a708f8fSGustavo F. Padovan } 29270a708f8fSGustavo F. Padovan 29280a708f8fSGustavo F. Padovan return skb; 29290a708f8fSGustavo F. Padovan 29300a708f8fSGustavo F. Padovan fail: 29310a708f8fSGustavo F. Padovan kfree_skb(skb); 29320a708f8fSGustavo F. Padovan return NULL; 29330a708f8fSGustavo F. Padovan } 29340a708f8fSGustavo F. Padovan 29352d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, 29362d792818SGustavo Padovan unsigned long *val) 29370a708f8fSGustavo F. Padovan { 29380a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 29390a708f8fSGustavo F. Padovan int len; 29400a708f8fSGustavo F. Padovan 29410a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len; 29420a708f8fSGustavo F. Padovan *ptr += len; 29430a708f8fSGustavo F. Padovan 29440a708f8fSGustavo F. Padovan *type = opt->type; 29450a708f8fSGustavo F. Padovan *olen = opt->len; 29460a708f8fSGustavo F. Padovan 29470a708f8fSGustavo F. Padovan switch (opt->len) { 29480a708f8fSGustavo F. Padovan case 1: 29490a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val); 29500a708f8fSGustavo F. Padovan break; 29510a708f8fSGustavo F. Padovan 29520a708f8fSGustavo F. Padovan case 2: 29530a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val); 29540a708f8fSGustavo F. Padovan break; 29550a708f8fSGustavo F. Padovan 29560a708f8fSGustavo F. Padovan case 4: 29570a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val); 29580a708f8fSGustavo F. Padovan break; 29590a708f8fSGustavo F. Padovan 29600a708f8fSGustavo F. Padovan default: 29610a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val; 29620a708f8fSGustavo F. Padovan break; 29630a708f8fSGustavo F. Padovan } 29640a708f8fSGustavo F. Padovan 2965b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val); 29660a708f8fSGustavo F. Padovan return len; 29670a708f8fSGustavo F. Padovan } 29680a708f8fSGustavo F. Padovan 29690a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) 29700a708f8fSGustavo F. Padovan { 29710a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 29720a708f8fSGustavo F. Padovan 2973b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val); 29740a708f8fSGustavo F. Padovan 29750a708f8fSGustavo F. Padovan opt->type = type; 29760a708f8fSGustavo F. Padovan opt->len = len; 29770a708f8fSGustavo F. Padovan 29780a708f8fSGustavo F. Padovan switch (len) { 29790a708f8fSGustavo F. Padovan case 1: 29800a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val; 29810a708f8fSGustavo F. Padovan break; 29820a708f8fSGustavo F. Padovan 29830a708f8fSGustavo F. Padovan case 2: 29840a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val); 29850a708f8fSGustavo F. Padovan break; 29860a708f8fSGustavo F. Padovan 29870a708f8fSGustavo F. Padovan case 4: 29880a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val); 29890a708f8fSGustavo F. Padovan break; 29900a708f8fSGustavo F. Padovan 29910a708f8fSGustavo F. Padovan default: 29920a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len); 29930a708f8fSGustavo F. Padovan break; 29940a708f8fSGustavo F. Padovan } 29950a708f8fSGustavo F. Padovan 29960a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len; 29970a708f8fSGustavo F. Padovan } 29980a708f8fSGustavo F. Padovan 2999f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) 3000f89cef09SAndrei Emeltchenko { 3001f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs; 3002f89cef09SAndrei Emeltchenko 3003f89cef09SAndrei Emeltchenko switch (chan->mode) { 3004f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM: 3005f89cef09SAndrei Emeltchenko efs.id = chan->local_id; 3006f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype; 3007f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 3008f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 3009dcf4adbfSJoe Perches efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); 3010dcf4adbfSJoe Perches efs.flush_to = cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO); 3011f89cef09SAndrei Emeltchenko break; 3012f89cef09SAndrei Emeltchenko 3013f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING: 3014f89cef09SAndrei Emeltchenko efs.id = 1; 3015f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT; 3016f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 3017f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 3018f89cef09SAndrei Emeltchenko efs.acc_lat = 0; 3019f89cef09SAndrei Emeltchenko efs.flush_to = 0; 3020f89cef09SAndrei Emeltchenko break; 3021f89cef09SAndrei Emeltchenko 3022f89cef09SAndrei Emeltchenko default: 3023f89cef09SAndrei Emeltchenko return; 3024f89cef09SAndrei Emeltchenko } 3025f89cef09SAndrei Emeltchenko 3026f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), 3027f89cef09SAndrei Emeltchenko (unsigned long) &efs); 3028f89cef09SAndrei Emeltchenko } 3029f89cef09SAndrei Emeltchenko 3030721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work) 30310a708f8fSGustavo F. Padovan { 3032721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 3033721c4181SGustavo F. Padovan ack_timer.work); 30340362520bSMat Martineau u16 frames_to_ack; 30350a708f8fSGustavo F. Padovan 30362fb9b3d4SGustavo F. Padovan BT_DBG("chan %p", chan); 30372fb9b3d4SGustavo F. Padovan 30386be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 30396be36555SAndrei Emeltchenko 30400362520bSMat Martineau frames_to_ack = __seq_offset(chan, chan->buffer_seq, 30410362520bSMat Martineau chan->last_acked_seq); 30420362520bSMat Martineau 30430362520bSMat Martineau if (frames_to_ack) 30440362520bSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 30456be36555SAndrei Emeltchenko 30466be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 304709bfb2eeSSzymon Janc l2cap_chan_put(chan); 30480a708f8fSGustavo F. Padovan } 30490a708f8fSGustavo F. Padovan 3050466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan) 30510a708f8fSGustavo F. Padovan { 30523c588192SMat Martineau int err; 30533c588192SMat Martineau 3054105bdf9eSMat Martineau chan->next_tx_seq = 0; 3055105bdf9eSMat Martineau chan->expected_tx_seq = 0; 305642e5c802SGustavo F. Padovan chan->expected_ack_seq = 0; 30576a026610SGustavo F. Padovan chan->unacked_frames = 0; 305842e5c802SGustavo F. Padovan chan->buffer_seq = 0; 30596a026610SGustavo F. Padovan chan->frames_sent = 0; 3060105bdf9eSMat Martineau chan->last_acked_seq = 0; 3061105bdf9eSMat Martineau chan->sdu = NULL; 3062105bdf9eSMat Martineau chan->sdu_last_frag = NULL; 3063105bdf9eSMat Martineau chan->sdu_len = 0; 3064105bdf9eSMat Martineau 3065d34c34fbSMat Martineau skb_queue_head_init(&chan->tx_q); 3066d34c34fbSMat Martineau 30676ed971caSMarcel Holtmann chan->local_amp_id = AMP_ID_BREDR; 30686ed971caSMarcel Holtmann chan->move_id = AMP_ID_BREDR; 306908333283SMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 307008333283SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 307108333283SMat Martineau 3072105bdf9eSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 3073105bdf9eSMat Martineau return 0; 3074105bdf9eSMat Martineau 3075105bdf9eSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 3076105bdf9eSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 30770a708f8fSGustavo F. Padovan 3078721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout); 3079721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout); 3080721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout); 30810a708f8fSGustavo F. Padovan 3082f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q); 30830a708f8fSGustavo F. Padovan 30843c588192SMat Martineau err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win); 30853c588192SMat Martineau if (err < 0) 30863c588192SMat Martineau return err; 30873c588192SMat Martineau 30889dc9affcSMat Martineau err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win); 30899dc9affcSMat Martineau if (err < 0) 30909dc9affcSMat Martineau l2cap_seq_list_free(&chan->srej_list); 30919dc9affcSMat Martineau 30929dc9affcSMat Martineau return err; 30930a708f8fSGustavo F. Padovan } 30940a708f8fSGustavo F. Padovan 30950a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) 30960a708f8fSGustavo F. Padovan { 30970a708f8fSGustavo F. Padovan switch (mode) { 30980a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 30990a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 31000a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask)) 31010a708f8fSGustavo F. Padovan return mode; 31020a708f8fSGustavo F. Padovan /* fall through */ 31030a708f8fSGustavo F. Padovan default: 31040a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC; 31050a708f8fSGustavo F. Padovan } 31060a708f8fSGustavo F. Padovan } 31070a708f8fSGustavo F. Padovan 3108848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn) 31096327eb98SAndrei Emeltchenko { 31100bd49fc7SJohan Hedberg return ((conn->local_fixed_chan & L2CAP_FC_A2MP) && 31110bd49fc7SJohan Hedberg (conn->feat_mask & L2CAP_FEAT_EXT_WINDOW)); 31126327eb98SAndrei Emeltchenko } 31136327eb98SAndrei Emeltchenko 3114848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn) 3115f89cef09SAndrei Emeltchenko { 31160bd49fc7SJohan Hedberg return ((conn->local_fixed_chan & L2CAP_FC_A2MP) && 31170bd49fc7SJohan Hedberg (conn->feat_mask & L2CAP_FEAT_EXT_FLOW)); 3118f89cef09SAndrei Emeltchenko } 3119f89cef09SAndrei Emeltchenko 312036c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan, 312136c86c85SMat Martineau struct l2cap_conf_rfc *rfc) 312236c86c85SMat Martineau { 31236ed971caSMarcel Holtmann if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) { 312436c86c85SMat Martineau u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to; 312536c86c85SMat Martineau 312636c86c85SMat Martineau /* Class 1 devices have must have ERTM timeouts 312736c86c85SMat Martineau * exceeding the Link Supervision Timeout. The 312836c86c85SMat Martineau * default Link Supervision Timeout for AMP 312936c86c85SMat Martineau * controllers is 10 seconds. 313036c86c85SMat Martineau * 313136c86c85SMat Martineau * Class 1 devices use 0xffffffff for their 313236c86c85SMat Martineau * best-effort flush timeout, so the clamping logic 313336c86c85SMat Martineau * will result in a timeout that meets the above 313436c86c85SMat Martineau * requirement. ERTM timeouts are 16-bit values, so 313536c86c85SMat Martineau * the maximum timeout is 65.535 seconds. 313636c86c85SMat Martineau */ 313736c86c85SMat Martineau 313836c86c85SMat Martineau /* Convert timeout to milliseconds and round */ 313936c86c85SMat Martineau ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000); 314036c86c85SMat Martineau 314136c86c85SMat Martineau /* This is the recommended formula for class 2 devices 314236c86c85SMat Martineau * that start ERTM timers when packets are sent to the 314336c86c85SMat Martineau * controller. 314436c86c85SMat Martineau */ 314536c86c85SMat Martineau ertm_to = 3 * ertm_to + 500; 314636c86c85SMat Martineau 314736c86c85SMat Martineau if (ertm_to > 0xffff) 314836c86c85SMat Martineau ertm_to = 0xffff; 314936c86c85SMat Martineau 315036c86c85SMat Martineau rfc->retrans_timeout = cpu_to_le16((u16) ertm_to); 315136c86c85SMat Martineau rfc->monitor_timeout = rfc->retrans_timeout; 315236c86c85SMat Martineau } else { 3153dcf4adbfSJoe Perches rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 3154dcf4adbfSJoe Perches rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 315536c86c85SMat Martineau } 315636c86c85SMat Martineau } 315736c86c85SMat Martineau 31586327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan) 31596327eb98SAndrei Emeltchenko { 31606327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && 3161848566b3SMarcel Holtmann __l2cap_ews_supported(chan->conn)) { 31626327eb98SAndrei Emeltchenko /* use extended control field */ 31636327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 3164836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 3165836be934SAndrei Emeltchenko } else { 31666327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win, 31676327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 3168836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 3169836be934SAndrei Emeltchenko } 3170c20f8e35SMat Martineau chan->ack_win = chan->tx_win; 31716327eb98SAndrei Emeltchenko } 31726327eb98SAndrei Emeltchenko 3173710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) 31740a708f8fSGustavo F. Padovan { 31750a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 31760c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode }; 31770a708f8fSGustavo F. Padovan void *ptr = req->data; 3178c8f79162SAndrei Emeltchenko u16 size; 31790a708f8fSGustavo F. Padovan 318049208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 31810a708f8fSGustavo F. Padovan 318273ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp) 31830a708f8fSGustavo F. Padovan goto done; 31840a708f8fSGustavo F. Padovan 31850c1bc5c6SGustavo F. Padovan switch (chan->mode) { 31860a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 31870a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3188c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) 31890a708f8fSGustavo F. Padovan break; 31900a708f8fSGustavo F. Padovan 3191848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn)) 3192f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 3193f89cef09SAndrei Emeltchenko 31940a708f8fSGustavo F. Padovan /* fall through */ 31950a708f8fSGustavo F. Padovan default: 31968c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); 31970a708f8fSGustavo F. Padovan break; 31980a708f8fSGustavo F. Padovan } 31990a708f8fSGustavo F. Padovan 32000a708f8fSGustavo F. Padovan done: 32010c1bc5c6SGustavo F. Padovan if (chan->imtu != L2CAP_DEFAULT_MTU) 32020c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 32030a708f8fSGustavo F. Padovan 32040c1bc5c6SGustavo F. Padovan switch (chan->mode) { 32050a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 32066fea7ad1SMarcel Holtmann if (disable_ertm) 32076fea7ad1SMarcel Holtmann break; 32086fea7ad1SMarcel Holtmann 32098c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && 32108c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) 32110a708f8fSGustavo F. Padovan break; 32120a708f8fSGustavo F. Padovan 32130a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC; 32140a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 32150a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 32160a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 32170a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 32180a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0; 32190a708f8fSGustavo F. Padovan 32200a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 32210a708f8fSGustavo F. Padovan (unsigned long) &rfc); 32220a708f8fSGustavo F. Padovan break; 32230a708f8fSGustavo F. Padovan 32240a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 32250a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM; 322647d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx; 322736c86c85SMat Martineau 322836c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc); 3229c8f79162SAndrei Emeltchenko 3230c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 32312d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - 3232c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3233c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 32340a708f8fSGustavo F. Padovan 32356327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan); 32366327eb98SAndrei Emeltchenko 32376327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win, 32386327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 32390a708f8fSGustavo F. Padovan 32400a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 32410a708f8fSGustavo F. Padovan (unsigned long) &rfc); 32420a708f8fSGustavo F. Padovan 3243f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 3244f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 3245f89cef09SAndrei Emeltchenko 32466327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 32476327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 32486327eb98SAndrei Emeltchenko chan->tx_win); 324960918918SAndrei Emeltchenko 325060918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS) 325160918918SAndrei Emeltchenko if (chan->fcs == L2CAP_FCS_NONE || 3252f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { 325360918918SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 325460918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, 325560918918SAndrei Emeltchenko chan->fcs); 325660918918SAndrei Emeltchenko } 32570a708f8fSGustavo F. Padovan break; 32580a708f8fSGustavo F. Padovan 32590a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3260273759e2SMat Martineau l2cap_txwin_setup(chan); 32610a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING; 32620a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 32630a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 32640a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 32650a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 3266c8f79162SAndrei Emeltchenko 3267c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 32682d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - 3269c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3270c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 32710a708f8fSGustavo F. Padovan 32720a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 32730a708f8fSGustavo F. Padovan (unsigned long) &rfc); 32740a708f8fSGustavo F. Padovan 3275f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 3276f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 3277f89cef09SAndrei Emeltchenko 327860918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS) 327947d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 3280f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { 328147d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 328260918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, 328360918918SAndrei Emeltchenko chan->fcs); 32840a708f8fSGustavo F. Padovan } 32850a708f8fSGustavo F. Padovan break; 32860a708f8fSGustavo F. Padovan } 32870a708f8fSGustavo F. Padovan 3288fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 3289dcf4adbfSJoe Perches req->flags = cpu_to_le16(0); 32900a708f8fSGustavo F. Padovan 32910a708f8fSGustavo F. Padovan return ptr - data; 32920a708f8fSGustavo F. Padovan } 32930a708f8fSGustavo F. Padovan 329473ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) 32950a708f8fSGustavo F. Padovan { 32960a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 32970a708f8fSGustavo F. Padovan void *ptr = rsp->data; 329873ffa904SGustavo F. Padovan void *req = chan->conf_req; 329973ffa904SGustavo F. Padovan int len = chan->conf_len; 33000a708f8fSGustavo F. Padovan int type, hint, olen; 33010a708f8fSGustavo F. Padovan unsigned long val; 33020a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 330342dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs; 330442dceae2SAndrei Emeltchenko u8 remote_efs = 0; 33050a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU; 33060a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS; 3307c8f79162SAndrei Emeltchenko u16 size; 33080a708f8fSGustavo F. Padovan 330973ffa904SGustavo F. Padovan BT_DBG("chan %p", chan); 33100a708f8fSGustavo F. Padovan 33110a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 33120a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val); 33130a708f8fSGustavo F. Padovan 33140a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT; 33150a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK; 33160a708f8fSGustavo F. Padovan 33170a708f8fSGustavo F. Padovan switch (type) { 33180a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 33190a708f8fSGustavo F. Padovan mtu = val; 33200a708f8fSGustavo F. Padovan break; 33210a708f8fSGustavo F. Padovan 33220a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 33230c1bc5c6SGustavo F. Padovan chan->flush_to = val; 33240a708f8fSGustavo F. Padovan break; 33250a708f8fSGustavo F. Padovan 33260a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS: 33270a708f8fSGustavo F. Padovan break; 33280a708f8fSGustavo F. Padovan 33290a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 33300a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 33310a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen); 33320a708f8fSGustavo F. Padovan break; 33330a708f8fSGustavo F. Padovan 33340a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS: 33350a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE) 3336f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, &chan->conf_state); 333742dceae2SAndrei Emeltchenko break; 33380a708f8fSGustavo F. Padovan 333942dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS: 334042dceae2SAndrei Emeltchenko remote_efs = 1; 334142dceae2SAndrei Emeltchenko if (olen == sizeof(efs)) 334242dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen); 33430a708f8fSGustavo F. Padovan break; 33440a708f8fSGustavo F. Padovan 33456327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 33460bd49fc7SJohan Hedberg if (!(chan->conn->local_fixed_chan & L2CAP_FC_A2MP)) 33476327eb98SAndrei Emeltchenko return -ECONNREFUSED; 33486327eb98SAndrei Emeltchenko 33496327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 33506327eb98SAndrei Emeltchenko set_bit(CONF_EWS_RECV, &chan->conf_state); 3351836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 33526327eb98SAndrei Emeltchenko chan->remote_tx_win = val; 33530a708f8fSGustavo F. Padovan break; 33540a708f8fSGustavo F. Padovan 33550a708f8fSGustavo F. Padovan default: 33560a708f8fSGustavo F. Padovan if (hint) 33570a708f8fSGustavo F. Padovan break; 33580a708f8fSGustavo F. Padovan 33590a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN; 33600a708f8fSGustavo F. Padovan *((u8 *) ptr++) = type; 33610a708f8fSGustavo F. Padovan break; 33620a708f8fSGustavo F. Padovan } 33630a708f8fSGustavo F. Padovan } 33640a708f8fSGustavo F. Padovan 336573ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1) 33660a708f8fSGustavo F. Padovan goto done; 33670a708f8fSGustavo F. Padovan 33680c1bc5c6SGustavo F. Padovan switch (chan->mode) { 33690a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 33700a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3371c1360a1cSGustavo F. Padovan if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { 33720c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, 33738c1d787bSGustavo F. Padovan chan->conn->feat_mask); 33740a708f8fSGustavo F. Padovan break; 33750a708f8fSGustavo F. Padovan } 33760a708f8fSGustavo F. Padovan 337742dceae2SAndrei Emeltchenko if (remote_efs) { 3378848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn)) 337942dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 338042dceae2SAndrei Emeltchenko else 338142dceae2SAndrei Emeltchenko return -ECONNREFUSED; 338242dceae2SAndrei Emeltchenko } 338342dceae2SAndrei Emeltchenko 33840c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) 33850a708f8fSGustavo F. Padovan return -ECONNREFUSED; 33860a708f8fSGustavo F. Padovan 33870a708f8fSGustavo F. Padovan break; 33880a708f8fSGustavo F. Padovan } 33890a708f8fSGustavo F. Padovan 33900a708f8fSGustavo F. Padovan done: 33910c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) { 33920a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 33930c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 33940a708f8fSGustavo F. Padovan 339573ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1) 33960a708f8fSGustavo F. Padovan return -ECONNREFUSED; 33970a708f8fSGustavo F. Padovan 33982d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 33992d792818SGustavo Padovan (unsigned long) &rfc); 34000a708f8fSGustavo F. Padovan } 34010a708f8fSGustavo F. Padovan 34020a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) { 34030a708f8fSGustavo F. Padovan /* Configure output options and let the other side know 34040a708f8fSGustavo F. Padovan * which ones we don't like. */ 34050a708f8fSGustavo F. Padovan 34060a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU) 34070a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 34080a708f8fSGustavo F. Padovan else { 34090c1bc5c6SGustavo F. Padovan chan->omtu = mtu; 3410c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state); 34110a708f8fSGustavo F. Padovan } 34120c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); 34130a708f8fSGustavo F. Padovan 341442dceae2SAndrei Emeltchenko if (remote_efs) { 341542dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 341642dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 341742dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) { 341842dceae2SAndrei Emeltchenko 341942dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT; 342042dceae2SAndrei Emeltchenko 342142dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1) 342242dceae2SAndrei Emeltchenko return -ECONNREFUSED; 342342dceae2SAndrei Emeltchenko 342442dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 342542dceae2SAndrei Emeltchenko sizeof(efs), 342642dceae2SAndrei Emeltchenko (unsigned long) &efs); 34270e8b207eSAndrei Emeltchenko } else { 34283e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */ 34290e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING; 34300e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 343142dceae2SAndrei Emeltchenko } 343242dceae2SAndrei Emeltchenko } 343342dceae2SAndrei Emeltchenko 34340a708f8fSGustavo F. Padovan switch (rfc.mode) { 34350a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 343647d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3437c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 34380a708f8fSGustavo F. Padovan break; 34390a708f8fSGustavo F. Padovan 34400a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 34416327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state)) 34422c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size; 34436327eb98SAndrei Emeltchenko else 34446327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; 34456327eb98SAndrei Emeltchenko 34462c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit; 34470a708f8fSGustavo F. Padovan 3448c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 34492d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE - 34502d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); 3451c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3452c8f79162SAndrei Emeltchenko chan->remote_mps = size; 34530a708f8fSGustavo F. Padovan 345436c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc); 34550a708f8fSGustavo F. Padovan 3456c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 34570a708f8fSGustavo F. Padovan 34580a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 34590a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 34600a708f8fSGustavo F. Padovan 346142dceae2SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 346242dceae2SAndrei Emeltchenko chan->remote_id = efs.id; 346342dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype; 346442dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu); 346542dceae2SAndrei Emeltchenko chan->remote_flush_to = 346642dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to); 346742dceae2SAndrei Emeltchenko chan->remote_acc_lat = 346842dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat); 346942dceae2SAndrei Emeltchenko chan->remote_sdu_itime = 347042dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 347142dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 34722d792818SGustavo Padovan sizeof(efs), 34732d792818SGustavo Padovan (unsigned long) &efs); 347442dceae2SAndrei Emeltchenko } 34750a708f8fSGustavo F. Padovan break; 34760a708f8fSGustavo F. Padovan 34770a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3478c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 34792d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE - 34802d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); 3481c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3482c8f79162SAndrei Emeltchenko chan->remote_mps = size; 34830a708f8fSGustavo F. Padovan 3484c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 34850a708f8fSGustavo F. Padovan 34862d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 34872d792818SGustavo Padovan (unsigned long) &rfc); 34880a708f8fSGustavo F. Padovan 34890a708f8fSGustavo F. Padovan break; 34900a708f8fSGustavo F. Padovan 34910a708f8fSGustavo F. Padovan default: 34920a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 34930a708f8fSGustavo F. Padovan 34940a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc)); 34950c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 34960a708f8fSGustavo F. Padovan } 34970a708f8fSGustavo F. Padovan 34980a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) 3499c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 35000a708f8fSGustavo F. Padovan } 3501fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 35020a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 3503dcf4adbfSJoe Perches rsp->flags = cpu_to_le16(0); 35040a708f8fSGustavo F. Padovan 35050a708f8fSGustavo F. Padovan return ptr - data; 35060a708f8fSGustavo F. Padovan } 35070a708f8fSGustavo F. Padovan 35082d792818SGustavo Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, 35092d792818SGustavo Padovan void *data, u16 *result) 35100a708f8fSGustavo F. Padovan { 35110a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 35120a708f8fSGustavo F. Padovan void *ptr = req->data; 35130a708f8fSGustavo F. Padovan int type, olen; 35140a708f8fSGustavo F. Padovan unsigned long val; 351536e999a8SMat Martineau struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 351666af7aafSAndrei Emeltchenko struct l2cap_conf_efs efs; 35170a708f8fSGustavo F. Padovan 3518fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); 35190a708f8fSGustavo F. Padovan 35200a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 35210a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 35220a708f8fSGustavo F. Padovan 35230a708f8fSGustavo F. Padovan switch (type) { 35240a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 35250a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) { 35260a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT; 35270c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU; 35280a708f8fSGustavo F. Padovan } else 35290c1bc5c6SGustavo F. Padovan chan->imtu = val; 35300c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 35310a708f8fSGustavo F. Padovan break; 35320a708f8fSGustavo F. Padovan 35330a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 35340c1bc5c6SGustavo F. Padovan chan->flush_to = val; 35350a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 35360c1bc5c6SGustavo F. Padovan 2, chan->flush_to); 35370a708f8fSGustavo F. Padovan break; 35380a708f8fSGustavo F. Padovan 35390a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 35400a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 35410a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 35420a708f8fSGustavo F. Padovan 3543c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && 35440c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode) 35450a708f8fSGustavo F. Padovan return -ECONNREFUSED; 35460a708f8fSGustavo F. Padovan 354747d1ec61SGustavo F. Padovan chan->fcs = 0; 35480a708f8fSGustavo F. Padovan 35490a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 35500a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 35510a708f8fSGustavo F. Padovan break; 35526327eb98SAndrei Emeltchenko 35536327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 3554c20f8e35SMat Martineau chan->ack_win = min_t(u16, val, chan->ack_win); 35553e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 35563e6b3b95SGustavo F. Padovan chan->tx_win); 35576327eb98SAndrei Emeltchenko break; 355866af7aafSAndrei Emeltchenko 355966af7aafSAndrei Emeltchenko case L2CAP_CONF_EFS: 356066af7aafSAndrei Emeltchenko if (olen == sizeof(efs)) 356166af7aafSAndrei Emeltchenko memcpy(&efs, (void *)val, olen); 356266af7aafSAndrei Emeltchenko 356366af7aafSAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 356466af7aafSAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 356566af7aafSAndrei Emeltchenko efs.stype != chan->local_stype) 356666af7aafSAndrei Emeltchenko return -ECONNREFUSED; 356766af7aafSAndrei Emeltchenko 35682d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), 35692d792818SGustavo Padovan (unsigned long) &efs); 357066af7aafSAndrei Emeltchenko break; 3571cbabee78SAndrei Emeltchenko 3572cbabee78SAndrei Emeltchenko case L2CAP_CONF_FCS: 3573cbabee78SAndrei Emeltchenko if (*result == L2CAP_CONF_PENDING) 3574cbabee78SAndrei Emeltchenko if (val == L2CAP_FCS_NONE) 3575f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, 3576cbabee78SAndrei Emeltchenko &chan->conf_state); 3577cbabee78SAndrei Emeltchenko break; 35780a708f8fSGustavo F. Padovan } 35790a708f8fSGustavo F. Padovan } 35800a708f8fSGustavo F. Padovan 35810c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) 35820a708f8fSGustavo F. Padovan return -ECONNREFUSED; 35830a708f8fSGustavo F. Padovan 35840c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode; 35850a708f8fSGustavo F. Padovan 35860e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) { 35870a708f8fSGustavo F. Padovan switch (rfc.mode) { 35880a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 358947d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 359047d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 359147d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 3592c20f8e35SMat Martineau if (!test_bit(FLAG_EXT_CTRL, &chan->flags)) 3593c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 3594c20f8e35SMat Martineau rfc.txwin_size); 359566af7aafSAndrei Emeltchenko 359666af7aafSAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 359766af7aafSAndrei Emeltchenko chan->local_msdu = le16_to_cpu(efs.msdu); 359866af7aafSAndrei Emeltchenko chan->local_sdu_itime = 359966af7aafSAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 360066af7aafSAndrei Emeltchenko chan->local_acc_lat = le32_to_cpu(efs.acc_lat); 360166af7aafSAndrei Emeltchenko chan->local_flush_to = 360266af7aafSAndrei Emeltchenko le32_to_cpu(efs.flush_to); 360366af7aafSAndrei Emeltchenko } 36040a708f8fSGustavo F. Padovan break; 360566af7aafSAndrei Emeltchenko 36060a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 360747d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 36080a708f8fSGustavo F. Padovan } 36090a708f8fSGustavo F. Padovan } 36100a708f8fSGustavo F. Padovan 3611fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 3612dcf4adbfSJoe Perches req->flags = cpu_to_le16(0); 36130a708f8fSGustavo F. Padovan 36140a708f8fSGustavo F. Padovan return ptr - data; 36150a708f8fSGustavo F. Padovan } 36160a708f8fSGustavo F. Padovan 36172d792818SGustavo Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, 36182d792818SGustavo Padovan u16 result, u16 flags) 36190a708f8fSGustavo F. Padovan { 36200a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 36210a708f8fSGustavo F. Padovan void *ptr = rsp->data; 36220a708f8fSGustavo F. Padovan 3623fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan); 36240a708f8fSGustavo F. Padovan 3625fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 36260a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 36270a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags); 36280a708f8fSGustavo F. Padovan 36290a708f8fSGustavo F. Padovan return ptr - data; 36300a708f8fSGustavo F. Padovan } 36310a708f8fSGustavo F. Padovan 363227e2d4c8SJohan Hedberg void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan) 363327e2d4c8SJohan Hedberg { 363427e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 363527e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn; 363627e2d4c8SJohan Hedberg 363727e2d4c8SJohan Hedberg BT_DBG("chan %p", chan); 363827e2d4c8SJohan Hedberg 363927e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 364027e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 36413916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps); 36420cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits); 3643dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 364427e2d4c8SJohan Hedberg 364527e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), 364627e2d4c8SJohan Hedberg &rsp); 364727e2d4c8SJohan Hedberg } 364827e2d4c8SJohan Hedberg 36498c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) 3650710f9b0aSGustavo F. Padovan { 3651710f9b0aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 36528c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 3653710f9b0aSGustavo F. Padovan u8 buf[128]; 3654439f34acSAndrei Emeltchenko u8 rsp_code; 3655710f9b0aSGustavo F. Padovan 3656fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 3657fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3658dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 3659dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 3660439f34acSAndrei Emeltchenko 3661439f34acSAndrei Emeltchenko if (chan->hs_hcon) 3662439f34acSAndrei Emeltchenko rsp_code = L2CAP_CREATE_CHAN_RSP; 3663439f34acSAndrei Emeltchenko else 3664439f34acSAndrei Emeltchenko rsp_code = L2CAP_CONN_RSP; 3665439f34acSAndrei Emeltchenko 3666439f34acSAndrei Emeltchenko BT_DBG("chan %p rsp_code %u", chan, rsp_code); 3667439f34acSAndrei Emeltchenko 3668439f34acSAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp); 3669710f9b0aSGustavo F. Padovan 3670c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 3671710f9b0aSGustavo F. Padovan return; 3672710f9b0aSGustavo F. Padovan 3673710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 3674710f9b0aSGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 3675710f9b0aSGustavo F. Padovan chan->num_conf_req++; 3676710f9b0aSGustavo F. Padovan } 3677710f9b0aSGustavo F. Padovan 367847d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) 36790a708f8fSGustavo F. Padovan { 36800a708f8fSGustavo F. Padovan int type, olen; 36810a708f8fSGustavo F. Padovan unsigned long val; 3682c20f8e35SMat Martineau /* Use sane default values in case a misbehaving remote device 3683c20f8e35SMat Martineau * did not send an RFC or extended window size option. 3684c20f8e35SMat Martineau */ 3685c20f8e35SMat Martineau u16 txwin_ext = chan->ack_win; 3686c20f8e35SMat Martineau struct l2cap_conf_rfc rfc = { 3687c20f8e35SMat Martineau .mode = chan->mode, 3688dcf4adbfSJoe Perches .retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO), 3689dcf4adbfSJoe Perches .monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO), 3690c20f8e35SMat Martineau .max_pdu_size = cpu_to_le16(chan->imtu), 3691c20f8e35SMat Martineau .txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW), 3692c20f8e35SMat Martineau }; 36930a708f8fSGustavo F. Padovan 369447d1ec61SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); 36950a708f8fSGustavo F. Padovan 36960c1bc5c6SGustavo F. Padovan if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) 36970a708f8fSGustavo F. Padovan return; 36980a708f8fSGustavo F. Padovan 36990a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 37000a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 37010a708f8fSGustavo F. Padovan 3702c20f8e35SMat Martineau switch (type) { 3703c20f8e35SMat Martineau case L2CAP_CONF_RFC: 3704c20f8e35SMat Martineau if (olen == sizeof(rfc)) 37050a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 3706c20f8e35SMat Martineau break; 3707c20f8e35SMat Martineau case L2CAP_CONF_EWS: 3708c20f8e35SMat Martineau txwin_ext = val; 3709c20f8e35SMat Martineau break; 3710c20f8e35SMat Martineau } 37110a708f8fSGustavo F. Padovan } 37120a708f8fSGustavo F. Padovan 37130a708f8fSGustavo F. Padovan switch (rfc.mode) { 37140a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 371547d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 371647d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 371747d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 3718c20f8e35SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 3719c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, txwin_ext); 3720c20f8e35SMat Martineau else 3721c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 3722c20f8e35SMat Martineau rfc.txwin_size); 37230a708f8fSGustavo F. Padovan break; 37240a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 372547d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 37260a708f8fSGustavo F. Padovan } 37270a708f8fSGustavo F. Padovan } 37280a708f8fSGustavo F. Padovan 37292d792818SGustavo Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, 3730cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 3731cb3b3152SJohan Hedberg u8 *data) 37320a708f8fSGustavo F. Padovan { 3733e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 37340a708f8fSGustavo F. Padovan 3735cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rej)) 3736cb3b3152SJohan Hedberg return -EPROTO; 3737cb3b3152SJohan Hedberg 3738e2fd318eSIlia Kolomisnky if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) 37390a708f8fSGustavo F. Padovan return 0; 37400a708f8fSGustavo F. Padovan 37410a708f8fSGustavo F. Padovan if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && 37420a708f8fSGustavo F. Padovan cmd->ident == conn->info_ident) { 374317cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 37440a708f8fSGustavo F. Padovan 37450a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 37460a708f8fSGustavo F. Padovan conn->info_ident = 0; 37470a708f8fSGustavo F. Padovan 37480a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 37490a708f8fSGustavo F. Padovan } 37500a708f8fSGustavo F. Padovan 37510a708f8fSGustavo F. Padovan return 0; 37520a708f8fSGustavo F. Padovan } 37530a708f8fSGustavo F. Padovan 37541700915fSMat Martineau static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, 37551700915fSMat Martineau struct l2cap_cmd_hdr *cmd, 37564c89b6aaSMat Martineau u8 *data, u8 rsp_code, u8 amp_id) 37570a708f8fSGustavo F. Padovan { 37580a708f8fSGustavo F. Padovan struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 37590a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 376023691d75SGustavo F. Padovan struct l2cap_chan *chan = NULL, *pchan; 37610a708f8fSGustavo F. Padovan int result, status = L2CAP_CS_NO_INFO; 37620a708f8fSGustavo F. Padovan 37630a708f8fSGustavo F. Padovan u16 dcid = 0, scid = __le16_to_cpu(req->scid); 37640a708f8fSGustavo F. Padovan __le16 psm = req->psm; 37650a708f8fSGustavo F. Padovan 3766097db76cSAndrei Emeltchenko BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); 37670a708f8fSGustavo F. Padovan 37680a708f8fSGustavo F. Padovan /* Check if we have socket listening on psm */ 37696f59b904SMarcel Holtmann pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 3770bf20fd4eSJohan Hedberg &conn->hcon->dst, ACL_LINK); 377123691d75SGustavo F. Padovan if (!pchan) { 37720a708f8fSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 37730a708f8fSGustavo F. Padovan goto sendresp; 37740a708f8fSGustavo F. Padovan } 37750a708f8fSGustavo F. Padovan 37763df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 37778ffb9290SGustavo Padovan l2cap_chan_lock(pchan); 37780a708f8fSGustavo F. Padovan 37790a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */ 3780dcf4adbfSJoe Perches if (psm != cpu_to_le16(L2CAP_PSM_SDP) && 37810a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) { 37829f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_AUTH_FAILURE; 37830a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 37840a708f8fSGustavo F. Padovan goto response; 37850a708f8fSGustavo F. Padovan } 37860a708f8fSGustavo F. Padovan 37870a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM; 37880a708f8fSGustavo F. Padovan 37892dfa1003SGustavo Padovan /* Check if we already have channel with that dcid */ 37902dfa1003SGustavo Padovan if (__l2cap_get_chan_by_dcid(conn, scid)) 37912dfa1003SGustavo Padovan goto response; 37922dfa1003SGustavo Padovan 379380b98027SGustavo Padovan chan = pchan->ops->new_connection(pchan); 379480808e43SGustavo F. Padovan if (!chan) 37950a708f8fSGustavo F. Padovan goto response; 37960a708f8fSGustavo F. Padovan 3797330b6c15SSyam Sidhardhan /* For certain devices (ex: HID mouse), support for authentication, 3798330b6c15SSyam Sidhardhan * pairing and bonding is optional. For such devices, inorder to avoid 3799330b6c15SSyam Sidhardhan * the ACL alive for too long after L2CAP disconnection, reset the ACL 3800330b6c15SSyam Sidhardhan * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect. 3801330b6c15SSyam Sidhardhan */ 3802330b6c15SSyam Sidhardhan conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 3803330b6c15SSyam Sidhardhan 38047eafc59eSMarcel Holtmann bacpy(&chan->src, &conn->hcon->src); 38057eafc59eSMarcel Holtmann bacpy(&chan->dst, &conn->hcon->dst); 3806a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(conn->hcon); 3807a250e048SJohan Hedberg chan->dst_type = bdaddr_dst_type(conn->hcon); 3808fe4128e0SGustavo F. Padovan chan->psm = psm; 3809fe4128e0SGustavo F. Padovan chan->dcid = scid; 38101700915fSMat Martineau chan->local_amp_id = amp_id; 38110a708f8fSGustavo F. Padovan 38126be36555SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 381348454079SGustavo F. Padovan 3814fe4128e0SGustavo F. Padovan dcid = chan->scid; 38150a708f8fSGustavo F. Padovan 38168d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 38170a708f8fSGustavo F. Padovan 3818fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident; 38190a708f8fSGustavo F. Padovan 38200a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { 3821e7cafc45SJohan Hedberg if (l2cap_chan_check_security(chan, false)) { 3822bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 3823f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 38240a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 38250a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND; 38262dc4e510SGustavo Padovan chan->ops->defer(chan); 38270a708f8fSGustavo F. Padovan } else { 38281700915fSMat Martineau /* Force pending result for AMP controllers. 38291700915fSMat Martineau * The connection will succeed after the 38301700915fSMat Martineau * physical link is up. 38311700915fSMat Martineau */ 38326ed971caSMarcel Holtmann if (amp_id == AMP_ID_BREDR) { 3833f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 38340a708f8fSGustavo F. Padovan result = L2CAP_CR_SUCCESS; 38356ed971caSMarcel Holtmann } else { 3836f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 38376ed971caSMarcel Holtmann result = L2CAP_CR_PEND; 38381700915fSMat Martineau } 38390a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 38400a708f8fSGustavo F. Padovan } 38410a708f8fSGustavo F. Padovan } else { 3842f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 38430a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 38440a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND; 38450a708f8fSGustavo F. Padovan } 38460a708f8fSGustavo F. Padovan } else { 3847f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 38480a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 38490a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 38500a708f8fSGustavo F. Padovan } 38510a708f8fSGustavo F. Padovan 38520a708f8fSGustavo F. Padovan response: 38538ffb9290SGustavo Padovan l2cap_chan_unlock(pchan); 38543df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 3855a24cce14SJohan Hedberg l2cap_chan_put(pchan); 38560a708f8fSGustavo F. Padovan 38570a708f8fSGustavo F. Padovan sendresp: 38580a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid); 38590a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid); 38600a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result); 38610a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status); 38624c89b6aaSMat Martineau l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp); 38630a708f8fSGustavo F. Padovan 38640a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { 38650a708f8fSGustavo F. Padovan struct l2cap_info_req info; 3866dcf4adbfSJoe Perches info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 38670a708f8fSGustavo F. Padovan 38680a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 38690a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 38700a708f8fSGustavo F. Padovan 3871ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 38720a708f8fSGustavo F. Padovan 38732d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, 38742d792818SGustavo Padovan sizeof(info), &info); 38750a708f8fSGustavo F. Padovan } 38760a708f8fSGustavo F. Padovan 3877c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && 38780a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) { 38790a708f8fSGustavo F. Padovan u8 buf[128]; 3880c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 38810a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 388273ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 388373ffa904SGustavo F. Padovan chan->num_conf_req++; 38840a708f8fSGustavo F. Padovan } 38851700915fSMat Martineau 38861700915fSMat Martineau return chan; 38874c89b6aaSMat Martineau } 38880a708f8fSGustavo F. Padovan 38894c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn, 3890cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 38914c89b6aaSMat Martineau { 38927b064edaSJaganath Kanakkassery struct hci_dev *hdev = conn->hcon->hdev; 38937b064edaSJaganath Kanakkassery struct hci_conn *hcon = conn->hcon; 38947b064edaSJaganath Kanakkassery 3895cb3b3152SJohan Hedberg if (cmd_len < sizeof(struct l2cap_conn_req)) 3896cb3b3152SJohan Hedberg return -EPROTO; 3897cb3b3152SJohan Hedberg 38987b064edaSJaganath Kanakkassery hci_dev_lock(hdev); 3899d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_MGMT) && 39007b064edaSJaganath Kanakkassery !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags)) 390148ec92faSAlfonso Acosta mgmt_device_connected(hdev, hcon, 0, NULL, 0); 39027b064edaSJaganath Kanakkassery hci_dev_unlock(hdev); 39037b064edaSJaganath Kanakkassery 3904300229f9SGustavo Padovan l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0); 39050a708f8fSGustavo F. Padovan return 0; 39060a708f8fSGustavo F. Padovan } 39070a708f8fSGustavo F. Padovan 39085909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn, 3909cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 3910cb3b3152SJohan Hedberg u8 *data) 39110a708f8fSGustavo F. Padovan { 39120a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; 39130a708f8fSGustavo F. Padovan u16 scid, dcid, result, status; 391448454079SGustavo F. Padovan struct l2cap_chan *chan; 39150a708f8fSGustavo F. Padovan u8 req[128]; 39163df91ea2SAndrei Emeltchenko int err; 39170a708f8fSGustavo F. Padovan 3918cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp)) 3919cb3b3152SJohan Hedberg return -EPROTO; 3920cb3b3152SJohan Hedberg 39210a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 39220a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 39230a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 39240a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status); 39250a708f8fSGustavo F. Padovan 39261b009c98SAndrei Emeltchenko BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", 39271b009c98SAndrei Emeltchenko dcid, scid, result, status); 39280a708f8fSGustavo F. Padovan 39293df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 39303df91ea2SAndrei Emeltchenko 39310a708f8fSGustavo F. Padovan if (scid) { 39323df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 39333df91ea2SAndrei Emeltchenko if (!chan) { 393421870b52SJohan Hedberg err = -EBADSLT; 39353df91ea2SAndrei Emeltchenko goto unlock; 39363df91ea2SAndrei Emeltchenko } 39370a708f8fSGustavo F. Padovan } else { 39383df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 39393df91ea2SAndrei Emeltchenko if (!chan) { 394021870b52SJohan Hedberg err = -EBADSLT; 39413df91ea2SAndrei Emeltchenko goto unlock; 39423df91ea2SAndrei Emeltchenko } 39430a708f8fSGustavo F. Padovan } 39440a708f8fSGustavo F. Padovan 39453df91ea2SAndrei Emeltchenko err = 0; 39463df91ea2SAndrei Emeltchenko 39476be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 394848454079SGustavo F. Padovan 39490a708f8fSGustavo F. Padovan switch (result) { 39500a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS: 395189bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 3952fc7f8a7eSGustavo F. Padovan chan->ident = 0; 3953fe4128e0SGustavo F. Padovan chan->dcid = dcid; 3954c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state); 39550a708f8fSGustavo F. Padovan 3956c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 39570a708f8fSGustavo F. Padovan break; 39580a708f8fSGustavo F. Padovan 39590a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 396073ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, req), req); 396173ffa904SGustavo F. Padovan chan->num_conf_req++; 39620a708f8fSGustavo F. Padovan break; 39630a708f8fSGustavo F. Padovan 39640a708f8fSGustavo F. Padovan case L2CAP_CR_PEND: 3965c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 39660a708f8fSGustavo F. Padovan break; 39670a708f8fSGustavo F. Padovan 39680a708f8fSGustavo F. Padovan default: 396948454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED); 39700a708f8fSGustavo F. Padovan break; 39710a708f8fSGustavo F. Padovan } 39720a708f8fSGustavo F. Padovan 39736be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 39743df91ea2SAndrei Emeltchenko 39753df91ea2SAndrei Emeltchenko unlock: 39763df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 39773df91ea2SAndrei Emeltchenko 39783df91ea2SAndrei Emeltchenko return err; 39790a708f8fSGustavo F. Padovan } 39800a708f8fSGustavo F. Padovan 398147d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan) 39820a708f8fSGustavo F. Padovan { 39830a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both 39840a708f8fSGustavo F. Padovan * sides request it. 39850a708f8fSGustavo F. Padovan */ 39860c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) 398747d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3988f2592d3eSAndrei Emeltchenko else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) 398947d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16; 39900a708f8fSGustavo F. Padovan } 39910a708f8fSGustavo F. Padovan 399229d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data, 399329d8a590SAndrei Emeltchenko u8 ident, u16 flags) 399429d8a590SAndrei Emeltchenko { 399529d8a590SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 399629d8a590SAndrei Emeltchenko 399729d8a590SAndrei Emeltchenko BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident, 399829d8a590SAndrei Emeltchenko flags); 399929d8a590SAndrei Emeltchenko 400029d8a590SAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 400129d8a590SAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 400229d8a590SAndrei Emeltchenko 400329d8a590SAndrei Emeltchenko l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP, 400429d8a590SAndrei Emeltchenko l2cap_build_conf_rsp(chan, data, 400529d8a590SAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), data); 400629d8a590SAndrei Emeltchenko } 400729d8a590SAndrei Emeltchenko 4008662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident, 4009662d652dSJohan Hedberg u16 scid, u16 dcid) 4010662d652dSJohan Hedberg { 4011662d652dSJohan Hedberg struct l2cap_cmd_rej_cid rej; 4012662d652dSJohan Hedberg 4013dcf4adbfSJoe Perches rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID); 4014662d652dSJohan Hedberg rej.scid = __cpu_to_le16(scid); 4015662d652dSJohan Hedberg rej.dcid = __cpu_to_le16(dcid); 4016662d652dSJohan Hedberg 4017662d652dSJohan Hedberg l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); 4018662d652dSJohan Hedberg } 4019662d652dSJohan Hedberg 40202d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, 40212d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len, 40222d792818SGustavo Padovan u8 *data) 40230a708f8fSGustavo F. Padovan { 40240a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; 40250a708f8fSGustavo F. Padovan u16 dcid, flags; 40260a708f8fSGustavo F. Padovan u8 rsp[64]; 402748454079SGustavo F. Padovan struct l2cap_chan *chan; 40283c588192SMat Martineau int len, err = 0; 40290a708f8fSGustavo F. Padovan 4030cb3b3152SJohan Hedberg if (cmd_len < sizeof(*req)) 4031cb3b3152SJohan Hedberg return -EPROTO; 4032cb3b3152SJohan Hedberg 40330a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 40340a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags); 40350a708f8fSGustavo F. Padovan 40360a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); 40370a708f8fSGustavo F. Padovan 4038baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid); 4039662d652dSJohan Hedberg if (!chan) { 4040662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0); 4041662d652dSJohan Hedberg return 0; 4042662d652dSJohan Hedberg } 40430a708f8fSGustavo F. Padovan 4044033b1142SDavid S. Miller if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { 4045662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, 4046662d652dSJohan Hedberg chan->dcid); 40470a708f8fSGustavo F. Padovan goto unlock; 40480a708f8fSGustavo F. Padovan } 40490a708f8fSGustavo F. Padovan 40500a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */ 40510a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req); 4052cb3b3152SJohan Hedberg if (chan->conf_len + len > sizeof(chan->conf_req)) { 40530a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 4054fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 40550a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp); 40560a708f8fSGustavo F. Padovan goto unlock; 40570a708f8fSGustavo F. Padovan } 40580a708f8fSGustavo F. Padovan 40590a708f8fSGustavo F. Padovan /* Store config. */ 406073ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len); 406173ffa904SGustavo F. Padovan chan->conf_len += len; 40620a708f8fSGustavo F. Padovan 406359e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) { 40640a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */ 40650a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 4066fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 40675325e5bbSAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), rsp); 40680a708f8fSGustavo F. Padovan goto unlock; 40690a708f8fSGustavo F. Padovan } 40700a708f8fSGustavo F. Padovan 40710a708f8fSGustavo F. Padovan /* Complete config. */ 407273ffa904SGustavo F. Padovan len = l2cap_parse_conf_req(chan, rsp); 40730a708f8fSGustavo F. Padovan if (len < 0) { 40745e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 40750a708f8fSGustavo F. Padovan goto unlock; 40760a708f8fSGustavo F. Padovan } 40770a708f8fSGustavo F. Padovan 40781500109bSMat Martineau chan->ident = cmd->ident; 40790a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); 408073ffa904SGustavo F. Padovan chan->num_conf_rsp++; 40810a708f8fSGustavo F. Padovan 40820a708f8fSGustavo F. Padovan /* Reset config buffer. */ 408373ffa904SGustavo F. Padovan chan->conf_len = 0; 40840a708f8fSGustavo F. Padovan 4085c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) 40860a708f8fSGustavo F. Padovan goto unlock; 40870a708f8fSGustavo F. Padovan 4088c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 408947d1ec61SGustavo F. Padovan set_default_fcs(chan); 40900a708f8fSGustavo F. Padovan 4091105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 4092105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 40933c588192SMat Martineau err = l2cap_ertm_init(chan); 40940a708f8fSGustavo F. Padovan 40953c588192SMat Martineau if (err < 0) 40965e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 40973c588192SMat Martineau else 4098cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 40993c588192SMat Martineau 41000a708f8fSGustavo F. Padovan goto unlock; 41010a708f8fSGustavo F. Padovan } 41020a708f8fSGustavo F. Padovan 4103c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { 41040a708f8fSGustavo F. Padovan u8 buf[64]; 41050a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 410673ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 410773ffa904SGustavo F. Padovan chan->num_conf_req++; 41080a708f8fSGustavo F. Padovan } 41090a708f8fSGustavo F. Padovan 411049c922bbSStephen Hemminger /* Got Conf Rsp PENDING from remote side and assume we sent 41110e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */ 41120e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && 41130e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 41140e8b207eSAndrei Emeltchenko 41150e8b207eSAndrei Emeltchenko /* check compatibility */ 41160e8b207eSAndrei Emeltchenko 411779de886dSAndrei Emeltchenko /* Send rsp for BR/EDR channel */ 4118f351bc72SAndrei Emeltchenko if (!chan->hs_hcon) 411929d8a590SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags); 412079de886dSAndrei Emeltchenko else 412179de886dSAndrei Emeltchenko chan->ident = cmd->ident; 41220e8b207eSAndrei Emeltchenko } 41230e8b207eSAndrei Emeltchenko 41240a708f8fSGustavo F. Padovan unlock: 41256be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 41263c588192SMat Martineau return err; 41270a708f8fSGustavo F. Padovan } 41280a708f8fSGustavo F. Padovan 41292d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, 4130cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4131cb3b3152SJohan Hedberg u8 *data) 41320a708f8fSGustavo F. Padovan { 41330a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; 41340a708f8fSGustavo F. Padovan u16 scid, flags, result; 413548454079SGustavo F. Padovan struct l2cap_chan *chan; 4136cb3b3152SJohan Hedberg int len = cmd_len - sizeof(*rsp); 41373c588192SMat Martineau int err = 0; 41380a708f8fSGustavo F. Padovan 4139cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp)) 4140cb3b3152SJohan Hedberg return -EPROTO; 4141cb3b3152SJohan Hedberg 41420a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 41430a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags); 41440a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 41450a708f8fSGustavo F. Padovan 414661386cbaSAndrei Emeltchenko BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags, 414761386cbaSAndrei Emeltchenko result, len); 41480a708f8fSGustavo F. Padovan 4149baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 415048454079SGustavo F. Padovan if (!chan) 41510a708f8fSGustavo F. Padovan return 0; 41520a708f8fSGustavo F. Padovan 41530a708f8fSGustavo F. Padovan switch (result) { 41540a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS: 415547d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len); 41560e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state); 41570a708f8fSGustavo F. Padovan break; 41580a708f8fSGustavo F. Padovan 41590e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING: 41600e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state); 41610e8b207eSAndrei Emeltchenko 41620e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 41630e8b207eSAndrei Emeltchenko char buf[64]; 41640e8b207eSAndrei Emeltchenko 41650e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len, 41660e8b207eSAndrei Emeltchenko buf, &result); 41670e8b207eSAndrei Emeltchenko if (len < 0) { 41685e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 41690e8b207eSAndrei Emeltchenko goto done; 41700e8b207eSAndrei Emeltchenko } 41710e8b207eSAndrei Emeltchenko 4172f351bc72SAndrei Emeltchenko if (!chan->hs_hcon) { 417379de886dSAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, buf, cmd->ident, 417479de886dSAndrei Emeltchenko 0); 41755ce66b59SAndrei Emeltchenko } else { 41765ce66b59SAndrei Emeltchenko if (l2cap_check_efs(chan)) { 41775ce66b59SAndrei Emeltchenko amp_create_logical_link(chan); 417879de886dSAndrei Emeltchenko chan->ident = cmd->ident; 41790e8b207eSAndrei Emeltchenko } 41805ce66b59SAndrei Emeltchenko } 41815ce66b59SAndrei Emeltchenko } 41820e8b207eSAndrei Emeltchenko goto done; 41830e8b207eSAndrei Emeltchenko 41840a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT: 418573ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { 41860a708f8fSGustavo F. Padovan char req[64]; 41870a708f8fSGustavo F. Padovan 41880a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { 41895e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 41900a708f8fSGustavo F. Padovan goto done; 41910a708f8fSGustavo F. Padovan } 41920a708f8fSGustavo F. Padovan 41930a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */ 41940a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS; 4195b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len, 4196b4450035SGustavo F. Padovan req, &result); 41970a708f8fSGustavo F. Padovan if (len < 0) { 41985e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 41990a708f8fSGustavo F. Padovan goto done; 42000a708f8fSGustavo F. Padovan } 42010a708f8fSGustavo F. Padovan 42020a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 42030a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req); 420473ffa904SGustavo F. Padovan chan->num_conf_req++; 42050a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS) 42060a708f8fSGustavo F. Padovan goto done; 42070a708f8fSGustavo F. Padovan break; 42080a708f8fSGustavo F. Padovan } 42090a708f8fSGustavo F. Padovan 42100a708f8fSGustavo F. Padovan default: 42116be36555SAndrei Emeltchenko l2cap_chan_set_err(chan, ECONNRESET); 42122e0052e4SAndrei Emeltchenko 4213ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); 42145e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 42150a708f8fSGustavo F. Padovan goto done; 42160a708f8fSGustavo F. Padovan } 42170a708f8fSGustavo F. Padovan 421859e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) 42190a708f8fSGustavo F. Padovan goto done; 42200a708f8fSGustavo F. Padovan 4221c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state); 42220a708f8fSGustavo F. Padovan 4223c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { 422447d1ec61SGustavo F. Padovan set_default_fcs(chan); 42250a708f8fSGustavo F. Padovan 4226105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 4227105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 42283c588192SMat Martineau err = l2cap_ertm_init(chan); 42290a708f8fSGustavo F. Padovan 42303c588192SMat Martineau if (err < 0) 42315e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 42323c588192SMat Martineau else 4233cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 42340a708f8fSGustavo F. Padovan } 42350a708f8fSGustavo F. Padovan 42360a708f8fSGustavo F. Padovan done: 42376be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 42383c588192SMat Martineau return err; 42390a708f8fSGustavo F. Padovan } 42400a708f8fSGustavo F. Padovan 42412d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, 4242cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4243cb3b3152SJohan Hedberg u8 *data) 42440a708f8fSGustavo F. Padovan { 42450a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; 42460a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp; 42470a708f8fSGustavo F. Padovan u16 dcid, scid; 424848454079SGustavo F. Padovan struct l2cap_chan *chan; 42490a708f8fSGustavo F. Padovan 4250cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req)) 4251cb3b3152SJohan Hedberg return -EPROTO; 4252cb3b3152SJohan Hedberg 42530a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid); 42540a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 42550a708f8fSGustavo F. Padovan 42560a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); 42570a708f8fSGustavo F. Padovan 42583df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 42593df91ea2SAndrei Emeltchenko 42603df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, dcid); 42613df91ea2SAndrei Emeltchenko if (!chan) { 42623df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4263662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid); 4264662d652dSJohan Hedberg return 0; 42653df91ea2SAndrei Emeltchenko } 42660a708f8fSGustavo F. Padovan 42676be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 42686be36555SAndrei Emeltchenko 4269fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 4270fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 42710a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); 42720a708f8fSGustavo F. Padovan 42735ec1bbe5SGustavo Padovan chan->ops->set_shutdown(chan); 42740a708f8fSGustavo F. Padovan 427561d6ef3eSMat Martineau l2cap_chan_hold(chan); 427648454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET); 42776be36555SAndrei Emeltchenko 42786be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 42790a708f8fSGustavo F. Padovan 428080b98027SGustavo Padovan chan->ops->close(chan); 428161d6ef3eSMat Martineau l2cap_chan_put(chan); 42823df91ea2SAndrei Emeltchenko 42833df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 42843df91ea2SAndrei Emeltchenko 42850a708f8fSGustavo F. Padovan return 0; 42860a708f8fSGustavo F. Padovan } 42870a708f8fSGustavo F. Padovan 42882d792818SGustavo Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, 4289cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4290cb3b3152SJohan Hedberg u8 *data) 42910a708f8fSGustavo F. Padovan { 42920a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; 42930a708f8fSGustavo F. Padovan u16 dcid, scid; 429448454079SGustavo F. Padovan struct l2cap_chan *chan; 42950a708f8fSGustavo F. Padovan 4296cb3b3152SJohan Hedberg if (cmd_len != sizeof(*rsp)) 4297cb3b3152SJohan Hedberg return -EPROTO; 4298cb3b3152SJohan Hedberg 42990a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 43000a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 43010a708f8fSGustavo F. Padovan 43020a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); 43030a708f8fSGustavo F. Padovan 43043df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 43053df91ea2SAndrei Emeltchenko 43063df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 43073df91ea2SAndrei Emeltchenko if (!chan) { 43083df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 43090a708f8fSGustavo F. Padovan return 0; 43103df91ea2SAndrei Emeltchenko } 43110a708f8fSGustavo F. Padovan 43126be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 431348454079SGustavo F. Padovan 431461d6ef3eSMat Martineau l2cap_chan_hold(chan); 431548454079SGustavo F. Padovan l2cap_chan_del(chan, 0); 43166be36555SAndrei Emeltchenko 43176be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 43180a708f8fSGustavo F. Padovan 431980b98027SGustavo Padovan chan->ops->close(chan); 432061d6ef3eSMat Martineau l2cap_chan_put(chan); 43213df91ea2SAndrei Emeltchenko 43223df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 43233df91ea2SAndrei Emeltchenko 43240a708f8fSGustavo F. Padovan return 0; 43250a708f8fSGustavo F. Padovan } 43260a708f8fSGustavo F. Padovan 43272d792818SGustavo Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, 4328cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4329cb3b3152SJohan Hedberg u8 *data) 43300a708f8fSGustavo F. Padovan { 43310a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data; 43320a708f8fSGustavo F. Padovan u16 type; 43330a708f8fSGustavo F. Padovan 4334cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req)) 4335cb3b3152SJohan Hedberg return -EPROTO; 4336cb3b3152SJohan Hedberg 43370a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type); 43380a708f8fSGustavo F. Padovan 43390a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type); 43400a708f8fSGustavo F. Padovan 43410a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) { 43420a708f8fSGustavo F. Padovan u8 buf[8]; 43430a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask; 43440a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 4345dcf4adbfSJoe Perches rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 4346dcf4adbfSJoe Perches rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 43470a708f8fSGustavo F. Padovan if (!disable_ertm) 43480a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING 43490a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS; 43500bd49fc7SJohan Hedberg if (conn->local_fixed_chan & L2CAP_FC_A2MP) 43516327eb98SAndrei Emeltchenko feat_mask |= L2CAP_FEAT_EXT_FLOW 43526327eb98SAndrei Emeltchenko | L2CAP_FEAT_EXT_WINDOW; 4353a5fd6f30SAndrei Emeltchenko 43540a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data); 43552d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), 43562d792818SGustavo Padovan buf); 43570a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) { 43580a708f8fSGustavo F. Padovan u8 buf[12]; 43590a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 436050a147cdSMat Martineau 4361dcf4adbfSJoe Perches rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 4362dcf4adbfSJoe Perches rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 43630bd49fc7SJohan Hedberg rsp->data[0] = conn->local_fixed_chan; 43640bd49fc7SJohan Hedberg memset(rsp->data + 1, 0, 7); 43652d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), 43662d792818SGustavo Padovan buf); 43670a708f8fSGustavo F. Padovan } else { 43680a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp; 43690a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type); 4370dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP); 43712d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), 43722d792818SGustavo Padovan &rsp); 43730a708f8fSGustavo F. Padovan } 43740a708f8fSGustavo F. Padovan 43750a708f8fSGustavo F. Padovan return 0; 43760a708f8fSGustavo F. Padovan } 43770a708f8fSGustavo F. Padovan 43782d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, 4379cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4380cb3b3152SJohan Hedberg u8 *data) 43810a708f8fSGustavo F. Padovan { 43820a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; 43830a708f8fSGustavo F. Padovan u16 type, result; 43840a708f8fSGustavo F. Padovan 43853f6fa3d4SJaganath Kanakkassery if (cmd_len < sizeof(*rsp)) 4386cb3b3152SJohan Hedberg return -EPROTO; 4387cb3b3152SJohan Hedberg 43880a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type); 43890a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 43900a708f8fSGustavo F. Padovan 43910a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); 43920a708f8fSGustavo F. Padovan 4393e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */ 4394e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident || 4395e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 4396e90165beSAndrei Emeltchenko return 0; 4397e90165beSAndrei Emeltchenko 439817cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 43990a708f8fSGustavo F. Padovan 44000a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) { 44010a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 44020a708f8fSGustavo F. Padovan conn->info_ident = 0; 44030a708f8fSGustavo F. Padovan 44040a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 44050a708f8fSGustavo F. Padovan 44060a708f8fSGustavo F. Padovan return 0; 44070a708f8fSGustavo F. Padovan } 44080a708f8fSGustavo F. Padovan 4409978c93b9SAndrei Emeltchenko switch (type) { 4410978c93b9SAndrei Emeltchenko case L2CAP_IT_FEAT_MASK: 44110a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data); 44120a708f8fSGustavo F. Padovan 44130a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { 44140a708f8fSGustavo F. Padovan struct l2cap_info_req req; 4415dcf4adbfSJoe Perches req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 44160a708f8fSGustavo F. Padovan 44170a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 44180a708f8fSGustavo F. Padovan 44190a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 44200a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 44210a708f8fSGustavo F. Padovan } else { 44220a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 44230a708f8fSGustavo F. Padovan conn->info_ident = 0; 44240a708f8fSGustavo F. Padovan 44250a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 44260a708f8fSGustavo F. Padovan } 4427978c93b9SAndrei Emeltchenko break; 4428978c93b9SAndrei Emeltchenko 4429978c93b9SAndrei Emeltchenko case L2CAP_IT_FIXED_CHAN: 44300bd49fc7SJohan Hedberg conn->remote_fixed_chan = rsp->data[0]; 44310a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 44320a708f8fSGustavo F. Padovan conn->info_ident = 0; 44330a708f8fSGustavo F. Padovan 44340a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 4435978c93b9SAndrei Emeltchenko break; 44360a708f8fSGustavo F. Padovan } 44370a708f8fSGustavo F. Padovan 44380a708f8fSGustavo F. Padovan return 0; 44390a708f8fSGustavo F. Padovan } 44400a708f8fSGustavo F. Padovan 44411700915fSMat Martineau static int l2cap_create_channel_req(struct l2cap_conn *conn, 44422d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, 44432d792818SGustavo Padovan u16 cmd_len, void *data) 4444f94ff6ffSMat Martineau { 4445f94ff6ffSMat Martineau struct l2cap_create_chan_req *req = data; 44466e1df6a6SAndrei Emeltchenko struct l2cap_create_chan_rsp rsp; 44471700915fSMat Martineau struct l2cap_chan *chan; 44486e1df6a6SAndrei Emeltchenko struct hci_dev *hdev; 4449f94ff6ffSMat Martineau u16 psm, scid; 4450f94ff6ffSMat Martineau 4451f94ff6ffSMat Martineau if (cmd_len != sizeof(*req)) 4452f94ff6ffSMat Martineau return -EPROTO; 4453f94ff6ffSMat Martineau 44540bd49fc7SJohan Hedberg if (!(conn->local_fixed_chan & L2CAP_FC_A2MP)) 4455f94ff6ffSMat Martineau return -EINVAL; 4456f94ff6ffSMat Martineau 4457f94ff6ffSMat Martineau psm = le16_to_cpu(req->psm); 4458f94ff6ffSMat Martineau scid = le16_to_cpu(req->scid); 4459f94ff6ffSMat Martineau 4460ad0ac6caSAndrei Emeltchenko BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id); 4461f94ff6ffSMat Martineau 44626e1df6a6SAndrei Emeltchenko /* For controller id 0 make BR/EDR connection */ 44636ed971caSMarcel Holtmann if (req->amp_id == AMP_ID_BREDR) { 44646e1df6a6SAndrei Emeltchenko l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, 44656e1df6a6SAndrei Emeltchenko req->amp_id); 44666e1df6a6SAndrei Emeltchenko return 0; 44676e1df6a6SAndrei Emeltchenko } 44681700915fSMat Martineau 44691700915fSMat Martineau /* Validate AMP controller id */ 44701700915fSMat Martineau hdev = hci_dev_get(req->amp_id); 44716e1df6a6SAndrei Emeltchenko if (!hdev) 44726e1df6a6SAndrei Emeltchenko goto error; 44731700915fSMat Martineau 44746e1df6a6SAndrei Emeltchenko if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) { 44756e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 44766e1df6a6SAndrei Emeltchenko goto error; 44776e1df6a6SAndrei Emeltchenko } 44786e1df6a6SAndrei Emeltchenko 44796e1df6a6SAndrei Emeltchenko chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, 44806e1df6a6SAndrei Emeltchenko req->amp_id); 44816e1df6a6SAndrei Emeltchenko if (chan) { 44826e1df6a6SAndrei Emeltchenko struct amp_mgr *mgr = conn->hcon->amp_mgr; 44836e1df6a6SAndrei Emeltchenko struct hci_conn *hs_hcon; 44846e1df6a6SAndrei Emeltchenko 448598e0f7eaSMarcel Holtmann hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, 448698e0f7eaSMarcel Holtmann &conn->hcon->dst); 44876e1df6a6SAndrei Emeltchenko if (!hs_hcon) { 44886e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 4489662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, 4490662d652dSJohan Hedberg chan->dcid); 4491662d652dSJohan Hedberg return 0; 44926e1df6a6SAndrei Emeltchenko } 44936e1df6a6SAndrei Emeltchenko 44946e1df6a6SAndrei Emeltchenko BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon); 44956e1df6a6SAndrei Emeltchenko 44966e1df6a6SAndrei Emeltchenko mgr->bredr_chan = chan; 44976e1df6a6SAndrei Emeltchenko chan->hs_hcon = hs_hcon; 4498fd45bf4cSAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 44996e1df6a6SAndrei Emeltchenko conn->mtu = hdev->block_mtu; 45006e1df6a6SAndrei Emeltchenko } 45016e1df6a6SAndrei Emeltchenko 45026e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 45036e1df6a6SAndrei Emeltchenko 45046e1df6a6SAndrei Emeltchenko return 0; 45056e1df6a6SAndrei Emeltchenko 45066e1df6a6SAndrei Emeltchenko error: 4507f94ff6ffSMat Martineau rsp.dcid = 0; 4508f94ff6ffSMat Martineau rsp.scid = cpu_to_le16(scid); 4509dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_BAD_AMP); 4510dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 4511f94ff6ffSMat Martineau 4512f94ff6ffSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, 4513f94ff6ffSMat Martineau sizeof(rsp), &rsp); 4514f94ff6ffSMat Martineau 4515dc280801SJohan Hedberg return 0; 4516f94ff6ffSMat Martineau } 4517f94ff6ffSMat Martineau 45188eb200bdSMat Martineau static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id) 45198eb200bdSMat Martineau { 45208eb200bdSMat Martineau struct l2cap_move_chan_req req; 45218eb200bdSMat Martineau u8 ident; 45228eb200bdSMat Martineau 45238eb200bdSMat Martineau BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id); 45248eb200bdSMat Martineau 45258eb200bdSMat Martineau ident = l2cap_get_ident(chan->conn); 45268eb200bdSMat Martineau chan->ident = ident; 45278eb200bdSMat Martineau 45288eb200bdSMat Martineau req.icid = cpu_to_le16(chan->scid); 45298eb200bdSMat Martineau req.dest_amp_id = dest_amp_id; 45308eb200bdSMat Martineau 45318eb200bdSMat Martineau l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req), 45328eb200bdSMat Martineau &req); 45338eb200bdSMat Martineau 45348eb200bdSMat Martineau __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); 45358eb200bdSMat Martineau } 45368eb200bdSMat Martineau 45371500109bSMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result) 45388d5a04a1SMat Martineau { 45398d5a04a1SMat Martineau struct l2cap_move_chan_rsp rsp; 45408d5a04a1SMat Martineau 45411500109bSMat Martineau BT_DBG("chan %p, result 0x%4.4x", chan, result); 45428d5a04a1SMat Martineau 45431500109bSMat Martineau rsp.icid = cpu_to_le16(chan->dcid); 45448d5a04a1SMat Martineau rsp.result = cpu_to_le16(result); 45458d5a04a1SMat Martineau 45461500109bSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP, 45471500109bSMat Martineau sizeof(rsp), &rsp); 45488d5a04a1SMat Martineau } 45498d5a04a1SMat Martineau 45505b155ef9SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result) 45518d5a04a1SMat Martineau { 45528d5a04a1SMat Martineau struct l2cap_move_chan_cfm cfm; 45538d5a04a1SMat Martineau 45545b155ef9SMat Martineau BT_DBG("chan %p, result 0x%4.4x", chan, result); 45558d5a04a1SMat Martineau 45565b155ef9SMat Martineau chan->ident = l2cap_get_ident(chan->conn); 45578d5a04a1SMat Martineau 45585b155ef9SMat Martineau cfm.icid = cpu_to_le16(chan->scid); 45598d5a04a1SMat Martineau cfm.result = cpu_to_le16(result); 45608d5a04a1SMat Martineau 45615b155ef9SMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM, 45625b155ef9SMat Martineau sizeof(cfm), &cfm); 45635b155ef9SMat Martineau 45645b155ef9SMat Martineau __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); 45655b155ef9SMat Martineau } 45665b155ef9SMat Martineau 45675b155ef9SMat Martineau static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid) 45685b155ef9SMat Martineau { 45695b155ef9SMat Martineau struct l2cap_move_chan_cfm cfm; 45705b155ef9SMat Martineau 45715b155ef9SMat Martineau BT_DBG("conn %p, icid 0x%4.4x", conn, icid); 45725b155ef9SMat Martineau 45735b155ef9SMat Martineau cfm.icid = cpu_to_le16(icid); 4574dcf4adbfSJoe Perches cfm.result = cpu_to_le16(L2CAP_MC_UNCONFIRMED); 45755b155ef9SMat Martineau 45765b155ef9SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM, 45775b155ef9SMat Martineau sizeof(cfm), &cfm); 45788d5a04a1SMat Martineau } 45798d5a04a1SMat Martineau 45808d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, 45818d5a04a1SMat Martineau u16 icid) 45828d5a04a1SMat Martineau { 45838d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp rsp; 45848d5a04a1SMat Martineau 4585ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 45868d5a04a1SMat Martineau 45878d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 45888d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp); 45898d5a04a1SMat Martineau } 45908d5a04a1SMat Martineau 45915f3847a4SMat Martineau static void __release_logical_link(struct l2cap_chan *chan) 45925f3847a4SMat Martineau { 45935f3847a4SMat Martineau chan->hs_hchan = NULL; 45945f3847a4SMat Martineau chan->hs_hcon = NULL; 45955f3847a4SMat Martineau 45965f3847a4SMat Martineau /* Placeholder - release the logical link */ 45975f3847a4SMat Martineau } 45985f3847a4SMat Martineau 45991500109bSMat Martineau static void l2cap_logical_fail(struct l2cap_chan *chan) 46001500109bSMat Martineau { 46011500109bSMat Martineau /* Logical link setup failed */ 46021500109bSMat Martineau if (chan->state != BT_CONNECTED) { 46031500109bSMat Martineau /* Create channel failure, disconnect */ 46045e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 46051500109bSMat Martineau return; 46061500109bSMat Martineau } 46071500109bSMat Martineau 46081500109bSMat Martineau switch (chan->move_role) { 46091500109bSMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 46101500109bSMat Martineau l2cap_move_done(chan); 46111500109bSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP); 46121500109bSMat Martineau break; 46131500109bSMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 46141500109bSMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP || 46151500109bSMat Martineau chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) { 46161500109bSMat Martineau /* Remote has only sent pending or 46171500109bSMat Martineau * success responses, clean up 46181500109bSMat Martineau */ 46191500109bSMat Martineau l2cap_move_done(chan); 46201500109bSMat Martineau } 46211500109bSMat Martineau 46221500109bSMat Martineau /* Other amp move states imply that the move 46231500109bSMat Martineau * has already aborted 46241500109bSMat Martineau */ 46251500109bSMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 46261500109bSMat Martineau break; 46271500109bSMat Martineau } 46281500109bSMat Martineau } 46291500109bSMat Martineau 46301500109bSMat Martineau static void l2cap_logical_finish_create(struct l2cap_chan *chan, 46311500109bSMat Martineau struct hci_chan *hchan) 46321500109bSMat Martineau { 46331500109bSMat Martineau struct l2cap_conf_rsp rsp; 46341500109bSMat Martineau 4635336178a3SAndrei Emeltchenko chan->hs_hchan = hchan; 46361500109bSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 46371500109bSMat Martineau 463835ba9561SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0); 46391500109bSMat Martineau 46401500109bSMat Martineau if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 4641fe79c6feSAndrei Emeltchenko int err; 46421500109bSMat Martineau 46431500109bSMat Martineau set_default_fcs(chan); 46441500109bSMat Martineau 46451500109bSMat Martineau err = l2cap_ertm_init(chan); 46461500109bSMat Martineau if (err < 0) 46475e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 46481500109bSMat Martineau else 46491500109bSMat Martineau l2cap_chan_ready(chan); 46501500109bSMat Martineau } 46511500109bSMat Martineau } 46521500109bSMat Martineau 46531500109bSMat Martineau static void l2cap_logical_finish_move(struct l2cap_chan *chan, 46541500109bSMat Martineau struct hci_chan *hchan) 46551500109bSMat Martineau { 46561500109bSMat Martineau chan->hs_hcon = hchan->conn; 46571500109bSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 46581500109bSMat Martineau 46591500109bSMat Martineau BT_DBG("move_state %d", chan->move_state); 46601500109bSMat Martineau 46611500109bSMat Martineau switch (chan->move_state) { 46621500109bSMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_COMP: 46631500109bSMat Martineau /* Move confirm will be sent after a success 46641500109bSMat Martineau * response is received 46651500109bSMat Martineau */ 46661500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 46671500109bSMat Martineau break; 46681500109bSMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_CFM: 46691500109bSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 46701500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 46711500109bSMat Martineau } else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { 46721500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; 46731500109bSMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 46741500109bSMat Martineau } else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { 46751500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 46761500109bSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); 46771500109bSMat Martineau } 46781500109bSMat Martineau break; 46791500109bSMat Martineau default: 46801500109bSMat Martineau /* Move was not in expected state, free the channel */ 46811500109bSMat Martineau __release_logical_link(chan); 46821500109bSMat Martineau 46831500109bSMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 46841500109bSMat Martineau } 46851500109bSMat Martineau } 46861500109bSMat Martineau 46871500109bSMat Martineau /* Call with chan locked */ 468827695fb4SAndrei Emeltchenko void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan, 46895b155ef9SMat Martineau u8 status) 46905b155ef9SMat Martineau { 46911500109bSMat Martineau BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status); 46921500109bSMat Martineau 46931500109bSMat Martineau if (status) { 46941500109bSMat Martineau l2cap_logical_fail(chan); 46951500109bSMat Martineau __release_logical_link(chan); 46965b155ef9SMat Martineau return; 46975b155ef9SMat Martineau } 46985b155ef9SMat Martineau 46991500109bSMat Martineau if (chan->state != BT_CONNECTED) { 47001500109bSMat Martineau /* Ignore logical link if channel is on BR/EDR */ 47016ed971caSMarcel Holtmann if (chan->local_amp_id != AMP_ID_BREDR) 47021500109bSMat Martineau l2cap_logical_finish_create(chan, hchan); 47031500109bSMat Martineau } else { 47041500109bSMat Martineau l2cap_logical_finish_move(chan, hchan); 47051500109bSMat Martineau } 47061500109bSMat Martineau } 47071500109bSMat Martineau 47083f7a56c4SMat Martineau void l2cap_move_start(struct l2cap_chan *chan) 47093f7a56c4SMat Martineau { 47103f7a56c4SMat Martineau BT_DBG("chan %p", chan); 47113f7a56c4SMat Martineau 47126ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR) { 47133f7a56c4SMat Martineau if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED) 47143f7a56c4SMat Martineau return; 47153f7a56c4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; 47163f7a56c4SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_PREPARE; 47173f7a56c4SMat Martineau /* Placeholder - start physical link setup */ 47183f7a56c4SMat Martineau } else { 47193f7a56c4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; 47203f7a56c4SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 47213f7a56c4SMat Martineau chan->move_id = 0; 47223f7a56c4SMat Martineau l2cap_move_setup(chan); 47233f7a56c4SMat Martineau l2cap_send_move_chan_req(chan, 0); 47243f7a56c4SMat Martineau } 47253f7a56c4SMat Martineau } 47263f7a56c4SMat Martineau 47278eb200bdSMat Martineau static void l2cap_do_create(struct l2cap_chan *chan, int result, 47288eb200bdSMat Martineau u8 local_amp_id, u8 remote_amp_id) 47298eb200bdSMat Martineau { 473062748ca1SAndrei Emeltchenko BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state), 473162748ca1SAndrei Emeltchenko local_amp_id, remote_amp_id); 473262748ca1SAndrei Emeltchenko 473312d6cc60SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 473412d6cc60SAndrei Emeltchenko 473562748ca1SAndrei Emeltchenko /* Outgoing channel on AMP */ 473662748ca1SAndrei Emeltchenko if (chan->state == BT_CONNECT) { 473762748ca1SAndrei Emeltchenko if (result == L2CAP_CR_SUCCESS) { 473862748ca1SAndrei Emeltchenko chan->local_amp_id = local_amp_id; 473962748ca1SAndrei Emeltchenko l2cap_send_create_chan_req(chan, remote_amp_id); 474062748ca1SAndrei Emeltchenko } else { 474162748ca1SAndrei Emeltchenko /* Revert to BR/EDR connect */ 474262748ca1SAndrei Emeltchenko l2cap_send_conn_req(chan); 474362748ca1SAndrei Emeltchenko } 474462748ca1SAndrei Emeltchenko 474562748ca1SAndrei Emeltchenko return; 474662748ca1SAndrei Emeltchenko } 474762748ca1SAndrei Emeltchenko 474862748ca1SAndrei Emeltchenko /* Incoming channel on AMP */ 474962748ca1SAndrei Emeltchenko if (__l2cap_no_conn_pending(chan)) { 47508eb200bdSMat Martineau struct l2cap_conn_rsp rsp; 47518eb200bdSMat Martineau char buf[128]; 47528eb200bdSMat Martineau rsp.scid = cpu_to_le16(chan->dcid); 47538eb200bdSMat Martineau rsp.dcid = cpu_to_le16(chan->scid); 47548eb200bdSMat Martineau 47558eb200bdSMat Martineau if (result == L2CAP_CR_SUCCESS) { 47568eb200bdSMat Martineau /* Send successful response */ 4757dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 4758dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 47598eb200bdSMat Martineau } else { 47608eb200bdSMat Martineau /* Send negative response */ 4761dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CR_NO_MEM); 4762dcf4adbfSJoe Perches rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 47638eb200bdSMat Martineau } 47648eb200bdSMat Martineau 47658eb200bdSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP, 47668eb200bdSMat Martineau sizeof(rsp), &rsp); 47678eb200bdSMat Martineau 47688eb200bdSMat Martineau if (result == L2CAP_CR_SUCCESS) { 4769f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 47708eb200bdSMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 47718eb200bdSMat Martineau l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn), 47728eb200bdSMat Martineau L2CAP_CONF_REQ, 47738eb200bdSMat Martineau l2cap_build_conf_req(chan, buf), buf); 47748eb200bdSMat Martineau chan->num_conf_req++; 47758eb200bdSMat Martineau } 47768eb200bdSMat Martineau } 47778eb200bdSMat Martineau } 47788eb200bdSMat Martineau 47798eb200bdSMat Martineau static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id, 47808eb200bdSMat Martineau u8 remote_amp_id) 47818eb200bdSMat Martineau { 47828eb200bdSMat Martineau l2cap_move_setup(chan); 47838eb200bdSMat Martineau chan->move_id = local_amp_id; 47848eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP; 47858eb200bdSMat Martineau 47868eb200bdSMat Martineau l2cap_send_move_chan_req(chan, remote_amp_id); 47878eb200bdSMat Martineau } 47888eb200bdSMat Martineau 47898eb200bdSMat Martineau static void l2cap_do_move_respond(struct l2cap_chan *chan, int result) 47908eb200bdSMat Martineau { 47918eb200bdSMat Martineau struct hci_chan *hchan = NULL; 47928eb200bdSMat Martineau 47938eb200bdSMat Martineau /* Placeholder - get hci_chan for logical link */ 47948eb200bdSMat Martineau 47958eb200bdSMat Martineau if (hchan) { 47968eb200bdSMat Martineau if (hchan->state == BT_CONNECTED) { 47978eb200bdSMat Martineau /* Logical link is ready to go */ 47988eb200bdSMat Martineau chan->hs_hcon = hchan->conn; 47998eb200bdSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 48008eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 48018eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); 48028eb200bdSMat Martineau 48038eb200bdSMat Martineau l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); 48048eb200bdSMat Martineau } else { 48058eb200bdSMat Martineau /* Wait for logical link to be ready */ 48068eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 48078eb200bdSMat Martineau } 48088eb200bdSMat Martineau } else { 48098eb200bdSMat Martineau /* Logical link not available */ 48108eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED); 48118eb200bdSMat Martineau } 48128eb200bdSMat Martineau } 48138eb200bdSMat Martineau 48148eb200bdSMat Martineau static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result) 48158eb200bdSMat Martineau { 48168eb200bdSMat Martineau if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { 48178eb200bdSMat Martineau u8 rsp_result; 48188eb200bdSMat Martineau if (result == -EINVAL) 48198eb200bdSMat Martineau rsp_result = L2CAP_MR_BAD_ID; 48208eb200bdSMat Martineau else 48218eb200bdSMat Martineau rsp_result = L2CAP_MR_NOT_ALLOWED; 48228eb200bdSMat Martineau 48238eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, rsp_result); 48248eb200bdSMat Martineau } 48258eb200bdSMat Martineau 48268eb200bdSMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 48278eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 48288eb200bdSMat Martineau 48298eb200bdSMat Martineau /* Restart data transmission */ 48308eb200bdSMat Martineau l2cap_ertm_send(chan); 48318eb200bdSMat Martineau } 48328eb200bdSMat Martineau 4833a514b17fSAndrei Emeltchenko /* Invoke with locked chan */ 4834a514b17fSAndrei Emeltchenko void __l2cap_physical_cfm(struct l2cap_chan *chan, int result) 48358eb200bdSMat Martineau { 4836770bfefaSAndrei Emeltchenko u8 local_amp_id = chan->local_amp_id; 4837fffadc08SAndrei Emeltchenko u8 remote_amp_id = chan->remote_amp_id; 4838770bfefaSAndrei Emeltchenko 48398eb200bdSMat Martineau BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d", 48408eb200bdSMat Martineau chan, result, local_amp_id, remote_amp_id); 48418eb200bdSMat Martineau 48428eb200bdSMat Martineau if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) { 48438eb200bdSMat Martineau l2cap_chan_unlock(chan); 48448eb200bdSMat Martineau return; 48458eb200bdSMat Martineau } 48468eb200bdSMat Martineau 48478eb200bdSMat Martineau if (chan->state != BT_CONNECTED) { 48488eb200bdSMat Martineau l2cap_do_create(chan, result, local_amp_id, remote_amp_id); 48498eb200bdSMat Martineau } else if (result != L2CAP_MR_SUCCESS) { 48508eb200bdSMat Martineau l2cap_do_move_cancel(chan, result); 48518eb200bdSMat Martineau } else { 48528eb200bdSMat Martineau switch (chan->move_role) { 48538eb200bdSMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 48548eb200bdSMat Martineau l2cap_do_move_initiate(chan, local_amp_id, 48558eb200bdSMat Martineau remote_amp_id); 48568eb200bdSMat Martineau break; 48578eb200bdSMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 48588eb200bdSMat Martineau l2cap_do_move_respond(chan, result); 48598eb200bdSMat Martineau break; 48608eb200bdSMat Martineau default: 48618eb200bdSMat Martineau l2cap_do_move_cancel(chan, result); 48628eb200bdSMat Martineau break; 48638eb200bdSMat Martineau } 48648eb200bdSMat Martineau } 48658eb200bdSMat Martineau } 48668eb200bdSMat Martineau 48678d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn, 4868ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 4869ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 48708d5a04a1SMat Martineau { 48718d5a04a1SMat Martineau struct l2cap_move_chan_req *req = data; 48721500109bSMat Martineau struct l2cap_move_chan_rsp rsp; 487302b0fbb9SMat Martineau struct l2cap_chan *chan; 48748d5a04a1SMat Martineau u16 icid = 0; 48758d5a04a1SMat Martineau u16 result = L2CAP_MR_NOT_ALLOWED; 48768d5a04a1SMat Martineau 48778d5a04a1SMat Martineau if (cmd_len != sizeof(*req)) 48788d5a04a1SMat Martineau return -EPROTO; 48798d5a04a1SMat Martineau 48808d5a04a1SMat Martineau icid = le16_to_cpu(req->icid); 48818d5a04a1SMat Martineau 4882ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id); 48838d5a04a1SMat Martineau 48840bd49fc7SJohan Hedberg if (!(conn->local_fixed_chan & L2CAP_FC_A2MP)) 48858d5a04a1SMat Martineau return -EINVAL; 48868d5a04a1SMat Martineau 488702b0fbb9SMat Martineau chan = l2cap_get_chan_by_dcid(conn, icid); 488802b0fbb9SMat Martineau if (!chan) { 48891500109bSMat Martineau rsp.icid = cpu_to_le16(icid); 4890dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_MR_NOT_ALLOWED); 48911500109bSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP, 48921500109bSMat Martineau sizeof(rsp), &rsp); 489302b0fbb9SMat Martineau return 0; 489402b0fbb9SMat Martineau } 489502b0fbb9SMat Martineau 48961500109bSMat Martineau chan->ident = cmd->ident; 48971500109bSMat Martineau 489802b0fbb9SMat Martineau if (chan->scid < L2CAP_CID_DYN_START || 489902b0fbb9SMat Martineau chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY || 490002b0fbb9SMat Martineau (chan->mode != L2CAP_MODE_ERTM && 490102b0fbb9SMat Martineau chan->mode != L2CAP_MODE_STREAMING)) { 490202b0fbb9SMat Martineau result = L2CAP_MR_NOT_ALLOWED; 490302b0fbb9SMat Martineau goto send_move_response; 490402b0fbb9SMat Martineau } 490502b0fbb9SMat Martineau 490602b0fbb9SMat Martineau if (chan->local_amp_id == req->dest_amp_id) { 490702b0fbb9SMat Martineau result = L2CAP_MR_SAME_ID; 490802b0fbb9SMat Martineau goto send_move_response; 490902b0fbb9SMat Martineau } 491002b0fbb9SMat Martineau 49116ed971caSMarcel Holtmann if (req->dest_amp_id != AMP_ID_BREDR) { 491202b0fbb9SMat Martineau struct hci_dev *hdev; 491302b0fbb9SMat Martineau hdev = hci_dev_get(req->dest_amp_id); 491402b0fbb9SMat Martineau if (!hdev || hdev->dev_type != HCI_AMP || 491502b0fbb9SMat Martineau !test_bit(HCI_UP, &hdev->flags)) { 491602b0fbb9SMat Martineau if (hdev) 491702b0fbb9SMat Martineau hci_dev_put(hdev); 491802b0fbb9SMat Martineau 491902b0fbb9SMat Martineau result = L2CAP_MR_BAD_ID; 492002b0fbb9SMat Martineau goto send_move_response; 492102b0fbb9SMat Martineau } 492202b0fbb9SMat Martineau hci_dev_put(hdev); 492302b0fbb9SMat Martineau } 492402b0fbb9SMat Martineau 492502b0fbb9SMat Martineau /* Detect a move collision. Only send a collision response 492602b0fbb9SMat Martineau * if this side has "lost", otherwise proceed with the move. 492702b0fbb9SMat Martineau * The winner has the larger bd_addr. 492802b0fbb9SMat Martineau */ 492902b0fbb9SMat Martineau if ((__chan_is_moving(chan) || 493002b0fbb9SMat Martineau chan->move_role != L2CAP_MOVE_ROLE_NONE) && 49316f59b904SMarcel Holtmann bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) { 493202b0fbb9SMat Martineau result = L2CAP_MR_COLLISION; 493302b0fbb9SMat Martineau goto send_move_response; 493402b0fbb9SMat Martineau } 493502b0fbb9SMat Martineau 493602b0fbb9SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; 493702b0fbb9SMat Martineau l2cap_move_setup(chan); 493802b0fbb9SMat Martineau chan->move_id = req->dest_amp_id; 493902b0fbb9SMat Martineau icid = chan->dcid; 494002b0fbb9SMat Martineau 49416ed971caSMarcel Holtmann if (req->dest_amp_id == AMP_ID_BREDR) { 494202b0fbb9SMat Martineau /* Moving to BR/EDR */ 494302b0fbb9SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 494402b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 494502b0fbb9SMat Martineau result = L2CAP_MR_PEND; 494602b0fbb9SMat Martineau } else { 494702b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 494802b0fbb9SMat Martineau result = L2CAP_MR_SUCCESS; 494902b0fbb9SMat Martineau } 495002b0fbb9SMat Martineau } else { 495102b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_PREPARE; 495202b0fbb9SMat Martineau /* Placeholder - uncomment when amp functions are available */ 495302b0fbb9SMat Martineau /*amp_accept_physical(chan, req->dest_amp_id);*/ 495402b0fbb9SMat Martineau result = L2CAP_MR_PEND; 495502b0fbb9SMat Martineau } 495602b0fbb9SMat Martineau 495702b0fbb9SMat Martineau send_move_response: 49581500109bSMat Martineau l2cap_send_move_chan_rsp(chan, result); 49598d5a04a1SMat Martineau 496002b0fbb9SMat Martineau l2cap_chan_unlock(chan); 496102b0fbb9SMat Martineau 49628d5a04a1SMat Martineau return 0; 49638d5a04a1SMat Martineau } 49648d5a04a1SMat Martineau 49655b155ef9SMat Martineau static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result) 49665b155ef9SMat Martineau { 49675b155ef9SMat Martineau struct l2cap_chan *chan; 49685b155ef9SMat Martineau struct hci_chan *hchan = NULL; 49695b155ef9SMat Martineau 49705b155ef9SMat Martineau chan = l2cap_get_chan_by_scid(conn, icid); 49715b155ef9SMat Martineau if (!chan) { 49725b155ef9SMat Martineau l2cap_send_move_chan_cfm_icid(conn, icid); 49735b155ef9SMat Martineau return; 49745b155ef9SMat Martineau } 49755b155ef9SMat Martineau 49765b155ef9SMat Martineau __clear_chan_timer(chan); 49775b155ef9SMat Martineau if (result == L2CAP_MR_PEND) 49785b155ef9SMat Martineau __set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT); 49795b155ef9SMat Martineau 49805b155ef9SMat Martineau switch (chan->move_state) { 49815b155ef9SMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_COMP: 49825b155ef9SMat Martineau /* Move confirm will be sent when logical link 49835b155ef9SMat Martineau * is complete. 49845b155ef9SMat Martineau */ 49855b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 49865b155ef9SMat Martineau break; 49875b155ef9SMat Martineau case L2CAP_MOVE_WAIT_RSP_SUCCESS: 49885b155ef9SMat Martineau if (result == L2CAP_MR_PEND) { 49895b155ef9SMat Martineau break; 49905b155ef9SMat Martineau } else if (test_bit(CONN_LOCAL_BUSY, 49915b155ef9SMat Martineau &chan->conn_state)) { 49925b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 49935b155ef9SMat Martineau } else { 49945b155ef9SMat Martineau /* Logical link is up or moving to BR/EDR, 49955b155ef9SMat Martineau * proceed with move 49965b155ef9SMat Martineau */ 49975b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; 49985b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 49995b155ef9SMat Martineau } 50005b155ef9SMat Martineau break; 50015b155ef9SMat Martineau case L2CAP_MOVE_WAIT_RSP: 50025b155ef9SMat Martineau /* Moving to AMP */ 50035b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS) { 50045b155ef9SMat Martineau /* Remote is ready, send confirm immediately 50055b155ef9SMat Martineau * after logical link is ready 50065b155ef9SMat Martineau */ 50075b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 50085b155ef9SMat Martineau } else { 50095b155ef9SMat Martineau /* Both logical link and move success 50105b155ef9SMat Martineau * are required to confirm 50115b155ef9SMat Martineau */ 50125b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP; 50135b155ef9SMat Martineau } 50145b155ef9SMat Martineau 50155b155ef9SMat Martineau /* Placeholder - get hci_chan for logical link */ 50165b155ef9SMat Martineau if (!hchan) { 50175b155ef9SMat Martineau /* Logical link not available */ 50185b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 50195b155ef9SMat Martineau break; 50205b155ef9SMat Martineau } 50215b155ef9SMat Martineau 50225b155ef9SMat Martineau /* If the logical link is not yet connected, do not 50235b155ef9SMat Martineau * send confirmation. 50245b155ef9SMat Martineau */ 50255b155ef9SMat Martineau if (hchan->state != BT_CONNECTED) 50265b155ef9SMat Martineau break; 50275b155ef9SMat Martineau 50285b155ef9SMat Martineau /* Logical link is already ready to go */ 50295b155ef9SMat Martineau 50305b155ef9SMat Martineau chan->hs_hcon = hchan->conn; 50315b155ef9SMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 50325b155ef9SMat Martineau 50335b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS) { 50345b155ef9SMat Martineau /* Can confirm now */ 50355b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 50365b155ef9SMat Martineau } else { 50375b155ef9SMat Martineau /* Now only need move success 50385b155ef9SMat Martineau * to confirm 50395b155ef9SMat Martineau */ 50405b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 50415b155ef9SMat Martineau } 50425b155ef9SMat Martineau 50435b155ef9SMat Martineau l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); 50445b155ef9SMat Martineau break; 50455b155ef9SMat Martineau default: 50465b155ef9SMat Martineau /* Any other amp move state means the move failed. */ 50475b155ef9SMat Martineau chan->move_id = chan->local_amp_id; 50485b155ef9SMat Martineau l2cap_move_done(chan); 50495b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 50505b155ef9SMat Martineau } 50515b155ef9SMat Martineau 50525b155ef9SMat Martineau l2cap_chan_unlock(chan); 50535b155ef9SMat Martineau } 50545b155ef9SMat Martineau 50555b155ef9SMat Martineau static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid, 50565b155ef9SMat Martineau u16 result) 50575b155ef9SMat Martineau { 50585b155ef9SMat Martineau struct l2cap_chan *chan; 50595b155ef9SMat Martineau 50605b155ef9SMat Martineau chan = l2cap_get_chan_by_ident(conn, ident); 50615b155ef9SMat Martineau if (!chan) { 50625b155ef9SMat Martineau /* Could not locate channel, icid is best guess */ 50635b155ef9SMat Martineau l2cap_send_move_chan_cfm_icid(conn, icid); 50645b155ef9SMat Martineau return; 50655b155ef9SMat Martineau } 50665b155ef9SMat Martineau 50675b155ef9SMat Martineau __clear_chan_timer(chan); 50685b155ef9SMat Martineau 50695b155ef9SMat Martineau if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { 50705b155ef9SMat Martineau if (result == L2CAP_MR_COLLISION) { 50715b155ef9SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; 50725b155ef9SMat Martineau } else { 50735b155ef9SMat Martineau /* Cleanup - cancel move */ 50745b155ef9SMat Martineau chan->move_id = chan->local_amp_id; 50755b155ef9SMat Martineau l2cap_move_done(chan); 50765b155ef9SMat Martineau } 50775b155ef9SMat Martineau } 50785b155ef9SMat Martineau 50795b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 50805b155ef9SMat Martineau 50815b155ef9SMat Martineau l2cap_chan_unlock(chan); 50825b155ef9SMat Martineau } 50835b155ef9SMat Martineau 50845b155ef9SMat Martineau static int l2cap_move_channel_rsp(struct l2cap_conn *conn, 5085ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5086ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 50878d5a04a1SMat Martineau { 50888d5a04a1SMat Martineau struct l2cap_move_chan_rsp *rsp = data; 50898d5a04a1SMat Martineau u16 icid, result; 50908d5a04a1SMat Martineau 50918d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 50928d5a04a1SMat Martineau return -EPROTO; 50938d5a04a1SMat Martineau 50948d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 50958d5a04a1SMat Martineau result = le16_to_cpu(rsp->result); 50968d5a04a1SMat Martineau 5097ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 50988d5a04a1SMat Martineau 50995b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND) 51005b155ef9SMat Martineau l2cap_move_continue(conn, icid, result); 51015b155ef9SMat Martineau else 51025b155ef9SMat Martineau l2cap_move_fail(conn, cmd->ident, icid, result); 51038d5a04a1SMat Martineau 51048d5a04a1SMat Martineau return 0; 51058d5a04a1SMat Martineau } 51068d5a04a1SMat Martineau 51075f3847a4SMat Martineau static int l2cap_move_channel_confirm(struct l2cap_conn *conn, 5108ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5109ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 51108d5a04a1SMat Martineau { 51118d5a04a1SMat Martineau struct l2cap_move_chan_cfm *cfm = data; 51125f3847a4SMat Martineau struct l2cap_chan *chan; 51138d5a04a1SMat Martineau u16 icid, result; 51148d5a04a1SMat Martineau 51158d5a04a1SMat Martineau if (cmd_len != sizeof(*cfm)) 51168d5a04a1SMat Martineau return -EPROTO; 51178d5a04a1SMat Martineau 51188d5a04a1SMat Martineau icid = le16_to_cpu(cfm->icid); 51198d5a04a1SMat Martineau result = le16_to_cpu(cfm->result); 51208d5a04a1SMat Martineau 5121ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 51228d5a04a1SMat Martineau 51235f3847a4SMat Martineau chan = l2cap_get_chan_by_dcid(conn, icid); 51245f3847a4SMat Martineau if (!chan) { 51255f3847a4SMat Martineau /* Spec requires a response even if the icid was not found */ 51268d5a04a1SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 51275f3847a4SMat Martineau return 0; 51285f3847a4SMat Martineau } 51295f3847a4SMat Martineau 51305f3847a4SMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) { 51315f3847a4SMat Martineau if (result == L2CAP_MC_CONFIRMED) { 51325f3847a4SMat Martineau chan->local_amp_id = chan->move_id; 51336ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR) 51345f3847a4SMat Martineau __release_logical_link(chan); 51355f3847a4SMat Martineau } else { 51365f3847a4SMat Martineau chan->move_id = chan->local_amp_id; 51375f3847a4SMat Martineau } 51385f3847a4SMat Martineau 51395f3847a4SMat Martineau l2cap_move_done(chan); 51405f3847a4SMat Martineau } 51415f3847a4SMat Martineau 51425f3847a4SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 51435f3847a4SMat Martineau 51445f3847a4SMat Martineau l2cap_chan_unlock(chan); 51458d5a04a1SMat Martineau 51468d5a04a1SMat Martineau return 0; 51478d5a04a1SMat Martineau } 51488d5a04a1SMat Martineau 51498d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, 5150ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5151ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 51528d5a04a1SMat Martineau { 51538d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp *rsp = data; 51543fd71a0aSMat Martineau struct l2cap_chan *chan; 51558d5a04a1SMat Martineau u16 icid; 51568d5a04a1SMat Martineau 51578d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 51588d5a04a1SMat Martineau return -EPROTO; 51598d5a04a1SMat Martineau 51608d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 51618d5a04a1SMat Martineau 5162ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 51638d5a04a1SMat Martineau 51643fd71a0aSMat Martineau chan = l2cap_get_chan_by_scid(conn, icid); 51653fd71a0aSMat Martineau if (!chan) 51663fd71a0aSMat Martineau return 0; 51673fd71a0aSMat Martineau 51683fd71a0aSMat Martineau __clear_chan_timer(chan); 51693fd71a0aSMat Martineau 51703fd71a0aSMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) { 51713fd71a0aSMat Martineau chan->local_amp_id = chan->move_id; 51723fd71a0aSMat Martineau 51736ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan) 51743fd71a0aSMat Martineau __release_logical_link(chan); 51753fd71a0aSMat Martineau 51763fd71a0aSMat Martineau l2cap_move_done(chan); 51773fd71a0aSMat Martineau } 51783fd71a0aSMat Martineau 51793fd71a0aSMat Martineau l2cap_chan_unlock(chan); 51803fd71a0aSMat Martineau 51818d5a04a1SMat Martineau return 0; 51828d5a04a1SMat Martineau } 51838d5a04a1SMat Martineau 5184de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, 51852d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, 5186203e639eSJohan Hedberg u16 cmd_len, u8 *data) 5187de73115aSClaudio Takahasi { 5188de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon; 5189de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req; 5190de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp; 5191203e639eSJohan Hedberg u16 min, max, latency, to_multiplier; 51922ce603ebSClaudio Takahasi int err; 5193de73115aSClaudio Takahasi 519440bef302SJohan Hedberg if (hcon->role != HCI_ROLE_MASTER) 5195de73115aSClaudio Takahasi return -EINVAL; 5196de73115aSClaudio Takahasi 5197de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) 5198de73115aSClaudio Takahasi return -EPROTO; 5199de73115aSClaudio Takahasi 5200de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data; 5201de73115aSClaudio Takahasi min = __le16_to_cpu(req->min); 5202de73115aSClaudio Takahasi max = __le16_to_cpu(req->max); 5203de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency); 5204de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier); 5205de73115aSClaudio Takahasi 5206de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", 5207de73115aSClaudio Takahasi min, max, latency, to_multiplier); 5208de73115aSClaudio Takahasi 5209de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp)); 52102ce603ebSClaudio Takahasi 5211d4905f24SAndre Guedes err = hci_check_conn_params(min, max, latency, to_multiplier); 52122ce603ebSClaudio Takahasi if (err) 5213dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); 5214de73115aSClaudio Takahasi else 5215dcf4adbfSJoe Perches rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); 5216de73115aSClaudio Takahasi 5217de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, 5218de73115aSClaudio Takahasi sizeof(rsp), &rsp); 5219de73115aSClaudio Takahasi 5220ffb5a827SAndre Guedes if (!err) { 5221f4869e2aSJohan Hedberg u8 store_hint; 5222ffb5a827SAndre Guedes 5223f4869e2aSJohan Hedberg store_hint = hci_le_conn_update(hcon, min, max, latency, 5224f4869e2aSJohan Hedberg to_multiplier); 5225f4869e2aSJohan Hedberg mgmt_new_conn_param(hcon->hdev, &hcon->dst, hcon->dst_type, 5226f4869e2aSJohan Hedberg store_hint, min, max, latency, 5227f4869e2aSJohan Hedberg to_multiplier); 5228f4869e2aSJohan Hedberg 5229ffb5a827SAndre Guedes } 52302ce603ebSClaudio Takahasi 5231de73115aSClaudio Takahasi return 0; 5232de73115aSClaudio Takahasi } 5233de73115aSClaudio Takahasi 5234f1496deeSJohan Hedberg static int l2cap_le_connect_rsp(struct l2cap_conn *conn, 5235f1496deeSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5236f1496deeSJohan Hedberg u8 *data) 5237f1496deeSJohan Hedberg { 5238f1496deeSJohan Hedberg struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data; 52393e64b7bdSJohan Hedberg struct hci_conn *hcon = conn->hcon; 5240f1496deeSJohan Hedberg u16 dcid, mtu, mps, credits, result; 5241f1496deeSJohan Hedberg struct l2cap_chan *chan; 52423e64b7bdSJohan Hedberg int err, sec_level; 5243f1496deeSJohan Hedberg 5244f1496deeSJohan Hedberg if (cmd_len < sizeof(*rsp)) 5245f1496deeSJohan Hedberg return -EPROTO; 5246f1496deeSJohan Hedberg 5247f1496deeSJohan Hedberg dcid = __le16_to_cpu(rsp->dcid); 5248f1496deeSJohan Hedberg mtu = __le16_to_cpu(rsp->mtu); 5249f1496deeSJohan Hedberg mps = __le16_to_cpu(rsp->mps); 5250f1496deeSJohan Hedberg credits = __le16_to_cpu(rsp->credits); 5251f1496deeSJohan Hedberg result = __le16_to_cpu(rsp->result); 5252f1496deeSJohan Hedberg 5253f1496deeSJohan Hedberg if (result == L2CAP_CR_SUCCESS && (mtu < 23 || mps < 23)) 5254f1496deeSJohan Hedberg return -EPROTO; 5255f1496deeSJohan Hedberg 5256f1496deeSJohan Hedberg BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x", 5257f1496deeSJohan Hedberg dcid, mtu, mps, credits, result); 5258f1496deeSJohan Hedberg 5259f1496deeSJohan Hedberg mutex_lock(&conn->chan_lock); 5260f1496deeSJohan Hedberg 5261f1496deeSJohan Hedberg chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 5262f1496deeSJohan Hedberg if (!chan) { 5263f1496deeSJohan Hedberg err = -EBADSLT; 5264f1496deeSJohan Hedberg goto unlock; 5265f1496deeSJohan Hedberg } 5266f1496deeSJohan Hedberg 5267f1496deeSJohan Hedberg err = 0; 5268f1496deeSJohan Hedberg 5269f1496deeSJohan Hedberg l2cap_chan_lock(chan); 5270f1496deeSJohan Hedberg 5271f1496deeSJohan Hedberg switch (result) { 5272f1496deeSJohan Hedberg case L2CAP_CR_SUCCESS: 5273f1496deeSJohan Hedberg chan->ident = 0; 5274f1496deeSJohan Hedberg chan->dcid = dcid; 5275f1496deeSJohan Hedberg chan->omtu = mtu; 5276f1496deeSJohan Hedberg chan->remote_mps = mps; 52770cd75f7eSJohan Hedberg chan->tx_credits = credits; 5278f1496deeSJohan Hedberg l2cap_chan_ready(chan); 5279f1496deeSJohan Hedberg break; 5280f1496deeSJohan Hedberg 52813e64b7bdSJohan Hedberg case L2CAP_CR_AUTHENTICATION: 52823e64b7bdSJohan Hedberg case L2CAP_CR_ENCRYPTION: 52833e64b7bdSJohan Hedberg /* If we already have MITM protection we can't do 52843e64b7bdSJohan Hedberg * anything. 52853e64b7bdSJohan Hedberg */ 52863e64b7bdSJohan Hedberg if (hcon->sec_level > BT_SECURITY_MEDIUM) { 52873e64b7bdSJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED); 52883e64b7bdSJohan Hedberg break; 52893e64b7bdSJohan Hedberg } 52903e64b7bdSJohan Hedberg 52913e64b7bdSJohan Hedberg sec_level = hcon->sec_level + 1; 52923e64b7bdSJohan Hedberg if (chan->sec_level < sec_level) 52933e64b7bdSJohan Hedberg chan->sec_level = sec_level; 52943e64b7bdSJohan Hedberg 52953e64b7bdSJohan Hedberg /* We'll need to send a new Connect Request */ 52963e64b7bdSJohan Hedberg clear_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags); 52973e64b7bdSJohan Hedberg 52983e64b7bdSJohan Hedberg smp_conn_security(hcon, chan->sec_level); 52993e64b7bdSJohan Hedberg break; 53003e64b7bdSJohan Hedberg 5301f1496deeSJohan Hedberg default: 5302f1496deeSJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED); 5303f1496deeSJohan Hedberg break; 5304f1496deeSJohan Hedberg } 5305f1496deeSJohan Hedberg 5306f1496deeSJohan Hedberg l2cap_chan_unlock(chan); 5307f1496deeSJohan Hedberg 5308f1496deeSJohan Hedberg unlock: 5309f1496deeSJohan Hedberg mutex_unlock(&conn->chan_lock); 5310f1496deeSJohan Hedberg 5311f1496deeSJohan Hedberg return err; 5312f1496deeSJohan Hedberg } 5313f1496deeSJohan Hedberg 53143300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, 53152d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len, 53162d792818SGustavo Padovan u8 *data) 53173300d9a9SClaudio Takahasi { 53183300d9a9SClaudio Takahasi int err = 0; 53193300d9a9SClaudio Takahasi 53203300d9a9SClaudio Takahasi switch (cmd->code) { 53213300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 5322cb3b3152SJohan Hedberg l2cap_command_rej(conn, cmd, cmd_len, data); 53233300d9a9SClaudio Takahasi break; 53243300d9a9SClaudio Takahasi 53253300d9a9SClaudio Takahasi case L2CAP_CONN_REQ: 5326cb3b3152SJohan Hedberg err = l2cap_connect_req(conn, cmd, cmd_len, data); 53273300d9a9SClaudio Takahasi break; 53283300d9a9SClaudio Takahasi 53293300d9a9SClaudio Takahasi case L2CAP_CONN_RSP: 5330f5a2598dSMat Martineau case L2CAP_CREATE_CHAN_RSP: 53319245e737SJohan Hedberg l2cap_connect_create_rsp(conn, cmd, cmd_len, data); 53323300d9a9SClaudio Takahasi break; 53333300d9a9SClaudio Takahasi 53343300d9a9SClaudio Takahasi case L2CAP_CONF_REQ: 53353300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data); 53363300d9a9SClaudio Takahasi break; 53373300d9a9SClaudio Takahasi 53383300d9a9SClaudio Takahasi case L2CAP_CONF_RSP: 53399245e737SJohan Hedberg l2cap_config_rsp(conn, cmd, cmd_len, data); 53403300d9a9SClaudio Takahasi break; 53413300d9a9SClaudio Takahasi 53423300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ: 5343cb3b3152SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data); 53443300d9a9SClaudio Takahasi break; 53453300d9a9SClaudio Takahasi 53463300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP: 53479245e737SJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data); 53483300d9a9SClaudio Takahasi break; 53493300d9a9SClaudio Takahasi 53503300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ: 53513300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data); 53523300d9a9SClaudio Takahasi break; 53533300d9a9SClaudio Takahasi 53543300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP: 53553300d9a9SClaudio Takahasi break; 53563300d9a9SClaudio Takahasi 53573300d9a9SClaudio Takahasi case L2CAP_INFO_REQ: 5358cb3b3152SJohan Hedberg err = l2cap_information_req(conn, cmd, cmd_len, data); 53593300d9a9SClaudio Takahasi break; 53603300d9a9SClaudio Takahasi 53613300d9a9SClaudio Takahasi case L2CAP_INFO_RSP: 53629245e737SJohan Hedberg l2cap_information_rsp(conn, cmd, cmd_len, data); 53633300d9a9SClaudio Takahasi break; 53643300d9a9SClaudio Takahasi 5365f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_REQ: 5366f94ff6ffSMat Martineau err = l2cap_create_channel_req(conn, cmd, cmd_len, data); 5367f94ff6ffSMat Martineau break; 5368f94ff6ffSMat Martineau 53698d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_REQ: 53708d5a04a1SMat Martineau err = l2cap_move_channel_req(conn, cmd, cmd_len, data); 53718d5a04a1SMat Martineau break; 53728d5a04a1SMat Martineau 53738d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_RSP: 53749245e737SJohan Hedberg l2cap_move_channel_rsp(conn, cmd, cmd_len, data); 53758d5a04a1SMat Martineau break; 53768d5a04a1SMat Martineau 53778d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM: 53788d5a04a1SMat Martineau err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data); 53798d5a04a1SMat Martineau break; 53808d5a04a1SMat Martineau 53818d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM_RSP: 53829245e737SJohan Hedberg l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data); 53838d5a04a1SMat Martineau break; 53848d5a04a1SMat Martineau 53853300d9a9SClaudio Takahasi default: 53863300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code); 53873300d9a9SClaudio Takahasi err = -EINVAL; 53883300d9a9SClaudio Takahasi break; 53893300d9a9SClaudio Takahasi } 53903300d9a9SClaudio Takahasi 53913300d9a9SClaudio Takahasi return err; 53923300d9a9SClaudio Takahasi } 53933300d9a9SClaudio Takahasi 539427e2d4c8SJohan Hedberg static int l2cap_le_connect_req(struct l2cap_conn *conn, 539527e2d4c8SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 539627e2d4c8SJohan Hedberg u8 *data) 539727e2d4c8SJohan Hedberg { 539827e2d4c8SJohan Hedberg struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data; 539927e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 540027e2d4c8SJohan Hedberg struct l2cap_chan *chan, *pchan; 54010cd75f7eSJohan Hedberg u16 dcid, scid, credits, mtu, mps; 540227e2d4c8SJohan Hedberg __le16 psm; 540327e2d4c8SJohan Hedberg u8 result; 540427e2d4c8SJohan Hedberg 540527e2d4c8SJohan Hedberg if (cmd_len != sizeof(*req)) 540627e2d4c8SJohan Hedberg return -EPROTO; 540727e2d4c8SJohan Hedberg 540827e2d4c8SJohan Hedberg scid = __le16_to_cpu(req->scid); 540927e2d4c8SJohan Hedberg mtu = __le16_to_cpu(req->mtu); 541027e2d4c8SJohan Hedberg mps = __le16_to_cpu(req->mps); 541127e2d4c8SJohan Hedberg psm = req->psm; 541227e2d4c8SJohan Hedberg dcid = 0; 54130cd75f7eSJohan Hedberg credits = 0; 541427e2d4c8SJohan Hedberg 541527e2d4c8SJohan Hedberg if (mtu < 23 || mps < 23) 541627e2d4c8SJohan Hedberg return -EPROTO; 541727e2d4c8SJohan Hedberg 541827e2d4c8SJohan Hedberg BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm), 541927e2d4c8SJohan Hedberg scid, mtu, mps); 542027e2d4c8SJohan Hedberg 542127e2d4c8SJohan Hedberg /* Check if we have socket listening on psm */ 542227e2d4c8SJohan Hedberg pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 542327e2d4c8SJohan Hedberg &conn->hcon->dst, LE_LINK); 542427e2d4c8SJohan Hedberg if (!pchan) { 542527e2d4c8SJohan Hedberg result = L2CAP_CR_BAD_PSM; 542627e2d4c8SJohan Hedberg chan = NULL; 542727e2d4c8SJohan Hedberg goto response; 542827e2d4c8SJohan Hedberg } 542927e2d4c8SJohan Hedberg 543027e2d4c8SJohan Hedberg mutex_lock(&conn->chan_lock); 543127e2d4c8SJohan Hedberg l2cap_chan_lock(pchan); 543227e2d4c8SJohan Hedberg 543335dc6f83SJohan Hedberg if (!smp_sufficient_security(conn->hcon, pchan->sec_level, 543435dc6f83SJohan Hedberg SMP_ALLOW_STK)) { 543527e2d4c8SJohan Hedberg result = L2CAP_CR_AUTHENTICATION; 543627e2d4c8SJohan Hedberg chan = NULL; 543727e2d4c8SJohan Hedberg goto response_unlock; 543827e2d4c8SJohan Hedberg } 543927e2d4c8SJohan Hedberg 544027e2d4c8SJohan Hedberg /* Check if we already have channel with that dcid */ 544127e2d4c8SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, scid)) { 544227e2d4c8SJohan Hedberg result = L2CAP_CR_NO_MEM; 544327e2d4c8SJohan Hedberg chan = NULL; 544427e2d4c8SJohan Hedberg goto response_unlock; 544527e2d4c8SJohan Hedberg } 544627e2d4c8SJohan Hedberg 544727e2d4c8SJohan Hedberg chan = pchan->ops->new_connection(pchan); 544827e2d4c8SJohan Hedberg if (!chan) { 544927e2d4c8SJohan Hedberg result = L2CAP_CR_NO_MEM; 545027e2d4c8SJohan Hedberg goto response_unlock; 545127e2d4c8SJohan Hedberg } 545227e2d4c8SJohan Hedberg 54530ce43ce6SJohan Hedberg l2cap_le_flowctl_init(chan); 54540ce43ce6SJohan Hedberg 545527e2d4c8SJohan Hedberg bacpy(&chan->src, &conn->hcon->src); 545627e2d4c8SJohan Hedberg bacpy(&chan->dst, &conn->hcon->dst); 5457a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(conn->hcon); 5458a250e048SJohan Hedberg chan->dst_type = bdaddr_dst_type(conn->hcon); 545927e2d4c8SJohan Hedberg chan->psm = psm; 546027e2d4c8SJohan Hedberg chan->dcid = scid; 546127e2d4c8SJohan Hedberg chan->omtu = mtu; 546227e2d4c8SJohan Hedberg chan->remote_mps = mps; 54630cd75f7eSJohan Hedberg chan->tx_credits = __le16_to_cpu(req->credits); 546427e2d4c8SJohan Hedberg 546527e2d4c8SJohan Hedberg __l2cap_chan_add(conn, chan); 546627e2d4c8SJohan Hedberg dcid = chan->scid; 54670cd75f7eSJohan Hedberg credits = chan->rx_credits; 546827e2d4c8SJohan Hedberg 546927e2d4c8SJohan Hedberg __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 547027e2d4c8SJohan Hedberg 547127e2d4c8SJohan Hedberg chan->ident = cmd->ident; 547227e2d4c8SJohan Hedberg 547327e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 547427e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_CONNECT2); 5475434714dcSJohan Hedberg /* The following result value is actually not defined 5476434714dcSJohan Hedberg * for LE CoC but we use it to let the function know 5477434714dcSJohan Hedberg * that it should bail out after doing its cleanup 5478434714dcSJohan Hedberg * instead of sending a response. 5479434714dcSJohan Hedberg */ 548027e2d4c8SJohan Hedberg result = L2CAP_CR_PEND; 548127e2d4c8SJohan Hedberg chan->ops->defer(chan); 548227e2d4c8SJohan Hedberg } else { 548327e2d4c8SJohan Hedberg l2cap_chan_ready(chan); 548427e2d4c8SJohan Hedberg result = L2CAP_CR_SUCCESS; 548527e2d4c8SJohan Hedberg } 548627e2d4c8SJohan Hedberg 548727e2d4c8SJohan Hedberg response_unlock: 548827e2d4c8SJohan Hedberg l2cap_chan_unlock(pchan); 548927e2d4c8SJohan Hedberg mutex_unlock(&conn->chan_lock); 5490a24cce14SJohan Hedberg l2cap_chan_put(pchan); 549127e2d4c8SJohan Hedberg 549227e2d4c8SJohan Hedberg if (result == L2CAP_CR_PEND) 549327e2d4c8SJohan Hedberg return 0; 549427e2d4c8SJohan Hedberg 549527e2d4c8SJohan Hedberg response: 549627e2d4c8SJohan Hedberg if (chan) { 549727e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 54983916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps); 549927e2d4c8SJohan Hedberg } else { 550027e2d4c8SJohan Hedberg rsp.mtu = 0; 550127e2d4c8SJohan Hedberg rsp.mps = 0; 550227e2d4c8SJohan Hedberg } 550327e2d4c8SJohan Hedberg 550427e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(dcid); 55050cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(credits); 550627e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result); 550727e2d4c8SJohan Hedberg 550827e2d4c8SJohan Hedberg l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp); 550927e2d4c8SJohan Hedberg 551027e2d4c8SJohan Hedberg return 0; 551127e2d4c8SJohan Hedberg } 551227e2d4c8SJohan Hedberg 5513fad5fc89SJohan Hedberg static inline int l2cap_le_credits(struct l2cap_conn *conn, 5514fad5fc89SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5515fad5fc89SJohan Hedberg u8 *data) 5516fad5fc89SJohan Hedberg { 5517fad5fc89SJohan Hedberg struct l2cap_le_credits *pkt; 5518fad5fc89SJohan Hedberg struct l2cap_chan *chan; 55190f1bfe4eSJohan Hedberg u16 cid, credits, max_credits; 5520fad5fc89SJohan Hedberg 5521fad5fc89SJohan Hedberg if (cmd_len != sizeof(*pkt)) 5522fad5fc89SJohan Hedberg return -EPROTO; 5523fad5fc89SJohan Hedberg 5524fad5fc89SJohan Hedberg pkt = (struct l2cap_le_credits *) data; 5525fad5fc89SJohan Hedberg cid = __le16_to_cpu(pkt->cid); 5526fad5fc89SJohan Hedberg credits = __le16_to_cpu(pkt->credits); 5527fad5fc89SJohan Hedberg 5528fad5fc89SJohan Hedberg BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits); 5529fad5fc89SJohan Hedberg 5530fad5fc89SJohan Hedberg chan = l2cap_get_chan_by_dcid(conn, cid); 5531fad5fc89SJohan Hedberg if (!chan) 5532fad5fc89SJohan Hedberg return -EBADSLT; 5533fad5fc89SJohan Hedberg 55340f1bfe4eSJohan Hedberg max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits; 55350f1bfe4eSJohan Hedberg if (credits > max_credits) { 55360f1bfe4eSJohan Hedberg BT_ERR("LE credits overflow"); 55370f1bfe4eSJohan Hedberg l2cap_send_disconn_req(chan, ECONNRESET); 5538ee93053dSMartin Townsend l2cap_chan_unlock(chan); 55390f1bfe4eSJohan Hedberg 55400f1bfe4eSJohan Hedberg /* Return 0 so that we don't trigger an unnecessary 55410f1bfe4eSJohan Hedberg * command reject packet. 55420f1bfe4eSJohan Hedberg */ 55430f1bfe4eSJohan Hedberg return 0; 55440f1bfe4eSJohan Hedberg } 55450f1bfe4eSJohan Hedberg 5546fad5fc89SJohan Hedberg chan->tx_credits += credits; 5547fad5fc89SJohan Hedberg 5548fad5fc89SJohan Hedberg while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) { 5549fad5fc89SJohan Hedberg l2cap_do_send(chan, skb_dequeue(&chan->tx_q)); 5550fad5fc89SJohan Hedberg chan->tx_credits--; 5551fad5fc89SJohan Hedberg } 5552fad5fc89SJohan Hedberg 5553fad5fc89SJohan Hedberg if (chan->tx_credits) 5554fad5fc89SJohan Hedberg chan->ops->resume(chan); 5555fad5fc89SJohan Hedberg 5556fad5fc89SJohan Hedberg l2cap_chan_unlock(chan); 5557fad5fc89SJohan Hedberg 5558fad5fc89SJohan Hedberg return 0; 5559fad5fc89SJohan Hedberg } 5560fad5fc89SJohan Hedberg 556171fb4197SJohan Hedberg static inline int l2cap_le_command_rej(struct l2cap_conn *conn, 556271fb4197SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 556371fb4197SJohan Hedberg u8 *data) 556471fb4197SJohan Hedberg { 556571fb4197SJohan Hedberg struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 556671fb4197SJohan Hedberg struct l2cap_chan *chan; 556771fb4197SJohan Hedberg 556871fb4197SJohan Hedberg if (cmd_len < sizeof(*rej)) 556971fb4197SJohan Hedberg return -EPROTO; 557071fb4197SJohan Hedberg 557171fb4197SJohan Hedberg mutex_lock(&conn->chan_lock); 557271fb4197SJohan Hedberg 557371fb4197SJohan Hedberg chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 557471fb4197SJohan Hedberg if (!chan) 557571fb4197SJohan Hedberg goto done; 557671fb4197SJohan Hedberg 557771fb4197SJohan Hedberg l2cap_chan_lock(chan); 557871fb4197SJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED); 557971fb4197SJohan Hedberg l2cap_chan_unlock(chan); 558071fb4197SJohan Hedberg 558171fb4197SJohan Hedberg done: 558271fb4197SJohan Hedberg mutex_unlock(&conn->chan_lock); 558371fb4197SJohan Hedberg return 0; 558471fb4197SJohan Hedberg } 558571fb4197SJohan Hedberg 55863300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, 5587203e639eSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5588203e639eSJohan Hedberg u8 *data) 55893300d9a9SClaudio Takahasi { 5590b5ecba64SJohan Hedberg int err = 0; 5591b5ecba64SJohan Hedberg 55923300d9a9SClaudio Takahasi switch (cmd->code) { 55933300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 559471fb4197SJohan Hedberg l2cap_le_command_rej(conn, cmd, cmd_len, data); 5595b5ecba64SJohan Hedberg break; 55963300d9a9SClaudio Takahasi 55973300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ: 5598b5ecba64SJohan Hedberg err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data); 5599b5ecba64SJohan Hedberg break; 56003300d9a9SClaudio Takahasi 56013300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP: 5602b5ecba64SJohan Hedberg break; 56033300d9a9SClaudio Takahasi 5604f1496deeSJohan Hedberg case L2CAP_LE_CONN_RSP: 5605f1496deeSJohan Hedberg l2cap_le_connect_rsp(conn, cmd, cmd_len, data); 5606b5ecba64SJohan Hedberg break; 5607f1496deeSJohan Hedberg 560827e2d4c8SJohan Hedberg case L2CAP_LE_CONN_REQ: 5609b5ecba64SJohan Hedberg err = l2cap_le_connect_req(conn, cmd, cmd_len, data); 5610b5ecba64SJohan Hedberg break; 561127e2d4c8SJohan Hedberg 5612fad5fc89SJohan Hedberg case L2CAP_LE_CREDITS: 5613fad5fc89SJohan Hedberg err = l2cap_le_credits(conn, cmd, cmd_len, data); 5614fad5fc89SJohan Hedberg break; 5615fad5fc89SJohan Hedberg 56163defe01aSJohan Hedberg case L2CAP_DISCONN_REQ: 5617b5ecba64SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data); 5618b5ecba64SJohan Hedberg break; 56193defe01aSJohan Hedberg 56203defe01aSJohan Hedberg case L2CAP_DISCONN_RSP: 56213defe01aSJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data); 5622b5ecba64SJohan Hedberg break; 56233defe01aSJohan Hedberg 56243300d9a9SClaudio Takahasi default: 56253300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code); 5626b5ecba64SJohan Hedberg err = -EINVAL; 5627b5ecba64SJohan Hedberg break; 56283300d9a9SClaudio Takahasi } 5629b5ecba64SJohan Hedberg 5630b5ecba64SJohan Hedberg return err; 56313300d9a9SClaudio Takahasi } 56323300d9a9SClaudio Takahasi 5633c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn, 5634c5623556SJohan Hedberg struct sk_buff *skb) 5635c5623556SJohan Hedberg { 563669c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon; 56374f3e219dSMarcel Holtmann struct l2cap_cmd_hdr *cmd; 56384f3e219dSMarcel Holtmann u16 len; 5639c5623556SJohan Hedberg int err; 5640c5623556SJohan Hedberg 564169c4e4e8SJohan Hedberg if (hcon->type != LE_LINK) 56423b166295SMarcel Holtmann goto drop; 564369c4e4e8SJohan Hedberg 56444f3e219dSMarcel Holtmann if (skb->len < L2CAP_CMD_HDR_SIZE) 56454f3e219dSMarcel Holtmann goto drop; 5646c5623556SJohan Hedberg 56474f3e219dSMarcel Holtmann cmd = (void *) skb->data; 56484f3e219dSMarcel Holtmann skb_pull(skb, L2CAP_CMD_HDR_SIZE); 5649c5623556SJohan Hedberg 56504f3e219dSMarcel Holtmann len = le16_to_cpu(cmd->len); 5651c5623556SJohan Hedberg 56524f3e219dSMarcel Holtmann BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident); 56534f3e219dSMarcel Holtmann 56544f3e219dSMarcel Holtmann if (len != skb->len || !cmd->ident) { 5655c5623556SJohan Hedberg BT_DBG("corrupted command"); 56564f3e219dSMarcel Holtmann goto drop; 5657c5623556SJohan Hedberg } 5658c5623556SJohan Hedberg 5659203e639eSJohan Hedberg err = l2cap_le_sig_cmd(conn, cmd, len, skb->data); 5660c5623556SJohan Hedberg if (err) { 5661c5623556SJohan Hedberg struct l2cap_cmd_rej_unk rej; 5662c5623556SJohan Hedberg 5663c5623556SJohan Hedberg BT_ERR("Wrong link type (%d)", err); 5664c5623556SJohan Hedberg 5665dcf4adbfSJoe Perches rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 56664f3e219dSMarcel Holtmann l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 5667c5623556SJohan Hedberg sizeof(rej), &rej); 5668c5623556SJohan Hedberg } 5669c5623556SJohan Hedberg 56703b166295SMarcel Holtmann drop: 5671c5623556SJohan Hedberg kfree_skb(skb); 5672c5623556SJohan Hedberg } 5673c5623556SJohan Hedberg 56743300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn, 56753300d9a9SClaudio Takahasi struct sk_buff *skb) 56760a708f8fSGustavo F. Padovan { 567769c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon; 56780a708f8fSGustavo F. Padovan u8 *data = skb->data; 56790a708f8fSGustavo F. Padovan int len = skb->len; 56800a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr cmd; 56813300d9a9SClaudio Takahasi int err; 56820a708f8fSGustavo F. Padovan 56830a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb); 56840a708f8fSGustavo F. Padovan 568569c4e4e8SJohan Hedberg if (hcon->type != ACL_LINK) 56863b166295SMarcel Holtmann goto drop; 568769c4e4e8SJohan Hedberg 56880a708f8fSGustavo F. Padovan while (len >= L2CAP_CMD_HDR_SIZE) { 56890a708f8fSGustavo F. Padovan u16 cmd_len; 56900a708f8fSGustavo F. Padovan memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); 56910a708f8fSGustavo F. Padovan data += L2CAP_CMD_HDR_SIZE; 56920a708f8fSGustavo F. Padovan len -= L2CAP_CMD_HDR_SIZE; 56930a708f8fSGustavo F. Padovan 56940a708f8fSGustavo F. Padovan cmd_len = le16_to_cpu(cmd.len); 56950a708f8fSGustavo F. Padovan 56962d792818SGustavo Padovan BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, 56972d792818SGustavo Padovan cmd.ident); 56980a708f8fSGustavo F. Padovan 56990a708f8fSGustavo F. Padovan if (cmd_len > len || !cmd.ident) { 57000a708f8fSGustavo F. Padovan BT_DBG("corrupted command"); 57010a708f8fSGustavo F. Padovan break; 57020a708f8fSGustavo F. Padovan } 57030a708f8fSGustavo F. Padovan 57043300d9a9SClaudio Takahasi err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data); 57050a708f8fSGustavo F. Padovan if (err) { 5706e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk rej; 57072c6d1a2eSGustavo F. Padovan 57082c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err); 57090a708f8fSGustavo F. Padovan 5710dcf4adbfSJoe Perches rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 57112d792818SGustavo Padovan l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, 57122d792818SGustavo Padovan sizeof(rej), &rej); 57130a708f8fSGustavo F. Padovan } 57140a708f8fSGustavo F. Padovan 57150a708f8fSGustavo F. Padovan data += cmd_len; 57160a708f8fSGustavo F. Padovan len -= cmd_len; 57170a708f8fSGustavo F. Padovan } 57180a708f8fSGustavo F. Padovan 57193b166295SMarcel Holtmann drop: 57200a708f8fSGustavo F. Padovan kfree_skb(skb); 57210a708f8fSGustavo F. Padovan } 57220a708f8fSGustavo F. Padovan 572347d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) 57240a708f8fSGustavo F. Padovan { 57250a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs; 5726e4ca6d98SAndrei Emeltchenko int hdr_size; 5727e4ca6d98SAndrei Emeltchenko 5728e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 5729e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE; 5730e4ca6d98SAndrei Emeltchenko else 5731e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE; 57320a708f8fSGustavo F. Padovan 573347d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 573403a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE); 57350a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len); 57360a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); 57370a708f8fSGustavo F. Padovan 57380a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs) 57390a708f8fSGustavo F. Padovan return -EBADMSG; 57400a708f8fSGustavo F. Padovan } 57410a708f8fSGustavo F. Padovan return 0; 57420a708f8fSGustavo F. Padovan } 57430a708f8fSGustavo F. Padovan 57446ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) 57450a708f8fSGustavo F. Padovan { 5746e31f7633SMat Martineau struct l2cap_ctrl control; 57470a708f8fSGustavo F. Padovan 5748e31f7633SMat Martineau BT_DBG("chan %p", chan); 57490a708f8fSGustavo F. Padovan 5750e31f7633SMat Martineau memset(&control, 0, sizeof(control)); 5751e31f7633SMat Martineau control.sframe = 1; 5752e31f7633SMat Martineau control.final = 1; 5753e31f7633SMat Martineau control.reqseq = chan->buffer_seq; 5754e31f7633SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 57550a708f8fSGustavo F. Padovan 5756e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 5757e31f7633SMat Martineau control.super = L2CAP_SUPER_RNR; 5758e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 57590a708f8fSGustavo F. Padovan } 57600a708f8fSGustavo F. Padovan 5761e31f7633SMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 5762e31f7633SMat Martineau chan->unacked_frames > 0) 5763e31f7633SMat Martineau __set_retrans_timer(chan); 57640a708f8fSGustavo F. Padovan 5765e31f7633SMat Martineau /* Send pending iframes */ 5766525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 57670a708f8fSGustavo F. Padovan 5768e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 5769e31f7633SMat Martineau test_bit(CONN_SEND_FBIT, &chan->conn_state)) { 5770e31f7633SMat Martineau /* F-bit wasn't sent in an s-frame or i-frame yet, so 5771e31f7633SMat Martineau * send it now. 5772e31f7633SMat Martineau */ 5773e31f7633SMat Martineau control.super = L2CAP_SUPER_RR; 5774e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 57750a708f8fSGustavo F. Padovan } 57760a708f8fSGustavo F. Padovan } 57770a708f8fSGustavo F. Padovan 57782d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag, 57792d792818SGustavo Padovan struct sk_buff **last_frag) 57800a708f8fSGustavo F. Padovan { 578184084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments 578284084a31SMat Martineau * skb->data_len reflects only data in fragments 578384084a31SMat Martineau */ 578484084a31SMat Martineau if (!skb_has_frag_list(skb)) 578584084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag; 578684084a31SMat Martineau 578784084a31SMat Martineau new_frag->next = NULL; 578884084a31SMat Martineau 578984084a31SMat Martineau (*last_frag)->next = new_frag; 579084084a31SMat Martineau *last_frag = new_frag; 579184084a31SMat Martineau 579284084a31SMat Martineau skb->len += new_frag->len; 579384084a31SMat Martineau skb->data_len += new_frag->len; 579484084a31SMat Martineau skb->truesize += new_frag->truesize; 579584084a31SMat Martineau } 579684084a31SMat Martineau 57974b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, 57984b51dae9SMat Martineau struct l2cap_ctrl *control) 579984084a31SMat Martineau { 580084084a31SMat Martineau int err = -EINVAL; 58010a708f8fSGustavo F. Padovan 58024b51dae9SMat Martineau switch (control->sar) { 58037e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED: 580484084a31SMat Martineau if (chan->sdu) 580584084a31SMat Martineau break; 58060a708f8fSGustavo F. Padovan 580780b98027SGustavo Padovan err = chan->ops->recv(chan, skb); 580884084a31SMat Martineau break; 58090a708f8fSGustavo F. Padovan 58107e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START: 581184084a31SMat Martineau if (chan->sdu) 581284084a31SMat Martineau break; 58130a708f8fSGustavo F. Padovan 58146f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data); 581503a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE); 58160a708f8fSGustavo F. Padovan 581784084a31SMat Martineau if (chan->sdu_len > chan->imtu) { 581884084a31SMat Martineau err = -EMSGSIZE; 581984084a31SMat Martineau break; 582084084a31SMat Martineau } 58210a708f8fSGustavo F. Padovan 582284084a31SMat Martineau if (skb->len >= chan->sdu_len) 582384084a31SMat Martineau break; 582484084a31SMat Martineau 582584084a31SMat Martineau chan->sdu = skb; 582684084a31SMat Martineau chan->sdu_last_frag = skb; 582784084a31SMat Martineau 582884084a31SMat Martineau skb = NULL; 582984084a31SMat Martineau err = 0; 58300a708f8fSGustavo F. Padovan break; 58310a708f8fSGustavo F. Padovan 58327e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE: 58336f61fd47SGustavo F. Padovan if (!chan->sdu) 583484084a31SMat Martineau break; 58350a708f8fSGustavo F. Padovan 583684084a31SMat Martineau append_skb_frag(chan->sdu, skb, 583784084a31SMat Martineau &chan->sdu_last_frag); 583884084a31SMat Martineau skb = NULL; 58390a708f8fSGustavo F. Padovan 584084084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len) 584184084a31SMat Martineau break; 58420a708f8fSGustavo F. Padovan 584384084a31SMat Martineau err = 0; 58440a708f8fSGustavo F. Padovan break; 58450a708f8fSGustavo F. Padovan 58467e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END: 58476f61fd47SGustavo F. Padovan if (!chan->sdu) 584884084a31SMat Martineau break; 58490a708f8fSGustavo F. Padovan 585084084a31SMat Martineau append_skb_frag(chan->sdu, skb, 585184084a31SMat Martineau &chan->sdu_last_frag); 585284084a31SMat Martineau skb = NULL; 58530a708f8fSGustavo F. Padovan 585484084a31SMat Martineau if (chan->sdu->len != chan->sdu_len) 585584084a31SMat Martineau break; 58560a708f8fSGustavo F. Padovan 585780b98027SGustavo Padovan err = chan->ops->recv(chan, chan->sdu); 58580a708f8fSGustavo F. Padovan 585984084a31SMat Martineau if (!err) { 586084084a31SMat Martineau /* Reassembly complete */ 586184084a31SMat Martineau chan->sdu = NULL; 586284084a31SMat Martineau chan->sdu_last_frag = NULL; 586384084a31SMat Martineau chan->sdu_len = 0; 58640a708f8fSGustavo F. Padovan } 58650a708f8fSGustavo F. Padovan break; 58660a708f8fSGustavo F. Padovan } 58670a708f8fSGustavo F. Padovan 586884084a31SMat Martineau if (err) { 58690a708f8fSGustavo F. Padovan kfree_skb(skb); 58706f61fd47SGustavo F. Padovan kfree_skb(chan->sdu); 58716f61fd47SGustavo F. Padovan chan->sdu = NULL; 587284084a31SMat Martineau chan->sdu_last_frag = NULL; 587384084a31SMat Martineau chan->sdu_len = 0; 587484084a31SMat Martineau } 58750a708f8fSGustavo F. Padovan 587684084a31SMat Martineau return err; 58770a708f8fSGustavo F. Padovan } 58780a708f8fSGustavo F. Padovan 587932b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan) 588032b32735SMat Martineau { 588132b32735SMat Martineau /* Placeholder */ 588232b32735SMat Martineau return 0; 588332b32735SMat Martineau } 588432b32735SMat Martineau 5885e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 58860a708f8fSGustavo F. Padovan { 588761aa4f5bSMat Martineau u8 event; 588861aa4f5bSMat Martineau 588961aa4f5bSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 589061aa4f5bSMat Martineau return; 589161aa4f5bSMat Martineau 589261aa4f5bSMat Martineau event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR; 5893401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, event); 58940a708f8fSGustavo F. Padovan } 58950a708f8fSGustavo F. Padovan 5896d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan) 5897d2a7ac5dSMat Martineau { 589863838725SMat Martineau int err = 0; 589963838725SMat Martineau /* Pass sequential frames to l2cap_reassemble_sdu() 590063838725SMat Martineau * until a gap is encountered. 590163838725SMat Martineau */ 590263838725SMat Martineau 590363838725SMat Martineau BT_DBG("chan %p", chan); 590463838725SMat Martineau 590563838725SMat Martineau while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 590663838725SMat Martineau struct sk_buff *skb; 590763838725SMat Martineau BT_DBG("Searching for skb with txseq %d (queue len %d)", 590863838725SMat Martineau chan->buffer_seq, skb_queue_len(&chan->srej_q)); 590963838725SMat Martineau 591063838725SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq); 591163838725SMat Martineau 591263838725SMat Martineau if (!skb) 591363838725SMat Martineau break; 591463838725SMat Martineau 591563838725SMat Martineau skb_unlink(skb, &chan->srej_q); 591663838725SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 5917a4368ff3SJohan Hedberg err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->l2cap); 591863838725SMat Martineau if (err) 591963838725SMat Martineau break; 592063838725SMat Martineau } 592163838725SMat Martineau 592263838725SMat Martineau if (skb_queue_empty(&chan->srej_q)) { 592363838725SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 592463838725SMat Martineau l2cap_send_ack(chan); 592563838725SMat Martineau } 592663838725SMat Martineau 592763838725SMat Martineau return err; 5928d2a7ac5dSMat Martineau } 5929d2a7ac5dSMat Martineau 5930d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan, 5931d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 5932d2a7ac5dSMat Martineau { 5933f80842a8SMat Martineau struct sk_buff *skb; 5934f80842a8SMat Martineau 5935f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 5936f80842a8SMat Martineau 5937f80842a8SMat Martineau if (control->reqseq == chan->next_tx_seq) { 5938f80842a8SMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 59395e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 5940f80842a8SMat Martineau return; 5941f80842a8SMat Martineau } 5942f80842a8SMat Martineau 5943f80842a8SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 5944f80842a8SMat Martineau 5945f80842a8SMat Martineau if (skb == NULL) { 5946f80842a8SMat Martineau BT_DBG("Seq %d not available for retransmission", 5947f80842a8SMat Martineau control->reqseq); 5948f80842a8SMat Martineau return; 5949f80842a8SMat Martineau } 5950f80842a8SMat Martineau 5951a4368ff3SJohan Hedberg if (chan->max_tx != 0 && bt_cb(skb)->l2cap.retries >= chan->max_tx) { 5952f80842a8SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 59535e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 5954f80842a8SMat Martineau return; 5955f80842a8SMat Martineau } 5956f80842a8SMat Martineau 5957f80842a8SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 5958f80842a8SMat Martineau 5959f80842a8SMat Martineau if (control->poll) { 5960f80842a8SMat Martineau l2cap_pass_to_tx(chan, control); 5961f80842a8SMat Martineau 5962f80842a8SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 5963f80842a8SMat Martineau l2cap_retransmit(chan, control); 5964f80842a8SMat Martineau l2cap_ertm_send(chan); 5965f80842a8SMat Martineau 5966f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 5967f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 5968f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 5969f80842a8SMat Martineau } 5970f80842a8SMat Martineau } else { 5971f80842a8SMat Martineau l2cap_pass_to_tx_fbit(chan, control); 5972f80842a8SMat Martineau 5973f80842a8SMat Martineau if (control->final) { 5974f80842a8SMat Martineau if (chan->srej_save_reqseq != control->reqseq || 5975f80842a8SMat Martineau !test_and_clear_bit(CONN_SREJ_ACT, 5976f80842a8SMat Martineau &chan->conn_state)) 5977f80842a8SMat Martineau l2cap_retransmit(chan, control); 5978f80842a8SMat Martineau } else { 5979f80842a8SMat Martineau l2cap_retransmit(chan, control); 5980f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 5981f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 5982f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 5983f80842a8SMat Martineau } 5984f80842a8SMat Martineau } 5985f80842a8SMat Martineau } 5986d2a7ac5dSMat Martineau } 5987d2a7ac5dSMat Martineau 5988d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan, 5989d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 5990d2a7ac5dSMat Martineau { 5991fcd289dfSMat Martineau struct sk_buff *skb; 5992fcd289dfSMat Martineau 5993fcd289dfSMat Martineau BT_DBG("chan %p, control %p", chan, control); 5994fcd289dfSMat Martineau 5995fcd289dfSMat Martineau if (control->reqseq == chan->next_tx_seq) { 5996fcd289dfSMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 59975e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 5998fcd289dfSMat Martineau return; 5999fcd289dfSMat Martineau } 6000fcd289dfSMat Martineau 6001fcd289dfSMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 6002fcd289dfSMat Martineau 6003fcd289dfSMat Martineau if (chan->max_tx && skb && 6004a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.retries >= chan->max_tx) { 6005fcd289dfSMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 60065e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6007fcd289dfSMat Martineau return; 6008fcd289dfSMat Martineau } 6009fcd289dfSMat Martineau 6010fcd289dfSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6011fcd289dfSMat Martineau 6012fcd289dfSMat Martineau l2cap_pass_to_tx(chan, control); 6013fcd289dfSMat Martineau 6014fcd289dfSMat Martineau if (control->final) { 6015fcd289dfSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 6016fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 6017fcd289dfSMat Martineau } else { 6018fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 6019fcd289dfSMat Martineau l2cap_ertm_send(chan); 6020fcd289dfSMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) 6021fcd289dfSMat Martineau set_bit(CONN_REJ_ACT, &chan->conn_state); 6022fcd289dfSMat Martineau } 6023d2a7ac5dSMat Martineau } 6024d2a7ac5dSMat Martineau 60254b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) 60264b51dae9SMat Martineau { 60274b51dae9SMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 60284b51dae9SMat Martineau 60294b51dae9SMat Martineau BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq, 60304b51dae9SMat Martineau chan->expected_tx_seq); 60314b51dae9SMat Martineau 60324b51dae9SMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 60334b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 60344b51dae9SMat Martineau chan->tx_win) { 60354b51dae9SMat Martineau /* See notes below regarding "double poll" and 60364b51dae9SMat Martineau * invalid packets. 60374b51dae9SMat Martineau */ 60384b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 60394b51dae9SMat Martineau BT_DBG("Invalid/Ignore - after SREJ"); 60404b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 60414b51dae9SMat Martineau } else { 60424b51dae9SMat Martineau BT_DBG("Invalid - in window after SREJ sent"); 60434b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 60444b51dae9SMat Martineau } 60454b51dae9SMat Martineau } 60464b51dae9SMat Martineau 60474b51dae9SMat Martineau if (chan->srej_list.head == txseq) { 60484b51dae9SMat Martineau BT_DBG("Expected SREJ"); 60494b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED_SREJ; 60504b51dae9SMat Martineau } 60514b51dae9SMat Martineau 60524b51dae9SMat Martineau if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) { 60534b51dae9SMat Martineau BT_DBG("Duplicate SREJ - txseq already stored"); 60544b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE_SREJ; 60554b51dae9SMat Martineau } 60564b51dae9SMat Martineau 60574b51dae9SMat Martineau if (l2cap_seq_list_contains(&chan->srej_list, txseq)) { 60584b51dae9SMat Martineau BT_DBG("Unexpected SREJ - not requested"); 60594b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED_SREJ; 60604b51dae9SMat Martineau } 60614b51dae9SMat Martineau } 60624b51dae9SMat Martineau 60634b51dae9SMat Martineau if (chan->expected_tx_seq == txseq) { 60644b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 60654b51dae9SMat Martineau chan->tx_win) { 60664b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 60674b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 60684b51dae9SMat Martineau } else { 60694b51dae9SMat Martineau BT_DBG("Expected"); 60704b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED; 60714b51dae9SMat Martineau } 60724b51dae9SMat Martineau } 60734b51dae9SMat Martineau 60744b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) < 60752d792818SGustavo Padovan __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) { 60764b51dae9SMat Martineau BT_DBG("Duplicate - expected_tx_seq later than txseq"); 60774b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE; 60784b51dae9SMat Martineau } 60794b51dae9SMat Martineau 60804b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) { 60814b51dae9SMat Martineau /* A source of invalid packets is a "double poll" condition, 60824b51dae9SMat Martineau * where delays cause us to send multiple poll packets. If 60834b51dae9SMat Martineau * the remote stack receives and processes both polls, 60844b51dae9SMat Martineau * sequence numbers can wrap around in such a way that a 60854b51dae9SMat Martineau * resent frame has a sequence number that looks like new data 60864b51dae9SMat Martineau * with a sequence gap. This would trigger an erroneous SREJ 60874b51dae9SMat Martineau * request. 60884b51dae9SMat Martineau * 60894b51dae9SMat Martineau * Fortunately, this is impossible with a tx window that's 60904b51dae9SMat Martineau * less than half of the maximum sequence number, which allows 60914b51dae9SMat Martineau * invalid frames to be safely ignored. 60924b51dae9SMat Martineau * 60934b51dae9SMat Martineau * With tx window sizes greater than half of the tx window 60944b51dae9SMat Martineau * maximum, the frame is invalid and cannot be ignored. This 60954b51dae9SMat Martineau * causes a disconnect. 60964b51dae9SMat Martineau */ 60974b51dae9SMat Martineau 60984b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 60994b51dae9SMat Martineau BT_DBG("Invalid/Ignore - txseq outside tx window"); 61004b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 61014b51dae9SMat Martineau } else { 61024b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 61034b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 61044b51dae9SMat Martineau } 61054b51dae9SMat Martineau } else { 61064b51dae9SMat Martineau BT_DBG("Unexpected - txseq indicates missing frames"); 61074b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED; 61084b51dae9SMat Martineau } 61094b51dae9SMat Martineau } 61104b51dae9SMat Martineau 6111d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan, 6112d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 6113d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 6114d2a7ac5dSMat Martineau { 6115d2a7ac5dSMat Martineau int err = 0; 6116941247f9SPeter Senna Tschudin bool skb_in_use = false; 6117d2a7ac5dSMat Martineau 6118d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 6119d2a7ac5dSMat Martineau event); 6120d2a7ac5dSMat Martineau 6121d2a7ac5dSMat Martineau switch (event) { 6122d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 6123d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, control->txseq)) { 6124d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 6125d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6126d2a7ac5dSMat Martineau 6127d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 6128d2a7ac5dSMat Martineau BT_DBG("Busy, discarding expected seq %d", 6129d2a7ac5dSMat Martineau control->txseq); 6130d2a7ac5dSMat Martineau break; 6131d2a7ac5dSMat Martineau } 6132d2a7ac5dSMat Martineau 6133d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, 6134d2a7ac5dSMat Martineau control->txseq); 6135d2a7ac5dSMat Martineau 6136d2a7ac5dSMat Martineau chan->buffer_seq = chan->expected_tx_seq; 6137941247f9SPeter Senna Tschudin skb_in_use = true; 6138d2a7ac5dSMat Martineau 6139d2a7ac5dSMat Martineau err = l2cap_reassemble_sdu(chan, skb, control); 6140d2a7ac5dSMat Martineau if (err) 6141d2a7ac5dSMat Martineau break; 6142d2a7ac5dSMat Martineau 6143d2a7ac5dSMat Martineau if (control->final) { 6144d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 6145d2a7ac5dSMat Martineau &chan->conn_state)) { 6146d2a7ac5dSMat Martineau control->final = 0; 6147d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6148d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6149d2a7ac5dSMat Martineau } 6150d2a7ac5dSMat Martineau } 6151d2a7ac5dSMat Martineau 6152d2a7ac5dSMat Martineau if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 6153d2a7ac5dSMat Martineau l2cap_send_ack(chan); 6154d2a7ac5dSMat Martineau break; 6155d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 6156d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6157d2a7ac5dSMat Martineau 6158d2a7ac5dSMat Martineau /* Can't issue SREJ frames in the local busy state. 6159d2a7ac5dSMat Martineau * Drop this frame, it will be seen as missing 6160d2a7ac5dSMat Martineau * when local busy is exited. 6161d2a7ac5dSMat Martineau */ 6162d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 6163d2a7ac5dSMat Martineau BT_DBG("Busy, discarding unexpected seq %d", 6164d2a7ac5dSMat Martineau control->txseq); 6165d2a7ac5dSMat Martineau break; 6166d2a7ac5dSMat Martineau } 6167d2a7ac5dSMat Martineau 6168d2a7ac5dSMat Martineau /* There was a gap in the sequence, so an SREJ 6169d2a7ac5dSMat Martineau * must be sent for each missing frame. The 6170d2a7ac5dSMat Martineau * current frame is stored for later use. 6171d2a7ac5dSMat Martineau */ 6172d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6173941247f9SPeter Senna Tschudin skb_in_use = true; 6174d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6175d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6176d2a7ac5dSMat Martineau 6177d2a7ac5dSMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 6178d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 6179d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 6180d2a7ac5dSMat Martineau 6181d2a7ac5dSMat Martineau chan->rx_state = L2CAP_RX_STATE_SREJ_SENT; 6182d2a7ac5dSMat Martineau break; 6183d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 6184d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6185d2a7ac5dSMat Martineau break; 6186d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 6187d2a7ac5dSMat Martineau break; 6188d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 6189d2a7ac5dSMat Martineau default: 61905e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6191d2a7ac5dSMat Martineau break; 6192d2a7ac5dSMat Martineau } 6193d2a7ac5dSMat Martineau break; 6194d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 6195d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6196d2a7ac5dSMat Martineau if (control->final) { 6197d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6198d2a7ac5dSMat Martineau 6199e6a3ee6eSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) && 6200e6a3ee6eSMat Martineau !__chan_is_moving(chan)) { 6201d2a7ac5dSMat Martineau control->final = 0; 6202d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6203d2a7ac5dSMat Martineau } 6204d2a7ac5dSMat Martineau 6205d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6206d2a7ac5dSMat Martineau } else if (control->poll) { 6207d2a7ac5dSMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 6208d2a7ac5dSMat Martineau } else { 6209d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6210d2a7ac5dSMat Martineau &chan->conn_state) && 6211d2a7ac5dSMat Martineau chan->unacked_frames) 6212d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6213d2a7ac5dSMat Martineau 6214d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6215d2a7ac5dSMat Martineau } 6216d2a7ac5dSMat Martineau break; 6217d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 6218d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6219d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6220d2a7ac5dSMat Martineau if (control && control->poll) { 6221d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6222d2a7ac5dSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 6223d2a7ac5dSMat Martineau } 6224d2a7ac5dSMat Martineau __clear_retrans_timer(chan); 6225d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 6226d2a7ac5dSMat Martineau break; 6227d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 6228d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 6229d2a7ac5dSMat Martineau break; 6230d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 6231d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 6232d2a7ac5dSMat Martineau break; 6233d2a7ac5dSMat Martineau default: 6234d2a7ac5dSMat Martineau break; 6235d2a7ac5dSMat Martineau } 6236d2a7ac5dSMat Martineau 6237d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 6238d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 6239d2a7ac5dSMat Martineau kfree_skb(skb); 6240d2a7ac5dSMat Martineau } 6241d2a7ac5dSMat Martineau 6242d2a7ac5dSMat Martineau return err; 6243d2a7ac5dSMat Martineau } 6244d2a7ac5dSMat Martineau 6245d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, 6246d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 6247d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 6248d2a7ac5dSMat Martineau { 6249d2a7ac5dSMat Martineau int err = 0; 6250d2a7ac5dSMat Martineau u16 txseq = control->txseq; 6251941247f9SPeter Senna Tschudin bool skb_in_use = false; 6252d2a7ac5dSMat Martineau 6253d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 6254d2a7ac5dSMat Martineau event); 6255d2a7ac5dSMat Martineau 6256d2a7ac5dSMat Martineau switch (event) { 6257d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 6258d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, txseq)) { 6259d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 6260d2a7ac5dSMat Martineau /* Keep frame for reassembly later */ 6261d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6262d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6263941247f9SPeter Senna Tschudin skb_in_use = true; 6264d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6265d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6266d2a7ac5dSMat Martineau 6267d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 6268d2a7ac5dSMat Martineau break; 6269d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED_SREJ: 6270d2a7ac5dSMat Martineau l2cap_seq_list_pop(&chan->srej_list); 6271d2a7ac5dSMat Martineau 6272d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6273d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6274941247f9SPeter Senna Tschudin skb_in_use = true; 6275d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6276d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6277d2a7ac5dSMat Martineau 6278d2a7ac5dSMat Martineau err = l2cap_rx_queued_iframes(chan); 6279d2a7ac5dSMat Martineau if (err) 6280d2a7ac5dSMat Martineau break; 6281d2a7ac5dSMat Martineau 6282d2a7ac5dSMat Martineau break; 6283d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 6284d2a7ac5dSMat Martineau /* Got a frame that can't be reassembled yet. 6285d2a7ac5dSMat Martineau * Save it for later, and send SREJs to cover 6286d2a7ac5dSMat Martineau * the missing frames. 6287d2a7ac5dSMat Martineau */ 6288d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6289941247f9SPeter Senna Tschudin skb_in_use = true; 6290d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6291d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6292d2a7ac5dSMat Martineau 6293d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6294d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 6295d2a7ac5dSMat Martineau break; 6296d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED_SREJ: 6297d2a7ac5dSMat Martineau /* This frame was requested with an SREJ, but 6298d2a7ac5dSMat Martineau * some expected retransmitted frames are 6299d2a7ac5dSMat Martineau * missing. Request retransmission of missing 6300d2a7ac5dSMat Martineau * SREJ'd frames. 6301d2a7ac5dSMat Martineau */ 6302d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6303941247f9SPeter Senna Tschudin skb_in_use = true; 6304d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6305d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6306d2a7ac5dSMat Martineau 6307d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6308d2a7ac5dSMat Martineau l2cap_send_srej_list(chan, control->txseq); 6309d2a7ac5dSMat Martineau break; 6310d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE_SREJ: 6311d2a7ac5dSMat Martineau /* We've already queued this frame. Drop this copy. */ 6312d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6313d2a7ac5dSMat Martineau break; 6314d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 6315d2a7ac5dSMat Martineau /* Expecting a later sequence number, so this frame 6316d2a7ac5dSMat Martineau * was already received. Ignore it completely. 6317d2a7ac5dSMat Martineau */ 6318d2a7ac5dSMat Martineau break; 6319d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 6320d2a7ac5dSMat Martineau break; 6321d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 6322d2a7ac5dSMat Martineau default: 63235e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6324d2a7ac5dSMat Martineau break; 6325d2a7ac5dSMat Martineau } 6326d2a7ac5dSMat Martineau break; 6327d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 6328d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6329d2a7ac5dSMat Martineau if (control->final) { 6330d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6331d2a7ac5dSMat Martineau 6332d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 6333d2a7ac5dSMat Martineau &chan->conn_state)) { 6334d2a7ac5dSMat Martineau control->final = 0; 6335d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6336d2a7ac5dSMat Martineau } 6337d2a7ac5dSMat Martineau 6338d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6339d2a7ac5dSMat Martineau } else if (control->poll) { 6340d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6341d2a7ac5dSMat Martineau &chan->conn_state) && 6342d2a7ac5dSMat Martineau chan->unacked_frames) { 6343d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6344d2a7ac5dSMat Martineau } 6345d2a7ac5dSMat Martineau 6346d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6347d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 6348d2a7ac5dSMat Martineau } else { 6349d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6350d2a7ac5dSMat Martineau &chan->conn_state) && 6351d2a7ac5dSMat Martineau chan->unacked_frames) 6352d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6353d2a7ac5dSMat Martineau 6354d2a7ac5dSMat Martineau l2cap_send_ack(chan); 6355d2a7ac5dSMat Martineau } 6356d2a7ac5dSMat Martineau break; 6357d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 6358d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6359d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6360d2a7ac5dSMat Martineau if (control->poll) { 6361d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 6362d2a7ac5dSMat Martineau } else { 6363d2a7ac5dSMat Martineau struct l2cap_ctrl rr_control; 6364d2a7ac5dSMat Martineau memset(&rr_control, 0, sizeof(rr_control)); 6365d2a7ac5dSMat Martineau rr_control.sframe = 1; 6366d2a7ac5dSMat Martineau rr_control.super = L2CAP_SUPER_RR; 6367d2a7ac5dSMat Martineau rr_control.reqseq = chan->buffer_seq; 6368d2a7ac5dSMat Martineau l2cap_send_sframe(chan, &rr_control); 6369d2a7ac5dSMat Martineau } 6370d2a7ac5dSMat Martineau 6371d2a7ac5dSMat Martineau break; 6372d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 6373d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 6374d2a7ac5dSMat Martineau break; 6375d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 6376d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 6377d2a7ac5dSMat Martineau break; 6378d2a7ac5dSMat Martineau } 6379d2a7ac5dSMat Martineau 6380d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 6381d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 6382d2a7ac5dSMat Martineau kfree_skb(skb); 6383d2a7ac5dSMat Martineau } 6384d2a7ac5dSMat Martineau 6385d2a7ac5dSMat Martineau return err; 6386d2a7ac5dSMat Martineau } 6387d2a7ac5dSMat Martineau 638832b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan) 638932b32735SMat Martineau { 639032b32735SMat Martineau BT_DBG("chan %p", chan); 639132b32735SMat Martineau 639232b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 639332b32735SMat Martineau 639432b32735SMat Martineau if (chan->hs_hcon) 639532b32735SMat Martineau chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; 639632b32735SMat Martineau else 639732b32735SMat Martineau chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; 639832b32735SMat Martineau 639932b32735SMat Martineau return l2cap_resegment(chan); 640032b32735SMat Martineau } 640132b32735SMat Martineau 640232b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan, 640332b32735SMat Martineau struct l2cap_ctrl *control, 640432b32735SMat Martineau struct sk_buff *skb, u8 event) 640532b32735SMat Martineau { 640632b32735SMat Martineau int err; 640732b32735SMat Martineau 640832b32735SMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 640932b32735SMat Martineau event); 641032b32735SMat Martineau 641132b32735SMat Martineau if (!control->poll) 641232b32735SMat Martineau return -EPROTO; 641332b32735SMat Martineau 641432b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq); 641532b32735SMat Martineau 641632b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q)) 641732b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q); 641832b32735SMat Martineau else 641932b32735SMat Martineau chan->tx_send_head = NULL; 642032b32735SMat Martineau 642132b32735SMat Martineau /* Rewind next_tx_seq to the point expected 642232b32735SMat Martineau * by the receiver. 642332b32735SMat Martineau */ 642432b32735SMat Martineau chan->next_tx_seq = control->reqseq; 642532b32735SMat Martineau chan->unacked_frames = 0; 642632b32735SMat Martineau 642732b32735SMat Martineau err = l2cap_finish_move(chan); 642832b32735SMat Martineau if (err) 642932b32735SMat Martineau return err; 643032b32735SMat Martineau 643132b32735SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 643232b32735SMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 643332b32735SMat Martineau 643432b32735SMat Martineau if (event == L2CAP_EV_RECV_IFRAME) 643532b32735SMat Martineau return -EPROTO; 643632b32735SMat Martineau 643732b32735SMat Martineau return l2cap_rx_state_recv(chan, control, NULL, event); 643832b32735SMat Martineau } 643932b32735SMat Martineau 644032b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan, 644132b32735SMat Martineau struct l2cap_ctrl *control, 644232b32735SMat Martineau struct sk_buff *skb, u8 event) 644332b32735SMat Martineau { 644432b32735SMat Martineau int err; 644532b32735SMat Martineau 644632b32735SMat Martineau if (!control->final) 644732b32735SMat Martineau return -EPROTO; 644832b32735SMat Martineau 644932b32735SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 645032b32735SMat Martineau 645132b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 645232b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq); 645332b32735SMat Martineau 645432b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q)) 645532b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q); 645632b32735SMat Martineau else 645732b32735SMat Martineau chan->tx_send_head = NULL; 645832b32735SMat Martineau 645932b32735SMat Martineau /* Rewind next_tx_seq to the point expected 646032b32735SMat Martineau * by the receiver. 646132b32735SMat Martineau */ 646232b32735SMat Martineau chan->next_tx_seq = control->reqseq; 646332b32735SMat Martineau chan->unacked_frames = 0; 646432b32735SMat Martineau 646532b32735SMat Martineau if (chan->hs_hcon) 646632b32735SMat Martineau chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; 646732b32735SMat Martineau else 646832b32735SMat Martineau chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; 646932b32735SMat Martineau 647032b32735SMat Martineau err = l2cap_resegment(chan); 647132b32735SMat Martineau 647232b32735SMat Martineau if (!err) 647332b32735SMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 647432b32735SMat Martineau 647532b32735SMat Martineau return err; 647632b32735SMat Martineau } 647732b32735SMat Martineau 6478d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq) 6479d2a7ac5dSMat Martineau { 6480d2a7ac5dSMat Martineau /* Make sure reqseq is for a packet that has been sent but not acked */ 6481d2a7ac5dSMat Martineau u16 unacked; 6482d2a7ac5dSMat Martineau 6483d2a7ac5dSMat Martineau unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq); 6484d2a7ac5dSMat Martineau return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked; 6485d2a7ac5dSMat Martineau } 6486d2a7ac5dSMat Martineau 6487cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 6488cec8ab6eSMat Martineau struct sk_buff *skb, u8 event) 64890a708f8fSGustavo F. Padovan { 6490d2a7ac5dSMat Martineau int err = 0; 6491d2a7ac5dSMat Martineau 6492d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan, 6493d2a7ac5dSMat Martineau control, skb, event, chan->rx_state); 6494d2a7ac5dSMat Martineau 6495d2a7ac5dSMat Martineau if (__valid_reqseq(chan, control->reqseq)) { 6496d2a7ac5dSMat Martineau switch (chan->rx_state) { 6497d2a7ac5dSMat Martineau case L2CAP_RX_STATE_RECV: 6498d2a7ac5dSMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 6499d2a7ac5dSMat Martineau break; 6500d2a7ac5dSMat Martineau case L2CAP_RX_STATE_SREJ_SENT: 6501d2a7ac5dSMat Martineau err = l2cap_rx_state_srej_sent(chan, control, skb, 6502d2a7ac5dSMat Martineau event); 6503d2a7ac5dSMat Martineau break; 650432b32735SMat Martineau case L2CAP_RX_STATE_WAIT_P: 650532b32735SMat Martineau err = l2cap_rx_state_wait_p(chan, control, skb, event); 650632b32735SMat Martineau break; 650732b32735SMat Martineau case L2CAP_RX_STATE_WAIT_F: 650832b32735SMat Martineau err = l2cap_rx_state_wait_f(chan, control, skb, event); 650932b32735SMat Martineau break; 6510d2a7ac5dSMat Martineau default: 6511d2a7ac5dSMat Martineau /* shut it down */ 6512d2a7ac5dSMat Martineau break; 6513d2a7ac5dSMat Martineau } 6514d2a7ac5dSMat Martineau } else { 6515d2a7ac5dSMat Martineau BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d", 6516d2a7ac5dSMat Martineau control->reqseq, chan->next_tx_seq, 6517d2a7ac5dSMat Martineau chan->expected_ack_seq); 65185e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6519d2a7ac5dSMat Martineau } 6520d2a7ac5dSMat Martineau 6521d2a7ac5dSMat Martineau return err; 6522cec8ab6eSMat Martineau } 6523cec8ab6eSMat Martineau 6524cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 6525cec8ab6eSMat Martineau struct sk_buff *skb) 6526cec8ab6eSMat Martineau { 65274b51dae9SMat Martineau int err = 0; 65284b51dae9SMat Martineau 65294b51dae9SMat Martineau BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb, 65304b51dae9SMat Martineau chan->rx_state); 65314b51dae9SMat Martineau 65324b51dae9SMat Martineau if (l2cap_classify_txseq(chan, control->txseq) == 65334b51dae9SMat Martineau L2CAP_TXSEQ_EXPECTED) { 65344b51dae9SMat Martineau l2cap_pass_to_tx(chan, control); 65354b51dae9SMat Martineau 65364b51dae9SMat Martineau BT_DBG("buffer_seq %d->%d", chan->buffer_seq, 65374b51dae9SMat Martineau __next_seq(chan, chan->buffer_seq)); 65384b51dae9SMat Martineau 65394b51dae9SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 65404b51dae9SMat Martineau 65414b51dae9SMat Martineau l2cap_reassemble_sdu(chan, skb, control); 65424b51dae9SMat Martineau } else { 65434b51dae9SMat Martineau if (chan->sdu) { 65444b51dae9SMat Martineau kfree_skb(chan->sdu); 65454b51dae9SMat Martineau chan->sdu = NULL; 65464b51dae9SMat Martineau } 65474b51dae9SMat Martineau chan->sdu_last_frag = NULL; 65484b51dae9SMat Martineau chan->sdu_len = 0; 65494b51dae9SMat Martineau 65504b51dae9SMat Martineau if (skb) { 65514b51dae9SMat Martineau BT_DBG("Freeing %p", skb); 65524b51dae9SMat Martineau kfree_skb(skb); 65534b51dae9SMat Martineau } 65544b51dae9SMat Martineau } 65554b51dae9SMat Martineau 65564b51dae9SMat Martineau chan->last_acked_seq = control->txseq; 65574b51dae9SMat Martineau chan->expected_tx_seq = __next_seq(chan, control->txseq); 65584b51dae9SMat Martineau 65594b51dae9SMat Martineau return err; 6560cec8ab6eSMat Martineau } 6561cec8ab6eSMat Martineau 6562cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 6563cec8ab6eSMat Martineau { 6564a4368ff3SJohan Hedberg struct l2cap_ctrl *control = &bt_cb(skb)->l2cap; 6565cec8ab6eSMat Martineau u16 len; 6566cec8ab6eSMat Martineau u8 event; 65670a708f8fSGustavo F. Padovan 6568b76bbd66SMat Martineau __unpack_control(chan, skb); 6569b76bbd66SMat Martineau 65700a708f8fSGustavo F. Padovan len = skb->len; 65710a708f8fSGustavo F. Padovan 65720a708f8fSGustavo F. Padovan /* 65730a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here. 65740a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery 6575cec8ab6eSMat Martineau * procedures and ask for retransmission. 65760a708f8fSGustavo F. Padovan */ 657747d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 65780a708f8fSGustavo F. Padovan goto drop; 65790a708f8fSGustavo F. Padovan 6580cec8ab6eSMat Martineau if (!control->sframe && control->sar == L2CAP_SAR_START) 658103a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 65820a708f8fSGustavo F. Padovan 658347d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 658403a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 65850a708f8fSGustavo F. Padovan 658647d1ec61SGustavo F. Padovan if (len > chan->mps) { 65875e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 65880a708f8fSGustavo F. Padovan goto drop; 65890a708f8fSGustavo F. Padovan } 65900a708f8fSGustavo F. Padovan 6591cec8ab6eSMat Martineau if (!control->sframe) { 6592cec8ab6eSMat Martineau int err; 65930a708f8fSGustavo F. Padovan 6594cec8ab6eSMat Martineau BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d", 6595cec8ab6eSMat Martineau control->sar, control->reqseq, control->final, 6596cec8ab6eSMat Martineau control->txseq); 6597836be934SAndrei Emeltchenko 6598cec8ab6eSMat Martineau /* Validate F-bit - F=0 always valid, F=1 only 6599cec8ab6eSMat Martineau * valid in TX WAIT_F 6600cec8ab6eSMat Martineau */ 6601cec8ab6eSMat Martineau if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F) 66020a708f8fSGustavo F. Padovan goto drop; 66030a708f8fSGustavo F. Padovan 6604cec8ab6eSMat Martineau if (chan->mode != L2CAP_MODE_STREAMING) { 6605cec8ab6eSMat Martineau event = L2CAP_EV_RECV_IFRAME; 6606cec8ab6eSMat Martineau err = l2cap_rx(chan, control, skb, event); 66070a708f8fSGustavo F. Padovan } else { 6608cec8ab6eSMat Martineau err = l2cap_stream_rx(chan, control, skb); 6609cec8ab6eSMat Martineau } 6610cec8ab6eSMat Martineau 6611cec8ab6eSMat Martineau if (err) 66125e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6613cec8ab6eSMat Martineau } else { 6614cec8ab6eSMat Martineau const u8 rx_func_to_event[4] = { 6615cec8ab6eSMat Martineau L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ, 6616cec8ab6eSMat Martineau L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ 6617cec8ab6eSMat Martineau }; 6618cec8ab6eSMat Martineau 6619cec8ab6eSMat Martineau /* Only I-frames are expected in streaming mode */ 6620cec8ab6eSMat Martineau if (chan->mode == L2CAP_MODE_STREAMING) 6621cec8ab6eSMat Martineau goto drop; 6622cec8ab6eSMat Martineau 6623cec8ab6eSMat Martineau BT_DBG("sframe reqseq %d, final %d, poll %d, super %d", 6624cec8ab6eSMat Martineau control->reqseq, control->final, control->poll, 6625cec8ab6eSMat Martineau control->super); 6626cec8ab6eSMat Martineau 66270a708f8fSGustavo F. Padovan if (len != 0) { 66281bb166e6SAndrei Emeltchenko BT_ERR("Trailing bytes: %d in sframe", len); 66295e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 66300a708f8fSGustavo F. Padovan goto drop; 66310a708f8fSGustavo F. Padovan } 66320a708f8fSGustavo F. Padovan 6633cec8ab6eSMat Martineau /* Validate F and P bits */ 6634cec8ab6eSMat Martineau if (control->final && (control->poll || 6635cec8ab6eSMat Martineau chan->tx_state != L2CAP_TX_STATE_WAIT_F)) 6636cec8ab6eSMat Martineau goto drop; 6637cec8ab6eSMat Martineau 6638cec8ab6eSMat Martineau event = rx_func_to_event[control->super]; 6639cec8ab6eSMat Martineau if (l2cap_rx(chan, control, skb, event)) 66405e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 66410a708f8fSGustavo F. Padovan } 66420a708f8fSGustavo F. Padovan 66430a708f8fSGustavo F. Padovan return 0; 66440a708f8fSGustavo F. Padovan 66450a708f8fSGustavo F. Padovan drop: 66460a708f8fSGustavo F. Padovan kfree_skb(skb); 66470a708f8fSGustavo F. Padovan return 0; 66480a708f8fSGustavo F. Padovan } 66490a708f8fSGustavo F. Padovan 6650b1c325c2SJohan Hedberg static void l2cap_chan_le_send_credits(struct l2cap_chan *chan) 6651b1c325c2SJohan Hedberg { 6652b1c325c2SJohan Hedberg struct l2cap_conn *conn = chan->conn; 6653b1c325c2SJohan Hedberg struct l2cap_le_credits pkt; 6654b1c325c2SJohan Hedberg u16 return_credits; 6655b1c325c2SJohan Hedberg 6656b1c325c2SJohan Hedberg /* We return more credits to the sender only after the amount of 6657b1c325c2SJohan Hedberg * credits falls below half of the initial amount. 6658b1c325c2SJohan Hedberg */ 6659f15b8ecfSJohan Hedberg if (chan->rx_credits >= (le_max_credits + 1) / 2) 6660b1c325c2SJohan Hedberg return; 6661b1c325c2SJohan Hedberg 6662f15b8ecfSJohan Hedberg return_credits = le_max_credits - chan->rx_credits; 6663b1c325c2SJohan Hedberg 6664b1c325c2SJohan Hedberg BT_DBG("chan %p returning %u credits to sender", chan, return_credits); 6665b1c325c2SJohan Hedberg 6666b1c325c2SJohan Hedberg chan->rx_credits += return_credits; 6667b1c325c2SJohan Hedberg 6668b1c325c2SJohan Hedberg pkt.cid = cpu_to_le16(chan->scid); 6669b1c325c2SJohan Hedberg pkt.credits = cpu_to_le16(return_credits); 6670b1c325c2SJohan Hedberg 6671b1c325c2SJohan Hedberg chan->ident = l2cap_get_ident(conn); 6672b1c325c2SJohan Hedberg 6673b1c325c2SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt); 6674b1c325c2SJohan Hedberg } 6675b1c325c2SJohan Hedberg 6676fad5fc89SJohan Hedberg static int l2cap_le_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 6677fad5fc89SJohan Hedberg { 6678aac23bf6SJohan Hedberg int err; 6679fad5fc89SJohan Hedberg 6680aac23bf6SJohan Hedberg if (!chan->rx_credits) { 6681aac23bf6SJohan Hedberg BT_ERR("No credits to receive LE L2CAP data"); 6682dfd9774cSJohan Hedberg l2cap_send_disconn_req(chan, ECONNRESET); 6683fad5fc89SJohan Hedberg return -ENOBUFS; 6684aac23bf6SJohan Hedberg } 6685aac23bf6SJohan Hedberg 6686aac23bf6SJohan Hedberg if (chan->imtu < skb->len) { 6687aac23bf6SJohan Hedberg BT_ERR("Too big LE L2CAP PDU"); 6688aac23bf6SJohan Hedberg return -ENOBUFS; 6689aac23bf6SJohan Hedberg } 6690fad5fc89SJohan Hedberg 6691fad5fc89SJohan Hedberg chan->rx_credits--; 6692fad5fc89SJohan Hedberg BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits); 6693fad5fc89SJohan Hedberg 6694fad5fc89SJohan Hedberg l2cap_chan_le_send_credits(chan); 6695fad5fc89SJohan Hedberg 6696aac23bf6SJohan Hedberg err = 0; 6697aac23bf6SJohan Hedberg 6698aac23bf6SJohan Hedberg if (!chan->sdu) { 6699aac23bf6SJohan Hedberg u16 sdu_len; 6700aac23bf6SJohan Hedberg 6701aac23bf6SJohan Hedberg sdu_len = get_unaligned_le16(skb->data); 6702aac23bf6SJohan Hedberg skb_pull(skb, L2CAP_SDULEN_SIZE); 6703aac23bf6SJohan Hedberg 6704aac23bf6SJohan Hedberg BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u", 6705aac23bf6SJohan Hedberg sdu_len, skb->len, chan->imtu); 6706aac23bf6SJohan Hedberg 6707aac23bf6SJohan Hedberg if (sdu_len > chan->imtu) { 6708aac23bf6SJohan Hedberg BT_ERR("Too big LE L2CAP SDU length received"); 6709aac23bf6SJohan Hedberg err = -EMSGSIZE; 6710aac23bf6SJohan Hedberg goto failed; 6711aac23bf6SJohan Hedberg } 6712aac23bf6SJohan Hedberg 6713aac23bf6SJohan Hedberg if (skb->len > sdu_len) { 6714aac23bf6SJohan Hedberg BT_ERR("Too much LE L2CAP data received"); 6715aac23bf6SJohan Hedberg err = -EINVAL; 6716aac23bf6SJohan Hedberg goto failed; 6717aac23bf6SJohan Hedberg } 6718aac23bf6SJohan Hedberg 6719aac23bf6SJohan Hedberg if (skb->len == sdu_len) 6720fad5fc89SJohan Hedberg return chan->ops->recv(chan, skb); 6721aac23bf6SJohan Hedberg 6722aac23bf6SJohan Hedberg chan->sdu = skb; 6723aac23bf6SJohan Hedberg chan->sdu_len = sdu_len; 6724aac23bf6SJohan Hedberg chan->sdu_last_frag = skb; 6725aac23bf6SJohan Hedberg 6726aac23bf6SJohan Hedberg return 0; 6727aac23bf6SJohan Hedberg } 6728aac23bf6SJohan Hedberg 6729aac23bf6SJohan Hedberg BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u", 6730aac23bf6SJohan Hedberg chan->sdu->len, skb->len, chan->sdu_len); 6731aac23bf6SJohan Hedberg 6732aac23bf6SJohan Hedberg if (chan->sdu->len + skb->len > chan->sdu_len) { 6733aac23bf6SJohan Hedberg BT_ERR("Too much LE L2CAP data received"); 6734aac23bf6SJohan Hedberg err = -EINVAL; 6735aac23bf6SJohan Hedberg goto failed; 6736aac23bf6SJohan Hedberg } 6737aac23bf6SJohan Hedberg 6738aac23bf6SJohan Hedberg append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag); 6739aac23bf6SJohan Hedberg skb = NULL; 6740aac23bf6SJohan Hedberg 6741aac23bf6SJohan Hedberg if (chan->sdu->len == chan->sdu_len) { 6742aac23bf6SJohan Hedberg err = chan->ops->recv(chan, chan->sdu); 6743aac23bf6SJohan Hedberg if (!err) { 6744aac23bf6SJohan Hedberg chan->sdu = NULL; 6745aac23bf6SJohan Hedberg chan->sdu_last_frag = NULL; 6746aac23bf6SJohan Hedberg chan->sdu_len = 0; 6747aac23bf6SJohan Hedberg } 6748aac23bf6SJohan Hedberg } 6749aac23bf6SJohan Hedberg 6750aac23bf6SJohan Hedberg failed: 6751aac23bf6SJohan Hedberg if (err) { 6752aac23bf6SJohan Hedberg kfree_skb(skb); 6753aac23bf6SJohan Hedberg kfree_skb(chan->sdu); 6754aac23bf6SJohan Hedberg chan->sdu = NULL; 6755aac23bf6SJohan Hedberg chan->sdu_last_frag = NULL; 6756aac23bf6SJohan Hedberg chan->sdu_len = 0; 6757aac23bf6SJohan Hedberg } 6758aac23bf6SJohan Hedberg 6759aac23bf6SJohan Hedberg /* We can't return an error here since we took care of the skb 6760aac23bf6SJohan Hedberg * freeing internally. An error return would cause the caller to 6761aac23bf6SJohan Hedberg * do a double-free of the skb. 6762aac23bf6SJohan Hedberg */ 6763aac23bf6SJohan Hedberg return 0; 6764fad5fc89SJohan Hedberg } 6765fad5fc89SJohan Hedberg 676613ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid, 676713ca56e0SAndrei Emeltchenko struct sk_buff *skb) 67680a708f8fSGustavo F. Padovan { 676948454079SGustavo F. Padovan struct l2cap_chan *chan; 67700a708f8fSGustavo F. Padovan 6771baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 677248454079SGustavo F. Padovan if (!chan) { 677397e8e89dSAndrei Emeltchenko if (cid == L2CAP_CID_A2MP) { 677497e8e89dSAndrei Emeltchenko chan = a2mp_channel_create(conn, skb); 677597e8e89dSAndrei Emeltchenko if (!chan) { 677697e8e89dSAndrei Emeltchenko kfree_skb(skb); 677713ca56e0SAndrei Emeltchenko return; 677897e8e89dSAndrei Emeltchenko } 677997e8e89dSAndrei Emeltchenko 678097e8e89dSAndrei Emeltchenko l2cap_chan_lock(chan); 678197e8e89dSAndrei Emeltchenko } else { 67820a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid); 67836be36555SAndrei Emeltchenko /* Drop packet and return */ 67843379013bSDan Carpenter kfree_skb(skb); 678513ca56e0SAndrei Emeltchenko return; 67860a708f8fSGustavo F. Padovan } 678797e8e89dSAndrei Emeltchenko } 67880a708f8fSGustavo F. Padovan 678949208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len); 67900a708f8fSGustavo F. Padovan 6791315917e0SJohan Hedberg /* If we receive data on a fixed channel before the info req/rsp 6792315917e0SJohan Hedberg * procdure is done simply assume that the channel is supported 6793315917e0SJohan Hedberg * and mark it as ready. 6794315917e0SJohan Hedberg */ 6795315917e0SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_FIXED) 6796315917e0SJohan Hedberg l2cap_chan_ready(chan); 6797315917e0SJohan Hedberg 679889bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 67990a708f8fSGustavo F. Padovan goto drop; 68000a708f8fSGustavo F. Padovan 68010c1bc5c6SGustavo F. Padovan switch (chan->mode) { 680238319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 6803fad5fc89SJohan Hedberg if (l2cap_le_data_rcv(chan, skb) < 0) 6804fad5fc89SJohan Hedberg goto drop; 6805fad5fc89SJohan Hedberg 6806fad5fc89SJohan Hedberg goto done; 6807fad5fc89SJohan Hedberg 68080a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 68090a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here 68100a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable. 68110a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't 68120a708f8fSGustavo F. Padovan * provide flow control mechanism. */ 68130a708f8fSGustavo F. Padovan 68142c96e03dSSzymon Janc if (chan->imtu < skb->len) { 68152c96e03dSSzymon Janc BT_ERR("Dropping L2CAP data: receive buffer overflow"); 68160a708f8fSGustavo F. Padovan goto drop; 68172c96e03dSSzymon Janc } 68180a708f8fSGustavo F. Padovan 681980b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 68200a708f8fSGustavo F. Padovan goto done; 68210a708f8fSGustavo F. Padovan break; 68220a708f8fSGustavo F. Padovan 68230a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 68240a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 6825cec8ab6eSMat Martineau l2cap_data_rcv(chan, skb); 68260a708f8fSGustavo F. Padovan goto done; 68270a708f8fSGustavo F. Padovan 68280a708f8fSGustavo F. Padovan default: 68290c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); 68300a708f8fSGustavo F. Padovan break; 68310a708f8fSGustavo F. Padovan } 68320a708f8fSGustavo F. Padovan 68330a708f8fSGustavo F. Padovan drop: 68340a708f8fSGustavo F. Padovan kfree_skb(skb); 68350a708f8fSGustavo F. Padovan 68360a708f8fSGustavo F. Padovan done: 68376be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 68380a708f8fSGustavo F. Padovan } 68390a708f8fSGustavo F. Padovan 684084104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, 684184104b24SAndrei Emeltchenko struct sk_buff *skb) 68420a708f8fSGustavo F. Padovan { 6843ae4fd2d3SMarcel Holtmann struct hci_conn *hcon = conn->hcon; 684423691d75SGustavo F. Padovan struct l2cap_chan *chan; 68450a708f8fSGustavo F. Padovan 6846ae4fd2d3SMarcel Holtmann if (hcon->type != ACL_LINK) 6847a24cce14SJohan Hedberg goto free_skb; 6848ae4fd2d3SMarcel Holtmann 6849bf20fd4eSJohan Hedberg chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst, 6850bf20fd4eSJohan Hedberg ACL_LINK); 685123691d75SGustavo F. Padovan if (!chan) 6852a24cce14SJohan Hedberg goto free_skb; 68530a708f8fSGustavo F. Padovan 68545b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 68550a708f8fSGustavo F. Padovan 685689bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 68570a708f8fSGustavo F. Padovan goto drop; 68580a708f8fSGustavo F. Padovan 6859e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 68600a708f8fSGustavo F. Padovan goto drop; 68610a708f8fSGustavo F. Padovan 68622edf870dSMarcel Holtmann /* Store remote BD_ADDR and PSM for msg_name */ 6863a4368ff3SJohan Hedberg bacpy(&bt_cb(skb)->l2cap.bdaddr, &hcon->dst); 6864a4368ff3SJohan Hedberg bt_cb(skb)->l2cap.psm = psm; 68652edf870dSMarcel Holtmann 6866a24cce14SJohan Hedberg if (!chan->ops->recv(chan, skb)) { 6867a24cce14SJohan Hedberg l2cap_chan_put(chan); 686884104b24SAndrei Emeltchenko return; 6869a24cce14SJohan Hedberg } 68700a708f8fSGustavo F. Padovan 68710a708f8fSGustavo F. Padovan drop: 6872a24cce14SJohan Hedberg l2cap_chan_put(chan); 6873a24cce14SJohan Hedberg free_skb: 68740a708f8fSGustavo F. Padovan kfree_skb(skb); 68750a708f8fSGustavo F. Padovan } 68760a708f8fSGustavo F. Padovan 68770a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) 68780a708f8fSGustavo F. Padovan { 68790a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data; 688061a939c6SJohan Hedberg struct hci_conn *hcon = conn->hcon; 68810a708f8fSGustavo F. Padovan u16 cid, len; 68820a708f8fSGustavo F. Padovan __le16 psm; 68830a708f8fSGustavo F. Padovan 688461a939c6SJohan Hedberg if (hcon->state != BT_CONNECTED) { 688561a939c6SJohan Hedberg BT_DBG("queueing pending rx skb"); 688661a939c6SJohan Hedberg skb_queue_tail(&conn->pending_rx, skb); 688761a939c6SJohan Hedberg return; 688861a939c6SJohan Hedberg } 688961a939c6SJohan Hedberg 68900a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE); 68910a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid); 68920a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len); 68930a708f8fSGustavo F. Padovan 68940a708f8fSGustavo F. Padovan if (len != skb->len) { 68950a708f8fSGustavo F. Padovan kfree_skb(skb); 68960a708f8fSGustavo F. Padovan return; 68970a708f8fSGustavo F. Padovan } 68980a708f8fSGustavo F. Padovan 68999e1d7e15SJohan Hedberg /* Since we can't actively block incoming LE connections we must 69009e1d7e15SJohan Hedberg * at least ensure that we ignore incoming data from them. 69019e1d7e15SJohan Hedberg */ 69029e1d7e15SJohan Hedberg if (hcon->type == LE_LINK && 6903dcc36c16SJohan Hedberg hci_bdaddr_list_lookup(&hcon->hdev->blacklist, &hcon->dst, 6904a250e048SJohan Hedberg bdaddr_dst_type(hcon))) { 6905e493150eSJohan Hedberg kfree_skb(skb); 6906e493150eSJohan Hedberg return; 6907e493150eSJohan Hedberg } 6908e493150eSJohan Hedberg 69090a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid); 69100a708f8fSGustavo F. Padovan 69110a708f8fSGustavo F. Padovan switch (cid) { 69120a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING: 69130a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb); 69140a708f8fSGustavo F. Padovan break; 69150a708f8fSGustavo F. Padovan 69160a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS: 6917097db76cSAndrei Emeltchenko psm = get_unaligned((__le16 *) skb->data); 69180181a70fSAndrei Emeltchenko skb_pull(skb, L2CAP_PSMLEN_SIZE); 69190a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb); 69200a708f8fSGustavo F. Padovan break; 69210a708f8fSGustavo F. Padovan 6922a2877629SMarcel Holtmann case L2CAP_CID_LE_SIGNALING: 6923a2877629SMarcel Holtmann l2cap_le_sig_channel(conn, skb); 6924a2877629SMarcel Holtmann break; 6925a2877629SMarcel Holtmann 69260a708f8fSGustavo F. Padovan default: 69270a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb); 69280a708f8fSGustavo F. Padovan break; 69290a708f8fSGustavo F. Padovan } 69300a708f8fSGustavo F. Padovan } 69310a708f8fSGustavo F. Padovan 693261a939c6SJohan Hedberg static void process_pending_rx(struct work_struct *work) 693361a939c6SJohan Hedberg { 693461a939c6SJohan Hedberg struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 693561a939c6SJohan Hedberg pending_rx_work); 693661a939c6SJohan Hedberg struct sk_buff *skb; 693761a939c6SJohan Hedberg 693861a939c6SJohan Hedberg BT_DBG(""); 693961a939c6SJohan Hedberg 694061a939c6SJohan Hedberg while ((skb = skb_dequeue(&conn->pending_rx))) 694161a939c6SJohan Hedberg l2cap_recv_frame(conn, skb); 694261a939c6SJohan Hedberg } 694361a939c6SJohan Hedberg 6944162b49e7SJohan Hedberg static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) 6945162b49e7SJohan Hedberg { 6946162b49e7SJohan Hedberg struct l2cap_conn *conn = hcon->l2cap_data; 6947162b49e7SJohan Hedberg struct hci_chan *hchan; 6948162b49e7SJohan Hedberg 6949162b49e7SJohan Hedberg if (conn) 6950162b49e7SJohan Hedberg return conn; 6951162b49e7SJohan Hedberg 6952162b49e7SJohan Hedberg hchan = hci_chan_create(hcon); 6953162b49e7SJohan Hedberg if (!hchan) 6954162b49e7SJohan Hedberg return NULL; 6955162b49e7SJohan Hedberg 695627f70f3eSJohan Hedberg conn = kzalloc(sizeof(*conn), GFP_KERNEL); 6957162b49e7SJohan Hedberg if (!conn) { 6958162b49e7SJohan Hedberg hci_chan_del(hchan); 6959162b49e7SJohan Hedberg return NULL; 6960162b49e7SJohan Hedberg } 6961162b49e7SJohan Hedberg 6962162b49e7SJohan Hedberg kref_init(&conn->ref); 6963162b49e7SJohan Hedberg hcon->l2cap_data = conn; 696451bb8457SJohan Hedberg conn->hcon = hci_conn_get(hcon); 6965162b49e7SJohan Hedberg conn->hchan = hchan; 6966162b49e7SJohan Hedberg 6967162b49e7SJohan Hedberg BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); 6968162b49e7SJohan Hedberg 6969162b49e7SJohan Hedberg switch (hcon->type) { 6970162b49e7SJohan Hedberg case LE_LINK: 6971162b49e7SJohan Hedberg if (hcon->hdev->le_mtu) { 6972162b49e7SJohan Hedberg conn->mtu = hcon->hdev->le_mtu; 6973162b49e7SJohan Hedberg break; 6974162b49e7SJohan Hedberg } 6975162b49e7SJohan Hedberg /* fall through */ 6976162b49e7SJohan Hedberg default: 6977162b49e7SJohan Hedberg conn->mtu = hcon->hdev->acl_mtu; 6978162b49e7SJohan Hedberg break; 6979162b49e7SJohan Hedberg } 6980162b49e7SJohan Hedberg 6981162b49e7SJohan Hedberg conn->feat_mask = 0; 6982162b49e7SJohan Hedberg 69830bd49fc7SJohan Hedberg conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS; 69840bd49fc7SJohan Hedberg 69850bd49fc7SJohan Hedberg if (hcon->type == ACL_LINK && 6986d7a5a11dSMarcel Holtmann hci_dev_test_flag(hcon->hdev, HCI_HS_ENABLED)) 69870bd49fc7SJohan Hedberg conn->local_fixed_chan |= L2CAP_FC_A2MP; 6988162b49e7SJohan Hedberg 6989d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED) && 6990f9be9e86SMarcel Holtmann (bredr_sc_enabled(hcon->hdev) || 6991b7cb93e5SMarcel Holtmann hci_dev_test_flag(hcon->hdev, HCI_FORCE_BREDR_SMP))) 6992b5ae344dSJohan Hedberg conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR; 6993b5ae344dSJohan Hedberg 69945a54e7c8SMarcel Holtmann mutex_init(&conn->ident_lock); 6995162b49e7SJohan Hedberg mutex_init(&conn->chan_lock); 6996162b49e7SJohan Hedberg 6997162b49e7SJohan Hedberg INIT_LIST_HEAD(&conn->chan_l); 6998162b49e7SJohan Hedberg INIT_LIST_HEAD(&conn->users); 6999162b49e7SJohan Hedberg 7000162b49e7SJohan Hedberg INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); 7001162b49e7SJohan Hedberg 700261a939c6SJohan Hedberg skb_queue_head_init(&conn->pending_rx); 700361a939c6SJohan Hedberg INIT_WORK(&conn->pending_rx_work, process_pending_rx); 7004f3d82d0cSJohan Hedberg INIT_WORK(&conn->id_addr_update_work, l2cap_conn_update_id_addr); 700561a939c6SJohan Hedberg 7006162b49e7SJohan Hedberg conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 7007162b49e7SJohan Hedberg 7008162b49e7SJohan Hedberg return conn; 7009162b49e7SJohan Hedberg } 7010162b49e7SJohan Hedberg 7011162b49e7SJohan Hedberg static bool is_valid_psm(u16 psm, u8 dst_type) { 7012162b49e7SJohan Hedberg if (!psm) 7013162b49e7SJohan Hedberg return false; 7014162b49e7SJohan Hedberg 7015162b49e7SJohan Hedberg if (bdaddr_type_is_le(dst_type)) 7016162b49e7SJohan Hedberg return (psm <= 0x00ff); 7017162b49e7SJohan Hedberg 7018162b49e7SJohan Hedberg /* PSM must be odd and lsb of upper byte must be 0 */ 7019162b49e7SJohan Hedberg return ((psm & 0x0101) == 0x0001); 7020162b49e7SJohan Hedberg } 7021162b49e7SJohan Hedberg 7022162b49e7SJohan Hedberg int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, 7023162b49e7SJohan Hedberg bdaddr_t *dst, u8 dst_type) 7024162b49e7SJohan Hedberg { 7025162b49e7SJohan Hedberg struct l2cap_conn *conn; 7026162b49e7SJohan Hedberg struct hci_conn *hcon; 7027162b49e7SJohan Hedberg struct hci_dev *hdev; 7028162b49e7SJohan Hedberg int err; 7029162b49e7SJohan Hedberg 7030162b49e7SJohan Hedberg BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst, 7031162b49e7SJohan Hedberg dst_type, __le16_to_cpu(psm)); 7032162b49e7SJohan Hedberg 7033162b49e7SJohan Hedberg hdev = hci_get_route(dst, &chan->src); 7034162b49e7SJohan Hedberg if (!hdev) 7035162b49e7SJohan Hedberg return -EHOSTUNREACH; 7036162b49e7SJohan Hedberg 7037162b49e7SJohan Hedberg hci_dev_lock(hdev); 7038162b49e7SJohan Hedberg 7039162b49e7SJohan Hedberg if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid && 7040162b49e7SJohan Hedberg chan->chan_type != L2CAP_CHAN_RAW) { 7041162b49e7SJohan Hedberg err = -EINVAL; 7042162b49e7SJohan Hedberg goto done; 7043162b49e7SJohan Hedberg } 7044162b49e7SJohan Hedberg 704521626e62SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !psm) { 704621626e62SJohan Hedberg err = -EINVAL; 704721626e62SJohan Hedberg goto done; 704821626e62SJohan Hedberg } 704921626e62SJohan Hedberg 705021626e62SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_FIXED && !cid) { 7051162b49e7SJohan Hedberg err = -EINVAL; 7052162b49e7SJohan Hedberg goto done; 7053162b49e7SJohan Hedberg } 7054162b49e7SJohan Hedberg 7055162b49e7SJohan Hedberg switch (chan->mode) { 7056162b49e7SJohan Hedberg case L2CAP_MODE_BASIC: 7057162b49e7SJohan Hedberg break; 7058162b49e7SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 7059162b49e7SJohan Hedberg l2cap_le_flowctl_init(chan); 7060162b49e7SJohan Hedberg break; 7061162b49e7SJohan Hedberg case L2CAP_MODE_ERTM: 7062162b49e7SJohan Hedberg case L2CAP_MODE_STREAMING: 7063162b49e7SJohan Hedberg if (!disable_ertm) 7064162b49e7SJohan Hedberg break; 7065162b49e7SJohan Hedberg /* fall through */ 7066162b49e7SJohan Hedberg default: 7067beb19e4cSJohan Hedberg err = -EOPNOTSUPP; 7068162b49e7SJohan Hedberg goto done; 7069162b49e7SJohan Hedberg } 7070162b49e7SJohan Hedberg 7071162b49e7SJohan Hedberg switch (chan->state) { 7072162b49e7SJohan Hedberg case BT_CONNECT: 7073162b49e7SJohan Hedberg case BT_CONNECT2: 7074162b49e7SJohan Hedberg case BT_CONFIG: 7075162b49e7SJohan Hedberg /* Already connecting */ 7076162b49e7SJohan Hedberg err = 0; 7077162b49e7SJohan Hedberg goto done; 7078162b49e7SJohan Hedberg 7079162b49e7SJohan Hedberg case BT_CONNECTED: 7080162b49e7SJohan Hedberg /* Already connected */ 7081162b49e7SJohan Hedberg err = -EISCONN; 7082162b49e7SJohan Hedberg goto done; 7083162b49e7SJohan Hedberg 7084162b49e7SJohan Hedberg case BT_OPEN: 7085162b49e7SJohan Hedberg case BT_BOUND: 7086162b49e7SJohan Hedberg /* Can connect */ 7087162b49e7SJohan Hedberg break; 7088162b49e7SJohan Hedberg 7089162b49e7SJohan Hedberg default: 7090162b49e7SJohan Hedberg err = -EBADFD; 7091162b49e7SJohan Hedberg goto done; 7092162b49e7SJohan Hedberg } 7093162b49e7SJohan Hedberg 7094162b49e7SJohan Hedberg /* Set destination address and psm */ 7095162b49e7SJohan Hedberg bacpy(&chan->dst, dst); 7096162b49e7SJohan Hedberg chan->dst_type = dst_type; 7097162b49e7SJohan Hedberg 7098162b49e7SJohan Hedberg chan->psm = psm; 7099162b49e7SJohan Hedberg chan->dcid = cid; 7100162b49e7SJohan Hedberg 71016f77d8c7SAndre Guedes if (bdaddr_type_is_le(dst_type)) { 7102e804d25dSJohan Hedberg u8 role; 7103cdd6275eSJohan Hedberg 71046f77d8c7SAndre Guedes /* Convert from L2CAP channel address type to HCI address type 71056f77d8c7SAndre Guedes */ 71066f77d8c7SAndre Guedes if (dst_type == BDADDR_LE_PUBLIC) 71076f77d8c7SAndre Guedes dst_type = ADDR_LE_DEV_PUBLIC; 71086f77d8c7SAndre Guedes else 71096f77d8c7SAndre Guedes dst_type = ADDR_LE_DEV_RANDOM; 71106f77d8c7SAndre Guedes 7111d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) 7112e804d25dSJohan Hedberg role = HCI_ROLE_SLAVE; 7113e804d25dSJohan Hedberg else 7114e804d25dSJohan Hedberg role = HCI_ROLE_MASTER; 7115cdd6275eSJohan Hedberg 711604a6c589SAndre Guedes hcon = hci_connect_le(hdev, dst, dst_type, chan->sec_level, 7117e804d25dSJohan Hedberg HCI_LE_CONN_TIMEOUT, role); 71186f77d8c7SAndre Guedes } else { 7119d93375a8SJohan Hedberg u8 auth_type = l2cap_get_auth_type(chan); 712004a6c589SAndre Guedes hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type); 71216f77d8c7SAndre Guedes } 7122162b49e7SJohan Hedberg 7123162b49e7SJohan Hedberg if (IS_ERR(hcon)) { 7124162b49e7SJohan Hedberg err = PTR_ERR(hcon); 7125162b49e7SJohan Hedberg goto done; 7126162b49e7SJohan Hedberg } 7127162b49e7SJohan Hedberg 7128162b49e7SJohan Hedberg conn = l2cap_conn_add(hcon); 7129162b49e7SJohan Hedberg if (!conn) { 7130162b49e7SJohan Hedberg hci_conn_drop(hcon); 7131162b49e7SJohan Hedberg err = -ENOMEM; 7132162b49e7SJohan Hedberg goto done; 7133162b49e7SJohan Hedberg } 7134162b49e7SJohan Hedberg 713502e246aeSJohan Hedberg mutex_lock(&conn->chan_lock); 713602e246aeSJohan Hedberg l2cap_chan_lock(chan); 713702e246aeSJohan Hedberg 7138162b49e7SJohan Hedberg if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { 7139162b49e7SJohan Hedberg hci_conn_drop(hcon); 7140162b49e7SJohan Hedberg err = -EBUSY; 714102e246aeSJohan Hedberg goto chan_unlock; 7142162b49e7SJohan Hedberg } 7143162b49e7SJohan Hedberg 7144162b49e7SJohan Hedberg /* Update source addr of the socket */ 7145162b49e7SJohan Hedberg bacpy(&chan->src, &hcon->src); 7146a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(hcon); 7147162b49e7SJohan Hedberg 714802e246aeSJohan Hedberg __l2cap_chan_add(conn, chan); 7149162b49e7SJohan Hedberg 7150162b49e7SJohan Hedberg /* l2cap_chan_add takes its own ref so we can drop this one */ 7151162b49e7SJohan Hedberg hci_conn_drop(hcon); 7152162b49e7SJohan Hedberg 7153162b49e7SJohan Hedberg l2cap_state_change(chan, BT_CONNECT); 7154162b49e7SJohan Hedberg __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 7155162b49e7SJohan Hedberg 715661202e4dSJohan Hedberg /* Release chan->sport so that it can be reused by other 715761202e4dSJohan Hedberg * sockets (as it's only used for listening sockets). 715861202e4dSJohan Hedberg */ 715961202e4dSJohan Hedberg write_lock(&chan_list_lock); 716061202e4dSJohan Hedberg chan->sport = 0; 716161202e4dSJohan Hedberg write_unlock(&chan_list_lock); 716261202e4dSJohan Hedberg 7163162b49e7SJohan Hedberg if (hcon->state == BT_CONNECTED) { 7164162b49e7SJohan Hedberg if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 7165162b49e7SJohan Hedberg __clear_chan_timer(chan); 7166e7cafc45SJohan Hedberg if (l2cap_chan_check_security(chan, true)) 7167162b49e7SJohan Hedberg l2cap_state_change(chan, BT_CONNECTED); 7168162b49e7SJohan Hedberg } else 7169162b49e7SJohan Hedberg l2cap_do_start(chan); 7170162b49e7SJohan Hedberg } 7171162b49e7SJohan Hedberg 7172162b49e7SJohan Hedberg err = 0; 7173162b49e7SJohan Hedberg 717402e246aeSJohan Hedberg chan_unlock: 7175162b49e7SJohan Hedberg l2cap_chan_unlock(chan); 717602e246aeSJohan Hedberg mutex_unlock(&conn->chan_lock); 717702e246aeSJohan Hedberg done: 7178162b49e7SJohan Hedberg hci_dev_unlock(hdev); 7179162b49e7SJohan Hedberg hci_dev_put(hdev); 7180162b49e7SJohan Hedberg return err; 7181162b49e7SJohan Hedberg } 71826b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_connect); 7183162b49e7SJohan Hedberg 71840a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */ 71850a708f8fSGustavo F. Padovan 7186686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) 71870a708f8fSGustavo F. Padovan { 71880a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0; 718923691d75SGustavo F. Padovan struct l2cap_chan *c; 71900a708f8fSGustavo F. Padovan 71916ed93dc6SAndrei Emeltchenko BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr); 71920a708f8fSGustavo F. Padovan 71930a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */ 719423691d75SGustavo F. Padovan read_lock(&chan_list_lock); 719523691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 719689bc500eSGustavo F. Padovan if (c->state != BT_LISTEN) 71970a708f8fSGustavo F. Padovan continue; 71980a708f8fSGustavo F. Padovan 71997eafc59eSMarcel Holtmann if (!bacmp(&c->src, &hdev->bdaddr)) { 72000a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT; 720143bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 72020a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER; 72030a708f8fSGustavo F. Padovan exact++; 72047eafc59eSMarcel Holtmann } else if (!bacmp(&c->src, BDADDR_ANY)) { 72050a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT; 720643bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 72070a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER; 72080a708f8fSGustavo F. Padovan } 72090a708f8fSGustavo F. Padovan } 721023691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 72110a708f8fSGustavo F. Padovan 72120a708f8fSGustavo F. Padovan return exact ? lm1 : lm2; 72130a708f8fSGustavo F. Padovan } 72140a708f8fSGustavo F. Padovan 7215e760ec12SJohan Hedberg /* Find the next fixed channel in BT_LISTEN state, continue iteration 7216e760ec12SJohan Hedberg * from an existing channel in the list or from the beginning of the 7217e760ec12SJohan Hedberg * global list (by passing NULL as first parameter). 7218e760ec12SJohan Hedberg */ 7219e760ec12SJohan Hedberg static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c, 7220327a7191SJohan Hedberg struct hci_conn *hcon) 7221e760ec12SJohan Hedberg { 7222327a7191SJohan Hedberg u8 src_type = bdaddr_src_type(hcon); 7223327a7191SJohan Hedberg 7224e760ec12SJohan Hedberg read_lock(&chan_list_lock); 7225e760ec12SJohan Hedberg 7226e760ec12SJohan Hedberg if (c) 7227e760ec12SJohan Hedberg c = list_next_entry(c, global_l); 7228e760ec12SJohan Hedberg else 7229e760ec12SJohan Hedberg c = list_entry(chan_list.next, typeof(*c), global_l); 7230e760ec12SJohan Hedberg 7231e760ec12SJohan Hedberg list_for_each_entry_from(c, &chan_list, global_l) { 7232e760ec12SJohan Hedberg if (c->chan_type != L2CAP_CHAN_FIXED) 7233e760ec12SJohan Hedberg continue; 7234e760ec12SJohan Hedberg if (c->state != BT_LISTEN) 7235e760ec12SJohan Hedberg continue; 7236327a7191SJohan Hedberg if (bacmp(&c->src, &hcon->src) && bacmp(&c->src, BDADDR_ANY)) 7237e760ec12SJohan Hedberg continue; 7238327a7191SJohan Hedberg if (src_type != c->src_type) 723954a1b626SJohan Hedberg continue; 7240e760ec12SJohan Hedberg 7241e760ec12SJohan Hedberg l2cap_chan_hold(c); 7242e760ec12SJohan Hedberg read_unlock(&chan_list_lock); 7243e760ec12SJohan Hedberg return c; 7244e760ec12SJohan Hedberg } 7245e760ec12SJohan Hedberg 7246e760ec12SJohan Hedberg read_unlock(&chan_list_lock); 7247e760ec12SJohan Hedberg 7248e760ec12SJohan Hedberg return NULL; 7249e760ec12SJohan Hedberg } 7250e760ec12SJohan Hedberg 7251539c496dSJohan Hedberg static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) 72520a708f8fSGustavo F. Padovan { 7253e760ec12SJohan Hedberg struct hci_dev *hdev = hcon->hdev; 72540a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 7255e760ec12SJohan Hedberg struct l2cap_chan *pchan; 7256e760ec12SJohan Hedberg u8 dst_type; 72570a708f8fSGustavo F. Padovan 7258539c496dSJohan Hedberg if (hcon->type != ACL_LINK && hcon->type != LE_LINK) 7259539c496dSJohan Hedberg return; 7260539c496dSJohan Hedberg 72616ed93dc6SAndrei Emeltchenko BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status); 72620a708f8fSGustavo F. Padovan 7263dc0f5088SJohan Hedberg if (status) { 7264e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status)); 7265dc0f5088SJohan Hedberg return; 7266ba6fc317SAndrei Emeltchenko } 7267dc0f5088SJohan Hedberg 7268dc0f5088SJohan Hedberg conn = l2cap_conn_add(hcon); 7269dc0f5088SJohan Hedberg if (!conn) 7270dc0f5088SJohan Hedberg return; 7271dc0f5088SJohan Hedberg 7272a250e048SJohan Hedberg dst_type = bdaddr_dst_type(hcon); 7273e760ec12SJohan Hedberg 7274e760ec12SJohan Hedberg /* If device is blocked, do not create channels for it */ 7275e760ec12SJohan Hedberg if (hci_bdaddr_list_lookup(&hdev->blacklist, &hcon->dst, dst_type)) 7276e760ec12SJohan Hedberg return; 7277e760ec12SJohan Hedberg 7278e760ec12SJohan Hedberg /* Find fixed channels and notify them of the new connection. We 7279e760ec12SJohan Hedberg * use multiple individual lookups, continuing each time where 7280e760ec12SJohan Hedberg * we left off, because the list lock would prevent calling the 7281e760ec12SJohan Hedberg * potentially sleeping l2cap_chan_lock() function. 7282e760ec12SJohan Hedberg */ 7283327a7191SJohan Hedberg pchan = l2cap_global_fixed_chan(NULL, hcon); 7284e760ec12SJohan Hedberg while (pchan) { 7285e760ec12SJohan Hedberg struct l2cap_chan *chan, *next; 7286e760ec12SJohan Hedberg 7287e760ec12SJohan Hedberg /* Client fixed channels should override server ones */ 7288e760ec12SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, pchan->scid)) 7289e760ec12SJohan Hedberg goto next; 7290e760ec12SJohan Hedberg 7291e760ec12SJohan Hedberg l2cap_chan_lock(pchan); 7292e760ec12SJohan Hedberg chan = pchan->ops->new_connection(pchan); 7293e760ec12SJohan Hedberg if (chan) { 7294e760ec12SJohan Hedberg bacpy(&chan->src, &hcon->src); 7295e760ec12SJohan Hedberg bacpy(&chan->dst, &hcon->dst); 7296a250e048SJohan Hedberg chan->src_type = bdaddr_src_type(hcon); 7297e760ec12SJohan Hedberg chan->dst_type = dst_type; 7298e760ec12SJohan Hedberg 7299e760ec12SJohan Hedberg __l2cap_chan_add(conn, chan); 7300e760ec12SJohan Hedberg } 7301e760ec12SJohan Hedberg 7302e760ec12SJohan Hedberg l2cap_chan_unlock(pchan); 7303e760ec12SJohan Hedberg next: 7304327a7191SJohan Hedberg next = l2cap_global_fixed_chan(pchan, hcon); 7305e760ec12SJohan Hedberg l2cap_chan_put(pchan); 7306e760ec12SJohan Hedberg pchan = next; 7307e760ec12SJohan Hedberg } 7308e760ec12SJohan Hedberg 7309dc0f5088SJohan Hedberg l2cap_conn_ready(conn); 73100a708f8fSGustavo F. Padovan } 73110a708f8fSGustavo F. Padovan 7312686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon) 73130a708f8fSGustavo F. Padovan { 73140a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 73150a708f8fSGustavo F. Padovan 73160a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon); 73170a708f8fSGustavo F. Padovan 7318686ebf28SUlisses Furquim if (!conn) 73199f5a0d7bSAndrei Emeltchenko return HCI_ERROR_REMOTE_USER_TERM; 73200a708f8fSGustavo F. Padovan return conn->disc_reason; 73210a708f8fSGustavo F. Padovan } 73220a708f8fSGustavo F. Padovan 73233a6d576bSJohan Hedberg static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) 73240a708f8fSGustavo F. Padovan { 73253a6d576bSJohan Hedberg if (hcon->type != ACL_LINK && hcon->type != LE_LINK) 73263a6d576bSJohan Hedberg return; 73273a6d576bSJohan Hedberg 73280a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason); 73290a708f8fSGustavo F. Padovan 7330e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason)); 73310a708f8fSGustavo F. Padovan } 73320a708f8fSGustavo F. Padovan 73334343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) 73340a708f8fSGustavo F. Padovan { 7335715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 73360a708f8fSGustavo F. Padovan return; 73370a708f8fSGustavo F. Padovan 73380a708f8fSGustavo F. Padovan if (encrypt == 0x00) { 73394343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) { 7340ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); 73417d513e92SMarcel Holtmann } else if (chan->sec_level == BT_SECURITY_HIGH || 73427d513e92SMarcel Holtmann chan->sec_level == BT_SECURITY_FIPS) 73430f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED); 73440a708f8fSGustavo F. Padovan } else { 73454343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) 7346c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 73470a708f8fSGustavo F. Padovan } 73480a708f8fSGustavo F. Padovan } 73490a708f8fSGustavo F. Padovan 7350354fe804SJohan Hedberg static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) 73510a708f8fSGustavo F. Padovan { 73520a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 735348454079SGustavo F. Padovan struct l2cap_chan *chan; 73540a708f8fSGustavo F. Padovan 73550a708f8fSGustavo F. Padovan if (!conn) 7356354fe804SJohan Hedberg return; 73570a708f8fSGustavo F. Padovan 735889d8b407SAndrei Emeltchenko BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt); 73590a708f8fSGustavo F. Padovan 73603df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 73610a708f8fSGustavo F. Padovan 73623df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 73636be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 73640a708f8fSGustavo F. Padovan 736589d8b407SAndrei Emeltchenko BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, 736689d8b407SAndrei Emeltchenko state_to_string(chan->state)); 7367f1cb9af5SVinicius Costa Gomes 73682338a7e0SJohan Hedberg if (chan->scid == L2CAP_CID_A2MP) { 736978eb2f98SAndrei Emeltchenko l2cap_chan_unlock(chan); 737078eb2f98SAndrei Emeltchenko continue; 737178eb2f98SAndrei Emeltchenko } 737278eb2f98SAndrei Emeltchenko 7373191eb398SJohan Hedberg if (!status && encrypt) 7374f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level; 7375f1cb9af5SVinicius Costa Gomes 737696eff46eSAndrei Emeltchenko if (!__l2cap_no_conn_pending(chan)) { 73776be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 73780a708f8fSGustavo F. Padovan continue; 73790a708f8fSGustavo F. Padovan } 73800a708f8fSGustavo F. Padovan 738189bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED || 738289bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) { 7383d97c899bSMarcel Holtmann chan->ops->resume(chan); 73844343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt); 73856be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 73860a708f8fSGustavo F. Padovan continue; 73870a708f8fSGustavo F. Padovan } 73880a708f8fSGustavo F. Padovan 738989bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 73906d3c15daSJohan Hedberg if (!status) 739193c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 73926d3c15daSJohan Hedberg else 7393ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 7394fa37c1aaSJohan Hedberg } else if (chan->state == BT_CONNECT2 && 7395fa37c1aaSJohan Hedberg chan->mode != L2CAP_MODE_LE_FLOWCTL) { 73960a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 7397df3c3931SJohan Hedberg __u16 res, stat; 73980a708f8fSGustavo F. Padovan 73990a708f8fSGustavo F. Padovan if (!status) { 7400bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 7401df3c3931SJohan Hedberg res = L2CAP_CR_PEND; 7402df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND; 74032dc4e510SGustavo Padovan chan->ops->defer(chan); 7404df3c3931SJohan Hedberg } else { 7405acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 7406df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS; 7407df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 7408df3c3931SJohan Hedberg } 74090a708f8fSGustavo F. Padovan } else { 7410acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_DISCONN); 7411ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 7412df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK; 7413df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 74140a708f8fSGustavo F. Padovan } 74150a708f8fSGustavo F. Padovan 7416fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 7417fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 7418df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res); 7419df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat); 7420fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 7421fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 74222d369359SMat Martineau 74232d369359SMat Martineau if (!test_bit(CONF_REQ_SENT, &chan->conf_state) && 74242d369359SMat Martineau res == L2CAP_CR_SUCCESS) { 74252d369359SMat Martineau char buf[128]; 74262d369359SMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 74272d369359SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), 74282d369359SMat Martineau L2CAP_CONF_REQ, 74292d369359SMat Martineau l2cap_build_conf_req(chan, buf), 74302d369359SMat Martineau buf); 74312d369359SMat Martineau chan->num_conf_req++; 74322d369359SMat Martineau } 74330a708f8fSGustavo F. Padovan } 74340a708f8fSGustavo F. Padovan 74356be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 74360a708f8fSGustavo F. Padovan } 74370a708f8fSGustavo F. Padovan 74383df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 74390a708f8fSGustavo F. Padovan } 74400a708f8fSGustavo F. Padovan 74419b4c3336SArron Wang void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) 74420a708f8fSGustavo F. Padovan { 74430a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 7444d73a0988SAndrei Emeltchenko struct l2cap_hdr *hdr; 7445d73a0988SAndrei Emeltchenko int len; 74460a708f8fSGustavo F. Padovan 74471d13a254SAndrei Emeltchenko /* For AMP controller do not create l2cap conn */ 74481d13a254SAndrei Emeltchenko if (!conn && hcon->hdev->dev_type != HCI_BREDR) 74491d13a254SAndrei Emeltchenko goto drop; 74500a708f8fSGustavo F. Padovan 74510a708f8fSGustavo F. Padovan if (!conn) 7452baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon); 74530a708f8fSGustavo F. Padovan 74540a708f8fSGustavo F. Padovan if (!conn) 74550a708f8fSGustavo F. Padovan goto drop; 74560a708f8fSGustavo F. Padovan 74570a708f8fSGustavo F. Padovan BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); 74580a708f8fSGustavo F. Padovan 7459d73a0988SAndrei Emeltchenko switch (flags) { 7460d73a0988SAndrei Emeltchenko case ACL_START: 7461d73a0988SAndrei Emeltchenko case ACL_START_NO_FLUSH: 7462d73a0988SAndrei Emeltchenko case ACL_COMPLETE: 74630a708f8fSGustavo F. Padovan if (conn->rx_len) { 74640a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len); 74650a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 74660a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 74670a708f8fSGustavo F. Padovan conn->rx_len = 0; 74680a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 74690a708f8fSGustavo F. Padovan } 74700a708f8fSGustavo F. Padovan 74710a708f8fSGustavo F. Padovan /* Start fragment always begin with Basic L2CAP header */ 74720a708f8fSGustavo F. Padovan if (skb->len < L2CAP_HDR_SIZE) { 74730a708f8fSGustavo F. Padovan BT_ERR("Frame is too short (len %d)", skb->len); 74740a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 74750a708f8fSGustavo F. Padovan goto drop; 74760a708f8fSGustavo F. Padovan } 74770a708f8fSGustavo F. Padovan 74780a708f8fSGustavo F. Padovan hdr = (struct l2cap_hdr *) skb->data; 74790a708f8fSGustavo F. Padovan len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; 74800a708f8fSGustavo F. Padovan 74810a708f8fSGustavo F. Padovan if (len == skb->len) { 74820a708f8fSGustavo F. Padovan /* Complete frame received */ 74830a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb); 74849b4c3336SArron Wang return; 74850a708f8fSGustavo F. Padovan } 74860a708f8fSGustavo F. Padovan 74870a708f8fSGustavo F. Padovan BT_DBG("Start: total len %d, frag len %d", len, skb->len); 74880a708f8fSGustavo F. Padovan 74890a708f8fSGustavo F. Padovan if (skb->len > len) { 74900a708f8fSGustavo F. Padovan BT_ERR("Frame is too long (len %d, expected len %d)", 74910a708f8fSGustavo F. Padovan skb->len, len); 74920a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 74930a708f8fSGustavo F. Padovan goto drop; 74940a708f8fSGustavo F. Padovan } 74950a708f8fSGustavo F. Padovan 74960a708f8fSGustavo F. Padovan /* Allocate skb for the complete frame (with header) */ 74978bcde1f2SGustavo Padovan conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL); 74980a708f8fSGustavo F. Padovan if (!conn->rx_skb) 74990a708f8fSGustavo F. Padovan goto drop; 75000a708f8fSGustavo F. Padovan 75010a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 75020a708f8fSGustavo F. Padovan skb->len); 75030a708f8fSGustavo F. Padovan conn->rx_len = len - skb->len; 7504d73a0988SAndrei Emeltchenko break; 7505d73a0988SAndrei Emeltchenko 7506d73a0988SAndrei Emeltchenko case ACL_CONT: 75070a708f8fSGustavo F. Padovan BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); 75080a708f8fSGustavo F. Padovan 75090a708f8fSGustavo F. Padovan if (!conn->rx_len) { 75100a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len); 75110a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 75120a708f8fSGustavo F. Padovan goto drop; 75130a708f8fSGustavo F. Padovan } 75140a708f8fSGustavo F. Padovan 75150a708f8fSGustavo F. Padovan if (skb->len > conn->rx_len) { 75160a708f8fSGustavo F. Padovan BT_ERR("Fragment is too long (len %d, expected %d)", 75170a708f8fSGustavo F. Padovan skb->len, conn->rx_len); 75180a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 75190a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 75200a708f8fSGustavo F. Padovan conn->rx_len = 0; 75210a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 75220a708f8fSGustavo F. Padovan goto drop; 75230a708f8fSGustavo F. Padovan } 75240a708f8fSGustavo F. Padovan 75250a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 75260a708f8fSGustavo F. Padovan skb->len); 75270a708f8fSGustavo F. Padovan conn->rx_len -= skb->len; 75280a708f8fSGustavo F. Padovan 75290a708f8fSGustavo F. Padovan if (!conn->rx_len) { 7530c4e5bafaSJohan Hedberg /* Complete frame received. l2cap_recv_frame 7531c4e5bafaSJohan Hedberg * takes ownership of the skb so set the global 7532c4e5bafaSJohan Hedberg * rx_skb pointer to NULL first. 7533c4e5bafaSJohan Hedberg */ 7534c4e5bafaSJohan Hedberg struct sk_buff *rx_skb = conn->rx_skb; 75350a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 7536c4e5bafaSJohan Hedberg l2cap_recv_frame(conn, rx_skb); 75370a708f8fSGustavo F. Padovan } 7538d73a0988SAndrei Emeltchenko break; 75390a708f8fSGustavo F. Padovan } 75400a708f8fSGustavo F. Padovan 75410a708f8fSGustavo F. Padovan drop: 75420a708f8fSGustavo F. Padovan kfree_skb(skb); 75430a708f8fSGustavo F. Padovan } 75440a708f8fSGustavo F. Padovan 7545354fe804SJohan Hedberg static struct hci_cb l2cap_cb = { 7546354fe804SJohan Hedberg .name = "L2CAP", 7547539c496dSJohan Hedberg .connect_cfm = l2cap_connect_cfm, 75483a6d576bSJohan Hedberg .disconn_cfm = l2cap_disconn_cfm, 7549354fe804SJohan Hedberg .security_cfm = l2cap_security_cfm, 7550354fe804SJohan Hedberg }; 7551354fe804SJohan Hedberg 75520a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p) 75530a708f8fSGustavo F. Padovan { 755423691d75SGustavo F. Padovan struct l2cap_chan *c; 75550a708f8fSGustavo F. Padovan 7556333055f2SGustavo F. Padovan read_lock(&chan_list_lock); 75570a708f8fSGustavo F. Padovan 755823691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 7559eeb5a067SMarcel Holtmann seq_printf(f, "%pMR (%u) %pMR (%u) %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", 7560eeb5a067SMarcel Holtmann &c->src, c->src_type, &c->dst, c->dst_type, 756189bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm), 756223691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu, 756323691d75SGustavo F. Padovan c->sec_level, c->mode); 75640a708f8fSGustavo F. Padovan } 75650a708f8fSGustavo F. Padovan 7566333055f2SGustavo F. Padovan read_unlock(&chan_list_lock); 75670a708f8fSGustavo F. Padovan 75680a708f8fSGustavo F. Padovan return 0; 75690a708f8fSGustavo F. Padovan } 75700a708f8fSGustavo F. Padovan 75710a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file) 75720a708f8fSGustavo F. Padovan { 75730a708f8fSGustavo F. Padovan return single_open(file, l2cap_debugfs_show, inode->i_private); 75740a708f8fSGustavo F. Padovan } 75750a708f8fSGustavo F. Padovan 75760a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = { 75770a708f8fSGustavo F. Padovan .open = l2cap_debugfs_open, 75780a708f8fSGustavo F. Padovan .read = seq_read, 75790a708f8fSGustavo F. Padovan .llseek = seq_lseek, 75800a708f8fSGustavo F. Padovan .release = single_release, 75810a708f8fSGustavo F. Padovan }; 75820a708f8fSGustavo F. Padovan 75830a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs; 75840a708f8fSGustavo F. Padovan 758564274518SGustavo F. Padovan int __init l2cap_init(void) 75860a708f8fSGustavo F. Padovan { 75870a708f8fSGustavo F. Padovan int err; 75880a708f8fSGustavo F. Padovan 7589bb58f747SGustavo F. Padovan err = l2cap_init_sockets(); 75900a708f8fSGustavo F. Padovan if (err < 0) 75910a708f8fSGustavo F. Padovan return err; 75920a708f8fSGustavo F. Padovan 7593354fe804SJohan Hedberg hci_register_cb(&l2cap_cb); 7594354fe804SJohan Hedberg 75951120e4bfSMarcel Holtmann if (IS_ERR_OR_NULL(bt_debugfs)) 75961120e4bfSMarcel Holtmann return 0; 75971120e4bfSMarcel Holtmann 75982d792818SGustavo Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, 75992d792818SGustavo Padovan NULL, &l2cap_debugfs_fops); 76000a708f8fSGustavo F. Padovan 760140b9397aSSamuel Ortiz debugfs_create_u16("l2cap_le_max_credits", 0644, bt_debugfs, 7602f15b8ecfSJohan Hedberg &le_max_credits); 760340b9397aSSamuel Ortiz debugfs_create_u16("l2cap_le_default_mps", 0644, bt_debugfs, 7604f15b8ecfSJohan Hedberg &le_default_mps); 7605f15b8ecfSJohan Hedberg 76060a708f8fSGustavo F. Padovan return 0; 76070a708f8fSGustavo F. Padovan } 76080a708f8fSGustavo F. Padovan 760964274518SGustavo F. Padovan void l2cap_exit(void) 76100a708f8fSGustavo F. Padovan { 76110a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs); 7612354fe804SJohan Hedberg hci_unregister_cb(&l2cap_cb); 7613bb58f747SGustavo F. Padovan l2cap_cleanup_sockets(); 76140a708f8fSGustavo F. Padovan } 76150a708f8fSGustavo F. Padovan 76160a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644); 76170a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); 7618