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: 61038319713SJohan Hedberg break; 61138319713SJohan Hedberg 612ee556f66SGustavo Padovan case L2CAP_MODE_ERTM: 6131a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 6141a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 6151a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 6160a708f8fSGustavo F. Padovan 617f1c6775bSGustavo F. Padovan skb_queue_purge(&chan->srej_q); 6180a708f8fSGustavo F. Padovan 6193c588192SMat Martineau l2cap_seq_list_free(&chan->srej_list); 6203c588192SMat Martineau l2cap_seq_list_free(&chan->retrans_list); 621ee556f66SGustavo Padovan 622ee556f66SGustavo Padovan /* fall through */ 623ee556f66SGustavo Padovan 624ee556f66SGustavo Padovan case L2CAP_MODE_STREAMING: 625ee556f66SGustavo Padovan skb_queue_purge(&chan->tx_q); 626ee556f66SGustavo Padovan break; 6270a708f8fSGustavo F. Padovan } 628ee556f66SGustavo Padovan 629ee556f66SGustavo Padovan return; 6300a708f8fSGustavo F. Padovan } 6310a708f8fSGustavo F. Padovan 63227e2d4c8SJohan Hedberg static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan) 63327e2d4c8SJohan Hedberg { 63427e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn; 63527e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 63627e2d4c8SJohan Hedberg u16 result; 63727e2d4c8SJohan Hedberg 63827e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 63927e2d4c8SJohan Hedberg result = L2CAP_CR_AUTHORIZATION; 64027e2d4c8SJohan Hedberg else 64127e2d4c8SJohan Hedberg result = L2CAP_CR_BAD_PSM; 64227e2d4c8SJohan Hedberg 64327e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_DISCONN); 64427e2d4c8SJohan Hedberg 64527e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 64627e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 64727e2d4c8SJohan Hedberg rsp.mps = __constant_cpu_to_le16(L2CAP_LE_DEFAULT_MPS); 6480cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits); 64927e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result); 65027e2d4c8SJohan Hedberg 65127e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), 65227e2d4c8SJohan Hedberg &rsp); 65327e2d4c8SJohan Hedberg } 65427e2d4c8SJohan Hedberg 655791d60f7SJohan Hedberg static void l2cap_chan_connect_reject(struct l2cap_chan *chan) 656791d60f7SJohan Hedberg { 657791d60f7SJohan Hedberg struct l2cap_conn *conn = chan->conn; 658791d60f7SJohan Hedberg struct l2cap_conn_rsp rsp; 659791d60f7SJohan Hedberg u16 result; 660791d60f7SJohan Hedberg 661791d60f7SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 662791d60f7SJohan Hedberg result = L2CAP_CR_SEC_BLOCK; 663791d60f7SJohan Hedberg else 664791d60f7SJohan Hedberg result = L2CAP_CR_BAD_PSM; 665791d60f7SJohan Hedberg 666791d60f7SJohan Hedberg l2cap_state_change(chan, BT_DISCONN); 667791d60f7SJohan Hedberg 668791d60f7SJohan Hedberg rsp.scid = cpu_to_le16(chan->dcid); 669791d60f7SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 670791d60f7SJohan Hedberg rsp.result = cpu_to_le16(result); 671791d60f7SJohan Hedberg rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 672791d60f7SJohan Hedberg 673791d60f7SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); 674791d60f7SJohan Hedberg } 675791d60f7SJohan Hedberg 6760f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason) 6774519de9aSGustavo F. Padovan { 6784519de9aSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 6794519de9aSGustavo F. Padovan 6807eafc59eSMarcel Holtmann BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 6814519de9aSGustavo F. Padovan 68289bc500eSGustavo F. Padovan switch (chan->state) { 6834519de9aSGustavo F. Padovan case BT_LISTEN: 684c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 6854519de9aSGustavo F. Padovan break; 6864519de9aSGustavo F. Padovan 6874519de9aSGustavo F. Padovan case BT_CONNECTED: 6884519de9aSGustavo F. Padovan case BT_CONFIG: 689cea04ce3SJohan Hedberg /* ATT uses L2CAP_CHAN_CONN_ORIENTED so we must also 690cea04ce3SJohan Hedberg * check for chan->psm. 691cea04ce3SJohan Hedberg */ 692cea04ce3SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && chan->psm) { 6938d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 6945e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, reason); 6954519de9aSGustavo F. Padovan } else 6964519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 6974519de9aSGustavo F. Padovan break; 6984519de9aSGustavo F. Padovan 6994519de9aSGustavo F. Padovan case BT_CONNECT2: 700791d60f7SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) { 701791d60f7SJohan Hedberg if (conn->hcon->type == ACL_LINK) 702791d60f7SJohan Hedberg l2cap_chan_connect_reject(chan); 70327e2d4c8SJohan Hedberg else if (conn->hcon->type == LE_LINK) 70427e2d4c8SJohan Hedberg l2cap_chan_le_connect_reject(chan); 7054519de9aSGustavo F. Padovan } 7064519de9aSGustavo F. Padovan 7074519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 7084519de9aSGustavo F. Padovan break; 7094519de9aSGustavo F. Padovan 7104519de9aSGustavo F. Padovan case BT_CONNECT: 7114519de9aSGustavo F. Padovan case BT_DISCONN: 7124519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 7134519de9aSGustavo F. Padovan break; 7144519de9aSGustavo F. Padovan 7154519de9aSGustavo F. Padovan default: 716c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 7174519de9aSGustavo F. Padovan break; 7184519de9aSGustavo F. Padovan } 7194519de9aSGustavo F. Padovan } 7204519de9aSGustavo F. Padovan 7214343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) 7220a708f8fSGustavo F. Padovan { 7236a974b50SMarcel Holtmann switch (chan->chan_type) { 7246a974b50SMarcel Holtmann case L2CAP_CHAN_RAW: 7254343478fSGustavo F. Padovan switch (chan->sec_level) { 7260a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 7270a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING_MITM; 7280a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 7290a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING; 7300a708f8fSGustavo F. Padovan default: 7310a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 7320a708f8fSGustavo F. Padovan } 7336a974b50SMarcel Holtmann break; 7343124b843SMarcel Holtmann case L2CAP_CHAN_CONN_LESS: 7353124b843SMarcel Holtmann if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_3DSP)) { 7363124b843SMarcel Holtmann if (chan->sec_level == BT_SECURITY_LOW) 7373124b843SMarcel Holtmann chan->sec_level = BT_SECURITY_SDP; 7383124b843SMarcel Holtmann } 7393124b843SMarcel Holtmann if (chan->sec_level == BT_SECURITY_HIGH) 7403124b843SMarcel Holtmann return HCI_AT_NO_BONDING_MITM; 7413124b843SMarcel Holtmann else 7423124b843SMarcel Holtmann return HCI_AT_NO_BONDING; 7433124b843SMarcel Holtmann break; 7446a974b50SMarcel Holtmann case L2CAP_CHAN_CONN_ORIENTED: 7456a974b50SMarcel Holtmann if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) { 7464343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_LOW) 7474343478fSGustavo F. Padovan chan->sec_level = BT_SECURITY_SDP; 7480a708f8fSGustavo F. Padovan 7494343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_HIGH) 7500a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING_MITM; 7510a708f8fSGustavo F. Padovan else 7520a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 7536a974b50SMarcel Holtmann } 7546a974b50SMarcel Holtmann /* fall through */ 7556a974b50SMarcel Holtmann default: 7564343478fSGustavo F. Padovan switch (chan->sec_level) { 7570a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 7580a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING_MITM; 7590a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 7600a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING; 7610a708f8fSGustavo F. Padovan default: 7620a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 7630a708f8fSGustavo F. Padovan } 7646a974b50SMarcel Holtmann break; 7650a708f8fSGustavo F. Padovan } 7660a708f8fSGustavo F. Padovan } 7670a708f8fSGustavo F. Padovan 7680a708f8fSGustavo F. Padovan /* Service level security */ 769d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan) 7700a708f8fSGustavo F. Padovan { 7718c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 7720a708f8fSGustavo F. Padovan __u8 auth_type; 7730a708f8fSGustavo F. Padovan 774a17de2feSJohan Hedberg if (conn->hcon->type == LE_LINK) 775a17de2feSJohan Hedberg return smp_conn_security(conn->hcon, chan->sec_level); 776a17de2feSJohan Hedberg 7774343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 7780a708f8fSGustavo F. Padovan 7794343478fSGustavo F. Padovan return hci_conn_security(conn->hcon, chan->sec_level, auth_type); 7800a708f8fSGustavo F. Padovan } 7810a708f8fSGustavo F. Padovan 782b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn) 7830a708f8fSGustavo F. Padovan { 7840a708f8fSGustavo F. Padovan u8 id; 7850a708f8fSGustavo F. Padovan 7860a708f8fSGustavo F. Padovan /* Get next available identificator. 7870a708f8fSGustavo F. Padovan * 1 - 128 are used by kernel. 7880a708f8fSGustavo F. Padovan * 129 - 199 are reserved. 7890a708f8fSGustavo F. Padovan * 200 - 254 are used by utilities like l2ping, etc. 7900a708f8fSGustavo F. Padovan */ 7910a708f8fSGustavo F. Padovan 792333055f2SGustavo F. Padovan spin_lock(&conn->lock); 7930a708f8fSGustavo F. Padovan 7940a708f8fSGustavo F. Padovan if (++conn->tx_ident > 128) 7950a708f8fSGustavo F. Padovan conn->tx_ident = 1; 7960a708f8fSGustavo F. Padovan 7970a708f8fSGustavo F. Padovan id = conn->tx_ident; 7980a708f8fSGustavo F. Padovan 799333055f2SGustavo F. Padovan spin_unlock(&conn->lock); 8000a708f8fSGustavo F. Padovan 8010a708f8fSGustavo F. Padovan return id; 8020a708f8fSGustavo F. Padovan } 8030a708f8fSGustavo F. Padovan 8042d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 8052d792818SGustavo Padovan void *data) 8060a708f8fSGustavo F. Padovan { 8070a708f8fSGustavo F. Padovan struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); 8080a708f8fSGustavo F. Padovan u8 flags; 8090a708f8fSGustavo F. Padovan 8100a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x", code); 8110a708f8fSGustavo F. Padovan 8120a708f8fSGustavo F. Padovan if (!skb) 8130a708f8fSGustavo F. Padovan return; 8140a708f8fSGustavo F. Padovan 8150a708f8fSGustavo F. Padovan if (lmp_no_flush_capable(conn->hcon->hdev)) 8160a708f8fSGustavo F. Padovan flags = ACL_START_NO_FLUSH; 8170a708f8fSGustavo F. Padovan else 8180a708f8fSGustavo F. Padovan flags = ACL_START; 8190a708f8fSGustavo F. Padovan 82014b12d0bSJaikumar Ganesh bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON; 8215e59b791SLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 82214b12d0bSJaikumar Ganesh 82373d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, flags); 8240a708f8fSGustavo F. Padovan } 8250a708f8fSGustavo F. Padovan 82602b0fbb9SMat Martineau static bool __chan_is_moving(struct l2cap_chan *chan) 82702b0fbb9SMat Martineau { 82802b0fbb9SMat Martineau return chan->move_state != L2CAP_MOVE_STABLE && 82902b0fbb9SMat Martineau chan->move_state != L2CAP_MOVE_WAIT_PREPARE; 83002b0fbb9SMat Martineau } 83102b0fbb9SMat Martineau 83273d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) 83373d80debSLuiz Augusto von Dentz { 83473d80debSLuiz Augusto von Dentz struct hci_conn *hcon = chan->conn->hcon; 83573d80debSLuiz Augusto von Dentz u16 flags; 83673d80debSLuiz Augusto von Dentz 83773d80debSLuiz Augusto von Dentz BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, 83873d80debSLuiz Augusto von Dentz skb->priority); 83973d80debSLuiz Augusto von Dentz 840d5f8a75dSMat Martineau if (chan->hs_hcon && !__chan_is_moving(chan)) { 841d5f8a75dSMat Martineau if (chan->hs_hchan) 842d5f8a75dSMat Martineau hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE); 843d5f8a75dSMat Martineau else 844d5f8a75dSMat Martineau kfree_skb(skb); 845d5f8a75dSMat Martineau 846d5f8a75dSMat Martineau return; 847d5f8a75dSMat Martineau } 848d5f8a75dSMat Martineau 84973d80debSLuiz Augusto von Dentz if (!test_bit(FLAG_FLUSHABLE, &chan->flags) && 85073d80debSLuiz Augusto von Dentz lmp_no_flush_capable(hcon->hdev)) 85173d80debSLuiz Augusto von Dentz flags = ACL_START_NO_FLUSH; 85273d80debSLuiz Augusto von Dentz else 85373d80debSLuiz Augusto von Dentz flags = ACL_START; 85473d80debSLuiz Augusto von Dentz 85573d80debSLuiz Augusto von Dentz bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); 85673d80debSLuiz Augusto von Dentz hci_send_acl(chan->conn->hchan, skb, flags); 8570a708f8fSGustavo F. Padovan } 8580a708f8fSGustavo F. Padovan 859b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control) 860b5c6aaedSMat Martineau { 861b5c6aaedSMat Martineau control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT; 862b5c6aaedSMat Martineau control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT; 863b5c6aaedSMat Martineau 864b5c6aaedSMat Martineau if (enh & L2CAP_CTRL_FRAME_TYPE) { 865b5c6aaedSMat Martineau /* S-Frame */ 866b5c6aaedSMat Martineau control->sframe = 1; 867b5c6aaedSMat Martineau control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT; 868b5c6aaedSMat Martineau control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT; 869b5c6aaedSMat Martineau 870b5c6aaedSMat Martineau control->sar = 0; 871b5c6aaedSMat Martineau control->txseq = 0; 872b5c6aaedSMat Martineau } else { 873b5c6aaedSMat Martineau /* I-Frame */ 874b5c6aaedSMat Martineau control->sframe = 0; 875b5c6aaedSMat Martineau control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT; 876b5c6aaedSMat Martineau control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT; 877b5c6aaedSMat Martineau 878b5c6aaedSMat Martineau control->poll = 0; 879b5c6aaedSMat Martineau control->super = 0; 880b5c6aaedSMat Martineau } 881b5c6aaedSMat Martineau } 882b5c6aaedSMat Martineau 883b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control) 884b5c6aaedSMat Martineau { 885b5c6aaedSMat Martineau control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT; 886b5c6aaedSMat Martineau control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT; 887b5c6aaedSMat Martineau 888b5c6aaedSMat Martineau if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) { 889b5c6aaedSMat Martineau /* S-Frame */ 890b5c6aaedSMat Martineau control->sframe = 1; 891b5c6aaedSMat Martineau control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT; 892b5c6aaedSMat Martineau control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT; 893b5c6aaedSMat Martineau 894b5c6aaedSMat Martineau control->sar = 0; 895b5c6aaedSMat Martineau control->txseq = 0; 896b5c6aaedSMat Martineau } else { 897b5c6aaedSMat Martineau /* I-Frame */ 898b5c6aaedSMat Martineau control->sframe = 0; 899b5c6aaedSMat Martineau control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT; 900b5c6aaedSMat Martineau control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT; 901b5c6aaedSMat Martineau 902b5c6aaedSMat Martineau control->poll = 0; 903b5c6aaedSMat Martineau control->super = 0; 904b5c6aaedSMat Martineau } 905b5c6aaedSMat Martineau } 906b5c6aaedSMat Martineau 907b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan, 908b5c6aaedSMat Martineau struct sk_buff *skb) 909b5c6aaedSMat Martineau { 910b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 911b5c6aaedSMat Martineau __unpack_extended_control(get_unaligned_le32(skb->data), 912b5c6aaedSMat Martineau &bt_cb(skb)->control); 913cec8ab6eSMat Martineau skb_pull(skb, L2CAP_EXT_CTRL_SIZE); 914b5c6aaedSMat Martineau } else { 915b5c6aaedSMat Martineau __unpack_enhanced_control(get_unaligned_le16(skb->data), 916b5c6aaedSMat Martineau &bt_cb(skb)->control); 917cec8ab6eSMat Martineau skb_pull(skb, L2CAP_ENH_CTRL_SIZE); 918b5c6aaedSMat Martineau } 919b5c6aaedSMat Martineau } 920b5c6aaedSMat Martineau 921b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control) 922b5c6aaedSMat Martineau { 923b5c6aaedSMat Martineau u32 packed; 924b5c6aaedSMat Martineau 925b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT; 926b5c6aaedSMat Martineau packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT; 927b5c6aaedSMat Martineau 928b5c6aaedSMat Martineau if (control->sframe) { 929b5c6aaedSMat Martineau packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT; 930b5c6aaedSMat Martineau packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT; 931b5c6aaedSMat Martineau packed |= L2CAP_EXT_CTRL_FRAME_TYPE; 932b5c6aaedSMat Martineau } else { 933b5c6aaedSMat Martineau packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT; 934b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT; 935b5c6aaedSMat Martineau } 936b5c6aaedSMat Martineau 937b5c6aaedSMat Martineau return packed; 938b5c6aaedSMat Martineau } 939b5c6aaedSMat Martineau 940b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control) 941b5c6aaedSMat Martineau { 942b5c6aaedSMat Martineau u16 packed; 943b5c6aaedSMat Martineau 944b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT; 945b5c6aaedSMat Martineau packed |= control->final << L2CAP_CTRL_FINAL_SHIFT; 946b5c6aaedSMat Martineau 947b5c6aaedSMat Martineau if (control->sframe) { 948b5c6aaedSMat Martineau packed |= control->poll << L2CAP_CTRL_POLL_SHIFT; 949b5c6aaedSMat Martineau packed |= control->super << L2CAP_CTRL_SUPER_SHIFT; 950b5c6aaedSMat Martineau packed |= L2CAP_CTRL_FRAME_TYPE; 951b5c6aaedSMat Martineau } else { 952b5c6aaedSMat Martineau packed |= control->sar << L2CAP_CTRL_SAR_SHIFT; 953b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT; 954b5c6aaedSMat Martineau } 955b5c6aaedSMat Martineau 956b5c6aaedSMat Martineau return packed; 957b5c6aaedSMat Martineau } 958b5c6aaedSMat Martineau 959b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan, 960b5c6aaedSMat Martineau struct l2cap_ctrl *control, 961b5c6aaedSMat Martineau struct sk_buff *skb) 962b5c6aaedSMat Martineau { 963b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 964b5c6aaedSMat Martineau put_unaligned_le32(__pack_extended_control(control), 965b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 966b5c6aaedSMat Martineau } else { 967b5c6aaedSMat Martineau put_unaligned_le16(__pack_enhanced_control(control), 968b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 969b5c6aaedSMat Martineau } 970b5c6aaedSMat Martineau } 971b5c6aaedSMat Martineau 972ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan) 973ba7aa64fSGustavo Padovan { 974ba7aa64fSGustavo Padovan if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 975ba7aa64fSGustavo Padovan return L2CAP_EXT_HDR_SIZE; 976ba7aa64fSGustavo Padovan else 977ba7aa64fSGustavo Padovan return L2CAP_ENH_HDR_SIZE; 978ba7aa64fSGustavo Padovan } 979ba7aa64fSGustavo Padovan 980a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan, 981a67d7f6fSMat Martineau u32 control) 9820a708f8fSGustavo F. Padovan { 9830a708f8fSGustavo F. Padovan struct sk_buff *skb; 9840a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 985ba7aa64fSGustavo Padovan int hlen = __ertm_hdr_size(chan); 9860a708f8fSGustavo F. Padovan 9870a708f8fSGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 98803a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 9890a708f8fSGustavo F. Padovan 990a67d7f6fSMat Martineau skb = bt_skb_alloc(hlen, GFP_KERNEL); 9910a708f8fSGustavo F. Padovan 9920a708f8fSGustavo F. Padovan if (!skb) 993a67d7f6fSMat Martineau return ERR_PTR(-ENOMEM); 9940a708f8fSGustavo F. Padovan 9950a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 9960a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); 997fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 99888843ab0SAndrei Emeltchenko 999a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1000a67d7f6fSMat Martineau put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 1001a67d7f6fSMat Martineau else 1002a67d7f6fSMat Martineau put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 10030a708f8fSGustavo F. Padovan 100447d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 1005a67d7f6fSMat Martineau u16 fcs = crc16(0, (u8 *)skb->data, skb->len); 100603a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 10070a708f8fSGustavo F. Padovan } 10080a708f8fSGustavo F. Padovan 100973d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 1010a67d7f6fSMat Martineau return skb; 1011a67d7f6fSMat Martineau } 1012a67d7f6fSMat Martineau 1013a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan, 1014a67d7f6fSMat Martineau struct l2cap_ctrl *control) 1015a67d7f6fSMat Martineau { 1016a67d7f6fSMat Martineau struct sk_buff *skb; 1017a67d7f6fSMat Martineau u32 control_field; 1018a67d7f6fSMat Martineau 1019a67d7f6fSMat Martineau BT_DBG("chan %p, control %p", chan, control); 1020a67d7f6fSMat Martineau 1021a67d7f6fSMat Martineau if (!control->sframe) 1022a67d7f6fSMat Martineau return; 1023a67d7f6fSMat Martineau 1024b99e13adSMat Martineau if (__chan_is_moving(chan)) 1025b99e13adSMat Martineau return; 1026b99e13adSMat Martineau 1027a67d7f6fSMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) && 1028a67d7f6fSMat Martineau !control->poll) 1029a67d7f6fSMat Martineau control->final = 1; 1030a67d7f6fSMat Martineau 1031a67d7f6fSMat Martineau if (control->super == L2CAP_SUPER_RR) 1032a67d7f6fSMat Martineau clear_bit(CONN_RNR_SENT, &chan->conn_state); 1033a67d7f6fSMat Martineau else if (control->super == L2CAP_SUPER_RNR) 1034a67d7f6fSMat Martineau set_bit(CONN_RNR_SENT, &chan->conn_state); 1035a67d7f6fSMat Martineau 1036a67d7f6fSMat Martineau if (control->super != L2CAP_SUPER_SREJ) { 1037a67d7f6fSMat Martineau chan->last_acked_seq = control->reqseq; 1038a67d7f6fSMat Martineau __clear_ack_timer(chan); 1039a67d7f6fSMat Martineau } 1040a67d7f6fSMat Martineau 1041a67d7f6fSMat Martineau BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq, 1042a67d7f6fSMat Martineau control->final, control->poll, control->super); 1043a67d7f6fSMat Martineau 1044a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1045a67d7f6fSMat Martineau control_field = __pack_extended_control(control); 1046a67d7f6fSMat Martineau else 1047a67d7f6fSMat Martineau control_field = __pack_enhanced_control(control); 1048a67d7f6fSMat Martineau 1049a67d7f6fSMat Martineau skb = l2cap_create_sframe_pdu(chan, control_field); 1050a67d7f6fSMat Martineau if (!IS_ERR(skb)) 105173d80debSLuiz Augusto von Dentz l2cap_do_send(chan, skb); 10520a708f8fSGustavo F. Padovan } 10530a708f8fSGustavo F. Padovan 1054c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll) 10550a708f8fSGustavo F. Padovan { 1056c9e3d5e0SMat Martineau struct l2cap_ctrl control; 10570a708f8fSGustavo F. Padovan 1058c9e3d5e0SMat Martineau BT_DBG("chan %p, poll %d", chan, poll); 1059c9e3d5e0SMat Martineau 1060c9e3d5e0SMat Martineau memset(&control, 0, sizeof(control)); 1061c9e3d5e0SMat Martineau control.sframe = 1; 1062c9e3d5e0SMat Martineau control.poll = poll; 1063c9e3d5e0SMat Martineau 1064c9e3d5e0SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 1065c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RNR; 1066c9e3d5e0SMat Martineau else 1067c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RR; 1068c9e3d5e0SMat Martineau 1069c9e3d5e0SMat Martineau control.reqseq = chan->buffer_seq; 1070c9e3d5e0SMat Martineau l2cap_send_sframe(chan, &control); 10710a708f8fSGustavo F. Padovan } 10720a708f8fSGustavo F. Padovan 1073b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) 10740a708f8fSGustavo F. Padovan { 1075c1360a1cSGustavo F. Padovan return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); 10760a708f8fSGustavo F. Padovan } 10770a708f8fSGustavo F. Padovan 107893c3e8f5SAndrei Emeltchenko static bool __amp_capable(struct l2cap_chan *chan) 107993c3e8f5SAndrei Emeltchenko { 108093c3e8f5SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 10811df7b17aSMarcel Holtmann struct hci_dev *hdev; 10821df7b17aSMarcel Holtmann bool amp_available = false; 108393c3e8f5SAndrei Emeltchenko 10841df7b17aSMarcel Holtmann if (!conn->hs_enabled) 10851df7b17aSMarcel Holtmann return false; 10861df7b17aSMarcel Holtmann 10871df7b17aSMarcel Holtmann if (!(conn->fixed_chan_mask & L2CAP_FC_A2MP)) 10881df7b17aSMarcel Holtmann return false; 10891df7b17aSMarcel Holtmann 10901df7b17aSMarcel Holtmann read_lock(&hci_dev_list_lock); 10911df7b17aSMarcel Holtmann list_for_each_entry(hdev, &hci_dev_list, list) { 10921df7b17aSMarcel Holtmann if (hdev->amp_type != AMP_TYPE_BREDR && 10931df7b17aSMarcel Holtmann test_bit(HCI_UP, &hdev->flags)) { 10941df7b17aSMarcel Holtmann amp_available = true; 10951df7b17aSMarcel Holtmann break; 10961df7b17aSMarcel Holtmann } 10971df7b17aSMarcel Holtmann } 10981df7b17aSMarcel Holtmann read_unlock(&hci_dev_list_lock); 10991df7b17aSMarcel Holtmann 11001df7b17aSMarcel Holtmann if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED) 11011df7b17aSMarcel Holtmann return amp_available; 1102848566b3SMarcel Holtmann 110393c3e8f5SAndrei Emeltchenko return false; 110493c3e8f5SAndrei Emeltchenko } 110593c3e8f5SAndrei Emeltchenko 11065ce66b59SAndrei Emeltchenko static bool l2cap_check_efs(struct l2cap_chan *chan) 11075ce66b59SAndrei Emeltchenko { 11085ce66b59SAndrei Emeltchenko /* Check EFS parameters */ 11095ce66b59SAndrei Emeltchenko return true; 11105ce66b59SAndrei Emeltchenko } 11115ce66b59SAndrei Emeltchenko 11122766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan) 11139b27f350SAndrei Emeltchenko { 11149b27f350SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 11159b27f350SAndrei Emeltchenko struct l2cap_conn_req req; 11169b27f350SAndrei Emeltchenko 11179b27f350SAndrei Emeltchenko req.scid = cpu_to_le16(chan->scid); 11189b27f350SAndrei Emeltchenko req.psm = chan->psm; 11199b27f350SAndrei Emeltchenko 11209b27f350SAndrei Emeltchenko chan->ident = l2cap_get_ident(conn); 11219b27f350SAndrei Emeltchenko 11229b27f350SAndrei Emeltchenko set_bit(CONF_CONNECT_PEND, &chan->conf_state); 11239b27f350SAndrei Emeltchenko 11249b27f350SAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); 11259b27f350SAndrei Emeltchenko } 11269b27f350SAndrei Emeltchenko 11278eb200bdSMat Martineau static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id) 11288eb200bdSMat Martineau { 11298eb200bdSMat Martineau struct l2cap_create_chan_req req; 11308eb200bdSMat Martineau req.scid = cpu_to_le16(chan->scid); 11318eb200bdSMat Martineau req.psm = chan->psm; 11328eb200bdSMat Martineau req.amp_id = amp_id; 11338eb200bdSMat Martineau 11348eb200bdSMat Martineau chan->ident = l2cap_get_ident(chan->conn); 11358eb200bdSMat Martineau 11368eb200bdSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ, 11378eb200bdSMat Martineau sizeof(req), &req); 11388eb200bdSMat Martineau } 11398eb200bdSMat Martineau 114002b0fbb9SMat Martineau static void l2cap_move_setup(struct l2cap_chan *chan) 114102b0fbb9SMat Martineau { 114202b0fbb9SMat Martineau struct sk_buff *skb; 114302b0fbb9SMat Martineau 114402b0fbb9SMat Martineau BT_DBG("chan %p", chan); 114502b0fbb9SMat Martineau 114602b0fbb9SMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 114702b0fbb9SMat Martineau return; 114802b0fbb9SMat Martineau 114902b0fbb9SMat Martineau __clear_retrans_timer(chan); 115002b0fbb9SMat Martineau __clear_monitor_timer(chan); 115102b0fbb9SMat Martineau __clear_ack_timer(chan); 115202b0fbb9SMat Martineau 115302b0fbb9SMat Martineau chan->retry_count = 0; 115402b0fbb9SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 115502b0fbb9SMat Martineau if (bt_cb(skb)->control.retries) 115602b0fbb9SMat Martineau bt_cb(skb)->control.retries = 1; 115702b0fbb9SMat Martineau else 115802b0fbb9SMat Martineau break; 115902b0fbb9SMat Martineau } 116002b0fbb9SMat Martineau 116102b0fbb9SMat Martineau chan->expected_tx_seq = chan->buffer_seq; 116202b0fbb9SMat Martineau 116302b0fbb9SMat Martineau clear_bit(CONN_REJ_ACT, &chan->conn_state); 116402b0fbb9SMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 116502b0fbb9SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 116602b0fbb9SMat Martineau l2cap_seq_list_clear(&chan->srej_list); 116702b0fbb9SMat Martineau skb_queue_purge(&chan->srej_q); 116802b0fbb9SMat Martineau 116902b0fbb9SMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 117002b0fbb9SMat Martineau chan->rx_state = L2CAP_RX_STATE_MOVE; 117102b0fbb9SMat Martineau 117202b0fbb9SMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 117302b0fbb9SMat Martineau } 117402b0fbb9SMat Martineau 11755f3847a4SMat Martineau static void l2cap_move_done(struct l2cap_chan *chan) 11765f3847a4SMat Martineau { 11775f3847a4SMat Martineau u8 move_role = chan->move_role; 11785f3847a4SMat Martineau BT_DBG("chan %p", chan); 11795f3847a4SMat Martineau 11805f3847a4SMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 11815f3847a4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 11825f3847a4SMat Martineau 11835f3847a4SMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 11845f3847a4SMat Martineau return; 11855f3847a4SMat Martineau 11865f3847a4SMat Martineau switch (move_role) { 11875f3847a4SMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 11885f3847a4SMat Martineau l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL); 11895f3847a4SMat Martineau chan->rx_state = L2CAP_RX_STATE_WAIT_F; 11905f3847a4SMat Martineau break; 11915f3847a4SMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 11925f3847a4SMat Martineau chan->rx_state = L2CAP_RX_STATE_WAIT_P; 11935f3847a4SMat Martineau break; 11945f3847a4SMat Martineau } 11955f3847a4SMat Martineau } 11965f3847a4SMat Martineau 11979f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan) 11989f0caeb1SVinicius Costa Gomes { 11992827011fSMat Martineau /* This clears all conf flags, including CONF_NOT_COMPLETE */ 12009f0caeb1SVinicius Costa Gomes chan->conf_state = 0; 12019f0caeb1SVinicius Costa Gomes __clear_chan_timer(chan); 12029f0caeb1SVinicius Costa Gomes 120354a59aa2SAndrei Emeltchenko chan->state = BT_CONNECTED; 12049f0caeb1SVinicius Costa Gomes 120554a59aa2SAndrei Emeltchenko chan->ops->ready(chan); 12069f0caeb1SVinicius Costa Gomes } 12079f0caeb1SVinicius Costa Gomes 1208f1496deeSJohan Hedberg static void l2cap_le_connect(struct l2cap_chan *chan) 1209f1496deeSJohan Hedberg { 1210f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1211f1496deeSJohan Hedberg struct l2cap_le_conn_req req; 1212f1496deeSJohan Hedberg 1213f1496deeSJohan Hedberg req.psm = chan->psm; 1214f1496deeSJohan Hedberg req.scid = cpu_to_le16(chan->scid); 1215f1496deeSJohan Hedberg req.mtu = cpu_to_le16(chan->imtu); 1216f1496deeSJohan Hedberg req.mps = __constant_cpu_to_le16(L2CAP_LE_DEFAULT_MPS); 12170cd75f7eSJohan Hedberg req.credits = cpu_to_le16(chan->rx_credits); 1218f1496deeSJohan Hedberg 1219f1496deeSJohan Hedberg chan->ident = l2cap_get_ident(conn); 1220f1496deeSJohan Hedberg 1221f1496deeSJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ, 1222f1496deeSJohan Hedberg sizeof(req), &req); 1223f1496deeSJohan Hedberg } 1224f1496deeSJohan Hedberg 1225f1496deeSJohan Hedberg static void l2cap_le_start(struct l2cap_chan *chan) 1226f1496deeSJohan Hedberg { 1227f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1228f1496deeSJohan Hedberg 1229f1496deeSJohan Hedberg if (!smp_conn_security(conn->hcon, chan->sec_level)) 1230f1496deeSJohan Hedberg return; 1231f1496deeSJohan Hedberg 1232f1496deeSJohan Hedberg if (!chan->psm) { 1233f1496deeSJohan Hedberg l2cap_chan_ready(chan); 1234f1496deeSJohan Hedberg return; 1235f1496deeSJohan Hedberg } 1236f1496deeSJohan Hedberg 1237f1496deeSJohan Hedberg if (chan->state == BT_CONNECT) 1238f1496deeSJohan Hedberg l2cap_le_connect(chan); 1239f1496deeSJohan Hedberg } 1240f1496deeSJohan Hedberg 124193c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan) 124293c3e8f5SAndrei Emeltchenko { 124393c3e8f5SAndrei Emeltchenko if (__amp_capable(chan)) { 124493c3e8f5SAndrei Emeltchenko BT_DBG("chan %p AMP capable: discover AMPs", chan); 124593c3e8f5SAndrei Emeltchenko a2mp_discover_amp(chan); 1246f1496deeSJohan Hedberg } else if (chan->conn->hcon->type == LE_LINK) { 1247f1496deeSJohan Hedberg l2cap_le_start(chan); 124893c3e8f5SAndrei Emeltchenko } else { 124993c3e8f5SAndrei Emeltchenko l2cap_send_conn_req(chan); 125093c3e8f5SAndrei Emeltchenko } 125193c3e8f5SAndrei Emeltchenko } 125293c3e8f5SAndrei Emeltchenko 1253fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan) 12540a708f8fSGustavo F. Padovan { 12558c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 12560a708f8fSGustavo F. Padovan 12579f0caeb1SVinicius Costa Gomes if (conn->hcon->type == LE_LINK) { 125896ac34fbSJohan Hedberg l2cap_le_start(chan); 12599f0caeb1SVinicius Costa Gomes return; 12609f0caeb1SVinicius Costa Gomes } 12619f0caeb1SVinicius Costa Gomes 12620a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { 12630a708f8fSGustavo F. Padovan if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) 12640a708f8fSGustavo F. Padovan return; 12650a708f8fSGustavo F. Padovan 1266d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan) && 126793c3e8f5SAndrei Emeltchenko __l2cap_no_conn_pending(chan)) { 126893c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 126993c3e8f5SAndrei Emeltchenko } 12700a708f8fSGustavo F. Padovan } else { 12710a708f8fSGustavo F. Padovan struct l2cap_info_req req; 1272ac73498cSAndrei Emeltchenko req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); 12730a708f8fSGustavo F. Padovan 12740a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 12750a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 12760a708f8fSGustavo F. Padovan 1277ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 12780a708f8fSGustavo F. Padovan 12792d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, 12802d792818SGustavo Padovan sizeof(req), &req); 12810a708f8fSGustavo F. Padovan } 12820a708f8fSGustavo F. Padovan } 12830a708f8fSGustavo F. Padovan 12840a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) 12850a708f8fSGustavo F. Padovan { 12860a708f8fSGustavo F. Padovan u32 local_feat_mask = l2cap_feat_mask; 12870a708f8fSGustavo F. Padovan if (!disable_ertm) 12880a708f8fSGustavo F. Padovan local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING; 12890a708f8fSGustavo F. Padovan 12900a708f8fSGustavo F. Padovan switch (mode) { 12910a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 12920a708f8fSGustavo F. Padovan return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask; 12930a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 12940a708f8fSGustavo F. Padovan return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask; 12950a708f8fSGustavo F. Padovan default: 12960a708f8fSGustavo F. Padovan return 0x00; 12970a708f8fSGustavo F. Padovan } 12980a708f8fSGustavo F. Padovan } 12990a708f8fSGustavo F. Padovan 13005e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err) 13010a708f8fSGustavo F. Padovan { 13025e4e3972SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 13030a708f8fSGustavo F. Padovan struct l2cap_disconn_req req; 13040a708f8fSGustavo F. Padovan 13050a708f8fSGustavo F. Padovan if (!conn) 13060a708f8fSGustavo F. Padovan return; 13070a708f8fSGustavo F. Padovan 1308aad3d0e3SAndrei Emeltchenko if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) { 13091a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 13101a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 13111a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 13120a708f8fSGustavo F. Padovan } 13130a708f8fSGustavo F. Padovan 1314416fa752SAndrei Emeltchenko if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { 1315d117773cSGustavo Padovan l2cap_state_change(chan, BT_DISCONN); 1316416fa752SAndrei Emeltchenko return; 1317416fa752SAndrei Emeltchenko } 1318416fa752SAndrei Emeltchenko 1319fe4128e0SGustavo F. Padovan req.dcid = cpu_to_le16(chan->dcid); 1320fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 13212d792818SGustavo Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ, 13222d792818SGustavo Padovan sizeof(req), &req); 13230a708f8fSGustavo F. Padovan 1324f8e73017SGustavo Padovan l2cap_state_change_and_error(chan, BT_DISCONN, err); 13250a708f8fSGustavo F. Padovan } 13260a708f8fSGustavo F. Padovan 13270a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */ 13280a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn) 13290a708f8fSGustavo F. Padovan { 13303df91ea2SAndrei Emeltchenko struct l2cap_chan *chan, *tmp; 13310a708f8fSGustavo F. Padovan 13320a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 13330a708f8fSGustavo F. Padovan 13343df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 13350a708f8fSGustavo F. Padovan 13363df91ea2SAndrei Emeltchenko list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 13376be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 13380a708f8fSGustavo F. Padovan 1339715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 13406be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13410a708f8fSGustavo F. Padovan continue; 13420a708f8fSGustavo F. Padovan } 13430a708f8fSGustavo F. Padovan 134489bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 1345d45fc423SGustavo F. Padovan if (!l2cap_chan_check_security(chan) || 1346b4450035SGustavo F. Padovan !__l2cap_no_conn_pending(chan)) { 13476be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13480a708f8fSGustavo F. Padovan continue; 13490a708f8fSGustavo F. Padovan } 13500a708f8fSGustavo F. Padovan 1351c1360a1cSGustavo F. Padovan if (!l2cap_mode_supported(chan->mode, conn->feat_mask) 1352c1360a1cSGustavo F. Padovan && test_bit(CONF_STATE2_DEVICE, 1353c1360a1cSGustavo F. Padovan &chan->conf_state)) { 13540f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 13556be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13560a708f8fSGustavo F. Padovan continue; 13570a708f8fSGustavo F. Padovan } 13580a708f8fSGustavo F. Padovan 135993c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 13600a708f8fSGustavo F. Padovan 136189bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 13620a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 13630a708f8fSGustavo F. Padovan char buf[128]; 1364fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 1365fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 13660a708f8fSGustavo F. Padovan 1367d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 1368bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 1369ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); 1370ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND); 13712dc4e510SGustavo Padovan chan->ops->defer(chan); 13720a708f8fSGustavo F. Padovan 13730a708f8fSGustavo F. Padovan } else { 1374acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 1375ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 1376ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 13770a708f8fSGustavo F. Padovan } 13780a708f8fSGustavo F. Padovan } else { 1379ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); 1380ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND); 13810a708f8fSGustavo F. Padovan } 13820a708f8fSGustavo F. Padovan 1383fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 1384fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 13850a708f8fSGustavo F. Padovan 1386c1360a1cSGustavo F. Padovan if (test_bit(CONF_REQ_SENT, &chan->conf_state) || 13870a708f8fSGustavo F. Padovan rsp.result != L2CAP_CR_SUCCESS) { 13886be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13890a708f8fSGustavo F. Padovan continue; 13900a708f8fSGustavo F. Padovan } 13910a708f8fSGustavo F. Padovan 1392c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 13930a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 139473ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 139573ffa904SGustavo F. Padovan chan->num_conf_req++; 13960a708f8fSGustavo F. Padovan } 13970a708f8fSGustavo F. Padovan 13986be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13990a708f8fSGustavo F. Padovan } 14000a708f8fSGustavo F. Padovan 14013df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 14020a708f8fSGustavo F. Padovan } 14030a708f8fSGustavo F. Padovan 1404c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr. 1405b62f328bSVille Tervo * Returns closest match, locked. 1406b62f328bSVille Tervo */ 1407d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, 1408c2287681SIdo Yariv bdaddr_t *src, 1409c2287681SIdo Yariv bdaddr_t *dst) 1410b62f328bSVille Tervo { 141123691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 1412b62f328bSVille Tervo 141323691d75SGustavo F. Padovan read_lock(&chan_list_lock); 1414b62f328bSVille Tervo 141523691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 141689bc500eSGustavo F. Padovan if (state && c->state != state) 1417b62f328bSVille Tervo continue; 1418b62f328bSVille Tervo 141923691d75SGustavo F. Padovan if (c->scid == cid) { 1420c2287681SIdo Yariv int src_match, dst_match; 1421c2287681SIdo Yariv int src_any, dst_any; 1422c2287681SIdo Yariv 1423b62f328bSVille Tervo /* Exact match. */ 14247eafc59eSMarcel Holtmann src_match = !bacmp(&c->src, src); 14257eafc59eSMarcel Holtmann dst_match = !bacmp(&c->dst, dst); 1426c2287681SIdo Yariv if (src_match && dst_match) { 142723691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 142823691d75SGustavo F. Padovan return c; 142923691d75SGustavo F. Padovan } 1430b62f328bSVille Tervo 1431b62f328bSVille Tervo /* Closest match */ 14327eafc59eSMarcel Holtmann src_any = !bacmp(&c->src, BDADDR_ANY); 14337eafc59eSMarcel Holtmann dst_any = !bacmp(&c->dst, BDADDR_ANY); 1434c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1435c2287681SIdo Yariv (src_any && dst_any)) 143623691d75SGustavo F. Padovan c1 = c; 1437b62f328bSVille Tervo } 1438b62f328bSVille Tervo } 1439280f294fSGustavo F. Padovan 144023691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 1441b62f328bSVille Tervo 144223691d75SGustavo F. Padovan return c1; 1443b62f328bSVille Tervo } 1444b62f328bSVille Tervo 1445b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn) 1446b62f328bSVille Tervo { 1447cc8dba2bSMarcel Holtmann struct hci_conn *hcon = conn->hcon; 144823691d75SGustavo F. Padovan struct l2cap_chan *chan, *pchan; 1449cc8dba2bSMarcel Holtmann u8 dst_type; 1450b62f328bSVille Tervo 1451b62f328bSVille Tervo BT_DBG(""); 1452b62f328bSVille Tervo 1453b62f328bSVille Tervo /* Check if we have socket listening on cid */ 1454073d1cf3SJohan Hedberg pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT, 1455cc8dba2bSMarcel Holtmann &hcon->src, &hcon->dst); 145623691d75SGustavo F. Padovan if (!pchan) 1457b62f328bSVille Tervo return; 1458b62f328bSVille Tervo 145944f3b0fbSJohan Hedberg /* Client ATT sockets should override the server one */ 146044f3b0fbSJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, L2CAP_CID_ATT)) 146144f3b0fbSJohan Hedberg return; 146244f3b0fbSJohan Hedberg 1463cc8dba2bSMarcel Holtmann dst_type = bdaddr_type(hcon, hcon->dst_type); 1464cc8dba2bSMarcel Holtmann 1465cc8dba2bSMarcel Holtmann /* If device is blocked, do not create a channel for it */ 1466cc8dba2bSMarcel Holtmann if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, dst_type)) 1467cc8dba2bSMarcel Holtmann return; 1468cc8dba2bSMarcel Holtmann 14698ffb9290SGustavo Padovan l2cap_chan_lock(pchan); 147062f3a2cfSGustavo F. Padovan 147180b98027SGustavo Padovan chan = pchan->ops->new_connection(pchan); 147280808e43SGustavo F. Padovan if (!chan) 1473b62f328bSVille Tervo goto clean; 1474b62f328bSVille Tervo 14759f22398cSJohan Hedberg chan->dcid = L2CAP_CID_ATT; 14769f22398cSJohan Hedberg 1477cc8dba2bSMarcel Holtmann bacpy(&chan->src, &hcon->src); 1478cc8dba2bSMarcel Holtmann bacpy(&chan->dst, &hcon->dst); 1479cc8dba2bSMarcel Holtmann chan->src_type = bdaddr_type(hcon, hcon->src_type); 1480cc8dba2bSMarcel Holtmann chan->dst_type = dst_type; 1481b62f328bSVille Tervo 148244f3b0fbSJohan Hedberg __l2cap_chan_add(conn, chan); 148348454079SGustavo F. Padovan 1484b62f328bSVille Tervo clean: 14858ffb9290SGustavo Padovan l2cap_chan_unlock(pchan); 1486b62f328bSVille Tervo } 1487b62f328bSVille Tervo 14880a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn) 14890a708f8fSGustavo F. Padovan { 149048454079SGustavo F. Padovan struct l2cap_chan *chan; 1491cc110922SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 14920a708f8fSGustavo F. Padovan 14930a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 14940a708f8fSGustavo F. Padovan 1495d8729922SJohan Hedberg /* For outgoing pairing which doesn't necessarily have an 1496d8729922SJohan Hedberg * associated socket (e.g. mgmt_pair_device). 1497d8729922SJohan Hedberg */ 1498cc110922SVinicius Costa Gomes if (hcon->out && hcon->type == LE_LINK) 1499cc110922SVinicius Costa Gomes smp_conn_security(hcon, hcon->pending_sec_level); 1500160dc6acSVinicius Costa Gomes 15013df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 15020a708f8fSGustavo F. Padovan 150344f3b0fbSJohan Hedberg if (hcon->type == LE_LINK) 150444f3b0fbSJohan Hedberg l2cap_le_conn_ready(conn); 150544f3b0fbSJohan Hedberg 15063df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1507baa7e1faSGustavo F. Padovan 15086be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 15090a708f8fSGustavo F. Padovan 1510416fa752SAndrei Emeltchenko if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { 1511416fa752SAndrei Emeltchenko l2cap_chan_unlock(chan); 1512416fa752SAndrei Emeltchenko continue; 1513416fa752SAndrei Emeltchenko } 1514416fa752SAndrei Emeltchenko 1515cc110922SVinicius Costa Gomes if (hcon->type == LE_LINK) { 1516f1496deeSJohan Hedberg l2cap_le_start(chan); 151763128451SVinicius Costa Gomes } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 151874e75740SGustavo Padovan l2cap_chan_ready(chan); 1519b501d6a1SAnderson Briglia 15201c244f79SGustavo Padovan } else if (chan->state == BT_CONNECT) { 1521fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 15221c244f79SGustavo Padovan } 15230a708f8fSGustavo F. Padovan 15246be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 15250a708f8fSGustavo F. Padovan } 15260a708f8fSGustavo F. Padovan 15273df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 15280a708f8fSGustavo F. Padovan } 15290a708f8fSGustavo F. Padovan 15300a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */ 15310a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) 15320a708f8fSGustavo F. Padovan { 153348454079SGustavo F. Padovan struct l2cap_chan *chan; 15340a708f8fSGustavo F. Padovan 15350a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 15360a708f8fSGustavo F. Padovan 15373df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 15380a708f8fSGustavo F. Padovan 15393df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1540ecf61bdbSAndrei Emeltchenko if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) 15411d8b1fd5SGustavo Padovan l2cap_chan_set_err(chan, err); 15420a708f8fSGustavo F. Padovan } 15430a708f8fSGustavo F. Padovan 15443df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 15450a708f8fSGustavo F. Padovan } 15460a708f8fSGustavo F. Padovan 1547f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work) 15480a708f8fSGustavo F. Padovan { 1549f878fcadSGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 1550030013d8SGustavo F. Padovan info_timer.work); 15510a708f8fSGustavo F. Padovan 15520a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 15530a708f8fSGustavo F. Padovan conn->info_ident = 0; 15540a708f8fSGustavo F. Padovan 15550a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 15560a708f8fSGustavo F. Padovan } 15570a708f8fSGustavo F. Padovan 15582c8e1411SDavid Herrmann /* 15592c8e1411SDavid Herrmann * l2cap_user 15602c8e1411SDavid Herrmann * External modules can register l2cap_user objects on l2cap_conn. The ->probe 15612c8e1411SDavid Herrmann * callback is called during registration. The ->remove callback is called 15622c8e1411SDavid Herrmann * during unregistration. 15632c8e1411SDavid Herrmann * An l2cap_user object can either be explicitly unregistered or when the 15642c8e1411SDavid Herrmann * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon, 15652c8e1411SDavid Herrmann * l2cap->hchan, .. are valid as long as the remove callback hasn't been called. 15662c8e1411SDavid Herrmann * External modules must own a reference to the l2cap_conn object if they intend 15672c8e1411SDavid Herrmann * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at 15682c8e1411SDavid Herrmann * any time if they don't. 15692c8e1411SDavid Herrmann */ 15702c8e1411SDavid Herrmann 15712c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) 15722c8e1411SDavid Herrmann { 15732c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev; 15742c8e1411SDavid Herrmann int ret; 15752c8e1411SDavid Herrmann 15762c8e1411SDavid Herrmann /* We need to check whether l2cap_conn is registered. If it is not, we 15772c8e1411SDavid Herrmann * must not register the l2cap_user. l2cap_conn_del() is unregisters 15782c8e1411SDavid Herrmann * l2cap_conn objects, but doesn't provide its own locking. Instead, it 15792c8e1411SDavid Herrmann * relies on the parent hci_conn object to be locked. This itself relies 15802c8e1411SDavid Herrmann * on the hci_dev object to be locked. So we must lock the hci device 15812c8e1411SDavid Herrmann * here, too. */ 15822c8e1411SDavid Herrmann 15832c8e1411SDavid Herrmann hci_dev_lock(hdev); 15842c8e1411SDavid Herrmann 15852c8e1411SDavid Herrmann if (user->list.next || user->list.prev) { 15862c8e1411SDavid Herrmann ret = -EINVAL; 15872c8e1411SDavid Herrmann goto out_unlock; 15882c8e1411SDavid Herrmann } 15892c8e1411SDavid Herrmann 15902c8e1411SDavid Herrmann /* conn->hchan is NULL after l2cap_conn_del() was called */ 15912c8e1411SDavid Herrmann if (!conn->hchan) { 15922c8e1411SDavid Herrmann ret = -ENODEV; 15932c8e1411SDavid Herrmann goto out_unlock; 15942c8e1411SDavid Herrmann } 15952c8e1411SDavid Herrmann 15962c8e1411SDavid Herrmann ret = user->probe(conn, user); 15972c8e1411SDavid Herrmann if (ret) 15982c8e1411SDavid Herrmann goto out_unlock; 15992c8e1411SDavid Herrmann 16002c8e1411SDavid Herrmann list_add(&user->list, &conn->users); 16012c8e1411SDavid Herrmann ret = 0; 16022c8e1411SDavid Herrmann 16032c8e1411SDavid Herrmann out_unlock: 16042c8e1411SDavid Herrmann hci_dev_unlock(hdev); 16052c8e1411SDavid Herrmann return ret; 16062c8e1411SDavid Herrmann } 16072c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user); 16082c8e1411SDavid Herrmann 16092c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) 16102c8e1411SDavid Herrmann { 16112c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev; 16122c8e1411SDavid Herrmann 16132c8e1411SDavid Herrmann hci_dev_lock(hdev); 16142c8e1411SDavid Herrmann 16152c8e1411SDavid Herrmann if (!user->list.next || !user->list.prev) 16162c8e1411SDavid Herrmann goto out_unlock; 16172c8e1411SDavid Herrmann 16182c8e1411SDavid Herrmann list_del(&user->list); 16192c8e1411SDavid Herrmann user->list.next = NULL; 16202c8e1411SDavid Herrmann user->list.prev = NULL; 16212c8e1411SDavid Herrmann user->remove(conn, user); 16222c8e1411SDavid Herrmann 16232c8e1411SDavid Herrmann out_unlock: 16242c8e1411SDavid Herrmann hci_dev_unlock(hdev); 16252c8e1411SDavid Herrmann } 16262c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user); 16272c8e1411SDavid Herrmann 16282c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn) 16292c8e1411SDavid Herrmann { 16302c8e1411SDavid Herrmann struct l2cap_user *user; 16312c8e1411SDavid Herrmann 16322c8e1411SDavid Herrmann while (!list_empty(&conn->users)) { 16332c8e1411SDavid Herrmann user = list_first_entry(&conn->users, struct l2cap_user, list); 16342c8e1411SDavid Herrmann list_del(&user->list); 16352c8e1411SDavid Herrmann user->list.next = NULL; 16362c8e1411SDavid Herrmann user->list.prev = NULL; 16372c8e1411SDavid Herrmann user->remove(conn, user); 16382c8e1411SDavid Herrmann } 16392c8e1411SDavid Herrmann } 16402c8e1411SDavid Herrmann 16415d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err) 16425d3de7dfSVinicius Costa Gomes { 16435d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 16445d3de7dfSVinicius Costa Gomes struct l2cap_chan *chan, *l; 16455d3de7dfSVinicius Costa Gomes 16465d3de7dfSVinicius Costa Gomes if (!conn) 16475d3de7dfSVinicius Costa Gomes return; 16485d3de7dfSVinicius Costa Gomes 16495d3de7dfSVinicius Costa Gomes BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); 16505d3de7dfSVinicius Costa Gomes 16515d3de7dfSVinicius Costa Gomes kfree_skb(conn->rx_skb); 16525d3de7dfSVinicius Costa Gomes 16532c8e1411SDavid Herrmann l2cap_unregister_all_users(conn); 16542c8e1411SDavid Herrmann 16553df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 16563df91ea2SAndrei Emeltchenko 16575d3de7dfSVinicius Costa Gomes /* Kill channels */ 16585d3de7dfSVinicius Costa Gomes list_for_each_entry_safe(chan, l, &conn->chan_l, list) { 165961d6ef3eSMat Martineau l2cap_chan_hold(chan); 16606be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 16616be36555SAndrei Emeltchenko 16625d3de7dfSVinicius Costa Gomes l2cap_chan_del(chan, err); 16636be36555SAndrei Emeltchenko 16646be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16656be36555SAndrei Emeltchenko 166680b98027SGustavo Padovan chan->ops->close(chan); 166761d6ef3eSMat Martineau l2cap_chan_put(chan); 16685d3de7dfSVinicius Costa Gomes } 16695d3de7dfSVinicius Costa Gomes 16703df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 16713df91ea2SAndrei Emeltchenko 167273d80debSLuiz Augusto von Dentz hci_chan_del(conn->hchan); 167373d80debSLuiz Augusto von Dentz 16745d3de7dfSVinicius Costa Gomes if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1675127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->info_timer); 16765d3de7dfSVinicius Costa Gomes 167751a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) { 1678127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->security_timer); 16798aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 1680d26a2345SVinicius Costa Gomes } 16815d3de7dfSVinicius Costa Gomes 16825d3de7dfSVinicius Costa Gomes hcon->l2cap_data = NULL; 16839c903e37SDavid Herrmann conn->hchan = NULL; 16849c903e37SDavid Herrmann l2cap_conn_put(conn); 16855d3de7dfSVinicius Costa Gomes } 16865d3de7dfSVinicius Costa Gomes 16876c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work) 16885d3de7dfSVinicius Costa Gomes { 16896c9d42a1SGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 16906c9d42a1SGustavo F. Padovan security_timer.work); 16915d3de7dfSVinicius Costa Gomes 1692d06cc416SJohan Hedberg BT_DBG("conn %p", conn); 1693d06cc416SJohan Hedberg 1694d06cc416SJohan Hedberg if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) { 1695d06cc416SJohan Hedberg smp_chan_destroy(conn); 16965d3de7dfSVinicius Costa Gomes l2cap_conn_del(conn->hcon, ETIMEDOUT); 16975d3de7dfSVinicius Costa Gomes } 1698d06cc416SJohan Hedberg } 16995d3de7dfSVinicius Costa Gomes 1700baf43251SClaudio Takahasi static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) 17010a708f8fSGustavo F. Padovan { 17020a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 170373d80debSLuiz Augusto von Dentz struct hci_chan *hchan; 17040a708f8fSGustavo F. Padovan 1705baf43251SClaudio Takahasi if (conn) 17060a708f8fSGustavo F. Padovan return conn; 17070a708f8fSGustavo F. Padovan 170873d80debSLuiz Augusto von Dentz hchan = hci_chan_create(hcon); 170973d80debSLuiz Augusto von Dentz if (!hchan) 17100a708f8fSGustavo F. Padovan return NULL; 17110a708f8fSGustavo F. Padovan 17128bcde1f2SGustavo Padovan conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL); 171373d80debSLuiz Augusto von Dentz if (!conn) { 171473d80debSLuiz Augusto von Dentz hci_chan_del(hchan); 171573d80debSLuiz Augusto von Dentz return NULL; 171673d80debSLuiz Augusto von Dentz } 171773d80debSLuiz Augusto von Dentz 17189c903e37SDavid Herrmann kref_init(&conn->ref); 17190a708f8fSGustavo F. Padovan hcon->l2cap_data = conn; 17200a708f8fSGustavo F. Padovan conn->hcon = hcon; 17219c903e37SDavid Herrmann hci_conn_get(conn->hcon); 172273d80debSLuiz Augusto von Dentz conn->hchan = hchan; 17230a708f8fSGustavo F. Padovan 172473d80debSLuiz Augusto von Dentz BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); 17250a708f8fSGustavo F. Padovan 1726dcc042d5SAndrei Emeltchenko switch (hcon->type) { 1727dcc042d5SAndrei Emeltchenko case LE_LINK: 1728dcc042d5SAndrei Emeltchenko if (hcon->hdev->le_mtu) { 1729acd7d370SVille Tervo conn->mtu = hcon->hdev->le_mtu; 1730dcc042d5SAndrei Emeltchenko break; 1731dcc042d5SAndrei Emeltchenko } 1732dcc042d5SAndrei Emeltchenko /* fall through */ 1733dcc042d5SAndrei Emeltchenko default: 17340a708f8fSGustavo F. Padovan conn->mtu = hcon->hdev->acl_mtu; 1735dcc042d5SAndrei Emeltchenko break; 1736dcc042d5SAndrei Emeltchenko } 1737acd7d370SVille Tervo 17380a708f8fSGustavo F. Padovan conn->feat_mask = 0; 17390a708f8fSGustavo F. Padovan 1740848566b3SMarcel Holtmann if (hcon->type == ACL_LINK) 1741848566b3SMarcel Holtmann conn->hs_enabled = test_bit(HCI_HS_ENABLED, 1742848566b3SMarcel Holtmann &hcon->hdev->dev_flags); 1743848566b3SMarcel Holtmann 17440a708f8fSGustavo F. Padovan spin_lock_init(&conn->lock); 17453df91ea2SAndrei Emeltchenko mutex_init(&conn->chan_lock); 1746baa7e1faSGustavo F. Padovan 1747baa7e1faSGustavo F. Padovan INIT_LIST_HEAD(&conn->chan_l); 17482c8e1411SDavid Herrmann INIT_LIST_HEAD(&conn->users); 17490a708f8fSGustavo F. Padovan 17505d3de7dfSVinicius Costa Gomes if (hcon->type == LE_LINK) 17516c9d42a1SGustavo F. Padovan INIT_DELAYED_WORK(&conn->security_timer, security_timeout); 17525d3de7dfSVinicius Costa Gomes else 1753030013d8SGustavo F. Padovan INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); 17540a708f8fSGustavo F. Padovan 17559f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 17560a708f8fSGustavo F. Padovan 17570a708f8fSGustavo F. Padovan return conn; 17580a708f8fSGustavo F. Padovan } 17590a708f8fSGustavo F. Padovan 17609c903e37SDavid Herrmann static void l2cap_conn_free(struct kref *ref) 17619c903e37SDavid Herrmann { 17629c903e37SDavid Herrmann struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref); 17639c903e37SDavid Herrmann 17649c903e37SDavid Herrmann hci_conn_put(conn->hcon); 17659c903e37SDavid Herrmann kfree(conn); 17669c903e37SDavid Herrmann } 17679c903e37SDavid Herrmann 17689c903e37SDavid Herrmann void l2cap_conn_get(struct l2cap_conn *conn) 17699c903e37SDavid Herrmann { 17709c903e37SDavid Herrmann kref_get(&conn->ref); 17719c903e37SDavid Herrmann } 17729c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_get); 17739c903e37SDavid Herrmann 17749c903e37SDavid Herrmann void l2cap_conn_put(struct l2cap_conn *conn) 17759c903e37SDavid Herrmann { 17769c903e37SDavid Herrmann kref_put(&conn->ref, l2cap_conn_free); 17779c903e37SDavid Herrmann } 17789c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_put); 17799c903e37SDavid Herrmann 17800a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */ 17810a708f8fSGustavo F. Padovan 1782c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr. 17830a708f8fSGustavo F. Padovan * Returns closest match. 17840a708f8fSGustavo F. Padovan */ 1785c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, 1786c2287681SIdo Yariv bdaddr_t *src, 1787bf20fd4eSJohan Hedberg bdaddr_t *dst, 1788bf20fd4eSJohan Hedberg u8 link_type) 17890a708f8fSGustavo F. Padovan { 179023691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 17910a708f8fSGustavo F. Padovan 179223691d75SGustavo F. Padovan read_lock(&chan_list_lock); 17930a708f8fSGustavo F. Padovan 179423691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 179589bc500eSGustavo F. Padovan if (state && c->state != state) 17960a708f8fSGustavo F. Padovan continue; 17970a708f8fSGustavo F. Padovan 1798bf20fd4eSJohan Hedberg if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR) 1799bf20fd4eSJohan Hedberg continue; 1800bf20fd4eSJohan Hedberg 1801bf20fd4eSJohan Hedberg if (link_type == LE_LINK && c->src_type == BDADDR_BREDR) 1802bf20fd4eSJohan Hedberg continue; 1803bf20fd4eSJohan Hedberg 180423691d75SGustavo F. Padovan if (c->psm == psm) { 1805c2287681SIdo Yariv int src_match, dst_match; 1806c2287681SIdo Yariv int src_any, dst_any; 1807c2287681SIdo Yariv 18080a708f8fSGustavo F. Padovan /* Exact match. */ 18097eafc59eSMarcel Holtmann src_match = !bacmp(&c->src, src); 18107eafc59eSMarcel Holtmann dst_match = !bacmp(&c->dst, dst); 1811c2287681SIdo Yariv if (src_match && dst_match) { 1812a7567b20SJohannes Berg read_unlock(&chan_list_lock); 181323691d75SGustavo F. Padovan return c; 181423691d75SGustavo F. Padovan } 18150a708f8fSGustavo F. Padovan 18160a708f8fSGustavo F. Padovan /* Closest match */ 18177eafc59eSMarcel Holtmann src_any = !bacmp(&c->src, BDADDR_ANY); 18187eafc59eSMarcel Holtmann dst_any = !bacmp(&c->dst, BDADDR_ANY); 1819c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1820c2287681SIdo Yariv (src_any && dst_any)) 182123691d75SGustavo F. Padovan c1 = c; 18220a708f8fSGustavo F. Padovan } 18230a708f8fSGustavo F. Padovan } 18240a708f8fSGustavo F. Padovan 182523691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 18260a708f8fSGustavo F. Padovan 182723691d75SGustavo F. Padovan return c1; 18280a708f8fSGustavo F. Padovan } 18290a708f8fSGustavo F. Padovan 18308e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, 18318e9f9892SAndre Guedes bdaddr_t *dst, u8 dst_type) 18320a708f8fSGustavo F. Padovan { 18330a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 18340a708f8fSGustavo F. Padovan struct hci_conn *hcon; 18350a708f8fSGustavo F. Padovan struct hci_dev *hdev; 18360a708f8fSGustavo F. Padovan __u8 auth_type; 18370a708f8fSGustavo F. Padovan int err; 18380a708f8fSGustavo F. Padovan 18397eafc59eSMarcel Holtmann BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst, 1840ab19516aSSyam Sidhardhan dst_type, __le16_to_cpu(psm)); 18410a708f8fSGustavo F. Padovan 18427eafc59eSMarcel Holtmann hdev = hci_get_route(dst, &chan->src); 18430a708f8fSGustavo F. Padovan if (!hdev) 18440a708f8fSGustavo F. Padovan return -EHOSTUNREACH; 18450a708f8fSGustavo F. Padovan 184609fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 18470a708f8fSGustavo F. Padovan 18486be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 184903a00194SGustavo F. Padovan 185003a00194SGustavo F. Padovan /* PSM must be odd and lsb of upper byte must be 0 */ 185103a00194SGustavo F. Padovan if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid && 185203a00194SGustavo F. Padovan chan->chan_type != L2CAP_CHAN_RAW) { 185303a00194SGustavo F. Padovan err = -EINVAL; 185403a00194SGustavo F. Padovan goto done; 185503a00194SGustavo F. Padovan } 185603a00194SGustavo F. Padovan 185703a00194SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) { 185803a00194SGustavo F. Padovan err = -EINVAL; 185903a00194SGustavo F. Padovan goto done; 186003a00194SGustavo F. Padovan } 186103a00194SGustavo F. Padovan 186203a00194SGustavo F. Padovan switch (chan->mode) { 186303a00194SGustavo F. Padovan case L2CAP_MODE_BASIC: 186438319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 186503a00194SGustavo F. Padovan break; 186603a00194SGustavo F. Padovan case L2CAP_MODE_ERTM: 186703a00194SGustavo F. Padovan case L2CAP_MODE_STREAMING: 186803a00194SGustavo F. Padovan if (!disable_ertm) 186903a00194SGustavo F. Padovan break; 187003a00194SGustavo F. Padovan /* fall through */ 187103a00194SGustavo F. Padovan default: 187203a00194SGustavo F. Padovan err = -ENOTSUPP; 187303a00194SGustavo F. Padovan goto done; 187403a00194SGustavo F. Padovan } 187503a00194SGustavo F. Padovan 18760797e01dSGustavo Padovan switch (chan->state) { 187703a00194SGustavo F. Padovan case BT_CONNECT: 187803a00194SGustavo F. Padovan case BT_CONNECT2: 187903a00194SGustavo F. Padovan case BT_CONFIG: 188003a00194SGustavo F. Padovan /* Already connecting */ 188103a00194SGustavo F. Padovan err = 0; 188203a00194SGustavo F. Padovan goto done; 188303a00194SGustavo F. Padovan 188403a00194SGustavo F. Padovan case BT_CONNECTED: 188503a00194SGustavo F. Padovan /* Already connected */ 188603a00194SGustavo F. Padovan err = -EISCONN; 188703a00194SGustavo F. Padovan goto done; 188803a00194SGustavo F. Padovan 188903a00194SGustavo F. Padovan case BT_OPEN: 189003a00194SGustavo F. Padovan case BT_BOUND: 189103a00194SGustavo F. Padovan /* Can connect */ 189203a00194SGustavo F. Padovan break; 189303a00194SGustavo F. Padovan 189403a00194SGustavo F. Padovan default: 189503a00194SGustavo F. Padovan err = -EBADFD; 189603a00194SGustavo F. Padovan goto done; 189703a00194SGustavo F. Padovan } 189803a00194SGustavo F. Padovan 189903a00194SGustavo F. Padovan /* Set destination address and psm */ 19007eafc59eSMarcel Holtmann bacpy(&chan->dst, dst); 19014f1654e0SMarcel Holtmann chan->dst_type = dst_type; 19026be36555SAndrei Emeltchenko 190303a00194SGustavo F. Padovan chan->psm = psm; 190403a00194SGustavo F. Padovan chan->dcid = cid; 19050a708f8fSGustavo F. Padovan 19064343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 19070a708f8fSGustavo F. Padovan 1908f224ca5fSJohan Hedberg if (bdaddr_type_is_le(dst_type)) 19098e9f9892SAndre Guedes hcon = hci_connect(hdev, LE_LINK, dst, dst_type, 19104343478fSGustavo F. Padovan chan->sec_level, auth_type); 1911acd7d370SVille Tervo else 19128e9f9892SAndre Guedes hcon = hci_connect(hdev, ACL_LINK, dst, dst_type, 19134343478fSGustavo F. Padovan chan->sec_level, auth_type); 1914acd7d370SVille Tervo 191530e76272SVille Tervo if (IS_ERR(hcon)) { 191630e76272SVille Tervo err = PTR_ERR(hcon); 19170a708f8fSGustavo F. Padovan goto done; 191830e76272SVille Tervo } 19190a708f8fSGustavo F. Padovan 1920baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon); 19210a708f8fSGustavo F. Padovan if (!conn) { 192276a68ba0SDavid Herrmann hci_conn_drop(hcon); 192330e76272SVille Tervo err = -ENOMEM; 19240a708f8fSGustavo F. Padovan goto done; 19250a708f8fSGustavo F. Padovan } 19260a708f8fSGustavo F. Padovan 1927141d5706SJohan Hedberg if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { 192876a68ba0SDavid Herrmann hci_conn_drop(hcon); 1929141d5706SJohan Hedberg err = -EBUSY; 19309f0caeb1SVinicius Costa Gomes goto done; 19319f0caeb1SVinicius Costa Gomes } 19329f0caeb1SVinicius Costa Gomes 19330a708f8fSGustavo F. Padovan /* Update source addr of the socket */ 19347eafc59eSMarcel Holtmann bacpy(&chan->src, &hcon->src); 19354f1654e0SMarcel Holtmann chan->src_type = bdaddr_type(hcon, hcon->src_type); 19360a708f8fSGustavo F. Padovan 19376be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 193848454079SGustavo F. Padovan l2cap_chan_add(conn, chan); 19396be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 194048454079SGustavo F. Padovan 19415ee9891dSJohan Hedberg /* l2cap_chan_add takes its own ref so we can drop this one */ 19425ee9891dSJohan Hedberg hci_conn_drop(hcon); 19435ee9891dSJohan Hedberg 19446be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECT); 19458d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 19460a708f8fSGustavo F. Padovan 19470a708f8fSGustavo F. Padovan if (hcon->state == BT_CONNECTED) { 1948715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1949c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 1950d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) 19516be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECTED); 19520a708f8fSGustavo F. Padovan } else 1953fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 19540a708f8fSGustavo F. Padovan } 19550a708f8fSGustavo F. Padovan 195630e76272SVille Tervo err = 0; 195730e76272SVille Tervo 19580a708f8fSGustavo F. Padovan done: 19596be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 196009fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 19610a708f8fSGustavo F. Padovan hci_dev_put(hdev); 19620a708f8fSGustavo F. Padovan return err; 19630a708f8fSGustavo F. Padovan } 19640a708f8fSGustavo F. Padovan 1965721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work) 19660a708f8fSGustavo F. Padovan { 1967721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1968721c4181SGustavo F. Padovan monitor_timer.work); 19690a708f8fSGustavo F. Padovan 1970525cd185SGustavo F. Padovan BT_DBG("chan %p", chan); 19710a708f8fSGustavo F. Padovan 19726be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 19736be36555SAndrei Emeltchenko 197480909e04SMat Martineau if (!chan->conn) { 19756be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 19768d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 19770a708f8fSGustavo F. Padovan return; 19780a708f8fSGustavo F. Padovan } 19790a708f8fSGustavo F. Padovan 1980401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO); 19810a708f8fSGustavo F. Padovan 19826be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 19838d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 19840a708f8fSGustavo F. Padovan } 19850a708f8fSGustavo F. Padovan 1986721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work) 19870a708f8fSGustavo F. Padovan { 1988721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1989721c4181SGustavo F. Padovan retrans_timer.work); 19900a708f8fSGustavo F. Padovan 199149208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 19920a708f8fSGustavo F. Padovan 19936be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 19946be36555SAndrei Emeltchenko 199580909e04SMat Martineau if (!chan->conn) { 199680909e04SMat Martineau l2cap_chan_unlock(chan); 199780909e04SMat Martineau l2cap_chan_put(chan); 199880909e04SMat Martineau return; 199980909e04SMat Martineau } 20000a708f8fSGustavo F. Padovan 2001401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO); 20026be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 20038d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 20040a708f8fSGustavo F. Padovan } 20050a708f8fSGustavo F. Padovan 2006d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan, 20073733937dSMat Martineau struct sk_buff_head *skbs) 20080a708f8fSGustavo F. Padovan { 20090a708f8fSGustavo F. Padovan struct sk_buff *skb; 20103733937dSMat Martineau struct l2cap_ctrl *control; 20110a708f8fSGustavo F. Padovan 20123733937dSMat Martineau BT_DBG("chan %p, skbs %p", chan, skbs); 20133733937dSMat Martineau 2014b99e13adSMat Martineau if (__chan_is_moving(chan)) 2015b99e13adSMat Martineau return; 2016b99e13adSMat Martineau 20173733937dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 20183733937dSMat Martineau 20193733937dSMat Martineau while (!skb_queue_empty(&chan->tx_q)) { 20203733937dSMat Martineau 20213733937dSMat Martineau skb = skb_dequeue(&chan->tx_q); 20223733937dSMat Martineau 20233733937dSMat Martineau bt_cb(skb)->control.retries = 1; 20243733937dSMat Martineau control = &bt_cb(skb)->control; 20253733937dSMat Martineau 20263733937dSMat Martineau control->reqseq = 0; 20273733937dSMat Martineau control->txseq = chan->next_tx_seq; 20283733937dSMat Martineau 20293733937dSMat Martineau __pack_control(chan, control, skb); 20300a708f8fSGustavo F. Padovan 203147d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 20323733937dSMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 20333733937dSMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 20340a708f8fSGustavo F. Padovan } 20350a708f8fSGustavo F. Padovan 20364343478fSGustavo F. Padovan l2cap_do_send(chan, skb); 20370a708f8fSGustavo F. Padovan 2038b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 20393733937dSMat Martineau 2040836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 20413733937dSMat Martineau chan->frames_sent++; 20420a708f8fSGustavo F. Padovan } 20430a708f8fSGustavo F. Padovan } 20440a708f8fSGustavo F. Padovan 204567c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan) 20460a708f8fSGustavo F. Padovan { 20470a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 204818a48e76SMat Martineau struct l2cap_ctrl *control; 204918a48e76SMat Martineau int sent = 0; 205018a48e76SMat Martineau 205118a48e76SMat Martineau BT_DBG("chan %p", chan); 20520a708f8fSGustavo F. Padovan 205389bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 20540a708f8fSGustavo F. Padovan return -ENOTCONN; 20550a708f8fSGustavo F. Padovan 205694122bbeSMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 205794122bbeSMat Martineau return 0; 205894122bbeSMat Martineau 2059b99e13adSMat Martineau if (__chan_is_moving(chan)) 2060b99e13adSMat Martineau return 0; 2061b99e13adSMat Martineau 206218a48e76SMat Martineau while (chan->tx_send_head && 206318a48e76SMat Martineau chan->unacked_frames < chan->remote_tx_win && 206418a48e76SMat Martineau chan->tx_state == L2CAP_TX_STATE_XMIT) { 20650a708f8fSGustavo F. Padovan 206618a48e76SMat Martineau skb = chan->tx_send_head; 20670a708f8fSGustavo F. Padovan 206818a48e76SMat Martineau bt_cb(skb)->control.retries = 1; 206918a48e76SMat Martineau control = &bt_cb(skb)->control; 20700a708f8fSGustavo F. Padovan 2071e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 207218a48e76SMat Martineau control->final = 1; 2073e2ab4353SGustavo F. Padovan 207418a48e76SMat Martineau control->reqseq = chan->buffer_seq; 207518a48e76SMat Martineau chan->last_acked_seq = chan->buffer_seq; 207618a48e76SMat Martineau control->txseq = chan->next_tx_seq; 20770a708f8fSGustavo F. Padovan 207818a48e76SMat Martineau __pack_control(chan, control, skb); 20790a708f8fSGustavo F. Padovan 208047d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 208118a48e76SMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 208218a48e76SMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 20830a708f8fSGustavo F. Padovan } 20840a708f8fSGustavo F. Padovan 208518a48e76SMat Martineau /* Clone after data has been modified. Data is assumed to be 208618a48e76SMat Martineau read-only (for locking purposes) on cloned sk_buffs. 208718a48e76SMat Martineau */ 208818a48e76SMat Martineau tx_skb = skb_clone(skb, GFP_KERNEL); 208918a48e76SMat Martineau 209018a48e76SMat Martineau if (!tx_skb) 209118a48e76SMat Martineau break; 20920a708f8fSGustavo F. Padovan 20931a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 20940a708f8fSGustavo F. Padovan 2095836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 20966a026610SGustavo F. Padovan chan->unacked_frames++; 20976a026610SGustavo F. Padovan chan->frames_sent++; 209818a48e76SMat Martineau sent++; 20990a708f8fSGustavo F. Padovan 210058d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 210158d35f87SGustavo F. Padovan chan->tx_send_head = NULL; 21020a708f8fSGustavo F. Padovan else 210358d35f87SGustavo F. Padovan chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); 210418a48e76SMat Martineau 210518a48e76SMat Martineau l2cap_do_send(chan, tx_skb); 2106b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 21070a708f8fSGustavo F. Padovan } 21080a708f8fSGustavo F. Padovan 2109b4400672SAndrei Emeltchenko BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent, 2110b4400672SAndrei Emeltchenko chan->unacked_frames, skb_queue_len(&chan->tx_q)); 211118a48e76SMat Martineau 211218a48e76SMat Martineau return sent; 21130a708f8fSGustavo F. Padovan } 21140a708f8fSGustavo F. Padovan 2115e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan) 2116e1fbd4c1SMat Martineau { 2117e1fbd4c1SMat Martineau struct l2cap_ctrl control; 2118e1fbd4c1SMat Martineau struct sk_buff *skb; 2119e1fbd4c1SMat Martineau struct sk_buff *tx_skb; 2120e1fbd4c1SMat Martineau u16 seq; 2121e1fbd4c1SMat Martineau 2122e1fbd4c1SMat Martineau BT_DBG("chan %p", chan); 2123e1fbd4c1SMat Martineau 2124e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 2125e1fbd4c1SMat Martineau return; 2126e1fbd4c1SMat Martineau 2127b99e13adSMat Martineau if (__chan_is_moving(chan)) 2128b99e13adSMat Martineau return; 2129b99e13adSMat Martineau 2130e1fbd4c1SMat Martineau while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) { 2131e1fbd4c1SMat Martineau seq = l2cap_seq_list_pop(&chan->retrans_list); 2132e1fbd4c1SMat Martineau 2133e1fbd4c1SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq); 2134e1fbd4c1SMat Martineau if (!skb) { 2135e1fbd4c1SMat Martineau BT_DBG("Error: Can't retransmit seq %d, frame missing", 2136e1fbd4c1SMat Martineau seq); 2137e1fbd4c1SMat Martineau continue; 2138e1fbd4c1SMat Martineau } 2139e1fbd4c1SMat Martineau 2140e1fbd4c1SMat Martineau bt_cb(skb)->control.retries++; 2141e1fbd4c1SMat Martineau control = bt_cb(skb)->control; 2142e1fbd4c1SMat Martineau 2143e1fbd4c1SMat Martineau if (chan->max_tx != 0 && 2144e1fbd4c1SMat Martineau bt_cb(skb)->control.retries > chan->max_tx) { 2145e1fbd4c1SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 21465e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 2147e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2148e1fbd4c1SMat Martineau break; 2149e1fbd4c1SMat Martineau } 2150e1fbd4c1SMat Martineau 2151e1fbd4c1SMat Martineau control.reqseq = chan->buffer_seq; 2152e1fbd4c1SMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 2153e1fbd4c1SMat Martineau control.final = 1; 2154e1fbd4c1SMat Martineau else 2155e1fbd4c1SMat Martineau control.final = 0; 2156e1fbd4c1SMat Martineau 2157e1fbd4c1SMat Martineau if (skb_cloned(skb)) { 2158e1fbd4c1SMat Martineau /* Cloned sk_buffs are read-only, so we need a 2159e1fbd4c1SMat Martineau * writeable copy 2160e1fbd4c1SMat Martineau */ 21618bcde1f2SGustavo Padovan tx_skb = skb_copy(skb, GFP_KERNEL); 2162e1fbd4c1SMat Martineau } else { 21638bcde1f2SGustavo Padovan tx_skb = skb_clone(skb, GFP_KERNEL); 2164e1fbd4c1SMat Martineau } 2165e1fbd4c1SMat Martineau 2166e1fbd4c1SMat Martineau if (!tx_skb) { 2167e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2168e1fbd4c1SMat Martineau break; 2169e1fbd4c1SMat Martineau } 2170e1fbd4c1SMat Martineau 2171e1fbd4c1SMat Martineau /* Update skb contents */ 2172e1fbd4c1SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 2173e1fbd4c1SMat Martineau put_unaligned_le32(__pack_extended_control(&control), 2174e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 2175e1fbd4c1SMat Martineau } else { 2176e1fbd4c1SMat Martineau put_unaligned_le16(__pack_enhanced_control(&control), 2177e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 2178e1fbd4c1SMat Martineau } 2179e1fbd4c1SMat Martineau 2180e1fbd4c1SMat Martineau if (chan->fcs == L2CAP_FCS_CRC16) { 2181e1fbd4c1SMat Martineau u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len); 2182e1fbd4c1SMat Martineau put_unaligned_le16(fcs, skb_put(tx_skb, 2183e1fbd4c1SMat Martineau L2CAP_FCS_SIZE)); 2184e1fbd4c1SMat Martineau } 2185e1fbd4c1SMat Martineau 2186e1fbd4c1SMat Martineau l2cap_do_send(chan, tx_skb); 2187e1fbd4c1SMat Martineau 2188e1fbd4c1SMat Martineau BT_DBG("Resent txseq %d", control.txseq); 2189e1fbd4c1SMat Martineau 2190e1fbd4c1SMat Martineau chan->last_acked_seq = chan->buffer_seq; 2191e1fbd4c1SMat Martineau } 2192e1fbd4c1SMat Martineau } 2193e1fbd4c1SMat Martineau 2194f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan, 2195f80842a8SMat Martineau struct l2cap_ctrl *control) 2196f80842a8SMat Martineau { 2197f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2198f80842a8SMat Martineau 2199f80842a8SMat Martineau l2cap_seq_list_append(&chan->retrans_list, control->reqseq); 2200f80842a8SMat Martineau l2cap_ertm_resend(chan); 2201f80842a8SMat Martineau } 2202f80842a8SMat Martineau 2203d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan, 2204d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 2205d2a7ac5dSMat Martineau { 2206e1fbd4c1SMat Martineau struct sk_buff *skb; 2207e1fbd4c1SMat Martineau 2208e1fbd4c1SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2209e1fbd4c1SMat Martineau 2210e1fbd4c1SMat Martineau if (control->poll) 2211e1fbd4c1SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 2212e1fbd4c1SMat Martineau 2213e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2214e1fbd4c1SMat Martineau 2215e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 2216e1fbd4c1SMat Martineau return; 2217e1fbd4c1SMat Martineau 2218e1fbd4c1SMat Martineau if (chan->unacked_frames) { 2219e1fbd4c1SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 2220e1fbd4c1SMat Martineau if (bt_cb(skb)->control.txseq == control->reqseq || 2221e1fbd4c1SMat Martineau skb == chan->tx_send_head) 2222e1fbd4c1SMat Martineau break; 2223e1fbd4c1SMat Martineau } 2224e1fbd4c1SMat Martineau 2225e1fbd4c1SMat Martineau skb_queue_walk_from(&chan->tx_q, skb) { 2226e1fbd4c1SMat Martineau if (skb == chan->tx_send_head) 2227e1fbd4c1SMat Martineau break; 2228e1fbd4c1SMat Martineau 2229e1fbd4c1SMat Martineau l2cap_seq_list_append(&chan->retrans_list, 2230e1fbd4c1SMat Martineau bt_cb(skb)->control.txseq); 2231e1fbd4c1SMat Martineau } 2232e1fbd4c1SMat Martineau 2233e1fbd4c1SMat Martineau l2cap_ertm_resend(chan); 2234e1fbd4c1SMat Martineau } 2235d2a7ac5dSMat Martineau } 2236d2a7ac5dSMat Martineau 2237b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan) 2238b17e73bbSSzymon Janc { 22390a0aba42SMat Martineau struct l2cap_ctrl control; 22400a0aba42SMat Martineau u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq, 22410a0aba42SMat Martineau chan->last_acked_seq); 22420a0aba42SMat Martineau int threshold; 22430a0aba42SMat Martineau 22440a0aba42SMat Martineau BT_DBG("chan %p last_acked_seq %d buffer_seq %d", 22450a0aba42SMat Martineau chan, chan->last_acked_seq, chan->buffer_seq); 22460a0aba42SMat Martineau 22470a0aba42SMat Martineau memset(&control, 0, sizeof(control)); 22480a0aba42SMat Martineau control.sframe = 1; 22490a0aba42SMat Martineau 22500a0aba42SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 22510a0aba42SMat Martineau chan->rx_state == L2CAP_RX_STATE_RECV) { 2252b17e73bbSSzymon Janc __clear_ack_timer(chan); 22530a0aba42SMat Martineau control.super = L2CAP_SUPER_RNR; 22540a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 22550a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 22560a0aba42SMat Martineau } else { 22570a0aba42SMat Martineau if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) { 22580a0aba42SMat Martineau l2cap_ertm_send(chan); 22590a0aba42SMat Martineau /* If any i-frames were sent, they included an ack */ 22600a0aba42SMat Martineau if (chan->buffer_seq == chan->last_acked_seq) 22610a0aba42SMat Martineau frames_to_ack = 0; 22620a0aba42SMat Martineau } 22630a0aba42SMat Martineau 2264c20f8e35SMat Martineau /* Ack now if the window is 3/4ths full. 22650a0aba42SMat Martineau * Calculate without mul or div 22660a0aba42SMat Martineau */ 2267c20f8e35SMat Martineau threshold = chan->ack_win; 22680a0aba42SMat Martineau threshold += threshold << 1; 22690a0aba42SMat Martineau threshold >>= 2; 22700a0aba42SMat Martineau 2271b4400672SAndrei Emeltchenko BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack, 22720a0aba42SMat Martineau threshold); 22730a0aba42SMat Martineau 22740a0aba42SMat Martineau if (frames_to_ack >= threshold) { 22750a0aba42SMat Martineau __clear_ack_timer(chan); 22760a0aba42SMat Martineau control.super = L2CAP_SUPER_RR; 22770a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 22780a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 22790a0aba42SMat Martineau frames_to_ack = 0; 22800a0aba42SMat Martineau } 22810a0aba42SMat Martineau 22820a0aba42SMat Martineau if (frames_to_ack) 22830a0aba42SMat Martineau __set_ack_timer(chan); 22840a0aba42SMat Martineau } 2285b17e73bbSSzymon Janc } 2286b17e73bbSSzymon Janc 228704124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, 228804124681SGustavo F. Padovan struct msghdr *msg, int len, 228904124681SGustavo F. Padovan int count, struct sk_buff *skb) 22900a708f8fSGustavo F. Padovan { 22910952a57aSAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 22920a708f8fSGustavo F. Padovan struct sk_buff **frag; 229390338947SGustavo Padovan int sent = 0; 22940a708f8fSGustavo F. Padovan 22950a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) 22960a708f8fSGustavo F. Padovan return -EFAULT; 22970a708f8fSGustavo F. Padovan 22980a708f8fSGustavo F. Padovan sent += count; 22990a708f8fSGustavo F. Padovan len -= count; 23000a708f8fSGustavo F. Padovan 23010a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 23020a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 23030a708f8fSGustavo F. Padovan while (len) { 2304fbe00700SGustavo Padovan struct sk_buff *tmp; 2305fbe00700SGustavo Padovan 23060a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 23070a708f8fSGustavo F. Padovan 2308fbe00700SGustavo Padovan tmp = chan->ops->alloc_skb(chan, count, 230990338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 2310fbe00700SGustavo Padovan if (IS_ERR(tmp)) 2311fbe00700SGustavo Padovan return PTR_ERR(tmp); 23122f7719ceSAndrei Emeltchenko 2313fbe00700SGustavo Padovan *frag = tmp; 2314fbe00700SGustavo Padovan 23150a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) 23160a708f8fSGustavo F. Padovan return -EFAULT; 23170a708f8fSGustavo F. Padovan 23185e59b791SLuiz Augusto von Dentz (*frag)->priority = skb->priority; 23195e59b791SLuiz Augusto von Dentz 23200a708f8fSGustavo F. Padovan sent += count; 23210a708f8fSGustavo F. Padovan len -= count; 23220a708f8fSGustavo F. Padovan 23232d0ed3d5SGustavo Padovan skb->len += (*frag)->len; 23242d0ed3d5SGustavo Padovan skb->data_len += (*frag)->len; 23252d0ed3d5SGustavo Padovan 23260a708f8fSGustavo F. Padovan frag = &(*frag)->next; 23270a708f8fSGustavo F. Padovan } 23280a708f8fSGustavo F. Padovan 23290a708f8fSGustavo F. Padovan return sent; 23300a708f8fSGustavo F. Padovan } 23310a708f8fSGustavo F. Padovan 23325e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, 23335e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 23345e59b791SLuiz Augusto von Dentz u32 priority) 23350a708f8fSGustavo F. Padovan { 23368c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 23370a708f8fSGustavo F. Padovan struct sk_buff *skb; 233803a51213SAndrei Emeltchenko int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; 23390a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 23400a708f8fSGustavo F. Padovan 234143b1b8dfSMarcel Holtmann BT_DBG("chan %p psm 0x%2.2x len %zu priority %u", chan, 234243b1b8dfSMarcel Holtmann __le16_to_cpu(chan->psm), len, priority); 23430a708f8fSGustavo F. Padovan 23440a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 23452f7719ceSAndrei Emeltchenko 23462f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 234790338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 234890338947SGustavo Padovan if (IS_ERR(skb)) 234990338947SGustavo Padovan return skb; 23500a708f8fSGustavo F. Padovan 23515e59b791SLuiz Augusto von Dentz skb->priority = priority; 23525e59b791SLuiz Augusto von Dentz 23530a708f8fSGustavo F. Padovan /* Create L2CAP header */ 23540a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2355fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 2356daf6a78cSAndrei Emeltchenko lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); 235743b1b8dfSMarcel Holtmann put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE)); 23580a708f8fSGustavo F. Padovan 23590952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 23600a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 23610a708f8fSGustavo F. Padovan kfree_skb(skb); 23620a708f8fSGustavo F. Padovan return ERR_PTR(err); 23630a708f8fSGustavo F. Padovan } 23640a708f8fSGustavo F. Padovan return skb; 23650a708f8fSGustavo F. Padovan } 23660a708f8fSGustavo F. Padovan 23675e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, 23685e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 23695e59b791SLuiz Augusto von Dentz u32 priority) 23700a708f8fSGustavo F. Padovan { 23718c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 23720a708f8fSGustavo F. Padovan struct sk_buff *skb; 2373f2ba7faeSGustavo Padovan int err, count; 23740a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 23750a708f8fSGustavo F. Padovan 2376b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 23770a708f8fSGustavo F. Padovan 2378f2ba7faeSGustavo Padovan count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); 23792f7719ceSAndrei Emeltchenko 2380f2ba7faeSGustavo Padovan skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE, 238190338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 238290338947SGustavo Padovan if (IS_ERR(skb)) 238390338947SGustavo Padovan return skb; 23840a708f8fSGustavo F. Padovan 23855e59b791SLuiz Augusto von Dentz skb->priority = priority; 23865e59b791SLuiz Augusto von Dentz 23870a708f8fSGustavo F. Padovan /* Create L2CAP header */ 23880a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2389fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 23906ff9b5efSGustavo Padovan lh->len = cpu_to_le16(len); 23910a708f8fSGustavo F. Padovan 23920952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 23930a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 23940a708f8fSGustavo F. Padovan kfree_skb(skb); 23950a708f8fSGustavo F. Padovan return ERR_PTR(err); 23960a708f8fSGustavo F. Padovan } 23970a708f8fSGustavo F. Padovan return skb; 23980a708f8fSGustavo F. Padovan } 23990a708f8fSGustavo F. Padovan 2400ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, 2401ab0ff76dSLuiz Augusto von Dentz struct msghdr *msg, size_t len, 240294122bbeSMat Martineau u16 sdulen) 24030a708f8fSGustavo F. Padovan { 24048c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 24050a708f8fSGustavo F. Padovan struct sk_buff *skb; 2406e4ca6d98SAndrei Emeltchenko int err, count, hlen; 24070a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 24080a708f8fSGustavo F. Padovan 2409b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 24100a708f8fSGustavo F. Padovan 24110a708f8fSGustavo F. Padovan if (!conn) 24120a708f8fSGustavo F. Padovan return ERR_PTR(-ENOTCONN); 24130a708f8fSGustavo F. Padovan 2414ba7aa64fSGustavo Padovan hlen = __ertm_hdr_size(chan); 2415e4ca6d98SAndrei Emeltchenko 24160a708f8fSGustavo F. Padovan if (sdulen) 241703a51213SAndrei Emeltchenko hlen += L2CAP_SDULEN_SIZE; 24180a708f8fSGustavo F. Padovan 241947d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 242003a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 24210a708f8fSGustavo F. Padovan 24220a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 24232f7719ceSAndrei Emeltchenko 24242f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 242590338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 242690338947SGustavo Padovan if (IS_ERR(skb)) 242790338947SGustavo Padovan return skb; 24280a708f8fSGustavo F. Padovan 24290a708f8fSGustavo F. Padovan /* Create L2CAP header */ 24300a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2431fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 24320a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 243388843ab0SAndrei Emeltchenko 243418a48e76SMat Martineau /* Control header is populated later */ 243518a48e76SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 243618a48e76SMat Martineau put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 243718a48e76SMat Martineau else 243818a48e76SMat Martineau put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 243988843ab0SAndrei Emeltchenko 24400a708f8fSGustavo F. Padovan if (sdulen) 244103a51213SAndrei Emeltchenko put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 24420a708f8fSGustavo F. Padovan 24430952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 24440a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 24450a708f8fSGustavo F. Padovan kfree_skb(skb); 24460a708f8fSGustavo F. Padovan return ERR_PTR(err); 24470a708f8fSGustavo F. Padovan } 24480a708f8fSGustavo F. Padovan 244918a48e76SMat Martineau bt_cb(skb)->control.fcs = chan->fcs; 24503ce3514fSMat Martineau bt_cb(skb)->control.retries = 0; 24510a708f8fSGustavo F. Padovan return skb; 24520a708f8fSGustavo F. Padovan } 24530a708f8fSGustavo F. Padovan 245494122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan, 245594122bbeSMat Martineau struct sk_buff_head *seg_queue, 245694122bbeSMat Martineau struct msghdr *msg, size_t len) 24570a708f8fSGustavo F. Padovan { 24580a708f8fSGustavo F. Padovan struct sk_buff *skb; 245994122bbeSMat Martineau u16 sdu_len; 246094122bbeSMat Martineau size_t pdu_len; 246194122bbeSMat Martineau u8 sar; 24620a708f8fSGustavo F. Padovan 2463b4400672SAndrei Emeltchenko BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); 24640a708f8fSGustavo F. Padovan 246594122bbeSMat Martineau /* It is critical that ERTM PDUs fit in a single HCI fragment, 246694122bbeSMat Martineau * so fragmented skbs are not used. The HCI layer's handling 246794122bbeSMat Martineau * of fragmented skbs is not compatible with ERTM's queueing. 246894122bbeSMat Martineau */ 246994122bbeSMat Martineau 247094122bbeSMat Martineau /* PDU size is derived from the HCI MTU */ 247194122bbeSMat Martineau pdu_len = chan->conn->mtu; 247294122bbeSMat Martineau 2473a549574dSMat Martineau /* Constrain PDU size for BR/EDR connections */ 2474a549574dSMat Martineau if (!chan->hs_hcon) 247594122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); 247694122bbeSMat Martineau 247794122bbeSMat Martineau /* Adjust for largest possible L2CAP overhead. */ 247835d401dfSGustavo Padovan if (chan->fcs) 247935d401dfSGustavo Padovan pdu_len -= L2CAP_FCS_SIZE; 248035d401dfSGustavo Padovan 2481ba7aa64fSGustavo Padovan pdu_len -= __ertm_hdr_size(chan); 248294122bbeSMat Martineau 248394122bbeSMat Martineau /* Remote device may have requested smaller PDUs */ 248494122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, chan->remote_mps); 248594122bbeSMat Martineau 248694122bbeSMat Martineau if (len <= pdu_len) { 248794122bbeSMat Martineau sar = L2CAP_SAR_UNSEGMENTED; 248894122bbeSMat Martineau sdu_len = 0; 248994122bbeSMat Martineau pdu_len = len; 249094122bbeSMat Martineau } else { 249194122bbeSMat Martineau sar = L2CAP_SAR_START; 249294122bbeSMat Martineau sdu_len = len; 249394122bbeSMat Martineau pdu_len -= L2CAP_SDULEN_SIZE; 249494122bbeSMat Martineau } 24950a708f8fSGustavo F. Padovan 24960a708f8fSGustavo F. Padovan while (len > 0) { 249794122bbeSMat Martineau skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len); 24980a708f8fSGustavo F. Padovan 24990a708f8fSGustavo F. Padovan if (IS_ERR(skb)) { 250094122bbeSMat Martineau __skb_queue_purge(seg_queue); 25010a708f8fSGustavo F. Padovan return PTR_ERR(skb); 25020a708f8fSGustavo F. Padovan } 25030a708f8fSGustavo F. Padovan 250494122bbeSMat Martineau bt_cb(skb)->control.sar = sar; 250594122bbeSMat Martineau __skb_queue_tail(seg_queue, skb); 25060a708f8fSGustavo F. Padovan 250794122bbeSMat Martineau len -= pdu_len; 250894122bbeSMat Martineau if (sdu_len) { 250994122bbeSMat Martineau sdu_len = 0; 251094122bbeSMat Martineau pdu_len += L2CAP_SDULEN_SIZE; 251194122bbeSMat Martineau } 251294122bbeSMat Martineau 251394122bbeSMat Martineau if (len <= pdu_len) { 251494122bbeSMat Martineau sar = L2CAP_SAR_END; 251594122bbeSMat Martineau pdu_len = len; 251694122bbeSMat Martineau } else { 251794122bbeSMat Martineau sar = L2CAP_SAR_CONTINUE; 251894122bbeSMat Martineau } 251994122bbeSMat Martineau } 252094122bbeSMat Martineau 2521f0f62799SGustavo Padovan return 0; 25220a708f8fSGustavo F. Padovan } 25230a708f8fSGustavo F. Padovan 25245e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, 25255e59b791SLuiz Augusto von Dentz u32 priority) 25269a91a04aSGustavo F. Padovan { 25279a91a04aSGustavo F. Padovan struct sk_buff *skb; 25289a91a04aSGustavo F. Padovan int err; 252994122bbeSMat Martineau struct sk_buff_head seg_queue; 25309a91a04aSGustavo F. Padovan 253131e8ce80SSeung-Woo Kim if (!chan->conn) 253231e8ce80SSeung-Woo Kim return -ENOTCONN; 253331e8ce80SSeung-Woo Kim 25349a91a04aSGustavo F. Padovan /* Connectionless channel */ 2535715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { 25365e59b791SLuiz Augusto von Dentz skb = l2cap_create_connless_pdu(chan, msg, len, priority); 25379a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 25389a91a04aSGustavo F. Padovan return PTR_ERR(skb); 25399a91a04aSGustavo F. Padovan 25409a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 25419a91a04aSGustavo F. Padovan return len; 25429a91a04aSGustavo F. Padovan } 25439a91a04aSGustavo F. Padovan 25449a91a04aSGustavo F. Padovan switch (chan->mode) { 25459a91a04aSGustavo F. Padovan case L2CAP_MODE_BASIC: 254638319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 25479a91a04aSGustavo F. Padovan /* Check outgoing MTU */ 25489a91a04aSGustavo F. Padovan if (len > chan->omtu) 25499a91a04aSGustavo F. Padovan return -EMSGSIZE; 25509a91a04aSGustavo F. Padovan 25519a91a04aSGustavo F. Padovan /* Create a basic PDU */ 25525e59b791SLuiz Augusto von Dentz skb = l2cap_create_basic_pdu(chan, msg, len, priority); 25539a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 25549a91a04aSGustavo F. Padovan return PTR_ERR(skb); 25559a91a04aSGustavo F. Padovan 25569a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 25579a91a04aSGustavo F. Padovan err = len; 25589a91a04aSGustavo F. Padovan break; 25599a91a04aSGustavo F. Padovan 25609a91a04aSGustavo F. Padovan case L2CAP_MODE_ERTM: 25619a91a04aSGustavo F. Padovan case L2CAP_MODE_STREAMING: 256294122bbeSMat Martineau /* Check outgoing MTU */ 256394122bbeSMat Martineau if (len > chan->omtu) { 256494122bbeSMat Martineau err = -EMSGSIZE; 25659a91a04aSGustavo F. Padovan break; 25669a91a04aSGustavo F. Padovan } 25679a91a04aSGustavo F. Padovan 256894122bbeSMat Martineau __skb_queue_head_init(&seg_queue); 256994122bbeSMat Martineau 257094122bbeSMat Martineau /* Do segmentation before calling in to the state machine, 257194122bbeSMat Martineau * since it's possible to block while waiting for memory 257294122bbeSMat Martineau * allocation. 257394122bbeSMat Martineau */ 257494122bbeSMat Martineau err = l2cap_segment_sdu(chan, &seg_queue, msg, len); 257594122bbeSMat Martineau 257694122bbeSMat Martineau /* The channel could have been closed while segmenting, 257794122bbeSMat Martineau * check that it is still connected. 257894122bbeSMat Martineau */ 257994122bbeSMat Martineau if (chan->state != BT_CONNECTED) { 258094122bbeSMat Martineau __skb_queue_purge(&seg_queue); 258194122bbeSMat Martineau err = -ENOTCONN; 25829a91a04aSGustavo F. Padovan } 25839a91a04aSGustavo F. Padovan 258494122bbeSMat Martineau if (err) 258594122bbeSMat Martineau break; 258694122bbeSMat Martineau 25873733937dSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) 2588d660366dSGustavo Padovan l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST); 25893733937dSMat Martineau else 2590d660366dSGustavo Padovan l2cap_streaming_send(chan, &seg_queue); 259194122bbeSMat Martineau 25929a91a04aSGustavo F. Padovan err = len; 25939a91a04aSGustavo F. Padovan 259494122bbeSMat Martineau /* If the skbs were not queued for sending, they'll still be in 259594122bbeSMat Martineau * seg_queue and need to be purged. 259694122bbeSMat Martineau */ 259794122bbeSMat Martineau __skb_queue_purge(&seg_queue); 25989a91a04aSGustavo F. Padovan break; 25999a91a04aSGustavo F. Padovan 26009a91a04aSGustavo F. Padovan default: 26019a91a04aSGustavo F. Padovan BT_DBG("bad state %1.1x", chan->mode); 26029a91a04aSGustavo F. Padovan err = -EBADFD; 26039a91a04aSGustavo F. Padovan } 26049a91a04aSGustavo F. Padovan 26059a91a04aSGustavo F. Padovan return err; 26069a91a04aSGustavo F. Padovan } 26079a91a04aSGustavo F. Padovan 2608d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq) 2609d2a7ac5dSMat Martineau { 2610bed68bdeSMat Martineau struct l2cap_ctrl control; 2611bed68bdeSMat Martineau u16 seq; 2612bed68bdeSMat Martineau 2613b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2614bed68bdeSMat Martineau 2615bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2616bed68bdeSMat Martineau control.sframe = 1; 2617bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2618bed68bdeSMat Martineau 2619bed68bdeSMat Martineau for (seq = chan->expected_tx_seq; seq != txseq; 2620bed68bdeSMat Martineau seq = __next_seq(chan, seq)) { 2621bed68bdeSMat Martineau if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) { 2622bed68bdeSMat Martineau control.reqseq = seq; 2623bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2624bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2625bed68bdeSMat Martineau } 2626bed68bdeSMat Martineau } 2627bed68bdeSMat Martineau 2628bed68bdeSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 2629d2a7ac5dSMat Martineau } 2630d2a7ac5dSMat Martineau 2631d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan) 2632d2a7ac5dSMat Martineau { 2633bed68bdeSMat Martineau struct l2cap_ctrl control; 2634bed68bdeSMat Martineau 2635bed68bdeSMat Martineau BT_DBG("chan %p", chan); 2636bed68bdeSMat Martineau 2637bed68bdeSMat Martineau if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR) 2638bed68bdeSMat Martineau return; 2639bed68bdeSMat Martineau 2640bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2641bed68bdeSMat Martineau control.sframe = 1; 2642bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2643bed68bdeSMat Martineau control.reqseq = chan->srej_list.tail; 2644bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2645d2a7ac5dSMat Martineau } 2646d2a7ac5dSMat Martineau 2647d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq) 2648d2a7ac5dSMat Martineau { 2649bed68bdeSMat Martineau struct l2cap_ctrl control; 2650bed68bdeSMat Martineau u16 initial_head; 2651bed68bdeSMat Martineau u16 seq; 2652bed68bdeSMat Martineau 2653b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2654bed68bdeSMat Martineau 2655bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2656bed68bdeSMat Martineau control.sframe = 1; 2657bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2658bed68bdeSMat Martineau 2659bed68bdeSMat Martineau /* Capture initial list head to allow only one pass through the list. */ 2660bed68bdeSMat Martineau initial_head = chan->srej_list.head; 2661bed68bdeSMat Martineau 2662bed68bdeSMat Martineau do { 2663bed68bdeSMat Martineau seq = l2cap_seq_list_pop(&chan->srej_list); 2664bed68bdeSMat Martineau if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR) 2665bed68bdeSMat Martineau break; 2666bed68bdeSMat Martineau 2667bed68bdeSMat Martineau control.reqseq = seq; 2668bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2669bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2670bed68bdeSMat Martineau } while (chan->srej_list.head != initial_head); 2671d2a7ac5dSMat Martineau } 2672d2a7ac5dSMat Martineau 2673608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq) 2674608bcc6dSMat Martineau { 2675608bcc6dSMat Martineau struct sk_buff *acked_skb; 2676608bcc6dSMat Martineau u16 ackseq; 2677608bcc6dSMat Martineau 2678b4400672SAndrei Emeltchenko BT_DBG("chan %p, reqseq %u", chan, reqseq); 2679608bcc6dSMat Martineau 2680608bcc6dSMat Martineau if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq) 2681608bcc6dSMat Martineau return; 2682608bcc6dSMat Martineau 2683b4400672SAndrei Emeltchenko BT_DBG("expected_ack_seq %u, unacked_frames %u", 2684608bcc6dSMat Martineau chan->expected_ack_seq, chan->unacked_frames); 2685608bcc6dSMat Martineau 2686608bcc6dSMat Martineau for (ackseq = chan->expected_ack_seq; ackseq != reqseq; 2687608bcc6dSMat Martineau ackseq = __next_seq(chan, ackseq)) { 2688608bcc6dSMat Martineau 2689608bcc6dSMat Martineau acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq); 2690608bcc6dSMat Martineau if (acked_skb) { 2691608bcc6dSMat Martineau skb_unlink(acked_skb, &chan->tx_q); 2692608bcc6dSMat Martineau kfree_skb(acked_skb); 2693608bcc6dSMat Martineau chan->unacked_frames--; 2694608bcc6dSMat Martineau } 2695608bcc6dSMat Martineau } 2696608bcc6dSMat Martineau 2697608bcc6dSMat Martineau chan->expected_ack_seq = reqseq; 2698608bcc6dSMat Martineau 2699608bcc6dSMat Martineau if (chan->unacked_frames == 0) 2700608bcc6dSMat Martineau __clear_retrans_timer(chan); 2701608bcc6dSMat Martineau 2702b4400672SAndrei Emeltchenko BT_DBG("unacked_frames %u", chan->unacked_frames); 2703608bcc6dSMat Martineau } 2704608bcc6dSMat Martineau 2705608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan) 2706608bcc6dSMat Martineau { 2707608bcc6dSMat Martineau BT_DBG("chan %p", chan); 2708608bcc6dSMat Martineau 2709608bcc6dSMat Martineau chan->expected_tx_seq = chan->buffer_seq; 2710608bcc6dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 2711608bcc6dSMat Martineau skb_queue_purge(&chan->srej_q); 2712608bcc6dSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2713608bcc6dSMat Martineau } 2714608bcc6dSMat Martineau 2715d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan, 2716608bcc6dSMat Martineau struct l2cap_ctrl *control, 2717608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2718608bcc6dSMat Martineau { 2719608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2720608bcc6dSMat Martineau event); 2721608bcc6dSMat Martineau 2722608bcc6dSMat Martineau switch (event) { 2723608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2724608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2725608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2726608bcc6dSMat Martineau 2727608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2728608bcc6dSMat Martineau l2cap_ertm_send(chan); 2729608bcc6dSMat Martineau break; 2730608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2731608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2732608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2733608bcc6dSMat Martineau 2734608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2735608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2736608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2737608bcc6dSMat Martineau */ 2738608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2739608bcc6dSMat Martineau } 2740608bcc6dSMat Martineau 2741608bcc6dSMat Martineau l2cap_send_ack(chan); 2742608bcc6dSMat Martineau 2743608bcc6dSMat Martineau break; 2744608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2745608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2746608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2747608bcc6dSMat Martineau 2748608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2749608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2750608bcc6dSMat Martineau 2751608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2752608bcc6dSMat Martineau local_control.sframe = 1; 2753608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2754608bcc6dSMat Martineau local_control.poll = 1; 2755608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2756a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2757608bcc6dSMat Martineau 2758608bcc6dSMat Martineau chan->retry_count = 1; 2759608bcc6dSMat Martineau __set_monitor_timer(chan); 2760608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2761608bcc6dSMat Martineau } 2762608bcc6dSMat Martineau break; 2763608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2764608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2765608bcc6dSMat Martineau break; 2766608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2767608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2768608bcc6dSMat Martineau chan->retry_count = 1; 2769608bcc6dSMat Martineau __set_monitor_timer(chan); 2770608bcc6dSMat Martineau __clear_ack_timer(chan); 2771608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2772608bcc6dSMat Martineau break; 2773608bcc6dSMat Martineau case L2CAP_EV_RETRANS_TO: 2774608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2775608bcc6dSMat Martineau chan->retry_count = 1; 2776608bcc6dSMat Martineau __set_monitor_timer(chan); 2777608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2778608bcc6dSMat Martineau break; 2779608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2780608bcc6dSMat Martineau /* Nothing to process */ 2781608bcc6dSMat Martineau break; 2782608bcc6dSMat Martineau default: 2783608bcc6dSMat Martineau break; 2784608bcc6dSMat Martineau } 2785608bcc6dSMat Martineau } 2786608bcc6dSMat Martineau 2787d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan, 2788608bcc6dSMat Martineau struct l2cap_ctrl *control, 2789608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2790608bcc6dSMat Martineau { 2791608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2792608bcc6dSMat Martineau event); 2793608bcc6dSMat Martineau 2794608bcc6dSMat Martineau switch (event) { 2795608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2796608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2797608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2798608bcc6dSMat Martineau /* Queue data, but don't send. */ 2799608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2800608bcc6dSMat Martineau break; 2801608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2802608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2803608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2804608bcc6dSMat Martineau 2805608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2806608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2807608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2808608bcc6dSMat Martineau */ 2809608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2810608bcc6dSMat Martineau } 2811608bcc6dSMat Martineau 2812608bcc6dSMat Martineau l2cap_send_ack(chan); 2813608bcc6dSMat Martineau 2814608bcc6dSMat Martineau break; 2815608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2816608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2817608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2818608bcc6dSMat Martineau 2819608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2820608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2821608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2822608bcc6dSMat Martineau local_control.sframe = 1; 2823608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2824608bcc6dSMat Martineau local_control.poll = 1; 2825608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2826a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2827608bcc6dSMat Martineau 2828608bcc6dSMat Martineau chan->retry_count = 1; 2829608bcc6dSMat Martineau __set_monitor_timer(chan); 2830608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2831608bcc6dSMat Martineau } 2832608bcc6dSMat Martineau break; 2833608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2834608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2835608bcc6dSMat Martineau 2836608bcc6dSMat Martineau /* Fall through */ 2837608bcc6dSMat Martineau 2838608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2839608bcc6dSMat Martineau if (control && control->final) { 2840608bcc6dSMat Martineau __clear_monitor_timer(chan); 2841608bcc6dSMat Martineau if (chan->unacked_frames > 0) 2842608bcc6dSMat Martineau __set_retrans_timer(chan); 2843608bcc6dSMat Martineau chan->retry_count = 0; 2844608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 2845608bcc6dSMat Martineau BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state); 2846608bcc6dSMat Martineau } 2847608bcc6dSMat Martineau break; 2848608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2849608bcc6dSMat Martineau /* Ignore */ 2850608bcc6dSMat Martineau break; 2851608bcc6dSMat Martineau case L2CAP_EV_MONITOR_TO: 2852608bcc6dSMat Martineau if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) { 2853608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2854608bcc6dSMat Martineau __set_monitor_timer(chan); 2855608bcc6dSMat Martineau chan->retry_count++; 2856608bcc6dSMat Martineau } else { 28575e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNABORTED); 2858608bcc6dSMat Martineau } 2859608bcc6dSMat Martineau break; 2860608bcc6dSMat Martineau default: 2861608bcc6dSMat Martineau break; 2862608bcc6dSMat Martineau } 2863608bcc6dSMat Martineau } 2864608bcc6dSMat Martineau 2865d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 2866608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2867608bcc6dSMat Martineau { 2868608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d, state %d", 2869608bcc6dSMat Martineau chan, control, skbs, event, chan->tx_state); 2870608bcc6dSMat Martineau 2871608bcc6dSMat Martineau switch (chan->tx_state) { 2872608bcc6dSMat Martineau case L2CAP_TX_STATE_XMIT: 2873d660366dSGustavo Padovan l2cap_tx_state_xmit(chan, control, skbs, event); 2874608bcc6dSMat Martineau break; 2875608bcc6dSMat Martineau case L2CAP_TX_STATE_WAIT_F: 2876d660366dSGustavo Padovan l2cap_tx_state_wait_f(chan, control, skbs, event); 2877608bcc6dSMat Martineau break; 2878608bcc6dSMat Martineau default: 2879608bcc6dSMat Martineau /* Ignore event */ 2880608bcc6dSMat Martineau break; 2881608bcc6dSMat Martineau } 2882608bcc6dSMat Martineau } 2883608bcc6dSMat Martineau 28844b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan, 28854b51dae9SMat Martineau struct l2cap_ctrl *control) 28864b51dae9SMat Martineau { 28874b51dae9SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2888401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT); 28894b51dae9SMat Martineau } 28904b51dae9SMat Martineau 2891f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan, 2892f80842a8SMat Martineau struct l2cap_ctrl *control) 2893f80842a8SMat Martineau { 2894f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2895401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT); 2896f80842a8SMat Martineau } 2897f80842a8SMat Martineau 28980a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */ 28990a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 29000a708f8fSGustavo F. Padovan { 29010a708f8fSGustavo F. Padovan struct sk_buff *nskb; 290248454079SGustavo F. Padovan struct l2cap_chan *chan; 29030a708f8fSGustavo F. Padovan 29040a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 29050a708f8fSGustavo F. Padovan 29063df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 29073d57dc68SGustavo F. Padovan 29083df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 2909715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW) 29100a708f8fSGustavo F. Padovan continue; 29110a708f8fSGustavo F. Padovan 29127f5396a7SGustavo Padovan /* Don't send frame to the channel it came from */ 29137f5396a7SGustavo Padovan if (bt_cb(skb)->chan == chan) 29140a708f8fSGustavo F. Padovan continue; 29157f5396a7SGustavo Padovan 29168bcde1f2SGustavo Padovan nskb = skb_clone(skb, GFP_KERNEL); 29170a708f8fSGustavo F. Padovan if (!nskb) 29180a708f8fSGustavo F. Padovan continue; 291980b98027SGustavo Padovan if (chan->ops->recv(chan, nskb)) 29200a708f8fSGustavo F. Padovan kfree_skb(nskb); 29210a708f8fSGustavo F. Padovan } 29223d57dc68SGustavo F. Padovan 29233df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 29240a708f8fSGustavo F. Padovan } 29250a708f8fSGustavo F. Padovan 29260a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */ 2927b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, 2928b4400672SAndrei Emeltchenko u8 ident, u16 dlen, void *data) 29290a708f8fSGustavo F. Padovan { 29300a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag; 29310a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd; 29320a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 29330a708f8fSGustavo F. Padovan int len, count; 29340a708f8fSGustavo F. Padovan 2935b4400672SAndrei Emeltchenko BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u", 29360a708f8fSGustavo F. Padovan conn, code, ident, dlen); 29370a708f8fSGustavo F. Padovan 2938300b962eSAnderson Lizardo if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE) 2939300b962eSAnderson Lizardo return NULL; 2940300b962eSAnderson Lizardo 29410a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; 29420a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 29430a708f8fSGustavo F. Padovan 29448bcde1f2SGustavo Padovan skb = bt_skb_alloc(count, GFP_KERNEL); 29450a708f8fSGustavo F. Padovan if (!skb) 29460a708f8fSGustavo F. Padovan return NULL; 29470a708f8fSGustavo F. Padovan 29480a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 29490a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); 29503300d9a9SClaudio Takahasi 29513300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 2952ac73498cSAndrei Emeltchenko lh->cid = __constant_cpu_to_le16(L2CAP_CID_LE_SIGNALING); 29533300d9a9SClaudio Takahasi else 2954ac73498cSAndrei Emeltchenko lh->cid = __constant_cpu_to_le16(L2CAP_CID_SIGNALING); 29550a708f8fSGustavo F. Padovan 29560a708f8fSGustavo F. Padovan cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); 29570a708f8fSGustavo F. Padovan cmd->code = code; 29580a708f8fSGustavo F. Padovan cmd->ident = ident; 29590a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen); 29600a708f8fSGustavo F. Padovan 29610a708f8fSGustavo F. Padovan if (dlen) { 29620a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE; 29630a708f8fSGustavo F. Padovan memcpy(skb_put(skb, count), data, count); 29640a708f8fSGustavo F. Padovan data += count; 29650a708f8fSGustavo F. Padovan } 29660a708f8fSGustavo F. Padovan 29670a708f8fSGustavo F. Padovan len -= skb->len; 29680a708f8fSGustavo F. Padovan 29690a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 29700a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 29710a708f8fSGustavo F. Padovan while (len) { 29720a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 29730a708f8fSGustavo F. Padovan 29748bcde1f2SGustavo Padovan *frag = bt_skb_alloc(count, GFP_KERNEL); 29750a708f8fSGustavo F. Padovan if (!*frag) 29760a708f8fSGustavo F. Padovan goto fail; 29770a708f8fSGustavo F. Padovan 29780a708f8fSGustavo F. Padovan memcpy(skb_put(*frag, count), data, count); 29790a708f8fSGustavo F. Padovan 29800a708f8fSGustavo F. Padovan len -= count; 29810a708f8fSGustavo F. Padovan data += count; 29820a708f8fSGustavo F. Padovan 29830a708f8fSGustavo F. Padovan frag = &(*frag)->next; 29840a708f8fSGustavo F. Padovan } 29850a708f8fSGustavo F. Padovan 29860a708f8fSGustavo F. Padovan return skb; 29870a708f8fSGustavo F. Padovan 29880a708f8fSGustavo F. Padovan fail: 29890a708f8fSGustavo F. Padovan kfree_skb(skb); 29900a708f8fSGustavo F. Padovan return NULL; 29910a708f8fSGustavo F. Padovan } 29920a708f8fSGustavo F. Padovan 29932d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, 29942d792818SGustavo Padovan unsigned long *val) 29950a708f8fSGustavo F. Padovan { 29960a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 29970a708f8fSGustavo F. Padovan int len; 29980a708f8fSGustavo F. Padovan 29990a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len; 30000a708f8fSGustavo F. Padovan *ptr += len; 30010a708f8fSGustavo F. Padovan 30020a708f8fSGustavo F. Padovan *type = opt->type; 30030a708f8fSGustavo F. Padovan *olen = opt->len; 30040a708f8fSGustavo F. Padovan 30050a708f8fSGustavo F. Padovan switch (opt->len) { 30060a708f8fSGustavo F. Padovan case 1: 30070a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val); 30080a708f8fSGustavo F. Padovan break; 30090a708f8fSGustavo F. Padovan 30100a708f8fSGustavo F. Padovan case 2: 30110a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val); 30120a708f8fSGustavo F. Padovan break; 30130a708f8fSGustavo F. Padovan 30140a708f8fSGustavo F. Padovan case 4: 30150a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val); 30160a708f8fSGustavo F. Padovan break; 30170a708f8fSGustavo F. Padovan 30180a708f8fSGustavo F. Padovan default: 30190a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val; 30200a708f8fSGustavo F. Padovan break; 30210a708f8fSGustavo F. Padovan } 30220a708f8fSGustavo F. Padovan 3023b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val); 30240a708f8fSGustavo F. Padovan return len; 30250a708f8fSGustavo F. Padovan } 30260a708f8fSGustavo F. Padovan 30270a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) 30280a708f8fSGustavo F. Padovan { 30290a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 30300a708f8fSGustavo F. Padovan 3031b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val); 30320a708f8fSGustavo F. Padovan 30330a708f8fSGustavo F. Padovan opt->type = type; 30340a708f8fSGustavo F. Padovan opt->len = len; 30350a708f8fSGustavo F. Padovan 30360a708f8fSGustavo F. Padovan switch (len) { 30370a708f8fSGustavo F. Padovan case 1: 30380a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val; 30390a708f8fSGustavo F. Padovan break; 30400a708f8fSGustavo F. Padovan 30410a708f8fSGustavo F. Padovan case 2: 30420a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val); 30430a708f8fSGustavo F. Padovan break; 30440a708f8fSGustavo F. Padovan 30450a708f8fSGustavo F. Padovan case 4: 30460a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val); 30470a708f8fSGustavo F. Padovan break; 30480a708f8fSGustavo F. Padovan 30490a708f8fSGustavo F. Padovan default: 30500a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len); 30510a708f8fSGustavo F. Padovan break; 30520a708f8fSGustavo F. Padovan } 30530a708f8fSGustavo F. Padovan 30540a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len; 30550a708f8fSGustavo F. Padovan } 30560a708f8fSGustavo F. Padovan 3057f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) 3058f89cef09SAndrei Emeltchenko { 3059f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs; 3060f89cef09SAndrei Emeltchenko 3061f89cef09SAndrei Emeltchenko switch (chan->mode) { 3062f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM: 3063f89cef09SAndrei Emeltchenko efs.id = chan->local_id; 3064f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype; 3065f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 3066f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 3067ac73498cSAndrei Emeltchenko efs.acc_lat = __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); 30688936fa6dSAndrei Emeltchenko efs.flush_to = __constant_cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO); 3069f89cef09SAndrei Emeltchenko break; 3070f89cef09SAndrei Emeltchenko 3071f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING: 3072f89cef09SAndrei Emeltchenko efs.id = 1; 3073f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT; 3074f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 3075f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 3076f89cef09SAndrei Emeltchenko efs.acc_lat = 0; 3077f89cef09SAndrei Emeltchenko efs.flush_to = 0; 3078f89cef09SAndrei Emeltchenko break; 3079f89cef09SAndrei Emeltchenko 3080f89cef09SAndrei Emeltchenko default: 3081f89cef09SAndrei Emeltchenko return; 3082f89cef09SAndrei Emeltchenko } 3083f89cef09SAndrei Emeltchenko 3084f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), 3085f89cef09SAndrei Emeltchenko (unsigned long) &efs); 3086f89cef09SAndrei Emeltchenko } 3087f89cef09SAndrei Emeltchenko 3088721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work) 30890a708f8fSGustavo F. Padovan { 3090721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 3091721c4181SGustavo F. Padovan ack_timer.work); 30920362520bSMat Martineau u16 frames_to_ack; 30930a708f8fSGustavo F. Padovan 30942fb9b3d4SGustavo F. Padovan BT_DBG("chan %p", chan); 30952fb9b3d4SGustavo F. Padovan 30966be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 30976be36555SAndrei Emeltchenko 30980362520bSMat Martineau frames_to_ack = __seq_offset(chan, chan->buffer_seq, 30990362520bSMat Martineau chan->last_acked_seq); 31000362520bSMat Martineau 31010362520bSMat Martineau if (frames_to_ack) 31020362520bSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 31036be36555SAndrei Emeltchenko 31046be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 310509bfb2eeSSzymon Janc l2cap_chan_put(chan); 31060a708f8fSGustavo F. Padovan } 31070a708f8fSGustavo F. Padovan 3108466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan) 31090a708f8fSGustavo F. Padovan { 31103c588192SMat Martineau int err; 31113c588192SMat Martineau 3112105bdf9eSMat Martineau chan->next_tx_seq = 0; 3113105bdf9eSMat Martineau chan->expected_tx_seq = 0; 311442e5c802SGustavo F. Padovan chan->expected_ack_seq = 0; 31156a026610SGustavo F. Padovan chan->unacked_frames = 0; 311642e5c802SGustavo F. Padovan chan->buffer_seq = 0; 31176a026610SGustavo F. Padovan chan->frames_sent = 0; 3118105bdf9eSMat Martineau chan->last_acked_seq = 0; 3119105bdf9eSMat Martineau chan->sdu = NULL; 3120105bdf9eSMat Martineau chan->sdu_last_frag = NULL; 3121105bdf9eSMat Martineau chan->sdu_len = 0; 3122105bdf9eSMat Martineau 3123d34c34fbSMat Martineau skb_queue_head_init(&chan->tx_q); 3124d34c34fbSMat Martineau 31256ed971caSMarcel Holtmann chan->local_amp_id = AMP_ID_BREDR; 31266ed971caSMarcel Holtmann chan->move_id = AMP_ID_BREDR; 312708333283SMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 312808333283SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 312908333283SMat Martineau 3130105bdf9eSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 3131105bdf9eSMat Martineau return 0; 3132105bdf9eSMat Martineau 3133105bdf9eSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 3134105bdf9eSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 31350a708f8fSGustavo F. Padovan 3136721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout); 3137721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout); 3138721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout); 31390a708f8fSGustavo F. Padovan 3140f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q); 31410a708f8fSGustavo F. Padovan 31423c588192SMat Martineau err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win); 31433c588192SMat Martineau if (err < 0) 31443c588192SMat Martineau return err; 31453c588192SMat Martineau 31469dc9affcSMat Martineau err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win); 31479dc9affcSMat Martineau if (err < 0) 31489dc9affcSMat Martineau l2cap_seq_list_free(&chan->srej_list); 31499dc9affcSMat Martineau 31509dc9affcSMat Martineau return err; 31510a708f8fSGustavo F. Padovan } 31520a708f8fSGustavo F. Padovan 31530a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) 31540a708f8fSGustavo F. Padovan { 31550a708f8fSGustavo F. Padovan switch (mode) { 31560a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 31570a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 31580a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask)) 31590a708f8fSGustavo F. Padovan return mode; 31600a708f8fSGustavo F. Padovan /* fall through */ 31610a708f8fSGustavo F. Padovan default: 31620a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC; 31630a708f8fSGustavo F. Padovan } 31640a708f8fSGustavo F. Padovan } 31650a708f8fSGustavo F. Padovan 3166848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn) 31676327eb98SAndrei Emeltchenko { 3168848566b3SMarcel Holtmann return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_WINDOW; 31696327eb98SAndrei Emeltchenko } 31706327eb98SAndrei Emeltchenko 3171848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn) 3172f89cef09SAndrei Emeltchenko { 3173848566b3SMarcel Holtmann return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_FLOW; 3174f89cef09SAndrei Emeltchenko } 3175f89cef09SAndrei Emeltchenko 317636c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan, 317736c86c85SMat Martineau struct l2cap_conf_rfc *rfc) 317836c86c85SMat Martineau { 31796ed971caSMarcel Holtmann if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) { 318036c86c85SMat Martineau u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to; 318136c86c85SMat Martineau 318236c86c85SMat Martineau /* Class 1 devices have must have ERTM timeouts 318336c86c85SMat Martineau * exceeding the Link Supervision Timeout. The 318436c86c85SMat Martineau * default Link Supervision Timeout for AMP 318536c86c85SMat Martineau * controllers is 10 seconds. 318636c86c85SMat Martineau * 318736c86c85SMat Martineau * Class 1 devices use 0xffffffff for their 318836c86c85SMat Martineau * best-effort flush timeout, so the clamping logic 318936c86c85SMat Martineau * will result in a timeout that meets the above 319036c86c85SMat Martineau * requirement. ERTM timeouts are 16-bit values, so 319136c86c85SMat Martineau * the maximum timeout is 65.535 seconds. 319236c86c85SMat Martineau */ 319336c86c85SMat Martineau 319436c86c85SMat Martineau /* Convert timeout to milliseconds and round */ 319536c86c85SMat Martineau ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000); 319636c86c85SMat Martineau 319736c86c85SMat Martineau /* This is the recommended formula for class 2 devices 319836c86c85SMat Martineau * that start ERTM timers when packets are sent to the 319936c86c85SMat Martineau * controller. 320036c86c85SMat Martineau */ 320136c86c85SMat Martineau ertm_to = 3 * ertm_to + 500; 320236c86c85SMat Martineau 320336c86c85SMat Martineau if (ertm_to > 0xffff) 320436c86c85SMat Martineau ertm_to = 0xffff; 320536c86c85SMat Martineau 320636c86c85SMat Martineau rfc->retrans_timeout = cpu_to_le16((u16) ertm_to); 320736c86c85SMat Martineau rfc->monitor_timeout = rfc->retrans_timeout; 320836c86c85SMat Martineau } else { 320936c86c85SMat Martineau rfc->retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 321036c86c85SMat Martineau rfc->monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 321136c86c85SMat Martineau } 321236c86c85SMat Martineau } 321336c86c85SMat Martineau 32146327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan) 32156327eb98SAndrei Emeltchenko { 32166327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && 3217848566b3SMarcel Holtmann __l2cap_ews_supported(chan->conn)) { 32186327eb98SAndrei Emeltchenko /* use extended control field */ 32196327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 3220836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 3221836be934SAndrei Emeltchenko } else { 32226327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win, 32236327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 3224836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 3225836be934SAndrei Emeltchenko } 3226c20f8e35SMat Martineau chan->ack_win = chan->tx_win; 32276327eb98SAndrei Emeltchenko } 32286327eb98SAndrei Emeltchenko 3229710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) 32300a708f8fSGustavo F. Padovan { 32310a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 32320c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode }; 32330a708f8fSGustavo F. Padovan void *ptr = req->data; 3234c8f79162SAndrei Emeltchenko u16 size; 32350a708f8fSGustavo F. Padovan 323649208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 32370a708f8fSGustavo F. Padovan 323873ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp) 32390a708f8fSGustavo F. Padovan goto done; 32400a708f8fSGustavo F. Padovan 32410c1bc5c6SGustavo F. Padovan switch (chan->mode) { 32420a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 32430a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3244c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) 32450a708f8fSGustavo F. Padovan break; 32460a708f8fSGustavo F. Padovan 3247848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn)) 3248f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 3249f89cef09SAndrei Emeltchenko 32500a708f8fSGustavo F. Padovan /* fall through */ 32510a708f8fSGustavo F. Padovan default: 32528c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); 32530a708f8fSGustavo F. Padovan break; 32540a708f8fSGustavo F. Padovan } 32550a708f8fSGustavo F. Padovan 32560a708f8fSGustavo F. Padovan done: 32570c1bc5c6SGustavo F. Padovan if (chan->imtu != L2CAP_DEFAULT_MTU) 32580c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 32590a708f8fSGustavo F. Padovan 32600c1bc5c6SGustavo F. Padovan switch (chan->mode) { 32610a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 32628c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && 32638c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) 32640a708f8fSGustavo F. Padovan break; 32650a708f8fSGustavo F. Padovan 32660a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC; 32670a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 32680a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 32690a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 32700a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 32710a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0; 32720a708f8fSGustavo F. Padovan 32730a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 32740a708f8fSGustavo F. Padovan (unsigned long) &rfc); 32750a708f8fSGustavo F. Padovan break; 32760a708f8fSGustavo F. Padovan 32770a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 32780a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM; 327947d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx; 328036c86c85SMat Martineau 328136c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc); 3282c8f79162SAndrei Emeltchenko 3283c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 32842d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - 3285c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3286c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 32870a708f8fSGustavo F. Padovan 32886327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan); 32896327eb98SAndrei Emeltchenko 32906327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win, 32916327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 32920a708f8fSGustavo F. Padovan 32930a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 32940a708f8fSGustavo F. Padovan (unsigned long) &rfc); 32950a708f8fSGustavo F. Padovan 3296f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 3297f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 3298f89cef09SAndrei Emeltchenko 32996327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 33006327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 33016327eb98SAndrei Emeltchenko chan->tx_win); 330260918918SAndrei Emeltchenko 330360918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS) 330460918918SAndrei Emeltchenko if (chan->fcs == L2CAP_FCS_NONE || 3305f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { 330660918918SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 330760918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, 330860918918SAndrei Emeltchenko chan->fcs); 330960918918SAndrei Emeltchenko } 33100a708f8fSGustavo F. Padovan break; 33110a708f8fSGustavo F. Padovan 33120a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3313273759e2SMat Martineau l2cap_txwin_setup(chan); 33140a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING; 33150a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 33160a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 33170a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 33180a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 3319c8f79162SAndrei Emeltchenko 3320c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 33212d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - 3322c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3323c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 33240a708f8fSGustavo F. Padovan 33250a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 33260a708f8fSGustavo F. Padovan (unsigned long) &rfc); 33270a708f8fSGustavo F. Padovan 3328f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 3329f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 3330f89cef09SAndrei Emeltchenko 333160918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS) 333247d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 3333f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { 333447d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 333560918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, 333660918918SAndrei Emeltchenko chan->fcs); 33370a708f8fSGustavo F. Padovan } 33380a708f8fSGustavo F. Padovan break; 33390a708f8fSGustavo F. Padovan } 33400a708f8fSGustavo F. Padovan 3341fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 334259e54bd1SAndrei Emeltchenko req->flags = __constant_cpu_to_le16(0); 33430a708f8fSGustavo F. Padovan 33440a708f8fSGustavo F. Padovan return ptr - data; 33450a708f8fSGustavo F. Padovan } 33460a708f8fSGustavo F. Padovan 334773ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) 33480a708f8fSGustavo F. Padovan { 33490a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 33500a708f8fSGustavo F. Padovan void *ptr = rsp->data; 335173ffa904SGustavo F. Padovan void *req = chan->conf_req; 335273ffa904SGustavo F. Padovan int len = chan->conf_len; 33530a708f8fSGustavo F. Padovan int type, hint, olen; 33540a708f8fSGustavo F. Padovan unsigned long val; 33550a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 335642dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs; 335742dceae2SAndrei Emeltchenko u8 remote_efs = 0; 33580a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU; 33590a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS; 3360c8f79162SAndrei Emeltchenko u16 size; 33610a708f8fSGustavo F. Padovan 336273ffa904SGustavo F. Padovan BT_DBG("chan %p", chan); 33630a708f8fSGustavo F. Padovan 33640a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 33650a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val); 33660a708f8fSGustavo F. Padovan 33670a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT; 33680a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK; 33690a708f8fSGustavo F. Padovan 33700a708f8fSGustavo F. Padovan switch (type) { 33710a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 33720a708f8fSGustavo F. Padovan mtu = val; 33730a708f8fSGustavo F. Padovan break; 33740a708f8fSGustavo F. Padovan 33750a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 33760c1bc5c6SGustavo F. Padovan chan->flush_to = val; 33770a708f8fSGustavo F. Padovan break; 33780a708f8fSGustavo F. Padovan 33790a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS: 33800a708f8fSGustavo F. Padovan break; 33810a708f8fSGustavo F. Padovan 33820a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 33830a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 33840a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen); 33850a708f8fSGustavo F. Padovan break; 33860a708f8fSGustavo F. Padovan 33870a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS: 33880a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE) 3389f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, &chan->conf_state); 339042dceae2SAndrei Emeltchenko break; 33910a708f8fSGustavo F. Padovan 339242dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS: 339342dceae2SAndrei Emeltchenko remote_efs = 1; 339442dceae2SAndrei Emeltchenko if (olen == sizeof(efs)) 339542dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen); 33960a708f8fSGustavo F. Padovan break; 33970a708f8fSGustavo F. Padovan 33986327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 3399848566b3SMarcel Holtmann if (!chan->conn->hs_enabled) 34006327eb98SAndrei Emeltchenko return -ECONNREFUSED; 34016327eb98SAndrei Emeltchenko 34026327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 34036327eb98SAndrei Emeltchenko set_bit(CONF_EWS_RECV, &chan->conf_state); 3404836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 34056327eb98SAndrei Emeltchenko chan->remote_tx_win = val; 34060a708f8fSGustavo F. Padovan break; 34070a708f8fSGustavo F. Padovan 34080a708f8fSGustavo F. Padovan default: 34090a708f8fSGustavo F. Padovan if (hint) 34100a708f8fSGustavo F. Padovan break; 34110a708f8fSGustavo F. Padovan 34120a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN; 34130a708f8fSGustavo F. Padovan *((u8 *) ptr++) = type; 34140a708f8fSGustavo F. Padovan break; 34150a708f8fSGustavo F. Padovan } 34160a708f8fSGustavo F. Padovan } 34170a708f8fSGustavo F. Padovan 341873ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1) 34190a708f8fSGustavo F. Padovan goto done; 34200a708f8fSGustavo F. Padovan 34210c1bc5c6SGustavo F. Padovan switch (chan->mode) { 34220a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 34230a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3424c1360a1cSGustavo F. Padovan if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { 34250c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, 34268c1d787bSGustavo F. Padovan chan->conn->feat_mask); 34270a708f8fSGustavo F. Padovan break; 34280a708f8fSGustavo F. Padovan } 34290a708f8fSGustavo F. Padovan 343042dceae2SAndrei Emeltchenko if (remote_efs) { 3431848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn)) 343242dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 343342dceae2SAndrei Emeltchenko else 343442dceae2SAndrei Emeltchenko return -ECONNREFUSED; 343542dceae2SAndrei Emeltchenko } 343642dceae2SAndrei Emeltchenko 34370c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) 34380a708f8fSGustavo F. Padovan return -ECONNREFUSED; 34390a708f8fSGustavo F. Padovan 34400a708f8fSGustavo F. Padovan break; 34410a708f8fSGustavo F. Padovan } 34420a708f8fSGustavo F. Padovan 34430a708f8fSGustavo F. Padovan done: 34440c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) { 34450a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 34460c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 34470a708f8fSGustavo F. Padovan 344873ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1) 34490a708f8fSGustavo F. Padovan return -ECONNREFUSED; 34500a708f8fSGustavo F. Padovan 34512d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 34522d792818SGustavo Padovan (unsigned long) &rfc); 34530a708f8fSGustavo F. Padovan } 34540a708f8fSGustavo F. Padovan 34550a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) { 34560a708f8fSGustavo F. Padovan /* Configure output options and let the other side know 34570a708f8fSGustavo F. Padovan * which ones we don't like. */ 34580a708f8fSGustavo F. Padovan 34590a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU) 34600a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 34610a708f8fSGustavo F. Padovan else { 34620c1bc5c6SGustavo F. Padovan chan->omtu = mtu; 3463c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state); 34640a708f8fSGustavo F. Padovan } 34650c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); 34660a708f8fSGustavo F. Padovan 346742dceae2SAndrei Emeltchenko if (remote_efs) { 346842dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 346942dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 347042dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) { 347142dceae2SAndrei Emeltchenko 347242dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT; 347342dceae2SAndrei Emeltchenko 347442dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1) 347542dceae2SAndrei Emeltchenko return -ECONNREFUSED; 347642dceae2SAndrei Emeltchenko 347742dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 347842dceae2SAndrei Emeltchenko sizeof(efs), 347942dceae2SAndrei Emeltchenko (unsigned long) &efs); 34800e8b207eSAndrei Emeltchenko } else { 34813e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */ 34820e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING; 34830e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 348442dceae2SAndrei Emeltchenko } 348542dceae2SAndrei Emeltchenko } 348642dceae2SAndrei Emeltchenko 34870a708f8fSGustavo F. Padovan switch (rfc.mode) { 34880a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 348947d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3490c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 34910a708f8fSGustavo F. Padovan break; 34920a708f8fSGustavo F. Padovan 34930a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 34946327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state)) 34952c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size; 34966327eb98SAndrei Emeltchenko else 34976327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; 34986327eb98SAndrei Emeltchenko 34992c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit; 35000a708f8fSGustavo F. Padovan 3501c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 35022d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE - 35032d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); 3504c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3505c8f79162SAndrei Emeltchenko chan->remote_mps = size; 35060a708f8fSGustavo F. Padovan 350736c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc); 35080a708f8fSGustavo F. Padovan 3509c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 35100a708f8fSGustavo F. Padovan 35110a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 35120a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 35130a708f8fSGustavo F. Padovan 351442dceae2SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 351542dceae2SAndrei Emeltchenko chan->remote_id = efs.id; 351642dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype; 351742dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu); 351842dceae2SAndrei Emeltchenko chan->remote_flush_to = 351942dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to); 352042dceae2SAndrei Emeltchenko chan->remote_acc_lat = 352142dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat); 352242dceae2SAndrei Emeltchenko chan->remote_sdu_itime = 352342dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 352442dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 35252d792818SGustavo Padovan sizeof(efs), 35262d792818SGustavo Padovan (unsigned long) &efs); 352742dceae2SAndrei Emeltchenko } 35280a708f8fSGustavo F. Padovan break; 35290a708f8fSGustavo F. Padovan 35300a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3531c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 35322d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE - 35332d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); 3534c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3535c8f79162SAndrei Emeltchenko chan->remote_mps = size; 35360a708f8fSGustavo F. Padovan 3537c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 35380a708f8fSGustavo F. Padovan 35392d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 35402d792818SGustavo Padovan (unsigned long) &rfc); 35410a708f8fSGustavo F. Padovan 35420a708f8fSGustavo F. Padovan break; 35430a708f8fSGustavo F. Padovan 35440a708f8fSGustavo F. Padovan default: 35450a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 35460a708f8fSGustavo F. Padovan 35470a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc)); 35480c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 35490a708f8fSGustavo F. Padovan } 35500a708f8fSGustavo F. Padovan 35510a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) 3552c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 35530a708f8fSGustavo F. Padovan } 3554fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 35550a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 355659e54bd1SAndrei Emeltchenko rsp->flags = __constant_cpu_to_le16(0); 35570a708f8fSGustavo F. Padovan 35580a708f8fSGustavo F. Padovan return ptr - data; 35590a708f8fSGustavo F. Padovan } 35600a708f8fSGustavo F. Padovan 35612d792818SGustavo Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, 35622d792818SGustavo Padovan void *data, u16 *result) 35630a708f8fSGustavo F. Padovan { 35640a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 35650a708f8fSGustavo F. Padovan void *ptr = req->data; 35660a708f8fSGustavo F. Padovan int type, olen; 35670a708f8fSGustavo F. Padovan unsigned long val; 356836e999a8SMat Martineau struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 356966af7aafSAndrei Emeltchenko struct l2cap_conf_efs efs; 35700a708f8fSGustavo F. Padovan 3571fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); 35720a708f8fSGustavo F. Padovan 35730a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 35740a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 35750a708f8fSGustavo F. Padovan 35760a708f8fSGustavo F. Padovan switch (type) { 35770a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 35780a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) { 35790a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT; 35800c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU; 35810a708f8fSGustavo F. Padovan } else 35820c1bc5c6SGustavo F. Padovan chan->imtu = val; 35830c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 35840a708f8fSGustavo F. Padovan break; 35850a708f8fSGustavo F. Padovan 35860a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 35870c1bc5c6SGustavo F. Padovan chan->flush_to = val; 35880a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 35890c1bc5c6SGustavo F. Padovan 2, chan->flush_to); 35900a708f8fSGustavo F. Padovan break; 35910a708f8fSGustavo F. Padovan 35920a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 35930a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 35940a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 35950a708f8fSGustavo F. Padovan 3596c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && 35970c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode) 35980a708f8fSGustavo F. Padovan return -ECONNREFUSED; 35990a708f8fSGustavo F. Padovan 360047d1ec61SGustavo F. Padovan chan->fcs = 0; 36010a708f8fSGustavo F. Padovan 36020a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 36030a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 36040a708f8fSGustavo F. Padovan break; 36056327eb98SAndrei Emeltchenko 36066327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 3607c20f8e35SMat Martineau chan->ack_win = min_t(u16, val, chan->ack_win); 36083e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 36093e6b3b95SGustavo F. Padovan chan->tx_win); 36106327eb98SAndrei Emeltchenko break; 361166af7aafSAndrei Emeltchenko 361266af7aafSAndrei Emeltchenko case L2CAP_CONF_EFS: 361366af7aafSAndrei Emeltchenko if (olen == sizeof(efs)) 361466af7aafSAndrei Emeltchenko memcpy(&efs, (void *)val, olen); 361566af7aafSAndrei Emeltchenko 361666af7aafSAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 361766af7aafSAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 361866af7aafSAndrei Emeltchenko efs.stype != chan->local_stype) 361966af7aafSAndrei Emeltchenko return -ECONNREFUSED; 362066af7aafSAndrei Emeltchenko 36212d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), 36222d792818SGustavo Padovan (unsigned long) &efs); 362366af7aafSAndrei Emeltchenko break; 3624cbabee78SAndrei Emeltchenko 3625cbabee78SAndrei Emeltchenko case L2CAP_CONF_FCS: 3626cbabee78SAndrei Emeltchenko if (*result == L2CAP_CONF_PENDING) 3627cbabee78SAndrei Emeltchenko if (val == L2CAP_FCS_NONE) 3628f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, 3629cbabee78SAndrei Emeltchenko &chan->conf_state); 3630cbabee78SAndrei Emeltchenko break; 36310a708f8fSGustavo F. Padovan } 36320a708f8fSGustavo F. Padovan } 36330a708f8fSGustavo F. Padovan 36340c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) 36350a708f8fSGustavo F. Padovan return -ECONNREFUSED; 36360a708f8fSGustavo F. Padovan 36370c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode; 36380a708f8fSGustavo F. Padovan 36390e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) { 36400a708f8fSGustavo F. Padovan switch (rfc.mode) { 36410a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 364247d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 364347d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 364447d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 3645c20f8e35SMat Martineau if (!test_bit(FLAG_EXT_CTRL, &chan->flags)) 3646c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 3647c20f8e35SMat Martineau rfc.txwin_size); 364866af7aafSAndrei Emeltchenko 364966af7aafSAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 365066af7aafSAndrei Emeltchenko chan->local_msdu = le16_to_cpu(efs.msdu); 365166af7aafSAndrei Emeltchenko chan->local_sdu_itime = 365266af7aafSAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 365366af7aafSAndrei Emeltchenko chan->local_acc_lat = le32_to_cpu(efs.acc_lat); 365466af7aafSAndrei Emeltchenko chan->local_flush_to = 365566af7aafSAndrei Emeltchenko le32_to_cpu(efs.flush_to); 365666af7aafSAndrei Emeltchenko } 36570a708f8fSGustavo F. Padovan break; 365866af7aafSAndrei Emeltchenko 36590a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 366047d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 36610a708f8fSGustavo F. Padovan } 36620a708f8fSGustavo F. Padovan } 36630a708f8fSGustavo F. Padovan 3664fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 366559e54bd1SAndrei Emeltchenko req->flags = __constant_cpu_to_le16(0); 36660a708f8fSGustavo F. Padovan 36670a708f8fSGustavo F. Padovan return ptr - data; 36680a708f8fSGustavo F. Padovan } 36690a708f8fSGustavo F. Padovan 36702d792818SGustavo Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, 36712d792818SGustavo Padovan u16 result, u16 flags) 36720a708f8fSGustavo F. Padovan { 36730a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 36740a708f8fSGustavo F. Padovan void *ptr = rsp->data; 36750a708f8fSGustavo F. Padovan 3676fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan); 36770a708f8fSGustavo F. Padovan 3678fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 36790a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 36800a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags); 36810a708f8fSGustavo F. Padovan 36820a708f8fSGustavo F. Padovan return ptr - data; 36830a708f8fSGustavo F. Padovan } 36840a708f8fSGustavo F. Padovan 368527e2d4c8SJohan Hedberg void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan) 368627e2d4c8SJohan Hedberg { 368727e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 368827e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn; 368927e2d4c8SJohan Hedberg 369027e2d4c8SJohan Hedberg BT_DBG("chan %p", chan); 369127e2d4c8SJohan Hedberg 369227e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 369327e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 369427e2d4c8SJohan Hedberg rsp.mps = __constant_cpu_to_le16(L2CAP_LE_DEFAULT_MPS); 36950cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits); 369627e2d4c8SJohan Hedberg rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 369727e2d4c8SJohan Hedberg 369827e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), 369927e2d4c8SJohan Hedberg &rsp); 370027e2d4c8SJohan Hedberg } 370127e2d4c8SJohan Hedberg 37028c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) 3703710f9b0aSGustavo F. Padovan { 3704710f9b0aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 37058c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 3706710f9b0aSGustavo F. Padovan u8 buf[128]; 3707439f34acSAndrei Emeltchenko u8 rsp_code; 3708710f9b0aSGustavo F. Padovan 3709fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 3710fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3711ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 3712ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 3713439f34acSAndrei Emeltchenko 3714439f34acSAndrei Emeltchenko if (chan->hs_hcon) 3715439f34acSAndrei Emeltchenko rsp_code = L2CAP_CREATE_CHAN_RSP; 3716439f34acSAndrei Emeltchenko else 3717439f34acSAndrei Emeltchenko rsp_code = L2CAP_CONN_RSP; 3718439f34acSAndrei Emeltchenko 3719439f34acSAndrei Emeltchenko BT_DBG("chan %p rsp_code %u", chan, rsp_code); 3720439f34acSAndrei Emeltchenko 3721439f34acSAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp); 3722710f9b0aSGustavo F. Padovan 3723c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 3724710f9b0aSGustavo F. Padovan return; 3725710f9b0aSGustavo F. Padovan 3726710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 3727710f9b0aSGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 3728710f9b0aSGustavo F. Padovan chan->num_conf_req++; 3729710f9b0aSGustavo F. Padovan } 3730710f9b0aSGustavo F. Padovan 373147d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) 37320a708f8fSGustavo F. Padovan { 37330a708f8fSGustavo F. Padovan int type, olen; 37340a708f8fSGustavo F. Padovan unsigned long val; 3735c20f8e35SMat Martineau /* Use sane default values in case a misbehaving remote device 3736c20f8e35SMat Martineau * did not send an RFC or extended window size option. 3737c20f8e35SMat Martineau */ 3738c20f8e35SMat Martineau u16 txwin_ext = chan->ack_win; 3739c20f8e35SMat Martineau struct l2cap_conf_rfc rfc = { 3740c20f8e35SMat Martineau .mode = chan->mode, 3741c20f8e35SMat Martineau .retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO), 3742c20f8e35SMat Martineau .monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO), 3743c20f8e35SMat Martineau .max_pdu_size = cpu_to_le16(chan->imtu), 3744c20f8e35SMat Martineau .txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW), 3745c20f8e35SMat Martineau }; 37460a708f8fSGustavo F. Padovan 374747d1ec61SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); 37480a708f8fSGustavo F. Padovan 37490c1bc5c6SGustavo F. Padovan if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) 37500a708f8fSGustavo F. Padovan return; 37510a708f8fSGustavo F. Padovan 37520a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 37530a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 37540a708f8fSGustavo F. Padovan 3755c20f8e35SMat Martineau switch (type) { 3756c20f8e35SMat Martineau case L2CAP_CONF_RFC: 3757c20f8e35SMat Martineau if (olen == sizeof(rfc)) 37580a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 3759c20f8e35SMat Martineau break; 3760c20f8e35SMat Martineau case L2CAP_CONF_EWS: 3761c20f8e35SMat Martineau txwin_ext = val; 3762c20f8e35SMat Martineau break; 3763c20f8e35SMat Martineau } 37640a708f8fSGustavo F. Padovan } 37650a708f8fSGustavo F. Padovan 37660a708f8fSGustavo F. Padovan switch (rfc.mode) { 37670a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 376847d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 376947d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 377047d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 3771c20f8e35SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 3772c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, txwin_ext); 3773c20f8e35SMat Martineau else 3774c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 3775c20f8e35SMat Martineau rfc.txwin_size); 37760a708f8fSGustavo F. Padovan break; 37770a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 377847d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 37790a708f8fSGustavo F. Padovan } 37800a708f8fSGustavo F. Padovan } 37810a708f8fSGustavo F. Padovan 37822d792818SGustavo Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, 3783cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 3784cb3b3152SJohan Hedberg u8 *data) 37850a708f8fSGustavo F. Padovan { 3786e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 37870a708f8fSGustavo F. Padovan 3788cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rej)) 3789cb3b3152SJohan Hedberg return -EPROTO; 3790cb3b3152SJohan Hedberg 3791e2fd318eSIlia Kolomisnky if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) 37920a708f8fSGustavo F. Padovan return 0; 37930a708f8fSGustavo F. Padovan 37940a708f8fSGustavo F. Padovan if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && 37950a708f8fSGustavo F. Padovan cmd->ident == conn->info_ident) { 379617cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 37970a708f8fSGustavo F. Padovan 37980a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 37990a708f8fSGustavo F. Padovan conn->info_ident = 0; 38000a708f8fSGustavo F. Padovan 38010a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 38020a708f8fSGustavo F. Padovan } 38030a708f8fSGustavo F. Padovan 38040a708f8fSGustavo F. Padovan return 0; 38050a708f8fSGustavo F. Padovan } 38060a708f8fSGustavo F. Padovan 38071700915fSMat Martineau static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, 38081700915fSMat Martineau struct l2cap_cmd_hdr *cmd, 38094c89b6aaSMat Martineau u8 *data, u8 rsp_code, u8 amp_id) 38100a708f8fSGustavo F. Padovan { 38110a708f8fSGustavo F. Padovan struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 38120a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 381323691d75SGustavo F. Padovan struct l2cap_chan *chan = NULL, *pchan; 38140a708f8fSGustavo F. Padovan int result, status = L2CAP_CS_NO_INFO; 38150a708f8fSGustavo F. Padovan 38160a708f8fSGustavo F. Padovan u16 dcid = 0, scid = __le16_to_cpu(req->scid); 38170a708f8fSGustavo F. Padovan __le16 psm = req->psm; 38180a708f8fSGustavo F. Padovan 3819097db76cSAndrei Emeltchenko BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); 38200a708f8fSGustavo F. Padovan 38210a708f8fSGustavo F. Padovan /* Check if we have socket listening on psm */ 38226f59b904SMarcel Holtmann pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 3823bf20fd4eSJohan Hedberg &conn->hcon->dst, ACL_LINK); 382423691d75SGustavo F. Padovan if (!pchan) { 38250a708f8fSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 38260a708f8fSGustavo F. Padovan goto sendresp; 38270a708f8fSGustavo F. Padovan } 38280a708f8fSGustavo F. Padovan 38293df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 38308ffb9290SGustavo Padovan l2cap_chan_lock(pchan); 38310a708f8fSGustavo F. Padovan 38320a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */ 38332983fd68SAndrei Emeltchenko if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) && 38340a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) { 38359f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_AUTH_FAILURE; 38360a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 38370a708f8fSGustavo F. Padovan goto response; 38380a708f8fSGustavo F. Padovan } 38390a708f8fSGustavo F. Padovan 38400a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM; 38410a708f8fSGustavo F. Padovan 38422dfa1003SGustavo Padovan /* Check if we already have channel with that dcid */ 38432dfa1003SGustavo Padovan if (__l2cap_get_chan_by_dcid(conn, scid)) 38442dfa1003SGustavo Padovan goto response; 38452dfa1003SGustavo Padovan 384680b98027SGustavo Padovan chan = pchan->ops->new_connection(pchan); 384780808e43SGustavo F. Padovan if (!chan) 38480a708f8fSGustavo F. Padovan goto response; 38490a708f8fSGustavo F. Padovan 3850330b6c15SSyam Sidhardhan /* For certain devices (ex: HID mouse), support for authentication, 3851330b6c15SSyam Sidhardhan * pairing and bonding is optional. For such devices, inorder to avoid 3852330b6c15SSyam Sidhardhan * the ACL alive for too long after L2CAP disconnection, reset the ACL 3853330b6c15SSyam Sidhardhan * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect. 3854330b6c15SSyam Sidhardhan */ 3855330b6c15SSyam Sidhardhan conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 3856330b6c15SSyam Sidhardhan 38577eafc59eSMarcel Holtmann bacpy(&chan->src, &conn->hcon->src); 38587eafc59eSMarcel Holtmann bacpy(&chan->dst, &conn->hcon->dst); 38594f1654e0SMarcel Holtmann chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type); 38604f1654e0SMarcel Holtmann chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type); 3861fe4128e0SGustavo F. Padovan chan->psm = psm; 3862fe4128e0SGustavo F. Padovan chan->dcid = scid; 38631700915fSMat Martineau chan->local_amp_id = amp_id; 38640a708f8fSGustavo F. Padovan 38656be36555SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 386648454079SGustavo F. Padovan 3867fe4128e0SGustavo F. Padovan dcid = chan->scid; 38680a708f8fSGustavo F. Padovan 38698d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 38700a708f8fSGustavo F. Padovan 3871fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident; 38720a708f8fSGustavo F. Padovan 38730a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { 3874d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 3875bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 3876f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 38770a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 38780a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND; 38792dc4e510SGustavo Padovan chan->ops->defer(chan); 38800a708f8fSGustavo F. Padovan } else { 38811700915fSMat Martineau /* Force pending result for AMP controllers. 38821700915fSMat Martineau * The connection will succeed after the 38831700915fSMat Martineau * physical link is up. 38841700915fSMat Martineau */ 38856ed971caSMarcel Holtmann if (amp_id == AMP_ID_BREDR) { 3886f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 38870a708f8fSGustavo F. Padovan result = L2CAP_CR_SUCCESS; 38886ed971caSMarcel Holtmann } else { 3889f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 38906ed971caSMarcel Holtmann result = L2CAP_CR_PEND; 38911700915fSMat Martineau } 38920a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 38930a708f8fSGustavo F. Padovan } 38940a708f8fSGustavo F. Padovan } else { 3895f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 38960a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 38970a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND; 38980a708f8fSGustavo F. Padovan } 38990a708f8fSGustavo F. Padovan } else { 3900f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 39010a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 39020a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 39030a708f8fSGustavo F. Padovan } 39040a708f8fSGustavo F. Padovan 39050a708f8fSGustavo F. Padovan response: 39068ffb9290SGustavo Padovan l2cap_chan_unlock(pchan); 39073df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 39080a708f8fSGustavo F. Padovan 39090a708f8fSGustavo F. Padovan sendresp: 39100a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid); 39110a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid); 39120a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result); 39130a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status); 39144c89b6aaSMat Martineau l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp); 39150a708f8fSGustavo F. Padovan 39160a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { 39170a708f8fSGustavo F. Padovan struct l2cap_info_req info; 3918ac73498cSAndrei Emeltchenko info.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); 39190a708f8fSGustavo F. Padovan 39200a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 39210a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 39220a708f8fSGustavo F. Padovan 3923ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 39240a708f8fSGustavo F. Padovan 39252d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, 39262d792818SGustavo Padovan sizeof(info), &info); 39270a708f8fSGustavo F. Padovan } 39280a708f8fSGustavo F. Padovan 3929c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && 39300a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) { 39310a708f8fSGustavo F. Padovan u8 buf[128]; 3932c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 39330a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 393473ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 393573ffa904SGustavo F. Padovan chan->num_conf_req++; 39360a708f8fSGustavo F. Padovan } 39371700915fSMat Martineau 39381700915fSMat Martineau return chan; 39394c89b6aaSMat Martineau } 39400a708f8fSGustavo F. Padovan 39414c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn, 3942cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 39434c89b6aaSMat Martineau { 39447b064edaSJaganath Kanakkassery struct hci_dev *hdev = conn->hcon->hdev; 39457b064edaSJaganath Kanakkassery struct hci_conn *hcon = conn->hcon; 39467b064edaSJaganath Kanakkassery 3947cb3b3152SJohan Hedberg if (cmd_len < sizeof(struct l2cap_conn_req)) 3948cb3b3152SJohan Hedberg return -EPROTO; 3949cb3b3152SJohan Hedberg 39507b064edaSJaganath Kanakkassery hci_dev_lock(hdev); 39517b064edaSJaganath Kanakkassery if (test_bit(HCI_MGMT, &hdev->dev_flags) && 39527b064edaSJaganath Kanakkassery !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags)) 39537b064edaSJaganath Kanakkassery mgmt_device_connected(hdev, &hcon->dst, hcon->type, 39547b064edaSJaganath Kanakkassery hcon->dst_type, 0, NULL, 0, 39557b064edaSJaganath Kanakkassery hcon->dev_class); 39567b064edaSJaganath Kanakkassery hci_dev_unlock(hdev); 39577b064edaSJaganath Kanakkassery 3958300229f9SGustavo Padovan l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0); 39590a708f8fSGustavo F. Padovan return 0; 39600a708f8fSGustavo F. Padovan } 39610a708f8fSGustavo F. Padovan 39625909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn, 3963cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 3964cb3b3152SJohan Hedberg u8 *data) 39650a708f8fSGustavo F. Padovan { 39660a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; 39670a708f8fSGustavo F. Padovan u16 scid, dcid, result, status; 396848454079SGustavo F. Padovan struct l2cap_chan *chan; 39690a708f8fSGustavo F. Padovan u8 req[128]; 39703df91ea2SAndrei Emeltchenko int err; 39710a708f8fSGustavo F. Padovan 3972cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp)) 3973cb3b3152SJohan Hedberg return -EPROTO; 3974cb3b3152SJohan Hedberg 39750a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 39760a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 39770a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 39780a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status); 39790a708f8fSGustavo F. Padovan 39801b009c98SAndrei Emeltchenko BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", 39811b009c98SAndrei Emeltchenko dcid, scid, result, status); 39820a708f8fSGustavo F. Padovan 39833df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 39843df91ea2SAndrei Emeltchenko 39850a708f8fSGustavo F. Padovan if (scid) { 39863df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 39873df91ea2SAndrei Emeltchenko if (!chan) { 398821870b52SJohan Hedberg err = -EBADSLT; 39893df91ea2SAndrei Emeltchenko goto unlock; 39903df91ea2SAndrei Emeltchenko } 39910a708f8fSGustavo F. Padovan } else { 39923df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 39933df91ea2SAndrei Emeltchenko if (!chan) { 399421870b52SJohan Hedberg err = -EBADSLT; 39953df91ea2SAndrei Emeltchenko goto unlock; 39963df91ea2SAndrei Emeltchenko } 39970a708f8fSGustavo F. Padovan } 39980a708f8fSGustavo F. Padovan 39993df91ea2SAndrei Emeltchenko err = 0; 40003df91ea2SAndrei Emeltchenko 40016be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 400248454079SGustavo F. Padovan 40030a708f8fSGustavo F. Padovan switch (result) { 40040a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS: 400589bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 4006fc7f8a7eSGustavo F. Padovan chan->ident = 0; 4007fe4128e0SGustavo F. Padovan chan->dcid = dcid; 4008c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state); 40090a708f8fSGustavo F. Padovan 4010c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 40110a708f8fSGustavo F. Padovan break; 40120a708f8fSGustavo F. Padovan 40130a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 401473ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, req), req); 401573ffa904SGustavo F. Padovan chan->num_conf_req++; 40160a708f8fSGustavo F. Padovan break; 40170a708f8fSGustavo F. Padovan 40180a708f8fSGustavo F. Padovan case L2CAP_CR_PEND: 4019c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 40200a708f8fSGustavo F. Padovan break; 40210a708f8fSGustavo F. Padovan 40220a708f8fSGustavo F. Padovan default: 402348454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED); 40240a708f8fSGustavo F. Padovan break; 40250a708f8fSGustavo F. Padovan } 40260a708f8fSGustavo F. Padovan 40276be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 40283df91ea2SAndrei Emeltchenko 40293df91ea2SAndrei Emeltchenko unlock: 40303df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 40313df91ea2SAndrei Emeltchenko 40323df91ea2SAndrei Emeltchenko return err; 40330a708f8fSGustavo F. Padovan } 40340a708f8fSGustavo F. Padovan 403547d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan) 40360a708f8fSGustavo F. Padovan { 40370a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both 40380a708f8fSGustavo F. Padovan * sides request it. 40390a708f8fSGustavo F. Padovan */ 40400c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) 404147d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 4042f2592d3eSAndrei Emeltchenko else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) 404347d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16; 40440a708f8fSGustavo F. Padovan } 40450a708f8fSGustavo F. Padovan 404629d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data, 404729d8a590SAndrei Emeltchenko u8 ident, u16 flags) 404829d8a590SAndrei Emeltchenko { 404929d8a590SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 405029d8a590SAndrei Emeltchenko 405129d8a590SAndrei Emeltchenko BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident, 405229d8a590SAndrei Emeltchenko flags); 405329d8a590SAndrei Emeltchenko 405429d8a590SAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 405529d8a590SAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 405629d8a590SAndrei Emeltchenko 405729d8a590SAndrei Emeltchenko l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP, 405829d8a590SAndrei Emeltchenko l2cap_build_conf_rsp(chan, data, 405929d8a590SAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), data); 406029d8a590SAndrei Emeltchenko } 406129d8a590SAndrei Emeltchenko 4062662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident, 4063662d652dSJohan Hedberg u16 scid, u16 dcid) 4064662d652dSJohan Hedberg { 4065662d652dSJohan Hedberg struct l2cap_cmd_rej_cid rej; 4066662d652dSJohan Hedberg 4067662d652dSJohan Hedberg rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID); 4068662d652dSJohan Hedberg rej.scid = __cpu_to_le16(scid); 4069662d652dSJohan Hedberg rej.dcid = __cpu_to_le16(dcid); 4070662d652dSJohan Hedberg 4071662d652dSJohan Hedberg l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); 4072662d652dSJohan Hedberg } 4073662d652dSJohan Hedberg 40742d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, 40752d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len, 40762d792818SGustavo Padovan u8 *data) 40770a708f8fSGustavo F. Padovan { 40780a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; 40790a708f8fSGustavo F. Padovan u16 dcid, flags; 40800a708f8fSGustavo F. Padovan u8 rsp[64]; 408148454079SGustavo F. Padovan struct l2cap_chan *chan; 40823c588192SMat Martineau int len, err = 0; 40830a708f8fSGustavo F. Padovan 4084cb3b3152SJohan Hedberg if (cmd_len < sizeof(*req)) 4085cb3b3152SJohan Hedberg return -EPROTO; 4086cb3b3152SJohan Hedberg 40870a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 40880a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags); 40890a708f8fSGustavo F. Padovan 40900a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); 40910a708f8fSGustavo F. Padovan 4092baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid); 4093662d652dSJohan Hedberg if (!chan) { 4094662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0); 4095662d652dSJohan Hedberg return 0; 4096662d652dSJohan Hedberg } 40970a708f8fSGustavo F. Padovan 4098033b1142SDavid S. Miller if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { 4099662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, 4100662d652dSJohan Hedberg chan->dcid); 41010a708f8fSGustavo F. Padovan goto unlock; 41020a708f8fSGustavo F. Padovan } 41030a708f8fSGustavo F. Padovan 41040a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */ 41050a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req); 4106cb3b3152SJohan Hedberg if (chan->conf_len + len > sizeof(chan->conf_req)) { 41070a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 4108fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 41090a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp); 41100a708f8fSGustavo F. Padovan goto unlock; 41110a708f8fSGustavo F. Padovan } 41120a708f8fSGustavo F. Padovan 41130a708f8fSGustavo F. Padovan /* Store config. */ 411473ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len); 411573ffa904SGustavo F. Padovan chan->conf_len += len; 41160a708f8fSGustavo F. Padovan 411759e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) { 41180a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */ 41190a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 4120fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 41215325e5bbSAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), rsp); 41220a708f8fSGustavo F. Padovan goto unlock; 41230a708f8fSGustavo F. Padovan } 41240a708f8fSGustavo F. Padovan 41250a708f8fSGustavo F. Padovan /* Complete config. */ 412673ffa904SGustavo F. Padovan len = l2cap_parse_conf_req(chan, rsp); 41270a708f8fSGustavo F. Padovan if (len < 0) { 41285e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 41290a708f8fSGustavo F. Padovan goto unlock; 41300a708f8fSGustavo F. Padovan } 41310a708f8fSGustavo F. Padovan 41321500109bSMat Martineau chan->ident = cmd->ident; 41330a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); 413473ffa904SGustavo F. Padovan chan->num_conf_rsp++; 41350a708f8fSGustavo F. Padovan 41360a708f8fSGustavo F. Padovan /* Reset config buffer. */ 413773ffa904SGustavo F. Padovan chan->conf_len = 0; 41380a708f8fSGustavo F. Padovan 4139c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) 41400a708f8fSGustavo F. Padovan goto unlock; 41410a708f8fSGustavo F. Padovan 4142c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 414347d1ec61SGustavo F. Padovan set_default_fcs(chan); 41440a708f8fSGustavo F. Padovan 4145105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 4146105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 41473c588192SMat Martineau err = l2cap_ertm_init(chan); 41480a708f8fSGustavo F. Padovan 41493c588192SMat Martineau if (err < 0) 41505e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 41513c588192SMat Martineau else 4152cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 41533c588192SMat Martineau 41540a708f8fSGustavo F. Padovan goto unlock; 41550a708f8fSGustavo F. Padovan } 41560a708f8fSGustavo F. Padovan 4157c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { 41580a708f8fSGustavo F. Padovan u8 buf[64]; 41590a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 416073ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 416173ffa904SGustavo F. Padovan chan->num_conf_req++; 41620a708f8fSGustavo F. Padovan } 41630a708f8fSGustavo F. Padovan 41640e8b207eSAndrei Emeltchenko /* Got Conf Rsp PENDING from remote side and asume we sent 41650e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */ 41660e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && 41670e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 41680e8b207eSAndrei Emeltchenko 41690e8b207eSAndrei Emeltchenko /* check compatibility */ 41700e8b207eSAndrei Emeltchenko 417179de886dSAndrei Emeltchenko /* Send rsp for BR/EDR channel */ 4172f351bc72SAndrei Emeltchenko if (!chan->hs_hcon) 417329d8a590SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags); 417479de886dSAndrei Emeltchenko else 417579de886dSAndrei Emeltchenko chan->ident = cmd->ident; 41760e8b207eSAndrei Emeltchenko } 41770e8b207eSAndrei Emeltchenko 41780a708f8fSGustavo F. Padovan unlock: 41796be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 41803c588192SMat Martineau return err; 41810a708f8fSGustavo F. Padovan } 41820a708f8fSGustavo F. Padovan 41832d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, 4184cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4185cb3b3152SJohan Hedberg u8 *data) 41860a708f8fSGustavo F. Padovan { 41870a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; 41880a708f8fSGustavo F. Padovan u16 scid, flags, result; 418948454079SGustavo F. Padovan struct l2cap_chan *chan; 4190cb3b3152SJohan Hedberg int len = cmd_len - sizeof(*rsp); 41913c588192SMat Martineau int err = 0; 41920a708f8fSGustavo F. Padovan 4193cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp)) 4194cb3b3152SJohan Hedberg return -EPROTO; 4195cb3b3152SJohan Hedberg 41960a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 41970a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags); 41980a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 41990a708f8fSGustavo F. Padovan 420061386cbaSAndrei Emeltchenko BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags, 420161386cbaSAndrei Emeltchenko result, len); 42020a708f8fSGustavo F. Padovan 4203baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 420448454079SGustavo F. Padovan if (!chan) 42050a708f8fSGustavo F. Padovan return 0; 42060a708f8fSGustavo F. Padovan 42070a708f8fSGustavo F. Padovan switch (result) { 42080a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS: 420947d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len); 42100e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state); 42110a708f8fSGustavo F. Padovan break; 42120a708f8fSGustavo F. Padovan 42130e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING: 42140e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state); 42150e8b207eSAndrei Emeltchenko 42160e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 42170e8b207eSAndrei Emeltchenko char buf[64]; 42180e8b207eSAndrei Emeltchenko 42190e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len, 42200e8b207eSAndrei Emeltchenko buf, &result); 42210e8b207eSAndrei Emeltchenko if (len < 0) { 42225e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 42230e8b207eSAndrei Emeltchenko goto done; 42240e8b207eSAndrei Emeltchenko } 42250e8b207eSAndrei Emeltchenko 4226f351bc72SAndrei Emeltchenko if (!chan->hs_hcon) { 422779de886dSAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, buf, cmd->ident, 422879de886dSAndrei Emeltchenko 0); 42295ce66b59SAndrei Emeltchenko } else { 42305ce66b59SAndrei Emeltchenko if (l2cap_check_efs(chan)) { 42315ce66b59SAndrei Emeltchenko amp_create_logical_link(chan); 423279de886dSAndrei Emeltchenko chan->ident = cmd->ident; 42330e8b207eSAndrei Emeltchenko } 42345ce66b59SAndrei Emeltchenko } 42355ce66b59SAndrei Emeltchenko } 42360e8b207eSAndrei Emeltchenko goto done; 42370e8b207eSAndrei Emeltchenko 42380a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT: 423973ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { 42400a708f8fSGustavo F. Padovan char req[64]; 42410a708f8fSGustavo F. Padovan 42420a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { 42435e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 42440a708f8fSGustavo F. Padovan goto done; 42450a708f8fSGustavo F. Padovan } 42460a708f8fSGustavo F. Padovan 42470a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */ 42480a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS; 4249b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len, 4250b4450035SGustavo F. Padovan req, &result); 42510a708f8fSGustavo F. Padovan if (len < 0) { 42525e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 42530a708f8fSGustavo F. Padovan goto done; 42540a708f8fSGustavo F. Padovan } 42550a708f8fSGustavo F. Padovan 42560a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 42570a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req); 425873ffa904SGustavo F. Padovan chan->num_conf_req++; 42590a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS) 42600a708f8fSGustavo F. Padovan goto done; 42610a708f8fSGustavo F. Padovan break; 42620a708f8fSGustavo F. Padovan } 42630a708f8fSGustavo F. Padovan 42640a708f8fSGustavo F. Padovan default: 42656be36555SAndrei Emeltchenko l2cap_chan_set_err(chan, ECONNRESET); 42662e0052e4SAndrei Emeltchenko 4267ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); 42685e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 42690a708f8fSGustavo F. Padovan goto done; 42700a708f8fSGustavo F. Padovan } 42710a708f8fSGustavo F. Padovan 427259e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) 42730a708f8fSGustavo F. Padovan goto done; 42740a708f8fSGustavo F. Padovan 4275c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state); 42760a708f8fSGustavo F. Padovan 4277c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { 427847d1ec61SGustavo F. Padovan set_default_fcs(chan); 42790a708f8fSGustavo F. Padovan 4280105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 4281105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 42823c588192SMat Martineau err = l2cap_ertm_init(chan); 42830a708f8fSGustavo F. Padovan 42843c588192SMat Martineau if (err < 0) 42855e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 42863c588192SMat Martineau else 4287cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 42880a708f8fSGustavo F. Padovan } 42890a708f8fSGustavo F. Padovan 42900a708f8fSGustavo F. Padovan done: 42916be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 42923c588192SMat Martineau return err; 42930a708f8fSGustavo F. Padovan } 42940a708f8fSGustavo F. Padovan 42952d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, 4296cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4297cb3b3152SJohan Hedberg u8 *data) 42980a708f8fSGustavo F. Padovan { 42990a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; 43000a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp; 43010a708f8fSGustavo F. Padovan u16 dcid, scid; 430248454079SGustavo F. Padovan struct l2cap_chan *chan; 43030a708f8fSGustavo F. Padovan 4304cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req)) 4305cb3b3152SJohan Hedberg return -EPROTO; 4306cb3b3152SJohan Hedberg 43070a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid); 43080a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 43090a708f8fSGustavo F. Padovan 43100a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); 43110a708f8fSGustavo F. Padovan 43123df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 43133df91ea2SAndrei Emeltchenko 43143df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, dcid); 43153df91ea2SAndrei Emeltchenko if (!chan) { 43163df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4317662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid); 4318662d652dSJohan Hedberg return 0; 43193df91ea2SAndrei Emeltchenko } 43200a708f8fSGustavo F. Padovan 43216be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 43226be36555SAndrei Emeltchenko 4323fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 4324fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 43250a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); 43260a708f8fSGustavo F. Padovan 43275ec1bbe5SGustavo Padovan chan->ops->set_shutdown(chan); 43280a708f8fSGustavo F. Padovan 432961d6ef3eSMat Martineau l2cap_chan_hold(chan); 433048454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET); 43316be36555SAndrei Emeltchenko 43326be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 43330a708f8fSGustavo F. Padovan 433480b98027SGustavo Padovan chan->ops->close(chan); 433561d6ef3eSMat Martineau l2cap_chan_put(chan); 43363df91ea2SAndrei Emeltchenko 43373df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 43383df91ea2SAndrei Emeltchenko 43390a708f8fSGustavo F. Padovan return 0; 43400a708f8fSGustavo F. Padovan } 43410a708f8fSGustavo F. Padovan 43422d792818SGustavo Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, 4343cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4344cb3b3152SJohan Hedberg u8 *data) 43450a708f8fSGustavo F. Padovan { 43460a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; 43470a708f8fSGustavo F. Padovan u16 dcid, scid; 434848454079SGustavo F. Padovan struct l2cap_chan *chan; 43490a708f8fSGustavo F. Padovan 4350cb3b3152SJohan Hedberg if (cmd_len != sizeof(*rsp)) 4351cb3b3152SJohan Hedberg return -EPROTO; 4352cb3b3152SJohan Hedberg 43530a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 43540a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 43550a708f8fSGustavo F. Padovan 43560a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); 43570a708f8fSGustavo F. Padovan 43583df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 43593df91ea2SAndrei Emeltchenko 43603df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 43613df91ea2SAndrei Emeltchenko if (!chan) { 43623df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 43630a708f8fSGustavo F. Padovan return 0; 43643df91ea2SAndrei Emeltchenko } 43650a708f8fSGustavo F. Padovan 43666be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 436748454079SGustavo F. Padovan 436861d6ef3eSMat Martineau l2cap_chan_hold(chan); 436948454079SGustavo F. Padovan l2cap_chan_del(chan, 0); 43706be36555SAndrei Emeltchenko 43716be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 43720a708f8fSGustavo F. Padovan 437380b98027SGustavo Padovan chan->ops->close(chan); 437461d6ef3eSMat Martineau l2cap_chan_put(chan); 43753df91ea2SAndrei Emeltchenko 43763df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 43773df91ea2SAndrei Emeltchenko 43780a708f8fSGustavo F. Padovan return 0; 43790a708f8fSGustavo F. Padovan } 43800a708f8fSGustavo F. Padovan 43812d792818SGustavo Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, 4382cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4383cb3b3152SJohan Hedberg u8 *data) 43840a708f8fSGustavo F. Padovan { 43850a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data; 43860a708f8fSGustavo F. Padovan u16 type; 43870a708f8fSGustavo F. Padovan 4388cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req)) 4389cb3b3152SJohan Hedberg return -EPROTO; 4390cb3b3152SJohan Hedberg 43910a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type); 43920a708f8fSGustavo F. Padovan 43930a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type); 43940a708f8fSGustavo F. Padovan 43950a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) { 43960a708f8fSGustavo F. Padovan u8 buf[8]; 43970a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask; 43980a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 4399ac73498cSAndrei Emeltchenko rsp->type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); 4400ac73498cSAndrei Emeltchenko rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); 44010a708f8fSGustavo F. Padovan if (!disable_ertm) 44020a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING 44030a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS; 4404848566b3SMarcel Holtmann if (conn->hs_enabled) 44056327eb98SAndrei Emeltchenko feat_mask |= L2CAP_FEAT_EXT_FLOW 44066327eb98SAndrei Emeltchenko | L2CAP_FEAT_EXT_WINDOW; 4407a5fd6f30SAndrei Emeltchenko 44080a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data); 44092d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), 44102d792818SGustavo Padovan buf); 44110a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) { 44120a708f8fSGustavo F. Padovan u8 buf[12]; 44130a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 441450a147cdSMat Martineau 4415848566b3SMarcel Holtmann if (conn->hs_enabled) 441650a147cdSMat Martineau l2cap_fixed_chan[0] |= L2CAP_FC_A2MP; 441750a147cdSMat Martineau else 441850a147cdSMat Martineau l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP; 441950a147cdSMat Martineau 4420ac73498cSAndrei Emeltchenko rsp->type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); 4421ac73498cSAndrei Emeltchenko rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); 4422c6337ea6SAndrei Emeltchenko memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); 44232d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), 44242d792818SGustavo Padovan buf); 44250a708f8fSGustavo F. Padovan } else { 44260a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp; 44270a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type); 4428ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP); 44292d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), 44302d792818SGustavo Padovan &rsp); 44310a708f8fSGustavo F. Padovan } 44320a708f8fSGustavo F. Padovan 44330a708f8fSGustavo F. Padovan return 0; 44340a708f8fSGustavo F. Padovan } 44350a708f8fSGustavo F. Padovan 44362d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, 4437cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4438cb3b3152SJohan Hedberg u8 *data) 44390a708f8fSGustavo F. Padovan { 44400a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; 44410a708f8fSGustavo F. Padovan u16 type, result; 44420a708f8fSGustavo F. Padovan 44433f6fa3d4SJaganath Kanakkassery if (cmd_len < sizeof(*rsp)) 4444cb3b3152SJohan Hedberg return -EPROTO; 4445cb3b3152SJohan Hedberg 44460a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type); 44470a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 44480a708f8fSGustavo F. Padovan 44490a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); 44500a708f8fSGustavo F. Padovan 4451e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */ 4452e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident || 4453e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 4454e90165beSAndrei Emeltchenko return 0; 4455e90165beSAndrei Emeltchenko 445617cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 44570a708f8fSGustavo F. Padovan 44580a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) { 44590a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 44600a708f8fSGustavo F. Padovan conn->info_ident = 0; 44610a708f8fSGustavo F. Padovan 44620a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 44630a708f8fSGustavo F. Padovan 44640a708f8fSGustavo F. Padovan return 0; 44650a708f8fSGustavo F. Padovan } 44660a708f8fSGustavo F. Padovan 4467978c93b9SAndrei Emeltchenko switch (type) { 4468978c93b9SAndrei Emeltchenko case L2CAP_IT_FEAT_MASK: 44690a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data); 44700a708f8fSGustavo F. Padovan 44710a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { 44720a708f8fSGustavo F. Padovan struct l2cap_info_req req; 4473ac73498cSAndrei Emeltchenko req.type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); 44740a708f8fSGustavo F. Padovan 44750a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 44760a708f8fSGustavo F. Padovan 44770a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 44780a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 44790a708f8fSGustavo F. Padovan } else { 44800a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 44810a708f8fSGustavo F. Padovan conn->info_ident = 0; 44820a708f8fSGustavo F. Padovan 44830a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 44840a708f8fSGustavo F. Padovan } 4485978c93b9SAndrei Emeltchenko break; 4486978c93b9SAndrei Emeltchenko 4487978c93b9SAndrei Emeltchenko case L2CAP_IT_FIXED_CHAN: 4488978c93b9SAndrei Emeltchenko conn->fixed_chan_mask = rsp->data[0]; 44890a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 44900a708f8fSGustavo F. Padovan conn->info_ident = 0; 44910a708f8fSGustavo F. Padovan 44920a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 4493978c93b9SAndrei Emeltchenko break; 44940a708f8fSGustavo F. Padovan } 44950a708f8fSGustavo F. Padovan 44960a708f8fSGustavo F. Padovan return 0; 44970a708f8fSGustavo F. Padovan } 44980a708f8fSGustavo F. Padovan 44991700915fSMat Martineau static int l2cap_create_channel_req(struct l2cap_conn *conn, 45002d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, 45012d792818SGustavo Padovan u16 cmd_len, void *data) 4502f94ff6ffSMat Martineau { 4503f94ff6ffSMat Martineau struct l2cap_create_chan_req *req = data; 45046e1df6a6SAndrei Emeltchenko struct l2cap_create_chan_rsp rsp; 45051700915fSMat Martineau struct l2cap_chan *chan; 45066e1df6a6SAndrei Emeltchenko struct hci_dev *hdev; 4507f94ff6ffSMat Martineau u16 psm, scid; 4508f94ff6ffSMat Martineau 4509f94ff6ffSMat Martineau if (cmd_len != sizeof(*req)) 4510f94ff6ffSMat Martineau return -EPROTO; 4511f94ff6ffSMat Martineau 4512848566b3SMarcel Holtmann if (!conn->hs_enabled) 4513f94ff6ffSMat Martineau return -EINVAL; 4514f94ff6ffSMat Martineau 4515f94ff6ffSMat Martineau psm = le16_to_cpu(req->psm); 4516f94ff6ffSMat Martineau scid = le16_to_cpu(req->scid); 4517f94ff6ffSMat Martineau 4518ad0ac6caSAndrei Emeltchenko BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id); 4519f94ff6ffSMat Martineau 45206e1df6a6SAndrei Emeltchenko /* For controller id 0 make BR/EDR connection */ 45216ed971caSMarcel Holtmann if (req->amp_id == AMP_ID_BREDR) { 45226e1df6a6SAndrei Emeltchenko l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, 45236e1df6a6SAndrei Emeltchenko req->amp_id); 45246e1df6a6SAndrei Emeltchenko return 0; 45256e1df6a6SAndrei Emeltchenko } 45261700915fSMat Martineau 45271700915fSMat Martineau /* Validate AMP controller id */ 45281700915fSMat Martineau hdev = hci_dev_get(req->amp_id); 45296e1df6a6SAndrei Emeltchenko if (!hdev) 45306e1df6a6SAndrei Emeltchenko goto error; 45311700915fSMat Martineau 45326e1df6a6SAndrei Emeltchenko if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) { 45336e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 45346e1df6a6SAndrei Emeltchenko goto error; 45356e1df6a6SAndrei Emeltchenko } 45366e1df6a6SAndrei Emeltchenko 45376e1df6a6SAndrei Emeltchenko chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, 45386e1df6a6SAndrei Emeltchenko req->amp_id); 45396e1df6a6SAndrei Emeltchenko if (chan) { 45406e1df6a6SAndrei Emeltchenko struct amp_mgr *mgr = conn->hcon->amp_mgr; 45416e1df6a6SAndrei Emeltchenko struct hci_conn *hs_hcon; 45426e1df6a6SAndrei Emeltchenko 454398e0f7eaSMarcel Holtmann hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, 454498e0f7eaSMarcel Holtmann &conn->hcon->dst); 45456e1df6a6SAndrei Emeltchenko if (!hs_hcon) { 45466e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 4547662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, 4548662d652dSJohan Hedberg chan->dcid); 4549662d652dSJohan Hedberg return 0; 45506e1df6a6SAndrei Emeltchenko } 45516e1df6a6SAndrei Emeltchenko 45526e1df6a6SAndrei Emeltchenko BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon); 45536e1df6a6SAndrei Emeltchenko 45546e1df6a6SAndrei Emeltchenko mgr->bredr_chan = chan; 45556e1df6a6SAndrei Emeltchenko chan->hs_hcon = hs_hcon; 4556fd45bf4cSAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 45576e1df6a6SAndrei Emeltchenko conn->mtu = hdev->block_mtu; 45586e1df6a6SAndrei Emeltchenko } 45596e1df6a6SAndrei Emeltchenko 45606e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 45616e1df6a6SAndrei Emeltchenko 45626e1df6a6SAndrei Emeltchenko return 0; 45636e1df6a6SAndrei Emeltchenko 45646e1df6a6SAndrei Emeltchenko error: 4565f94ff6ffSMat Martineau rsp.dcid = 0; 4566f94ff6ffSMat Martineau rsp.scid = cpu_to_le16(scid); 45671700915fSMat Martineau rsp.result = __constant_cpu_to_le16(L2CAP_CR_BAD_AMP); 45688ce0c498SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 4569f94ff6ffSMat Martineau 4570f94ff6ffSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, 4571f94ff6ffSMat Martineau sizeof(rsp), &rsp); 4572f94ff6ffSMat Martineau 4573dc280801SJohan Hedberg return 0; 4574f94ff6ffSMat Martineau } 4575f94ff6ffSMat Martineau 45768eb200bdSMat Martineau static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id) 45778eb200bdSMat Martineau { 45788eb200bdSMat Martineau struct l2cap_move_chan_req req; 45798eb200bdSMat Martineau u8 ident; 45808eb200bdSMat Martineau 45818eb200bdSMat Martineau BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id); 45828eb200bdSMat Martineau 45838eb200bdSMat Martineau ident = l2cap_get_ident(chan->conn); 45848eb200bdSMat Martineau chan->ident = ident; 45858eb200bdSMat Martineau 45868eb200bdSMat Martineau req.icid = cpu_to_le16(chan->scid); 45878eb200bdSMat Martineau req.dest_amp_id = dest_amp_id; 45888eb200bdSMat Martineau 45898eb200bdSMat Martineau l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req), 45908eb200bdSMat Martineau &req); 45918eb200bdSMat Martineau 45928eb200bdSMat Martineau __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); 45938eb200bdSMat Martineau } 45948eb200bdSMat Martineau 45951500109bSMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result) 45968d5a04a1SMat Martineau { 45978d5a04a1SMat Martineau struct l2cap_move_chan_rsp rsp; 45988d5a04a1SMat Martineau 45991500109bSMat Martineau BT_DBG("chan %p, result 0x%4.4x", chan, result); 46008d5a04a1SMat Martineau 46011500109bSMat Martineau rsp.icid = cpu_to_le16(chan->dcid); 46028d5a04a1SMat Martineau rsp.result = cpu_to_le16(result); 46038d5a04a1SMat Martineau 46041500109bSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP, 46051500109bSMat Martineau sizeof(rsp), &rsp); 46068d5a04a1SMat Martineau } 46078d5a04a1SMat Martineau 46085b155ef9SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result) 46098d5a04a1SMat Martineau { 46108d5a04a1SMat Martineau struct l2cap_move_chan_cfm cfm; 46118d5a04a1SMat Martineau 46125b155ef9SMat Martineau BT_DBG("chan %p, result 0x%4.4x", chan, result); 46138d5a04a1SMat Martineau 46145b155ef9SMat Martineau chan->ident = l2cap_get_ident(chan->conn); 46158d5a04a1SMat Martineau 46165b155ef9SMat Martineau cfm.icid = cpu_to_le16(chan->scid); 46178d5a04a1SMat Martineau cfm.result = cpu_to_le16(result); 46188d5a04a1SMat Martineau 46195b155ef9SMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM, 46205b155ef9SMat Martineau sizeof(cfm), &cfm); 46215b155ef9SMat Martineau 46225b155ef9SMat Martineau __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); 46235b155ef9SMat Martineau } 46245b155ef9SMat Martineau 46255b155ef9SMat Martineau static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid) 46265b155ef9SMat Martineau { 46275b155ef9SMat Martineau struct l2cap_move_chan_cfm cfm; 46285b155ef9SMat Martineau 46295b155ef9SMat Martineau BT_DBG("conn %p, icid 0x%4.4x", conn, icid); 46305b155ef9SMat Martineau 46315b155ef9SMat Martineau cfm.icid = cpu_to_le16(icid); 46325b155ef9SMat Martineau cfm.result = __constant_cpu_to_le16(L2CAP_MC_UNCONFIRMED); 46335b155ef9SMat Martineau 46345b155ef9SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM, 46355b155ef9SMat Martineau sizeof(cfm), &cfm); 46368d5a04a1SMat Martineau } 46378d5a04a1SMat Martineau 46388d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, 46398d5a04a1SMat Martineau u16 icid) 46408d5a04a1SMat Martineau { 46418d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp rsp; 46428d5a04a1SMat Martineau 4643ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 46448d5a04a1SMat Martineau 46458d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 46468d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp); 46478d5a04a1SMat Martineau } 46488d5a04a1SMat Martineau 46495f3847a4SMat Martineau static void __release_logical_link(struct l2cap_chan *chan) 46505f3847a4SMat Martineau { 46515f3847a4SMat Martineau chan->hs_hchan = NULL; 46525f3847a4SMat Martineau chan->hs_hcon = NULL; 46535f3847a4SMat Martineau 46545f3847a4SMat Martineau /* Placeholder - release the logical link */ 46555f3847a4SMat Martineau } 46565f3847a4SMat Martineau 46571500109bSMat Martineau static void l2cap_logical_fail(struct l2cap_chan *chan) 46581500109bSMat Martineau { 46591500109bSMat Martineau /* Logical link setup failed */ 46601500109bSMat Martineau if (chan->state != BT_CONNECTED) { 46611500109bSMat Martineau /* Create channel failure, disconnect */ 46625e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 46631500109bSMat Martineau return; 46641500109bSMat Martineau } 46651500109bSMat Martineau 46661500109bSMat Martineau switch (chan->move_role) { 46671500109bSMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 46681500109bSMat Martineau l2cap_move_done(chan); 46691500109bSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP); 46701500109bSMat Martineau break; 46711500109bSMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 46721500109bSMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP || 46731500109bSMat Martineau chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) { 46741500109bSMat Martineau /* Remote has only sent pending or 46751500109bSMat Martineau * success responses, clean up 46761500109bSMat Martineau */ 46771500109bSMat Martineau l2cap_move_done(chan); 46781500109bSMat Martineau } 46791500109bSMat Martineau 46801500109bSMat Martineau /* Other amp move states imply that the move 46811500109bSMat Martineau * has already aborted 46821500109bSMat Martineau */ 46831500109bSMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 46841500109bSMat Martineau break; 46851500109bSMat Martineau } 46861500109bSMat Martineau } 46871500109bSMat Martineau 46881500109bSMat Martineau static void l2cap_logical_finish_create(struct l2cap_chan *chan, 46891500109bSMat Martineau struct hci_chan *hchan) 46901500109bSMat Martineau { 46911500109bSMat Martineau struct l2cap_conf_rsp rsp; 46921500109bSMat Martineau 4693336178a3SAndrei Emeltchenko chan->hs_hchan = hchan; 46941500109bSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 46951500109bSMat Martineau 469635ba9561SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0); 46971500109bSMat Martineau 46981500109bSMat Martineau if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 4699fe79c6feSAndrei Emeltchenko int err; 47001500109bSMat Martineau 47011500109bSMat Martineau set_default_fcs(chan); 47021500109bSMat Martineau 47031500109bSMat Martineau err = l2cap_ertm_init(chan); 47041500109bSMat Martineau if (err < 0) 47055e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 47061500109bSMat Martineau else 47071500109bSMat Martineau l2cap_chan_ready(chan); 47081500109bSMat Martineau } 47091500109bSMat Martineau } 47101500109bSMat Martineau 47111500109bSMat Martineau static void l2cap_logical_finish_move(struct l2cap_chan *chan, 47121500109bSMat Martineau struct hci_chan *hchan) 47131500109bSMat Martineau { 47141500109bSMat Martineau chan->hs_hcon = hchan->conn; 47151500109bSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 47161500109bSMat Martineau 47171500109bSMat Martineau BT_DBG("move_state %d", chan->move_state); 47181500109bSMat Martineau 47191500109bSMat Martineau switch (chan->move_state) { 47201500109bSMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_COMP: 47211500109bSMat Martineau /* Move confirm will be sent after a success 47221500109bSMat Martineau * response is received 47231500109bSMat Martineau */ 47241500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 47251500109bSMat Martineau break; 47261500109bSMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_CFM: 47271500109bSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 47281500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 47291500109bSMat Martineau } else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { 47301500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; 47311500109bSMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 47321500109bSMat Martineau } else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { 47331500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 47341500109bSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); 47351500109bSMat Martineau } 47361500109bSMat Martineau break; 47371500109bSMat Martineau default: 47381500109bSMat Martineau /* Move was not in expected state, free the channel */ 47391500109bSMat Martineau __release_logical_link(chan); 47401500109bSMat Martineau 47411500109bSMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 47421500109bSMat Martineau } 47431500109bSMat Martineau } 47441500109bSMat Martineau 47451500109bSMat Martineau /* Call with chan locked */ 474627695fb4SAndrei Emeltchenko void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan, 47475b155ef9SMat Martineau u8 status) 47485b155ef9SMat Martineau { 47491500109bSMat Martineau BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status); 47501500109bSMat Martineau 47511500109bSMat Martineau if (status) { 47521500109bSMat Martineau l2cap_logical_fail(chan); 47531500109bSMat Martineau __release_logical_link(chan); 47545b155ef9SMat Martineau return; 47555b155ef9SMat Martineau } 47565b155ef9SMat Martineau 47571500109bSMat Martineau if (chan->state != BT_CONNECTED) { 47581500109bSMat Martineau /* Ignore logical link if channel is on BR/EDR */ 47596ed971caSMarcel Holtmann if (chan->local_amp_id != AMP_ID_BREDR) 47601500109bSMat Martineau l2cap_logical_finish_create(chan, hchan); 47611500109bSMat Martineau } else { 47621500109bSMat Martineau l2cap_logical_finish_move(chan, hchan); 47631500109bSMat Martineau } 47641500109bSMat Martineau } 47651500109bSMat Martineau 47663f7a56c4SMat Martineau void l2cap_move_start(struct l2cap_chan *chan) 47673f7a56c4SMat Martineau { 47683f7a56c4SMat Martineau BT_DBG("chan %p", chan); 47693f7a56c4SMat Martineau 47706ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR) { 47713f7a56c4SMat Martineau if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED) 47723f7a56c4SMat Martineau return; 47733f7a56c4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; 47743f7a56c4SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_PREPARE; 47753f7a56c4SMat Martineau /* Placeholder - start physical link setup */ 47763f7a56c4SMat Martineau } else { 47773f7a56c4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; 47783f7a56c4SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 47793f7a56c4SMat Martineau chan->move_id = 0; 47803f7a56c4SMat Martineau l2cap_move_setup(chan); 47813f7a56c4SMat Martineau l2cap_send_move_chan_req(chan, 0); 47823f7a56c4SMat Martineau } 47833f7a56c4SMat Martineau } 47843f7a56c4SMat Martineau 47858eb200bdSMat Martineau static void l2cap_do_create(struct l2cap_chan *chan, int result, 47868eb200bdSMat Martineau u8 local_amp_id, u8 remote_amp_id) 47878eb200bdSMat Martineau { 478862748ca1SAndrei Emeltchenko BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state), 478962748ca1SAndrei Emeltchenko local_amp_id, remote_amp_id); 479062748ca1SAndrei Emeltchenko 479112d6cc60SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 479212d6cc60SAndrei Emeltchenko 479362748ca1SAndrei Emeltchenko /* Outgoing channel on AMP */ 479462748ca1SAndrei Emeltchenko if (chan->state == BT_CONNECT) { 479562748ca1SAndrei Emeltchenko if (result == L2CAP_CR_SUCCESS) { 479662748ca1SAndrei Emeltchenko chan->local_amp_id = local_amp_id; 479762748ca1SAndrei Emeltchenko l2cap_send_create_chan_req(chan, remote_amp_id); 479862748ca1SAndrei Emeltchenko } else { 479962748ca1SAndrei Emeltchenko /* Revert to BR/EDR connect */ 480062748ca1SAndrei Emeltchenko l2cap_send_conn_req(chan); 480162748ca1SAndrei Emeltchenko } 480262748ca1SAndrei Emeltchenko 480362748ca1SAndrei Emeltchenko return; 480462748ca1SAndrei Emeltchenko } 480562748ca1SAndrei Emeltchenko 480662748ca1SAndrei Emeltchenko /* Incoming channel on AMP */ 480762748ca1SAndrei Emeltchenko if (__l2cap_no_conn_pending(chan)) { 48088eb200bdSMat Martineau struct l2cap_conn_rsp rsp; 48098eb200bdSMat Martineau char buf[128]; 48108eb200bdSMat Martineau rsp.scid = cpu_to_le16(chan->dcid); 48118eb200bdSMat Martineau rsp.dcid = cpu_to_le16(chan->scid); 48128eb200bdSMat Martineau 48138eb200bdSMat Martineau if (result == L2CAP_CR_SUCCESS) { 48148eb200bdSMat Martineau /* Send successful response */ 481562cd50e2SAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 481662cd50e2SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 48178eb200bdSMat Martineau } else { 48188eb200bdSMat Martineau /* Send negative response */ 481962cd50e2SAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM); 482062cd50e2SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 48218eb200bdSMat Martineau } 48228eb200bdSMat Martineau 48238eb200bdSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP, 48248eb200bdSMat Martineau sizeof(rsp), &rsp); 48258eb200bdSMat Martineau 48268eb200bdSMat Martineau if (result == L2CAP_CR_SUCCESS) { 4827f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 48288eb200bdSMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 48298eb200bdSMat Martineau l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn), 48308eb200bdSMat Martineau L2CAP_CONF_REQ, 48318eb200bdSMat Martineau l2cap_build_conf_req(chan, buf), buf); 48328eb200bdSMat Martineau chan->num_conf_req++; 48338eb200bdSMat Martineau } 48348eb200bdSMat Martineau } 48358eb200bdSMat Martineau } 48368eb200bdSMat Martineau 48378eb200bdSMat Martineau static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id, 48388eb200bdSMat Martineau u8 remote_amp_id) 48398eb200bdSMat Martineau { 48408eb200bdSMat Martineau l2cap_move_setup(chan); 48418eb200bdSMat Martineau chan->move_id = local_amp_id; 48428eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP; 48438eb200bdSMat Martineau 48448eb200bdSMat Martineau l2cap_send_move_chan_req(chan, remote_amp_id); 48458eb200bdSMat Martineau } 48468eb200bdSMat Martineau 48478eb200bdSMat Martineau static void l2cap_do_move_respond(struct l2cap_chan *chan, int result) 48488eb200bdSMat Martineau { 48498eb200bdSMat Martineau struct hci_chan *hchan = NULL; 48508eb200bdSMat Martineau 48518eb200bdSMat Martineau /* Placeholder - get hci_chan for logical link */ 48528eb200bdSMat Martineau 48538eb200bdSMat Martineau if (hchan) { 48548eb200bdSMat Martineau if (hchan->state == BT_CONNECTED) { 48558eb200bdSMat Martineau /* Logical link is ready to go */ 48568eb200bdSMat Martineau chan->hs_hcon = hchan->conn; 48578eb200bdSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 48588eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 48598eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); 48608eb200bdSMat Martineau 48618eb200bdSMat Martineau l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); 48628eb200bdSMat Martineau } else { 48638eb200bdSMat Martineau /* Wait for logical link to be ready */ 48648eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 48658eb200bdSMat Martineau } 48668eb200bdSMat Martineau } else { 48678eb200bdSMat Martineau /* Logical link not available */ 48688eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED); 48698eb200bdSMat Martineau } 48708eb200bdSMat Martineau } 48718eb200bdSMat Martineau 48728eb200bdSMat Martineau static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result) 48738eb200bdSMat Martineau { 48748eb200bdSMat Martineau if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { 48758eb200bdSMat Martineau u8 rsp_result; 48768eb200bdSMat Martineau if (result == -EINVAL) 48778eb200bdSMat Martineau rsp_result = L2CAP_MR_BAD_ID; 48788eb200bdSMat Martineau else 48798eb200bdSMat Martineau rsp_result = L2CAP_MR_NOT_ALLOWED; 48808eb200bdSMat Martineau 48818eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, rsp_result); 48828eb200bdSMat Martineau } 48838eb200bdSMat Martineau 48848eb200bdSMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 48858eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 48868eb200bdSMat Martineau 48878eb200bdSMat Martineau /* Restart data transmission */ 48888eb200bdSMat Martineau l2cap_ertm_send(chan); 48898eb200bdSMat Martineau } 48908eb200bdSMat Martineau 4891a514b17fSAndrei Emeltchenko /* Invoke with locked chan */ 4892a514b17fSAndrei Emeltchenko void __l2cap_physical_cfm(struct l2cap_chan *chan, int result) 48938eb200bdSMat Martineau { 4894770bfefaSAndrei Emeltchenko u8 local_amp_id = chan->local_amp_id; 4895fffadc08SAndrei Emeltchenko u8 remote_amp_id = chan->remote_amp_id; 4896770bfefaSAndrei Emeltchenko 48978eb200bdSMat Martineau BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d", 48988eb200bdSMat Martineau chan, result, local_amp_id, remote_amp_id); 48998eb200bdSMat Martineau 49008eb200bdSMat Martineau if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) { 49018eb200bdSMat Martineau l2cap_chan_unlock(chan); 49028eb200bdSMat Martineau return; 49038eb200bdSMat Martineau } 49048eb200bdSMat Martineau 49058eb200bdSMat Martineau if (chan->state != BT_CONNECTED) { 49068eb200bdSMat Martineau l2cap_do_create(chan, result, local_amp_id, remote_amp_id); 49078eb200bdSMat Martineau } else if (result != L2CAP_MR_SUCCESS) { 49088eb200bdSMat Martineau l2cap_do_move_cancel(chan, result); 49098eb200bdSMat Martineau } else { 49108eb200bdSMat Martineau switch (chan->move_role) { 49118eb200bdSMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 49128eb200bdSMat Martineau l2cap_do_move_initiate(chan, local_amp_id, 49138eb200bdSMat Martineau remote_amp_id); 49148eb200bdSMat Martineau break; 49158eb200bdSMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 49168eb200bdSMat Martineau l2cap_do_move_respond(chan, result); 49178eb200bdSMat Martineau break; 49188eb200bdSMat Martineau default: 49198eb200bdSMat Martineau l2cap_do_move_cancel(chan, result); 49208eb200bdSMat Martineau break; 49218eb200bdSMat Martineau } 49228eb200bdSMat Martineau } 49238eb200bdSMat Martineau } 49248eb200bdSMat Martineau 49258d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn, 4926ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 4927ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 49288d5a04a1SMat Martineau { 49298d5a04a1SMat Martineau struct l2cap_move_chan_req *req = data; 49301500109bSMat Martineau struct l2cap_move_chan_rsp rsp; 493102b0fbb9SMat Martineau struct l2cap_chan *chan; 49328d5a04a1SMat Martineau u16 icid = 0; 49338d5a04a1SMat Martineau u16 result = L2CAP_MR_NOT_ALLOWED; 49348d5a04a1SMat Martineau 49358d5a04a1SMat Martineau if (cmd_len != sizeof(*req)) 49368d5a04a1SMat Martineau return -EPROTO; 49378d5a04a1SMat Martineau 49388d5a04a1SMat Martineau icid = le16_to_cpu(req->icid); 49398d5a04a1SMat Martineau 4940ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id); 49418d5a04a1SMat Martineau 4942848566b3SMarcel Holtmann if (!conn->hs_enabled) 49438d5a04a1SMat Martineau return -EINVAL; 49448d5a04a1SMat Martineau 494502b0fbb9SMat Martineau chan = l2cap_get_chan_by_dcid(conn, icid); 494602b0fbb9SMat Martineau if (!chan) { 49471500109bSMat Martineau rsp.icid = cpu_to_le16(icid); 49481500109bSMat Martineau rsp.result = __constant_cpu_to_le16(L2CAP_MR_NOT_ALLOWED); 49491500109bSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP, 49501500109bSMat Martineau sizeof(rsp), &rsp); 495102b0fbb9SMat Martineau return 0; 495202b0fbb9SMat Martineau } 495302b0fbb9SMat Martineau 49541500109bSMat Martineau chan->ident = cmd->ident; 49551500109bSMat Martineau 495602b0fbb9SMat Martineau if (chan->scid < L2CAP_CID_DYN_START || 495702b0fbb9SMat Martineau chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY || 495802b0fbb9SMat Martineau (chan->mode != L2CAP_MODE_ERTM && 495902b0fbb9SMat Martineau chan->mode != L2CAP_MODE_STREAMING)) { 496002b0fbb9SMat Martineau result = L2CAP_MR_NOT_ALLOWED; 496102b0fbb9SMat Martineau goto send_move_response; 496202b0fbb9SMat Martineau } 496302b0fbb9SMat Martineau 496402b0fbb9SMat Martineau if (chan->local_amp_id == req->dest_amp_id) { 496502b0fbb9SMat Martineau result = L2CAP_MR_SAME_ID; 496602b0fbb9SMat Martineau goto send_move_response; 496702b0fbb9SMat Martineau } 496802b0fbb9SMat Martineau 49696ed971caSMarcel Holtmann if (req->dest_amp_id != AMP_ID_BREDR) { 497002b0fbb9SMat Martineau struct hci_dev *hdev; 497102b0fbb9SMat Martineau hdev = hci_dev_get(req->dest_amp_id); 497202b0fbb9SMat Martineau if (!hdev || hdev->dev_type != HCI_AMP || 497302b0fbb9SMat Martineau !test_bit(HCI_UP, &hdev->flags)) { 497402b0fbb9SMat Martineau if (hdev) 497502b0fbb9SMat Martineau hci_dev_put(hdev); 497602b0fbb9SMat Martineau 497702b0fbb9SMat Martineau result = L2CAP_MR_BAD_ID; 497802b0fbb9SMat Martineau goto send_move_response; 497902b0fbb9SMat Martineau } 498002b0fbb9SMat Martineau hci_dev_put(hdev); 498102b0fbb9SMat Martineau } 498202b0fbb9SMat Martineau 498302b0fbb9SMat Martineau /* Detect a move collision. Only send a collision response 498402b0fbb9SMat Martineau * if this side has "lost", otherwise proceed with the move. 498502b0fbb9SMat Martineau * The winner has the larger bd_addr. 498602b0fbb9SMat Martineau */ 498702b0fbb9SMat Martineau if ((__chan_is_moving(chan) || 498802b0fbb9SMat Martineau chan->move_role != L2CAP_MOVE_ROLE_NONE) && 49896f59b904SMarcel Holtmann bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) { 499002b0fbb9SMat Martineau result = L2CAP_MR_COLLISION; 499102b0fbb9SMat Martineau goto send_move_response; 499202b0fbb9SMat Martineau } 499302b0fbb9SMat Martineau 499402b0fbb9SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; 499502b0fbb9SMat Martineau l2cap_move_setup(chan); 499602b0fbb9SMat Martineau chan->move_id = req->dest_amp_id; 499702b0fbb9SMat Martineau icid = chan->dcid; 499802b0fbb9SMat Martineau 49996ed971caSMarcel Holtmann if (req->dest_amp_id == AMP_ID_BREDR) { 500002b0fbb9SMat Martineau /* Moving to BR/EDR */ 500102b0fbb9SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 500202b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 500302b0fbb9SMat Martineau result = L2CAP_MR_PEND; 500402b0fbb9SMat Martineau } else { 500502b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 500602b0fbb9SMat Martineau result = L2CAP_MR_SUCCESS; 500702b0fbb9SMat Martineau } 500802b0fbb9SMat Martineau } else { 500902b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_PREPARE; 501002b0fbb9SMat Martineau /* Placeholder - uncomment when amp functions are available */ 501102b0fbb9SMat Martineau /*amp_accept_physical(chan, req->dest_amp_id);*/ 501202b0fbb9SMat Martineau result = L2CAP_MR_PEND; 501302b0fbb9SMat Martineau } 501402b0fbb9SMat Martineau 501502b0fbb9SMat Martineau send_move_response: 50161500109bSMat Martineau l2cap_send_move_chan_rsp(chan, result); 50178d5a04a1SMat Martineau 501802b0fbb9SMat Martineau l2cap_chan_unlock(chan); 501902b0fbb9SMat Martineau 50208d5a04a1SMat Martineau return 0; 50218d5a04a1SMat Martineau } 50228d5a04a1SMat Martineau 50235b155ef9SMat Martineau static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result) 50245b155ef9SMat Martineau { 50255b155ef9SMat Martineau struct l2cap_chan *chan; 50265b155ef9SMat Martineau struct hci_chan *hchan = NULL; 50275b155ef9SMat Martineau 50285b155ef9SMat Martineau chan = l2cap_get_chan_by_scid(conn, icid); 50295b155ef9SMat Martineau if (!chan) { 50305b155ef9SMat Martineau l2cap_send_move_chan_cfm_icid(conn, icid); 50315b155ef9SMat Martineau return; 50325b155ef9SMat Martineau } 50335b155ef9SMat Martineau 50345b155ef9SMat Martineau __clear_chan_timer(chan); 50355b155ef9SMat Martineau if (result == L2CAP_MR_PEND) 50365b155ef9SMat Martineau __set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT); 50375b155ef9SMat Martineau 50385b155ef9SMat Martineau switch (chan->move_state) { 50395b155ef9SMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_COMP: 50405b155ef9SMat Martineau /* Move confirm will be sent when logical link 50415b155ef9SMat Martineau * is complete. 50425b155ef9SMat Martineau */ 50435b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 50445b155ef9SMat Martineau break; 50455b155ef9SMat Martineau case L2CAP_MOVE_WAIT_RSP_SUCCESS: 50465b155ef9SMat Martineau if (result == L2CAP_MR_PEND) { 50475b155ef9SMat Martineau break; 50485b155ef9SMat Martineau } else if (test_bit(CONN_LOCAL_BUSY, 50495b155ef9SMat Martineau &chan->conn_state)) { 50505b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 50515b155ef9SMat Martineau } else { 50525b155ef9SMat Martineau /* Logical link is up or moving to BR/EDR, 50535b155ef9SMat Martineau * proceed with move 50545b155ef9SMat Martineau */ 50555b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; 50565b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 50575b155ef9SMat Martineau } 50585b155ef9SMat Martineau break; 50595b155ef9SMat Martineau case L2CAP_MOVE_WAIT_RSP: 50605b155ef9SMat Martineau /* Moving to AMP */ 50615b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS) { 50625b155ef9SMat Martineau /* Remote is ready, send confirm immediately 50635b155ef9SMat Martineau * after logical link is ready 50645b155ef9SMat Martineau */ 50655b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 50665b155ef9SMat Martineau } else { 50675b155ef9SMat Martineau /* Both logical link and move success 50685b155ef9SMat Martineau * are required to confirm 50695b155ef9SMat Martineau */ 50705b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP; 50715b155ef9SMat Martineau } 50725b155ef9SMat Martineau 50735b155ef9SMat Martineau /* Placeholder - get hci_chan for logical link */ 50745b155ef9SMat Martineau if (!hchan) { 50755b155ef9SMat Martineau /* Logical link not available */ 50765b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 50775b155ef9SMat Martineau break; 50785b155ef9SMat Martineau } 50795b155ef9SMat Martineau 50805b155ef9SMat Martineau /* If the logical link is not yet connected, do not 50815b155ef9SMat Martineau * send confirmation. 50825b155ef9SMat Martineau */ 50835b155ef9SMat Martineau if (hchan->state != BT_CONNECTED) 50845b155ef9SMat Martineau break; 50855b155ef9SMat Martineau 50865b155ef9SMat Martineau /* Logical link is already ready to go */ 50875b155ef9SMat Martineau 50885b155ef9SMat Martineau chan->hs_hcon = hchan->conn; 50895b155ef9SMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 50905b155ef9SMat Martineau 50915b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS) { 50925b155ef9SMat Martineau /* Can confirm now */ 50935b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 50945b155ef9SMat Martineau } else { 50955b155ef9SMat Martineau /* Now only need move success 50965b155ef9SMat Martineau * to confirm 50975b155ef9SMat Martineau */ 50985b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 50995b155ef9SMat Martineau } 51005b155ef9SMat Martineau 51015b155ef9SMat Martineau l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); 51025b155ef9SMat Martineau break; 51035b155ef9SMat Martineau default: 51045b155ef9SMat Martineau /* Any other amp move state means the move failed. */ 51055b155ef9SMat Martineau chan->move_id = chan->local_amp_id; 51065b155ef9SMat Martineau l2cap_move_done(chan); 51075b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 51085b155ef9SMat Martineau } 51095b155ef9SMat Martineau 51105b155ef9SMat Martineau l2cap_chan_unlock(chan); 51115b155ef9SMat Martineau } 51125b155ef9SMat Martineau 51135b155ef9SMat Martineau static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid, 51145b155ef9SMat Martineau u16 result) 51155b155ef9SMat Martineau { 51165b155ef9SMat Martineau struct l2cap_chan *chan; 51175b155ef9SMat Martineau 51185b155ef9SMat Martineau chan = l2cap_get_chan_by_ident(conn, ident); 51195b155ef9SMat Martineau if (!chan) { 51205b155ef9SMat Martineau /* Could not locate channel, icid is best guess */ 51215b155ef9SMat Martineau l2cap_send_move_chan_cfm_icid(conn, icid); 51225b155ef9SMat Martineau return; 51235b155ef9SMat Martineau } 51245b155ef9SMat Martineau 51255b155ef9SMat Martineau __clear_chan_timer(chan); 51265b155ef9SMat Martineau 51275b155ef9SMat Martineau if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { 51285b155ef9SMat Martineau if (result == L2CAP_MR_COLLISION) { 51295b155ef9SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; 51305b155ef9SMat Martineau } else { 51315b155ef9SMat Martineau /* Cleanup - cancel move */ 51325b155ef9SMat Martineau chan->move_id = chan->local_amp_id; 51335b155ef9SMat Martineau l2cap_move_done(chan); 51345b155ef9SMat Martineau } 51355b155ef9SMat Martineau } 51365b155ef9SMat Martineau 51375b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 51385b155ef9SMat Martineau 51395b155ef9SMat Martineau l2cap_chan_unlock(chan); 51405b155ef9SMat Martineau } 51415b155ef9SMat Martineau 51425b155ef9SMat Martineau static int l2cap_move_channel_rsp(struct l2cap_conn *conn, 5143ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5144ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 51458d5a04a1SMat Martineau { 51468d5a04a1SMat Martineau struct l2cap_move_chan_rsp *rsp = data; 51478d5a04a1SMat Martineau u16 icid, result; 51488d5a04a1SMat Martineau 51498d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 51508d5a04a1SMat Martineau return -EPROTO; 51518d5a04a1SMat Martineau 51528d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 51538d5a04a1SMat Martineau result = le16_to_cpu(rsp->result); 51548d5a04a1SMat Martineau 5155ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 51568d5a04a1SMat Martineau 51575b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND) 51585b155ef9SMat Martineau l2cap_move_continue(conn, icid, result); 51595b155ef9SMat Martineau else 51605b155ef9SMat Martineau l2cap_move_fail(conn, cmd->ident, icid, result); 51618d5a04a1SMat Martineau 51628d5a04a1SMat Martineau return 0; 51638d5a04a1SMat Martineau } 51648d5a04a1SMat Martineau 51655f3847a4SMat Martineau static int l2cap_move_channel_confirm(struct l2cap_conn *conn, 5166ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5167ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 51688d5a04a1SMat Martineau { 51698d5a04a1SMat Martineau struct l2cap_move_chan_cfm *cfm = data; 51705f3847a4SMat Martineau struct l2cap_chan *chan; 51718d5a04a1SMat Martineau u16 icid, result; 51728d5a04a1SMat Martineau 51738d5a04a1SMat Martineau if (cmd_len != sizeof(*cfm)) 51748d5a04a1SMat Martineau return -EPROTO; 51758d5a04a1SMat Martineau 51768d5a04a1SMat Martineau icid = le16_to_cpu(cfm->icid); 51778d5a04a1SMat Martineau result = le16_to_cpu(cfm->result); 51788d5a04a1SMat Martineau 5179ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 51808d5a04a1SMat Martineau 51815f3847a4SMat Martineau chan = l2cap_get_chan_by_dcid(conn, icid); 51825f3847a4SMat Martineau if (!chan) { 51835f3847a4SMat Martineau /* Spec requires a response even if the icid was not found */ 51848d5a04a1SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 51855f3847a4SMat Martineau return 0; 51865f3847a4SMat Martineau } 51875f3847a4SMat Martineau 51885f3847a4SMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) { 51895f3847a4SMat Martineau if (result == L2CAP_MC_CONFIRMED) { 51905f3847a4SMat Martineau chan->local_amp_id = chan->move_id; 51916ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR) 51925f3847a4SMat Martineau __release_logical_link(chan); 51935f3847a4SMat Martineau } else { 51945f3847a4SMat Martineau chan->move_id = chan->local_amp_id; 51955f3847a4SMat Martineau } 51965f3847a4SMat Martineau 51975f3847a4SMat Martineau l2cap_move_done(chan); 51985f3847a4SMat Martineau } 51995f3847a4SMat Martineau 52005f3847a4SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 52015f3847a4SMat Martineau 52025f3847a4SMat Martineau l2cap_chan_unlock(chan); 52038d5a04a1SMat Martineau 52048d5a04a1SMat Martineau return 0; 52058d5a04a1SMat Martineau } 52068d5a04a1SMat Martineau 52078d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, 5208ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5209ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 52108d5a04a1SMat Martineau { 52118d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp *rsp = data; 52123fd71a0aSMat Martineau struct l2cap_chan *chan; 52138d5a04a1SMat Martineau u16 icid; 52148d5a04a1SMat Martineau 52158d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 52168d5a04a1SMat Martineau return -EPROTO; 52178d5a04a1SMat Martineau 52188d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 52198d5a04a1SMat Martineau 5220ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 52218d5a04a1SMat Martineau 52223fd71a0aSMat Martineau chan = l2cap_get_chan_by_scid(conn, icid); 52233fd71a0aSMat Martineau if (!chan) 52243fd71a0aSMat Martineau return 0; 52253fd71a0aSMat Martineau 52263fd71a0aSMat Martineau __clear_chan_timer(chan); 52273fd71a0aSMat Martineau 52283fd71a0aSMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) { 52293fd71a0aSMat Martineau chan->local_amp_id = chan->move_id; 52303fd71a0aSMat Martineau 52316ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan) 52323fd71a0aSMat Martineau __release_logical_link(chan); 52333fd71a0aSMat Martineau 52343fd71a0aSMat Martineau l2cap_move_done(chan); 52353fd71a0aSMat Martineau } 52363fd71a0aSMat Martineau 52373fd71a0aSMat Martineau l2cap_chan_unlock(chan); 52383fd71a0aSMat Martineau 52398d5a04a1SMat Martineau return 0; 52408d5a04a1SMat Martineau } 52418d5a04a1SMat Martineau 5242e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency, 5243de73115aSClaudio Takahasi u16 to_multiplier) 5244de73115aSClaudio Takahasi { 5245de73115aSClaudio Takahasi u16 max_latency; 5246de73115aSClaudio Takahasi 5247de73115aSClaudio Takahasi if (min > max || min < 6 || max > 3200) 5248de73115aSClaudio Takahasi return -EINVAL; 5249de73115aSClaudio Takahasi 5250de73115aSClaudio Takahasi if (to_multiplier < 10 || to_multiplier > 3200) 5251de73115aSClaudio Takahasi return -EINVAL; 5252de73115aSClaudio Takahasi 5253de73115aSClaudio Takahasi if (max >= to_multiplier * 8) 5254de73115aSClaudio Takahasi return -EINVAL; 5255de73115aSClaudio Takahasi 5256de73115aSClaudio Takahasi max_latency = (to_multiplier * 8 / max) - 1; 5257de73115aSClaudio Takahasi if (latency > 499 || latency > max_latency) 5258de73115aSClaudio Takahasi return -EINVAL; 5259de73115aSClaudio Takahasi 5260de73115aSClaudio Takahasi return 0; 5261de73115aSClaudio Takahasi } 5262de73115aSClaudio Takahasi 5263de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, 52642d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, 5265203e639eSJohan Hedberg u16 cmd_len, u8 *data) 5266de73115aSClaudio Takahasi { 5267de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon; 5268de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req; 5269de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp; 5270203e639eSJohan Hedberg u16 min, max, latency, to_multiplier; 52712ce603ebSClaudio Takahasi int err; 5272de73115aSClaudio Takahasi 5273de73115aSClaudio Takahasi if (!(hcon->link_mode & HCI_LM_MASTER)) 5274de73115aSClaudio Takahasi return -EINVAL; 5275de73115aSClaudio Takahasi 5276de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) 5277de73115aSClaudio Takahasi return -EPROTO; 5278de73115aSClaudio Takahasi 5279de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data; 5280de73115aSClaudio Takahasi min = __le16_to_cpu(req->min); 5281de73115aSClaudio Takahasi max = __le16_to_cpu(req->max); 5282de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency); 5283de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier); 5284de73115aSClaudio Takahasi 5285de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", 5286de73115aSClaudio Takahasi min, max, latency, to_multiplier); 5287de73115aSClaudio Takahasi 5288de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp)); 52892ce603ebSClaudio Takahasi 52902ce603ebSClaudio Takahasi err = l2cap_check_conn_param(min, max, latency, to_multiplier); 52912ce603ebSClaudio Takahasi if (err) 5292ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); 5293de73115aSClaudio Takahasi else 5294ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); 5295de73115aSClaudio Takahasi 5296de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, 5297de73115aSClaudio Takahasi sizeof(rsp), &rsp); 5298de73115aSClaudio Takahasi 52992ce603ebSClaudio Takahasi if (!err) 53002ce603ebSClaudio Takahasi hci_le_conn_update(hcon, min, max, latency, to_multiplier); 53012ce603ebSClaudio Takahasi 5302de73115aSClaudio Takahasi return 0; 5303de73115aSClaudio Takahasi } 5304de73115aSClaudio Takahasi 5305f1496deeSJohan Hedberg static int l2cap_le_connect_rsp(struct l2cap_conn *conn, 5306f1496deeSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5307f1496deeSJohan Hedberg u8 *data) 5308f1496deeSJohan Hedberg { 5309f1496deeSJohan Hedberg struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data; 5310f1496deeSJohan Hedberg u16 dcid, mtu, mps, credits, result; 5311f1496deeSJohan Hedberg struct l2cap_chan *chan; 5312f1496deeSJohan Hedberg int err; 5313f1496deeSJohan Hedberg 5314f1496deeSJohan Hedberg if (cmd_len < sizeof(*rsp)) 5315f1496deeSJohan Hedberg return -EPROTO; 5316f1496deeSJohan Hedberg 5317f1496deeSJohan Hedberg dcid = __le16_to_cpu(rsp->dcid); 5318f1496deeSJohan Hedberg mtu = __le16_to_cpu(rsp->mtu); 5319f1496deeSJohan Hedberg mps = __le16_to_cpu(rsp->mps); 5320f1496deeSJohan Hedberg credits = __le16_to_cpu(rsp->credits); 5321f1496deeSJohan Hedberg result = __le16_to_cpu(rsp->result); 5322f1496deeSJohan Hedberg 5323f1496deeSJohan Hedberg if (result == L2CAP_CR_SUCCESS && (mtu < 23 || mps < 23)) 5324f1496deeSJohan Hedberg return -EPROTO; 5325f1496deeSJohan Hedberg 5326f1496deeSJohan Hedberg BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x", 5327f1496deeSJohan Hedberg dcid, mtu, mps, credits, result); 5328f1496deeSJohan Hedberg 5329f1496deeSJohan Hedberg mutex_lock(&conn->chan_lock); 5330f1496deeSJohan Hedberg 5331f1496deeSJohan Hedberg chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 5332f1496deeSJohan Hedberg if (!chan) { 5333f1496deeSJohan Hedberg err = -EBADSLT; 5334f1496deeSJohan Hedberg goto unlock; 5335f1496deeSJohan Hedberg } 5336f1496deeSJohan Hedberg 5337f1496deeSJohan Hedberg err = 0; 5338f1496deeSJohan Hedberg 5339f1496deeSJohan Hedberg l2cap_chan_lock(chan); 5340f1496deeSJohan Hedberg 5341f1496deeSJohan Hedberg switch (result) { 5342f1496deeSJohan Hedberg case L2CAP_CR_SUCCESS: 5343f1496deeSJohan Hedberg chan->ident = 0; 5344f1496deeSJohan Hedberg chan->dcid = dcid; 5345f1496deeSJohan Hedberg chan->omtu = mtu; 5346f1496deeSJohan Hedberg chan->remote_mps = mps; 53470cd75f7eSJohan Hedberg chan->tx_credits = credits; 5348f1496deeSJohan Hedberg l2cap_chan_ready(chan); 5349f1496deeSJohan Hedberg break; 5350f1496deeSJohan Hedberg 5351f1496deeSJohan Hedberg default: 5352f1496deeSJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED); 5353f1496deeSJohan Hedberg break; 5354f1496deeSJohan Hedberg } 5355f1496deeSJohan Hedberg 5356f1496deeSJohan Hedberg l2cap_chan_unlock(chan); 5357f1496deeSJohan Hedberg 5358f1496deeSJohan Hedberg unlock: 5359f1496deeSJohan Hedberg mutex_unlock(&conn->chan_lock); 5360f1496deeSJohan Hedberg 5361f1496deeSJohan Hedberg return err; 5362f1496deeSJohan Hedberg } 5363f1496deeSJohan Hedberg 53643300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, 53652d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len, 53662d792818SGustavo Padovan u8 *data) 53673300d9a9SClaudio Takahasi { 53683300d9a9SClaudio Takahasi int err = 0; 53693300d9a9SClaudio Takahasi 53703300d9a9SClaudio Takahasi switch (cmd->code) { 53713300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 5372cb3b3152SJohan Hedberg l2cap_command_rej(conn, cmd, cmd_len, data); 53733300d9a9SClaudio Takahasi break; 53743300d9a9SClaudio Takahasi 53753300d9a9SClaudio Takahasi case L2CAP_CONN_REQ: 5376cb3b3152SJohan Hedberg err = l2cap_connect_req(conn, cmd, cmd_len, data); 53773300d9a9SClaudio Takahasi break; 53783300d9a9SClaudio Takahasi 53793300d9a9SClaudio Takahasi case L2CAP_CONN_RSP: 5380f5a2598dSMat Martineau case L2CAP_CREATE_CHAN_RSP: 53819245e737SJohan Hedberg l2cap_connect_create_rsp(conn, cmd, cmd_len, data); 53823300d9a9SClaudio Takahasi break; 53833300d9a9SClaudio Takahasi 53843300d9a9SClaudio Takahasi case L2CAP_CONF_REQ: 53853300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data); 53863300d9a9SClaudio Takahasi break; 53873300d9a9SClaudio Takahasi 53883300d9a9SClaudio Takahasi case L2CAP_CONF_RSP: 53899245e737SJohan Hedberg l2cap_config_rsp(conn, cmd, cmd_len, data); 53903300d9a9SClaudio Takahasi break; 53913300d9a9SClaudio Takahasi 53923300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ: 5393cb3b3152SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data); 53943300d9a9SClaudio Takahasi break; 53953300d9a9SClaudio Takahasi 53963300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP: 53979245e737SJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data); 53983300d9a9SClaudio Takahasi break; 53993300d9a9SClaudio Takahasi 54003300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ: 54013300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data); 54023300d9a9SClaudio Takahasi break; 54033300d9a9SClaudio Takahasi 54043300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP: 54053300d9a9SClaudio Takahasi break; 54063300d9a9SClaudio Takahasi 54073300d9a9SClaudio Takahasi case L2CAP_INFO_REQ: 5408cb3b3152SJohan Hedberg err = l2cap_information_req(conn, cmd, cmd_len, data); 54093300d9a9SClaudio Takahasi break; 54103300d9a9SClaudio Takahasi 54113300d9a9SClaudio Takahasi case L2CAP_INFO_RSP: 54129245e737SJohan Hedberg l2cap_information_rsp(conn, cmd, cmd_len, data); 54133300d9a9SClaudio Takahasi break; 54143300d9a9SClaudio Takahasi 5415f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_REQ: 5416f94ff6ffSMat Martineau err = l2cap_create_channel_req(conn, cmd, cmd_len, data); 5417f94ff6ffSMat Martineau break; 5418f94ff6ffSMat Martineau 54198d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_REQ: 54208d5a04a1SMat Martineau err = l2cap_move_channel_req(conn, cmd, cmd_len, data); 54218d5a04a1SMat Martineau break; 54228d5a04a1SMat Martineau 54238d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_RSP: 54249245e737SJohan Hedberg l2cap_move_channel_rsp(conn, cmd, cmd_len, data); 54258d5a04a1SMat Martineau break; 54268d5a04a1SMat Martineau 54278d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM: 54288d5a04a1SMat Martineau err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data); 54298d5a04a1SMat Martineau break; 54308d5a04a1SMat Martineau 54318d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM_RSP: 54329245e737SJohan Hedberg l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data); 54338d5a04a1SMat Martineau break; 54348d5a04a1SMat Martineau 54353300d9a9SClaudio Takahasi default: 54363300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code); 54373300d9a9SClaudio Takahasi err = -EINVAL; 54383300d9a9SClaudio Takahasi break; 54393300d9a9SClaudio Takahasi } 54403300d9a9SClaudio Takahasi 54413300d9a9SClaudio Takahasi return err; 54423300d9a9SClaudio Takahasi } 54433300d9a9SClaudio Takahasi 544427e2d4c8SJohan Hedberg static int l2cap_le_connect_req(struct l2cap_conn *conn, 544527e2d4c8SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 544627e2d4c8SJohan Hedberg u8 *data) 544727e2d4c8SJohan Hedberg { 544827e2d4c8SJohan Hedberg struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data; 544927e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 545027e2d4c8SJohan Hedberg struct l2cap_chan *chan, *pchan; 54510cd75f7eSJohan Hedberg u16 dcid, scid, credits, mtu, mps; 545227e2d4c8SJohan Hedberg __le16 psm; 545327e2d4c8SJohan Hedberg u8 result; 545427e2d4c8SJohan Hedberg 545527e2d4c8SJohan Hedberg if (cmd_len != sizeof(*req)) 545627e2d4c8SJohan Hedberg return -EPROTO; 545727e2d4c8SJohan Hedberg 545827e2d4c8SJohan Hedberg scid = __le16_to_cpu(req->scid); 545927e2d4c8SJohan Hedberg mtu = __le16_to_cpu(req->mtu); 546027e2d4c8SJohan Hedberg mps = __le16_to_cpu(req->mps); 546127e2d4c8SJohan Hedberg psm = req->psm; 546227e2d4c8SJohan Hedberg dcid = 0; 54630cd75f7eSJohan Hedberg credits = 0; 546427e2d4c8SJohan Hedberg 546527e2d4c8SJohan Hedberg if (mtu < 23 || mps < 23) 546627e2d4c8SJohan Hedberg return -EPROTO; 546727e2d4c8SJohan Hedberg 546827e2d4c8SJohan Hedberg BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm), 546927e2d4c8SJohan Hedberg scid, mtu, mps); 547027e2d4c8SJohan Hedberg 547127e2d4c8SJohan Hedberg /* Check if we have socket listening on psm */ 547227e2d4c8SJohan Hedberg pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 547327e2d4c8SJohan Hedberg &conn->hcon->dst, LE_LINK); 547427e2d4c8SJohan Hedberg if (!pchan) { 547527e2d4c8SJohan Hedberg result = L2CAP_CR_BAD_PSM; 547627e2d4c8SJohan Hedberg chan = NULL; 547727e2d4c8SJohan Hedberg goto response; 547827e2d4c8SJohan Hedberg } 547927e2d4c8SJohan Hedberg 548027e2d4c8SJohan Hedberg mutex_lock(&conn->chan_lock); 548127e2d4c8SJohan Hedberg l2cap_chan_lock(pchan); 548227e2d4c8SJohan Hedberg 548327e2d4c8SJohan Hedberg if (!smp_sufficient_security(conn->hcon, pchan->sec_level)) { 548427e2d4c8SJohan Hedberg result = L2CAP_CR_AUTHENTICATION; 548527e2d4c8SJohan Hedberg chan = NULL; 548627e2d4c8SJohan Hedberg goto response_unlock; 548727e2d4c8SJohan Hedberg } 548827e2d4c8SJohan Hedberg 548927e2d4c8SJohan Hedberg /* Check if we already have channel with that dcid */ 549027e2d4c8SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, scid)) { 549127e2d4c8SJohan Hedberg result = L2CAP_CR_NO_MEM; 549227e2d4c8SJohan Hedberg chan = NULL; 549327e2d4c8SJohan Hedberg goto response_unlock; 549427e2d4c8SJohan Hedberg } 549527e2d4c8SJohan Hedberg 549627e2d4c8SJohan Hedberg chan = pchan->ops->new_connection(pchan); 549727e2d4c8SJohan Hedberg if (!chan) { 549827e2d4c8SJohan Hedberg result = L2CAP_CR_NO_MEM; 549927e2d4c8SJohan Hedberg goto response_unlock; 550027e2d4c8SJohan Hedberg } 550127e2d4c8SJohan Hedberg 550227e2d4c8SJohan Hedberg bacpy(&chan->src, &conn->hcon->src); 550327e2d4c8SJohan Hedberg bacpy(&chan->dst, &conn->hcon->dst); 550427e2d4c8SJohan Hedberg chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type); 550527e2d4c8SJohan Hedberg chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type); 550627e2d4c8SJohan Hedberg chan->psm = psm; 550727e2d4c8SJohan Hedberg chan->dcid = scid; 550827e2d4c8SJohan Hedberg chan->omtu = mtu; 550927e2d4c8SJohan Hedberg chan->remote_mps = mps; 55100cd75f7eSJohan Hedberg chan->tx_credits = __le16_to_cpu(req->credits); 551127e2d4c8SJohan Hedberg 551227e2d4c8SJohan Hedberg __l2cap_chan_add(conn, chan); 551327e2d4c8SJohan Hedberg dcid = chan->scid; 55140cd75f7eSJohan Hedberg credits = chan->rx_credits; 551527e2d4c8SJohan Hedberg 551627e2d4c8SJohan Hedberg __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 551727e2d4c8SJohan Hedberg 551827e2d4c8SJohan Hedberg chan->ident = cmd->ident; 551927e2d4c8SJohan Hedberg 552027e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 552127e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_CONNECT2); 552227e2d4c8SJohan Hedberg result = L2CAP_CR_PEND; 552327e2d4c8SJohan Hedberg chan->ops->defer(chan); 552427e2d4c8SJohan Hedberg } else { 552527e2d4c8SJohan Hedberg l2cap_chan_ready(chan); 552627e2d4c8SJohan Hedberg result = L2CAP_CR_SUCCESS; 552727e2d4c8SJohan Hedberg } 552827e2d4c8SJohan Hedberg 552927e2d4c8SJohan Hedberg response_unlock: 553027e2d4c8SJohan Hedberg l2cap_chan_unlock(pchan); 553127e2d4c8SJohan Hedberg mutex_unlock(&conn->chan_lock); 553227e2d4c8SJohan Hedberg 553327e2d4c8SJohan Hedberg if (result == L2CAP_CR_PEND) 553427e2d4c8SJohan Hedberg return 0; 553527e2d4c8SJohan Hedberg 553627e2d4c8SJohan Hedberg response: 553727e2d4c8SJohan Hedberg if (chan) { 553827e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 553927e2d4c8SJohan Hedberg rsp.mps = __constant_cpu_to_le16(L2CAP_LE_DEFAULT_MPS); 554027e2d4c8SJohan Hedberg } else { 554127e2d4c8SJohan Hedberg rsp.mtu = 0; 554227e2d4c8SJohan Hedberg rsp.mps = 0; 554327e2d4c8SJohan Hedberg } 554427e2d4c8SJohan Hedberg 554527e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(dcid); 55460cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(credits); 554727e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result); 554827e2d4c8SJohan Hedberg 554927e2d4c8SJohan Hedberg l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp); 555027e2d4c8SJohan Hedberg 555127e2d4c8SJohan Hedberg return 0; 555227e2d4c8SJohan Hedberg } 555327e2d4c8SJohan Hedberg 55543300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, 5555203e639eSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5556203e639eSJohan Hedberg u8 *data) 55573300d9a9SClaudio Takahasi { 5558b5ecba64SJohan Hedberg int err = 0; 5559b5ecba64SJohan Hedberg 55603300d9a9SClaudio Takahasi switch (cmd->code) { 55613300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 5562b5ecba64SJohan Hedberg break; 55633300d9a9SClaudio Takahasi 55643300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ: 5565b5ecba64SJohan Hedberg err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data); 5566b5ecba64SJohan Hedberg break; 55673300d9a9SClaudio Takahasi 55683300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP: 5569b5ecba64SJohan Hedberg break; 55703300d9a9SClaudio Takahasi 5571f1496deeSJohan Hedberg case L2CAP_LE_CONN_RSP: 5572f1496deeSJohan Hedberg l2cap_le_connect_rsp(conn, cmd, cmd_len, data); 5573b5ecba64SJohan Hedberg break; 5574f1496deeSJohan Hedberg 557527e2d4c8SJohan Hedberg case L2CAP_LE_CONN_REQ: 5576b5ecba64SJohan Hedberg err = l2cap_le_connect_req(conn, cmd, cmd_len, data); 5577b5ecba64SJohan Hedberg break; 557827e2d4c8SJohan Hedberg 55793defe01aSJohan Hedberg case L2CAP_DISCONN_REQ: 5580b5ecba64SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data); 5581b5ecba64SJohan Hedberg break; 55823defe01aSJohan Hedberg 55833defe01aSJohan Hedberg case L2CAP_DISCONN_RSP: 55843defe01aSJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data); 5585b5ecba64SJohan Hedberg break; 55863defe01aSJohan Hedberg 55873300d9a9SClaudio Takahasi default: 55883300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code); 5589b5ecba64SJohan Hedberg err = -EINVAL; 5590b5ecba64SJohan Hedberg break; 55913300d9a9SClaudio Takahasi } 5592b5ecba64SJohan Hedberg 5593b5ecba64SJohan Hedberg return err; 55943300d9a9SClaudio Takahasi } 55953300d9a9SClaudio Takahasi 5596c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn, 5597c5623556SJohan Hedberg struct sk_buff *skb) 5598c5623556SJohan Hedberg { 559969c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon; 56004f3e219dSMarcel Holtmann struct l2cap_cmd_hdr *cmd; 56014f3e219dSMarcel Holtmann u16 len; 5602c5623556SJohan Hedberg int err; 5603c5623556SJohan Hedberg 560469c4e4e8SJohan Hedberg if (hcon->type != LE_LINK) 56053b166295SMarcel Holtmann goto drop; 560669c4e4e8SJohan Hedberg 56074f3e219dSMarcel Holtmann if (skb->len < L2CAP_CMD_HDR_SIZE) 56084f3e219dSMarcel Holtmann goto drop; 5609c5623556SJohan Hedberg 56104f3e219dSMarcel Holtmann cmd = (void *) skb->data; 56114f3e219dSMarcel Holtmann skb_pull(skb, L2CAP_CMD_HDR_SIZE); 5612c5623556SJohan Hedberg 56134f3e219dSMarcel Holtmann len = le16_to_cpu(cmd->len); 5614c5623556SJohan Hedberg 56154f3e219dSMarcel Holtmann BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident); 56164f3e219dSMarcel Holtmann 56174f3e219dSMarcel Holtmann if (len != skb->len || !cmd->ident) { 5618c5623556SJohan Hedberg BT_DBG("corrupted command"); 56194f3e219dSMarcel Holtmann goto drop; 5620c5623556SJohan Hedberg } 5621c5623556SJohan Hedberg 5622203e639eSJohan Hedberg err = l2cap_le_sig_cmd(conn, cmd, len, skb->data); 5623c5623556SJohan Hedberg if (err) { 5624c5623556SJohan Hedberg struct l2cap_cmd_rej_unk rej; 5625c5623556SJohan Hedberg 5626c5623556SJohan Hedberg BT_ERR("Wrong link type (%d)", err); 5627c5623556SJohan Hedberg 5628a521149aSJohan Hedberg rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 56294f3e219dSMarcel Holtmann l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 5630c5623556SJohan Hedberg sizeof(rej), &rej); 5631c5623556SJohan Hedberg } 5632c5623556SJohan Hedberg 56333b166295SMarcel Holtmann drop: 5634c5623556SJohan Hedberg kfree_skb(skb); 5635c5623556SJohan Hedberg } 5636c5623556SJohan Hedberg 56373300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn, 56383300d9a9SClaudio Takahasi struct sk_buff *skb) 56390a708f8fSGustavo F. Padovan { 564069c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon; 56410a708f8fSGustavo F. Padovan u8 *data = skb->data; 56420a708f8fSGustavo F. Padovan int len = skb->len; 56430a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr cmd; 56443300d9a9SClaudio Takahasi int err; 56450a708f8fSGustavo F. Padovan 56460a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb); 56470a708f8fSGustavo F. Padovan 564869c4e4e8SJohan Hedberg if (hcon->type != ACL_LINK) 56493b166295SMarcel Holtmann goto drop; 565069c4e4e8SJohan Hedberg 56510a708f8fSGustavo F. Padovan while (len >= L2CAP_CMD_HDR_SIZE) { 56520a708f8fSGustavo F. Padovan u16 cmd_len; 56530a708f8fSGustavo F. Padovan memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); 56540a708f8fSGustavo F. Padovan data += L2CAP_CMD_HDR_SIZE; 56550a708f8fSGustavo F. Padovan len -= L2CAP_CMD_HDR_SIZE; 56560a708f8fSGustavo F. Padovan 56570a708f8fSGustavo F. Padovan cmd_len = le16_to_cpu(cmd.len); 56580a708f8fSGustavo F. Padovan 56592d792818SGustavo Padovan BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, 56602d792818SGustavo Padovan cmd.ident); 56610a708f8fSGustavo F. Padovan 56620a708f8fSGustavo F. Padovan if (cmd_len > len || !cmd.ident) { 56630a708f8fSGustavo F. Padovan BT_DBG("corrupted command"); 56640a708f8fSGustavo F. Padovan break; 56650a708f8fSGustavo F. Padovan } 56660a708f8fSGustavo F. Padovan 56673300d9a9SClaudio Takahasi err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data); 56680a708f8fSGustavo F. Padovan if (err) { 5669e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk rej; 56702c6d1a2eSGustavo F. Padovan 56712c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err); 56720a708f8fSGustavo F. Padovan 5673a521149aSJohan Hedberg rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 56742d792818SGustavo Padovan l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, 56752d792818SGustavo Padovan sizeof(rej), &rej); 56760a708f8fSGustavo F. Padovan } 56770a708f8fSGustavo F. Padovan 56780a708f8fSGustavo F. Padovan data += cmd_len; 56790a708f8fSGustavo F. Padovan len -= cmd_len; 56800a708f8fSGustavo F. Padovan } 56810a708f8fSGustavo F. Padovan 56823b166295SMarcel Holtmann drop: 56830a708f8fSGustavo F. Padovan kfree_skb(skb); 56840a708f8fSGustavo F. Padovan } 56850a708f8fSGustavo F. Padovan 568647d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) 56870a708f8fSGustavo F. Padovan { 56880a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs; 5689e4ca6d98SAndrei Emeltchenko int hdr_size; 5690e4ca6d98SAndrei Emeltchenko 5691e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 5692e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE; 5693e4ca6d98SAndrei Emeltchenko else 5694e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE; 56950a708f8fSGustavo F. Padovan 569647d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 569703a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE); 56980a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len); 56990a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); 57000a708f8fSGustavo F. Padovan 57010a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs) 57020a708f8fSGustavo F. Padovan return -EBADMSG; 57030a708f8fSGustavo F. Padovan } 57040a708f8fSGustavo F. Padovan return 0; 57050a708f8fSGustavo F. Padovan } 57060a708f8fSGustavo F. Padovan 57076ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) 57080a708f8fSGustavo F. Padovan { 5709e31f7633SMat Martineau struct l2cap_ctrl control; 57100a708f8fSGustavo F. Padovan 5711e31f7633SMat Martineau BT_DBG("chan %p", chan); 57120a708f8fSGustavo F. Padovan 5713e31f7633SMat Martineau memset(&control, 0, sizeof(control)); 5714e31f7633SMat Martineau control.sframe = 1; 5715e31f7633SMat Martineau control.final = 1; 5716e31f7633SMat Martineau control.reqseq = chan->buffer_seq; 5717e31f7633SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 57180a708f8fSGustavo F. Padovan 5719e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 5720e31f7633SMat Martineau control.super = L2CAP_SUPER_RNR; 5721e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 57220a708f8fSGustavo F. Padovan } 57230a708f8fSGustavo F. Padovan 5724e31f7633SMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 5725e31f7633SMat Martineau chan->unacked_frames > 0) 5726e31f7633SMat Martineau __set_retrans_timer(chan); 57270a708f8fSGustavo F. Padovan 5728e31f7633SMat Martineau /* Send pending iframes */ 5729525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 57300a708f8fSGustavo F. Padovan 5731e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 5732e31f7633SMat Martineau test_bit(CONN_SEND_FBIT, &chan->conn_state)) { 5733e31f7633SMat Martineau /* F-bit wasn't sent in an s-frame or i-frame yet, so 5734e31f7633SMat Martineau * send it now. 5735e31f7633SMat Martineau */ 5736e31f7633SMat Martineau control.super = L2CAP_SUPER_RR; 5737e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 57380a708f8fSGustavo F. Padovan } 57390a708f8fSGustavo F. Padovan } 57400a708f8fSGustavo F. Padovan 57412d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag, 57422d792818SGustavo Padovan struct sk_buff **last_frag) 57430a708f8fSGustavo F. Padovan { 574484084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments 574584084a31SMat Martineau * skb->data_len reflects only data in fragments 574684084a31SMat Martineau */ 574784084a31SMat Martineau if (!skb_has_frag_list(skb)) 574884084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag; 574984084a31SMat Martineau 575084084a31SMat Martineau new_frag->next = NULL; 575184084a31SMat Martineau 575284084a31SMat Martineau (*last_frag)->next = new_frag; 575384084a31SMat Martineau *last_frag = new_frag; 575484084a31SMat Martineau 575584084a31SMat Martineau skb->len += new_frag->len; 575684084a31SMat Martineau skb->data_len += new_frag->len; 575784084a31SMat Martineau skb->truesize += new_frag->truesize; 575884084a31SMat Martineau } 575984084a31SMat Martineau 57604b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, 57614b51dae9SMat Martineau struct l2cap_ctrl *control) 576284084a31SMat Martineau { 576384084a31SMat Martineau int err = -EINVAL; 57640a708f8fSGustavo F. Padovan 57654b51dae9SMat Martineau switch (control->sar) { 57667e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED: 576784084a31SMat Martineau if (chan->sdu) 576884084a31SMat Martineau break; 57690a708f8fSGustavo F. Padovan 577080b98027SGustavo Padovan err = chan->ops->recv(chan, skb); 577184084a31SMat Martineau break; 57720a708f8fSGustavo F. Padovan 57737e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START: 577484084a31SMat Martineau if (chan->sdu) 577584084a31SMat Martineau break; 57760a708f8fSGustavo F. Padovan 57776f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data); 577803a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE); 57790a708f8fSGustavo F. Padovan 578084084a31SMat Martineau if (chan->sdu_len > chan->imtu) { 578184084a31SMat Martineau err = -EMSGSIZE; 578284084a31SMat Martineau break; 578384084a31SMat Martineau } 57840a708f8fSGustavo F. Padovan 578584084a31SMat Martineau if (skb->len >= chan->sdu_len) 578684084a31SMat Martineau break; 578784084a31SMat Martineau 578884084a31SMat Martineau chan->sdu = skb; 578984084a31SMat Martineau chan->sdu_last_frag = skb; 579084084a31SMat Martineau 579184084a31SMat Martineau skb = NULL; 579284084a31SMat Martineau err = 0; 57930a708f8fSGustavo F. Padovan break; 57940a708f8fSGustavo F. Padovan 57957e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE: 57966f61fd47SGustavo F. Padovan if (!chan->sdu) 579784084a31SMat Martineau break; 57980a708f8fSGustavo F. Padovan 579984084a31SMat Martineau append_skb_frag(chan->sdu, skb, 580084084a31SMat Martineau &chan->sdu_last_frag); 580184084a31SMat Martineau skb = NULL; 58020a708f8fSGustavo F. Padovan 580384084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len) 580484084a31SMat Martineau break; 58050a708f8fSGustavo F. Padovan 580684084a31SMat Martineau err = 0; 58070a708f8fSGustavo F. Padovan break; 58080a708f8fSGustavo F. Padovan 58097e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END: 58106f61fd47SGustavo F. Padovan if (!chan->sdu) 581184084a31SMat Martineau break; 58120a708f8fSGustavo F. Padovan 581384084a31SMat Martineau append_skb_frag(chan->sdu, skb, 581484084a31SMat Martineau &chan->sdu_last_frag); 581584084a31SMat Martineau skb = NULL; 58160a708f8fSGustavo F. Padovan 581784084a31SMat Martineau if (chan->sdu->len != chan->sdu_len) 581884084a31SMat Martineau break; 58190a708f8fSGustavo F. Padovan 582080b98027SGustavo Padovan err = chan->ops->recv(chan, chan->sdu); 58210a708f8fSGustavo F. Padovan 582284084a31SMat Martineau if (!err) { 582384084a31SMat Martineau /* Reassembly complete */ 582484084a31SMat Martineau chan->sdu = NULL; 582584084a31SMat Martineau chan->sdu_last_frag = NULL; 582684084a31SMat Martineau chan->sdu_len = 0; 58270a708f8fSGustavo F. Padovan } 58280a708f8fSGustavo F. Padovan break; 58290a708f8fSGustavo F. Padovan } 58300a708f8fSGustavo F. Padovan 583184084a31SMat Martineau if (err) { 58320a708f8fSGustavo F. Padovan kfree_skb(skb); 58336f61fd47SGustavo F. Padovan kfree_skb(chan->sdu); 58346f61fd47SGustavo F. Padovan chan->sdu = NULL; 583584084a31SMat Martineau chan->sdu_last_frag = NULL; 583684084a31SMat Martineau chan->sdu_len = 0; 583784084a31SMat Martineau } 58380a708f8fSGustavo F. Padovan 583984084a31SMat Martineau return err; 58400a708f8fSGustavo F. Padovan } 58410a708f8fSGustavo F. Padovan 584232b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan) 584332b32735SMat Martineau { 584432b32735SMat Martineau /* Placeholder */ 584532b32735SMat Martineau return 0; 584632b32735SMat Martineau } 584732b32735SMat Martineau 5848e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 58490a708f8fSGustavo F. Padovan { 585061aa4f5bSMat Martineau u8 event; 585161aa4f5bSMat Martineau 585261aa4f5bSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 585361aa4f5bSMat Martineau return; 585461aa4f5bSMat Martineau 585561aa4f5bSMat Martineau event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR; 5856401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, event); 58570a708f8fSGustavo F. Padovan } 58580a708f8fSGustavo F. Padovan 5859d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan) 5860d2a7ac5dSMat Martineau { 586163838725SMat Martineau int err = 0; 586263838725SMat Martineau /* Pass sequential frames to l2cap_reassemble_sdu() 586363838725SMat Martineau * until a gap is encountered. 586463838725SMat Martineau */ 586563838725SMat Martineau 586663838725SMat Martineau BT_DBG("chan %p", chan); 586763838725SMat Martineau 586863838725SMat Martineau while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 586963838725SMat Martineau struct sk_buff *skb; 587063838725SMat Martineau BT_DBG("Searching for skb with txseq %d (queue len %d)", 587163838725SMat Martineau chan->buffer_seq, skb_queue_len(&chan->srej_q)); 587263838725SMat Martineau 587363838725SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq); 587463838725SMat Martineau 587563838725SMat Martineau if (!skb) 587663838725SMat Martineau break; 587763838725SMat Martineau 587863838725SMat Martineau skb_unlink(skb, &chan->srej_q); 587963838725SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 588063838725SMat Martineau err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->control); 588163838725SMat Martineau if (err) 588263838725SMat Martineau break; 588363838725SMat Martineau } 588463838725SMat Martineau 588563838725SMat Martineau if (skb_queue_empty(&chan->srej_q)) { 588663838725SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 588763838725SMat Martineau l2cap_send_ack(chan); 588863838725SMat Martineau } 588963838725SMat Martineau 589063838725SMat Martineau return err; 5891d2a7ac5dSMat Martineau } 5892d2a7ac5dSMat Martineau 5893d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan, 5894d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 5895d2a7ac5dSMat Martineau { 5896f80842a8SMat Martineau struct sk_buff *skb; 5897f80842a8SMat Martineau 5898f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 5899f80842a8SMat Martineau 5900f80842a8SMat Martineau if (control->reqseq == chan->next_tx_seq) { 5901f80842a8SMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 59025e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 5903f80842a8SMat Martineau return; 5904f80842a8SMat Martineau } 5905f80842a8SMat Martineau 5906f80842a8SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 5907f80842a8SMat Martineau 5908f80842a8SMat Martineau if (skb == NULL) { 5909f80842a8SMat Martineau BT_DBG("Seq %d not available for retransmission", 5910f80842a8SMat Martineau control->reqseq); 5911f80842a8SMat Martineau return; 5912f80842a8SMat Martineau } 5913f80842a8SMat Martineau 5914f80842a8SMat Martineau if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) { 5915f80842a8SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 59165e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 5917f80842a8SMat Martineau return; 5918f80842a8SMat Martineau } 5919f80842a8SMat Martineau 5920f80842a8SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 5921f80842a8SMat Martineau 5922f80842a8SMat Martineau if (control->poll) { 5923f80842a8SMat Martineau l2cap_pass_to_tx(chan, control); 5924f80842a8SMat Martineau 5925f80842a8SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 5926f80842a8SMat Martineau l2cap_retransmit(chan, control); 5927f80842a8SMat Martineau l2cap_ertm_send(chan); 5928f80842a8SMat Martineau 5929f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 5930f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 5931f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 5932f80842a8SMat Martineau } 5933f80842a8SMat Martineau } else { 5934f80842a8SMat Martineau l2cap_pass_to_tx_fbit(chan, control); 5935f80842a8SMat Martineau 5936f80842a8SMat Martineau if (control->final) { 5937f80842a8SMat Martineau if (chan->srej_save_reqseq != control->reqseq || 5938f80842a8SMat Martineau !test_and_clear_bit(CONN_SREJ_ACT, 5939f80842a8SMat Martineau &chan->conn_state)) 5940f80842a8SMat Martineau l2cap_retransmit(chan, control); 5941f80842a8SMat Martineau } else { 5942f80842a8SMat Martineau l2cap_retransmit(chan, control); 5943f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 5944f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 5945f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 5946f80842a8SMat Martineau } 5947f80842a8SMat Martineau } 5948f80842a8SMat Martineau } 5949d2a7ac5dSMat Martineau } 5950d2a7ac5dSMat Martineau 5951d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan, 5952d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 5953d2a7ac5dSMat Martineau { 5954fcd289dfSMat Martineau struct sk_buff *skb; 5955fcd289dfSMat Martineau 5956fcd289dfSMat Martineau BT_DBG("chan %p, control %p", chan, control); 5957fcd289dfSMat Martineau 5958fcd289dfSMat Martineau if (control->reqseq == chan->next_tx_seq) { 5959fcd289dfSMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 59605e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 5961fcd289dfSMat Martineau return; 5962fcd289dfSMat Martineau } 5963fcd289dfSMat Martineau 5964fcd289dfSMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 5965fcd289dfSMat Martineau 5966fcd289dfSMat Martineau if (chan->max_tx && skb && 5967fcd289dfSMat Martineau bt_cb(skb)->control.retries >= chan->max_tx) { 5968fcd289dfSMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 59695e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 5970fcd289dfSMat Martineau return; 5971fcd289dfSMat Martineau } 5972fcd289dfSMat Martineau 5973fcd289dfSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 5974fcd289dfSMat Martineau 5975fcd289dfSMat Martineau l2cap_pass_to_tx(chan, control); 5976fcd289dfSMat Martineau 5977fcd289dfSMat Martineau if (control->final) { 5978fcd289dfSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 5979fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 5980fcd289dfSMat Martineau } else { 5981fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 5982fcd289dfSMat Martineau l2cap_ertm_send(chan); 5983fcd289dfSMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) 5984fcd289dfSMat Martineau set_bit(CONN_REJ_ACT, &chan->conn_state); 5985fcd289dfSMat Martineau } 5986d2a7ac5dSMat Martineau } 5987d2a7ac5dSMat Martineau 59884b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) 59894b51dae9SMat Martineau { 59904b51dae9SMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 59914b51dae9SMat Martineau 59924b51dae9SMat Martineau BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq, 59934b51dae9SMat Martineau chan->expected_tx_seq); 59944b51dae9SMat Martineau 59954b51dae9SMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 59964b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 59974b51dae9SMat Martineau chan->tx_win) { 59984b51dae9SMat Martineau /* See notes below regarding "double poll" and 59994b51dae9SMat Martineau * invalid packets. 60004b51dae9SMat Martineau */ 60014b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 60024b51dae9SMat Martineau BT_DBG("Invalid/Ignore - after SREJ"); 60034b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 60044b51dae9SMat Martineau } else { 60054b51dae9SMat Martineau BT_DBG("Invalid - in window after SREJ sent"); 60064b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 60074b51dae9SMat Martineau } 60084b51dae9SMat Martineau } 60094b51dae9SMat Martineau 60104b51dae9SMat Martineau if (chan->srej_list.head == txseq) { 60114b51dae9SMat Martineau BT_DBG("Expected SREJ"); 60124b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED_SREJ; 60134b51dae9SMat Martineau } 60144b51dae9SMat Martineau 60154b51dae9SMat Martineau if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) { 60164b51dae9SMat Martineau BT_DBG("Duplicate SREJ - txseq already stored"); 60174b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE_SREJ; 60184b51dae9SMat Martineau } 60194b51dae9SMat Martineau 60204b51dae9SMat Martineau if (l2cap_seq_list_contains(&chan->srej_list, txseq)) { 60214b51dae9SMat Martineau BT_DBG("Unexpected SREJ - not requested"); 60224b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED_SREJ; 60234b51dae9SMat Martineau } 60244b51dae9SMat Martineau } 60254b51dae9SMat Martineau 60264b51dae9SMat Martineau if (chan->expected_tx_seq == txseq) { 60274b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 60284b51dae9SMat Martineau chan->tx_win) { 60294b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 60304b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 60314b51dae9SMat Martineau } else { 60324b51dae9SMat Martineau BT_DBG("Expected"); 60334b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED; 60344b51dae9SMat Martineau } 60354b51dae9SMat Martineau } 60364b51dae9SMat Martineau 60374b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) < 60382d792818SGustavo Padovan __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) { 60394b51dae9SMat Martineau BT_DBG("Duplicate - expected_tx_seq later than txseq"); 60404b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE; 60414b51dae9SMat Martineau } 60424b51dae9SMat Martineau 60434b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) { 60444b51dae9SMat Martineau /* A source of invalid packets is a "double poll" condition, 60454b51dae9SMat Martineau * where delays cause us to send multiple poll packets. If 60464b51dae9SMat Martineau * the remote stack receives and processes both polls, 60474b51dae9SMat Martineau * sequence numbers can wrap around in such a way that a 60484b51dae9SMat Martineau * resent frame has a sequence number that looks like new data 60494b51dae9SMat Martineau * with a sequence gap. This would trigger an erroneous SREJ 60504b51dae9SMat Martineau * request. 60514b51dae9SMat Martineau * 60524b51dae9SMat Martineau * Fortunately, this is impossible with a tx window that's 60534b51dae9SMat Martineau * less than half of the maximum sequence number, which allows 60544b51dae9SMat Martineau * invalid frames to be safely ignored. 60554b51dae9SMat Martineau * 60564b51dae9SMat Martineau * With tx window sizes greater than half of the tx window 60574b51dae9SMat Martineau * maximum, the frame is invalid and cannot be ignored. This 60584b51dae9SMat Martineau * causes a disconnect. 60594b51dae9SMat Martineau */ 60604b51dae9SMat Martineau 60614b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 60624b51dae9SMat Martineau BT_DBG("Invalid/Ignore - txseq outside tx window"); 60634b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 60644b51dae9SMat Martineau } else { 60654b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 60664b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 60674b51dae9SMat Martineau } 60684b51dae9SMat Martineau } else { 60694b51dae9SMat Martineau BT_DBG("Unexpected - txseq indicates missing frames"); 60704b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED; 60714b51dae9SMat Martineau } 60724b51dae9SMat Martineau } 60734b51dae9SMat Martineau 6074d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan, 6075d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 6076d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 6077d2a7ac5dSMat Martineau { 6078d2a7ac5dSMat Martineau int err = 0; 6079941247f9SPeter Senna Tschudin bool skb_in_use = false; 6080d2a7ac5dSMat Martineau 6081d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 6082d2a7ac5dSMat Martineau event); 6083d2a7ac5dSMat Martineau 6084d2a7ac5dSMat Martineau switch (event) { 6085d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 6086d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, control->txseq)) { 6087d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 6088d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6089d2a7ac5dSMat Martineau 6090d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 6091d2a7ac5dSMat Martineau BT_DBG("Busy, discarding expected seq %d", 6092d2a7ac5dSMat Martineau control->txseq); 6093d2a7ac5dSMat Martineau break; 6094d2a7ac5dSMat Martineau } 6095d2a7ac5dSMat Martineau 6096d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, 6097d2a7ac5dSMat Martineau control->txseq); 6098d2a7ac5dSMat Martineau 6099d2a7ac5dSMat Martineau chan->buffer_seq = chan->expected_tx_seq; 6100941247f9SPeter Senna Tschudin skb_in_use = true; 6101d2a7ac5dSMat Martineau 6102d2a7ac5dSMat Martineau err = l2cap_reassemble_sdu(chan, skb, control); 6103d2a7ac5dSMat Martineau if (err) 6104d2a7ac5dSMat Martineau break; 6105d2a7ac5dSMat Martineau 6106d2a7ac5dSMat Martineau if (control->final) { 6107d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 6108d2a7ac5dSMat Martineau &chan->conn_state)) { 6109d2a7ac5dSMat Martineau control->final = 0; 6110d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6111d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6112d2a7ac5dSMat Martineau } 6113d2a7ac5dSMat Martineau } 6114d2a7ac5dSMat Martineau 6115d2a7ac5dSMat Martineau if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 6116d2a7ac5dSMat Martineau l2cap_send_ack(chan); 6117d2a7ac5dSMat Martineau break; 6118d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 6119d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6120d2a7ac5dSMat Martineau 6121d2a7ac5dSMat Martineau /* Can't issue SREJ frames in the local busy state. 6122d2a7ac5dSMat Martineau * Drop this frame, it will be seen as missing 6123d2a7ac5dSMat Martineau * when local busy is exited. 6124d2a7ac5dSMat Martineau */ 6125d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 6126d2a7ac5dSMat Martineau BT_DBG("Busy, discarding unexpected seq %d", 6127d2a7ac5dSMat Martineau control->txseq); 6128d2a7ac5dSMat Martineau break; 6129d2a7ac5dSMat Martineau } 6130d2a7ac5dSMat Martineau 6131d2a7ac5dSMat Martineau /* There was a gap in the sequence, so an SREJ 6132d2a7ac5dSMat Martineau * must be sent for each missing frame. The 6133d2a7ac5dSMat Martineau * current frame is stored for later use. 6134d2a7ac5dSMat Martineau */ 6135d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6136941247f9SPeter Senna Tschudin skb_in_use = true; 6137d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6138d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6139d2a7ac5dSMat Martineau 6140d2a7ac5dSMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 6141d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 6142d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 6143d2a7ac5dSMat Martineau 6144d2a7ac5dSMat Martineau chan->rx_state = L2CAP_RX_STATE_SREJ_SENT; 6145d2a7ac5dSMat Martineau break; 6146d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 6147d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6148d2a7ac5dSMat Martineau break; 6149d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 6150d2a7ac5dSMat Martineau break; 6151d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 6152d2a7ac5dSMat Martineau default: 61535e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6154d2a7ac5dSMat Martineau break; 6155d2a7ac5dSMat Martineau } 6156d2a7ac5dSMat Martineau break; 6157d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 6158d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6159d2a7ac5dSMat Martineau if (control->final) { 6160d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6161d2a7ac5dSMat Martineau 6162e6a3ee6eSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) && 6163e6a3ee6eSMat Martineau !__chan_is_moving(chan)) { 6164d2a7ac5dSMat Martineau control->final = 0; 6165d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6166d2a7ac5dSMat Martineau } 6167d2a7ac5dSMat Martineau 6168d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6169d2a7ac5dSMat Martineau } else if (control->poll) { 6170d2a7ac5dSMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 6171d2a7ac5dSMat Martineau } else { 6172d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6173d2a7ac5dSMat Martineau &chan->conn_state) && 6174d2a7ac5dSMat Martineau chan->unacked_frames) 6175d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6176d2a7ac5dSMat Martineau 6177d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6178d2a7ac5dSMat Martineau } 6179d2a7ac5dSMat Martineau break; 6180d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 6181d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6182d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6183d2a7ac5dSMat Martineau if (control && control->poll) { 6184d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6185d2a7ac5dSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 6186d2a7ac5dSMat Martineau } 6187d2a7ac5dSMat Martineau __clear_retrans_timer(chan); 6188d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 6189d2a7ac5dSMat Martineau break; 6190d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 6191d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 6192d2a7ac5dSMat Martineau break; 6193d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 6194d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 6195d2a7ac5dSMat Martineau break; 6196d2a7ac5dSMat Martineau default: 6197d2a7ac5dSMat Martineau break; 6198d2a7ac5dSMat Martineau } 6199d2a7ac5dSMat Martineau 6200d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 6201d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 6202d2a7ac5dSMat Martineau kfree_skb(skb); 6203d2a7ac5dSMat Martineau } 6204d2a7ac5dSMat Martineau 6205d2a7ac5dSMat Martineau return err; 6206d2a7ac5dSMat Martineau } 6207d2a7ac5dSMat Martineau 6208d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, 6209d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 6210d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 6211d2a7ac5dSMat Martineau { 6212d2a7ac5dSMat Martineau int err = 0; 6213d2a7ac5dSMat Martineau u16 txseq = control->txseq; 6214941247f9SPeter Senna Tschudin bool skb_in_use = false; 6215d2a7ac5dSMat Martineau 6216d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 6217d2a7ac5dSMat Martineau event); 6218d2a7ac5dSMat Martineau 6219d2a7ac5dSMat Martineau switch (event) { 6220d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 6221d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, txseq)) { 6222d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 6223d2a7ac5dSMat Martineau /* Keep frame for reassembly later */ 6224d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6225d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6226941247f9SPeter Senna Tschudin skb_in_use = true; 6227d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6228d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6229d2a7ac5dSMat Martineau 6230d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 6231d2a7ac5dSMat Martineau break; 6232d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED_SREJ: 6233d2a7ac5dSMat Martineau l2cap_seq_list_pop(&chan->srej_list); 6234d2a7ac5dSMat Martineau 6235d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6236d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6237941247f9SPeter Senna Tschudin skb_in_use = true; 6238d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6239d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6240d2a7ac5dSMat Martineau 6241d2a7ac5dSMat Martineau err = l2cap_rx_queued_iframes(chan); 6242d2a7ac5dSMat Martineau if (err) 6243d2a7ac5dSMat Martineau break; 6244d2a7ac5dSMat Martineau 6245d2a7ac5dSMat Martineau break; 6246d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 6247d2a7ac5dSMat Martineau /* Got a frame that can't be reassembled yet. 6248d2a7ac5dSMat Martineau * Save it for later, and send SREJs to cover 6249d2a7ac5dSMat Martineau * the missing frames. 6250d2a7ac5dSMat Martineau */ 6251d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6252941247f9SPeter Senna Tschudin skb_in_use = true; 6253d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6254d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6255d2a7ac5dSMat Martineau 6256d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6257d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 6258d2a7ac5dSMat Martineau break; 6259d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED_SREJ: 6260d2a7ac5dSMat Martineau /* This frame was requested with an SREJ, but 6261d2a7ac5dSMat Martineau * some expected retransmitted frames are 6262d2a7ac5dSMat Martineau * missing. Request retransmission of missing 6263d2a7ac5dSMat Martineau * SREJ'd frames. 6264d2a7ac5dSMat Martineau */ 6265d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6266941247f9SPeter Senna Tschudin skb_in_use = true; 6267d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6268d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6269d2a7ac5dSMat Martineau 6270d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6271d2a7ac5dSMat Martineau l2cap_send_srej_list(chan, control->txseq); 6272d2a7ac5dSMat Martineau break; 6273d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE_SREJ: 6274d2a7ac5dSMat Martineau /* We've already queued this frame. Drop this copy. */ 6275d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6276d2a7ac5dSMat Martineau break; 6277d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 6278d2a7ac5dSMat Martineau /* Expecting a later sequence number, so this frame 6279d2a7ac5dSMat Martineau * was already received. Ignore it completely. 6280d2a7ac5dSMat Martineau */ 6281d2a7ac5dSMat Martineau break; 6282d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 6283d2a7ac5dSMat Martineau break; 6284d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 6285d2a7ac5dSMat Martineau default: 62865e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6287d2a7ac5dSMat Martineau break; 6288d2a7ac5dSMat Martineau } 6289d2a7ac5dSMat Martineau break; 6290d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 6291d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6292d2a7ac5dSMat Martineau if (control->final) { 6293d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6294d2a7ac5dSMat Martineau 6295d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 6296d2a7ac5dSMat Martineau &chan->conn_state)) { 6297d2a7ac5dSMat Martineau control->final = 0; 6298d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6299d2a7ac5dSMat Martineau } 6300d2a7ac5dSMat Martineau 6301d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6302d2a7ac5dSMat Martineau } else if (control->poll) { 6303d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6304d2a7ac5dSMat Martineau &chan->conn_state) && 6305d2a7ac5dSMat Martineau chan->unacked_frames) { 6306d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6307d2a7ac5dSMat Martineau } 6308d2a7ac5dSMat Martineau 6309d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6310d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 6311d2a7ac5dSMat Martineau } else { 6312d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6313d2a7ac5dSMat Martineau &chan->conn_state) && 6314d2a7ac5dSMat Martineau chan->unacked_frames) 6315d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6316d2a7ac5dSMat Martineau 6317d2a7ac5dSMat Martineau l2cap_send_ack(chan); 6318d2a7ac5dSMat Martineau } 6319d2a7ac5dSMat Martineau break; 6320d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 6321d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6322d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6323d2a7ac5dSMat Martineau if (control->poll) { 6324d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 6325d2a7ac5dSMat Martineau } else { 6326d2a7ac5dSMat Martineau struct l2cap_ctrl rr_control; 6327d2a7ac5dSMat Martineau memset(&rr_control, 0, sizeof(rr_control)); 6328d2a7ac5dSMat Martineau rr_control.sframe = 1; 6329d2a7ac5dSMat Martineau rr_control.super = L2CAP_SUPER_RR; 6330d2a7ac5dSMat Martineau rr_control.reqseq = chan->buffer_seq; 6331d2a7ac5dSMat Martineau l2cap_send_sframe(chan, &rr_control); 6332d2a7ac5dSMat Martineau } 6333d2a7ac5dSMat Martineau 6334d2a7ac5dSMat Martineau break; 6335d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 6336d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 6337d2a7ac5dSMat Martineau break; 6338d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 6339d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 6340d2a7ac5dSMat Martineau break; 6341d2a7ac5dSMat Martineau } 6342d2a7ac5dSMat Martineau 6343d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 6344d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 6345d2a7ac5dSMat Martineau kfree_skb(skb); 6346d2a7ac5dSMat Martineau } 6347d2a7ac5dSMat Martineau 6348d2a7ac5dSMat Martineau return err; 6349d2a7ac5dSMat Martineau } 6350d2a7ac5dSMat Martineau 635132b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan) 635232b32735SMat Martineau { 635332b32735SMat Martineau BT_DBG("chan %p", chan); 635432b32735SMat Martineau 635532b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 635632b32735SMat Martineau 635732b32735SMat Martineau if (chan->hs_hcon) 635832b32735SMat Martineau chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; 635932b32735SMat Martineau else 636032b32735SMat Martineau chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; 636132b32735SMat Martineau 636232b32735SMat Martineau return l2cap_resegment(chan); 636332b32735SMat Martineau } 636432b32735SMat Martineau 636532b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan, 636632b32735SMat Martineau struct l2cap_ctrl *control, 636732b32735SMat Martineau struct sk_buff *skb, u8 event) 636832b32735SMat Martineau { 636932b32735SMat Martineau int err; 637032b32735SMat Martineau 637132b32735SMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 637232b32735SMat Martineau event); 637332b32735SMat Martineau 637432b32735SMat Martineau if (!control->poll) 637532b32735SMat Martineau return -EPROTO; 637632b32735SMat Martineau 637732b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq); 637832b32735SMat Martineau 637932b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q)) 638032b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q); 638132b32735SMat Martineau else 638232b32735SMat Martineau chan->tx_send_head = NULL; 638332b32735SMat Martineau 638432b32735SMat Martineau /* Rewind next_tx_seq to the point expected 638532b32735SMat Martineau * by the receiver. 638632b32735SMat Martineau */ 638732b32735SMat Martineau chan->next_tx_seq = control->reqseq; 638832b32735SMat Martineau chan->unacked_frames = 0; 638932b32735SMat Martineau 639032b32735SMat Martineau err = l2cap_finish_move(chan); 639132b32735SMat Martineau if (err) 639232b32735SMat Martineau return err; 639332b32735SMat Martineau 639432b32735SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 639532b32735SMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 639632b32735SMat Martineau 639732b32735SMat Martineau if (event == L2CAP_EV_RECV_IFRAME) 639832b32735SMat Martineau return -EPROTO; 639932b32735SMat Martineau 640032b32735SMat Martineau return l2cap_rx_state_recv(chan, control, NULL, event); 640132b32735SMat Martineau } 640232b32735SMat Martineau 640332b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan, 640432b32735SMat Martineau struct l2cap_ctrl *control, 640532b32735SMat Martineau struct sk_buff *skb, u8 event) 640632b32735SMat Martineau { 640732b32735SMat Martineau int err; 640832b32735SMat Martineau 640932b32735SMat Martineau if (!control->final) 641032b32735SMat Martineau return -EPROTO; 641132b32735SMat Martineau 641232b32735SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 641332b32735SMat Martineau 641432b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 641532b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq); 641632b32735SMat Martineau 641732b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q)) 641832b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q); 641932b32735SMat Martineau else 642032b32735SMat Martineau chan->tx_send_head = NULL; 642132b32735SMat Martineau 642232b32735SMat Martineau /* Rewind next_tx_seq to the point expected 642332b32735SMat Martineau * by the receiver. 642432b32735SMat Martineau */ 642532b32735SMat Martineau chan->next_tx_seq = control->reqseq; 642632b32735SMat Martineau chan->unacked_frames = 0; 642732b32735SMat Martineau 642832b32735SMat Martineau if (chan->hs_hcon) 642932b32735SMat Martineau chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; 643032b32735SMat Martineau else 643132b32735SMat Martineau chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; 643232b32735SMat Martineau 643332b32735SMat Martineau err = l2cap_resegment(chan); 643432b32735SMat Martineau 643532b32735SMat Martineau if (!err) 643632b32735SMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 643732b32735SMat Martineau 643832b32735SMat Martineau return err; 643932b32735SMat Martineau } 644032b32735SMat Martineau 6441d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq) 6442d2a7ac5dSMat Martineau { 6443d2a7ac5dSMat Martineau /* Make sure reqseq is for a packet that has been sent but not acked */ 6444d2a7ac5dSMat Martineau u16 unacked; 6445d2a7ac5dSMat Martineau 6446d2a7ac5dSMat Martineau unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq); 6447d2a7ac5dSMat Martineau return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked; 6448d2a7ac5dSMat Martineau } 6449d2a7ac5dSMat Martineau 6450cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 6451cec8ab6eSMat Martineau struct sk_buff *skb, u8 event) 64520a708f8fSGustavo F. Padovan { 6453d2a7ac5dSMat Martineau int err = 0; 6454d2a7ac5dSMat Martineau 6455d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan, 6456d2a7ac5dSMat Martineau control, skb, event, chan->rx_state); 6457d2a7ac5dSMat Martineau 6458d2a7ac5dSMat Martineau if (__valid_reqseq(chan, control->reqseq)) { 6459d2a7ac5dSMat Martineau switch (chan->rx_state) { 6460d2a7ac5dSMat Martineau case L2CAP_RX_STATE_RECV: 6461d2a7ac5dSMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 6462d2a7ac5dSMat Martineau break; 6463d2a7ac5dSMat Martineau case L2CAP_RX_STATE_SREJ_SENT: 6464d2a7ac5dSMat Martineau err = l2cap_rx_state_srej_sent(chan, control, skb, 6465d2a7ac5dSMat Martineau event); 6466d2a7ac5dSMat Martineau break; 646732b32735SMat Martineau case L2CAP_RX_STATE_WAIT_P: 646832b32735SMat Martineau err = l2cap_rx_state_wait_p(chan, control, skb, event); 646932b32735SMat Martineau break; 647032b32735SMat Martineau case L2CAP_RX_STATE_WAIT_F: 647132b32735SMat Martineau err = l2cap_rx_state_wait_f(chan, control, skb, event); 647232b32735SMat Martineau break; 6473d2a7ac5dSMat Martineau default: 6474d2a7ac5dSMat Martineau /* shut it down */ 6475d2a7ac5dSMat Martineau break; 6476d2a7ac5dSMat Martineau } 6477d2a7ac5dSMat Martineau } else { 6478d2a7ac5dSMat Martineau BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d", 6479d2a7ac5dSMat Martineau control->reqseq, chan->next_tx_seq, 6480d2a7ac5dSMat Martineau chan->expected_ack_seq); 64815e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6482d2a7ac5dSMat Martineau } 6483d2a7ac5dSMat Martineau 6484d2a7ac5dSMat Martineau return err; 6485cec8ab6eSMat Martineau } 6486cec8ab6eSMat Martineau 6487cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 6488cec8ab6eSMat Martineau struct sk_buff *skb) 6489cec8ab6eSMat Martineau { 64904b51dae9SMat Martineau int err = 0; 64914b51dae9SMat Martineau 64924b51dae9SMat Martineau BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb, 64934b51dae9SMat Martineau chan->rx_state); 64944b51dae9SMat Martineau 64954b51dae9SMat Martineau if (l2cap_classify_txseq(chan, control->txseq) == 64964b51dae9SMat Martineau L2CAP_TXSEQ_EXPECTED) { 64974b51dae9SMat Martineau l2cap_pass_to_tx(chan, control); 64984b51dae9SMat Martineau 64994b51dae9SMat Martineau BT_DBG("buffer_seq %d->%d", chan->buffer_seq, 65004b51dae9SMat Martineau __next_seq(chan, chan->buffer_seq)); 65014b51dae9SMat Martineau 65024b51dae9SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 65034b51dae9SMat Martineau 65044b51dae9SMat Martineau l2cap_reassemble_sdu(chan, skb, control); 65054b51dae9SMat Martineau } else { 65064b51dae9SMat Martineau if (chan->sdu) { 65074b51dae9SMat Martineau kfree_skb(chan->sdu); 65084b51dae9SMat Martineau chan->sdu = NULL; 65094b51dae9SMat Martineau } 65104b51dae9SMat Martineau chan->sdu_last_frag = NULL; 65114b51dae9SMat Martineau chan->sdu_len = 0; 65124b51dae9SMat Martineau 65134b51dae9SMat Martineau if (skb) { 65144b51dae9SMat Martineau BT_DBG("Freeing %p", skb); 65154b51dae9SMat Martineau kfree_skb(skb); 65164b51dae9SMat Martineau } 65174b51dae9SMat Martineau } 65184b51dae9SMat Martineau 65194b51dae9SMat Martineau chan->last_acked_seq = control->txseq; 65204b51dae9SMat Martineau chan->expected_tx_seq = __next_seq(chan, control->txseq); 65214b51dae9SMat Martineau 65224b51dae9SMat Martineau return err; 6523cec8ab6eSMat Martineau } 6524cec8ab6eSMat Martineau 6525cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 6526cec8ab6eSMat Martineau { 6527cec8ab6eSMat Martineau struct l2cap_ctrl *control = &bt_cb(skb)->control; 6528cec8ab6eSMat Martineau u16 len; 6529cec8ab6eSMat Martineau u8 event; 65300a708f8fSGustavo F. Padovan 6531b76bbd66SMat Martineau __unpack_control(chan, skb); 6532b76bbd66SMat Martineau 65330a708f8fSGustavo F. Padovan len = skb->len; 65340a708f8fSGustavo F. Padovan 65350a708f8fSGustavo F. Padovan /* 65360a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here. 65370a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery 6538cec8ab6eSMat Martineau * procedures and ask for retransmission. 65390a708f8fSGustavo F. Padovan */ 654047d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 65410a708f8fSGustavo F. Padovan goto drop; 65420a708f8fSGustavo F. Padovan 6543cec8ab6eSMat Martineau if (!control->sframe && control->sar == L2CAP_SAR_START) 654403a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 65450a708f8fSGustavo F. Padovan 654647d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 654703a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 65480a708f8fSGustavo F. Padovan 654947d1ec61SGustavo F. Padovan if (len > chan->mps) { 65505e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 65510a708f8fSGustavo F. Padovan goto drop; 65520a708f8fSGustavo F. Padovan } 65530a708f8fSGustavo F. Padovan 6554cec8ab6eSMat Martineau if (!control->sframe) { 6555cec8ab6eSMat Martineau int err; 65560a708f8fSGustavo F. Padovan 6557cec8ab6eSMat Martineau BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d", 6558cec8ab6eSMat Martineau control->sar, control->reqseq, control->final, 6559cec8ab6eSMat Martineau control->txseq); 6560836be934SAndrei Emeltchenko 6561cec8ab6eSMat Martineau /* Validate F-bit - F=0 always valid, F=1 only 6562cec8ab6eSMat Martineau * valid in TX WAIT_F 6563cec8ab6eSMat Martineau */ 6564cec8ab6eSMat Martineau if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F) 65650a708f8fSGustavo F. Padovan goto drop; 65660a708f8fSGustavo F. Padovan 6567cec8ab6eSMat Martineau if (chan->mode != L2CAP_MODE_STREAMING) { 6568cec8ab6eSMat Martineau event = L2CAP_EV_RECV_IFRAME; 6569cec8ab6eSMat Martineau err = l2cap_rx(chan, control, skb, event); 65700a708f8fSGustavo F. Padovan } else { 6571cec8ab6eSMat Martineau err = l2cap_stream_rx(chan, control, skb); 6572cec8ab6eSMat Martineau } 6573cec8ab6eSMat Martineau 6574cec8ab6eSMat Martineau if (err) 65755e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6576cec8ab6eSMat Martineau } else { 6577cec8ab6eSMat Martineau const u8 rx_func_to_event[4] = { 6578cec8ab6eSMat Martineau L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ, 6579cec8ab6eSMat Martineau L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ 6580cec8ab6eSMat Martineau }; 6581cec8ab6eSMat Martineau 6582cec8ab6eSMat Martineau /* Only I-frames are expected in streaming mode */ 6583cec8ab6eSMat Martineau if (chan->mode == L2CAP_MODE_STREAMING) 6584cec8ab6eSMat Martineau goto drop; 6585cec8ab6eSMat Martineau 6586cec8ab6eSMat Martineau BT_DBG("sframe reqseq %d, final %d, poll %d, super %d", 6587cec8ab6eSMat Martineau control->reqseq, control->final, control->poll, 6588cec8ab6eSMat Martineau control->super); 6589cec8ab6eSMat Martineau 65900a708f8fSGustavo F. Padovan if (len != 0) { 65911bb166e6SAndrei Emeltchenko BT_ERR("Trailing bytes: %d in sframe", len); 65925e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 65930a708f8fSGustavo F. Padovan goto drop; 65940a708f8fSGustavo F. Padovan } 65950a708f8fSGustavo F. Padovan 6596cec8ab6eSMat Martineau /* Validate F and P bits */ 6597cec8ab6eSMat Martineau if (control->final && (control->poll || 6598cec8ab6eSMat Martineau chan->tx_state != L2CAP_TX_STATE_WAIT_F)) 6599cec8ab6eSMat Martineau goto drop; 6600cec8ab6eSMat Martineau 6601cec8ab6eSMat Martineau event = rx_func_to_event[control->super]; 6602cec8ab6eSMat Martineau if (l2cap_rx(chan, control, skb, event)) 66035e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 66040a708f8fSGustavo F. Padovan } 66050a708f8fSGustavo F. Padovan 66060a708f8fSGustavo F. Padovan return 0; 66070a708f8fSGustavo F. Padovan 66080a708f8fSGustavo F. Padovan drop: 66090a708f8fSGustavo F. Padovan kfree_skb(skb); 66100a708f8fSGustavo F. Padovan return 0; 66110a708f8fSGustavo F. Padovan } 66120a708f8fSGustavo F. Padovan 661313ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid, 661413ca56e0SAndrei Emeltchenko struct sk_buff *skb) 66150a708f8fSGustavo F. Padovan { 661648454079SGustavo F. Padovan struct l2cap_chan *chan; 66170a708f8fSGustavo F. Padovan 6618baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 661948454079SGustavo F. Padovan if (!chan) { 662097e8e89dSAndrei Emeltchenko if (cid == L2CAP_CID_A2MP) { 662197e8e89dSAndrei Emeltchenko chan = a2mp_channel_create(conn, skb); 662297e8e89dSAndrei Emeltchenko if (!chan) { 662397e8e89dSAndrei Emeltchenko kfree_skb(skb); 662413ca56e0SAndrei Emeltchenko return; 662597e8e89dSAndrei Emeltchenko } 662697e8e89dSAndrei Emeltchenko 662797e8e89dSAndrei Emeltchenko l2cap_chan_lock(chan); 662897e8e89dSAndrei Emeltchenko } else { 66290a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid); 66306be36555SAndrei Emeltchenko /* Drop packet and return */ 66313379013bSDan Carpenter kfree_skb(skb); 663213ca56e0SAndrei Emeltchenko return; 66330a708f8fSGustavo F. Padovan } 663497e8e89dSAndrei Emeltchenko } 66350a708f8fSGustavo F. Padovan 663649208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len); 66370a708f8fSGustavo F. Padovan 663889bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 66390a708f8fSGustavo F. Padovan goto drop; 66400a708f8fSGustavo F. Padovan 66410c1bc5c6SGustavo F. Padovan switch (chan->mode) { 664238319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 66430a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 66440a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here 66450a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable. 66460a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't 66470a708f8fSGustavo F. Padovan * provide flow control mechanism. */ 66480a708f8fSGustavo F. Padovan 66490c1bc5c6SGustavo F. Padovan if (chan->imtu < skb->len) 66500a708f8fSGustavo F. Padovan goto drop; 66510a708f8fSGustavo F. Padovan 665280b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 66530a708f8fSGustavo F. Padovan goto done; 66540a708f8fSGustavo F. Padovan break; 66550a708f8fSGustavo F. Padovan 66560a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 66570a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 6658cec8ab6eSMat Martineau l2cap_data_rcv(chan, skb); 66590a708f8fSGustavo F. Padovan goto done; 66600a708f8fSGustavo F. Padovan 66610a708f8fSGustavo F. Padovan default: 66620c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); 66630a708f8fSGustavo F. Padovan break; 66640a708f8fSGustavo F. Padovan } 66650a708f8fSGustavo F. Padovan 66660a708f8fSGustavo F. Padovan drop: 66670a708f8fSGustavo F. Padovan kfree_skb(skb); 66680a708f8fSGustavo F. Padovan 66690a708f8fSGustavo F. Padovan done: 66706be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 66710a708f8fSGustavo F. Padovan } 66720a708f8fSGustavo F. Padovan 667384104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, 667484104b24SAndrei Emeltchenko struct sk_buff *skb) 66750a708f8fSGustavo F. Padovan { 6676ae4fd2d3SMarcel Holtmann struct hci_conn *hcon = conn->hcon; 667723691d75SGustavo F. Padovan struct l2cap_chan *chan; 66780a708f8fSGustavo F. Padovan 6679ae4fd2d3SMarcel Holtmann if (hcon->type != ACL_LINK) 6680ae4fd2d3SMarcel Holtmann goto drop; 6681ae4fd2d3SMarcel Holtmann 6682bf20fd4eSJohan Hedberg chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst, 6683bf20fd4eSJohan Hedberg ACL_LINK); 668423691d75SGustavo F. Padovan if (!chan) 66850a708f8fSGustavo F. Padovan goto drop; 66860a708f8fSGustavo F. Padovan 66875b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 66880a708f8fSGustavo F. Padovan 668989bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 66900a708f8fSGustavo F. Padovan goto drop; 66910a708f8fSGustavo F. Padovan 6692e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 66930a708f8fSGustavo F. Padovan goto drop; 66940a708f8fSGustavo F. Padovan 66952edf870dSMarcel Holtmann /* Store remote BD_ADDR and PSM for msg_name */ 669606ae3314SMarcel Holtmann bacpy(&bt_cb(skb)->bdaddr, &hcon->dst); 66972edf870dSMarcel Holtmann bt_cb(skb)->psm = psm; 66982edf870dSMarcel Holtmann 669980b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 670084104b24SAndrei Emeltchenko return; 67010a708f8fSGustavo F. Padovan 67020a708f8fSGustavo F. Padovan drop: 67030a708f8fSGustavo F. Padovan kfree_skb(skb); 67040a708f8fSGustavo F. Padovan } 67050a708f8fSGustavo F. Padovan 670672f78356SMarcel Holtmann static void l2cap_att_channel(struct l2cap_conn *conn, 6707d9b88702SAndrei Emeltchenko struct sk_buff *skb) 67089f69bda6SGustavo F. Padovan { 6709b99707d7SMarcel Holtmann struct hci_conn *hcon = conn->hcon; 671023691d75SGustavo F. Padovan struct l2cap_chan *chan; 67119f69bda6SGustavo F. Padovan 6712b99707d7SMarcel Holtmann if (hcon->type != LE_LINK) 6713b99707d7SMarcel Holtmann goto drop; 6714b99707d7SMarcel Holtmann 6715af1c0134SJohan Hedberg chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT, 671606ae3314SMarcel Holtmann &hcon->src, &hcon->dst); 671723691d75SGustavo F. Padovan if (!chan) 67189f69bda6SGustavo F. Padovan goto drop; 67199f69bda6SGustavo F. Padovan 67205b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 67219f69bda6SGustavo F. Padovan 6722cc8dba2bSMarcel Holtmann if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, hcon->dst_type)) 6723cc8dba2bSMarcel Holtmann goto drop; 6724cc8dba2bSMarcel Holtmann 6725e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 67269f69bda6SGustavo F. Padovan goto drop; 67279f69bda6SGustavo F. Padovan 672880b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 67296810fca7SAndrei Emeltchenko return; 67309f69bda6SGustavo F. Padovan 67319f69bda6SGustavo F. Padovan drop: 67329f69bda6SGustavo F. Padovan kfree_skb(skb); 67339f69bda6SGustavo F. Padovan } 67349f69bda6SGustavo F. Padovan 67350a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) 67360a708f8fSGustavo F. Padovan { 67370a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data; 67380a708f8fSGustavo F. Padovan u16 cid, len; 67390a708f8fSGustavo F. Padovan __le16 psm; 67400a708f8fSGustavo F. Padovan 67410a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE); 67420a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid); 67430a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len); 67440a708f8fSGustavo F. Padovan 67450a708f8fSGustavo F. Padovan if (len != skb->len) { 67460a708f8fSGustavo F. Padovan kfree_skb(skb); 67470a708f8fSGustavo F. Padovan return; 67480a708f8fSGustavo F. Padovan } 67490a708f8fSGustavo F. Padovan 67500a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid); 67510a708f8fSGustavo F. Padovan 67520a708f8fSGustavo F. Padovan switch (cid) { 67530a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING: 67540a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb); 67550a708f8fSGustavo F. Padovan break; 67560a708f8fSGustavo F. Padovan 67570a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS: 6758097db76cSAndrei Emeltchenko psm = get_unaligned((__le16 *) skb->data); 67590181a70fSAndrei Emeltchenko skb_pull(skb, L2CAP_PSMLEN_SIZE); 67600a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb); 67610a708f8fSGustavo F. Padovan break; 67620a708f8fSGustavo F. Padovan 6763073d1cf3SJohan Hedberg case L2CAP_CID_ATT: 676472f78356SMarcel Holtmann l2cap_att_channel(conn, skb); 67659f69bda6SGustavo F. Padovan break; 67669f69bda6SGustavo F. Padovan 6767a2877629SMarcel Holtmann case L2CAP_CID_LE_SIGNALING: 6768a2877629SMarcel Holtmann l2cap_le_sig_channel(conn, skb); 6769a2877629SMarcel Holtmann break; 6770a2877629SMarcel Holtmann 6771b501d6a1SAnderson Briglia case L2CAP_CID_SMP: 6772b501d6a1SAnderson Briglia if (smp_sig_channel(conn, skb)) 6773b501d6a1SAnderson Briglia l2cap_conn_del(conn->hcon, EACCES); 6774b501d6a1SAnderson Briglia break; 6775b501d6a1SAnderson Briglia 67760a708f8fSGustavo F. Padovan default: 67770a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb); 67780a708f8fSGustavo F. Padovan break; 67790a708f8fSGustavo F. Padovan } 67800a708f8fSGustavo F. Padovan } 67810a708f8fSGustavo F. Padovan 67820a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */ 67830a708f8fSGustavo F. Padovan 6784686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) 67850a708f8fSGustavo F. Padovan { 67860a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0; 678723691d75SGustavo F. Padovan struct l2cap_chan *c; 67880a708f8fSGustavo F. Padovan 67896ed93dc6SAndrei Emeltchenko BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr); 67900a708f8fSGustavo F. Padovan 67910a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */ 679223691d75SGustavo F. Padovan read_lock(&chan_list_lock); 679323691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 679489bc500eSGustavo F. Padovan if (c->state != BT_LISTEN) 67950a708f8fSGustavo F. Padovan continue; 67960a708f8fSGustavo F. Padovan 67977eafc59eSMarcel Holtmann if (!bacmp(&c->src, &hdev->bdaddr)) { 67980a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT; 679943bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 68000a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER; 68010a708f8fSGustavo F. Padovan exact++; 68027eafc59eSMarcel Holtmann } else if (!bacmp(&c->src, BDADDR_ANY)) { 68030a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT; 680443bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 68050a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER; 68060a708f8fSGustavo F. Padovan } 68070a708f8fSGustavo F. Padovan } 680823691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 68090a708f8fSGustavo F. Padovan 68100a708f8fSGustavo F. Padovan return exact ? lm1 : lm2; 68110a708f8fSGustavo F. Padovan } 68120a708f8fSGustavo F. Padovan 68139e664631SAndrei Emeltchenko void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) 68140a708f8fSGustavo F. Padovan { 68150a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 68160a708f8fSGustavo F. Padovan 68176ed93dc6SAndrei Emeltchenko BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status); 68180a708f8fSGustavo F. Padovan 68190a708f8fSGustavo F. Padovan if (!status) { 6820baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon); 68210a708f8fSGustavo F. Padovan if (conn) 68220a708f8fSGustavo F. Padovan l2cap_conn_ready(conn); 6823ba6fc317SAndrei Emeltchenko } else { 6824e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status)); 6825ba6fc317SAndrei Emeltchenko } 68260a708f8fSGustavo F. Padovan } 68270a708f8fSGustavo F. Padovan 6828686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon) 68290a708f8fSGustavo F. Padovan { 68300a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 68310a708f8fSGustavo F. Padovan 68320a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon); 68330a708f8fSGustavo F. Padovan 6834686ebf28SUlisses Furquim if (!conn) 68359f5a0d7bSAndrei Emeltchenko return HCI_ERROR_REMOTE_USER_TERM; 68360a708f8fSGustavo F. Padovan return conn->disc_reason; 68370a708f8fSGustavo F. Padovan } 68380a708f8fSGustavo F. Padovan 68399e664631SAndrei Emeltchenko void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) 68400a708f8fSGustavo F. Padovan { 68410a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason); 68420a708f8fSGustavo F. Padovan 6843e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason)); 68440a708f8fSGustavo F. Padovan } 68450a708f8fSGustavo F. Padovan 68464343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) 68470a708f8fSGustavo F. Padovan { 6848715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 68490a708f8fSGustavo F. Padovan return; 68500a708f8fSGustavo F. Padovan 68510a708f8fSGustavo F. Padovan if (encrypt == 0x00) { 68524343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) { 6853ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); 68544343478fSGustavo F. Padovan } else if (chan->sec_level == BT_SECURITY_HIGH) 68550f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED); 68560a708f8fSGustavo F. Padovan } else { 68574343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) 6858c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 68590a708f8fSGustavo F. Padovan } 68600a708f8fSGustavo F. Padovan } 68610a708f8fSGustavo F. Padovan 6862686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) 68630a708f8fSGustavo F. Padovan { 68640a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 686548454079SGustavo F. Padovan struct l2cap_chan *chan; 68660a708f8fSGustavo F. Padovan 68670a708f8fSGustavo F. Padovan if (!conn) 68680a708f8fSGustavo F. Padovan return 0; 68690a708f8fSGustavo F. Padovan 687089d8b407SAndrei Emeltchenko BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt); 68710a708f8fSGustavo F. Padovan 6872160dc6acSVinicius Costa Gomes if (hcon->type == LE_LINK) { 687335d4adccSHemant Gupta if (!status && encrypt) 6874160dc6acSVinicius Costa Gomes smp_distribute_keys(conn, 0); 687517cd3f37SUlisses Furquim cancel_delayed_work(&conn->security_timer); 6876160dc6acSVinicius Costa Gomes } 6877160dc6acSVinicius Costa Gomes 68783df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 68790a708f8fSGustavo F. Padovan 68803df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 68816be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 68820a708f8fSGustavo F. Padovan 688389d8b407SAndrei Emeltchenko BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, 688489d8b407SAndrei Emeltchenko state_to_string(chan->state)); 6885f1cb9af5SVinicius Costa Gomes 688678eb2f98SAndrei Emeltchenko if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { 688778eb2f98SAndrei Emeltchenko l2cap_chan_unlock(chan); 688878eb2f98SAndrei Emeltchenko continue; 688978eb2f98SAndrei Emeltchenko } 689078eb2f98SAndrei Emeltchenko 6891073d1cf3SJohan Hedberg if (chan->scid == L2CAP_CID_ATT) { 6892f1cb9af5SVinicius Costa Gomes if (!status && encrypt) { 6893f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level; 6894cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 6895f1cb9af5SVinicius Costa Gomes } 6896f1cb9af5SVinicius Costa Gomes 68976be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 6898f1cb9af5SVinicius Costa Gomes continue; 6899f1cb9af5SVinicius Costa Gomes } 6900f1cb9af5SVinicius Costa Gomes 690196eff46eSAndrei Emeltchenko if (!__l2cap_no_conn_pending(chan)) { 69026be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 69030a708f8fSGustavo F. Padovan continue; 69040a708f8fSGustavo F. Padovan } 69050a708f8fSGustavo F. Padovan 690689bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED || 690789bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) { 6908d97c899bSMarcel Holtmann chan->ops->resume(chan); 69094343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt); 69106be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 69110a708f8fSGustavo F. Padovan continue; 69120a708f8fSGustavo F. Padovan } 69130a708f8fSGustavo F. Padovan 691489bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 69156d3c15daSJohan Hedberg if (!status) 691693c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 69176d3c15daSJohan Hedberg else 6918ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 691989bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 69200a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 6921df3c3931SJohan Hedberg __u16 res, stat; 69220a708f8fSGustavo F. Padovan 69230a708f8fSGustavo F. Padovan if (!status) { 6924bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 6925df3c3931SJohan Hedberg res = L2CAP_CR_PEND; 6926df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND; 69272dc4e510SGustavo Padovan chan->ops->defer(chan); 6928df3c3931SJohan Hedberg } else { 6929acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 6930df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS; 6931df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 6932df3c3931SJohan Hedberg } 69330a708f8fSGustavo F. Padovan } else { 6934acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_DISCONN); 6935ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 6936df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK; 6937df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 69380a708f8fSGustavo F. Padovan } 69390a708f8fSGustavo F. Padovan 6940fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 6941fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 6942df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res); 6943df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat); 6944fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 6945fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 69462d369359SMat Martineau 69472d369359SMat Martineau if (!test_bit(CONF_REQ_SENT, &chan->conf_state) && 69482d369359SMat Martineau res == L2CAP_CR_SUCCESS) { 69492d369359SMat Martineau char buf[128]; 69502d369359SMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 69512d369359SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), 69522d369359SMat Martineau L2CAP_CONF_REQ, 69532d369359SMat Martineau l2cap_build_conf_req(chan, buf), 69542d369359SMat Martineau buf); 69552d369359SMat Martineau chan->num_conf_req++; 69562d369359SMat Martineau } 69570a708f8fSGustavo F. Padovan } 69580a708f8fSGustavo F. Padovan 69596be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 69600a708f8fSGustavo F. Padovan } 69610a708f8fSGustavo F. Padovan 69623df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 69630a708f8fSGustavo F. Padovan 69640a708f8fSGustavo F. Padovan return 0; 69650a708f8fSGustavo F. Padovan } 69660a708f8fSGustavo F. Padovan 6967686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) 69680a708f8fSGustavo F. Padovan { 69690a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 6970d73a0988SAndrei Emeltchenko struct l2cap_hdr *hdr; 6971d73a0988SAndrei Emeltchenko int len; 69720a708f8fSGustavo F. Padovan 69731d13a254SAndrei Emeltchenko /* For AMP controller do not create l2cap conn */ 69741d13a254SAndrei Emeltchenko if (!conn && hcon->hdev->dev_type != HCI_BREDR) 69751d13a254SAndrei Emeltchenko goto drop; 69760a708f8fSGustavo F. Padovan 69770a708f8fSGustavo F. Padovan if (!conn) 6978baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon); 69790a708f8fSGustavo F. Padovan 69800a708f8fSGustavo F. Padovan if (!conn) 69810a708f8fSGustavo F. Padovan goto drop; 69820a708f8fSGustavo F. Padovan 69830a708f8fSGustavo F. Padovan BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); 69840a708f8fSGustavo F. Padovan 6985d73a0988SAndrei Emeltchenko switch (flags) { 6986d73a0988SAndrei Emeltchenko case ACL_START: 6987d73a0988SAndrei Emeltchenko case ACL_START_NO_FLUSH: 6988d73a0988SAndrei Emeltchenko case ACL_COMPLETE: 69890a708f8fSGustavo F. Padovan if (conn->rx_len) { 69900a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len); 69910a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 69920a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 69930a708f8fSGustavo F. Padovan conn->rx_len = 0; 69940a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 69950a708f8fSGustavo F. Padovan } 69960a708f8fSGustavo F. Padovan 69970a708f8fSGustavo F. Padovan /* Start fragment always begin with Basic L2CAP header */ 69980a708f8fSGustavo F. Padovan if (skb->len < L2CAP_HDR_SIZE) { 69990a708f8fSGustavo F. Padovan BT_ERR("Frame is too short (len %d)", skb->len); 70000a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 70010a708f8fSGustavo F. Padovan goto drop; 70020a708f8fSGustavo F. Padovan } 70030a708f8fSGustavo F. Padovan 70040a708f8fSGustavo F. Padovan hdr = (struct l2cap_hdr *) skb->data; 70050a708f8fSGustavo F. Padovan len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; 70060a708f8fSGustavo F. Padovan 70070a708f8fSGustavo F. Padovan if (len == skb->len) { 70080a708f8fSGustavo F. Padovan /* Complete frame received */ 70090a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb); 70100a708f8fSGustavo F. Padovan return 0; 70110a708f8fSGustavo F. Padovan } 70120a708f8fSGustavo F. Padovan 70130a708f8fSGustavo F. Padovan BT_DBG("Start: total len %d, frag len %d", len, skb->len); 70140a708f8fSGustavo F. Padovan 70150a708f8fSGustavo F. Padovan if (skb->len > len) { 70160a708f8fSGustavo F. Padovan BT_ERR("Frame is too long (len %d, expected len %d)", 70170a708f8fSGustavo F. Padovan skb->len, len); 70180a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 70190a708f8fSGustavo F. Padovan goto drop; 70200a708f8fSGustavo F. Padovan } 70210a708f8fSGustavo F. Padovan 70220a708f8fSGustavo F. Padovan /* Allocate skb for the complete frame (with header) */ 70238bcde1f2SGustavo Padovan conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL); 70240a708f8fSGustavo F. Padovan if (!conn->rx_skb) 70250a708f8fSGustavo F. Padovan goto drop; 70260a708f8fSGustavo F. Padovan 70270a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 70280a708f8fSGustavo F. Padovan skb->len); 70290a708f8fSGustavo F. Padovan conn->rx_len = len - skb->len; 7030d73a0988SAndrei Emeltchenko break; 7031d73a0988SAndrei Emeltchenko 7032d73a0988SAndrei Emeltchenko case ACL_CONT: 70330a708f8fSGustavo F. Padovan BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); 70340a708f8fSGustavo F. Padovan 70350a708f8fSGustavo F. Padovan if (!conn->rx_len) { 70360a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len); 70370a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 70380a708f8fSGustavo F. Padovan goto drop; 70390a708f8fSGustavo F. Padovan } 70400a708f8fSGustavo F. Padovan 70410a708f8fSGustavo F. Padovan if (skb->len > conn->rx_len) { 70420a708f8fSGustavo F. Padovan BT_ERR("Fragment is too long (len %d, expected %d)", 70430a708f8fSGustavo F. Padovan skb->len, conn->rx_len); 70440a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 70450a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 70460a708f8fSGustavo F. Padovan conn->rx_len = 0; 70470a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 70480a708f8fSGustavo F. Padovan goto drop; 70490a708f8fSGustavo F. Padovan } 70500a708f8fSGustavo F. Padovan 70510a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 70520a708f8fSGustavo F. Padovan skb->len); 70530a708f8fSGustavo F. Padovan conn->rx_len -= skb->len; 70540a708f8fSGustavo F. Padovan 70550a708f8fSGustavo F. Padovan if (!conn->rx_len) { 7056c4e5bafaSJohan Hedberg /* Complete frame received. l2cap_recv_frame 7057c4e5bafaSJohan Hedberg * takes ownership of the skb so set the global 7058c4e5bafaSJohan Hedberg * rx_skb pointer to NULL first. 7059c4e5bafaSJohan Hedberg */ 7060c4e5bafaSJohan Hedberg struct sk_buff *rx_skb = conn->rx_skb; 70610a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 7062c4e5bafaSJohan Hedberg l2cap_recv_frame(conn, rx_skb); 70630a708f8fSGustavo F. Padovan } 7064d73a0988SAndrei Emeltchenko break; 70650a708f8fSGustavo F. Padovan } 70660a708f8fSGustavo F. Padovan 70670a708f8fSGustavo F. Padovan drop: 70680a708f8fSGustavo F. Padovan kfree_skb(skb); 70690a708f8fSGustavo F. Padovan return 0; 70700a708f8fSGustavo F. Padovan } 70710a708f8fSGustavo F. Padovan 70720a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p) 70730a708f8fSGustavo F. Padovan { 707423691d75SGustavo F. Padovan struct l2cap_chan *c; 70750a708f8fSGustavo F. Padovan 7076333055f2SGustavo F. Padovan read_lock(&chan_list_lock); 70770a708f8fSGustavo F. Padovan 707823691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 7079fcb73338SAndrei Emeltchenko seq_printf(f, "%pMR %pMR %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", 70807eafc59eSMarcel Holtmann &c->src, &c->dst, 708189bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm), 708223691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu, 708323691d75SGustavo F. Padovan c->sec_level, c->mode); 70840a708f8fSGustavo F. Padovan } 70850a708f8fSGustavo F. Padovan 7086333055f2SGustavo F. Padovan read_unlock(&chan_list_lock); 70870a708f8fSGustavo F. Padovan 70880a708f8fSGustavo F. Padovan return 0; 70890a708f8fSGustavo F. Padovan } 70900a708f8fSGustavo F. Padovan 70910a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file) 70920a708f8fSGustavo F. Padovan { 70930a708f8fSGustavo F. Padovan return single_open(file, l2cap_debugfs_show, inode->i_private); 70940a708f8fSGustavo F. Padovan } 70950a708f8fSGustavo F. Padovan 70960a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = { 70970a708f8fSGustavo F. Padovan .open = l2cap_debugfs_open, 70980a708f8fSGustavo F. Padovan .read = seq_read, 70990a708f8fSGustavo F. Padovan .llseek = seq_lseek, 71000a708f8fSGustavo F. Padovan .release = single_release, 71010a708f8fSGustavo F. Padovan }; 71020a708f8fSGustavo F. Padovan 71030a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs; 71040a708f8fSGustavo F. Padovan 710564274518SGustavo F. Padovan int __init l2cap_init(void) 71060a708f8fSGustavo F. Padovan { 71070a708f8fSGustavo F. Padovan int err; 71080a708f8fSGustavo F. Padovan 7109bb58f747SGustavo F. Padovan err = l2cap_init_sockets(); 71100a708f8fSGustavo F. Padovan if (err < 0) 71110a708f8fSGustavo F. Padovan return err; 71120a708f8fSGustavo F. Padovan 71131120e4bfSMarcel Holtmann if (IS_ERR_OR_NULL(bt_debugfs)) 71141120e4bfSMarcel Holtmann return 0; 71151120e4bfSMarcel Holtmann 71162d792818SGustavo Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, 71172d792818SGustavo Padovan NULL, &l2cap_debugfs_fops); 71180a708f8fSGustavo F. Padovan 71190a708f8fSGustavo F. Padovan return 0; 71200a708f8fSGustavo F. Padovan } 71210a708f8fSGustavo F. Padovan 712264274518SGustavo F. Padovan void l2cap_exit(void) 71230a708f8fSGustavo F. Padovan { 71240a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs); 7125bb58f747SGustavo F. Padovan l2cap_cleanup_sockets(); 71260a708f8fSGustavo F. Padovan } 71270a708f8fSGustavo F. Padovan 71280a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644); 71290a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); 7130