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 44d1de6d46SMat Martineau bool disable_ertm; 450a708f8fSGustavo F. Padovan 46547d1032SMarcel Holtmann static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD; 47d40bffbcSMarcel Holtmann static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP | L2CAP_FC_CONNLESS, }; 480a708f8fSGustavo F. Padovan 49b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list); 50b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock); 510a708f8fSGustavo F. Padovan 520a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 530a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data); 544519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 554519de9aSGustavo F. Padovan void *data); 56710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); 575e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err); 580a708f8fSGustavo F. Padovan 59d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 60608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event); 61608bcc6dSMat Martineau 624f1654e0SMarcel Holtmann static inline __u8 bdaddr_type(struct hci_conn *hcon, __u8 type) 634f1654e0SMarcel Holtmann { 644f1654e0SMarcel Holtmann if (hcon->type == LE_LINK) { 654f1654e0SMarcel Holtmann if (type == ADDR_LE_DEV_PUBLIC) 664f1654e0SMarcel Holtmann return BDADDR_LE_PUBLIC; 674f1654e0SMarcel Holtmann else 684f1654e0SMarcel Holtmann return BDADDR_LE_RANDOM; 694f1654e0SMarcel Holtmann } 704f1654e0SMarcel Holtmann 714f1654e0SMarcel Holtmann return BDADDR_BREDR; 724f1654e0SMarcel Holtmann } 734f1654e0SMarcel Holtmann 740a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */ 7571ba0e56SGustavo F. Padovan 762d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, 772d792818SGustavo Padovan u16 cid) 780a708f8fSGustavo F. Padovan { 793df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 80baa7e1faSGustavo F. Padovan 813df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 823df91ea2SAndrei Emeltchenko if (c->dcid == cid) 833df91ea2SAndrei Emeltchenko return c; 840a708f8fSGustavo F. Padovan } 853df91ea2SAndrei Emeltchenko return NULL; 86baa7e1faSGustavo F. Padovan } 870a708f8fSGustavo F. Padovan 882d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, 892d792818SGustavo Padovan u16 cid) 900a708f8fSGustavo F. Padovan { 913df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 92baa7e1faSGustavo F. Padovan 933df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 943df91ea2SAndrei Emeltchenko if (c->scid == cid) 953df91ea2SAndrei Emeltchenko return c; 960a708f8fSGustavo F. Padovan } 973df91ea2SAndrei Emeltchenko return NULL; 98baa7e1faSGustavo F. Padovan } 990a708f8fSGustavo F. Padovan 1000a708f8fSGustavo F. Padovan /* Find channel with given SCID. 101ef191adeSMat Martineau * Returns locked channel. */ 1022d792818SGustavo Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, 1032d792818SGustavo Padovan u16 cid) 1040a708f8fSGustavo F. Padovan { 10548454079SGustavo F. Padovan struct l2cap_chan *c; 106baa7e1faSGustavo F. Padovan 1073df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 108baa7e1faSGustavo F. Padovan c = __l2cap_get_chan_by_scid(conn, cid); 109ef191adeSMat Martineau if (c) 110ef191adeSMat Martineau l2cap_chan_lock(c); 1113df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 1123df91ea2SAndrei Emeltchenko 11348454079SGustavo F. Padovan return c; 1140a708f8fSGustavo F. Padovan } 1150a708f8fSGustavo F. Padovan 116b1a130b7SMat Martineau /* Find channel with given DCID. 117b1a130b7SMat Martineau * Returns locked channel. 118b1a130b7SMat Martineau */ 119b1a130b7SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn, 120b1a130b7SMat Martineau u16 cid) 121b1a130b7SMat Martineau { 122b1a130b7SMat Martineau struct l2cap_chan *c; 123b1a130b7SMat Martineau 124b1a130b7SMat Martineau mutex_lock(&conn->chan_lock); 125b1a130b7SMat Martineau c = __l2cap_get_chan_by_dcid(conn, cid); 126b1a130b7SMat Martineau if (c) 127b1a130b7SMat Martineau l2cap_chan_lock(c); 128b1a130b7SMat Martineau mutex_unlock(&conn->chan_lock); 129b1a130b7SMat Martineau 130b1a130b7SMat Martineau return c; 131b1a130b7SMat Martineau } 132b1a130b7SMat Martineau 1332d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, 1342d792818SGustavo Padovan u8 ident) 1350a708f8fSGustavo F. Padovan { 1363df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 137baa7e1faSGustavo F. Padovan 1383df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 1393df91ea2SAndrei Emeltchenko if (c->ident == ident) 1403df91ea2SAndrei Emeltchenko return c; 1410a708f8fSGustavo F. Padovan } 1423df91ea2SAndrei Emeltchenko return NULL; 143baa7e1faSGustavo F. Padovan } 1440a708f8fSGustavo F. Padovan 1455b155ef9SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, 1465b155ef9SMat Martineau u8 ident) 1475b155ef9SMat Martineau { 1485b155ef9SMat Martineau struct l2cap_chan *c; 1495b155ef9SMat Martineau 1505b155ef9SMat Martineau mutex_lock(&conn->chan_lock); 1515b155ef9SMat Martineau c = __l2cap_get_chan_by_ident(conn, ident); 1525b155ef9SMat Martineau if (c) 1535b155ef9SMat Martineau l2cap_chan_lock(c); 1545b155ef9SMat Martineau mutex_unlock(&conn->chan_lock); 1555b155ef9SMat Martineau 1565b155ef9SMat Martineau return c; 1575b155ef9SMat Martineau } 1585b155ef9SMat Martineau 15923691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src) 1609e4425ffSGustavo F. Padovan { 16123691d75SGustavo F. Padovan struct l2cap_chan *c; 1629e4425ffSGustavo F. Padovan 16323691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 1647eafc59eSMarcel Holtmann if (c->sport == psm && !bacmp(&c->src, src)) 16523691d75SGustavo F. Padovan return c; 1669e4425ffSGustavo F. Padovan } 167250938cbSSzymon Janc return NULL; 168250938cbSSzymon Janc } 1699e4425ffSGustavo F. Padovan 1709e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) 1719e4425ffSGustavo F. Padovan { 17273b2ec18SGustavo F. Padovan int err; 17373b2ec18SGustavo F. Padovan 174333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 1759e4425ffSGustavo F. Padovan 17623691d75SGustavo F. Padovan if (psm && __l2cap_global_chan_by_addr(psm, src)) { 17773b2ec18SGustavo F. Padovan err = -EADDRINUSE; 17873b2ec18SGustavo F. Padovan goto done; 1799e4425ffSGustavo F. Padovan } 1809e4425ffSGustavo F. Padovan 18173b2ec18SGustavo F. Padovan if (psm) { 1829e4425ffSGustavo F. Padovan chan->psm = psm; 1839e4425ffSGustavo F. Padovan chan->sport = psm; 18473b2ec18SGustavo F. Padovan err = 0; 18573b2ec18SGustavo F. Padovan } else { 18673b2ec18SGustavo F. Padovan u16 p; 1879e4425ffSGustavo F. Padovan 18873b2ec18SGustavo F. Padovan err = -EINVAL; 18973b2ec18SGustavo F. Padovan for (p = 0x1001; p < 0x1100; p += 2) 19023691d75SGustavo F. Padovan if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) { 19173b2ec18SGustavo F. Padovan chan->psm = cpu_to_le16(p); 19273b2ec18SGustavo F. Padovan chan->sport = cpu_to_le16(p); 19373b2ec18SGustavo F. Padovan err = 0; 19473b2ec18SGustavo F. Padovan break; 19573b2ec18SGustavo F. Padovan } 19673b2ec18SGustavo F. Padovan } 19773b2ec18SGustavo F. Padovan 19873b2ec18SGustavo F. Padovan done: 199333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 20073b2ec18SGustavo F. Padovan return err; 2019e4425ffSGustavo F. Padovan } 2029e4425ffSGustavo F. Padovan 2039e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) 2049e4425ffSGustavo F. Padovan { 205333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 2069e4425ffSGustavo F. Padovan 2079e4425ffSGustavo F. Padovan chan->scid = scid; 2089e4425ffSGustavo F. Padovan 209333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 2109e4425ffSGustavo F. Padovan 2119e4425ffSGustavo F. Padovan return 0; 2129e4425ffSGustavo F. Padovan } 2139e4425ffSGustavo F. Padovan 214baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn) 2150a708f8fSGustavo F. Padovan { 216e77af755SJohan Hedberg u16 cid, dyn_end; 2170a708f8fSGustavo F. Padovan 218e77af755SJohan Hedberg if (conn->hcon->type == LE_LINK) 219e77af755SJohan Hedberg dyn_end = L2CAP_CID_LE_DYN_END; 220e77af755SJohan Hedberg else 221e77af755SJohan Hedberg dyn_end = L2CAP_CID_DYN_END; 222e77af755SJohan Hedberg 223e77af755SJohan Hedberg for (cid = L2CAP_CID_DYN_START; cid < dyn_end; cid++) { 224baa7e1faSGustavo F. Padovan if (!__l2cap_get_chan_by_scid(conn, cid)) 2250a708f8fSGustavo F. Padovan return cid; 2260a708f8fSGustavo F. Padovan } 2270a708f8fSGustavo F. Padovan 2280a708f8fSGustavo F. Padovan return 0; 2290a708f8fSGustavo F. Padovan } 2300a708f8fSGustavo F. Padovan 231f93fa273SGustavo Padovan static void l2cap_state_change(struct l2cap_chan *chan, int state) 23289bc500eSGustavo F. Padovan { 23342d2d87cSAndrei Emeltchenko BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state), 234badaaa00SGustavo F. Padovan state_to_string(state)); 235badaaa00SGustavo F. Padovan 23689bc500eSGustavo F. Padovan chan->state = state; 23753f52121SGustavo Padovan chan->ops->state_change(chan, state, 0); 23889bc500eSGustavo F. Padovan } 23989bc500eSGustavo F. Padovan 240f8e73017SGustavo Padovan static inline void l2cap_state_change_and_error(struct l2cap_chan *chan, 241f8e73017SGustavo Padovan int state, int err) 2422e0052e4SAndrei Emeltchenko { 243f8e73017SGustavo Padovan chan->state = state; 24453f52121SGustavo Padovan chan->ops->state_change(chan, chan->state, err); 2452e0052e4SAndrei Emeltchenko } 2462e0052e4SAndrei Emeltchenko 2472e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err) 2482e0052e4SAndrei Emeltchenko { 249f8e73017SGustavo Padovan chan->ops->state_change(chan, chan->state, err); 2502e0052e4SAndrei Emeltchenko } 2512e0052e4SAndrei Emeltchenko 2524239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan) 2534239d16fSMat Martineau { 2544239d16fSMat Martineau if (!delayed_work_pending(&chan->monitor_timer) && 2554239d16fSMat Martineau chan->retrans_timeout) { 2564239d16fSMat Martineau l2cap_set_timer(chan, &chan->retrans_timer, 2574239d16fSMat Martineau msecs_to_jiffies(chan->retrans_timeout)); 2584239d16fSMat Martineau } 2594239d16fSMat Martineau } 2604239d16fSMat Martineau 2614239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan) 2624239d16fSMat Martineau { 2634239d16fSMat Martineau __clear_retrans_timer(chan); 2644239d16fSMat Martineau if (chan->monitor_timeout) { 2654239d16fSMat Martineau l2cap_set_timer(chan, &chan->monitor_timer, 2664239d16fSMat Martineau msecs_to_jiffies(chan->monitor_timeout)); 2674239d16fSMat Martineau } 2684239d16fSMat Martineau } 2694239d16fSMat Martineau 270608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head, 271608bcc6dSMat Martineau u16 seq) 272608bcc6dSMat Martineau { 273608bcc6dSMat Martineau struct sk_buff *skb; 274608bcc6dSMat Martineau 275608bcc6dSMat Martineau skb_queue_walk(head, skb) { 276608bcc6dSMat Martineau if (bt_cb(skb)->control.txseq == seq) 277608bcc6dSMat Martineau return skb; 278608bcc6dSMat Martineau } 279608bcc6dSMat Martineau 280608bcc6dSMat Martineau return NULL; 281608bcc6dSMat Martineau } 282608bcc6dSMat Martineau 2833c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */ 2843c588192SMat Martineau 2853c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for 2863c588192SMat Martineau * SREJ requests that are received and for frames that are to be 2873c588192SMat Martineau * retransmitted. These seq_list functions implement a singly-linked 2883c588192SMat Martineau * list in an array, where membership in the list can also be checked 2893c588192SMat Martineau * in constant time. Items can also be added to the tail of the list 2903c588192SMat Martineau * and removed from the head in constant time, without further memory 2913c588192SMat Martineau * allocs or frees. 2923c588192SMat Martineau */ 2933c588192SMat Martineau 2943c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size) 2953c588192SMat Martineau { 2963c588192SMat Martineau size_t alloc_size, i; 2973c588192SMat Martineau 2983c588192SMat Martineau /* Allocated size is a power of 2 to map sequence numbers 2993c588192SMat Martineau * (which may be up to 14 bits) in to a smaller array that is 3003c588192SMat Martineau * sized for the negotiated ERTM transmit windows. 3013c588192SMat Martineau */ 3023c588192SMat Martineau alloc_size = roundup_pow_of_two(size); 3033c588192SMat Martineau 3043c588192SMat Martineau seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL); 3053c588192SMat Martineau if (!seq_list->list) 3063c588192SMat Martineau return -ENOMEM; 3073c588192SMat Martineau 3083c588192SMat Martineau seq_list->mask = alloc_size - 1; 3093c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3103c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3113c588192SMat Martineau for (i = 0; i < alloc_size; i++) 3123c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 3133c588192SMat Martineau 3143c588192SMat Martineau return 0; 3153c588192SMat Martineau } 3163c588192SMat Martineau 3173c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list) 3183c588192SMat Martineau { 3193c588192SMat Martineau kfree(seq_list->list); 3203c588192SMat Martineau } 3213c588192SMat Martineau 3223c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list, 3233c588192SMat Martineau u16 seq) 3243c588192SMat Martineau { 3253c588192SMat Martineau /* Constant-time check for list membership */ 3263c588192SMat Martineau return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR; 3273c588192SMat Martineau } 3283c588192SMat Martineau 3293c588192SMat Martineau static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq) 3303c588192SMat Martineau { 3313c588192SMat Martineau u16 mask = seq_list->mask; 3323c588192SMat Martineau 3333c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) { 3343c588192SMat Martineau /* In case someone tries to pop the head of an empty list */ 3353c588192SMat Martineau return L2CAP_SEQ_LIST_CLEAR; 3363c588192SMat Martineau } else if (seq_list->head == seq) { 3373c588192SMat Martineau /* Head can be removed in constant time */ 3383c588192SMat Martineau seq_list->head = seq_list->list[seq & mask]; 3393c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; 3403c588192SMat Martineau 3413c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_TAIL) { 3423c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3433c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3443c588192SMat Martineau } 3453c588192SMat Martineau } else { 3463c588192SMat Martineau /* Walk the list to find the sequence number */ 3473c588192SMat Martineau u16 prev = seq_list->head; 3483c588192SMat Martineau while (seq_list->list[prev & mask] != seq) { 3493c588192SMat Martineau prev = seq_list->list[prev & mask]; 3503c588192SMat Martineau if (prev == L2CAP_SEQ_LIST_TAIL) 3513c588192SMat Martineau return L2CAP_SEQ_LIST_CLEAR; 3523c588192SMat Martineau } 3533c588192SMat Martineau 3543c588192SMat Martineau /* Unlink the number from the list and clear it */ 3553c588192SMat Martineau seq_list->list[prev & mask] = seq_list->list[seq & mask]; 3563c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; 3573c588192SMat Martineau if (seq_list->tail == seq) 3583c588192SMat Martineau seq_list->tail = prev; 3593c588192SMat Martineau } 3603c588192SMat Martineau return seq; 3613c588192SMat Martineau } 3623c588192SMat Martineau 3633c588192SMat Martineau static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list) 3643c588192SMat Martineau { 3653c588192SMat Martineau /* Remove the head in constant time */ 3663c588192SMat Martineau return l2cap_seq_list_remove(seq_list, seq_list->head); 3673c588192SMat Martineau } 3683c588192SMat Martineau 3693c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list) 3703c588192SMat Martineau { 3713c588192SMat Martineau u16 i; 372f522ae36SGustavo Padovan 373f522ae36SGustavo Padovan if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) 374f522ae36SGustavo Padovan return; 375f522ae36SGustavo Padovan 3763c588192SMat Martineau for (i = 0; i <= seq_list->mask; i++) 3773c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 3783c588192SMat Martineau 3793c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3803c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3813c588192SMat Martineau } 3823c588192SMat Martineau 3833c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq) 3843c588192SMat Martineau { 3853c588192SMat Martineau u16 mask = seq_list->mask; 3863c588192SMat Martineau 3873c588192SMat Martineau /* All appends happen in constant time */ 3883c588192SMat Martineau 389f522ae36SGustavo Padovan if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR) 390f522ae36SGustavo Padovan return; 391f522ae36SGustavo Padovan 3923c588192SMat Martineau if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR) 3933c588192SMat Martineau seq_list->head = seq; 3943c588192SMat Martineau else 3953c588192SMat Martineau seq_list->list[seq_list->tail & mask] = seq; 3963c588192SMat Martineau 3973c588192SMat Martineau seq_list->tail = seq; 3983c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL; 3993c588192SMat Martineau } 4003c588192SMat Martineau 401721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work) 402ab07801dSGustavo F. Padovan { 403721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 404721c4181SGustavo F. Padovan chan_timer.work); 4053df91ea2SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 406ab07801dSGustavo F. Padovan int reason; 407ab07801dSGustavo F. Padovan 408e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 409ab07801dSGustavo F. Padovan 4103df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 4116be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 412ab07801dSGustavo F. Padovan 41389bc500eSGustavo F. Padovan if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) 414ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 41589bc500eSGustavo F. Padovan else if (chan->state == BT_CONNECT && 416ab07801dSGustavo F. Padovan chan->sec_level != BT_SECURITY_SDP) 417ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 418ab07801dSGustavo F. Padovan else 419ab07801dSGustavo F. Padovan reason = ETIMEDOUT; 420ab07801dSGustavo F. Padovan 4210f852724SGustavo F. Padovan l2cap_chan_close(chan, reason); 422ab07801dSGustavo F. Padovan 4236be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 424ab07801dSGustavo F. Padovan 42580b98027SGustavo Padovan chan->ops->close(chan); 4263df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4273df91ea2SAndrei Emeltchenko 428371fd835SUlisses Furquim l2cap_chan_put(chan); 429ab07801dSGustavo F. Padovan } 430ab07801dSGustavo F. Padovan 431eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void) 4320a708f8fSGustavo F. Padovan { 43348454079SGustavo F. Padovan struct l2cap_chan *chan; 4340a708f8fSGustavo F. Padovan 43548454079SGustavo F. Padovan chan = kzalloc(sizeof(*chan), GFP_ATOMIC); 43648454079SGustavo F. Padovan if (!chan) 43748454079SGustavo F. Padovan return NULL; 4380a708f8fSGustavo F. Padovan 439c03b355eSAndrei Emeltchenko mutex_init(&chan->lock); 440c03b355eSAndrei Emeltchenko 441333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 44223691d75SGustavo F. Padovan list_add(&chan->global_l, &chan_list); 443333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 44423691d75SGustavo F. Padovan 445721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout); 446ab07801dSGustavo F. Padovan 44789bc500eSGustavo F. Padovan chan->state = BT_OPEN; 44889bc500eSGustavo F. Padovan 449144ad330SSyam Sidhardhan kref_init(&chan->kref); 45071ba0e56SGustavo F. Padovan 4512827011fSMat Martineau /* This flag is cleared in l2cap_chan_ready() */ 4522827011fSMat Martineau set_bit(CONF_NOT_COMPLETE, &chan->conf_state); 4532827011fSMat Martineau 454eef1d9b6SGustavo Padovan BT_DBG("chan %p", chan); 455abc545b8SSzymon Janc 45648454079SGustavo F. Padovan return chan; 4570a708f8fSGustavo F. Padovan } 4580a708f8fSGustavo F. Padovan 459144ad330SSyam Sidhardhan static void l2cap_chan_destroy(struct kref *kref) 4606ff5abbfSGustavo F. Padovan { 461144ad330SSyam Sidhardhan struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref); 462144ad330SSyam Sidhardhan 4634af66c69SJaganath Kanakkassery BT_DBG("chan %p", chan); 4644af66c69SJaganath Kanakkassery 465333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 46623691d75SGustavo F. Padovan list_del(&chan->global_l); 467333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 46823691d75SGustavo F. Padovan 4694af66c69SJaganath Kanakkassery kfree(chan); 4706ff5abbfSGustavo F. Padovan } 4716ff5abbfSGustavo F. Padovan 47230648372SJaganath Kanakkassery void l2cap_chan_hold(struct l2cap_chan *c) 47330648372SJaganath Kanakkassery { 474144ad330SSyam Sidhardhan BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount)); 47530648372SJaganath Kanakkassery 476144ad330SSyam Sidhardhan kref_get(&c->kref); 47730648372SJaganath Kanakkassery } 47830648372SJaganath Kanakkassery 47930648372SJaganath Kanakkassery void l2cap_chan_put(struct l2cap_chan *c) 48030648372SJaganath Kanakkassery { 481144ad330SSyam Sidhardhan BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount)); 48230648372SJaganath Kanakkassery 483144ad330SSyam Sidhardhan kref_put(&c->kref, l2cap_chan_destroy); 48430648372SJaganath Kanakkassery } 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; 492c20f8e35SMat Martineau chan->ack_win = L2CAP_DEFAULT_TX_WINDOW; 493bd4b1653SAndrei Emeltchenko chan->sec_level = BT_SECURITY_LOW; 494bd4b1653SAndrei Emeltchenko 495bd4b1653SAndrei Emeltchenko set_bit(FLAG_FORCE_ACTIVE, &chan->flags); 496bd4b1653SAndrei Emeltchenko } 497bd4b1653SAndrei Emeltchenko 49838319713SJohan Hedberg void l2cap_le_flowctl_init(struct l2cap_chan *chan) 49938319713SJohan Hedberg { 50038319713SJohan Hedberg chan->imtu = L2CAP_DEFAULT_MTU; 50138319713SJohan Hedberg chan->omtu = L2CAP_LE_MIN_MTU; 50238319713SJohan Hedberg chan->mode = L2CAP_MODE_LE_FLOWCTL; 5030cd75f7eSJohan Hedberg chan->tx_credits = 0; 5040cd75f7eSJohan Hedberg chan->rx_credits = L2CAP_LE_MAX_CREDITS; 5053916aed8SJohan Hedberg 5063916aed8SJohan Hedberg if (chan->imtu < L2CAP_LE_DEFAULT_MPS) 5073916aed8SJohan Hedberg chan->mps = chan->imtu; 5083916aed8SJohan Hedberg else 5093916aed8SJohan Hedberg chan->mps = L2CAP_LE_DEFAULT_MPS; 51038319713SJohan Hedberg } 51138319713SJohan Hedberg 51293c3e8f5SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 5130a708f8fSGustavo F. Padovan { 5140a708f8fSGustavo F. Padovan BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, 515097db76cSAndrei Emeltchenko __le16_to_cpu(chan->psm), chan->dcid); 5160a708f8fSGustavo F. Padovan 5179f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 5180a708f8fSGustavo F. Padovan 5198c1d787bSGustavo F. Padovan chan->conn = conn; 5200a708f8fSGustavo F. Padovan 5215491120eSAndrei Emeltchenko switch (chan->chan_type) { 5225491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_ORIENTED: 523b62f328bSVille Tervo if (conn->hcon->type == LE_LINK) { 524aeddd075SJohan Hedberg if (chan->dcid == L2CAP_CID_ATT) { 5256fcb06a2SAndre Guedes chan->omtu = L2CAP_DEFAULT_MTU; 526073d1cf3SJohan Hedberg chan->scid = L2CAP_CID_ATT; 527aeddd075SJohan Hedberg } else { 5289f22398cSJohan Hedberg chan->scid = l2cap_alloc_cid(conn); 529aeddd075SJohan Hedberg } 530b62f328bSVille Tervo } else { 5310a708f8fSGustavo F. Padovan /* Alloc CID for connection-oriented socket */ 532fe4128e0SGustavo F. Padovan chan->scid = l2cap_alloc_cid(conn); 5330c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 534b62f328bSVille Tervo } 5355491120eSAndrei Emeltchenko break; 5365491120eSAndrei Emeltchenko 5375491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_LESS: 5380a708f8fSGustavo F. Padovan /* Connectionless socket */ 539fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_CONN_LESS; 540fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_CONN_LESS; 5410c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 5425491120eSAndrei Emeltchenko break; 5435491120eSAndrei Emeltchenko 544416fa752SAndrei Emeltchenko case L2CAP_CHAN_CONN_FIX_A2MP: 545416fa752SAndrei Emeltchenko chan->scid = L2CAP_CID_A2MP; 546416fa752SAndrei Emeltchenko chan->dcid = L2CAP_CID_A2MP; 547416fa752SAndrei Emeltchenko chan->omtu = L2CAP_A2MP_DEFAULT_MTU; 548416fa752SAndrei Emeltchenko chan->imtu = L2CAP_A2MP_DEFAULT_MTU; 549416fa752SAndrei Emeltchenko break; 550416fa752SAndrei Emeltchenko 5515491120eSAndrei Emeltchenko default: 5520a708f8fSGustavo F. Padovan /* Raw socket can send/recv signalling messages only */ 553fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_SIGNALING; 554fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_SIGNALING; 5550c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 5560a708f8fSGustavo F. Padovan } 5570a708f8fSGustavo F. Padovan 5588f7975b1SAndrei Emeltchenko chan->local_id = L2CAP_BESTEFFORT_ID; 5598f7975b1SAndrei Emeltchenko chan->local_stype = L2CAP_SERV_BESTEFFORT; 5608f7975b1SAndrei Emeltchenko chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE; 5618f7975b1SAndrei Emeltchenko chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME; 5628f7975b1SAndrei Emeltchenko chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT; 5638936fa6dSAndrei Emeltchenko chan->local_flush_to = L2CAP_EFS_DEFAULT_FLUSH_TO; 5648f7975b1SAndrei Emeltchenko 565371fd835SUlisses Furquim l2cap_chan_hold(chan); 566baa7e1faSGustavo F. Padovan 5675ee9891dSJohan Hedberg hci_conn_hold(conn->hcon); 5685ee9891dSJohan Hedberg 5693df91ea2SAndrei Emeltchenko list_add(&chan->list, &conn->chan_l); 570643162a8SAndrei Emeltchenko } 571643162a8SAndrei Emeltchenko 572466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 573643162a8SAndrei Emeltchenko { 574643162a8SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 575643162a8SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 5763df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 5770a708f8fSGustavo F. Padovan } 5780a708f8fSGustavo F. Padovan 579466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err) 5800a708f8fSGustavo F. Padovan { 5818c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 5820a708f8fSGustavo F. Padovan 583c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 5840a708f8fSGustavo F. Padovan 58549208c9cSGustavo F. Padovan BT_DBG("chan %p, conn %p, err %d", chan, conn, err); 5860a708f8fSGustavo F. Padovan 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 5963cabbfdaSAndrei Emeltchenko if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP) 59776a68ba0SDavid Herrmann hci_conn_drop(conn->hcon); 59856f60984SAndrei Emeltchenko 59956f60984SAndrei Emeltchenko if (mgr && mgr->bredr_chan == chan) 60056f60984SAndrei Emeltchenko mgr->bredr_chan = NULL; 6010a708f8fSGustavo F. Padovan } 6020a708f8fSGustavo F. Padovan 603419e08c1SAndrei Emeltchenko if (chan->hs_hchan) { 604419e08c1SAndrei Emeltchenko struct hci_chan *hs_hchan = chan->hs_hchan; 605419e08c1SAndrei Emeltchenko 606419e08c1SAndrei Emeltchenko BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan); 607419e08c1SAndrei Emeltchenko amp_disconnect_logical_link(hs_hchan); 608419e08c1SAndrei Emeltchenko } 609419e08c1SAndrei Emeltchenko 610c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, err); 6116be36555SAndrei Emeltchenko 6122827011fSMat Martineau if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) 6136ff5abbfSGustavo F. Padovan return; 6142ead70b8SGustavo F. Padovan 615ee556f66SGustavo Padovan switch(chan->mode) { 616ee556f66SGustavo Padovan case L2CAP_MODE_BASIC: 617ee556f66SGustavo Padovan break; 6180a708f8fSGustavo F. Padovan 61938319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 620177f8f2bSJohan Hedberg skb_queue_purge(&chan->tx_q); 62138319713SJohan Hedberg break; 62238319713SJohan Hedberg 623ee556f66SGustavo Padovan case L2CAP_MODE_ERTM: 6241a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 6251a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 6261a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 6270a708f8fSGustavo F. Padovan 628f1c6775bSGustavo F. Padovan skb_queue_purge(&chan->srej_q); 6290a708f8fSGustavo F. Padovan 6303c588192SMat Martineau l2cap_seq_list_free(&chan->srej_list); 6313c588192SMat Martineau l2cap_seq_list_free(&chan->retrans_list); 632ee556f66SGustavo Padovan 633ee556f66SGustavo Padovan /* fall through */ 634ee556f66SGustavo Padovan 635ee556f66SGustavo Padovan case L2CAP_MODE_STREAMING: 636ee556f66SGustavo Padovan skb_queue_purge(&chan->tx_q); 637ee556f66SGustavo Padovan break; 6380a708f8fSGustavo F. Padovan } 639ee556f66SGustavo Padovan 640ee556f66SGustavo Padovan return; 6410a708f8fSGustavo F. Padovan } 6420a708f8fSGustavo F. Padovan 64327e2d4c8SJohan Hedberg static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan) 64427e2d4c8SJohan Hedberg { 64527e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn; 64627e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 64727e2d4c8SJohan Hedberg u16 result; 64827e2d4c8SJohan Hedberg 64927e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 65027e2d4c8SJohan Hedberg result = L2CAP_CR_AUTHORIZATION; 65127e2d4c8SJohan Hedberg else 65227e2d4c8SJohan Hedberg result = L2CAP_CR_BAD_PSM; 65327e2d4c8SJohan Hedberg 65427e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_DISCONN); 65527e2d4c8SJohan Hedberg 65627e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 65727e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 6583916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps); 6590cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits); 66027e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result); 66127e2d4c8SJohan Hedberg 66227e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), 66327e2d4c8SJohan Hedberg &rsp); 66427e2d4c8SJohan Hedberg } 66527e2d4c8SJohan Hedberg 666791d60f7SJohan Hedberg static void l2cap_chan_connect_reject(struct l2cap_chan *chan) 667791d60f7SJohan Hedberg { 668791d60f7SJohan Hedberg struct l2cap_conn *conn = chan->conn; 669791d60f7SJohan Hedberg struct l2cap_conn_rsp rsp; 670791d60f7SJohan Hedberg u16 result; 671791d60f7SJohan Hedberg 672791d60f7SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 673791d60f7SJohan Hedberg result = L2CAP_CR_SEC_BLOCK; 674791d60f7SJohan Hedberg else 675791d60f7SJohan Hedberg result = L2CAP_CR_BAD_PSM; 676791d60f7SJohan Hedberg 677791d60f7SJohan Hedberg l2cap_state_change(chan, BT_DISCONN); 678791d60f7SJohan Hedberg 679791d60f7SJohan Hedberg rsp.scid = cpu_to_le16(chan->dcid); 680791d60f7SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 681791d60f7SJohan Hedberg rsp.result = cpu_to_le16(result); 682791d60f7SJohan Hedberg rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 683791d60f7SJohan Hedberg 684791d60f7SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); 685791d60f7SJohan Hedberg } 686791d60f7SJohan Hedberg 6870f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason) 6884519de9aSGustavo F. Padovan { 6894519de9aSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 6904519de9aSGustavo F. Padovan 6917eafc59eSMarcel Holtmann BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 6924519de9aSGustavo F. Padovan 69389bc500eSGustavo F. Padovan switch (chan->state) { 6944519de9aSGustavo F. Padovan case BT_LISTEN: 695c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 6964519de9aSGustavo F. Padovan break; 6974519de9aSGustavo F. Padovan 6984519de9aSGustavo F. Padovan case BT_CONNECTED: 6994519de9aSGustavo F. Padovan case BT_CONFIG: 700cea04ce3SJohan Hedberg /* ATT uses L2CAP_CHAN_CONN_ORIENTED so we must also 701cea04ce3SJohan Hedberg * check for chan->psm. 702cea04ce3SJohan Hedberg */ 703cea04ce3SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && chan->psm) { 7048d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 7055e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, reason); 7064519de9aSGustavo F. Padovan } else 7074519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 7084519de9aSGustavo F. Padovan break; 7094519de9aSGustavo F. Padovan 7104519de9aSGustavo F. Padovan case BT_CONNECT2: 711791d60f7SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) { 712791d60f7SJohan Hedberg if (conn->hcon->type == ACL_LINK) 713791d60f7SJohan Hedberg l2cap_chan_connect_reject(chan); 71427e2d4c8SJohan Hedberg else if (conn->hcon->type == LE_LINK) 71527e2d4c8SJohan Hedberg l2cap_chan_le_connect_reject(chan); 7164519de9aSGustavo F. Padovan } 7174519de9aSGustavo F. Padovan 7184519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 7194519de9aSGustavo F. Padovan break; 7204519de9aSGustavo F. Padovan 7214519de9aSGustavo F. Padovan case BT_CONNECT: 7224519de9aSGustavo F. Padovan case BT_DISCONN: 7234519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 7244519de9aSGustavo F. Padovan break; 7254519de9aSGustavo F. Padovan 7264519de9aSGustavo F. Padovan default: 727c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 7284519de9aSGustavo F. Padovan break; 7294519de9aSGustavo F. Padovan } 7304519de9aSGustavo F. Padovan } 7314519de9aSGustavo F. Padovan 7324343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) 7330a708f8fSGustavo F. Padovan { 7346a974b50SMarcel Holtmann switch (chan->chan_type) { 7356a974b50SMarcel Holtmann case L2CAP_CHAN_RAW: 7364343478fSGustavo F. Padovan switch (chan->sec_level) { 7370a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 7380a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING_MITM; 7390a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 7400a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING; 7410a708f8fSGustavo F. Padovan default: 7420a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 7430a708f8fSGustavo F. Padovan } 7446a974b50SMarcel Holtmann break; 7453124b843SMarcel Holtmann case L2CAP_CHAN_CONN_LESS: 7463124b843SMarcel Holtmann if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_3DSP)) { 7473124b843SMarcel Holtmann if (chan->sec_level == BT_SECURITY_LOW) 7483124b843SMarcel Holtmann chan->sec_level = BT_SECURITY_SDP; 7493124b843SMarcel Holtmann } 7503124b843SMarcel Holtmann if (chan->sec_level == BT_SECURITY_HIGH) 7513124b843SMarcel Holtmann return HCI_AT_NO_BONDING_MITM; 7523124b843SMarcel Holtmann else 7533124b843SMarcel Holtmann return HCI_AT_NO_BONDING; 7543124b843SMarcel Holtmann break; 7556a974b50SMarcel Holtmann case L2CAP_CHAN_CONN_ORIENTED: 7566a974b50SMarcel Holtmann if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) { 7574343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_LOW) 7584343478fSGustavo F. Padovan chan->sec_level = BT_SECURITY_SDP; 7590a708f8fSGustavo F. Padovan 7604343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_HIGH) 7610a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING_MITM; 7620a708f8fSGustavo F. Padovan else 7630a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 7646a974b50SMarcel Holtmann } 7656a974b50SMarcel Holtmann /* fall through */ 7666a974b50SMarcel Holtmann default: 7674343478fSGustavo F. Padovan switch (chan->sec_level) { 7680a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 7690a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING_MITM; 7700a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 7710a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING; 7720a708f8fSGustavo F. Padovan default: 7730a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 7740a708f8fSGustavo F. Padovan } 7756a974b50SMarcel Holtmann break; 7760a708f8fSGustavo F. Padovan } 7770a708f8fSGustavo F. Padovan } 7780a708f8fSGustavo F. Padovan 7790a708f8fSGustavo F. Padovan /* Service level security */ 780d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan) 7810a708f8fSGustavo F. Padovan { 7828c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 7830a708f8fSGustavo F. Padovan __u8 auth_type; 7840a708f8fSGustavo F. Padovan 785a17de2feSJohan Hedberg if (conn->hcon->type == LE_LINK) 786a17de2feSJohan Hedberg return smp_conn_security(conn->hcon, chan->sec_level); 787a17de2feSJohan Hedberg 7884343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 7890a708f8fSGustavo F. Padovan 7904343478fSGustavo F. Padovan return hci_conn_security(conn->hcon, chan->sec_level, auth_type); 7910a708f8fSGustavo F. Padovan } 7920a708f8fSGustavo F. Padovan 793b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn) 7940a708f8fSGustavo F. Padovan { 7950a708f8fSGustavo F. Padovan u8 id; 7960a708f8fSGustavo F. Padovan 7970a708f8fSGustavo F. Padovan /* Get next available identificator. 7980a708f8fSGustavo F. Padovan * 1 - 128 are used by kernel. 7990a708f8fSGustavo F. Padovan * 129 - 199 are reserved. 8000a708f8fSGustavo F. Padovan * 200 - 254 are used by utilities like l2ping, etc. 8010a708f8fSGustavo F. Padovan */ 8020a708f8fSGustavo F. Padovan 803333055f2SGustavo F. Padovan spin_lock(&conn->lock); 8040a708f8fSGustavo F. Padovan 8050a708f8fSGustavo F. Padovan if (++conn->tx_ident > 128) 8060a708f8fSGustavo F. Padovan conn->tx_ident = 1; 8070a708f8fSGustavo F. Padovan 8080a708f8fSGustavo F. Padovan id = conn->tx_ident; 8090a708f8fSGustavo F. Padovan 810333055f2SGustavo F. Padovan spin_unlock(&conn->lock); 8110a708f8fSGustavo F. Padovan 8120a708f8fSGustavo F. Padovan return id; 8130a708f8fSGustavo F. Padovan } 8140a708f8fSGustavo F. Padovan 8152d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 8162d792818SGustavo Padovan void *data) 8170a708f8fSGustavo F. Padovan { 8180a708f8fSGustavo F. Padovan struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); 8190a708f8fSGustavo F. Padovan u8 flags; 8200a708f8fSGustavo F. Padovan 8210a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x", code); 8220a708f8fSGustavo F. Padovan 8230a708f8fSGustavo F. Padovan if (!skb) 8240a708f8fSGustavo F. Padovan return; 8250a708f8fSGustavo F. Padovan 8260a708f8fSGustavo F. Padovan if (lmp_no_flush_capable(conn->hcon->hdev)) 8270a708f8fSGustavo F. Padovan flags = ACL_START_NO_FLUSH; 8280a708f8fSGustavo F. Padovan else 8290a708f8fSGustavo F. Padovan flags = ACL_START; 8300a708f8fSGustavo F. Padovan 83114b12d0bSJaikumar Ganesh bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON; 8325e59b791SLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 83314b12d0bSJaikumar Ganesh 83473d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, flags); 8350a708f8fSGustavo F. Padovan } 8360a708f8fSGustavo F. Padovan 83702b0fbb9SMat Martineau static bool __chan_is_moving(struct l2cap_chan *chan) 83802b0fbb9SMat Martineau { 83902b0fbb9SMat Martineau return chan->move_state != L2CAP_MOVE_STABLE && 84002b0fbb9SMat Martineau chan->move_state != L2CAP_MOVE_WAIT_PREPARE; 84102b0fbb9SMat Martineau } 84202b0fbb9SMat Martineau 84373d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) 84473d80debSLuiz Augusto von Dentz { 84573d80debSLuiz Augusto von Dentz struct hci_conn *hcon = chan->conn->hcon; 84673d80debSLuiz Augusto von Dentz u16 flags; 84773d80debSLuiz Augusto von Dentz 84873d80debSLuiz Augusto von Dentz BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, 84973d80debSLuiz Augusto von Dentz skb->priority); 85073d80debSLuiz Augusto von Dentz 851d5f8a75dSMat Martineau if (chan->hs_hcon && !__chan_is_moving(chan)) { 852d5f8a75dSMat Martineau if (chan->hs_hchan) 853d5f8a75dSMat Martineau hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE); 854d5f8a75dSMat Martineau else 855d5f8a75dSMat Martineau kfree_skb(skb); 856d5f8a75dSMat Martineau 857d5f8a75dSMat Martineau return; 858d5f8a75dSMat Martineau } 859d5f8a75dSMat Martineau 86073d80debSLuiz Augusto von Dentz if (!test_bit(FLAG_FLUSHABLE, &chan->flags) && 86173d80debSLuiz Augusto von Dentz lmp_no_flush_capable(hcon->hdev)) 86273d80debSLuiz Augusto von Dentz flags = ACL_START_NO_FLUSH; 86373d80debSLuiz Augusto von Dentz else 86473d80debSLuiz Augusto von Dentz flags = ACL_START; 86573d80debSLuiz Augusto von Dentz 86673d80debSLuiz Augusto von Dentz bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); 86773d80debSLuiz Augusto von Dentz hci_send_acl(chan->conn->hchan, skb, flags); 8680a708f8fSGustavo F. Padovan } 8690a708f8fSGustavo F. Padovan 870b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control) 871b5c6aaedSMat Martineau { 872b5c6aaedSMat Martineau control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT; 873b5c6aaedSMat Martineau control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT; 874b5c6aaedSMat Martineau 875b5c6aaedSMat Martineau if (enh & L2CAP_CTRL_FRAME_TYPE) { 876b5c6aaedSMat Martineau /* S-Frame */ 877b5c6aaedSMat Martineau control->sframe = 1; 878b5c6aaedSMat Martineau control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT; 879b5c6aaedSMat Martineau control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT; 880b5c6aaedSMat Martineau 881b5c6aaedSMat Martineau control->sar = 0; 882b5c6aaedSMat Martineau control->txseq = 0; 883b5c6aaedSMat Martineau } else { 884b5c6aaedSMat Martineau /* I-Frame */ 885b5c6aaedSMat Martineau control->sframe = 0; 886b5c6aaedSMat Martineau control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT; 887b5c6aaedSMat Martineau control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT; 888b5c6aaedSMat Martineau 889b5c6aaedSMat Martineau control->poll = 0; 890b5c6aaedSMat Martineau control->super = 0; 891b5c6aaedSMat Martineau } 892b5c6aaedSMat Martineau } 893b5c6aaedSMat Martineau 894b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control) 895b5c6aaedSMat Martineau { 896b5c6aaedSMat Martineau control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT; 897b5c6aaedSMat Martineau control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT; 898b5c6aaedSMat Martineau 899b5c6aaedSMat Martineau if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) { 900b5c6aaedSMat Martineau /* S-Frame */ 901b5c6aaedSMat Martineau control->sframe = 1; 902b5c6aaedSMat Martineau control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT; 903b5c6aaedSMat Martineau control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT; 904b5c6aaedSMat Martineau 905b5c6aaedSMat Martineau control->sar = 0; 906b5c6aaedSMat Martineau control->txseq = 0; 907b5c6aaedSMat Martineau } else { 908b5c6aaedSMat Martineau /* I-Frame */ 909b5c6aaedSMat Martineau control->sframe = 0; 910b5c6aaedSMat Martineau control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT; 911b5c6aaedSMat Martineau control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT; 912b5c6aaedSMat Martineau 913b5c6aaedSMat Martineau control->poll = 0; 914b5c6aaedSMat Martineau control->super = 0; 915b5c6aaedSMat Martineau } 916b5c6aaedSMat Martineau } 917b5c6aaedSMat Martineau 918b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan, 919b5c6aaedSMat Martineau struct sk_buff *skb) 920b5c6aaedSMat Martineau { 921b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 922b5c6aaedSMat Martineau __unpack_extended_control(get_unaligned_le32(skb->data), 923b5c6aaedSMat Martineau &bt_cb(skb)->control); 924cec8ab6eSMat Martineau skb_pull(skb, L2CAP_EXT_CTRL_SIZE); 925b5c6aaedSMat Martineau } else { 926b5c6aaedSMat Martineau __unpack_enhanced_control(get_unaligned_le16(skb->data), 927b5c6aaedSMat Martineau &bt_cb(skb)->control); 928cec8ab6eSMat Martineau skb_pull(skb, L2CAP_ENH_CTRL_SIZE); 929b5c6aaedSMat Martineau } 930b5c6aaedSMat Martineau } 931b5c6aaedSMat Martineau 932b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control) 933b5c6aaedSMat Martineau { 934b5c6aaedSMat Martineau u32 packed; 935b5c6aaedSMat Martineau 936b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT; 937b5c6aaedSMat Martineau packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT; 938b5c6aaedSMat Martineau 939b5c6aaedSMat Martineau if (control->sframe) { 940b5c6aaedSMat Martineau packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT; 941b5c6aaedSMat Martineau packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT; 942b5c6aaedSMat Martineau packed |= L2CAP_EXT_CTRL_FRAME_TYPE; 943b5c6aaedSMat Martineau } else { 944b5c6aaedSMat Martineau packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT; 945b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT; 946b5c6aaedSMat Martineau } 947b5c6aaedSMat Martineau 948b5c6aaedSMat Martineau return packed; 949b5c6aaedSMat Martineau } 950b5c6aaedSMat Martineau 951b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control) 952b5c6aaedSMat Martineau { 953b5c6aaedSMat Martineau u16 packed; 954b5c6aaedSMat Martineau 955b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT; 956b5c6aaedSMat Martineau packed |= control->final << L2CAP_CTRL_FINAL_SHIFT; 957b5c6aaedSMat Martineau 958b5c6aaedSMat Martineau if (control->sframe) { 959b5c6aaedSMat Martineau packed |= control->poll << L2CAP_CTRL_POLL_SHIFT; 960b5c6aaedSMat Martineau packed |= control->super << L2CAP_CTRL_SUPER_SHIFT; 961b5c6aaedSMat Martineau packed |= L2CAP_CTRL_FRAME_TYPE; 962b5c6aaedSMat Martineau } else { 963b5c6aaedSMat Martineau packed |= control->sar << L2CAP_CTRL_SAR_SHIFT; 964b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT; 965b5c6aaedSMat Martineau } 966b5c6aaedSMat Martineau 967b5c6aaedSMat Martineau return packed; 968b5c6aaedSMat Martineau } 969b5c6aaedSMat Martineau 970b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan, 971b5c6aaedSMat Martineau struct l2cap_ctrl *control, 972b5c6aaedSMat Martineau struct sk_buff *skb) 973b5c6aaedSMat Martineau { 974b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 975b5c6aaedSMat Martineau put_unaligned_le32(__pack_extended_control(control), 976b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 977b5c6aaedSMat Martineau } else { 978b5c6aaedSMat Martineau put_unaligned_le16(__pack_enhanced_control(control), 979b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 980b5c6aaedSMat Martineau } 981b5c6aaedSMat Martineau } 982b5c6aaedSMat Martineau 983ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan) 984ba7aa64fSGustavo Padovan { 985ba7aa64fSGustavo Padovan if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 986ba7aa64fSGustavo Padovan return L2CAP_EXT_HDR_SIZE; 987ba7aa64fSGustavo Padovan else 988ba7aa64fSGustavo Padovan return L2CAP_ENH_HDR_SIZE; 989ba7aa64fSGustavo Padovan } 990ba7aa64fSGustavo Padovan 991a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan, 992a67d7f6fSMat Martineau u32 control) 9930a708f8fSGustavo F. Padovan { 9940a708f8fSGustavo F. Padovan struct sk_buff *skb; 9950a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 996ba7aa64fSGustavo Padovan int hlen = __ertm_hdr_size(chan); 9970a708f8fSGustavo F. Padovan 9980a708f8fSGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 99903a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 10000a708f8fSGustavo F. Padovan 1001a67d7f6fSMat Martineau skb = bt_skb_alloc(hlen, GFP_KERNEL); 10020a708f8fSGustavo F. Padovan 10030a708f8fSGustavo F. Padovan if (!skb) 1004a67d7f6fSMat Martineau return ERR_PTR(-ENOMEM); 10050a708f8fSGustavo F. Padovan 10060a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 10070a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); 1008fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 100988843ab0SAndrei Emeltchenko 1010a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1011a67d7f6fSMat Martineau put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 1012a67d7f6fSMat Martineau else 1013a67d7f6fSMat Martineau put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 10140a708f8fSGustavo F. Padovan 101547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 1016a67d7f6fSMat Martineau u16 fcs = crc16(0, (u8 *)skb->data, skb->len); 101703a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 10180a708f8fSGustavo F. Padovan } 10190a708f8fSGustavo F. Padovan 102073d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 1021a67d7f6fSMat Martineau return skb; 1022a67d7f6fSMat Martineau } 1023a67d7f6fSMat Martineau 1024a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan, 1025a67d7f6fSMat Martineau struct l2cap_ctrl *control) 1026a67d7f6fSMat Martineau { 1027a67d7f6fSMat Martineau struct sk_buff *skb; 1028a67d7f6fSMat Martineau u32 control_field; 1029a67d7f6fSMat Martineau 1030a67d7f6fSMat Martineau BT_DBG("chan %p, control %p", chan, control); 1031a67d7f6fSMat Martineau 1032a67d7f6fSMat Martineau if (!control->sframe) 1033a67d7f6fSMat Martineau return; 1034a67d7f6fSMat Martineau 1035b99e13adSMat Martineau if (__chan_is_moving(chan)) 1036b99e13adSMat Martineau return; 1037b99e13adSMat Martineau 1038a67d7f6fSMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) && 1039a67d7f6fSMat Martineau !control->poll) 1040a67d7f6fSMat Martineau control->final = 1; 1041a67d7f6fSMat Martineau 1042a67d7f6fSMat Martineau if (control->super == L2CAP_SUPER_RR) 1043a67d7f6fSMat Martineau clear_bit(CONN_RNR_SENT, &chan->conn_state); 1044a67d7f6fSMat Martineau else if (control->super == L2CAP_SUPER_RNR) 1045a67d7f6fSMat Martineau set_bit(CONN_RNR_SENT, &chan->conn_state); 1046a67d7f6fSMat Martineau 1047a67d7f6fSMat Martineau if (control->super != L2CAP_SUPER_SREJ) { 1048a67d7f6fSMat Martineau chan->last_acked_seq = control->reqseq; 1049a67d7f6fSMat Martineau __clear_ack_timer(chan); 1050a67d7f6fSMat Martineau } 1051a67d7f6fSMat Martineau 1052a67d7f6fSMat Martineau BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq, 1053a67d7f6fSMat Martineau control->final, control->poll, control->super); 1054a67d7f6fSMat Martineau 1055a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1056a67d7f6fSMat Martineau control_field = __pack_extended_control(control); 1057a67d7f6fSMat Martineau else 1058a67d7f6fSMat Martineau control_field = __pack_enhanced_control(control); 1059a67d7f6fSMat Martineau 1060a67d7f6fSMat Martineau skb = l2cap_create_sframe_pdu(chan, control_field); 1061a67d7f6fSMat Martineau if (!IS_ERR(skb)) 106273d80debSLuiz Augusto von Dentz l2cap_do_send(chan, skb); 10630a708f8fSGustavo F. Padovan } 10640a708f8fSGustavo F. Padovan 1065c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll) 10660a708f8fSGustavo F. Padovan { 1067c9e3d5e0SMat Martineau struct l2cap_ctrl control; 10680a708f8fSGustavo F. Padovan 1069c9e3d5e0SMat Martineau BT_DBG("chan %p, poll %d", chan, poll); 1070c9e3d5e0SMat Martineau 1071c9e3d5e0SMat Martineau memset(&control, 0, sizeof(control)); 1072c9e3d5e0SMat Martineau control.sframe = 1; 1073c9e3d5e0SMat Martineau control.poll = poll; 1074c9e3d5e0SMat Martineau 1075c9e3d5e0SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 1076c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RNR; 1077c9e3d5e0SMat Martineau else 1078c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RR; 1079c9e3d5e0SMat Martineau 1080c9e3d5e0SMat Martineau control.reqseq = chan->buffer_seq; 1081c9e3d5e0SMat Martineau l2cap_send_sframe(chan, &control); 10820a708f8fSGustavo F. Padovan } 10830a708f8fSGustavo F. Padovan 1084b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) 10850a708f8fSGustavo F. Padovan { 1086c1360a1cSGustavo F. Padovan return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); 10870a708f8fSGustavo F. Padovan } 10880a708f8fSGustavo F. Padovan 108993c3e8f5SAndrei Emeltchenko static bool __amp_capable(struct l2cap_chan *chan) 109093c3e8f5SAndrei Emeltchenko { 109193c3e8f5SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 10921df7b17aSMarcel Holtmann struct hci_dev *hdev; 10931df7b17aSMarcel Holtmann bool amp_available = false; 109493c3e8f5SAndrei Emeltchenko 10951df7b17aSMarcel Holtmann if (!conn->hs_enabled) 10961df7b17aSMarcel Holtmann return false; 10971df7b17aSMarcel Holtmann 10981df7b17aSMarcel Holtmann if (!(conn->fixed_chan_mask & L2CAP_FC_A2MP)) 10991df7b17aSMarcel Holtmann return false; 11001df7b17aSMarcel Holtmann 11011df7b17aSMarcel Holtmann read_lock(&hci_dev_list_lock); 11021df7b17aSMarcel Holtmann list_for_each_entry(hdev, &hci_dev_list, list) { 11031df7b17aSMarcel Holtmann if (hdev->amp_type != AMP_TYPE_BREDR && 11041df7b17aSMarcel Holtmann test_bit(HCI_UP, &hdev->flags)) { 11051df7b17aSMarcel Holtmann amp_available = true; 11061df7b17aSMarcel Holtmann break; 11071df7b17aSMarcel Holtmann } 11081df7b17aSMarcel Holtmann } 11091df7b17aSMarcel Holtmann read_unlock(&hci_dev_list_lock); 11101df7b17aSMarcel Holtmann 11111df7b17aSMarcel Holtmann if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED) 11121df7b17aSMarcel Holtmann return amp_available; 1113848566b3SMarcel Holtmann 111493c3e8f5SAndrei Emeltchenko return false; 111593c3e8f5SAndrei Emeltchenko } 111693c3e8f5SAndrei Emeltchenko 11175ce66b59SAndrei Emeltchenko static bool l2cap_check_efs(struct l2cap_chan *chan) 11185ce66b59SAndrei Emeltchenko { 11195ce66b59SAndrei Emeltchenko /* Check EFS parameters */ 11205ce66b59SAndrei Emeltchenko return true; 11215ce66b59SAndrei Emeltchenko } 11225ce66b59SAndrei Emeltchenko 11232766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan) 11249b27f350SAndrei Emeltchenko { 11259b27f350SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 11269b27f350SAndrei Emeltchenko struct l2cap_conn_req req; 11279b27f350SAndrei Emeltchenko 11289b27f350SAndrei Emeltchenko req.scid = cpu_to_le16(chan->scid); 11299b27f350SAndrei Emeltchenko req.psm = chan->psm; 11309b27f350SAndrei Emeltchenko 11319b27f350SAndrei Emeltchenko chan->ident = l2cap_get_ident(conn); 11329b27f350SAndrei Emeltchenko 11339b27f350SAndrei Emeltchenko set_bit(CONF_CONNECT_PEND, &chan->conf_state); 11349b27f350SAndrei Emeltchenko 11359b27f350SAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); 11369b27f350SAndrei Emeltchenko } 11379b27f350SAndrei Emeltchenko 11388eb200bdSMat Martineau static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id) 11398eb200bdSMat Martineau { 11408eb200bdSMat Martineau struct l2cap_create_chan_req req; 11418eb200bdSMat Martineau req.scid = cpu_to_le16(chan->scid); 11428eb200bdSMat Martineau req.psm = chan->psm; 11438eb200bdSMat Martineau req.amp_id = amp_id; 11448eb200bdSMat Martineau 11458eb200bdSMat Martineau chan->ident = l2cap_get_ident(chan->conn); 11468eb200bdSMat Martineau 11478eb200bdSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ, 11488eb200bdSMat Martineau sizeof(req), &req); 11498eb200bdSMat Martineau } 11508eb200bdSMat Martineau 115102b0fbb9SMat Martineau static void l2cap_move_setup(struct l2cap_chan *chan) 115202b0fbb9SMat Martineau { 115302b0fbb9SMat Martineau struct sk_buff *skb; 115402b0fbb9SMat Martineau 115502b0fbb9SMat Martineau BT_DBG("chan %p", chan); 115602b0fbb9SMat Martineau 115702b0fbb9SMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 115802b0fbb9SMat Martineau return; 115902b0fbb9SMat Martineau 116002b0fbb9SMat Martineau __clear_retrans_timer(chan); 116102b0fbb9SMat Martineau __clear_monitor_timer(chan); 116202b0fbb9SMat Martineau __clear_ack_timer(chan); 116302b0fbb9SMat Martineau 116402b0fbb9SMat Martineau chan->retry_count = 0; 116502b0fbb9SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 116602b0fbb9SMat Martineau if (bt_cb(skb)->control.retries) 116702b0fbb9SMat Martineau bt_cb(skb)->control.retries = 1; 116802b0fbb9SMat Martineau else 116902b0fbb9SMat Martineau break; 117002b0fbb9SMat Martineau } 117102b0fbb9SMat Martineau 117202b0fbb9SMat Martineau chan->expected_tx_seq = chan->buffer_seq; 117302b0fbb9SMat Martineau 117402b0fbb9SMat Martineau clear_bit(CONN_REJ_ACT, &chan->conn_state); 117502b0fbb9SMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 117602b0fbb9SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 117702b0fbb9SMat Martineau l2cap_seq_list_clear(&chan->srej_list); 117802b0fbb9SMat Martineau skb_queue_purge(&chan->srej_q); 117902b0fbb9SMat Martineau 118002b0fbb9SMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 118102b0fbb9SMat Martineau chan->rx_state = L2CAP_RX_STATE_MOVE; 118202b0fbb9SMat Martineau 118302b0fbb9SMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 118402b0fbb9SMat Martineau } 118502b0fbb9SMat Martineau 11865f3847a4SMat Martineau static void l2cap_move_done(struct l2cap_chan *chan) 11875f3847a4SMat Martineau { 11885f3847a4SMat Martineau u8 move_role = chan->move_role; 11895f3847a4SMat Martineau BT_DBG("chan %p", chan); 11905f3847a4SMat Martineau 11915f3847a4SMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 11925f3847a4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 11935f3847a4SMat Martineau 11945f3847a4SMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 11955f3847a4SMat Martineau return; 11965f3847a4SMat Martineau 11975f3847a4SMat Martineau switch (move_role) { 11985f3847a4SMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 11995f3847a4SMat Martineau l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL); 12005f3847a4SMat Martineau chan->rx_state = L2CAP_RX_STATE_WAIT_F; 12015f3847a4SMat Martineau break; 12025f3847a4SMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 12035f3847a4SMat Martineau chan->rx_state = L2CAP_RX_STATE_WAIT_P; 12045f3847a4SMat Martineau break; 12055f3847a4SMat Martineau } 12065f3847a4SMat Martineau } 12075f3847a4SMat Martineau 1208177f8f2bSJohan Hedberg static void l2cap_le_flowctl_start(struct l2cap_chan *chan) 1209177f8f2bSJohan Hedberg { 1210177f8f2bSJohan Hedberg chan->sdu = NULL; 1211177f8f2bSJohan Hedberg chan->sdu_last_frag = NULL; 1212177f8f2bSJohan Hedberg chan->sdu_len = 0; 1213177f8f2bSJohan Hedberg 12143916aed8SJohan Hedberg if (chan->imtu < L2CAP_LE_DEFAULT_MPS) 12153916aed8SJohan Hedberg chan->mps = chan->imtu; 12163916aed8SJohan Hedberg else 12173916aed8SJohan Hedberg chan->mps = L2CAP_LE_DEFAULT_MPS; 12183916aed8SJohan Hedberg 1219177f8f2bSJohan Hedberg skb_queue_head_init(&chan->tx_q); 1220029727a3SJohan Hedberg 1221029727a3SJohan Hedberg if (!chan->tx_credits) 1222029727a3SJohan Hedberg chan->ops->suspend(chan); 1223177f8f2bSJohan Hedberg } 1224177f8f2bSJohan Hedberg 12259f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan) 12269f0caeb1SVinicius Costa Gomes { 12272827011fSMat Martineau /* This clears all conf flags, including CONF_NOT_COMPLETE */ 12289f0caeb1SVinicius Costa Gomes chan->conf_state = 0; 12299f0caeb1SVinicius Costa Gomes __clear_chan_timer(chan); 12309f0caeb1SVinicius Costa Gomes 1231177f8f2bSJohan Hedberg if (chan->mode == L2CAP_MODE_LE_FLOWCTL) 1232177f8f2bSJohan Hedberg l2cap_le_flowctl_start(chan); 1233177f8f2bSJohan Hedberg 123454a59aa2SAndrei Emeltchenko chan->state = BT_CONNECTED; 12359f0caeb1SVinicius Costa Gomes 123654a59aa2SAndrei Emeltchenko chan->ops->ready(chan); 12379f0caeb1SVinicius Costa Gomes } 12389f0caeb1SVinicius Costa Gomes 1239f1496deeSJohan Hedberg static void l2cap_le_connect(struct l2cap_chan *chan) 1240f1496deeSJohan Hedberg { 1241f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1242f1496deeSJohan Hedberg struct l2cap_le_conn_req req; 1243f1496deeSJohan Hedberg 1244595177f3SJohan Hedberg if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags)) 1245595177f3SJohan Hedberg return; 1246595177f3SJohan Hedberg 1247f1496deeSJohan Hedberg req.psm = chan->psm; 1248f1496deeSJohan Hedberg req.scid = cpu_to_le16(chan->scid); 1249f1496deeSJohan Hedberg req.mtu = cpu_to_le16(chan->imtu); 12503916aed8SJohan Hedberg req.mps = cpu_to_le16(chan->mps); 12510cd75f7eSJohan Hedberg req.credits = cpu_to_le16(chan->rx_credits); 1252f1496deeSJohan Hedberg 1253f1496deeSJohan Hedberg chan->ident = l2cap_get_ident(conn); 1254f1496deeSJohan Hedberg 1255f1496deeSJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ, 1256f1496deeSJohan Hedberg sizeof(req), &req); 1257f1496deeSJohan Hedberg } 1258f1496deeSJohan Hedberg 1259f1496deeSJohan Hedberg static void l2cap_le_start(struct l2cap_chan *chan) 1260f1496deeSJohan Hedberg { 1261f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1262f1496deeSJohan Hedberg 1263f1496deeSJohan Hedberg if (!smp_conn_security(conn->hcon, chan->sec_level)) 1264f1496deeSJohan Hedberg return; 1265f1496deeSJohan Hedberg 1266f1496deeSJohan Hedberg if (!chan->psm) { 1267f1496deeSJohan Hedberg l2cap_chan_ready(chan); 1268f1496deeSJohan Hedberg return; 1269f1496deeSJohan Hedberg } 1270f1496deeSJohan Hedberg 1271f1496deeSJohan Hedberg if (chan->state == BT_CONNECT) 1272f1496deeSJohan Hedberg l2cap_le_connect(chan); 1273f1496deeSJohan Hedberg } 1274f1496deeSJohan Hedberg 127593c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan) 127693c3e8f5SAndrei Emeltchenko { 127793c3e8f5SAndrei Emeltchenko if (__amp_capable(chan)) { 127893c3e8f5SAndrei Emeltchenko BT_DBG("chan %p AMP capable: discover AMPs", chan); 127993c3e8f5SAndrei Emeltchenko a2mp_discover_amp(chan); 1280f1496deeSJohan Hedberg } else if (chan->conn->hcon->type == LE_LINK) { 1281f1496deeSJohan Hedberg l2cap_le_start(chan); 128293c3e8f5SAndrei Emeltchenko } else { 128393c3e8f5SAndrei Emeltchenko l2cap_send_conn_req(chan); 128493c3e8f5SAndrei Emeltchenko } 128593c3e8f5SAndrei Emeltchenko } 128693c3e8f5SAndrei Emeltchenko 1287fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan) 12880a708f8fSGustavo F. Padovan { 12898c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 12900a708f8fSGustavo F. Padovan 12919f0caeb1SVinicius Costa Gomes if (conn->hcon->type == LE_LINK) { 129296ac34fbSJohan Hedberg l2cap_le_start(chan); 12939f0caeb1SVinicius Costa Gomes return; 12949f0caeb1SVinicius Costa Gomes } 12959f0caeb1SVinicius Costa Gomes 12960a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { 12970a708f8fSGustavo F. Padovan if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) 12980a708f8fSGustavo F. Padovan return; 12990a708f8fSGustavo F. Padovan 1300d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan) && 130193c3e8f5SAndrei Emeltchenko __l2cap_no_conn_pending(chan)) { 130293c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 130393c3e8f5SAndrei Emeltchenko } 13040a708f8fSGustavo F. Padovan } else { 13050a708f8fSGustavo F. Padovan struct l2cap_info_req req; 1306ac73498cSAndrei Emeltchenko req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); 13070a708f8fSGustavo F. Padovan 13080a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 13090a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 13100a708f8fSGustavo F. Padovan 1311ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 13120a708f8fSGustavo F. Padovan 13132d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, 13142d792818SGustavo Padovan sizeof(req), &req); 13150a708f8fSGustavo F. Padovan } 13160a708f8fSGustavo F. Padovan } 13170a708f8fSGustavo F. Padovan 13180a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) 13190a708f8fSGustavo F. Padovan { 13200a708f8fSGustavo F. Padovan u32 local_feat_mask = l2cap_feat_mask; 13210a708f8fSGustavo F. Padovan if (!disable_ertm) 13220a708f8fSGustavo F. Padovan local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING; 13230a708f8fSGustavo F. Padovan 13240a708f8fSGustavo F. Padovan switch (mode) { 13250a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 13260a708f8fSGustavo F. Padovan return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask; 13270a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 13280a708f8fSGustavo F. Padovan return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask; 13290a708f8fSGustavo F. Padovan default: 13300a708f8fSGustavo F. Padovan return 0x00; 13310a708f8fSGustavo F. Padovan } 13320a708f8fSGustavo F. Padovan } 13330a708f8fSGustavo F. Padovan 13345e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err) 13350a708f8fSGustavo F. Padovan { 13365e4e3972SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 13370a708f8fSGustavo F. Padovan struct l2cap_disconn_req req; 13380a708f8fSGustavo F. Padovan 13390a708f8fSGustavo F. Padovan if (!conn) 13400a708f8fSGustavo F. Padovan return; 13410a708f8fSGustavo F. Padovan 1342aad3d0e3SAndrei Emeltchenko if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) { 13431a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 13441a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 13451a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 13460a708f8fSGustavo F. Padovan } 13470a708f8fSGustavo F. Padovan 1348416fa752SAndrei Emeltchenko if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { 1349d117773cSGustavo Padovan l2cap_state_change(chan, BT_DISCONN); 1350416fa752SAndrei Emeltchenko return; 1351416fa752SAndrei Emeltchenko } 1352416fa752SAndrei Emeltchenko 1353fe4128e0SGustavo F. Padovan req.dcid = cpu_to_le16(chan->dcid); 1354fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 13552d792818SGustavo Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ, 13562d792818SGustavo Padovan sizeof(req), &req); 13570a708f8fSGustavo F. Padovan 1358f8e73017SGustavo Padovan l2cap_state_change_and_error(chan, BT_DISCONN, err); 13590a708f8fSGustavo F. Padovan } 13600a708f8fSGustavo F. Padovan 13610a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */ 13620a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn) 13630a708f8fSGustavo F. Padovan { 13643df91ea2SAndrei Emeltchenko struct l2cap_chan *chan, *tmp; 13650a708f8fSGustavo F. Padovan 13660a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 13670a708f8fSGustavo F. Padovan 13683df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 13690a708f8fSGustavo F. Padovan 13703df91ea2SAndrei Emeltchenko list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 13716be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 13720a708f8fSGustavo F. Padovan 1373715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 13746be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13750a708f8fSGustavo F. Padovan continue; 13760a708f8fSGustavo F. Padovan } 13770a708f8fSGustavo F. Padovan 137889bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 1379d45fc423SGustavo F. Padovan if (!l2cap_chan_check_security(chan) || 1380b4450035SGustavo F. Padovan !__l2cap_no_conn_pending(chan)) { 13816be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13820a708f8fSGustavo F. Padovan continue; 13830a708f8fSGustavo F. Padovan } 13840a708f8fSGustavo F. Padovan 1385c1360a1cSGustavo F. Padovan if (!l2cap_mode_supported(chan->mode, conn->feat_mask) 1386c1360a1cSGustavo F. Padovan && test_bit(CONF_STATE2_DEVICE, 1387c1360a1cSGustavo F. Padovan &chan->conf_state)) { 13880f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 13896be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13900a708f8fSGustavo F. Padovan continue; 13910a708f8fSGustavo F. Padovan } 13920a708f8fSGustavo F. Padovan 139393c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 13940a708f8fSGustavo F. Padovan 139589bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 13960a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 13970a708f8fSGustavo F. Padovan char buf[128]; 1398fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 1399fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 14000a708f8fSGustavo F. Padovan 1401d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 1402bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 1403ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); 1404ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND); 14052dc4e510SGustavo Padovan chan->ops->defer(chan); 14060a708f8fSGustavo F. Padovan 14070a708f8fSGustavo F. Padovan } else { 1408acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 1409ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 1410ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 14110a708f8fSGustavo F. Padovan } 14120a708f8fSGustavo F. Padovan } else { 1413ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); 1414ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND); 14150a708f8fSGustavo F. Padovan } 14160a708f8fSGustavo F. Padovan 1417fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 1418fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 14190a708f8fSGustavo F. Padovan 1420c1360a1cSGustavo F. Padovan if (test_bit(CONF_REQ_SENT, &chan->conf_state) || 14210a708f8fSGustavo F. Padovan rsp.result != L2CAP_CR_SUCCESS) { 14226be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 14230a708f8fSGustavo F. Padovan continue; 14240a708f8fSGustavo F. Padovan } 14250a708f8fSGustavo F. Padovan 1426c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 14270a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 142873ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 142973ffa904SGustavo F. Padovan chan->num_conf_req++; 14300a708f8fSGustavo F. Padovan } 14310a708f8fSGustavo F. Padovan 14326be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 14330a708f8fSGustavo F. Padovan } 14340a708f8fSGustavo F. Padovan 14353df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 14360a708f8fSGustavo F. Padovan } 14370a708f8fSGustavo F. Padovan 1438c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr. 1439b62f328bSVille Tervo * Returns closest match, locked. 1440b62f328bSVille Tervo */ 1441d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, 1442c2287681SIdo Yariv bdaddr_t *src, 1443c2287681SIdo Yariv bdaddr_t *dst) 1444b62f328bSVille Tervo { 144523691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 1446b62f328bSVille Tervo 144723691d75SGustavo F. Padovan read_lock(&chan_list_lock); 1448b62f328bSVille Tervo 144923691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 145089bc500eSGustavo F. Padovan if (state && c->state != state) 1451b62f328bSVille Tervo continue; 1452b62f328bSVille Tervo 145323691d75SGustavo F. Padovan if (c->scid == cid) { 1454c2287681SIdo Yariv int src_match, dst_match; 1455c2287681SIdo Yariv int src_any, dst_any; 1456c2287681SIdo Yariv 1457b62f328bSVille Tervo /* Exact match. */ 14587eafc59eSMarcel Holtmann src_match = !bacmp(&c->src, src); 14597eafc59eSMarcel Holtmann dst_match = !bacmp(&c->dst, dst); 1460c2287681SIdo Yariv if (src_match && dst_match) { 146123691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 146223691d75SGustavo F. Padovan return c; 146323691d75SGustavo F. Padovan } 1464b62f328bSVille Tervo 1465b62f328bSVille Tervo /* Closest match */ 14667eafc59eSMarcel Holtmann src_any = !bacmp(&c->src, BDADDR_ANY); 14677eafc59eSMarcel Holtmann dst_any = !bacmp(&c->dst, BDADDR_ANY); 1468c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1469c2287681SIdo Yariv (src_any && dst_any)) 147023691d75SGustavo F. Padovan c1 = c; 1471b62f328bSVille Tervo } 1472b62f328bSVille Tervo } 1473280f294fSGustavo F. Padovan 147423691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 1475b62f328bSVille Tervo 147623691d75SGustavo F. Padovan return c1; 1477b62f328bSVille Tervo } 1478b62f328bSVille Tervo 1479b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn) 1480b62f328bSVille Tervo { 1481cc8dba2bSMarcel Holtmann struct hci_conn *hcon = conn->hcon; 148223691d75SGustavo F. Padovan struct l2cap_chan *chan, *pchan; 1483cc8dba2bSMarcel Holtmann u8 dst_type; 1484b62f328bSVille Tervo 1485b62f328bSVille Tervo BT_DBG(""); 1486b62f328bSVille Tervo 1487b62f328bSVille Tervo /* Check if we have socket listening on cid */ 1488073d1cf3SJohan Hedberg pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT, 1489cc8dba2bSMarcel Holtmann &hcon->src, &hcon->dst); 149023691d75SGustavo F. Padovan if (!pchan) 1491b62f328bSVille Tervo return; 1492b62f328bSVille Tervo 149344f3b0fbSJohan Hedberg /* Client ATT sockets should override the server one */ 149444f3b0fbSJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, L2CAP_CID_ATT)) 149544f3b0fbSJohan Hedberg return; 149644f3b0fbSJohan Hedberg 1497cc8dba2bSMarcel Holtmann dst_type = bdaddr_type(hcon, hcon->dst_type); 1498cc8dba2bSMarcel Holtmann 1499cc8dba2bSMarcel Holtmann /* If device is blocked, do not create a channel for it */ 1500cc8dba2bSMarcel Holtmann if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, dst_type)) 1501cc8dba2bSMarcel Holtmann return; 1502cc8dba2bSMarcel Holtmann 15038ffb9290SGustavo Padovan l2cap_chan_lock(pchan); 150462f3a2cfSGustavo F. Padovan 150580b98027SGustavo Padovan chan = pchan->ops->new_connection(pchan); 150680808e43SGustavo F. Padovan if (!chan) 1507b62f328bSVille Tervo goto clean; 1508b62f328bSVille Tervo 15099f22398cSJohan Hedberg chan->dcid = L2CAP_CID_ATT; 15109f22398cSJohan Hedberg 1511cc8dba2bSMarcel Holtmann bacpy(&chan->src, &hcon->src); 1512cc8dba2bSMarcel Holtmann bacpy(&chan->dst, &hcon->dst); 1513cc8dba2bSMarcel Holtmann chan->src_type = bdaddr_type(hcon, hcon->src_type); 1514cc8dba2bSMarcel Holtmann chan->dst_type = dst_type; 1515b62f328bSVille Tervo 151644f3b0fbSJohan Hedberg __l2cap_chan_add(conn, chan); 151748454079SGustavo F. Padovan 1518b62f328bSVille Tervo clean: 15198ffb9290SGustavo Padovan l2cap_chan_unlock(pchan); 1520b62f328bSVille Tervo } 1521b62f328bSVille Tervo 15220a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn) 15230a708f8fSGustavo F. Padovan { 152448454079SGustavo F. Padovan struct l2cap_chan *chan; 1525cc110922SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 15260a708f8fSGustavo F. Padovan 15270a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 15280a708f8fSGustavo F. Padovan 1529d8729922SJohan Hedberg /* For outgoing pairing which doesn't necessarily have an 1530d8729922SJohan Hedberg * associated socket (e.g. mgmt_pair_device). 1531d8729922SJohan Hedberg */ 1532cc110922SVinicius Costa Gomes if (hcon->out && hcon->type == LE_LINK) 1533cc110922SVinicius Costa Gomes smp_conn_security(hcon, hcon->pending_sec_level); 1534160dc6acSVinicius Costa Gomes 15353df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 15360a708f8fSGustavo F. Padovan 153744f3b0fbSJohan Hedberg if (hcon->type == LE_LINK) 153844f3b0fbSJohan Hedberg l2cap_le_conn_ready(conn); 153944f3b0fbSJohan Hedberg 15403df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1541baa7e1faSGustavo F. Padovan 15426be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 15430a708f8fSGustavo F. Padovan 1544416fa752SAndrei Emeltchenko if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { 1545416fa752SAndrei Emeltchenko l2cap_chan_unlock(chan); 1546416fa752SAndrei Emeltchenko continue; 1547416fa752SAndrei Emeltchenko } 1548416fa752SAndrei Emeltchenko 1549cc110922SVinicius Costa Gomes if (hcon->type == LE_LINK) { 1550f1496deeSJohan Hedberg l2cap_le_start(chan); 155163128451SVinicius Costa Gomes } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 155274e75740SGustavo Padovan l2cap_chan_ready(chan); 1553b501d6a1SAnderson Briglia 15541c244f79SGustavo Padovan } else if (chan->state == BT_CONNECT) { 1555fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 15561c244f79SGustavo Padovan } 15570a708f8fSGustavo F. Padovan 15586be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 15590a708f8fSGustavo F. Padovan } 15600a708f8fSGustavo F. Padovan 15613df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 15620a708f8fSGustavo F. Padovan } 15630a708f8fSGustavo F. Padovan 15640a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */ 15650a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) 15660a708f8fSGustavo F. Padovan { 156748454079SGustavo F. Padovan struct l2cap_chan *chan; 15680a708f8fSGustavo F. Padovan 15690a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 15700a708f8fSGustavo F. Padovan 15713df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 15720a708f8fSGustavo F. Padovan 15733df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1574ecf61bdbSAndrei Emeltchenko if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) 15751d8b1fd5SGustavo Padovan l2cap_chan_set_err(chan, err); 15760a708f8fSGustavo F. Padovan } 15770a708f8fSGustavo F. Padovan 15783df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 15790a708f8fSGustavo F. Padovan } 15800a708f8fSGustavo F. Padovan 1581f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work) 15820a708f8fSGustavo F. Padovan { 1583f878fcadSGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 1584030013d8SGustavo F. Padovan info_timer.work); 15850a708f8fSGustavo F. Padovan 15860a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 15870a708f8fSGustavo F. Padovan conn->info_ident = 0; 15880a708f8fSGustavo F. Padovan 15890a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 15900a708f8fSGustavo F. Padovan } 15910a708f8fSGustavo F. Padovan 15922c8e1411SDavid Herrmann /* 15932c8e1411SDavid Herrmann * l2cap_user 15942c8e1411SDavid Herrmann * External modules can register l2cap_user objects on l2cap_conn. The ->probe 15952c8e1411SDavid Herrmann * callback is called during registration. The ->remove callback is called 15962c8e1411SDavid Herrmann * during unregistration. 15972c8e1411SDavid Herrmann * An l2cap_user object can either be explicitly unregistered or when the 15982c8e1411SDavid Herrmann * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon, 15992c8e1411SDavid Herrmann * l2cap->hchan, .. are valid as long as the remove callback hasn't been called. 16002c8e1411SDavid Herrmann * External modules must own a reference to the l2cap_conn object if they intend 16012c8e1411SDavid Herrmann * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at 16022c8e1411SDavid Herrmann * any time if they don't. 16032c8e1411SDavid Herrmann */ 16042c8e1411SDavid Herrmann 16052c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) 16062c8e1411SDavid Herrmann { 16072c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev; 16082c8e1411SDavid Herrmann int ret; 16092c8e1411SDavid Herrmann 16102c8e1411SDavid Herrmann /* We need to check whether l2cap_conn is registered. If it is not, we 16112c8e1411SDavid Herrmann * must not register the l2cap_user. l2cap_conn_del() is unregisters 16122c8e1411SDavid Herrmann * l2cap_conn objects, but doesn't provide its own locking. Instead, it 16132c8e1411SDavid Herrmann * relies on the parent hci_conn object to be locked. This itself relies 16142c8e1411SDavid Herrmann * on the hci_dev object to be locked. So we must lock the hci device 16152c8e1411SDavid Herrmann * here, too. */ 16162c8e1411SDavid Herrmann 16172c8e1411SDavid Herrmann hci_dev_lock(hdev); 16182c8e1411SDavid Herrmann 16192c8e1411SDavid Herrmann if (user->list.next || user->list.prev) { 16202c8e1411SDavid Herrmann ret = -EINVAL; 16212c8e1411SDavid Herrmann goto out_unlock; 16222c8e1411SDavid Herrmann } 16232c8e1411SDavid Herrmann 16242c8e1411SDavid Herrmann /* conn->hchan is NULL after l2cap_conn_del() was called */ 16252c8e1411SDavid Herrmann if (!conn->hchan) { 16262c8e1411SDavid Herrmann ret = -ENODEV; 16272c8e1411SDavid Herrmann goto out_unlock; 16282c8e1411SDavid Herrmann } 16292c8e1411SDavid Herrmann 16302c8e1411SDavid Herrmann ret = user->probe(conn, user); 16312c8e1411SDavid Herrmann if (ret) 16322c8e1411SDavid Herrmann goto out_unlock; 16332c8e1411SDavid Herrmann 16342c8e1411SDavid Herrmann list_add(&user->list, &conn->users); 16352c8e1411SDavid Herrmann ret = 0; 16362c8e1411SDavid Herrmann 16372c8e1411SDavid Herrmann out_unlock: 16382c8e1411SDavid Herrmann hci_dev_unlock(hdev); 16392c8e1411SDavid Herrmann return ret; 16402c8e1411SDavid Herrmann } 16412c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user); 16422c8e1411SDavid Herrmann 16432c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) 16442c8e1411SDavid Herrmann { 16452c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev; 16462c8e1411SDavid Herrmann 16472c8e1411SDavid Herrmann hci_dev_lock(hdev); 16482c8e1411SDavid Herrmann 16492c8e1411SDavid Herrmann if (!user->list.next || !user->list.prev) 16502c8e1411SDavid Herrmann goto out_unlock; 16512c8e1411SDavid Herrmann 16522c8e1411SDavid Herrmann list_del(&user->list); 16532c8e1411SDavid Herrmann user->list.next = NULL; 16542c8e1411SDavid Herrmann user->list.prev = NULL; 16552c8e1411SDavid Herrmann user->remove(conn, user); 16562c8e1411SDavid Herrmann 16572c8e1411SDavid Herrmann out_unlock: 16582c8e1411SDavid Herrmann hci_dev_unlock(hdev); 16592c8e1411SDavid Herrmann } 16602c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user); 16612c8e1411SDavid Herrmann 16622c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn) 16632c8e1411SDavid Herrmann { 16642c8e1411SDavid Herrmann struct l2cap_user *user; 16652c8e1411SDavid Herrmann 16662c8e1411SDavid Herrmann while (!list_empty(&conn->users)) { 16672c8e1411SDavid Herrmann user = list_first_entry(&conn->users, struct l2cap_user, list); 16682c8e1411SDavid Herrmann list_del(&user->list); 16692c8e1411SDavid Herrmann user->list.next = NULL; 16702c8e1411SDavid Herrmann user->list.prev = NULL; 16712c8e1411SDavid Herrmann user->remove(conn, user); 16722c8e1411SDavid Herrmann } 16732c8e1411SDavid Herrmann } 16742c8e1411SDavid Herrmann 16755d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err) 16765d3de7dfSVinicius Costa Gomes { 16775d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 16785d3de7dfSVinicius Costa Gomes struct l2cap_chan *chan, *l; 16795d3de7dfSVinicius Costa Gomes 16805d3de7dfSVinicius Costa Gomes if (!conn) 16815d3de7dfSVinicius Costa Gomes return; 16825d3de7dfSVinicius Costa Gomes 16835d3de7dfSVinicius Costa Gomes BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); 16845d3de7dfSVinicius Costa Gomes 16855d3de7dfSVinicius Costa Gomes kfree_skb(conn->rx_skb); 16865d3de7dfSVinicius Costa Gomes 16872c8e1411SDavid Herrmann l2cap_unregister_all_users(conn); 16882c8e1411SDavid Herrmann 16893df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 16903df91ea2SAndrei Emeltchenko 16915d3de7dfSVinicius Costa Gomes /* Kill channels */ 16925d3de7dfSVinicius Costa Gomes list_for_each_entry_safe(chan, l, &conn->chan_l, list) { 169361d6ef3eSMat Martineau l2cap_chan_hold(chan); 16946be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 16956be36555SAndrei Emeltchenko 16965d3de7dfSVinicius Costa Gomes l2cap_chan_del(chan, err); 16976be36555SAndrei Emeltchenko 16986be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16996be36555SAndrei Emeltchenko 170080b98027SGustavo Padovan chan->ops->close(chan); 170161d6ef3eSMat Martineau l2cap_chan_put(chan); 17025d3de7dfSVinicius Costa Gomes } 17035d3de7dfSVinicius Costa Gomes 17043df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 17053df91ea2SAndrei Emeltchenko 170673d80debSLuiz Augusto von Dentz hci_chan_del(conn->hchan); 170773d80debSLuiz Augusto von Dentz 17085d3de7dfSVinicius Costa Gomes if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1709127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->info_timer); 17105d3de7dfSVinicius Costa Gomes 171151a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) { 1712127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->security_timer); 17138aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 1714d26a2345SVinicius Costa Gomes } 17155d3de7dfSVinicius Costa Gomes 17165d3de7dfSVinicius Costa Gomes hcon->l2cap_data = NULL; 17179c903e37SDavid Herrmann conn->hchan = NULL; 17189c903e37SDavid Herrmann l2cap_conn_put(conn); 17195d3de7dfSVinicius Costa Gomes } 17205d3de7dfSVinicius Costa Gomes 17216c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work) 17225d3de7dfSVinicius Costa Gomes { 17236c9d42a1SGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 17246c9d42a1SGustavo F. Padovan security_timer.work); 17255d3de7dfSVinicius Costa Gomes 1726d06cc416SJohan Hedberg BT_DBG("conn %p", conn); 1727d06cc416SJohan Hedberg 1728d06cc416SJohan Hedberg if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) { 1729d06cc416SJohan Hedberg smp_chan_destroy(conn); 17305d3de7dfSVinicius Costa Gomes l2cap_conn_del(conn->hcon, ETIMEDOUT); 17315d3de7dfSVinicius Costa Gomes } 1732d06cc416SJohan Hedberg } 17335d3de7dfSVinicius Costa Gomes 1734baf43251SClaudio Takahasi static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) 17350a708f8fSGustavo F. Padovan { 17360a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 173773d80debSLuiz Augusto von Dentz struct hci_chan *hchan; 17380a708f8fSGustavo F. Padovan 1739baf43251SClaudio Takahasi if (conn) 17400a708f8fSGustavo F. Padovan return conn; 17410a708f8fSGustavo F. Padovan 174273d80debSLuiz Augusto von Dentz hchan = hci_chan_create(hcon); 174373d80debSLuiz Augusto von Dentz if (!hchan) 17440a708f8fSGustavo F. Padovan return NULL; 17450a708f8fSGustavo F. Padovan 17468bcde1f2SGustavo Padovan conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL); 174773d80debSLuiz Augusto von Dentz if (!conn) { 174873d80debSLuiz Augusto von Dentz hci_chan_del(hchan); 174973d80debSLuiz Augusto von Dentz return NULL; 175073d80debSLuiz Augusto von Dentz } 175173d80debSLuiz Augusto von Dentz 17529c903e37SDavid Herrmann kref_init(&conn->ref); 17530a708f8fSGustavo F. Padovan hcon->l2cap_data = conn; 17540a708f8fSGustavo F. Padovan conn->hcon = hcon; 17559c903e37SDavid Herrmann hci_conn_get(conn->hcon); 175673d80debSLuiz Augusto von Dentz conn->hchan = hchan; 17570a708f8fSGustavo F. Padovan 175873d80debSLuiz Augusto von Dentz BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); 17590a708f8fSGustavo F. Padovan 1760dcc042d5SAndrei Emeltchenko switch (hcon->type) { 1761dcc042d5SAndrei Emeltchenko case LE_LINK: 1762dcc042d5SAndrei Emeltchenko if (hcon->hdev->le_mtu) { 1763acd7d370SVille Tervo conn->mtu = hcon->hdev->le_mtu; 1764dcc042d5SAndrei Emeltchenko break; 1765dcc042d5SAndrei Emeltchenko } 1766dcc042d5SAndrei Emeltchenko /* fall through */ 1767dcc042d5SAndrei Emeltchenko default: 17680a708f8fSGustavo F. Padovan conn->mtu = hcon->hdev->acl_mtu; 1769dcc042d5SAndrei Emeltchenko break; 1770dcc042d5SAndrei Emeltchenko } 1771acd7d370SVille Tervo 17720a708f8fSGustavo F. Padovan conn->feat_mask = 0; 17730a708f8fSGustavo F. Padovan 1774848566b3SMarcel Holtmann if (hcon->type == ACL_LINK) 1775848566b3SMarcel Holtmann conn->hs_enabled = test_bit(HCI_HS_ENABLED, 1776848566b3SMarcel Holtmann &hcon->hdev->dev_flags); 1777848566b3SMarcel Holtmann 17780a708f8fSGustavo F. Padovan spin_lock_init(&conn->lock); 17793df91ea2SAndrei Emeltchenko mutex_init(&conn->chan_lock); 1780baa7e1faSGustavo F. Padovan 1781baa7e1faSGustavo F. Padovan INIT_LIST_HEAD(&conn->chan_l); 17822c8e1411SDavid Herrmann INIT_LIST_HEAD(&conn->users); 17830a708f8fSGustavo F. Padovan 17845d3de7dfSVinicius Costa Gomes if (hcon->type == LE_LINK) 17856c9d42a1SGustavo F. Padovan INIT_DELAYED_WORK(&conn->security_timer, security_timeout); 17865d3de7dfSVinicius Costa Gomes else 1787030013d8SGustavo F. Padovan INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); 17880a708f8fSGustavo F. Padovan 17899f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 17900a708f8fSGustavo F. Padovan 17910a708f8fSGustavo F. Padovan return conn; 17920a708f8fSGustavo F. Padovan } 17930a708f8fSGustavo F. Padovan 17949c903e37SDavid Herrmann static void l2cap_conn_free(struct kref *ref) 17959c903e37SDavid Herrmann { 17969c903e37SDavid Herrmann struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref); 17979c903e37SDavid Herrmann 17989c903e37SDavid Herrmann hci_conn_put(conn->hcon); 17999c903e37SDavid Herrmann kfree(conn); 18009c903e37SDavid Herrmann } 18019c903e37SDavid Herrmann 18029c903e37SDavid Herrmann void l2cap_conn_get(struct l2cap_conn *conn) 18039c903e37SDavid Herrmann { 18049c903e37SDavid Herrmann kref_get(&conn->ref); 18059c903e37SDavid Herrmann } 18069c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_get); 18079c903e37SDavid Herrmann 18089c903e37SDavid Herrmann void l2cap_conn_put(struct l2cap_conn *conn) 18099c903e37SDavid Herrmann { 18109c903e37SDavid Herrmann kref_put(&conn->ref, l2cap_conn_free); 18119c903e37SDavid Herrmann } 18129c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_put); 18139c903e37SDavid Herrmann 18140a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */ 18150a708f8fSGustavo F. Padovan 1816c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr. 18170a708f8fSGustavo F. Padovan * Returns closest match. 18180a708f8fSGustavo F. Padovan */ 1819c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, 1820c2287681SIdo Yariv bdaddr_t *src, 1821bf20fd4eSJohan Hedberg bdaddr_t *dst, 1822bf20fd4eSJohan Hedberg u8 link_type) 18230a708f8fSGustavo F. Padovan { 182423691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 18250a708f8fSGustavo F. Padovan 182623691d75SGustavo F. Padovan read_lock(&chan_list_lock); 18270a708f8fSGustavo F. Padovan 182823691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 182989bc500eSGustavo F. Padovan if (state && c->state != state) 18300a708f8fSGustavo F. Padovan continue; 18310a708f8fSGustavo F. Padovan 1832bf20fd4eSJohan Hedberg if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR) 1833bf20fd4eSJohan Hedberg continue; 1834bf20fd4eSJohan Hedberg 1835bf20fd4eSJohan Hedberg if (link_type == LE_LINK && c->src_type == BDADDR_BREDR) 1836bf20fd4eSJohan Hedberg continue; 1837bf20fd4eSJohan Hedberg 183823691d75SGustavo F. Padovan if (c->psm == psm) { 1839c2287681SIdo Yariv int src_match, dst_match; 1840c2287681SIdo Yariv int src_any, dst_any; 1841c2287681SIdo Yariv 18420a708f8fSGustavo F. Padovan /* Exact match. */ 18437eafc59eSMarcel Holtmann src_match = !bacmp(&c->src, src); 18447eafc59eSMarcel Holtmann dst_match = !bacmp(&c->dst, dst); 1845c2287681SIdo Yariv if (src_match && dst_match) { 1846a7567b20SJohannes Berg read_unlock(&chan_list_lock); 184723691d75SGustavo F. Padovan return c; 184823691d75SGustavo F. Padovan } 18490a708f8fSGustavo F. Padovan 18500a708f8fSGustavo F. Padovan /* Closest match */ 18517eafc59eSMarcel Holtmann src_any = !bacmp(&c->src, BDADDR_ANY); 18527eafc59eSMarcel Holtmann dst_any = !bacmp(&c->dst, BDADDR_ANY); 1853c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1854c2287681SIdo Yariv (src_any && dst_any)) 185523691d75SGustavo F. Padovan c1 = c; 18560a708f8fSGustavo F. Padovan } 18570a708f8fSGustavo F. Padovan } 18580a708f8fSGustavo F. Padovan 185923691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 18600a708f8fSGustavo F. Padovan 186123691d75SGustavo F. Padovan return c1; 18620a708f8fSGustavo F. Padovan } 18630a708f8fSGustavo F. Padovan 18648e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, 18658e9f9892SAndre Guedes bdaddr_t *dst, u8 dst_type) 18660a708f8fSGustavo F. Padovan { 18670a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 18680a708f8fSGustavo F. Padovan struct hci_conn *hcon; 18690a708f8fSGustavo F. Padovan struct hci_dev *hdev; 18700a708f8fSGustavo F. Padovan __u8 auth_type; 18710a708f8fSGustavo F. Padovan int err; 18720a708f8fSGustavo F. Padovan 18737eafc59eSMarcel Holtmann BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst, 1874ab19516aSSyam Sidhardhan dst_type, __le16_to_cpu(psm)); 18750a708f8fSGustavo F. Padovan 18767eafc59eSMarcel Holtmann hdev = hci_get_route(dst, &chan->src); 18770a708f8fSGustavo F. Padovan if (!hdev) 18780a708f8fSGustavo F. Padovan return -EHOSTUNREACH; 18790a708f8fSGustavo F. Padovan 188009fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 18810a708f8fSGustavo F. Padovan 18826be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 188303a00194SGustavo F. Padovan 188403a00194SGustavo F. Padovan /* PSM must be odd and lsb of upper byte must be 0 */ 188503a00194SGustavo F. Padovan if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid && 188603a00194SGustavo F. Padovan chan->chan_type != L2CAP_CHAN_RAW) { 188703a00194SGustavo F. Padovan err = -EINVAL; 188803a00194SGustavo F. Padovan goto done; 188903a00194SGustavo F. Padovan } 189003a00194SGustavo F. Padovan 189103a00194SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) { 189203a00194SGustavo F. Padovan err = -EINVAL; 189303a00194SGustavo F. Padovan goto done; 189403a00194SGustavo F. Padovan } 189503a00194SGustavo F. Padovan 189603a00194SGustavo F. Padovan switch (chan->mode) { 189703a00194SGustavo F. Padovan case L2CAP_MODE_BASIC: 189838319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 189903a00194SGustavo F. Padovan break; 190003a00194SGustavo F. Padovan case L2CAP_MODE_ERTM: 190103a00194SGustavo F. Padovan case L2CAP_MODE_STREAMING: 190203a00194SGustavo F. Padovan if (!disable_ertm) 190303a00194SGustavo F. Padovan break; 190403a00194SGustavo F. Padovan /* fall through */ 190503a00194SGustavo F. Padovan default: 190603a00194SGustavo F. Padovan err = -ENOTSUPP; 190703a00194SGustavo F. Padovan goto done; 190803a00194SGustavo F. Padovan } 190903a00194SGustavo F. Padovan 19100797e01dSGustavo Padovan switch (chan->state) { 191103a00194SGustavo F. Padovan case BT_CONNECT: 191203a00194SGustavo F. Padovan case BT_CONNECT2: 191303a00194SGustavo F. Padovan case BT_CONFIG: 191403a00194SGustavo F. Padovan /* Already connecting */ 191503a00194SGustavo F. Padovan err = 0; 191603a00194SGustavo F. Padovan goto done; 191703a00194SGustavo F. Padovan 191803a00194SGustavo F. Padovan case BT_CONNECTED: 191903a00194SGustavo F. Padovan /* Already connected */ 192003a00194SGustavo F. Padovan err = -EISCONN; 192103a00194SGustavo F. Padovan goto done; 192203a00194SGustavo F. Padovan 192303a00194SGustavo F. Padovan case BT_OPEN: 192403a00194SGustavo F. Padovan case BT_BOUND: 192503a00194SGustavo F. Padovan /* Can connect */ 192603a00194SGustavo F. Padovan break; 192703a00194SGustavo F. Padovan 192803a00194SGustavo F. Padovan default: 192903a00194SGustavo F. Padovan err = -EBADFD; 193003a00194SGustavo F. Padovan goto done; 193103a00194SGustavo F. Padovan } 193203a00194SGustavo F. Padovan 193303a00194SGustavo F. Padovan /* Set destination address and psm */ 19347eafc59eSMarcel Holtmann bacpy(&chan->dst, dst); 19354f1654e0SMarcel Holtmann chan->dst_type = dst_type; 19366be36555SAndrei Emeltchenko 193703a00194SGustavo F. Padovan chan->psm = psm; 193803a00194SGustavo F. Padovan chan->dcid = cid; 19390a708f8fSGustavo F. Padovan 19404343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 19410a708f8fSGustavo F. Padovan 1942f224ca5fSJohan Hedberg if (bdaddr_type_is_le(dst_type)) 19438e9f9892SAndre Guedes hcon = hci_connect(hdev, LE_LINK, dst, dst_type, 19444343478fSGustavo F. Padovan chan->sec_level, auth_type); 1945acd7d370SVille Tervo else 19468e9f9892SAndre Guedes hcon = hci_connect(hdev, ACL_LINK, dst, dst_type, 19474343478fSGustavo F. Padovan chan->sec_level, auth_type); 1948acd7d370SVille Tervo 194930e76272SVille Tervo if (IS_ERR(hcon)) { 195030e76272SVille Tervo err = PTR_ERR(hcon); 19510a708f8fSGustavo F. Padovan goto done; 195230e76272SVille Tervo } 19530a708f8fSGustavo F. Padovan 1954baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon); 19550a708f8fSGustavo F. Padovan if (!conn) { 195676a68ba0SDavid Herrmann hci_conn_drop(hcon); 195730e76272SVille Tervo err = -ENOMEM; 19580a708f8fSGustavo F. Padovan goto done; 19590a708f8fSGustavo F. Padovan } 19600a708f8fSGustavo F. Padovan 1961141d5706SJohan Hedberg if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { 196276a68ba0SDavid Herrmann hci_conn_drop(hcon); 1963141d5706SJohan Hedberg err = -EBUSY; 19649f0caeb1SVinicius Costa Gomes goto done; 19659f0caeb1SVinicius Costa Gomes } 19669f0caeb1SVinicius Costa Gomes 19670a708f8fSGustavo F. Padovan /* Update source addr of the socket */ 19687eafc59eSMarcel Holtmann bacpy(&chan->src, &hcon->src); 19694f1654e0SMarcel Holtmann chan->src_type = bdaddr_type(hcon, hcon->src_type); 19700a708f8fSGustavo F. Padovan 19716be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 197248454079SGustavo F. Padovan l2cap_chan_add(conn, chan); 19736be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 197448454079SGustavo F. Padovan 19755ee9891dSJohan Hedberg /* l2cap_chan_add takes its own ref so we can drop this one */ 19765ee9891dSJohan Hedberg hci_conn_drop(hcon); 19775ee9891dSJohan Hedberg 19786be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECT); 19798d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 19800a708f8fSGustavo F. Padovan 19810a708f8fSGustavo F. Padovan if (hcon->state == BT_CONNECTED) { 1982715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1983c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 1984d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) 19856be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECTED); 19860a708f8fSGustavo F. Padovan } else 1987fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 19880a708f8fSGustavo F. Padovan } 19890a708f8fSGustavo F. Padovan 199030e76272SVille Tervo err = 0; 199130e76272SVille Tervo 19920a708f8fSGustavo F. Padovan done: 19936be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 199409fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 19950a708f8fSGustavo F. Padovan hci_dev_put(hdev); 19960a708f8fSGustavo F. Padovan return err; 19970a708f8fSGustavo F. Padovan } 19980a708f8fSGustavo F. Padovan 1999721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work) 20000a708f8fSGustavo F. Padovan { 2001721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 2002721c4181SGustavo F. Padovan monitor_timer.work); 20030a708f8fSGustavo F. Padovan 2004525cd185SGustavo F. Padovan BT_DBG("chan %p", chan); 20050a708f8fSGustavo F. Padovan 20066be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 20076be36555SAndrei Emeltchenko 200880909e04SMat Martineau if (!chan->conn) { 20096be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 20108d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 20110a708f8fSGustavo F. Padovan return; 20120a708f8fSGustavo F. Padovan } 20130a708f8fSGustavo F. Padovan 2014401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO); 20150a708f8fSGustavo F. Padovan 20166be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 20178d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 20180a708f8fSGustavo F. Padovan } 20190a708f8fSGustavo F. Padovan 2020721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work) 20210a708f8fSGustavo F. Padovan { 2022721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 2023721c4181SGustavo F. Padovan retrans_timer.work); 20240a708f8fSGustavo F. Padovan 202549208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 20260a708f8fSGustavo F. Padovan 20276be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 20286be36555SAndrei Emeltchenko 202980909e04SMat Martineau if (!chan->conn) { 203080909e04SMat Martineau l2cap_chan_unlock(chan); 203180909e04SMat Martineau l2cap_chan_put(chan); 203280909e04SMat Martineau return; 203380909e04SMat Martineau } 20340a708f8fSGustavo F. Padovan 2035401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO); 20366be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 20378d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 20380a708f8fSGustavo F. Padovan } 20390a708f8fSGustavo F. Padovan 2040d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan, 20413733937dSMat Martineau struct sk_buff_head *skbs) 20420a708f8fSGustavo F. Padovan { 20430a708f8fSGustavo F. Padovan struct sk_buff *skb; 20443733937dSMat Martineau struct l2cap_ctrl *control; 20450a708f8fSGustavo F. Padovan 20463733937dSMat Martineau BT_DBG("chan %p, skbs %p", chan, skbs); 20473733937dSMat Martineau 2048b99e13adSMat Martineau if (__chan_is_moving(chan)) 2049b99e13adSMat Martineau return; 2050b99e13adSMat Martineau 20513733937dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 20523733937dSMat Martineau 20533733937dSMat Martineau while (!skb_queue_empty(&chan->tx_q)) { 20543733937dSMat Martineau 20553733937dSMat Martineau skb = skb_dequeue(&chan->tx_q); 20563733937dSMat Martineau 20573733937dSMat Martineau bt_cb(skb)->control.retries = 1; 20583733937dSMat Martineau control = &bt_cb(skb)->control; 20593733937dSMat Martineau 20603733937dSMat Martineau control->reqseq = 0; 20613733937dSMat Martineau control->txseq = chan->next_tx_seq; 20623733937dSMat Martineau 20633733937dSMat Martineau __pack_control(chan, control, skb); 20640a708f8fSGustavo F. Padovan 206547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 20663733937dSMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 20673733937dSMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 20680a708f8fSGustavo F. Padovan } 20690a708f8fSGustavo F. Padovan 20704343478fSGustavo F. Padovan l2cap_do_send(chan, skb); 20710a708f8fSGustavo F. Padovan 2072b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 20733733937dSMat Martineau 2074836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 20753733937dSMat Martineau chan->frames_sent++; 20760a708f8fSGustavo F. Padovan } 20770a708f8fSGustavo F. Padovan } 20780a708f8fSGustavo F. Padovan 207967c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan) 20800a708f8fSGustavo F. Padovan { 20810a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 208218a48e76SMat Martineau struct l2cap_ctrl *control; 208318a48e76SMat Martineau int sent = 0; 208418a48e76SMat Martineau 208518a48e76SMat Martineau BT_DBG("chan %p", chan); 20860a708f8fSGustavo F. Padovan 208789bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 20880a708f8fSGustavo F. Padovan return -ENOTCONN; 20890a708f8fSGustavo F. Padovan 209094122bbeSMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 209194122bbeSMat Martineau return 0; 209294122bbeSMat Martineau 2093b99e13adSMat Martineau if (__chan_is_moving(chan)) 2094b99e13adSMat Martineau return 0; 2095b99e13adSMat Martineau 209618a48e76SMat Martineau while (chan->tx_send_head && 209718a48e76SMat Martineau chan->unacked_frames < chan->remote_tx_win && 209818a48e76SMat Martineau chan->tx_state == L2CAP_TX_STATE_XMIT) { 20990a708f8fSGustavo F. Padovan 210018a48e76SMat Martineau skb = chan->tx_send_head; 21010a708f8fSGustavo F. Padovan 210218a48e76SMat Martineau bt_cb(skb)->control.retries = 1; 210318a48e76SMat Martineau control = &bt_cb(skb)->control; 21040a708f8fSGustavo F. Padovan 2105e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 210618a48e76SMat Martineau control->final = 1; 2107e2ab4353SGustavo F. Padovan 210818a48e76SMat Martineau control->reqseq = chan->buffer_seq; 210918a48e76SMat Martineau chan->last_acked_seq = chan->buffer_seq; 211018a48e76SMat Martineau control->txseq = chan->next_tx_seq; 21110a708f8fSGustavo F. Padovan 211218a48e76SMat Martineau __pack_control(chan, control, skb); 21130a708f8fSGustavo F. Padovan 211447d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 211518a48e76SMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 211618a48e76SMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 21170a708f8fSGustavo F. Padovan } 21180a708f8fSGustavo F. Padovan 211918a48e76SMat Martineau /* Clone after data has been modified. Data is assumed to be 212018a48e76SMat Martineau read-only (for locking purposes) on cloned sk_buffs. 212118a48e76SMat Martineau */ 212218a48e76SMat Martineau tx_skb = skb_clone(skb, GFP_KERNEL); 212318a48e76SMat Martineau 212418a48e76SMat Martineau if (!tx_skb) 212518a48e76SMat Martineau break; 21260a708f8fSGustavo F. Padovan 21271a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 21280a708f8fSGustavo F. Padovan 2129836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 21306a026610SGustavo F. Padovan chan->unacked_frames++; 21316a026610SGustavo F. Padovan chan->frames_sent++; 213218a48e76SMat Martineau sent++; 21330a708f8fSGustavo F. Padovan 213458d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 213558d35f87SGustavo F. Padovan chan->tx_send_head = NULL; 21360a708f8fSGustavo F. Padovan else 213758d35f87SGustavo F. Padovan chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); 213818a48e76SMat Martineau 213918a48e76SMat Martineau l2cap_do_send(chan, tx_skb); 2140b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 21410a708f8fSGustavo F. Padovan } 21420a708f8fSGustavo F. Padovan 2143b4400672SAndrei Emeltchenko BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent, 2144b4400672SAndrei Emeltchenko chan->unacked_frames, skb_queue_len(&chan->tx_q)); 214518a48e76SMat Martineau 214618a48e76SMat Martineau return sent; 21470a708f8fSGustavo F. Padovan } 21480a708f8fSGustavo F. Padovan 2149e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan) 2150e1fbd4c1SMat Martineau { 2151e1fbd4c1SMat Martineau struct l2cap_ctrl control; 2152e1fbd4c1SMat Martineau struct sk_buff *skb; 2153e1fbd4c1SMat Martineau struct sk_buff *tx_skb; 2154e1fbd4c1SMat Martineau u16 seq; 2155e1fbd4c1SMat Martineau 2156e1fbd4c1SMat Martineau BT_DBG("chan %p", chan); 2157e1fbd4c1SMat Martineau 2158e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 2159e1fbd4c1SMat Martineau return; 2160e1fbd4c1SMat Martineau 2161b99e13adSMat Martineau if (__chan_is_moving(chan)) 2162b99e13adSMat Martineau return; 2163b99e13adSMat Martineau 2164e1fbd4c1SMat Martineau while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) { 2165e1fbd4c1SMat Martineau seq = l2cap_seq_list_pop(&chan->retrans_list); 2166e1fbd4c1SMat Martineau 2167e1fbd4c1SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq); 2168e1fbd4c1SMat Martineau if (!skb) { 2169e1fbd4c1SMat Martineau BT_DBG("Error: Can't retransmit seq %d, frame missing", 2170e1fbd4c1SMat Martineau seq); 2171e1fbd4c1SMat Martineau continue; 2172e1fbd4c1SMat Martineau } 2173e1fbd4c1SMat Martineau 2174e1fbd4c1SMat Martineau bt_cb(skb)->control.retries++; 2175e1fbd4c1SMat Martineau control = bt_cb(skb)->control; 2176e1fbd4c1SMat Martineau 2177e1fbd4c1SMat Martineau if (chan->max_tx != 0 && 2178e1fbd4c1SMat Martineau bt_cb(skb)->control.retries > chan->max_tx) { 2179e1fbd4c1SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 21805e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 2181e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2182e1fbd4c1SMat Martineau break; 2183e1fbd4c1SMat Martineau } 2184e1fbd4c1SMat Martineau 2185e1fbd4c1SMat Martineau control.reqseq = chan->buffer_seq; 2186e1fbd4c1SMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 2187e1fbd4c1SMat Martineau control.final = 1; 2188e1fbd4c1SMat Martineau else 2189e1fbd4c1SMat Martineau control.final = 0; 2190e1fbd4c1SMat Martineau 2191e1fbd4c1SMat Martineau if (skb_cloned(skb)) { 2192e1fbd4c1SMat Martineau /* Cloned sk_buffs are read-only, so we need a 2193e1fbd4c1SMat Martineau * writeable copy 2194e1fbd4c1SMat Martineau */ 21958bcde1f2SGustavo Padovan tx_skb = skb_copy(skb, GFP_KERNEL); 2196e1fbd4c1SMat Martineau } else { 21978bcde1f2SGustavo Padovan tx_skb = skb_clone(skb, GFP_KERNEL); 2198e1fbd4c1SMat Martineau } 2199e1fbd4c1SMat Martineau 2200e1fbd4c1SMat Martineau if (!tx_skb) { 2201e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2202e1fbd4c1SMat Martineau break; 2203e1fbd4c1SMat Martineau } 2204e1fbd4c1SMat Martineau 2205e1fbd4c1SMat Martineau /* Update skb contents */ 2206e1fbd4c1SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 2207e1fbd4c1SMat Martineau put_unaligned_le32(__pack_extended_control(&control), 2208e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 2209e1fbd4c1SMat Martineau } else { 2210e1fbd4c1SMat Martineau put_unaligned_le16(__pack_enhanced_control(&control), 2211e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 2212e1fbd4c1SMat Martineau } 2213e1fbd4c1SMat Martineau 2214e1fbd4c1SMat Martineau if (chan->fcs == L2CAP_FCS_CRC16) { 2215e1fbd4c1SMat Martineau u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len); 2216e1fbd4c1SMat Martineau put_unaligned_le16(fcs, skb_put(tx_skb, 2217e1fbd4c1SMat Martineau L2CAP_FCS_SIZE)); 2218e1fbd4c1SMat Martineau } 2219e1fbd4c1SMat Martineau 2220e1fbd4c1SMat Martineau l2cap_do_send(chan, tx_skb); 2221e1fbd4c1SMat Martineau 2222e1fbd4c1SMat Martineau BT_DBG("Resent txseq %d", control.txseq); 2223e1fbd4c1SMat Martineau 2224e1fbd4c1SMat Martineau chan->last_acked_seq = chan->buffer_seq; 2225e1fbd4c1SMat Martineau } 2226e1fbd4c1SMat Martineau } 2227e1fbd4c1SMat Martineau 2228f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan, 2229f80842a8SMat Martineau struct l2cap_ctrl *control) 2230f80842a8SMat Martineau { 2231f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2232f80842a8SMat Martineau 2233f80842a8SMat Martineau l2cap_seq_list_append(&chan->retrans_list, control->reqseq); 2234f80842a8SMat Martineau l2cap_ertm_resend(chan); 2235f80842a8SMat Martineau } 2236f80842a8SMat Martineau 2237d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan, 2238d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 2239d2a7ac5dSMat Martineau { 2240e1fbd4c1SMat Martineau struct sk_buff *skb; 2241e1fbd4c1SMat Martineau 2242e1fbd4c1SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2243e1fbd4c1SMat Martineau 2244e1fbd4c1SMat Martineau if (control->poll) 2245e1fbd4c1SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 2246e1fbd4c1SMat Martineau 2247e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2248e1fbd4c1SMat Martineau 2249e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 2250e1fbd4c1SMat Martineau return; 2251e1fbd4c1SMat Martineau 2252e1fbd4c1SMat Martineau if (chan->unacked_frames) { 2253e1fbd4c1SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 2254e1fbd4c1SMat Martineau if (bt_cb(skb)->control.txseq == control->reqseq || 2255e1fbd4c1SMat Martineau skb == chan->tx_send_head) 2256e1fbd4c1SMat Martineau break; 2257e1fbd4c1SMat Martineau } 2258e1fbd4c1SMat Martineau 2259e1fbd4c1SMat Martineau skb_queue_walk_from(&chan->tx_q, skb) { 2260e1fbd4c1SMat Martineau if (skb == chan->tx_send_head) 2261e1fbd4c1SMat Martineau break; 2262e1fbd4c1SMat Martineau 2263e1fbd4c1SMat Martineau l2cap_seq_list_append(&chan->retrans_list, 2264e1fbd4c1SMat Martineau bt_cb(skb)->control.txseq); 2265e1fbd4c1SMat Martineau } 2266e1fbd4c1SMat Martineau 2267e1fbd4c1SMat Martineau l2cap_ertm_resend(chan); 2268e1fbd4c1SMat Martineau } 2269d2a7ac5dSMat Martineau } 2270d2a7ac5dSMat Martineau 2271b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan) 2272b17e73bbSSzymon Janc { 22730a0aba42SMat Martineau struct l2cap_ctrl control; 22740a0aba42SMat Martineau u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq, 22750a0aba42SMat Martineau chan->last_acked_seq); 22760a0aba42SMat Martineau int threshold; 22770a0aba42SMat Martineau 22780a0aba42SMat Martineau BT_DBG("chan %p last_acked_seq %d buffer_seq %d", 22790a0aba42SMat Martineau chan, chan->last_acked_seq, chan->buffer_seq); 22800a0aba42SMat Martineau 22810a0aba42SMat Martineau memset(&control, 0, sizeof(control)); 22820a0aba42SMat Martineau control.sframe = 1; 22830a0aba42SMat Martineau 22840a0aba42SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 22850a0aba42SMat Martineau chan->rx_state == L2CAP_RX_STATE_RECV) { 2286b17e73bbSSzymon Janc __clear_ack_timer(chan); 22870a0aba42SMat Martineau control.super = L2CAP_SUPER_RNR; 22880a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 22890a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 22900a0aba42SMat Martineau } else { 22910a0aba42SMat Martineau if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) { 22920a0aba42SMat Martineau l2cap_ertm_send(chan); 22930a0aba42SMat Martineau /* If any i-frames were sent, they included an ack */ 22940a0aba42SMat Martineau if (chan->buffer_seq == chan->last_acked_seq) 22950a0aba42SMat Martineau frames_to_ack = 0; 22960a0aba42SMat Martineau } 22970a0aba42SMat Martineau 2298c20f8e35SMat Martineau /* Ack now if the window is 3/4ths full. 22990a0aba42SMat Martineau * Calculate without mul or div 23000a0aba42SMat Martineau */ 2301c20f8e35SMat Martineau threshold = chan->ack_win; 23020a0aba42SMat Martineau threshold += threshold << 1; 23030a0aba42SMat Martineau threshold >>= 2; 23040a0aba42SMat Martineau 2305b4400672SAndrei Emeltchenko BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack, 23060a0aba42SMat Martineau threshold); 23070a0aba42SMat Martineau 23080a0aba42SMat Martineau if (frames_to_ack >= threshold) { 23090a0aba42SMat Martineau __clear_ack_timer(chan); 23100a0aba42SMat Martineau control.super = L2CAP_SUPER_RR; 23110a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 23120a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 23130a0aba42SMat Martineau frames_to_ack = 0; 23140a0aba42SMat Martineau } 23150a0aba42SMat Martineau 23160a0aba42SMat Martineau if (frames_to_ack) 23170a0aba42SMat Martineau __set_ack_timer(chan); 23180a0aba42SMat Martineau } 2319b17e73bbSSzymon Janc } 2320b17e73bbSSzymon Janc 232104124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, 232204124681SGustavo F. Padovan struct msghdr *msg, int len, 232304124681SGustavo F. Padovan int count, struct sk_buff *skb) 23240a708f8fSGustavo F. Padovan { 23250952a57aSAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 23260a708f8fSGustavo F. Padovan struct sk_buff **frag; 232790338947SGustavo Padovan int sent = 0; 23280a708f8fSGustavo F. Padovan 23290a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) 23300a708f8fSGustavo F. Padovan return -EFAULT; 23310a708f8fSGustavo F. Padovan 23320a708f8fSGustavo F. Padovan sent += count; 23330a708f8fSGustavo F. Padovan len -= count; 23340a708f8fSGustavo F. Padovan 23350a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 23360a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 23370a708f8fSGustavo F. Padovan while (len) { 2338fbe00700SGustavo Padovan struct sk_buff *tmp; 2339fbe00700SGustavo Padovan 23400a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 23410a708f8fSGustavo F. Padovan 2342fbe00700SGustavo Padovan tmp = chan->ops->alloc_skb(chan, count, 234390338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 2344fbe00700SGustavo Padovan if (IS_ERR(tmp)) 2345fbe00700SGustavo Padovan return PTR_ERR(tmp); 23462f7719ceSAndrei Emeltchenko 2347fbe00700SGustavo Padovan *frag = tmp; 2348fbe00700SGustavo Padovan 23490a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) 23500a708f8fSGustavo F. Padovan return -EFAULT; 23510a708f8fSGustavo F. Padovan 23525e59b791SLuiz Augusto von Dentz (*frag)->priority = skb->priority; 23535e59b791SLuiz Augusto von Dentz 23540a708f8fSGustavo F. Padovan sent += count; 23550a708f8fSGustavo F. Padovan len -= count; 23560a708f8fSGustavo F. Padovan 23572d0ed3d5SGustavo Padovan skb->len += (*frag)->len; 23582d0ed3d5SGustavo Padovan skb->data_len += (*frag)->len; 23592d0ed3d5SGustavo Padovan 23600a708f8fSGustavo F. Padovan frag = &(*frag)->next; 23610a708f8fSGustavo F. Padovan } 23620a708f8fSGustavo F. Padovan 23630a708f8fSGustavo F. Padovan return sent; 23640a708f8fSGustavo F. Padovan } 23650a708f8fSGustavo F. Padovan 23665e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, 23675e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 23685e59b791SLuiz Augusto von Dentz u32 priority) 23690a708f8fSGustavo F. Padovan { 23708c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 23710a708f8fSGustavo F. Padovan struct sk_buff *skb; 237203a51213SAndrei Emeltchenko int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; 23730a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 23740a708f8fSGustavo F. Padovan 237543b1b8dfSMarcel Holtmann BT_DBG("chan %p psm 0x%2.2x len %zu priority %u", chan, 237643b1b8dfSMarcel Holtmann __le16_to_cpu(chan->psm), len, priority); 23770a708f8fSGustavo F. Padovan 23780a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 23792f7719ceSAndrei Emeltchenko 23802f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 238190338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 238290338947SGustavo Padovan if (IS_ERR(skb)) 238390338947SGustavo Padovan return skb; 23840a708f8fSGustavo F. Padovan 23855e59b791SLuiz Augusto von Dentz skb->priority = priority; 23865e59b791SLuiz Augusto von Dentz 23870a708f8fSGustavo F. Padovan /* Create L2CAP header */ 23880a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2389fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 2390daf6a78cSAndrei Emeltchenko lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); 239143b1b8dfSMarcel Holtmann put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE)); 23920a708f8fSGustavo F. Padovan 23930952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 23940a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 23950a708f8fSGustavo F. Padovan kfree_skb(skb); 23960a708f8fSGustavo F. Padovan return ERR_PTR(err); 23970a708f8fSGustavo F. Padovan } 23980a708f8fSGustavo F. Padovan return skb; 23990a708f8fSGustavo F. Padovan } 24000a708f8fSGustavo F. Padovan 24015e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, 24025e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 24035e59b791SLuiz Augusto von Dentz u32 priority) 24040a708f8fSGustavo F. Padovan { 24058c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 24060a708f8fSGustavo F. Padovan struct sk_buff *skb; 2407f2ba7faeSGustavo Padovan int err, count; 24080a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 24090a708f8fSGustavo F. Padovan 2410b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 24110a708f8fSGustavo F. Padovan 2412f2ba7faeSGustavo Padovan count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); 24132f7719ceSAndrei Emeltchenko 2414f2ba7faeSGustavo Padovan skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE, 241590338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 241690338947SGustavo Padovan if (IS_ERR(skb)) 241790338947SGustavo Padovan return skb; 24180a708f8fSGustavo F. Padovan 24195e59b791SLuiz Augusto von Dentz skb->priority = priority; 24205e59b791SLuiz Augusto von Dentz 24210a708f8fSGustavo F. Padovan /* Create L2CAP header */ 24220a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2423fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 24246ff9b5efSGustavo Padovan lh->len = cpu_to_le16(len); 24250a708f8fSGustavo F. Padovan 24260952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 24270a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 24280a708f8fSGustavo F. Padovan kfree_skb(skb); 24290a708f8fSGustavo F. Padovan return ERR_PTR(err); 24300a708f8fSGustavo F. Padovan } 24310a708f8fSGustavo F. Padovan return skb; 24320a708f8fSGustavo F. Padovan } 24330a708f8fSGustavo F. Padovan 2434ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, 2435ab0ff76dSLuiz Augusto von Dentz struct msghdr *msg, size_t len, 243694122bbeSMat Martineau u16 sdulen) 24370a708f8fSGustavo F. Padovan { 24388c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 24390a708f8fSGustavo F. Padovan struct sk_buff *skb; 2440e4ca6d98SAndrei Emeltchenko int err, count, hlen; 24410a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 24420a708f8fSGustavo F. Padovan 2443b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 24440a708f8fSGustavo F. Padovan 24450a708f8fSGustavo F. Padovan if (!conn) 24460a708f8fSGustavo F. Padovan return ERR_PTR(-ENOTCONN); 24470a708f8fSGustavo F. Padovan 2448ba7aa64fSGustavo Padovan hlen = __ertm_hdr_size(chan); 2449e4ca6d98SAndrei Emeltchenko 24500a708f8fSGustavo F. Padovan if (sdulen) 245103a51213SAndrei Emeltchenko hlen += L2CAP_SDULEN_SIZE; 24520a708f8fSGustavo F. Padovan 245347d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 245403a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 24550a708f8fSGustavo F. Padovan 24560a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 24572f7719ceSAndrei Emeltchenko 24582f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 245990338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 246090338947SGustavo Padovan if (IS_ERR(skb)) 246190338947SGustavo Padovan return skb; 24620a708f8fSGustavo F. Padovan 24630a708f8fSGustavo F. Padovan /* Create L2CAP header */ 24640a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2465fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 24660a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 246788843ab0SAndrei Emeltchenko 246818a48e76SMat Martineau /* Control header is populated later */ 246918a48e76SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 247018a48e76SMat Martineau put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 247118a48e76SMat Martineau else 247218a48e76SMat Martineau put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 247388843ab0SAndrei Emeltchenko 24740a708f8fSGustavo F. Padovan if (sdulen) 247503a51213SAndrei Emeltchenko put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 24760a708f8fSGustavo F. Padovan 24770952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 24780a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 24790a708f8fSGustavo F. Padovan kfree_skb(skb); 24800a708f8fSGustavo F. Padovan return ERR_PTR(err); 24810a708f8fSGustavo F. Padovan } 24820a708f8fSGustavo F. Padovan 248318a48e76SMat Martineau bt_cb(skb)->control.fcs = chan->fcs; 24843ce3514fSMat Martineau bt_cb(skb)->control.retries = 0; 24850a708f8fSGustavo F. Padovan return skb; 24860a708f8fSGustavo F. Padovan } 24870a708f8fSGustavo F. Padovan 248894122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan, 248994122bbeSMat Martineau struct sk_buff_head *seg_queue, 249094122bbeSMat Martineau struct msghdr *msg, size_t len) 24910a708f8fSGustavo F. Padovan { 24920a708f8fSGustavo F. Padovan struct sk_buff *skb; 249394122bbeSMat Martineau u16 sdu_len; 249494122bbeSMat Martineau size_t pdu_len; 249594122bbeSMat Martineau u8 sar; 24960a708f8fSGustavo F. Padovan 2497b4400672SAndrei Emeltchenko BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); 24980a708f8fSGustavo F. Padovan 249994122bbeSMat Martineau /* It is critical that ERTM PDUs fit in a single HCI fragment, 250094122bbeSMat Martineau * so fragmented skbs are not used. The HCI layer's handling 250194122bbeSMat Martineau * of fragmented skbs is not compatible with ERTM's queueing. 250294122bbeSMat Martineau */ 250394122bbeSMat Martineau 250494122bbeSMat Martineau /* PDU size is derived from the HCI MTU */ 250594122bbeSMat Martineau pdu_len = chan->conn->mtu; 250694122bbeSMat Martineau 2507a549574dSMat Martineau /* Constrain PDU size for BR/EDR connections */ 2508a549574dSMat Martineau if (!chan->hs_hcon) 250994122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); 251094122bbeSMat Martineau 251194122bbeSMat Martineau /* Adjust for largest possible L2CAP overhead. */ 251235d401dfSGustavo Padovan if (chan->fcs) 251335d401dfSGustavo Padovan pdu_len -= L2CAP_FCS_SIZE; 251435d401dfSGustavo Padovan 2515ba7aa64fSGustavo Padovan pdu_len -= __ertm_hdr_size(chan); 251694122bbeSMat Martineau 251794122bbeSMat Martineau /* Remote device may have requested smaller PDUs */ 251894122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, chan->remote_mps); 251994122bbeSMat Martineau 252094122bbeSMat Martineau if (len <= pdu_len) { 252194122bbeSMat Martineau sar = L2CAP_SAR_UNSEGMENTED; 252294122bbeSMat Martineau sdu_len = 0; 252394122bbeSMat Martineau pdu_len = len; 252494122bbeSMat Martineau } else { 252594122bbeSMat Martineau sar = L2CAP_SAR_START; 252694122bbeSMat Martineau sdu_len = len; 252794122bbeSMat Martineau pdu_len -= L2CAP_SDULEN_SIZE; 252894122bbeSMat Martineau } 25290a708f8fSGustavo F. Padovan 25300a708f8fSGustavo F. Padovan while (len > 0) { 253194122bbeSMat Martineau skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len); 25320a708f8fSGustavo F. Padovan 25330a708f8fSGustavo F. Padovan if (IS_ERR(skb)) { 253494122bbeSMat Martineau __skb_queue_purge(seg_queue); 25350a708f8fSGustavo F. Padovan return PTR_ERR(skb); 25360a708f8fSGustavo F. Padovan } 25370a708f8fSGustavo F. Padovan 253894122bbeSMat Martineau bt_cb(skb)->control.sar = sar; 253994122bbeSMat Martineau __skb_queue_tail(seg_queue, skb); 25400a708f8fSGustavo F. Padovan 254194122bbeSMat Martineau len -= pdu_len; 254294122bbeSMat Martineau if (sdu_len) { 254394122bbeSMat Martineau sdu_len = 0; 254494122bbeSMat Martineau pdu_len += L2CAP_SDULEN_SIZE; 254594122bbeSMat Martineau } 254694122bbeSMat Martineau 254794122bbeSMat Martineau if (len <= pdu_len) { 254894122bbeSMat Martineau sar = L2CAP_SAR_END; 254994122bbeSMat Martineau pdu_len = len; 255094122bbeSMat Martineau } else { 255194122bbeSMat Martineau sar = L2CAP_SAR_CONTINUE; 255294122bbeSMat Martineau } 255394122bbeSMat Martineau } 255494122bbeSMat Martineau 2555f0f62799SGustavo Padovan return 0; 25560a708f8fSGustavo F. Padovan } 25570a708f8fSGustavo F. Padovan 2558177f8f2bSJohan Hedberg static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan, 2559177f8f2bSJohan Hedberg struct msghdr *msg, 2560177f8f2bSJohan Hedberg size_t len, u16 sdulen) 2561177f8f2bSJohan Hedberg { 2562177f8f2bSJohan Hedberg struct l2cap_conn *conn = chan->conn; 2563177f8f2bSJohan Hedberg struct sk_buff *skb; 2564177f8f2bSJohan Hedberg int err, count, hlen; 2565177f8f2bSJohan Hedberg struct l2cap_hdr *lh; 2566177f8f2bSJohan Hedberg 2567177f8f2bSJohan Hedberg BT_DBG("chan %p len %zu", chan, len); 2568177f8f2bSJohan Hedberg 2569177f8f2bSJohan Hedberg if (!conn) 2570177f8f2bSJohan Hedberg return ERR_PTR(-ENOTCONN); 2571177f8f2bSJohan Hedberg 2572177f8f2bSJohan Hedberg hlen = L2CAP_HDR_SIZE; 2573177f8f2bSJohan Hedberg 2574177f8f2bSJohan Hedberg if (sdulen) 2575177f8f2bSJohan Hedberg hlen += L2CAP_SDULEN_SIZE; 2576177f8f2bSJohan Hedberg 2577177f8f2bSJohan Hedberg count = min_t(unsigned int, (conn->mtu - hlen), len); 2578177f8f2bSJohan Hedberg 2579177f8f2bSJohan Hedberg skb = chan->ops->alloc_skb(chan, count + hlen, 2580177f8f2bSJohan Hedberg msg->msg_flags & MSG_DONTWAIT); 2581177f8f2bSJohan Hedberg if (IS_ERR(skb)) 2582177f8f2bSJohan Hedberg return skb; 2583177f8f2bSJohan Hedberg 2584177f8f2bSJohan Hedberg /* Create L2CAP header */ 2585177f8f2bSJohan Hedberg lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2586177f8f2bSJohan Hedberg lh->cid = cpu_to_le16(chan->dcid); 2587177f8f2bSJohan Hedberg lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 2588177f8f2bSJohan Hedberg 2589177f8f2bSJohan Hedberg if (sdulen) 2590177f8f2bSJohan Hedberg put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 2591177f8f2bSJohan Hedberg 2592177f8f2bSJohan Hedberg err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 2593177f8f2bSJohan Hedberg if (unlikely(err < 0)) { 2594177f8f2bSJohan Hedberg kfree_skb(skb); 2595177f8f2bSJohan Hedberg return ERR_PTR(err); 2596177f8f2bSJohan Hedberg } 2597177f8f2bSJohan Hedberg 2598177f8f2bSJohan Hedberg return skb; 2599177f8f2bSJohan Hedberg } 2600177f8f2bSJohan Hedberg 2601177f8f2bSJohan Hedberg static int l2cap_segment_le_sdu(struct l2cap_chan *chan, 2602177f8f2bSJohan Hedberg struct sk_buff_head *seg_queue, 2603177f8f2bSJohan Hedberg struct msghdr *msg, size_t len) 2604177f8f2bSJohan Hedberg { 2605177f8f2bSJohan Hedberg struct sk_buff *skb; 2606177f8f2bSJohan Hedberg size_t pdu_len; 2607177f8f2bSJohan Hedberg u16 sdu_len; 2608177f8f2bSJohan Hedberg 2609177f8f2bSJohan Hedberg BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); 2610177f8f2bSJohan Hedberg 2611177f8f2bSJohan Hedberg pdu_len = chan->conn->mtu - L2CAP_HDR_SIZE; 2612177f8f2bSJohan Hedberg 2613177f8f2bSJohan Hedberg pdu_len = min_t(size_t, pdu_len, chan->remote_mps); 2614177f8f2bSJohan Hedberg 2615177f8f2bSJohan Hedberg sdu_len = len; 2616177f8f2bSJohan Hedberg pdu_len -= L2CAP_SDULEN_SIZE; 2617177f8f2bSJohan Hedberg 2618177f8f2bSJohan Hedberg while (len > 0) { 2619177f8f2bSJohan Hedberg if (len <= pdu_len) 2620177f8f2bSJohan Hedberg pdu_len = len; 2621177f8f2bSJohan Hedberg 2622177f8f2bSJohan Hedberg skb = l2cap_create_le_flowctl_pdu(chan, msg, pdu_len, sdu_len); 2623177f8f2bSJohan Hedberg if (IS_ERR(skb)) { 2624177f8f2bSJohan Hedberg __skb_queue_purge(seg_queue); 2625177f8f2bSJohan Hedberg return PTR_ERR(skb); 2626177f8f2bSJohan Hedberg } 2627177f8f2bSJohan Hedberg 2628177f8f2bSJohan Hedberg __skb_queue_tail(seg_queue, skb); 2629177f8f2bSJohan Hedberg 2630177f8f2bSJohan Hedberg len -= pdu_len; 2631177f8f2bSJohan Hedberg 2632177f8f2bSJohan Hedberg if (sdu_len) { 2633177f8f2bSJohan Hedberg sdu_len = 0; 2634177f8f2bSJohan Hedberg pdu_len += L2CAP_SDULEN_SIZE; 2635177f8f2bSJohan Hedberg } 2636177f8f2bSJohan Hedberg } 2637177f8f2bSJohan Hedberg 2638177f8f2bSJohan Hedberg return 0; 2639177f8f2bSJohan Hedberg } 2640177f8f2bSJohan Hedberg 26415e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, 26425e59b791SLuiz Augusto von Dentz u32 priority) 26439a91a04aSGustavo F. Padovan { 26449a91a04aSGustavo F. Padovan struct sk_buff *skb; 26459a91a04aSGustavo F. Padovan int err; 264694122bbeSMat Martineau struct sk_buff_head seg_queue; 26479a91a04aSGustavo F. Padovan 264831e8ce80SSeung-Woo Kim if (!chan->conn) 264931e8ce80SSeung-Woo Kim return -ENOTCONN; 265031e8ce80SSeung-Woo Kim 26519a91a04aSGustavo F. Padovan /* Connectionless channel */ 2652715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { 26535e59b791SLuiz Augusto von Dentz skb = l2cap_create_connless_pdu(chan, msg, len, priority); 26549a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 26559a91a04aSGustavo F. Padovan return PTR_ERR(skb); 26569a91a04aSGustavo F. Padovan 26579a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 26589a91a04aSGustavo F. Padovan return len; 26599a91a04aSGustavo F. Padovan } 26609a91a04aSGustavo F. Padovan 26619a91a04aSGustavo F. Padovan switch (chan->mode) { 266238319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 2663177f8f2bSJohan Hedberg /* Check outgoing MTU */ 2664177f8f2bSJohan Hedberg if (len > chan->omtu) 2665177f8f2bSJohan Hedberg return -EMSGSIZE; 2666177f8f2bSJohan Hedberg 2667fad5fc89SJohan Hedberg if (!chan->tx_credits) 2668fad5fc89SJohan Hedberg return -EAGAIN; 2669fad5fc89SJohan Hedberg 2670177f8f2bSJohan Hedberg __skb_queue_head_init(&seg_queue); 2671177f8f2bSJohan Hedberg 2672177f8f2bSJohan Hedberg err = l2cap_segment_le_sdu(chan, &seg_queue, msg, len); 2673177f8f2bSJohan Hedberg 2674177f8f2bSJohan Hedberg if (chan->state != BT_CONNECTED) { 2675177f8f2bSJohan Hedberg __skb_queue_purge(&seg_queue); 2676177f8f2bSJohan Hedberg err = -ENOTCONN; 2677177f8f2bSJohan Hedberg } 2678177f8f2bSJohan Hedberg 2679177f8f2bSJohan Hedberg if (err) 2680177f8f2bSJohan Hedberg return err; 2681177f8f2bSJohan Hedberg 2682177f8f2bSJohan Hedberg skb_queue_splice_tail_init(&seg_queue, &chan->tx_q); 2683177f8f2bSJohan Hedberg 2684177f8f2bSJohan Hedberg while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) { 2685177f8f2bSJohan Hedberg l2cap_do_send(chan, skb_dequeue(&chan->tx_q)); 2686177f8f2bSJohan Hedberg chan->tx_credits--; 2687177f8f2bSJohan Hedberg } 2688177f8f2bSJohan Hedberg 2689177f8f2bSJohan Hedberg if (!chan->tx_credits) 2690177f8f2bSJohan Hedberg chan->ops->suspend(chan); 2691177f8f2bSJohan Hedberg 2692177f8f2bSJohan Hedberg err = len; 2693177f8f2bSJohan Hedberg 2694177f8f2bSJohan Hedberg break; 2695177f8f2bSJohan Hedberg 2696fad5fc89SJohan Hedberg case L2CAP_MODE_BASIC: 26979a91a04aSGustavo F. Padovan /* Check outgoing MTU */ 26989a91a04aSGustavo F. Padovan if (len > chan->omtu) 26999a91a04aSGustavo F. Padovan return -EMSGSIZE; 27009a91a04aSGustavo F. Padovan 27019a91a04aSGustavo F. Padovan /* Create a basic PDU */ 27025e59b791SLuiz Augusto von Dentz skb = l2cap_create_basic_pdu(chan, msg, len, priority); 27039a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 27049a91a04aSGustavo F. Padovan return PTR_ERR(skb); 27059a91a04aSGustavo F. Padovan 27069a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 27079a91a04aSGustavo F. Padovan err = len; 27089a91a04aSGustavo F. Padovan break; 27099a91a04aSGustavo F. Padovan 27109a91a04aSGustavo F. Padovan case L2CAP_MODE_ERTM: 27119a91a04aSGustavo F. Padovan case L2CAP_MODE_STREAMING: 271294122bbeSMat Martineau /* Check outgoing MTU */ 271394122bbeSMat Martineau if (len > chan->omtu) { 271494122bbeSMat Martineau err = -EMSGSIZE; 27159a91a04aSGustavo F. Padovan break; 27169a91a04aSGustavo F. Padovan } 27179a91a04aSGustavo F. Padovan 271894122bbeSMat Martineau __skb_queue_head_init(&seg_queue); 271994122bbeSMat Martineau 272094122bbeSMat Martineau /* Do segmentation before calling in to the state machine, 272194122bbeSMat Martineau * since it's possible to block while waiting for memory 272294122bbeSMat Martineau * allocation. 272394122bbeSMat Martineau */ 272494122bbeSMat Martineau err = l2cap_segment_sdu(chan, &seg_queue, msg, len); 272594122bbeSMat Martineau 272694122bbeSMat Martineau /* The channel could have been closed while segmenting, 272794122bbeSMat Martineau * check that it is still connected. 272894122bbeSMat Martineau */ 272994122bbeSMat Martineau if (chan->state != BT_CONNECTED) { 273094122bbeSMat Martineau __skb_queue_purge(&seg_queue); 273194122bbeSMat Martineau err = -ENOTCONN; 27329a91a04aSGustavo F. Padovan } 27339a91a04aSGustavo F. Padovan 273494122bbeSMat Martineau if (err) 273594122bbeSMat Martineau break; 273694122bbeSMat Martineau 27373733937dSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) 2738d660366dSGustavo Padovan l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST); 27393733937dSMat Martineau else 2740d660366dSGustavo Padovan l2cap_streaming_send(chan, &seg_queue); 274194122bbeSMat Martineau 27429a91a04aSGustavo F. Padovan err = len; 27439a91a04aSGustavo F. Padovan 274494122bbeSMat Martineau /* If the skbs were not queued for sending, they'll still be in 274594122bbeSMat Martineau * seg_queue and need to be purged. 274694122bbeSMat Martineau */ 274794122bbeSMat Martineau __skb_queue_purge(&seg_queue); 27489a91a04aSGustavo F. Padovan break; 27499a91a04aSGustavo F. Padovan 27509a91a04aSGustavo F. Padovan default: 27519a91a04aSGustavo F. Padovan BT_DBG("bad state %1.1x", chan->mode); 27529a91a04aSGustavo F. Padovan err = -EBADFD; 27539a91a04aSGustavo F. Padovan } 27549a91a04aSGustavo F. Padovan 27559a91a04aSGustavo F. Padovan return err; 27569a91a04aSGustavo F. Padovan } 27579a91a04aSGustavo F. Padovan 2758d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq) 2759d2a7ac5dSMat Martineau { 2760bed68bdeSMat Martineau struct l2cap_ctrl control; 2761bed68bdeSMat Martineau u16 seq; 2762bed68bdeSMat Martineau 2763b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2764bed68bdeSMat Martineau 2765bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2766bed68bdeSMat Martineau control.sframe = 1; 2767bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2768bed68bdeSMat Martineau 2769bed68bdeSMat Martineau for (seq = chan->expected_tx_seq; seq != txseq; 2770bed68bdeSMat Martineau seq = __next_seq(chan, seq)) { 2771bed68bdeSMat Martineau if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) { 2772bed68bdeSMat Martineau control.reqseq = seq; 2773bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2774bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2775bed68bdeSMat Martineau } 2776bed68bdeSMat Martineau } 2777bed68bdeSMat Martineau 2778bed68bdeSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 2779d2a7ac5dSMat Martineau } 2780d2a7ac5dSMat Martineau 2781d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan) 2782d2a7ac5dSMat Martineau { 2783bed68bdeSMat Martineau struct l2cap_ctrl control; 2784bed68bdeSMat Martineau 2785bed68bdeSMat Martineau BT_DBG("chan %p", chan); 2786bed68bdeSMat Martineau 2787bed68bdeSMat Martineau if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR) 2788bed68bdeSMat Martineau return; 2789bed68bdeSMat Martineau 2790bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2791bed68bdeSMat Martineau control.sframe = 1; 2792bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2793bed68bdeSMat Martineau control.reqseq = chan->srej_list.tail; 2794bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2795d2a7ac5dSMat Martineau } 2796d2a7ac5dSMat Martineau 2797d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq) 2798d2a7ac5dSMat Martineau { 2799bed68bdeSMat Martineau struct l2cap_ctrl control; 2800bed68bdeSMat Martineau u16 initial_head; 2801bed68bdeSMat Martineau u16 seq; 2802bed68bdeSMat Martineau 2803b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2804bed68bdeSMat Martineau 2805bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2806bed68bdeSMat Martineau control.sframe = 1; 2807bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2808bed68bdeSMat Martineau 2809bed68bdeSMat Martineau /* Capture initial list head to allow only one pass through the list. */ 2810bed68bdeSMat Martineau initial_head = chan->srej_list.head; 2811bed68bdeSMat Martineau 2812bed68bdeSMat Martineau do { 2813bed68bdeSMat Martineau seq = l2cap_seq_list_pop(&chan->srej_list); 2814bed68bdeSMat Martineau if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR) 2815bed68bdeSMat Martineau break; 2816bed68bdeSMat Martineau 2817bed68bdeSMat Martineau control.reqseq = seq; 2818bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2819bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2820bed68bdeSMat Martineau } while (chan->srej_list.head != initial_head); 2821d2a7ac5dSMat Martineau } 2822d2a7ac5dSMat Martineau 2823608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq) 2824608bcc6dSMat Martineau { 2825608bcc6dSMat Martineau struct sk_buff *acked_skb; 2826608bcc6dSMat Martineau u16 ackseq; 2827608bcc6dSMat Martineau 2828b4400672SAndrei Emeltchenko BT_DBG("chan %p, reqseq %u", chan, reqseq); 2829608bcc6dSMat Martineau 2830608bcc6dSMat Martineau if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq) 2831608bcc6dSMat Martineau return; 2832608bcc6dSMat Martineau 2833b4400672SAndrei Emeltchenko BT_DBG("expected_ack_seq %u, unacked_frames %u", 2834608bcc6dSMat Martineau chan->expected_ack_seq, chan->unacked_frames); 2835608bcc6dSMat Martineau 2836608bcc6dSMat Martineau for (ackseq = chan->expected_ack_seq; ackseq != reqseq; 2837608bcc6dSMat Martineau ackseq = __next_seq(chan, ackseq)) { 2838608bcc6dSMat Martineau 2839608bcc6dSMat Martineau acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq); 2840608bcc6dSMat Martineau if (acked_skb) { 2841608bcc6dSMat Martineau skb_unlink(acked_skb, &chan->tx_q); 2842608bcc6dSMat Martineau kfree_skb(acked_skb); 2843608bcc6dSMat Martineau chan->unacked_frames--; 2844608bcc6dSMat Martineau } 2845608bcc6dSMat Martineau } 2846608bcc6dSMat Martineau 2847608bcc6dSMat Martineau chan->expected_ack_seq = reqseq; 2848608bcc6dSMat Martineau 2849608bcc6dSMat Martineau if (chan->unacked_frames == 0) 2850608bcc6dSMat Martineau __clear_retrans_timer(chan); 2851608bcc6dSMat Martineau 2852b4400672SAndrei Emeltchenko BT_DBG("unacked_frames %u", chan->unacked_frames); 2853608bcc6dSMat Martineau } 2854608bcc6dSMat Martineau 2855608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan) 2856608bcc6dSMat Martineau { 2857608bcc6dSMat Martineau BT_DBG("chan %p", chan); 2858608bcc6dSMat Martineau 2859608bcc6dSMat Martineau chan->expected_tx_seq = chan->buffer_seq; 2860608bcc6dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 2861608bcc6dSMat Martineau skb_queue_purge(&chan->srej_q); 2862608bcc6dSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2863608bcc6dSMat Martineau } 2864608bcc6dSMat Martineau 2865d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan, 2866608bcc6dSMat Martineau struct l2cap_ctrl *control, 2867608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2868608bcc6dSMat Martineau { 2869608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2870608bcc6dSMat Martineau event); 2871608bcc6dSMat Martineau 2872608bcc6dSMat Martineau switch (event) { 2873608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2874608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2875608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2876608bcc6dSMat Martineau 2877608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2878608bcc6dSMat Martineau l2cap_ertm_send(chan); 2879608bcc6dSMat Martineau break; 2880608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2881608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2882608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2883608bcc6dSMat Martineau 2884608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2885608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2886608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2887608bcc6dSMat Martineau */ 2888608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2889608bcc6dSMat Martineau } 2890608bcc6dSMat Martineau 2891608bcc6dSMat Martineau l2cap_send_ack(chan); 2892608bcc6dSMat Martineau 2893608bcc6dSMat Martineau break; 2894608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2895608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2896608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2897608bcc6dSMat Martineau 2898608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2899608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2900608bcc6dSMat Martineau 2901608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2902608bcc6dSMat Martineau local_control.sframe = 1; 2903608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2904608bcc6dSMat Martineau local_control.poll = 1; 2905608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2906a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2907608bcc6dSMat Martineau 2908608bcc6dSMat Martineau chan->retry_count = 1; 2909608bcc6dSMat Martineau __set_monitor_timer(chan); 2910608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2911608bcc6dSMat Martineau } 2912608bcc6dSMat Martineau break; 2913608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2914608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2915608bcc6dSMat Martineau break; 2916608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2917608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2918608bcc6dSMat Martineau chan->retry_count = 1; 2919608bcc6dSMat Martineau __set_monitor_timer(chan); 2920608bcc6dSMat Martineau __clear_ack_timer(chan); 2921608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2922608bcc6dSMat Martineau break; 2923608bcc6dSMat Martineau case L2CAP_EV_RETRANS_TO: 2924608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2925608bcc6dSMat Martineau chan->retry_count = 1; 2926608bcc6dSMat Martineau __set_monitor_timer(chan); 2927608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2928608bcc6dSMat Martineau break; 2929608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2930608bcc6dSMat Martineau /* Nothing to process */ 2931608bcc6dSMat Martineau break; 2932608bcc6dSMat Martineau default: 2933608bcc6dSMat Martineau break; 2934608bcc6dSMat Martineau } 2935608bcc6dSMat Martineau } 2936608bcc6dSMat Martineau 2937d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan, 2938608bcc6dSMat Martineau struct l2cap_ctrl *control, 2939608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2940608bcc6dSMat Martineau { 2941608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2942608bcc6dSMat Martineau event); 2943608bcc6dSMat Martineau 2944608bcc6dSMat Martineau switch (event) { 2945608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2946608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2947608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2948608bcc6dSMat Martineau /* Queue data, but don't send. */ 2949608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2950608bcc6dSMat Martineau break; 2951608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2952608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2953608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2954608bcc6dSMat Martineau 2955608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2956608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2957608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2958608bcc6dSMat Martineau */ 2959608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2960608bcc6dSMat Martineau } 2961608bcc6dSMat Martineau 2962608bcc6dSMat Martineau l2cap_send_ack(chan); 2963608bcc6dSMat Martineau 2964608bcc6dSMat Martineau break; 2965608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2966608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2967608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2968608bcc6dSMat Martineau 2969608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2970608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2971608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2972608bcc6dSMat Martineau local_control.sframe = 1; 2973608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2974608bcc6dSMat Martineau local_control.poll = 1; 2975608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2976a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2977608bcc6dSMat Martineau 2978608bcc6dSMat Martineau chan->retry_count = 1; 2979608bcc6dSMat Martineau __set_monitor_timer(chan); 2980608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2981608bcc6dSMat Martineau } 2982608bcc6dSMat Martineau break; 2983608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2984608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2985608bcc6dSMat Martineau 2986608bcc6dSMat Martineau /* Fall through */ 2987608bcc6dSMat Martineau 2988608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2989608bcc6dSMat Martineau if (control && control->final) { 2990608bcc6dSMat Martineau __clear_monitor_timer(chan); 2991608bcc6dSMat Martineau if (chan->unacked_frames > 0) 2992608bcc6dSMat Martineau __set_retrans_timer(chan); 2993608bcc6dSMat Martineau chan->retry_count = 0; 2994608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 2995608bcc6dSMat Martineau BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state); 2996608bcc6dSMat Martineau } 2997608bcc6dSMat Martineau break; 2998608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2999608bcc6dSMat Martineau /* Ignore */ 3000608bcc6dSMat Martineau break; 3001608bcc6dSMat Martineau case L2CAP_EV_MONITOR_TO: 3002608bcc6dSMat Martineau if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) { 3003608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 3004608bcc6dSMat Martineau __set_monitor_timer(chan); 3005608bcc6dSMat Martineau chan->retry_count++; 3006608bcc6dSMat Martineau } else { 30075e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNABORTED); 3008608bcc6dSMat Martineau } 3009608bcc6dSMat Martineau break; 3010608bcc6dSMat Martineau default: 3011608bcc6dSMat Martineau break; 3012608bcc6dSMat Martineau } 3013608bcc6dSMat Martineau } 3014608bcc6dSMat Martineau 3015d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 3016608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 3017608bcc6dSMat Martineau { 3018608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d, state %d", 3019608bcc6dSMat Martineau chan, control, skbs, event, chan->tx_state); 3020608bcc6dSMat Martineau 3021608bcc6dSMat Martineau switch (chan->tx_state) { 3022608bcc6dSMat Martineau case L2CAP_TX_STATE_XMIT: 3023d660366dSGustavo Padovan l2cap_tx_state_xmit(chan, control, skbs, event); 3024608bcc6dSMat Martineau break; 3025608bcc6dSMat Martineau case L2CAP_TX_STATE_WAIT_F: 3026d660366dSGustavo Padovan l2cap_tx_state_wait_f(chan, control, skbs, event); 3027608bcc6dSMat Martineau break; 3028608bcc6dSMat Martineau default: 3029608bcc6dSMat Martineau /* Ignore event */ 3030608bcc6dSMat Martineau break; 3031608bcc6dSMat Martineau } 3032608bcc6dSMat Martineau } 3033608bcc6dSMat Martineau 30344b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan, 30354b51dae9SMat Martineau struct l2cap_ctrl *control) 30364b51dae9SMat Martineau { 30374b51dae9SMat Martineau BT_DBG("chan %p, control %p", chan, control); 3038401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT); 30394b51dae9SMat Martineau } 30404b51dae9SMat Martineau 3041f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan, 3042f80842a8SMat Martineau struct l2cap_ctrl *control) 3043f80842a8SMat Martineau { 3044f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 3045401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT); 3046f80842a8SMat Martineau } 3047f80842a8SMat Martineau 30480a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */ 30490a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 30500a708f8fSGustavo F. Padovan { 30510a708f8fSGustavo F. Padovan struct sk_buff *nskb; 305248454079SGustavo F. Padovan struct l2cap_chan *chan; 30530a708f8fSGustavo F. Padovan 30540a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 30550a708f8fSGustavo F. Padovan 30563df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 30573d57dc68SGustavo F. Padovan 30583df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 3059715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW) 30600a708f8fSGustavo F. Padovan continue; 30610a708f8fSGustavo F. Padovan 30627f5396a7SGustavo Padovan /* Don't send frame to the channel it came from */ 30637f5396a7SGustavo Padovan if (bt_cb(skb)->chan == chan) 30640a708f8fSGustavo F. Padovan continue; 30657f5396a7SGustavo Padovan 30668bcde1f2SGustavo Padovan nskb = skb_clone(skb, GFP_KERNEL); 30670a708f8fSGustavo F. Padovan if (!nskb) 30680a708f8fSGustavo F. Padovan continue; 306980b98027SGustavo Padovan if (chan->ops->recv(chan, nskb)) 30700a708f8fSGustavo F. Padovan kfree_skb(nskb); 30710a708f8fSGustavo F. Padovan } 30723d57dc68SGustavo F. Padovan 30733df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 30740a708f8fSGustavo F. Padovan } 30750a708f8fSGustavo F. Padovan 30760a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */ 3077b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, 3078b4400672SAndrei Emeltchenko u8 ident, u16 dlen, void *data) 30790a708f8fSGustavo F. Padovan { 30800a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag; 30810a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd; 30820a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 30830a708f8fSGustavo F. Padovan int len, count; 30840a708f8fSGustavo F. Padovan 3085b4400672SAndrei Emeltchenko BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u", 30860a708f8fSGustavo F. Padovan conn, code, ident, dlen); 30870a708f8fSGustavo F. Padovan 3088300b962eSAnderson Lizardo if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE) 3089300b962eSAnderson Lizardo return NULL; 3090300b962eSAnderson Lizardo 30910a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; 30920a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 30930a708f8fSGustavo F. Padovan 30948bcde1f2SGustavo Padovan skb = bt_skb_alloc(count, GFP_KERNEL); 30950a708f8fSGustavo F. Padovan if (!skb) 30960a708f8fSGustavo F. Padovan return NULL; 30970a708f8fSGustavo F. Padovan 30980a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 30990a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); 31003300d9a9SClaudio Takahasi 31013300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 3102ac73498cSAndrei Emeltchenko lh->cid = __constant_cpu_to_le16(L2CAP_CID_LE_SIGNALING); 31033300d9a9SClaudio Takahasi else 3104ac73498cSAndrei Emeltchenko lh->cid = __constant_cpu_to_le16(L2CAP_CID_SIGNALING); 31050a708f8fSGustavo F. Padovan 31060a708f8fSGustavo F. Padovan cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); 31070a708f8fSGustavo F. Padovan cmd->code = code; 31080a708f8fSGustavo F. Padovan cmd->ident = ident; 31090a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen); 31100a708f8fSGustavo F. Padovan 31110a708f8fSGustavo F. Padovan if (dlen) { 31120a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE; 31130a708f8fSGustavo F. Padovan memcpy(skb_put(skb, count), data, count); 31140a708f8fSGustavo F. Padovan data += count; 31150a708f8fSGustavo F. Padovan } 31160a708f8fSGustavo F. Padovan 31170a708f8fSGustavo F. Padovan len -= skb->len; 31180a708f8fSGustavo F. Padovan 31190a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 31200a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 31210a708f8fSGustavo F. Padovan while (len) { 31220a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 31230a708f8fSGustavo F. Padovan 31248bcde1f2SGustavo Padovan *frag = bt_skb_alloc(count, GFP_KERNEL); 31250a708f8fSGustavo F. Padovan if (!*frag) 31260a708f8fSGustavo F. Padovan goto fail; 31270a708f8fSGustavo F. Padovan 31280a708f8fSGustavo F. Padovan memcpy(skb_put(*frag, count), data, count); 31290a708f8fSGustavo F. Padovan 31300a708f8fSGustavo F. Padovan len -= count; 31310a708f8fSGustavo F. Padovan data += count; 31320a708f8fSGustavo F. Padovan 31330a708f8fSGustavo F. Padovan frag = &(*frag)->next; 31340a708f8fSGustavo F. Padovan } 31350a708f8fSGustavo F. Padovan 31360a708f8fSGustavo F. Padovan return skb; 31370a708f8fSGustavo F. Padovan 31380a708f8fSGustavo F. Padovan fail: 31390a708f8fSGustavo F. Padovan kfree_skb(skb); 31400a708f8fSGustavo F. Padovan return NULL; 31410a708f8fSGustavo F. Padovan } 31420a708f8fSGustavo F. Padovan 31432d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, 31442d792818SGustavo Padovan unsigned long *val) 31450a708f8fSGustavo F. Padovan { 31460a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 31470a708f8fSGustavo F. Padovan int len; 31480a708f8fSGustavo F. Padovan 31490a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len; 31500a708f8fSGustavo F. Padovan *ptr += len; 31510a708f8fSGustavo F. Padovan 31520a708f8fSGustavo F. Padovan *type = opt->type; 31530a708f8fSGustavo F. Padovan *olen = opt->len; 31540a708f8fSGustavo F. Padovan 31550a708f8fSGustavo F. Padovan switch (opt->len) { 31560a708f8fSGustavo F. Padovan case 1: 31570a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val); 31580a708f8fSGustavo F. Padovan break; 31590a708f8fSGustavo F. Padovan 31600a708f8fSGustavo F. Padovan case 2: 31610a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val); 31620a708f8fSGustavo F. Padovan break; 31630a708f8fSGustavo F. Padovan 31640a708f8fSGustavo F. Padovan case 4: 31650a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val); 31660a708f8fSGustavo F. Padovan break; 31670a708f8fSGustavo F. Padovan 31680a708f8fSGustavo F. Padovan default: 31690a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val; 31700a708f8fSGustavo F. Padovan break; 31710a708f8fSGustavo F. Padovan } 31720a708f8fSGustavo F. Padovan 3173b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val); 31740a708f8fSGustavo F. Padovan return len; 31750a708f8fSGustavo F. Padovan } 31760a708f8fSGustavo F. Padovan 31770a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) 31780a708f8fSGustavo F. Padovan { 31790a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 31800a708f8fSGustavo F. Padovan 3181b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val); 31820a708f8fSGustavo F. Padovan 31830a708f8fSGustavo F. Padovan opt->type = type; 31840a708f8fSGustavo F. Padovan opt->len = len; 31850a708f8fSGustavo F. Padovan 31860a708f8fSGustavo F. Padovan switch (len) { 31870a708f8fSGustavo F. Padovan case 1: 31880a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val; 31890a708f8fSGustavo F. Padovan break; 31900a708f8fSGustavo F. Padovan 31910a708f8fSGustavo F. Padovan case 2: 31920a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val); 31930a708f8fSGustavo F. Padovan break; 31940a708f8fSGustavo F. Padovan 31950a708f8fSGustavo F. Padovan case 4: 31960a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val); 31970a708f8fSGustavo F. Padovan break; 31980a708f8fSGustavo F. Padovan 31990a708f8fSGustavo F. Padovan default: 32000a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len); 32010a708f8fSGustavo F. Padovan break; 32020a708f8fSGustavo F. Padovan } 32030a708f8fSGustavo F. Padovan 32040a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len; 32050a708f8fSGustavo F. Padovan } 32060a708f8fSGustavo F. Padovan 3207f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) 3208f89cef09SAndrei Emeltchenko { 3209f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs; 3210f89cef09SAndrei Emeltchenko 3211f89cef09SAndrei Emeltchenko switch (chan->mode) { 3212f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM: 3213f89cef09SAndrei Emeltchenko efs.id = chan->local_id; 3214f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype; 3215f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 3216f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 3217ac73498cSAndrei Emeltchenko efs.acc_lat = __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); 32188936fa6dSAndrei Emeltchenko efs.flush_to = __constant_cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO); 3219f89cef09SAndrei Emeltchenko break; 3220f89cef09SAndrei Emeltchenko 3221f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING: 3222f89cef09SAndrei Emeltchenko efs.id = 1; 3223f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT; 3224f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 3225f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 3226f89cef09SAndrei Emeltchenko efs.acc_lat = 0; 3227f89cef09SAndrei Emeltchenko efs.flush_to = 0; 3228f89cef09SAndrei Emeltchenko break; 3229f89cef09SAndrei Emeltchenko 3230f89cef09SAndrei Emeltchenko default: 3231f89cef09SAndrei Emeltchenko return; 3232f89cef09SAndrei Emeltchenko } 3233f89cef09SAndrei Emeltchenko 3234f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), 3235f89cef09SAndrei Emeltchenko (unsigned long) &efs); 3236f89cef09SAndrei Emeltchenko } 3237f89cef09SAndrei Emeltchenko 3238721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work) 32390a708f8fSGustavo F. Padovan { 3240721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 3241721c4181SGustavo F. Padovan ack_timer.work); 32420362520bSMat Martineau u16 frames_to_ack; 32430a708f8fSGustavo F. Padovan 32442fb9b3d4SGustavo F. Padovan BT_DBG("chan %p", chan); 32452fb9b3d4SGustavo F. Padovan 32466be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 32476be36555SAndrei Emeltchenko 32480362520bSMat Martineau frames_to_ack = __seq_offset(chan, chan->buffer_seq, 32490362520bSMat Martineau chan->last_acked_seq); 32500362520bSMat Martineau 32510362520bSMat Martineau if (frames_to_ack) 32520362520bSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 32536be36555SAndrei Emeltchenko 32546be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 325509bfb2eeSSzymon Janc l2cap_chan_put(chan); 32560a708f8fSGustavo F. Padovan } 32570a708f8fSGustavo F. Padovan 3258466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan) 32590a708f8fSGustavo F. Padovan { 32603c588192SMat Martineau int err; 32613c588192SMat Martineau 3262105bdf9eSMat Martineau chan->next_tx_seq = 0; 3263105bdf9eSMat Martineau chan->expected_tx_seq = 0; 326442e5c802SGustavo F. Padovan chan->expected_ack_seq = 0; 32656a026610SGustavo F. Padovan chan->unacked_frames = 0; 326642e5c802SGustavo F. Padovan chan->buffer_seq = 0; 32676a026610SGustavo F. Padovan chan->frames_sent = 0; 3268105bdf9eSMat Martineau chan->last_acked_seq = 0; 3269105bdf9eSMat Martineau chan->sdu = NULL; 3270105bdf9eSMat Martineau chan->sdu_last_frag = NULL; 3271105bdf9eSMat Martineau chan->sdu_len = 0; 3272105bdf9eSMat Martineau 3273d34c34fbSMat Martineau skb_queue_head_init(&chan->tx_q); 3274d34c34fbSMat Martineau 32756ed971caSMarcel Holtmann chan->local_amp_id = AMP_ID_BREDR; 32766ed971caSMarcel Holtmann chan->move_id = AMP_ID_BREDR; 327708333283SMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 327808333283SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 327908333283SMat Martineau 3280105bdf9eSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 3281105bdf9eSMat Martineau return 0; 3282105bdf9eSMat Martineau 3283105bdf9eSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 3284105bdf9eSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 32850a708f8fSGustavo F. Padovan 3286721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout); 3287721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout); 3288721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout); 32890a708f8fSGustavo F. Padovan 3290f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q); 32910a708f8fSGustavo F. Padovan 32923c588192SMat Martineau err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win); 32933c588192SMat Martineau if (err < 0) 32943c588192SMat Martineau return err; 32953c588192SMat Martineau 32969dc9affcSMat Martineau err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win); 32979dc9affcSMat Martineau if (err < 0) 32989dc9affcSMat Martineau l2cap_seq_list_free(&chan->srej_list); 32999dc9affcSMat Martineau 33009dc9affcSMat Martineau return err; 33010a708f8fSGustavo F. Padovan } 33020a708f8fSGustavo F. Padovan 33030a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) 33040a708f8fSGustavo F. Padovan { 33050a708f8fSGustavo F. Padovan switch (mode) { 33060a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 33070a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 33080a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask)) 33090a708f8fSGustavo F. Padovan return mode; 33100a708f8fSGustavo F. Padovan /* fall through */ 33110a708f8fSGustavo F. Padovan default: 33120a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC; 33130a708f8fSGustavo F. Padovan } 33140a708f8fSGustavo F. Padovan } 33150a708f8fSGustavo F. Padovan 3316848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn) 33176327eb98SAndrei Emeltchenko { 3318848566b3SMarcel Holtmann return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_WINDOW; 33196327eb98SAndrei Emeltchenko } 33206327eb98SAndrei Emeltchenko 3321848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn) 3322f89cef09SAndrei Emeltchenko { 3323848566b3SMarcel Holtmann return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_FLOW; 3324f89cef09SAndrei Emeltchenko } 3325f89cef09SAndrei Emeltchenko 332636c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan, 332736c86c85SMat Martineau struct l2cap_conf_rfc *rfc) 332836c86c85SMat Martineau { 33296ed971caSMarcel Holtmann if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) { 333036c86c85SMat Martineau u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to; 333136c86c85SMat Martineau 333236c86c85SMat Martineau /* Class 1 devices have must have ERTM timeouts 333336c86c85SMat Martineau * exceeding the Link Supervision Timeout. The 333436c86c85SMat Martineau * default Link Supervision Timeout for AMP 333536c86c85SMat Martineau * controllers is 10 seconds. 333636c86c85SMat Martineau * 333736c86c85SMat Martineau * Class 1 devices use 0xffffffff for their 333836c86c85SMat Martineau * best-effort flush timeout, so the clamping logic 333936c86c85SMat Martineau * will result in a timeout that meets the above 334036c86c85SMat Martineau * requirement. ERTM timeouts are 16-bit values, so 334136c86c85SMat Martineau * the maximum timeout is 65.535 seconds. 334236c86c85SMat Martineau */ 334336c86c85SMat Martineau 334436c86c85SMat Martineau /* Convert timeout to milliseconds and round */ 334536c86c85SMat Martineau ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000); 334636c86c85SMat Martineau 334736c86c85SMat Martineau /* This is the recommended formula for class 2 devices 334836c86c85SMat Martineau * that start ERTM timers when packets are sent to the 334936c86c85SMat Martineau * controller. 335036c86c85SMat Martineau */ 335136c86c85SMat Martineau ertm_to = 3 * ertm_to + 500; 335236c86c85SMat Martineau 335336c86c85SMat Martineau if (ertm_to > 0xffff) 335436c86c85SMat Martineau ertm_to = 0xffff; 335536c86c85SMat Martineau 335636c86c85SMat Martineau rfc->retrans_timeout = cpu_to_le16((u16) ertm_to); 335736c86c85SMat Martineau rfc->monitor_timeout = rfc->retrans_timeout; 335836c86c85SMat Martineau } else { 335936c86c85SMat Martineau rfc->retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 336036c86c85SMat Martineau rfc->monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 336136c86c85SMat Martineau } 336236c86c85SMat Martineau } 336336c86c85SMat Martineau 33646327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan) 33656327eb98SAndrei Emeltchenko { 33666327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && 3367848566b3SMarcel Holtmann __l2cap_ews_supported(chan->conn)) { 33686327eb98SAndrei Emeltchenko /* use extended control field */ 33696327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 3370836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 3371836be934SAndrei Emeltchenko } else { 33726327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win, 33736327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 3374836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 3375836be934SAndrei Emeltchenko } 3376c20f8e35SMat Martineau chan->ack_win = chan->tx_win; 33776327eb98SAndrei Emeltchenko } 33786327eb98SAndrei Emeltchenko 3379710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) 33800a708f8fSGustavo F. Padovan { 33810a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 33820c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode }; 33830a708f8fSGustavo F. Padovan void *ptr = req->data; 3384c8f79162SAndrei Emeltchenko u16 size; 33850a708f8fSGustavo F. Padovan 338649208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 33870a708f8fSGustavo F. Padovan 338873ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp) 33890a708f8fSGustavo F. Padovan goto done; 33900a708f8fSGustavo F. Padovan 33910c1bc5c6SGustavo F. Padovan switch (chan->mode) { 33920a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 33930a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3394c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) 33950a708f8fSGustavo F. Padovan break; 33960a708f8fSGustavo F. Padovan 3397848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn)) 3398f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 3399f89cef09SAndrei Emeltchenko 34000a708f8fSGustavo F. Padovan /* fall through */ 34010a708f8fSGustavo F. Padovan default: 34028c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); 34030a708f8fSGustavo F. Padovan break; 34040a708f8fSGustavo F. Padovan } 34050a708f8fSGustavo F. Padovan 34060a708f8fSGustavo F. Padovan done: 34070c1bc5c6SGustavo F. Padovan if (chan->imtu != L2CAP_DEFAULT_MTU) 34080c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 34090a708f8fSGustavo F. Padovan 34100c1bc5c6SGustavo F. Padovan switch (chan->mode) { 34110a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 34128c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && 34138c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) 34140a708f8fSGustavo F. Padovan break; 34150a708f8fSGustavo F. Padovan 34160a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC; 34170a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 34180a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 34190a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 34200a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 34210a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0; 34220a708f8fSGustavo F. Padovan 34230a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 34240a708f8fSGustavo F. Padovan (unsigned long) &rfc); 34250a708f8fSGustavo F. Padovan break; 34260a708f8fSGustavo F. Padovan 34270a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 34280a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM; 342947d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx; 343036c86c85SMat Martineau 343136c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc); 3432c8f79162SAndrei Emeltchenko 3433c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 34342d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - 3435c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3436c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 34370a708f8fSGustavo F. Padovan 34386327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan); 34396327eb98SAndrei Emeltchenko 34406327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win, 34416327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 34420a708f8fSGustavo F. Padovan 34430a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 34440a708f8fSGustavo F. Padovan (unsigned long) &rfc); 34450a708f8fSGustavo F. Padovan 3446f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 3447f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 3448f89cef09SAndrei Emeltchenko 34496327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 34506327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 34516327eb98SAndrei Emeltchenko chan->tx_win); 345260918918SAndrei Emeltchenko 345360918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS) 345460918918SAndrei Emeltchenko if (chan->fcs == L2CAP_FCS_NONE || 3455f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { 345660918918SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 345760918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, 345860918918SAndrei Emeltchenko chan->fcs); 345960918918SAndrei Emeltchenko } 34600a708f8fSGustavo F. Padovan break; 34610a708f8fSGustavo F. Padovan 34620a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3463273759e2SMat Martineau l2cap_txwin_setup(chan); 34640a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING; 34650a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 34660a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 34670a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 34680a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 3469c8f79162SAndrei Emeltchenko 3470c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 34712d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - 3472c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3473c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 34740a708f8fSGustavo F. Padovan 34750a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 34760a708f8fSGustavo F. Padovan (unsigned long) &rfc); 34770a708f8fSGustavo F. Padovan 3478f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 3479f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 3480f89cef09SAndrei Emeltchenko 348160918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS) 348247d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 3483f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { 348447d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 348560918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, 348660918918SAndrei Emeltchenko chan->fcs); 34870a708f8fSGustavo F. Padovan } 34880a708f8fSGustavo F. Padovan break; 34890a708f8fSGustavo F. Padovan } 34900a708f8fSGustavo F. Padovan 3491fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 349259e54bd1SAndrei Emeltchenko req->flags = __constant_cpu_to_le16(0); 34930a708f8fSGustavo F. Padovan 34940a708f8fSGustavo F. Padovan return ptr - data; 34950a708f8fSGustavo F. Padovan } 34960a708f8fSGustavo F. Padovan 349773ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) 34980a708f8fSGustavo F. Padovan { 34990a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 35000a708f8fSGustavo F. Padovan void *ptr = rsp->data; 350173ffa904SGustavo F. Padovan void *req = chan->conf_req; 350273ffa904SGustavo F. Padovan int len = chan->conf_len; 35030a708f8fSGustavo F. Padovan int type, hint, olen; 35040a708f8fSGustavo F. Padovan unsigned long val; 35050a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 350642dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs; 350742dceae2SAndrei Emeltchenko u8 remote_efs = 0; 35080a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU; 35090a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS; 3510c8f79162SAndrei Emeltchenko u16 size; 35110a708f8fSGustavo F. Padovan 351273ffa904SGustavo F. Padovan BT_DBG("chan %p", chan); 35130a708f8fSGustavo F. Padovan 35140a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 35150a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val); 35160a708f8fSGustavo F. Padovan 35170a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT; 35180a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK; 35190a708f8fSGustavo F. Padovan 35200a708f8fSGustavo F. Padovan switch (type) { 35210a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 35220a708f8fSGustavo F. Padovan mtu = val; 35230a708f8fSGustavo F. Padovan break; 35240a708f8fSGustavo F. Padovan 35250a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 35260c1bc5c6SGustavo F. Padovan chan->flush_to = val; 35270a708f8fSGustavo F. Padovan break; 35280a708f8fSGustavo F. Padovan 35290a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS: 35300a708f8fSGustavo F. Padovan break; 35310a708f8fSGustavo F. Padovan 35320a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 35330a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 35340a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen); 35350a708f8fSGustavo F. Padovan break; 35360a708f8fSGustavo F. Padovan 35370a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS: 35380a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE) 3539f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, &chan->conf_state); 354042dceae2SAndrei Emeltchenko break; 35410a708f8fSGustavo F. Padovan 354242dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS: 354342dceae2SAndrei Emeltchenko remote_efs = 1; 354442dceae2SAndrei Emeltchenko if (olen == sizeof(efs)) 354542dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen); 35460a708f8fSGustavo F. Padovan break; 35470a708f8fSGustavo F. Padovan 35486327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 3549848566b3SMarcel Holtmann if (!chan->conn->hs_enabled) 35506327eb98SAndrei Emeltchenko return -ECONNREFUSED; 35516327eb98SAndrei Emeltchenko 35526327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 35536327eb98SAndrei Emeltchenko set_bit(CONF_EWS_RECV, &chan->conf_state); 3554836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 35556327eb98SAndrei Emeltchenko chan->remote_tx_win = val; 35560a708f8fSGustavo F. Padovan break; 35570a708f8fSGustavo F. Padovan 35580a708f8fSGustavo F. Padovan default: 35590a708f8fSGustavo F. Padovan if (hint) 35600a708f8fSGustavo F. Padovan break; 35610a708f8fSGustavo F. Padovan 35620a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN; 35630a708f8fSGustavo F. Padovan *((u8 *) ptr++) = type; 35640a708f8fSGustavo F. Padovan break; 35650a708f8fSGustavo F. Padovan } 35660a708f8fSGustavo F. Padovan } 35670a708f8fSGustavo F. Padovan 356873ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1) 35690a708f8fSGustavo F. Padovan goto done; 35700a708f8fSGustavo F. Padovan 35710c1bc5c6SGustavo F. Padovan switch (chan->mode) { 35720a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 35730a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3574c1360a1cSGustavo F. Padovan if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { 35750c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, 35768c1d787bSGustavo F. Padovan chan->conn->feat_mask); 35770a708f8fSGustavo F. Padovan break; 35780a708f8fSGustavo F. Padovan } 35790a708f8fSGustavo F. Padovan 358042dceae2SAndrei Emeltchenko if (remote_efs) { 3581848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn)) 358242dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 358342dceae2SAndrei Emeltchenko else 358442dceae2SAndrei Emeltchenko return -ECONNREFUSED; 358542dceae2SAndrei Emeltchenko } 358642dceae2SAndrei Emeltchenko 35870c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) 35880a708f8fSGustavo F. Padovan return -ECONNREFUSED; 35890a708f8fSGustavo F. Padovan 35900a708f8fSGustavo F. Padovan break; 35910a708f8fSGustavo F. Padovan } 35920a708f8fSGustavo F. Padovan 35930a708f8fSGustavo F. Padovan done: 35940c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) { 35950a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 35960c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 35970a708f8fSGustavo F. Padovan 359873ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1) 35990a708f8fSGustavo F. Padovan return -ECONNREFUSED; 36000a708f8fSGustavo F. Padovan 36012d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 36022d792818SGustavo Padovan (unsigned long) &rfc); 36030a708f8fSGustavo F. Padovan } 36040a708f8fSGustavo F. Padovan 36050a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) { 36060a708f8fSGustavo F. Padovan /* Configure output options and let the other side know 36070a708f8fSGustavo F. Padovan * which ones we don't like. */ 36080a708f8fSGustavo F. Padovan 36090a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU) 36100a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 36110a708f8fSGustavo F. Padovan else { 36120c1bc5c6SGustavo F. Padovan chan->omtu = mtu; 3613c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state); 36140a708f8fSGustavo F. Padovan } 36150c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); 36160a708f8fSGustavo F. Padovan 361742dceae2SAndrei Emeltchenko if (remote_efs) { 361842dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 361942dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 362042dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) { 362142dceae2SAndrei Emeltchenko 362242dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT; 362342dceae2SAndrei Emeltchenko 362442dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1) 362542dceae2SAndrei Emeltchenko return -ECONNREFUSED; 362642dceae2SAndrei Emeltchenko 362742dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 362842dceae2SAndrei Emeltchenko sizeof(efs), 362942dceae2SAndrei Emeltchenko (unsigned long) &efs); 36300e8b207eSAndrei Emeltchenko } else { 36313e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */ 36320e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING; 36330e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 363442dceae2SAndrei Emeltchenko } 363542dceae2SAndrei Emeltchenko } 363642dceae2SAndrei Emeltchenko 36370a708f8fSGustavo F. Padovan switch (rfc.mode) { 36380a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 363947d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3640c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 36410a708f8fSGustavo F. Padovan break; 36420a708f8fSGustavo F. Padovan 36430a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 36446327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state)) 36452c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size; 36466327eb98SAndrei Emeltchenko else 36476327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; 36486327eb98SAndrei Emeltchenko 36492c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit; 36500a708f8fSGustavo F. Padovan 3651c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 36522d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE - 36532d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); 3654c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3655c8f79162SAndrei Emeltchenko chan->remote_mps = size; 36560a708f8fSGustavo F. Padovan 365736c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc); 36580a708f8fSGustavo F. Padovan 3659c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 36600a708f8fSGustavo F. Padovan 36610a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 36620a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 36630a708f8fSGustavo F. Padovan 366442dceae2SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 366542dceae2SAndrei Emeltchenko chan->remote_id = efs.id; 366642dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype; 366742dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu); 366842dceae2SAndrei Emeltchenko chan->remote_flush_to = 366942dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to); 367042dceae2SAndrei Emeltchenko chan->remote_acc_lat = 367142dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat); 367242dceae2SAndrei Emeltchenko chan->remote_sdu_itime = 367342dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 367442dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 36752d792818SGustavo Padovan sizeof(efs), 36762d792818SGustavo Padovan (unsigned long) &efs); 367742dceae2SAndrei Emeltchenko } 36780a708f8fSGustavo F. Padovan break; 36790a708f8fSGustavo F. Padovan 36800a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3681c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 36822d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE - 36832d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); 3684c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3685c8f79162SAndrei Emeltchenko chan->remote_mps = size; 36860a708f8fSGustavo F. Padovan 3687c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 36880a708f8fSGustavo F. Padovan 36892d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 36902d792818SGustavo Padovan (unsigned long) &rfc); 36910a708f8fSGustavo F. Padovan 36920a708f8fSGustavo F. Padovan break; 36930a708f8fSGustavo F. Padovan 36940a708f8fSGustavo F. Padovan default: 36950a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 36960a708f8fSGustavo F. Padovan 36970a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc)); 36980c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 36990a708f8fSGustavo F. Padovan } 37000a708f8fSGustavo F. Padovan 37010a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) 3702c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 37030a708f8fSGustavo F. Padovan } 3704fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 37050a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 370659e54bd1SAndrei Emeltchenko rsp->flags = __constant_cpu_to_le16(0); 37070a708f8fSGustavo F. Padovan 37080a708f8fSGustavo F. Padovan return ptr - data; 37090a708f8fSGustavo F. Padovan } 37100a708f8fSGustavo F. Padovan 37112d792818SGustavo Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, 37122d792818SGustavo Padovan void *data, u16 *result) 37130a708f8fSGustavo F. Padovan { 37140a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 37150a708f8fSGustavo F. Padovan void *ptr = req->data; 37160a708f8fSGustavo F. Padovan int type, olen; 37170a708f8fSGustavo F. Padovan unsigned long val; 371836e999a8SMat Martineau struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 371966af7aafSAndrei Emeltchenko struct l2cap_conf_efs efs; 37200a708f8fSGustavo F. Padovan 3721fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); 37220a708f8fSGustavo F. Padovan 37230a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 37240a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 37250a708f8fSGustavo F. Padovan 37260a708f8fSGustavo F. Padovan switch (type) { 37270a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 37280a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) { 37290a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT; 37300c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU; 37310a708f8fSGustavo F. Padovan } else 37320c1bc5c6SGustavo F. Padovan chan->imtu = val; 37330c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 37340a708f8fSGustavo F. Padovan break; 37350a708f8fSGustavo F. Padovan 37360a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 37370c1bc5c6SGustavo F. Padovan chan->flush_to = val; 37380a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 37390c1bc5c6SGustavo F. Padovan 2, chan->flush_to); 37400a708f8fSGustavo F. Padovan break; 37410a708f8fSGustavo F. Padovan 37420a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 37430a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 37440a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 37450a708f8fSGustavo F. Padovan 3746c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && 37470c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode) 37480a708f8fSGustavo F. Padovan return -ECONNREFUSED; 37490a708f8fSGustavo F. Padovan 375047d1ec61SGustavo F. Padovan chan->fcs = 0; 37510a708f8fSGustavo F. Padovan 37520a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 37530a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 37540a708f8fSGustavo F. Padovan break; 37556327eb98SAndrei Emeltchenko 37566327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 3757c20f8e35SMat Martineau chan->ack_win = min_t(u16, val, chan->ack_win); 37583e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 37593e6b3b95SGustavo F. Padovan chan->tx_win); 37606327eb98SAndrei Emeltchenko break; 376166af7aafSAndrei Emeltchenko 376266af7aafSAndrei Emeltchenko case L2CAP_CONF_EFS: 376366af7aafSAndrei Emeltchenko if (olen == sizeof(efs)) 376466af7aafSAndrei Emeltchenko memcpy(&efs, (void *)val, olen); 376566af7aafSAndrei Emeltchenko 376666af7aafSAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 376766af7aafSAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 376866af7aafSAndrei Emeltchenko efs.stype != chan->local_stype) 376966af7aafSAndrei Emeltchenko return -ECONNREFUSED; 377066af7aafSAndrei Emeltchenko 37712d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), 37722d792818SGustavo Padovan (unsigned long) &efs); 377366af7aafSAndrei Emeltchenko break; 3774cbabee78SAndrei Emeltchenko 3775cbabee78SAndrei Emeltchenko case L2CAP_CONF_FCS: 3776cbabee78SAndrei Emeltchenko if (*result == L2CAP_CONF_PENDING) 3777cbabee78SAndrei Emeltchenko if (val == L2CAP_FCS_NONE) 3778f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, 3779cbabee78SAndrei Emeltchenko &chan->conf_state); 3780cbabee78SAndrei Emeltchenko break; 37810a708f8fSGustavo F. Padovan } 37820a708f8fSGustavo F. Padovan } 37830a708f8fSGustavo F. Padovan 37840c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) 37850a708f8fSGustavo F. Padovan return -ECONNREFUSED; 37860a708f8fSGustavo F. Padovan 37870c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode; 37880a708f8fSGustavo F. Padovan 37890e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) { 37900a708f8fSGustavo F. Padovan switch (rfc.mode) { 37910a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 379247d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 379347d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 379447d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 3795c20f8e35SMat Martineau if (!test_bit(FLAG_EXT_CTRL, &chan->flags)) 3796c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 3797c20f8e35SMat Martineau rfc.txwin_size); 379866af7aafSAndrei Emeltchenko 379966af7aafSAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 380066af7aafSAndrei Emeltchenko chan->local_msdu = le16_to_cpu(efs.msdu); 380166af7aafSAndrei Emeltchenko chan->local_sdu_itime = 380266af7aafSAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 380366af7aafSAndrei Emeltchenko chan->local_acc_lat = le32_to_cpu(efs.acc_lat); 380466af7aafSAndrei Emeltchenko chan->local_flush_to = 380566af7aafSAndrei Emeltchenko le32_to_cpu(efs.flush_to); 380666af7aafSAndrei Emeltchenko } 38070a708f8fSGustavo F. Padovan break; 380866af7aafSAndrei Emeltchenko 38090a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 381047d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 38110a708f8fSGustavo F. Padovan } 38120a708f8fSGustavo F. Padovan } 38130a708f8fSGustavo F. Padovan 3814fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 381559e54bd1SAndrei Emeltchenko req->flags = __constant_cpu_to_le16(0); 38160a708f8fSGustavo F. Padovan 38170a708f8fSGustavo F. Padovan return ptr - data; 38180a708f8fSGustavo F. Padovan } 38190a708f8fSGustavo F. Padovan 38202d792818SGustavo Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, 38212d792818SGustavo Padovan u16 result, u16 flags) 38220a708f8fSGustavo F. Padovan { 38230a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 38240a708f8fSGustavo F. Padovan void *ptr = rsp->data; 38250a708f8fSGustavo F. Padovan 3826fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan); 38270a708f8fSGustavo F. Padovan 3828fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 38290a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 38300a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags); 38310a708f8fSGustavo F. Padovan 38320a708f8fSGustavo F. Padovan return ptr - data; 38330a708f8fSGustavo F. Padovan } 38340a708f8fSGustavo F. Padovan 383527e2d4c8SJohan Hedberg void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan) 383627e2d4c8SJohan Hedberg { 383727e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 383827e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn; 383927e2d4c8SJohan Hedberg 384027e2d4c8SJohan Hedberg BT_DBG("chan %p", chan); 384127e2d4c8SJohan Hedberg 384227e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 384327e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 38443916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps); 38450cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits); 384627e2d4c8SJohan Hedberg rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 384727e2d4c8SJohan Hedberg 384827e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), 384927e2d4c8SJohan Hedberg &rsp); 385027e2d4c8SJohan Hedberg } 385127e2d4c8SJohan Hedberg 38528c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) 3853710f9b0aSGustavo F. Padovan { 3854710f9b0aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 38558c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 3856710f9b0aSGustavo F. Padovan u8 buf[128]; 3857439f34acSAndrei Emeltchenko u8 rsp_code; 3858710f9b0aSGustavo F. Padovan 3859fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 3860fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3861ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 3862ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 3863439f34acSAndrei Emeltchenko 3864439f34acSAndrei Emeltchenko if (chan->hs_hcon) 3865439f34acSAndrei Emeltchenko rsp_code = L2CAP_CREATE_CHAN_RSP; 3866439f34acSAndrei Emeltchenko else 3867439f34acSAndrei Emeltchenko rsp_code = L2CAP_CONN_RSP; 3868439f34acSAndrei Emeltchenko 3869439f34acSAndrei Emeltchenko BT_DBG("chan %p rsp_code %u", chan, rsp_code); 3870439f34acSAndrei Emeltchenko 3871439f34acSAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp); 3872710f9b0aSGustavo F. Padovan 3873c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 3874710f9b0aSGustavo F. Padovan return; 3875710f9b0aSGustavo F. Padovan 3876710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 3877710f9b0aSGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 3878710f9b0aSGustavo F. Padovan chan->num_conf_req++; 3879710f9b0aSGustavo F. Padovan } 3880710f9b0aSGustavo F. Padovan 388147d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) 38820a708f8fSGustavo F. Padovan { 38830a708f8fSGustavo F. Padovan int type, olen; 38840a708f8fSGustavo F. Padovan unsigned long val; 3885c20f8e35SMat Martineau /* Use sane default values in case a misbehaving remote device 3886c20f8e35SMat Martineau * did not send an RFC or extended window size option. 3887c20f8e35SMat Martineau */ 3888c20f8e35SMat Martineau u16 txwin_ext = chan->ack_win; 3889c20f8e35SMat Martineau struct l2cap_conf_rfc rfc = { 3890c20f8e35SMat Martineau .mode = chan->mode, 3891c20f8e35SMat Martineau .retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO), 3892c20f8e35SMat Martineau .monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO), 3893c20f8e35SMat Martineau .max_pdu_size = cpu_to_le16(chan->imtu), 3894c20f8e35SMat Martineau .txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW), 3895c20f8e35SMat Martineau }; 38960a708f8fSGustavo F. Padovan 389747d1ec61SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); 38980a708f8fSGustavo F. Padovan 38990c1bc5c6SGustavo F. Padovan if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) 39000a708f8fSGustavo F. Padovan return; 39010a708f8fSGustavo F. Padovan 39020a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 39030a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 39040a708f8fSGustavo F. Padovan 3905c20f8e35SMat Martineau switch (type) { 3906c20f8e35SMat Martineau case L2CAP_CONF_RFC: 3907c20f8e35SMat Martineau if (olen == sizeof(rfc)) 39080a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 3909c20f8e35SMat Martineau break; 3910c20f8e35SMat Martineau case L2CAP_CONF_EWS: 3911c20f8e35SMat Martineau txwin_ext = val; 3912c20f8e35SMat Martineau break; 3913c20f8e35SMat Martineau } 39140a708f8fSGustavo F. Padovan } 39150a708f8fSGustavo F. Padovan 39160a708f8fSGustavo F. Padovan switch (rfc.mode) { 39170a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 391847d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 391947d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 392047d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 3921c20f8e35SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 3922c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, txwin_ext); 3923c20f8e35SMat Martineau else 3924c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 3925c20f8e35SMat Martineau rfc.txwin_size); 39260a708f8fSGustavo F. Padovan break; 39270a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 392847d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 39290a708f8fSGustavo F. Padovan } 39300a708f8fSGustavo F. Padovan } 39310a708f8fSGustavo F. Padovan 39322d792818SGustavo Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, 3933cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 3934cb3b3152SJohan Hedberg u8 *data) 39350a708f8fSGustavo F. Padovan { 3936e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 39370a708f8fSGustavo F. Padovan 3938cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rej)) 3939cb3b3152SJohan Hedberg return -EPROTO; 3940cb3b3152SJohan Hedberg 3941e2fd318eSIlia Kolomisnky if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) 39420a708f8fSGustavo F. Padovan return 0; 39430a708f8fSGustavo F. Padovan 39440a708f8fSGustavo F. Padovan if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && 39450a708f8fSGustavo F. Padovan cmd->ident == conn->info_ident) { 394617cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 39470a708f8fSGustavo F. Padovan 39480a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 39490a708f8fSGustavo F. Padovan conn->info_ident = 0; 39500a708f8fSGustavo F. Padovan 39510a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 39520a708f8fSGustavo F. Padovan } 39530a708f8fSGustavo F. Padovan 39540a708f8fSGustavo F. Padovan return 0; 39550a708f8fSGustavo F. Padovan } 39560a708f8fSGustavo F. Padovan 39571700915fSMat Martineau static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, 39581700915fSMat Martineau struct l2cap_cmd_hdr *cmd, 39594c89b6aaSMat Martineau u8 *data, u8 rsp_code, u8 amp_id) 39600a708f8fSGustavo F. Padovan { 39610a708f8fSGustavo F. Padovan struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 39620a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 396323691d75SGustavo F. Padovan struct l2cap_chan *chan = NULL, *pchan; 39640a708f8fSGustavo F. Padovan int result, status = L2CAP_CS_NO_INFO; 39650a708f8fSGustavo F. Padovan 39660a708f8fSGustavo F. Padovan u16 dcid = 0, scid = __le16_to_cpu(req->scid); 39670a708f8fSGustavo F. Padovan __le16 psm = req->psm; 39680a708f8fSGustavo F. Padovan 3969097db76cSAndrei Emeltchenko BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); 39700a708f8fSGustavo F. Padovan 39710a708f8fSGustavo F. Padovan /* Check if we have socket listening on psm */ 39726f59b904SMarcel Holtmann pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 3973bf20fd4eSJohan Hedberg &conn->hcon->dst, ACL_LINK); 397423691d75SGustavo F. Padovan if (!pchan) { 39750a708f8fSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 39760a708f8fSGustavo F. Padovan goto sendresp; 39770a708f8fSGustavo F. Padovan } 39780a708f8fSGustavo F. Padovan 39793df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 39808ffb9290SGustavo Padovan l2cap_chan_lock(pchan); 39810a708f8fSGustavo F. Padovan 39820a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */ 39832983fd68SAndrei Emeltchenko if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) && 39840a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) { 39859f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_AUTH_FAILURE; 39860a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 39870a708f8fSGustavo F. Padovan goto response; 39880a708f8fSGustavo F. Padovan } 39890a708f8fSGustavo F. Padovan 39900a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM; 39910a708f8fSGustavo F. Padovan 39922dfa1003SGustavo Padovan /* Check if we already have channel with that dcid */ 39932dfa1003SGustavo Padovan if (__l2cap_get_chan_by_dcid(conn, scid)) 39942dfa1003SGustavo Padovan goto response; 39952dfa1003SGustavo Padovan 399680b98027SGustavo Padovan chan = pchan->ops->new_connection(pchan); 399780808e43SGustavo F. Padovan if (!chan) 39980a708f8fSGustavo F. Padovan goto response; 39990a708f8fSGustavo F. Padovan 4000330b6c15SSyam Sidhardhan /* For certain devices (ex: HID mouse), support for authentication, 4001330b6c15SSyam Sidhardhan * pairing and bonding is optional. For such devices, inorder to avoid 4002330b6c15SSyam Sidhardhan * the ACL alive for too long after L2CAP disconnection, reset the ACL 4003330b6c15SSyam Sidhardhan * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect. 4004330b6c15SSyam Sidhardhan */ 4005330b6c15SSyam Sidhardhan conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 4006330b6c15SSyam Sidhardhan 40077eafc59eSMarcel Holtmann bacpy(&chan->src, &conn->hcon->src); 40087eafc59eSMarcel Holtmann bacpy(&chan->dst, &conn->hcon->dst); 40094f1654e0SMarcel Holtmann chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type); 40104f1654e0SMarcel Holtmann chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type); 4011fe4128e0SGustavo F. Padovan chan->psm = psm; 4012fe4128e0SGustavo F. Padovan chan->dcid = scid; 40131700915fSMat Martineau chan->local_amp_id = amp_id; 40140a708f8fSGustavo F. Padovan 40156be36555SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 401648454079SGustavo F. Padovan 4017fe4128e0SGustavo F. Padovan dcid = chan->scid; 40180a708f8fSGustavo F. Padovan 40198d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 40200a708f8fSGustavo F. Padovan 4021fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident; 40220a708f8fSGustavo F. Padovan 40230a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { 4024d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 4025bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 4026f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 40270a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 40280a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND; 40292dc4e510SGustavo Padovan chan->ops->defer(chan); 40300a708f8fSGustavo F. Padovan } else { 40311700915fSMat Martineau /* Force pending result for AMP controllers. 40321700915fSMat Martineau * The connection will succeed after the 40331700915fSMat Martineau * physical link is up. 40341700915fSMat Martineau */ 40356ed971caSMarcel Holtmann if (amp_id == AMP_ID_BREDR) { 4036f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 40370a708f8fSGustavo F. Padovan result = L2CAP_CR_SUCCESS; 40386ed971caSMarcel Holtmann } else { 4039f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 40406ed971caSMarcel Holtmann result = L2CAP_CR_PEND; 40411700915fSMat Martineau } 40420a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 40430a708f8fSGustavo F. Padovan } 40440a708f8fSGustavo F. Padovan } else { 4045f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 40460a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 40470a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND; 40480a708f8fSGustavo F. Padovan } 40490a708f8fSGustavo F. Padovan } else { 4050f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 40510a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 40520a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 40530a708f8fSGustavo F. Padovan } 40540a708f8fSGustavo F. Padovan 40550a708f8fSGustavo F. Padovan response: 40568ffb9290SGustavo Padovan l2cap_chan_unlock(pchan); 40573df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 40580a708f8fSGustavo F. Padovan 40590a708f8fSGustavo F. Padovan sendresp: 40600a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid); 40610a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid); 40620a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result); 40630a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status); 40644c89b6aaSMat Martineau l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp); 40650a708f8fSGustavo F. Padovan 40660a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { 40670a708f8fSGustavo F. Padovan struct l2cap_info_req info; 4068ac73498cSAndrei Emeltchenko info.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); 40690a708f8fSGustavo F. Padovan 40700a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 40710a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 40720a708f8fSGustavo F. Padovan 4073ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 40740a708f8fSGustavo F. Padovan 40752d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, 40762d792818SGustavo Padovan sizeof(info), &info); 40770a708f8fSGustavo F. Padovan } 40780a708f8fSGustavo F. Padovan 4079c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && 40800a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) { 40810a708f8fSGustavo F. Padovan u8 buf[128]; 4082c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 40830a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 408473ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 408573ffa904SGustavo F. Padovan chan->num_conf_req++; 40860a708f8fSGustavo F. Padovan } 40871700915fSMat Martineau 40881700915fSMat Martineau return chan; 40894c89b6aaSMat Martineau } 40900a708f8fSGustavo F. Padovan 40914c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn, 4092cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 40934c89b6aaSMat Martineau { 40947b064edaSJaganath Kanakkassery struct hci_dev *hdev = conn->hcon->hdev; 40957b064edaSJaganath Kanakkassery struct hci_conn *hcon = conn->hcon; 40967b064edaSJaganath Kanakkassery 4097cb3b3152SJohan Hedberg if (cmd_len < sizeof(struct l2cap_conn_req)) 4098cb3b3152SJohan Hedberg return -EPROTO; 4099cb3b3152SJohan Hedberg 41007b064edaSJaganath Kanakkassery hci_dev_lock(hdev); 41017b064edaSJaganath Kanakkassery if (test_bit(HCI_MGMT, &hdev->dev_flags) && 41027b064edaSJaganath Kanakkassery !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags)) 41037b064edaSJaganath Kanakkassery mgmt_device_connected(hdev, &hcon->dst, hcon->type, 41047b064edaSJaganath Kanakkassery hcon->dst_type, 0, NULL, 0, 41057b064edaSJaganath Kanakkassery hcon->dev_class); 41067b064edaSJaganath Kanakkassery hci_dev_unlock(hdev); 41077b064edaSJaganath Kanakkassery 4108300229f9SGustavo Padovan l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0); 41090a708f8fSGustavo F. Padovan return 0; 41100a708f8fSGustavo F. Padovan } 41110a708f8fSGustavo F. Padovan 41125909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn, 4113cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4114cb3b3152SJohan Hedberg u8 *data) 41150a708f8fSGustavo F. Padovan { 41160a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; 41170a708f8fSGustavo F. Padovan u16 scid, dcid, result, status; 411848454079SGustavo F. Padovan struct l2cap_chan *chan; 41190a708f8fSGustavo F. Padovan u8 req[128]; 41203df91ea2SAndrei Emeltchenko int err; 41210a708f8fSGustavo F. Padovan 4122cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp)) 4123cb3b3152SJohan Hedberg return -EPROTO; 4124cb3b3152SJohan Hedberg 41250a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 41260a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 41270a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 41280a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status); 41290a708f8fSGustavo F. Padovan 41301b009c98SAndrei Emeltchenko BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", 41311b009c98SAndrei Emeltchenko dcid, scid, result, status); 41320a708f8fSGustavo F. Padovan 41333df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 41343df91ea2SAndrei Emeltchenko 41350a708f8fSGustavo F. Padovan if (scid) { 41363df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 41373df91ea2SAndrei Emeltchenko if (!chan) { 413821870b52SJohan Hedberg err = -EBADSLT; 41393df91ea2SAndrei Emeltchenko goto unlock; 41403df91ea2SAndrei Emeltchenko } 41410a708f8fSGustavo F. Padovan } else { 41423df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 41433df91ea2SAndrei Emeltchenko if (!chan) { 414421870b52SJohan Hedberg err = -EBADSLT; 41453df91ea2SAndrei Emeltchenko goto unlock; 41463df91ea2SAndrei Emeltchenko } 41470a708f8fSGustavo F. Padovan } 41480a708f8fSGustavo F. Padovan 41493df91ea2SAndrei Emeltchenko err = 0; 41503df91ea2SAndrei Emeltchenko 41516be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 415248454079SGustavo F. Padovan 41530a708f8fSGustavo F. Padovan switch (result) { 41540a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS: 415589bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 4156fc7f8a7eSGustavo F. Padovan chan->ident = 0; 4157fe4128e0SGustavo F. Padovan chan->dcid = dcid; 4158c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state); 41590a708f8fSGustavo F. Padovan 4160c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 41610a708f8fSGustavo F. Padovan break; 41620a708f8fSGustavo F. Padovan 41630a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 416473ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, req), req); 416573ffa904SGustavo F. Padovan chan->num_conf_req++; 41660a708f8fSGustavo F. Padovan break; 41670a708f8fSGustavo F. Padovan 41680a708f8fSGustavo F. Padovan case L2CAP_CR_PEND: 4169c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 41700a708f8fSGustavo F. Padovan break; 41710a708f8fSGustavo F. Padovan 41720a708f8fSGustavo F. Padovan default: 417348454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED); 41740a708f8fSGustavo F. Padovan break; 41750a708f8fSGustavo F. Padovan } 41760a708f8fSGustavo F. Padovan 41776be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 41783df91ea2SAndrei Emeltchenko 41793df91ea2SAndrei Emeltchenko unlock: 41803df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 41813df91ea2SAndrei Emeltchenko 41823df91ea2SAndrei Emeltchenko return err; 41830a708f8fSGustavo F. Padovan } 41840a708f8fSGustavo F. Padovan 418547d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan) 41860a708f8fSGustavo F. Padovan { 41870a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both 41880a708f8fSGustavo F. Padovan * sides request it. 41890a708f8fSGustavo F. Padovan */ 41900c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) 419147d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 4192f2592d3eSAndrei Emeltchenko else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) 419347d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16; 41940a708f8fSGustavo F. Padovan } 41950a708f8fSGustavo F. Padovan 419629d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data, 419729d8a590SAndrei Emeltchenko u8 ident, u16 flags) 419829d8a590SAndrei Emeltchenko { 419929d8a590SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 420029d8a590SAndrei Emeltchenko 420129d8a590SAndrei Emeltchenko BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident, 420229d8a590SAndrei Emeltchenko flags); 420329d8a590SAndrei Emeltchenko 420429d8a590SAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 420529d8a590SAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 420629d8a590SAndrei Emeltchenko 420729d8a590SAndrei Emeltchenko l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP, 420829d8a590SAndrei Emeltchenko l2cap_build_conf_rsp(chan, data, 420929d8a590SAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), data); 421029d8a590SAndrei Emeltchenko } 421129d8a590SAndrei Emeltchenko 4212662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident, 4213662d652dSJohan Hedberg u16 scid, u16 dcid) 4214662d652dSJohan Hedberg { 4215662d652dSJohan Hedberg struct l2cap_cmd_rej_cid rej; 4216662d652dSJohan Hedberg 4217662d652dSJohan Hedberg rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID); 4218662d652dSJohan Hedberg rej.scid = __cpu_to_le16(scid); 4219662d652dSJohan Hedberg rej.dcid = __cpu_to_le16(dcid); 4220662d652dSJohan Hedberg 4221662d652dSJohan Hedberg l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); 4222662d652dSJohan Hedberg } 4223662d652dSJohan Hedberg 42242d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, 42252d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len, 42262d792818SGustavo Padovan u8 *data) 42270a708f8fSGustavo F. Padovan { 42280a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; 42290a708f8fSGustavo F. Padovan u16 dcid, flags; 42300a708f8fSGustavo F. Padovan u8 rsp[64]; 423148454079SGustavo F. Padovan struct l2cap_chan *chan; 42323c588192SMat Martineau int len, err = 0; 42330a708f8fSGustavo F. Padovan 4234cb3b3152SJohan Hedberg if (cmd_len < sizeof(*req)) 4235cb3b3152SJohan Hedberg return -EPROTO; 4236cb3b3152SJohan Hedberg 42370a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 42380a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags); 42390a708f8fSGustavo F. Padovan 42400a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); 42410a708f8fSGustavo F. Padovan 4242baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid); 4243662d652dSJohan Hedberg if (!chan) { 4244662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0); 4245662d652dSJohan Hedberg return 0; 4246662d652dSJohan Hedberg } 42470a708f8fSGustavo F. Padovan 4248033b1142SDavid S. Miller if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { 4249662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, 4250662d652dSJohan Hedberg chan->dcid); 42510a708f8fSGustavo F. Padovan goto unlock; 42520a708f8fSGustavo F. Padovan } 42530a708f8fSGustavo F. Padovan 42540a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */ 42550a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req); 4256cb3b3152SJohan Hedberg if (chan->conf_len + len > sizeof(chan->conf_req)) { 42570a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 4258fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 42590a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp); 42600a708f8fSGustavo F. Padovan goto unlock; 42610a708f8fSGustavo F. Padovan } 42620a708f8fSGustavo F. Padovan 42630a708f8fSGustavo F. Padovan /* Store config. */ 426473ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len); 426573ffa904SGustavo F. Padovan chan->conf_len += len; 42660a708f8fSGustavo F. Padovan 426759e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) { 42680a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */ 42690a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 4270fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 42715325e5bbSAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), rsp); 42720a708f8fSGustavo F. Padovan goto unlock; 42730a708f8fSGustavo F. Padovan } 42740a708f8fSGustavo F. Padovan 42750a708f8fSGustavo F. Padovan /* Complete config. */ 427673ffa904SGustavo F. Padovan len = l2cap_parse_conf_req(chan, rsp); 42770a708f8fSGustavo F. Padovan if (len < 0) { 42785e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 42790a708f8fSGustavo F. Padovan goto unlock; 42800a708f8fSGustavo F. Padovan } 42810a708f8fSGustavo F. Padovan 42821500109bSMat Martineau chan->ident = cmd->ident; 42830a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); 428473ffa904SGustavo F. Padovan chan->num_conf_rsp++; 42850a708f8fSGustavo F. Padovan 42860a708f8fSGustavo F. Padovan /* Reset config buffer. */ 428773ffa904SGustavo F. Padovan chan->conf_len = 0; 42880a708f8fSGustavo F. Padovan 4289c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) 42900a708f8fSGustavo F. Padovan goto unlock; 42910a708f8fSGustavo F. Padovan 4292c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 429347d1ec61SGustavo F. Padovan set_default_fcs(chan); 42940a708f8fSGustavo F. Padovan 4295105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 4296105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 42973c588192SMat Martineau err = l2cap_ertm_init(chan); 42980a708f8fSGustavo F. Padovan 42993c588192SMat Martineau if (err < 0) 43005e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 43013c588192SMat Martineau else 4302cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 43033c588192SMat Martineau 43040a708f8fSGustavo F. Padovan goto unlock; 43050a708f8fSGustavo F. Padovan } 43060a708f8fSGustavo F. Padovan 4307c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { 43080a708f8fSGustavo F. Padovan u8 buf[64]; 43090a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 431073ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 431173ffa904SGustavo F. Padovan chan->num_conf_req++; 43120a708f8fSGustavo F. Padovan } 43130a708f8fSGustavo F. Padovan 43140e8b207eSAndrei Emeltchenko /* Got Conf Rsp PENDING from remote side and asume we sent 43150e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */ 43160e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && 43170e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 43180e8b207eSAndrei Emeltchenko 43190e8b207eSAndrei Emeltchenko /* check compatibility */ 43200e8b207eSAndrei Emeltchenko 432179de886dSAndrei Emeltchenko /* Send rsp for BR/EDR channel */ 4322f351bc72SAndrei Emeltchenko if (!chan->hs_hcon) 432329d8a590SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags); 432479de886dSAndrei Emeltchenko else 432579de886dSAndrei Emeltchenko chan->ident = cmd->ident; 43260e8b207eSAndrei Emeltchenko } 43270e8b207eSAndrei Emeltchenko 43280a708f8fSGustavo F. Padovan unlock: 43296be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 43303c588192SMat Martineau return err; 43310a708f8fSGustavo F. Padovan } 43320a708f8fSGustavo F. Padovan 43332d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, 4334cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4335cb3b3152SJohan Hedberg u8 *data) 43360a708f8fSGustavo F. Padovan { 43370a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; 43380a708f8fSGustavo F. Padovan u16 scid, flags, result; 433948454079SGustavo F. Padovan struct l2cap_chan *chan; 4340cb3b3152SJohan Hedberg int len = cmd_len - sizeof(*rsp); 43413c588192SMat Martineau int err = 0; 43420a708f8fSGustavo F. Padovan 4343cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp)) 4344cb3b3152SJohan Hedberg return -EPROTO; 4345cb3b3152SJohan Hedberg 43460a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 43470a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags); 43480a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 43490a708f8fSGustavo F. Padovan 435061386cbaSAndrei Emeltchenko BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags, 435161386cbaSAndrei Emeltchenko result, len); 43520a708f8fSGustavo F. Padovan 4353baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 435448454079SGustavo F. Padovan if (!chan) 43550a708f8fSGustavo F. Padovan return 0; 43560a708f8fSGustavo F. Padovan 43570a708f8fSGustavo F. Padovan switch (result) { 43580a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS: 435947d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len); 43600e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state); 43610a708f8fSGustavo F. Padovan break; 43620a708f8fSGustavo F. Padovan 43630e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING: 43640e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state); 43650e8b207eSAndrei Emeltchenko 43660e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 43670e8b207eSAndrei Emeltchenko char buf[64]; 43680e8b207eSAndrei Emeltchenko 43690e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len, 43700e8b207eSAndrei Emeltchenko buf, &result); 43710e8b207eSAndrei Emeltchenko if (len < 0) { 43725e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 43730e8b207eSAndrei Emeltchenko goto done; 43740e8b207eSAndrei Emeltchenko } 43750e8b207eSAndrei Emeltchenko 4376f351bc72SAndrei Emeltchenko if (!chan->hs_hcon) { 437779de886dSAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, buf, cmd->ident, 437879de886dSAndrei Emeltchenko 0); 43795ce66b59SAndrei Emeltchenko } else { 43805ce66b59SAndrei Emeltchenko if (l2cap_check_efs(chan)) { 43815ce66b59SAndrei Emeltchenko amp_create_logical_link(chan); 438279de886dSAndrei Emeltchenko chan->ident = cmd->ident; 43830e8b207eSAndrei Emeltchenko } 43845ce66b59SAndrei Emeltchenko } 43855ce66b59SAndrei Emeltchenko } 43860e8b207eSAndrei Emeltchenko goto done; 43870e8b207eSAndrei Emeltchenko 43880a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT: 438973ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { 43900a708f8fSGustavo F. Padovan char req[64]; 43910a708f8fSGustavo F. Padovan 43920a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { 43935e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 43940a708f8fSGustavo F. Padovan goto done; 43950a708f8fSGustavo F. Padovan } 43960a708f8fSGustavo F. Padovan 43970a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */ 43980a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS; 4399b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len, 4400b4450035SGustavo F. Padovan req, &result); 44010a708f8fSGustavo F. Padovan if (len < 0) { 44025e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 44030a708f8fSGustavo F. Padovan goto done; 44040a708f8fSGustavo F. Padovan } 44050a708f8fSGustavo F. Padovan 44060a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 44070a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req); 440873ffa904SGustavo F. Padovan chan->num_conf_req++; 44090a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS) 44100a708f8fSGustavo F. Padovan goto done; 44110a708f8fSGustavo F. Padovan break; 44120a708f8fSGustavo F. Padovan } 44130a708f8fSGustavo F. Padovan 44140a708f8fSGustavo F. Padovan default: 44156be36555SAndrei Emeltchenko l2cap_chan_set_err(chan, ECONNRESET); 44162e0052e4SAndrei Emeltchenko 4417ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); 44185e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 44190a708f8fSGustavo F. Padovan goto done; 44200a708f8fSGustavo F. Padovan } 44210a708f8fSGustavo F. Padovan 442259e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) 44230a708f8fSGustavo F. Padovan goto done; 44240a708f8fSGustavo F. Padovan 4425c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state); 44260a708f8fSGustavo F. Padovan 4427c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { 442847d1ec61SGustavo F. Padovan set_default_fcs(chan); 44290a708f8fSGustavo F. Padovan 4430105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 4431105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 44323c588192SMat Martineau err = l2cap_ertm_init(chan); 44330a708f8fSGustavo F. Padovan 44343c588192SMat Martineau if (err < 0) 44355e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 44363c588192SMat Martineau else 4437cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 44380a708f8fSGustavo F. Padovan } 44390a708f8fSGustavo F. Padovan 44400a708f8fSGustavo F. Padovan done: 44416be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 44423c588192SMat Martineau return err; 44430a708f8fSGustavo F. Padovan } 44440a708f8fSGustavo F. Padovan 44452d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, 4446cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4447cb3b3152SJohan Hedberg u8 *data) 44480a708f8fSGustavo F. Padovan { 44490a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; 44500a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp; 44510a708f8fSGustavo F. Padovan u16 dcid, scid; 445248454079SGustavo F. Padovan struct l2cap_chan *chan; 44530a708f8fSGustavo F. Padovan 4454cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req)) 4455cb3b3152SJohan Hedberg return -EPROTO; 4456cb3b3152SJohan Hedberg 44570a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid); 44580a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 44590a708f8fSGustavo F. Padovan 44600a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); 44610a708f8fSGustavo F. Padovan 44623df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 44633df91ea2SAndrei Emeltchenko 44643df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, dcid); 44653df91ea2SAndrei Emeltchenko if (!chan) { 44663df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4467662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid); 4468662d652dSJohan Hedberg return 0; 44693df91ea2SAndrei Emeltchenko } 44700a708f8fSGustavo F. Padovan 44716be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 44726be36555SAndrei Emeltchenko 4473fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 4474fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 44750a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); 44760a708f8fSGustavo F. Padovan 44775ec1bbe5SGustavo Padovan chan->ops->set_shutdown(chan); 44780a708f8fSGustavo F. Padovan 447961d6ef3eSMat Martineau l2cap_chan_hold(chan); 448048454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET); 44816be36555SAndrei Emeltchenko 44826be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 44830a708f8fSGustavo F. Padovan 448480b98027SGustavo Padovan chan->ops->close(chan); 448561d6ef3eSMat Martineau l2cap_chan_put(chan); 44863df91ea2SAndrei Emeltchenko 44873df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 44883df91ea2SAndrei Emeltchenko 44890a708f8fSGustavo F. Padovan return 0; 44900a708f8fSGustavo F. Padovan } 44910a708f8fSGustavo F. Padovan 44922d792818SGustavo Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, 4493cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4494cb3b3152SJohan Hedberg u8 *data) 44950a708f8fSGustavo F. Padovan { 44960a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; 44970a708f8fSGustavo F. Padovan u16 dcid, scid; 449848454079SGustavo F. Padovan struct l2cap_chan *chan; 44990a708f8fSGustavo F. Padovan 4500cb3b3152SJohan Hedberg if (cmd_len != sizeof(*rsp)) 4501cb3b3152SJohan Hedberg return -EPROTO; 4502cb3b3152SJohan Hedberg 45030a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 45040a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 45050a708f8fSGustavo F. Padovan 45060a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); 45070a708f8fSGustavo F. Padovan 45083df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 45093df91ea2SAndrei Emeltchenko 45103df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 45113df91ea2SAndrei Emeltchenko if (!chan) { 45123df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 45130a708f8fSGustavo F. Padovan return 0; 45143df91ea2SAndrei Emeltchenko } 45150a708f8fSGustavo F. Padovan 45166be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 451748454079SGustavo F. Padovan 451861d6ef3eSMat Martineau l2cap_chan_hold(chan); 451948454079SGustavo F. Padovan l2cap_chan_del(chan, 0); 45206be36555SAndrei Emeltchenko 45216be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 45220a708f8fSGustavo F. Padovan 452380b98027SGustavo Padovan chan->ops->close(chan); 452461d6ef3eSMat Martineau l2cap_chan_put(chan); 45253df91ea2SAndrei Emeltchenko 45263df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 45273df91ea2SAndrei Emeltchenko 45280a708f8fSGustavo F. Padovan return 0; 45290a708f8fSGustavo F. Padovan } 45300a708f8fSGustavo F. Padovan 45312d792818SGustavo Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, 4532cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4533cb3b3152SJohan Hedberg u8 *data) 45340a708f8fSGustavo F. Padovan { 45350a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data; 45360a708f8fSGustavo F. Padovan u16 type; 45370a708f8fSGustavo F. Padovan 4538cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req)) 4539cb3b3152SJohan Hedberg return -EPROTO; 4540cb3b3152SJohan Hedberg 45410a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type); 45420a708f8fSGustavo F. Padovan 45430a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type); 45440a708f8fSGustavo F. Padovan 45450a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) { 45460a708f8fSGustavo F. Padovan u8 buf[8]; 45470a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask; 45480a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 4549ac73498cSAndrei Emeltchenko rsp->type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); 4550ac73498cSAndrei Emeltchenko rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); 45510a708f8fSGustavo F. Padovan if (!disable_ertm) 45520a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING 45530a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS; 4554848566b3SMarcel Holtmann if (conn->hs_enabled) 45556327eb98SAndrei Emeltchenko feat_mask |= L2CAP_FEAT_EXT_FLOW 45566327eb98SAndrei Emeltchenko | L2CAP_FEAT_EXT_WINDOW; 4557a5fd6f30SAndrei Emeltchenko 45580a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data); 45592d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), 45602d792818SGustavo Padovan buf); 45610a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) { 45620a708f8fSGustavo F. Padovan u8 buf[12]; 45630a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 456450a147cdSMat Martineau 4565848566b3SMarcel Holtmann if (conn->hs_enabled) 456650a147cdSMat Martineau l2cap_fixed_chan[0] |= L2CAP_FC_A2MP; 456750a147cdSMat Martineau else 456850a147cdSMat Martineau l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP; 456950a147cdSMat Martineau 4570ac73498cSAndrei Emeltchenko rsp->type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); 4571ac73498cSAndrei Emeltchenko rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); 4572c6337ea6SAndrei Emeltchenko memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); 45732d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), 45742d792818SGustavo Padovan buf); 45750a708f8fSGustavo F. Padovan } else { 45760a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp; 45770a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type); 4578ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP); 45792d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), 45802d792818SGustavo Padovan &rsp); 45810a708f8fSGustavo F. Padovan } 45820a708f8fSGustavo F. Padovan 45830a708f8fSGustavo F. Padovan return 0; 45840a708f8fSGustavo F. Padovan } 45850a708f8fSGustavo F. Padovan 45862d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, 4587cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4588cb3b3152SJohan Hedberg u8 *data) 45890a708f8fSGustavo F. Padovan { 45900a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; 45910a708f8fSGustavo F. Padovan u16 type, result; 45920a708f8fSGustavo F. Padovan 45933f6fa3d4SJaganath Kanakkassery if (cmd_len < sizeof(*rsp)) 4594cb3b3152SJohan Hedberg return -EPROTO; 4595cb3b3152SJohan Hedberg 45960a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type); 45970a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 45980a708f8fSGustavo F. Padovan 45990a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); 46000a708f8fSGustavo F. Padovan 4601e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */ 4602e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident || 4603e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 4604e90165beSAndrei Emeltchenko return 0; 4605e90165beSAndrei Emeltchenko 460617cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 46070a708f8fSGustavo F. Padovan 46080a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) { 46090a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 46100a708f8fSGustavo F. Padovan conn->info_ident = 0; 46110a708f8fSGustavo F. Padovan 46120a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 46130a708f8fSGustavo F. Padovan 46140a708f8fSGustavo F. Padovan return 0; 46150a708f8fSGustavo F. Padovan } 46160a708f8fSGustavo F. Padovan 4617978c93b9SAndrei Emeltchenko switch (type) { 4618978c93b9SAndrei Emeltchenko case L2CAP_IT_FEAT_MASK: 46190a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data); 46200a708f8fSGustavo F. Padovan 46210a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { 46220a708f8fSGustavo F. Padovan struct l2cap_info_req req; 4623ac73498cSAndrei Emeltchenko req.type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); 46240a708f8fSGustavo F. Padovan 46250a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 46260a708f8fSGustavo F. Padovan 46270a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 46280a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 46290a708f8fSGustavo F. Padovan } else { 46300a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 46310a708f8fSGustavo F. Padovan conn->info_ident = 0; 46320a708f8fSGustavo F. Padovan 46330a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 46340a708f8fSGustavo F. Padovan } 4635978c93b9SAndrei Emeltchenko break; 4636978c93b9SAndrei Emeltchenko 4637978c93b9SAndrei Emeltchenko case L2CAP_IT_FIXED_CHAN: 4638978c93b9SAndrei Emeltchenko conn->fixed_chan_mask = rsp->data[0]; 46390a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 46400a708f8fSGustavo F. Padovan conn->info_ident = 0; 46410a708f8fSGustavo F. Padovan 46420a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 4643978c93b9SAndrei Emeltchenko break; 46440a708f8fSGustavo F. Padovan } 46450a708f8fSGustavo F. Padovan 46460a708f8fSGustavo F. Padovan return 0; 46470a708f8fSGustavo F. Padovan } 46480a708f8fSGustavo F. Padovan 46491700915fSMat Martineau static int l2cap_create_channel_req(struct l2cap_conn *conn, 46502d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, 46512d792818SGustavo Padovan u16 cmd_len, void *data) 4652f94ff6ffSMat Martineau { 4653f94ff6ffSMat Martineau struct l2cap_create_chan_req *req = data; 46546e1df6a6SAndrei Emeltchenko struct l2cap_create_chan_rsp rsp; 46551700915fSMat Martineau struct l2cap_chan *chan; 46566e1df6a6SAndrei Emeltchenko struct hci_dev *hdev; 4657f94ff6ffSMat Martineau u16 psm, scid; 4658f94ff6ffSMat Martineau 4659f94ff6ffSMat Martineau if (cmd_len != sizeof(*req)) 4660f94ff6ffSMat Martineau return -EPROTO; 4661f94ff6ffSMat Martineau 4662848566b3SMarcel Holtmann if (!conn->hs_enabled) 4663f94ff6ffSMat Martineau return -EINVAL; 4664f94ff6ffSMat Martineau 4665f94ff6ffSMat Martineau psm = le16_to_cpu(req->psm); 4666f94ff6ffSMat Martineau scid = le16_to_cpu(req->scid); 4667f94ff6ffSMat Martineau 4668ad0ac6caSAndrei Emeltchenko BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id); 4669f94ff6ffSMat Martineau 46706e1df6a6SAndrei Emeltchenko /* For controller id 0 make BR/EDR connection */ 46716ed971caSMarcel Holtmann if (req->amp_id == AMP_ID_BREDR) { 46726e1df6a6SAndrei Emeltchenko l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, 46736e1df6a6SAndrei Emeltchenko req->amp_id); 46746e1df6a6SAndrei Emeltchenko return 0; 46756e1df6a6SAndrei Emeltchenko } 46761700915fSMat Martineau 46771700915fSMat Martineau /* Validate AMP controller id */ 46781700915fSMat Martineau hdev = hci_dev_get(req->amp_id); 46796e1df6a6SAndrei Emeltchenko if (!hdev) 46806e1df6a6SAndrei Emeltchenko goto error; 46811700915fSMat Martineau 46826e1df6a6SAndrei Emeltchenko if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) { 46836e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 46846e1df6a6SAndrei Emeltchenko goto error; 46856e1df6a6SAndrei Emeltchenko } 46866e1df6a6SAndrei Emeltchenko 46876e1df6a6SAndrei Emeltchenko chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, 46886e1df6a6SAndrei Emeltchenko req->amp_id); 46896e1df6a6SAndrei Emeltchenko if (chan) { 46906e1df6a6SAndrei Emeltchenko struct amp_mgr *mgr = conn->hcon->amp_mgr; 46916e1df6a6SAndrei Emeltchenko struct hci_conn *hs_hcon; 46926e1df6a6SAndrei Emeltchenko 469398e0f7eaSMarcel Holtmann hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, 469498e0f7eaSMarcel Holtmann &conn->hcon->dst); 46956e1df6a6SAndrei Emeltchenko if (!hs_hcon) { 46966e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 4697662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, 4698662d652dSJohan Hedberg chan->dcid); 4699662d652dSJohan Hedberg return 0; 47006e1df6a6SAndrei Emeltchenko } 47016e1df6a6SAndrei Emeltchenko 47026e1df6a6SAndrei Emeltchenko BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon); 47036e1df6a6SAndrei Emeltchenko 47046e1df6a6SAndrei Emeltchenko mgr->bredr_chan = chan; 47056e1df6a6SAndrei Emeltchenko chan->hs_hcon = hs_hcon; 4706fd45bf4cSAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 47076e1df6a6SAndrei Emeltchenko conn->mtu = hdev->block_mtu; 47086e1df6a6SAndrei Emeltchenko } 47096e1df6a6SAndrei Emeltchenko 47106e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 47116e1df6a6SAndrei Emeltchenko 47126e1df6a6SAndrei Emeltchenko return 0; 47136e1df6a6SAndrei Emeltchenko 47146e1df6a6SAndrei Emeltchenko error: 4715f94ff6ffSMat Martineau rsp.dcid = 0; 4716f94ff6ffSMat Martineau rsp.scid = cpu_to_le16(scid); 47171700915fSMat Martineau rsp.result = __constant_cpu_to_le16(L2CAP_CR_BAD_AMP); 47188ce0c498SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 4719f94ff6ffSMat Martineau 4720f94ff6ffSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, 4721f94ff6ffSMat Martineau sizeof(rsp), &rsp); 4722f94ff6ffSMat Martineau 4723dc280801SJohan Hedberg return 0; 4724f94ff6ffSMat Martineau } 4725f94ff6ffSMat Martineau 47268eb200bdSMat Martineau static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id) 47278eb200bdSMat Martineau { 47288eb200bdSMat Martineau struct l2cap_move_chan_req req; 47298eb200bdSMat Martineau u8 ident; 47308eb200bdSMat Martineau 47318eb200bdSMat Martineau BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id); 47328eb200bdSMat Martineau 47338eb200bdSMat Martineau ident = l2cap_get_ident(chan->conn); 47348eb200bdSMat Martineau chan->ident = ident; 47358eb200bdSMat Martineau 47368eb200bdSMat Martineau req.icid = cpu_to_le16(chan->scid); 47378eb200bdSMat Martineau req.dest_amp_id = dest_amp_id; 47388eb200bdSMat Martineau 47398eb200bdSMat Martineau l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req), 47408eb200bdSMat Martineau &req); 47418eb200bdSMat Martineau 47428eb200bdSMat Martineau __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); 47438eb200bdSMat Martineau } 47448eb200bdSMat Martineau 47451500109bSMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result) 47468d5a04a1SMat Martineau { 47478d5a04a1SMat Martineau struct l2cap_move_chan_rsp rsp; 47488d5a04a1SMat Martineau 47491500109bSMat Martineau BT_DBG("chan %p, result 0x%4.4x", chan, result); 47508d5a04a1SMat Martineau 47511500109bSMat Martineau rsp.icid = cpu_to_le16(chan->dcid); 47528d5a04a1SMat Martineau rsp.result = cpu_to_le16(result); 47538d5a04a1SMat Martineau 47541500109bSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP, 47551500109bSMat Martineau sizeof(rsp), &rsp); 47568d5a04a1SMat Martineau } 47578d5a04a1SMat Martineau 47585b155ef9SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result) 47598d5a04a1SMat Martineau { 47608d5a04a1SMat Martineau struct l2cap_move_chan_cfm cfm; 47618d5a04a1SMat Martineau 47625b155ef9SMat Martineau BT_DBG("chan %p, result 0x%4.4x", chan, result); 47638d5a04a1SMat Martineau 47645b155ef9SMat Martineau chan->ident = l2cap_get_ident(chan->conn); 47658d5a04a1SMat Martineau 47665b155ef9SMat Martineau cfm.icid = cpu_to_le16(chan->scid); 47678d5a04a1SMat Martineau cfm.result = cpu_to_le16(result); 47688d5a04a1SMat Martineau 47695b155ef9SMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM, 47705b155ef9SMat Martineau sizeof(cfm), &cfm); 47715b155ef9SMat Martineau 47725b155ef9SMat Martineau __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); 47735b155ef9SMat Martineau } 47745b155ef9SMat Martineau 47755b155ef9SMat Martineau static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid) 47765b155ef9SMat Martineau { 47775b155ef9SMat Martineau struct l2cap_move_chan_cfm cfm; 47785b155ef9SMat Martineau 47795b155ef9SMat Martineau BT_DBG("conn %p, icid 0x%4.4x", conn, icid); 47805b155ef9SMat Martineau 47815b155ef9SMat Martineau cfm.icid = cpu_to_le16(icid); 47825b155ef9SMat Martineau cfm.result = __constant_cpu_to_le16(L2CAP_MC_UNCONFIRMED); 47835b155ef9SMat Martineau 47845b155ef9SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM, 47855b155ef9SMat Martineau sizeof(cfm), &cfm); 47868d5a04a1SMat Martineau } 47878d5a04a1SMat Martineau 47888d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, 47898d5a04a1SMat Martineau u16 icid) 47908d5a04a1SMat Martineau { 47918d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp rsp; 47928d5a04a1SMat Martineau 4793ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 47948d5a04a1SMat Martineau 47958d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 47968d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp); 47978d5a04a1SMat Martineau } 47988d5a04a1SMat Martineau 47995f3847a4SMat Martineau static void __release_logical_link(struct l2cap_chan *chan) 48005f3847a4SMat Martineau { 48015f3847a4SMat Martineau chan->hs_hchan = NULL; 48025f3847a4SMat Martineau chan->hs_hcon = NULL; 48035f3847a4SMat Martineau 48045f3847a4SMat Martineau /* Placeholder - release the logical link */ 48055f3847a4SMat Martineau } 48065f3847a4SMat Martineau 48071500109bSMat Martineau static void l2cap_logical_fail(struct l2cap_chan *chan) 48081500109bSMat Martineau { 48091500109bSMat Martineau /* Logical link setup failed */ 48101500109bSMat Martineau if (chan->state != BT_CONNECTED) { 48111500109bSMat Martineau /* Create channel failure, disconnect */ 48125e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 48131500109bSMat Martineau return; 48141500109bSMat Martineau } 48151500109bSMat Martineau 48161500109bSMat Martineau switch (chan->move_role) { 48171500109bSMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 48181500109bSMat Martineau l2cap_move_done(chan); 48191500109bSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP); 48201500109bSMat Martineau break; 48211500109bSMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 48221500109bSMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP || 48231500109bSMat Martineau chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) { 48241500109bSMat Martineau /* Remote has only sent pending or 48251500109bSMat Martineau * success responses, clean up 48261500109bSMat Martineau */ 48271500109bSMat Martineau l2cap_move_done(chan); 48281500109bSMat Martineau } 48291500109bSMat Martineau 48301500109bSMat Martineau /* Other amp move states imply that the move 48311500109bSMat Martineau * has already aborted 48321500109bSMat Martineau */ 48331500109bSMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 48341500109bSMat Martineau break; 48351500109bSMat Martineau } 48361500109bSMat Martineau } 48371500109bSMat Martineau 48381500109bSMat Martineau static void l2cap_logical_finish_create(struct l2cap_chan *chan, 48391500109bSMat Martineau struct hci_chan *hchan) 48401500109bSMat Martineau { 48411500109bSMat Martineau struct l2cap_conf_rsp rsp; 48421500109bSMat Martineau 4843336178a3SAndrei Emeltchenko chan->hs_hchan = hchan; 48441500109bSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 48451500109bSMat Martineau 484635ba9561SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0); 48471500109bSMat Martineau 48481500109bSMat Martineau if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 4849fe79c6feSAndrei Emeltchenko int err; 48501500109bSMat Martineau 48511500109bSMat Martineau set_default_fcs(chan); 48521500109bSMat Martineau 48531500109bSMat Martineau err = l2cap_ertm_init(chan); 48541500109bSMat Martineau if (err < 0) 48555e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 48561500109bSMat Martineau else 48571500109bSMat Martineau l2cap_chan_ready(chan); 48581500109bSMat Martineau } 48591500109bSMat Martineau } 48601500109bSMat Martineau 48611500109bSMat Martineau static void l2cap_logical_finish_move(struct l2cap_chan *chan, 48621500109bSMat Martineau struct hci_chan *hchan) 48631500109bSMat Martineau { 48641500109bSMat Martineau chan->hs_hcon = hchan->conn; 48651500109bSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 48661500109bSMat Martineau 48671500109bSMat Martineau BT_DBG("move_state %d", chan->move_state); 48681500109bSMat Martineau 48691500109bSMat Martineau switch (chan->move_state) { 48701500109bSMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_COMP: 48711500109bSMat Martineau /* Move confirm will be sent after a success 48721500109bSMat Martineau * response is received 48731500109bSMat Martineau */ 48741500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 48751500109bSMat Martineau break; 48761500109bSMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_CFM: 48771500109bSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 48781500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 48791500109bSMat Martineau } else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { 48801500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; 48811500109bSMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 48821500109bSMat Martineau } else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { 48831500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 48841500109bSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); 48851500109bSMat Martineau } 48861500109bSMat Martineau break; 48871500109bSMat Martineau default: 48881500109bSMat Martineau /* Move was not in expected state, free the channel */ 48891500109bSMat Martineau __release_logical_link(chan); 48901500109bSMat Martineau 48911500109bSMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 48921500109bSMat Martineau } 48931500109bSMat Martineau } 48941500109bSMat Martineau 48951500109bSMat Martineau /* Call with chan locked */ 489627695fb4SAndrei Emeltchenko void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan, 48975b155ef9SMat Martineau u8 status) 48985b155ef9SMat Martineau { 48991500109bSMat Martineau BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status); 49001500109bSMat Martineau 49011500109bSMat Martineau if (status) { 49021500109bSMat Martineau l2cap_logical_fail(chan); 49031500109bSMat Martineau __release_logical_link(chan); 49045b155ef9SMat Martineau return; 49055b155ef9SMat Martineau } 49065b155ef9SMat Martineau 49071500109bSMat Martineau if (chan->state != BT_CONNECTED) { 49081500109bSMat Martineau /* Ignore logical link if channel is on BR/EDR */ 49096ed971caSMarcel Holtmann if (chan->local_amp_id != AMP_ID_BREDR) 49101500109bSMat Martineau l2cap_logical_finish_create(chan, hchan); 49111500109bSMat Martineau } else { 49121500109bSMat Martineau l2cap_logical_finish_move(chan, hchan); 49131500109bSMat Martineau } 49141500109bSMat Martineau } 49151500109bSMat Martineau 49163f7a56c4SMat Martineau void l2cap_move_start(struct l2cap_chan *chan) 49173f7a56c4SMat Martineau { 49183f7a56c4SMat Martineau BT_DBG("chan %p", chan); 49193f7a56c4SMat Martineau 49206ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR) { 49213f7a56c4SMat Martineau if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED) 49223f7a56c4SMat Martineau return; 49233f7a56c4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; 49243f7a56c4SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_PREPARE; 49253f7a56c4SMat Martineau /* Placeholder - start physical link setup */ 49263f7a56c4SMat Martineau } else { 49273f7a56c4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; 49283f7a56c4SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 49293f7a56c4SMat Martineau chan->move_id = 0; 49303f7a56c4SMat Martineau l2cap_move_setup(chan); 49313f7a56c4SMat Martineau l2cap_send_move_chan_req(chan, 0); 49323f7a56c4SMat Martineau } 49333f7a56c4SMat Martineau } 49343f7a56c4SMat Martineau 49358eb200bdSMat Martineau static void l2cap_do_create(struct l2cap_chan *chan, int result, 49368eb200bdSMat Martineau u8 local_amp_id, u8 remote_amp_id) 49378eb200bdSMat Martineau { 493862748ca1SAndrei Emeltchenko BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state), 493962748ca1SAndrei Emeltchenko local_amp_id, remote_amp_id); 494062748ca1SAndrei Emeltchenko 494112d6cc60SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 494212d6cc60SAndrei Emeltchenko 494362748ca1SAndrei Emeltchenko /* Outgoing channel on AMP */ 494462748ca1SAndrei Emeltchenko if (chan->state == BT_CONNECT) { 494562748ca1SAndrei Emeltchenko if (result == L2CAP_CR_SUCCESS) { 494662748ca1SAndrei Emeltchenko chan->local_amp_id = local_amp_id; 494762748ca1SAndrei Emeltchenko l2cap_send_create_chan_req(chan, remote_amp_id); 494862748ca1SAndrei Emeltchenko } else { 494962748ca1SAndrei Emeltchenko /* Revert to BR/EDR connect */ 495062748ca1SAndrei Emeltchenko l2cap_send_conn_req(chan); 495162748ca1SAndrei Emeltchenko } 495262748ca1SAndrei Emeltchenko 495362748ca1SAndrei Emeltchenko return; 495462748ca1SAndrei Emeltchenko } 495562748ca1SAndrei Emeltchenko 495662748ca1SAndrei Emeltchenko /* Incoming channel on AMP */ 495762748ca1SAndrei Emeltchenko if (__l2cap_no_conn_pending(chan)) { 49588eb200bdSMat Martineau struct l2cap_conn_rsp rsp; 49598eb200bdSMat Martineau char buf[128]; 49608eb200bdSMat Martineau rsp.scid = cpu_to_le16(chan->dcid); 49618eb200bdSMat Martineau rsp.dcid = cpu_to_le16(chan->scid); 49628eb200bdSMat Martineau 49638eb200bdSMat Martineau if (result == L2CAP_CR_SUCCESS) { 49648eb200bdSMat Martineau /* Send successful response */ 496562cd50e2SAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 496662cd50e2SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 49678eb200bdSMat Martineau } else { 49688eb200bdSMat Martineau /* Send negative response */ 496962cd50e2SAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM); 497062cd50e2SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 49718eb200bdSMat Martineau } 49728eb200bdSMat Martineau 49738eb200bdSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP, 49748eb200bdSMat Martineau sizeof(rsp), &rsp); 49758eb200bdSMat Martineau 49768eb200bdSMat Martineau if (result == L2CAP_CR_SUCCESS) { 4977f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 49788eb200bdSMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 49798eb200bdSMat Martineau l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn), 49808eb200bdSMat Martineau L2CAP_CONF_REQ, 49818eb200bdSMat Martineau l2cap_build_conf_req(chan, buf), buf); 49828eb200bdSMat Martineau chan->num_conf_req++; 49838eb200bdSMat Martineau } 49848eb200bdSMat Martineau } 49858eb200bdSMat Martineau } 49868eb200bdSMat Martineau 49878eb200bdSMat Martineau static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id, 49888eb200bdSMat Martineau u8 remote_amp_id) 49898eb200bdSMat Martineau { 49908eb200bdSMat Martineau l2cap_move_setup(chan); 49918eb200bdSMat Martineau chan->move_id = local_amp_id; 49928eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP; 49938eb200bdSMat Martineau 49948eb200bdSMat Martineau l2cap_send_move_chan_req(chan, remote_amp_id); 49958eb200bdSMat Martineau } 49968eb200bdSMat Martineau 49978eb200bdSMat Martineau static void l2cap_do_move_respond(struct l2cap_chan *chan, int result) 49988eb200bdSMat Martineau { 49998eb200bdSMat Martineau struct hci_chan *hchan = NULL; 50008eb200bdSMat Martineau 50018eb200bdSMat Martineau /* Placeholder - get hci_chan for logical link */ 50028eb200bdSMat Martineau 50038eb200bdSMat Martineau if (hchan) { 50048eb200bdSMat Martineau if (hchan->state == BT_CONNECTED) { 50058eb200bdSMat Martineau /* Logical link is ready to go */ 50068eb200bdSMat Martineau chan->hs_hcon = hchan->conn; 50078eb200bdSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 50088eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 50098eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); 50108eb200bdSMat Martineau 50118eb200bdSMat Martineau l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); 50128eb200bdSMat Martineau } else { 50138eb200bdSMat Martineau /* Wait for logical link to be ready */ 50148eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 50158eb200bdSMat Martineau } 50168eb200bdSMat Martineau } else { 50178eb200bdSMat Martineau /* Logical link not available */ 50188eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED); 50198eb200bdSMat Martineau } 50208eb200bdSMat Martineau } 50218eb200bdSMat Martineau 50228eb200bdSMat Martineau static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result) 50238eb200bdSMat Martineau { 50248eb200bdSMat Martineau if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { 50258eb200bdSMat Martineau u8 rsp_result; 50268eb200bdSMat Martineau if (result == -EINVAL) 50278eb200bdSMat Martineau rsp_result = L2CAP_MR_BAD_ID; 50288eb200bdSMat Martineau else 50298eb200bdSMat Martineau rsp_result = L2CAP_MR_NOT_ALLOWED; 50308eb200bdSMat Martineau 50318eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, rsp_result); 50328eb200bdSMat Martineau } 50338eb200bdSMat Martineau 50348eb200bdSMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 50358eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 50368eb200bdSMat Martineau 50378eb200bdSMat Martineau /* Restart data transmission */ 50388eb200bdSMat Martineau l2cap_ertm_send(chan); 50398eb200bdSMat Martineau } 50408eb200bdSMat Martineau 5041a514b17fSAndrei Emeltchenko /* Invoke with locked chan */ 5042a514b17fSAndrei Emeltchenko void __l2cap_physical_cfm(struct l2cap_chan *chan, int result) 50438eb200bdSMat Martineau { 5044770bfefaSAndrei Emeltchenko u8 local_amp_id = chan->local_amp_id; 5045fffadc08SAndrei Emeltchenko u8 remote_amp_id = chan->remote_amp_id; 5046770bfefaSAndrei Emeltchenko 50478eb200bdSMat Martineau BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d", 50488eb200bdSMat Martineau chan, result, local_amp_id, remote_amp_id); 50498eb200bdSMat Martineau 50508eb200bdSMat Martineau if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) { 50518eb200bdSMat Martineau l2cap_chan_unlock(chan); 50528eb200bdSMat Martineau return; 50538eb200bdSMat Martineau } 50548eb200bdSMat Martineau 50558eb200bdSMat Martineau if (chan->state != BT_CONNECTED) { 50568eb200bdSMat Martineau l2cap_do_create(chan, result, local_amp_id, remote_amp_id); 50578eb200bdSMat Martineau } else if (result != L2CAP_MR_SUCCESS) { 50588eb200bdSMat Martineau l2cap_do_move_cancel(chan, result); 50598eb200bdSMat Martineau } else { 50608eb200bdSMat Martineau switch (chan->move_role) { 50618eb200bdSMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 50628eb200bdSMat Martineau l2cap_do_move_initiate(chan, local_amp_id, 50638eb200bdSMat Martineau remote_amp_id); 50648eb200bdSMat Martineau break; 50658eb200bdSMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 50668eb200bdSMat Martineau l2cap_do_move_respond(chan, result); 50678eb200bdSMat Martineau break; 50688eb200bdSMat Martineau default: 50698eb200bdSMat Martineau l2cap_do_move_cancel(chan, result); 50708eb200bdSMat Martineau break; 50718eb200bdSMat Martineau } 50728eb200bdSMat Martineau } 50738eb200bdSMat Martineau } 50748eb200bdSMat Martineau 50758d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn, 5076ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5077ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 50788d5a04a1SMat Martineau { 50798d5a04a1SMat Martineau struct l2cap_move_chan_req *req = data; 50801500109bSMat Martineau struct l2cap_move_chan_rsp rsp; 508102b0fbb9SMat Martineau struct l2cap_chan *chan; 50828d5a04a1SMat Martineau u16 icid = 0; 50838d5a04a1SMat Martineau u16 result = L2CAP_MR_NOT_ALLOWED; 50848d5a04a1SMat Martineau 50858d5a04a1SMat Martineau if (cmd_len != sizeof(*req)) 50868d5a04a1SMat Martineau return -EPROTO; 50878d5a04a1SMat Martineau 50888d5a04a1SMat Martineau icid = le16_to_cpu(req->icid); 50898d5a04a1SMat Martineau 5090ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id); 50918d5a04a1SMat Martineau 5092848566b3SMarcel Holtmann if (!conn->hs_enabled) 50938d5a04a1SMat Martineau return -EINVAL; 50948d5a04a1SMat Martineau 509502b0fbb9SMat Martineau chan = l2cap_get_chan_by_dcid(conn, icid); 509602b0fbb9SMat Martineau if (!chan) { 50971500109bSMat Martineau rsp.icid = cpu_to_le16(icid); 50981500109bSMat Martineau rsp.result = __constant_cpu_to_le16(L2CAP_MR_NOT_ALLOWED); 50991500109bSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP, 51001500109bSMat Martineau sizeof(rsp), &rsp); 510102b0fbb9SMat Martineau return 0; 510202b0fbb9SMat Martineau } 510302b0fbb9SMat Martineau 51041500109bSMat Martineau chan->ident = cmd->ident; 51051500109bSMat Martineau 510602b0fbb9SMat Martineau if (chan->scid < L2CAP_CID_DYN_START || 510702b0fbb9SMat Martineau chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY || 510802b0fbb9SMat Martineau (chan->mode != L2CAP_MODE_ERTM && 510902b0fbb9SMat Martineau chan->mode != L2CAP_MODE_STREAMING)) { 511002b0fbb9SMat Martineau result = L2CAP_MR_NOT_ALLOWED; 511102b0fbb9SMat Martineau goto send_move_response; 511202b0fbb9SMat Martineau } 511302b0fbb9SMat Martineau 511402b0fbb9SMat Martineau if (chan->local_amp_id == req->dest_amp_id) { 511502b0fbb9SMat Martineau result = L2CAP_MR_SAME_ID; 511602b0fbb9SMat Martineau goto send_move_response; 511702b0fbb9SMat Martineau } 511802b0fbb9SMat Martineau 51196ed971caSMarcel Holtmann if (req->dest_amp_id != AMP_ID_BREDR) { 512002b0fbb9SMat Martineau struct hci_dev *hdev; 512102b0fbb9SMat Martineau hdev = hci_dev_get(req->dest_amp_id); 512202b0fbb9SMat Martineau if (!hdev || hdev->dev_type != HCI_AMP || 512302b0fbb9SMat Martineau !test_bit(HCI_UP, &hdev->flags)) { 512402b0fbb9SMat Martineau if (hdev) 512502b0fbb9SMat Martineau hci_dev_put(hdev); 512602b0fbb9SMat Martineau 512702b0fbb9SMat Martineau result = L2CAP_MR_BAD_ID; 512802b0fbb9SMat Martineau goto send_move_response; 512902b0fbb9SMat Martineau } 513002b0fbb9SMat Martineau hci_dev_put(hdev); 513102b0fbb9SMat Martineau } 513202b0fbb9SMat Martineau 513302b0fbb9SMat Martineau /* Detect a move collision. Only send a collision response 513402b0fbb9SMat Martineau * if this side has "lost", otherwise proceed with the move. 513502b0fbb9SMat Martineau * The winner has the larger bd_addr. 513602b0fbb9SMat Martineau */ 513702b0fbb9SMat Martineau if ((__chan_is_moving(chan) || 513802b0fbb9SMat Martineau chan->move_role != L2CAP_MOVE_ROLE_NONE) && 51396f59b904SMarcel Holtmann bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) { 514002b0fbb9SMat Martineau result = L2CAP_MR_COLLISION; 514102b0fbb9SMat Martineau goto send_move_response; 514202b0fbb9SMat Martineau } 514302b0fbb9SMat Martineau 514402b0fbb9SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; 514502b0fbb9SMat Martineau l2cap_move_setup(chan); 514602b0fbb9SMat Martineau chan->move_id = req->dest_amp_id; 514702b0fbb9SMat Martineau icid = chan->dcid; 514802b0fbb9SMat Martineau 51496ed971caSMarcel Holtmann if (req->dest_amp_id == AMP_ID_BREDR) { 515002b0fbb9SMat Martineau /* Moving to BR/EDR */ 515102b0fbb9SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 515202b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 515302b0fbb9SMat Martineau result = L2CAP_MR_PEND; 515402b0fbb9SMat Martineau } else { 515502b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 515602b0fbb9SMat Martineau result = L2CAP_MR_SUCCESS; 515702b0fbb9SMat Martineau } 515802b0fbb9SMat Martineau } else { 515902b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_PREPARE; 516002b0fbb9SMat Martineau /* Placeholder - uncomment when amp functions are available */ 516102b0fbb9SMat Martineau /*amp_accept_physical(chan, req->dest_amp_id);*/ 516202b0fbb9SMat Martineau result = L2CAP_MR_PEND; 516302b0fbb9SMat Martineau } 516402b0fbb9SMat Martineau 516502b0fbb9SMat Martineau send_move_response: 51661500109bSMat Martineau l2cap_send_move_chan_rsp(chan, result); 51678d5a04a1SMat Martineau 516802b0fbb9SMat Martineau l2cap_chan_unlock(chan); 516902b0fbb9SMat Martineau 51708d5a04a1SMat Martineau return 0; 51718d5a04a1SMat Martineau } 51728d5a04a1SMat Martineau 51735b155ef9SMat Martineau static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result) 51745b155ef9SMat Martineau { 51755b155ef9SMat Martineau struct l2cap_chan *chan; 51765b155ef9SMat Martineau struct hci_chan *hchan = NULL; 51775b155ef9SMat Martineau 51785b155ef9SMat Martineau chan = l2cap_get_chan_by_scid(conn, icid); 51795b155ef9SMat Martineau if (!chan) { 51805b155ef9SMat Martineau l2cap_send_move_chan_cfm_icid(conn, icid); 51815b155ef9SMat Martineau return; 51825b155ef9SMat Martineau } 51835b155ef9SMat Martineau 51845b155ef9SMat Martineau __clear_chan_timer(chan); 51855b155ef9SMat Martineau if (result == L2CAP_MR_PEND) 51865b155ef9SMat Martineau __set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT); 51875b155ef9SMat Martineau 51885b155ef9SMat Martineau switch (chan->move_state) { 51895b155ef9SMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_COMP: 51905b155ef9SMat Martineau /* Move confirm will be sent when logical link 51915b155ef9SMat Martineau * is complete. 51925b155ef9SMat Martineau */ 51935b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 51945b155ef9SMat Martineau break; 51955b155ef9SMat Martineau case L2CAP_MOVE_WAIT_RSP_SUCCESS: 51965b155ef9SMat Martineau if (result == L2CAP_MR_PEND) { 51975b155ef9SMat Martineau break; 51985b155ef9SMat Martineau } else if (test_bit(CONN_LOCAL_BUSY, 51995b155ef9SMat Martineau &chan->conn_state)) { 52005b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 52015b155ef9SMat Martineau } else { 52025b155ef9SMat Martineau /* Logical link is up or moving to BR/EDR, 52035b155ef9SMat Martineau * proceed with move 52045b155ef9SMat Martineau */ 52055b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; 52065b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 52075b155ef9SMat Martineau } 52085b155ef9SMat Martineau break; 52095b155ef9SMat Martineau case L2CAP_MOVE_WAIT_RSP: 52105b155ef9SMat Martineau /* Moving to AMP */ 52115b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS) { 52125b155ef9SMat Martineau /* Remote is ready, send confirm immediately 52135b155ef9SMat Martineau * after logical link is ready 52145b155ef9SMat Martineau */ 52155b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 52165b155ef9SMat Martineau } else { 52175b155ef9SMat Martineau /* Both logical link and move success 52185b155ef9SMat Martineau * are required to confirm 52195b155ef9SMat Martineau */ 52205b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP; 52215b155ef9SMat Martineau } 52225b155ef9SMat Martineau 52235b155ef9SMat Martineau /* Placeholder - get hci_chan for logical link */ 52245b155ef9SMat Martineau if (!hchan) { 52255b155ef9SMat Martineau /* Logical link not available */ 52265b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 52275b155ef9SMat Martineau break; 52285b155ef9SMat Martineau } 52295b155ef9SMat Martineau 52305b155ef9SMat Martineau /* If the logical link is not yet connected, do not 52315b155ef9SMat Martineau * send confirmation. 52325b155ef9SMat Martineau */ 52335b155ef9SMat Martineau if (hchan->state != BT_CONNECTED) 52345b155ef9SMat Martineau break; 52355b155ef9SMat Martineau 52365b155ef9SMat Martineau /* Logical link is already ready to go */ 52375b155ef9SMat Martineau 52385b155ef9SMat Martineau chan->hs_hcon = hchan->conn; 52395b155ef9SMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 52405b155ef9SMat Martineau 52415b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS) { 52425b155ef9SMat Martineau /* Can confirm now */ 52435b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 52445b155ef9SMat Martineau } else { 52455b155ef9SMat Martineau /* Now only need move success 52465b155ef9SMat Martineau * to confirm 52475b155ef9SMat Martineau */ 52485b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 52495b155ef9SMat Martineau } 52505b155ef9SMat Martineau 52515b155ef9SMat Martineau l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); 52525b155ef9SMat Martineau break; 52535b155ef9SMat Martineau default: 52545b155ef9SMat Martineau /* Any other amp move state means the move failed. */ 52555b155ef9SMat Martineau chan->move_id = chan->local_amp_id; 52565b155ef9SMat Martineau l2cap_move_done(chan); 52575b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 52585b155ef9SMat Martineau } 52595b155ef9SMat Martineau 52605b155ef9SMat Martineau l2cap_chan_unlock(chan); 52615b155ef9SMat Martineau } 52625b155ef9SMat Martineau 52635b155ef9SMat Martineau static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid, 52645b155ef9SMat Martineau u16 result) 52655b155ef9SMat Martineau { 52665b155ef9SMat Martineau struct l2cap_chan *chan; 52675b155ef9SMat Martineau 52685b155ef9SMat Martineau chan = l2cap_get_chan_by_ident(conn, ident); 52695b155ef9SMat Martineau if (!chan) { 52705b155ef9SMat Martineau /* Could not locate channel, icid is best guess */ 52715b155ef9SMat Martineau l2cap_send_move_chan_cfm_icid(conn, icid); 52725b155ef9SMat Martineau return; 52735b155ef9SMat Martineau } 52745b155ef9SMat Martineau 52755b155ef9SMat Martineau __clear_chan_timer(chan); 52765b155ef9SMat Martineau 52775b155ef9SMat Martineau if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { 52785b155ef9SMat Martineau if (result == L2CAP_MR_COLLISION) { 52795b155ef9SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; 52805b155ef9SMat Martineau } else { 52815b155ef9SMat Martineau /* Cleanup - cancel move */ 52825b155ef9SMat Martineau chan->move_id = chan->local_amp_id; 52835b155ef9SMat Martineau l2cap_move_done(chan); 52845b155ef9SMat Martineau } 52855b155ef9SMat Martineau } 52865b155ef9SMat Martineau 52875b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 52885b155ef9SMat Martineau 52895b155ef9SMat Martineau l2cap_chan_unlock(chan); 52905b155ef9SMat Martineau } 52915b155ef9SMat Martineau 52925b155ef9SMat Martineau static int l2cap_move_channel_rsp(struct l2cap_conn *conn, 5293ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5294ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 52958d5a04a1SMat Martineau { 52968d5a04a1SMat Martineau struct l2cap_move_chan_rsp *rsp = data; 52978d5a04a1SMat Martineau u16 icid, result; 52988d5a04a1SMat Martineau 52998d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 53008d5a04a1SMat Martineau return -EPROTO; 53018d5a04a1SMat Martineau 53028d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 53038d5a04a1SMat Martineau result = le16_to_cpu(rsp->result); 53048d5a04a1SMat Martineau 5305ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 53068d5a04a1SMat Martineau 53075b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND) 53085b155ef9SMat Martineau l2cap_move_continue(conn, icid, result); 53095b155ef9SMat Martineau else 53105b155ef9SMat Martineau l2cap_move_fail(conn, cmd->ident, icid, result); 53118d5a04a1SMat Martineau 53128d5a04a1SMat Martineau return 0; 53138d5a04a1SMat Martineau } 53148d5a04a1SMat Martineau 53155f3847a4SMat Martineau static int l2cap_move_channel_confirm(struct l2cap_conn *conn, 5316ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5317ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 53188d5a04a1SMat Martineau { 53198d5a04a1SMat Martineau struct l2cap_move_chan_cfm *cfm = data; 53205f3847a4SMat Martineau struct l2cap_chan *chan; 53218d5a04a1SMat Martineau u16 icid, result; 53228d5a04a1SMat Martineau 53238d5a04a1SMat Martineau if (cmd_len != sizeof(*cfm)) 53248d5a04a1SMat Martineau return -EPROTO; 53258d5a04a1SMat Martineau 53268d5a04a1SMat Martineau icid = le16_to_cpu(cfm->icid); 53278d5a04a1SMat Martineau result = le16_to_cpu(cfm->result); 53288d5a04a1SMat Martineau 5329ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 53308d5a04a1SMat Martineau 53315f3847a4SMat Martineau chan = l2cap_get_chan_by_dcid(conn, icid); 53325f3847a4SMat Martineau if (!chan) { 53335f3847a4SMat Martineau /* Spec requires a response even if the icid was not found */ 53348d5a04a1SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 53355f3847a4SMat Martineau return 0; 53365f3847a4SMat Martineau } 53375f3847a4SMat Martineau 53385f3847a4SMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) { 53395f3847a4SMat Martineau if (result == L2CAP_MC_CONFIRMED) { 53405f3847a4SMat Martineau chan->local_amp_id = chan->move_id; 53416ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR) 53425f3847a4SMat Martineau __release_logical_link(chan); 53435f3847a4SMat Martineau } else { 53445f3847a4SMat Martineau chan->move_id = chan->local_amp_id; 53455f3847a4SMat Martineau } 53465f3847a4SMat Martineau 53475f3847a4SMat Martineau l2cap_move_done(chan); 53485f3847a4SMat Martineau } 53495f3847a4SMat Martineau 53505f3847a4SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 53515f3847a4SMat Martineau 53525f3847a4SMat Martineau l2cap_chan_unlock(chan); 53538d5a04a1SMat Martineau 53548d5a04a1SMat Martineau return 0; 53558d5a04a1SMat Martineau } 53568d5a04a1SMat Martineau 53578d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, 5358ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5359ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 53608d5a04a1SMat Martineau { 53618d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp *rsp = data; 53623fd71a0aSMat Martineau struct l2cap_chan *chan; 53638d5a04a1SMat Martineau u16 icid; 53648d5a04a1SMat Martineau 53658d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 53668d5a04a1SMat Martineau return -EPROTO; 53678d5a04a1SMat Martineau 53688d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 53698d5a04a1SMat Martineau 5370ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 53718d5a04a1SMat Martineau 53723fd71a0aSMat Martineau chan = l2cap_get_chan_by_scid(conn, icid); 53733fd71a0aSMat Martineau if (!chan) 53743fd71a0aSMat Martineau return 0; 53753fd71a0aSMat Martineau 53763fd71a0aSMat Martineau __clear_chan_timer(chan); 53773fd71a0aSMat Martineau 53783fd71a0aSMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) { 53793fd71a0aSMat Martineau chan->local_amp_id = chan->move_id; 53803fd71a0aSMat Martineau 53816ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan) 53823fd71a0aSMat Martineau __release_logical_link(chan); 53833fd71a0aSMat Martineau 53843fd71a0aSMat Martineau l2cap_move_done(chan); 53853fd71a0aSMat Martineau } 53863fd71a0aSMat Martineau 53873fd71a0aSMat Martineau l2cap_chan_unlock(chan); 53883fd71a0aSMat Martineau 53898d5a04a1SMat Martineau return 0; 53908d5a04a1SMat Martineau } 53918d5a04a1SMat Martineau 5392e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency, 5393de73115aSClaudio Takahasi u16 to_multiplier) 5394de73115aSClaudio Takahasi { 5395de73115aSClaudio Takahasi u16 max_latency; 5396de73115aSClaudio Takahasi 5397de73115aSClaudio Takahasi if (min > max || min < 6 || max > 3200) 5398de73115aSClaudio Takahasi return -EINVAL; 5399de73115aSClaudio Takahasi 5400de73115aSClaudio Takahasi if (to_multiplier < 10 || to_multiplier > 3200) 5401de73115aSClaudio Takahasi return -EINVAL; 5402de73115aSClaudio Takahasi 5403de73115aSClaudio Takahasi if (max >= to_multiplier * 8) 5404de73115aSClaudio Takahasi return -EINVAL; 5405de73115aSClaudio Takahasi 5406de73115aSClaudio Takahasi max_latency = (to_multiplier * 8 / max) - 1; 5407de73115aSClaudio Takahasi if (latency > 499 || latency > max_latency) 5408de73115aSClaudio Takahasi return -EINVAL; 5409de73115aSClaudio Takahasi 5410de73115aSClaudio Takahasi return 0; 5411de73115aSClaudio Takahasi } 5412de73115aSClaudio Takahasi 5413de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, 54142d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, 5415203e639eSJohan Hedberg u16 cmd_len, u8 *data) 5416de73115aSClaudio Takahasi { 5417de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon; 5418de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req; 5419de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp; 5420203e639eSJohan Hedberg u16 min, max, latency, to_multiplier; 54212ce603ebSClaudio Takahasi int err; 5422de73115aSClaudio Takahasi 5423de73115aSClaudio Takahasi if (!(hcon->link_mode & HCI_LM_MASTER)) 5424de73115aSClaudio Takahasi return -EINVAL; 5425de73115aSClaudio Takahasi 5426de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) 5427de73115aSClaudio Takahasi return -EPROTO; 5428de73115aSClaudio Takahasi 5429de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data; 5430de73115aSClaudio Takahasi min = __le16_to_cpu(req->min); 5431de73115aSClaudio Takahasi max = __le16_to_cpu(req->max); 5432de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency); 5433de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier); 5434de73115aSClaudio Takahasi 5435de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", 5436de73115aSClaudio Takahasi min, max, latency, to_multiplier); 5437de73115aSClaudio Takahasi 5438de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp)); 54392ce603ebSClaudio Takahasi 54402ce603ebSClaudio Takahasi err = l2cap_check_conn_param(min, max, latency, to_multiplier); 54412ce603ebSClaudio Takahasi if (err) 5442ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); 5443de73115aSClaudio Takahasi else 5444ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); 5445de73115aSClaudio Takahasi 5446de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, 5447de73115aSClaudio Takahasi sizeof(rsp), &rsp); 5448de73115aSClaudio Takahasi 54492ce603ebSClaudio Takahasi if (!err) 54502ce603ebSClaudio Takahasi hci_le_conn_update(hcon, min, max, latency, to_multiplier); 54512ce603ebSClaudio Takahasi 5452de73115aSClaudio Takahasi return 0; 5453de73115aSClaudio Takahasi } 5454de73115aSClaudio Takahasi 5455f1496deeSJohan Hedberg static int l2cap_le_connect_rsp(struct l2cap_conn *conn, 5456f1496deeSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5457f1496deeSJohan Hedberg u8 *data) 5458f1496deeSJohan Hedberg { 5459f1496deeSJohan Hedberg struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data; 5460f1496deeSJohan Hedberg u16 dcid, mtu, mps, credits, result; 5461f1496deeSJohan Hedberg struct l2cap_chan *chan; 5462f1496deeSJohan Hedberg int err; 5463f1496deeSJohan Hedberg 5464f1496deeSJohan Hedberg if (cmd_len < sizeof(*rsp)) 5465f1496deeSJohan Hedberg return -EPROTO; 5466f1496deeSJohan Hedberg 5467f1496deeSJohan Hedberg dcid = __le16_to_cpu(rsp->dcid); 5468f1496deeSJohan Hedberg mtu = __le16_to_cpu(rsp->mtu); 5469f1496deeSJohan Hedberg mps = __le16_to_cpu(rsp->mps); 5470f1496deeSJohan Hedberg credits = __le16_to_cpu(rsp->credits); 5471f1496deeSJohan Hedberg result = __le16_to_cpu(rsp->result); 5472f1496deeSJohan Hedberg 5473f1496deeSJohan Hedberg if (result == L2CAP_CR_SUCCESS && (mtu < 23 || mps < 23)) 5474f1496deeSJohan Hedberg return -EPROTO; 5475f1496deeSJohan Hedberg 5476f1496deeSJohan Hedberg BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x", 5477f1496deeSJohan Hedberg dcid, mtu, mps, credits, result); 5478f1496deeSJohan Hedberg 5479f1496deeSJohan Hedberg mutex_lock(&conn->chan_lock); 5480f1496deeSJohan Hedberg 5481f1496deeSJohan Hedberg chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 5482f1496deeSJohan Hedberg if (!chan) { 5483f1496deeSJohan Hedberg err = -EBADSLT; 5484f1496deeSJohan Hedberg goto unlock; 5485f1496deeSJohan Hedberg } 5486f1496deeSJohan Hedberg 5487f1496deeSJohan Hedberg err = 0; 5488f1496deeSJohan Hedberg 5489f1496deeSJohan Hedberg l2cap_chan_lock(chan); 5490f1496deeSJohan Hedberg 5491f1496deeSJohan Hedberg switch (result) { 5492f1496deeSJohan Hedberg case L2CAP_CR_SUCCESS: 5493f1496deeSJohan Hedberg chan->ident = 0; 5494f1496deeSJohan Hedberg chan->dcid = dcid; 5495f1496deeSJohan Hedberg chan->omtu = mtu; 5496f1496deeSJohan Hedberg chan->remote_mps = mps; 54970cd75f7eSJohan Hedberg chan->tx_credits = credits; 5498f1496deeSJohan Hedberg l2cap_chan_ready(chan); 5499f1496deeSJohan Hedberg break; 5500f1496deeSJohan Hedberg 5501f1496deeSJohan Hedberg default: 5502f1496deeSJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED); 5503f1496deeSJohan Hedberg break; 5504f1496deeSJohan Hedberg } 5505f1496deeSJohan Hedberg 5506f1496deeSJohan Hedberg l2cap_chan_unlock(chan); 5507f1496deeSJohan Hedberg 5508f1496deeSJohan Hedberg unlock: 5509f1496deeSJohan Hedberg mutex_unlock(&conn->chan_lock); 5510f1496deeSJohan Hedberg 5511f1496deeSJohan Hedberg return err; 5512f1496deeSJohan Hedberg } 5513f1496deeSJohan Hedberg 55143300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, 55152d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len, 55162d792818SGustavo Padovan u8 *data) 55173300d9a9SClaudio Takahasi { 55183300d9a9SClaudio Takahasi int err = 0; 55193300d9a9SClaudio Takahasi 55203300d9a9SClaudio Takahasi switch (cmd->code) { 55213300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 5522cb3b3152SJohan Hedberg l2cap_command_rej(conn, cmd, cmd_len, data); 55233300d9a9SClaudio Takahasi break; 55243300d9a9SClaudio Takahasi 55253300d9a9SClaudio Takahasi case L2CAP_CONN_REQ: 5526cb3b3152SJohan Hedberg err = l2cap_connect_req(conn, cmd, cmd_len, data); 55273300d9a9SClaudio Takahasi break; 55283300d9a9SClaudio Takahasi 55293300d9a9SClaudio Takahasi case L2CAP_CONN_RSP: 5530f5a2598dSMat Martineau case L2CAP_CREATE_CHAN_RSP: 55319245e737SJohan Hedberg l2cap_connect_create_rsp(conn, cmd, cmd_len, data); 55323300d9a9SClaudio Takahasi break; 55333300d9a9SClaudio Takahasi 55343300d9a9SClaudio Takahasi case L2CAP_CONF_REQ: 55353300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data); 55363300d9a9SClaudio Takahasi break; 55373300d9a9SClaudio Takahasi 55383300d9a9SClaudio Takahasi case L2CAP_CONF_RSP: 55399245e737SJohan Hedberg l2cap_config_rsp(conn, cmd, cmd_len, data); 55403300d9a9SClaudio Takahasi break; 55413300d9a9SClaudio Takahasi 55423300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ: 5543cb3b3152SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data); 55443300d9a9SClaudio Takahasi break; 55453300d9a9SClaudio Takahasi 55463300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP: 55479245e737SJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data); 55483300d9a9SClaudio Takahasi break; 55493300d9a9SClaudio Takahasi 55503300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ: 55513300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data); 55523300d9a9SClaudio Takahasi break; 55533300d9a9SClaudio Takahasi 55543300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP: 55553300d9a9SClaudio Takahasi break; 55563300d9a9SClaudio Takahasi 55573300d9a9SClaudio Takahasi case L2CAP_INFO_REQ: 5558cb3b3152SJohan Hedberg err = l2cap_information_req(conn, cmd, cmd_len, data); 55593300d9a9SClaudio Takahasi break; 55603300d9a9SClaudio Takahasi 55613300d9a9SClaudio Takahasi case L2CAP_INFO_RSP: 55629245e737SJohan Hedberg l2cap_information_rsp(conn, cmd, cmd_len, data); 55633300d9a9SClaudio Takahasi break; 55643300d9a9SClaudio Takahasi 5565f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_REQ: 5566f94ff6ffSMat Martineau err = l2cap_create_channel_req(conn, cmd, cmd_len, data); 5567f94ff6ffSMat Martineau break; 5568f94ff6ffSMat Martineau 55698d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_REQ: 55708d5a04a1SMat Martineau err = l2cap_move_channel_req(conn, cmd, cmd_len, data); 55718d5a04a1SMat Martineau break; 55728d5a04a1SMat Martineau 55738d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_RSP: 55749245e737SJohan Hedberg l2cap_move_channel_rsp(conn, cmd, cmd_len, data); 55758d5a04a1SMat Martineau break; 55768d5a04a1SMat Martineau 55778d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM: 55788d5a04a1SMat Martineau err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data); 55798d5a04a1SMat Martineau break; 55808d5a04a1SMat Martineau 55818d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM_RSP: 55829245e737SJohan Hedberg l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data); 55838d5a04a1SMat Martineau break; 55848d5a04a1SMat Martineau 55853300d9a9SClaudio Takahasi default: 55863300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code); 55873300d9a9SClaudio Takahasi err = -EINVAL; 55883300d9a9SClaudio Takahasi break; 55893300d9a9SClaudio Takahasi } 55903300d9a9SClaudio Takahasi 55913300d9a9SClaudio Takahasi return err; 55923300d9a9SClaudio Takahasi } 55933300d9a9SClaudio Takahasi 559427e2d4c8SJohan Hedberg static int l2cap_le_connect_req(struct l2cap_conn *conn, 559527e2d4c8SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 559627e2d4c8SJohan Hedberg u8 *data) 559727e2d4c8SJohan Hedberg { 559827e2d4c8SJohan Hedberg struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data; 559927e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 560027e2d4c8SJohan Hedberg struct l2cap_chan *chan, *pchan; 56010cd75f7eSJohan Hedberg u16 dcid, scid, credits, mtu, mps; 560227e2d4c8SJohan Hedberg __le16 psm; 560327e2d4c8SJohan Hedberg u8 result; 560427e2d4c8SJohan Hedberg 560527e2d4c8SJohan Hedberg if (cmd_len != sizeof(*req)) 560627e2d4c8SJohan Hedberg return -EPROTO; 560727e2d4c8SJohan Hedberg 560827e2d4c8SJohan Hedberg scid = __le16_to_cpu(req->scid); 560927e2d4c8SJohan Hedberg mtu = __le16_to_cpu(req->mtu); 561027e2d4c8SJohan Hedberg mps = __le16_to_cpu(req->mps); 561127e2d4c8SJohan Hedberg psm = req->psm; 561227e2d4c8SJohan Hedberg dcid = 0; 56130cd75f7eSJohan Hedberg credits = 0; 561427e2d4c8SJohan Hedberg 561527e2d4c8SJohan Hedberg if (mtu < 23 || mps < 23) 561627e2d4c8SJohan Hedberg return -EPROTO; 561727e2d4c8SJohan Hedberg 561827e2d4c8SJohan Hedberg BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm), 561927e2d4c8SJohan Hedberg scid, mtu, mps); 562027e2d4c8SJohan Hedberg 562127e2d4c8SJohan Hedberg /* Check if we have socket listening on psm */ 562227e2d4c8SJohan Hedberg pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 562327e2d4c8SJohan Hedberg &conn->hcon->dst, LE_LINK); 562427e2d4c8SJohan Hedberg if (!pchan) { 562527e2d4c8SJohan Hedberg result = L2CAP_CR_BAD_PSM; 562627e2d4c8SJohan Hedberg chan = NULL; 562727e2d4c8SJohan Hedberg goto response; 562827e2d4c8SJohan Hedberg } 562927e2d4c8SJohan Hedberg 563027e2d4c8SJohan Hedberg mutex_lock(&conn->chan_lock); 563127e2d4c8SJohan Hedberg l2cap_chan_lock(pchan); 563227e2d4c8SJohan Hedberg 563327e2d4c8SJohan Hedberg if (!smp_sufficient_security(conn->hcon, pchan->sec_level)) { 563427e2d4c8SJohan Hedberg result = L2CAP_CR_AUTHENTICATION; 563527e2d4c8SJohan Hedberg chan = NULL; 563627e2d4c8SJohan Hedberg goto response_unlock; 563727e2d4c8SJohan Hedberg } 563827e2d4c8SJohan Hedberg 563927e2d4c8SJohan Hedberg /* Check if we already have channel with that dcid */ 564027e2d4c8SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, scid)) { 564127e2d4c8SJohan Hedberg result = L2CAP_CR_NO_MEM; 564227e2d4c8SJohan Hedberg chan = NULL; 564327e2d4c8SJohan Hedberg goto response_unlock; 564427e2d4c8SJohan Hedberg } 564527e2d4c8SJohan Hedberg 564627e2d4c8SJohan Hedberg chan = pchan->ops->new_connection(pchan); 564727e2d4c8SJohan Hedberg if (!chan) { 564827e2d4c8SJohan Hedberg result = L2CAP_CR_NO_MEM; 564927e2d4c8SJohan Hedberg goto response_unlock; 565027e2d4c8SJohan Hedberg } 565127e2d4c8SJohan Hedberg 565227e2d4c8SJohan Hedberg bacpy(&chan->src, &conn->hcon->src); 565327e2d4c8SJohan Hedberg bacpy(&chan->dst, &conn->hcon->dst); 565427e2d4c8SJohan Hedberg chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type); 565527e2d4c8SJohan Hedberg chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type); 565627e2d4c8SJohan Hedberg chan->psm = psm; 565727e2d4c8SJohan Hedberg chan->dcid = scid; 565827e2d4c8SJohan Hedberg chan->omtu = mtu; 565927e2d4c8SJohan Hedberg chan->remote_mps = mps; 56600cd75f7eSJohan Hedberg chan->tx_credits = __le16_to_cpu(req->credits); 566127e2d4c8SJohan Hedberg 566227e2d4c8SJohan Hedberg __l2cap_chan_add(conn, chan); 566327e2d4c8SJohan Hedberg dcid = chan->scid; 56640cd75f7eSJohan Hedberg credits = chan->rx_credits; 566527e2d4c8SJohan Hedberg 566627e2d4c8SJohan Hedberg __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 566727e2d4c8SJohan Hedberg 566827e2d4c8SJohan Hedberg chan->ident = cmd->ident; 566927e2d4c8SJohan Hedberg 567027e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 567127e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_CONNECT2); 567227e2d4c8SJohan Hedberg result = L2CAP_CR_PEND; 567327e2d4c8SJohan Hedberg chan->ops->defer(chan); 567427e2d4c8SJohan Hedberg } else { 567527e2d4c8SJohan Hedberg l2cap_chan_ready(chan); 567627e2d4c8SJohan Hedberg result = L2CAP_CR_SUCCESS; 567727e2d4c8SJohan Hedberg } 567827e2d4c8SJohan Hedberg 567927e2d4c8SJohan Hedberg response_unlock: 568027e2d4c8SJohan Hedberg l2cap_chan_unlock(pchan); 568127e2d4c8SJohan Hedberg mutex_unlock(&conn->chan_lock); 568227e2d4c8SJohan Hedberg 568327e2d4c8SJohan Hedberg if (result == L2CAP_CR_PEND) 568427e2d4c8SJohan Hedberg return 0; 568527e2d4c8SJohan Hedberg 568627e2d4c8SJohan Hedberg response: 568727e2d4c8SJohan Hedberg if (chan) { 568827e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 56893916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps); 569027e2d4c8SJohan Hedberg } else { 569127e2d4c8SJohan Hedberg rsp.mtu = 0; 569227e2d4c8SJohan Hedberg rsp.mps = 0; 569327e2d4c8SJohan Hedberg } 569427e2d4c8SJohan Hedberg 569527e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(dcid); 56960cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(credits); 569727e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result); 569827e2d4c8SJohan Hedberg 569927e2d4c8SJohan Hedberg l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp); 570027e2d4c8SJohan Hedberg 570127e2d4c8SJohan Hedberg return 0; 570227e2d4c8SJohan Hedberg } 570327e2d4c8SJohan Hedberg 5704fad5fc89SJohan Hedberg static inline int l2cap_le_credits(struct l2cap_conn *conn, 5705fad5fc89SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5706fad5fc89SJohan Hedberg u8 *data) 5707fad5fc89SJohan Hedberg { 5708fad5fc89SJohan Hedberg struct l2cap_le_credits *pkt; 5709fad5fc89SJohan Hedberg struct l2cap_chan *chan; 5710fad5fc89SJohan Hedberg u16 cid, credits; 5711fad5fc89SJohan Hedberg 5712fad5fc89SJohan Hedberg if (cmd_len != sizeof(*pkt)) 5713fad5fc89SJohan Hedberg return -EPROTO; 5714fad5fc89SJohan Hedberg 5715fad5fc89SJohan Hedberg pkt = (struct l2cap_le_credits *) data; 5716fad5fc89SJohan Hedberg cid = __le16_to_cpu(pkt->cid); 5717fad5fc89SJohan Hedberg credits = __le16_to_cpu(pkt->credits); 5718fad5fc89SJohan Hedberg 5719fad5fc89SJohan Hedberg BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits); 5720fad5fc89SJohan Hedberg 5721fad5fc89SJohan Hedberg chan = l2cap_get_chan_by_dcid(conn, cid); 5722fad5fc89SJohan Hedberg if (!chan) 5723fad5fc89SJohan Hedberg return -EBADSLT; 5724fad5fc89SJohan Hedberg 5725fad5fc89SJohan Hedberg chan->tx_credits += credits; 5726fad5fc89SJohan Hedberg 5727fad5fc89SJohan Hedberg while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) { 5728fad5fc89SJohan Hedberg l2cap_do_send(chan, skb_dequeue(&chan->tx_q)); 5729fad5fc89SJohan Hedberg chan->tx_credits--; 5730fad5fc89SJohan Hedberg } 5731fad5fc89SJohan Hedberg 5732fad5fc89SJohan Hedberg if (chan->tx_credits) 5733fad5fc89SJohan Hedberg chan->ops->resume(chan); 5734fad5fc89SJohan Hedberg 5735fad5fc89SJohan Hedberg l2cap_chan_unlock(chan); 5736fad5fc89SJohan Hedberg 5737fad5fc89SJohan Hedberg return 0; 5738fad5fc89SJohan Hedberg } 5739fad5fc89SJohan Hedberg 57403300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, 5741203e639eSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5742203e639eSJohan Hedberg u8 *data) 57433300d9a9SClaudio Takahasi { 5744b5ecba64SJohan Hedberg int err = 0; 5745b5ecba64SJohan Hedberg 57463af8ace6SJohan Hedberg if (!enable_lecoc) { 57473af8ace6SJohan Hedberg switch (cmd->code) { 57483af8ace6SJohan Hedberg case L2CAP_LE_CONN_REQ: 57493af8ace6SJohan Hedberg case L2CAP_LE_CONN_RSP: 57503af8ace6SJohan Hedberg case L2CAP_LE_CREDITS: 57513af8ace6SJohan Hedberg case L2CAP_DISCONN_REQ: 57523af8ace6SJohan Hedberg case L2CAP_DISCONN_RSP: 57533af8ace6SJohan Hedberg return -EINVAL; 57543af8ace6SJohan Hedberg } 57553af8ace6SJohan Hedberg } 57563af8ace6SJohan Hedberg 57573300d9a9SClaudio Takahasi switch (cmd->code) { 57583300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 5759b5ecba64SJohan Hedberg break; 57603300d9a9SClaudio Takahasi 57613300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ: 5762b5ecba64SJohan Hedberg err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data); 5763b5ecba64SJohan Hedberg break; 57643300d9a9SClaudio Takahasi 57653300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP: 5766b5ecba64SJohan Hedberg break; 57673300d9a9SClaudio Takahasi 5768f1496deeSJohan Hedberg case L2CAP_LE_CONN_RSP: 5769f1496deeSJohan Hedberg l2cap_le_connect_rsp(conn, cmd, cmd_len, data); 5770b5ecba64SJohan Hedberg break; 5771f1496deeSJohan Hedberg 577227e2d4c8SJohan Hedberg case L2CAP_LE_CONN_REQ: 5773b5ecba64SJohan Hedberg err = l2cap_le_connect_req(conn, cmd, cmd_len, data); 5774b5ecba64SJohan Hedberg break; 577527e2d4c8SJohan Hedberg 5776fad5fc89SJohan Hedberg case L2CAP_LE_CREDITS: 5777fad5fc89SJohan Hedberg err = l2cap_le_credits(conn, cmd, cmd_len, data); 5778fad5fc89SJohan Hedberg break; 5779fad5fc89SJohan Hedberg 57803defe01aSJohan Hedberg case L2CAP_DISCONN_REQ: 5781b5ecba64SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data); 5782b5ecba64SJohan Hedberg break; 57833defe01aSJohan Hedberg 57843defe01aSJohan Hedberg case L2CAP_DISCONN_RSP: 57853defe01aSJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data); 5786b5ecba64SJohan Hedberg break; 57873defe01aSJohan Hedberg 57883300d9a9SClaudio Takahasi default: 57893300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code); 5790b5ecba64SJohan Hedberg err = -EINVAL; 5791b5ecba64SJohan Hedberg break; 57923300d9a9SClaudio Takahasi } 5793b5ecba64SJohan Hedberg 5794b5ecba64SJohan Hedberg return err; 57953300d9a9SClaudio Takahasi } 57963300d9a9SClaudio Takahasi 5797c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn, 5798c5623556SJohan Hedberg struct sk_buff *skb) 5799c5623556SJohan Hedberg { 580069c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon; 58014f3e219dSMarcel Holtmann struct l2cap_cmd_hdr *cmd; 58024f3e219dSMarcel Holtmann u16 len; 5803c5623556SJohan Hedberg int err; 5804c5623556SJohan Hedberg 580569c4e4e8SJohan Hedberg if (hcon->type != LE_LINK) 58063b166295SMarcel Holtmann goto drop; 580769c4e4e8SJohan Hedberg 58084f3e219dSMarcel Holtmann if (skb->len < L2CAP_CMD_HDR_SIZE) 58094f3e219dSMarcel Holtmann goto drop; 5810c5623556SJohan Hedberg 58114f3e219dSMarcel Holtmann cmd = (void *) skb->data; 58124f3e219dSMarcel Holtmann skb_pull(skb, L2CAP_CMD_HDR_SIZE); 5813c5623556SJohan Hedberg 58144f3e219dSMarcel Holtmann len = le16_to_cpu(cmd->len); 5815c5623556SJohan Hedberg 58164f3e219dSMarcel Holtmann BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident); 58174f3e219dSMarcel Holtmann 58184f3e219dSMarcel Holtmann if (len != skb->len || !cmd->ident) { 5819c5623556SJohan Hedberg BT_DBG("corrupted command"); 58204f3e219dSMarcel Holtmann goto drop; 5821c5623556SJohan Hedberg } 5822c5623556SJohan Hedberg 5823203e639eSJohan Hedberg err = l2cap_le_sig_cmd(conn, cmd, len, skb->data); 5824c5623556SJohan Hedberg if (err) { 5825c5623556SJohan Hedberg struct l2cap_cmd_rej_unk rej; 5826c5623556SJohan Hedberg 5827c5623556SJohan Hedberg BT_ERR("Wrong link type (%d)", err); 5828c5623556SJohan Hedberg 5829a521149aSJohan Hedberg rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 58304f3e219dSMarcel Holtmann l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 5831c5623556SJohan Hedberg sizeof(rej), &rej); 5832c5623556SJohan Hedberg } 5833c5623556SJohan Hedberg 58343b166295SMarcel Holtmann drop: 5835c5623556SJohan Hedberg kfree_skb(skb); 5836c5623556SJohan Hedberg } 5837c5623556SJohan Hedberg 58383300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn, 58393300d9a9SClaudio Takahasi struct sk_buff *skb) 58400a708f8fSGustavo F. Padovan { 584169c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon; 58420a708f8fSGustavo F. Padovan u8 *data = skb->data; 58430a708f8fSGustavo F. Padovan int len = skb->len; 58440a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr cmd; 58453300d9a9SClaudio Takahasi int err; 58460a708f8fSGustavo F. Padovan 58470a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb); 58480a708f8fSGustavo F. Padovan 584969c4e4e8SJohan Hedberg if (hcon->type != ACL_LINK) 58503b166295SMarcel Holtmann goto drop; 585169c4e4e8SJohan Hedberg 58520a708f8fSGustavo F. Padovan while (len >= L2CAP_CMD_HDR_SIZE) { 58530a708f8fSGustavo F. Padovan u16 cmd_len; 58540a708f8fSGustavo F. Padovan memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); 58550a708f8fSGustavo F. Padovan data += L2CAP_CMD_HDR_SIZE; 58560a708f8fSGustavo F. Padovan len -= L2CAP_CMD_HDR_SIZE; 58570a708f8fSGustavo F. Padovan 58580a708f8fSGustavo F. Padovan cmd_len = le16_to_cpu(cmd.len); 58590a708f8fSGustavo F. Padovan 58602d792818SGustavo Padovan BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, 58612d792818SGustavo Padovan cmd.ident); 58620a708f8fSGustavo F. Padovan 58630a708f8fSGustavo F. Padovan if (cmd_len > len || !cmd.ident) { 58640a708f8fSGustavo F. Padovan BT_DBG("corrupted command"); 58650a708f8fSGustavo F. Padovan break; 58660a708f8fSGustavo F. Padovan } 58670a708f8fSGustavo F. Padovan 58683300d9a9SClaudio Takahasi err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data); 58690a708f8fSGustavo F. Padovan if (err) { 5870e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk rej; 58712c6d1a2eSGustavo F. Padovan 58722c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err); 58730a708f8fSGustavo F. Padovan 5874a521149aSJohan Hedberg rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 58752d792818SGustavo Padovan l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, 58762d792818SGustavo Padovan sizeof(rej), &rej); 58770a708f8fSGustavo F. Padovan } 58780a708f8fSGustavo F. Padovan 58790a708f8fSGustavo F. Padovan data += cmd_len; 58800a708f8fSGustavo F. Padovan len -= cmd_len; 58810a708f8fSGustavo F. Padovan } 58820a708f8fSGustavo F. Padovan 58833b166295SMarcel Holtmann drop: 58840a708f8fSGustavo F. Padovan kfree_skb(skb); 58850a708f8fSGustavo F. Padovan } 58860a708f8fSGustavo F. Padovan 588747d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) 58880a708f8fSGustavo F. Padovan { 58890a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs; 5890e4ca6d98SAndrei Emeltchenko int hdr_size; 5891e4ca6d98SAndrei Emeltchenko 5892e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 5893e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE; 5894e4ca6d98SAndrei Emeltchenko else 5895e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE; 58960a708f8fSGustavo F. Padovan 589747d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 589803a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE); 58990a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len); 59000a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); 59010a708f8fSGustavo F. Padovan 59020a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs) 59030a708f8fSGustavo F. Padovan return -EBADMSG; 59040a708f8fSGustavo F. Padovan } 59050a708f8fSGustavo F. Padovan return 0; 59060a708f8fSGustavo F. Padovan } 59070a708f8fSGustavo F. Padovan 59086ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) 59090a708f8fSGustavo F. Padovan { 5910e31f7633SMat Martineau struct l2cap_ctrl control; 59110a708f8fSGustavo F. Padovan 5912e31f7633SMat Martineau BT_DBG("chan %p", chan); 59130a708f8fSGustavo F. Padovan 5914e31f7633SMat Martineau memset(&control, 0, sizeof(control)); 5915e31f7633SMat Martineau control.sframe = 1; 5916e31f7633SMat Martineau control.final = 1; 5917e31f7633SMat Martineau control.reqseq = chan->buffer_seq; 5918e31f7633SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 59190a708f8fSGustavo F. Padovan 5920e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 5921e31f7633SMat Martineau control.super = L2CAP_SUPER_RNR; 5922e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 59230a708f8fSGustavo F. Padovan } 59240a708f8fSGustavo F. Padovan 5925e31f7633SMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 5926e31f7633SMat Martineau chan->unacked_frames > 0) 5927e31f7633SMat Martineau __set_retrans_timer(chan); 59280a708f8fSGustavo F. Padovan 5929e31f7633SMat Martineau /* Send pending iframes */ 5930525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 59310a708f8fSGustavo F. Padovan 5932e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 5933e31f7633SMat Martineau test_bit(CONN_SEND_FBIT, &chan->conn_state)) { 5934e31f7633SMat Martineau /* F-bit wasn't sent in an s-frame or i-frame yet, so 5935e31f7633SMat Martineau * send it now. 5936e31f7633SMat Martineau */ 5937e31f7633SMat Martineau control.super = L2CAP_SUPER_RR; 5938e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 59390a708f8fSGustavo F. Padovan } 59400a708f8fSGustavo F. Padovan } 59410a708f8fSGustavo F. Padovan 59422d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag, 59432d792818SGustavo Padovan struct sk_buff **last_frag) 59440a708f8fSGustavo F. Padovan { 594584084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments 594684084a31SMat Martineau * skb->data_len reflects only data in fragments 594784084a31SMat Martineau */ 594884084a31SMat Martineau if (!skb_has_frag_list(skb)) 594984084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag; 595084084a31SMat Martineau 595184084a31SMat Martineau new_frag->next = NULL; 595284084a31SMat Martineau 595384084a31SMat Martineau (*last_frag)->next = new_frag; 595484084a31SMat Martineau *last_frag = new_frag; 595584084a31SMat Martineau 595684084a31SMat Martineau skb->len += new_frag->len; 595784084a31SMat Martineau skb->data_len += new_frag->len; 595884084a31SMat Martineau skb->truesize += new_frag->truesize; 595984084a31SMat Martineau } 596084084a31SMat Martineau 59614b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, 59624b51dae9SMat Martineau struct l2cap_ctrl *control) 596384084a31SMat Martineau { 596484084a31SMat Martineau int err = -EINVAL; 59650a708f8fSGustavo F. Padovan 59664b51dae9SMat Martineau switch (control->sar) { 59677e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED: 596884084a31SMat Martineau if (chan->sdu) 596984084a31SMat Martineau break; 59700a708f8fSGustavo F. Padovan 597180b98027SGustavo Padovan err = chan->ops->recv(chan, skb); 597284084a31SMat Martineau break; 59730a708f8fSGustavo F. Padovan 59747e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START: 597584084a31SMat Martineau if (chan->sdu) 597684084a31SMat Martineau break; 59770a708f8fSGustavo F. Padovan 59786f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data); 597903a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE); 59800a708f8fSGustavo F. Padovan 598184084a31SMat Martineau if (chan->sdu_len > chan->imtu) { 598284084a31SMat Martineau err = -EMSGSIZE; 598384084a31SMat Martineau break; 598484084a31SMat Martineau } 59850a708f8fSGustavo F. Padovan 598684084a31SMat Martineau if (skb->len >= chan->sdu_len) 598784084a31SMat Martineau break; 598884084a31SMat Martineau 598984084a31SMat Martineau chan->sdu = skb; 599084084a31SMat Martineau chan->sdu_last_frag = skb; 599184084a31SMat Martineau 599284084a31SMat Martineau skb = NULL; 599384084a31SMat Martineau err = 0; 59940a708f8fSGustavo F. Padovan break; 59950a708f8fSGustavo F. Padovan 59967e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE: 59976f61fd47SGustavo F. Padovan if (!chan->sdu) 599884084a31SMat Martineau break; 59990a708f8fSGustavo F. Padovan 600084084a31SMat Martineau append_skb_frag(chan->sdu, skb, 600184084a31SMat Martineau &chan->sdu_last_frag); 600284084a31SMat Martineau skb = NULL; 60030a708f8fSGustavo F. Padovan 600484084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len) 600584084a31SMat Martineau break; 60060a708f8fSGustavo F. Padovan 600784084a31SMat Martineau err = 0; 60080a708f8fSGustavo F. Padovan break; 60090a708f8fSGustavo F. Padovan 60107e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END: 60116f61fd47SGustavo F. Padovan if (!chan->sdu) 601284084a31SMat Martineau break; 60130a708f8fSGustavo F. Padovan 601484084a31SMat Martineau append_skb_frag(chan->sdu, skb, 601584084a31SMat Martineau &chan->sdu_last_frag); 601684084a31SMat Martineau skb = NULL; 60170a708f8fSGustavo F. Padovan 601884084a31SMat Martineau if (chan->sdu->len != chan->sdu_len) 601984084a31SMat Martineau break; 60200a708f8fSGustavo F. Padovan 602180b98027SGustavo Padovan err = chan->ops->recv(chan, chan->sdu); 60220a708f8fSGustavo F. Padovan 602384084a31SMat Martineau if (!err) { 602484084a31SMat Martineau /* Reassembly complete */ 602584084a31SMat Martineau chan->sdu = NULL; 602684084a31SMat Martineau chan->sdu_last_frag = NULL; 602784084a31SMat Martineau chan->sdu_len = 0; 60280a708f8fSGustavo F. Padovan } 60290a708f8fSGustavo F. Padovan break; 60300a708f8fSGustavo F. Padovan } 60310a708f8fSGustavo F. Padovan 603284084a31SMat Martineau if (err) { 60330a708f8fSGustavo F. Padovan kfree_skb(skb); 60346f61fd47SGustavo F. Padovan kfree_skb(chan->sdu); 60356f61fd47SGustavo F. Padovan chan->sdu = NULL; 603684084a31SMat Martineau chan->sdu_last_frag = NULL; 603784084a31SMat Martineau chan->sdu_len = 0; 603884084a31SMat Martineau } 60390a708f8fSGustavo F. Padovan 604084084a31SMat Martineau return err; 60410a708f8fSGustavo F. Padovan } 60420a708f8fSGustavo F. Padovan 604332b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan) 604432b32735SMat Martineau { 604532b32735SMat Martineau /* Placeholder */ 604632b32735SMat Martineau return 0; 604732b32735SMat Martineau } 604832b32735SMat Martineau 6049e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 60500a708f8fSGustavo F. Padovan { 605161aa4f5bSMat Martineau u8 event; 605261aa4f5bSMat Martineau 605361aa4f5bSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 605461aa4f5bSMat Martineau return; 605561aa4f5bSMat Martineau 605661aa4f5bSMat Martineau event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR; 6057401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, event); 60580a708f8fSGustavo F. Padovan } 60590a708f8fSGustavo F. Padovan 6060d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan) 6061d2a7ac5dSMat Martineau { 606263838725SMat Martineau int err = 0; 606363838725SMat Martineau /* Pass sequential frames to l2cap_reassemble_sdu() 606463838725SMat Martineau * until a gap is encountered. 606563838725SMat Martineau */ 606663838725SMat Martineau 606763838725SMat Martineau BT_DBG("chan %p", chan); 606863838725SMat Martineau 606963838725SMat Martineau while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 607063838725SMat Martineau struct sk_buff *skb; 607163838725SMat Martineau BT_DBG("Searching for skb with txseq %d (queue len %d)", 607263838725SMat Martineau chan->buffer_seq, skb_queue_len(&chan->srej_q)); 607363838725SMat Martineau 607463838725SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq); 607563838725SMat Martineau 607663838725SMat Martineau if (!skb) 607763838725SMat Martineau break; 607863838725SMat Martineau 607963838725SMat Martineau skb_unlink(skb, &chan->srej_q); 608063838725SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 608163838725SMat Martineau err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->control); 608263838725SMat Martineau if (err) 608363838725SMat Martineau break; 608463838725SMat Martineau } 608563838725SMat Martineau 608663838725SMat Martineau if (skb_queue_empty(&chan->srej_q)) { 608763838725SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 608863838725SMat Martineau l2cap_send_ack(chan); 608963838725SMat Martineau } 609063838725SMat Martineau 609163838725SMat Martineau return err; 6092d2a7ac5dSMat Martineau } 6093d2a7ac5dSMat Martineau 6094d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan, 6095d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 6096d2a7ac5dSMat Martineau { 6097f80842a8SMat Martineau struct sk_buff *skb; 6098f80842a8SMat Martineau 6099f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 6100f80842a8SMat Martineau 6101f80842a8SMat Martineau if (control->reqseq == chan->next_tx_seq) { 6102f80842a8SMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 61035e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6104f80842a8SMat Martineau return; 6105f80842a8SMat Martineau } 6106f80842a8SMat Martineau 6107f80842a8SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 6108f80842a8SMat Martineau 6109f80842a8SMat Martineau if (skb == NULL) { 6110f80842a8SMat Martineau BT_DBG("Seq %d not available for retransmission", 6111f80842a8SMat Martineau control->reqseq); 6112f80842a8SMat Martineau return; 6113f80842a8SMat Martineau } 6114f80842a8SMat Martineau 6115f80842a8SMat Martineau if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) { 6116f80842a8SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 61175e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6118f80842a8SMat Martineau return; 6119f80842a8SMat Martineau } 6120f80842a8SMat Martineau 6121f80842a8SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6122f80842a8SMat Martineau 6123f80842a8SMat Martineau if (control->poll) { 6124f80842a8SMat Martineau l2cap_pass_to_tx(chan, control); 6125f80842a8SMat Martineau 6126f80842a8SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6127f80842a8SMat Martineau l2cap_retransmit(chan, control); 6128f80842a8SMat Martineau l2cap_ertm_send(chan); 6129f80842a8SMat Martineau 6130f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 6131f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 6132f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 6133f80842a8SMat Martineau } 6134f80842a8SMat Martineau } else { 6135f80842a8SMat Martineau l2cap_pass_to_tx_fbit(chan, control); 6136f80842a8SMat Martineau 6137f80842a8SMat Martineau if (control->final) { 6138f80842a8SMat Martineau if (chan->srej_save_reqseq != control->reqseq || 6139f80842a8SMat Martineau !test_and_clear_bit(CONN_SREJ_ACT, 6140f80842a8SMat Martineau &chan->conn_state)) 6141f80842a8SMat Martineau l2cap_retransmit(chan, control); 6142f80842a8SMat Martineau } else { 6143f80842a8SMat Martineau l2cap_retransmit(chan, control); 6144f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 6145f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 6146f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 6147f80842a8SMat Martineau } 6148f80842a8SMat Martineau } 6149f80842a8SMat Martineau } 6150d2a7ac5dSMat Martineau } 6151d2a7ac5dSMat Martineau 6152d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan, 6153d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 6154d2a7ac5dSMat Martineau { 6155fcd289dfSMat Martineau struct sk_buff *skb; 6156fcd289dfSMat Martineau 6157fcd289dfSMat Martineau BT_DBG("chan %p, control %p", chan, control); 6158fcd289dfSMat Martineau 6159fcd289dfSMat Martineau if (control->reqseq == chan->next_tx_seq) { 6160fcd289dfSMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 61615e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6162fcd289dfSMat Martineau return; 6163fcd289dfSMat Martineau } 6164fcd289dfSMat Martineau 6165fcd289dfSMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 6166fcd289dfSMat Martineau 6167fcd289dfSMat Martineau if (chan->max_tx && skb && 6168fcd289dfSMat Martineau bt_cb(skb)->control.retries >= chan->max_tx) { 6169fcd289dfSMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 61705e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6171fcd289dfSMat Martineau return; 6172fcd289dfSMat Martineau } 6173fcd289dfSMat Martineau 6174fcd289dfSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6175fcd289dfSMat Martineau 6176fcd289dfSMat Martineau l2cap_pass_to_tx(chan, control); 6177fcd289dfSMat Martineau 6178fcd289dfSMat Martineau if (control->final) { 6179fcd289dfSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 6180fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 6181fcd289dfSMat Martineau } else { 6182fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 6183fcd289dfSMat Martineau l2cap_ertm_send(chan); 6184fcd289dfSMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) 6185fcd289dfSMat Martineau set_bit(CONN_REJ_ACT, &chan->conn_state); 6186fcd289dfSMat Martineau } 6187d2a7ac5dSMat Martineau } 6188d2a7ac5dSMat Martineau 61894b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) 61904b51dae9SMat Martineau { 61914b51dae9SMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 61924b51dae9SMat Martineau 61934b51dae9SMat Martineau BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq, 61944b51dae9SMat Martineau chan->expected_tx_seq); 61954b51dae9SMat Martineau 61964b51dae9SMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 61974b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 61984b51dae9SMat Martineau chan->tx_win) { 61994b51dae9SMat Martineau /* See notes below regarding "double poll" and 62004b51dae9SMat Martineau * invalid packets. 62014b51dae9SMat Martineau */ 62024b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 62034b51dae9SMat Martineau BT_DBG("Invalid/Ignore - after SREJ"); 62044b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 62054b51dae9SMat Martineau } else { 62064b51dae9SMat Martineau BT_DBG("Invalid - in window after SREJ sent"); 62074b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 62084b51dae9SMat Martineau } 62094b51dae9SMat Martineau } 62104b51dae9SMat Martineau 62114b51dae9SMat Martineau if (chan->srej_list.head == txseq) { 62124b51dae9SMat Martineau BT_DBG("Expected SREJ"); 62134b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED_SREJ; 62144b51dae9SMat Martineau } 62154b51dae9SMat Martineau 62164b51dae9SMat Martineau if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) { 62174b51dae9SMat Martineau BT_DBG("Duplicate SREJ - txseq already stored"); 62184b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE_SREJ; 62194b51dae9SMat Martineau } 62204b51dae9SMat Martineau 62214b51dae9SMat Martineau if (l2cap_seq_list_contains(&chan->srej_list, txseq)) { 62224b51dae9SMat Martineau BT_DBG("Unexpected SREJ - not requested"); 62234b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED_SREJ; 62244b51dae9SMat Martineau } 62254b51dae9SMat Martineau } 62264b51dae9SMat Martineau 62274b51dae9SMat Martineau if (chan->expected_tx_seq == txseq) { 62284b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 62294b51dae9SMat Martineau chan->tx_win) { 62304b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 62314b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 62324b51dae9SMat Martineau } else { 62334b51dae9SMat Martineau BT_DBG("Expected"); 62344b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED; 62354b51dae9SMat Martineau } 62364b51dae9SMat Martineau } 62374b51dae9SMat Martineau 62384b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) < 62392d792818SGustavo Padovan __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) { 62404b51dae9SMat Martineau BT_DBG("Duplicate - expected_tx_seq later than txseq"); 62414b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE; 62424b51dae9SMat Martineau } 62434b51dae9SMat Martineau 62444b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) { 62454b51dae9SMat Martineau /* A source of invalid packets is a "double poll" condition, 62464b51dae9SMat Martineau * where delays cause us to send multiple poll packets. If 62474b51dae9SMat Martineau * the remote stack receives and processes both polls, 62484b51dae9SMat Martineau * sequence numbers can wrap around in such a way that a 62494b51dae9SMat Martineau * resent frame has a sequence number that looks like new data 62504b51dae9SMat Martineau * with a sequence gap. This would trigger an erroneous SREJ 62514b51dae9SMat Martineau * request. 62524b51dae9SMat Martineau * 62534b51dae9SMat Martineau * Fortunately, this is impossible with a tx window that's 62544b51dae9SMat Martineau * less than half of the maximum sequence number, which allows 62554b51dae9SMat Martineau * invalid frames to be safely ignored. 62564b51dae9SMat Martineau * 62574b51dae9SMat Martineau * With tx window sizes greater than half of the tx window 62584b51dae9SMat Martineau * maximum, the frame is invalid and cannot be ignored. This 62594b51dae9SMat Martineau * causes a disconnect. 62604b51dae9SMat Martineau */ 62614b51dae9SMat Martineau 62624b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 62634b51dae9SMat Martineau BT_DBG("Invalid/Ignore - txseq outside tx window"); 62644b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 62654b51dae9SMat Martineau } else { 62664b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 62674b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 62684b51dae9SMat Martineau } 62694b51dae9SMat Martineau } else { 62704b51dae9SMat Martineau BT_DBG("Unexpected - txseq indicates missing frames"); 62714b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED; 62724b51dae9SMat Martineau } 62734b51dae9SMat Martineau } 62744b51dae9SMat Martineau 6275d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan, 6276d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 6277d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 6278d2a7ac5dSMat Martineau { 6279d2a7ac5dSMat Martineau int err = 0; 6280941247f9SPeter Senna Tschudin bool skb_in_use = false; 6281d2a7ac5dSMat Martineau 6282d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 6283d2a7ac5dSMat Martineau event); 6284d2a7ac5dSMat Martineau 6285d2a7ac5dSMat Martineau switch (event) { 6286d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 6287d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, control->txseq)) { 6288d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 6289d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6290d2a7ac5dSMat Martineau 6291d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 6292d2a7ac5dSMat Martineau BT_DBG("Busy, discarding expected seq %d", 6293d2a7ac5dSMat Martineau control->txseq); 6294d2a7ac5dSMat Martineau break; 6295d2a7ac5dSMat Martineau } 6296d2a7ac5dSMat Martineau 6297d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, 6298d2a7ac5dSMat Martineau control->txseq); 6299d2a7ac5dSMat Martineau 6300d2a7ac5dSMat Martineau chan->buffer_seq = chan->expected_tx_seq; 6301941247f9SPeter Senna Tschudin skb_in_use = true; 6302d2a7ac5dSMat Martineau 6303d2a7ac5dSMat Martineau err = l2cap_reassemble_sdu(chan, skb, control); 6304d2a7ac5dSMat Martineau if (err) 6305d2a7ac5dSMat Martineau break; 6306d2a7ac5dSMat Martineau 6307d2a7ac5dSMat Martineau if (control->final) { 6308d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 6309d2a7ac5dSMat Martineau &chan->conn_state)) { 6310d2a7ac5dSMat Martineau control->final = 0; 6311d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6312d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6313d2a7ac5dSMat Martineau } 6314d2a7ac5dSMat Martineau } 6315d2a7ac5dSMat Martineau 6316d2a7ac5dSMat Martineau if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 6317d2a7ac5dSMat Martineau l2cap_send_ack(chan); 6318d2a7ac5dSMat Martineau break; 6319d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 6320d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6321d2a7ac5dSMat Martineau 6322d2a7ac5dSMat Martineau /* Can't issue SREJ frames in the local busy state. 6323d2a7ac5dSMat Martineau * Drop this frame, it will be seen as missing 6324d2a7ac5dSMat Martineau * when local busy is exited. 6325d2a7ac5dSMat Martineau */ 6326d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 6327d2a7ac5dSMat Martineau BT_DBG("Busy, discarding unexpected seq %d", 6328d2a7ac5dSMat Martineau control->txseq); 6329d2a7ac5dSMat Martineau break; 6330d2a7ac5dSMat Martineau } 6331d2a7ac5dSMat Martineau 6332d2a7ac5dSMat Martineau /* There was a gap in the sequence, so an SREJ 6333d2a7ac5dSMat Martineau * must be sent for each missing frame. The 6334d2a7ac5dSMat Martineau * current frame is stored for later use. 6335d2a7ac5dSMat Martineau */ 6336d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6337941247f9SPeter Senna Tschudin skb_in_use = true; 6338d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6339d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6340d2a7ac5dSMat Martineau 6341d2a7ac5dSMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 6342d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 6343d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 6344d2a7ac5dSMat Martineau 6345d2a7ac5dSMat Martineau chan->rx_state = L2CAP_RX_STATE_SREJ_SENT; 6346d2a7ac5dSMat Martineau break; 6347d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 6348d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6349d2a7ac5dSMat Martineau break; 6350d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 6351d2a7ac5dSMat Martineau break; 6352d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 6353d2a7ac5dSMat Martineau default: 63545e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6355d2a7ac5dSMat Martineau break; 6356d2a7ac5dSMat Martineau } 6357d2a7ac5dSMat Martineau break; 6358d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 6359d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6360d2a7ac5dSMat Martineau if (control->final) { 6361d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6362d2a7ac5dSMat Martineau 6363e6a3ee6eSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) && 6364e6a3ee6eSMat Martineau !__chan_is_moving(chan)) { 6365d2a7ac5dSMat Martineau control->final = 0; 6366d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6367d2a7ac5dSMat Martineau } 6368d2a7ac5dSMat Martineau 6369d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6370d2a7ac5dSMat Martineau } else if (control->poll) { 6371d2a7ac5dSMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 6372d2a7ac5dSMat Martineau } else { 6373d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6374d2a7ac5dSMat Martineau &chan->conn_state) && 6375d2a7ac5dSMat Martineau chan->unacked_frames) 6376d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6377d2a7ac5dSMat Martineau 6378d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6379d2a7ac5dSMat Martineau } 6380d2a7ac5dSMat Martineau break; 6381d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 6382d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6383d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6384d2a7ac5dSMat Martineau if (control && control->poll) { 6385d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6386d2a7ac5dSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 6387d2a7ac5dSMat Martineau } 6388d2a7ac5dSMat Martineau __clear_retrans_timer(chan); 6389d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 6390d2a7ac5dSMat Martineau break; 6391d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 6392d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 6393d2a7ac5dSMat Martineau break; 6394d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 6395d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 6396d2a7ac5dSMat Martineau break; 6397d2a7ac5dSMat Martineau default: 6398d2a7ac5dSMat Martineau break; 6399d2a7ac5dSMat Martineau } 6400d2a7ac5dSMat Martineau 6401d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 6402d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 6403d2a7ac5dSMat Martineau kfree_skb(skb); 6404d2a7ac5dSMat Martineau } 6405d2a7ac5dSMat Martineau 6406d2a7ac5dSMat Martineau return err; 6407d2a7ac5dSMat Martineau } 6408d2a7ac5dSMat Martineau 6409d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, 6410d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 6411d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 6412d2a7ac5dSMat Martineau { 6413d2a7ac5dSMat Martineau int err = 0; 6414d2a7ac5dSMat Martineau u16 txseq = control->txseq; 6415941247f9SPeter Senna Tschudin bool skb_in_use = false; 6416d2a7ac5dSMat Martineau 6417d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 6418d2a7ac5dSMat Martineau event); 6419d2a7ac5dSMat Martineau 6420d2a7ac5dSMat Martineau switch (event) { 6421d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 6422d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, txseq)) { 6423d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 6424d2a7ac5dSMat Martineau /* Keep frame for reassembly later */ 6425d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6426d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6427941247f9SPeter Senna Tschudin skb_in_use = true; 6428d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6429d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6430d2a7ac5dSMat Martineau 6431d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 6432d2a7ac5dSMat Martineau break; 6433d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED_SREJ: 6434d2a7ac5dSMat Martineau l2cap_seq_list_pop(&chan->srej_list); 6435d2a7ac5dSMat Martineau 6436d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6437d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6438941247f9SPeter Senna Tschudin skb_in_use = true; 6439d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6440d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6441d2a7ac5dSMat Martineau 6442d2a7ac5dSMat Martineau err = l2cap_rx_queued_iframes(chan); 6443d2a7ac5dSMat Martineau if (err) 6444d2a7ac5dSMat Martineau break; 6445d2a7ac5dSMat Martineau 6446d2a7ac5dSMat Martineau break; 6447d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 6448d2a7ac5dSMat Martineau /* Got a frame that can't be reassembled yet. 6449d2a7ac5dSMat Martineau * Save it for later, and send SREJs to cover 6450d2a7ac5dSMat Martineau * the missing frames. 6451d2a7ac5dSMat Martineau */ 6452d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6453941247f9SPeter Senna Tschudin skb_in_use = true; 6454d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6455d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6456d2a7ac5dSMat Martineau 6457d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6458d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 6459d2a7ac5dSMat Martineau break; 6460d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED_SREJ: 6461d2a7ac5dSMat Martineau /* This frame was requested with an SREJ, but 6462d2a7ac5dSMat Martineau * some expected retransmitted frames are 6463d2a7ac5dSMat Martineau * missing. Request retransmission of missing 6464d2a7ac5dSMat Martineau * SREJ'd frames. 6465d2a7ac5dSMat Martineau */ 6466d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6467941247f9SPeter Senna Tschudin skb_in_use = true; 6468d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6469d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6470d2a7ac5dSMat Martineau 6471d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6472d2a7ac5dSMat Martineau l2cap_send_srej_list(chan, control->txseq); 6473d2a7ac5dSMat Martineau break; 6474d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE_SREJ: 6475d2a7ac5dSMat Martineau /* We've already queued this frame. Drop this copy. */ 6476d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6477d2a7ac5dSMat Martineau break; 6478d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 6479d2a7ac5dSMat Martineau /* Expecting a later sequence number, so this frame 6480d2a7ac5dSMat Martineau * was already received. Ignore it completely. 6481d2a7ac5dSMat Martineau */ 6482d2a7ac5dSMat Martineau break; 6483d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 6484d2a7ac5dSMat Martineau break; 6485d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 6486d2a7ac5dSMat Martineau default: 64875e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6488d2a7ac5dSMat Martineau break; 6489d2a7ac5dSMat Martineau } 6490d2a7ac5dSMat Martineau break; 6491d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 6492d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6493d2a7ac5dSMat Martineau if (control->final) { 6494d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6495d2a7ac5dSMat Martineau 6496d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 6497d2a7ac5dSMat Martineau &chan->conn_state)) { 6498d2a7ac5dSMat Martineau control->final = 0; 6499d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6500d2a7ac5dSMat Martineau } 6501d2a7ac5dSMat Martineau 6502d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6503d2a7ac5dSMat Martineau } else if (control->poll) { 6504d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6505d2a7ac5dSMat Martineau &chan->conn_state) && 6506d2a7ac5dSMat Martineau chan->unacked_frames) { 6507d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6508d2a7ac5dSMat Martineau } 6509d2a7ac5dSMat Martineau 6510d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6511d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 6512d2a7ac5dSMat Martineau } else { 6513d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6514d2a7ac5dSMat Martineau &chan->conn_state) && 6515d2a7ac5dSMat Martineau chan->unacked_frames) 6516d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6517d2a7ac5dSMat Martineau 6518d2a7ac5dSMat Martineau l2cap_send_ack(chan); 6519d2a7ac5dSMat Martineau } 6520d2a7ac5dSMat Martineau break; 6521d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 6522d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6523d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6524d2a7ac5dSMat Martineau if (control->poll) { 6525d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 6526d2a7ac5dSMat Martineau } else { 6527d2a7ac5dSMat Martineau struct l2cap_ctrl rr_control; 6528d2a7ac5dSMat Martineau memset(&rr_control, 0, sizeof(rr_control)); 6529d2a7ac5dSMat Martineau rr_control.sframe = 1; 6530d2a7ac5dSMat Martineau rr_control.super = L2CAP_SUPER_RR; 6531d2a7ac5dSMat Martineau rr_control.reqseq = chan->buffer_seq; 6532d2a7ac5dSMat Martineau l2cap_send_sframe(chan, &rr_control); 6533d2a7ac5dSMat Martineau } 6534d2a7ac5dSMat Martineau 6535d2a7ac5dSMat Martineau break; 6536d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 6537d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 6538d2a7ac5dSMat Martineau break; 6539d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 6540d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 6541d2a7ac5dSMat Martineau break; 6542d2a7ac5dSMat Martineau } 6543d2a7ac5dSMat Martineau 6544d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 6545d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 6546d2a7ac5dSMat Martineau kfree_skb(skb); 6547d2a7ac5dSMat Martineau } 6548d2a7ac5dSMat Martineau 6549d2a7ac5dSMat Martineau return err; 6550d2a7ac5dSMat Martineau } 6551d2a7ac5dSMat Martineau 655232b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan) 655332b32735SMat Martineau { 655432b32735SMat Martineau BT_DBG("chan %p", chan); 655532b32735SMat Martineau 655632b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 655732b32735SMat Martineau 655832b32735SMat Martineau if (chan->hs_hcon) 655932b32735SMat Martineau chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; 656032b32735SMat Martineau else 656132b32735SMat Martineau chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; 656232b32735SMat Martineau 656332b32735SMat Martineau return l2cap_resegment(chan); 656432b32735SMat Martineau } 656532b32735SMat Martineau 656632b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan, 656732b32735SMat Martineau struct l2cap_ctrl *control, 656832b32735SMat Martineau struct sk_buff *skb, u8 event) 656932b32735SMat Martineau { 657032b32735SMat Martineau int err; 657132b32735SMat Martineau 657232b32735SMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 657332b32735SMat Martineau event); 657432b32735SMat Martineau 657532b32735SMat Martineau if (!control->poll) 657632b32735SMat Martineau return -EPROTO; 657732b32735SMat Martineau 657832b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq); 657932b32735SMat Martineau 658032b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q)) 658132b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q); 658232b32735SMat Martineau else 658332b32735SMat Martineau chan->tx_send_head = NULL; 658432b32735SMat Martineau 658532b32735SMat Martineau /* Rewind next_tx_seq to the point expected 658632b32735SMat Martineau * by the receiver. 658732b32735SMat Martineau */ 658832b32735SMat Martineau chan->next_tx_seq = control->reqseq; 658932b32735SMat Martineau chan->unacked_frames = 0; 659032b32735SMat Martineau 659132b32735SMat Martineau err = l2cap_finish_move(chan); 659232b32735SMat Martineau if (err) 659332b32735SMat Martineau return err; 659432b32735SMat Martineau 659532b32735SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 659632b32735SMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 659732b32735SMat Martineau 659832b32735SMat Martineau if (event == L2CAP_EV_RECV_IFRAME) 659932b32735SMat Martineau return -EPROTO; 660032b32735SMat Martineau 660132b32735SMat Martineau return l2cap_rx_state_recv(chan, control, NULL, event); 660232b32735SMat Martineau } 660332b32735SMat Martineau 660432b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan, 660532b32735SMat Martineau struct l2cap_ctrl *control, 660632b32735SMat Martineau struct sk_buff *skb, u8 event) 660732b32735SMat Martineau { 660832b32735SMat Martineau int err; 660932b32735SMat Martineau 661032b32735SMat Martineau if (!control->final) 661132b32735SMat Martineau return -EPROTO; 661232b32735SMat Martineau 661332b32735SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 661432b32735SMat Martineau 661532b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 661632b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq); 661732b32735SMat Martineau 661832b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q)) 661932b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q); 662032b32735SMat Martineau else 662132b32735SMat Martineau chan->tx_send_head = NULL; 662232b32735SMat Martineau 662332b32735SMat Martineau /* Rewind next_tx_seq to the point expected 662432b32735SMat Martineau * by the receiver. 662532b32735SMat Martineau */ 662632b32735SMat Martineau chan->next_tx_seq = control->reqseq; 662732b32735SMat Martineau chan->unacked_frames = 0; 662832b32735SMat Martineau 662932b32735SMat Martineau if (chan->hs_hcon) 663032b32735SMat Martineau chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; 663132b32735SMat Martineau else 663232b32735SMat Martineau chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; 663332b32735SMat Martineau 663432b32735SMat Martineau err = l2cap_resegment(chan); 663532b32735SMat Martineau 663632b32735SMat Martineau if (!err) 663732b32735SMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 663832b32735SMat Martineau 663932b32735SMat Martineau return err; 664032b32735SMat Martineau } 664132b32735SMat Martineau 6642d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq) 6643d2a7ac5dSMat Martineau { 6644d2a7ac5dSMat Martineau /* Make sure reqseq is for a packet that has been sent but not acked */ 6645d2a7ac5dSMat Martineau u16 unacked; 6646d2a7ac5dSMat Martineau 6647d2a7ac5dSMat Martineau unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq); 6648d2a7ac5dSMat Martineau return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked; 6649d2a7ac5dSMat Martineau } 6650d2a7ac5dSMat Martineau 6651cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 6652cec8ab6eSMat Martineau struct sk_buff *skb, u8 event) 66530a708f8fSGustavo F. Padovan { 6654d2a7ac5dSMat Martineau int err = 0; 6655d2a7ac5dSMat Martineau 6656d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan, 6657d2a7ac5dSMat Martineau control, skb, event, chan->rx_state); 6658d2a7ac5dSMat Martineau 6659d2a7ac5dSMat Martineau if (__valid_reqseq(chan, control->reqseq)) { 6660d2a7ac5dSMat Martineau switch (chan->rx_state) { 6661d2a7ac5dSMat Martineau case L2CAP_RX_STATE_RECV: 6662d2a7ac5dSMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 6663d2a7ac5dSMat Martineau break; 6664d2a7ac5dSMat Martineau case L2CAP_RX_STATE_SREJ_SENT: 6665d2a7ac5dSMat Martineau err = l2cap_rx_state_srej_sent(chan, control, skb, 6666d2a7ac5dSMat Martineau event); 6667d2a7ac5dSMat Martineau break; 666832b32735SMat Martineau case L2CAP_RX_STATE_WAIT_P: 666932b32735SMat Martineau err = l2cap_rx_state_wait_p(chan, control, skb, event); 667032b32735SMat Martineau break; 667132b32735SMat Martineau case L2CAP_RX_STATE_WAIT_F: 667232b32735SMat Martineau err = l2cap_rx_state_wait_f(chan, control, skb, event); 667332b32735SMat Martineau break; 6674d2a7ac5dSMat Martineau default: 6675d2a7ac5dSMat Martineau /* shut it down */ 6676d2a7ac5dSMat Martineau break; 6677d2a7ac5dSMat Martineau } 6678d2a7ac5dSMat Martineau } else { 6679d2a7ac5dSMat Martineau BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d", 6680d2a7ac5dSMat Martineau control->reqseq, chan->next_tx_seq, 6681d2a7ac5dSMat Martineau chan->expected_ack_seq); 66825e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6683d2a7ac5dSMat Martineau } 6684d2a7ac5dSMat Martineau 6685d2a7ac5dSMat Martineau return err; 6686cec8ab6eSMat Martineau } 6687cec8ab6eSMat Martineau 6688cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 6689cec8ab6eSMat Martineau struct sk_buff *skb) 6690cec8ab6eSMat Martineau { 66914b51dae9SMat Martineau int err = 0; 66924b51dae9SMat Martineau 66934b51dae9SMat Martineau BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb, 66944b51dae9SMat Martineau chan->rx_state); 66954b51dae9SMat Martineau 66964b51dae9SMat Martineau if (l2cap_classify_txseq(chan, control->txseq) == 66974b51dae9SMat Martineau L2CAP_TXSEQ_EXPECTED) { 66984b51dae9SMat Martineau l2cap_pass_to_tx(chan, control); 66994b51dae9SMat Martineau 67004b51dae9SMat Martineau BT_DBG("buffer_seq %d->%d", chan->buffer_seq, 67014b51dae9SMat Martineau __next_seq(chan, chan->buffer_seq)); 67024b51dae9SMat Martineau 67034b51dae9SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 67044b51dae9SMat Martineau 67054b51dae9SMat Martineau l2cap_reassemble_sdu(chan, skb, control); 67064b51dae9SMat Martineau } else { 67074b51dae9SMat Martineau if (chan->sdu) { 67084b51dae9SMat Martineau kfree_skb(chan->sdu); 67094b51dae9SMat Martineau chan->sdu = NULL; 67104b51dae9SMat Martineau } 67114b51dae9SMat Martineau chan->sdu_last_frag = NULL; 67124b51dae9SMat Martineau chan->sdu_len = 0; 67134b51dae9SMat Martineau 67144b51dae9SMat Martineau if (skb) { 67154b51dae9SMat Martineau BT_DBG("Freeing %p", skb); 67164b51dae9SMat Martineau kfree_skb(skb); 67174b51dae9SMat Martineau } 67184b51dae9SMat Martineau } 67194b51dae9SMat Martineau 67204b51dae9SMat Martineau chan->last_acked_seq = control->txseq; 67214b51dae9SMat Martineau chan->expected_tx_seq = __next_seq(chan, control->txseq); 67224b51dae9SMat Martineau 67234b51dae9SMat Martineau return err; 6724cec8ab6eSMat Martineau } 6725cec8ab6eSMat Martineau 6726cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 6727cec8ab6eSMat Martineau { 6728cec8ab6eSMat Martineau struct l2cap_ctrl *control = &bt_cb(skb)->control; 6729cec8ab6eSMat Martineau u16 len; 6730cec8ab6eSMat Martineau u8 event; 67310a708f8fSGustavo F. Padovan 6732b76bbd66SMat Martineau __unpack_control(chan, skb); 6733b76bbd66SMat Martineau 67340a708f8fSGustavo F. Padovan len = skb->len; 67350a708f8fSGustavo F. Padovan 67360a708f8fSGustavo F. Padovan /* 67370a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here. 67380a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery 6739cec8ab6eSMat Martineau * procedures and ask for retransmission. 67400a708f8fSGustavo F. Padovan */ 674147d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 67420a708f8fSGustavo F. Padovan goto drop; 67430a708f8fSGustavo F. Padovan 6744cec8ab6eSMat Martineau if (!control->sframe && control->sar == L2CAP_SAR_START) 674503a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 67460a708f8fSGustavo F. Padovan 674747d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 674803a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 67490a708f8fSGustavo F. Padovan 675047d1ec61SGustavo F. Padovan if (len > chan->mps) { 67515e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 67520a708f8fSGustavo F. Padovan goto drop; 67530a708f8fSGustavo F. Padovan } 67540a708f8fSGustavo F. Padovan 6755cec8ab6eSMat Martineau if (!control->sframe) { 6756cec8ab6eSMat Martineau int err; 67570a708f8fSGustavo F. Padovan 6758cec8ab6eSMat Martineau BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d", 6759cec8ab6eSMat Martineau control->sar, control->reqseq, control->final, 6760cec8ab6eSMat Martineau control->txseq); 6761836be934SAndrei Emeltchenko 6762cec8ab6eSMat Martineau /* Validate F-bit - F=0 always valid, F=1 only 6763cec8ab6eSMat Martineau * valid in TX WAIT_F 6764cec8ab6eSMat Martineau */ 6765cec8ab6eSMat Martineau if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F) 67660a708f8fSGustavo F. Padovan goto drop; 67670a708f8fSGustavo F. Padovan 6768cec8ab6eSMat Martineau if (chan->mode != L2CAP_MODE_STREAMING) { 6769cec8ab6eSMat Martineau event = L2CAP_EV_RECV_IFRAME; 6770cec8ab6eSMat Martineau err = l2cap_rx(chan, control, skb, event); 67710a708f8fSGustavo F. Padovan } else { 6772cec8ab6eSMat Martineau err = l2cap_stream_rx(chan, control, skb); 6773cec8ab6eSMat Martineau } 6774cec8ab6eSMat Martineau 6775cec8ab6eSMat Martineau if (err) 67765e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6777cec8ab6eSMat Martineau } else { 6778cec8ab6eSMat Martineau const u8 rx_func_to_event[4] = { 6779cec8ab6eSMat Martineau L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ, 6780cec8ab6eSMat Martineau L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ 6781cec8ab6eSMat Martineau }; 6782cec8ab6eSMat Martineau 6783cec8ab6eSMat Martineau /* Only I-frames are expected in streaming mode */ 6784cec8ab6eSMat Martineau if (chan->mode == L2CAP_MODE_STREAMING) 6785cec8ab6eSMat Martineau goto drop; 6786cec8ab6eSMat Martineau 6787cec8ab6eSMat Martineau BT_DBG("sframe reqseq %d, final %d, poll %d, super %d", 6788cec8ab6eSMat Martineau control->reqseq, control->final, control->poll, 6789cec8ab6eSMat Martineau control->super); 6790cec8ab6eSMat Martineau 67910a708f8fSGustavo F. Padovan if (len != 0) { 67921bb166e6SAndrei Emeltchenko BT_ERR("Trailing bytes: %d in sframe", len); 67935e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 67940a708f8fSGustavo F. Padovan goto drop; 67950a708f8fSGustavo F. Padovan } 67960a708f8fSGustavo F. Padovan 6797cec8ab6eSMat Martineau /* Validate F and P bits */ 6798cec8ab6eSMat Martineau if (control->final && (control->poll || 6799cec8ab6eSMat Martineau chan->tx_state != L2CAP_TX_STATE_WAIT_F)) 6800cec8ab6eSMat Martineau goto drop; 6801cec8ab6eSMat Martineau 6802cec8ab6eSMat Martineau event = rx_func_to_event[control->super]; 6803cec8ab6eSMat Martineau if (l2cap_rx(chan, control, skb, event)) 68045e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 68050a708f8fSGustavo F. Padovan } 68060a708f8fSGustavo F. Padovan 68070a708f8fSGustavo F. Padovan return 0; 68080a708f8fSGustavo F. Padovan 68090a708f8fSGustavo F. Padovan drop: 68100a708f8fSGustavo F. Padovan kfree_skb(skb); 68110a708f8fSGustavo F. Padovan return 0; 68120a708f8fSGustavo F. Padovan } 68130a708f8fSGustavo F. Padovan 6814b1c325c2SJohan Hedberg static void l2cap_chan_le_send_credits(struct l2cap_chan *chan) 6815b1c325c2SJohan Hedberg { 6816b1c325c2SJohan Hedberg struct l2cap_conn *conn = chan->conn; 6817b1c325c2SJohan Hedberg struct l2cap_le_credits pkt; 6818b1c325c2SJohan Hedberg u16 return_credits; 6819b1c325c2SJohan Hedberg 6820b1c325c2SJohan Hedberg /* We return more credits to the sender only after the amount of 6821b1c325c2SJohan Hedberg * credits falls below half of the initial amount. 6822b1c325c2SJohan Hedberg */ 6823b1c325c2SJohan Hedberg if (chan->rx_credits >= (L2CAP_LE_MAX_CREDITS + 1) / 2) 6824b1c325c2SJohan Hedberg return; 6825b1c325c2SJohan Hedberg 6826b1c325c2SJohan Hedberg return_credits = L2CAP_LE_MAX_CREDITS - chan->rx_credits; 6827b1c325c2SJohan Hedberg 6828b1c325c2SJohan Hedberg BT_DBG("chan %p returning %u credits to sender", chan, return_credits); 6829b1c325c2SJohan Hedberg 6830b1c325c2SJohan Hedberg chan->rx_credits += return_credits; 6831b1c325c2SJohan Hedberg 6832b1c325c2SJohan Hedberg pkt.cid = cpu_to_le16(chan->scid); 6833b1c325c2SJohan Hedberg pkt.credits = cpu_to_le16(return_credits); 6834b1c325c2SJohan Hedberg 6835b1c325c2SJohan Hedberg chan->ident = l2cap_get_ident(conn); 6836b1c325c2SJohan Hedberg 6837b1c325c2SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt); 6838b1c325c2SJohan Hedberg } 6839b1c325c2SJohan Hedberg 6840fad5fc89SJohan Hedberg static int l2cap_le_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 6841fad5fc89SJohan Hedberg { 6842aac23bf6SJohan Hedberg int err; 6843fad5fc89SJohan Hedberg 6844aac23bf6SJohan Hedberg if (!chan->rx_credits) { 6845aac23bf6SJohan Hedberg BT_ERR("No credits to receive LE L2CAP data"); 6846fad5fc89SJohan Hedberg return -ENOBUFS; 6847aac23bf6SJohan Hedberg } 6848aac23bf6SJohan Hedberg 6849aac23bf6SJohan Hedberg if (chan->imtu < skb->len) { 6850aac23bf6SJohan Hedberg BT_ERR("Too big LE L2CAP PDU"); 6851aac23bf6SJohan Hedberg return -ENOBUFS; 6852aac23bf6SJohan Hedberg } 6853fad5fc89SJohan Hedberg 6854fad5fc89SJohan Hedberg chan->rx_credits--; 6855fad5fc89SJohan Hedberg BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits); 6856fad5fc89SJohan Hedberg 6857fad5fc89SJohan Hedberg l2cap_chan_le_send_credits(chan); 6858fad5fc89SJohan Hedberg 6859aac23bf6SJohan Hedberg err = 0; 6860aac23bf6SJohan Hedberg 6861aac23bf6SJohan Hedberg if (!chan->sdu) { 6862aac23bf6SJohan Hedberg u16 sdu_len; 6863aac23bf6SJohan Hedberg 6864aac23bf6SJohan Hedberg sdu_len = get_unaligned_le16(skb->data); 6865aac23bf6SJohan Hedberg skb_pull(skb, L2CAP_SDULEN_SIZE); 6866aac23bf6SJohan Hedberg 6867aac23bf6SJohan Hedberg BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u", 6868aac23bf6SJohan Hedberg sdu_len, skb->len, chan->imtu); 6869aac23bf6SJohan Hedberg 6870aac23bf6SJohan Hedberg if (sdu_len > chan->imtu) { 6871aac23bf6SJohan Hedberg BT_ERR("Too big LE L2CAP SDU length received"); 6872aac23bf6SJohan Hedberg err = -EMSGSIZE; 6873aac23bf6SJohan Hedberg goto failed; 6874aac23bf6SJohan Hedberg } 6875aac23bf6SJohan Hedberg 6876aac23bf6SJohan Hedberg if (skb->len > sdu_len) { 6877aac23bf6SJohan Hedberg BT_ERR("Too much LE L2CAP data received"); 6878aac23bf6SJohan Hedberg err = -EINVAL; 6879aac23bf6SJohan Hedberg goto failed; 6880aac23bf6SJohan Hedberg } 6881aac23bf6SJohan Hedberg 6882aac23bf6SJohan Hedberg if (skb->len == sdu_len) 6883fad5fc89SJohan Hedberg return chan->ops->recv(chan, skb); 6884aac23bf6SJohan Hedberg 6885aac23bf6SJohan Hedberg chan->sdu = skb; 6886aac23bf6SJohan Hedberg chan->sdu_len = sdu_len; 6887aac23bf6SJohan Hedberg chan->sdu_last_frag = skb; 6888aac23bf6SJohan Hedberg 6889aac23bf6SJohan Hedberg return 0; 6890aac23bf6SJohan Hedberg } 6891aac23bf6SJohan Hedberg 6892aac23bf6SJohan Hedberg BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u", 6893aac23bf6SJohan Hedberg chan->sdu->len, skb->len, chan->sdu_len); 6894aac23bf6SJohan Hedberg 6895aac23bf6SJohan Hedberg if (chan->sdu->len + skb->len > chan->sdu_len) { 6896aac23bf6SJohan Hedberg BT_ERR("Too much LE L2CAP data received"); 6897aac23bf6SJohan Hedberg err = -EINVAL; 6898aac23bf6SJohan Hedberg goto failed; 6899aac23bf6SJohan Hedberg } 6900aac23bf6SJohan Hedberg 6901aac23bf6SJohan Hedberg append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag); 6902aac23bf6SJohan Hedberg skb = NULL; 6903aac23bf6SJohan Hedberg 6904aac23bf6SJohan Hedberg if (chan->sdu->len == chan->sdu_len) { 6905aac23bf6SJohan Hedberg err = chan->ops->recv(chan, chan->sdu); 6906aac23bf6SJohan Hedberg if (!err) { 6907aac23bf6SJohan Hedberg chan->sdu = NULL; 6908aac23bf6SJohan Hedberg chan->sdu_last_frag = NULL; 6909aac23bf6SJohan Hedberg chan->sdu_len = 0; 6910aac23bf6SJohan Hedberg } 6911aac23bf6SJohan Hedberg } 6912aac23bf6SJohan Hedberg 6913aac23bf6SJohan Hedberg failed: 6914aac23bf6SJohan Hedberg if (err) { 6915aac23bf6SJohan Hedberg kfree_skb(skb); 6916aac23bf6SJohan Hedberg kfree_skb(chan->sdu); 6917aac23bf6SJohan Hedberg chan->sdu = NULL; 6918aac23bf6SJohan Hedberg chan->sdu_last_frag = NULL; 6919aac23bf6SJohan Hedberg chan->sdu_len = 0; 6920aac23bf6SJohan Hedberg } 6921aac23bf6SJohan Hedberg 6922aac23bf6SJohan Hedberg /* We can't return an error here since we took care of the skb 6923aac23bf6SJohan Hedberg * freeing internally. An error return would cause the caller to 6924aac23bf6SJohan Hedberg * do a double-free of the skb. 6925aac23bf6SJohan Hedberg */ 6926aac23bf6SJohan Hedberg return 0; 6927fad5fc89SJohan Hedberg } 6928fad5fc89SJohan Hedberg 692913ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid, 693013ca56e0SAndrei Emeltchenko struct sk_buff *skb) 69310a708f8fSGustavo F. Padovan { 693248454079SGustavo F. Padovan struct l2cap_chan *chan; 69330a708f8fSGustavo F. Padovan 6934baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 693548454079SGustavo F. Padovan if (!chan) { 693697e8e89dSAndrei Emeltchenko if (cid == L2CAP_CID_A2MP) { 693797e8e89dSAndrei Emeltchenko chan = a2mp_channel_create(conn, skb); 693897e8e89dSAndrei Emeltchenko if (!chan) { 693997e8e89dSAndrei Emeltchenko kfree_skb(skb); 694013ca56e0SAndrei Emeltchenko return; 694197e8e89dSAndrei Emeltchenko } 694297e8e89dSAndrei Emeltchenko 694397e8e89dSAndrei Emeltchenko l2cap_chan_lock(chan); 694497e8e89dSAndrei Emeltchenko } else { 69450a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid); 69466be36555SAndrei Emeltchenko /* Drop packet and return */ 69473379013bSDan Carpenter kfree_skb(skb); 694813ca56e0SAndrei Emeltchenko return; 69490a708f8fSGustavo F. Padovan } 695097e8e89dSAndrei Emeltchenko } 69510a708f8fSGustavo F. Padovan 695249208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len); 69530a708f8fSGustavo F. Padovan 695489bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 69550a708f8fSGustavo F. Padovan goto drop; 69560a708f8fSGustavo F. Padovan 69570c1bc5c6SGustavo F. Padovan switch (chan->mode) { 695838319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 6959fad5fc89SJohan Hedberg if (l2cap_le_data_rcv(chan, skb) < 0) 6960fad5fc89SJohan Hedberg goto drop; 6961fad5fc89SJohan Hedberg 6962fad5fc89SJohan Hedberg goto done; 6963fad5fc89SJohan Hedberg 69640a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 69650a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here 69660a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable. 69670a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't 69680a708f8fSGustavo F. Padovan * provide flow control mechanism. */ 69690a708f8fSGustavo F. Padovan 69700c1bc5c6SGustavo F. Padovan if (chan->imtu < skb->len) 69710a708f8fSGustavo F. Padovan goto drop; 69720a708f8fSGustavo F. Padovan 697380b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 69740a708f8fSGustavo F. Padovan goto done; 69750a708f8fSGustavo F. Padovan break; 69760a708f8fSGustavo F. Padovan 69770a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 69780a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 6979cec8ab6eSMat Martineau l2cap_data_rcv(chan, skb); 69800a708f8fSGustavo F. Padovan goto done; 69810a708f8fSGustavo F. Padovan 69820a708f8fSGustavo F. Padovan default: 69830c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); 69840a708f8fSGustavo F. Padovan break; 69850a708f8fSGustavo F. Padovan } 69860a708f8fSGustavo F. Padovan 69870a708f8fSGustavo F. Padovan drop: 69880a708f8fSGustavo F. Padovan kfree_skb(skb); 69890a708f8fSGustavo F. Padovan 69900a708f8fSGustavo F. Padovan done: 69916be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 69920a708f8fSGustavo F. Padovan } 69930a708f8fSGustavo F. Padovan 699484104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, 699584104b24SAndrei Emeltchenko struct sk_buff *skb) 69960a708f8fSGustavo F. Padovan { 6997ae4fd2d3SMarcel Holtmann struct hci_conn *hcon = conn->hcon; 699823691d75SGustavo F. Padovan struct l2cap_chan *chan; 69990a708f8fSGustavo F. Padovan 7000ae4fd2d3SMarcel Holtmann if (hcon->type != ACL_LINK) 7001ae4fd2d3SMarcel Holtmann goto drop; 7002ae4fd2d3SMarcel Holtmann 7003bf20fd4eSJohan Hedberg chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst, 7004bf20fd4eSJohan Hedberg ACL_LINK); 700523691d75SGustavo F. Padovan if (!chan) 70060a708f8fSGustavo F. Padovan goto drop; 70070a708f8fSGustavo F. Padovan 70085b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 70090a708f8fSGustavo F. Padovan 701089bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 70110a708f8fSGustavo F. Padovan goto drop; 70120a708f8fSGustavo F. Padovan 7013e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 70140a708f8fSGustavo F. Padovan goto drop; 70150a708f8fSGustavo F. Padovan 70162edf870dSMarcel Holtmann /* Store remote BD_ADDR and PSM for msg_name */ 701706ae3314SMarcel Holtmann bacpy(&bt_cb(skb)->bdaddr, &hcon->dst); 70182edf870dSMarcel Holtmann bt_cb(skb)->psm = psm; 70192edf870dSMarcel Holtmann 702080b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 702184104b24SAndrei Emeltchenko return; 70220a708f8fSGustavo F. Padovan 70230a708f8fSGustavo F. Padovan drop: 70240a708f8fSGustavo F. Padovan kfree_skb(skb); 70250a708f8fSGustavo F. Padovan } 70260a708f8fSGustavo F. Padovan 702772f78356SMarcel Holtmann static void l2cap_att_channel(struct l2cap_conn *conn, 7028d9b88702SAndrei Emeltchenko struct sk_buff *skb) 70299f69bda6SGustavo F. Padovan { 7030b99707d7SMarcel Holtmann struct hci_conn *hcon = conn->hcon; 703123691d75SGustavo F. Padovan struct l2cap_chan *chan; 70329f69bda6SGustavo F. Padovan 7033b99707d7SMarcel Holtmann if (hcon->type != LE_LINK) 7034b99707d7SMarcel Holtmann goto drop; 7035b99707d7SMarcel Holtmann 7036af1c0134SJohan Hedberg chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT, 703706ae3314SMarcel Holtmann &hcon->src, &hcon->dst); 703823691d75SGustavo F. Padovan if (!chan) 70399f69bda6SGustavo F. Padovan goto drop; 70409f69bda6SGustavo F. Padovan 70415b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 70429f69bda6SGustavo F. Padovan 7043cc8dba2bSMarcel Holtmann if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, hcon->dst_type)) 7044cc8dba2bSMarcel Holtmann goto drop; 7045cc8dba2bSMarcel Holtmann 7046e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 70479f69bda6SGustavo F. Padovan goto drop; 70489f69bda6SGustavo F. Padovan 704980b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 70506810fca7SAndrei Emeltchenko return; 70519f69bda6SGustavo F. Padovan 70529f69bda6SGustavo F. Padovan drop: 70539f69bda6SGustavo F. Padovan kfree_skb(skb); 70549f69bda6SGustavo F. Padovan } 70559f69bda6SGustavo F. Padovan 70560a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) 70570a708f8fSGustavo F. Padovan { 70580a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data; 70590a708f8fSGustavo F. Padovan u16 cid, len; 70600a708f8fSGustavo F. Padovan __le16 psm; 70610a708f8fSGustavo F. Padovan 70620a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE); 70630a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid); 70640a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len); 70650a708f8fSGustavo F. Padovan 70660a708f8fSGustavo F. Padovan if (len != skb->len) { 70670a708f8fSGustavo F. Padovan kfree_skb(skb); 70680a708f8fSGustavo F. Padovan return; 70690a708f8fSGustavo F. Padovan } 70700a708f8fSGustavo F. Padovan 70710a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid); 70720a708f8fSGustavo F. Padovan 70730a708f8fSGustavo F. Padovan switch (cid) { 70740a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING: 70750a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb); 70760a708f8fSGustavo F. Padovan break; 70770a708f8fSGustavo F. Padovan 70780a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS: 7079097db76cSAndrei Emeltchenko psm = get_unaligned((__le16 *) skb->data); 70800181a70fSAndrei Emeltchenko skb_pull(skb, L2CAP_PSMLEN_SIZE); 70810a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb); 70820a708f8fSGustavo F. Padovan break; 70830a708f8fSGustavo F. Padovan 7084073d1cf3SJohan Hedberg case L2CAP_CID_ATT: 708572f78356SMarcel Holtmann l2cap_att_channel(conn, skb); 70869f69bda6SGustavo F. Padovan break; 70879f69bda6SGustavo F. Padovan 7088a2877629SMarcel Holtmann case L2CAP_CID_LE_SIGNALING: 7089a2877629SMarcel Holtmann l2cap_le_sig_channel(conn, skb); 7090a2877629SMarcel Holtmann break; 7091a2877629SMarcel Holtmann 7092b501d6a1SAnderson Briglia case L2CAP_CID_SMP: 7093b501d6a1SAnderson Briglia if (smp_sig_channel(conn, skb)) 7094b501d6a1SAnderson Briglia l2cap_conn_del(conn->hcon, EACCES); 7095b501d6a1SAnderson Briglia break; 7096b501d6a1SAnderson Briglia 70970a708f8fSGustavo F. Padovan default: 70980a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb); 70990a708f8fSGustavo F. Padovan break; 71000a708f8fSGustavo F. Padovan } 71010a708f8fSGustavo F. Padovan } 71020a708f8fSGustavo F. Padovan 71030a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */ 71040a708f8fSGustavo F. Padovan 7105686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) 71060a708f8fSGustavo F. Padovan { 71070a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0; 710823691d75SGustavo F. Padovan struct l2cap_chan *c; 71090a708f8fSGustavo F. Padovan 71106ed93dc6SAndrei Emeltchenko BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr); 71110a708f8fSGustavo F. Padovan 71120a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */ 711323691d75SGustavo F. Padovan read_lock(&chan_list_lock); 711423691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 711589bc500eSGustavo F. Padovan if (c->state != BT_LISTEN) 71160a708f8fSGustavo F. Padovan continue; 71170a708f8fSGustavo F. Padovan 71187eafc59eSMarcel Holtmann if (!bacmp(&c->src, &hdev->bdaddr)) { 71190a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT; 712043bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 71210a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER; 71220a708f8fSGustavo F. Padovan exact++; 71237eafc59eSMarcel Holtmann } else if (!bacmp(&c->src, BDADDR_ANY)) { 71240a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT; 712543bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 71260a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER; 71270a708f8fSGustavo F. Padovan } 71280a708f8fSGustavo F. Padovan } 712923691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 71300a708f8fSGustavo F. Padovan 71310a708f8fSGustavo F. Padovan return exact ? lm1 : lm2; 71320a708f8fSGustavo F. Padovan } 71330a708f8fSGustavo F. Padovan 71349e664631SAndrei Emeltchenko void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) 71350a708f8fSGustavo F. Padovan { 71360a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 71370a708f8fSGustavo F. Padovan 71386ed93dc6SAndrei Emeltchenko BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status); 71390a708f8fSGustavo F. Padovan 71400a708f8fSGustavo F. Padovan if (!status) { 7141baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon); 71420a708f8fSGustavo F. Padovan if (conn) 71430a708f8fSGustavo F. Padovan l2cap_conn_ready(conn); 7144ba6fc317SAndrei Emeltchenko } else { 7145e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status)); 7146ba6fc317SAndrei Emeltchenko } 71470a708f8fSGustavo F. Padovan } 71480a708f8fSGustavo F. Padovan 7149686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon) 71500a708f8fSGustavo F. Padovan { 71510a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 71520a708f8fSGustavo F. Padovan 71530a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon); 71540a708f8fSGustavo F. Padovan 7155686ebf28SUlisses Furquim if (!conn) 71569f5a0d7bSAndrei Emeltchenko return HCI_ERROR_REMOTE_USER_TERM; 71570a708f8fSGustavo F. Padovan return conn->disc_reason; 71580a708f8fSGustavo F. Padovan } 71590a708f8fSGustavo F. Padovan 71609e664631SAndrei Emeltchenko void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) 71610a708f8fSGustavo F. Padovan { 71620a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason); 71630a708f8fSGustavo F. Padovan 7164e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason)); 71650a708f8fSGustavo F. Padovan } 71660a708f8fSGustavo F. Padovan 71674343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) 71680a708f8fSGustavo F. Padovan { 7169715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 71700a708f8fSGustavo F. Padovan return; 71710a708f8fSGustavo F. Padovan 71720a708f8fSGustavo F. Padovan if (encrypt == 0x00) { 71734343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) { 7174ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); 71754343478fSGustavo F. Padovan } else if (chan->sec_level == BT_SECURITY_HIGH) 71760f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED); 71770a708f8fSGustavo F. Padovan } else { 71784343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) 7179c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 71800a708f8fSGustavo F. Padovan } 71810a708f8fSGustavo F. Padovan } 71820a708f8fSGustavo F. Padovan 7183686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) 71840a708f8fSGustavo F. Padovan { 71850a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 718648454079SGustavo F. Padovan struct l2cap_chan *chan; 71870a708f8fSGustavo F. Padovan 71880a708f8fSGustavo F. Padovan if (!conn) 71890a708f8fSGustavo F. Padovan return 0; 71900a708f8fSGustavo F. Padovan 719189d8b407SAndrei Emeltchenko BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt); 71920a708f8fSGustavo F. Padovan 7193160dc6acSVinicius Costa Gomes if (hcon->type == LE_LINK) { 719435d4adccSHemant Gupta if (!status && encrypt) 7195160dc6acSVinicius Costa Gomes smp_distribute_keys(conn, 0); 719617cd3f37SUlisses Furquim cancel_delayed_work(&conn->security_timer); 7197160dc6acSVinicius Costa Gomes } 7198160dc6acSVinicius Costa Gomes 71993df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 72000a708f8fSGustavo F. Padovan 72013df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 72026be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 72030a708f8fSGustavo F. Padovan 720489d8b407SAndrei Emeltchenko BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, 720589d8b407SAndrei Emeltchenko state_to_string(chan->state)); 7206f1cb9af5SVinicius Costa Gomes 720778eb2f98SAndrei Emeltchenko if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { 720878eb2f98SAndrei Emeltchenko l2cap_chan_unlock(chan); 720978eb2f98SAndrei Emeltchenko continue; 721078eb2f98SAndrei Emeltchenko } 721178eb2f98SAndrei Emeltchenko 7212073d1cf3SJohan Hedberg if (chan->scid == L2CAP_CID_ATT) { 7213f1cb9af5SVinicius Costa Gomes if (!status && encrypt) { 7214f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level; 7215cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 7216f1cb9af5SVinicius Costa Gomes } 7217f1cb9af5SVinicius Costa Gomes 72186be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 7219f1cb9af5SVinicius Costa Gomes continue; 7220f1cb9af5SVinicius Costa Gomes } 7221f1cb9af5SVinicius Costa Gomes 722296eff46eSAndrei Emeltchenko if (!__l2cap_no_conn_pending(chan)) { 72236be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 72240a708f8fSGustavo F. Padovan continue; 72250a708f8fSGustavo F. Padovan } 72260a708f8fSGustavo F. Padovan 722789bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED || 722889bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) { 7229d97c899bSMarcel Holtmann chan->ops->resume(chan); 72304343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt); 72316be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 72320a708f8fSGustavo F. Padovan continue; 72330a708f8fSGustavo F. Padovan } 72340a708f8fSGustavo F. Padovan 723589bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 72366d3c15daSJohan Hedberg if (!status) 723793c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 72386d3c15daSJohan Hedberg else 7239ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 724089bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 72410a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 7242df3c3931SJohan Hedberg __u16 res, stat; 72430a708f8fSGustavo F. Padovan 72440a708f8fSGustavo F. Padovan if (!status) { 7245bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 7246df3c3931SJohan Hedberg res = L2CAP_CR_PEND; 7247df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND; 72482dc4e510SGustavo Padovan chan->ops->defer(chan); 7249df3c3931SJohan Hedberg } else { 7250acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 7251df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS; 7252df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 7253df3c3931SJohan Hedberg } 72540a708f8fSGustavo F. Padovan } else { 7255acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_DISCONN); 7256ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 7257df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK; 7258df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 72590a708f8fSGustavo F. Padovan } 72600a708f8fSGustavo F. Padovan 7261fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 7262fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 7263df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res); 7264df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat); 7265fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 7266fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 72672d369359SMat Martineau 72682d369359SMat Martineau if (!test_bit(CONF_REQ_SENT, &chan->conf_state) && 72692d369359SMat Martineau res == L2CAP_CR_SUCCESS) { 72702d369359SMat Martineau char buf[128]; 72712d369359SMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 72722d369359SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), 72732d369359SMat Martineau L2CAP_CONF_REQ, 72742d369359SMat Martineau l2cap_build_conf_req(chan, buf), 72752d369359SMat Martineau buf); 72762d369359SMat Martineau chan->num_conf_req++; 72772d369359SMat Martineau } 72780a708f8fSGustavo F. Padovan } 72790a708f8fSGustavo F. Padovan 72806be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 72810a708f8fSGustavo F. Padovan } 72820a708f8fSGustavo F. Padovan 72833df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 72840a708f8fSGustavo F. Padovan 72850a708f8fSGustavo F. Padovan return 0; 72860a708f8fSGustavo F. Padovan } 72870a708f8fSGustavo F. Padovan 7288686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) 72890a708f8fSGustavo F. Padovan { 72900a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 7291d73a0988SAndrei Emeltchenko struct l2cap_hdr *hdr; 7292d73a0988SAndrei Emeltchenko int len; 72930a708f8fSGustavo F. Padovan 72941d13a254SAndrei Emeltchenko /* For AMP controller do not create l2cap conn */ 72951d13a254SAndrei Emeltchenko if (!conn && hcon->hdev->dev_type != HCI_BREDR) 72961d13a254SAndrei Emeltchenko goto drop; 72970a708f8fSGustavo F. Padovan 72980a708f8fSGustavo F. Padovan if (!conn) 7299baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon); 73000a708f8fSGustavo F. Padovan 73010a708f8fSGustavo F. Padovan if (!conn) 73020a708f8fSGustavo F. Padovan goto drop; 73030a708f8fSGustavo F. Padovan 73040a708f8fSGustavo F. Padovan BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); 73050a708f8fSGustavo F. Padovan 7306d73a0988SAndrei Emeltchenko switch (flags) { 7307d73a0988SAndrei Emeltchenko case ACL_START: 7308d73a0988SAndrei Emeltchenko case ACL_START_NO_FLUSH: 7309d73a0988SAndrei Emeltchenko case ACL_COMPLETE: 73100a708f8fSGustavo F. Padovan if (conn->rx_len) { 73110a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len); 73120a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 73130a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 73140a708f8fSGustavo F. Padovan conn->rx_len = 0; 73150a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 73160a708f8fSGustavo F. Padovan } 73170a708f8fSGustavo F. Padovan 73180a708f8fSGustavo F. Padovan /* Start fragment always begin with Basic L2CAP header */ 73190a708f8fSGustavo F. Padovan if (skb->len < L2CAP_HDR_SIZE) { 73200a708f8fSGustavo F. Padovan BT_ERR("Frame is too short (len %d)", skb->len); 73210a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 73220a708f8fSGustavo F. Padovan goto drop; 73230a708f8fSGustavo F. Padovan } 73240a708f8fSGustavo F. Padovan 73250a708f8fSGustavo F. Padovan hdr = (struct l2cap_hdr *) skb->data; 73260a708f8fSGustavo F. Padovan len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; 73270a708f8fSGustavo F. Padovan 73280a708f8fSGustavo F. Padovan if (len == skb->len) { 73290a708f8fSGustavo F. Padovan /* Complete frame received */ 73300a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb); 73310a708f8fSGustavo F. Padovan return 0; 73320a708f8fSGustavo F. Padovan } 73330a708f8fSGustavo F. Padovan 73340a708f8fSGustavo F. Padovan BT_DBG("Start: total len %d, frag len %d", len, skb->len); 73350a708f8fSGustavo F. Padovan 73360a708f8fSGustavo F. Padovan if (skb->len > len) { 73370a708f8fSGustavo F. Padovan BT_ERR("Frame is too long (len %d, expected len %d)", 73380a708f8fSGustavo F. Padovan skb->len, len); 73390a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 73400a708f8fSGustavo F. Padovan goto drop; 73410a708f8fSGustavo F. Padovan } 73420a708f8fSGustavo F. Padovan 73430a708f8fSGustavo F. Padovan /* Allocate skb for the complete frame (with header) */ 73448bcde1f2SGustavo Padovan conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL); 73450a708f8fSGustavo F. Padovan if (!conn->rx_skb) 73460a708f8fSGustavo F. Padovan goto drop; 73470a708f8fSGustavo F. Padovan 73480a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 73490a708f8fSGustavo F. Padovan skb->len); 73500a708f8fSGustavo F. Padovan conn->rx_len = len - skb->len; 7351d73a0988SAndrei Emeltchenko break; 7352d73a0988SAndrei Emeltchenko 7353d73a0988SAndrei Emeltchenko case ACL_CONT: 73540a708f8fSGustavo F. Padovan BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); 73550a708f8fSGustavo F. Padovan 73560a708f8fSGustavo F. Padovan if (!conn->rx_len) { 73570a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len); 73580a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 73590a708f8fSGustavo F. Padovan goto drop; 73600a708f8fSGustavo F. Padovan } 73610a708f8fSGustavo F. Padovan 73620a708f8fSGustavo F. Padovan if (skb->len > conn->rx_len) { 73630a708f8fSGustavo F. Padovan BT_ERR("Fragment is too long (len %d, expected %d)", 73640a708f8fSGustavo F. Padovan skb->len, conn->rx_len); 73650a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 73660a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 73670a708f8fSGustavo F. Padovan conn->rx_len = 0; 73680a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 73690a708f8fSGustavo F. Padovan goto drop; 73700a708f8fSGustavo F. Padovan } 73710a708f8fSGustavo F. Padovan 73720a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 73730a708f8fSGustavo F. Padovan skb->len); 73740a708f8fSGustavo F. Padovan conn->rx_len -= skb->len; 73750a708f8fSGustavo F. Padovan 73760a708f8fSGustavo F. Padovan if (!conn->rx_len) { 7377c4e5bafaSJohan Hedberg /* Complete frame received. l2cap_recv_frame 7378c4e5bafaSJohan Hedberg * takes ownership of the skb so set the global 7379c4e5bafaSJohan Hedberg * rx_skb pointer to NULL first. 7380c4e5bafaSJohan Hedberg */ 7381c4e5bafaSJohan Hedberg struct sk_buff *rx_skb = conn->rx_skb; 73820a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 7383c4e5bafaSJohan Hedberg l2cap_recv_frame(conn, rx_skb); 73840a708f8fSGustavo F. Padovan } 7385d73a0988SAndrei Emeltchenko break; 73860a708f8fSGustavo F. Padovan } 73870a708f8fSGustavo F. Padovan 73880a708f8fSGustavo F. Padovan drop: 73890a708f8fSGustavo F. Padovan kfree_skb(skb); 73900a708f8fSGustavo F. Padovan return 0; 73910a708f8fSGustavo F. Padovan } 73920a708f8fSGustavo F. Padovan 73930a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p) 73940a708f8fSGustavo F. Padovan { 739523691d75SGustavo F. Padovan struct l2cap_chan *c; 73960a708f8fSGustavo F. Padovan 7397333055f2SGustavo F. Padovan read_lock(&chan_list_lock); 73980a708f8fSGustavo F. Padovan 739923691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 7400fcb73338SAndrei Emeltchenko seq_printf(f, "%pMR %pMR %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", 74017eafc59eSMarcel Holtmann &c->src, &c->dst, 740289bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm), 740323691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu, 740423691d75SGustavo F. Padovan c->sec_level, c->mode); 74050a708f8fSGustavo F. Padovan } 74060a708f8fSGustavo F. Padovan 7407333055f2SGustavo F. Padovan read_unlock(&chan_list_lock); 74080a708f8fSGustavo F. Padovan 74090a708f8fSGustavo F. Padovan return 0; 74100a708f8fSGustavo F. Padovan } 74110a708f8fSGustavo F. Padovan 74120a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file) 74130a708f8fSGustavo F. Padovan { 74140a708f8fSGustavo F. Padovan return single_open(file, l2cap_debugfs_show, inode->i_private); 74150a708f8fSGustavo F. Padovan } 74160a708f8fSGustavo F. Padovan 74170a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = { 74180a708f8fSGustavo F. Padovan .open = l2cap_debugfs_open, 74190a708f8fSGustavo F. Padovan .read = seq_read, 74200a708f8fSGustavo F. Padovan .llseek = seq_lseek, 74210a708f8fSGustavo F. Padovan .release = single_release, 74220a708f8fSGustavo F. Padovan }; 74230a708f8fSGustavo F. Padovan 74240a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs; 74250a708f8fSGustavo F. Padovan 742664274518SGustavo F. Padovan int __init l2cap_init(void) 74270a708f8fSGustavo F. Padovan { 74280a708f8fSGustavo F. Padovan int err; 74290a708f8fSGustavo F. Padovan 7430bb58f747SGustavo F. Padovan err = l2cap_init_sockets(); 74310a708f8fSGustavo F. Padovan if (err < 0) 74320a708f8fSGustavo F. Padovan return err; 74330a708f8fSGustavo F. Padovan 74341120e4bfSMarcel Holtmann if (IS_ERR_OR_NULL(bt_debugfs)) 74351120e4bfSMarcel Holtmann return 0; 74361120e4bfSMarcel Holtmann 74372d792818SGustavo Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, 74382d792818SGustavo Padovan NULL, &l2cap_debugfs_fops); 74390a708f8fSGustavo F. Padovan 74400a708f8fSGustavo F. Padovan return 0; 74410a708f8fSGustavo F. Padovan } 74420a708f8fSGustavo F. Padovan 744364274518SGustavo F. Padovan void l2cap_exit(void) 74440a708f8fSGustavo F. Padovan { 74450a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs); 7446bb58f747SGustavo F. Padovan l2cap_cleanup_sockets(); 74470a708f8fSGustavo F. Padovan } 74480a708f8fSGustavo F. Padovan 74490a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644); 74500a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); 7451