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 { 2160a708f8fSGustavo F. Padovan u16 cid = L2CAP_CID_DYN_START; 2170a708f8fSGustavo F. Padovan 2180a708f8fSGustavo F. Padovan for (; cid < L2CAP_CID_DYN_END; cid++) { 219baa7e1faSGustavo F. Padovan if (!__l2cap_get_chan_by_scid(conn, cid)) 2200a708f8fSGustavo F. Padovan return cid; 2210a708f8fSGustavo F. Padovan } 2220a708f8fSGustavo F. Padovan 2230a708f8fSGustavo F. Padovan return 0; 2240a708f8fSGustavo F. Padovan } 2250a708f8fSGustavo F. Padovan 226f93fa273SGustavo Padovan static void l2cap_state_change(struct l2cap_chan *chan, int state) 22789bc500eSGustavo F. Padovan { 22842d2d87cSAndrei Emeltchenko BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state), 229badaaa00SGustavo F. Padovan state_to_string(state)); 230badaaa00SGustavo F. Padovan 23189bc500eSGustavo F. Padovan chan->state = state; 23253f52121SGustavo Padovan chan->ops->state_change(chan, state, 0); 23389bc500eSGustavo F. Padovan } 23489bc500eSGustavo F. Padovan 235f8e73017SGustavo Padovan static inline void l2cap_state_change_and_error(struct l2cap_chan *chan, 236f8e73017SGustavo Padovan int state, int err) 2372e0052e4SAndrei Emeltchenko { 238f8e73017SGustavo Padovan chan->state = state; 23953f52121SGustavo Padovan chan->ops->state_change(chan, chan->state, err); 2402e0052e4SAndrei Emeltchenko } 2412e0052e4SAndrei Emeltchenko 2422e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err) 2432e0052e4SAndrei Emeltchenko { 244f8e73017SGustavo Padovan chan->ops->state_change(chan, chan->state, err); 2452e0052e4SAndrei Emeltchenko } 2462e0052e4SAndrei Emeltchenko 2474239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan) 2484239d16fSMat Martineau { 2494239d16fSMat Martineau if (!delayed_work_pending(&chan->monitor_timer) && 2504239d16fSMat Martineau chan->retrans_timeout) { 2514239d16fSMat Martineau l2cap_set_timer(chan, &chan->retrans_timer, 2524239d16fSMat Martineau msecs_to_jiffies(chan->retrans_timeout)); 2534239d16fSMat Martineau } 2544239d16fSMat Martineau } 2554239d16fSMat Martineau 2564239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan) 2574239d16fSMat Martineau { 2584239d16fSMat Martineau __clear_retrans_timer(chan); 2594239d16fSMat Martineau if (chan->monitor_timeout) { 2604239d16fSMat Martineau l2cap_set_timer(chan, &chan->monitor_timer, 2614239d16fSMat Martineau msecs_to_jiffies(chan->monitor_timeout)); 2624239d16fSMat Martineau } 2634239d16fSMat Martineau } 2644239d16fSMat Martineau 265608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head, 266608bcc6dSMat Martineau u16 seq) 267608bcc6dSMat Martineau { 268608bcc6dSMat Martineau struct sk_buff *skb; 269608bcc6dSMat Martineau 270608bcc6dSMat Martineau skb_queue_walk(head, skb) { 271608bcc6dSMat Martineau if (bt_cb(skb)->control.txseq == seq) 272608bcc6dSMat Martineau return skb; 273608bcc6dSMat Martineau } 274608bcc6dSMat Martineau 275608bcc6dSMat Martineau return NULL; 276608bcc6dSMat Martineau } 277608bcc6dSMat Martineau 2783c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */ 2793c588192SMat Martineau 2803c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for 2813c588192SMat Martineau * SREJ requests that are received and for frames that are to be 2823c588192SMat Martineau * retransmitted. These seq_list functions implement a singly-linked 2833c588192SMat Martineau * list in an array, where membership in the list can also be checked 2843c588192SMat Martineau * in constant time. Items can also be added to the tail of the list 2853c588192SMat Martineau * and removed from the head in constant time, without further memory 2863c588192SMat Martineau * allocs or frees. 2873c588192SMat Martineau */ 2883c588192SMat Martineau 2893c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size) 2903c588192SMat Martineau { 2913c588192SMat Martineau size_t alloc_size, i; 2923c588192SMat Martineau 2933c588192SMat Martineau /* Allocated size is a power of 2 to map sequence numbers 2943c588192SMat Martineau * (which may be up to 14 bits) in to a smaller array that is 2953c588192SMat Martineau * sized for the negotiated ERTM transmit windows. 2963c588192SMat Martineau */ 2973c588192SMat Martineau alloc_size = roundup_pow_of_two(size); 2983c588192SMat Martineau 2993c588192SMat Martineau seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL); 3003c588192SMat Martineau if (!seq_list->list) 3013c588192SMat Martineau return -ENOMEM; 3023c588192SMat Martineau 3033c588192SMat Martineau seq_list->mask = alloc_size - 1; 3043c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3053c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3063c588192SMat Martineau for (i = 0; i < alloc_size; i++) 3073c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 3083c588192SMat Martineau 3093c588192SMat Martineau return 0; 3103c588192SMat Martineau } 3113c588192SMat Martineau 3123c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list) 3133c588192SMat Martineau { 3143c588192SMat Martineau kfree(seq_list->list); 3153c588192SMat Martineau } 3163c588192SMat Martineau 3173c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list, 3183c588192SMat Martineau u16 seq) 3193c588192SMat Martineau { 3203c588192SMat Martineau /* Constant-time check for list membership */ 3213c588192SMat Martineau return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR; 3223c588192SMat Martineau } 3233c588192SMat Martineau 3243c588192SMat Martineau static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq) 3253c588192SMat Martineau { 3263c588192SMat Martineau u16 mask = seq_list->mask; 3273c588192SMat Martineau 3283c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) { 3293c588192SMat Martineau /* In case someone tries to pop the head of an empty list */ 3303c588192SMat Martineau return L2CAP_SEQ_LIST_CLEAR; 3313c588192SMat Martineau } else if (seq_list->head == seq) { 3323c588192SMat Martineau /* Head can be removed in constant time */ 3333c588192SMat Martineau seq_list->head = seq_list->list[seq & mask]; 3343c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; 3353c588192SMat Martineau 3363c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_TAIL) { 3373c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3383c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3393c588192SMat Martineau } 3403c588192SMat Martineau } else { 3413c588192SMat Martineau /* Walk the list to find the sequence number */ 3423c588192SMat Martineau u16 prev = seq_list->head; 3433c588192SMat Martineau while (seq_list->list[prev & mask] != seq) { 3443c588192SMat Martineau prev = seq_list->list[prev & mask]; 3453c588192SMat Martineau if (prev == L2CAP_SEQ_LIST_TAIL) 3463c588192SMat Martineau return L2CAP_SEQ_LIST_CLEAR; 3473c588192SMat Martineau } 3483c588192SMat Martineau 3493c588192SMat Martineau /* Unlink the number from the list and clear it */ 3503c588192SMat Martineau seq_list->list[prev & mask] = seq_list->list[seq & mask]; 3513c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; 3523c588192SMat Martineau if (seq_list->tail == seq) 3533c588192SMat Martineau seq_list->tail = prev; 3543c588192SMat Martineau } 3553c588192SMat Martineau return seq; 3563c588192SMat Martineau } 3573c588192SMat Martineau 3583c588192SMat Martineau static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list) 3593c588192SMat Martineau { 3603c588192SMat Martineau /* Remove the head in constant time */ 3613c588192SMat Martineau return l2cap_seq_list_remove(seq_list, seq_list->head); 3623c588192SMat Martineau } 3633c588192SMat Martineau 3643c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list) 3653c588192SMat Martineau { 3663c588192SMat Martineau u16 i; 367f522ae36SGustavo Padovan 368f522ae36SGustavo Padovan if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) 369f522ae36SGustavo Padovan return; 370f522ae36SGustavo Padovan 3713c588192SMat Martineau for (i = 0; i <= seq_list->mask; i++) 3723c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 3733c588192SMat Martineau 3743c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3753c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3763c588192SMat Martineau } 3773c588192SMat Martineau 3783c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq) 3793c588192SMat Martineau { 3803c588192SMat Martineau u16 mask = seq_list->mask; 3813c588192SMat Martineau 3823c588192SMat Martineau /* All appends happen in constant time */ 3833c588192SMat Martineau 384f522ae36SGustavo Padovan if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR) 385f522ae36SGustavo Padovan return; 386f522ae36SGustavo Padovan 3873c588192SMat Martineau if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR) 3883c588192SMat Martineau seq_list->head = seq; 3893c588192SMat Martineau else 3903c588192SMat Martineau seq_list->list[seq_list->tail & mask] = seq; 3913c588192SMat Martineau 3923c588192SMat Martineau seq_list->tail = seq; 3933c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL; 3943c588192SMat Martineau } 3953c588192SMat Martineau 396721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work) 397ab07801dSGustavo F. Padovan { 398721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 399721c4181SGustavo F. Padovan chan_timer.work); 4003df91ea2SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 401ab07801dSGustavo F. Padovan int reason; 402ab07801dSGustavo F. Padovan 403e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 404ab07801dSGustavo F. Padovan 4053df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 4066be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 407ab07801dSGustavo F. Padovan 40889bc500eSGustavo F. Padovan if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) 409ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 41089bc500eSGustavo F. Padovan else if (chan->state == BT_CONNECT && 411ab07801dSGustavo F. Padovan chan->sec_level != BT_SECURITY_SDP) 412ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 413ab07801dSGustavo F. Padovan else 414ab07801dSGustavo F. Padovan reason = ETIMEDOUT; 415ab07801dSGustavo F. Padovan 4160f852724SGustavo F. Padovan l2cap_chan_close(chan, reason); 417ab07801dSGustavo F. Padovan 4186be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 419ab07801dSGustavo F. Padovan 42080b98027SGustavo Padovan chan->ops->close(chan); 4213df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4223df91ea2SAndrei Emeltchenko 423371fd835SUlisses Furquim l2cap_chan_put(chan); 424ab07801dSGustavo F. Padovan } 425ab07801dSGustavo F. Padovan 426eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void) 4270a708f8fSGustavo F. Padovan { 42848454079SGustavo F. Padovan struct l2cap_chan *chan; 4290a708f8fSGustavo F. Padovan 43048454079SGustavo F. Padovan chan = kzalloc(sizeof(*chan), GFP_ATOMIC); 43148454079SGustavo F. Padovan if (!chan) 43248454079SGustavo F. Padovan return NULL; 4330a708f8fSGustavo F. Padovan 434c03b355eSAndrei Emeltchenko mutex_init(&chan->lock); 435c03b355eSAndrei Emeltchenko 436333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 43723691d75SGustavo F. Padovan list_add(&chan->global_l, &chan_list); 438333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 43923691d75SGustavo F. Padovan 440721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout); 441ab07801dSGustavo F. Padovan 44289bc500eSGustavo F. Padovan chan->state = BT_OPEN; 44389bc500eSGustavo F. Padovan 444144ad330SSyam Sidhardhan kref_init(&chan->kref); 44571ba0e56SGustavo F. Padovan 4462827011fSMat Martineau /* This flag is cleared in l2cap_chan_ready() */ 4472827011fSMat Martineau set_bit(CONF_NOT_COMPLETE, &chan->conf_state); 4482827011fSMat Martineau 449eef1d9b6SGustavo Padovan BT_DBG("chan %p", chan); 450abc545b8SSzymon Janc 45148454079SGustavo F. Padovan return chan; 4520a708f8fSGustavo F. Padovan } 4530a708f8fSGustavo F. Padovan 454144ad330SSyam Sidhardhan static void l2cap_chan_destroy(struct kref *kref) 4556ff5abbfSGustavo F. Padovan { 456144ad330SSyam Sidhardhan struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref); 457144ad330SSyam Sidhardhan 4584af66c69SJaganath Kanakkassery BT_DBG("chan %p", chan); 4594af66c69SJaganath Kanakkassery 460333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 46123691d75SGustavo F. Padovan list_del(&chan->global_l); 462333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 46323691d75SGustavo F. Padovan 4644af66c69SJaganath Kanakkassery kfree(chan); 4656ff5abbfSGustavo F. Padovan } 4666ff5abbfSGustavo F. Padovan 46730648372SJaganath Kanakkassery void l2cap_chan_hold(struct l2cap_chan *c) 46830648372SJaganath Kanakkassery { 469144ad330SSyam Sidhardhan BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount)); 47030648372SJaganath Kanakkassery 471144ad330SSyam Sidhardhan kref_get(&c->kref); 47230648372SJaganath Kanakkassery } 47330648372SJaganath Kanakkassery 47430648372SJaganath Kanakkassery void l2cap_chan_put(struct l2cap_chan *c) 47530648372SJaganath Kanakkassery { 476144ad330SSyam Sidhardhan BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount)); 47730648372SJaganath Kanakkassery 478144ad330SSyam Sidhardhan kref_put(&c->kref, l2cap_chan_destroy); 47930648372SJaganath Kanakkassery } 48030648372SJaganath Kanakkassery 481bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan) 482bd4b1653SAndrei Emeltchenko { 483bd4b1653SAndrei Emeltchenko chan->fcs = L2CAP_FCS_CRC16; 484bd4b1653SAndrei Emeltchenko chan->max_tx = L2CAP_DEFAULT_MAX_TX; 485bd4b1653SAndrei Emeltchenko chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; 486bd4b1653SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 487c20f8e35SMat Martineau chan->ack_win = L2CAP_DEFAULT_TX_WINDOW; 488bd4b1653SAndrei Emeltchenko chan->sec_level = BT_SECURITY_LOW; 489bd4b1653SAndrei Emeltchenko 490bd4b1653SAndrei Emeltchenko set_bit(FLAG_FORCE_ACTIVE, &chan->flags); 491bd4b1653SAndrei Emeltchenko } 492bd4b1653SAndrei Emeltchenko 49338319713SJohan Hedberg void l2cap_le_flowctl_init(struct l2cap_chan *chan) 49438319713SJohan Hedberg { 49538319713SJohan Hedberg chan->imtu = L2CAP_DEFAULT_MTU; 49638319713SJohan Hedberg chan->omtu = L2CAP_LE_MIN_MTU; 49738319713SJohan Hedberg chan->mode = L2CAP_MODE_LE_FLOWCTL; 4980cd75f7eSJohan Hedberg chan->tx_credits = 0; 4990cd75f7eSJohan Hedberg chan->rx_credits = L2CAP_LE_MAX_CREDITS; 50038319713SJohan Hedberg } 50138319713SJohan Hedberg 50293c3e8f5SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 5030a708f8fSGustavo F. Padovan { 5040a708f8fSGustavo F. Padovan BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, 505097db76cSAndrei Emeltchenko __le16_to_cpu(chan->psm), chan->dcid); 5060a708f8fSGustavo F. Padovan 5079f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 5080a708f8fSGustavo F. Padovan 5098c1d787bSGustavo F. Padovan chan->conn = conn; 5100a708f8fSGustavo F. Padovan 5115491120eSAndrei Emeltchenko switch (chan->chan_type) { 5125491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_ORIENTED: 513b62f328bSVille Tervo if (conn->hcon->type == LE_LINK) { 514b62f328bSVille Tervo /* LE connection */ 5156fcb06a2SAndre Guedes chan->omtu = L2CAP_DEFAULT_MTU; 5169f22398cSJohan Hedberg if (chan->dcid == L2CAP_CID_ATT) 517073d1cf3SJohan Hedberg chan->scid = L2CAP_CID_ATT; 5189f22398cSJohan Hedberg else 5199f22398cSJohan Hedberg chan->scid = l2cap_alloc_cid(conn); 520b62f328bSVille Tervo } else { 5210a708f8fSGustavo F. Padovan /* Alloc CID for connection-oriented socket */ 522fe4128e0SGustavo F. Padovan chan->scid = l2cap_alloc_cid(conn); 5230c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 524b62f328bSVille Tervo } 5255491120eSAndrei Emeltchenko break; 5265491120eSAndrei Emeltchenko 5275491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_LESS: 5280a708f8fSGustavo F. Padovan /* Connectionless socket */ 529fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_CONN_LESS; 530fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_CONN_LESS; 5310c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 5325491120eSAndrei Emeltchenko break; 5335491120eSAndrei Emeltchenko 534416fa752SAndrei Emeltchenko case L2CAP_CHAN_CONN_FIX_A2MP: 535416fa752SAndrei Emeltchenko chan->scid = L2CAP_CID_A2MP; 536416fa752SAndrei Emeltchenko chan->dcid = L2CAP_CID_A2MP; 537416fa752SAndrei Emeltchenko chan->omtu = L2CAP_A2MP_DEFAULT_MTU; 538416fa752SAndrei Emeltchenko chan->imtu = L2CAP_A2MP_DEFAULT_MTU; 539416fa752SAndrei Emeltchenko break; 540416fa752SAndrei Emeltchenko 5415491120eSAndrei Emeltchenko default: 5420a708f8fSGustavo F. Padovan /* Raw socket can send/recv signalling messages only */ 543fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_SIGNALING; 544fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_SIGNALING; 5450c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 5460a708f8fSGustavo F. Padovan } 5470a708f8fSGustavo F. Padovan 5488f7975b1SAndrei Emeltchenko chan->local_id = L2CAP_BESTEFFORT_ID; 5498f7975b1SAndrei Emeltchenko chan->local_stype = L2CAP_SERV_BESTEFFORT; 5508f7975b1SAndrei Emeltchenko chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE; 5518f7975b1SAndrei Emeltchenko chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME; 5528f7975b1SAndrei Emeltchenko chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT; 5538936fa6dSAndrei Emeltchenko chan->local_flush_to = L2CAP_EFS_DEFAULT_FLUSH_TO; 5548f7975b1SAndrei Emeltchenko 555371fd835SUlisses Furquim l2cap_chan_hold(chan); 556baa7e1faSGustavo F. Padovan 5575ee9891dSJohan Hedberg hci_conn_hold(conn->hcon); 5585ee9891dSJohan Hedberg 5593df91ea2SAndrei Emeltchenko list_add(&chan->list, &conn->chan_l); 560643162a8SAndrei Emeltchenko } 561643162a8SAndrei Emeltchenko 562466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 563643162a8SAndrei Emeltchenko { 564643162a8SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 565643162a8SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 5663df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 5670a708f8fSGustavo F. Padovan } 5680a708f8fSGustavo F. Padovan 569466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err) 5700a708f8fSGustavo F. Padovan { 5718c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 5720a708f8fSGustavo F. Padovan 573c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 5740a708f8fSGustavo F. Padovan 57549208c9cSGustavo F. Padovan BT_DBG("chan %p, conn %p, err %d", chan, conn, err); 5760a708f8fSGustavo F. Padovan 5770a708f8fSGustavo F. Padovan if (conn) { 57856f60984SAndrei Emeltchenko struct amp_mgr *mgr = conn->hcon->amp_mgr; 579baa7e1faSGustavo F. Padovan /* Delete from channel list */ 5803df91ea2SAndrei Emeltchenko list_del(&chan->list); 5813d57dc68SGustavo F. Padovan 582371fd835SUlisses Furquim l2cap_chan_put(chan); 583baa7e1faSGustavo F. Padovan 5848c1d787bSGustavo F. Padovan chan->conn = NULL; 5853cabbfdaSAndrei Emeltchenko 5863cabbfdaSAndrei Emeltchenko if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP) 58776a68ba0SDavid Herrmann hci_conn_drop(conn->hcon); 58856f60984SAndrei Emeltchenko 58956f60984SAndrei Emeltchenko if (mgr && mgr->bredr_chan == chan) 59056f60984SAndrei Emeltchenko mgr->bredr_chan = NULL; 5910a708f8fSGustavo F. Padovan } 5920a708f8fSGustavo F. Padovan 593419e08c1SAndrei Emeltchenko if (chan->hs_hchan) { 594419e08c1SAndrei Emeltchenko struct hci_chan *hs_hchan = chan->hs_hchan; 595419e08c1SAndrei Emeltchenko 596419e08c1SAndrei Emeltchenko BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan); 597419e08c1SAndrei Emeltchenko amp_disconnect_logical_link(hs_hchan); 598419e08c1SAndrei Emeltchenko } 599419e08c1SAndrei Emeltchenko 600c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, err); 6016be36555SAndrei Emeltchenko 6022827011fSMat Martineau if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) 6036ff5abbfSGustavo F. Padovan return; 6042ead70b8SGustavo F. Padovan 605ee556f66SGustavo Padovan switch(chan->mode) { 606ee556f66SGustavo Padovan case L2CAP_MODE_BASIC: 607ee556f66SGustavo Padovan break; 6080a708f8fSGustavo F. Padovan 60938319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 610177f8f2bSJohan Hedberg skb_queue_purge(&chan->tx_q); 61138319713SJohan Hedberg break; 61238319713SJohan Hedberg 613ee556f66SGustavo Padovan case L2CAP_MODE_ERTM: 6141a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 6151a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 6161a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 6170a708f8fSGustavo F. Padovan 618f1c6775bSGustavo F. Padovan skb_queue_purge(&chan->srej_q); 6190a708f8fSGustavo F. Padovan 6203c588192SMat Martineau l2cap_seq_list_free(&chan->srej_list); 6213c588192SMat Martineau l2cap_seq_list_free(&chan->retrans_list); 622ee556f66SGustavo Padovan 623ee556f66SGustavo Padovan /* fall through */ 624ee556f66SGustavo Padovan 625ee556f66SGustavo Padovan case L2CAP_MODE_STREAMING: 626ee556f66SGustavo Padovan skb_queue_purge(&chan->tx_q); 627ee556f66SGustavo Padovan break; 6280a708f8fSGustavo F. Padovan } 629ee556f66SGustavo Padovan 630ee556f66SGustavo Padovan return; 6310a708f8fSGustavo F. Padovan } 6320a708f8fSGustavo F. Padovan 63327e2d4c8SJohan Hedberg static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan) 63427e2d4c8SJohan Hedberg { 63527e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn; 63627e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 63727e2d4c8SJohan Hedberg u16 result; 63827e2d4c8SJohan Hedberg 63927e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 64027e2d4c8SJohan Hedberg result = L2CAP_CR_AUTHORIZATION; 64127e2d4c8SJohan Hedberg else 64227e2d4c8SJohan Hedberg result = L2CAP_CR_BAD_PSM; 64327e2d4c8SJohan Hedberg 64427e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_DISCONN); 64527e2d4c8SJohan Hedberg 64627e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 64727e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 64827e2d4c8SJohan Hedberg rsp.mps = __constant_cpu_to_le16(L2CAP_LE_DEFAULT_MPS); 6490cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits); 65027e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result); 65127e2d4c8SJohan Hedberg 65227e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), 65327e2d4c8SJohan Hedberg &rsp); 65427e2d4c8SJohan Hedberg } 65527e2d4c8SJohan Hedberg 656791d60f7SJohan Hedberg static void l2cap_chan_connect_reject(struct l2cap_chan *chan) 657791d60f7SJohan Hedberg { 658791d60f7SJohan Hedberg struct l2cap_conn *conn = chan->conn; 659791d60f7SJohan Hedberg struct l2cap_conn_rsp rsp; 660791d60f7SJohan Hedberg u16 result; 661791d60f7SJohan Hedberg 662791d60f7SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 663791d60f7SJohan Hedberg result = L2CAP_CR_SEC_BLOCK; 664791d60f7SJohan Hedberg else 665791d60f7SJohan Hedberg result = L2CAP_CR_BAD_PSM; 666791d60f7SJohan Hedberg 667791d60f7SJohan Hedberg l2cap_state_change(chan, BT_DISCONN); 668791d60f7SJohan Hedberg 669791d60f7SJohan Hedberg rsp.scid = cpu_to_le16(chan->dcid); 670791d60f7SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 671791d60f7SJohan Hedberg rsp.result = cpu_to_le16(result); 672791d60f7SJohan Hedberg rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 673791d60f7SJohan Hedberg 674791d60f7SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); 675791d60f7SJohan Hedberg } 676791d60f7SJohan Hedberg 6770f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason) 6784519de9aSGustavo F. Padovan { 6794519de9aSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 6804519de9aSGustavo F. Padovan 6817eafc59eSMarcel Holtmann BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 6824519de9aSGustavo F. Padovan 68389bc500eSGustavo F. Padovan switch (chan->state) { 6844519de9aSGustavo F. Padovan case BT_LISTEN: 685c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 6864519de9aSGustavo F. Padovan break; 6874519de9aSGustavo F. Padovan 6884519de9aSGustavo F. Padovan case BT_CONNECTED: 6894519de9aSGustavo F. Padovan case BT_CONFIG: 690cea04ce3SJohan Hedberg /* ATT uses L2CAP_CHAN_CONN_ORIENTED so we must also 691cea04ce3SJohan Hedberg * check for chan->psm. 692cea04ce3SJohan Hedberg */ 693cea04ce3SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && chan->psm) { 6948d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 6955e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, reason); 6964519de9aSGustavo F. Padovan } else 6974519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 6984519de9aSGustavo F. Padovan break; 6994519de9aSGustavo F. Padovan 7004519de9aSGustavo F. Padovan case BT_CONNECT2: 701791d60f7SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) { 702791d60f7SJohan Hedberg if (conn->hcon->type == ACL_LINK) 703791d60f7SJohan Hedberg l2cap_chan_connect_reject(chan); 70427e2d4c8SJohan Hedberg else if (conn->hcon->type == LE_LINK) 70527e2d4c8SJohan Hedberg l2cap_chan_le_connect_reject(chan); 7064519de9aSGustavo F. Padovan } 7074519de9aSGustavo F. Padovan 7084519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 7094519de9aSGustavo F. Padovan break; 7104519de9aSGustavo F. Padovan 7114519de9aSGustavo F. Padovan case BT_CONNECT: 7124519de9aSGustavo F. Padovan case BT_DISCONN: 7134519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 7144519de9aSGustavo F. Padovan break; 7154519de9aSGustavo F. Padovan 7164519de9aSGustavo F. Padovan default: 717c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 7184519de9aSGustavo F. Padovan break; 7194519de9aSGustavo F. Padovan } 7204519de9aSGustavo F. Padovan } 7214519de9aSGustavo F. Padovan 7224343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) 7230a708f8fSGustavo F. Padovan { 7246a974b50SMarcel Holtmann switch (chan->chan_type) { 7256a974b50SMarcel Holtmann case L2CAP_CHAN_RAW: 7264343478fSGustavo F. Padovan switch (chan->sec_level) { 7270a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 7280a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING_MITM; 7290a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 7300a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING; 7310a708f8fSGustavo F. Padovan default: 7320a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 7330a708f8fSGustavo F. Padovan } 7346a974b50SMarcel Holtmann break; 7353124b843SMarcel Holtmann case L2CAP_CHAN_CONN_LESS: 7363124b843SMarcel Holtmann if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_3DSP)) { 7373124b843SMarcel Holtmann if (chan->sec_level == BT_SECURITY_LOW) 7383124b843SMarcel Holtmann chan->sec_level = BT_SECURITY_SDP; 7393124b843SMarcel Holtmann } 7403124b843SMarcel Holtmann if (chan->sec_level == BT_SECURITY_HIGH) 7413124b843SMarcel Holtmann return HCI_AT_NO_BONDING_MITM; 7423124b843SMarcel Holtmann else 7433124b843SMarcel Holtmann return HCI_AT_NO_BONDING; 7443124b843SMarcel Holtmann break; 7456a974b50SMarcel Holtmann case L2CAP_CHAN_CONN_ORIENTED: 7466a974b50SMarcel Holtmann if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) { 7474343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_LOW) 7484343478fSGustavo F. Padovan chan->sec_level = BT_SECURITY_SDP; 7490a708f8fSGustavo F. Padovan 7504343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_HIGH) 7510a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING_MITM; 7520a708f8fSGustavo F. Padovan else 7530a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 7546a974b50SMarcel Holtmann } 7556a974b50SMarcel Holtmann /* fall through */ 7566a974b50SMarcel Holtmann default: 7574343478fSGustavo F. Padovan switch (chan->sec_level) { 7580a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 7590a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING_MITM; 7600a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 7610a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING; 7620a708f8fSGustavo F. Padovan default: 7630a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 7640a708f8fSGustavo F. Padovan } 7656a974b50SMarcel Holtmann break; 7660a708f8fSGustavo F. Padovan } 7670a708f8fSGustavo F. Padovan } 7680a708f8fSGustavo F. Padovan 7690a708f8fSGustavo F. Padovan /* Service level security */ 770d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan) 7710a708f8fSGustavo F. Padovan { 7728c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 7730a708f8fSGustavo F. Padovan __u8 auth_type; 7740a708f8fSGustavo F. Padovan 775a17de2feSJohan Hedberg if (conn->hcon->type == LE_LINK) 776a17de2feSJohan Hedberg return smp_conn_security(conn->hcon, chan->sec_level); 777a17de2feSJohan Hedberg 7784343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 7790a708f8fSGustavo F. Padovan 7804343478fSGustavo F. Padovan return hci_conn_security(conn->hcon, chan->sec_level, auth_type); 7810a708f8fSGustavo F. Padovan } 7820a708f8fSGustavo F. Padovan 783b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn) 7840a708f8fSGustavo F. Padovan { 7850a708f8fSGustavo F. Padovan u8 id; 7860a708f8fSGustavo F. Padovan 7870a708f8fSGustavo F. Padovan /* Get next available identificator. 7880a708f8fSGustavo F. Padovan * 1 - 128 are used by kernel. 7890a708f8fSGustavo F. Padovan * 129 - 199 are reserved. 7900a708f8fSGustavo F. Padovan * 200 - 254 are used by utilities like l2ping, etc. 7910a708f8fSGustavo F. Padovan */ 7920a708f8fSGustavo F. Padovan 793333055f2SGustavo F. Padovan spin_lock(&conn->lock); 7940a708f8fSGustavo F. Padovan 7950a708f8fSGustavo F. Padovan if (++conn->tx_ident > 128) 7960a708f8fSGustavo F. Padovan conn->tx_ident = 1; 7970a708f8fSGustavo F. Padovan 7980a708f8fSGustavo F. Padovan id = conn->tx_ident; 7990a708f8fSGustavo F. Padovan 800333055f2SGustavo F. Padovan spin_unlock(&conn->lock); 8010a708f8fSGustavo F. Padovan 8020a708f8fSGustavo F. Padovan return id; 8030a708f8fSGustavo F. Padovan } 8040a708f8fSGustavo F. Padovan 8052d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 8062d792818SGustavo Padovan void *data) 8070a708f8fSGustavo F. Padovan { 8080a708f8fSGustavo F. Padovan struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); 8090a708f8fSGustavo F. Padovan u8 flags; 8100a708f8fSGustavo F. Padovan 8110a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x", code); 8120a708f8fSGustavo F. Padovan 8130a708f8fSGustavo F. Padovan if (!skb) 8140a708f8fSGustavo F. Padovan return; 8150a708f8fSGustavo F. Padovan 8160a708f8fSGustavo F. Padovan if (lmp_no_flush_capable(conn->hcon->hdev)) 8170a708f8fSGustavo F. Padovan flags = ACL_START_NO_FLUSH; 8180a708f8fSGustavo F. Padovan else 8190a708f8fSGustavo F. Padovan flags = ACL_START; 8200a708f8fSGustavo F. Padovan 82114b12d0bSJaikumar Ganesh bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON; 8225e59b791SLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 82314b12d0bSJaikumar Ganesh 82473d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, flags); 8250a708f8fSGustavo F. Padovan } 8260a708f8fSGustavo F. Padovan 82702b0fbb9SMat Martineau static bool __chan_is_moving(struct l2cap_chan *chan) 82802b0fbb9SMat Martineau { 82902b0fbb9SMat Martineau return chan->move_state != L2CAP_MOVE_STABLE && 83002b0fbb9SMat Martineau chan->move_state != L2CAP_MOVE_WAIT_PREPARE; 83102b0fbb9SMat Martineau } 83202b0fbb9SMat Martineau 83373d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) 83473d80debSLuiz Augusto von Dentz { 83573d80debSLuiz Augusto von Dentz struct hci_conn *hcon = chan->conn->hcon; 83673d80debSLuiz Augusto von Dentz u16 flags; 83773d80debSLuiz Augusto von Dentz 83873d80debSLuiz Augusto von Dentz BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, 83973d80debSLuiz Augusto von Dentz skb->priority); 84073d80debSLuiz Augusto von Dentz 841d5f8a75dSMat Martineau if (chan->hs_hcon && !__chan_is_moving(chan)) { 842d5f8a75dSMat Martineau if (chan->hs_hchan) 843d5f8a75dSMat Martineau hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE); 844d5f8a75dSMat Martineau else 845d5f8a75dSMat Martineau kfree_skb(skb); 846d5f8a75dSMat Martineau 847d5f8a75dSMat Martineau return; 848d5f8a75dSMat Martineau } 849d5f8a75dSMat Martineau 85073d80debSLuiz Augusto von Dentz if (!test_bit(FLAG_FLUSHABLE, &chan->flags) && 85173d80debSLuiz Augusto von Dentz lmp_no_flush_capable(hcon->hdev)) 85273d80debSLuiz Augusto von Dentz flags = ACL_START_NO_FLUSH; 85373d80debSLuiz Augusto von Dentz else 85473d80debSLuiz Augusto von Dentz flags = ACL_START; 85573d80debSLuiz Augusto von Dentz 85673d80debSLuiz Augusto von Dentz bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); 85773d80debSLuiz Augusto von Dentz hci_send_acl(chan->conn->hchan, skb, flags); 8580a708f8fSGustavo F. Padovan } 8590a708f8fSGustavo F. Padovan 860b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control) 861b5c6aaedSMat Martineau { 862b5c6aaedSMat Martineau control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT; 863b5c6aaedSMat Martineau control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT; 864b5c6aaedSMat Martineau 865b5c6aaedSMat Martineau if (enh & L2CAP_CTRL_FRAME_TYPE) { 866b5c6aaedSMat Martineau /* S-Frame */ 867b5c6aaedSMat Martineau control->sframe = 1; 868b5c6aaedSMat Martineau control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT; 869b5c6aaedSMat Martineau control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT; 870b5c6aaedSMat Martineau 871b5c6aaedSMat Martineau control->sar = 0; 872b5c6aaedSMat Martineau control->txseq = 0; 873b5c6aaedSMat Martineau } else { 874b5c6aaedSMat Martineau /* I-Frame */ 875b5c6aaedSMat Martineau control->sframe = 0; 876b5c6aaedSMat Martineau control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT; 877b5c6aaedSMat Martineau control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT; 878b5c6aaedSMat Martineau 879b5c6aaedSMat Martineau control->poll = 0; 880b5c6aaedSMat Martineau control->super = 0; 881b5c6aaedSMat Martineau } 882b5c6aaedSMat Martineau } 883b5c6aaedSMat Martineau 884b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control) 885b5c6aaedSMat Martineau { 886b5c6aaedSMat Martineau control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT; 887b5c6aaedSMat Martineau control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT; 888b5c6aaedSMat Martineau 889b5c6aaedSMat Martineau if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) { 890b5c6aaedSMat Martineau /* S-Frame */ 891b5c6aaedSMat Martineau control->sframe = 1; 892b5c6aaedSMat Martineau control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT; 893b5c6aaedSMat Martineau control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT; 894b5c6aaedSMat Martineau 895b5c6aaedSMat Martineau control->sar = 0; 896b5c6aaedSMat Martineau control->txseq = 0; 897b5c6aaedSMat Martineau } else { 898b5c6aaedSMat Martineau /* I-Frame */ 899b5c6aaedSMat Martineau control->sframe = 0; 900b5c6aaedSMat Martineau control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT; 901b5c6aaedSMat Martineau control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT; 902b5c6aaedSMat Martineau 903b5c6aaedSMat Martineau control->poll = 0; 904b5c6aaedSMat Martineau control->super = 0; 905b5c6aaedSMat Martineau } 906b5c6aaedSMat Martineau } 907b5c6aaedSMat Martineau 908b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan, 909b5c6aaedSMat Martineau struct sk_buff *skb) 910b5c6aaedSMat Martineau { 911b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 912b5c6aaedSMat Martineau __unpack_extended_control(get_unaligned_le32(skb->data), 913b5c6aaedSMat Martineau &bt_cb(skb)->control); 914cec8ab6eSMat Martineau skb_pull(skb, L2CAP_EXT_CTRL_SIZE); 915b5c6aaedSMat Martineau } else { 916b5c6aaedSMat Martineau __unpack_enhanced_control(get_unaligned_le16(skb->data), 917b5c6aaedSMat Martineau &bt_cb(skb)->control); 918cec8ab6eSMat Martineau skb_pull(skb, L2CAP_ENH_CTRL_SIZE); 919b5c6aaedSMat Martineau } 920b5c6aaedSMat Martineau } 921b5c6aaedSMat Martineau 922b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control) 923b5c6aaedSMat Martineau { 924b5c6aaedSMat Martineau u32 packed; 925b5c6aaedSMat Martineau 926b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT; 927b5c6aaedSMat Martineau packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT; 928b5c6aaedSMat Martineau 929b5c6aaedSMat Martineau if (control->sframe) { 930b5c6aaedSMat Martineau packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT; 931b5c6aaedSMat Martineau packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT; 932b5c6aaedSMat Martineau packed |= L2CAP_EXT_CTRL_FRAME_TYPE; 933b5c6aaedSMat Martineau } else { 934b5c6aaedSMat Martineau packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT; 935b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT; 936b5c6aaedSMat Martineau } 937b5c6aaedSMat Martineau 938b5c6aaedSMat Martineau return packed; 939b5c6aaedSMat Martineau } 940b5c6aaedSMat Martineau 941b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control) 942b5c6aaedSMat Martineau { 943b5c6aaedSMat Martineau u16 packed; 944b5c6aaedSMat Martineau 945b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT; 946b5c6aaedSMat Martineau packed |= control->final << L2CAP_CTRL_FINAL_SHIFT; 947b5c6aaedSMat Martineau 948b5c6aaedSMat Martineau if (control->sframe) { 949b5c6aaedSMat Martineau packed |= control->poll << L2CAP_CTRL_POLL_SHIFT; 950b5c6aaedSMat Martineau packed |= control->super << L2CAP_CTRL_SUPER_SHIFT; 951b5c6aaedSMat Martineau packed |= L2CAP_CTRL_FRAME_TYPE; 952b5c6aaedSMat Martineau } else { 953b5c6aaedSMat Martineau packed |= control->sar << L2CAP_CTRL_SAR_SHIFT; 954b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT; 955b5c6aaedSMat Martineau } 956b5c6aaedSMat Martineau 957b5c6aaedSMat Martineau return packed; 958b5c6aaedSMat Martineau } 959b5c6aaedSMat Martineau 960b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan, 961b5c6aaedSMat Martineau struct l2cap_ctrl *control, 962b5c6aaedSMat Martineau struct sk_buff *skb) 963b5c6aaedSMat Martineau { 964b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 965b5c6aaedSMat Martineau put_unaligned_le32(__pack_extended_control(control), 966b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 967b5c6aaedSMat Martineau } else { 968b5c6aaedSMat Martineau put_unaligned_le16(__pack_enhanced_control(control), 969b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 970b5c6aaedSMat Martineau } 971b5c6aaedSMat Martineau } 972b5c6aaedSMat Martineau 973ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan) 974ba7aa64fSGustavo Padovan { 975ba7aa64fSGustavo Padovan if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 976ba7aa64fSGustavo Padovan return L2CAP_EXT_HDR_SIZE; 977ba7aa64fSGustavo Padovan else 978ba7aa64fSGustavo Padovan return L2CAP_ENH_HDR_SIZE; 979ba7aa64fSGustavo Padovan } 980ba7aa64fSGustavo Padovan 981a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan, 982a67d7f6fSMat Martineau u32 control) 9830a708f8fSGustavo F. Padovan { 9840a708f8fSGustavo F. Padovan struct sk_buff *skb; 9850a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 986ba7aa64fSGustavo Padovan int hlen = __ertm_hdr_size(chan); 9870a708f8fSGustavo F. Padovan 9880a708f8fSGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 98903a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 9900a708f8fSGustavo F. Padovan 991a67d7f6fSMat Martineau skb = bt_skb_alloc(hlen, GFP_KERNEL); 9920a708f8fSGustavo F. Padovan 9930a708f8fSGustavo F. Padovan if (!skb) 994a67d7f6fSMat Martineau return ERR_PTR(-ENOMEM); 9950a708f8fSGustavo F. Padovan 9960a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 9970a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); 998fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 99988843ab0SAndrei Emeltchenko 1000a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1001a67d7f6fSMat Martineau put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 1002a67d7f6fSMat Martineau else 1003a67d7f6fSMat Martineau put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 10040a708f8fSGustavo F. Padovan 100547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 1006a67d7f6fSMat Martineau u16 fcs = crc16(0, (u8 *)skb->data, skb->len); 100703a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 10080a708f8fSGustavo F. Padovan } 10090a708f8fSGustavo F. Padovan 101073d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 1011a67d7f6fSMat Martineau return skb; 1012a67d7f6fSMat Martineau } 1013a67d7f6fSMat Martineau 1014a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan, 1015a67d7f6fSMat Martineau struct l2cap_ctrl *control) 1016a67d7f6fSMat Martineau { 1017a67d7f6fSMat Martineau struct sk_buff *skb; 1018a67d7f6fSMat Martineau u32 control_field; 1019a67d7f6fSMat Martineau 1020a67d7f6fSMat Martineau BT_DBG("chan %p, control %p", chan, control); 1021a67d7f6fSMat Martineau 1022a67d7f6fSMat Martineau if (!control->sframe) 1023a67d7f6fSMat Martineau return; 1024a67d7f6fSMat Martineau 1025b99e13adSMat Martineau if (__chan_is_moving(chan)) 1026b99e13adSMat Martineau return; 1027b99e13adSMat Martineau 1028a67d7f6fSMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) && 1029a67d7f6fSMat Martineau !control->poll) 1030a67d7f6fSMat Martineau control->final = 1; 1031a67d7f6fSMat Martineau 1032a67d7f6fSMat Martineau if (control->super == L2CAP_SUPER_RR) 1033a67d7f6fSMat Martineau clear_bit(CONN_RNR_SENT, &chan->conn_state); 1034a67d7f6fSMat Martineau else if (control->super == L2CAP_SUPER_RNR) 1035a67d7f6fSMat Martineau set_bit(CONN_RNR_SENT, &chan->conn_state); 1036a67d7f6fSMat Martineau 1037a67d7f6fSMat Martineau if (control->super != L2CAP_SUPER_SREJ) { 1038a67d7f6fSMat Martineau chan->last_acked_seq = control->reqseq; 1039a67d7f6fSMat Martineau __clear_ack_timer(chan); 1040a67d7f6fSMat Martineau } 1041a67d7f6fSMat Martineau 1042a67d7f6fSMat Martineau BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq, 1043a67d7f6fSMat Martineau control->final, control->poll, control->super); 1044a67d7f6fSMat Martineau 1045a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1046a67d7f6fSMat Martineau control_field = __pack_extended_control(control); 1047a67d7f6fSMat Martineau else 1048a67d7f6fSMat Martineau control_field = __pack_enhanced_control(control); 1049a67d7f6fSMat Martineau 1050a67d7f6fSMat Martineau skb = l2cap_create_sframe_pdu(chan, control_field); 1051a67d7f6fSMat Martineau if (!IS_ERR(skb)) 105273d80debSLuiz Augusto von Dentz l2cap_do_send(chan, skb); 10530a708f8fSGustavo F. Padovan } 10540a708f8fSGustavo F. Padovan 1055c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll) 10560a708f8fSGustavo F. Padovan { 1057c9e3d5e0SMat Martineau struct l2cap_ctrl control; 10580a708f8fSGustavo F. Padovan 1059c9e3d5e0SMat Martineau BT_DBG("chan %p, poll %d", chan, poll); 1060c9e3d5e0SMat Martineau 1061c9e3d5e0SMat Martineau memset(&control, 0, sizeof(control)); 1062c9e3d5e0SMat Martineau control.sframe = 1; 1063c9e3d5e0SMat Martineau control.poll = poll; 1064c9e3d5e0SMat Martineau 1065c9e3d5e0SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 1066c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RNR; 1067c9e3d5e0SMat Martineau else 1068c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RR; 1069c9e3d5e0SMat Martineau 1070c9e3d5e0SMat Martineau control.reqseq = chan->buffer_seq; 1071c9e3d5e0SMat Martineau l2cap_send_sframe(chan, &control); 10720a708f8fSGustavo F. Padovan } 10730a708f8fSGustavo F. Padovan 1074b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) 10750a708f8fSGustavo F. Padovan { 1076c1360a1cSGustavo F. Padovan return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); 10770a708f8fSGustavo F. Padovan } 10780a708f8fSGustavo F. Padovan 107993c3e8f5SAndrei Emeltchenko static bool __amp_capable(struct l2cap_chan *chan) 108093c3e8f5SAndrei Emeltchenko { 108193c3e8f5SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 10821df7b17aSMarcel Holtmann struct hci_dev *hdev; 10831df7b17aSMarcel Holtmann bool amp_available = false; 108493c3e8f5SAndrei Emeltchenko 10851df7b17aSMarcel Holtmann if (!conn->hs_enabled) 10861df7b17aSMarcel Holtmann return false; 10871df7b17aSMarcel Holtmann 10881df7b17aSMarcel Holtmann if (!(conn->fixed_chan_mask & L2CAP_FC_A2MP)) 10891df7b17aSMarcel Holtmann return false; 10901df7b17aSMarcel Holtmann 10911df7b17aSMarcel Holtmann read_lock(&hci_dev_list_lock); 10921df7b17aSMarcel Holtmann list_for_each_entry(hdev, &hci_dev_list, list) { 10931df7b17aSMarcel Holtmann if (hdev->amp_type != AMP_TYPE_BREDR && 10941df7b17aSMarcel Holtmann test_bit(HCI_UP, &hdev->flags)) { 10951df7b17aSMarcel Holtmann amp_available = true; 10961df7b17aSMarcel Holtmann break; 10971df7b17aSMarcel Holtmann } 10981df7b17aSMarcel Holtmann } 10991df7b17aSMarcel Holtmann read_unlock(&hci_dev_list_lock); 11001df7b17aSMarcel Holtmann 11011df7b17aSMarcel Holtmann if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED) 11021df7b17aSMarcel Holtmann return amp_available; 1103848566b3SMarcel Holtmann 110493c3e8f5SAndrei Emeltchenko return false; 110593c3e8f5SAndrei Emeltchenko } 110693c3e8f5SAndrei Emeltchenko 11075ce66b59SAndrei Emeltchenko static bool l2cap_check_efs(struct l2cap_chan *chan) 11085ce66b59SAndrei Emeltchenko { 11095ce66b59SAndrei Emeltchenko /* Check EFS parameters */ 11105ce66b59SAndrei Emeltchenko return true; 11115ce66b59SAndrei Emeltchenko } 11125ce66b59SAndrei Emeltchenko 11132766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan) 11149b27f350SAndrei Emeltchenko { 11159b27f350SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 11169b27f350SAndrei Emeltchenko struct l2cap_conn_req req; 11179b27f350SAndrei Emeltchenko 11189b27f350SAndrei Emeltchenko req.scid = cpu_to_le16(chan->scid); 11199b27f350SAndrei Emeltchenko req.psm = chan->psm; 11209b27f350SAndrei Emeltchenko 11219b27f350SAndrei Emeltchenko chan->ident = l2cap_get_ident(conn); 11229b27f350SAndrei Emeltchenko 11239b27f350SAndrei Emeltchenko set_bit(CONF_CONNECT_PEND, &chan->conf_state); 11249b27f350SAndrei Emeltchenko 11259b27f350SAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); 11269b27f350SAndrei Emeltchenko } 11279b27f350SAndrei Emeltchenko 11288eb200bdSMat Martineau static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id) 11298eb200bdSMat Martineau { 11308eb200bdSMat Martineau struct l2cap_create_chan_req req; 11318eb200bdSMat Martineau req.scid = cpu_to_le16(chan->scid); 11328eb200bdSMat Martineau req.psm = chan->psm; 11338eb200bdSMat Martineau req.amp_id = amp_id; 11348eb200bdSMat Martineau 11358eb200bdSMat Martineau chan->ident = l2cap_get_ident(chan->conn); 11368eb200bdSMat Martineau 11378eb200bdSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ, 11388eb200bdSMat Martineau sizeof(req), &req); 11398eb200bdSMat Martineau } 11408eb200bdSMat Martineau 114102b0fbb9SMat Martineau static void l2cap_move_setup(struct l2cap_chan *chan) 114202b0fbb9SMat Martineau { 114302b0fbb9SMat Martineau struct sk_buff *skb; 114402b0fbb9SMat Martineau 114502b0fbb9SMat Martineau BT_DBG("chan %p", chan); 114602b0fbb9SMat Martineau 114702b0fbb9SMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 114802b0fbb9SMat Martineau return; 114902b0fbb9SMat Martineau 115002b0fbb9SMat Martineau __clear_retrans_timer(chan); 115102b0fbb9SMat Martineau __clear_monitor_timer(chan); 115202b0fbb9SMat Martineau __clear_ack_timer(chan); 115302b0fbb9SMat Martineau 115402b0fbb9SMat Martineau chan->retry_count = 0; 115502b0fbb9SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 115602b0fbb9SMat Martineau if (bt_cb(skb)->control.retries) 115702b0fbb9SMat Martineau bt_cb(skb)->control.retries = 1; 115802b0fbb9SMat Martineau else 115902b0fbb9SMat Martineau break; 116002b0fbb9SMat Martineau } 116102b0fbb9SMat Martineau 116202b0fbb9SMat Martineau chan->expected_tx_seq = chan->buffer_seq; 116302b0fbb9SMat Martineau 116402b0fbb9SMat Martineau clear_bit(CONN_REJ_ACT, &chan->conn_state); 116502b0fbb9SMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 116602b0fbb9SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 116702b0fbb9SMat Martineau l2cap_seq_list_clear(&chan->srej_list); 116802b0fbb9SMat Martineau skb_queue_purge(&chan->srej_q); 116902b0fbb9SMat Martineau 117002b0fbb9SMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 117102b0fbb9SMat Martineau chan->rx_state = L2CAP_RX_STATE_MOVE; 117202b0fbb9SMat Martineau 117302b0fbb9SMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 117402b0fbb9SMat Martineau } 117502b0fbb9SMat Martineau 11765f3847a4SMat Martineau static void l2cap_move_done(struct l2cap_chan *chan) 11775f3847a4SMat Martineau { 11785f3847a4SMat Martineau u8 move_role = chan->move_role; 11795f3847a4SMat Martineau BT_DBG("chan %p", chan); 11805f3847a4SMat Martineau 11815f3847a4SMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 11825f3847a4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 11835f3847a4SMat Martineau 11845f3847a4SMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 11855f3847a4SMat Martineau return; 11865f3847a4SMat Martineau 11875f3847a4SMat Martineau switch (move_role) { 11885f3847a4SMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 11895f3847a4SMat Martineau l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL); 11905f3847a4SMat Martineau chan->rx_state = L2CAP_RX_STATE_WAIT_F; 11915f3847a4SMat Martineau break; 11925f3847a4SMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 11935f3847a4SMat Martineau chan->rx_state = L2CAP_RX_STATE_WAIT_P; 11945f3847a4SMat Martineau break; 11955f3847a4SMat Martineau } 11965f3847a4SMat Martineau } 11975f3847a4SMat Martineau 1198177f8f2bSJohan Hedberg static void l2cap_le_flowctl_start(struct l2cap_chan *chan) 1199177f8f2bSJohan Hedberg { 1200177f8f2bSJohan Hedberg chan->sdu = NULL; 1201177f8f2bSJohan Hedberg chan->sdu_last_frag = NULL; 1202177f8f2bSJohan Hedberg chan->sdu_len = 0; 1203177f8f2bSJohan Hedberg 1204177f8f2bSJohan Hedberg skb_queue_head_init(&chan->tx_q); 1205177f8f2bSJohan Hedberg } 1206177f8f2bSJohan Hedberg 12079f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan) 12089f0caeb1SVinicius Costa Gomes { 12092827011fSMat Martineau /* This clears all conf flags, including CONF_NOT_COMPLETE */ 12109f0caeb1SVinicius Costa Gomes chan->conf_state = 0; 12119f0caeb1SVinicius Costa Gomes __clear_chan_timer(chan); 12129f0caeb1SVinicius Costa Gomes 1213177f8f2bSJohan Hedberg if (chan->mode == L2CAP_MODE_LE_FLOWCTL) 1214177f8f2bSJohan Hedberg l2cap_le_flowctl_start(chan); 1215177f8f2bSJohan Hedberg 121654a59aa2SAndrei Emeltchenko chan->state = BT_CONNECTED; 12179f0caeb1SVinicius Costa Gomes 121854a59aa2SAndrei Emeltchenko chan->ops->ready(chan); 12199f0caeb1SVinicius Costa Gomes } 12209f0caeb1SVinicius Costa Gomes 1221f1496deeSJohan Hedberg static void l2cap_le_connect(struct l2cap_chan *chan) 1222f1496deeSJohan Hedberg { 1223f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1224f1496deeSJohan Hedberg struct l2cap_le_conn_req req; 1225f1496deeSJohan Hedberg 1226f1496deeSJohan Hedberg req.psm = chan->psm; 1227f1496deeSJohan Hedberg req.scid = cpu_to_le16(chan->scid); 1228f1496deeSJohan Hedberg req.mtu = cpu_to_le16(chan->imtu); 1229f1496deeSJohan Hedberg req.mps = __constant_cpu_to_le16(L2CAP_LE_DEFAULT_MPS); 12300cd75f7eSJohan Hedberg req.credits = cpu_to_le16(chan->rx_credits); 1231f1496deeSJohan Hedberg 1232f1496deeSJohan Hedberg chan->ident = l2cap_get_ident(conn); 1233f1496deeSJohan Hedberg 1234f1496deeSJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ, 1235f1496deeSJohan Hedberg sizeof(req), &req); 1236f1496deeSJohan Hedberg } 1237f1496deeSJohan Hedberg 1238f1496deeSJohan Hedberg static void l2cap_le_start(struct l2cap_chan *chan) 1239f1496deeSJohan Hedberg { 1240f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1241f1496deeSJohan Hedberg 1242f1496deeSJohan Hedberg if (!smp_conn_security(conn->hcon, chan->sec_level)) 1243f1496deeSJohan Hedberg return; 1244f1496deeSJohan Hedberg 1245f1496deeSJohan Hedberg if (!chan->psm) { 1246f1496deeSJohan Hedberg l2cap_chan_ready(chan); 1247f1496deeSJohan Hedberg return; 1248f1496deeSJohan Hedberg } 1249f1496deeSJohan Hedberg 1250f1496deeSJohan Hedberg if (chan->state == BT_CONNECT) 1251f1496deeSJohan Hedberg l2cap_le_connect(chan); 1252f1496deeSJohan Hedberg } 1253f1496deeSJohan Hedberg 125493c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan) 125593c3e8f5SAndrei Emeltchenko { 125693c3e8f5SAndrei Emeltchenko if (__amp_capable(chan)) { 125793c3e8f5SAndrei Emeltchenko BT_DBG("chan %p AMP capable: discover AMPs", chan); 125893c3e8f5SAndrei Emeltchenko a2mp_discover_amp(chan); 1259f1496deeSJohan Hedberg } else if (chan->conn->hcon->type == LE_LINK) { 1260f1496deeSJohan Hedberg l2cap_le_start(chan); 126193c3e8f5SAndrei Emeltchenko } else { 126293c3e8f5SAndrei Emeltchenko l2cap_send_conn_req(chan); 126393c3e8f5SAndrei Emeltchenko } 126493c3e8f5SAndrei Emeltchenko } 126593c3e8f5SAndrei Emeltchenko 1266fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan) 12670a708f8fSGustavo F. Padovan { 12688c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 12690a708f8fSGustavo F. Padovan 12709f0caeb1SVinicius Costa Gomes if (conn->hcon->type == LE_LINK) { 127196ac34fbSJohan Hedberg l2cap_le_start(chan); 12729f0caeb1SVinicius Costa Gomes return; 12739f0caeb1SVinicius Costa Gomes } 12749f0caeb1SVinicius Costa Gomes 12750a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { 12760a708f8fSGustavo F. Padovan if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) 12770a708f8fSGustavo F. Padovan return; 12780a708f8fSGustavo F. Padovan 1279d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan) && 128093c3e8f5SAndrei Emeltchenko __l2cap_no_conn_pending(chan)) { 128193c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 128293c3e8f5SAndrei Emeltchenko } 12830a708f8fSGustavo F. Padovan } else { 12840a708f8fSGustavo F. Padovan struct l2cap_info_req req; 1285ac73498cSAndrei Emeltchenko req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); 12860a708f8fSGustavo F. Padovan 12870a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 12880a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 12890a708f8fSGustavo F. Padovan 1290ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 12910a708f8fSGustavo F. Padovan 12922d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, 12932d792818SGustavo Padovan sizeof(req), &req); 12940a708f8fSGustavo F. Padovan } 12950a708f8fSGustavo F. Padovan } 12960a708f8fSGustavo F. Padovan 12970a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) 12980a708f8fSGustavo F. Padovan { 12990a708f8fSGustavo F. Padovan u32 local_feat_mask = l2cap_feat_mask; 13000a708f8fSGustavo F. Padovan if (!disable_ertm) 13010a708f8fSGustavo F. Padovan local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING; 13020a708f8fSGustavo F. Padovan 13030a708f8fSGustavo F. Padovan switch (mode) { 13040a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 13050a708f8fSGustavo F. Padovan return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask; 13060a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 13070a708f8fSGustavo F. Padovan return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask; 13080a708f8fSGustavo F. Padovan default: 13090a708f8fSGustavo F. Padovan return 0x00; 13100a708f8fSGustavo F. Padovan } 13110a708f8fSGustavo F. Padovan } 13120a708f8fSGustavo F. Padovan 13135e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err) 13140a708f8fSGustavo F. Padovan { 13155e4e3972SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 13160a708f8fSGustavo F. Padovan struct l2cap_disconn_req req; 13170a708f8fSGustavo F. Padovan 13180a708f8fSGustavo F. Padovan if (!conn) 13190a708f8fSGustavo F. Padovan return; 13200a708f8fSGustavo F. Padovan 1321aad3d0e3SAndrei Emeltchenko if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) { 13221a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 13231a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 13241a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 13250a708f8fSGustavo F. Padovan } 13260a708f8fSGustavo F. Padovan 1327416fa752SAndrei Emeltchenko if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { 1328d117773cSGustavo Padovan l2cap_state_change(chan, BT_DISCONN); 1329416fa752SAndrei Emeltchenko return; 1330416fa752SAndrei Emeltchenko } 1331416fa752SAndrei Emeltchenko 1332fe4128e0SGustavo F. Padovan req.dcid = cpu_to_le16(chan->dcid); 1333fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 13342d792818SGustavo Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ, 13352d792818SGustavo Padovan sizeof(req), &req); 13360a708f8fSGustavo F. Padovan 1337f8e73017SGustavo Padovan l2cap_state_change_and_error(chan, BT_DISCONN, err); 13380a708f8fSGustavo F. Padovan } 13390a708f8fSGustavo F. Padovan 13400a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */ 13410a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn) 13420a708f8fSGustavo F. Padovan { 13433df91ea2SAndrei Emeltchenko struct l2cap_chan *chan, *tmp; 13440a708f8fSGustavo F. Padovan 13450a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 13460a708f8fSGustavo F. Padovan 13473df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 13480a708f8fSGustavo F. Padovan 13493df91ea2SAndrei Emeltchenko list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 13506be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 13510a708f8fSGustavo F. Padovan 1352715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 13536be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13540a708f8fSGustavo F. Padovan continue; 13550a708f8fSGustavo F. Padovan } 13560a708f8fSGustavo F. Padovan 135789bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 1358d45fc423SGustavo F. Padovan if (!l2cap_chan_check_security(chan) || 1359b4450035SGustavo F. Padovan !__l2cap_no_conn_pending(chan)) { 13606be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13610a708f8fSGustavo F. Padovan continue; 13620a708f8fSGustavo F. Padovan } 13630a708f8fSGustavo F. Padovan 1364c1360a1cSGustavo F. Padovan if (!l2cap_mode_supported(chan->mode, conn->feat_mask) 1365c1360a1cSGustavo F. Padovan && test_bit(CONF_STATE2_DEVICE, 1366c1360a1cSGustavo F. Padovan &chan->conf_state)) { 13670f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 13686be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13690a708f8fSGustavo F. Padovan continue; 13700a708f8fSGustavo F. Padovan } 13710a708f8fSGustavo F. Padovan 137293c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 13730a708f8fSGustavo F. Padovan 137489bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 13750a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 13760a708f8fSGustavo F. Padovan char buf[128]; 1377fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 1378fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 13790a708f8fSGustavo F. Padovan 1380d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 1381bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 1382ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); 1383ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND); 13842dc4e510SGustavo Padovan chan->ops->defer(chan); 13850a708f8fSGustavo F. Padovan 13860a708f8fSGustavo F. Padovan } else { 1387acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 1388ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 1389ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 13900a708f8fSGustavo F. Padovan } 13910a708f8fSGustavo F. Padovan } else { 1392ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); 1393ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND); 13940a708f8fSGustavo F. Padovan } 13950a708f8fSGustavo F. Padovan 1396fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 1397fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 13980a708f8fSGustavo F. Padovan 1399c1360a1cSGustavo F. Padovan if (test_bit(CONF_REQ_SENT, &chan->conf_state) || 14000a708f8fSGustavo F. Padovan rsp.result != L2CAP_CR_SUCCESS) { 14016be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 14020a708f8fSGustavo F. Padovan continue; 14030a708f8fSGustavo F. Padovan } 14040a708f8fSGustavo F. Padovan 1405c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 14060a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 140773ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 140873ffa904SGustavo F. Padovan chan->num_conf_req++; 14090a708f8fSGustavo F. Padovan } 14100a708f8fSGustavo F. Padovan 14116be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 14120a708f8fSGustavo F. Padovan } 14130a708f8fSGustavo F. Padovan 14143df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 14150a708f8fSGustavo F. Padovan } 14160a708f8fSGustavo F. Padovan 1417c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr. 1418b62f328bSVille Tervo * Returns closest match, locked. 1419b62f328bSVille Tervo */ 1420d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, 1421c2287681SIdo Yariv bdaddr_t *src, 1422c2287681SIdo Yariv bdaddr_t *dst) 1423b62f328bSVille Tervo { 142423691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 1425b62f328bSVille Tervo 142623691d75SGustavo F. Padovan read_lock(&chan_list_lock); 1427b62f328bSVille Tervo 142823691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 142989bc500eSGustavo F. Padovan if (state && c->state != state) 1430b62f328bSVille Tervo continue; 1431b62f328bSVille Tervo 143223691d75SGustavo F. Padovan if (c->scid == cid) { 1433c2287681SIdo Yariv int src_match, dst_match; 1434c2287681SIdo Yariv int src_any, dst_any; 1435c2287681SIdo Yariv 1436b62f328bSVille Tervo /* Exact match. */ 14377eafc59eSMarcel Holtmann src_match = !bacmp(&c->src, src); 14387eafc59eSMarcel Holtmann dst_match = !bacmp(&c->dst, dst); 1439c2287681SIdo Yariv if (src_match && dst_match) { 144023691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 144123691d75SGustavo F. Padovan return c; 144223691d75SGustavo F. Padovan } 1443b62f328bSVille Tervo 1444b62f328bSVille Tervo /* Closest match */ 14457eafc59eSMarcel Holtmann src_any = !bacmp(&c->src, BDADDR_ANY); 14467eafc59eSMarcel Holtmann dst_any = !bacmp(&c->dst, BDADDR_ANY); 1447c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1448c2287681SIdo Yariv (src_any && dst_any)) 144923691d75SGustavo F. Padovan c1 = c; 1450b62f328bSVille Tervo } 1451b62f328bSVille Tervo } 1452280f294fSGustavo F. Padovan 145323691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 1454b62f328bSVille Tervo 145523691d75SGustavo F. Padovan return c1; 1456b62f328bSVille Tervo } 1457b62f328bSVille Tervo 1458b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn) 1459b62f328bSVille Tervo { 1460cc8dba2bSMarcel Holtmann struct hci_conn *hcon = conn->hcon; 146123691d75SGustavo F. Padovan struct l2cap_chan *chan, *pchan; 1462cc8dba2bSMarcel Holtmann u8 dst_type; 1463b62f328bSVille Tervo 1464b62f328bSVille Tervo BT_DBG(""); 1465b62f328bSVille Tervo 1466b62f328bSVille Tervo /* Check if we have socket listening on cid */ 1467073d1cf3SJohan Hedberg pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT, 1468cc8dba2bSMarcel Holtmann &hcon->src, &hcon->dst); 146923691d75SGustavo F. Padovan if (!pchan) 1470b62f328bSVille Tervo return; 1471b62f328bSVille Tervo 147244f3b0fbSJohan Hedberg /* Client ATT sockets should override the server one */ 147344f3b0fbSJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, L2CAP_CID_ATT)) 147444f3b0fbSJohan Hedberg return; 147544f3b0fbSJohan Hedberg 1476cc8dba2bSMarcel Holtmann dst_type = bdaddr_type(hcon, hcon->dst_type); 1477cc8dba2bSMarcel Holtmann 1478cc8dba2bSMarcel Holtmann /* If device is blocked, do not create a channel for it */ 1479cc8dba2bSMarcel Holtmann if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, dst_type)) 1480cc8dba2bSMarcel Holtmann return; 1481cc8dba2bSMarcel Holtmann 14828ffb9290SGustavo Padovan l2cap_chan_lock(pchan); 148362f3a2cfSGustavo F. Padovan 148480b98027SGustavo Padovan chan = pchan->ops->new_connection(pchan); 148580808e43SGustavo F. Padovan if (!chan) 1486b62f328bSVille Tervo goto clean; 1487b62f328bSVille Tervo 14889f22398cSJohan Hedberg chan->dcid = L2CAP_CID_ATT; 14899f22398cSJohan Hedberg 1490cc8dba2bSMarcel Holtmann bacpy(&chan->src, &hcon->src); 1491cc8dba2bSMarcel Holtmann bacpy(&chan->dst, &hcon->dst); 1492cc8dba2bSMarcel Holtmann chan->src_type = bdaddr_type(hcon, hcon->src_type); 1493cc8dba2bSMarcel Holtmann chan->dst_type = dst_type; 1494b62f328bSVille Tervo 149544f3b0fbSJohan Hedberg __l2cap_chan_add(conn, chan); 149648454079SGustavo F. Padovan 1497b62f328bSVille Tervo clean: 14988ffb9290SGustavo Padovan l2cap_chan_unlock(pchan); 1499b62f328bSVille Tervo } 1500b62f328bSVille Tervo 15010a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn) 15020a708f8fSGustavo F. Padovan { 150348454079SGustavo F. Padovan struct l2cap_chan *chan; 1504cc110922SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 15050a708f8fSGustavo F. Padovan 15060a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 15070a708f8fSGustavo F. Padovan 1508d8729922SJohan Hedberg /* For outgoing pairing which doesn't necessarily have an 1509d8729922SJohan Hedberg * associated socket (e.g. mgmt_pair_device). 1510d8729922SJohan Hedberg */ 1511cc110922SVinicius Costa Gomes if (hcon->out && hcon->type == LE_LINK) 1512cc110922SVinicius Costa Gomes smp_conn_security(hcon, hcon->pending_sec_level); 1513160dc6acSVinicius Costa Gomes 15143df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 15150a708f8fSGustavo F. Padovan 151644f3b0fbSJohan Hedberg if (hcon->type == LE_LINK) 151744f3b0fbSJohan Hedberg l2cap_le_conn_ready(conn); 151844f3b0fbSJohan Hedberg 15193df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1520baa7e1faSGustavo F. Padovan 15216be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 15220a708f8fSGustavo F. Padovan 1523416fa752SAndrei Emeltchenko if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { 1524416fa752SAndrei Emeltchenko l2cap_chan_unlock(chan); 1525416fa752SAndrei Emeltchenko continue; 1526416fa752SAndrei Emeltchenko } 1527416fa752SAndrei Emeltchenko 1528cc110922SVinicius Costa Gomes if (hcon->type == LE_LINK) { 1529f1496deeSJohan Hedberg l2cap_le_start(chan); 153063128451SVinicius Costa Gomes } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 153174e75740SGustavo Padovan l2cap_chan_ready(chan); 1532b501d6a1SAnderson Briglia 15331c244f79SGustavo Padovan } else if (chan->state == BT_CONNECT) { 1534fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 15351c244f79SGustavo Padovan } 15360a708f8fSGustavo F. Padovan 15376be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 15380a708f8fSGustavo F. Padovan } 15390a708f8fSGustavo F. Padovan 15403df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 15410a708f8fSGustavo F. Padovan } 15420a708f8fSGustavo F. Padovan 15430a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */ 15440a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) 15450a708f8fSGustavo F. Padovan { 154648454079SGustavo F. Padovan struct l2cap_chan *chan; 15470a708f8fSGustavo F. Padovan 15480a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 15490a708f8fSGustavo F. Padovan 15503df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 15510a708f8fSGustavo F. Padovan 15523df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1553ecf61bdbSAndrei Emeltchenko if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) 15541d8b1fd5SGustavo Padovan l2cap_chan_set_err(chan, err); 15550a708f8fSGustavo F. Padovan } 15560a708f8fSGustavo F. Padovan 15573df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 15580a708f8fSGustavo F. Padovan } 15590a708f8fSGustavo F. Padovan 1560f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work) 15610a708f8fSGustavo F. Padovan { 1562f878fcadSGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 1563030013d8SGustavo F. Padovan info_timer.work); 15640a708f8fSGustavo F. Padovan 15650a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 15660a708f8fSGustavo F. Padovan conn->info_ident = 0; 15670a708f8fSGustavo F. Padovan 15680a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 15690a708f8fSGustavo F. Padovan } 15700a708f8fSGustavo F. Padovan 15712c8e1411SDavid Herrmann /* 15722c8e1411SDavid Herrmann * l2cap_user 15732c8e1411SDavid Herrmann * External modules can register l2cap_user objects on l2cap_conn. The ->probe 15742c8e1411SDavid Herrmann * callback is called during registration. The ->remove callback is called 15752c8e1411SDavid Herrmann * during unregistration. 15762c8e1411SDavid Herrmann * An l2cap_user object can either be explicitly unregistered or when the 15772c8e1411SDavid Herrmann * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon, 15782c8e1411SDavid Herrmann * l2cap->hchan, .. are valid as long as the remove callback hasn't been called. 15792c8e1411SDavid Herrmann * External modules must own a reference to the l2cap_conn object if they intend 15802c8e1411SDavid Herrmann * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at 15812c8e1411SDavid Herrmann * any time if they don't. 15822c8e1411SDavid Herrmann */ 15832c8e1411SDavid Herrmann 15842c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) 15852c8e1411SDavid Herrmann { 15862c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev; 15872c8e1411SDavid Herrmann int ret; 15882c8e1411SDavid Herrmann 15892c8e1411SDavid Herrmann /* We need to check whether l2cap_conn is registered. If it is not, we 15902c8e1411SDavid Herrmann * must not register the l2cap_user. l2cap_conn_del() is unregisters 15912c8e1411SDavid Herrmann * l2cap_conn objects, but doesn't provide its own locking. Instead, it 15922c8e1411SDavid Herrmann * relies on the parent hci_conn object to be locked. This itself relies 15932c8e1411SDavid Herrmann * on the hci_dev object to be locked. So we must lock the hci device 15942c8e1411SDavid Herrmann * here, too. */ 15952c8e1411SDavid Herrmann 15962c8e1411SDavid Herrmann hci_dev_lock(hdev); 15972c8e1411SDavid Herrmann 15982c8e1411SDavid Herrmann if (user->list.next || user->list.prev) { 15992c8e1411SDavid Herrmann ret = -EINVAL; 16002c8e1411SDavid Herrmann goto out_unlock; 16012c8e1411SDavid Herrmann } 16022c8e1411SDavid Herrmann 16032c8e1411SDavid Herrmann /* conn->hchan is NULL after l2cap_conn_del() was called */ 16042c8e1411SDavid Herrmann if (!conn->hchan) { 16052c8e1411SDavid Herrmann ret = -ENODEV; 16062c8e1411SDavid Herrmann goto out_unlock; 16072c8e1411SDavid Herrmann } 16082c8e1411SDavid Herrmann 16092c8e1411SDavid Herrmann ret = user->probe(conn, user); 16102c8e1411SDavid Herrmann if (ret) 16112c8e1411SDavid Herrmann goto out_unlock; 16122c8e1411SDavid Herrmann 16132c8e1411SDavid Herrmann list_add(&user->list, &conn->users); 16142c8e1411SDavid Herrmann ret = 0; 16152c8e1411SDavid Herrmann 16162c8e1411SDavid Herrmann out_unlock: 16172c8e1411SDavid Herrmann hci_dev_unlock(hdev); 16182c8e1411SDavid Herrmann return ret; 16192c8e1411SDavid Herrmann } 16202c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user); 16212c8e1411SDavid Herrmann 16222c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) 16232c8e1411SDavid Herrmann { 16242c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev; 16252c8e1411SDavid Herrmann 16262c8e1411SDavid Herrmann hci_dev_lock(hdev); 16272c8e1411SDavid Herrmann 16282c8e1411SDavid Herrmann if (!user->list.next || !user->list.prev) 16292c8e1411SDavid Herrmann goto out_unlock; 16302c8e1411SDavid Herrmann 16312c8e1411SDavid Herrmann list_del(&user->list); 16322c8e1411SDavid Herrmann user->list.next = NULL; 16332c8e1411SDavid Herrmann user->list.prev = NULL; 16342c8e1411SDavid Herrmann user->remove(conn, user); 16352c8e1411SDavid Herrmann 16362c8e1411SDavid Herrmann out_unlock: 16372c8e1411SDavid Herrmann hci_dev_unlock(hdev); 16382c8e1411SDavid Herrmann } 16392c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user); 16402c8e1411SDavid Herrmann 16412c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn) 16422c8e1411SDavid Herrmann { 16432c8e1411SDavid Herrmann struct l2cap_user *user; 16442c8e1411SDavid Herrmann 16452c8e1411SDavid Herrmann while (!list_empty(&conn->users)) { 16462c8e1411SDavid Herrmann user = list_first_entry(&conn->users, struct l2cap_user, list); 16472c8e1411SDavid Herrmann list_del(&user->list); 16482c8e1411SDavid Herrmann user->list.next = NULL; 16492c8e1411SDavid Herrmann user->list.prev = NULL; 16502c8e1411SDavid Herrmann user->remove(conn, user); 16512c8e1411SDavid Herrmann } 16522c8e1411SDavid Herrmann } 16532c8e1411SDavid Herrmann 16545d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err) 16555d3de7dfSVinicius Costa Gomes { 16565d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 16575d3de7dfSVinicius Costa Gomes struct l2cap_chan *chan, *l; 16585d3de7dfSVinicius Costa Gomes 16595d3de7dfSVinicius Costa Gomes if (!conn) 16605d3de7dfSVinicius Costa Gomes return; 16615d3de7dfSVinicius Costa Gomes 16625d3de7dfSVinicius Costa Gomes BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); 16635d3de7dfSVinicius Costa Gomes 16645d3de7dfSVinicius Costa Gomes kfree_skb(conn->rx_skb); 16655d3de7dfSVinicius Costa Gomes 16662c8e1411SDavid Herrmann l2cap_unregister_all_users(conn); 16672c8e1411SDavid Herrmann 16683df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 16693df91ea2SAndrei Emeltchenko 16705d3de7dfSVinicius Costa Gomes /* Kill channels */ 16715d3de7dfSVinicius Costa Gomes list_for_each_entry_safe(chan, l, &conn->chan_l, list) { 167261d6ef3eSMat Martineau l2cap_chan_hold(chan); 16736be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 16746be36555SAndrei Emeltchenko 16755d3de7dfSVinicius Costa Gomes l2cap_chan_del(chan, err); 16766be36555SAndrei Emeltchenko 16776be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16786be36555SAndrei Emeltchenko 167980b98027SGustavo Padovan chan->ops->close(chan); 168061d6ef3eSMat Martineau l2cap_chan_put(chan); 16815d3de7dfSVinicius Costa Gomes } 16825d3de7dfSVinicius Costa Gomes 16833df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 16843df91ea2SAndrei Emeltchenko 168573d80debSLuiz Augusto von Dentz hci_chan_del(conn->hchan); 168673d80debSLuiz Augusto von Dentz 16875d3de7dfSVinicius Costa Gomes if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1688127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->info_timer); 16895d3de7dfSVinicius Costa Gomes 169051a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) { 1691127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->security_timer); 16928aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 1693d26a2345SVinicius Costa Gomes } 16945d3de7dfSVinicius Costa Gomes 16955d3de7dfSVinicius Costa Gomes hcon->l2cap_data = NULL; 16969c903e37SDavid Herrmann conn->hchan = NULL; 16979c903e37SDavid Herrmann l2cap_conn_put(conn); 16985d3de7dfSVinicius Costa Gomes } 16995d3de7dfSVinicius Costa Gomes 17006c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work) 17015d3de7dfSVinicius Costa Gomes { 17026c9d42a1SGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 17036c9d42a1SGustavo F. Padovan security_timer.work); 17045d3de7dfSVinicius Costa Gomes 1705d06cc416SJohan Hedberg BT_DBG("conn %p", conn); 1706d06cc416SJohan Hedberg 1707d06cc416SJohan Hedberg if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) { 1708d06cc416SJohan Hedberg smp_chan_destroy(conn); 17095d3de7dfSVinicius Costa Gomes l2cap_conn_del(conn->hcon, ETIMEDOUT); 17105d3de7dfSVinicius Costa Gomes } 1711d06cc416SJohan Hedberg } 17125d3de7dfSVinicius Costa Gomes 1713baf43251SClaudio Takahasi static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) 17140a708f8fSGustavo F. Padovan { 17150a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 171673d80debSLuiz Augusto von Dentz struct hci_chan *hchan; 17170a708f8fSGustavo F. Padovan 1718baf43251SClaudio Takahasi if (conn) 17190a708f8fSGustavo F. Padovan return conn; 17200a708f8fSGustavo F. Padovan 172173d80debSLuiz Augusto von Dentz hchan = hci_chan_create(hcon); 172273d80debSLuiz Augusto von Dentz if (!hchan) 17230a708f8fSGustavo F. Padovan return NULL; 17240a708f8fSGustavo F. Padovan 17258bcde1f2SGustavo Padovan conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL); 172673d80debSLuiz Augusto von Dentz if (!conn) { 172773d80debSLuiz Augusto von Dentz hci_chan_del(hchan); 172873d80debSLuiz Augusto von Dentz return NULL; 172973d80debSLuiz Augusto von Dentz } 173073d80debSLuiz Augusto von Dentz 17319c903e37SDavid Herrmann kref_init(&conn->ref); 17320a708f8fSGustavo F. Padovan hcon->l2cap_data = conn; 17330a708f8fSGustavo F. Padovan conn->hcon = hcon; 17349c903e37SDavid Herrmann hci_conn_get(conn->hcon); 173573d80debSLuiz Augusto von Dentz conn->hchan = hchan; 17360a708f8fSGustavo F. Padovan 173773d80debSLuiz Augusto von Dentz BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); 17380a708f8fSGustavo F. Padovan 1739dcc042d5SAndrei Emeltchenko switch (hcon->type) { 1740dcc042d5SAndrei Emeltchenko case LE_LINK: 1741dcc042d5SAndrei Emeltchenko if (hcon->hdev->le_mtu) { 1742acd7d370SVille Tervo conn->mtu = hcon->hdev->le_mtu; 1743dcc042d5SAndrei Emeltchenko break; 1744dcc042d5SAndrei Emeltchenko } 1745dcc042d5SAndrei Emeltchenko /* fall through */ 1746dcc042d5SAndrei Emeltchenko default: 17470a708f8fSGustavo F. Padovan conn->mtu = hcon->hdev->acl_mtu; 1748dcc042d5SAndrei Emeltchenko break; 1749dcc042d5SAndrei Emeltchenko } 1750acd7d370SVille Tervo 17510a708f8fSGustavo F. Padovan conn->feat_mask = 0; 17520a708f8fSGustavo F. Padovan 1753848566b3SMarcel Holtmann if (hcon->type == ACL_LINK) 1754848566b3SMarcel Holtmann conn->hs_enabled = test_bit(HCI_HS_ENABLED, 1755848566b3SMarcel Holtmann &hcon->hdev->dev_flags); 1756848566b3SMarcel Holtmann 17570a708f8fSGustavo F. Padovan spin_lock_init(&conn->lock); 17583df91ea2SAndrei Emeltchenko mutex_init(&conn->chan_lock); 1759baa7e1faSGustavo F. Padovan 1760baa7e1faSGustavo F. Padovan INIT_LIST_HEAD(&conn->chan_l); 17612c8e1411SDavid Herrmann INIT_LIST_HEAD(&conn->users); 17620a708f8fSGustavo F. Padovan 17635d3de7dfSVinicius Costa Gomes if (hcon->type == LE_LINK) 17646c9d42a1SGustavo F. Padovan INIT_DELAYED_WORK(&conn->security_timer, security_timeout); 17655d3de7dfSVinicius Costa Gomes else 1766030013d8SGustavo F. Padovan INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); 17670a708f8fSGustavo F. Padovan 17689f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 17690a708f8fSGustavo F. Padovan 17700a708f8fSGustavo F. Padovan return conn; 17710a708f8fSGustavo F. Padovan } 17720a708f8fSGustavo F. Padovan 17739c903e37SDavid Herrmann static void l2cap_conn_free(struct kref *ref) 17749c903e37SDavid Herrmann { 17759c903e37SDavid Herrmann struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref); 17769c903e37SDavid Herrmann 17779c903e37SDavid Herrmann hci_conn_put(conn->hcon); 17789c903e37SDavid Herrmann kfree(conn); 17799c903e37SDavid Herrmann } 17809c903e37SDavid Herrmann 17819c903e37SDavid Herrmann void l2cap_conn_get(struct l2cap_conn *conn) 17829c903e37SDavid Herrmann { 17839c903e37SDavid Herrmann kref_get(&conn->ref); 17849c903e37SDavid Herrmann } 17859c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_get); 17869c903e37SDavid Herrmann 17879c903e37SDavid Herrmann void l2cap_conn_put(struct l2cap_conn *conn) 17889c903e37SDavid Herrmann { 17899c903e37SDavid Herrmann kref_put(&conn->ref, l2cap_conn_free); 17909c903e37SDavid Herrmann } 17919c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_put); 17929c903e37SDavid Herrmann 17930a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */ 17940a708f8fSGustavo F. Padovan 1795c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr. 17960a708f8fSGustavo F. Padovan * Returns closest match. 17970a708f8fSGustavo F. Padovan */ 1798c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, 1799c2287681SIdo Yariv bdaddr_t *src, 1800bf20fd4eSJohan Hedberg bdaddr_t *dst, 1801bf20fd4eSJohan Hedberg u8 link_type) 18020a708f8fSGustavo F. Padovan { 180323691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 18040a708f8fSGustavo F. Padovan 180523691d75SGustavo F. Padovan read_lock(&chan_list_lock); 18060a708f8fSGustavo F. Padovan 180723691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 180889bc500eSGustavo F. Padovan if (state && c->state != state) 18090a708f8fSGustavo F. Padovan continue; 18100a708f8fSGustavo F. Padovan 1811bf20fd4eSJohan Hedberg if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR) 1812bf20fd4eSJohan Hedberg continue; 1813bf20fd4eSJohan Hedberg 1814bf20fd4eSJohan Hedberg if (link_type == LE_LINK && c->src_type == BDADDR_BREDR) 1815bf20fd4eSJohan Hedberg continue; 1816bf20fd4eSJohan Hedberg 181723691d75SGustavo F. Padovan if (c->psm == psm) { 1818c2287681SIdo Yariv int src_match, dst_match; 1819c2287681SIdo Yariv int src_any, dst_any; 1820c2287681SIdo Yariv 18210a708f8fSGustavo F. Padovan /* Exact match. */ 18227eafc59eSMarcel Holtmann src_match = !bacmp(&c->src, src); 18237eafc59eSMarcel Holtmann dst_match = !bacmp(&c->dst, dst); 1824c2287681SIdo Yariv if (src_match && dst_match) { 1825a7567b20SJohannes Berg read_unlock(&chan_list_lock); 182623691d75SGustavo F. Padovan return c; 182723691d75SGustavo F. Padovan } 18280a708f8fSGustavo F. Padovan 18290a708f8fSGustavo F. Padovan /* Closest match */ 18307eafc59eSMarcel Holtmann src_any = !bacmp(&c->src, BDADDR_ANY); 18317eafc59eSMarcel Holtmann dst_any = !bacmp(&c->dst, BDADDR_ANY); 1832c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1833c2287681SIdo Yariv (src_any && dst_any)) 183423691d75SGustavo F. Padovan c1 = c; 18350a708f8fSGustavo F. Padovan } 18360a708f8fSGustavo F. Padovan } 18370a708f8fSGustavo F. Padovan 183823691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 18390a708f8fSGustavo F. Padovan 184023691d75SGustavo F. Padovan return c1; 18410a708f8fSGustavo F. Padovan } 18420a708f8fSGustavo F. Padovan 18438e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, 18448e9f9892SAndre Guedes bdaddr_t *dst, u8 dst_type) 18450a708f8fSGustavo F. Padovan { 18460a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 18470a708f8fSGustavo F. Padovan struct hci_conn *hcon; 18480a708f8fSGustavo F. Padovan struct hci_dev *hdev; 18490a708f8fSGustavo F. Padovan __u8 auth_type; 18500a708f8fSGustavo F. Padovan int err; 18510a708f8fSGustavo F. Padovan 18527eafc59eSMarcel Holtmann BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst, 1853ab19516aSSyam Sidhardhan dst_type, __le16_to_cpu(psm)); 18540a708f8fSGustavo F. Padovan 18557eafc59eSMarcel Holtmann hdev = hci_get_route(dst, &chan->src); 18560a708f8fSGustavo F. Padovan if (!hdev) 18570a708f8fSGustavo F. Padovan return -EHOSTUNREACH; 18580a708f8fSGustavo F. Padovan 185909fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 18600a708f8fSGustavo F. Padovan 18616be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 186203a00194SGustavo F. Padovan 186303a00194SGustavo F. Padovan /* PSM must be odd and lsb of upper byte must be 0 */ 186403a00194SGustavo F. Padovan if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid && 186503a00194SGustavo F. Padovan chan->chan_type != L2CAP_CHAN_RAW) { 186603a00194SGustavo F. Padovan err = -EINVAL; 186703a00194SGustavo F. Padovan goto done; 186803a00194SGustavo F. Padovan } 186903a00194SGustavo F. Padovan 187003a00194SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) { 187103a00194SGustavo F. Padovan err = -EINVAL; 187203a00194SGustavo F. Padovan goto done; 187303a00194SGustavo F. Padovan } 187403a00194SGustavo F. Padovan 187503a00194SGustavo F. Padovan switch (chan->mode) { 187603a00194SGustavo F. Padovan case L2CAP_MODE_BASIC: 187738319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 187803a00194SGustavo F. Padovan break; 187903a00194SGustavo F. Padovan case L2CAP_MODE_ERTM: 188003a00194SGustavo F. Padovan case L2CAP_MODE_STREAMING: 188103a00194SGustavo F. Padovan if (!disable_ertm) 188203a00194SGustavo F. Padovan break; 188303a00194SGustavo F. Padovan /* fall through */ 188403a00194SGustavo F. Padovan default: 188503a00194SGustavo F. Padovan err = -ENOTSUPP; 188603a00194SGustavo F. Padovan goto done; 188703a00194SGustavo F. Padovan } 188803a00194SGustavo F. Padovan 18890797e01dSGustavo Padovan switch (chan->state) { 189003a00194SGustavo F. Padovan case BT_CONNECT: 189103a00194SGustavo F. Padovan case BT_CONNECT2: 189203a00194SGustavo F. Padovan case BT_CONFIG: 189303a00194SGustavo F. Padovan /* Already connecting */ 189403a00194SGustavo F. Padovan err = 0; 189503a00194SGustavo F. Padovan goto done; 189603a00194SGustavo F. Padovan 189703a00194SGustavo F. Padovan case BT_CONNECTED: 189803a00194SGustavo F. Padovan /* Already connected */ 189903a00194SGustavo F. Padovan err = -EISCONN; 190003a00194SGustavo F. Padovan goto done; 190103a00194SGustavo F. Padovan 190203a00194SGustavo F. Padovan case BT_OPEN: 190303a00194SGustavo F. Padovan case BT_BOUND: 190403a00194SGustavo F. Padovan /* Can connect */ 190503a00194SGustavo F. Padovan break; 190603a00194SGustavo F. Padovan 190703a00194SGustavo F. Padovan default: 190803a00194SGustavo F. Padovan err = -EBADFD; 190903a00194SGustavo F. Padovan goto done; 191003a00194SGustavo F. Padovan } 191103a00194SGustavo F. Padovan 191203a00194SGustavo F. Padovan /* Set destination address and psm */ 19137eafc59eSMarcel Holtmann bacpy(&chan->dst, dst); 19144f1654e0SMarcel Holtmann chan->dst_type = dst_type; 19156be36555SAndrei Emeltchenko 191603a00194SGustavo F. Padovan chan->psm = psm; 191703a00194SGustavo F. Padovan chan->dcid = cid; 19180a708f8fSGustavo F. Padovan 19194343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 19200a708f8fSGustavo F. Padovan 1921f224ca5fSJohan Hedberg if (bdaddr_type_is_le(dst_type)) 19228e9f9892SAndre Guedes hcon = hci_connect(hdev, LE_LINK, dst, dst_type, 19234343478fSGustavo F. Padovan chan->sec_level, auth_type); 1924acd7d370SVille Tervo else 19258e9f9892SAndre Guedes hcon = hci_connect(hdev, ACL_LINK, dst, dst_type, 19264343478fSGustavo F. Padovan chan->sec_level, auth_type); 1927acd7d370SVille Tervo 192830e76272SVille Tervo if (IS_ERR(hcon)) { 192930e76272SVille Tervo err = PTR_ERR(hcon); 19300a708f8fSGustavo F. Padovan goto done; 193130e76272SVille Tervo } 19320a708f8fSGustavo F. Padovan 1933baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon); 19340a708f8fSGustavo F. Padovan if (!conn) { 193576a68ba0SDavid Herrmann hci_conn_drop(hcon); 193630e76272SVille Tervo err = -ENOMEM; 19370a708f8fSGustavo F. Padovan goto done; 19380a708f8fSGustavo F. Padovan } 19390a708f8fSGustavo F. Padovan 1940141d5706SJohan Hedberg if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { 194176a68ba0SDavid Herrmann hci_conn_drop(hcon); 1942141d5706SJohan Hedberg err = -EBUSY; 19439f0caeb1SVinicius Costa Gomes goto done; 19449f0caeb1SVinicius Costa Gomes } 19459f0caeb1SVinicius Costa Gomes 19460a708f8fSGustavo F. Padovan /* Update source addr of the socket */ 19477eafc59eSMarcel Holtmann bacpy(&chan->src, &hcon->src); 19484f1654e0SMarcel Holtmann chan->src_type = bdaddr_type(hcon, hcon->src_type); 19490a708f8fSGustavo F. Padovan 19506be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 195148454079SGustavo F. Padovan l2cap_chan_add(conn, chan); 19526be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 195348454079SGustavo F. Padovan 19545ee9891dSJohan Hedberg /* l2cap_chan_add takes its own ref so we can drop this one */ 19555ee9891dSJohan Hedberg hci_conn_drop(hcon); 19565ee9891dSJohan Hedberg 19576be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECT); 19588d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 19590a708f8fSGustavo F. Padovan 19600a708f8fSGustavo F. Padovan if (hcon->state == BT_CONNECTED) { 1961715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1962c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 1963d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) 19646be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECTED); 19650a708f8fSGustavo F. Padovan } else 1966fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 19670a708f8fSGustavo F. Padovan } 19680a708f8fSGustavo F. Padovan 196930e76272SVille Tervo err = 0; 197030e76272SVille Tervo 19710a708f8fSGustavo F. Padovan done: 19726be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 197309fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 19740a708f8fSGustavo F. Padovan hci_dev_put(hdev); 19750a708f8fSGustavo F. Padovan return err; 19760a708f8fSGustavo F. Padovan } 19770a708f8fSGustavo F. Padovan 1978721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work) 19790a708f8fSGustavo F. Padovan { 1980721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1981721c4181SGustavo F. Padovan monitor_timer.work); 19820a708f8fSGustavo F. Padovan 1983525cd185SGustavo F. Padovan BT_DBG("chan %p", chan); 19840a708f8fSGustavo F. Padovan 19856be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 19866be36555SAndrei Emeltchenko 198780909e04SMat Martineau if (!chan->conn) { 19886be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 19898d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 19900a708f8fSGustavo F. Padovan return; 19910a708f8fSGustavo F. Padovan } 19920a708f8fSGustavo F. Padovan 1993401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO); 19940a708f8fSGustavo F. Padovan 19956be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 19968d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 19970a708f8fSGustavo F. Padovan } 19980a708f8fSGustavo F. Padovan 1999721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work) 20000a708f8fSGustavo F. Padovan { 2001721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 2002721c4181SGustavo F. Padovan retrans_timer.work); 20030a708f8fSGustavo F. Padovan 200449208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 20050a708f8fSGustavo F. Padovan 20066be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 20076be36555SAndrei Emeltchenko 200880909e04SMat Martineau if (!chan->conn) { 200980909e04SMat Martineau l2cap_chan_unlock(chan); 201080909e04SMat Martineau l2cap_chan_put(chan); 201180909e04SMat Martineau return; 201280909e04SMat Martineau } 20130a708f8fSGustavo F. Padovan 2014401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO); 20156be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 20168d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 20170a708f8fSGustavo F. Padovan } 20180a708f8fSGustavo F. Padovan 2019d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan, 20203733937dSMat Martineau struct sk_buff_head *skbs) 20210a708f8fSGustavo F. Padovan { 20220a708f8fSGustavo F. Padovan struct sk_buff *skb; 20233733937dSMat Martineau struct l2cap_ctrl *control; 20240a708f8fSGustavo F. Padovan 20253733937dSMat Martineau BT_DBG("chan %p, skbs %p", chan, skbs); 20263733937dSMat Martineau 2027b99e13adSMat Martineau if (__chan_is_moving(chan)) 2028b99e13adSMat Martineau return; 2029b99e13adSMat Martineau 20303733937dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 20313733937dSMat Martineau 20323733937dSMat Martineau while (!skb_queue_empty(&chan->tx_q)) { 20333733937dSMat Martineau 20343733937dSMat Martineau skb = skb_dequeue(&chan->tx_q); 20353733937dSMat Martineau 20363733937dSMat Martineau bt_cb(skb)->control.retries = 1; 20373733937dSMat Martineau control = &bt_cb(skb)->control; 20383733937dSMat Martineau 20393733937dSMat Martineau control->reqseq = 0; 20403733937dSMat Martineau control->txseq = chan->next_tx_seq; 20413733937dSMat Martineau 20423733937dSMat Martineau __pack_control(chan, control, skb); 20430a708f8fSGustavo F. Padovan 204447d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 20453733937dSMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 20463733937dSMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 20470a708f8fSGustavo F. Padovan } 20480a708f8fSGustavo F. Padovan 20494343478fSGustavo F. Padovan l2cap_do_send(chan, skb); 20500a708f8fSGustavo F. Padovan 2051b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 20523733937dSMat Martineau 2053836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 20543733937dSMat Martineau chan->frames_sent++; 20550a708f8fSGustavo F. Padovan } 20560a708f8fSGustavo F. Padovan } 20570a708f8fSGustavo F. Padovan 205867c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan) 20590a708f8fSGustavo F. Padovan { 20600a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 206118a48e76SMat Martineau struct l2cap_ctrl *control; 206218a48e76SMat Martineau int sent = 0; 206318a48e76SMat Martineau 206418a48e76SMat Martineau BT_DBG("chan %p", chan); 20650a708f8fSGustavo F. Padovan 206689bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 20670a708f8fSGustavo F. Padovan return -ENOTCONN; 20680a708f8fSGustavo F. Padovan 206994122bbeSMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 207094122bbeSMat Martineau return 0; 207194122bbeSMat Martineau 2072b99e13adSMat Martineau if (__chan_is_moving(chan)) 2073b99e13adSMat Martineau return 0; 2074b99e13adSMat Martineau 207518a48e76SMat Martineau while (chan->tx_send_head && 207618a48e76SMat Martineau chan->unacked_frames < chan->remote_tx_win && 207718a48e76SMat Martineau chan->tx_state == L2CAP_TX_STATE_XMIT) { 20780a708f8fSGustavo F. Padovan 207918a48e76SMat Martineau skb = chan->tx_send_head; 20800a708f8fSGustavo F. Padovan 208118a48e76SMat Martineau bt_cb(skb)->control.retries = 1; 208218a48e76SMat Martineau control = &bt_cb(skb)->control; 20830a708f8fSGustavo F. Padovan 2084e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 208518a48e76SMat Martineau control->final = 1; 2086e2ab4353SGustavo F. Padovan 208718a48e76SMat Martineau control->reqseq = chan->buffer_seq; 208818a48e76SMat Martineau chan->last_acked_seq = chan->buffer_seq; 208918a48e76SMat Martineau control->txseq = chan->next_tx_seq; 20900a708f8fSGustavo F. Padovan 209118a48e76SMat Martineau __pack_control(chan, control, skb); 20920a708f8fSGustavo F. Padovan 209347d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 209418a48e76SMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 209518a48e76SMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 20960a708f8fSGustavo F. Padovan } 20970a708f8fSGustavo F. Padovan 209818a48e76SMat Martineau /* Clone after data has been modified. Data is assumed to be 209918a48e76SMat Martineau read-only (for locking purposes) on cloned sk_buffs. 210018a48e76SMat Martineau */ 210118a48e76SMat Martineau tx_skb = skb_clone(skb, GFP_KERNEL); 210218a48e76SMat Martineau 210318a48e76SMat Martineau if (!tx_skb) 210418a48e76SMat Martineau break; 21050a708f8fSGustavo F. Padovan 21061a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 21070a708f8fSGustavo F. Padovan 2108836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 21096a026610SGustavo F. Padovan chan->unacked_frames++; 21106a026610SGustavo F. Padovan chan->frames_sent++; 211118a48e76SMat Martineau sent++; 21120a708f8fSGustavo F. Padovan 211358d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 211458d35f87SGustavo F. Padovan chan->tx_send_head = NULL; 21150a708f8fSGustavo F. Padovan else 211658d35f87SGustavo F. Padovan chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); 211718a48e76SMat Martineau 211818a48e76SMat Martineau l2cap_do_send(chan, tx_skb); 2119b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 21200a708f8fSGustavo F. Padovan } 21210a708f8fSGustavo F. Padovan 2122b4400672SAndrei Emeltchenko BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent, 2123b4400672SAndrei Emeltchenko chan->unacked_frames, skb_queue_len(&chan->tx_q)); 212418a48e76SMat Martineau 212518a48e76SMat Martineau return sent; 21260a708f8fSGustavo F. Padovan } 21270a708f8fSGustavo F. Padovan 2128e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan) 2129e1fbd4c1SMat Martineau { 2130e1fbd4c1SMat Martineau struct l2cap_ctrl control; 2131e1fbd4c1SMat Martineau struct sk_buff *skb; 2132e1fbd4c1SMat Martineau struct sk_buff *tx_skb; 2133e1fbd4c1SMat Martineau u16 seq; 2134e1fbd4c1SMat Martineau 2135e1fbd4c1SMat Martineau BT_DBG("chan %p", chan); 2136e1fbd4c1SMat Martineau 2137e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 2138e1fbd4c1SMat Martineau return; 2139e1fbd4c1SMat Martineau 2140b99e13adSMat Martineau if (__chan_is_moving(chan)) 2141b99e13adSMat Martineau return; 2142b99e13adSMat Martineau 2143e1fbd4c1SMat Martineau while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) { 2144e1fbd4c1SMat Martineau seq = l2cap_seq_list_pop(&chan->retrans_list); 2145e1fbd4c1SMat Martineau 2146e1fbd4c1SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq); 2147e1fbd4c1SMat Martineau if (!skb) { 2148e1fbd4c1SMat Martineau BT_DBG("Error: Can't retransmit seq %d, frame missing", 2149e1fbd4c1SMat Martineau seq); 2150e1fbd4c1SMat Martineau continue; 2151e1fbd4c1SMat Martineau } 2152e1fbd4c1SMat Martineau 2153e1fbd4c1SMat Martineau bt_cb(skb)->control.retries++; 2154e1fbd4c1SMat Martineau control = bt_cb(skb)->control; 2155e1fbd4c1SMat Martineau 2156e1fbd4c1SMat Martineau if (chan->max_tx != 0 && 2157e1fbd4c1SMat Martineau bt_cb(skb)->control.retries > chan->max_tx) { 2158e1fbd4c1SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 21595e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 2160e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2161e1fbd4c1SMat Martineau break; 2162e1fbd4c1SMat Martineau } 2163e1fbd4c1SMat Martineau 2164e1fbd4c1SMat Martineau control.reqseq = chan->buffer_seq; 2165e1fbd4c1SMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 2166e1fbd4c1SMat Martineau control.final = 1; 2167e1fbd4c1SMat Martineau else 2168e1fbd4c1SMat Martineau control.final = 0; 2169e1fbd4c1SMat Martineau 2170e1fbd4c1SMat Martineau if (skb_cloned(skb)) { 2171e1fbd4c1SMat Martineau /* Cloned sk_buffs are read-only, so we need a 2172e1fbd4c1SMat Martineau * writeable copy 2173e1fbd4c1SMat Martineau */ 21748bcde1f2SGustavo Padovan tx_skb = skb_copy(skb, GFP_KERNEL); 2175e1fbd4c1SMat Martineau } else { 21768bcde1f2SGustavo Padovan tx_skb = skb_clone(skb, GFP_KERNEL); 2177e1fbd4c1SMat Martineau } 2178e1fbd4c1SMat Martineau 2179e1fbd4c1SMat Martineau if (!tx_skb) { 2180e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2181e1fbd4c1SMat Martineau break; 2182e1fbd4c1SMat Martineau } 2183e1fbd4c1SMat Martineau 2184e1fbd4c1SMat Martineau /* Update skb contents */ 2185e1fbd4c1SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 2186e1fbd4c1SMat Martineau put_unaligned_le32(__pack_extended_control(&control), 2187e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 2188e1fbd4c1SMat Martineau } else { 2189e1fbd4c1SMat Martineau put_unaligned_le16(__pack_enhanced_control(&control), 2190e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 2191e1fbd4c1SMat Martineau } 2192e1fbd4c1SMat Martineau 2193e1fbd4c1SMat Martineau if (chan->fcs == L2CAP_FCS_CRC16) { 2194e1fbd4c1SMat Martineau u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len); 2195e1fbd4c1SMat Martineau put_unaligned_le16(fcs, skb_put(tx_skb, 2196e1fbd4c1SMat Martineau L2CAP_FCS_SIZE)); 2197e1fbd4c1SMat Martineau } 2198e1fbd4c1SMat Martineau 2199e1fbd4c1SMat Martineau l2cap_do_send(chan, tx_skb); 2200e1fbd4c1SMat Martineau 2201e1fbd4c1SMat Martineau BT_DBG("Resent txseq %d", control.txseq); 2202e1fbd4c1SMat Martineau 2203e1fbd4c1SMat Martineau chan->last_acked_seq = chan->buffer_seq; 2204e1fbd4c1SMat Martineau } 2205e1fbd4c1SMat Martineau } 2206e1fbd4c1SMat Martineau 2207f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan, 2208f80842a8SMat Martineau struct l2cap_ctrl *control) 2209f80842a8SMat Martineau { 2210f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2211f80842a8SMat Martineau 2212f80842a8SMat Martineau l2cap_seq_list_append(&chan->retrans_list, control->reqseq); 2213f80842a8SMat Martineau l2cap_ertm_resend(chan); 2214f80842a8SMat Martineau } 2215f80842a8SMat Martineau 2216d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan, 2217d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 2218d2a7ac5dSMat Martineau { 2219e1fbd4c1SMat Martineau struct sk_buff *skb; 2220e1fbd4c1SMat Martineau 2221e1fbd4c1SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2222e1fbd4c1SMat Martineau 2223e1fbd4c1SMat Martineau if (control->poll) 2224e1fbd4c1SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 2225e1fbd4c1SMat Martineau 2226e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2227e1fbd4c1SMat Martineau 2228e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 2229e1fbd4c1SMat Martineau return; 2230e1fbd4c1SMat Martineau 2231e1fbd4c1SMat Martineau if (chan->unacked_frames) { 2232e1fbd4c1SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 2233e1fbd4c1SMat Martineau if (bt_cb(skb)->control.txseq == control->reqseq || 2234e1fbd4c1SMat Martineau skb == chan->tx_send_head) 2235e1fbd4c1SMat Martineau break; 2236e1fbd4c1SMat Martineau } 2237e1fbd4c1SMat Martineau 2238e1fbd4c1SMat Martineau skb_queue_walk_from(&chan->tx_q, skb) { 2239e1fbd4c1SMat Martineau if (skb == chan->tx_send_head) 2240e1fbd4c1SMat Martineau break; 2241e1fbd4c1SMat Martineau 2242e1fbd4c1SMat Martineau l2cap_seq_list_append(&chan->retrans_list, 2243e1fbd4c1SMat Martineau bt_cb(skb)->control.txseq); 2244e1fbd4c1SMat Martineau } 2245e1fbd4c1SMat Martineau 2246e1fbd4c1SMat Martineau l2cap_ertm_resend(chan); 2247e1fbd4c1SMat Martineau } 2248d2a7ac5dSMat Martineau } 2249d2a7ac5dSMat Martineau 2250b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan) 2251b17e73bbSSzymon Janc { 22520a0aba42SMat Martineau struct l2cap_ctrl control; 22530a0aba42SMat Martineau u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq, 22540a0aba42SMat Martineau chan->last_acked_seq); 22550a0aba42SMat Martineau int threshold; 22560a0aba42SMat Martineau 22570a0aba42SMat Martineau BT_DBG("chan %p last_acked_seq %d buffer_seq %d", 22580a0aba42SMat Martineau chan, chan->last_acked_seq, chan->buffer_seq); 22590a0aba42SMat Martineau 22600a0aba42SMat Martineau memset(&control, 0, sizeof(control)); 22610a0aba42SMat Martineau control.sframe = 1; 22620a0aba42SMat Martineau 22630a0aba42SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 22640a0aba42SMat Martineau chan->rx_state == L2CAP_RX_STATE_RECV) { 2265b17e73bbSSzymon Janc __clear_ack_timer(chan); 22660a0aba42SMat Martineau control.super = L2CAP_SUPER_RNR; 22670a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 22680a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 22690a0aba42SMat Martineau } else { 22700a0aba42SMat Martineau if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) { 22710a0aba42SMat Martineau l2cap_ertm_send(chan); 22720a0aba42SMat Martineau /* If any i-frames were sent, they included an ack */ 22730a0aba42SMat Martineau if (chan->buffer_seq == chan->last_acked_seq) 22740a0aba42SMat Martineau frames_to_ack = 0; 22750a0aba42SMat Martineau } 22760a0aba42SMat Martineau 2277c20f8e35SMat Martineau /* Ack now if the window is 3/4ths full. 22780a0aba42SMat Martineau * Calculate without mul or div 22790a0aba42SMat Martineau */ 2280c20f8e35SMat Martineau threshold = chan->ack_win; 22810a0aba42SMat Martineau threshold += threshold << 1; 22820a0aba42SMat Martineau threshold >>= 2; 22830a0aba42SMat Martineau 2284b4400672SAndrei Emeltchenko BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack, 22850a0aba42SMat Martineau threshold); 22860a0aba42SMat Martineau 22870a0aba42SMat Martineau if (frames_to_ack >= threshold) { 22880a0aba42SMat Martineau __clear_ack_timer(chan); 22890a0aba42SMat Martineau control.super = L2CAP_SUPER_RR; 22900a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 22910a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 22920a0aba42SMat Martineau frames_to_ack = 0; 22930a0aba42SMat Martineau } 22940a0aba42SMat Martineau 22950a0aba42SMat Martineau if (frames_to_ack) 22960a0aba42SMat Martineau __set_ack_timer(chan); 22970a0aba42SMat Martineau } 2298b17e73bbSSzymon Janc } 2299b17e73bbSSzymon Janc 230004124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, 230104124681SGustavo F. Padovan struct msghdr *msg, int len, 230204124681SGustavo F. Padovan int count, struct sk_buff *skb) 23030a708f8fSGustavo F. Padovan { 23040952a57aSAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 23050a708f8fSGustavo F. Padovan struct sk_buff **frag; 230690338947SGustavo Padovan int sent = 0; 23070a708f8fSGustavo F. Padovan 23080a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) 23090a708f8fSGustavo F. Padovan return -EFAULT; 23100a708f8fSGustavo F. Padovan 23110a708f8fSGustavo F. Padovan sent += count; 23120a708f8fSGustavo F. Padovan len -= count; 23130a708f8fSGustavo F. Padovan 23140a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 23150a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 23160a708f8fSGustavo F. Padovan while (len) { 2317fbe00700SGustavo Padovan struct sk_buff *tmp; 2318fbe00700SGustavo Padovan 23190a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 23200a708f8fSGustavo F. Padovan 2321fbe00700SGustavo Padovan tmp = chan->ops->alloc_skb(chan, count, 232290338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 2323fbe00700SGustavo Padovan if (IS_ERR(tmp)) 2324fbe00700SGustavo Padovan return PTR_ERR(tmp); 23252f7719ceSAndrei Emeltchenko 2326fbe00700SGustavo Padovan *frag = tmp; 2327fbe00700SGustavo Padovan 23280a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) 23290a708f8fSGustavo F. Padovan return -EFAULT; 23300a708f8fSGustavo F. Padovan 23315e59b791SLuiz Augusto von Dentz (*frag)->priority = skb->priority; 23325e59b791SLuiz Augusto von Dentz 23330a708f8fSGustavo F. Padovan sent += count; 23340a708f8fSGustavo F. Padovan len -= count; 23350a708f8fSGustavo F. Padovan 23362d0ed3d5SGustavo Padovan skb->len += (*frag)->len; 23372d0ed3d5SGustavo Padovan skb->data_len += (*frag)->len; 23382d0ed3d5SGustavo Padovan 23390a708f8fSGustavo F. Padovan frag = &(*frag)->next; 23400a708f8fSGustavo F. Padovan } 23410a708f8fSGustavo F. Padovan 23420a708f8fSGustavo F. Padovan return sent; 23430a708f8fSGustavo F. Padovan } 23440a708f8fSGustavo F. Padovan 23455e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, 23465e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 23475e59b791SLuiz Augusto von Dentz u32 priority) 23480a708f8fSGustavo F. Padovan { 23498c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 23500a708f8fSGustavo F. Padovan struct sk_buff *skb; 235103a51213SAndrei Emeltchenko int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; 23520a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 23530a708f8fSGustavo F. Padovan 235443b1b8dfSMarcel Holtmann BT_DBG("chan %p psm 0x%2.2x len %zu priority %u", chan, 235543b1b8dfSMarcel Holtmann __le16_to_cpu(chan->psm), len, priority); 23560a708f8fSGustavo F. Padovan 23570a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 23582f7719ceSAndrei Emeltchenko 23592f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 236090338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 236190338947SGustavo Padovan if (IS_ERR(skb)) 236290338947SGustavo Padovan return skb; 23630a708f8fSGustavo F. Padovan 23645e59b791SLuiz Augusto von Dentz skb->priority = priority; 23655e59b791SLuiz Augusto von Dentz 23660a708f8fSGustavo F. Padovan /* Create L2CAP header */ 23670a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2368fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 2369daf6a78cSAndrei Emeltchenko lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); 237043b1b8dfSMarcel Holtmann put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE)); 23710a708f8fSGustavo F. Padovan 23720952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 23730a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 23740a708f8fSGustavo F. Padovan kfree_skb(skb); 23750a708f8fSGustavo F. Padovan return ERR_PTR(err); 23760a708f8fSGustavo F. Padovan } 23770a708f8fSGustavo F. Padovan return skb; 23780a708f8fSGustavo F. Padovan } 23790a708f8fSGustavo F. Padovan 23805e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, 23815e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 23825e59b791SLuiz Augusto von Dentz u32 priority) 23830a708f8fSGustavo F. Padovan { 23848c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 23850a708f8fSGustavo F. Padovan struct sk_buff *skb; 2386f2ba7faeSGustavo Padovan int err, count; 23870a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 23880a708f8fSGustavo F. Padovan 2389b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 23900a708f8fSGustavo F. Padovan 2391f2ba7faeSGustavo Padovan count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); 23922f7719ceSAndrei Emeltchenko 2393f2ba7faeSGustavo Padovan skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE, 239490338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 239590338947SGustavo Padovan if (IS_ERR(skb)) 239690338947SGustavo Padovan return skb; 23970a708f8fSGustavo F. Padovan 23985e59b791SLuiz Augusto von Dentz skb->priority = priority; 23995e59b791SLuiz Augusto von Dentz 24000a708f8fSGustavo F. Padovan /* Create L2CAP header */ 24010a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2402fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 24036ff9b5efSGustavo Padovan lh->len = cpu_to_le16(len); 24040a708f8fSGustavo F. Padovan 24050952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 24060a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 24070a708f8fSGustavo F. Padovan kfree_skb(skb); 24080a708f8fSGustavo F. Padovan return ERR_PTR(err); 24090a708f8fSGustavo F. Padovan } 24100a708f8fSGustavo F. Padovan return skb; 24110a708f8fSGustavo F. Padovan } 24120a708f8fSGustavo F. Padovan 2413ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, 2414ab0ff76dSLuiz Augusto von Dentz struct msghdr *msg, size_t len, 241594122bbeSMat Martineau u16 sdulen) 24160a708f8fSGustavo F. Padovan { 24178c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 24180a708f8fSGustavo F. Padovan struct sk_buff *skb; 2419e4ca6d98SAndrei Emeltchenko int err, count, hlen; 24200a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 24210a708f8fSGustavo F. Padovan 2422b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 24230a708f8fSGustavo F. Padovan 24240a708f8fSGustavo F. Padovan if (!conn) 24250a708f8fSGustavo F. Padovan return ERR_PTR(-ENOTCONN); 24260a708f8fSGustavo F. Padovan 2427ba7aa64fSGustavo Padovan hlen = __ertm_hdr_size(chan); 2428e4ca6d98SAndrei Emeltchenko 24290a708f8fSGustavo F. Padovan if (sdulen) 243003a51213SAndrei Emeltchenko hlen += L2CAP_SDULEN_SIZE; 24310a708f8fSGustavo F. Padovan 243247d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 243303a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 24340a708f8fSGustavo F. Padovan 24350a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 24362f7719ceSAndrei Emeltchenko 24372f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 243890338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 243990338947SGustavo Padovan if (IS_ERR(skb)) 244090338947SGustavo Padovan return skb; 24410a708f8fSGustavo F. Padovan 24420a708f8fSGustavo F. Padovan /* Create L2CAP header */ 24430a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2444fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 24450a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 244688843ab0SAndrei Emeltchenko 244718a48e76SMat Martineau /* Control header is populated later */ 244818a48e76SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 244918a48e76SMat Martineau put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 245018a48e76SMat Martineau else 245118a48e76SMat Martineau put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 245288843ab0SAndrei Emeltchenko 24530a708f8fSGustavo F. Padovan if (sdulen) 245403a51213SAndrei Emeltchenko put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 24550a708f8fSGustavo F. Padovan 24560952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 24570a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 24580a708f8fSGustavo F. Padovan kfree_skb(skb); 24590a708f8fSGustavo F. Padovan return ERR_PTR(err); 24600a708f8fSGustavo F. Padovan } 24610a708f8fSGustavo F. Padovan 246218a48e76SMat Martineau bt_cb(skb)->control.fcs = chan->fcs; 24633ce3514fSMat Martineau bt_cb(skb)->control.retries = 0; 24640a708f8fSGustavo F. Padovan return skb; 24650a708f8fSGustavo F. Padovan } 24660a708f8fSGustavo F. Padovan 246794122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan, 246894122bbeSMat Martineau struct sk_buff_head *seg_queue, 246994122bbeSMat Martineau struct msghdr *msg, size_t len) 24700a708f8fSGustavo F. Padovan { 24710a708f8fSGustavo F. Padovan struct sk_buff *skb; 247294122bbeSMat Martineau u16 sdu_len; 247394122bbeSMat Martineau size_t pdu_len; 247494122bbeSMat Martineau u8 sar; 24750a708f8fSGustavo F. Padovan 2476b4400672SAndrei Emeltchenko BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); 24770a708f8fSGustavo F. Padovan 247894122bbeSMat Martineau /* It is critical that ERTM PDUs fit in a single HCI fragment, 247994122bbeSMat Martineau * so fragmented skbs are not used. The HCI layer's handling 248094122bbeSMat Martineau * of fragmented skbs is not compatible with ERTM's queueing. 248194122bbeSMat Martineau */ 248294122bbeSMat Martineau 248394122bbeSMat Martineau /* PDU size is derived from the HCI MTU */ 248494122bbeSMat Martineau pdu_len = chan->conn->mtu; 248594122bbeSMat Martineau 2486a549574dSMat Martineau /* Constrain PDU size for BR/EDR connections */ 2487a549574dSMat Martineau if (!chan->hs_hcon) 248894122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); 248994122bbeSMat Martineau 249094122bbeSMat Martineau /* Adjust for largest possible L2CAP overhead. */ 249135d401dfSGustavo Padovan if (chan->fcs) 249235d401dfSGustavo Padovan pdu_len -= L2CAP_FCS_SIZE; 249335d401dfSGustavo Padovan 2494ba7aa64fSGustavo Padovan pdu_len -= __ertm_hdr_size(chan); 249594122bbeSMat Martineau 249694122bbeSMat Martineau /* Remote device may have requested smaller PDUs */ 249794122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, chan->remote_mps); 249894122bbeSMat Martineau 249994122bbeSMat Martineau if (len <= pdu_len) { 250094122bbeSMat Martineau sar = L2CAP_SAR_UNSEGMENTED; 250194122bbeSMat Martineau sdu_len = 0; 250294122bbeSMat Martineau pdu_len = len; 250394122bbeSMat Martineau } else { 250494122bbeSMat Martineau sar = L2CAP_SAR_START; 250594122bbeSMat Martineau sdu_len = len; 250694122bbeSMat Martineau pdu_len -= L2CAP_SDULEN_SIZE; 250794122bbeSMat Martineau } 25080a708f8fSGustavo F. Padovan 25090a708f8fSGustavo F. Padovan while (len > 0) { 251094122bbeSMat Martineau skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len); 25110a708f8fSGustavo F. Padovan 25120a708f8fSGustavo F. Padovan if (IS_ERR(skb)) { 251394122bbeSMat Martineau __skb_queue_purge(seg_queue); 25140a708f8fSGustavo F. Padovan return PTR_ERR(skb); 25150a708f8fSGustavo F. Padovan } 25160a708f8fSGustavo F. Padovan 251794122bbeSMat Martineau bt_cb(skb)->control.sar = sar; 251894122bbeSMat Martineau __skb_queue_tail(seg_queue, skb); 25190a708f8fSGustavo F. Padovan 252094122bbeSMat Martineau len -= pdu_len; 252194122bbeSMat Martineau if (sdu_len) { 252294122bbeSMat Martineau sdu_len = 0; 252394122bbeSMat Martineau pdu_len += L2CAP_SDULEN_SIZE; 252494122bbeSMat Martineau } 252594122bbeSMat Martineau 252694122bbeSMat Martineau if (len <= pdu_len) { 252794122bbeSMat Martineau sar = L2CAP_SAR_END; 252894122bbeSMat Martineau pdu_len = len; 252994122bbeSMat Martineau } else { 253094122bbeSMat Martineau sar = L2CAP_SAR_CONTINUE; 253194122bbeSMat Martineau } 253294122bbeSMat Martineau } 253394122bbeSMat Martineau 2534f0f62799SGustavo Padovan return 0; 25350a708f8fSGustavo F. Padovan } 25360a708f8fSGustavo F. Padovan 2537177f8f2bSJohan Hedberg static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan, 2538177f8f2bSJohan Hedberg struct msghdr *msg, 2539177f8f2bSJohan Hedberg size_t len, u16 sdulen) 2540177f8f2bSJohan Hedberg { 2541177f8f2bSJohan Hedberg struct l2cap_conn *conn = chan->conn; 2542177f8f2bSJohan Hedberg struct sk_buff *skb; 2543177f8f2bSJohan Hedberg int err, count, hlen; 2544177f8f2bSJohan Hedberg struct l2cap_hdr *lh; 2545177f8f2bSJohan Hedberg 2546177f8f2bSJohan Hedberg BT_DBG("chan %p len %zu", chan, len); 2547177f8f2bSJohan Hedberg 2548177f8f2bSJohan Hedberg if (!conn) 2549177f8f2bSJohan Hedberg return ERR_PTR(-ENOTCONN); 2550177f8f2bSJohan Hedberg 2551177f8f2bSJohan Hedberg hlen = L2CAP_HDR_SIZE; 2552177f8f2bSJohan Hedberg 2553177f8f2bSJohan Hedberg if (sdulen) 2554177f8f2bSJohan Hedberg hlen += L2CAP_SDULEN_SIZE; 2555177f8f2bSJohan Hedberg 2556177f8f2bSJohan Hedberg count = min_t(unsigned int, (conn->mtu - hlen), len); 2557177f8f2bSJohan Hedberg 2558177f8f2bSJohan Hedberg skb = chan->ops->alloc_skb(chan, count + hlen, 2559177f8f2bSJohan Hedberg msg->msg_flags & MSG_DONTWAIT); 2560177f8f2bSJohan Hedberg if (IS_ERR(skb)) 2561177f8f2bSJohan Hedberg return skb; 2562177f8f2bSJohan Hedberg 2563177f8f2bSJohan Hedberg /* Create L2CAP header */ 2564177f8f2bSJohan Hedberg lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2565177f8f2bSJohan Hedberg lh->cid = cpu_to_le16(chan->dcid); 2566177f8f2bSJohan Hedberg lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 2567177f8f2bSJohan Hedberg 2568177f8f2bSJohan Hedberg if (sdulen) 2569177f8f2bSJohan Hedberg put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 2570177f8f2bSJohan Hedberg 2571177f8f2bSJohan Hedberg err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 2572177f8f2bSJohan Hedberg if (unlikely(err < 0)) { 2573177f8f2bSJohan Hedberg kfree_skb(skb); 2574177f8f2bSJohan Hedberg return ERR_PTR(err); 2575177f8f2bSJohan Hedberg } 2576177f8f2bSJohan Hedberg 2577177f8f2bSJohan Hedberg return skb; 2578177f8f2bSJohan Hedberg } 2579177f8f2bSJohan Hedberg 2580177f8f2bSJohan Hedberg static int l2cap_segment_le_sdu(struct l2cap_chan *chan, 2581177f8f2bSJohan Hedberg struct sk_buff_head *seg_queue, 2582177f8f2bSJohan Hedberg struct msghdr *msg, size_t len) 2583177f8f2bSJohan Hedberg { 2584177f8f2bSJohan Hedberg struct sk_buff *skb; 2585177f8f2bSJohan Hedberg size_t pdu_len; 2586177f8f2bSJohan Hedberg u16 sdu_len; 2587177f8f2bSJohan Hedberg 2588177f8f2bSJohan Hedberg BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); 2589177f8f2bSJohan Hedberg 2590177f8f2bSJohan Hedberg pdu_len = chan->conn->mtu - L2CAP_HDR_SIZE; 2591177f8f2bSJohan Hedberg 2592177f8f2bSJohan Hedberg pdu_len = min_t(size_t, pdu_len, chan->remote_mps); 2593177f8f2bSJohan Hedberg 2594177f8f2bSJohan Hedberg sdu_len = len; 2595177f8f2bSJohan Hedberg pdu_len -= L2CAP_SDULEN_SIZE; 2596177f8f2bSJohan Hedberg 2597177f8f2bSJohan Hedberg while (len > 0) { 2598177f8f2bSJohan Hedberg if (len <= pdu_len) 2599177f8f2bSJohan Hedberg pdu_len = len; 2600177f8f2bSJohan Hedberg 2601177f8f2bSJohan Hedberg skb = l2cap_create_le_flowctl_pdu(chan, msg, pdu_len, sdu_len); 2602177f8f2bSJohan Hedberg if (IS_ERR(skb)) { 2603177f8f2bSJohan Hedberg __skb_queue_purge(seg_queue); 2604177f8f2bSJohan Hedberg return PTR_ERR(skb); 2605177f8f2bSJohan Hedberg } 2606177f8f2bSJohan Hedberg 2607177f8f2bSJohan Hedberg __skb_queue_tail(seg_queue, skb); 2608177f8f2bSJohan Hedberg 2609177f8f2bSJohan Hedberg len -= pdu_len; 2610177f8f2bSJohan Hedberg 2611177f8f2bSJohan Hedberg if (sdu_len) { 2612177f8f2bSJohan Hedberg sdu_len = 0; 2613177f8f2bSJohan Hedberg pdu_len += L2CAP_SDULEN_SIZE; 2614177f8f2bSJohan Hedberg } 2615177f8f2bSJohan Hedberg } 2616177f8f2bSJohan Hedberg 2617177f8f2bSJohan Hedberg return 0; 2618177f8f2bSJohan Hedberg } 2619177f8f2bSJohan Hedberg 26205e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, 26215e59b791SLuiz Augusto von Dentz u32 priority) 26229a91a04aSGustavo F. Padovan { 26239a91a04aSGustavo F. Padovan struct sk_buff *skb; 26249a91a04aSGustavo F. Padovan int err; 262594122bbeSMat Martineau struct sk_buff_head seg_queue; 26269a91a04aSGustavo F. Padovan 262731e8ce80SSeung-Woo Kim if (!chan->conn) 262831e8ce80SSeung-Woo Kim return -ENOTCONN; 262931e8ce80SSeung-Woo Kim 26309a91a04aSGustavo F. Padovan /* Connectionless channel */ 2631715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { 26325e59b791SLuiz Augusto von Dentz skb = l2cap_create_connless_pdu(chan, msg, len, priority); 26339a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 26349a91a04aSGustavo F. Padovan return PTR_ERR(skb); 26359a91a04aSGustavo F. Padovan 26369a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 26379a91a04aSGustavo F. Padovan return len; 26389a91a04aSGustavo F. Padovan } 26399a91a04aSGustavo F. Padovan 26409a91a04aSGustavo F. Padovan switch (chan->mode) { 264138319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 2642177f8f2bSJohan Hedberg /* Check outgoing MTU */ 2643177f8f2bSJohan Hedberg if (len > chan->omtu) 2644177f8f2bSJohan Hedberg return -EMSGSIZE; 2645177f8f2bSJohan Hedberg 2646fad5fc89SJohan Hedberg if (!chan->tx_credits) 2647fad5fc89SJohan Hedberg return -EAGAIN; 2648fad5fc89SJohan Hedberg 2649177f8f2bSJohan Hedberg __skb_queue_head_init(&seg_queue); 2650177f8f2bSJohan Hedberg 2651177f8f2bSJohan Hedberg err = l2cap_segment_le_sdu(chan, &seg_queue, msg, len); 2652177f8f2bSJohan Hedberg 2653177f8f2bSJohan Hedberg if (chan->state != BT_CONNECTED) { 2654177f8f2bSJohan Hedberg __skb_queue_purge(&seg_queue); 2655177f8f2bSJohan Hedberg err = -ENOTCONN; 2656177f8f2bSJohan Hedberg } 2657177f8f2bSJohan Hedberg 2658177f8f2bSJohan Hedberg if (err) 2659177f8f2bSJohan Hedberg return err; 2660177f8f2bSJohan Hedberg 2661177f8f2bSJohan Hedberg skb_queue_splice_tail_init(&seg_queue, &chan->tx_q); 2662177f8f2bSJohan Hedberg 2663177f8f2bSJohan Hedberg while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) { 2664177f8f2bSJohan Hedberg l2cap_do_send(chan, skb_dequeue(&chan->tx_q)); 2665177f8f2bSJohan Hedberg chan->tx_credits--; 2666177f8f2bSJohan Hedberg } 2667177f8f2bSJohan Hedberg 2668177f8f2bSJohan Hedberg if (!chan->tx_credits) 2669177f8f2bSJohan Hedberg chan->ops->suspend(chan); 2670177f8f2bSJohan Hedberg 2671177f8f2bSJohan Hedberg err = len; 2672177f8f2bSJohan Hedberg 2673177f8f2bSJohan Hedberg break; 2674177f8f2bSJohan Hedberg 2675fad5fc89SJohan Hedberg case L2CAP_MODE_BASIC: 26769a91a04aSGustavo F. Padovan /* Check outgoing MTU */ 26779a91a04aSGustavo F. Padovan if (len > chan->omtu) 26789a91a04aSGustavo F. Padovan return -EMSGSIZE; 26799a91a04aSGustavo F. Padovan 26809a91a04aSGustavo F. Padovan /* Create a basic PDU */ 26815e59b791SLuiz Augusto von Dentz skb = l2cap_create_basic_pdu(chan, msg, len, priority); 26829a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 26839a91a04aSGustavo F. Padovan return PTR_ERR(skb); 26849a91a04aSGustavo F. Padovan 26859a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 26869a91a04aSGustavo F. Padovan err = len; 26879a91a04aSGustavo F. Padovan break; 26889a91a04aSGustavo F. Padovan 26899a91a04aSGustavo F. Padovan case L2CAP_MODE_ERTM: 26909a91a04aSGustavo F. Padovan case L2CAP_MODE_STREAMING: 269194122bbeSMat Martineau /* Check outgoing MTU */ 269294122bbeSMat Martineau if (len > chan->omtu) { 269394122bbeSMat Martineau err = -EMSGSIZE; 26949a91a04aSGustavo F. Padovan break; 26959a91a04aSGustavo F. Padovan } 26969a91a04aSGustavo F. Padovan 269794122bbeSMat Martineau __skb_queue_head_init(&seg_queue); 269894122bbeSMat Martineau 269994122bbeSMat Martineau /* Do segmentation before calling in to the state machine, 270094122bbeSMat Martineau * since it's possible to block while waiting for memory 270194122bbeSMat Martineau * allocation. 270294122bbeSMat Martineau */ 270394122bbeSMat Martineau err = l2cap_segment_sdu(chan, &seg_queue, msg, len); 270494122bbeSMat Martineau 270594122bbeSMat Martineau /* The channel could have been closed while segmenting, 270694122bbeSMat Martineau * check that it is still connected. 270794122bbeSMat Martineau */ 270894122bbeSMat Martineau if (chan->state != BT_CONNECTED) { 270994122bbeSMat Martineau __skb_queue_purge(&seg_queue); 271094122bbeSMat Martineau err = -ENOTCONN; 27119a91a04aSGustavo F. Padovan } 27129a91a04aSGustavo F. Padovan 271394122bbeSMat Martineau if (err) 271494122bbeSMat Martineau break; 271594122bbeSMat Martineau 27163733937dSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) 2717d660366dSGustavo Padovan l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST); 27183733937dSMat Martineau else 2719d660366dSGustavo Padovan l2cap_streaming_send(chan, &seg_queue); 272094122bbeSMat Martineau 27219a91a04aSGustavo F. Padovan err = len; 27229a91a04aSGustavo F. Padovan 272394122bbeSMat Martineau /* If the skbs were not queued for sending, they'll still be in 272494122bbeSMat Martineau * seg_queue and need to be purged. 272594122bbeSMat Martineau */ 272694122bbeSMat Martineau __skb_queue_purge(&seg_queue); 27279a91a04aSGustavo F. Padovan break; 27289a91a04aSGustavo F. Padovan 27299a91a04aSGustavo F. Padovan default: 27309a91a04aSGustavo F. Padovan BT_DBG("bad state %1.1x", chan->mode); 27319a91a04aSGustavo F. Padovan err = -EBADFD; 27329a91a04aSGustavo F. Padovan } 27339a91a04aSGustavo F. Padovan 27349a91a04aSGustavo F. Padovan return err; 27359a91a04aSGustavo F. Padovan } 27369a91a04aSGustavo F. Padovan 2737d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq) 2738d2a7ac5dSMat Martineau { 2739bed68bdeSMat Martineau struct l2cap_ctrl control; 2740bed68bdeSMat Martineau u16 seq; 2741bed68bdeSMat Martineau 2742b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2743bed68bdeSMat Martineau 2744bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2745bed68bdeSMat Martineau control.sframe = 1; 2746bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2747bed68bdeSMat Martineau 2748bed68bdeSMat Martineau for (seq = chan->expected_tx_seq; seq != txseq; 2749bed68bdeSMat Martineau seq = __next_seq(chan, seq)) { 2750bed68bdeSMat Martineau if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) { 2751bed68bdeSMat Martineau control.reqseq = seq; 2752bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2753bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2754bed68bdeSMat Martineau } 2755bed68bdeSMat Martineau } 2756bed68bdeSMat Martineau 2757bed68bdeSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 2758d2a7ac5dSMat Martineau } 2759d2a7ac5dSMat Martineau 2760d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan) 2761d2a7ac5dSMat Martineau { 2762bed68bdeSMat Martineau struct l2cap_ctrl control; 2763bed68bdeSMat Martineau 2764bed68bdeSMat Martineau BT_DBG("chan %p", chan); 2765bed68bdeSMat Martineau 2766bed68bdeSMat Martineau if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR) 2767bed68bdeSMat Martineau return; 2768bed68bdeSMat Martineau 2769bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2770bed68bdeSMat Martineau control.sframe = 1; 2771bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2772bed68bdeSMat Martineau control.reqseq = chan->srej_list.tail; 2773bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2774d2a7ac5dSMat Martineau } 2775d2a7ac5dSMat Martineau 2776d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq) 2777d2a7ac5dSMat Martineau { 2778bed68bdeSMat Martineau struct l2cap_ctrl control; 2779bed68bdeSMat Martineau u16 initial_head; 2780bed68bdeSMat Martineau u16 seq; 2781bed68bdeSMat Martineau 2782b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2783bed68bdeSMat Martineau 2784bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2785bed68bdeSMat Martineau control.sframe = 1; 2786bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2787bed68bdeSMat Martineau 2788bed68bdeSMat Martineau /* Capture initial list head to allow only one pass through the list. */ 2789bed68bdeSMat Martineau initial_head = chan->srej_list.head; 2790bed68bdeSMat Martineau 2791bed68bdeSMat Martineau do { 2792bed68bdeSMat Martineau seq = l2cap_seq_list_pop(&chan->srej_list); 2793bed68bdeSMat Martineau if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR) 2794bed68bdeSMat Martineau break; 2795bed68bdeSMat Martineau 2796bed68bdeSMat Martineau control.reqseq = seq; 2797bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2798bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2799bed68bdeSMat Martineau } while (chan->srej_list.head != initial_head); 2800d2a7ac5dSMat Martineau } 2801d2a7ac5dSMat Martineau 2802608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq) 2803608bcc6dSMat Martineau { 2804608bcc6dSMat Martineau struct sk_buff *acked_skb; 2805608bcc6dSMat Martineau u16 ackseq; 2806608bcc6dSMat Martineau 2807b4400672SAndrei Emeltchenko BT_DBG("chan %p, reqseq %u", chan, reqseq); 2808608bcc6dSMat Martineau 2809608bcc6dSMat Martineau if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq) 2810608bcc6dSMat Martineau return; 2811608bcc6dSMat Martineau 2812b4400672SAndrei Emeltchenko BT_DBG("expected_ack_seq %u, unacked_frames %u", 2813608bcc6dSMat Martineau chan->expected_ack_seq, chan->unacked_frames); 2814608bcc6dSMat Martineau 2815608bcc6dSMat Martineau for (ackseq = chan->expected_ack_seq; ackseq != reqseq; 2816608bcc6dSMat Martineau ackseq = __next_seq(chan, ackseq)) { 2817608bcc6dSMat Martineau 2818608bcc6dSMat Martineau acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq); 2819608bcc6dSMat Martineau if (acked_skb) { 2820608bcc6dSMat Martineau skb_unlink(acked_skb, &chan->tx_q); 2821608bcc6dSMat Martineau kfree_skb(acked_skb); 2822608bcc6dSMat Martineau chan->unacked_frames--; 2823608bcc6dSMat Martineau } 2824608bcc6dSMat Martineau } 2825608bcc6dSMat Martineau 2826608bcc6dSMat Martineau chan->expected_ack_seq = reqseq; 2827608bcc6dSMat Martineau 2828608bcc6dSMat Martineau if (chan->unacked_frames == 0) 2829608bcc6dSMat Martineau __clear_retrans_timer(chan); 2830608bcc6dSMat Martineau 2831b4400672SAndrei Emeltchenko BT_DBG("unacked_frames %u", chan->unacked_frames); 2832608bcc6dSMat Martineau } 2833608bcc6dSMat Martineau 2834608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan) 2835608bcc6dSMat Martineau { 2836608bcc6dSMat Martineau BT_DBG("chan %p", chan); 2837608bcc6dSMat Martineau 2838608bcc6dSMat Martineau chan->expected_tx_seq = chan->buffer_seq; 2839608bcc6dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 2840608bcc6dSMat Martineau skb_queue_purge(&chan->srej_q); 2841608bcc6dSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2842608bcc6dSMat Martineau } 2843608bcc6dSMat Martineau 2844d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan, 2845608bcc6dSMat Martineau struct l2cap_ctrl *control, 2846608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2847608bcc6dSMat Martineau { 2848608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2849608bcc6dSMat Martineau event); 2850608bcc6dSMat Martineau 2851608bcc6dSMat Martineau switch (event) { 2852608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2853608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2854608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2855608bcc6dSMat Martineau 2856608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2857608bcc6dSMat Martineau l2cap_ertm_send(chan); 2858608bcc6dSMat Martineau break; 2859608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2860608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2861608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2862608bcc6dSMat Martineau 2863608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2864608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2865608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2866608bcc6dSMat Martineau */ 2867608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2868608bcc6dSMat Martineau } 2869608bcc6dSMat Martineau 2870608bcc6dSMat Martineau l2cap_send_ack(chan); 2871608bcc6dSMat Martineau 2872608bcc6dSMat Martineau break; 2873608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2874608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2875608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2876608bcc6dSMat Martineau 2877608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2878608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2879608bcc6dSMat Martineau 2880608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2881608bcc6dSMat Martineau local_control.sframe = 1; 2882608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2883608bcc6dSMat Martineau local_control.poll = 1; 2884608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2885a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2886608bcc6dSMat Martineau 2887608bcc6dSMat Martineau chan->retry_count = 1; 2888608bcc6dSMat Martineau __set_monitor_timer(chan); 2889608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2890608bcc6dSMat Martineau } 2891608bcc6dSMat Martineau break; 2892608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2893608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2894608bcc6dSMat Martineau break; 2895608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2896608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2897608bcc6dSMat Martineau chan->retry_count = 1; 2898608bcc6dSMat Martineau __set_monitor_timer(chan); 2899608bcc6dSMat Martineau __clear_ack_timer(chan); 2900608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2901608bcc6dSMat Martineau break; 2902608bcc6dSMat Martineau case L2CAP_EV_RETRANS_TO: 2903608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2904608bcc6dSMat Martineau chan->retry_count = 1; 2905608bcc6dSMat Martineau __set_monitor_timer(chan); 2906608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2907608bcc6dSMat Martineau break; 2908608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2909608bcc6dSMat Martineau /* Nothing to process */ 2910608bcc6dSMat Martineau break; 2911608bcc6dSMat Martineau default: 2912608bcc6dSMat Martineau break; 2913608bcc6dSMat Martineau } 2914608bcc6dSMat Martineau } 2915608bcc6dSMat Martineau 2916d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan, 2917608bcc6dSMat Martineau struct l2cap_ctrl *control, 2918608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2919608bcc6dSMat Martineau { 2920608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2921608bcc6dSMat Martineau event); 2922608bcc6dSMat Martineau 2923608bcc6dSMat Martineau switch (event) { 2924608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2925608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2926608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2927608bcc6dSMat Martineau /* Queue data, but don't send. */ 2928608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2929608bcc6dSMat Martineau break; 2930608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2931608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2932608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2933608bcc6dSMat Martineau 2934608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2935608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2936608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2937608bcc6dSMat Martineau */ 2938608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2939608bcc6dSMat Martineau } 2940608bcc6dSMat Martineau 2941608bcc6dSMat Martineau l2cap_send_ack(chan); 2942608bcc6dSMat Martineau 2943608bcc6dSMat Martineau break; 2944608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2945608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2946608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2947608bcc6dSMat Martineau 2948608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2949608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2950608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2951608bcc6dSMat Martineau local_control.sframe = 1; 2952608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2953608bcc6dSMat Martineau local_control.poll = 1; 2954608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2955a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2956608bcc6dSMat Martineau 2957608bcc6dSMat Martineau chan->retry_count = 1; 2958608bcc6dSMat Martineau __set_monitor_timer(chan); 2959608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2960608bcc6dSMat Martineau } 2961608bcc6dSMat Martineau break; 2962608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2963608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2964608bcc6dSMat Martineau 2965608bcc6dSMat Martineau /* Fall through */ 2966608bcc6dSMat Martineau 2967608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2968608bcc6dSMat Martineau if (control && control->final) { 2969608bcc6dSMat Martineau __clear_monitor_timer(chan); 2970608bcc6dSMat Martineau if (chan->unacked_frames > 0) 2971608bcc6dSMat Martineau __set_retrans_timer(chan); 2972608bcc6dSMat Martineau chan->retry_count = 0; 2973608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 2974608bcc6dSMat Martineau BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state); 2975608bcc6dSMat Martineau } 2976608bcc6dSMat Martineau break; 2977608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2978608bcc6dSMat Martineau /* Ignore */ 2979608bcc6dSMat Martineau break; 2980608bcc6dSMat Martineau case L2CAP_EV_MONITOR_TO: 2981608bcc6dSMat Martineau if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) { 2982608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2983608bcc6dSMat Martineau __set_monitor_timer(chan); 2984608bcc6dSMat Martineau chan->retry_count++; 2985608bcc6dSMat Martineau } else { 29865e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNABORTED); 2987608bcc6dSMat Martineau } 2988608bcc6dSMat Martineau break; 2989608bcc6dSMat Martineau default: 2990608bcc6dSMat Martineau break; 2991608bcc6dSMat Martineau } 2992608bcc6dSMat Martineau } 2993608bcc6dSMat Martineau 2994d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 2995608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2996608bcc6dSMat Martineau { 2997608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d, state %d", 2998608bcc6dSMat Martineau chan, control, skbs, event, chan->tx_state); 2999608bcc6dSMat Martineau 3000608bcc6dSMat Martineau switch (chan->tx_state) { 3001608bcc6dSMat Martineau case L2CAP_TX_STATE_XMIT: 3002d660366dSGustavo Padovan l2cap_tx_state_xmit(chan, control, skbs, event); 3003608bcc6dSMat Martineau break; 3004608bcc6dSMat Martineau case L2CAP_TX_STATE_WAIT_F: 3005d660366dSGustavo Padovan l2cap_tx_state_wait_f(chan, control, skbs, event); 3006608bcc6dSMat Martineau break; 3007608bcc6dSMat Martineau default: 3008608bcc6dSMat Martineau /* Ignore event */ 3009608bcc6dSMat Martineau break; 3010608bcc6dSMat Martineau } 3011608bcc6dSMat Martineau } 3012608bcc6dSMat Martineau 30134b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan, 30144b51dae9SMat Martineau struct l2cap_ctrl *control) 30154b51dae9SMat Martineau { 30164b51dae9SMat Martineau BT_DBG("chan %p, control %p", chan, control); 3017401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT); 30184b51dae9SMat Martineau } 30194b51dae9SMat Martineau 3020f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan, 3021f80842a8SMat Martineau struct l2cap_ctrl *control) 3022f80842a8SMat Martineau { 3023f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 3024401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT); 3025f80842a8SMat Martineau } 3026f80842a8SMat Martineau 30270a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */ 30280a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 30290a708f8fSGustavo F. Padovan { 30300a708f8fSGustavo F. Padovan struct sk_buff *nskb; 303148454079SGustavo F. Padovan struct l2cap_chan *chan; 30320a708f8fSGustavo F. Padovan 30330a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 30340a708f8fSGustavo F. Padovan 30353df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 30363d57dc68SGustavo F. Padovan 30373df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 3038715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW) 30390a708f8fSGustavo F. Padovan continue; 30400a708f8fSGustavo F. Padovan 30417f5396a7SGustavo Padovan /* Don't send frame to the channel it came from */ 30427f5396a7SGustavo Padovan if (bt_cb(skb)->chan == chan) 30430a708f8fSGustavo F. Padovan continue; 30447f5396a7SGustavo Padovan 30458bcde1f2SGustavo Padovan nskb = skb_clone(skb, GFP_KERNEL); 30460a708f8fSGustavo F. Padovan if (!nskb) 30470a708f8fSGustavo F. Padovan continue; 304880b98027SGustavo Padovan if (chan->ops->recv(chan, nskb)) 30490a708f8fSGustavo F. Padovan kfree_skb(nskb); 30500a708f8fSGustavo F. Padovan } 30513d57dc68SGustavo F. Padovan 30523df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 30530a708f8fSGustavo F. Padovan } 30540a708f8fSGustavo F. Padovan 30550a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */ 3056b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, 3057b4400672SAndrei Emeltchenko u8 ident, u16 dlen, void *data) 30580a708f8fSGustavo F. Padovan { 30590a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag; 30600a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd; 30610a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 30620a708f8fSGustavo F. Padovan int len, count; 30630a708f8fSGustavo F. Padovan 3064b4400672SAndrei Emeltchenko BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u", 30650a708f8fSGustavo F. Padovan conn, code, ident, dlen); 30660a708f8fSGustavo F. Padovan 3067300b962eSAnderson Lizardo if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE) 3068300b962eSAnderson Lizardo return NULL; 3069300b962eSAnderson Lizardo 30700a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; 30710a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 30720a708f8fSGustavo F. Padovan 30738bcde1f2SGustavo Padovan skb = bt_skb_alloc(count, GFP_KERNEL); 30740a708f8fSGustavo F. Padovan if (!skb) 30750a708f8fSGustavo F. Padovan return NULL; 30760a708f8fSGustavo F. Padovan 30770a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 30780a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); 30793300d9a9SClaudio Takahasi 30803300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 3081ac73498cSAndrei Emeltchenko lh->cid = __constant_cpu_to_le16(L2CAP_CID_LE_SIGNALING); 30823300d9a9SClaudio Takahasi else 3083ac73498cSAndrei Emeltchenko lh->cid = __constant_cpu_to_le16(L2CAP_CID_SIGNALING); 30840a708f8fSGustavo F. Padovan 30850a708f8fSGustavo F. Padovan cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); 30860a708f8fSGustavo F. Padovan cmd->code = code; 30870a708f8fSGustavo F. Padovan cmd->ident = ident; 30880a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen); 30890a708f8fSGustavo F. Padovan 30900a708f8fSGustavo F. Padovan if (dlen) { 30910a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE; 30920a708f8fSGustavo F. Padovan memcpy(skb_put(skb, count), data, count); 30930a708f8fSGustavo F. Padovan data += count; 30940a708f8fSGustavo F. Padovan } 30950a708f8fSGustavo F. Padovan 30960a708f8fSGustavo F. Padovan len -= skb->len; 30970a708f8fSGustavo F. Padovan 30980a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 30990a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 31000a708f8fSGustavo F. Padovan while (len) { 31010a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 31020a708f8fSGustavo F. Padovan 31038bcde1f2SGustavo Padovan *frag = bt_skb_alloc(count, GFP_KERNEL); 31040a708f8fSGustavo F. Padovan if (!*frag) 31050a708f8fSGustavo F. Padovan goto fail; 31060a708f8fSGustavo F. Padovan 31070a708f8fSGustavo F. Padovan memcpy(skb_put(*frag, count), data, count); 31080a708f8fSGustavo F. Padovan 31090a708f8fSGustavo F. Padovan len -= count; 31100a708f8fSGustavo F. Padovan data += count; 31110a708f8fSGustavo F. Padovan 31120a708f8fSGustavo F. Padovan frag = &(*frag)->next; 31130a708f8fSGustavo F. Padovan } 31140a708f8fSGustavo F. Padovan 31150a708f8fSGustavo F. Padovan return skb; 31160a708f8fSGustavo F. Padovan 31170a708f8fSGustavo F. Padovan fail: 31180a708f8fSGustavo F. Padovan kfree_skb(skb); 31190a708f8fSGustavo F. Padovan return NULL; 31200a708f8fSGustavo F. Padovan } 31210a708f8fSGustavo F. Padovan 31222d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, 31232d792818SGustavo Padovan unsigned long *val) 31240a708f8fSGustavo F. Padovan { 31250a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 31260a708f8fSGustavo F. Padovan int len; 31270a708f8fSGustavo F. Padovan 31280a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len; 31290a708f8fSGustavo F. Padovan *ptr += len; 31300a708f8fSGustavo F. Padovan 31310a708f8fSGustavo F. Padovan *type = opt->type; 31320a708f8fSGustavo F. Padovan *olen = opt->len; 31330a708f8fSGustavo F. Padovan 31340a708f8fSGustavo F. Padovan switch (opt->len) { 31350a708f8fSGustavo F. Padovan case 1: 31360a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val); 31370a708f8fSGustavo F. Padovan break; 31380a708f8fSGustavo F. Padovan 31390a708f8fSGustavo F. Padovan case 2: 31400a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val); 31410a708f8fSGustavo F. Padovan break; 31420a708f8fSGustavo F. Padovan 31430a708f8fSGustavo F. Padovan case 4: 31440a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val); 31450a708f8fSGustavo F. Padovan break; 31460a708f8fSGustavo F. Padovan 31470a708f8fSGustavo F. Padovan default: 31480a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val; 31490a708f8fSGustavo F. Padovan break; 31500a708f8fSGustavo F. Padovan } 31510a708f8fSGustavo F. Padovan 3152b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val); 31530a708f8fSGustavo F. Padovan return len; 31540a708f8fSGustavo F. Padovan } 31550a708f8fSGustavo F. Padovan 31560a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) 31570a708f8fSGustavo F. Padovan { 31580a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 31590a708f8fSGustavo F. Padovan 3160b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val); 31610a708f8fSGustavo F. Padovan 31620a708f8fSGustavo F. Padovan opt->type = type; 31630a708f8fSGustavo F. Padovan opt->len = len; 31640a708f8fSGustavo F. Padovan 31650a708f8fSGustavo F. Padovan switch (len) { 31660a708f8fSGustavo F. Padovan case 1: 31670a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val; 31680a708f8fSGustavo F. Padovan break; 31690a708f8fSGustavo F. Padovan 31700a708f8fSGustavo F. Padovan case 2: 31710a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val); 31720a708f8fSGustavo F. Padovan break; 31730a708f8fSGustavo F. Padovan 31740a708f8fSGustavo F. Padovan case 4: 31750a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val); 31760a708f8fSGustavo F. Padovan break; 31770a708f8fSGustavo F. Padovan 31780a708f8fSGustavo F. Padovan default: 31790a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len); 31800a708f8fSGustavo F. Padovan break; 31810a708f8fSGustavo F. Padovan } 31820a708f8fSGustavo F. Padovan 31830a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len; 31840a708f8fSGustavo F. Padovan } 31850a708f8fSGustavo F. Padovan 3186f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) 3187f89cef09SAndrei Emeltchenko { 3188f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs; 3189f89cef09SAndrei Emeltchenko 3190f89cef09SAndrei Emeltchenko switch (chan->mode) { 3191f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM: 3192f89cef09SAndrei Emeltchenko efs.id = chan->local_id; 3193f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype; 3194f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 3195f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 3196ac73498cSAndrei Emeltchenko efs.acc_lat = __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); 31978936fa6dSAndrei Emeltchenko efs.flush_to = __constant_cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO); 3198f89cef09SAndrei Emeltchenko break; 3199f89cef09SAndrei Emeltchenko 3200f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING: 3201f89cef09SAndrei Emeltchenko efs.id = 1; 3202f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT; 3203f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 3204f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 3205f89cef09SAndrei Emeltchenko efs.acc_lat = 0; 3206f89cef09SAndrei Emeltchenko efs.flush_to = 0; 3207f89cef09SAndrei Emeltchenko break; 3208f89cef09SAndrei Emeltchenko 3209f89cef09SAndrei Emeltchenko default: 3210f89cef09SAndrei Emeltchenko return; 3211f89cef09SAndrei Emeltchenko } 3212f89cef09SAndrei Emeltchenko 3213f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), 3214f89cef09SAndrei Emeltchenko (unsigned long) &efs); 3215f89cef09SAndrei Emeltchenko } 3216f89cef09SAndrei Emeltchenko 3217721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work) 32180a708f8fSGustavo F. Padovan { 3219721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 3220721c4181SGustavo F. Padovan ack_timer.work); 32210362520bSMat Martineau u16 frames_to_ack; 32220a708f8fSGustavo F. Padovan 32232fb9b3d4SGustavo F. Padovan BT_DBG("chan %p", chan); 32242fb9b3d4SGustavo F. Padovan 32256be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 32266be36555SAndrei Emeltchenko 32270362520bSMat Martineau frames_to_ack = __seq_offset(chan, chan->buffer_seq, 32280362520bSMat Martineau chan->last_acked_seq); 32290362520bSMat Martineau 32300362520bSMat Martineau if (frames_to_ack) 32310362520bSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 32326be36555SAndrei Emeltchenko 32336be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 323409bfb2eeSSzymon Janc l2cap_chan_put(chan); 32350a708f8fSGustavo F. Padovan } 32360a708f8fSGustavo F. Padovan 3237466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan) 32380a708f8fSGustavo F. Padovan { 32393c588192SMat Martineau int err; 32403c588192SMat Martineau 3241105bdf9eSMat Martineau chan->next_tx_seq = 0; 3242105bdf9eSMat Martineau chan->expected_tx_seq = 0; 324342e5c802SGustavo F. Padovan chan->expected_ack_seq = 0; 32446a026610SGustavo F. Padovan chan->unacked_frames = 0; 324542e5c802SGustavo F. Padovan chan->buffer_seq = 0; 32466a026610SGustavo F. Padovan chan->frames_sent = 0; 3247105bdf9eSMat Martineau chan->last_acked_seq = 0; 3248105bdf9eSMat Martineau chan->sdu = NULL; 3249105bdf9eSMat Martineau chan->sdu_last_frag = NULL; 3250105bdf9eSMat Martineau chan->sdu_len = 0; 3251105bdf9eSMat Martineau 3252d34c34fbSMat Martineau skb_queue_head_init(&chan->tx_q); 3253d34c34fbSMat Martineau 32546ed971caSMarcel Holtmann chan->local_amp_id = AMP_ID_BREDR; 32556ed971caSMarcel Holtmann chan->move_id = AMP_ID_BREDR; 325608333283SMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 325708333283SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 325808333283SMat Martineau 3259105bdf9eSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 3260105bdf9eSMat Martineau return 0; 3261105bdf9eSMat Martineau 3262105bdf9eSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 3263105bdf9eSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 32640a708f8fSGustavo F. Padovan 3265721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout); 3266721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout); 3267721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout); 32680a708f8fSGustavo F. Padovan 3269f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q); 32700a708f8fSGustavo F. Padovan 32713c588192SMat Martineau err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win); 32723c588192SMat Martineau if (err < 0) 32733c588192SMat Martineau return err; 32743c588192SMat Martineau 32759dc9affcSMat Martineau err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win); 32769dc9affcSMat Martineau if (err < 0) 32779dc9affcSMat Martineau l2cap_seq_list_free(&chan->srej_list); 32789dc9affcSMat Martineau 32799dc9affcSMat Martineau return err; 32800a708f8fSGustavo F. Padovan } 32810a708f8fSGustavo F. Padovan 32820a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) 32830a708f8fSGustavo F. Padovan { 32840a708f8fSGustavo F. Padovan switch (mode) { 32850a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 32860a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 32870a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask)) 32880a708f8fSGustavo F. Padovan return mode; 32890a708f8fSGustavo F. Padovan /* fall through */ 32900a708f8fSGustavo F. Padovan default: 32910a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC; 32920a708f8fSGustavo F. Padovan } 32930a708f8fSGustavo F. Padovan } 32940a708f8fSGustavo F. Padovan 3295848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn) 32966327eb98SAndrei Emeltchenko { 3297848566b3SMarcel Holtmann return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_WINDOW; 32986327eb98SAndrei Emeltchenko } 32996327eb98SAndrei Emeltchenko 3300848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn) 3301f89cef09SAndrei Emeltchenko { 3302848566b3SMarcel Holtmann return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_FLOW; 3303f89cef09SAndrei Emeltchenko } 3304f89cef09SAndrei Emeltchenko 330536c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan, 330636c86c85SMat Martineau struct l2cap_conf_rfc *rfc) 330736c86c85SMat Martineau { 33086ed971caSMarcel Holtmann if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) { 330936c86c85SMat Martineau u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to; 331036c86c85SMat Martineau 331136c86c85SMat Martineau /* Class 1 devices have must have ERTM timeouts 331236c86c85SMat Martineau * exceeding the Link Supervision Timeout. The 331336c86c85SMat Martineau * default Link Supervision Timeout for AMP 331436c86c85SMat Martineau * controllers is 10 seconds. 331536c86c85SMat Martineau * 331636c86c85SMat Martineau * Class 1 devices use 0xffffffff for their 331736c86c85SMat Martineau * best-effort flush timeout, so the clamping logic 331836c86c85SMat Martineau * will result in a timeout that meets the above 331936c86c85SMat Martineau * requirement. ERTM timeouts are 16-bit values, so 332036c86c85SMat Martineau * the maximum timeout is 65.535 seconds. 332136c86c85SMat Martineau */ 332236c86c85SMat Martineau 332336c86c85SMat Martineau /* Convert timeout to milliseconds and round */ 332436c86c85SMat Martineau ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000); 332536c86c85SMat Martineau 332636c86c85SMat Martineau /* This is the recommended formula for class 2 devices 332736c86c85SMat Martineau * that start ERTM timers when packets are sent to the 332836c86c85SMat Martineau * controller. 332936c86c85SMat Martineau */ 333036c86c85SMat Martineau ertm_to = 3 * ertm_to + 500; 333136c86c85SMat Martineau 333236c86c85SMat Martineau if (ertm_to > 0xffff) 333336c86c85SMat Martineau ertm_to = 0xffff; 333436c86c85SMat Martineau 333536c86c85SMat Martineau rfc->retrans_timeout = cpu_to_le16((u16) ertm_to); 333636c86c85SMat Martineau rfc->monitor_timeout = rfc->retrans_timeout; 333736c86c85SMat Martineau } else { 333836c86c85SMat Martineau rfc->retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 333936c86c85SMat Martineau rfc->monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 334036c86c85SMat Martineau } 334136c86c85SMat Martineau } 334236c86c85SMat Martineau 33436327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan) 33446327eb98SAndrei Emeltchenko { 33456327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && 3346848566b3SMarcel Holtmann __l2cap_ews_supported(chan->conn)) { 33476327eb98SAndrei Emeltchenko /* use extended control field */ 33486327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 3349836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 3350836be934SAndrei Emeltchenko } else { 33516327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win, 33526327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 3353836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 3354836be934SAndrei Emeltchenko } 3355c20f8e35SMat Martineau chan->ack_win = chan->tx_win; 33566327eb98SAndrei Emeltchenko } 33576327eb98SAndrei Emeltchenko 3358710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) 33590a708f8fSGustavo F. Padovan { 33600a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 33610c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode }; 33620a708f8fSGustavo F. Padovan void *ptr = req->data; 3363c8f79162SAndrei Emeltchenko u16 size; 33640a708f8fSGustavo F. Padovan 336549208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 33660a708f8fSGustavo F. Padovan 336773ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp) 33680a708f8fSGustavo F. Padovan goto done; 33690a708f8fSGustavo F. Padovan 33700c1bc5c6SGustavo F. Padovan switch (chan->mode) { 33710a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 33720a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3373c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) 33740a708f8fSGustavo F. Padovan break; 33750a708f8fSGustavo F. Padovan 3376848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn)) 3377f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 3378f89cef09SAndrei Emeltchenko 33790a708f8fSGustavo F. Padovan /* fall through */ 33800a708f8fSGustavo F. Padovan default: 33818c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); 33820a708f8fSGustavo F. Padovan break; 33830a708f8fSGustavo F. Padovan } 33840a708f8fSGustavo F. Padovan 33850a708f8fSGustavo F. Padovan done: 33860c1bc5c6SGustavo F. Padovan if (chan->imtu != L2CAP_DEFAULT_MTU) 33870c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 33880a708f8fSGustavo F. Padovan 33890c1bc5c6SGustavo F. Padovan switch (chan->mode) { 33900a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 33918c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && 33928c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) 33930a708f8fSGustavo F. Padovan break; 33940a708f8fSGustavo F. Padovan 33950a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC; 33960a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 33970a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 33980a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 33990a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 34000a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0; 34010a708f8fSGustavo F. Padovan 34020a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 34030a708f8fSGustavo F. Padovan (unsigned long) &rfc); 34040a708f8fSGustavo F. Padovan break; 34050a708f8fSGustavo F. Padovan 34060a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 34070a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM; 340847d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx; 340936c86c85SMat Martineau 341036c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc); 3411c8f79162SAndrei Emeltchenko 3412c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 34132d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - 3414c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3415c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 34160a708f8fSGustavo F. Padovan 34176327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan); 34186327eb98SAndrei Emeltchenko 34196327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win, 34206327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 34210a708f8fSGustavo F. Padovan 34220a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 34230a708f8fSGustavo F. Padovan (unsigned long) &rfc); 34240a708f8fSGustavo F. Padovan 3425f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 3426f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 3427f89cef09SAndrei Emeltchenko 34286327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 34296327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 34306327eb98SAndrei Emeltchenko chan->tx_win); 343160918918SAndrei Emeltchenko 343260918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS) 343360918918SAndrei Emeltchenko if (chan->fcs == L2CAP_FCS_NONE || 3434f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { 343560918918SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 343660918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, 343760918918SAndrei Emeltchenko chan->fcs); 343860918918SAndrei Emeltchenko } 34390a708f8fSGustavo F. Padovan break; 34400a708f8fSGustavo F. Padovan 34410a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3442273759e2SMat Martineau l2cap_txwin_setup(chan); 34430a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING; 34440a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 34450a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 34460a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 34470a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 3448c8f79162SAndrei Emeltchenko 3449c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 34502d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - 3451c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3452c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 34530a708f8fSGustavo F. Padovan 34540a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 34550a708f8fSGustavo F. Padovan (unsigned long) &rfc); 34560a708f8fSGustavo F. Padovan 3457f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 3458f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 3459f89cef09SAndrei Emeltchenko 346060918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS) 346147d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 3462f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { 346347d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 346460918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, 346560918918SAndrei Emeltchenko chan->fcs); 34660a708f8fSGustavo F. Padovan } 34670a708f8fSGustavo F. Padovan break; 34680a708f8fSGustavo F. Padovan } 34690a708f8fSGustavo F. Padovan 3470fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 347159e54bd1SAndrei Emeltchenko req->flags = __constant_cpu_to_le16(0); 34720a708f8fSGustavo F. Padovan 34730a708f8fSGustavo F. Padovan return ptr - data; 34740a708f8fSGustavo F. Padovan } 34750a708f8fSGustavo F. Padovan 347673ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) 34770a708f8fSGustavo F. Padovan { 34780a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 34790a708f8fSGustavo F. Padovan void *ptr = rsp->data; 348073ffa904SGustavo F. Padovan void *req = chan->conf_req; 348173ffa904SGustavo F. Padovan int len = chan->conf_len; 34820a708f8fSGustavo F. Padovan int type, hint, olen; 34830a708f8fSGustavo F. Padovan unsigned long val; 34840a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 348542dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs; 348642dceae2SAndrei Emeltchenko u8 remote_efs = 0; 34870a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU; 34880a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS; 3489c8f79162SAndrei Emeltchenko u16 size; 34900a708f8fSGustavo F. Padovan 349173ffa904SGustavo F. Padovan BT_DBG("chan %p", chan); 34920a708f8fSGustavo F. Padovan 34930a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 34940a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val); 34950a708f8fSGustavo F. Padovan 34960a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT; 34970a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK; 34980a708f8fSGustavo F. Padovan 34990a708f8fSGustavo F. Padovan switch (type) { 35000a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 35010a708f8fSGustavo F. Padovan mtu = val; 35020a708f8fSGustavo F. Padovan break; 35030a708f8fSGustavo F. Padovan 35040a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 35050c1bc5c6SGustavo F. Padovan chan->flush_to = val; 35060a708f8fSGustavo F. Padovan break; 35070a708f8fSGustavo F. Padovan 35080a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS: 35090a708f8fSGustavo F. Padovan break; 35100a708f8fSGustavo F. Padovan 35110a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 35120a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 35130a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen); 35140a708f8fSGustavo F. Padovan break; 35150a708f8fSGustavo F. Padovan 35160a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS: 35170a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE) 3518f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, &chan->conf_state); 351942dceae2SAndrei Emeltchenko break; 35200a708f8fSGustavo F. Padovan 352142dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS: 352242dceae2SAndrei Emeltchenko remote_efs = 1; 352342dceae2SAndrei Emeltchenko if (olen == sizeof(efs)) 352442dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen); 35250a708f8fSGustavo F. Padovan break; 35260a708f8fSGustavo F. Padovan 35276327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 3528848566b3SMarcel Holtmann if (!chan->conn->hs_enabled) 35296327eb98SAndrei Emeltchenko return -ECONNREFUSED; 35306327eb98SAndrei Emeltchenko 35316327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 35326327eb98SAndrei Emeltchenko set_bit(CONF_EWS_RECV, &chan->conf_state); 3533836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 35346327eb98SAndrei Emeltchenko chan->remote_tx_win = val; 35350a708f8fSGustavo F. Padovan break; 35360a708f8fSGustavo F. Padovan 35370a708f8fSGustavo F. Padovan default: 35380a708f8fSGustavo F. Padovan if (hint) 35390a708f8fSGustavo F. Padovan break; 35400a708f8fSGustavo F. Padovan 35410a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN; 35420a708f8fSGustavo F. Padovan *((u8 *) ptr++) = type; 35430a708f8fSGustavo F. Padovan break; 35440a708f8fSGustavo F. Padovan } 35450a708f8fSGustavo F. Padovan } 35460a708f8fSGustavo F. Padovan 354773ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1) 35480a708f8fSGustavo F. Padovan goto done; 35490a708f8fSGustavo F. Padovan 35500c1bc5c6SGustavo F. Padovan switch (chan->mode) { 35510a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 35520a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3553c1360a1cSGustavo F. Padovan if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { 35540c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, 35558c1d787bSGustavo F. Padovan chan->conn->feat_mask); 35560a708f8fSGustavo F. Padovan break; 35570a708f8fSGustavo F. Padovan } 35580a708f8fSGustavo F. Padovan 355942dceae2SAndrei Emeltchenko if (remote_efs) { 3560848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn)) 356142dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 356242dceae2SAndrei Emeltchenko else 356342dceae2SAndrei Emeltchenko return -ECONNREFUSED; 356442dceae2SAndrei Emeltchenko } 356542dceae2SAndrei Emeltchenko 35660c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) 35670a708f8fSGustavo F. Padovan return -ECONNREFUSED; 35680a708f8fSGustavo F. Padovan 35690a708f8fSGustavo F. Padovan break; 35700a708f8fSGustavo F. Padovan } 35710a708f8fSGustavo F. Padovan 35720a708f8fSGustavo F. Padovan done: 35730c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) { 35740a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 35750c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 35760a708f8fSGustavo F. Padovan 357773ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1) 35780a708f8fSGustavo F. Padovan return -ECONNREFUSED; 35790a708f8fSGustavo F. Padovan 35802d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 35812d792818SGustavo Padovan (unsigned long) &rfc); 35820a708f8fSGustavo F. Padovan } 35830a708f8fSGustavo F. Padovan 35840a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) { 35850a708f8fSGustavo F. Padovan /* Configure output options and let the other side know 35860a708f8fSGustavo F. Padovan * which ones we don't like. */ 35870a708f8fSGustavo F. Padovan 35880a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU) 35890a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 35900a708f8fSGustavo F. Padovan else { 35910c1bc5c6SGustavo F. Padovan chan->omtu = mtu; 3592c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state); 35930a708f8fSGustavo F. Padovan } 35940c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); 35950a708f8fSGustavo F. Padovan 359642dceae2SAndrei Emeltchenko if (remote_efs) { 359742dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 359842dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 359942dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) { 360042dceae2SAndrei Emeltchenko 360142dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT; 360242dceae2SAndrei Emeltchenko 360342dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1) 360442dceae2SAndrei Emeltchenko return -ECONNREFUSED; 360542dceae2SAndrei Emeltchenko 360642dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 360742dceae2SAndrei Emeltchenko sizeof(efs), 360842dceae2SAndrei Emeltchenko (unsigned long) &efs); 36090e8b207eSAndrei Emeltchenko } else { 36103e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */ 36110e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING; 36120e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 361342dceae2SAndrei Emeltchenko } 361442dceae2SAndrei Emeltchenko } 361542dceae2SAndrei Emeltchenko 36160a708f8fSGustavo F. Padovan switch (rfc.mode) { 36170a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 361847d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3619c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 36200a708f8fSGustavo F. Padovan break; 36210a708f8fSGustavo F. Padovan 36220a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 36236327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state)) 36242c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size; 36256327eb98SAndrei Emeltchenko else 36266327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; 36276327eb98SAndrei Emeltchenko 36282c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit; 36290a708f8fSGustavo F. Padovan 3630c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 36312d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE - 36322d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); 3633c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3634c8f79162SAndrei Emeltchenko chan->remote_mps = size; 36350a708f8fSGustavo F. Padovan 363636c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc); 36370a708f8fSGustavo F. Padovan 3638c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 36390a708f8fSGustavo F. Padovan 36400a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 36410a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 36420a708f8fSGustavo F. Padovan 364342dceae2SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 364442dceae2SAndrei Emeltchenko chan->remote_id = efs.id; 364542dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype; 364642dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu); 364742dceae2SAndrei Emeltchenko chan->remote_flush_to = 364842dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to); 364942dceae2SAndrei Emeltchenko chan->remote_acc_lat = 365042dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat); 365142dceae2SAndrei Emeltchenko chan->remote_sdu_itime = 365242dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 365342dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 36542d792818SGustavo Padovan sizeof(efs), 36552d792818SGustavo Padovan (unsigned long) &efs); 365642dceae2SAndrei Emeltchenko } 36570a708f8fSGustavo F. Padovan break; 36580a708f8fSGustavo F. Padovan 36590a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3660c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 36612d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE - 36622d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); 3663c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3664c8f79162SAndrei Emeltchenko chan->remote_mps = size; 36650a708f8fSGustavo F. Padovan 3666c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 36670a708f8fSGustavo F. Padovan 36682d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 36692d792818SGustavo Padovan (unsigned long) &rfc); 36700a708f8fSGustavo F. Padovan 36710a708f8fSGustavo F. Padovan break; 36720a708f8fSGustavo F. Padovan 36730a708f8fSGustavo F. Padovan default: 36740a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 36750a708f8fSGustavo F. Padovan 36760a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc)); 36770c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 36780a708f8fSGustavo F. Padovan } 36790a708f8fSGustavo F. Padovan 36800a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) 3681c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 36820a708f8fSGustavo F. Padovan } 3683fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 36840a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 368559e54bd1SAndrei Emeltchenko rsp->flags = __constant_cpu_to_le16(0); 36860a708f8fSGustavo F. Padovan 36870a708f8fSGustavo F. Padovan return ptr - data; 36880a708f8fSGustavo F. Padovan } 36890a708f8fSGustavo F. Padovan 36902d792818SGustavo Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, 36912d792818SGustavo Padovan void *data, u16 *result) 36920a708f8fSGustavo F. Padovan { 36930a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 36940a708f8fSGustavo F. Padovan void *ptr = req->data; 36950a708f8fSGustavo F. Padovan int type, olen; 36960a708f8fSGustavo F. Padovan unsigned long val; 369736e999a8SMat Martineau struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 369866af7aafSAndrei Emeltchenko struct l2cap_conf_efs efs; 36990a708f8fSGustavo F. Padovan 3700fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); 37010a708f8fSGustavo F. Padovan 37020a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 37030a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 37040a708f8fSGustavo F. Padovan 37050a708f8fSGustavo F. Padovan switch (type) { 37060a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 37070a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) { 37080a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT; 37090c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU; 37100a708f8fSGustavo F. Padovan } else 37110c1bc5c6SGustavo F. Padovan chan->imtu = val; 37120c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 37130a708f8fSGustavo F. Padovan break; 37140a708f8fSGustavo F. Padovan 37150a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 37160c1bc5c6SGustavo F. Padovan chan->flush_to = val; 37170a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 37180c1bc5c6SGustavo F. Padovan 2, chan->flush_to); 37190a708f8fSGustavo F. Padovan break; 37200a708f8fSGustavo F. Padovan 37210a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 37220a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 37230a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 37240a708f8fSGustavo F. Padovan 3725c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && 37260c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode) 37270a708f8fSGustavo F. Padovan return -ECONNREFUSED; 37280a708f8fSGustavo F. Padovan 372947d1ec61SGustavo F. Padovan chan->fcs = 0; 37300a708f8fSGustavo F. Padovan 37310a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 37320a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 37330a708f8fSGustavo F. Padovan break; 37346327eb98SAndrei Emeltchenko 37356327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 3736c20f8e35SMat Martineau chan->ack_win = min_t(u16, val, chan->ack_win); 37373e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 37383e6b3b95SGustavo F. Padovan chan->tx_win); 37396327eb98SAndrei Emeltchenko break; 374066af7aafSAndrei Emeltchenko 374166af7aafSAndrei Emeltchenko case L2CAP_CONF_EFS: 374266af7aafSAndrei Emeltchenko if (olen == sizeof(efs)) 374366af7aafSAndrei Emeltchenko memcpy(&efs, (void *)val, olen); 374466af7aafSAndrei Emeltchenko 374566af7aafSAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 374666af7aafSAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 374766af7aafSAndrei Emeltchenko efs.stype != chan->local_stype) 374866af7aafSAndrei Emeltchenko return -ECONNREFUSED; 374966af7aafSAndrei Emeltchenko 37502d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), 37512d792818SGustavo Padovan (unsigned long) &efs); 375266af7aafSAndrei Emeltchenko break; 3753cbabee78SAndrei Emeltchenko 3754cbabee78SAndrei Emeltchenko case L2CAP_CONF_FCS: 3755cbabee78SAndrei Emeltchenko if (*result == L2CAP_CONF_PENDING) 3756cbabee78SAndrei Emeltchenko if (val == L2CAP_FCS_NONE) 3757f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, 3758cbabee78SAndrei Emeltchenko &chan->conf_state); 3759cbabee78SAndrei Emeltchenko break; 37600a708f8fSGustavo F. Padovan } 37610a708f8fSGustavo F. Padovan } 37620a708f8fSGustavo F. Padovan 37630c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) 37640a708f8fSGustavo F. Padovan return -ECONNREFUSED; 37650a708f8fSGustavo F. Padovan 37660c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode; 37670a708f8fSGustavo F. Padovan 37680e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) { 37690a708f8fSGustavo F. Padovan switch (rfc.mode) { 37700a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 377147d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 377247d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 377347d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 3774c20f8e35SMat Martineau if (!test_bit(FLAG_EXT_CTRL, &chan->flags)) 3775c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 3776c20f8e35SMat Martineau rfc.txwin_size); 377766af7aafSAndrei Emeltchenko 377866af7aafSAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 377966af7aafSAndrei Emeltchenko chan->local_msdu = le16_to_cpu(efs.msdu); 378066af7aafSAndrei Emeltchenko chan->local_sdu_itime = 378166af7aafSAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 378266af7aafSAndrei Emeltchenko chan->local_acc_lat = le32_to_cpu(efs.acc_lat); 378366af7aafSAndrei Emeltchenko chan->local_flush_to = 378466af7aafSAndrei Emeltchenko le32_to_cpu(efs.flush_to); 378566af7aafSAndrei Emeltchenko } 37860a708f8fSGustavo F. Padovan break; 378766af7aafSAndrei Emeltchenko 37880a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 378947d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 37900a708f8fSGustavo F. Padovan } 37910a708f8fSGustavo F. Padovan } 37920a708f8fSGustavo F. Padovan 3793fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 379459e54bd1SAndrei Emeltchenko req->flags = __constant_cpu_to_le16(0); 37950a708f8fSGustavo F. Padovan 37960a708f8fSGustavo F. Padovan return ptr - data; 37970a708f8fSGustavo F. Padovan } 37980a708f8fSGustavo F. Padovan 37992d792818SGustavo Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, 38002d792818SGustavo Padovan u16 result, u16 flags) 38010a708f8fSGustavo F. Padovan { 38020a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 38030a708f8fSGustavo F. Padovan void *ptr = rsp->data; 38040a708f8fSGustavo F. Padovan 3805fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan); 38060a708f8fSGustavo F. Padovan 3807fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 38080a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 38090a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags); 38100a708f8fSGustavo F. Padovan 38110a708f8fSGustavo F. Padovan return ptr - data; 38120a708f8fSGustavo F. Padovan } 38130a708f8fSGustavo F. Padovan 381427e2d4c8SJohan Hedberg void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan) 381527e2d4c8SJohan Hedberg { 381627e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 381727e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn; 381827e2d4c8SJohan Hedberg 381927e2d4c8SJohan Hedberg BT_DBG("chan %p", chan); 382027e2d4c8SJohan Hedberg 382127e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 382227e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 382327e2d4c8SJohan Hedberg rsp.mps = __constant_cpu_to_le16(L2CAP_LE_DEFAULT_MPS); 38240cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits); 382527e2d4c8SJohan Hedberg rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 382627e2d4c8SJohan Hedberg 382727e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), 382827e2d4c8SJohan Hedberg &rsp); 382927e2d4c8SJohan Hedberg } 383027e2d4c8SJohan Hedberg 38318c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) 3832710f9b0aSGustavo F. Padovan { 3833710f9b0aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 38348c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 3835710f9b0aSGustavo F. Padovan u8 buf[128]; 3836439f34acSAndrei Emeltchenko u8 rsp_code; 3837710f9b0aSGustavo F. Padovan 3838fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 3839fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3840ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 3841ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 3842439f34acSAndrei Emeltchenko 3843439f34acSAndrei Emeltchenko if (chan->hs_hcon) 3844439f34acSAndrei Emeltchenko rsp_code = L2CAP_CREATE_CHAN_RSP; 3845439f34acSAndrei Emeltchenko else 3846439f34acSAndrei Emeltchenko rsp_code = L2CAP_CONN_RSP; 3847439f34acSAndrei Emeltchenko 3848439f34acSAndrei Emeltchenko BT_DBG("chan %p rsp_code %u", chan, rsp_code); 3849439f34acSAndrei Emeltchenko 3850439f34acSAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp); 3851710f9b0aSGustavo F. Padovan 3852c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 3853710f9b0aSGustavo F. Padovan return; 3854710f9b0aSGustavo F. Padovan 3855710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 3856710f9b0aSGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 3857710f9b0aSGustavo F. Padovan chan->num_conf_req++; 3858710f9b0aSGustavo F. Padovan } 3859710f9b0aSGustavo F. Padovan 386047d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) 38610a708f8fSGustavo F. Padovan { 38620a708f8fSGustavo F. Padovan int type, olen; 38630a708f8fSGustavo F. Padovan unsigned long val; 3864c20f8e35SMat Martineau /* Use sane default values in case a misbehaving remote device 3865c20f8e35SMat Martineau * did not send an RFC or extended window size option. 3866c20f8e35SMat Martineau */ 3867c20f8e35SMat Martineau u16 txwin_ext = chan->ack_win; 3868c20f8e35SMat Martineau struct l2cap_conf_rfc rfc = { 3869c20f8e35SMat Martineau .mode = chan->mode, 3870c20f8e35SMat Martineau .retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO), 3871c20f8e35SMat Martineau .monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO), 3872c20f8e35SMat Martineau .max_pdu_size = cpu_to_le16(chan->imtu), 3873c20f8e35SMat Martineau .txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW), 3874c20f8e35SMat Martineau }; 38750a708f8fSGustavo F. Padovan 387647d1ec61SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); 38770a708f8fSGustavo F. Padovan 38780c1bc5c6SGustavo F. Padovan if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) 38790a708f8fSGustavo F. Padovan return; 38800a708f8fSGustavo F. Padovan 38810a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 38820a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 38830a708f8fSGustavo F. Padovan 3884c20f8e35SMat Martineau switch (type) { 3885c20f8e35SMat Martineau case L2CAP_CONF_RFC: 3886c20f8e35SMat Martineau if (olen == sizeof(rfc)) 38870a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 3888c20f8e35SMat Martineau break; 3889c20f8e35SMat Martineau case L2CAP_CONF_EWS: 3890c20f8e35SMat Martineau txwin_ext = val; 3891c20f8e35SMat Martineau break; 3892c20f8e35SMat Martineau } 38930a708f8fSGustavo F. Padovan } 38940a708f8fSGustavo F. Padovan 38950a708f8fSGustavo F. Padovan switch (rfc.mode) { 38960a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 389747d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 389847d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 389947d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 3900c20f8e35SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 3901c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, txwin_ext); 3902c20f8e35SMat Martineau else 3903c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 3904c20f8e35SMat Martineau rfc.txwin_size); 39050a708f8fSGustavo F. Padovan break; 39060a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 390747d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 39080a708f8fSGustavo F. Padovan } 39090a708f8fSGustavo F. Padovan } 39100a708f8fSGustavo F. Padovan 39112d792818SGustavo Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, 3912cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 3913cb3b3152SJohan Hedberg u8 *data) 39140a708f8fSGustavo F. Padovan { 3915e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 39160a708f8fSGustavo F. Padovan 3917cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rej)) 3918cb3b3152SJohan Hedberg return -EPROTO; 3919cb3b3152SJohan Hedberg 3920e2fd318eSIlia Kolomisnky if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) 39210a708f8fSGustavo F. Padovan return 0; 39220a708f8fSGustavo F. Padovan 39230a708f8fSGustavo F. Padovan if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && 39240a708f8fSGustavo F. Padovan cmd->ident == conn->info_ident) { 392517cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 39260a708f8fSGustavo F. Padovan 39270a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 39280a708f8fSGustavo F. Padovan conn->info_ident = 0; 39290a708f8fSGustavo F. Padovan 39300a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 39310a708f8fSGustavo F. Padovan } 39320a708f8fSGustavo F. Padovan 39330a708f8fSGustavo F. Padovan return 0; 39340a708f8fSGustavo F. Padovan } 39350a708f8fSGustavo F. Padovan 39361700915fSMat Martineau static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, 39371700915fSMat Martineau struct l2cap_cmd_hdr *cmd, 39384c89b6aaSMat Martineau u8 *data, u8 rsp_code, u8 amp_id) 39390a708f8fSGustavo F. Padovan { 39400a708f8fSGustavo F. Padovan struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 39410a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 394223691d75SGustavo F. Padovan struct l2cap_chan *chan = NULL, *pchan; 39430a708f8fSGustavo F. Padovan int result, status = L2CAP_CS_NO_INFO; 39440a708f8fSGustavo F. Padovan 39450a708f8fSGustavo F. Padovan u16 dcid = 0, scid = __le16_to_cpu(req->scid); 39460a708f8fSGustavo F. Padovan __le16 psm = req->psm; 39470a708f8fSGustavo F. Padovan 3948097db76cSAndrei Emeltchenko BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); 39490a708f8fSGustavo F. Padovan 39500a708f8fSGustavo F. Padovan /* Check if we have socket listening on psm */ 39516f59b904SMarcel Holtmann pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 3952bf20fd4eSJohan Hedberg &conn->hcon->dst, ACL_LINK); 395323691d75SGustavo F. Padovan if (!pchan) { 39540a708f8fSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 39550a708f8fSGustavo F. Padovan goto sendresp; 39560a708f8fSGustavo F. Padovan } 39570a708f8fSGustavo F. Padovan 39583df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 39598ffb9290SGustavo Padovan l2cap_chan_lock(pchan); 39600a708f8fSGustavo F. Padovan 39610a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */ 39622983fd68SAndrei Emeltchenko if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) && 39630a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) { 39649f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_AUTH_FAILURE; 39650a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 39660a708f8fSGustavo F. Padovan goto response; 39670a708f8fSGustavo F. Padovan } 39680a708f8fSGustavo F. Padovan 39690a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM; 39700a708f8fSGustavo F. Padovan 39712dfa1003SGustavo Padovan /* Check if we already have channel with that dcid */ 39722dfa1003SGustavo Padovan if (__l2cap_get_chan_by_dcid(conn, scid)) 39732dfa1003SGustavo Padovan goto response; 39742dfa1003SGustavo Padovan 397580b98027SGustavo Padovan chan = pchan->ops->new_connection(pchan); 397680808e43SGustavo F. Padovan if (!chan) 39770a708f8fSGustavo F. Padovan goto response; 39780a708f8fSGustavo F. Padovan 3979330b6c15SSyam Sidhardhan /* For certain devices (ex: HID mouse), support for authentication, 3980330b6c15SSyam Sidhardhan * pairing and bonding is optional. For such devices, inorder to avoid 3981330b6c15SSyam Sidhardhan * the ACL alive for too long after L2CAP disconnection, reset the ACL 3982330b6c15SSyam Sidhardhan * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect. 3983330b6c15SSyam Sidhardhan */ 3984330b6c15SSyam Sidhardhan conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 3985330b6c15SSyam Sidhardhan 39867eafc59eSMarcel Holtmann bacpy(&chan->src, &conn->hcon->src); 39877eafc59eSMarcel Holtmann bacpy(&chan->dst, &conn->hcon->dst); 39884f1654e0SMarcel Holtmann chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type); 39894f1654e0SMarcel Holtmann chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type); 3990fe4128e0SGustavo F. Padovan chan->psm = psm; 3991fe4128e0SGustavo F. Padovan chan->dcid = scid; 39921700915fSMat Martineau chan->local_amp_id = amp_id; 39930a708f8fSGustavo F. Padovan 39946be36555SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 399548454079SGustavo F. Padovan 3996fe4128e0SGustavo F. Padovan dcid = chan->scid; 39970a708f8fSGustavo F. Padovan 39988d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 39990a708f8fSGustavo F. Padovan 4000fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident; 40010a708f8fSGustavo F. Padovan 40020a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { 4003d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 4004bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 4005f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 40060a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 40070a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND; 40082dc4e510SGustavo Padovan chan->ops->defer(chan); 40090a708f8fSGustavo F. Padovan } else { 40101700915fSMat Martineau /* Force pending result for AMP controllers. 40111700915fSMat Martineau * The connection will succeed after the 40121700915fSMat Martineau * physical link is up. 40131700915fSMat Martineau */ 40146ed971caSMarcel Holtmann if (amp_id == AMP_ID_BREDR) { 4015f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 40160a708f8fSGustavo F. Padovan result = L2CAP_CR_SUCCESS; 40176ed971caSMarcel Holtmann } else { 4018f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 40196ed971caSMarcel Holtmann result = L2CAP_CR_PEND; 40201700915fSMat Martineau } 40210a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 40220a708f8fSGustavo F. Padovan } 40230a708f8fSGustavo F. Padovan } else { 4024f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 40250a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 40260a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND; 40270a708f8fSGustavo F. Padovan } 40280a708f8fSGustavo F. Padovan } else { 4029f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 40300a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 40310a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 40320a708f8fSGustavo F. Padovan } 40330a708f8fSGustavo F. Padovan 40340a708f8fSGustavo F. Padovan response: 40358ffb9290SGustavo Padovan l2cap_chan_unlock(pchan); 40363df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 40370a708f8fSGustavo F. Padovan 40380a708f8fSGustavo F. Padovan sendresp: 40390a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid); 40400a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid); 40410a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result); 40420a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status); 40434c89b6aaSMat Martineau l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp); 40440a708f8fSGustavo F. Padovan 40450a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { 40460a708f8fSGustavo F. Padovan struct l2cap_info_req info; 4047ac73498cSAndrei Emeltchenko info.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); 40480a708f8fSGustavo F. Padovan 40490a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 40500a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 40510a708f8fSGustavo F. Padovan 4052ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 40530a708f8fSGustavo F. Padovan 40542d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, 40552d792818SGustavo Padovan sizeof(info), &info); 40560a708f8fSGustavo F. Padovan } 40570a708f8fSGustavo F. Padovan 4058c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && 40590a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) { 40600a708f8fSGustavo F. Padovan u8 buf[128]; 4061c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 40620a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 406373ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 406473ffa904SGustavo F. Padovan chan->num_conf_req++; 40650a708f8fSGustavo F. Padovan } 40661700915fSMat Martineau 40671700915fSMat Martineau return chan; 40684c89b6aaSMat Martineau } 40690a708f8fSGustavo F. Padovan 40704c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn, 4071cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 40724c89b6aaSMat Martineau { 40737b064edaSJaganath Kanakkassery struct hci_dev *hdev = conn->hcon->hdev; 40747b064edaSJaganath Kanakkassery struct hci_conn *hcon = conn->hcon; 40757b064edaSJaganath Kanakkassery 4076cb3b3152SJohan Hedberg if (cmd_len < sizeof(struct l2cap_conn_req)) 4077cb3b3152SJohan Hedberg return -EPROTO; 4078cb3b3152SJohan Hedberg 40797b064edaSJaganath Kanakkassery hci_dev_lock(hdev); 40807b064edaSJaganath Kanakkassery if (test_bit(HCI_MGMT, &hdev->dev_flags) && 40817b064edaSJaganath Kanakkassery !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags)) 40827b064edaSJaganath Kanakkassery mgmt_device_connected(hdev, &hcon->dst, hcon->type, 40837b064edaSJaganath Kanakkassery hcon->dst_type, 0, NULL, 0, 40847b064edaSJaganath Kanakkassery hcon->dev_class); 40857b064edaSJaganath Kanakkassery hci_dev_unlock(hdev); 40867b064edaSJaganath Kanakkassery 4087300229f9SGustavo Padovan l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0); 40880a708f8fSGustavo F. Padovan return 0; 40890a708f8fSGustavo F. Padovan } 40900a708f8fSGustavo F. Padovan 40915909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn, 4092cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4093cb3b3152SJohan Hedberg u8 *data) 40940a708f8fSGustavo F. Padovan { 40950a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; 40960a708f8fSGustavo F. Padovan u16 scid, dcid, result, status; 409748454079SGustavo F. Padovan struct l2cap_chan *chan; 40980a708f8fSGustavo F. Padovan u8 req[128]; 40993df91ea2SAndrei Emeltchenko int err; 41000a708f8fSGustavo F. Padovan 4101cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp)) 4102cb3b3152SJohan Hedberg return -EPROTO; 4103cb3b3152SJohan Hedberg 41040a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 41050a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 41060a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 41070a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status); 41080a708f8fSGustavo F. Padovan 41091b009c98SAndrei Emeltchenko BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", 41101b009c98SAndrei Emeltchenko dcid, scid, result, status); 41110a708f8fSGustavo F. Padovan 41123df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 41133df91ea2SAndrei Emeltchenko 41140a708f8fSGustavo F. Padovan if (scid) { 41153df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 41163df91ea2SAndrei Emeltchenko if (!chan) { 411721870b52SJohan Hedberg err = -EBADSLT; 41183df91ea2SAndrei Emeltchenko goto unlock; 41193df91ea2SAndrei Emeltchenko } 41200a708f8fSGustavo F. Padovan } else { 41213df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 41223df91ea2SAndrei Emeltchenko if (!chan) { 412321870b52SJohan Hedberg err = -EBADSLT; 41243df91ea2SAndrei Emeltchenko goto unlock; 41253df91ea2SAndrei Emeltchenko } 41260a708f8fSGustavo F. Padovan } 41270a708f8fSGustavo F. Padovan 41283df91ea2SAndrei Emeltchenko err = 0; 41293df91ea2SAndrei Emeltchenko 41306be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 413148454079SGustavo F. Padovan 41320a708f8fSGustavo F. Padovan switch (result) { 41330a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS: 413489bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 4135fc7f8a7eSGustavo F. Padovan chan->ident = 0; 4136fe4128e0SGustavo F. Padovan chan->dcid = dcid; 4137c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state); 41380a708f8fSGustavo F. Padovan 4139c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 41400a708f8fSGustavo F. Padovan break; 41410a708f8fSGustavo F. Padovan 41420a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 414373ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, req), req); 414473ffa904SGustavo F. Padovan chan->num_conf_req++; 41450a708f8fSGustavo F. Padovan break; 41460a708f8fSGustavo F. Padovan 41470a708f8fSGustavo F. Padovan case L2CAP_CR_PEND: 4148c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 41490a708f8fSGustavo F. Padovan break; 41500a708f8fSGustavo F. Padovan 41510a708f8fSGustavo F. Padovan default: 415248454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED); 41530a708f8fSGustavo F. Padovan break; 41540a708f8fSGustavo F. Padovan } 41550a708f8fSGustavo F. Padovan 41566be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 41573df91ea2SAndrei Emeltchenko 41583df91ea2SAndrei Emeltchenko unlock: 41593df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 41603df91ea2SAndrei Emeltchenko 41613df91ea2SAndrei Emeltchenko return err; 41620a708f8fSGustavo F. Padovan } 41630a708f8fSGustavo F. Padovan 416447d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan) 41650a708f8fSGustavo F. Padovan { 41660a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both 41670a708f8fSGustavo F. Padovan * sides request it. 41680a708f8fSGustavo F. Padovan */ 41690c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) 417047d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 4171f2592d3eSAndrei Emeltchenko else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) 417247d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16; 41730a708f8fSGustavo F. Padovan } 41740a708f8fSGustavo F. Padovan 417529d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data, 417629d8a590SAndrei Emeltchenko u8 ident, u16 flags) 417729d8a590SAndrei Emeltchenko { 417829d8a590SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 417929d8a590SAndrei Emeltchenko 418029d8a590SAndrei Emeltchenko BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident, 418129d8a590SAndrei Emeltchenko flags); 418229d8a590SAndrei Emeltchenko 418329d8a590SAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 418429d8a590SAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 418529d8a590SAndrei Emeltchenko 418629d8a590SAndrei Emeltchenko l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP, 418729d8a590SAndrei Emeltchenko l2cap_build_conf_rsp(chan, data, 418829d8a590SAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), data); 418929d8a590SAndrei Emeltchenko } 419029d8a590SAndrei Emeltchenko 4191662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident, 4192662d652dSJohan Hedberg u16 scid, u16 dcid) 4193662d652dSJohan Hedberg { 4194662d652dSJohan Hedberg struct l2cap_cmd_rej_cid rej; 4195662d652dSJohan Hedberg 4196662d652dSJohan Hedberg rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID); 4197662d652dSJohan Hedberg rej.scid = __cpu_to_le16(scid); 4198662d652dSJohan Hedberg rej.dcid = __cpu_to_le16(dcid); 4199662d652dSJohan Hedberg 4200662d652dSJohan Hedberg l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); 4201662d652dSJohan Hedberg } 4202662d652dSJohan Hedberg 42032d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, 42042d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len, 42052d792818SGustavo Padovan u8 *data) 42060a708f8fSGustavo F. Padovan { 42070a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; 42080a708f8fSGustavo F. Padovan u16 dcid, flags; 42090a708f8fSGustavo F. Padovan u8 rsp[64]; 421048454079SGustavo F. Padovan struct l2cap_chan *chan; 42113c588192SMat Martineau int len, err = 0; 42120a708f8fSGustavo F. Padovan 4213cb3b3152SJohan Hedberg if (cmd_len < sizeof(*req)) 4214cb3b3152SJohan Hedberg return -EPROTO; 4215cb3b3152SJohan Hedberg 42160a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 42170a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags); 42180a708f8fSGustavo F. Padovan 42190a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); 42200a708f8fSGustavo F. Padovan 4221baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid); 4222662d652dSJohan Hedberg if (!chan) { 4223662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0); 4224662d652dSJohan Hedberg return 0; 4225662d652dSJohan Hedberg } 42260a708f8fSGustavo F. Padovan 4227033b1142SDavid S. Miller if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { 4228662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, 4229662d652dSJohan Hedberg chan->dcid); 42300a708f8fSGustavo F. Padovan goto unlock; 42310a708f8fSGustavo F. Padovan } 42320a708f8fSGustavo F. Padovan 42330a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */ 42340a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req); 4235cb3b3152SJohan Hedberg if (chan->conf_len + len > sizeof(chan->conf_req)) { 42360a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 4237fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 42380a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp); 42390a708f8fSGustavo F. Padovan goto unlock; 42400a708f8fSGustavo F. Padovan } 42410a708f8fSGustavo F. Padovan 42420a708f8fSGustavo F. Padovan /* Store config. */ 424373ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len); 424473ffa904SGustavo F. Padovan chan->conf_len += len; 42450a708f8fSGustavo F. Padovan 424659e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) { 42470a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */ 42480a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 4249fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 42505325e5bbSAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), rsp); 42510a708f8fSGustavo F. Padovan goto unlock; 42520a708f8fSGustavo F. Padovan } 42530a708f8fSGustavo F. Padovan 42540a708f8fSGustavo F. Padovan /* Complete config. */ 425573ffa904SGustavo F. Padovan len = l2cap_parse_conf_req(chan, rsp); 42560a708f8fSGustavo F. Padovan if (len < 0) { 42575e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 42580a708f8fSGustavo F. Padovan goto unlock; 42590a708f8fSGustavo F. Padovan } 42600a708f8fSGustavo F. Padovan 42611500109bSMat Martineau chan->ident = cmd->ident; 42620a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); 426373ffa904SGustavo F. Padovan chan->num_conf_rsp++; 42640a708f8fSGustavo F. Padovan 42650a708f8fSGustavo F. Padovan /* Reset config buffer. */ 426673ffa904SGustavo F. Padovan chan->conf_len = 0; 42670a708f8fSGustavo F. Padovan 4268c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) 42690a708f8fSGustavo F. Padovan goto unlock; 42700a708f8fSGustavo F. Padovan 4271c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 427247d1ec61SGustavo F. Padovan set_default_fcs(chan); 42730a708f8fSGustavo F. Padovan 4274105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 4275105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 42763c588192SMat Martineau err = l2cap_ertm_init(chan); 42770a708f8fSGustavo F. Padovan 42783c588192SMat Martineau if (err < 0) 42795e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 42803c588192SMat Martineau else 4281cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 42823c588192SMat Martineau 42830a708f8fSGustavo F. Padovan goto unlock; 42840a708f8fSGustavo F. Padovan } 42850a708f8fSGustavo F. Padovan 4286c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { 42870a708f8fSGustavo F. Padovan u8 buf[64]; 42880a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 428973ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 429073ffa904SGustavo F. Padovan chan->num_conf_req++; 42910a708f8fSGustavo F. Padovan } 42920a708f8fSGustavo F. Padovan 42930e8b207eSAndrei Emeltchenko /* Got Conf Rsp PENDING from remote side and asume we sent 42940e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */ 42950e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && 42960e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 42970e8b207eSAndrei Emeltchenko 42980e8b207eSAndrei Emeltchenko /* check compatibility */ 42990e8b207eSAndrei Emeltchenko 430079de886dSAndrei Emeltchenko /* Send rsp for BR/EDR channel */ 4301f351bc72SAndrei Emeltchenko if (!chan->hs_hcon) 430229d8a590SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags); 430379de886dSAndrei Emeltchenko else 430479de886dSAndrei Emeltchenko chan->ident = cmd->ident; 43050e8b207eSAndrei Emeltchenko } 43060e8b207eSAndrei Emeltchenko 43070a708f8fSGustavo F. Padovan unlock: 43086be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 43093c588192SMat Martineau return err; 43100a708f8fSGustavo F. Padovan } 43110a708f8fSGustavo F. Padovan 43122d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, 4313cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4314cb3b3152SJohan Hedberg u8 *data) 43150a708f8fSGustavo F. Padovan { 43160a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; 43170a708f8fSGustavo F. Padovan u16 scid, flags, result; 431848454079SGustavo F. Padovan struct l2cap_chan *chan; 4319cb3b3152SJohan Hedberg int len = cmd_len - sizeof(*rsp); 43203c588192SMat Martineau int err = 0; 43210a708f8fSGustavo F. Padovan 4322cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp)) 4323cb3b3152SJohan Hedberg return -EPROTO; 4324cb3b3152SJohan Hedberg 43250a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 43260a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags); 43270a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 43280a708f8fSGustavo F. Padovan 432961386cbaSAndrei Emeltchenko BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags, 433061386cbaSAndrei Emeltchenko result, len); 43310a708f8fSGustavo F. Padovan 4332baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 433348454079SGustavo F. Padovan if (!chan) 43340a708f8fSGustavo F. Padovan return 0; 43350a708f8fSGustavo F. Padovan 43360a708f8fSGustavo F. Padovan switch (result) { 43370a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS: 433847d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len); 43390e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state); 43400a708f8fSGustavo F. Padovan break; 43410a708f8fSGustavo F. Padovan 43420e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING: 43430e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state); 43440e8b207eSAndrei Emeltchenko 43450e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 43460e8b207eSAndrei Emeltchenko char buf[64]; 43470e8b207eSAndrei Emeltchenko 43480e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len, 43490e8b207eSAndrei Emeltchenko buf, &result); 43500e8b207eSAndrei Emeltchenko if (len < 0) { 43515e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 43520e8b207eSAndrei Emeltchenko goto done; 43530e8b207eSAndrei Emeltchenko } 43540e8b207eSAndrei Emeltchenko 4355f351bc72SAndrei Emeltchenko if (!chan->hs_hcon) { 435679de886dSAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, buf, cmd->ident, 435779de886dSAndrei Emeltchenko 0); 43585ce66b59SAndrei Emeltchenko } else { 43595ce66b59SAndrei Emeltchenko if (l2cap_check_efs(chan)) { 43605ce66b59SAndrei Emeltchenko amp_create_logical_link(chan); 436179de886dSAndrei Emeltchenko chan->ident = cmd->ident; 43620e8b207eSAndrei Emeltchenko } 43635ce66b59SAndrei Emeltchenko } 43645ce66b59SAndrei Emeltchenko } 43650e8b207eSAndrei Emeltchenko goto done; 43660e8b207eSAndrei Emeltchenko 43670a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT: 436873ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { 43690a708f8fSGustavo F. Padovan char req[64]; 43700a708f8fSGustavo F. Padovan 43710a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { 43725e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 43730a708f8fSGustavo F. Padovan goto done; 43740a708f8fSGustavo F. Padovan } 43750a708f8fSGustavo F. Padovan 43760a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */ 43770a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS; 4378b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len, 4379b4450035SGustavo F. Padovan req, &result); 43800a708f8fSGustavo F. Padovan if (len < 0) { 43815e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 43820a708f8fSGustavo F. Padovan goto done; 43830a708f8fSGustavo F. Padovan } 43840a708f8fSGustavo F. Padovan 43850a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 43860a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req); 438773ffa904SGustavo F. Padovan chan->num_conf_req++; 43880a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS) 43890a708f8fSGustavo F. Padovan goto done; 43900a708f8fSGustavo F. Padovan break; 43910a708f8fSGustavo F. Padovan } 43920a708f8fSGustavo F. Padovan 43930a708f8fSGustavo F. Padovan default: 43946be36555SAndrei Emeltchenko l2cap_chan_set_err(chan, ECONNRESET); 43952e0052e4SAndrei Emeltchenko 4396ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); 43975e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 43980a708f8fSGustavo F. Padovan goto done; 43990a708f8fSGustavo F. Padovan } 44000a708f8fSGustavo F. Padovan 440159e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) 44020a708f8fSGustavo F. Padovan goto done; 44030a708f8fSGustavo F. Padovan 4404c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state); 44050a708f8fSGustavo F. Padovan 4406c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { 440747d1ec61SGustavo F. Padovan set_default_fcs(chan); 44080a708f8fSGustavo F. Padovan 4409105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 4410105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 44113c588192SMat Martineau err = l2cap_ertm_init(chan); 44120a708f8fSGustavo F. Padovan 44133c588192SMat Martineau if (err < 0) 44145e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 44153c588192SMat Martineau else 4416cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 44170a708f8fSGustavo F. Padovan } 44180a708f8fSGustavo F. Padovan 44190a708f8fSGustavo F. Padovan done: 44206be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 44213c588192SMat Martineau return err; 44220a708f8fSGustavo F. Padovan } 44230a708f8fSGustavo F. Padovan 44242d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, 4425cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4426cb3b3152SJohan Hedberg u8 *data) 44270a708f8fSGustavo F. Padovan { 44280a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; 44290a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp; 44300a708f8fSGustavo F. Padovan u16 dcid, scid; 443148454079SGustavo F. Padovan struct l2cap_chan *chan; 44320a708f8fSGustavo F. Padovan 4433cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req)) 4434cb3b3152SJohan Hedberg return -EPROTO; 4435cb3b3152SJohan Hedberg 44360a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid); 44370a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 44380a708f8fSGustavo F. Padovan 44390a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); 44400a708f8fSGustavo F. Padovan 44413df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 44423df91ea2SAndrei Emeltchenko 44433df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, dcid); 44443df91ea2SAndrei Emeltchenko if (!chan) { 44453df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4446662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid); 4447662d652dSJohan Hedberg return 0; 44483df91ea2SAndrei Emeltchenko } 44490a708f8fSGustavo F. Padovan 44506be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 44516be36555SAndrei Emeltchenko 4452fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 4453fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 44540a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); 44550a708f8fSGustavo F. Padovan 44565ec1bbe5SGustavo Padovan chan->ops->set_shutdown(chan); 44570a708f8fSGustavo F. Padovan 445861d6ef3eSMat Martineau l2cap_chan_hold(chan); 445948454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET); 44606be36555SAndrei Emeltchenko 44616be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 44620a708f8fSGustavo F. Padovan 446380b98027SGustavo Padovan chan->ops->close(chan); 446461d6ef3eSMat Martineau l2cap_chan_put(chan); 44653df91ea2SAndrei Emeltchenko 44663df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 44673df91ea2SAndrei Emeltchenko 44680a708f8fSGustavo F. Padovan return 0; 44690a708f8fSGustavo F. Padovan } 44700a708f8fSGustavo F. Padovan 44712d792818SGustavo Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, 4472cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4473cb3b3152SJohan Hedberg u8 *data) 44740a708f8fSGustavo F. Padovan { 44750a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; 44760a708f8fSGustavo F. Padovan u16 dcid, scid; 447748454079SGustavo F. Padovan struct l2cap_chan *chan; 44780a708f8fSGustavo F. Padovan 4479cb3b3152SJohan Hedberg if (cmd_len != sizeof(*rsp)) 4480cb3b3152SJohan Hedberg return -EPROTO; 4481cb3b3152SJohan Hedberg 44820a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 44830a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 44840a708f8fSGustavo F. Padovan 44850a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); 44860a708f8fSGustavo F. Padovan 44873df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 44883df91ea2SAndrei Emeltchenko 44893df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 44903df91ea2SAndrei Emeltchenko if (!chan) { 44913df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 44920a708f8fSGustavo F. Padovan return 0; 44933df91ea2SAndrei Emeltchenko } 44940a708f8fSGustavo F. Padovan 44956be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 449648454079SGustavo F. Padovan 449761d6ef3eSMat Martineau l2cap_chan_hold(chan); 449848454079SGustavo F. Padovan l2cap_chan_del(chan, 0); 44996be36555SAndrei Emeltchenko 45006be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 45010a708f8fSGustavo F. Padovan 450280b98027SGustavo Padovan chan->ops->close(chan); 450361d6ef3eSMat Martineau l2cap_chan_put(chan); 45043df91ea2SAndrei Emeltchenko 45053df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 45063df91ea2SAndrei Emeltchenko 45070a708f8fSGustavo F. Padovan return 0; 45080a708f8fSGustavo F. Padovan } 45090a708f8fSGustavo F. Padovan 45102d792818SGustavo Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, 4511cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4512cb3b3152SJohan Hedberg u8 *data) 45130a708f8fSGustavo F. Padovan { 45140a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data; 45150a708f8fSGustavo F. Padovan u16 type; 45160a708f8fSGustavo F. Padovan 4517cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req)) 4518cb3b3152SJohan Hedberg return -EPROTO; 4519cb3b3152SJohan Hedberg 45200a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type); 45210a708f8fSGustavo F. Padovan 45220a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type); 45230a708f8fSGustavo F. Padovan 45240a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) { 45250a708f8fSGustavo F. Padovan u8 buf[8]; 45260a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask; 45270a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 4528ac73498cSAndrei Emeltchenko rsp->type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); 4529ac73498cSAndrei Emeltchenko rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); 45300a708f8fSGustavo F. Padovan if (!disable_ertm) 45310a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING 45320a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS; 4533848566b3SMarcel Holtmann if (conn->hs_enabled) 45346327eb98SAndrei Emeltchenko feat_mask |= L2CAP_FEAT_EXT_FLOW 45356327eb98SAndrei Emeltchenko | L2CAP_FEAT_EXT_WINDOW; 4536a5fd6f30SAndrei Emeltchenko 45370a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data); 45382d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), 45392d792818SGustavo Padovan buf); 45400a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) { 45410a708f8fSGustavo F. Padovan u8 buf[12]; 45420a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 454350a147cdSMat Martineau 4544848566b3SMarcel Holtmann if (conn->hs_enabled) 454550a147cdSMat Martineau l2cap_fixed_chan[0] |= L2CAP_FC_A2MP; 454650a147cdSMat Martineau else 454750a147cdSMat Martineau l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP; 454850a147cdSMat Martineau 4549ac73498cSAndrei Emeltchenko rsp->type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); 4550ac73498cSAndrei Emeltchenko rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); 4551c6337ea6SAndrei Emeltchenko memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); 45522d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), 45532d792818SGustavo Padovan buf); 45540a708f8fSGustavo F. Padovan } else { 45550a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp; 45560a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type); 4557ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP); 45582d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), 45592d792818SGustavo Padovan &rsp); 45600a708f8fSGustavo F. Padovan } 45610a708f8fSGustavo F. Padovan 45620a708f8fSGustavo F. Padovan return 0; 45630a708f8fSGustavo F. Padovan } 45640a708f8fSGustavo F. Padovan 45652d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, 4566cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4567cb3b3152SJohan Hedberg u8 *data) 45680a708f8fSGustavo F. Padovan { 45690a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; 45700a708f8fSGustavo F. Padovan u16 type, result; 45710a708f8fSGustavo F. Padovan 45723f6fa3d4SJaganath Kanakkassery if (cmd_len < sizeof(*rsp)) 4573cb3b3152SJohan Hedberg return -EPROTO; 4574cb3b3152SJohan Hedberg 45750a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type); 45760a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 45770a708f8fSGustavo F. Padovan 45780a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); 45790a708f8fSGustavo F. Padovan 4580e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */ 4581e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident || 4582e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 4583e90165beSAndrei Emeltchenko return 0; 4584e90165beSAndrei Emeltchenko 458517cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 45860a708f8fSGustavo F. Padovan 45870a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) { 45880a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 45890a708f8fSGustavo F. Padovan conn->info_ident = 0; 45900a708f8fSGustavo F. Padovan 45910a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 45920a708f8fSGustavo F. Padovan 45930a708f8fSGustavo F. Padovan return 0; 45940a708f8fSGustavo F. Padovan } 45950a708f8fSGustavo F. Padovan 4596978c93b9SAndrei Emeltchenko switch (type) { 4597978c93b9SAndrei Emeltchenko case L2CAP_IT_FEAT_MASK: 45980a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data); 45990a708f8fSGustavo F. Padovan 46000a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { 46010a708f8fSGustavo F. Padovan struct l2cap_info_req req; 4602ac73498cSAndrei Emeltchenko req.type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); 46030a708f8fSGustavo F. Padovan 46040a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 46050a708f8fSGustavo F. Padovan 46060a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 46070a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 46080a708f8fSGustavo F. Padovan } else { 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 } 4614978c93b9SAndrei Emeltchenko break; 4615978c93b9SAndrei Emeltchenko 4616978c93b9SAndrei Emeltchenko case L2CAP_IT_FIXED_CHAN: 4617978c93b9SAndrei Emeltchenko conn->fixed_chan_mask = rsp->data[0]; 46180a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 46190a708f8fSGustavo F. Padovan conn->info_ident = 0; 46200a708f8fSGustavo F. Padovan 46210a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 4622978c93b9SAndrei Emeltchenko break; 46230a708f8fSGustavo F. Padovan } 46240a708f8fSGustavo F. Padovan 46250a708f8fSGustavo F. Padovan return 0; 46260a708f8fSGustavo F. Padovan } 46270a708f8fSGustavo F. Padovan 46281700915fSMat Martineau static int l2cap_create_channel_req(struct l2cap_conn *conn, 46292d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, 46302d792818SGustavo Padovan u16 cmd_len, void *data) 4631f94ff6ffSMat Martineau { 4632f94ff6ffSMat Martineau struct l2cap_create_chan_req *req = data; 46336e1df6a6SAndrei Emeltchenko struct l2cap_create_chan_rsp rsp; 46341700915fSMat Martineau struct l2cap_chan *chan; 46356e1df6a6SAndrei Emeltchenko struct hci_dev *hdev; 4636f94ff6ffSMat Martineau u16 psm, scid; 4637f94ff6ffSMat Martineau 4638f94ff6ffSMat Martineau if (cmd_len != sizeof(*req)) 4639f94ff6ffSMat Martineau return -EPROTO; 4640f94ff6ffSMat Martineau 4641848566b3SMarcel Holtmann if (!conn->hs_enabled) 4642f94ff6ffSMat Martineau return -EINVAL; 4643f94ff6ffSMat Martineau 4644f94ff6ffSMat Martineau psm = le16_to_cpu(req->psm); 4645f94ff6ffSMat Martineau scid = le16_to_cpu(req->scid); 4646f94ff6ffSMat Martineau 4647ad0ac6caSAndrei Emeltchenko BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id); 4648f94ff6ffSMat Martineau 46496e1df6a6SAndrei Emeltchenko /* For controller id 0 make BR/EDR connection */ 46506ed971caSMarcel Holtmann if (req->amp_id == AMP_ID_BREDR) { 46516e1df6a6SAndrei Emeltchenko l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, 46526e1df6a6SAndrei Emeltchenko req->amp_id); 46536e1df6a6SAndrei Emeltchenko return 0; 46546e1df6a6SAndrei Emeltchenko } 46551700915fSMat Martineau 46561700915fSMat Martineau /* Validate AMP controller id */ 46571700915fSMat Martineau hdev = hci_dev_get(req->amp_id); 46586e1df6a6SAndrei Emeltchenko if (!hdev) 46596e1df6a6SAndrei Emeltchenko goto error; 46601700915fSMat Martineau 46616e1df6a6SAndrei Emeltchenko if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) { 46626e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 46636e1df6a6SAndrei Emeltchenko goto error; 46646e1df6a6SAndrei Emeltchenko } 46656e1df6a6SAndrei Emeltchenko 46666e1df6a6SAndrei Emeltchenko chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, 46676e1df6a6SAndrei Emeltchenko req->amp_id); 46686e1df6a6SAndrei Emeltchenko if (chan) { 46696e1df6a6SAndrei Emeltchenko struct amp_mgr *mgr = conn->hcon->amp_mgr; 46706e1df6a6SAndrei Emeltchenko struct hci_conn *hs_hcon; 46716e1df6a6SAndrei Emeltchenko 467298e0f7eaSMarcel Holtmann hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, 467398e0f7eaSMarcel Holtmann &conn->hcon->dst); 46746e1df6a6SAndrei Emeltchenko if (!hs_hcon) { 46756e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 4676662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, 4677662d652dSJohan Hedberg chan->dcid); 4678662d652dSJohan Hedberg return 0; 46796e1df6a6SAndrei Emeltchenko } 46806e1df6a6SAndrei Emeltchenko 46816e1df6a6SAndrei Emeltchenko BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon); 46826e1df6a6SAndrei Emeltchenko 46836e1df6a6SAndrei Emeltchenko mgr->bredr_chan = chan; 46846e1df6a6SAndrei Emeltchenko chan->hs_hcon = hs_hcon; 4685fd45bf4cSAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 46866e1df6a6SAndrei Emeltchenko conn->mtu = hdev->block_mtu; 46876e1df6a6SAndrei Emeltchenko } 46886e1df6a6SAndrei Emeltchenko 46896e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 46906e1df6a6SAndrei Emeltchenko 46916e1df6a6SAndrei Emeltchenko return 0; 46926e1df6a6SAndrei Emeltchenko 46936e1df6a6SAndrei Emeltchenko error: 4694f94ff6ffSMat Martineau rsp.dcid = 0; 4695f94ff6ffSMat Martineau rsp.scid = cpu_to_le16(scid); 46961700915fSMat Martineau rsp.result = __constant_cpu_to_le16(L2CAP_CR_BAD_AMP); 46978ce0c498SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 4698f94ff6ffSMat Martineau 4699f94ff6ffSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, 4700f94ff6ffSMat Martineau sizeof(rsp), &rsp); 4701f94ff6ffSMat Martineau 4702dc280801SJohan Hedberg return 0; 4703f94ff6ffSMat Martineau } 4704f94ff6ffSMat Martineau 47058eb200bdSMat Martineau static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id) 47068eb200bdSMat Martineau { 47078eb200bdSMat Martineau struct l2cap_move_chan_req req; 47088eb200bdSMat Martineau u8 ident; 47098eb200bdSMat Martineau 47108eb200bdSMat Martineau BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id); 47118eb200bdSMat Martineau 47128eb200bdSMat Martineau ident = l2cap_get_ident(chan->conn); 47138eb200bdSMat Martineau chan->ident = ident; 47148eb200bdSMat Martineau 47158eb200bdSMat Martineau req.icid = cpu_to_le16(chan->scid); 47168eb200bdSMat Martineau req.dest_amp_id = dest_amp_id; 47178eb200bdSMat Martineau 47188eb200bdSMat Martineau l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req), 47198eb200bdSMat Martineau &req); 47208eb200bdSMat Martineau 47218eb200bdSMat Martineau __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); 47228eb200bdSMat Martineau } 47238eb200bdSMat Martineau 47241500109bSMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result) 47258d5a04a1SMat Martineau { 47268d5a04a1SMat Martineau struct l2cap_move_chan_rsp rsp; 47278d5a04a1SMat Martineau 47281500109bSMat Martineau BT_DBG("chan %p, result 0x%4.4x", chan, result); 47298d5a04a1SMat Martineau 47301500109bSMat Martineau rsp.icid = cpu_to_le16(chan->dcid); 47318d5a04a1SMat Martineau rsp.result = cpu_to_le16(result); 47328d5a04a1SMat Martineau 47331500109bSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP, 47341500109bSMat Martineau sizeof(rsp), &rsp); 47358d5a04a1SMat Martineau } 47368d5a04a1SMat Martineau 47375b155ef9SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result) 47388d5a04a1SMat Martineau { 47398d5a04a1SMat Martineau struct l2cap_move_chan_cfm cfm; 47408d5a04a1SMat Martineau 47415b155ef9SMat Martineau BT_DBG("chan %p, result 0x%4.4x", chan, result); 47428d5a04a1SMat Martineau 47435b155ef9SMat Martineau chan->ident = l2cap_get_ident(chan->conn); 47448d5a04a1SMat Martineau 47455b155ef9SMat Martineau cfm.icid = cpu_to_le16(chan->scid); 47468d5a04a1SMat Martineau cfm.result = cpu_to_le16(result); 47478d5a04a1SMat Martineau 47485b155ef9SMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM, 47495b155ef9SMat Martineau sizeof(cfm), &cfm); 47505b155ef9SMat Martineau 47515b155ef9SMat Martineau __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); 47525b155ef9SMat Martineau } 47535b155ef9SMat Martineau 47545b155ef9SMat Martineau static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid) 47555b155ef9SMat Martineau { 47565b155ef9SMat Martineau struct l2cap_move_chan_cfm cfm; 47575b155ef9SMat Martineau 47585b155ef9SMat Martineau BT_DBG("conn %p, icid 0x%4.4x", conn, icid); 47595b155ef9SMat Martineau 47605b155ef9SMat Martineau cfm.icid = cpu_to_le16(icid); 47615b155ef9SMat Martineau cfm.result = __constant_cpu_to_le16(L2CAP_MC_UNCONFIRMED); 47625b155ef9SMat Martineau 47635b155ef9SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM, 47645b155ef9SMat Martineau sizeof(cfm), &cfm); 47658d5a04a1SMat Martineau } 47668d5a04a1SMat Martineau 47678d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, 47688d5a04a1SMat Martineau u16 icid) 47698d5a04a1SMat Martineau { 47708d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp rsp; 47718d5a04a1SMat Martineau 4772ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 47738d5a04a1SMat Martineau 47748d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 47758d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp); 47768d5a04a1SMat Martineau } 47778d5a04a1SMat Martineau 47785f3847a4SMat Martineau static void __release_logical_link(struct l2cap_chan *chan) 47795f3847a4SMat Martineau { 47805f3847a4SMat Martineau chan->hs_hchan = NULL; 47815f3847a4SMat Martineau chan->hs_hcon = NULL; 47825f3847a4SMat Martineau 47835f3847a4SMat Martineau /* Placeholder - release the logical link */ 47845f3847a4SMat Martineau } 47855f3847a4SMat Martineau 47861500109bSMat Martineau static void l2cap_logical_fail(struct l2cap_chan *chan) 47871500109bSMat Martineau { 47881500109bSMat Martineau /* Logical link setup failed */ 47891500109bSMat Martineau if (chan->state != BT_CONNECTED) { 47901500109bSMat Martineau /* Create channel failure, disconnect */ 47915e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 47921500109bSMat Martineau return; 47931500109bSMat Martineau } 47941500109bSMat Martineau 47951500109bSMat Martineau switch (chan->move_role) { 47961500109bSMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 47971500109bSMat Martineau l2cap_move_done(chan); 47981500109bSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP); 47991500109bSMat Martineau break; 48001500109bSMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 48011500109bSMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP || 48021500109bSMat Martineau chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) { 48031500109bSMat Martineau /* Remote has only sent pending or 48041500109bSMat Martineau * success responses, clean up 48051500109bSMat Martineau */ 48061500109bSMat Martineau l2cap_move_done(chan); 48071500109bSMat Martineau } 48081500109bSMat Martineau 48091500109bSMat Martineau /* Other amp move states imply that the move 48101500109bSMat Martineau * has already aborted 48111500109bSMat Martineau */ 48121500109bSMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 48131500109bSMat Martineau break; 48141500109bSMat Martineau } 48151500109bSMat Martineau } 48161500109bSMat Martineau 48171500109bSMat Martineau static void l2cap_logical_finish_create(struct l2cap_chan *chan, 48181500109bSMat Martineau struct hci_chan *hchan) 48191500109bSMat Martineau { 48201500109bSMat Martineau struct l2cap_conf_rsp rsp; 48211500109bSMat Martineau 4822336178a3SAndrei Emeltchenko chan->hs_hchan = hchan; 48231500109bSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 48241500109bSMat Martineau 482535ba9561SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0); 48261500109bSMat Martineau 48271500109bSMat Martineau if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 4828fe79c6feSAndrei Emeltchenko int err; 48291500109bSMat Martineau 48301500109bSMat Martineau set_default_fcs(chan); 48311500109bSMat Martineau 48321500109bSMat Martineau err = l2cap_ertm_init(chan); 48331500109bSMat Martineau if (err < 0) 48345e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 48351500109bSMat Martineau else 48361500109bSMat Martineau l2cap_chan_ready(chan); 48371500109bSMat Martineau } 48381500109bSMat Martineau } 48391500109bSMat Martineau 48401500109bSMat Martineau static void l2cap_logical_finish_move(struct l2cap_chan *chan, 48411500109bSMat Martineau struct hci_chan *hchan) 48421500109bSMat Martineau { 48431500109bSMat Martineau chan->hs_hcon = hchan->conn; 48441500109bSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 48451500109bSMat Martineau 48461500109bSMat Martineau BT_DBG("move_state %d", chan->move_state); 48471500109bSMat Martineau 48481500109bSMat Martineau switch (chan->move_state) { 48491500109bSMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_COMP: 48501500109bSMat Martineau /* Move confirm will be sent after a success 48511500109bSMat Martineau * response is received 48521500109bSMat Martineau */ 48531500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 48541500109bSMat Martineau break; 48551500109bSMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_CFM: 48561500109bSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 48571500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 48581500109bSMat Martineau } else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { 48591500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; 48601500109bSMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 48611500109bSMat Martineau } else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { 48621500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 48631500109bSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); 48641500109bSMat Martineau } 48651500109bSMat Martineau break; 48661500109bSMat Martineau default: 48671500109bSMat Martineau /* Move was not in expected state, free the channel */ 48681500109bSMat Martineau __release_logical_link(chan); 48691500109bSMat Martineau 48701500109bSMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 48711500109bSMat Martineau } 48721500109bSMat Martineau } 48731500109bSMat Martineau 48741500109bSMat Martineau /* Call with chan locked */ 487527695fb4SAndrei Emeltchenko void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan, 48765b155ef9SMat Martineau u8 status) 48775b155ef9SMat Martineau { 48781500109bSMat Martineau BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status); 48791500109bSMat Martineau 48801500109bSMat Martineau if (status) { 48811500109bSMat Martineau l2cap_logical_fail(chan); 48821500109bSMat Martineau __release_logical_link(chan); 48835b155ef9SMat Martineau return; 48845b155ef9SMat Martineau } 48855b155ef9SMat Martineau 48861500109bSMat Martineau if (chan->state != BT_CONNECTED) { 48871500109bSMat Martineau /* Ignore logical link if channel is on BR/EDR */ 48886ed971caSMarcel Holtmann if (chan->local_amp_id != AMP_ID_BREDR) 48891500109bSMat Martineau l2cap_logical_finish_create(chan, hchan); 48901500109bSMat Martineau } else { 48911500109bSMat Martineau l2cap_logical_finish_move(chan, hchan); 48921500109bSMat Martineau } 48931500109bSMat Martineau } 48941500109bSMat Martineau 48953f7a56c4SMat Martineau void l2cap_move_start(struct l2cap_chan *chan) 48963f7a56c4SMat Martineau { 48973f7a56c4SMat Martineau BT_DBG("chan %p", chan); 48983f7a56c4SMat Martineau 48996ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR) { 49003f7a56c4SMat Martineau if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED) 49013f7a56c4SMat Martineau return; 49023f7a56c4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; 49033f7a56c4SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_PREPARE; 49043f7a56c4SMat Martineau /* Placeholder - start physical link setup */ 49053f7a56c4SMat Martineau } else { 49063f7a56c4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; 49073f7a56c4SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 49083f7a56c4SMat Martineau chan->move_id = 0; 49093f7a56c4SMat Martineau l2cap_move_setup(chan); 49103f7a56c4SMat Martineau l2cap_send_move_chan_req(chan, 0); 49113f7a56c4SMat Martineau } 49123f7a56c4SMat Martineau } 49133f7a56c4SMat Martineau 49148eb200bdSMat Martineau static void l2cap_do_create(struct l2cap_chan *chan, int result, 49158eb200bdSMat Martineau u8 local_amp_id, u8 remote_amp_id) 49168eb200bdSMat Martineau { 491762748ca1SAndrei Emeltchenko BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state), 491862748ca1SAndrei Emeltchenko local_amp_id, remote_amp_id); 491962748ca1SAndrei Emeltchenko 492012d6cc60SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 492112d6cc60SAndrei Emeltchenko 492262748ca1SAndrei Emeltchenko /* Outgoing channel on AMP */ 492362748ca1SAndrei Emeltchenko if (chan->state == BT_CONNECT) { 492462748ca1SAndrei Emeltchenko if (result == L2CAP_CR_SUCCESS) { 492562748ca1SAndrei Emeltchenko chan->local_amp_id = local_amp_id; 492662748ca1SAndrei Emeltchenko l2cap_send_create_chan_req(chan, remote_amp_id); 492762748ca1SAndrei Emeltchenko } else { 492862748ca1SAndrei Emeltchenko /* Revert to BR/EDR connect */ 492962748ca1SAndrei Emeltchenko l2cap_send_conn_req(chan); 493062748ca1SAndrei Emeltchenko } 493162748ca1SAndrei Emeltchenko 493262748ca1SAndrei Emeltchenko return; 493362748ca1SAndrei Emeltchenko } 493462748ca1SAndrei Emeltchenko 493562748ca1SAndrei Emeltchenko /* Incoming channel on AMP */ 493662748ca1SAndrei Emeltchenko if (__l2cap_no_conn_pending(chan)) { 49378eb200bdSMat Martineau struct l2cap_conn_rsp rsp; 49388eb200bdSMat Martineau char buf[128]; 49398eb200bdSMat Martineau rsp.scid = cpu_to_le16(chan->dcid); 49408eb200bdSMat Martineau rsp.dcid = cpu_to_le16(chan->scid); 49418eb200bdSMat Martineau 49428eb200bdSMat Martineau if (result == L2CAP_CR_SUCCESS) { 49438eb200bdSMat Martineau /* Send successful response */ 494462cd50e2SAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 494562cd50e2SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 49468eb200bdSMat Martineau } else { 49478eb200bdSMat Martineau /* Send negative response */ 494862cd50e2SAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM); 494962cd50e2SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 49508eb200bdSMat Martineau } 49518eb200bdSMat Martineau 49528eb200bdSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP, 49538eb200bdSMat Martineau sizeof(rsp), &rsp); 49548eb200bdSMat Martineau 49558eb200bdSMat Martineau if (result == L2CAP_CR_SUCCESS) { 4956f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 49578eb200bdSMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 49588eb200bdSMat Martineau l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn), 49598eb200bdSMat Martineau L2CAP_CONF_REQ, 49608eb200bdSMat Martineau l2cap_build_conf_req(chan, buf), buf); 49618eb200bdSMat Martineau chan->num_conf_req++; 49628eb200bdSMat Martineau } 49638eb200bdSMat Martineau } 49648eb200bdSMat Martineau } 49658eb200bdSMat Martineau 49668eb200bdSMat Martineau static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id, 49678eb200bdSMat Martineau u8 remote_amp_id) 49688eb200bdSMat Martineau { 49698eb200bdSMat Martineau l2cap_move_setup(chan); 49708eb200bdSMat Martineau chan->move_id = local_amp_id; 49718eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP; 49728eb200bdSMat Martineau 49738eb200bdSMat Martineau l2cap_send_move_chan_req(chan, remote_amp_id); 49748eb200bdSMat Martineau } 49758eb200bdSMat Martineau 49768eb200bdSMat Martineau static void l2cap_do_move_respond(struct l2cap_chan *chan, int result) 49778eb200bdSMat Martineau { 49788eb200bdSMat Martineau struct hci_chan *hchan = NULL; 49798eb200bdSMat Martineau 49808eb200bdSMat Martineau /* Placeholder - get hci_chan for logical link */ 49818eb200bdSMat Martineau 49828eb200bdSMat Martineau if (hchan) { 49838eb200bdSMat Martineau if (hchan->state == BT_CONNECTED) { 49848eb200bdSMat Martineau /* Logical link is ready to go */ 49858eb200bdSMat Martineau chan->hs_hcon = hchan->conn; 49868eb200bdSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 49878eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 49888eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); 49898eb200bdSMat Martineau 49908eb200bdSMat Martineau l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); 49918eb200bdSMat Martineau } else { 49928eb200bdSMat Martineau /* Wait for logical link to be ready */ 49938eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 49948eb200bdSMat Martineau } 49958eb200bdSMat Martineau } else { 49968eb200bdSMat Martineau /* Logical link not available */ 49978eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED); 49988eb200bdSMat Martineau } 49998eb200bdSMat Martineau } 50008eb200bdSMat Martineau 50018eb200bdSMat Martineau static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result) 50028eb200bdSMat Martineau { 50038eb200bdSMat Martineau if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { 50048eb200bdSMat Martineau u8 rsp_result; 50058eb200bdSMat Martineau if (result == -EINVAL) 50068eb200bdSMat Martineau rsp_result = L2CAP_MR_BAD_ID; 50078eb200bdSMat Martineau else 50088eb200bdSMat Martineau rsp_result = L2CAP_MR_NOT_ALLOWED; 50098eb200bdSMat Martineau 50108eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, rsp_result); 50118eb200bdSMat Martineau } 50128eb200bdSMat Martineau 50138eb200bdSMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 50148eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 50158eb200bdSMat Martineau 50168eb200bdSMat Martineau /* Restart data transmission */ 50178eb200bdSMat Martineau l2cap_ertm_send(chan); 50188eb200bdSMat Martineau } 50198eb200bdSMat Martineau 5020a514b17fSAndrei Emeltchenko /* Invoke with locked chan */ 5021a514b17fSAndrei Emeltchenko void __l2cap_physical_cfm(struct l2cap_chan *chan, int result) 50228eb200bdSMat Martineau { 5023770bfefaSAndrei Emeltchenko u8 local_amp_id = chan->local_amp_id; 5024fffadc08SAndrei Emeltchenko u8 remote_amp_id = chan->remote_amp_id; 5025770bfefaSAndrei Emeltchenko 50268eb200bdSMat Martineau BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d", 50278eb200bdSMat Martineau chan, result, local_amp_id, remote_amp_id); 50288eb200bdSMat Martineau 50298eb200bdSMat Martineau if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) { 50308eb200bdSMat Martineau l2cap_chan_unlock(chan); 50318eb200bdSMat Martineau return; 50328eb200bdSMat Martineau } 50338eb200bdSMat Martineau 50348eb200bdSMat Martineau if (chan->state != BT_CONNECTED) { 50358eb200bdSMat Martineau l2cap_do_create(chan, result, local_amp_id, remote_amp_id); 50368eb200bdSMat Martineau } else if (result != L2CAP_MR_SUCCESS) { 50378eb200bdSMat Martineau l2cap_do_move_cancel(chan, result); 50388eb200bdSMat Martineau } else { 50398eb200bdSMat Martineau switch (chan->move_role) { 50408eb200bdSMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 50418eb200bdSMat Martineau l2cap_do_move_initiate(chan, local_amp_id, 50428eb200bdSMat Martineau remote_amp_id); 50438eb200bdSMat Martineau break; 50448eb200bdSMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 50458eb200bdSMat Martineau l2cap_do_move_respond(chan, result); 50468eb200bdSMat Martineau break; 50478eb200bdSMat Martineau default: 50488eb200bdSMat Martineau l2cap_do_move_cancel(chan, result); 50498eb200bdSMat Martineau break; 50508eb200bdSMat Martineau } 50518eb200bdSMat Martineau } 50528eb200bdSMat Martineau } 50538eb200bdSMat Martineau 50548d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn, 5055ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5056ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 50578d5a04a1SMat Martineau { 50588d5a04a1SMat Martineau struct l2cap_move_chan_req *req = data; 50591500109bSMat Martineau struct l2cap_move_chan_rsp rsp; 506002b0fbb9SMat Martineau struct l2cap_chan *chan; 50618d5a04a1SMat Martineau u16 icid = 0; 50628d5a04a1SMat Martineau u16 result = L2CAP_MR_NOT_ALLOWED; 50638d5a04a1SMat Martineau 50648d5a04a1SMat Martineau if (cmd_len != sizeof(*req)) 50658d5a04a1SMat Martineau return -EPROTO; 50668d5a04a1SMat Martineau 50678d5a04a1SMat Martineau icid = le16_to_cpu(req->icid); 50688d5a04a1SMat Martineau 5069ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id); 50708d5a04a1SMat Martineau 5071848566b3SMarcel Holtmann if (!conn->hs_enabled) 50728d5a04a1SMat Martineau return -EINVAL; 50738d5a04a1SMat Martineau 507402b0fbb9SMat Martineau chan = l2cap_get_chan_by_dcid(conn, icid); 507502b0fbb9SMat Martineau if (!chan) { 50761500109bSMat Martineau rsp.icid = cpu_to_le16(icid); 50771500109bSMat Martineau rsp.result = __constant_cpu_to_le16(L2CAP_MR_NOT_ALLOWED); 50781500109bSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP, 50791500109bSMat Martineau sizeof(rsp), &rsp); 508002b0fbb9SMat Martineau return 0; 508102b0fbb9SMat Martineau } 508202b0fbb9SMat Martineau 50831500109bSMat Martineau chan->ident = cmd->ident; 50841500109bSMat Martineau 508502b0fbb9SMat Martineau if (chan->scid < L2CAP_CID_DYN_START || 508602b0fbb9SMat Martineau chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY || 508702b0fbb9SMat Martineau (chan->mode != L2CAP_MODE_ERTM && 508802b0fbb9SMat Martineau chan->mode != L2CAP_MODE_STREAMING)) { 508902b0fbb9SMat Martineau result = L2CAP_MR_NOT_ALLOWED; 509002b0fbb9SMat Martineau goto send_move_response; 509102b0fbb9SMat Martineau } 509202b0fbb9SMat Martineau 509302b0fbb9SMat Martineau if (chan->local_amp_id == req->dest_amp_id) { 509402b0fbb9SMat Martineau result = L2CAP_MR_SAME_ID; 509502b0fbb9SMat Martineau goto send_move_response; 509602b0fbb9SMat Martineau } 509702b0fbb9SMat Martineau 50986ed971caSMarcel Holtmann if (req->dest_amp_id != AMP_ID_BREDR) { 509902b0fbb9SMat Martineau struct hci_dev *hdev; 510002b0fbb9SMat Martineau hdev = hci_dev_get(req->dest_amp_id); 510102b0fbb9SMat Martineau if (!hdev || hdev->dev_type != HCI_AMP || 510202b0fbb9SMat Martineau !test_bit(HCI_UP, &hdev->flags)) { 510302b0fbb9SMat Martineau if (hdev) 510402b0fbb9SMat Martineau hci_dev_put(hdev); 510502b0fbb9SMat Martineau 510602b0fbb9SMat Martineau result = L2CAP_MR_BAD_ID; 510702b0fbb9SMat Martineau goto send_move_response; 510802b0fbb9SMat Martineau } 510902b0fbb9SMat Martineau hci_dev_put(hdev); 511002b0fbb9SMat Martineau } 511102b0fbb9SMat Martineau 511202b0fbb9SMat Martineau /* Detect a move collision. Only send a collision response 511302b0fbb9SMat Martineau * if this side has "lost", otherwise proceed with the move. 511402b0fbb9SMat Martineau * The winner has the larger bd_addr. 511502b0fbb9SMat Martineau */ 511602b0fbb9SMat Martineau if ((__chan_is_moving(chan) || 511702b0fbb9SMat Martineau chan->move_role != L2CAP_MOVE_ROLE_NONE) && 51186f59b904SMarcel Holtmann bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) { 511902b0fbb9SMat Martineau result = L2CAP_MR_COLLISION; 512002b0fbb9SMat Martineau goto send_move_response; 512102b0fbb9SMat Martineau } 512202b0fbb9SMat Martineau 512302b0fbb9SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; 512402b0fbb9SMat Martineau l2cap_move_setup(chan); 512502b0fbb9SMat Martineau chan->move_id = req->dest_amp_id; 512602b0fbb9SMat Martineau icid = chan->dcid; 512702b0fbb9SMat Martineau 51286ed971caSMarcel Holtmann if (req->dest_amp_id == AMP_ID_BREDR) { 512902b0fbb9SMat Martineau /* Moving to BR/EDR */ 513002b0fbb9SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 513102b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 513202b0fbb9SMat Martineau result = L2CAP_MR_PEND; 513302b0fbb9SMat Martineau } else { 513402b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 513502b0fbb9SMat Martineau result = L2CAP_MR_SUCCESS; 513602b0fbb9SMat Martineau } 513702b0fbb9SMat Martineau } else { 513802b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_PREPARE; 513902b0fbb9SMat Martineau /* Placeholder - uncomment when amp functions are available */ 514002b0fbb9SMat Martineau /*amp_accept_physical(chan, req->dest_amp_id);*/ 514102b0fbb9SMat Martineau result = L2CAP_MR_PEND; 514202b0fbb9SMat Martineau } 514302b0fbb9SMat Martineau 514402b0fbb9SMat Martineau send_move_response: 51451500109bSMat Martineau l2cap_send_move_chan_rsp(chan, result); 51468d5a04a1SMat Martineau 514702b0fbb9SMat Martineau l2cap_chan_unlock(chan); 514802b0fbb9SMat Martineau 51498d5a04a1SMat Martineau return 0; 51508d5a04a1SMat Martineau } 51518d5a04a1SMat Martineau 51525b155ef9SMat Martineau static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result) 51535b155ef9SMat Martineau { 51545b155ef9SMat Martineau struct l2cap_chan *chan; 51555b155ef9SMat Martineau struct hci_chan *hchan = NULL; 51565b155ef9SMat Martineau 51575b155ef9SMat Martineau chan = l2cap_get_chan_by_scid(conn, icid); 51585b155ef9SMat Martineau if (!chan) { 51595b155ef9SMat Martineau l2cap_send_move_chan_cfm_icid(conn, icid); 51605b155ef9SMat Martineau return; 51615b155ef9SMat Martineau } 51625b155ef9SMat Martineau 51635b155ef9SMat Martineau __clear_chan_timer(chan); 51645b155ef9SMat Martineau if (result == L2CAP_MR_PEND) 51655b155ef9SMat Martineau __set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT); 51665b155ef9SMat Martineau 51675b155ef9SMat Martineau switch (chan->move_state) { 51685b155ef9SMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_COMP: 51695b155ef9SMat Martineau /* Move confirm will be sent when logical link 51705b155ef9SMat Martineau * is complete. 51715b155ef9SMat Martineau */ 51725b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 51735b155ef9SMat Martineau break; 51745b155ef9SMat Martineau case L2CAP_MOVE_WAIT_RSP_SUCCESS: 51755b155ef9SMat Martineau if (result == L2CAP_MR_PEND) { 51765b155ef9SMat Martineau break; 51775b155ef9SMat Martineau } else if (test_bit(CONN_LOCAL_BUSY, 51785b155ef9SMat Martineau &chan->conn_state)) { 51795b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 51805b155ef9SMat Martineau } else { 51815b155ef9SMat Martineau /* Logical link is up or moving to BR/EDR, 51825b155ef9SMat Martineau * proceed with move 51835b155ef9SMat Martineau */ 51845b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; 51855b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 51865b155ef9SMat Martineau } 51875b155ef9SMat Martineau break; 51885b155ef9SMat Martineau case L2CAP_MOVE_WAIT_RSP: 51895b155ef9SMat Martineau /* Moving to AMP */ 51905b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS) { 51915b155ef9SMat Martineau /* Remote is ready, send confirm immediately 51925b155ef9SMat Martineau * after logical link is ready 51935b155ef9SMat Martineau */ 51945b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 51955b155ef9SMat Martineau } else { 51965b155ef9SMat Martineau /* Both logical link and move success 51975b155ef9SMat Martineau * are required to confirm 51985b155ef9SMat Martineau */ 51995b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP; 52005b155ef9SMat Martineau } 52015b155ef9SMat Martineau 52025b155ef9SMat Martineau /* Placeholder - get hci_chan for logical link */ 52035b155ef9SMat Martineau if (!hchan) { 52045b155ef9SMat Martineau /* Logical link not available */ 52055b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 52065b155ef9SMat Martineau break; 52075b155ef9SMat Martineau } 52085b155ef9SMat Martineau 52095b155ef9SMat Martineau /* If the logical link is not yet connected, do not 52105b155ef9SMat Martineau * send confirmation. 52115b155ef9SMat Martineau */ 52125b155ef9SMat Martineau if (hchan->state != BT_CONNECTED) 52135b155ef9SMat Martineau break; 52145b155ef9SMat Martineau 52155b155ef9SMat Martineau /* Logical link is already ready to go */ 52165b155ef9SMat Martineau 52175b155ef9SMat Martineau chan->hs_hcon = hchan->conn; 52185b155ef9SMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 52195b155ef9SMat Martineau 52205b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS) { 52215b155ef9SMat Martineau /* Can confirm now */ 52225b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 52235b155ef9SMat Martineau } else { 52245b155ef9SMat Martineau /* Now only need move success 52255b155ef9SMat Martineau * to confirm 52265b155ef9SMat Martineau */ 52275b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 52285b155ef9SMat Martineau } 52295b155ef9SMat Martineau 52305b155ef9SMat Martineau l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); 52315b155ef9SMat Martineau break; 52325b155ef9SMat Martineau default: 52335b155ef9SMat Martineau /* Any other amp move state means the move failed. */ 52345b155ef9SMat Martineau chan->move_id = chan->local_amp_id; 52355b155ef9SMat Martineau l2cap_move_done(chan); 52365b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 52375b155ef9SMat Martineau } 52385b155ef9SMat Martineau 52395b155ef9SMat Martineau l2cap_chan_unlock(chan); 52405b155ef9SMat Martineau } 52415b155ef9SMat Martineau 52425b155ef9SMat Martineau static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid, 52435b155ef9SMat Martineau u16 result) 52445b155ef9SMat Martineau { 52455b155ef9SMat Martineau struct l2cap_chan *chan; 52465b155ef9SMat Martineau 52475b155ef9SMat Martineau chan = l2cap_get_chan_by_ident(conn, ident); 52485b155ef9SMat Martineau if (!chan) { 52495b155ef9SMat Martineau /* Could not locate channel, icid is best guess */ 52505b155ef9SMat Martineau l2cap_send_move_chan_cfm_icid(conn, icid); 52515b155ef9SMat Martineau return; 52525b155ef9SMat Martineau } 52535b155ef9SMat Martineau 52545b155ef9SMat Martineau __clear_chan_timer(chan); 52555b155ef9SMat Martineau 52565b155ef9SMat Martineau if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { 52575b155ef9SMat Martineau if (result == L2CAP_MR_COLLISION) { 52585b155ef9SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; 52595b155ef9SMat Martineau } else { 52605b155ef9SMat Martineau /* Cleanup - cancel move */ 52615b155ef9SMat Martineau chan->move_id = chan->local_amp_id; 52625b155ef9SMat Martineau l2cap_move_done(chan); 52635b155ef9SMat Martineau } 52645b155ef9SMat Martineau } 52655b155ef9SMat Martineau 52665b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 52675b155ef9SMat Martineau 52685b155ef9SMat Martineau l2cap_chan_unlock(chan); 52695b155ef9SMat Martineau } 52705b155ef9SMat Martineau 52715b155ef9SMat Martineau static int l2cap_move_channel_rsp(struct l2cap_conn *conn, 5272ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5273ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 52748d5a04a1SMat Martineau { 52758d5a04a1SMat Martineau struct l2cap_move_chan_rsp *rsp = data; 52768d5a04a1SMat Martineau u16 icid, result; 52778d5a04a1SMat Martineau 52788d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 52798d5a04a1SMat Martineau return -EPROTO; 52808d5a04a1SMat Martineau 52818d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 52828d5a04a1SMat Martineau result = le16_to_cpu(rsp->result); 52838d5a04a1SMat Martineau 5284ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 52858d5a04a1SMat Martineau 52865b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND) 52875b155ef9SMat Martineau l2cap_move_continue(conn, icid, result); 52885b155ef9SMat Martineau else 52895b155ef9SMat Martineau l2cap_move_fail(conn, cmd->ident, icid, result); 52908d5a04a1SMat Martineau 52918d5a04a1SMat Martineau return 0; 52928d5a04a1SMat Martineau } 52938d5a04a1SMat Martineau 52945f3847a4SMat Martineau static int l2cap_move_channel_confirm(struct l2cap_conn *conn, 5295ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5296ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 52978d5a04a1SMat Martineau { 52988d5a04a1SMat Martineau struct l2cap_move_chan_cfm *cfm = data; 52995f3847a4SMat Martineau struct l2cap_chan *chan; 53008d5a04a1SMat Martineau u16 icid, result; 53018d5a04a1SMat Martineau 53028d5a04a1SMat Martineau if (cmd_len != sizeof(*cfm)) 53038d5a04a1SMat Martineau return -EPROTO; 53048d5a04a1SMat Martineau 53058d5a04a1SMat Martineau icid = le16_to_cpu(cfm->icid); 53068d5a04a1SMat Martineau result = le16_to_cpu(cfm->result); 53078d5a04a1SMat Martineau 5308ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 53098d5a04a1SMat Martineau 53105f3847a4SMat Martineau chan = l2cap_get_chan_by_dcid(conn, icid); 53115f3847a4SMat Martineau if (!chan) { 53125f3847a4SMat Martineau /* Spec requires a response even if the icid was not found */ 53138d5a04a1SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 53145f3847a4SMat Martineau return 0; 53155f3847a4SMat Martineau } 53165f3847a4SMat Martineau 53175f3847a4SMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) { 53185f3847a4SMat Martineau if (result == L2CAP_MC_CONFIRMED) { 53195f3847a4SMat Martineau chan->local_amp_id = chan->move_id; 53206ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR) 53215f3847a4SMat Martineau __release_logical_link(chan); 53225f3847a4SMat Martineau } else { 53235f3847a4SMat Martineau chan->move_id = chan->local_amp_id; 53245f3847a4SMat Martineau } 53255f3847a4SMat Martineau 53265f3847a4SMat Martineau l2cap_move_done(chan); 53275f3847a4SMat Martineau } 53285f3847a4SMat Martineau 53295f3847a4SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 53305f3847a4SMat Martineau 53315f3847a4SMat Martineau l2cap_chan_unlock(chan); 53328d5a04a1SMat Martineau 53338d5a04a1SMat Martineau return 0; 53348d5a04a1SMat Martineau } 53358d5a04a1SMat Martineau 53368d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, 5337ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5338ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 53398d5a04a1SMat Martineau { 53408d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp *rsp = data; 53413fd71a0aSMat Martineau struct l2cap_chan *chan; 53428d5a04a1SMat Martineau u16 icid; 53438d5a04a1SMat Martineau 53448d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 53458d5a04a1SMat Martineau return -EPROTO; 53468d5a04a1SMat Martineau 53478d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 53488d5a04a1SMat Martineau 5349ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 53508d5a04a1SMat Martineau 53513fd71a0aSMat Martineau chan = l2cap_get_chan_by_scid(conn, icid); 53523fd71a0aSMat Martineau if (!chan) 53533fd71a0aSMat Martineau return 0; 53543fd71a0aSMat Martineau 53553fd71a0aSMat Martineau __clear_chan_timer(chan); 53563fd71a0aSMat Martineau 53573fd71a0aSMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) { 53583fd71a0aSMat Martineau chan->local_amp_id = chan->move_id; 53593fd71a0aSMat Martineau 53606ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan) 53613fd71a0aSMat Martineau __release_logical_link(chan); 53623fd71a0aSMat Martineau 53633fd71a0aSMat Martineau l2cap_move_done(chan); 53643fd71a0aSMat Martineau } 53653fd71a0aSMat Martineau 53663fd71a0aSMat Martineau l2cap_chan_unlock(chan); 53673fd71a0aSMat Martineau 53688d5a04a1SMat Martineau return 0; 53698d5a04a1SMat Martineau } 53708d5a04a1SMat Martineau 5371e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency, 5372de73115aSClaudio Takahasi u16 to_multiplier) 5373de73115aSClaudio Takahasi { 5374de73115aSClaudio Takahasi u16 max_latency; 5375de73115aSClaudio Takahasi 5376de73115aSClaudio Takahasi if (min > max || min < 6 || max > 3200) 5377de73115aSClaudio Takahasi return -EINVAL; 5378de73115aSClaudio Takahasi 5379de73115aSClaudio Takahasi if (to_multiplier < 10 || to_multiplier > 3200) 5380de73115aSClaudio Takahasi return -EINVAL; 5381de73115aSClaudio Takahasi 5382de73115aSClaudio Takahasi if (max >= to_multiplier * 8) 5383de73115aSClaudio Takahasi return -EINVAL; 5384de73115aSClaudio Takahasi 5385de73115aSClaudio Takahasi max_latency = (to_multiplier * 8 / max) - 1; 5386de73115aSClaudio Takahasi if (latency > 499 || latency > max_latency) 5387de73115aSClaudio Takahasi return -EINVAL; 5388de73115aSClaudio Takahasi 5389de73115aSClaudio Takahasi return 0; 5390de73115aSClaudio Takahasi } 5391de73115aSClaudio Takahasi 5392de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, 53932d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, 5394203e639eSJohan Hedberg u16 cmd_len, u8 *data) 5395de73115aSClaudio Takahasi { 5396de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon; 5397de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req; 5398de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp; 5399203e639eSJohan Hedberg u16 min, max, latency, to_multiplier; 54002ce603ebSClaudio Takahasi int err; 5401de73115aSClaudio Takahasi 5402de73115aSClaudio Takahasi if (!(hcon->link_mode & HCI_LM_MASTER)) 5403de73115aSClaudio Takahasi return -EINVAL; 5404de73115aSClaudio Takahasi 5405de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) 5406de73115aSClaudio Takahasi return -EPROTO; 5407de73115aSClaudio Takahasi 5408de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data; 5409de73115aSClaudio Takahasi min = __le16_to_cpu(req->min); 5410de73115aSClaudio Takahasi max = __le16_to_cpu(req->max); 5411de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency); 5412de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier); 5413de73115aSClaudio Takahasi 5414de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", 5415de73115aSClaudio Takahasi min, max, latency, to_multiplier); 5416de73115aSClaudio Takahasi 5417de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp)); 54182ce603ebSClaudio Takahasi 54192ce603ebSClaudio Takahasi err = l2cap_check_conn_param(min, max, latency, to_multiplier); 54202ce603ebSClaudio Takahasi if (err) 5421ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); 5422de73115aSClaudio Takahasi else 5423ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); 5424de73115aSClaudio Takahasi 5425de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, 5426de73115aSClaudio Takahasi sizeof(rsp), &rsp); 5427de73115aSClaudio Takahasi 54282ce603ebSClaudio Takahasi if (!err) 54292ce603ebSClaudio Takahasi hci_le_conn_update(hcon, min, max, latency, to_multiplier); 54302ce603ebSClaudio Takahasi 5431de73115aSClaudio Takahasi return 0; 5432de73115aSClaudio Takahasi } 5433de73115aSClaudio Takahasi 5434f1496deeSJohan Hedberg static int l2cap_le_connect_rsp(struct l2cap_conn *conn, 5435f1496deeSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5436f1496deeSJohan Hedberg u8 *data) 5437f1496deeSJohan Hedberg { 5438f1496deeSJohan Hedberg struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data; 5439f1496deeSJohan Hedberg u16 dcid, mtu, mps, credits, result; 5440f1496deeSJohan Hedberg struct l2cap_chan *chan; 5441f1496deeSJohan Hedberg int err; 5442f1496deeSJohan Hedberg 5443f1496deeSJohan Hedberg if (cmd_len < sizeof(*rsp)) 5444f1496deeSJohan Hedberg return -EPROTO; 5445f1496deeSJohan Hedberg 5446f1496deeSJohan Hedberg dcid = __le16_to_cpu(rsp->dcid); 5447f1496deeSJohan Hedberg mtu = __le16_to_cpu(rsp->mtu); 5448f1496deeSJohan Hedberg mps = __le16_to_cpu(rsp->mps); 5449f1496deeSJohan Hedberg credits = __le16_to_cpu(rsp->credits); 5450f1496deeSJohan Hedberg result = __le16_to_cpu(rsp->result); 5451f1496deeSJohan Hedberg 5452f1496deeSJohan Hedberg if (result == L2CAP_CR_SUCCESS && (mtu < 23 || mps < 23)) 5453f1496deeSJohan Hedberg return -EPROTO; 5454f1496deeSJohan Hedberg 5455f1496deeSJohan Hedberg BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x", 5456f1496deeSJohan Hedberg dcid, mtu, mps, credits, result); 5457f1496deeSJohan Hedberg 5458f1496deeSJohan Hedberg mutex_lock(&conn->chan_lock); 5459f1496deeSJohan Hedberg 5460f1496deeSJohan Hedberg chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 5461f1496deeSJohan Hedberg if (!chan) { 5462f1496deeSJohan Hedberg err = -EBADSLT; 5463f1496deeSJohan Hedberg goto unlock; 5464f1496deeSJohan Hedberg } 5465f1496deeSJohan Hedberg 5466f1496deeSJohan Hedberg err = 0; 5467f1496deeSJohan Hedberg 5468f1496deeSJohan Hedberg l2cap_chan_lock(chan); 5469f1496deeSJohan Hedberg 5470f1496deeSJohan Hedberg switch (result) { 5471f1496deeSJohan Hedberg case L2CAP_CR_SUCCESS: 5472f1496deeSJohan Hedberg chan->ident = 0; 5473f1496deeSJohan Hedberg chan->dcid = dcid; 5474f1496deeSJohan Hedberg chan->omtu = mtu; 5475f1496deeSJohan Hedberg chan->remote_mps = mps; 54760cd75f7eSJohan Hedberg chan->tx_credits = credits; 5477f1496deeSJohan Hedberg l2cap_chan_ready(chan); 5478f1496deeSJohan Hedberg break; 5479f1496deeSJohan Hedberg 5480f1496deeSJohan Hedberg default: 5481f1496deeSJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED); 5482f1496deeSJohan Hedberg break; 5483f1496deeSJohan Hedberg } 5484f1496deeSJohan Hedberg 5485f1496deeSJohan Hedberg l2cap_chan_unlock(chan); 5486f1496deeSJohan Hedberg 5487f1496deeSJohan Hedberg unlock: 5488f1496deeSJohan Hedberg mutex_unlock(&conn->chan_lock); 5489f1496deeSJohan Hedberg 5490f1496deeSJohan Hedberg return err; 5491f1496deeSJohan Hedberg } 5492f1496deeSJohan Hedberg 54933300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, 54942d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len, 54952d792818SGustavo Padovan u8 *data) 54963300d9a9SClaudio Takahasi { 54973300d9a9SClaudio Takahasi int err = 0; 54983300d9a9SClaudio Takahasi 54993300d9a9SClaudio Takahasi switch (cmd->code) { 55003300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 5501cb3b3152SJohan Hedberg l2cap_command_rej(conn, cmd, cmd_len, data); 55023300d9a9SClaudio Takahasi break; 55033300d9a9SClaudio Takahasi 55043300d9a9SClaudio Takahasi case L2CAP_CONN_REQ: 5505cb3b3152SJohan Hedberg err = l2cap_connect_req(conn, cmd, cmd_len, data); 55063300d9a9SClaudio Takahasi break; 55073300d9a9SClaudio Takahasi 55083300d9a9SClaudio Takahasi case L2CAP_CONN_RSP: 5509f5a2598dSMat Martineau case L2CAP_CREATE_CHAN_RSP: 55109245e737SJohan Hedberg l2cap_connect_create_rsp(conn, cmd, cmd_len, data); 55113300d9a9SClaudio Takahasi break; 55123300d9a9SClaudio Takahasi 55133300d9a9SClaudio Takahasi case L2CAP_CONF_REQ: 55143300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data); 55153300d9a9SClaudio Takahasi break; 55163300d9a9SClaudio Takahasi 55173300d9a9SClaudio Takahasi case L2CAP_CONF_RSP: 55189245e737SJohan Hedberg l2cap_config_rsp(conn, cmd, cmd_len, data); 55193300d9a9SClaudio Takahasi break; 55203300d9a9SClaudio Takahasi 55213300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ: 5522cb3b3152SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data); 55233300d9a9SClaudio Takahasi break; 55243300d9a9SClaudio Takahasi 55253300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP: 55269245e737SJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data); 55273300d9a9SClaudio Takahasi break; 55283300d9a9SClaudio Takahasi 55293300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ: 55303300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data); 55313300d9a9SClaudio Takahasi break; 55323300d9a9SClaudio Takahasi 55333300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP: 55343300d9a9SClaudio Takahasi break; 55353300d9a9SClaudio Takahasi 55363300d9a9SClaudio Takahasi case L2CAP_INFO_REQ: 5537cb3b3152SJohan Hedberg err = l2cap_information_req(conn, cmd, cmd_len, data); 55383300d9a9SClaudio Takahasi break; 55393300d9a9SClaudio Takahasi 55403300d9a9SClaudio Takahasi case L2CAP_INFO_RSP: 55419245e737SJohan Hedberg l2cap_information_rsp(conn, cmd, cmd_len, data); 55423300d9a9SClaudio Takahasi break; 55433300d9a9SClaudio Takahasi 5544f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_REQ: 5545f94ff6ffSMat Martineau err = l2cap_create_channel_req(conn, cmd, cmd_len, data); 5546f94ff6ffSMat Martineau break; 5547f94ff6ffSMat Martineau 55488d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_REQ: 55498d5a04a1SMat Martineau err = l2cap_move_channel_req(conn, cmd, cmd_len, data); 55508d5a04a1SMat Martineau break; 55518d5a04a1SMat Martineau 55528d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_RSP: 55539245e737SJohan Hedberg l2cap_move_channel_rsp(conn, cmd, cmd_len, data); 55548d5a04a1SMat Martineau break; 55558d5a04a1SMat Martineau 55568d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM: 55578d5a04a1SMat Martineau err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data); 55588d5a04a1SMat Martineau break; 55598d5a04a1SMat Martineau 55608d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM_RSP: 55619245e737SJohan Hedberg l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data); 55628d5a04a1SMat Martineau break; 55638d5a04a1SMat Martineau 55643300d9a9SClaudio Takahasi default: 55653300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code); 55663300d9a9SClaudio Takahasi err = -EINVAL; 55673300d9a9SClaudio Takahasi break; 55683300d9a9SClaudio Takahasi } 55693300d9a9SClaudio Takahasi 55703300d9a9SClaudio Takahasi return err; 55713300d9a9SClaudio Takahasi } 55723300d9a9SClaudio Takahasi 557327e2d4c8SJohan Hedberg static int l2cap_le_connect_req(struct l2cap_conn *conn, 557427e2d4c8SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 557527e2d4c8SJohan Hedberg u8 *data) 557627e2d4c8SJohan Hedberg { 557727e2d4c8SJohan Hedberg struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data; 557827e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 557927e2d4c8SJohan Hedberg struct l2cap_chan *chan, *pchan; 55800cd75f7eSJohan Hedberg u16 dcid, scid, credits, mtu, mps; 558127e2d4c8SJohan Hedberg __le16 psm; 558227e2d4c8SJohan Hedberg u8 result; 558327e2d4c8SJohan Hedberg 558427e2d4c8SJohan Hedberg if (cmd_len != sizeof(*req)) 558527e2d4c8SJohan Hedberg return -EPROTO; 558627e2d4c8SJohan Hedberg 558727e2d4c8SJohan Hedberg scid = __le16_to_cpu(req->scid); 558827e2d4c8SJohan Hedberg mtu = __le16_to_cpu(req->mtu); 558927e2d4c8SJohan Hedberg mps = __le16_to_cpu(req->mps); 559027e2d4c8SJohan Hedberg psm = req->psm; 559127e2d4c8SJohan Hedberg dcid = 0; 55920cd75f7eSJohan Hedberg credits = 0; 559327e2d4c8SJohan Hedberg 559427e2d4c8SJohan Hedberg if (mtu < 23 || mps < 23) 559527e2d4c8SJohan Hedberg return -EPROTO; 559627e2d4c8SJohan Hedberg 559727e2d4c8SJohan Hedberg BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm), 559827e2d4c8SJohan Hedberg scid, mtu, mps); 559927e2d4c8SJohan Hedberg 560027e2d4c8SJohan Hedberg /* Check if we have socket listening on psm */ 560127e2d4c8SJohan Hedberg pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 560227e2d4c8SJohan Hedberg &conn->hcon->dst, LE_LINK); 560327e2d4c8SJohan Hedberg if (!pchan) { 560427e2d4c8SJohan Hedberg result = L2CAP_CR_BAD_PSM; 560527e2d4c8SJohan Hedberg chan = NULL; 560627e2d4c8SJohan Hedberg goto response; 560727e2d4c8SJohan Hedberg } 560827e2d4c8SJohan Hedberg 560927e2d4c8SJohan Hedberg mutex_lock(&conn->chan_lock); 561027e2d4c8SJohan Hedberg l2cap_chan_lock(pchan); 561127e2d4c8SJohan Hedberg 561227e2d4c8SJohan Hedberg if (!smp_sufficient_security(conn->hcon, pchan->sec_level)) { 561327e2d4c8SJohan Hedberg result = L2CAP_CR_AUTHENTICATION; 561427e2d4c8SJohan Hedberg chan = NULL; 561527e2d4c8SJohan Hedberg goto response_unlock; 561627e2d4c8SJohan Hedberg } 561727e2d4c8SJohan Hedberg 561827e2d4c8SJohan Hedberg /* Check if we already have channel with that dcid */ 561927e2d4c8SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, scid)) { 562027e2d4c8SJohan Hedberg result = L2CAP_CR_NO_MEM; 562127e2d4c8SJohan Hedberg chan = NULL; 562227e2d4c8SJohan Hedberg goto response_unlock; 562327e2d4c8SJohan Hedberg } 562427e2d4c8SJohan Hedberg 562527e2d4c8SJohan Hedberg chan = pchan->ops->new_connection(pchan); 562627e2d4c8SJohan Hedberg if (!chan) { 562727e2d4c8SJohan Hedberg result = L2CAP_CR_NO_MEM; 562827e2d4c8SJohan Hedberg goto response_unlock; 562927e2d4c8SJohan Hedberg } 563027e2d4c8SJohan Hedberg 563127e2d4c8SJohan Hedberg bacpy(&chan->src, &conn->hcon->src); 563227e2d4c8SJohan Hedberg bacpy(&chan->dst, &conn->hcon->dst); 563327e2d4c8SJohan Hedberg chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type); 563427e2d4c8SJohan Hedberg chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type); 563527e2d4c8SJohan Hedberg chan->psm = psm; 563627e2d4c8SJohan Hedberg chan->dcid = scid; 563727e2d4c8SJohan Hedberg chan->omtu = mtu; 563827e2d4c8SJohan Hedberg chan->remote_mps = mps; 56390cd75f7eSJohan Hedberg chan->tx_credits = __le16_to_cpu(req->credits); 564027e2d4c8SJohan Hedberg 564127e2d4c8SJohan Hedberg __l2cap_chan_add(conn, chan); 564227e2d4c8SJohan Hedberg dcid = chan->scid; 56430cd75f7eSJohan Hedberg credits = chan->rx_credits; 564427e2d4c8SJohan Hedberg 564527e2d4c8SJohan Hedberg __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 564627e2d4c8SJohan Hedberg 564727e2d4c8SJohan Hedberg chan->ident = cmd->ident; 564827e2d4c8SJohan Hedberg 564927e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 565027e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_CONNECT2); 565127e2d4c8SJohan Hedberg result = L2CAP_CR_PEND; 565227e2d4c8SJohan Hedberg chan->ops->defer(chan); 565327e2d4c8SJohan Hedberg } else { 565427e2d4c8SJohan Hedberg l2cap_chan_ready(chan); 565527e2d4c8SJohan Hedberg result = L2CAP_CR_SUCCESS; 565627e2d4c8SJohan Hedberg } 565727e2d4c8SJohan Hedberg 565827e2d4c8SJohan Hedberg response_unlock: 565927e2d4c8SJohan Hedberg l2cap_chan_unlock(pchan); 566027e2d4c8SJohan Hedberg mutex_unlock(&conn->chan_lock); 566127e2d4c8SJohan Hedberg 566227e2d4c8SJohan Hedberg if (result == L2CAP_CR_PEND) 566327e2d4c8SJohan Hedberg return 0; 566427e2d4c8SJohan Hedberg 566527e2d4c8SJohan Hedberg response: 566627e2d4c8SJohan Hedberg if (chan) { 566727e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 566827e2d4c8SJohan Hedberg rsp.mps = __constant_cpu_to_le16(L2CAP_LE_DEFAULT_MPS); 566927e2d4c8SJohan Hedberg } else { 567027e2d4c8SJohan Hedberg rsp.mtu = 0; 567127e2d4c8SJohan Hedberg rsp.mps = 0; 567227e2d4c8SJohan Hedberg } 567327e2d4c8SJohan Hedberg 567427e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(dcid); 56750cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(credits); 567627e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result); 567727e2d4c8SJohan Hedberg 567827e2d4c8SJohan Hedberg l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp); 567927e2d4c8SJohan Hedberg 568027e2d4c8SJohan Hedberg return 0; 568127e2d4c8SJohan Hedberg } 568227e2d4c8SJohan Hedberg 5683fad5fc89SJohan Hedberg static inline int l2cap_le_credits(struct l2cap_conn *conn, 5684fad5fc89SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5685fad5fc89SJohan Hedberg u8 *data) 5686fad5fc89SJohan Hedberg { 5687fad5fc89SJohan Hedberg struct l2cap_le_credits *pkt; 5688fad5fc89SJohan Hedberg struct l2cap_chan *chan; 5689fad5fc89SJohan Hedberg u16 cid, credits; 5690fad5fc89SJohan Hedberg 5691fad5fc89SJohan Hedberg if (cmd_len != sizeof(*pkt)) 5692fad5fc89SJohan Hedberg return -EPROTO; 5693fad5fc89SJohan Hedberg 5694fad5fc89SJohan Hedberg pkt = (struct l2cap_le_credits *) data; 5695fad5fc89SJohan Hedberg cid = __le16_to_cpu(pkt->cid); 5696fad5fc89SJohan Hedberg credits = __le16_to_cpu(pkt->credits); 5697fad5fc89SJohan Hedberg 5698fad5fc89SJohan Hedberg BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits); 5699fad5fc89SJohan Hedberg 5700fad5fc89SJohan Hedberg chan = l2cap_get_chan_by_dcid(conn, cid); 5701fad5fc89SJohan Hedberg if (!chan) 5702fad5fc89SJohan Hedberg return -EBADSLT; 5703fad5fc89SJohan Hedberg 5704fad5fc89SJohan Hedberg chan->tx_credits += credits; 5705fad5fc89SJohan Hedberg 5706fad5fc89SJohan Hedberg while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) { 5707fad5fc89SJohan Hedberg l2cap_do_send(chan, skb_dequeue(&chan->tx_q)); 5708fad5fc89SJohan Hedberg chan->tx_credits--; 5709fad5fc89SJohan Hedberg } 5710fad5fc89SJohan Hedberg 5711fad5fc89SJohan Hedberg if (chan->tx_credits) 5712fad5fc89SJohan Hedberg chan->ops->resume(chan); 5713fad5fc89SJohan Hedberg 5714fad5fc89SJohan Hedberg l2cap_chan_unlock(chan); 5715fad5fc89SJohan Hedberg 5716fad5fc89SJohan Hedberg return 0; 5717fad5fc89SJohan Hedberg } 5718fad5fc89SJohan Hedberg 57193300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, 5720203e639eSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5721203e639eSJohan Hedberg u8 *data) 57223300d9a9SClaudio Takahasi { 5723b5ecba64SJohan Hedberg int err = 0; 5724b5ecba64SJohan Hedberg 57253af8ace6SJohan Hedberg if (!enable_lecoc) { 57263af8ace6SJohan Hedberg switch (cmd->code) { 57273af8ace6SJohan Hedberg case L2CAP_LE_CONN_REQ: 57283af8ace6SJohan Hedberg case L2CAP_LE_CONN_RSP: 57293af8ace6SJohan Hedberg case L2CAP_LE_CREDITS: 57303af8ace6SJohan Hedberg case L2CAP_DISCONN_REQ: 57313af8ace6SJohan Hedberg case L2CAP_DISCONN_RSP: 57323af8ace6SJohan Hedberg return -EINVAL; 57333af8ace6SJohan Hedberg } 57343af8ace6SJohan Hedberg } 57353af8ace6SJohan Hedberg 57363300d9a9SClaudio Takahasi switch (cmd->code) { 57373300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 5738b5ecba64SJohan Hedberg break; 57393300d9a9SClaudio Takahasi 57403300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ: 5741b5ecba64SJohan Hedberg err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data); 5742b5ecba64SJohan Hedberg break; 57433300d9a9SClaudio Takahasi 57443300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP: 5745b5ecba64SJohan Hedberg break; 57463300d9a9SClaudio Takahasi 5747f1496deeSJohan Hedberg case L2CAP_LE_CONN_RSP: 5748f1496deeSJohan Hedberg l2cap_le_connect_rsp(conn, cmd, cmd_len, data); 5749b5ecba64SJohan Hedberg break; 5750f1496deeSJohan Hedberg 575127e2d4c8SJohan Hedberg case L2CAP_LE_CONN_REQ: 5752b5ecba64SJohan Hedberg err = l2cap_le_connect_req(conn, cmd, cmd_len, data); 5753b5ecba64SJohan Hedberg break; 575427e2d4c8SJohan Hedberg 5755fad5fc89SJohan Hedberg case L2CAP_LE_CREDITS: 5756fad5fc89SJohan Hedberg err = l2cap_le_credits(conn, cmd, cmd_len, data); 5757fad5fc89SJohan Hedberg break; 5758fad5fc89SJohan Hedberg 57593defe01aSJohan Hedberg case L2CAP_DISCONN_REQ: 5760b5ecba64SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data); 5761b5ecba64SJohan Hedberg break; 57623defe01aSJohan Hedberg 57633defe01aSJohan Hedberg case L2CAP_DISCONN_RSP: 57643defe01aSJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data); 5765b5ecba64SJohan Hedberg break; 57663defe01aSJohan Hedberg 57673300d9a9SClaudio Takahasi default: 57683300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code); 5769b5ecba64SJohan Hedberg err = -EINVAL; 5770b5ecba64SJohan Hedberg break; 57713300d9a9SClaudio Takahasi } 5772b5ecba64SJohan Hedberg 5773b5ecba64SJohan Hedberg return err; 57743300d9a9SClaudio Takahasi } 57753300d9a9SClaudio Takahasi 5776c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn, 5777c5623556SJohan Hedberg struct sk_buff *skb) 5778c5623556SJohan Hedberg { 577969c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon; 57804f3e219dSMarcel Holtmann struct l2cap_cmd_hdr *cmd; 57814f3e219dSMarcel Holtmann u16 len; 5782c5623556SJohan Hedberg int err; 5783c5623556SJohan Hedberg 578469c4e4e8SJohan Hedberg if (hcon->type != LE_LINK) 57853b166295SMarcel Holtmann goto drop; 578669c4e4e8SJohan Hedberg 57874f3e219dSMarcel Holtmann if (skb->len < L2CAP_CMD_HDR_SIZE) 57884f3e219dSMarcel Holtmann goto drop; 5789c5623556SJohan Hedberg 57904f3e219dSMarcel Holtmann cmd = (void *) skb->data; 57914f3e219dSMarcel Holtmann skb_pull(skb, L2CAP_CMD_HDR_SIZE); 5792c5623556SJohan Hedberg 57934f3e219dSMarcel Holtmann len = le16_to_cpu(cmd->len); 5794c5623556SJohan Hedberg 57954f3e219dSMarcel Holtmann BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident); 57964f3e219dSMarcel Holtmann 57974f3e219dSMarcel Holtmann if (len != skb->len || !cmd->ident) { 5798c5623556SJohan Hedberg BT_DBG("corrupted command"); 57994f3e219dSMarcel Holtmann goto drop; 5800c5623556SJohan Hedberg } 5801c5623556SJohan Hedberg 5802203e639eSJohan Hedberg err = l2cap_le_sig_cmd(conn, cmd, len, skb->data); 5803c5623556SJohan Hedberg if (err) { 5804c5623556SJohan Hedberg struct l2cap_cmd_rej_unk rej; 5805c5623556SJohan Hedberg 5806c5623556SJohan Hedberg BT_ERR("Wrong link type (%d)", err); 5807c5623556SJohan Hedberg 5808a521149aSJohan Hedberg rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 58094f3e219dSMarcel Holtmann l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 5810c5623556SJohan Hedberg sizeof(rej), &rej); 5811c5623556SJohan Hedberg } 5812c5623556SJohan Hedberg 58133b166295SMarcel Holtmann drop: 5814c5623556SJohan Hedberg kfree_skb(skb); 5815c5623556SJohan Hedberg } 5816c5623556SJohan Hedberg 58173300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn, 58183300d9a9SClaudio Takahasi struct sk_buff *skb) 58190a708f8fSGustavo F. Padovan { 582069c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon; 58210a708f8fSGustavo F. Padovan u8 *data = skb->data; 58220a708f8fSGustavo F. Padovan int len = skb->len; 58230a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr cmd; 58243300d9a9SClaudio Takahasi int err; 58250a708f8fSGustavo F. Padovan 58260a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb); 58270a708f8fSGustavo F. Padovan 582869c4e4e8SJohan Hedberg if (hcon->type != ACL_LINK) 58293b166295SMarcel Holtmann goto drop; 583069c4e4e8SJohan Hedberg 58310a708f8fSGustavo F. Padovan while (len >= L2CAP_CMD_HDR_SIZE) { 58320a708f8fSGustavo F. Padovan u16 cmd_len; 58330a708f8fSGustavo F. Padovan memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); 58340a708f8fSGustavo F. Padovan data += L2CAP_CMD_HDR_SIZE; 58350a708f8fSGustavo F. Padovan len -= L2CAP_CMD_HDR_SIZE; 58360a708f8fSGustavo F. Padovan 58370a708f8fSGustavo F. Padovan cmd_len = le16_to_cpu(cmd.len); 58380a708f8fSGustavo F. Padovan 58392d792818SGustavo Padovan BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, 58402d792818SGustavo Padovan cmd.ident); 58410a708f8fSGustavo F. Padovan 58420a708f8fSGustavo F. Padovan if (cmd_len > len || !cmd.ident) { 58430a708f8fSGustavo F. Padovan BT_DBG("corrupted command"); 58440a708f8fSGustavo F. Padovan break; 58450a708f8fSGustavo F. Padovan } 58460a708f8fSGustavo F. Padovan 58473300d9a9SClaudio Takahasi err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data); 58480a708f8fSGustavo F. Padovan if (err) { 5849e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk rej; 58502c6d1a2eSGustavo F. Padovan 58512c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err); 58520a708f8fSGustavo F. Padovan 5853a521149aSJohan Hedberg rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 58542d792818SGustavo Padovan l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, 58552d792818SGustavo Padovan sizeof(rej), &rej); 58560a708f8fSGustavo F. Padovan } 58570a708f8fSGustavo F. Padovan 58580a708f8fSGustavo F. Padovan data += cmd_len; 58590a708f8fSGustavo F. Padovan len -= cmd_len; 58600a708f8fSGustavo F. Padovan } 58610a708f8fSGustavo F. Padovan 58623b166295SMarcel Holtmann drop: 58630a708f8fSGustavo F. Padovan kfree_skb(skb); 58640a708f8fSGustavo F. Padovan } 58650a708f8fSGustavo F. Padovan 586647d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) 58670a708f8fSGustavo F. Padovan { 58680a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs; 5869e4ca6d98SAndrei Emeltchenko int hdr_size; 5870e4ca6d98SAndrei Emeltchenko 5871e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 5872e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE; 5873e4ca6d98SAndrei Emeltchenko else 5874e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE; 58750a708f8fSGustavo F. Padovan 587647d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 587703a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE); 58780a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len); 58790a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); 58800a708f8fSGustavo F. Padovan 58810a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs) 58820a708f8fSGustavo F. Padovan return -EBADMSG; 58830a708f8fSGustavo F. Padovan } 58840a708f8fSGustavo F. Padovan return 0; 58850a708f8fSGustavo F. Padovan } 58860a708f8fSGustavo F. Padovan 58876ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) 58880a708f8fSGustavo F. Padovan { 5889e31f7633SMat Martineau struct l2cap_ctrl control; 58900a708f8fSGustavo F. Padovan 5891e31f7633SMat Martineau BT_DBG("chan %p", chan); 58920a708f8fSGustavo F. Padovan 5893e31f7633SMat Martineau memset(&control, 0, sizeof(control)); 5894e31f7633SMat Martineau control.sframe = 1; 5895e31f7633SMat Martineau control.final = 1; 5896e31f7633SMat Martineau control.reqseq = chan->buffer_seq; 5897e31f7633SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 58980a708f8fSGustavo F. Padovan 5899e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 5900e31f7633SMat Martineau control.super = L2CAP_SUPER_RNR; 5901e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 59020a708f8fSGustavo F. Padovan } 59030a708f8fSGustavo F. Padovan 5904e31f7633SMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 5905e31f7633SMat Martineau chan->unacked_frames > 0) 5906e31f7633SMat Martineau __set_retrans_timer(chan); 59070a708f8fSGustavo F. Padovan 5908e31f7633SMat Martineau /* Send pending iframes */ 5909525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 59100a708f8fSGustavo F. Padovan 5911e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 5912e31f7633SMat Martineau test_bit(CONN_SEND_FBIT, &chan->conn_state)) { 5913e31f7633SMat Martineau /* F-bit wasn't sent in an s-frame or i-frame yet, so 5914e31f7633SMat Martineau * send it now. 5915e31f7633SMat Martineau */ 5916e31f7633SMat Martineau control.super = L2CAP_SUPER_RR; 5917e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 59180a708f8fSGustavo F. Padovan } 59190a708f8fSGustavo F. Padovan } 59200a708f8fSGustavo F. Padovan 59212d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag, 59222d792818SGustavo Padovan struct sk_buff **last_frag) 59230a708f8fSGustavo F. Padovan { 592484084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments 592584084a31SMat Martineau * skb->data_len reflects only data in fragments 592684084a31SMat Martineau */ 592784084a31SMat Martineau if (!skb_has_frag_list(skb)) 592884084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag; 592984084a31SMat Martineau 593084084a31SMat Martineau new_frag->next = NULL; 593184084a31SMat Martineau 593284084a31SMat Martineau (*last_frag)->next = new_frag; 593384084a31SMat Martineau *last_frag = new_frag; 593484084a31SMat Martineau 593584084a31SMat Martineau skb->len += new_frag->len; 593684084a31SMat Martineau skb->data_len += new_frag->len; 593784084a31SMat Martineau skb->truesize += new_frag->truesize; 593884084a31SMat Martineau } 593984084a31SMat Martineau 59404b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, 59414b51dae9SMat Martineau struct l2cap_ctrl *control) 594284084a31SMat Martineau { 594384084a31SMat Martineau int err = -EINVAL; 59440a708f8fSGustavo F. Padovan 59454b51dae9SMat Martineau switch (control->sar) { 59467e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED: 594784084a31SMat Martineau if (chan->sdu) 594884084a31SMat Martineau break; 59490a708f8fSGustavo F. Padovan 595080b98027SGustavo Padovan err = chan->ops->recv(chan, skb); 595184084a31SMat Martineau break; 59520a708f8fSGustavo F. Padovan 59537e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START: 595484084a31SMat Martineau if (chan->sdu) 595584084a31SMat Martineau break; 59560a708f8fSGustavo F. Padovan 59576f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data); 595803a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE); 59590a708f8fSGustavo F. Padovan 596084084a31SMat Martineau if (chan->sdu_len > chan->imtu) { 596184084a31SMat Martineau err = -EMSGSIZE; 596284084a31SMat Martineau break; 596384084a31SMat Martineau } 59640a708f8fSGustavo F. Padovan 596584084a31SMat Martineau if (skb->len >= chan->sdu_len) 596684084a31SMat Martineau break; 596784084a31SMat Martineau 596884084a31SMat Martineau chan->sdu = skb; 596984084a31SMat Martineau chan->sdu_last_frag = skb; 597084084a31SMat Martineau 597184084a31SMat Martineau skb = NULL; 597284084a31SMat Martineau err = 0; 59730a708f8fSGustavo F. Padovan break; 59740a708f8fSGustavo F. Padovan 59757e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE: 59766f61fd47SGustavo F. Padovan if (!chan->sdu) 597784084a31SMat Martineau break; 59780a708f8fSGustavo F. Padovan 597984084a31SMat Martineau append_skb_frag(chan->sdu, skb, 598084084a31SMat Martineau &chan->sdu_last_frag); 598184084a31SMat Martineau skb = NULL; 59820a708f8fSGustavo F. Padovan 598384084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len) 598484084a31SMat Martineau break; 59850a708f8fSGustavo F. Padovan 598684084a31SMat Martineau err = 0; 59870a708f8fSGustavo F. Padovan break; 59880a708f8fSGustavo F. Padovan 59897e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END: 59906f61fd47SGustavo F. Padovan if (!chan->sdu) 599184084a31SMat Martineau break; 59920a708f8fSGustavo F. Padovan 599384084a31SMat Martineau append_skb_frag(chan->sdu, skb, 599484084a31SMat Martineau &chan->sdu_last_frag); 599584084a31SMat Martineau skb = NULL; 59960a708f8fSGustavo F. Padovan 599784084a31SMat Martineau if (chan->sdu->len != chan->sdu_len) 599884084a31SMat Martineau break; 59990a708f8fSGustavo F. Padovan 600080b98027SGustavo Padovan err = chan->ops->recv(chan, chan->sdu); 60010a708f8fSGustavo F. Padovan 600284084a31SMat Martineau if (!err) { 600384084a31SMat Martineau /* Reassembly complete */ 600484084a31SMat Martineau chan->sdu = NULL; 600584084a31SMat Martineau chan->sdu_last_frag = NULL; 600684084a31SMat Martineau chan->sdu_len = 0; 60070a708f8fSGustavo F. Padovan } 60080a708f8fSGustavo F. Padovan break; 60090a708f8fSGustavo F. Padovan } 60100a708f8fSGustavo F. Padovan 601184084a31SMat Martineau if (err) { 60120a708f8fSGustavo F. Padovan kfree_skb(skb); 60136f61fd47SGustavo F. Padovan kfree_skb(chan->sdu); 60146f61fd47SGustavo F. Padovan chan->sdu = NULL; 601584084a31SMat Martineau chan->sdu_last_frag = NULL; 601684084a31SMat Martineau chan->sdu_len = 0; 601784084a31SMat Martineau } 60180a708f8fSGustavo F. Padovan 601984084a31SMat Martineau return err; 60200a708f8fSGustavo F. Padovan } 60210a708f8fSGustavo F. Padovan 602232b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan) 602332b32735SMat Martineau { 602432b32735SMat Martineau /* Placeholder */ 602532b32735SMat Martineau return 0; 602632b32735SMat Martineau } 602732b32735SMat Martineau 6028e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 60290a708f8fSGustavo F. Padovan { 603061aa4f5bSMat Martineau u8 event; 603161aa4f5bSMat Martineau 603261aa4f5bSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 603361aa4f5bSMat Martineau return; 603461aa4f5bSMat Martineau 603561aa4f5bSMat Martineau event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR; 6036401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, event); 60370a708f8fSGustavo F. Padovan } 60380a708f8fSGustavo F. Padovan 6039d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan) 6040d2a7ac5dSMat Martineau { 604163838725SMat Martineau int err = 0; 604263838725SMat Martineau /* Pass sequential frames to l2cap_reassemble_sdu() 604363838725SMat Martineau * until a gap is encountered. 604463838725SMat Martineau */ 604563838725SMat Martineau 604663838725SMat Martineau BT_DBG("chan %p", chan); 604763838725SMat Martineau 604863838725SMat Martineau while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 604963838725SMat Martineau struct sk_buff *skb; 605063838725SMat Martineau BT_DBG("Searching for skb with txseq %d (queue len %d)", 605163838725SMat Martineau chan->buffer_seq, skb_queue_len(&chan->srej_q)); 605263838725SMat Martineau 605363838725SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq); 605463838725SMat Martineau 605563838725SMat Martineau if (!skb) 605663838725SMat Martineau break; 605763838725SMat Martineau 605863838725SMat Martineau skb_unlink(skb, &chan->srej_q); 605963838725SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 606063838725SMat Martineau err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->control); 606163838725SMat Martineau if (err) 606263838725SMat Martineau break; 606363838725SMat Martineau } 606463838725SMat Martineau 606563838725SMat Martineau if (skb_queue_empty(&chan->srej_q)) { 606663838725SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 606763838725SMat Martineau l2cap_send_ack(chan); 606863838725SMat Martineau } 606963838725SMat Martineau 607063838725SMat Martineau return err; 6071d2a7ac5dSMat Martineau } 6072d2a7ac5dSMat Martineau 6073d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan, 6074d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 6075d2a7ac5dSMat Martineau { 6076f80842a8SMat Martineau struct sk_buff *skb; 6077f80842a8SMat Martineau 6078f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 6079f80842a8SMat Martineau 6080f80842a8SMat Martineau if (control->reqseq == chan->next_tx_seq) { 6081f80842a8SMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 60825e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6083f80842a8SMat Martineau return; 6084f80842a8SMat Martineau } 6085f80842a8SMat Martineau 6086f80842a8SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 6087f80842a8SMat Martineau 6088f80842a8SMat Martineau if (skb == NULL) { 6089f80842a8SMat Martineau BT_DBG("Seq %d not available for retransmission", 6090f80842a8SMat Martineau control->reqseq); 6091f80842a8SMat Martineau return; 6092f80842a8SMat Martineau } 6093f80842a8SMat Martineau 6094f80842a8SMat Martineau if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) { 6095f80842a8SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 60965e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6097f80842a8SMat Martineau return; 6098f80842a8SMat Martineau } 6099f80842a8SMat Martineau 6100f80842a8SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6101f80842a8SMat Martineau 6102f80842a8SMat Martineau if (control->poll) { 6103f80842a8SMat Martineau l2cap_pass_to_tx(chan, control); 6104f80842a8SMat Martineau 6105f80842a8SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6106f80842a8SMat Martineau l2cap_retransmit(chan, control); 6107f80842a8SMat Martineau l2cap_ertm_send(chan); 6108f80842a8SMat Martineau 6109f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 6110f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 6111f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 6112f80842a8SMat Martineau } 6113f80842a8SMat Martineau } else { 6114f80842a8SMat Martineau l2cap_pass_to_tx_fbit(chan, control); 6115f80842a8SMat Martineau 6116f80842a8SMat Martineau if (control->final) { 6117f80842a8SMat Martineau if (chan->srej_save_reqseq != control->reqseq || 6118f80842a8SMat Martineau !test_and_clear_bit(CONN_SREJ_ACT, 6119f80842a8SMat Martineau &chan->conn_state)) 6120f80842a8SMat Martineau l2cap_retransmit(chan, control); 6121f80842a8SMat Martineau } else { 6122f80842a8SMat Martineau l2cap_retransmit(chan, control); 6123f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 6124f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 6125f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 6126f80842a8SMat Martineau } 6127f80842a8SMat Martineau } 6128f80842a8SMat Martineau } 6129d2a7ac5dSMat Martineau } 6130d2a7ac5dSMat Martineau 6131d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan, 6132d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 6133d2a7ac5dSMat Martineau { 6134fcd289dfSMat Martineau struct sk_buff *skb; 6135fcd289dfSMat Martineau 6136fcd289dfSMat Martineau BT_DBG("chan %p, control %p", chan, control); 6137fcd289dfSMat Martineau 6138fcd289dfSMat Martineau if (control->reqseq == chan->next_tx_seq) { 6139fcd289dfSMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 61405e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6141fcd289dfSMat Martineau return; 6142fcd289dfSMat Martineau } 6143fcd289dfSMat Martineau 6144fcd289dfSMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 6145fcd289dfSMat Martineau 6146fcd289dfSMat Martineau if (chan->max_tx && skb && 6147fcd289dfSMat Martineau bt_cb(skb)->control.retries >= chan->max_tx) { 6148fcd289dfSMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 61495e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6150fcd289dfSMat Martineau return; 6151fcd289dfSMat Martineau } 6152fcd289dfSMat Martineau 6153fcd289dfSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6154fcd289dfSMat Martineau 6155fcd289dfSMat Martineau l2cap_pass_to_tx(chan, control); 6156fcd289dfSMat Martineau 6157fcd289dfSMat Martineau if (control->final) { 6158fcd289dfSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 6159fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 6160fcd289dfSMat Martineau } else { 6161fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 6162fcd289dfSMat Martineau l2cap_ertm_send(chan); 6163fcd289dfSMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) 6164fcd289dfSMat Martineau set_bit(CONN_REJ_ACT, &chan->conn_state); 6165fcd289dfSMat Martineau } 6166d2a7ac5dSMat Martineau } 6167d2a7ac5dSMat Martineau 61684b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) 61694b51dae9SMat Martineau { 61704b51dae9SMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 61714b51dae9SMat Martineau 61724b51dae9SMat Martineau BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq, 61734b51dae9SMat Martineau chan->expected_tx_seq); 61744b51dae9SMat Martineau 61754b51dae9SMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 61764b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 61774b51dae9SMat Martineau chan->tx_win) { 61784b51dae9SMat Martineau /* See notes below regarding "double poll" and 61794b51dae9SMat Martineau * invalid packets. 61804b51dae9SMat Martineau */ 61814b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 61824b51dae9SMat Martineau BT_DBG("Invalid/Ignore - after SREJ"); 61834b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 61844b51dae9SMat Martineau } else { 61854b51dae9SMat Martineau BT_DBG("Invalid - in window after SREJ sent"); 61864b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 61874b51dae9SMat Martineau } 61884b51dae9SMat Martineau } 61894b51dae9SMat Martineau 61904b51dae9SMat Martineau if (chan->srej_list.head == txseq) { 61914b51dae9SMat Martineau BT_DBG("Expected SREJ"); 61924b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED_SREJ; 61934b51dae9SMat Martineau } 61944b51dae9SMat Martineau 61954b51dae9SMat Martineau if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) { 61964b51dae9SMat Martineau BT_DBG("Duplicate SREJ - txseq already stored"); 61974b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE_SREJ; 61984b51dae9SMat Martineau } 61994b51dae9SMat Martineau 62004b51dae9SMat Martineau if (l2cap_seq_list_contains(&chan->srej_list, txseq)) { 62014b51dae9SMat Martineau BT_DBG("Unexpected SREJ - not requested"); 62024b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED_SREJ; 62034b51dae9SMat Martineau } 62044b51dae9SMat Martineau } 62054b51dae9SMat Martineau 62064b51dae9SMat Martineau if (chan->expected_tx_seq == txseq) { 62074b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 62084b51dae9SMat Martineau chan->tx_win) { 62094b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 62104b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 62114b51dae9SMat Martineau } else { 62124b51dae9SMat Martineau BT_DBG("Expected"); 62134b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED; 62144b51dae9SMat Martineau } 62154b51dae9SMat Martineau } 62164b51dae9SMat Martineau 62174b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) < 62182d792818SGustavo Padovan __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) { 62194b51dae9SMat Martineau BT_DBG("Duplicate - expected_tx_seq later than txseq"); 62204b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE; 62214b51dae9SMat Martineau } 62224b51dae9SMat Martineau 62234b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) { 62244b51dae9SMat Martineau /* A source of invalid packets is a "double poll" condition, 62254b51dae9SMat Martineau * where delays cause us to send multiple poll packets. If 62264b51dae9SMat Martineau * the remote stack receives and processes both polls, 62274b51dae9SMat Martineau * sequence numbers can wrap around in such a way that a 62284b51dae9SMat Martineau * resent frame has a sequence number that looks like new data 62294b51dae9SMat Martineau * with a sequence gap. This would trigger an erroneous SREJ 62304b51dae9SMat Martineau * request. 62314b51dae9SMat Martineau * 62324b51dae9SMat Martineau * Fortunately, this is impossible with a tx window that's 62334b51dae9SMat Martineau * less than half of the maximum sequence number, which allows 62344b51dae9SMat Martineau * invalid frames to be safely ignored. 62354b51dae9SMat Martineau * 62364b51dae9SMat Martineau * With tx window sizes greater than half of the tx window 62374b51dae9SMat Martineau * maximum, the frame is invalid and cannot be ignored. This 62384b51dae9SMat Martineau * causes a disconnect. 62394b51dae9SMat Martineau */ 62404b51dae9SMat Martineau 62414b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 62424b51dae9SMat Martineau BT_DBG("Invalid/Ignore - txseq outside tx window"); 62434b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 62444b51dae9SMat Martineau } else { 62454b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 62464b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 62474b51dae9SMat Martineau } 62484b51dae9SMat Martineau } else { 62494b51dae9SMat Martineau BT_DBG("Unexpected - txseq indicates missing frames"); 62504b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED; 62514b51dae9SMat Martineau } 62524b51dae9SMat Martineau } 62534b51dae9SMat Martineau 6254d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan, 6255d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 6256d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 6257d2a7ac5dSMat Martineau { 6258d2a7ac5dSMat Martineau int err = 0; 6259941247f9SPeter Senna Tschudin bool skb_in_use = false; 6260d2a7ac5dSMat Martineau 6261d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 6262d2a7ac5dSMat Martineau event); 6263d2a7ac5dSMat Martineau 6264d2a7ac5dSMat Martineau switch (event) { 6265d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 6266d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, control->txseq)) { 6267d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 6268d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6269d2a7ac5dSMat Martineau 6270d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 6271d2a7ac5dSMat Martineau BT_DBG("Busy, discarding expected seq %d", 6272d2a7ac5dSMat Martineau control->txseq); 6273d2a7ac5dSMat Martineau break; 6274d2a7ac5dSMat Martineau } 6275d2a7ac5dSMat Martineau 6276d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, 6277d2a7ac5dSMat Martineau control->txseq); 6278d2a7ac5dSMat Martineau 6279d2a7ac5dSMat Martineau chan->buffer_seq = chan->expected_tx_seq; 6280941247f9SPeter Senna Tschudin skb_in_use = true; 6281d2a7ac5dSMat Martineau 6282d2a7ac5dSMat Martineau err = l2cap_reassemble_sdu(chan, skb, control); 6283d2a7ac5dSMat Martineau if (err) 6284d2a7ac5dSMat Martineau break; 6285d2a7ac5dSMat Martineau 6286d2a7ac5dSMat Martineau if (control->final) { 6287d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 6288d2a7ac5dSMat Martineau &chan->conn_state)) { 6289d2a7ac5dSMat Martineau control->final = 0; 6290d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6291d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6292d2a7ac5dSMat Martineau } 6293d2a7ac5dSMat Martineau } 6294d2a7ac5dSMat Martineau 6295d2a7ac5dSMat Martineau if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 6296d2a7ac5dSMat Martineau l2cap_send_ack(chan); 6297d2a7ac5dSMat Martineau break; 6298d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 6299d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6300d2a7ac5dSMat Martineau 6301d2a7ac5dSMat Martineau /* Can't issue SREJ frames in the local busy state. 6302d2a7ac5dSMat Martineau * Drop this frame, it will be seen as missing 6303d2a7ac5dSMat Martineau * when local busy is exited. 6304d2a7ac5dSMat Martineau */ 6305d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 6306d2a7ac5dSMat Martineau BT_DBG("Busy, discarding unexpected seq %d", 6307d2a7ac5dSMat Martineau control->txseq); 6308d2a7ac5dSMat Martineau break; 6309d2a7ac5dSMat Martineau } 6310d2a7ac5dSMat Martineau 6311d2a7ac5dSMat Martineau /* There was a gap in the sequence, so an SREJ 6312d2a7ac5dSMat Martineau * must be sent for each missing frame. The 6313d2a7ac5dSMat Martineau * current frame is stored for later use. 6314d2a7ac5dSMat Martineau */ 6315d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6316941247f9SPeter Senna Tschudin skb_in_use = true; 6317d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6318d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6319d2a7ac5dSMat Martineau 6320d2a7ac5dSMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 6321d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 6322d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 6323d2a7ac5dSMat Martineau 6324d2a7ac5dSMat Martineau chan->rx_state = L2CAP_RX_STATE_SREJ_SENT; 6325d2a7ac5dSMat Martineau break; 6326d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 6327d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6328d2a7ac5dSMat Martineau break; 6329d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 6330d2a7ac5dSMat Martineau break; 6331d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 6332d2a7ac5dSMat Martineau default: 63335e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6334d2a7ac5dSMat Martineau break; 6335d2a7ac5dSMat Martineau } 6336d2a7ac5dSMat Martineau break; 6337d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 6338d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6339d2a7ac5dSMat Martineau if (control->final) { 6340d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6341d2a7ac5dSMat Martineau 6342e6a3ee6eSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) && 6343e6a3ee6eSMat Martineau !__chan_is_moving(chan)) { 6344d2a7ac5dSMat Martineau control->final = 0; 6345d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6346d2a7ac5dSMat Martineau } 6347d2a7ac5dSMat Martineau 6348d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6349d2a7ac5dSMat Martineau } else if (control->poll) { 6350d2a7ac5dSMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 6351d2a7ac5dSMat Martineau } else { 6352d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6353d2a7ac5dSMat Martineau &chan->conn_state) && 6354d2a7ac5dSMat Martineau chan->unacked_frames) 6355d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6356d2a7ac5dSMat Martineau 6357d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6358d2a7ac5dSMat Martineau } 6359d2a7ac5dSMat Martineau break; 6360d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 6361d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6362d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6363d2a7ac5dSMat Martineau if (control && control->poll) { 6364d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6365d2a7ac5dSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 6366d2a7ac5dSMat Martineau } 6367d2a7ac5dSMat Martineau __clear_retrans_timer(chan); 6368d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 6369d2a7ac5dSMat Martineau break; 6370d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 6371d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 6372d2a7ac5dSMat Martineau break; 6373d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 6374d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 6375d2a7ac5dSMat Martineau break; 6376d2a7ac5dSMat Martineau default: 6377d2a7ac5dSMat Martineau break; 6378d2a7ac5dSMat Martineau } 6379d2a7ac5dSMat Martineau 6380d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 6381d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 6382d2a7ac5dSMat Martineau kfree_skb(skb); 6383d2a7ac5dSMat Martineau } 6384d2a7ac5dSMat Martineau 6385d2a7ac5dSMat Martineau return err; 6386d2a7ac5dSMat Martineau } 6387d2a7ac5dSMat Martineau 6388d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, 6389d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 6390d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 6391d2a7ac5dSMat Martineau { 6392d2a7ac5dSMat Martineau int err = 0; 6393d2a7ac5dSMat Martineau u16 txseq = control->txseq; 6394941247f9SPeter Senna Tschudin bool skb_in_use = false; 6395d2a7ac5dSMat Martineau 6396d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 6397d2a7ac5dSMat Martineau event); 6398d2a7ac5dSMat Martineau 6399d2a7ac5dSMat Martineau switch (event) { 6400d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 6401d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, txseq)) { 6402d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 6403d2a7ac5dSMat Martineau /* Keep frame for reassembly later */ 6404d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6405d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6406941247f9SPeter Senna Tschudin skb_in_use = true; 6407d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6408d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6409d2a7ac5dSMat Martineau 6410d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 6411d2a7ac5dSMat Martineau break; 6412d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED_SREJ: 6413d2a7ac5dSMat Martineau l2cap_seq_list_pop(&chan->srej_list); 6414d2a7ac5dSMat Martineau 6415d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6416d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6417941247f9SPeter Senna Tschudin skb_in_use = true; 6418d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6419d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6420d2a7ac5dSMat Martineau 6421d2a7ac5dSMat Martineau err = l2cap_rx_queued_iframes(chan); 6422d2a7ac5dSMat Martineau if (err) 6423d2a7ac5dSMat Martineau break; 6424d2a7ac5dSMat Martineau 6425d2a7ac5dSMat Martineau break; 6426d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 6427d2a7ac5dSMat Martineau /* Got a frame that can't be reassembled yet. 6428d2a7ac5dSMat Martineau * Save it for later, and send SREJs to cover 6429d2a7ac5dSMat Martineau * the missing frames. 6430d2a7ac5dSMat Martineau */ 6431d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6432941247f9SPeter Senna Tschudin skb_in_use = true; 6433d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6434d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6435d2a7ac5dSMat Martineau 6436d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6437d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 6438d2a7ac5dSMat Martineau break; 6439d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED_SREJ: 6440d2a7ac5dSMat Martineau /* This frame was requested with an SREJ, but 6441d2a7ac5dSMat Martineau * some expected retransmitted frames are 6442d2a7ac5dSMat Martineau * missing. Request retransmission of missing 6443d2a7ac5dSMat Martineau * SREJ'd frames. 6444d2a7ac5dSMat Martineau */ 6445d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6446941247f9SPeter Senna Tschudin skb_in_use = true; 6447d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6448d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6449d2a7ac5dSMat Martineau 6450d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6451d2a7ac5dSMat Martineau l2cap_send_srej_list(chan, control->txseq); 6452d2a7ac5dSMat Martineau break; 6453d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE_SREJ: 6454d2a7ac5dSMat Martineau /* We've already queued this frame. Drop this copy. */ 6455d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6456d2a7ac5dSMat Martineau break; 6457d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 6458d2a7ac5dSMat Martineau /* Expecting a later sequence number, so this frame 6459d2a7ac5dSMat Martineau * was already received. Ignore it completely. 6460d2a7ac5dSMat Martineau */ 6461d2a7ac5dSMat Martineau break; 6462d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 6463d2a7ac5dSMat Martineau break; 6464d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 6465d2a7ac5dSMat Martineau default: 64665e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6467d2a7ac5dSMat Martineau break; 6468d2a7ac5dSMat Martineau } 6469d2a7ac5dSMat Martineau break; 6470d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 6471d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6472d2a7ac5dSMat Martineau if (control->final) { 6473d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6474d2a7ac5dSMat Martineau 6475d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 6476d2a7ac5dSMat Martineau &chan->conn_state)) { 6477d2a7ac5dSMat Martineau control->final = 0; 6478d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6479d2a7ac5dSMat Martineau } 6480d2a7ac5dSMat Martineau 6481d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6482d2a7ac5dSMat Martineau } else if (control->poll) { 6483d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6484d2a7ac5dSMat Martineau &chan->conn_state) && 6485d2a7ac5dSMat Martineau chan->unacked_frames) { 6486d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6487d2a7ac5dSMat Martineau } 6488d2a7ac5dSMat Martineau 6489d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6490d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 6491d2a7ac5dSMat Martineau } else { 6492d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6493d2a7ac5dSMat Martineau &chan->conn_state) && 6494d2a7ac5dSMat Martineau chan->unacked_frames) 6495d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6496d2a7ac5dSMat Martineau 6497d2a7ac5dSMat Martineau l2cap_send_ack(chan); 6498d2a7ac5dSMat Martineau } 6499d2a7ac5dSMat Martineau break; 6500d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 6501d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6502d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6503d2a7ac5dSMat Martineau if (control->poll) { 6504d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 6505d2a7ac5dSMat Martineau } else { 6506d2a7ac5dSMat Martineau struct l2cap_ctrl rr_control; 6507d2a7ac5dSMat Martineau memset(&rr_control, 0, sizeof(rr_control)); 6508d2a7ac5dSMat Martineau rr_control.sframe = 1; 6509d2a7ac5dSMat Martineau rr_control.super = L2CAP_SUPER_RR; 6510d2a7ac5dSMat Martineau rr_control.reqseq = chan->buffer_seq; 6511d2a7ac5dSMat Martineau l2cap_send_sframe(chan, &rr_control); 6512d2a7ac5dSMat Martineau } 6513d2a7ac5dSMat Martineau 6514d2a7ac5dSMat Martineau break; 6515d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 6516d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 6517d2a7ac5dSMat Martineau break; 6518d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 6519d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 6520d2a7ac5dSMat Martineau break; 6521d2a7ac5dSMat Martineau } 6522d2a7ac5dSMat Martineau 6523d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 6524d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 6525d2a7ac5dSMat Martineau kfree_skb(skb); 6526d2a7ac5dSMat Martineau } 6527d2a7ac5dSMat Martineau 6528d2a7ac5dSMat Martineau return err; 6529d2a7ac5dSMat Martineau } 6530d2a7ac5dSMat Martineau 653132b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan) 653232b32735SMat Martineau { 653332b32735SMat Martineau BT_DBG("chan %p", chan); 653432b32735SMat Martineau 653532b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 653632b32735SMat Martineau 653732b32735SMat Martineau if (chan->hs_hcon) 653832b32735SMat Martineau chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; 653932b32735SMat Martineau else 654032b32735SMat Martineau chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; 654132b32735SMat Martineau 654232b32735SMat Martineau return l2cap_resegment(chan); 654332b32735SMat Martineau } 654432b32735SMat Martineau 654532b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan, 654632b32735SMat Martineau struct l2cap_ctrl *control, 654732b32735SMat Martineau struct sk_buff *skb, u8 event) 654832b32735SMat Martineau { 654932b32735SMat Martineau int err; 655032b32735SMat Martineau 655132b32735SMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 655232b32735SMat Martineau event); 655332b32735SMat Martineau 655432b32735SMat Martineau if (!control->poll) 655532b32735SMat Martineau return -EPROTO; 655632b32735SMat Martineau 655732b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq); 655832b32735SMat Martineau 655932b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q)) 656032b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q); 656132b32735SMat Martineau else 656232b32735SMat Martineau chan->tx_send_head = NULL; 656332b32735SMat Martineau 656432b32735SMat Martineau /* Rewind next_tx_seq to the point expected 656532b32735SMat Martineau * by the receiver. 656632b32735SMat Martineau */ 656732b32735SMat Martineau chan->next_tx_seq = control->reqseq; 656832b32735SMat Martineau chan->unacked_frames = 0; 656932b32735SMat Martineau 657032b32735SMat Martineau err = l2cap_finish_move(chan); 657132b32735SMat Martineau if (err) 657232b32735SMat Martineau return err; 657332b32735SMat Martineau 657432b32735SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 657532b32735SMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 657632b32735SMat Martineau 657732b32735SMat Martineau if (event == L2CAP_EV_RECV_IFRAME) 657832b32735SMat Martineau return -EPROTO; 657932b32735SMat Martineau 658032b32735SMat Martineau return l2cap_rx_state_recv(chan, control, NULL, event); 658132b32735SMat Martineau } 658232b32735SMat Martineau 658332b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan, 658432b32735SMat Martineau struct l2cap_ctrl *control, 658532b32735SMat Martineau struct sk_buff *skb, u8 event) 658632b32735SMat Martineau { 658732b32735SMat Martineau int err; 658832b32735SMat Martineau 658932b32735SMat Martineau if (!control->final) 659032b32735SMat Martineau return -EPROTO; 659132b32735SMat Martineau 659232b32735SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 659332b32735SMat Martineau 659432b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 659532b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq); 659632b32735SMat Martineau 659732b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q)) 659832b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q); 659932b32735SMat Martineau else 660032b32735SMat Martineau chan->tx_send_head = NULL; 660132b32735SMat Martineau 660232b32735SMat Martineau /* Rewind next_tx_seq to the point expected 660332b32735SMat Martineau * by the receiver. 660432b32735SMat Martineau */ 660532b32735SMat Martineau chan->next_tx_seq = control->reqseq; 660632b32735SMat Martineau chan->unacked_frames = 0; 660732b32735SMat Martineau 660832b32735SMat Martineau if (chan->hs_hcon) 660932b32735SMat Martineau chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; 661032b32735SMat Martineau else 661132b32735SMat Martineau chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; 661232b32735SMat Martineau 661332b32735SMat Martineau err = l2cap_resegment(chan); 661432b32735SMat Martineau 661532b32735SMat Martineau if (!err) 661632b32735SMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 661732b32735SMat Martineau 661832b32735SMat Martineau return err; 661932b32735SMat Martineau } 662032b32735SMat Martineau 6621d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq) 6622d2a7ac5dSMat Martineau { 6623d2a7ac5dSMat Martineau /* Make sure reqseq is for a packet that has been sent but not acked */ 6624d2a7ac5dSMat Martineau u16 unacked; 6625d2a7ac5dSMat Martineau 6626d2a7ac5dSMat Martineau unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq); 6627d2a7ac5dSMat Martineau return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked; 6628d2a7ac5dSMat Martineau } 6629d2a7ac5dSMat Martineau 6630cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 6631cec8ab6eSMat Martineau struct sk_buff *skb, u8 event) 66320a708f8fSGustavo F. Padovan { 6633d2a7ac5dSMat Martineau int err = 0; 6634d2a7ac5dSMat Martineau 6635d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan, 6636d2a7ac5dSMat Martineau control, skb, event, chan->rx_state); 6637d2a7ac5dSMat Martineau 6638d2a7ac5dSMat Martineau if (__valid_reqseq(chan, control->reqseq)) { 6639d2a7ac5dSMat Martineau switch (chan->rx_state) { 6640d2a7ac5dSMat Martineau case L2CAP_RX_STATE_RECV: 6641d2a7ac5dSMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 6642d2a7ac5dSMat Martineau break; 6643d2a7ac5dSMat Martineau case L2CAP_RX_STATE_SREJ_SENT: 6644d2a7ac5dSMat Martineau err = l2cap_rx_state_srej_sent(chan, control, skb, 6645d2a7ac5dSMat Martineau event); 6646d2a7ac5dSMat Martineau break; 664732b32735SMat Martineau case L2CAP_RX_STATE_WAIT_P: 664832b32735SMat Martineau err = l2cap_rx_state_wait_p(chan, control, skb, event); 664932b32735SMat Martineau break; 665032b32735SMat Martineau case L2CAP_RX_STATE_WAIT_F: 665132b32735SMat Martineau err = l2cap_rx_state_wait_f(chan, control, skb, event); 665232b32735SMat Martineau break; 6653d2a7ac5dSMat Martineau default: 6654d2a7ac5dSMat Martineau /* shut it down */ 6655d2a7ac5dSMat Martineau break; 6656d2a7ac5dSMat Martineau } 6657d2a7ac5dSMat Martineau } else { 6658d2a7ac5dSMat Martineau BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d", 6659d2a7ac5dSMat Martineau control->reqseq, chan->next_tx_seq, 6660d2a7ac5dSMat Martineau chan->expected_ack_seq); 66615e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6662d2a7ac5dSMat Martineau } 6663d2a7ac5dSMat Martineau 6664d2a7ac5dSMat Martineau return err; 6665cec8ab6eSMat Martineau } 6666cec8ab6eSMat Martineau 6667cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 6668cec8ab6eSMat Martineau struct sk_buff *skb) 6669cec8ab6eSMat Martineau { 66704b51dae9SMat Martineau int err = 0; 66714b51dae9SMat Martineau 66724b51dae9SMat Martineau BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb, 66734b51dae9SMat Martineau chan->rx_state); 66744b51dae9SMat Martineau 66754b51dae9SMat Martineau if (l2cap_classify_txseq(chan, control->txseq) == 66764b51dae9SMat Martineau L2CAP_TXSEQ_EXPECTED) { 66774b51dae9SMat Martineau l2cap_pass_to_tx(chan, control); 66784b51dae9SMat Martineau 66794b51dae9SMat Martineau BT_DBG("buffer_seq %d->%d", chan->buffer_seq, 66804b51dae9SMat Martineau __next_seq(chan, chan->buffer_seq)); 66814b51dae9SMat Martineau 66824b51dae9SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 66834b51dae9SMat Martineau 66844b51dae9SMat Martineau l2cap_reassemble_sdu(chan, skb, control); 66854b51dae9SMat Martineau } else { 66864b51dae9SMat Martineau if (chan->sdu) { 66874b51dae9SMat Martineau kfree_skb(chan->sdu); 66884b51dae9SMat Martineau chan->sdu = NULL; 66894b51dae9SMat Martineau } 66904b51dae9SMat Martineau chan->sdu_last_frag = NULL; 66914b51dae9SMat Martineau chan->sdu_len = 0; 66924b51dae9SMat Martineau 66934b51dae9SMat Martineau if (skb) { 66944b51dae9SMat Martineau BT_DBG("Freeing %p", skb); 66954b51dae9SMat Martineau kfree_skb(skb); 66964b51dae9SMat Martineau } 66974b51dae9SMat Martineau } 66984b51dae9SMat Martineau 66994b51dae9SMat Martineau chan->last_acked_seq = control->txseq; 67004b51dae9SMat Martineau chan->expected_tx_seq = __next_seq(chan, control->txseq); 67014b51dae9SMat Martineau 67024b51dae9SMat Martineau return err; 6703cec8ab6eSMat Martineau } 6704cec8ab6eSMat Martineau 6705cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 6706cec8ab6eSMat Martineau { 6707cec8ab6eSMat Martineau struct l2cap_ctrl *control = &bt_cb(skb)->control; 6708cec8ab6eSMat Martineau u16 len; 6709cec8ab6eSMat Martineau u8 event; 67100a708f8fSGustavo F. Padovan 6711b76bbd66SMat Martineau __unpack_control(chan, skb); 6712b76bbd66SMat Martineau 67130a708f8fSGustavo F. Padovan len = skb->len; 67140a708f8fSGustavo F. Padovan 67150a708f8fSGustavo F. Padovan /* 67160a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here. 67170a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery 6718cec8ab6eSMat Martineau * procedures and ask for retransmission. 67190a708f8fSGustavo F. Padovan */ 672047d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 67210a708f8fSGustavo F. Padovan goto drop; 67220a708f8fSGustavo F. Padovan 6723cec8ab6eSMat Martineau if (!control->sframe && control->sar == L2CAP_SAR_START) 672403a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 67250a708f8fSGustavo F. Padovan 672647d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 672703a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 67280a708f8fSGustavo F. Padovan 672947d1ec61SGustavo F. Padovan if (len > chan->mps) { 67305e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 67310a708f8fSGustavo F. Padovan goto drop; 67320a708f8fSGustavo F. Padovan } 67330a708f8fSGustavo F. Padovan 6734cec8ab6eSMat Martineau if (!control->sframe) { 6735cec8ab6eSMat Martineau int err; 67360a708f8fSGustavo F. Padovan 6737cec8ab6eSMat Martineau BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d", 6738cec8ab6eSMat Martineau control->sar, control->reqseq, control->final, 6739cec8ab6eSMat Martineau control->txseq); 6740836be934SAndrei Emeltchenko 6741cec8ab6eSMat Martineau /* Validate F-bit - F=0 always valid, F=1 only 6742cec8ab6eSMat Martineau * valid in TX WAIT_F 6743cec8ab6eSMat Martineau */ 6744cec8ab6eSMat Martineau if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F) 67450a708f8fSGustavo F. Padovan goto drop; 67460a708f8fSGustavo F. Padovan 6747cec8ab6eSMat Martineau if (chan->mode != L2CAP_MODE_STREAMING) { 6748cec8ab6eSMat Martineau event = L2CAP_EV_RECV_IFRAME; 6749cec8ab6eSMat Martineau err = l2cap_rx(chan, control, skb, event); 67500a708f8fSGustavo F. Padovan } else { 6751cec8ab6eSMat Martineau err = l2cap_stream_rx(chan, control, skb); 6752cec8ab6eSMat Martineau } 6753cec8ab6eSMat Martineau 6754cec8ab6eSMat Martineau if (err) 67555e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6756cec8ab6eSMat Martineau } else { 6757cec8ab6eSMat Martineau const u8 rx_func_to_event[4] = { 6758cec8ab6eSMat Martineau L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ, 6759cec8ab6eSMat Martineau L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ 6760cec8ab6eSMat Martineau }; 6761cec8ab6eSMat Martineau 6762cec8ab6eSMat Martineau /* Only I-frames are expected in streaming mode */ 6763cec8ab6eSMat Martineau if (chan->mode == L2CAP_MODE_STREAMING) 6764cec8ab6eSMat Martineau goto drop; 6765cec8ab6eSMat Martineau 6766cec8ab6eSMat Martineau BT_DBG("sframe reqseq %d, final %d, poll %d, super %d", 6767cec8ab6eSMat Martineau control->reqseq, control->final, control->poll, 6768cec8ab6eSMat Martineau control->super); 6769cec8ab6eSMat Martineau 67700a708f8fSGustavo F. Padovan if (len != 0) { 67711bb166e6SAndrei Emeltchenko BT_ERR("Trailing bytes: %d in sframe", len); 67725e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 67730a708f8fSGustavo F. Padovan goto drop; 67740a708f8fSGustavo F. Padovan } 67750a708f8fSGustavo F. Padovan 6776cec8ab6eSMat Martineau /* Validate F and P bits */ 6777cec8ab6eSMat Martineau if (control->final && (control->poll || 6778cec8ab6eSMat Martineau chan->tx_state != L2CAP_TX_STATE_WAIT_F)) 6779cec8ab6eSMat Martineau goto drop; 6780cec8ab6eSMat Martineau 6781cec8ab6eSMat Martineau event = rx_func_to_event[control->super]; 6782cec8ab6eSMat Martineau if (l2cap_rx(chan, control, skb, event)) 67835e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 67840a708f8fSGustavo F. Padovan } 67850a708f8fSGustavo F. Padovan 67860a708f8fSGustavo F. Padovan return 0; 67870a708f8fSGustavo F. Padovan 67880a708f8fSGustavo F. Padovan drop: 67890a708f8fSGustavo F. Padovan kfree_skb(skb); 67900a708f8fSGustavo F. Padovan return 0; 67910a708f8fSGustavo F. Padovan } 67920a708f8fSGustavo F. Padovan 6793b1c325c2SJohan Hedberg static void l2cap_chan_le_send_credits(struct l2cap_chan *chan) 6794b1c325c2SJohan Hedberg { 6795b1c325c2SJohan Hedberg struct l2cap_conn *conn = chan->conn; 6796b1c325c2SJohan Hedberg struct l2cap_le_credits pkt; 6797b1c325c2SJohan Hedberg u16 return_credits; 6798b1c325c2SJohan Hedberg 6799b1c325c2SJohan Hedberg /* We return more credits to the sender only after the amount of 6800b1c325c2SJohan Hedberg * credits falls below half of the initial amount. 6801b1c325c2SJohan Hedberg */ 6802b1c325c2SJohan Hedberg if (chan->rx_credits >= (L2CAP_LE_MAX_CREDITS + 1) / 2) 6803b1c325c2SJohan Hedberg return; 6804b1c325c2SJohan Hedberg 6805b1c325c2SJohan Hedberg return_credits = L2CAP_LE_MAX_CREDITS - chan->rx_credits; 6806b1c325c2SJohan Hedberg 6807b1c325c2SJohan Hedberg BT_DBG("chan %p returning %u credits to sender", chan, return_credits); 6808b1c325c2SJohan Hedberg 6809b1c325c2SJohan Hedberg chan->rx_credits += return_credits; 6810b1c325c2SJohan Hedberg 6811b1c325c2SJohan Hedberg pkt.cid = cpu_to_le16(chan->scid); 6812b1c325c2SJohan Hedberg pkt.credits = cpu_to_le16(return_credits); 6813b1c325c2SJohan Hedberg 6814b1c325c2SJohan Hedberg chan->ident = l2cap_get_ident(conn); 6815b1c325c2SJohan Hedberg 6816b1c325c2SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt); 6817b1c325c2SJohan Hedberg } 6818b1c325c2SJohan Hedberg 6819fad5fc89SJohan Hedberg static int l2cap_le_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 6820fad5fc89SJohan Hedberg { 6821*aac23bf6SJohan Hedberg int err; 6822fad5fc89SJohan Hedberg 6823*aac23bf6SJohan Hedberg if (!chan->rx_credits) { 6824*aac23bf6SJohan Hedberg BT_ERR("No credits to receive LE L2CAP data"); 6825fad5fc89SJohan Hedberg return -ENOBUFS; 6826*aac23bf6SJohan Hedberg } 6827*aac23bf6SJohan Hedberg 6828*aac23bf6SJohan Hedberg if (chan->imtu < skb->len) { 6829*aac23bf6SJohan Hedberg BT_ERR("Too big LE L2CAP PDU"); 6830*aac23bf6SJohan Hedberg return -ENOBUFS; 6831*aac23bf6SJohan Hedberg } 6832fad5fc89SJohan Hedberg 6833fad5fc89SJohan Hedberg chan->rx_credits--; 6834fad5fc89SJohan Hedberg BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits); 6835fad5fc89SJohan Hedberg 6836fad5fc89SJohan Hedberg l2cap_chan_le_send_credits(chan); 6837fad5fc89SJohan Hedberg 6838*aac23bf6SJohan Hedberg err = 0; 6839*aac23bf6SJohan Hedberg 6840*aac23bf6SJohan Hedberg if (!chan->sdu) { 6841*aac23bf6SJohan Hedberg u16 sdu_len; 6842*aac23bf6SJohan Hedberg 6843*aac23bf6SJohan Hedberg sdu_len = get_unaligned_le16(skb->data); 6844*aac23bf6SJohan Hedberg skb_pull(skb, L2CAP_SDULEN_SIZE); 6845*aac23bf6SJohan Hedberg 6846*aac23bf6SJohan Hedberg BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u", 6847*aac23bf6SJohan Hedberg sdu_len, skb->len, chan->imtu); 6848*aac23bf6SJohan Hedberg 6849*aac23bf6SJohan Hedberg if (sdu_len > chan->imtu) { 6850*aac23bf6SJohan Hedberg BT_ERR("Too big LE L2CAP SDU length received"); 6851*aac23bf6SJohan Hedberg err = -EMSGSIZE; 6852*aac23bf6SJohan Hedberg goto failed; 6853*aac23bf6SJohan Hedberg } 6854*aac23bf6SJohan Hedberg 6855*aac23bf6SJohan Hedberg if (skb->len > sdu_len) { 6856*aac23bf6SJohan Hedberg BT_ERR("Too much LE L2CAP data received"); 6857*aac23bf6SJohan Hedberg err = -EINVAL; 6858*aac23bf6SJohan Hedberg goto failed; 6859*aac23bf6SJohan Hedberg } 6860*aac23bf6SJohan Hedberg 6861*aac23bf6SJohan Hedberg if (skb->len == sdu_len) 6862fad5fc89SJohan Hedberg return chan->ops->recv(chan, skb); 6863*aac23bf6SJohan Hedberg 6864*aac23bf6SJohan Hedberg chan->sdu = skb; 6865*aac23bf6SJohan Hedberg chan->sdu_len = sdu_len; 6866*aac23bf6SJohan Hedberg chan->sdu_last_frag = skb; 6867*aac23bf6SJohan Hedberg 6868*aac23bf6SJohan Hedberg return 0; 6869*aac23bf6SJohan Hedberg } 6870*aac23bf6SJohan Hedberg 6871*aac23bf6SJohan Hedberg BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u", 6872*aac23bf6SJohan Hedberg chan->sdu->len, skb->len, chan->sdu_len); 6873*aac23bf6SJohan Hedberg 6874*aac23bf6SJohan Hedberg if (chan->sdu->len + skb->len > chan->sdu_len) { 6875*aac23bf6SJohan Hedberg BT_ERR("Too much LE L2CAP data received"); 6876*aac23bf6SJohan Hedberg err = -EINVAL; 6877*aac23bf6SJohan Hedberg goto failed; 6878*aac23bf6SJohan Hedberg } 6879*aac23bf6SJohan Hedberg 6880*aac23bf6SJohan Hedberg append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag); 6881*aac23bf6SJohan Hedberg skb = NULL; 6882*aac23bf6SJohan Hedberg 6883*aac23bf6SJohan Hedberg if (chan->sdu->len == chan->sdu_len) { 6884*aac23bf6SJohan Hedberg err = chan->ops->recv(chan, chan->sdu); 6885*aac23bf6SJohan Hedberg if (!err) { 6886*aac23bf6SJohan Hedberg chan->sdu = NULL; 6887*aac23bf6SJohan Hedberg chan->sdu_last_frag = NULL; 6888*aac23bf6SJohan Hedberg chan->sdu_len = 0; 6889*aac23bf6SJohan Hedberg } 6890*aac23bf6SJohan Hedberg } 6891*aac23bf6SJohan Hedberg 6892*aac23bf6SJohan Hedberg failed: 6893*aac23bf6SJohan Hedberg if (err) { 6894*aac23bf6SJohan Hedberg kfree_skb(skb); 6895*aac23bf6SJohan Hedberg kfree_skb(chan->sdu); 6896*aac23bf6SJohan Hedberg chan->sdu = NULL; 6897*aac23bf6SJohan Hedberg chan->sdu_last_frag = NULL; 6898*aac23bf6SJohan Hedberg chan->sdu_len = 0; 6899*aac23bf6SJohan Hedberg } 6900*aac23bf6SJohan Hedberg 6901*aac23bf6SJohan Hedberg /* We can't return an error here since we took care of the skb 6902*aac23bf6SJohan Hedberg * freeing internally. An error return would cause the caller to 6903*aac23bf6SJohan Hedberg * do a double-free of the skb. 6904*aac23bf6SJohan Hedberg */ 6905*aac23bf6SJohan Hedberg return 0; 6906fad5fc89SJohan Hedberg } 6907fad5fc89SJohan Hedberg 690813ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid, 690913ca56e0SAndrei Emeltchenko struct sk_buff *skb) 69100a708f8fSGustavo F. Padovan { 691148454079SGustavo F. Padovan struct l2cap_chan *chan; 69120a708f8fSGustavo F. Padovan 6913baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 691448454079SGustavo F. Padovan if (!chan) { 691597e8e89dSAndrei Emeltchenko if (cid == L2CAP_CID_A2MP) { 691697e8e89dSAndrei Emeltchenko chan = a2mp_channel_create(conn, skb); 691797e8e89dSAndrei Emeltchenko if (!chan) { 691897e8e89dSAndrei Emeltchenko kfree_skb(skb); 691913ca56e0SAndrei Emeltchenko return; 692097e8e89dSAndrei Emeltchenko } 692197e8e89dSAndrei Emeltchenko 692297e8e89dSAndrei Emeltchenko l2cap_chan_lock(chan); 692397e8e89dSAndrei Emeltchenko } else { 69240a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid); 69256be36555SAndrei Emeltchenko /* Drop packet and return */ 69263379013bSDan Carpenter kfree_skb(skb); 692713ca56e0SAndrei Emeltchenko return; 69280a708f8fSGustavo F. Padovan } 692997e8e89dSAndrei Emeltchenko } 69300a708f8fSGustavo F. Padovan 693149208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len); 69320a708f8fSGustavo F. Padovan 693389bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 69340a708f8fSGustavo F. Padovan goto drop; 69350a708f8fSGustavo F. Padovan 69360c1bc5c6SGustavo F. Padovan switch (chan->mode) { 693738319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 6938fad5fc89SJohan Hedberg if (l2cap_le_data_rcv(chan, skb) < 0) 6939fad5fc89SJohan Hedberg goto drop; 6940fad5fc89SJohan Hedberg 6941fad5fc89SJohan Hedberg goto done; 6942fad5fc89SJohan Hedberg 69430a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 69440a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here 69450a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable. 69460a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't 69470a708f8fSGustavo F. Padovan * provide flow control mechanism. */ 69480a708f8fSGustavo F. Padovan 69490c1bc5c6SGustavo F. Padovan if (chan->imtu < skb->len) 69500a708f8fSGustavo F. Padovan goto drop; 69510a708f8fSGustavo F. Padovan 695280b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 69530a708f8fSGustavo F. Padovan goto done; 69540a708f8fSGustavo F. Padovan break; 69550a708f8fSGustavo F. Padovan 69560a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 69570a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 6958cec8ab6eSMat Martineau l2cap_data_rcv(chan, skb); 69590a708f8fSGustavo F. Padovan goto done; 69600a708f8fSGustavo F. Padovan 69610a708f8fSGustavo F. Padovan default: 69620c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); 69630a708f8fSGustavo F. Padovan break; 69640a708f8fSGustavo F. Padovan } 69650a708f8fSGustavo F. Padovan 69660a708f8fSGustavo F. Padovan drop: 69670a708f8fSGustavo F. Padovan kfree_skb(skb); 69680a708f8fSGustavo F. Padovan 69690a708f8fSGustavo F. Padovan done: 69706be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 69710a708f8fSGustavo F. Padovan } 69720a708f8fSGustavo F. Padovan 697384104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, 697484104b24SAndrei Emeltchenko struct sk_buff *skb) 69750a708f8fSGustavo F. Padovan { 6976ae4fd2d3SMarcel Holtmann struct hci_conn *hcon = conn->hcon; 697723691d75SGustavo F. Padovan struct l2cap_chan *chan; 69780a708f8fSGustavo F. Padovan 6979ae4fd2d3SMarcel Holtmann if (hcon->type != ACL_LINK) 6980ae4fd2d3SMarcel Holtmann goto drop; 6981ae4fd2d3SMarcel Holtmann 6982bf20fd4eSJohan Hedberg chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst, 6983bf20fd4eSJohan Hedberg ACL_LINK); 698423691d75SGustavo F. Padovan if (!chan) 69850a708f8fSGustavo F. Padovan goto drop; 69860a708f8fSGustavo F. Padovan 69875b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 69880a708f8fSGustavo F. Padovan 698989bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 69900a708f8fSGustavo F. Padovan goto drop; 69910a708f8fSGustavo F. Padovan 6992e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 69930a708f8fSGustavo F. Padovan goto drop; 69940a708f8fSGustavo F. Padovan 69952edf870dSMarcel Holtmann /* Store remote BD_ADDR and PSM for msg_name */ 699606ae3314SMarcel Holtmann bacpy(&bt_cb(skb)->bdaddr, &hcon->dst); 69972edf870dSMarcel Holtmann bt_cb(skb)->psm = psm; 69982edf870dSMarcel Holtmann 699980b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 700084104b24SAndrei Emeltchenko return; 70010a708f8fSGustavo F. Padovan 70020a708f8fSGustavo F. Padovan drop: 70030a708f8fSGustavo F. Padovan kfree_skb(skb); 70040a708f8fSGustavo F. Padovan } 70050a708f8fSGustavo F. Padovan 700672f78356SMarcel Holtmann static void l2cap_att_channel(struct l2cap_conn *conn, 7007d9b88702SAndrei Emeltchenko struct sk_buff *skb) 70089f69bda6SGustavo F. Padovan { 7009b99707d7SMarcel Holtmann struct hci_conn *hcon = conn->hcon; 701023691d75SGustavo F. Padovan struct l2cap_chan *chan; 70119f69bda6SGustavo F. Padovan 7012b99707d7SMarcel Holtmann if (hcon->type != LE_LINK) 7013b99707d7SMarcel Holtmann goto drop; 7014b99707d7SMarcel Holtmann 7015af1c0134SJohan Hedberg chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT, 701606ae3314SMarcel Holtmann &hcon->src, &hcon->dst); 701723691d75SGustavo F. Padovan if (!chan) 70189f69bda6SGustavo F. Padovan goto drop; 70199f69bda6SGustavo F. Padovan 70205b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 70219f69bda6SGustavo F. Padovan 7022cc8dba2bSMarcel Holtmann if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, hcon->dst_type)) 7023cc8dba2bSMarcel Holtmann goto drop; 7024cc8dba2bSMarcel Holtmann 7025e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 70269f69bda6SGustavo F. Padovan goto drop; 70279f69bda6SGustavo F. Padovan 702880b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 70296810fca7SAndrei Emeltchenko return; 70309f69bda6SGustavo F. Padovan 70319f69bda6SGustavo F. Padovan drop: 70329f69bda6SGustavo F. Padovan kfree_skb(skb); 70339f69bda6SGustavo F. Padovan } 70349f69bda6SGustavo F. Padovan 70350a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) 70360a708f8fSGustavo F. Padovan { 70370a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data; 70380a708f8fSGustavo F. Padovan u16 cid, len; 70390a708f8fSGustavo F. Padovan __le16 psm; 70400a708f8fSGustavo F. Padovan 70410a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE); 70420a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid); 70430a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len); 70440a708f8fSGustavo F. Padovan 70450a708f8fSGustavo F. Padovan if (len != skb->len) { 70460a708f8fSGustavo F. Padovan kfree_skb(skb); 70470a708f8fSGustavo F. Padovan return; 70480a708f8fSGustavo F. Padovan } 70490a708f8fSGustavo F. Padovan 70500a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid); 70510a708f8fSGustavo F. Padovan 70520a708f8fSGustavo F. Padovan switch (cid) { 70530a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING: 70540a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb); 70550a708f8fSGustavo F. Padovan break; 70560a708f8fSGustavo F. Padovan 70570a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS: 7058097db76cSAndrei Emeltchenko psm = get_unaligned((__le16 *) skb->data); 70590181a70fSAndrei Emeltchenko skb_pull(skb, L2CAP_PSMLEN_SIZE); 70600a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb); 70610a708f8fSGustavo F. Padovan break; 70620a708f8fSGustavo F. Padovan 7063073d1cf3SJohan Hedberg case L2CAP_CID_ATT: 706472f78356SMarcel Holtmann l2cap_att_channel(conn, skb); 70659f69bda6SGustavo F. Padovan break; 70669f69bda6SGustavo F. Padovan 7067a2877629SMarcel Holtmann case L2CAP_CID_LE_SIGNALING: 7068a2877629SMarcel Holtmann l2cap_le_sig_channel(conn, skb); 7069a2877629SMarcel Holtmann break; 7070a2877629SMarcel Holtmann 7071b501d6a1SAnderson Briglia case L2CAP_CID_SMP: 7072b501d6a1SAnderson Briglia if (smp_sig_channel(conn, skb)) 7073b501d6a1SAnderson Briglia l2cap_conn_del(conn->hcon, EACCES); 7074b501d6a1SAnderson Briglia break; 7075b501d6a1SAnderson Briglia 70760a708f8fSGustavo F. Padovan default: 70770a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb); 70780a708f8fSGustavo F. Padovan break; 70790a708f8fSGustavo F. Padovan } 70800a708f8fSGustavo F. Padovan } 70810a708f8fSGustavo F. Padovan 70820a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */ 70830a708f8fSGustavo F. Padovan 7084686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) 70850a708f8fSGustavo F. Padovan { 70860a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0; 708723691d75SGustavo F. Padovan struct l2cap_chan *c; 70880a708f8fSGustavo F. Padovan 70896ed93dc6SAndrei Emeltchenko BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr); 70900a708f8fSGustavo F. Padovan 70910a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */ 709223691d75SGustavo F. Padovan read_lock(&chan_list_lock); 709323691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 709489bc500eSGustavo F. Padovan if (c->state != BT_LISTEN) 70950a708f8fSGustavo F. Padovan continue; 70960a708f8fSGustavo F. Padovan 70977eafc59eSMarcel Holtmann if (!bacmp(&c->src, &hdev->bdaddr)) { 70980a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT; 709943bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 71000a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER; 71010a708f8fSGustavo F. Padovan exact++; 71027eafc59eSMarcel Holtmann } else if (!bacmp(&c->src, BDADDR_ANY)) { 71030a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT; 710443bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 71050a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER; 71060a708f8fSGustavo F. Padovan } 71070a708f8fSGustavo F. Padovan } 710823691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 71090a708f8fSGustavo F. Padovan 71100a708f8fSGustavo F. Padovan return exact ? lm1 : lm2; 71110a708f8fSGustavo F. Padovan } 71120a708f8fSGustavo F. Padovan 71139e664631SAndrei Emeltchenko void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) 71140a708f8fSGustavo F. Padovan { 71150a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 71160a708f8fSGustavo F. Padovan 71176ed93dc6SAndrei Emeltchenko BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status); 71180a708f8fSGustavo F. Padovan 71190a708f8fSGustavo F. Padovan if (!status) { 7120baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon); 71210a708f8fSGustavo F. Padovan if (conn) 71220a708f8fSGustavo F. Padovan l2cap_conn_ready(conn); 7123ba6fc317SAndrei Emeltchenko } else { 7124e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status)); 7125ba6fc317SAndrei Emeltchenko } 71260a708f8fSGustavo F. Padovan } 71270a708f8fSGustavo F. Padovan 7128686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon) 71290a708f8fSGustavo F. Padovan { 71300a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 71310a708f8fSGustavo F. Padovan 71320a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon); 71330a708f8fSGustavo F. Padovan 7134686ebf28SUlisses Furquim if (!conn) 71359f5a0d7bSAndrei Emeltchenko return HCI_ERROR_REMOTE_USER_TERM; 71360a708f8fSGustavo F. Padovan return conn->disc_reason; 71370a708f8fSGustavo F. Padovan } 71380a708f8fSGustavo F. Padovan 71399e664631SAndrei Emeltchenko void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) 71400a708f8fSGustavo F. Padovan { 71410a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason); 71420a708f8fSGustavo F. Padovan 7143e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason)); 71440a708f8fSGustavo F. Padovan } 71450a708f8fSGustavo F. Padovan 71464343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) 71470a708f8fSGustavo F. Padovan { 7148715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 71490a708f8fSGustavo F. Padovan return; 71500a708f8fSGustavo F. Padovan 71510a708f8fSGustavo F. Padovan if (encrypt == 0x00) { 71524343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) { 7153ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); 71544343478fSGustavo F. Padovan } else if (chan->sec_level == BT_SECURITY_HIGH) 71550f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED); 71560a708f8fSGustavo F. Padovan } else { 71574343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) 7158c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 71590a708f8fSGustavo F. Padovan } 71600a708f8fSGustavo F. Padovan } 71610a708f8fSGustavo F. Padovan 7162686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) 71630a708f8fSGustavo F. Padovan { 71640a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 716548454079SGustavo F. Padovan struct l2cap_chan *chan; 71660a708f8fSGustavo F. Padovan 71670a708f8fSGustavo F. Padovan if (!conn) 71680a708f8fSGustavo F. Padovan return 0; 71690a708f8fSGustavo F. Padovan 717089d8b407SAndrei Emeltchenko BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt); 71710a708f8fSGustavo F. Padovan 7172160dc6acSVinicius Costa Gomes if (hcon->type == LE_LINK) { 717335d4adccSHemant Gupta if (!status && encrypt) 7174160dc6acSVinicius Costa Gomes smp_distribute_keys(conn, 0); 717517cd3f37SUlisses Furquim cancel_delayed_work(&conn->security_timer); 7176160dc6acSVinicius Costa Gomes } 7177160dc6acSVinicius Costa Gomes 71783df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 71790a708f8fSGustavo F. Padovan 71803df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 71816be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 71820a708f8fSGustavo F. Padovan 718389d8b407SAndrei Emeltchenko BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, 718489d8b407SAndrei Emeltchenko state_to_string(chan->state)); 7185f1cb9af5SVinicius Costa Gomes 718678eb2f98SAndrei Emeltchenko if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { 718778eb2f98SAndrei Emeltchenko l2cap_chan_unlock(chan); 718878eb2f98SAndrei Emeltchenko continue; 718978eb2f98SAndrei Emeltchenko } 719078eb2f98SAndrei Emeltchenko 7191073d1cf3SJohan Hedberg if (chan->scid == L2CAP_CID_ATT) { 7192f1cb9af5SVinicius Costa Gomes if (!status && encrypt) { 7193f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level; 7194cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 7195f1cb9af5SVinicius Costa Gomes } 7196f1cb9af5SVinicius Costa Gomes 71976be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 7198f1cb9af5SVinicius Costa Gomes continue; 7199f1cb9af5SVinicius Costa Gomes } 7200f1cb9af5SVinicius Costa Gomes 720196eff46eSAndrei Emeltchenko if (!__l2cap_no_conn_pending(chan)) { 72026be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 72030a708f8fSGustavo F. Padovan continue; 72040a708f8fSGustavo F. Padovan } 72050a708f8fSGustavo F. Padovan 720689bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED || 720789bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) { 7208d97c899bSMarcel Holtmann chan->ops->resume(chan); 72094343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt); 72106be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 72110a708f8fSGustavo F. Padovan continue; 72120a708f8fSGustavo F. Padovan } 72130a708f8fSGustavo F. Padovan 721489bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 72156d3c15daSJohan Hedberg if (!status) 721693c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 72176d3c15daSJohan Hedberg else 7218ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 721989bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 72200a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 7221df3c3931SJohan Hedberg __u16 res, stat; 72220a708f8fSGustavo F. Padovan 72230a708f8fSGustavo F. Padovan if (!status) { 7224bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 7225df3c3931SJohan Hedberg res = L2CAP_CR_PEND; 7226df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND; 72272dc4e510SGustavo Padovan chan->ops->defer(chan); 7228df3c3931SJohan Hedberg } else { 7229acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 7230df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS; 7231df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 7232df3c3931SJohan Hedberg } 72330a708f8fSGustavo F. Padovan } else { 7234acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_DISCONN); 7235ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 7236df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK; 7237df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 72380a708f8fSGustavo F. Padovan } 72390a708f8fSGustavo F. Padovan 7240fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 7241fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 7242df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res); 7243df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat); 7244fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 7245fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 72462d369359SMat Martineau 72472d369359SMat Martineau if (!test_bit(CONF_REQ_SENT, &chan->conf_state) && 72482d369359SMat Martineau res == L2CAP_CR_SUCCESS) { 72492d369359SMat Martineau char buf[128]; 72502d369359SMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 72512d369359SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), 72522d369359SMat Martineau L2CAP_CONF_REQ, 72532d369359SMat Martineau l2cap_build_conf_req(chan, buf), 72542d369359SMat Martineau buf); 72552d369359SMat Martineau chan->num_conf_req++; 72562d369359SMat Martineau } 72570a708f8fSGustavo F. Padovan } 72580a708f8fSGustavo F. Padovan 72596be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 72600a708f8fSGustavo F. Padovan } 72610a708f8fSGustavo F. Padovan 72623df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 72630a708f8fSGustavo F. Padovan 72640a708f8fSGustavo F. Padovan return 0; 72650a708f8fSGustavo F. Padovan } 72660a708f8fSGustavo F. Padovan 7267686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) 72680a708f8fSGustavo F. Padovan { 72690a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 7270d73a0988SAndrei Emeltchenko struct l2cap_hdr *hdr; 7271d73a0988SAndrei Emeltchenko int len; 72720a708f8fSGustavo F. Padovan 72731d13a254SAndrei Emeltchenko /* For AMP controller do not create l2cap conn */ 72741d13a254SAndrei Emeltchenko if (!conn && hcon->hdev->dev_type != HCI_BREDR) 72751d13a254SAndrei Emeltchenko goto drop; 72760a708f8fSGustavo F. Padovan 72770a708f8fSGustavo F. Padovan if (!conn) 7278baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon); 72790a708f8fSGustavo F. Padovan 72800a708f8fSGustavo F. Padovan if (!conn) 72810a708f8fSGustavo F. Padovan goto drop; 72820a708f8fSGustavo F. Padovan 72830a708f8fSGustavo F. Padovan BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); 72840a708f8fSGustavo F. Padovan 7285d73a0988SAndrei Emeltchenko switch (flags) { 7286d73a0988SAndrei Emeltchenko case ACL_START: 7287d73a0988SAndrei Emeltchenko case ACL_START_NO_FLUSH: 7288d73a0988SAndrei Emeltchenko case ACL_COMPLETE: 72890a708f8fSGustavo F. Padovan if (conn->rx_len) { 72900a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len); 72910a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 72920a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 72930a708f8fSGustavo F. Padovan conn->rx_len = 0; 72940a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 72950a708f8fSGustavo F. Padovan } 72960a708f8fSGustavo F. Padovan 72970a708f8fSGustavo F. Padovan /* Start fragment always begin with Basic L2CAP header */ 72980a708f8fSGustavo F. Padovan if (skb->len < L2CAP_HDR_SIZE) { 72990a708f8fSGustavo F. Padovan BT_ERR("Frame is too short (len %d)", skb->len); 73000a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 73010a708f8fSGustavo F. Padovan goto drop; 73020a708f8fSGustavo F. Padovan } 73030a708f8fSGustavo F. Padovan 73040a708f8fSGustavo F. Padovan hdr = (struct l2cap_hdr *) skb->data; 73050a708f8fSGustavo F. Padovan len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; 73060a708f8fSGustavo F. Padovan 73070a708f8fSGustavo F. Padovan if (len == skb->len) { 73080a708f8fSGustavo F. Padovan /* Complete frame received */ 73090a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb); 73100a708f8fSGustavo F. Padovan return 0; 73110a708f8fSGustavo F. Padovan } 73120a708f8fSGustavo F. Padovan 73130a708f8fSGustavo F. Padovan BT_DBG("Start: total len %d, frag len %d", len, skb->len); 73140a708f8fSGustavo F. Padovan 73150a708f8fSGustavo F. Padovan if (skb->len > len) { 73160a708f8fSGustavo F. Padovan BT_ERR("Frame is too long (len %d, expected len %d)", 73170a708f8fSGustavo F. Padovan skb->len, len); 73180a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 73190a708f8fSGustavo F. Padovan goto drop; 73200a708f8fSGustavo F. Padovan } 73210a708f8fSGustavo F. Padovan 73220a708f8fSGustavo F. Padovan /* Allocate skb for the complete frame (with header) */ 73238bcde1f2SGustavo Padovan conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL); 73240a708f8fSGustavo F. Padovan if (!conn->rx_skb) 73250a708f8fSGustavo F. Padovan goto drop; 73260a708f8fSGustavo F. Padovan 73270a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 73280a708f8fSGustavo F. Padovan skb->len); 73290a708f8fSGustavo F. Padovan conn->rx_len = len - skb->len; 7330d73a0988SAndrei Emeltchenko break; 7331d73a0988SAndrei Emeltchenko 7332d73a0988SAndrei Emeltchenko case ACL_CONT: 73330a708f8fSGustavo F. Padovan BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); 73340a708f8fSGustavo F. Padovan 73350a708f8fSGustavo F. Padovan if (!conn->rx_len) { 73360a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len); 73370a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 73380a708f8fSGustavo F. Padovan goto drop; 73390a708f8fSGustavo F. Padovan } 73400a708f8fSGustavo F. Padovan 73410a708f8fSGustavo F. Padovan if (skb->len > conn->rx_len) { 73420a708f8fSGustavo F. Padovan BT_ERR("Fragment is too long (len %d, expected %d)", 73430a708f8fSGustavo F. Padovan skb->len, conn->rx_len); 73440a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 73450a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 73460a708f8fSGustavo F. Padovan conn->rx_len = 0; 73470a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 73480a708f8fSGustavo F. Padovan goto drop; 73490a708f8fSGustavo F. Padovan } 73500a708f8fSGustavo F. Padovan 73510a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 73520a708f8fSGustavo F. Padovan skb->len); 73530a708f8fSGustavo F. Padovan conn->rx_len -= skb->len; 73540a708f8fSGustavo F. Padovan 73550a708f8fSGustavo F. Padovan if (!conn->rx_len) { 7356c4e5bafaSJohan Hedberg /* Complete frame received. l2cap_recv_frame 7357c4e5bafaSJohan Hedberg * takes ownership of the skb so set the global 7358c4e5bafaSJohan Hedberg * rx_skb pointer to NULL first. 7359c4e5bafaSJohan Hedberg */ 7360c4e5bafaSJohan Hedberg struct sk_buff *rx_skb = conn->rx_skb; 73610a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 7362c4e5bafaSJohan Hedberg l2cap_recv_frame(conn, rx_skb); 73630a708f8fSGustavo F. Padovan } 7364d73a0988SAndrei Emeltchenko break; 73650a708f8fSGustavo F. Padovan } 73660a708f8fSGustavo F. Padovan 73670a708f8fSGustavo F. Padovan drop: 73680a708f8fSGustavo F. Padovan kfree_skb(skb); 73690a708f8fSGustavo F. Padovan return 0; 73700a708f8fSGustavo F. Padovan } 73710a708f8fSGustavo F. Padovan 73720a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p) 73730a708f8fSGustavo F. Padovan { 737423691d75SGustavo F. Padovan struct l2cap_chan *c; 73750a708f8fSGustavo F. Padovan 7376333055f2SGustavo F. Padovan read_lock(&chan_list_lock); 73770a708f8fSGustavo F. Padovan 737823691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 7379fcb73338SAndrei Emeltchenko seq_printf(f, "%pMR %pMR %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", 73807eafc59eSMarcel Holtmann &c->src, &c->dst, 738189bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm), 738223691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu, 738323691d75SGustavo F. Padovan c->sec_level, c->mode); 73840a708f8fSGustavo F. Padovan } 73850a708f8fSGustavo F. Padovan 7386333055f2SGustavo F. Padovan read_unlock(&chan_list_lock); 73870a708f8fSGustavo F. Padovan 73880a708f8fSGustavo F. Padovan return 0; 73890a708f8fSGustavo F. Padovan } 73900a708f8fSGustavo F. Padovan 73910a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file) 73920a708f8fSGustavo F. Padovan { 73930a708f8fSGustavo F. Padovan return single_open(file, l2cap_debugfs_show, inode->i_private); 73940a708f8fSGustavo F. Padovan } 73950a708f8fSGustavo F. Padovan 73960a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = { 73970a708f8fSGustavo F. Padovan .open = l2cap_debugfs_open, 73980a708f8fSGustavo F. Padovan .read = seq_read, 73990a708f8fSGustavo F. Padovan .llseek = seq_lseek, 74000a708f8fSGustavo F. Padovan .release = single_release, 74010a708f8fSGustavo F. Padovan }; 74020a708f8fSGustavo F. Padovan 74030a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs; 74040a708f8fSGustavo F. Padovan 740564274518SGustavo F. Padovan int __init l2cap_init(void) 74060a708f8fSGustavo F. Padovan { 74070a708f8fSGustavo F. Padovan int err; 74080a708f8fSGustavo F. Padovan 7409bb58f747SGustavo F. Padovan err = l2cap_init_sockets(); 74100a708f8fSGustavo F. Padovan if (err < 0) 74110a708f8fSGustavo F. Padovan return err; 74120a708f8fSGustavo F. Padovan 74131120e4bfSMarcel Holtmann if (IS_ERR_OR_NULL(bt_debugfs)) 74141120e4bfSMarcel Holtmann return 0; 74151120e4bfSMarcel Holtmann 74162d792818SGustavo Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, 74172d792818SGustavo Padovan NULL, &l2cap_debugfs_fops); 74180a708f8fSGustavo F. Padovan 74190a708f8fSGustavo F. Padovan return 0; 74200a708f8fSGustavo F. Padovan } 74210a708f8fSGustavo F. Padovan 742264274518SGustavo F. Padovan void l2cap_exit(void) 74230a708f8fSGustavo F. Padovan { 74240a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs); 7425bb58f747SGustavo F. Padovan l2cap_cleanup_sockets(); 74260a708f8fSGustavo F. Padovan } 74270a708f8fSGustavo F. Padovan 74280a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644); 74290a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); 7430