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 226*f93fa273SGustavo 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 49393c3e8f5SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 4940a708f8fSGustavo F. Padovan { 4950a708f8fSGustavo F. Padovan BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, 496097db76cSAndrei Emeltchenko __le16_to_cpu(chan->psm), chan->dcid); 4970a708f8fSGustavo F. Padovan 4989f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 4990a708f8fSGustavo F. Padovan 5008c1d787bSGustavo F. Padovan chan->conn = conn; 5010a708f8fSGustavo F. Padovan 5025491120eSAndrei Emeltchenko switch (chan->chan_type) { 5035491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_ORIENTED: 504b62f328bSVille Tervo if (conn->hcon->type == LE_LINK) { 505b62f328bSVille Tervo /* LE connection */ 5066fcb06a2SAndre Guedes chan->omtu = L2CAP_DEFAULT_MTU; 5079f22398cSJohan Hedberg if (chan->dcid == L2CAP_CID_ATT) 508073d1cf3SJohan Hedberg chan->scid = L2CAP_CID_ATT; 5099f22398cSJohan Hedberg else 5109f22398cSJohan Hedberg chan->scid = l2cap_alloc_cid(conn); 511b62f328bSVille Tervo } else { 5120a708f8fSGustavo F. Padovan /* Alloc CID for connection-oriented socket */ 513fe4128e0SGustavo F. Padovan chan->scid = l2cap_alloc_cid(conn); 5140c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 515b62f328bSVille Tervo } 5165491120eSAndrei Emeltchenko break; 5175491120eSAndrei Emeltchenko 5185491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_LESS: 5190a708f8fSGustavo F. Padovan /* Connectionless socket */ 520fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_CONN_LESS; 521fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_CONN_LESS; 5220c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 5235491120eSAndrei Emeltchenko break; 5245491120eSAndrei Emeltchenko 525416fa752SAndrei Emeltchenko case L2CAP_CHAN_CONN_FIX_A2MP: 526416fa752SAndrei Emeltchenko chan->scid = L2CAP_CID_A2MP; 527416fa752SAndrei Emeltchenko chan->dcid = L2CAP_CID_A2MP; 528416fa752SAndrei Emeltchenko chan->omtu = L2CAP_A2MP_DEFAULT_MTU; 529416fa752SAndrei Emeltchenko chan->imtu = L2CAP_A2MP_DEFAULT_MTU; 530416fa752SAndrei Emeltchenko break; 531416fa752SAndrei Emeltchenko 5325491120eSAndrei Emeltchenko default: 5330a708f8fSGustavo F. Padovan /* Raw socket can send/recv signalling messages only */ 534fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_SIGNALING; 535fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_SIGNALING; 5360c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 5370a708f8fSGustavo F. Padovan } 5380a708f8fSGustavo F. Padovan 5398f7975b1SAndrei Emeltchenko chan->local_id = L2CAP_BESTEFFORT_ID; 5408f7975b1SAndrei Emeltchenko chan->local_stype = L2CAP_SERV_BESTEFFORT; 5418f7975b1SAndrei Emeltchenko chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE; 5428f7975b1SAndrei Emeltchenko chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME; 5438f7975b1SAndrei Emeltchenko chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT; 5448936fa6dSAndrei Emeltchenko chan->local_flush_to = L2CAP_EFS_DEFAULT_FLUSH_TO; 5458f7975b1SAndrei Emeltchenko 546371fd835SUlisses Furquim l2cap_chan_hold(chan); 547baa7e1faSGustavo F. Padovan 5485ee9891dSJohan Hedberg hci_conn_hold(conn->hcon); 5495ee9891dSJohan Hedberg 5503df91ea2SAndrei Emeltchenko list_add(&chan->list, &conn->chan_l); 551643162a8SAndrei Emeltchenko } 552643162a8SAndrei Emeltchenko 553466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 554643162a8SAndrei Emeltchenko { 555643162a8SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 556643162a8SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 5573df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 5580a708f8fSGustavo F. Padovan } 5590a708f8fSGustavo F. Padovan 560466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err) 5610a708f8fSGustavo F. Padovan { 5628c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 5630a708f8fSGustavo F. Padovan 564c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 5650a708f8fSGustavo F. Padovan 56649208c9cSGustavo F. Padovan BT_DBG("chan %p, conn %p, err %d", chan, conn, err); 5670a708f8fSGustavo F. Padovan 5680a708f8fSGustavo F. Padovan if (conn) { 56956f60984SAndrei Emeltchenko struct amp_mgr *mgr = conn->hcon->amp_mgr; 570baa7e1faSGustavo F. Padovan /* Delete from channel list */ 5713df91ea2SAndrei Emeltchenko list_del(&chan->list); 5723d57dc68SGustavo F. Padovan 573371fd835SUlisses Furquim l2cap_chan_put(chan); 574baa7e1faSGustavo F. Padovan 5758c1d787bSGustavo F. Padovan chan->conn = NULL; 5763cabbfdaSAndrei Emeltchenko 5773cabbfdaSAndrei Emeltchenko if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP) 57876a68ba0SDavid Herrmann hci_conn_drop(conn->hcon); 57956f60984SAndrei Emeltchenko 58056f60984SAndrei Emeltchenko if (mgr && mgr->bredr_chan == chan) 58156f60984SAndrei Emeltchenko mgr->bredr_chan = NULL; 5820a708f8fSGustavo F. Padovan } 5830a708f8fSGustavo F. Padovan 584419e08c1SAndrei Emeltchenko if (chan->hs_hchan) { 585419e08c1SAndrei Emeltchenko struct hci_chan *hs_hchan = chan->hs_hchan; 586419e08c1SAndrei Emeltchenko 587419e08c1SAndrei Emeltchenko BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan); 588419e08c1SAndrei Emeltchenko amp_disconnect_logical_link(hs_hchan); 589419e08c1SAndrei Emeltchenko } 590419e08c1SAndrei Emeltchenko 591c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, err); 5926be36555SAndrei Emeltchenko 5932827011fSMat Martineau if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) 5946ff5abbfSGustavo F. Padovan return; 5952ead70b8SGustavo F. Padovan 596ee556f66SGustavo Padovan switch(chan->mode) { 597ee556f66SGustavo Padovan case L2CAP_MODE_BASIC: 598ee556f66SGustavo Padovan break; 5990a708f8fSGustavo F. Padovan 600ee556f66SGustavo Padovan case L2CAP_MODE_ERTM: 6011a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 6021a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 6031a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 6040a708f8fSGustavo F. Padovan 605f1c6775bSGustavo F. Padovan skb_queue_purge(&chan->srej_q); 6060a708f8fSGustavo F. Padovan 6073c588192SMat Martineau l2cap_seq_list_free(&chan->srej_list); 6083c588192SMat Martineau l2cap_seq_list_free(&chan->retrans_list); 609ee556f66SGustavo Padovan 610ee556f66SGustavo Padovan /* fall through */ 611ee556f66SGustavo Padovan 612ee556f66SGustavo Padovan case L2CAP_MODE_STREAMING: 613ee556f66SGustavo Padovan skb_queue_purge(&chan->tx_q); 614ee556f66SGustavo Padovan break; 6150a708f8fSGustavo F. Padovan } 616ee556f66SGustavo Padovan 617ee556f66SGustavo Padovan return; 6180a708f8fSGustavo F. Padovan } 6190a708f8fSGustavo F. Padovan 6200f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason) 6214519de9aSGustavo F. Padovan { 6224519de9aSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 6234519de9aSGustavo F. Padovan 6247eafc59eSMarcel Holtmann BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 6254519de9aSGustavo F. Padovan 62689bc500eSGustavo F. Padovan switch (chan->state) { 6274519de9aSGustavo F. Padovan case BT_LISTEN: 628c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 6294519de9aSGustavo F. Padovan break; 6304519de9aSGustavo F. Padovan 6314519de9aSGustavo F. Padovan case BT_CONNECTED: 6324519de9aSGustavo F. Padovan case BT_CONFIG: 633715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && 6344519de9aSGustavo F. Padovan conn->hcon->type == ACL_LINK) { 6358d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 6365e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, reason); 6374519de9aSGustavo F. Padovan } else 6384519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 6394519de9aSGustavo F. Padovan break; 6404519de9aSGustavo F. Padovan 6414519de9aSGustavo F. Padovan case BT_CONNECT2: 642715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && 6434519de9aSGustavo F. Padovan conn->hcon->type == ACL_LINK) { 6444519de9aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 6454519de9aSGustavo F. Padovan __u16 result; 6464519de9aSGustavo F. Padovan 647bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 6484519de9aSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 6494519de9aSGustavo F. Padovan else 6504519de9aSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 651bdc25783SMarcel Holtmann 65289bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_DISCONN); 6534519de9aSGustavo F. Padovan 6544519de9aSGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 6554519de9aSGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 6564519de9aSGustavo F. Padovan rsp.result = cpu_to_le16(result); 657ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 6584519de9aSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 6594519de9aSGustavo F. Padovan sizeof(rsp), &rsp); 6604519de9aSGustavo F. Padovan } 6614519de9aSGustavo F. Padovan 6624519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 6634519de9aSGustavo F. Padovan break; 6644519de9aSGustavo F. Padovan 6654519de9aSGustavo F. Padovan case BT_CONNECT: 6664519de9aSGustavo F. Padovan case BT_DISCONN: 6674519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 6684519de9aSGustavo F. Padovan break; 6694519de9aSGustavo F. Padovan 6704519de9aSGustavo F. Padovan default: 671c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 6724519de9aSGustavo F. Padovan break; 6734519de9aSGustavo F. Padovan } 6744519de9aSGustavo F. Padovan } 6754519de9aSGustavo F. Padovan 6764343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) 6770a708f8fSGustavo F. Padovan { 6786a974b50SMarcel Holtmann switch (chan->chan_type) { 6796a974b50SMarcel Holtmann case L2CAP_CHAN_RAW: 6804343478fSGustavo F. Padovan switch (chan->sec_level) { 6810a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 6820a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING_MITM; 6830a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 6840a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING; 6850a708f8fSGustavo F. Padovan default: 6860a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 6870a708f8fSGustavo F. Padovan } 6886a974b50SMarcel Holtmann break; 6893124b843SMarcel Holtmann case L2CAP_CHAN_CONN_LESS: 6903124b843SMarcel Holtmann if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_3DSP)) { 6913124b843SMarcel Holtmann if (chan->sec_level == BT_SECURITY_LOW) 6923124b843SMarcel Holtmann chan->sec_level = BT_SECURITY_SDP; 6933124b843SMarcel Holtmann } 6943124b843SMarcel Holtmann if (chan->sec_level == BT_SECURITY_HIGH) 6953124b843SMarcel Holtmann return HCI_AT_NO_BONDING_MITM; 6963124b843SMarcel Holtmann else 6973124b843SMarcel Holtmann return HCI_AT_NO_BONDING; 6983124b843SMarcel Holtmann break; 6996a974b50SMarcel Holtmann case L2CAP_CHAN_CONN_ORIENTED: 7006a974b50SMarcel Holtmann if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) { 7014343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_LOW) 7024343478fSGustavo F. Padovan chan->sec_level = BT_SECURITY_SDP; 7030a708f8fSGustavo F. Padovan 7044343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_HIGH) 7050a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING_MITM; 7060a708f8fSGustavo F. Padovan else 7070a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 7086a974b50SMarcel Holtmann } 7096a974b50SMarcel Holtmann /* fall through */ 7106a974b50SMarcel Holtmann default: 7114343478fSGustavo F. Padovan switch (chan->sec_level) { 7120a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 7130a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING_MITM; 7140a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 7150a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING; 7160a708f8fSGustavo F. Padovan default: 7170a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 7180a708f8fSGustavo F. Padovan } 7196a974b50SMarcel Holtmann break; 7200a708f8fSGustavo F. Padovan } 7210a708f8fSGustavo F. Padovan } 7220a708f8fSGustavo F. Padovan 7230a708f8fSGustavo F. Padovan /* Service level security */ 724d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan) 7250a708f8fSGustavo F. Padovan { 7268c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 7270a708f8fSGustavo F. Padovan __u8 auth_type; 7280a708f8fSGustavo F. Padovan 7294343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 7300a708f8fSGustavo F. Padovan 7314343478fSGustavo F. Padovan return hci_conn_security(conn->hcon, chan->sec_level, auth_type); 7320a708f8fSGustavo F. Padovan } 7330a708f8fSGustavo F. Padovan 734b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn) 7350a708f8fSGustavo F. Padovan { 7360a708f8fSGustavo F. Padovan u8 id; 7370a708f8fSGustavo F. Padovan 7380a708f8fSGustavo F. Padovan /* Get next available identificator. 7390a708f8fSGustavo F. Padovan * 1 - 128 are used by kernel. 7400a708f8fSGustavo F. Padovan * 129 - 199 are reserved. 7410a708f8fSGustavo F. Padovan * 200 - 254 are used by utilities like l2ping, etc. 7420a708f8fSGustavo F. Padovan */ 7430a708f8fSGustavo F. Padovan 744333055f2SGustavo F. Padovan spin_lock(&conn->lock); 7450a708f8fSGustavo F. Padovan 7460a708f8fSGustavo F. Padovan if (++conn->tx_ident > 128) 7470a708f8fSGustavo F. Padovan conn->tx_ident = 1; 7480a708f8fSGustavo F. Padovan 7490a708f8fSGustavo F. Padovan id = conn->tx_ident; 7500a708f8fSGustavo F. Padovan 751333055f2SGustavo F. Padovan spin_unlock(&conn->lock); 7520a708f8fSGustavo F. Padovan 7530a708f8fSGustavo F. Padovan return id; 7540a708f8fSGustavo F. Padovan } 7550a708f8fSGustavo F. Padovan 7562d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 7572d792818SGustavo Padovan void *data) 7580a708f8fSGustavo F. Padovan { 7590a708f8fSGustavo F. Padovan struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); 7600a708f8fSGustavo F. Padovan u8 flags; 7610a708f8fSGustavo F. Padovan 7620a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x", code); 7630a708f8fSGustavo F. Padovan 7640a708f8fSGustavo F. Padovan if (!skb) 7650a708f8fSGustavo F. Padovan return; 7660a708f8fSGustavo F. Padovan 7670a708f8fSGustavo F. Padovan if (lmp_no_flush_capable(conn->hcon->hdev)) 7680a708f8fSGustavo F. Padovan flags = ACL_START_NO_FLUSH; 7690a708f8fSGustavo F. Padovan else 7700a708f8fSGustavo F. Padovan flags = ACL_START; 7710a708f8fSGustavo F. Padovan 77214b12d0bSJaikumar Ganesh bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON; 7735e59b791SLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 77414b12d0bSJaikumar Ganesh 77573d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, flags); 7760a708f8fSGustavo F. Padovan } 7770a708f8fSGustavo F. Padovan 77802b0fbb9SMat Martineau static bool __chan_is_moving(struct l2cap_chan *chan) 77902b0fbb9SMat Martineau { 78002b0fbb9SMat Martineau return chan->move_state != L2CAP_MOVE_STABLE && 78102b0fbb9SMat Martineau chan->move_state != L2CAP_MOVE_WAIT_PREPARE; 78202b0fbb9SMat Martineau } 78302b0fbb9SMat Martineau 78473d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) 78573d80debSLuiz Augusto von Dentz { 78673d80debSLuiz Augusto von Dentz struct hci_conn *hcon = chan->conn->hcon; 78773d80debSLuiz Augusto von Dentz u16 flags; 78873d80debSLuiz Augusto von Dentz 78973d80debSLuiz Augusto von Dentz BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, 79073d80debSLuiz Augusto von Dentz skb->priority); 79173d80debSLuiz Augusto von Dentz 792d5f8a75dSMat Martineau if (chan->hs_hcon && !__chan_is_moving(chan)) { 793d5f8a75dSMat Martineau if (chan->hs_hchan) 794d5f8a75dSMat Martineau hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE); 795d5f8a75dSMat Martineau else 796d5f8a75dSMat Martineau kfree_skb(skb); 797d5f8a75dSMat Martineau 798d5f8a75dSMat Martineau return; 799d5f8a75dSMat Martineau } 800d5f8a75dSMat Martineau 80173d80debSLuiz Augusto von Dentz if (!test_bit(FLAG_FLUSHABLE, &chan->flags) && 80273d80debSLuiz Augusto von Dentz lmp_no_flush_capable(hcon->hdev)) 80373d80debSLuiz Augusto von Dentz flags = ACL_START_NO_FLUSH; 80473d80debSLuiz Augusto von Dentz else 80573d80debSLuiz Augusto von Dentz flags = ACL_START; 80673d80debSLuiz Augusto von Dentz 80773d80debSLuiz Augusto von Dentz bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); 80873d80debSLuiz Augusto von Dentz hci_send_acl(chan->conn->hchan, skb, flags); 8090a708f8fSGustavo F. Padovan } 8100a708f8fSGustavo F. Padovan 811b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control) 812b5c6aaedSMat Martineau { 813b5c6aaedSMat Martineau control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT; 814b5c6aaedSMat Martineau control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT; 815b5c6aaedSMat Martineau 816b5c6aaedSMat Martineau if (enh & L2CAP_CTRL_FRAME_TYPE) { 817b5c6aaedSMat Martineau /* S-Frame */ 818b5c6aaedSMat Martineau control->sframe = 1; 819b5c6aaedSMat Martineau control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT; 820b5c6aaedSMat Martineau control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT; 821b5c6aaedSMat Martineau 822b5c6aaedSMat Martineau control->sar = 0; 823b5c6aaedSMat Martineau control->txseq = 0; 824b5c6aaedSMat Martineau } else { 825b5c6aaedSMat Martineau /* I-Frame */ 826b5c6aaedSMat Martineau control->sframe = 0; 827b5c6aaedSMat Martineau control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT; 828b5c6aaedSMat Martineau control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT; 829b5c6aaedSMat Martineau 830b5c6aaedSMat Martineau control->poll = 0; 831b5c6aaedSMat Martineau control->super = 0; 832b5c6aaedSMat Martineau } 833b5c6aaedSMat Martineau } 834b5c6aaedSMat Martineau 835b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control) 836b5c6aaedSMat Martineau { 837b5c6aaedSMat Martineau control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT; 838b5c6aaedSMat Martineau control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT; 839b5c6aaedSMat Martineau 840b5c6aaedSMat Martineau if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) { 841b5c6aaedSMat Martineau /* S-Frame */ 842b5c6aaedSMat Martineau control->sframe = 1; 843b5c6aaedSMat Martineau control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT; 844b5c6aaedSMat Martineau control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT; 845b5c6aaedSMat Martineau 846b5c6aaedSMat Martineau control->sar = 0; 847b5c6aaedSMat Martineau control->txseq = 0; 848b5c6aaedSMat Martineau } else { 849b5c6aaedSMat Martineau /* I-Frame */ 850b5c6aaedSMat Martineau control->sframe = 0; 851b5c6aaedSMat Martineau control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT; 852b5c6aaedSMat Martineau control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT; 853b5c6aaedSMat Martineau 854b5c6aaedSMat Martineau control->poll = 0; 855b5c6aaedSMat Martineau control->super = 0; 856b5c6aaedSMat Martineau } 857b5c6aaedSMat Martineau } 858b5c6aaedSMat Martineau 859b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan, 860b5c6aaedSMat Martineau struct sk_buff *skb) 861b5c6aaedSMat Martineau { 862b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 863b5c6aaedSMat Martineau __unpack_extended_control(get_unaligned_le32(skb->data), 864b5c6aaedSMat Martineau &bt_cb(skb)->control); 865cec8ab6eSMat Martineau skb_pull(skb, L2CAP_EXT_CTRL_SIZE); 866b5c6aaedSMat Martineau } else { 867b5c6aaedSMat Martineau __unpack_enhanced_control(get_unaligned_le16(skb->data), 868b5c6aaedSMat Martineau &bt_cb(skb)->control); 869cec8ab6eSMat Martineau skb_pull(skb, L2CAP_ENH_CTRL_SIZE); 870b5c6aaedSMat Martineau } 871b5c6aaedSMat Martineau } 872b5c6aaedSMat Martineau 873b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control) 874b5c6aaedSMat Martineau { 875b5c6aaedSMat Martineau u32 packed; 876b5c6aaedSMat Martineau 877b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT; 878b5c6aaedSMat Martineau packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT; 879b5c6aaedSMat Martineau 880b5c6aaedSMat Martineau if (control->sframe) { 881b5c6aaedSMat Martineau packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT; 882b5c6aaedSMat Martineau packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT; 883b5c6aaedSMat Martineau packed |= L2CAP_EXT_CTRL_FRAME_TYPE; 884b5c6aaedSMat Martineau } else { 885b5c6aaedSMat Martineau packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT; 886b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT; 887b5c6aaedSMat Martineau } 888b5c6aaedSMat Martineau 889b5c6aaedSMat Martineau return packed; 890b5c6aaedSMat Martineau } 891b5c6aaedSMat Martineau 892b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control) 893b5c6aaedSMat Martineau { 894b5c6aaedSMat Martineau u16 packed; 895b5c6aaedSMat Martineau 896b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT; 897b5c6aaedSMat Martineau packed |= control->final << L2CAP_CTRL_FINAL_SHIFT; 898b5c6aaedSMat Martineau 899b5c6aaedSMat Martineau if (control->sframe) { 900b5c6aaedSMat Martineau packed |= control->poll << L2CAP_CTRL_POLL_SHIFT; 901b5c6aaedSMat Martineau packed |= control->super << L2CAP_CTRL_SUPER_SHIFT; 902b5c6aaedSMat Martineau packed |= L2CAP_CTRL_FRAME_TYPE; 903b5c6aaedSMat Martineau } else { 904b5c6aaedSMat Martineau packed |= control->sar << L2CAP_CTRL_SAR_SHIFT; 905b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT; 906b5c6aaedSMat Martineau } 907b5c6aaedSMat Martineau 908b5c6aaedSMat Martineau return packed; 909b5c6aaedSMat Martineau } 910b5c6aaedSMat Martineau 911b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan, 912b5c6aaedSMat Martineau struct l2cap_ctrl *control, 913b5c6aaedSMat Martineau struct sk_buff *skb) 914b5c6aaedSMat Martineau { 915b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 916b5c6aaedSMat Martineau put_unaligned_le32(__pack_extended_control(control), 917b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 918b5c6aaedSMat Martineau } else { 919b5c6aaedSMat Martineau put_unaligned_le16(__pack_enhanced_control(control), 920b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 921b5c6aaedSMat Martineau } 922b5c6aaedSMat Martineau } 923b5c6aaedSMat Martineau 924ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan) 925ba7aa64fSGustavo Padovan { 926ba7aa64fSGustavo Padovan if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 927ba7aa64fSGustavo Padovan return L2CAP_EXT_HDR_SIZE; 928ba7aa64fSGustavo Padovan else 929ba7aa64fSGustavo Padovan return L2CAP_ENH_HDR_SIZE; 930ba7aa64fSGustavo Padovan } 931ba7aa64fSGustavo Padovan 932a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan, 933a67d7f6fSMat Martineau u32 control) 9340a708f8fSGustavo F. Padovan { 9350a708f8fSGustavo F. Padovan struct sk_buff *skb; 9360a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 937ba7aa64fSGustavo Padovan int hlen = __ertm_hdr_size(chan); 9380a708f8fSGustavo F. Padovan 9390a708f8fSGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 94003a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 9410a708f8fSGustavo F. Padovan 942a67d7f6fSMat Martineau skb = bt_skb_alloc(hlen, GFP_KERNEL); 9430a708f8fSGustavo F. Padovan 9440a708f8fSGustavo F. Padovan if (!skb) 945a67d7f6fSMat Martineau return ERR_PTR(-ENOMEM); 9460a708f8fSGustavo F. Padovan 9470a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 9480a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); 949fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 95088843ab0SAndrei Emeltchenko 951a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 952a67d7f6fSMat Martineau put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 953a67d7f6fSMat Martineau else 954a67d7f6fSMat Martineau put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 9550a708f8fSGustavo F. Padovan 95647d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 957a67d7f6fSMat Martineau u16 fcs = crc16(0, (u8 *)skb->data, skb->len); 95803a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 9590a708f8fSGustavo F. Padovan } 9600a708f8fSGustavo F. Padovan 96173d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 962a67d7f6fSMat Martineau return skb; 963a67d7f6fSMat Martineau } 964a67d7f6fSMat Martineau 965a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan, 966a67d7f6fSMat Martineau struct l2cap_ctrl *control) 967a67d7f6fSMat Martineau { 968a67d7f6fSMat Martineau struct sk_buff *skb; 969a67d7f6fSMat Martineau u32 control_field; 970a67d7f6fSMat Martineau 971a67d7f6fSMat Martineau BT_DBG("chan %p, control %p", chan, control); 972a67d7f6fSMat Martineau 973a67d7f6fSMat Martineau if (!control->sframe) 974a67d7f6fSMat Martineau return; 975a67d7f6fSMat Martineau 976b99e13adSMat Martineau if (__chan_is_moving(chan)) 977b99e13adSMat Martineau return; 978b99e13adSMat Martineau 979a67d7f6fSMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) && 980a67d7f6fSMat Martineau !control->poll) 981a67d7f6fSMat Martineau control->final = 1; 982a67d7f6fSMat Martineau 983a67d7f6fSMat Martineau if (control->super == L2CAP_SUPER_RR) 984a67d7f6fSMat Martineau clear_bit(CONN_RNR_SENT, &chan->conn_state); 985a67d7f6fSMat Martineau else if (control->super == L2CAP_SUPER_RNR) 986a67d7f6fSMat Martineau set_bit(CONN_RNR_SENT, &chan->conn_state); 987a67d7f6fSMat Martineau 988a67d7f6fSMat Martineau if (control->super != L2CAP_SUPER_SREJ) { 989a67d7f6fSMat Martineau chan->last_acked_seq = control->reqseq; 990a67d7f6fSMat Martineau __clear_ack_timer(chan); 991a67d7f6fSMat Martineau } 992a67d7f6fSMat Martineau 993a67d7f6fSMat Martineau BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq, 994a67d7f6fSMat Martineau control->final, control->poll, control->super); 995a67d7f6fSMat Martineau 996a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 997a67d7f6fSMat Martineau control_field = __pack_extended_control(control); 998a67d7f6fSMat Martineau else 999a67d7f6fSMat Martineau control_field = __pack_enhanced_control(control); 1000a67d7f6fSMat Martineau 1001a67d7f6fSMat Martineau skb = l2cap_create_sframe_pdu(chan, control_field); 1002a67d7f6fSMat Martineau if (!IS_ERR(skb)) 100373d80debSLuiz Augusto von Dentz l2cap_do_send(chan, skb); 10040a708f8fSGustavo F. Padovan } 10050a708f8fSGustavo F. Padovan 1006c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll) 10070a708f8fSGustavo F. Padovan { 1008c9e3d5e0SMat Martineau struct l2cap_ctrl control; 10090a708f8fSGustavo F. Padovan 1010c9e3d5e0SMat Martineau BT_DBG("chan %p, poll %d", chan, poll); 1011c9e3d5e0SMat Martineau 1012c9e3d5e0SMat Martineau memset(&control, 0, sizeof(control)); 1013c9e3d5e0SMat Martineau control.sframe = 1; 1014c9e3d5e0SMat Martineau control.poll = poll; 1015c9e3d5e0SMat Martineau 1016c9e3d5e0SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 1017c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RNR; 1018c9e3d5e0SMat Martineau else 1019c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RR; 1020c9e3d5e0SMat Martineau 1021c9e3d5e0SMat Martineau control.reqseq = chan->buffer_seq; 1022c9e3d5e0SMat Martineau l2cap_send_sframe(chan, &control); 10230a708f8fSGustavo F. Padovan } 10240a708f8fSGustavo F. Padovan 1025b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) 10260a708f8fSGustavo F. Padovan { 1027c1360a1cSGustavo F. Padovan return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); 10280a708f8fSGustavo F. Padovan } 10290a708f8fSGustavo F. Padovan 103093c3e8f5SAndrei Emeltchenko static bool __amp_capable(struct l2cap_chan *chan) 103193c3e8f5SAndrei Emeltchenko { 103293c3e8f5SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 10331df7b17aSMarcel Holtmann struct hci_dev *hdev; 10341df7b17aSMarcel Holtmann bool amp_available = false; 103593c3e8f5SAndrei Emeltchenko 10361df7b17aSMarcel Holtmann if (!conn->hs_enabled) 10371df7b17aSMarcel Holtmann return false; 10381df7b17aSMarcel Holtmann 10391df7b17aSMarcel Holtmann if (!(conn->fixed_chan_mask & L2CAP_FC_A2MP)) 10401df7b17aSMarcel Holtmann return false; 10411df7b17aSMarcel Holtmann 10421df7b17aSMarcel Holtmann read_lock(&hci_dev_list_lock); 10431df7b17aSMarcel Holtmann list_for_each_entry(hdev, &hci_dev_list, list) { 10441df7b17aSMarcel Holtmann if (hdev->amp_type != AMP_TYPE_BREDR && 10451df7b17aSMarcel Holtmann test_bit(HCI_UP, &hdev->flags)) { 10461df7b17aSMarcel Holtmann amp_available = true; 10471df7b17aSMarcel Holtmann break; 10481df7b17aSMarcel Holtmann } 10491df7b17aSMarcel Holtmann } 10501df7b17aSMarcel Holtmann read_unlock(&hci_dev_list_lock); 10511df7b17aSMarcel Holtmann 10521df7b17aSMarcel Holtmann if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED) 10531df7b17aSMarcel Holtmann return amp_available; 1054848566b3SMarcel Holtmann 105593c3e8f5SAndrei Emeltchenko return false; 105693c3e8f5SAndrei Emeltchenko } 105793c3e8f5SAndrei Emeltchenko 10585ce66b59SAndrei Emeltchenko static bool l2cap_check_efs(struct l2cap_chan *chan) 10595ce66b59SAndrei Emeltchenko { 10605ce66b59SAndrei Emeltchenko /* Check EFS parameters */ 10615ce66b59SAndrei Emeltchenko return true; 10625ce66b59SAndrei Emeltchenko } 10635ce66b59SAndrei Emeltchenko 10642766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan) 10659b27f350SAndrei Emeltchenko { 10669b27f350SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 10679b27f350SAndrei Emeltchenko struct l2cap_conn_req req; 10689b27f350SAndrei Emeltchenko 10699b27f350SAndrei Emeltchenko req.scid = cpu_to_le16(chan->scid); 10709b27f350SAndrei Emeltchenko req.psm = chan->psm; 10719b27f350SAndrei Emeltchenko 10729b27f350SAndrei Emeltchenko chan->ident = l2cap_get_ident(conn); 10739b27f350SAndrei Emeltchenko 10749b27f350SAndrei Emeltchenko set_bit(CONF_CONNECT_PEND, &chan->conf_state); 10759b27f350SAndrei Emeltchenko 10769b27f350SAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); 10779b27f350SAndrei Emeltchenko } 10789b27f350SAndrei Emeltchenko 10798eb200bdSMat Martineau static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id) 10808eb200bdSMat Martineau { 10818eb200bdSMat Martineau struct l2cap_create_chan_req req; 10828eb200bdSMat Martineau req.scid = cpu_to_le16(chan->scid); 10838eb200bdSMat Martineau req.psm = chan->psm; 10848eb200bdSMat Martineau req.amp_id = amp_id; 10858eb200bdSMat Martineau 10868eb200bdSMat Martineau chan->ident = l2cap_get_ident(chan->conn); 10878eb200bdSMat Martineau 10888eb200bdSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ, 10898eb200bdSMat Martineau sizeof(req), &req); 10908eb200bdSMat Martineau } 10918eb200bdSMat Martineau 109202b0fbb9SMat Martineau static void l2cap_move_setup(struct l2cap_chan *chan) 109302b0fbb9SMat Martineau { 109402b0fbb9SMat Martineau struct sk_buff *skb; 109502b0fbb9SMat Martineau 109602b0fbb9SMat Martineau BT_DBG("chan %p", chan); 109702b0fbb9SMat Martineau 109802b0fbb9SMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 109902b0fbb9SMat Martineau return; 110002b0fbb9SMat Martineau 110102b0fbb9SMat Martineau __clear_retrans_timer(chan); 110202b0fbb9SMat Martineau __clear_monitor_timer(chan); 110302b0fbb9SMat Martineau __clear_ack_timer(chan); 110402b0fbb9SMat Martineau 110502b0fbb9SMat Martineau chan->retry_count = 0; 110602b0fbb9SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 110702b0fbb9SMat Martineau if (bt_cb(skb)->control.retries) 110802b0fbb9SMat Martineau bt_cb(skb)->control.retries = 1; 110902b0fbb9SMat Martineau else 111002b0fbb9SMat Martineau break; 111102b0fbb9SMat Martineau } 111202b0fbb9SMat Martineau 111302b0fbb9SMat Martineau chan->expected_tx_seq = chan->buffer_seq; 111402b0fbb9SMat Martineau 111502b0fbb9SMat Martineau clear_bit(CONN_REJ_ACT, &chan->conn_state); 111602b0fbb9SMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 111702b0fbb9SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 111802b0fbb9SMat Martineau l2cap_seq_list_clear(&chan->srej_list); 111902b0fbb9SMat Martineau skb_queue_purge(&chan->srej_q); 112002b0fbb9SMat Martineau 112102b0fbb9SMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 112202b0fbb9SMat Martineau chan->rx_state = L2CAP_RX_STATE_MOVE; 112302b0fbb9SMat Martineau 112402b0fbb9SMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 112502b0fbb9SMat Martineau } 112602b0fbb9SMat Martineau 11275f3847a4SMat Martineau static void l2cap_move_done(struct l2cap_chan *chan) 11285f3847a4SMat Martineau { 11295f3847a4SMat Martineau u8 move_role = chan->move_role; 11305f3847a4SMat Martineau BT_DBG("chan %p", chan); 11315f3847a4SMat Martineau 11325f3847a4SMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 11335f3847a4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 11345f3847a4SMat Martineau 11355f3847a4SMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 11365f3847a4SMat Martineau return; 11375f3847a4SMat Martineau 11385f3847a4SMat Martineau switch (move_role) { 11395f3847a4SMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 11405f3847a4SMat Martineau l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL); 11415f3847a4SMat Martineau chan->rx_state = L2CAP_RX_STATE_WAIT_F; 11425f3847a4SMat Martineau break; 11435f3847a4SMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 11445f3847a4SMat Martineau chan->rx_state = L2CAP_RX_STATE_WAIT_P; 11455f3847a4SMat Martineau break; 11465f3847a4SMat Martineau } 11475f3847a4SMat Martineau } 11485f3847a4SMat Martineau 11499f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan) 11509f0caeb1SVinicius Costa Gomes { 11512827011fSMat Martineau /* This clears all conf flags, including CONF_NOT_COMPLETE */ 11529f0caeb1SVinicius Costa Gomes chan->conf_state = 0; 11539f0caeb1SVinicius Costa Gomes __clear_chan_timer(chan); 11549f0caeb1SVinicius Costa Gomes 115554a59aa2SAndrei Emeltchenko chan->state = BT_CONNECTED; 11569f0caeb1SVinicius Costa Gomes 115754a59aa2SAndrei Emeltchenko chan->ops->ready(chan); 11589f0caeb1SVinicius Costa Gomes } 11599f0caeb1SVinicius Costa Gomes 116093c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan) 116193c3e8f5SAndrei Emeltchenko { 116293c3e8f5SAndrei Emeltchenko if (__amp_capable(chan)) { 116393c3e8f5SAndrei Emeltchenko BT_DBG("chan %p AMP capable: discover AMPs", chan); 116493c3e8f5SAndrei Emeltchenko a2mp_discover_amp(chan); 116593c3e8f5SAndrei Emeltchenko } else { 116693c3e8f5SAndrei Emeltchenko l2cap_send_conn_req(chan); 116793c3e8f5SAndrei Emeltchenko } 116893c3e8f5SAndrei Emeltchenko } 116993c3e8f5SAndrei Emeltchenko 1170fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan) 11710a708f8fSGustavo F. Padovan { 11728c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 11730a708f8fSGustavo F. Padovan 11749f0caeb1SVinicius Costa Gomes if (conn->hcon->type == LE_LINK) { 11759f0caeb1SVinicius Costa Gomes l2cap_chan_ready(chan); 11769f0caeb1SVinicius Costa Gomes return; 11779f0caeb1SVinicius Costa Gomes } 11789f0caeb1SVinicius Costa Gomes 11790a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { 11800a708f8fSGustavo F. Padovan if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) 11810a708f8fSGustavo F. Padovan return; 11820a708f8fSGustavo F. Padovan 1183d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan) && 118493c3e8f5SAndrei Emeltchenko __l2cap_no_conn_pending(chan)) { 118593c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 118693c3e8f5SAndrei Emeltchenko } 11870a708f8fSGustavo F. Padovan } else { 11880a708f8fSGustavo F. Padovan struct l2cap_info_req req; 1189ac73498cSAndrei Emeltchenko req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); 11900a708f8fSGustavo F. Padovan 11910a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 11920a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 11930a708f8fSGustavo F. Padovan 1194ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 11950a708f8fSGustavo F. Padovan 11962d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, 11972d792818SGustavo Padovan sizeof(req), &req); 11980a708f8fSGustavo F. Padovan } 11990a708f8fSGustavo F. Padovan } 12000a708f8fSGustavo F. Padovan 12010a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) 12020a708f8fSGustavo F. Padovan { 12030a708f8fSGustavo F. Padovan u32 local_feat_mask = l2cap_feat_mask; 12040a708f8fSGustavo F. Padovan if (!disable_ertm) 12050a708f8fSGustavo F. Padovan local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING; 12060a708f8fSGustavo F. Padovan 12070a708f8fSGustavo F. Padovan switch (mode) { 12080a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 12090a708f8fSGustavo F. Padovan return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask; 12100a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 12110a708f8fSGustavo F. Padovan return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask; 12120a708f8fSGustavo F. Padovan default: 12130a708f8fSGustavo F. Padovan return 0x00; 12140a708f8fSGustavo F. Padovan } 12150a708f8fSGustavo F. Padovan } 12160a708f8fSGustavo F. Padovan 12175e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err) 12180a708f8fSGustavo F. Padovan { 12195e4e3972SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 12200a708f8fSGustavo F. Padovan struct l2cap_disconn_req req; 12210a708f8fSGustavo F. Padovan 12220a708f8fSGustavo F. Padovan if (!conn) 12230a708f8fSGustavo F. Padovan return; 12240a708f8fSGustavo F. Padovan 1225aad3d0e3SAndrei Emeltchenko if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) { 12261a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 12271a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 12281a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 12290a708f8fSGustavo F. Padovan } 12300a708f8fSGustavo F. Padovan 1231416fa752SAndrei Emeltchenko if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { 1232d117773cSGustavo Padovan l2cap_state_change(chan, BT_DISCONN); 1233416fa752SAndrei Emeltchenko return; 1234416fa752SAndrei Emeltchenko } 1235416fa752SAndrei Emeltchenko 1236fe4128e0SGustavo F. Padovan req.dcid = cpu_to_le16(chan->dcid); 1237fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 12382d792818SGustavo Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ, 12392d792818SGustavo Padovan sizeof(req), &req); 12400a708f8fSGustavo F. Padovan 1241f8e73017SGustavo Padovan l2cap_state_change_and_error(chan, BT_DISCONN, err); 12420a708f8fSGustavo F. Padovan } 12430a708f8fSGustavo F. Padovan 12440a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */ 12450a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn) 12460a708f8fSGustavo F. Padovan { 12473df91ea2SAndrei Emeltchenko struct l2cap_chan *chan, *tmp; 12480a708f8fSGustavo F. Padovan 12490a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 12500a708f8fSGustavo F. Padovan 12513df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 12520a708f8fSGustavo F. Padovan 12533df91ea2SAndrei Emeltchenko list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 12546be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 12550a708f8fSGustavo F. Padovan 1256715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 12576be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 12580a708f8fSGustavo F. Padovan continue; 12590a708f8fSGustavo F. Padovan } 12600a708f8fSGustavo F. Padovan 126189bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 1262d45fc423SGustavo F. Padovan if (!l2cap_chan_check_security(chan) || 1263b4450035SGustavo F. Padovan !__l2cap_no_conn_pending(chan)) { 12646be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 12650a708f8fSGustavo F. Padovan continue; 12660a708f8fSGustavo F. Padovan } 12670a708f8fSGustavo F. Padovan 1268c1360a1cSGustavo F. Padovan if (!l2cap_mode_supported(chan->mode, conn->feat_mask) 1269c1360a1cSGustavo F. Padovan && test_bit(CONF_STATE2_DEVICE, 1270c1360a1cSGustavo F. Padovan &chan->conf_state)) { 12710f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 12726be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 12730a708f8fSGustavo F. Padovan continue; 12740a708f8fSGustavo F. Padovan } 12750a708f8fSGustavo F. Padovan 127693c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 12770a708f8fSGustavo F. Padovan 127889bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 12790a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 12800a708f8fSGustavo F. Padovan char buf[128]; 1281fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 1282fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 12830a708f8fSGustavo F. Padovan 1284d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 1285bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 1286ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); 1287ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND); 12882dc4e510SGustavo Padovan chan->ops->defer(chan); 12890a708f8fSGustavo F. Padovan 12900a708f8fSGustavo F. Padovan } else { 1291acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 1292ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 1293ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 12940a708f8fSGustavo F. Padovan } 12950a708f8fSGustavo F. Padovan } else { 1296ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); 1297ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND); 12980a708f8fSGustavo F. Padovan } 12990a708f8fSGustavo F. Padovan 1300fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 1301fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 13020a708f8fSGustavo F. Padovan 1303c1360a1cSGustavo F. Padovan if (test_bit(CONF_REQ_SENT, &chan->conf_state) || 13040a708f8fSGustavo F. Padovan rsp.result != L2CAP_CR_SUCCESS) { 13056be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13060a708f8fSGustavo F. Padovan continue; 13070a708f8fSGustavo F. Padovan } 13080a708f8fSGustavo F. Padovan 1309c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 13100a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 131173ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 131273ffa904SGustavo F. Padovan chan->num_conf_req++; 13130a708f8fSGustavo F. Padovan } 13140a708f8fSGustavo F. Padovan 13156be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13160a708f8fSGustavo F. Padovan } 13170a708f8fSGustavo F. Padovan 13183df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 13190a708f8fSGustavo F. Padovan } 13200a708f8fSGustavo F. Padovan 1321c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr. 1322b62f328bSVille Tervo * Returns closest match, locked. 1323b62f328bSVille Tervo */ 1324d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, 1325c2287681SIdo Yariv bdaddr_t *src, 1326c2287681SIdo Yariv bdaddr_t *dst) 1327b62f328bSVille Tervo { 132823691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 1329b62f328bSVille Tervo 133023691d75SGustavo F. Padovan read_lock(&chan_list_lock); 1331b62f328bSVille Tervo 133223691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 133389bc500eSGustavo F. Padovan if (state && c->state != state) 1334b62f328bSVille Tervo continue; 1335b62f328bSVille Tervo 133623691d75SGustavo F. Padovan if (c->scid == cid) { 1337c2287681SIdo Yariv int src_match, dst_match; 1338c2287681SIdo Yariv int src_any, dst_any; 1339c2287681SIdo Yariv 1340b62f328bSVille Tervo /* Exact match. */ 13417eafc59eSMarcel Holtmann src_match = !bacmp(&c->src, src); 13427eafc59eSMarcel Holtmann dst_match = !bacmp(&c->dst, dst); 1343c2287681SIdo Yariv if (src_match && dst_match) { 134423691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 134523691d75SGustavo F. Padovan return c; 134623691d75SGustavo F. Padovan } 1347b62f328bSVille Tervo 1348b62f328bSVille Tervo /* Closest match */ 13497eafc59eSMarcel Holtmann src_any = !bacmp(&c->src, BDADDR_ANY); 13507eafc59eSMarcel Holtmann dst_any = !bacmp(&c->dst, BDADDR_ANY); 1351c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1352c2287681SIdo Yariv (src_any && dst_any)) 135323691d75SGustavo F. Padovan c1 = c; 1354b62f328bSVille Tervo } 1355b62f328bSVille Tervo } 1356280f294fSGustavo F. Padovan 135723691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 1358b62f328bSVille Tervo 135923691d75SGustavo F. Padovan return c1; 1360b62f328bSVille Tervo } 1361b62f328bSVille Tervo 1362b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn) 1363b62f328bSVille Tervo { 1364cc8dba2bSMarcel Holtmann struct hci_conn *hcon = conn->hcon; 136560bac184SJohan Hedberg struct sock *parent; 136623691d75SGustavo F. Padovan struct l2cap_chan *chan, *pchan; 1367cc8dba2bSMarcel Holtmann u8 dst_type; 1368b62f328bSVille Tervo 1369b62f328bSVille Tervo BT_DBG(""); 1370b62f328bSVille Tervo 1371b62f328bSVille Tervo /* Check if we have socket listening on cid */ 1372073d1cf3SJohan Hedberg pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT, 1373cc8dba2bSMarcel Holtmann &hcon->src, &hcon->dst); 137423691d75SGustavo F. Padovan if (!pchan) 1375b62f328bSVille Tervo return; 1376b62f328bSVille Tervo 137744f3b0fbSJohan Hedberg /* Client ATT sockets should override the server one */ 137844f3b0fbSJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, L2CAP_CID_ATT)) 137944f3b0fbSJohan Hedberg return; 138044f3b0fbSJohan Hedberg 1381cc8dba2bSMarcel Holtmann dst_type = bdaddr_type(hcon, hcon->dst_type); 1382cc8dba2bSMarcel Holtmann 1383cc8dba2bSMarcel Holtmann /* If device is blocked, do not create a channel for it */ 1384cc8dba2bSMarcel Holtmann if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, dst_type)) 1385cc8dba2bSMarcel Holtmann return; 1386cc8dba2bSMarcel Holtmann 138723691d75SGustavo F. Padovan parent = pchan->sk; 138823691d75SGustavo F. Padovan 1389aa2ac881SGustavo F. Padovan lock_sock(parent); 139062f3a2cfSGustavo F. Padovan 139180b98027SGustavo Padovan chan = pchan->ops->new_connection(pchan); 139280808e43SGustavo F. Padovan if (!chan) 1393b62f328bSVille Tervo goto clean; 1394b62f328bSVille Tervo 13959f22398cSJohan Hedberg chan->dcid = L2CAP_CID_ATT; 13969f22398cSJohan Hedberg 1397cc8dba2bSMarcel Holtmann bacpy(&chan->src, &hcon->src); 1398cc8dba2bSMarcel Holtmann bacpy(&chan->dst, &hcon->dst); 1399cc8dba2bSMarcel Holtmann chan->src_type = bdaddr_type(hcon, hcon->src_type); 1400cc8dba2bSMarcel Holtmann chan->dst_type = dst_type; 1401b62f328bSVille Tervo 140244f3b0fbSJohan Hedberg __l2cap_chan_add(conn, chan); 140348454079SGustavo F. Padovan 1404b62f328bSVille Tervo clean: 1405aa2ac881SGustavo F. Padovan release_sock(parent); 1406b62f328bSVille Tervo } 1407b62f328bSVille Tervo 14080a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn) 14090a708f8fSGustavo F. Padovan { 141048454079SGustavo F. Padovan struct l2cap_chan *chan; 1411cc110922SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 14120a708f8fSGustavo F. Padovan 14130a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 14140a708f8fSGustavo F. Padovan 1415d8729922SJohan Hedberg /* For outgoing pairing which doesn't necessarily have an 1416d8729922SJohan Hedberg * associated socket (e.g. mgmt_pair_device). 1417d8729922SJohan Hedberg */ 1418cc110922SVinicius Costa Gomes if (hcon->out && hcon->type == LE_LINK) 1419cc110922SVinicius Costa Gomes smp_conn_security(hcon, hcon->pending_sec_level); 1420160dc6acSVinicius Costa Gomes 14213df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 14220a708f8fSGustavo F. Padovan 142344f3b0fbSJohan Hedberg if (hcon->type == LE_LINK) 142444f3b0fbSJohan Hedberg l2cap_le_conn_ready(conn); 142544f3b0fbSJohan Hedberg 14263df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1427baa7e1faSGustavo F. Padovan 14286be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 14290a708f8fSGustavo F. Padovan 1430416fa752SAndrei Emeltchenko if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { 1431416fa752SAndrei Emeltchenko l2cap_chan_unlock(chan); 1432416fa752SAndrei Emeltchenko continue; 1433416fa752SAndrei Emeltchenko } 1434416fa752SAndrei Emeltchenko 1435cc110922SVinicius Costa Gomes if (hcon->type == LE_LINK) { 1436cc110922SVinicius Costa Gomes if (smp_conn_security(hcon, chan->sec_level)) 1437cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 1438acd7d370SVille Tervo 143963128451SVinicius Costa Gomes } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 144074e75740SGustavo Padovan l2cap_chan_ready(chan); 1441b501d6a1SAnderson Briglia 14421c244f79SGustavo Padovan } else if (chan->state == BT_CONNECT) { 1443fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 14441c244f79SGustavo Padovan } 14450a708f8fSGustavo F. Padovan 14466be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 14470a708f8fSGustavo F. Padovan } 14480a708f8fSGustavo F. Padovan 14493df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 14500a708f8fSGustavo F. Padovan } 14510a708f8fSGustavo F. Padovan 14520a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */ 14530a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) 14540a708f8fSGustavo F. Padovan { 145548454079SGustavo F. Padovan struct l2cap_chan *chan; 14560a708f8fSGustavo F. Padovan 14570a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 14580a708f8fSGustavo F. Padovan 14593df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 14600a708f8fSGustavo F. Padovan 14613df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1462ecf61bdbSAndrei Emeltchenko if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) 14631d8b1fd5SGustavo Padovan l2cap_chan_set_err(chan, err); 14640a708f8fSGustavo F. Padovan } 14650a708f8fSGustavo F. Padovan 14663df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 14670a708f8fSGustavo F. Padovan } 14680a708f8fSGustavo F. Padovan 1469f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work) 14700a708f8fSGustavo F. Padovan { 1471f878fcadSGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 1472030013d8SGustavo F. Padovan info_timer.work); 14730a708f8fSGustavo F. Padovan 14740a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 14750a708f8fSGustavo F. Padovan conn->info_ident = 0; 14760a708f8fSGustavo F. Padovan 14770a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 14780a708f8fSGustavo F. Padovan } 14790a708f8fSGustavo F. Padovan 14802c8e1411SDavid Herrmann /* 14812c8e1411SDavid Herrmann * l2cap_user 14822c8e1411SDavid Herrmann * External modules can register l2cap_user objects on l2cap_conn. The ->probe 14832c8e1411SDavid Herrmann * callback is called during registration. The ->remove callback is called 14842c8e1411SDavid Herrmann * during unregistration. 14852c8e1411SDavid Herrmann * An l2cap_user object can either be explicitly unregistered or when the 14862c8e1411SDavid Herrmann * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon, 14872c8e1411SDavid Herrmann * l2cap->hchan, .. are valid as long as the remove callback hasn't been called. 14882c8e1411SDavid Herrmann * External modules must own a reference to the l2cap_conn object if they intend 14892c8e1411SDavid Herrmann * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at 14902c8e1411SDavid Herrmann * any time if they don't. 14912c8e1411SDavid Herrmann */ 14922c8e1411SDavid Herrmann 14932c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) 14942c8e1411SDavid Herrmann { 14952c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev; 14962c8e1411SDavid Herrmann int ret; 14972c8e1411SDavid Herrmann 14982c8e1411SDavid Herrmann /* We need to check whether l2cap_conn is registered. If it is not, we 14992c8e1411SDavid Herrmann * must not register the l2cap_user. l2cap_conn_del() is unregisters 15002c8e1411SDavid Herrmann * l2cap_conn objects, but doesn't provide its own locking. Instead, it 15012c8e1411SDavid Herrmann * relies on the parent hci_conn object to be locked. This itself relies 15022c8e1411SDavid Herrmann * on the hci_dev object to be locked. So we must lock the hci device 15032c8e1411SDavid Herrmann * here, too. */ 15042c8e1411SDavid Herrmann 15052c8e1411SDavid Herrmann hci_dev_lock(hdev); 15062c8e1411SDavid Herrmann 15072c8e1411SDavid Herrmann if (user->list.next || user->list.prev) { 15082c8e1411SDavid Herrmann ret = -EINVAL; 15092c8e1411SDavid Herrmann goto out_unlock; 15102c8e1411SDavid Herrmann } 15112c8e1411SDavid Herrmann 15122c8e1411SDavid Herrmann /* conn->hchan is NULL after l2cap_conn_del() was called */ 15132c8e1411SDavid Herrmann if (!conn->hchan) { 15142c8e1411SDavid Herrmann ret = -ENODEV; 15152c8e1411SDavid Herrmann goto out_unlock; 15162c8e1411SDavid Herrmann } 15172c8e1411SDavid Herrmann 15182c8e1411SDavid Herrmann ret = user->probe(conn, user); 15192c8e1411SDavid Herrmann if (ret) 15202c8e1411SDavid Herrmann goto out_unlock; 15212c8e1411SDavid Herrmann 15222c8e1411SDavid Herrmann list_add(&user->list, &conn->users); 15232c8e1411SDavid Herrmann ret = 0; 15242c8e1411SDavid Herrmann 15252c8e1411SDavid Herrmann out_unlock: 15262c8e1411SDavid Herrmann hci_dev_unlock(hdev); 15272c8e1411SDavid Herrmann return ret; 15282c8e1411SDavid Herrmann } 15292c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user); 15302c8e1411SDavid Herrmann 15312c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) 15322c8e1411SDavid Herrmann { 15332c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev; 15342c8e1411SDavid Herrmann 15352c8e1411SDavid Herrmann hci_dev_lock(hdev); 15362c8e1411SDavid Herrmann 15372c8e1411SDavid Herrmann if (!user->list.next || !user->list.prev) 15382c8e1411SDavid Herrmann goto out_unlock; 15392c8e1411SDavid Herrmann 15402c8e1411SDavid Herrmann list_del(&user->list); 15412c8e1411SDavid Herrmann user->list.next = NULL; 15422c8e1411SDavid Herrmann user->list.prev = NULL; 15432c8e1411SDavid Herrmann user->remove(conn, user); 15442c8e1411SDavid Herrmann 15452c8e1411SDavid Herrmann out_unlock: 15462c8e1411SDavid Herrmann hci_dev_unlock(hdev); 15472c8e1411SDavid Herrmann } 15482c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user); 15492c8e1411SDavid Herrmann 15502c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn) 15512c8e1411SDavid Herrmann { 15522c8e1411SDavid Herrmann struct l2cap_user *user; 15532c8e1411SDavid Herrmann 15542c8e1411SDavid Herrmann while (!list_empty(&conn->users)) { 15552c8e1411SDavid Herrmann user = list_first_entry(&conn->users, struct l2cap_user, list); 15562c8e1411SDavid Herrmann list_del(&user->list); 15572c8e1411SDavid Herrmann user->list.next = NULL; 15582c8e1411SDavid Herrmann user->list.prev = NULL; 15592c8e1411SDavid Herrmann user->remove(conn, user); 15602c8e1411SDavid Herrmann } 15612c8e1411SDavid Herrmann } 15622c8e1411SDavid Herrmann 15635d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err) 15645d3de7dfSVinicius Costa Gomes { 15655d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 15665d3de7dfSVinicius Costa Gomes struct l2cap_chan *chan, *l; 15675d3de7dfSVinicius Costa Gomes 15685d3de7dfSVinicius Costa Gomes if (!conn) 15695d3de7dfSVinicius Costa Gomes return; 15705d3de7dfSVinicius Costa Gomes 15715d3de7dfSVinicius Costa Gomes BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); 15725d3de7dfSVinicius Costa Gomes 15735d3de7dfSVinicius Costa Gomes kfree_skb(conn->rx_skb); 15745d3de7dfSVinicius Costa Gomes 15752c8e1411SDavid Herrmann l2cap_unregister_all_users(conn); 15762c8e1411SDavid Herrmann 15773df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 15783df91ea2SAndrei Emeltchenko 15795d3de7dfSVinicius Costa Gomes /* Kill channels */ 15805d3de7dfSVinicius Costa Gomes list_for_each_entry_safe(chan, l, &conn->chan_l, list) { 158161d6ef3eSMat Martineau l2cap_chan_hold(chan); 15826be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 15836be36555SAndrei Emeltchenko 15845d3de7dfSVinicius Costa Gomes l2cap_chan_del(chan, err); 15856be36555SAndrei Emeltchenko 15866be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 15876be36555SAndrei Emeltchenko 158880b98027SGustavo Padovan chan->ops->close(chan); 158961d6ef3eSMat Martineau l2cap_chan_put(chan); 15905d3de7dfSVinicius Costa Gomes } 15915d3de7dfSVinicius Costa Gomes 15923df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 15933df91ea2SAndrei Emeltchenko 159473d80debSLuiz Augusto von Dentz hci_chan_del(conn->hchan); 159573d80debSLuiz Augusto von Dentz 15965d3de7dfSVinicius Costa Gomes if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1597127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->info_timer); 15985d3de7dfSVinicius Costa Gomes 159951a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) { 1600127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->security_timer); 16018aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 1602d26a2345SVinicius Costa Gomes } 16035d3de7dfSVinicius Costa Gomes 16045d3de7dfSVinicius Costa Gomes hcon->l2cap_data = NULL; 16059c903e37SDavid Herrmann conn->hchan = NULL; 16069c903e37SDavid Herrmann l2cap_conn_put(conn); 16075d3de7dfSVinicius Costa Gomes } 16085d3de7dfSVinicius Costa Gomes 16096c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work) 16105d3de7dfSVinicius Costa Gomes { 16116c9d42a1SGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 16126c9d42a1SGustavo F. Padovan security_timer.work); 16135d3de7dfSVinicius Costa Gomes 1614d06cc416SJohan Hedberg BT_DBG("conn %p", conn); 1615d06cc416SJohan Hedberg 1616d06cc416SJohan Hedberg if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) { 1617d06cc416SJohan Hedberg smp_chan_destroy(conn); 16185d3de7dfSVinicius Costa Gomes l2cap_conn_del(conn->hcon, ETIMEDOUT); 16195d3de7dfSVinicius Costa Gomes } 1620d06cc416SJohan Hedberg } 16215d3de7dfSVinicius Costa Gomes 1622baf43251SClaudio Takahasi static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) 16230a708f8fSGustavo F. Padovan { 16240a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 162573d80debSLuiz Augusto von Dentz struct hci_chan *hchan; 16260a708f8fSGustavo F. Padovan 1627baf43251SClaudio Takahasi if (conn) 16280a708f8fSGustavo F. Padovan return conn; 16290a708f8fSGustavo F. Padovan 163073d80debSLuiz Augusto von Dentz hchan = hci_chan_create(hcon); 163173d80debSLuiz Augusto von Dentz if (!hchan) 16320a708f8fSGustavo F. Padovan return NULL; 16330a708f8fSGustavo F. Padovan 16348bcde1f2SGustavo Padovan conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL); 163573d80debSLuiz Augusto von Dentz if (!conn) { 163673d80debSLuiz Augusto von Dentz hci_chan_del(hchan); 163773d80debSLuiz Augusto von Dentz return NULL; 163873d80debSLuiz Augusto von Dentz } 163973d80debSLuiz Augusto von Dentz 16409c903e37SDavid Herrmann kref_init(&conn->ref); 16410a708f8fSGustavo F. Padovan hcon->l2cap_data = conn; 16420a708f8fSGustavo F. Padovan conn->hcon = hcon; 16439c903e37SDavid Herrmann hci_conn_get(conn->hcon); 164473d80debSLuiz Augusto von Dentz conn->hchan = hchan; 16450a708f8fSGustavo F. Padovan 164673d80debSLuiz Augusto von Dentz BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); 16470a708f8fSGustavo F. Padovan 1648dcc042d5SAndrei Emeltchenko switch (hcon->type) { 1649dcc042d5SAndrei Emeltchenko case LE_LINK: 1650dcc042d5SAndrei Emeltchenko if (hcon->hdev->le_mtu) { 1651acd7d370SVille Tervo conn->mtu = hcon->hdev->le_mtu; 1652dcc042d5SAndrei Emeltchenko break; 1653dcc042d5SAndrei Emeltchenko } 1654dcc042d5SAndrei Emeltchenko /* fall through */ 1655dcc042d5SAndrei Emeltchenko default: 16560a708f8fSGustavo F. Padovan conn->mtu = hcon->hdev->acl_mtu; 1657dcc042d5SAndrei Emeltchenko break; 1658dcc042d5SAndrei Emeltchenko } 1659acd7d370SVille Tervo 16600a708f8fSGustavo F. Padovan conn->feat_mask = 0; 16610a708f8fSGustavo F. Padovan 1662848566b3SMarcel Holtmann if (hcon->type == ACL_LINK) 1663848566b3SMarcel Holtmann conn->hs_enabled = test_bit(HCI_HS_ENABLED, 1664848566b3SMarcel Holtmann &hcon->hdev->dev_flags); 1665848566b3SMarcel Holtmann 16660a708f8fSGustavo F. Padovan spin_lock_init(&conn->lock); 16673df91ea2SAndrei Emeltchenko mutex_init(&conn->chan_lock); 1668baa7e1faSGustavo F. Padovan 1669baa7e1faSGustavo F. Padovan INIT_LIST_HEAD(&conn->chan_l); 16702c8e1411SDavid Herrmann INIT_LIST_HEAD(&conn->users); 16710a708f8fSGustavo F. Padovan 16725d3de7dfSVinicius Costa Gomes if (hcon->type == LE_LINK) 16736c9d42a1SGustavo F. Padovan INIT_DELAYED_WORK(&conn->security_timer, security_timeout); 16745d3de7dfSVinicius Costa Gomes else 1675030013d8SGustavo F. Padovan INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); 16760a708f8fSGustavo F. Padovan 16779f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 16780a708f8fSGustavo F. Padovan 16790a708f8fSGustavo F. Padovan return conn; 16800a708f8fSGustavo F. Padovan } 16810a708f8fSGustavo F. Padovan 16829c903e37SDavid Herrmann static void l2cap_conn_free(struct kref *ref) 16839c903e37SDavid Herrmann { 16849c903e37SDavid Herrmann struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref); 16859c903e37SDavid Herrmann 16869c903e37SDavid Herrmann hci_conn_put(conn->hcon); 16879c903e37SDavid Herrmann kfree(conn); 16889c903e37SDavid Herrmann } 16899c903e37SDavid Herrmann 16909c903e37SDavid Herrmann void l2cap_conn_get(struct l2cap_conn *conn) 16919c903e37SDavid Herrmann { 16929c903e37SDavid Herrmann kref_get(&conn->ref); 16939c903e37SDavid Herrmann } 16949c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_get); 16959c903e37SDavid Herrmann 16969c903e37SDavid Herrmann void l2cap_conn_put(struct l2cap_conn *conn) 16979c903e37SDavid Herrmann { 16989c903e37SDavid Herrmann kref_put(&conn->ref, l2cap_conn_free); 16999c903e37SDavid Herrmann } 17009c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_put); 17019c903e37SDavid Herrmann 17020a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */ 17030a708f8fSGustavo F. Padovan 1704c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr. 17050a708f8fSGustavo F. Padovan * Returns closest match. 17060a708f8fSGustavo F. Padovan */ 1707c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, 1708c2287681SIdo Yariv bdaddr_t *src, 1709c2287681SIdo Yariv bdaddr_t *dst) 17100a708f8fSGustavo F. Padovan { 171123691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 17120a708f8fSGustavo F. Padovan 171323691d75SGustavo F. Padovan read_lock(&chan_list_lock); 17140a708f8fSGustavo F. Padovan 171523691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 171689bc500eSGustavo F. Padovan if (state && c->state != state) 17170a708f8fSGustavo F. Padovan continue; 17180a708f8fSGustavo F. Padovan 171923691d75SGustavo F. Padovan if (c->psm == psm) { 1720c2287681SIdo Yariv int src_match, dst_match; 1721c2287681SIdo Yariv int src_any, dst_any; 1722c2287681SIdo Yariv 17230a708f8fSGustavo F. Padovan /* Exact match. */ 17247eafc59eSMarcel Holtmann src_match = !bacmp(&c->src, src); 17257eafc59eSMarcel Holtmann dst_match = !bacmp(&c->dst, dst); 1726c2287681SIdo Yariv if (src_match && dst_match) { 1727a7567b20SJohannes Berg read_unlock(&chan_list_lock); 172823691d75SGustavo F. Padovan return c; 172923691d75SGustavo F. Padovan } 17300a708f8fSGustavo F. Padovan 17310a708f8fSGustavo F. Padovan /* Closest match */ 17327eafc59eSMarcel Holtmann src_any = !bacmp(&c->src, BDADDR_ANY); 17337eafc59eSMarcel Holtmann dst_any = !bacmp(&c->dst, BDADDR_ANY); 1734c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1735c2287681SIdo Yariv (src_any && dst_any)) 173623691d75SGustavo F. Padovan c1 = c; 17370a708f8fSGustavo F. Padovan } 17380a708f8fSGustavo F. Padovan } 17390a708f8fSGustavo F. Padovan 174023691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 17410a708f8fSGustavo F. Padovan 174223691d75SGustavo F. Padovan return c1; 17430a708f8fSGustavo F. Padovan } 17440a708f8fSGustavo F. Padovan 17458e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, 17468e9f9892SAndre Guedes bdaddr_t *dst, u8 dst_type) 17470a708f8fSGustavo F. Padovan { 17480a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 17490a708f8fSGustavo F. Padovan struct hci_conn *hcon; 17500a708f8fSGustavo F. Padovan struct hci_dev *hdev; 17510a708f8fSGustavo F. Padovan __u8 auth_type; 17520a708f8fSGustavo F. Padovan int err; 17530a708f8fSGustavo F. Padovan 17547eafc59eSMarcel Holtmann BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst, 1755ab19516aSSyam Sidhardhan dst_type, __le16_to_cpu(psm)); 17560a708f8fSGustavo F. Padovan 17577eafc59eSMarcel Holtmann hdev = hci_get_route(dst, &chan->src); 17580a708f8fSGustavo F. Padovan if (!hdev) 17590a708f8fSGustavo F. Padovan return -EHOSTUNREACH; 17600a708f8fSGustavo F. Padovan 176109fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 17620a708f8fSGustavo F. Padovan 17636be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 176403a00194SGustavo F. Padovan 176503a00194SGustavo F. Padovan /* PSM must be odd and lsb of upper byte must be 0 */ 176603a00194SGustavo F. Padovan if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid && 176703a00194SGustavo F. Padovan chan->chan_type != L2CAP_CHAN_RAW) { 176803a00194SGustavo F. Padovan err = -EINVAL; 176903a00194SGustavo F. Padovan goto done; 177003a00194SGustavo F. Padovan } 177103a00194SGustavo F. Padovan 177203a00194SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) { 177303a00194SGustavo F. Padovan err = -EINVAL; 177403a00194SGustavo F. Padovan goto done; 177503a00194SGustavo F. Padovan } 177603a00194SGustavo F. Padovan 177703a00194SGustavo F. Padovan switch (chan->mode) { 177803a00194SGustavo F. Padovan case L2CAP_MODE_BASIC: 177903a00194SGustavo F. Padovan break; 178003a00194SGustavo F. Padovan case L2CAP_MODE_ERTM: 178103a00194SGustavo F. Padovan case L2CAP_MODE_STREAMING: 178203a00194SGustavo F. Padovan if (!disable_ertm) 178303a00194SGustavo F. Padovan break; 178403a00194SGustavo F. Padovan /* fall through */ 178503a00194SGustavo F. Padovan default: 178603a00194SGustavo F. Padovan err = -ENOTSUPP; 178703a00194SGustavo F. Padovan goto done; 178803a00194SGustavo F. Padovan } 178903a00194SGustavo F. Padovan 17900797e01dSGustavo Padovan switch (chan->state) { 179103a00194SGustavo F. Padovan case BT_CONNECT: 179203a00194SGustavo F. Padovan case BT_CONNECT2: 179303a00194SGustavo F. Padovan case BT_CONFIG: 179403a00194SGustavo F. Padovan /* Already connecting */ 179503a00194SGustavo F. Padovan err = 0; 179603a00194SGustavo F. Padovan goto done; 179703a00194SGustavo F. Padovan 179803a00194SGustavo F. Padovan case BT_CONNECTED: 179903a00194SGustavo F. Padovan /* Already connected */ 180003a00194SGustavo F. Padovan err = -EISCONN; 180103a00194SGustavo F. Padovan goto done; 180203a00194SGustavo F. Padovan 180303a00194SGustavo F. Padovan case BT_OPEN: 180403a00194SGustavo F. Padovan case BT_BOUND: 180503a00194SGustavo F. Padovan /* Can connect */ 180603a00194SGustavo F. Padovan break; 180703a00194SGustavo F. Padovan 180803a00194SGustavo F. Padovan default: 180903a00194SGustavo F. Padovan err = -EBADFD; 181003a00194SGustavo F. Padovan goto done; 181103a00194SGustavo F. Padovan } 181203a00194SGustavo F. Padovan 181303a00194SGustavo F. Padovan /* Set destination address and psm */ 18147eafc59eSMarcel Holtmann bacpy(&chan->dst, dst); 18154f1654e0SMarcel Holtmann chan->dst_type = dst_type; 18166be36555SAndrei Emeltchenko 181703a00194SGustavo F. Padovan chan->psm = psm; 181803a00194SGustavo F. Padovan chan->dcid = cid; 18190a708f8fSGustavo F. Padovan 18204343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 18210a708f8fSGustavo F. Padovan 1822f224ca5fSJohan Hedberg if (bdaddr_type_is_le(dst_type)) 18238e9f9892SAndre Guedes hcon = hci_connect(hdev, LE_LINK, dst, dst_type, 18244343478fSGustavo F. Padovan chan->sec_level, auth_type); 1825acd7d370SVille Tervo else 18268e9f9892SAndre Guedes hcon = hci_connect(hdev, ACL_LINK, dst, dst_type, 18274343478fSGustavo F. Padovan chan->sec_level, auth_type); 1828acd7d370SVille Tervo 182930e76272SVille Tervo if (IS_ERR(hcon)) { 183030e76272SVille Tervo err = PTR_ERR(hcon); 18310a708f8fSGustavo F. Padovan goto done; 183230e76272SVille Tervo } 18330a708f8fSGustavo F. Padovan 1834baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon); 18350a708f8fSGustavo F. Padovan if (!conn) { 183676a68ba0SDavid Herrmann hci_conn_drop(hcon); 183730e76272SVille Tervo err = -ENOMEM; 18380a708f8fSGustavo F. Padovan goto done; 18390a708f8fSGustavo F. Padovan } 18400a708f8fSGustavo F. Padovan 1841141d5706SJohan Hedberg if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { 184276a68ba0SDavid Herrmann hci_conn_drop(hcon); 1843141d5706SJohan Hedberg err = -EBUSY; 18449f0caeb1SVinicius Costa Gomes goto done; 18459f0caeb1SVinicius Costa Gomes } 18469f0caeb1SVinicius Costa Gomes 18470a708f8fSGustavo F. Padovan /* Update source addr of the socket */ 18487eafc59eSMarcel Holtmann bacpy(&chan->src, &hcon->src); 18494f1654e0SMarcel Holtmann chan->src_type = bdaddr_type(hcon, hcon->src_type); 18500a708f8fSGustavo F. Padovan 18516be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 185248454079SGustavo F. Padovan l2cap_chan_add(conn, chan); 18536be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 185448454079SGustavo F. Padovan 18555ee9891dSJohan Hedberg /* l2cap_chan_add takes its own ref so we can drop this one */ 18565ee9891dSJohan Hedberg hci_conn_drop(hcon); 18575ee9891dSJohan Hedberg 18586be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECT); 18598d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 18600a708f8fSGustavo F. Padovan 18610a708f8fSGustavo F. Padovan if (hcon->state == BT_CONNECTED) { 1862715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1863c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 1864d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) 18656be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECTED); 18660a708f8fSGustavo F. Padovan } else 1867fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 18680a708f8fSGustavo F. Padovan } 18690a708f8fSGustavo F. Padovan 187030e76272SVille Tervo err = 0; 187130e76272SVille Tervo 18720a708f8fSGustavo F. Padovan done: 18736be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 187409fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 18750a708f8fSGustavo F. Padovan hci_dev_put(hdev); 18760a708f8fSGustavo F. Padovan return err; 18770a708f8fSGustavo F. Padovan } 18780a708f8fSGustavo F. Padovan 1879721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work) 18800a708f8fSGustavo F. Padovan { 1881721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1882721c4181SGustavo F. Padovan monitor_timer.work); 18830a708f8fSGustavo F. Padovan 1884525cd185SGustavo F. Padovan BT_DBG("chan %p", chan); 18850a708f8fSGustavo F. Padovan 18866be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 18876be36555SAndrei Emeltchenko 188880909e04SMat Martineau if (!chan->conn) { 18896be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 18908d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 18910a708f8fSGustavo F. Padovan return; 18920a708f8fSGustavo F. Padovan } 18930a708f8fSGustavo F. Padovan 1894401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO); 18950a708f8fSGustavo F. Padovan 18966be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 18978d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 18980a708f8fSGustavo F. Padovan } 18990a708f8fSGustavo F. Padovan 1900721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work) 19010a708f8fSGustavo F. Padovan { 1902721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1903721c4181SGustavo F. Padovan retrans_timer.work); 19040a708f8fSGustavo F. Padovan 190549208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 19060a708f8fSGustavo F. Padovan 19076be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 19086be36555SAndrei Emeltchenko 190980909e04SMat Martineau if (!chan->conn) { 191080909e04SMat Martineau l2cap_chan_unlock(chan); 191180909e04SMat Martineau l2cap_chan_put(chan); 191280909e04SMat Martineau return; 191380909e04SMat Martineau } 19140a708f8fSGustavo F. Padovan 1915401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO); 19166be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 19178d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 19180a708f8fSGustavo F. Padovan } 19190a708f8fSGustavo F. Padovan 1920d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan, 19213733937dSMat Martineau struct sk_buff_head *skbs) 19220a708f8fSGustavo F. Padovan { 19230a708f8fSGustavo F. Padovan struct sk_buff *skb; 19243733937dSMat Martineau struct l2cap_ctrl *control; 19250a708f8fSGustavo F. Padovan 19263733937dSMat Martineau BT_DBG("chan %p, skbs %p", chan, skbs); 19273733937dSMat Martineau 1928b99e13adSMat Martineau if (__chan_is_moving(chan)) 1929b99e13adSMat Martineau return; 1930b99e13adSMat Martineau 19313733937dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 19323733937dSMat Martineau 19333733937dSMat Martineau while (!skb_queue_empty(&chan->tx_q)) { 19343733937dSMat Martineau 19353733937dSMat Martineau skb = skb_dequeue(&chan->tx_q); 19363733937dSMat Martineau 19373733937dSMat Martineau bt_cb(skb)->control.retries = 1; 19383733937dSMat Martineau control = &bt_cb(skb)->control; 19393733937dSMat Martineau 19403733937dSMat Martineau control->reqseq = 0; 19413733937dSMat Martineau control->txseq = chan->next_tx_seq; 19423733937dSMat Martineau 19433733937dSMat Martineau __pack_control(chan, control, skb); 19440a708f8fSGustavo F. Padovan 194547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 19463733937dSMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 19473733937dSMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 19480a708f8fSGustavo F. Padovan } 19490a708f8fSGustavo F. Padovan 19504343478fSGustavo F. Padovan l2cap_do_send(chan, skb); 19510a708f8fSGustavo F. Padovan 1952b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 19533733937dSMat Martineau 1954836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 19553733937dSMat Martineau chan->frames_sent++; 19560a708f8fSGustavo F. Padovan } 19570a708f8fSGustavo F. Padovan } 19580a708f8fSGustavo F. Padovan 195967c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan) 19600a708f8fSGustavo F. Padovan { 19610a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 196218a48e76SMat Martineau struct l2cap_ctrl *control; 196318a48e76SMat Martineau int sent = 0; 196418a48e76SMat Martineau 196518a48e76SMat Martineau BT_DBG("chan %p", chan); 19660a708f8fSGustavo F. Padovan 196789bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 19680a708f8fSGustavo F. Padovan return -ENOTCONN; 19690a708f8fSGustavo F. Padovan 197094122bbeSMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 197194122bbeSMat Martineau return 0; 197294122bbeSMat Martineau 1973b99e13adSMat Martineau if (__chan_is_moving(chan)) 1974b99e13adSMat Martineau return 0; 1975b99e13adSMat Martineau 197618a48e76SMat Martineau while (chan->tx_send_head && 197718a48e76SMat Martineau chan->unacked_frames < chan->remote_tx_win && 197818a48e76SMat Martineau chan->tx_state == L2CAP_TX_STATE_XMIT) { 19790a708f8fSGustavo F. Padovan 198018a48e76SMat Martineau skb = chan->tx_send_head; 19810a708f8fSGustavo F. Padovan 198218a48e76SMat Martineau bt_cb(skb)->control.retries = 1; 198318a48e76SMat Martineau control = &bt_cb(skb)->control; 19840a708f8fSGustavo F. Padovan 1985e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 198618a48e76SMat Martineau control->final = 1; 1987e2ab4353SGustavo F. Padovan 198818a48e76SMat Martineau control->reqseq = chan->buffer_seq; 198918a48e76SMat Martineau chan->last_acked_seq = chan->buffer_seq; 199018a48e76SMat Martineau control->txseq = chan->next_tx_seq; 19910a708f8fSGustavo F. Padovan 199218a48e76SMat Martineau __pack_control(chan, control, skb); 19930a708f8fSGustavo F. Padovan 199447d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 199518a48e76SMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 199618a48e76SMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 19970a708f8fSGustavo F. Padovan } 19980a708f8fSGustavo F. Padovan 199918a48e76SMat Martineau /* Clone after data has been modified. Data is assumed to be 200018a48e76SMat Martineau read-only (for locking purposes) on cloned sk_buffs. 200118a48e76SMat Martineau */ 200218a48e76SMat Martineau tx_skb = skb_clone(skb, GFP_KERNEL); 200318a48e76SMat Martineau 200418a48e76SMat Martineau if (!tx_skb) 200518a48e76SMat Martineau break; 20060a708f8fSGustavo F. Padovan 20071a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 20080a708f8fSGustavo F. Padovan 2009836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 20106a026610SGustavo F. Padovan chan->unacked_frames++; 20116a026610SGustavo F. Padovan chan->frames_sent++; 201218a48e76SMat Martineau sent++; 20130a708f8fSGustavo F. Padovan 201458d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 201558d35f87SGustavo F. Padovan chan->tx_send_head = NULL; 20160a708f8fSGustavo F. Padovan else 201758d35f87SGustavo F. Padovan chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); 201818a48e76SMat Martineau 201918a48e76SMat Martineau l2cap_do_send(chan, tx_skb); 2020b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 20210a708f8fSGustavo F. Padovan } 20220a708f8fSGustavo F. Padovan 2023b4400672SAndrei Emeltchenko BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent, 2024b4400672SAndrei Emeltchenko chan->unacked_frames, skb_queue_len(&chan->tx_q)); 202518a48e76SMat Martineau 202618a48e76SMat Martineau return sent; 20270a708f8fSGustavo F. Padovan } 20280a708f8fSGustavo F. Padovan 2029e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan) 2030e1fbd4c1SMat Martineau { 2031e1fbd4c1SMat Martineau struct l2cap_ctrl control; 2032e1fbd4c1SMat Martineau struct sk_buff *skb; 2033e1fbd4c1SMat Martineau struct sk_buff *tx_skb; 2034e1fbd4c1SMat Martineau u16 seq; 2035e1fbd4c1SMat Martineau 2036e1fbd4c1SMat Martineau BT_DBG("chan %p", chan); 2037e1fbd4c1SMat Martineau 2038e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 2039e1fbd4c1SMat Martineau return; 2040e1fbd4c1SMat Martineau 2041b99e13adSMat Martineau if (__chan_is_moving(chan)) 2042b99e13adSMat Martineau return; 2043b99e13adSMat Martineau 2044e1fbd4c1SMat Martineau while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) { 2045e1fbd4c1SMat Martineau seq = l2cap_seq_list_pop(&chan->retrans_list); 2046e1fbd4c1SMat Martineau 2047e1fbd4c1SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq); 2048e1fbd4c1SMat Martineau if (!skb) { 2049e1fbd4c1SMat Martineau BT_DBG("Error: Can't retransmit seq %d, frame missing", 2050e1fbd4c1SMat Martineau seq); 2051e1fbd4c1SMat Martineau continue; 2052e1fbd4c1SMat Martineau } 2053e1fbd4c1SMat Martineau 2054e1fbd4c1SMat Martineau bt_cb(skb)->control.retries++; 2055e1fbd4c1SMat Martineau control = bt_cb(skb)->control; 2056e1fbd4c1SMat Martineau 2057e1fbd4c1SMat Martineau if (chan->max_tx != 0 && 2058e1fbd4c1SMat Martineau bt_cb(skb)->control.retries > chan->max_tx) { 2059e1fbd4c1SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 20605e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 2061e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2062e1fbd4c1SMat Martineau break; 2063e1fbd4c1SMat Martineau } 2064e1fbd4c1SMat Martineau 2065e1fbd4c1SMat Martineau control.reqseq = chan->buffer_seq; 2066e1fbd4c1SMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 2067e1fbd4c1SMat Martineau control.final = 1; 2068e1fbd4c1SMat Martineau else 2069e1fbd4c1SMat Martineau control.final = 0; 2070e1fbd4c1SMat Martineau 2071e1fbd4c1SMat Martineau if (skb_cloned(skb)) { 2072e1fbd4c1SMat Martineau /* Cloned sk_buffs are read-only, so we need a 2073e1fbd4c1SMat Martineau * writeable copy 2074e1fbd4c1SMat Martineau */ 20758bcde1f2SGustavo Padovan tx_skb = skb_copy(skb, GFP_KERNEL); 2076e1fbd4c1SMat Martineau } else { 20778bcde1f2SGustavo Padovan tx_skb = skb_clone(skb, GFP_KERNEL); 2078e1fbd4c1SMat Martineau } 2079e1fbd4c1SMat Martineau 2080e1fbd4c1SMat Martineau if (!tx_skb) { 2081e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2082e1fbd4c1SMat Martineau break; 2083e1fbd4c1SMat Martineau } 2084e1fbd4c1SMat Martineau 2085e1fbd4c1SMat Martineau /* Update skb contents */ 2086e1fbd4c1SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 2087e1fbd4c1SMat Martineau put_unaligned_le32(__pack_extended_control(&control), 2088e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 2089e1fbd4c1SMat Martineau } else { 2090e1fbd4c1SMat Martineau put_unaligned_le16(__pack_enhanced_control(&control), 2091e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 2092e1fbd4c1SMat Martineau } 2093e1fbd4c1SMat Martineau 2094e1fbd4c1SMat Martineau if (chan->fcs == L2CAP_FCS_CRC16) { 2095e1fbd4c1SMat Martineau u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len); 2096e1fbd4c1SMat Martineau put_unaligned_le16(fcs, skb_put(tx_skb, 2097e1fbd4c1SMat Martineau L2CAP_FCS_SIZE)); 2098e1fbd4c1SMat Martineau } 2099e1fbd4c1SMat Martineau 2100e1fbd4c1SMat Martineau l2cap_do_send(chan, tx_skb); 2101e1fbd4c1SMat Martineau 2102e1fbd4c1SMat Martineau BT_DBG("Resent txseq %d", control.txseq); 2103e1fbd4c1SMat Martineau 2104e1fbd4c1SMat Martineau chan->last_acked_seq = chan->buffer_seq; 2105e1fbd4c1SMat Martineau } 2106e1fbd4c1SMat Martineau } 2107e1fbd4c1SMat Martineau 2108f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan, 2109f80842a8SMat Martineau struct l2cap_ctrl *control) 2110f80842a8SMat Martineau { 2111f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2112f80842a8SMat Martineau 2113f80842a8SMat Martineau l2cap_seq_list_append(&chan->retrans_list, control->reqseq); 2114f80842a8SMat Martineau l2cap_ertm_resend(chan); 2115f80842a8SMat Martineau } 2116f80842a8SMat Martineau 2117d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan, 2118d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 2119d2a7ac5dSMat Martineau { 2120e1fbd4c1SMat Martineau struct sk_buff *skb; 2121e1fbd4c1SMat Martineau 2122e1fbd4c1SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2123e1fbd4c1SMat Martineau 2124e1fbd4c1SMat Martineau if (control->poll) 2125e1fbd4c1SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 2126e1fbd4c1SMat Martineau 2127e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2128e1fbd4c1SMat Martineau 2129e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 2130e1fbd4c1SMat Martineau return; 2131e1fbd4c1SMat Martineau 2132e1fbd4c1SMat Martineau if (chan->unacked_frames) { 2133e1fbd4c1SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 2134e1fbd4c1SMat Martineau if (bt_cb(skb)->control.txseq == control->reqseq || 2135e1fbd4c1SMat Martineau skb == chan->tx_send_head) 2136e1fbd4c1SMat Martineau break; 2137e1fbd4c1SMat Martineau } 2138e1fbd4c1SMat Martineau 2139e1fbd4c1SMat Martineau skb_queue_walk_from(&chan->tx_q, skb) { 2140e1fbd4c1SMat Martineau if (skb == chan->tx_send_head) 2141e1fbd4c1SMat Martineau break; 2142e1fbd4c1SMat Martineau 2143e1fbd4c1SMat Martineau l2cap_seq_list_append(&chan->retrans_list, 2144e1fbd4c1SMat Martineau bt_cb(skb)->control.txseq); 2145e1fbd4c1SMat Martineau } 2146e1fbd4c1SMat Martineau 2147e1fbd4c1SMat Martineau l2cap_ertm_resend(chan); 2148e1fbd4c1SMat Martineau } 2149d2a7ac5dSMat Martineau } 2150d2a7ac5dSMat Martineau 2151b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan) 2152b17e73bbSSzymon Janc { 21530a0aba42SMat Martineau struct l2cap_ctrl control; 21540a0aba42SMat Martineau u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq, 21550a0aba42SMat Martineau chan->last_acked_seq); 21560a0aba42SMat Martineau int threshold; 21570a0aba42SMat Martineau 21580a0aba42SMat Martineau BT_DBG("chan %p last_acked_seq %d buffer_seq %d", 21590a0aba42SMat Martineau chan, chan->last_acked_seq, chan->buffer_seq); 21600a0aba42SMat Martineau 21610a0aba42SMat Martineau memset(&control, 0, sizeof(control)); 21620a0aba42SMat Martineau control.sframe = 1; 21630a0aba42SMat Martineau 21640a0aba42SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 21650a0aba42SMat Martineau chan->rx_state == L2CAP_RX_STATE_RECV) { 2166b17e73bbSSzymon Janc __clear_ack_timer(chan); 21670a0aba42SMat Martineau control.super = L2CAP_SUPER_RNR; 21680a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 21690a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 21700a0aba42SMat Martineau } else { 21710a0aba42SMat Martineau if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) { 21720a0aba42SMat Martineau l2cap_ertm_send(chan); 21730a0aba42SMat Martineau /* If any i-frames were sent, they included an ack */ 21740a0aba42SMat Martineau if (chan->buffer_seq == chan->last_acked_seq) 21750a0aba42SMat Martineau frames_to_ack = 0; 21760a0aba42SMat Martineau } 21770a0aba42SMat Martineau 2178c20f8e35SMat Martineau /* Ack now if the window is 3/4ths full. 21790a0aba42SMat Martineau * Calculate without mul or div 21800a0aba42SMat Martineau */ 2181c20f8e35SMat Martineau threshold = chan->ack_win; 21820a0aba42SMat Martineau threshold += threshold << 1; 21830a0aba42SMat Martineau threshold >>= 2; 21840a0aba42SMat Martineau 2185b4400672SAndrei Emeltchenko BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack, 21860a0aba42SMat Martineau threshold); 21870a0aba42SMat Martineau 21880a0aba42SMat Martineau if (frames_to_ack >= threshold) { 21890a0aba42SMat Martineau __clear_ack_timer(chan); 21900a0aba42SMat Martineau control.super = L2CAP_SUPER_RR; 21910a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 21920a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 21930a0aba42SMat Martineau frames_to_ack = 0; 21940a0aba42SMat Martineau } 21950a0aba42SMat Martineau 21960a0aba42SMat Martineau if (frames_to_ack) 21970a0aba42SMat Martineau __set_ack_timer(chan); 21980a0aba42SMat Martineau } 2199b17e73bbSSzymon Janc } 2200b17e73bbSSzymon Janc 220104124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, 220204124681SGustavo F. Padovan struct msghdr *msg, int len, 220304124681SGustavo F. Padovan int count, struct sk_buff *skb) 22040a708f8fSGustavo F. Padovan { 22050952a57aSAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 22060a708f8fSGustavo F. Padovan struct sk_buff **frag; 220790338947SGustavo Padovan int sent = 0; 22080a708f8fSGustavo F. Padovan 22090a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) 22100a708f8fSGustavo F. Padovan return -EFAULT; 22110a708f8fSGustavo F. Padovan 22120a708f8fSGustavo F. Padovan sent += count; 22130a708f8fSGustavo F. Padovan len -= count; 22140a708f8fSGustavo F. Padovan 22150a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 22160a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 22170a708f8fSGustavo F. Padovan while (len) { 2218fbe00700SGustavo Padovan struct sk_buff *tmp; 2219fbe00700SGustavo Padovan 22200a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 22210a708f8fSGustavo F. Padovan 2222fbe00700SGustavo Padovan tmp = chan->ops->alloc_skb(chan, count, 222390338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 2224fbe00700SGustavo Padovan if (IS_ERR(tmp)) 2225fbe00700SGustavo Padovan return PTR_ERR(tmp); 22262f7719ceSAndrei Emeltchenko 2227fbe00700SGustavo Padovan *frag = tmp; 2228fbe00700SGustavo Padovan 22290a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) 22300a708f8fSGustavo F. Padovan return -EFAULT; 22310a708f8fSGustavo F. Padovan 22325e59b791SLuiz Augusto von Dentz (*frag)->priority = skb->priority; 22335e59b791SLuiz Augusto von Dentz 22340a708f8fSGustavo F. Padovan sent += count; 22350a708f8fSGustavo F. Padovan len -= count; 22360a708f8fSGustavo F. Padovan 22372d0ed3d5SGustavo Padovan skb->len += (*frag)->len; 22382d0ed3d5SGustavo Padovan skb->data_len += (*frag)->len; 22392d0ed3d5SGustavo Padovan 22400a708f8fSGustavo F. Padovan frag = &(*frag)->next; 22410a708f8fSGustavo F. Padovan } 22420a708f8fSGustavo F. Padovan 22430a708f8fSGustavo F. Padovan return sent; 22440a708f8fSGustavo F. Padovan } 22450a708f8fSGustavo F. Padovan 22465e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, 22475e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 22485e59b791SLuiz Augusto von Dentz u32 priority) 22490a708f8fSGustavo F. Padovan { 22508c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 22510a708f8fSGustavo F. Padovan struct sk_buff *skb; 225203a51213SAndrei Emeltchenko int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; 22530a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 22540a708f8fSGustavo F. Padovan 225543b1b8dfSMarcel Holtmann BT_DBG("chan %p psm 0x%2.2x len %zu priority %u", chan, 225643b1b8dfSMarcel Holtmann __le16_to_cpu(chan->psm), len, priority); 22570a708f8fSGustavo F. Padovan 22580a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 22592f7719ceSAndrei Emeltchenko 22602f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 226190338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 226290338947SGustavo Padovan if (IS_ERR(skb)) 226390338947SGustavo Padovan return skb; 22640a708f8fSGustavo F. Padovan 22655e59b791SLuiz Augusto von Dentz skb->priority = priority; 22665e59b791SLuiz Augusto von Dentz 22670a708f8fSGustavo F. Padovan /* Create L2CAP header */ 22680a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2269fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 2270daf6a78cSAndrei Emeltchenko lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); 227143b1b8dfSMarcel Holtmann put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE)); 22720a708f8fSGustavo F. Padovan 22730952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 22740a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 22750a708f8fSGustavo F. Padovan kfree_skb(skb); 22760a708f8fSGustavo F. Padovan return ERR_PTR(err); 22770a708f8fSGustavo F. Padovan } 22780a708f8fSGustavo F. Padovan return skb; 22790a708f8fSGustavo F. Padovan } 22800a708f8fSGustavo F. Padovan 22815e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, 22825e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 22835e59b791SLuiz Augusto von Dentz u32 priority) 22840a708f8fSGustavo F. Padovan { 22858c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 22860a708f8fSGustavo F. Padovan struct sk_buff *skb; 2287f2ba7faeSGustavo Padovan int err, count; 22880a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 22890a708f8fSGustavo F. Padovan 2290b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 22910a708f8fSGustavo F. Padovan 2292f2ba7faeSGustavo Padovan count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); 22932f7719ceSAndrei Emeltchenko 2294f2ba7faeSGustavo Padovan skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE, 229590338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 229690338947SGustavo Padovan if (IS_ERR(skb)) 229790338947SGustavo Padovan return skb; 22980a708f8fSGustavo F. Padovan 22995e59b791SLuiz Augusto von Dentz skb->priority = priority; 23005e59b791SLuiz Augusto von Dentz 23010a708f8fSGustavo F. Padovan /* Create L2CAP header */ 23020a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2303fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 23046ff9b5efSGustavo Padovan lh->len = cpu_to_le16(len); 23050a708f8fSGustavo F. Padovan 23060952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 23070a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 23080a708f8fSGustavo F. Padovan kfree_skb(skb); 23090a708f8fSGustavo F. Padovan return ERR_PTR(err); 23100a708f8fSGustavo F. Padovan } 23110a708f8fSGustavo F. Padovan return skb; 23120a708f8fSGustavo F. Padovan } 23130a708f8fSGustavo F. Padovan 2314ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, 2315ab0ff76dSLuiz Augusto von Dentz struct msghdr *msg, size_t len, 231694122bbeSMat Martineau u16 sdulen) 23170a708f8fSGustavo F. Padovan { 23188c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 23190a708f8fSGustavo F. Padovan struct sk_buff *skb; 2320e4ca6d98SAndrei Emeltchenko int err, count, hlen; 23210a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 23220a708f8fSGustavo F. Padovan 2323b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 23240a708f8fSGustavo F. Padovan 23250a708f8fSGustavo F. Padovan if (!conn) 23260a708f8fSGustavo F. Padovan return ERR_PTR(-ENOTCONN); 23270a708f8fSGustavo F. Padovan 2328ba7aa64fSGustavo Padovan hlen = __ertm_hdr_size(chan); 2329e4ca6d98SAndrei Emeltchenko 23300a708f8fSGustavo F. Padovan if (sdulen) 233103a51213SAndrei Emeltchenko hlen += L2CAP_SDULEN_SIZE; 23320a708f8fSGustavo F. Padovan 233347d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 233403a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 23350a708f8fSGustavo F. Padovan 23360a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 23372f7719ceSAndrei Emeltchenko 23382f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 233990338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 234090338947SGustavo Padovan if (IS_ERR(skb)) 234190338947SGustavo Padovan return skb; 23420a708f8fSGustavo F. Padovan 23430a708f8fSGustavo F. Padovan /* Create L2CAP header */ 23440a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2345fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 23460a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 234788843ab0SAndrei Emeltchenko 234818a48e76SMat Martineau /* Control header is populated later */ 234918a48e76SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 235018a48e76SMat Martineau put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 235118a48e76SMat Martineau else 235218a48e76SMat Martineau put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 235388843ab0SAndrei Emeltchenko 23540a708f8fSGustavo F. Padovan if (sdulen) 235503a51213SAndrei Emeltchenko put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 23560a708f8fSGustavo F. Padovan 23570952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 23580a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 23590a708f8fSGustavo F. Padovan kfree_skb(skb); 23600a708f8fSGustavo F. Padovan return ERR_PTR(err); 23610a708f8fSGustavo F. Padovan } 23620a708f8fSGustavo F. Padovan 236318a48e76SMat Martineau bt_cb(skb)->control.fcs = chan->fcs; 23643ce3514fSMat Martineau bt_cb(skb)->control.retries = 0; 23650a708f8fSGustavo F. Padovan return skb; 23660a708f8fSGustavo F. Padovan } 23670a708f8fSGustavo F. Padovan 236894122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan, 236994122bbeSMat Martineau struct sk_buff_head *seg_queue, 237094122bbeSMat Martineau struct msghdr *msg, size_t len) 23710a708f8fSGustavo F. Padovan { 23720a708f8fSGustavo F. Padovan struct sk_buff *skb; 237394122bbeSMat Martineau u16 sdu_len; 237494122bbeSMat Martineau size_t pdu_len; 237594122bbeSMat Martineau u8 sar; 23760a708f8fSGustavo F. Padovan 2377b4400672SAndrei Emeltchenko BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); 23780a708f8fSGustavo F. Padovan 237994122bbeSMat Martineau /* It is critical that ERTM PDUs fit in a single HCI fragment, 238094122bbeSMat Martineau * so fragmented skbs are not used. The HCI layer's handling 238194122bbeSMat Martineau * of fragmented skbs is not compatible with ERTM's queueing. 238294122bbeSMat Martineau */ 238394122bbeSMat Martineau 238494122bbeSMat Martineau /* PDU size is derived from the HCI MTU */ 238594122bbeSMat Martineau pdu_len = chan->conn->mtu; 238694122bbeSMat Martineau 2387a549574dSMat Martineau /* Constrain PDU size for BR/EDR connections */ 2388a549574dSMat Martineau if (!chan->hs_hcon) 238994122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); 239094122bbeSMat Martineau 239194122bbeSMat Martineau /* Adjust for largest possible L2CAP overhead. */ 239235d401dfSGustavo Padovan if (chan->fcs) 239335d401dfSGustavo Padovan pdu_len -= L2CAP_FCS_SIZE; 239435d401dfSGustavo Padovan 2395ba7aa64fSGustavo Padovan pdu_len -= __ertm_hdr_size(chan); 239694122bbeSMat Martineau 239794122bbeSMat Martineau /* Remote device may have requested smaller PDUs */ 239894122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, chan->remote_mps); 239994122bbeSMat Martineau 240094122bbeSMat Martineau if (len <= pdu_len) { 240194122bbeSMat Martineau sar = L2CAP_SAR_UNSEGMENTED; 240294122bbeSMat Martineau sdu_len = 0; 240394122bbeSMat Martineau pdu_len = len; 240494122bbeSMat Martineau } else { 240594122bbeSMat Martineau sar = L2CAP_SAR_START; 240694122bbeSMat Martineau sdu_len = len; 240794122bbeSMat Martineau pdu_len -= L2CAP_SDULEN_SIZE; 240894122bbeSMat Martineau } 24090a708f8fSGustavo F. Padovan 24100a708f8fSGustavo F. Padovan while (len > 0) { 241194122bbeSMat Martineau skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len); 24120a708f8fSGustavo F. Padovan 24130a708f8fSGustavo F. Padovan if (IS_ERR(skb)) { 241494122bbeSMat Martineau __skb_queue_purge(seg_queue); 24150a708f8fSGustavo F. Padovan return PTR_ERR(skb); 24160a708f8fSGustavo F. Padovan } 24170a708f8fSGustavo F. Padovan 241894122bbeSMat Martineau bt_cb(skb)->control.sar = sar; 241994122bbeSMat Martineau __skb_queue_tail(seg_queue, skb); 24200a708f8fSGustavo F. Padovan 242194122bbeSMat Martineau len -= pdu_len; 242294122bbeSMat Martineau if (sdu_len) { 242394122bbeSMat Martineau sdu_len = 0; 242494122bbeSMat Martineau pdu_len += L2CAP_SDULEN_SIZE; 242594122bbeSMat Martineau } 242694122bbeSMat Martineau 242794122bbeSMat Martineau if (len <= pdu_len) { 242894122bbeSMat Martineau sar = L2CAP_SAR_END; 242994122bbeSMat Martineau pdu_len = len; 243094122bbeSMat Martineau } else { 243194122bbeSMat Martineau sar = L2CAP_SAR_CONTINUE; 243294122bbeSMat Martineau } 243394122bbeSMat Martineau } 243494122bbeSMat Martineau 2435f0f62799SGustavo Padovan return 0; 24360a708f8fSGustavo F. Padovan } 24370a708f8fSGustavo F. Padovan 24385e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, 24395e59b791SLuiz Augusto von Dentz u32 priority) 24409a91a04aSGustavo F. Padovan { 24419a91a04aSGustavo F. Padovan struct sk_buff *skb; 24429a91a04aSGustavo F. Padovan int err; 244394122bbeSMat Martineau struct sk_buff_head seg_queue; 24449a91a04aSGustavo F. Padovan 24459a91a04aSGustavo F. Padovan /* Connectionless channel */ 2446715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { 24475e59b791SLuiz Augusto von Dentz skb = l2cap_create_connless_pdu(chan, msg, len, priority); 24489a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 24499a91a04aSGustavo F. Padovan return PTR_ERR(skb); 24509a91a04aSGustavo F. Padovan 24519a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 24529a91a04aSGustavo F. Padovan return len; 24539a91a04aSGustavo F. Padovan } 24549a91a04aSGustavo F. Padovan 24559a91a04aSGustavo F. Padovan switch (chan->mode) { 24569a91a04aSGustavo F. Padovan case L2CAP_MODE_BASIC: 24579a91a04aSGustavo F. Padovan /* Check outgoing MTU */ 24589a91a04aSGustavo F. Padovan if (len > chan->omtu) 24599a91a04aSGustavo F. Padovan return -EMSGSIZE; 24609a91a04aSGustavo F. Padovan 24619a91a04aSGustavo F. Padovan /* Create a basic PDU */ 24625e59b791SLuiz Augusto von Dentz skb = l2cap_create_basic_pdu(chan, msg, len, priority); 24639a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 24649a91a04aSGustavo F. Padovan return PTR_ERR(skb); 24659a91a04aSGustavo F. Padovan 24669a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 24679a91a04aSGustavo F. Padovan err = len; 24689a91a04aSGustavo F. Padovan break; 24699a91a04aSGustavo F. Padovan 24709a91a04aSGustavo F. Padovan case L2CAP_MODE_ERTM: 24719a91a04aSGustavo F. Padovan case L2CAP_MODE_STREAMING: 247294122bbeSMat Martineau /* Check outgoing MTU */ 247394122bbeSMat Martineau if (len > chan->omtu) { 247494122bbeSMat Martineau err = -EMSGSIZE; 24759a91a04aSGustavo F. Padovan break; 24769a91a04aSGustavo F. Padovan } 24779a91a04aSGustavo F. Padovan 247894122bbeSMat Martineau __skb_queue_head_init(&seg_queue); 247994122bbeSMat Martineau 248094122bbeSMat Martineau /* Do segmentation before calling in to the state machine, 248194122bbeSMat Martineau * since it's possible to block while waiting for memory 248294122bbeSMat Martineau * allocation. 248394122bbeSMat Martineau */ 248494122bbeSMat Martineau err = l2cap_segment_sdu(chan, &seg_queue, msg, len); 248594122bbeSMat Martineau 248694122bbeSMat Martineau /* The channel could have been closed while segmenting, 248794122bbeSMat Martineau * check that it is still connected. 248894122bbeSMat Martineau */ 248994122bbeSMat Martineau if (chan->state != BT_CONNECTED) { 249094122bbeSMat Martineau __skb_queue_purge(&seg_queue); 249194122bbeSMat Martineau err = -ENOTCONN; 24929a91a04aSGustavo F. Padovan } 24939a91a04aSGustavo F. Padovan 249494122bbeSMat Martineau if (err) 249594122bbeSMat Martineau break; 249694122bbeSMat Martineau 24973733937dSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) 2498d660366dSGustavo Padovan l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST); 24993733937dSMat Martineau else 2500d660366dSGustavo Padovan l2cap_streaming_send(chan, &seg_queue); 250194122bbeSMat Martineau 25029a91a04aSGustavo F. Padovan err = len; 25039a91a04aSGustavo F. Padovan 250494122bbeSMat Martineau /* If the skbs were not queued for sending, they'll still be in 250594122bbeSMat Martineau * seg_queue and need to be purged. 250694122bbeSMat Martineau */ 250794122bbeSMat Martineau __skb_queue_purge(&seg_queue); 25089a91a04aSGustavo F. Padovan break; 25099a91a04aSGustavo F. Padovan 25109a91a04aSGustavo F. Padovan default: 25119a91a04aSGustavo F. Padovan BT_DBG("bad state %1.1x", chan->mode); 25129a91a04aSGustavo F. Padovan err = -EBADFD; 25139a91a04aSGustavo F. Padovan } 25149a91a04aSGustavo F. Padovan 25159a91a04aSGustavo F. Padovan return err; 25169a91a04aSGustavo F. Padovan } 25179a91a04aSGustavo F. Padovan 2518d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq) 2519d2a7ac5dSMat Martineau { 2520bed68bdeSMat Martineau struct l2cap_ctrl control; 2521bed68bdeSMat Martineau u16 seq; 2522bed68bdeSMat Martineau 2523b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2524bed68bdeSMat Martineau 2525bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2526bed68bdeSMat Martineau control.sframe = 1; 2527bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2528bed68bdeSMat Martineau 2529bed68bdeSMat Martineau for (seq = chan->expected_tx_seq; seq != txseq; 2530bed68bdeSMat Martineau seq = __next_seq(chan, seq)) { 2531bed68bdeSMat Martineau if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) { 2532bed68bdeSMat Martineau control.reqseq = seq; 2533bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2534bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2535bed68bdeSMat Martineau } 2536bed68bdeSMat Martineau } 2537bed68bdeSMat Martineau 2538bed68bdeSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 2539d2a7ac5dSMat Martineau } 2540d2a7ac5dSMat Martineau 2541d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan) 2542d2a7ac5dSMat Martineau { 2543bed68bdeSMat Martineau struct l2cap_ctrl control; 2544bed68bdeSMat Martineau 2545bed68bdeSMat Martineau BT_DBG("chan %p", chan); 2546bed68bdeSMat Martineau 2547bed68bdeSMat Martineau if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR) 2548bed68bdeSMat Martineau return; 2549bed68bdeSMat Martineau 2550bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2551bed68bdeSMat Martineau control.sframe = 1; 2552bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2553bed68bdeSMat Martineau control.reqseq = chan->srej_list.tail; 2554bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2555d2a7ac5dSMat Martineau } 2556d2a7ac5dSMat Martineau 2557d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq) 2558d2a7ac5dSMat Martineau { 2559bed68bdeSMat Martineau struct l2cap_ctrl control; 2560bed68bdeSMat Martineau u16 initial_head; 2561bed68bdeSMat Martineau u16 seq; 2562bed68bdeSMat Martineau 2563b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2564bed68bdeSMat Martineau 2565bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2566bed68bdeSMat Martineau control.sframe = 1; 2567bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2568bed68bdeSMat Martineau 2569bed68bdeSMat Martineau /* Capture initial list head to allow only one pass through the list. */ 2570bed68bdeSMat Martineau initial_head = chan->srej_list.head; 2571bed68bdeSMat Martineau 2572bed68bdeSMat Martineau do { 2573bed68bdeSMat Martineau seq = l2cap_seq_list_pop(&chan->srej_list); 2574bed68bdeSMat Martineau if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR) 2575bed68bdeSMat Martineau break; 2576bed68bdeSMat Martineau 2577bed68bdeSMat Martineau control.reqseq = seq; 2578bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2579bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2580bed68bdeSMat Martineau } while (chan->srej_list.head != initial_head); 2581d2a7ac5dSMat Martineau } 2582d2a7ac5dSMat Martineau 2583608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq) 2584608bcc6dSMat Martineau { 2585608bcc6dSMat Martineau struct sk_buff *acked_skb; 2586608bcc6dSMat Martineau u16 ackseq; 2587608bcc6dSMat Martineau 2588b4400672SAndrei Emeltchenko BT_DBG("chan %p, reqseq %u", chan, reqseq); 2589608bcc6dSMat Martineau 2590608bcc6dSMat Martineau if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq) 2591608bcc6dSMat Martineau return; 2592608bcc6dSMat Martineau 2593b4400672SAndrei Emeltchenko BT_DBG("expected_ack_seq %u, unacked_frames %u", 2594608bcc6dSMat Martineau chan->expected_ack_seq, chan->unacked_frames); 2595608bcc6dSMat Martineau 2596608bcc6dSMat Martineau for (ackseq = chan->expected_ack_seq; ackseq != reqseq; 2597608bcc6dSMat Martineau ackseq = __next_seq(chan, ackseq)) { 2598608bcc6dSMat Martineau 2599608bcc6dSMat Martineau acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq); 2600608bcc6dSMat Martineau if (acked_skb) { 2601608bcc6dSMat Martineau skb_unlink(acked_skb, &chan->tx_q); 2602608bcc6dSMat Martineau kfree_skb(acked_skb); 2603608bcc6dSMat Martineau chan->unacked_frames--; 2604608bcc6dSMat Martineau } 2605608bcc6dSMat Martineau } 2606608bcc6dSMat Martineau 2607608bcc6dSMat Martineau chan->expected_ack_seq = reqseq; 2608608bcc6dSMat Martineau 2609608bcc6dSMat Martineau if (chan->unacked_frames == 0) 2610608bcc6dSMat Martineau __clear_retrans_timer(chan); 2611608bcc6dSMat Martineau 2612b4400672SAndrei Emeltchenko BT_DBG("unacked_frames %u", chan->unacked_frames); 2613608bcc6dSMat Martineau } 2614608bcc6dSMat Martineau 2615608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan) 2616608bcc6dSMat Martineau { 2617608bcc6dSMat Martineau BT_DBG("chan %p", chan); 2618608bcc6dSMat Martineau 2619608bcc6dSMat Martineau chan->expected_tx_seq = chan->buffer_seq; 2620608bcc6dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 2621608bcc6dSMat Martineau skb_queue_purge(&chan->srej_q); 2622608bcc6dSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2623608bcc6dSMat Martineau } 2624608bcc6dSMat Martineau 2625d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan, 2626608bcc6dSMat Martineau struct l2cap_ctrl *control, 2627608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2628608bcc6dSMat Martineau { 2629608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2630608bcc6dSMat Martineau event); 2631608bcc6dSMat Martineau 2632608bcc6dSMat Martineau switch (event) { 2633608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2634608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2635608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2636608bcc6dSMat Martineau 2637608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2638608bcc6dSMat Martineau l2cap_ertm_send(chan); 2639608bcc6dSMat Martineau break; 2640608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2641608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2642608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2643608bcc6dSMat Martineau 2644608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2645608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2646608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2647608bcc6dSMat Martineau */ 2648608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2649608bcc6dSMat Martineau } 2650608bcc6dSMat Martineau 2651608bcc6dSMat Martineau l2cap_send_ack(chan); 2652608bcc6dSMat Martineau 2653608bcc6dSMat Martineau break; 2654608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2655608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2656608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2657608bcc6dSMat Martineau 2658608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2659608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2660608bcc6dSMat Martineau 2661608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2662608bcc6dSMat Martineau local_control.sframe = 1; 2663608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2664608bcc6dSMat Martineau local_control.poll = 1; 2665608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2666a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2667608bcc6dSMat Martineau 2668608bcc6dSMat Martineau chan->retry_count = 1; 2669608bcc6dSMat Martineau __set_monitor_timer(chan); 2670608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2671608bcc6dSMat Martineau } 2672608bcc6dSMat Martineau break; 2673608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2674608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2675608bcc6dSMat Martineau break; 2676608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2677608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2678608bcc6dSMat Martineau chan->retry_count = 1; 2679608bcc6dSMat Martineau __set_monitor_timer(chan); 2680608bcc6dSMat Martineau __clear_ack_timer(chan); 2681608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2682608bcc6dSMat Martineau break; 2683608bcc6dSMat Martineau case L2CAP_EV_RETRANS_TO: 2684608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2685608bcc6dSMat Martineau chan->retry_count = 1; 2686608bcc6dSMat Martineau __set_monitor_timer(chan); 2687608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2688608bcc6dSMat Martineau break; 2689608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2690608bcc6dSMat Martineau /* Nothing to process */ 2691608bcc6dSMat Martineau break; 2692608bcc6dSMat Martineau default: 2693608bcc6dSMat Martineau break; 2694608bcc6dSMat Martineau } 2695608bcc6dSMat Martineau } 2696608bcc6dSMat Martineau 2697d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan, 2698608bcc6dSMat Martineau struct l2cap_ctrl *control, 2699608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2700608bcc6dSMat Martineau { 2701608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2702608bcc6dSMat Martineau event); 2703608bcc6dSMat Martineau 2704608bcc6dSMat Martineau switch (event) { 2705608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2706608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2707608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2708608bcc6dSMat Martineau /* Queue data, but don't send. */ 2709608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2710608bcc6dSMat Martineau break; 2711608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2712608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2713608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2714608bcc6dSMat Martineau 2715608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2716608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2717608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2718608bcc6dSMat Martineau */ 2719608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2720608bcc6dSMat Martineau } 2721608bcc6dSMat Martineau 2722608bcc6dSMat Martineau l2cap_send_ack(chan); 2723608bcc6dSMat Martineau 2724608bcc6dSMat Martineau break; 2725608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2726608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2727608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2728608bcc6dSMat Martineau 2729608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2730608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2731608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2732608bcc6dSMat Martineau local_control.sframe = 1; 2733608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2734608bcc6dSMat Martineau local_control.poll = 1; 2735608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2736a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2737608bcc6dSMat Martineau 2738608bcc6dSMat Martineau chan->retry_count = 1; 2739608bcc6dSMat Martineau __set_monitor_timer(chan); 2740608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2741608bcc6dSMat Martineau } 2742608bcc6dSMat Martineau break; 2743608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2744608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2745608bcc6dSMat Martineau 2746608bcc6dSMat Martineau /* Fall through */ 2747608bcc6dSMat Martineau 2748608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2749608bcc6dSMat Martineau if (control && control->final) { 2750608bcc6dSMat Martineau __clear_monitor_timer(chan); 2751608bcc6dSMat Martineau if (chan->unacked_frames > 0) 2752608bcc6dSMat Martineau __set_retrans_timer(chan); 2753608bcc6dSMat Martineau chan->retry_count = 0; 2754608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 2755608bcc6dSMat Martineau BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state); 2756608bcc6dSMat Martineau } 2757608bcc6dSMat Martineau break; 2758608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2759608bcc6dSMat Martineau /* Ignore */ 2760608bcc6dSMat Martineau break; 2761608bcc6dSMat Martineau case L2CAP_EV_MONITOR_TO: 2762608bcc6dSMat Martineau if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) { 2763608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2764608bcc6dSMat Martineau __set_monitor_timer(chan); 2765608bcc6dSMat Martineau chan->retry_count++; 2766608bcc6dSMat Martineau } else { 27675e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNABORTED); 2768608bcc6dSMat Martineau } 2769608bcc6dSMat Martineau break; 2770608bcc6dSMat Martineau default: 2771608bcc6dSMat Martineau break; 2772608bcc6dSMat Martineau } 2773608bcc6dSMat Martineau } 2774608bcc6dSMat Martineau 2775d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 2776608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2777608bcc6dSMat Martineau { 2778608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d, state %d", 2779608bcc6dSMat Martineau chan, control, skbs, event, chan->tx_state); 2780608bcc6dSMat Martineau 2781608bcc6dSMat Martineau switch (chan->tx_state) { 2782608bcc6dSMat Martineau case L2CAP_TX_STATE_XMIT: 2783d660366dSGustavo Padovan l2cap_tx_state_xmit(chan, control, skbs, event); 2784608bcc6dSMat Martineau break; 2785608bcc6dSMat Martineau case L2CAP_TX_STATE_WAIT_F: 2786d660366dSGustavo Padovan l2cap_tx_state_wait_f(chan, control, skbs, event); 2787608bcc6dSMat Martineau break; 2788608bcc6dSMat Martineau default: 2789608bcc6dSMat Martineau /* Ignore event */ 2790608bcc6dSMat Martineau break; 2791608bcc6dSMat Martineau } 2792608bcc6dSMat Martineau } 2793608bcc6dSMat Martineau 27944b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan, 27954b51dae9SMat Martineau struct l2cap_ctrl *control) 27964b51dae9SMat Martineau { 27974b51dae9SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2798401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT); 27994b51dae9SMat Martineau } 28004b51dae9SMat Martineau 2801f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan, 2802f80842a8SMat Martineau struct l2cap_ctrl *control) 2803f80842a8SMat Martineau { 2804f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2805401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT); 2806f80842a8SMat Martineau } 2807f80842a8SMat Martineau 28080a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */ 28090a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 28100a708f8fSGustavo F. Padovan { 28110a708f8fSGustavo F. Padovan struct sk_buff *nskb; 281248454079SGustavo F. Padovan struct l2cap_chan *chan; 28130a708f8fSGustavo F. Padovan 28140a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 28150a708f8fSGustavo F. Padovan 28163df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 28173d57dc68SGustavo F. Padovan 28183df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 281948454079SGustavo F. Padovan struct sock *sk = chan->sk; 2820715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW) 28210a708f8fSGustavo F. Padovan continue; 28220a708f8fSGustavo F. Padovan 28230a708f8fSGustavo F. Padovan /* Don't send frame to the socket it came from */ 28240a708f8fSGustavo F. Padovan if (skb->sk == sk) 28250a708f8fSGustavo F. Padovan continue; 28268bcde1f2SGustavo Padovan nskb = skb_clone(skb, GFP_KERNEL); 28270a708f8fSGustavo F. Padovan if (!nskb) 28280a708f8fSGustavo F. Padovan continue; 28290a708f8fSGustavo F. Padovan 283080b98027SGustavo Padovan if (chan->ops->recv(chan, nskb)) 28310a708f8fSGustavo F. Padovan kfree_skb(nskb); 28320a708f8fSGustavo F. Padovan } 28333d57dc68SGustavo F. Padovan 28343df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 28350a708f8fSGustavo F. Padovan } 28360a708f8fSGustavo F. Padovan 28370a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */ 2838b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, 2839b4400672SAndrei Emeltchenko u8 ident, u16 dlen, void *data) 28400a708f8fSGustavo F. Padovan { 28410a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag; 28420a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd; 28430a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 28440a708f8fSGustavo F. Padovan int len, count; 28450a708f8fSGustavo F. Padovan 2846b4400672SAndrei Emeltchenko BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u", 28470a708f8fSGustavo F. Padovan conn, code, ident, dlen); 28480a708f8fSGustavo F. Padovan 2849300b962eSAnderson Lizardo if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE) 2850300b962eSAnderson Lizardo return NULL; 2851300b962eSAnderson Lizardo 28520a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; 28530a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 28540a708f8fSGustavo F. Padovan 28558bcde1f2SGustavo Padovan skb = bt_skb_alloc(count, GFP_KERNEL); 28560a708f8fSGustavo F. Padovan if (!skb) 28570a708f8fSGustavo F. Padovan return NULL; 28580a708f8fSGustavo F. Padovan 28590a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 28600a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); 28613300d9a9SClaudio Takahasi 28623300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 2863ac73498cSAndrei Emeltchenko lh->cid = __constant_cpu_to_le16(L2CAP_CID_LE_SIGNALING); 28643300d9a9SClaudio Takahasi else 2865ac73498cSAndrei Emeltchenko lh->cid = __constant_cpu_to_le16(L2CAP_CID_SIGNALING); 28660a708f8fSGustavo F. Padovan 28670a708f8fSGustavo F. Padovan cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); 28680a708f8fSGustavo F. Padovan cmd->code = code; 28690a708f8fSGustavo F. Padovan cmd->ident = ident; 28700a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen); 28710a708f8fSGustavo F. Padovan 28720a708f8fSGustavo F. Padovan if (dlen) { 28730a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE; 28740a708f8fSGustavo F. Padovan memcpy(skb_put(skb, count), data, count); 28750a708f8fSGustavo F. Padovan data += count; 28760a708f8fSGustavo F. Padovan } 28770a708f8fSGustavo F. Padovan 28780a708f8fSGustavo F. Padovan len -= skb->len; 28790a708f8fSGustavo F. Padovan 28800a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 28810a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 28820a708f8fSGustavo F. Padovan while (len) { 28830a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 28840a708f8fSGustavo F. Padovan 28858bcde1f2SGustavo Padovan *frag = bt_skb_alloc(count, GFP_KERNEL); 28860a708f8fSGustavo F. Padovan if (!*frag) 28870a708f8fSGustavo F. Padovan goto fail; 28880a708f8fSGustavo F. Padovan 28890a708f8fSGustavo F. Padovan memcpy(skb_put(*frag, count), data, count); 28900a708f8fSGustavo F. Padovan 28910a708f8fSGustavo F. Padovan len -= count; 28920a708f8fSGustavo F. Padovan data += count; 28930a708f8fSGustavo F. Padovan 28940a708f8fSGustavo F. Padovan frag = &(*frag)->next; 28950a708f8fSGustavo F. Padovan } 28960a708f8fSGustavo F. Padovan 28970a708f8fSGustavo F. Padovan return skb; 28980a708f8fSGustavo F. Padovan 28990a708f8fSGustavo F. Padovan fail: 29000a708f8fSGustavo F. Padovan kfree_skb(skb); 29010a708f8fSGustavo F. Padovan return NULL; 29020a708f8fSGustavo F. Padovan } 29030a708f8fSGustavo F. Padovan 29042d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, 29052d792818SGustavo Padovan unsigned long *val) 29060a708f8fSGustavo F. Padovan { 29070a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 29080a708f8fSGustavo F. Padovan int len; 29090a708f8fSGustavo F. Padovan 29100a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len; 29110a708f8fSGustavo F. Padovan *ptr += len; 29120a708f8fSGustavo F. Padovan 29130a708f8fSGustavo F. Padovan *type = opt->type; 29140a708f8fSGustavo F. Padovan *olen = opt->len; 29150a708f8fSGustavo F. Padovan 29160a708f8fSGustavo F. Padovan switch (opt->len) { 29170a708f8fSGustavo F. Padovan case 1: 29180a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val); 29190a708f8fSGustavo F. Padovan break; 29200a708f8fSGustavo F. Padovan 29210a708f8fSGustavo F. Padovan case 2: 29220a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val); 29230a708f8fSGustavo F. Padovan break; 29240a708f8fSGustavo F. Padovan 29250a708f8fSGustavo F. Padovan case 4: 29260a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val); 29270a708f8fSGustavo F. Padovan break; 29280a708f8fSGustavo F. Padovan 29290a708f8fSGustavo F. Padovan default: 29300a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val; 29310a708f8fSGustavo F. Padovan break; 29320a708f8fSGustavo F. Padovan } 29330a708f8fSGustavo F. Padovan 2934b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val); 29350a708f8fSGustavo F. Padovan return len; 29360a708f8fSGustavo F. Padovan } 29370a708f8fSGustavo F. Padovan 29380a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) 29390a708f8fSGustavo F. Padovan { 29400a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 29410a708f8fSGustavo F. Padovan 2942b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val); 29430a708f8fSGustavo F. Padovan 29440a708f8fSGustavo F. Padovan opt->type = type; 29450a708f8fSGustavo F. Padovan opt->len = len; 29460a708f8fSGustavo F. Padovan 29470a708f8fSGustavo F. Padovan switch (len) { 29480a708f8fSGustavo F. Padovan case 1: 29490a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val; 29500a708f8fSGustavo F. Padovan break; 29510a708f8fSGustavo F. Padovan 29520a708f8fSGustavo F. Padovan case 2: 29530a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val); 29540a708f8fSGustavo F. Padovan break; 29550a708f8fSGustavo F. Padovan 29560a708f8fSGustavo F. Padovan case 4: 29570a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val); 29580a708f8fSGustavo F. Padovan break; 29590a708f8fSGustavo F. Padovan 29600a708f8fSGustavo F. Padovan default: 29610a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len); 29620a708f8fSGustavo F. Padovan break; 29630a708f8fSGustavo F. Padovan } 29640a708f8fSGustavo F. Padovan 29650a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len; 29660a708f8fSGustavo F. Padovan } 29670a708f8fSGustavo F. Padovan 2968f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) 2969f89cef09SAndrei Emeltchenko { 2970f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs; 2971f89cef09SAndrei Emeltchenko 2972f89cef09SAndrei Emeltchenko switch (chan->mode) { 2973f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM: 2974f89cef09SAndrei Emeltchenko efs.id = chan->local_id; 2975f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype; 2976f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 2977f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 2978ac73498cSAndrei Emeltchenko efs.acc_lat = __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); 29798936fa6dSAndrei Emeltchenko efs.flush_to = __constant_cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO); 2980f89cef09SAndrei Emeltchenko break; 2981f89cef09SAndrei Emeltchenko 2982f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING: 2983f89cef09SAndrei Emeltchenko efs.id = 1; 2984f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT; 2985f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 2986f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 2987f89cef09SAndrei Emeltchenko efs.acc_lat = 0; 2988f89cef09SAndrei Emeltchenko efs.flush_to = 0; 2989f89cef09SAndrei Emeltchenko break; 2990f89cef09SAndrei Emeltchenko 2991f89cef09SAndrei Emeltchenko default: 2992f89cef09SAndrei Emeltchenko return; 2993f89cef09SAndrei Emeltchenko } 2994f89cef09SAndrei Emeltchenko 2995f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), 2996f89cef09SAndrei Emeltchenko (unsigned long) &efs); 2997f89cef09SAndrei Emeltchenko } 2998f89cef09SAndrei Emeltchenko 2999721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work) 30000a708f8fSGustavo F. Padovan { 3001721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 3002721c4181SGustavo F. Padovan ack_timer.work); 30030362520bSMat Martineau u16 frames_to_ack; 30040a708f8fSGustavo F. Padovan 30052fb9b3d4SGustavo F. Padovan BT_DBG("chan %p", chan); 30062fb9b3d4SGustavo F. Padovan 30076be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 30086be36555SAndrei Emeltchenko 30090362520bSMat Martineau frames_to_ack = __seq_offset(chan, chan->buffer_seq, 30100362520bSMat Martineau chan->last_acked_seq); 30110362520bSMat Martineau 30120362520bSMat Martineau if (frames_to_ack) 30130362520bSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 30146be36555SAndrei Emeltchenko 30156be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 301609bfb2eeSSzymon Janc l2cap_chan_put(chan); 30170a708f8fSGustavo F. Padovan } 30180a708f8fSGustavo F. Padovan 3019466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan) 30200a708f8fSGustavo F. Padovan { 30213c588192SMat Martineau int err; 30223c588192SMat Martineau 3023105bdf9eSMat Martineau chan->next_tx_seq = 0; 3024105bdf9eSMat Martineau chan->expected_tx_seq = 0; 302542e5c802SGustavo F. Padovan chan->expected_ack_seq = 0; 30266a026610SGustavo F. Padovan chan->unacked_frames = 0; 302742e5c802SGustavo F. Padovan chan->buffer_seq = 0; 30286a026610SGustavo F. Padovan chan->frames_sent = 0; 3029105bdf9eSMat Martineau chan->last_acked_seq = 0; 3030105bdf9eSMat Martineau chan->sdu = NULL; 3031105bdf9eSMat Martineau chan->sdu_last_frag = NULL; 3032105bdf9eSMat Martineau chan->sdu_len = 0; 3033105bdf9eSMat Martineau 3034d34c34fbSMat Martineau skb_queue_head_init(&chan->tx_q); 3035d34c34fbSMat Martineau 30366ed971caSMarcel Holtmann chan->local_amp_id = AMP_ID_BREDR; 30376ed971caSMarcel Holtmann chan->move_id = AMP_ID_BREDR; 303808333283SMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 303908333283SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 304008333283SMat Martineau 3041105bdf9eSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 3042105bdf9eSMat Martineau return 0; 3043105bdf9eSMat Martineau 3044105bdf9eSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 3045105bdf9eSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 30460a708f8fSGustavo F. Padovan 3047721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout); 3048721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout); 3049721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout); 30500a708f8fSGustavo F. Padovan 3051f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q); 30520a708f8fSGustavo F. Padovan 30533c588192SMat Martineau err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win); 30543c588192SMat Martineau if (err < 0) 30553c588192SMat Martineau return err; 30563c588192SMat Martineau 30579dc9affcSMat Martineau err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win); 30589dc9affcSMat Martineau if (err < 0) 30599dc9affcSMat Martineau l2cap_seq_list_free(&chan->srej_list); 30609dc9affcSMat Martineau 30619dc9affcSMat Martineau return err; 30620a708f8fSGustavo F. Padovan } 30630a708f8fSGustavo F. Padovan 30640a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) 30650a708f8fSGustavo F. Padovan { 30660a708f8fSGustavo F. Padovan switch (mode) { 30670a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 30680a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 30690a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask)) 30700a708f8fSGustavo F. Padovan return mode; 30710a708f8fSGustavo F. Padovan /* fall through */ 30720a708f8fSGustavo F. Padovan default: 30730a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC; 30740a708f8fSGustavo F. Padovan } 30750a708f8fSGustavo F. Padovan } 30760a708f8fSGustavo F. Padovan 3077848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn) 30786327eb98SAndrei Emeltchenko { 3079848566b3SMarcel Holtmann return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_WINDOW; 30806327eb98SAndrei Emeltchenko } 30816327eb98SAndrei Emeltchenko 3082848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn) 3083f89cef09SAndrei Emeltchenko { 3084848566b3SMarcel Holtmann return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_FLOW; 3085f89cef09SAndrei Emeltchenko } 3086f89cef09SAndrei Emeltchenko 308736c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan, 308836c86c85SMat Martineau struct l2cap_conf_rfc *rfc) 308936c86c85SMat Martineau { 30906ed971caSMarcel Holtmann if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) { 309136c86c85SMat Martineau u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to; 309236c86c85SMat Martineau 309336c86c85SMat Martineau /* Class 1 devices have must have ERTM timeouts 309436c86c85SMat Martineau * exceeding the Link Supervision Timeout. The 309536c86c85SMat Martineau * default Link Supervision Timeout for AMP 309636c86c85SMat Martineau * controllers is 10 seconds. 309736c86c85SMat Martineau * 309836c86c85SMat Martineau * Class 1 devices use 0xffffffff for their 309936c86c85SMat Martineau * best-effort flush timeout, so the clamping logic 310036c86c85SMat Martineau * will result in a timeout that meets the above 310136c86c85SMat Martineau * requirement. ERTM timeouts are 16-bit values, so 310236c86c85SMat Martineau * the maximum timeout is 65.535 seconds. 310336c86c85SMat Martineau */ 310436c86c85SMat Martineau 310536c86c85SMat Martineau /* Convert timeout to milliseconds and round */ 310636c86c85SMat Martineau ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000); 310736c86c85SMat Martineau 310836c86c85SMat Martineau /* This is the recommended formula for class 2 devices 310936c86c85SMat Martineau * that start ERTM timers when packets are sent to the 311036c86c85SMat Martineau * controller. 311136c86c85SMat Martineau */ 311236c86c85SMat Martineau ertm_to = 3 * ertm_to + 500; 311336c86c85SMat Martineau 311436c86c85SMat Martineau if (ertm_to > 0xffff) 311536c86c85SMat Martineau ertm_to = 0xffff; 311636c86c85SMat Martineau 311736c86c85SMat Martineau rfc->retrans_timeout = cpu_to_le16((u16) ertm_to); 311836c86c85SMat Martineau rfc->monitor_timeout = rfc->retrans_timeout; 311936c86c85SMat Martineau } else { 312036c86c85SMat Martineau rfc->retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 312136c86c85SMat Martineau rfc->monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 312236c86c85SMat Martineau } 312336c86c85SMat Martineau } 312436c86c85SMat Martineau 31256327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan) 31266327eb98SAndrei Emeltchenko { 31276327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && 3128848566b3SMarcel Holtmann __l2cap_ews_supported(chan->conn)) { 31296327eb98SAndrei Emeltchenko /* use extended control field */ 31306327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 3131836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 3132836be934SAndrei Emeltchenko } else { 31336327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win, 31346327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 3135836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 3136836be934SAndrei Emeltchenko } 3137c20f8e35SMat Martineau chan->ack_win = chan->tx_win; 31386327eb98SAndrei Emeltchenko } 31396327eb98SAndrei Emeltchenko 3140710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) 31410a708f8fSGustavo F. Padovan { 31420a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 31430c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode }; 31440a708f8fSGustavo F. Padovan void *ptr = req->data; 3145c8f79162SAndrei Emeltchenko u16 size; 31460a708f8fSGustavo F. Padovan 314749208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 31480a708f8fSGustavo F. Padovan 314973ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp) 31500a708f8fSGustavo F. Padovan goto done; 31510a708f8fSGustavo F. Padovan 31520c1bc5c6SGustavo F. Padovan switch (chan->mode) { 31530a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 31540a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3155c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) 31560a708f8fSGustavo F. Padovan break; 31570a708f8fSGustavo F. Padovan 3158848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn)) 3159f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 3160f89cef09SAndrei Emeltchenko 31610a708f8fSGustavo F. Padovan /* fall through */ 31620a708f8fSGustavo F. Padovan default: 31638c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); 31640a708f8fSGustavo F. Padovan break; 31650a708f8fSGustavo F. Padovan } 31660a708f8fSGustavo F. Padovan 31670a708f8fSGustavo F. Padovan done: 31680c1bc5c6SGustavo F. Padovan if (chan->imtu != L2CAP_DEFAULT_MTU) 31690c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 31700a708f8fSGustavo F. Padovan 31710c1bc5c6SGustavo F. Padovan switch (chan->mode) { 31720a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 31738c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && 31748c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) 31750a708f8fSGustavo F. Padovan break; 31760a708f8fSGustavo F. Padovan 31770a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC; 31780a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 31790a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 31800a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 31810a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 31820a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0; 31830a708f8fSGustavo F. Padovan 31840a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 31850a708f8fSGustavo F. Padovan (unsigned long) &rfc); 31860a708f8fSGustavo F. Padovan break; 31870a708f8fSGustavo F. Padovan 31880a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 31890a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM; 319047d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx; 319136c86c85SMat Martineau 319236c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc); 3193c8f79162SAndrei Emeltchenko 3194c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 31952d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - 3196c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3197c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 31980a708f8fSGustavo F. Padovan 31996327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan); 32006327eb98SAndrei Emeltchenko 32016327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win, 32026327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 32030a708f8fSGustavo F. Padovan 32040a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 32050a708f8fSGustavo F. Padovan (unsigned long) &rfc); 32060a708f8fSGustavo F. Padovan 3207f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 3208f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 3209f89cef09SAndrei Emeltchenko 32106327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 32116327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 32126327eb98SAndrei Emeltchenko chan->tx_win); 321360918918SAndrei Emeltchenko 321460918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS) 321560918918SAndrei Emeltchenko if (chan->fcs == L2CAP_FCS_NONE || 3216f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { 321760918918SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 321860918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, 321960918918SAndrei Emeltchenko chan->fcs); 322060918918SAndrei Emeltchenko } 32210a708f8fSGustavo F. Padovan break; 32220a708f8fSGustavo F. Padovan 32230a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3224273759e2SMat Martineau l2cap_txwin_setup(chan); 32250a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING; 32260a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 32270a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 32280a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 32290a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 3230c8f79162SAndrei Emeltchenko 3231c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 32322d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - 3233c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3234c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 32350a708f8fSGustavo F. Padovan 32360a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 32370a708f8fSGustavo F. Padovan (unsigned long) &rfc); 32380a708f8fSGustavo F. Padovan 3239f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 3240f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 3241f89cef09SAndrei Emeltchenko 324260918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS) 324347d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 3244f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { 324547d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 324660918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, 324760918918SAndrei Emeltchenko chan->fcs); 32480a708f8fSGustavo F. Padovan } 32490a708f8fSGustavo F. Padovan break; 32500a708f8fSGustavo F. Padovan } 32510a708f8fSGustavo F. Padovan 3252fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 325359e54bd1SAndrei Emeltchenko req->flags = __constant_cpu_to_le16(0); 32540a708f8fSGustavo F. Padovan 32550a708f8fSGustavo F. Padovan return ptr - data; 32560a708f8fSGustavo F. Padovan } 32570a708f8fSGustavo F. Padovan 325873ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) 32590a708f8fSGustavo F. Padovan { 32600a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 32610a708f8fSGustavo F. Padovan void *ptr = rsp->data; 326273ffa904SGustavo F. Padovan void *req = chan->conf_req; 326373ffa904SGustavo F. Padovan int len = chan->conf_len; 32640a708f8fSGustavo F. Padovan int type, hint, olen; 32650a708f8fSGustavo F. Padovan unsigned long val; 32660a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 326742dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs; 326842dceae2SAndrei Emeltchenko u8 remote_efs = 0; 32690a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU; 32700a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS; 3271c8f79162SAndrei Emeltchenko u16 size; 32720a708f8fSGustavo F. Padovan 327373ffa904SGustavo F. Padovan BT_DBG("chan %p", chan); 32740a708f8fSGustavo F. Padovan 32750a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 32760a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val); 32770a708f8fSGustavo F. Padovan 32780a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT; 32790a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK; 32800a708f8fSGustavo F. Padovan 32810a708f8fSGustavo F. Padovan switch (type) { 32820a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 32830a708f8fSGustavo F. Padovan mtu = val; 32840a708f8fSGustavo F. Padovan break; 32850a708f8fSGustavo F. Padovan 32860a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 32870c1bc5c6SGustavo F. Padovan chan->flush_to = val; 32880a708f8fSGustavo F. Padovan break; 32890a708f8fSGustavo F. Padovan 32900a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS: 32910a708f8fSGustavo F. Padovan break; 32920a708f8fSGustavo F. Padovan 32930a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 32940a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 32950a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen); 32960a708f8fSGustavo F. Padovan break; 32970a708f8fSGustavo F. Padovan 32980a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS: 32990a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE) 3300f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, &chan->conf_state); 330142dceae2SAndrei Emeltchenko break; 33020a708f8fSGustavo F. Padovan 330342dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS: 330442dceae2SAndrei Emeltchenko remote_efs = 1; 330542dceae2SAndrei Emeltchenko if (olen == sizeof(efs)) 330642dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen); 33070a708f8fSGustavo F. Padovan break; 33080a708f8fSGustavo F. Padovan 33096327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 3310848566b3SMarcel Holtmann if (!chan->conn->hs_enabled) 33116327eb98SAndrei Emeltchenko return -ECONNREFUSED; 33126327eb98SAndrei Emeltchenko 33136327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 33146327eb98SAndrei Emeltchenko set_bit(CONF_EWS_RECV, &chan->conf_state); 3315836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 33166327eb98SAndrei Emeltchenko chan->remote_tx_win = val; 33170a708f8fSGustavo F. Padovan break; 33180a708f8fSGustavo F. Padovan 33190a708f8fSGustavo F. Padovan default: 33200a708f8fSGustavo F. Padovan if (hint) 33210a708f8fSGustavo F. Padovan break; 33220a708f8fSGustavo F. Padovan 33230a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN; 33240a708f8fSGustavo F. Padovan *((u8 *) ptr++) = type; 33250a708f8fSGustavo F. Padovan break; 33260a708f8fSGustavo F. Padovan } 33270a708f8fSGustavo F. Padovan } 33280a708f8fSGustavo F. Padovan 332973ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1) 33300a708f8fSGustavo F. Padovan goto done; 33310a708f8fSGustavo F. Padovan 33320c1bc5c6SGustavo F. Padovan switch (chan->mode) { 33330a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 33340a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3335c1360a1cSGustavo F. Padovan if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { 33360c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, 33378c1d787bSGustavo F. Padovan chan->conn->feat_mask); 33380a708f8fSGustavo F. Padovan break; 33390a708f8fSGustavo F. Padovan } 33400a708f8fSGustavo F. Padovan 334142dceae2SAndrei Emeltchenko if (remote_efs) { 3342848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn)) 334342dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 334442dceae2SAndrei Emeltchenko else 334542dceae2SAndrei Emeltchenko return -ECONNREFUSED; 334642dceae2SAndrei Emeltchenko } 334742dceae2SAndrei Emeltchenko 33480c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) 33490a708f8fSGustavo F. Padovan return -ECONNREFUSED; 33500a708f8fSGustavo F. Padovan 33510a708f8fSGustavo F. Padovan break; 33520a708f8fSGustavo F. Padovan } 33530a708f8fSGustavo F. Padovan 33540a708f8fSGustavo F. Padovan done: 33550c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) { 33560a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 33570c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 33580a708f8fSGustavo F. Padovan 335973ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1) 33600a708f8fSGustavo F. Padovan return -ECONNREFUSED; 33610a708f8fSGustavo F. Padovan 33622d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 33632d792818SGustavo Padovan (unsigned long) &rfc); 33640a708f8fSGustavo F. Padovan } 33650a708f8fSGustavo F. Padovan 33660a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) { 33670a708f8fSGustavo F. Padovan /* Configure output options and let the other side know 33680a708f8fSGustavo F. Padovan * which ones we don't like. */ 33690a708f8fSGustavo F. Padovan 33700a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU) 33710a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 33720a708f8fSGustavo F. Padovan else { 33730c1bc5c6SGustavo F. Padovan chan->omtu = mtu; 3374c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state); 33750a708f8fSGustavo F. Padovan } 33760c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); 33770a708f8fSGustavo F. Padovan 337842dceae2SAndrei Emeltchenko if (remote_efs) { 337942dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 338042dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 338142dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) { 338242dceae2SAndrei Emeltchenko 338342dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT; 338442dceae2SAndrei Emeltchenko 338542dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1) 338642dceae2SAndrei Emeltchenko return -ECONNREFUSED; 338742dceae2SAndrei Emeltchenko 338842dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 338942dceae2SAndrei Emeltchenko sizeof(efs), 339042dceae2SAndrei Emeltchenko (unsigned long) &efs); 33910e8b207eSAndrei Emeltchenko } else { 33923e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */ 33930e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING; 33940e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 339542dceae2SAndrei Emeltchenko } 339642dceae2SAndrei Emeltchenko } 339742dceae2SAndrei Emeltchenko 33980a708f8fSGustavo F. Padovan switch (rfc.mode) { 33990a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 340047d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3401c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 34020a708f8fSGustavo F. Padovan break; 34030a708f8fSGustavo F. Padovan 34040a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 34056327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state)) 34062c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size; 34076327eb98SAndrei Emeltchenko else 34086327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; 34096327eb98SAndrei Emeltchenko 34102c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit; 34110a708f8fSGustavo F. Padovan 3412c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 34132d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE - 34142d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); 3415c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3416c8f79162SAndrei Emeltchenko chan->remote_mps = size; 34170a708f8fSGustavo F. Padovan 341836c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc); 34190a708f8fSGustavo F. Padovan 3420c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 34210a708f8fSGustavo F. Padovan 34220a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 34230a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 34240a708f8fSGustavo F. Padovan 342542dceae2SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 342642dceae2SAndrei Emeltchenko chan->remote_id = efs.id; 342742dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype; 342842dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu); 342942dceae2SAndrei Emeltchenko chan->remote_flush_to = 343042dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to); 343142dceae2SAndrei Emeltchenko chan->remote_acc_lat = 343242dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat); 343342dceae2SAndrei Emeltchenko chan->remote_sdu_itime = 343442dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 343542dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 34362d792818SGustavo Padovan sizeof(efs), 34372d792818SGustavo Padovan (unsigned long) &efs); 343842dceae2SAndrei Emeltchenko } 34390a708f8fSGustavo F. Padovan break; 34400a708f8fSGustavo F. Padovan 34410a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3442c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 34432d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE - 34442d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); 3445c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3446c8f79162SAndrei Emeltchenko chan->remote_mps = size; 34470a708f8fSGustavo F. Padovan 3448c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 34490a708f8fSGustavo F. Padovan 34502d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 34512d792818SGustavo Padovan (unsigned long) &rfc); 34520a708f8fSGustavo F. Padovan 34530a708f8fSGustavo F. Padovan break; 34540a708f8fSGustavo F. Padovan 34550a708f8fSGustavo F. Padovan default: 34560a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 34570a708f8fSGustavo F. Padovan 34580a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc)); 34590c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 34600a708f8fSGustavo F. Padovan } 34610a708f8fSGustavo F. Padovan 34620a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) 3463c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 34640a708f8fSGustavo F. Padovan } 3465fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 34660a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 346759e54bd1SAndrei Emeltchenko rsp->flags = __constant_cpu_to_le16(0); 34680a708f8fSGustavo F. Padovan 34690a708f8fSGustavo F. Padovan return ptr - data; 34700a708f8fSGustavo F. Padovan } 34710a708f8fSGustavo F. Padovan 34722d792818SGustavo Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, 34732d792818SGustavo Padovan void *data, u16 *result) 34740a708f8fSGustavo F. Padovan { 34750a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 34760a708f8fSGustavo F. Padovan void *ptr = req->data; 34770a708f8fSGustavo F. Padovan int type, olen; 34780a708f8fSGustavo F. Padovan unsigned long val; 347936e999a8SMat Martineau struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 348066af7aafSAndrei Emeltchenko struct l2cap_conf_efs efs; 34810a708f8fSGustavo F. Padovan 3482fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); 34830a708f8fSGustavo F. Padovan 34840a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 34850a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 34860a708f8fSGustavo F. Padovan 34870a708f8fSGustavo F. Padovan switch (type) { 34880a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 34890a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) { 34900a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT; 34910c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU; 34920a708f8fSGustavo F. Padovan } else 34930c1bc5c6SGustavo F. Padovan chan->imtu = val; 34940c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 34950a708f8fSGustavo F. Padovan break; 34960a708f8fSGustavo F. Padovan 34970a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 34980c1bc5c6SGustavo F. Padovan chan->flush_to = val; 34990a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 35000c1bc5c6SGustavo F. Padovan 2, chan->flush_to); 35010a708f8fSGustavo F. Padovan break; 35020a708f8fSGustavo F. Padovan 35030a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 35040a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 35050a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 35060a708f8fSGustavo F. Padovan 3507c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && 35080c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode) 35090a708f8fSGustavo F. Padovan return -ECONNREFUSED; 35100a708f8fSGustavo F. Padovan 351147d1ec61SGustavo F. Padovan chan->fcs = 0; 35120a708f8fSGustavo F. Padovan 35130a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 35140a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 35150a708f8fSGustavo F. Padovan break; 35166327eb98SAndrei Emeltchenko 35176327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 3518c20f8e35SMat Martineau chan->ack_win = min_t(u16, val, chan->ack_win); 35193e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 35203e6b3b95SGustavo F. Padovan chan->tx_win); 35216327eb98SAndrei Emeltchenko break; 352266af7aafSAndrei Emeltchenko 352366af7aafSAndrei Emeltchenko case L2CAP_CONF_EFS: 352466af7aafSAndrei Emeltchenko if (olen == sizeof(efs)) 352566af7aafSAndrei Emeltchenko memcpy(&efs, (void *)val, olen); 352666af7aafSAndrei Emeltchenko 352766af7aafSAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 352866af7aafSAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 352966af7aafSAndrei Emeltchenko efs.stype != chan->local_stype) 353066af7aafSAndrei Emeltchenko return -ECONNREFUSED; 353166af7aafSAndrei Emeltchenko 35322d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), 35332d792818SGustavo Padovan (unsigned long) &efs); 353466af7aafSAndrei Emeltchenko break; 3535cbabee78SAndrei Emeltchenko 3536cbabee78SAndrei Emeltchenko case L2CAP_CONF_FCS: 3537cbabee78SAndrei Emeltchenko if (*result == L2CAP_CONF_PENDING) 3538cbabee78SAndrei Emeltchenko if (val == L2CAP_FCS_NONE) 3539f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, 3540cbabee78SAndrei Emeltchenko &chan->conf_state); 3541cbabee78SAndrei Emeltchenko break; 35420a708f8fSGustavo F. Padovan } 35430a708f8fSGustavo F. Padovan } 35440a708f8fSGustavo F. Padovan 35450c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) 35460a708f8fSGustavo F. Padovan return -ECONNREFUSED; 35470a708f8fSGustavo F. Padovan 35480c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode; 35490a708f8fSGustavo F. Padovan 35500e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) { 35510a708f8fSGustavo F. Padovan switch (rfc.mode) { 35520a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 355347d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 355447d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 355547d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 3556c20f8e35SMat Martineau if (!test_bit(FLAG_EXT_CTRL, &chan->flags)) 3557c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 3558c20f8e35SMat Martineau rfc.txwin_size); 355966af7aafSAndrei Emeltchenko 356066af7aafSAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 356166af7aafSAndrei Emeltchenko chan->local_msdu = le16_to_cpu(efs.msdu); 356266af7aafSAndrei Emeltchenko chan->local_sdu_itime = 356366af7aafSAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 356466af7aafSAndrei Emeltchenko chan->local_acc_lat = le32_to_cpu(efs.acc_lat); 356566af7aafSAndrei Emeltchenko chan->local_flush_to = 356666af7aafSAndrei Emeltchenko le32_to_cpu(efs.flush_to); 356766af7aafSAndrei Emeltchenko } 35680a708f8fSGustavo F. Padovan break; 356966af7aafSAndrei Emeltchenko 35700a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 357147d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 35720a708f8fSGustavo F. Padovan } 35730a708f8fSGustavo F. Padovan } 35740a708f8fSGustavo F. Padovan 3575fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 357659e54bd1SAndrei Emeltchenko req->flags = __constant_cpu_to_le16(0); 35770a708f8fSGustavo F. Padovan 35780a708f8fSGustavo F. Padovan return ptr - data; 35790a708f8fSGustavo F. Padovan } 35800a708f8fSGustavo F. Padovan 35812d792818SGustavo Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, 35822d792818SGustavo Padovan u16 result, u16 flags) 35830a708f8fSGustavo F. Padovan { 35840a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 35850a708f8fSGustavo F. Padovan void *ptr = rsp->data; 35860a708f8fSGustavo F. Padovan 3587fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan); 35880a708f8fSGustavo F. Padovan 3589fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 35900a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 35910a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags); 35920a708f8fSGustavo F. Padovan 35930a708f8fSGustavo F. Padovan return ptr - data; 35940a708f8fSGustavo F. Padovan } 35950a708f8fSGustavo F. Padovan 35968c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) 3597710f9b0aSGustavo F. Padovan { 3598710f9b0aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 35998c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 3600710f9b0aSGustavo F. Padovan u8 buf[128]; 3601439f34acSAndrei Emeltchenko u8 rsp_code; 3602710f9b0aSGustavo F. Padovan 3603fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 3604fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3605ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 3606ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 3607439f34acSAndrei Emeltchenko 3608439f34acSAndrei Emeltchenko if (chan->hs_hcon) 3609439f34acSAndrei Emeltchenko rsp_code = L2CAP_CREATE_CHAN_RSP; 3610439f34acSAndrei Emeltchenko else 3611439f34acSAndrei Emeltchenko rsp_code = L2CAP_CONN_RSP; 3612439f34acSAndrei Emeltchenko 3613439f34acSAndrei Emeltchenko BT_DBG("chan %p rsp_code %u", chan, rsp_code); 3614439f34acSAndrei Emeltchenko 3615439f34acSAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp); 3616710f9b0aSGustavo F. Padovan 3617c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 3618710f9b0aSGustavo F. Padovan return; 3619710f9b0aSGustavo F. Padovan 3620710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 3621710f9b0aSGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 3622710f9b0aSGustavo F. Padovan chan->num_conf_req++; 3623710f9b0aSGustavo F. Padovan } 3624710f9b0aSGustavo F. Padovan 362547d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) 36260a708f8fSGustavo F. Padovan { 36270a708f8fSGustavo F. Padovan int type, olen; 36280a708f8fSGustavo F. Padovan unsigned long val; 3629c20f8e35SMat Martineau /* Use sane default values in case a misbehaving remote device 3630c20f8e35SMat Martineau * did not send an RFC or extended window size option. 3631c20f8e35SMat Martineau */ 3632c20f8e35SMat Martineau u16 txwin_ext = chan->ack_win; 3633c20f8e35SMat Martineau struct l2cap_conf_rfc rfc = { 3634c20f8e35SMat Martineau .mode = chan->mode, 3635c20f8e35SMat Martineau .retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO), 3636c20f8e35SMat Martineau .monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO), 3637c20f8e35SMat Martineau .max_pdu_size = cpu_to_le16(chan->imtu), 3638c20f8e35SMat Martineau .txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW), 3639c20f8e35SMat Martineau }; 36400a708f8fSGustavo F. Padovan 364147d1ec61SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); 36420a708f8fSGustavo F. Padovan 36430c1bc5c6SGustavo F. Padovan if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) 36440a708f8fSGustavo F. Padovan return; 36450a708f8fSGustavo F. Padovan 36460a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 36470a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 36480a708f8fSGustavo F. Padovan 3649c20f8e35SMat Martineau switch (type) { 3650c20f8e35SMat Martineau case L2CAP_CONF_RFC: 3651c20f8e35SMat Martineau if (olen == sizeof(rfc)) 36520a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 3653c20f8e35SMat Martineau break; 3654c20f8e35SMat Martineau case L2CAP_CONF_EWS: 3655c20f8e35SMat Martineau txwin_ext = val; 3656c20f8e35SMat Martineau break; 3657c20f8e35SMat Martineau } 36580a708f8fSGustavo F. Padovan } 36590a708f8fSGustavo F. Padovan 36600a708f8fSGustavo F. Padovan switch (rfc.mode) { 36610a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 366247d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 366347d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 366447d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 3665c20f8e35SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 3666c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, txwin_ext); 3667c20f8e35SMat Martineau else 3668c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 3669c20f8e35SMat Martineau rfc.txwin_size); 36700a708f8fSGustavo F. Padovan break; 36710a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 367247d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 36730a708f8fSGustavo F. Padovan } 36740a708f8fSGustavo F. Padovan } 36750a708f8fSGustavo F. Padovan 36762d792818SGustavo Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, 3677cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 3678cb3b3152SJohan Hedberg u8 *data) 36790a708f8fSGustavo F. Padovan { 3680e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 36810a708f8fSGustavo F. Padovan 3682cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rej)) 3683cb3b3152SJohan Hedberg return -EPROTO; 3684cb3b3152SJohan Hedberg 3685e2fd318eSIlia Kolomisnky if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) 36860a708f8fSGustavo F. Padovan return 0; 36870a708f8fSGustavo F. Padovan 36880a708f8fSGustavo F. Padovan if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && 36890a708f8fSGustavo F. Padovan cmd->ident == conn->info_ident) { 369017cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 36910a708f8fSGustavo F. Padovan 36920a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 36930a708f8fSGustavo F. Padovan conn->info_ident = 0; 36940a708f8fSGustavo F. Padovan 36950a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 36960a708f8fSGustavo F. Padovan } 36970a708f8fSGustavo F. Padovan 36980a708f8fSGustavo F. Padovan return 0; 36990a708f8fSGustavo F. Padovan } 37000a708f8fSGustavo F. Padovan 37011700915fSMat Martineau static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, 37021700915fSMat Martineau struct l2cap_cmd_hdr *cmd, 37034c89b6aaSMat Martineau u8 *data, u8 rsp_code, u8 amp_id) 37040a708f8fSGustavo F. Padovan { 37050a708f8fSGustavo F. Padovan struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 37060a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 370723691d75SGustavo F. Padovan struct l2cap_chan *chan = NULL, *pchan; 3708d42970f3SGustavo Padovan struct sock *parent; 37090a708f8fSGustavo F. Padovan int result, status = L2CAP_CS_NO_INFO; 37100a708f8fSGustavo F. Padovan 37110a708f8fSGustavo F. Padovan u16 dcid = 0, scid = __le16_to_cpu(req->scid); 37120a708f8fSGustavo F. Padovan __le16 psm = req->psm; 37130a708f8fSGustavo F. Padovan 3714097db76cSAndrei Emeltchenko BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); 37150a708f8fSGustavo F. Padovan 37160a708f8fSGustavo F. Padovan /* Check if we have socket listening on psm */ 37176f59b904SMarcel Holtmann pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 371898e0f7eaSMarcel Holtmann &conn->hcon->dst); 371923691d75SGustavo F. Padovan if (!pchan) { 37200a708f8fSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 37210a708f8fSGustavo F. Padovan goto sendresp; 37220a708f8fSGustavo F. Padovan } 37230a708f8fSGustavo F. Padovan 372423691d75SGustavo F. Padovan parent = pchan->sk; 372523691d75SGustavo F. Padovan 37263df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 3727aa2ac881SGustavo F. Padovan lock_sock(parent); 37280a708f8fSGustavo F. Padovan 37290a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */ 37302983fd68SAndrei Emeltchenko if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) && 37310a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) { 37329f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_AUTH_FAILURE; 37330a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 37340a708f8fSGustavo F. Padovan goto response; 37350a708f8fSGustavo F. Padovan } 37360a708f8fSGustavo F. Padovan 37370a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM; 37380a708f8fSGustavo F. Padovan 37392dfa1003SGustavo Padovan /* Check if we already have channel with that dcid */ 37402dfa1003SGustavo Padovan if (__l2cap_get_chan_by_dcid(conn, scid)) 37412dfa1003SGustavo Padovan goto response; 37422dfa1003SGustavo Padovan 374380b98027SGustavo Padovan chan = pchan->ops->new_connection(pchan); 374480808e43SGustavo F. Padovan if (!chan) 37450a708f8fSGustavo F. Padovan goto response; 37460a708f8fSGustavo F. Padovan 3747330b6c15SSyam Sidhardhan /* For certain devices (ex: HID mouse), support for authentication, 3748330b6c15SSyam Sidhardhan * pairing and bonding is optional. For such devices, inorder to avoid 3749330b6c15SSyam Sidhardhan * the ACL alive for too long after L2CAP disconnection, reset the ACL 3750330b6c15SSyam Sidhardhan * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect. 3751330b6c15SSyam Sidhardhan */ 3752330b6c15SSyam Sidhardhan conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 3753330b6c15SSyam Sidhardhan 37547eafc59eSMarcel Holtmann bacpy(&chan->src, &conn->hcon->src); 37557eafc59eSMarcel Holtmann bacpy(&chan->dst, &conn->hcon->dst); 37564f1654e0SMarcel Holtmann chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type); 37574f1654e0SMarcel Holtmann chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type); 3758fe4128e0SGustavo F. Padovan chan->psm = psm; 3759fe4128e0SGustavo F. Padovan chan->dcid = scid; 37601700915fSMat Martineau chan->local_amp_id = amp_id; 37610a708f8fSGustavo F. Padovan 37626be36555SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 376348454079SGustavo F. Padovan 3764fe4128e0SGustavo F. Padovan dcid = chan->scid; 37650a708f8fSGustavo F. Padovan 37668d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 37670a708f8fSGustavo F. Padovan 3768fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident; 37690a708f8fSGustavo F. Padovan 37700a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { 3771d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 3772bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 3773*f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 37740a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 37750a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND; 37762dc4e510SGustavo Padovan chan->ops->defer(chan); 37770a708f8fSGustavo F. Padovan } else { 37781700915fSMat Martineau /* Force pending result for AMP controllers. 37791700915fSMat Martineau * The connection will succeed after the 37801700915fSMat Martineau * physical link is up. 37811700915fSMat Martineau */ 37826ed971caSMarcel Holtmann if (amp_id == AMP_ID_BREDR) { 3783*f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 37840a708f8fSGustavo F. Padovan result = L2CAP_CR_SUCCESS; 37856ed971caSMarcel Holtmann } else { 3786*f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 37876ed971caSMarcel Holtmann result = L2CAP_CR_PEND; 37881700915fSMat Martineau } 37890a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 37900a708f8fSGustavo F. Padovan } 37910a708f8fSGustavo F. Padovan } else { 3792*f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 37930a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 37940a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND; 37950a708f8fSGustavo F. Padovan } 37960a708f8fSGustavo F. Padovan } else { 3797*f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 37980a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 37990a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 38000a708f8fSGustavo F. Padovan } 38010a708f8fSGustavo F. Padovan 38020a708f8fSGustavo F. Padovan response: 3803aa2ac881SGustavo F. Padovan release_sock(parent); 38043df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 38050a708f8fSGustavo F. Padovan 38060a708f8fSGustavo F. Padovan sendresp: 38070a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid); 38080a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid); 38090a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result); 38100a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status); 38114c89b6aaSMat Martineau l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp); 38120a708f8fSGustavo F. Padovan 38130a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { 38140a708f8fSGustavo F. Padovan struct l2cap_info_req info; 3815ac73498cSAndrei Emeltchenko info.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); 38160a708f8fSGustavo F. Padovan 38170a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 38180a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 38190a708f8fSGustavo F. Padovan 3820ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 38210a708f8fSGustavo F. Padovan 38222d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, 38232d792818SGustavo Padovan sizeof(info), &info); 38240a708f8fSGustavo F. Padovan } 38250a708f8fSGustavo F. Padovan 3826c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && 38270a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) { 38280a708f8fSGustavo F. Padovan u8 buf[128]; 3829c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 38300a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 383173ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 383273ffa904SGustavo F. Padovan chan->num_conf_req++; 38330a708f8fSGustavo F. Padovan } 38341700915fSMat Martineau 38351700915fSMat Martineau return chan; 38364c89b6aaSMat Martineau } 38370a708f8fSGustavo F. Padovan 38384c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn, 3839cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 38404c89b6aaSMat Martineau { 38417b064edaSJaganath Kanakkassery struct hci_dev *hdev = conn->hcon->hdev; 38427b064edaSJaganath Kanakkassery struct hci_conn *hcon = conn->hcon; 38437b064edaSJaganath Kanakkassery 3844cb3b3152SJohan Hedberg if (cmd_len < sizeof(struct l2cap_conn_req)) 3845cb3b3152SJohan Hedberg return -EPROTO; 3846cb3b3152SJohan Hedberg 38477b064edaSJaganath Kanakkassery hci_dev_lock(hdev); 38487b064edaSJaganath Kanakkassery if (test_bit(HCI_MGMT, &hdev->dev_flags) && 38497b064edaSJaganath Kanakkassery !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags)) 38507b064edaSJaganath Kanakkassery mgmt_device_connected(hdev, &hcon->dst, hcon->type, 38517b064edaSJaganath Kanakkassery hcon->dst_type, 0, NULL, 0, 38527b064edaSJaganath Kanakkassery hcon->dev_class); 38537b064edaSJaganath Kanakkassery hci_dev_unlock(hdev); 38547b064edaSJaganath Kanakkassery 3855300229f9SGustavo Padovan l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0); 38560a708f8fSGustavo F. Padovan return 0; 38570a708f8fSGustavo F. Padovan } 38580a708f8fSGustavo F. Padovan 38595909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn, 3860cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 3861cb3b3152SJohan Hedberg u8 *data) 38620a708f8fSGustavo F. Padovan { 38630a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; 38640a708f8fSGustavo F. Padovan u16 scid, dcid, result, status; 386548454079SGustavo F. Padovan struct l2cap_chan *chan; 38660a708f8fSGustavo F. Padovan u8 req[128]; 38673df91ea2SAndrei Emeltchenko int err; 38680a708f8fSGustavo F. Padovan 3869cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp)) 3870cb3b3152SJohan Hedberg return -EPROTO; 3871cb3b3152SJohan Hedberg 38720a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 38730a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 38740a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 38750a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status); 38760a708f8fSGustavo F. Padovan 38771b009c98SAndrei Emeltchenko BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", 38781b009c98SAndrei Emeltchenko dcid, scid, result, status); 38790a708f8fSGustavo F. Padovan 38803df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 38813df91ea2SAndrei Emeltchenko 38820a708f8fSGustavo F. Padovan if (scid) { 38833df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 38843df91ea2SAndrei Emeltchenko if (!chan) { 388521870b52SJohan Hedberg err = -EBADSLT; 38863df91ea2SAndrei Emeltchenko goto unlock; 38873df91ea2SAndrei Emeltchenko } 38880a708f8fSGustavo F. Padovan } else { 38893df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 38903df91ea2SAndrei Emeltchenko if (!chan) { 389121870b52SJohan Hedberg err = -EBADSLT; 38923df91ea2SAndrei Emeltchenko goto unlock; 38933df91ea2SAndrei Emeltchenko } 38940a708f8fSGustavo F. Padovan } 38950a708f8fSGustavo F. Padovan 38963df91ea2SAndrei Emeltchenko err = 0; 38973df91ea2SAndrei Emeltchenko 38986be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 389948454079SGustavo F. Padovan 39000a708f8fSGustavo F. Padovan switch (result) { 39010a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS: 390289bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 3903fc7f8a7eSGustavo F. Padovan chan->ident = 0; 3904fe4128e0SGustavo F. Padovan chan->dcid = dcid; 3905c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state); 39060a708f8fSGustavo F. Padovan 3907c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 39080a708f8fSGustavo F. Padovan break; 39090a708f8fSGustavo F. Padovan 39100a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 391173ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, req), req); 391273ffa904SGustavo F. Padovan chan->num_conf_req++; 39130a708f8fSGustavo F. Padovan break; 39140a708f8fSGustavo F. Padovan 39150a708f8fSGustavo F. Padovan case L2CAP_CR_PEND: 3916c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 39170a708f8fSGustavo F. Padovan break; 39180a708f8fSGustavo F. Padovan 39190a708f8fSGustavo F. Padovan default: 392048454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED); 39210a708f8fSGustavo F. Padovan break; 39220a708f8fSGustavo F. Padovan } 39230a708f8fSGustavo F. Padovan 39246be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 39253df91ea2SAndrei Emeltchenko 39263df91ea2SAndrei Emeltchenko unlock: 39273df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 39283df91ea2SAndrei Emeltchenko 39293df91ea2SAndrei Emeltchenko return err; 39300a708f8fSGustavo F. Padovan } 39310a708f8fSGustavo F. Padovan 393247d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan) 39330a708f8fSGustavo F. Padovan { 39340a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both 39350a708f8fSGustavo F. Padovan * sides request it. 39360a708f8fSGustavo F. Padovan */ 39370c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) 393847d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3939f2592d3eSAndrei Emeltchenko else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) 394047d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16; 39410a708f8fSGustavo F. Padovan } 39420a708f8fSGustavo F. Padovan 394329d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data, 394429d8a590SAndrei Emeltchenko u8 ident, u16 flags) 394529d8a590SAndrei Emeltchenko { 394629d8a590SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 394729d8a590SAndrei Emeltchenko 394829d8a590SAndrei Emeltchenko BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident, 394929d8a590SAndrei Emeltchenko flags); 395029d8a590SAndrei Emeltchenko 395129d8a590SAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 395229d8a590SAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 395329d8a590SAndrei Emeltchenko 395429d8a590SAndrei Emeltchenko l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP, 395529d8a590SAndrei Emeltchenko l2cap_build_conf_rsp(chan, data, 395629d8a590SAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), data); 395729d8a590SAndrei Emeltchenko } 395829d8a590SAndrei Emeltchenko 3959662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident, 3960662d652dSJohan Hedberg u16 scid, u16 dcid) 3961662d652dSJohan Hedberg { 3962662d652dSJohan Hedberg struct l2cap_cmd_rej_cid rej; 3963662d652dSJohan Hedberg 3964662d652dSJohan Hedberg rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID); 3965662d652dSJohan Hedberg rej.scid = __cpu_to_le16(scid); 3966662d652dSJohan Hedberg rej.dcid = __cpu_to_le16(dcid); 3967662d652dSJohan Hedberg 3968662d652dSJohan Hedberg l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); 3969662d652dSJohan Hedberg } 3970662d652dSJohan Hedberg 39712d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, 39722d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len, 39732d792818SGustavo Padovan u8 *data) 39740a708f8fSGustavo F. Padovan { 39750a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; 39760a708f8fSGustavo F. Padovan u16 dcid, flags; 39770a708f8fSGustavo F. Padovan u8 rsp[64]; 397848454079SGustavo F. Padovan struct l2cap_chan *chan; 39793c588192SMat Martineau int len, err = 0; 39800a708f8fSGustavo F. Padovan 3981cb3b3152SJohan Hedberg if (cmd_len < sizeof(*req)) 3982cb3b3152SJohan Hedberg return -EPROTO; 3983cb3b3152SJohan Hedberg 39840a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 39850a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags); 39860a708f8fSGustavo F. Padovan 39870a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); 39880a708f8fSGustavo F. Padovan 3989baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid); 3990662d652dSJohan Hedberg if (!chan) { 3991662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0); 3992662d652dSJohan Hedberg return 0; 3993662d652dSJohan Hedberg } 39940a708f8fSGustavo F. Padovan 3995033b1142SDavid S. Miller if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { 3996662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, 3997662d652dSJohan Hedberg chan->dcid); 39980a708f8fSGustavo F. Padovan goto unlock; 39990a708f8fSGustavo F. Padovan } 40000a708f8fSGustavo F. Padovan 40010a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */ 40020a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req); 4003cb3b3152SJohan Hedberg if (chan->conf_len + len > sizeof(chan->conf_req)) { 40040a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 4005fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 40060a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp); 40070a708f8fSGustavo F. Padovan goto unlock; 40080a708f8fSGustavo F. Padovan } 40090a708f8fSGustavo F. Padovan 40100a708f8fSGustavo F. Padovan /* Store config. */ 401173ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len); 401273ffa904SGustavo F. Padovan chan->conf_len += len; 40130a708f8fSGustavo F. Padovan 401459e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) { 40150a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */ 40160a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 4017fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 40185325e5bbSAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), rsp); 40190a708f8fSGustavo F. Padovan goto unlock; 40200a708f8fSGustavo F. Padovan } 40210a708f8fSGustavo F. Padovan 40220a708f8fSGustavo F. Padovan /* Complete config. */ 402373ffa904SGustavo F. Padovan len = l2cap_parse_conf_req(chan, rsp); 40240a708f8fSGustavo F. Padovan if (len < 0) { 40255e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 40260a708f8fSGustavo F. Padovan goto unlock; 40270a708f8fSGustavo F. Padovan } 40280a708f8fSGustavo F. Padovan 40291500109bSMat Martineau chan->ident = cmd->ident; 40300a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); 403173ffa904SGustavo F. Padovan chan->num_conf_rsp++; 40320a708f8fSGustavo F. Padovan 40330a708f8fSGustavo F. Padovan /* Reset config buffer. */ 403473ffa904SGustavo F. Padovan chan->conf_len = 0; 40350a708f8fSGustavo F. Padovan 4036c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) 40370a708f8fSGustavo F. Padovan goto unlock; 40380a708f8fSGustavo F. Padovan 4039c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 404047d1ec61SGustavo F. Padovan set_default_fcs(chan); 40410a708f8fSGustavo F. Padovan 4042105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 4043105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 40443c588192SMat Martineau err = l2cap_ertm_init(chan); 40450a708f8fSGustavo F. Padovan 40463c588192SMat Martineau if (err < 0) 40475e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 40483c588192SMat Martineau else 4049cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 40503c588192SMat Martineau 40510a708f8fSGustavo F. Padovan goto unlock; 40520a708f8fSGustavo F. Padovan } 40530a708f8fSGustavo F. Padovan 4054c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { 40550a708f8fSGustavo F. Padovan u8 buf[64]; 40560a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 405773ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 405873ffa904SGustavo F. Padovan chan->num_conf_req++; 40590a708f8fSGustavo F. Padovan } 40600a708f8fSGustavo F. Padovan 40610e8b207eSAndrei Emeltchenko /* Got Conf Rsp PENDING from remote side and asume we sent 40620e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */ 40630e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && 40640e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 40650e8b207eSAndrei Emeltchenko 40660e8b207eSAndrei Emeltchenko /* check compatibility */ 40670e8b207eSAndrei Emeltchenko 406879de886dSAndrei Emeltchenko /* Send rsp for BR/EDR channel */ 4069f351bc72SAndrei Emeltchenko if (!chan->hs_hcon) 407029d8a590SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags); 407179de886dSAndrei Emeltchenko else 407279de886dSAndrei Emeltchenko chan->ident = cmd->ident; 40730e8b207eSAndrei Emeltchenko } 40740e8b207eSAndrei Emeltchenko 40750a708f8fSGustavo F. Padovan unlock: 40766be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 40773c588192SMat Martineau return err; 40780a708f8fSGustavo F. Padovan } 40790a708f8fSGustavo F. Padovan 40802d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, 4081cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4082cb3b3152SJohan Hedberg u8 *data) 40830a708f8fSGustavo F. Padovan { 40840a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; 40850a708f8fSGustavo F. Padovan u16 scid, flags, result; 408648454079SGustavo F. Padovan struct l2cap_chan *chan; 4087cb3b3152SJohan Hedberg int len = cmd_len - sizeof(*rsp); 40883c588192SMat Martineau int err = 0; 40890a708f8fSGustavo F. Padovan 4090cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp)) 4091cb3b3152SJohan Hedberg return -EPROTO; 4092cb3b3152SJohan Hedberg 40930a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 40940a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags); 40950a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 40960a708f8fSGustavo F. Padovan 409761386cbaSAndrei Emeltchenko BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags, 409861386cbaSAndrei Emeltchenko result, len); 40990a708f8fSGustavo F. Padovan 4100baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 410148454079SGustavo F. Padovan if (!chan) 41020a708f8fSGustavo F. Padovan return 0; 41030a708f8fSGustavo F. Padovan 41040a708f8fSGustavo F. Padovan switch (result) { 41050a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS: 410647d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len); 41070e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state); 41080a708f8fSGustavo F. Padovan break; 41090a708f8fSGustavo F. Padovan 41100e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING: 41110e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state); 41120e8b207eSAndrei Emeltchenko 41130e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 41140e8b207eSAndrei Emeltchenko char buf[64]; 41150e8b207eSAndrei Emeltchenko 41160e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len, 41170e8b207eSAndrei Emeltchenko buf, &result); 41180e8b207eSAndrei Emeltchenko if (len < 0) { 41195e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 41200e8b207eSAndrei Emeltchenko goto done; 41210e8b207eSAndrei Emeltchenko } 41220e8b207eSAndrei Emeltchenko 4123f351bc72SAndrei Emeltchenko if (!chan->hs_hcon) { 412479de886dSAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, buf, cmd->ident, 412579de886dSAndrei Emeltchenko 0); 41265ce66b59SAndrei Emeltchenko } else { 41275ce66b59SAndrei Emeltchenko if (l2cap_check_efs(chan)) { 41285ce66b59SAndrei Emeltchenko amp_create_logical_link(chan); 412979de886dSAndrei Emeltchenko chan->ident = cmd->ident; 41300e8b207eSAndrei Emeltchenko } 41315ce66b59SAndrei Emeltchenko } 41325ce66b59SAndrei Emeltchenko } 41330e8b207eSAndrei Emeltchenko goto done; 41340e8b207eSAndrei Emeltchenko 41350a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT: 413673ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { 41370a708f8fSGustavo F. Padovan char req[64]; 41380a708f8fSGustavo F. Padovan 41390a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { 41405e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 41410a708f8fSGustavo F. Padovan goto done; 41420a708f8fSGustavo F. Padovan } 41430a708f8fSGustavo F. Padovan 41440a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */ 41450a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS; 4146b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len, 4147b4450035SGustavo F. Padovan req, &result); 41480a708f8fSGustavo F. Padovan if (len < 0) { 41495e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 41500a708f8fSGustavo F. Padovan goto done; 41510a708f8fSGustavo F. Padovan } 41520a708f8fSGustavo F. Padovan 41530a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 41540a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req); 415573ffa904SGustavo F. Padovan chan->num_conf_req++; 41560a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS) 41570a708f8fSGustavo F. Padovan goto done; 41580a708f8fSGustavo F. Padovan break; 41590a708f8fSGustavo F. Padovan } 41600a708f8fSGustavo F. Padovan 41610a708f8fSGustavo F. Padovan default: 41626be36555SAndrei Emeltchenko l2cap_chan_set_err(chan, ECONNRESET); 41632e0052e4SAndrei Emeltchenko 4164ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); 41655e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 41660a708f8fSGustavo F. Padovan goto done; 41670a708f8fSGustavo F. Padovan } 41680a708f8fSGustavo F. Padovan 416959e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) 41700a708f8fSGustavo F. Padovan goto done; 41710a708f8fSGustavo F. Padovan 4172c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state); 41730a708f8fSGustavo F. Padovan 4174c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { 417547d1ec61SGustavo F. Padovan set_default_fcs(chan); 41760a708f8fSGustavo F. Padovan 4177105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 4178105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 41793c588192SMat Martineau err = l2cap_ertm_init(chan); 41800a708f8fSGustavo F. Padovan 41813c588192SMat Martineau if (err < 0) 41825e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 41833c588192SMat Martineau else 4184cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 41850a708f8fSGustavo F. Padovan } 41860a708f8fSGustavo F. Padovan 41870a708f8fSGustavo F. Padovan done: 41886be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 41893c588192SMat Martineau return err; 41900a708f8fSGustavo F. Padovan } 41910a708f8fSGustavo F. Padovan 41922d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, 4193cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4194cb3b3152SJohan Hedberg u8 *data) 41950a708f8fSGustavo F. Padovan { 41960a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; 41970a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp; 41980a708f8fSGustavo F. Padovan u16 dcid, scid; 419948454079SGustavo F. Padovan struct l2cap_chan *chan; 42000a708f8fSGustavo F. Padovan 4201cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req)) 4202cb3b3152SJohan Hedberg return -EPROTO; 4203cb3b3152SJohan Hedberg 42040a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid); 42050a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 42060a708f8fSGustavo F. Padovan 42070a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); 42080a708f8fSGustavo F. Padovan 42093df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 42103df91ea2SAndrei Emeltchenko 42113df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, dcid); 42123df91ea2SAndrei Emeltchenko if (!chan) { 42133df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4214662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid); 4215662d652dSJohan Hedberg return 0; 42163df91ea2SAndrei Emeltchenko } 42170a708f8fSGustavo F. Padovan 42186be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 42196be36555SAndrei Emeltchenko 4220fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 4221fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 42220a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); 42230a708f8fSGustavo F. Padovan 42245ec1bbe5SGustavo Padovan chan->ops->set_shutdown(chan); 42250a708f8fSGustavo F. Padovan 422661d6ef3eSMat Martineau l2cap_chan_hold(chan); 422748454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET); 42286be36555SAndrei Emeltchenko 42296be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 42300a708f8fSGustavo F. Padovan 423180b98027SGustavo Padovan chan->ops->close(chan); 423261d6ef3eSMat Martineau l2cap_chan_put(chan); 42333df91ea2SAndrei Emeltchenko 42343df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 42353df91ea2SAndrei Emeltchenko 42360a708f8fSGustavo F. Padovan return 0; 42370a708f8fSGustavo F. Padovan } 42380a708f8fSGustavo F. Padovan 42392d792818SGustavo Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, 4240cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4241cb3b3152SJohan Hedberg u8 *data) 42420a708f8fSGustavo F. Padovan { 42430a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; 42440a708f8fSGustavo F. Padovan u16 dcid, scid; 424548454079SGustavo F. Padovan struct l2cap_chan *chan; 42460a708f8fSGustavo F. Padovan 4247cb3b3152SJohan Hedberg if (cmd_len != sizeof(*rsp)) 4248cb3b3152SJohan Hedberg return -EPROTO; 4249cb3b3152SJohan Hedberg 42500a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 42510a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 42520a708f8fSGustavo F. Padovan 42530a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); 42540a708f8fSGustavo F. Padovan 42553df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 42563df91ea2SAndrei Emeltchenko 42573df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 42583df91ea2SAndrei Emeltchenko if (!chan) { 42593df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 42600a708f8fSGustavo F. Padovan return 0; 42613df91ea2SAndrei Emeltchenko } 42620a708f8fSGustavo F. Padovan 42636be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 426448454079SGustavo F. Padovan 426561d6ef3eSMat Martineau l2cap_chan_hold(chan); 426648454079SGustavo F. Padovan l2cap_chan_del(chan, 0); 42676be36555SAndrei Emeltchenko 42686be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 42690a708f8fSGustavo F. Padovan 427080b98027SGustavo Padovan chan->ops->close(chan); 427161d6ef3eSMat Martineau l2cap_chan_put(chan); 42723df91ea2SAndrei Emeltchenko 42733df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 42743df91ea2SAndrei Emeltchenko 42750a708f8fSGustavo F. Padovan return 0; 42760a708f8fSGustavo F. Padovan } 42770a708f8fSGustavo F. Padovan 42782d792818SGustavo Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, 4279cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4280cb3b3152SJohan Hedberg u8 *data) 42810a708f8fSGustavo F. Padovan { 42820a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data; 42830a708f8fSGustavo F. Padovan u16 type; 42840a708f8fSGustavo F. Padovan 4285cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req)) 4286cb3b3152SJohan Hedberg return -EPROTO; 4287cb3b3152SJohan Hedberg 42880a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type); 42890a708f8fSGustavo F. Padovan 42900a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type); 42910a708f8fSGustavo F. Padovan 42920a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) { 42930a708f8fSGustavo F. Padovan u8 buf[8]; 42940a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask; 42950a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 4296ac73498cSAndrei Emeltchenko rsp->type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); 4297ac73498cSAndrei Emeltchenko rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); 42980a708f8fSGustavo F. Padovan if (!disable_ertm) 42990a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING 43000a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS; 4301848566b3SMarcel Holtmann if (conn->hs_enabled) 43026327eb98SAndrei Emeltchenko feat_mask |= L2CAP_FEAT_EXT_FLOW 43036327eb98SAndrei Emeltchenko | L2CAP_FEAT_EXT_WINDOW; 4304a5fd6f30SAndrei Emeltchenko 43050a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data); 43062d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), 43072d792818SGustavo Padovan buf); 43080a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) { 43090a708f8fSGustavo F. Padovan u8 buf[12]; 43100a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 431150a147cdSMat Martineau 4312848566b3SMarcel Holtmann if (conn->hs_enabled) 431350a147cdSMat Martineau l2cap_fixed_chan[0] |= L2CAP_FC_A2MP; 431450a147cdSMat Martineau else 431550a147cdSMat Martineau l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP; 431650a147cdSMat Martineau 4317ac73498cSAndrei Emeltchenko rsp->type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); 4318ac73498cSAndrei Emeltchenko rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); 4319c6337ea6SAndrei Emeltchenko memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); 43202d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), 43212d792818SGustavo Padovan buf); 43220a708f8fSGustavo F. Padovan } else { 43230a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp; 43240a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type); 4325ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP); 43262d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), 43272d792818SGustavo Padovan &rsp); 43280a708f8fSGustavo F. Padovan } 43290a708f8fSGustavo F. Padovan 43300a708f8fSGustavo F. Padovan return 0; 43310a708f8fSGustavo F. Padovan } 43320a708f8fSGustavo F. Padovan 43332d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, 4334cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4335cb3b3152SJohan Hedberg u8 *data) 43360a708f8fSGustavo F. Padovan { 43370a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; 43380a708f8fSGustavo F. Padovan u16 type, result; 43390a708f8fSGustavo F. Padovan 43403f6fa3d4SJaganath Kanakkassery if (cmd_len < sizeof(*rsp)) 4341cb3b3152SJohan Hedberg return -EPROTO; 4342cb3b3152SJohan Hedberg 43430a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type); 43440a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 43450a708f8fSGustavo F. Padovan 43460a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); 43470a708f8fSGustavo F. Padovan 4348e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */ 4349e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident || 4350e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 4351e90165beSAndrei Emeltchenko return 0; 4352e90165beSAndrei Emeltchenko 435317cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 43540a708f8fSGustavo F. Padovan 43550a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) { 43560a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 43570a708f8fSGustavo F. Padovan conn->info_ident = 0; 43580a708f8fSGustavo F. Padovan 43590a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 43600a708f8fSGustavo F. Padovan 43610a708f8fSGustavo F. Padovan return 0; 43620a708f8fSGustavo F. Padovan } 43630a708f8fSGustavo F. Padovan 4364978c93b9SAndrei Emeltchenko switch (type) { 4365978c93b9SAndrei Emeltchenko case L2CAP_IT_FEAT_MASK: 43660a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data); 43670a708f8fSGustavo F. Padovan 43680a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { 43690a708f8fSGustavo F. Padovan struct l2cap_info_req req; 4370ac73498cSAndrei Emeltchenko req.type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); 43710a708f8fSGustavo F. Padovan 43720a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 43730a708f8fSGustavo F. Padovan 43740a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 43750a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 43760a708f8fSGustavo F. Padovan } else { 43770a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 43780a708f8fSGustavo F. Padovan conn->info_ident = 0; 43790a708f8fSGustavo F. Padovan 43800a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 43810a708f8fSGustavo F. Padovan } 4382978c93b9SAndrei Emeltchenko break; 4383978c93b9SAndrei Emeltchenko 4384978c93b9SAndrei Emeltchenko case L2CAP_IT_FIXED_CHAN: 4385978c93b9SAndrei Emeltchenko conn->fixed_chan_mask = rsp->data[0]; 43860a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 43870a708f8fSGustavo F. Padovan conn->info_ident = 0; 43880a708f8fSGustavo F. Padovan 43890a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 4390978c93b9SAndrei Emeltchenko break; 43910a708f8fSGustavo F. Padovan } 43920a708f8fSGustavo F. Padovan 43930a708f8fSGustavo F. Padovan return 0; 43940a708f8fSGustavo F. Padovan } 43950a708f8fSGustavo F. Padovan 43961700915fSMat Martineau static int l2cap_create_channel_req(struct l2cap_conn *conn, 43972d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, 43982d792818SGustavo Padovan u16 cmd_len, void *data) 4399f94ff6ffSMat Martineau { 4400f94ff6ffSMat Martineau struct l2cap_create_chan_req *req = data; 44016e1df6a6SAndrei Emeltchenko struct l2cap_create_chan_rsp rsp; 44021700915fSMat Martineau struct l2cap_chan *chan; 44036e1df6a6SAndrei Emeltchenko struct hci_dev *hdev; 4404f94ff6ffSMat Martineau u16 psm, scid; 4405f94ff6ffSMat Martineau 4406f94ff6ffSMat Martineau if (cmd_len != sizeof(*req)) 4407f94ff6ffSMat Martineau return -EPROTO; 4408f94ff6ffSMat Martineau 4409848566b3SMarcel Holtmann if (!conn->hs_enabled) 4410f94ff6ffSMat Martineau return -EINVAL; 4411f94ff6ffSMat Martineau 4412f94ff6ffSMat Martineau psm = le16_to_cpu(req->psm); 4413f94ff6ffSMat Martineau scid = le16_to_cpu(req->scid); 4414f94ff6ffSMat Martineau 4415ad0ac6caSAndrei Emeltchenko BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id); 4416f94ff6ffSMat Martineau 44176e1df6a6SAndrei Emeltchenko /* For controller id 0 make BR/EDR connection */ 44186ed971caSMarcel Holtmann if (req->amp_id == AMP_ID_BREDR) { 44196e1df6a6SAndrei Emeltchenko l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, 44206e1df6a6SAndrei Emeltchenko req->amp_id); 44216e1df6a6SAndrei Emeltchenko return 0; 44226e1df6a6SAndrei Emeltchenko } 44231700915fSMat Martineau 44241700915fSMat Martineau /* Validate AMP controller id */ 44251700915fSMat Martineau hdev = hci_dev_get(req->amp_id); 44266e1df6a6SAndrei Emeltchenko if (!hdev) 44276e1df6a6SAndrei Emeltchenko goto error; 44281700915fSMat Martineau 44296e1df6a6SAndrei Emeltchenko if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) { 44306e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 44316e1df6a6SAndrei Emeltchenko goto error; 44326e1df6a6SAndrei Emeltchenko } 44336e1df6a6SAndrei Emeltchenko 44346e1df6a6SAndrei Emeltchenko chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, 44356e1df6a6SAndrei Emeltchenko req->amp_id); 44366e1df6a6SAndrei Emeltchenko if (chan) { 44376e1df6a6SAndrei Emeltchenko struct amp_mgr *mgr = conn->hcon->amp_mgr; 44386e1df6a6SAndrei Emeltchenko struct hci_conn *hs_hcon; 44396e1df6a6SAndrei Emeltchenko 444098e0f7eaSMarcel Holtmann hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, 444198e0f7eaSMarcel Holtmann &conn->hcon->dst); 44426e1df6a6SAndrei Emeltchenko if (!hs_hcon) { 44436e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 4444662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, 4445662d652dSJohan Hedberg chan->dcid); 4446662d652dSJohan Hedberg return 0; 44476e1df6a6SAndrei Emeltchenko } 44486e1df6a6SAndrei Emeltchenko 44496e1df6a6SAndrei Emeltchenko BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon); 44506e1df6a6SAndrei Emeltchenko 44516e1df6a6SAndrei Emeltchenko mgr->bredr_chan = chan; 44526e1df6a6SAndrei Emeltchenko chan->hs_hcon = hs_hcon; 4453fd45bf4cSAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 44546e1df6a6SAndrei Emeltchenko conn->mtu = hdev->block_mtu; 44556e1df6a6SAndrei Emeltchenko } 44566e1df6a6SAndrei Emeltchenko 44576e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 44586e1df6a6SAndrei Emeltchenko 44596e1df6a6SAndrei Emeltchenko return 0; 44606e1df6a6SAndrei Emeltchenko 44616e1df6a6SAndrei Emeltchenko error: 4462f94ff6ffSMat Martineau rsp.dcid = 0; 4463f94ff6ffSMat Martineau rsp.scid = cpu_to_le16(scid); 44641700915fSMat Martineau rsp.result = __constant_cpu_to_le16(L2CAP_CR_BAD_AMP); 44658ce0c498SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 4466f94ff6ffSMat Martineau 4467f94ff6ffSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, 4468f94ff6ffSMat Martineau sizeof(rsp), &rsp); 4469f94ff6ffSMat Martineau 4470dc280801SJohan Hedberg return 0; 4471f94ff6ffSMat Martineau } 4472f94ff6ffSMat Martineau 44738eb200bdSMat Martineau static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id) 44748eb200bdSMat Martineau { 44758eb200bdSMat Martineau struct l2cap_move_chan_req req; 44768eb200bdSMat Martineau u8 ident; 44778eb200bdSMat Martineau 44788eb200bdSMat Martineau BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id); 44798eb200bdSMat Martineau 44808eb200bdSMat Martineau ident = l2cap_get_ident(chan->conn); 44818eb200bdSMat Martineau chan->ident = ident; 44828eb200bdSMat Martineau 44838eb200bdSMat Martineau req.icid = cpu_to_le16(chan->scid); 44848eb200bdSMat Martineau req.dest_amp_id = dest_amp_id; 44858eb200bdSMat Martineau 44868eb200bdSMat Martineau l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req), 44878eb200bdSMat Martineau &req); 44888eb200bdSMat Martineau 44898eb200bdSMat Martineau __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); 44908eb200bdSMat Martineau } 44918eb200bdSMat Martineau 44921500109bSMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result) 44938d5a04a1SMat Martineau { 44948d5a04a1SMat Martineau struct l2cap_move_chan_rsp rsp; 44958d5a04a1SMat Martineau 44961500109bSMat Martineau BT_DBG("chan %p, result 0x%4.4x", chan, result); 44978d5a04a1SMat Martineau 44981500109bSMat Martineau rsp.icid = cpu_to_le16(chan->dcid); 44998d5a04a1SMat Martineau rsp.result = cpu_to_le16(result); 45008d5a04a1SMat Martineau 45011500109bSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP, 45021500109bSMat Martineau sizeof(rsp), &rsp); 45038d5a04a1SMat Martineau } 45048d5a04a1SMat Martineau 45055b155ef9SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result) 45068d5a04a1SMat Martineau { 45078d5a04a1SMat Martineau struct l2cap_move_chan_cfm cfm; 45088d5a04a1SMat Martineau 45095b155ef9SMat Martineau BT_DBG("chan %p, result 0x%4.4x", chan, result); 45108d5a04a1SMat Martineau 45115b155ef9SMat Martineau chan->ident = l2cap_get_ident(chan->conn); 45128d5a04a1SMat Martineau 45135b155ef9SMat Martineau cfm.icid = cpu_to_le16(chan->scid); 45148d5a04a1SMat Martineau cfm.result = cpu_to_le16(result); 45158d5a04a1SMat Martineau 45165b155ef9SMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM, 45175b155ef9SMat Martineau sizeof(cfm), &cfm); 45185b155ef9SMat Martineau 45195b155ef9SMat Martineau __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); 45205b155ef9SMat Martineau } 45215b155ef9SMat Martineau 45225b155ef9SMat Martineau static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid) 45235b155ef9SMat Martineau { 45245b155ef9SMat Martineau struct l2cap_move_chan_cfm cfm; 45255b155ef9SMat Martineau 45265b155ef9SMat Martineau BT_DBG("conn %p, icid 0x%4.4x", conn, icid); 45275b155ef9SMat Martineau 45285b155ef9SMat Martineau cfm.icid = cpu_to_le16(icid); 45295b155ef9SMat Martineau cfm.result = __constant_cpu_to_le16(L2CAP_MC_UNCONFIRMED); 45305b155ef9SMat Martineau 45315b155ef9SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM, 45325b155ef9SMat Martineau sizeof(cfm), &cfm); 45338d5a04a1SMat Martineau } 45348d5a04a1SMat Martineau 45358d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, 45368d5a04a1SMat Martineau u16 icid) 45378d5a04a1SMat Martineau { 45388d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp rsp; 45398d5a04a1SMat Martineau 4540ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 45418d5a04a1SMat Martineau 45428d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 45438d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp); 45448d5a04a1SMat Martineau } 45458d5a04a1SMat Martineau 45465f3847a4SMat Martineau static void __release_logical_link(struct l2cap_chan *chan) 45475f3847a4SMat Martineau { 45485f3847a4SMat Martineau chan->hs_hchan = NULL; 45495f3847a4SMat Martineau chan->hs_hcon = NULL; 45505f3847a4SMat Martineau 45515f3847a4SMat Martineau /* Placeholder - release the logical link */ 45525f3847a4SMat Martineau } 45535f3847a4SMat Martineau 45541500109bSMat Martineau static void l2cap_logical_fail(struct l2cap_chan *chan) 45551500109bSMat Martineau { 45561500109bSMat Martineau /* Logical link setup failed */ 45571500109bSMat Martineau if (chan->state != BT_CONNECTED) { 45581500109bSMat Martineau /* Create channel failure, disconnect */ 45595e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 45601500109bSMat Martineau return; 45611500109bSMat Martineau } 45621500109bSMat Martineau 45631500109bSMat Martineau switch (chan->move_role) { 45641500109bSMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 45651500109bSMat Martineau l2cap_move_done(chan); 45661500109bSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP); 45671500109bSMat Martineau break; 45681500109bSMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 45691500109bSMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP || 45701500109bSMat Martineau chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) { 45711500109bSMat Martineau /* Remote has only sent pending or 45721500109bSMat Martineau * success responses, clean up 45731500109bSMat Martineau */ 45741500109bSMat Martineau l2cap_move_done(chan); 45751500109bSMat Martineau } 45761500109bSMat Martineau 45771500109bSMat Martineau /* Other amp move states imply that the move 45781500109bSMat Martineau * has already aborted 45791500109bSMat Martineau */ 45801500109bSMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 45811500109bSMat Martineau break; 45821500109bSMat Martineau } 45831500109bSMat Martineau } 45841500109bSMat Martineau 45851500109bSMat Martineau static void l2cap_logical_finish_create(struct l2cap_chan *chan, 45861500109bSMat Martineau struct hci_chan *hchan) 45871500109bSMat Martineau { 45881500109bSMat Martineau struct l2cap_conf_rsp rsp; 45891500109bSMat Martineau 4590336178a3SAndrei Emeltchenko chan->hs_hchan = hchan; 45911500109bSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 45921500109bSMat Martineau 459335ba9561SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0); 45941500109bSMat Martineau 45951500109bSMat Martineau if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 4596fe79c6feSAndrei Emeltchenko int err; 45971500109bSMat Martineau 45981500109bSMat Martineau set_default_fcs(chan); 45991500109bSMat Martineau 46001500109bSMat Martineau err = l2cap_ertm_init(chan); 46011500109bSMat Martineau if (err < 0) 46025e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 46031500109bSMat Martineau else 46041500109bSMat Martineau l2cap_chan_ready(chan); 46051500109bSMat Martineau } 46061500109bSMat Martineau } 46071500109bSMat Martineau 46081500109bSMat Martineau static void l2cap_logical_finish_move(struct l2cap_chan *chan, 46091500109bSMat Martineau struct hci_chan *hchan) 46101500109bSMat Martineau { 46111500109bSMat Martineau chan->hs_hcon = hchan->conn; 46121500109bSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 46131500109bSMat Martineau 46141500109bSMat Martineau BT_DBG("move_state %d", chan->move_state); 46151500109bSMat Martineau 46161500109bSMat Martineau switch (chan->move_state) { 46171500109bSMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_COMP: 46181500109bSMat Martineau /* Move confirm will be sent after a success 46191500109bSMat Martineau * response is received 46201500109bSMat Martineau */ 46211500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 46221500109bSMat Martineau break; 46231500109bSMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_CFM: 46241500109bSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 46251500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 46261500109bSMat Martineau } else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { 46271500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; 46281500109bSMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 46291500109bSMat Martineau } else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { 46301500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 46311500109bSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); 46321500109bSMat Martineau } 46331500109bSMat Martineau break; 46341500109bSMat Martineau default: 46351500109bSMat Martineau /* Move was not in expected state, free the channel */ 46361500109bSMat Martineau __release_logical_link(chan); 46371500109bSMat Martineau 46381500109bSMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 46391500109bSMat Martineau } 46401500109bSMat Martineau } 46411500109bSMat Martineau 46421500109bSMat Martineau /* Call with chan locked */ 464327695fb4SAndrei Emeltchenko void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan, 46445b155ef9SMat Martineau u8 status) 46455b155ef9SMat Martineau { 46461500109bSMat Martineau BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status); 46471500109bSMat Martineau 46481500109bSMat Martineau if (status) { 46491500109bSMat Martineau l2cap_logical_fail(chan); 46501500109bSMat Martineau __release_logical_link(chan); 46515b155ef9SMat Martineau return; 46525b155ef9SMat Martineau } 46535b155ef9SMat Martineau 46541500109bSMat Martineau if (chan->state != BT_CONNECTED) { 46551500109bSMat Martineau /* Ignore logical link if channel is on BR/EDR */ 46566ed971caSMarcel Holtmann if (chan->local_amp_id != AMP_ID_BREDR) 46571500109bSMat Martineau l2cap_logical_finish_create(chan, hchan); 46581500109bSMat Martineau } else { 46591500109bSMat Martineau l2cap_logical_finish_move(chan, hchan); 46601500109bSMat Martineau } 46611500109bSMat Martineau } 46621500109bSMat Martineau 46633f7a56c4SMat Martineau void l2cap_move_start(struct l2cap_chan *chan) 46643f7a56c4SMat Martineau { 46653f7a56c4SMat Martineau BT_DBG("chan %p", chan); 46663f7a56c4SMat Martineau 46676ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR) { 46683f7a56c4SMat Martineau if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED) 46693f7a56c4SMat Martineau return; 46703f7a56c4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; 46713f7a56c4SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_PREPARE; 46723f7a56c4SMat Martineau /* Placeholder - start physical link setup */ 46733f7a56c4SMat Martineau } else { 46743f7a56c4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; 46753f7a56c4SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 46763f7a56c4SMat Martineau chan->move_id = 0; 46773f7a56c4SMat Martineau l2cap_move_setup(chan); 46783f7a56c4SMat Martineau l2cap_send_move_chan_req(chan, 0); 46793f7a56c4SMat Martineau } 46803f7a56c4SMat Martineau } 46813f7a56c4SMat Martineau 46828eb200bdSMat Martineau static void l2cap_do_create(struct l2cap_chan *chan, int result, 46838eb200bdSMat Martineau u8 local_amp_id, u8 remote_amp_id) 46848eb200bdSMat Martineau { 468562748ca1SAndrei Emeltchenko BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state), 468662748ca1SAndrei Emeltchenko local_amp_id, remote_amp_id); 468762748ca1SAndrei Emeltchenko 468812d6cc60SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 468912d6cc60SAndrei Emeltchenko 469062748ca1SAndrei Emeltchenko /* Outgoing channel on AMP */ 469162748ca1SAndrei Emeltchenko if (chan->state == BT_CONNECT) { 469262748ca1SAndrei Emeltchenko if (result == L2CAP_CR_SUCCESS) { 469362748ca1SAndrei Emeltchenko chan->local_amp_id = local_amp_id; 469462748ca1SAndrei Emeltchenko l2cap_send_create_chan_req(chan, remote_amp_id); 469562748ca1SAndrei Emeltchenko } else { 469662748ca1SAndrei Emeltchenko /* Revert to BR/EDR connect */ 469762748ca1SAndrei Emeltchenko l2cap_send_conn_req(chan); 469862748ca1SAndrei Emeltchenko } 469962748ca1SAndrei Emeltchenko 470062748ca1SAndrei Emeltchenko return; 470162748ca1SAndrei Emeltchenko } 470262748ca1SAndrei Emeltchenko 470362748ca1SAndrei Emeltchenko /* Incoming channel on AMP */ 470462748ca1SAndrei Emeltchenko if (__l2cap_no_conn_pending(chan)) { 47058eb200bdSMat Martineau struct l2cap_conn_rsp rsp; 47068eb200bdSMat Martineau char buf[128]; 47078eb200bdSMat Martineau rsp.scid = cpu_to_le16(chan->dcid); 47088eb200bdSMat Martineau rsp.dcid = cpu_to_le16(chan->scid); 47098eb200bdSMat Martineau 47108eb200bdSMat Martineau if (result == L2CAP_CR_SUCCESS) { 47118eb200bdSMat Martineau /* Send successful response */ 471262cd50e2SAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 471362cd50e2SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 47148eb200bdSMat Martineau } else { 47158eb200bdSMat Martineau /* Send negative response */ 471662cd50e2SAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM); 471762cd50e2SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 47188eb200bdSMat Martineau } 47198eb200bdSMat Martineau 47208eb200bdSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP, 47218eb200bdSMat Martineau sizeof(rsp), &rsp); 47228eb200bdSMat Martineau 47238eb200bdSMat Martineau if (result == L2CAP_CR_SUCCESS) { 4724*f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 47258eb200bdSMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 47268eb200bdSMat Martineau l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn), 47278eb200bdSMat Martineau L2CAP_CONF_REQ, 47288eb200bdSMat Martineau l2cap_build_conf_req(chan, buf), buf); 47298eb200bdSMat Martineau chan->num_conf_req++; 47308eb200bdSMat Martineau } 47318eb200bdSMat Martineau } 47328eb200bdSMat Martineau } 47338eb200bdSMat Martineau 47348eb200bdSMat Martineau static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id, 47358eb200bdSMat Martineau u8 remote_amp_id) 47368eb200bdSMat Martineau { 47378eb200bdSMat Martineau l2cap_move_setup(chan); 47388eb200bdSMat Martineau chan->move_id = local_amp_id; 47398eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP; 47408eb200bdSMat Martineau 47418eb200bdSMat Martineau l2cap_send_move_chan_req(chan, remote_amp_id); 47428eb200bdSMat Martineau } 47438eb200bdSMat Martineau 47448eb200bdSMat Martineau static void l2cap_do_move_respond(struct l2cap_chan *chan, int result) 47458eb200bdSMat Martineau { 47468eb200bdSMat Martineau struct hci_chan *hchan = NULL; 47478eb200bdSMat Martineau 47488eb200bdSMat Martineau /* Placeholder - get hci_chan for logical link */ 47498eb200bdSMat Martineau 47508eb200bdSMat Martineau if (hchan) { 47518eb200bdSMat Martineau if (hchan->state == BT_CONNECTED) { 47528eb200bdSMat Martineau /* Logical link is ready to go */ 47538eb200bdSMat Martineau chan->hs_hcon = hchan->conn; 47548eb200bdSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 47558eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 47568eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); 47578eb200bdSMat Martineau 47588eb200bdSMat Martineau l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); 47598eb200bdSMat Martineau } else { 47608eb200bdSMat Martineau /* Wait for logical link to be ready */ 47618eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 47628eb200bdSMat Martineau } 47638eb200bdSMat Martineau } else { 47648eb200bdSMat Martineau /* Logical link not available */ 47658eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED); 47668eb200bdSMat Martineau } 47678eb200bdSMat Martineau } 47688eb200bdSMat Martineau 47698eb200bdSMat Martineau static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result) 47708eb200bdSMat Martineau { 47718eb200bdSMat Martineau if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { 47728eb200bdSMat Martineau u8 rsp_result; 47738eb200bdSMat Martineau if (result == -EINVAL) 47748eb200bdSMat Martineau rsp_result = L2CAP_MR_BAD_ID; 47758eb200bdSMat Martineau else 47768eb200bdSMat Martineau rsp_result = L2CAP_MR_NOT_ALLOWED; 47778eb200bdSMat Martineau 47788eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, rsp_result); 47798eb200bdSMat Martineau } 47808eb200bdSMat Martineau 47818eb200bdSMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 47828eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 47838eb200bdSMat Martineau 47848eb200bdSMat Martineau /* Restart data transmission */ 47858eb200bdSMat Martineau l2cap_ertm_send(chan); 47868eb200bdSMat Martineau } 47878eb200bdSMat Martineau 4788a514b17fSAndrei Emeltchenko /* Invoke with locked chan */ 4789a514b17fSAndrei Emeltchenko void __l2cap_physical_cfm(struct l2cap_chan *chan, int result) 47908eb200bdSMat Martineau { 4791770bfefaSAndrei Emeltchenko u8 local_amp_id = chan->local_amp_id; 4792fffadc08SAndrei Emeltchenko u8 remote_amp_id = chan->remote_amp_id; 4793770bfefaSAndrei Emeltchenko 47948eb200bdSMat Martineau BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d", 47958eb200bdSMat Martineau chan, result, local_amp_id, remote_amp_id); 47968eb200bdSMat Martineau 47978eb200bdSMat Martineau if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) { 47988eb200bdSMat Martineau l2cap_chan_unlock(chan); 47998eb200bdSMat Martineau return; 48008eb200bdSMat Martineau } 48018eb200bdSMat Martineau 48028eb200bdSMat Martineau if (chan->state != BT_CONNECTED) { 48038eb200bdSMat Martineau l2cap_do_create(chan, result, local_amp_id, remote_amp_id); 48048eb200bdSMat Martineau } else if (result != L2CAP_MR_SUCCESS) { 48058eb200bdSMat Martineau l2cap_do_move_cancel(chan, result); 48068eb200bdSMat Martineau } else { 48078eb200bdSMat Martineau switch (chan->move_role) { 48088eb200bdSMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 48098eb200bdSMat Martineau l2cap_do_move_initiate(chan, local_amp_id, 48108eb200bdSMat Martineau remote_amp_id); 48118eb200bdSMat Martineau break; 48128eb200bdSMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 48138eb200bdSMat Martineau l2cap_do_move_respond(chan, result); 48148eb200bdSMat Martineau break; 48158eb200bdSMat Martineau default: 48168eb200bdSMat Martineau l2cap_do_move_cancel(chan, result); 48178eb200bdSMat Martineau break; 48188eb200bdSMat Martineau } 48198eb200bdSMat Martineau } 48208eb200bdSMat Martineau } 48218eb200bdSMat Martineau 48228d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn, 4823ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 4824ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 48258d5a04a1SMat Martineau { 48268d5a04a1SMat Martineau struct l2cap_move_chan_req *req = data; 48271500109bSMat Martineau struct l2cap_move_chan_rsp rsp; 482802b0fbb9SMat Martineau struct l2cap_chan *chan; 48298d5a04a1SMat Martineau u16 icid = 0; 48308d5a04a1SMat Martineau u16 result = L2CAP_MR_NOT_ALLOWED; 48318d5a04a1SMat Martineau 48328d5a04a1SMat Martineau if (cmd_len != sizeof(*req)) 48338d5a04a1SMat Martineau return -EPROTO; 48348d5a04a1SMat Martineau 48358d5a04a1SMat Martineau icid = le16_to_cpu(req->icid); 48368d5a04a1SMat Martineau 4837ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id); 48388d5a04a1SMat Martineau 4839848566b3SMarcel Holtmann if (!conn->hs_enabled) 48408d5a04a1SMat Martineau return -EINVAL; 48418d5a04a1SMat Martineau 484202b0fbb9SMat Martineau chan = l2cap_get_chan_by_dcid(conn, icid); 484302b0fbb9SMat Martineau if (!chan) { 48441500109bSMat Martineau rsp.icid = cpu_to_le16(icid); 48451500109bSMat Martineau rsp.result = __constant_cpu_to_le16(L2CAP_MR_NOT_ALLOWED); 48461500109bSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP, 48471500109bSMat Martineau sizeof(rsp), &rsp); 484802b0fbb9SMat Martineau return 0; 484902b0fbb9SMat Martineau } 485002b0fbb9SMat Martineau 48511500109bSMat Martineau chan->ident = cmd->ident; 48521500109bSMat Martineau 485302b0fbb9SMat Martineau if (chan->scid < L2CAP_CID_DYN_START || 485402b0fbb9SMat Martineau chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY || 485502b0fbb9SMat Martineau (chan->mode != L2CAP_MODE_ERTM && 485602b0fbb9SMat Martineau chan->mode != L2CAP_MODE_STREAMING)) { 485702b0fbb9SMat Martineau result = L2CAP_MR_NOT_ALLOWED; 485802b0fbb9SMat Martineau goto send_move_response; 485902b0fbb9SMat Martineau } 486002b0fbb9SMat Martineau 486102b0fbb9SMat Martineau if (chan->local_amp_id == req->dest_amp_id) { 486202b0fbb9SMat Martineau result = L2CAP_MR_SAME_ID; 486302b0fbb9SMat Martineau goto send_move_response; 486402b0fbb9SMat Martineau } 486502b0fbb9SMat Martineau 48666ed971caSMarcel Holtmann if (req->dest_amp_id != AMP_ID_BREDR) { 486702b0fbb9SMat Martineau struct hci_dev *hdev; 486802b0fbb9SMat Martineau hdev = hci_dev_get(req->dest_amp_id); 486902b0fbb9SMat Martineau if (!hdev || hdev->dev_type != HCI_AMP || 487002b0fbb9SMat Martineau !test_bit(HCI_UP, &hdev->flags)) { 487102b0fbb9SMat Martineau if (hdev) 487202b0fbb9SMat Martineau hci_dev_put(hdev); 487302b0fbb9SMat Martineau 487402b0fbb9SMat Martineau result = L2CAP_MR_BAD_ID; 487502b0fbb9SMat Martineau goto send_move_response; 487602b0fbb9SMat Martineau } 487702b0fbb9SMat Martineau hci_dev_put(hdev); 487802b0fbb9SMat Martineau } 487902b0fbb9SMat Martineau 488002b0fbb9SMat Martineau /* Detect a move collision. Only send a collision response 488102b0fbb9SMat Martineau * if this side has "lost", otherwise proceed with the move. 488202b0fbb9SMat Martineau * The winner has the larger bd_addr. 488302b0fbb9SMat Martineau */ 488402b0fbb9SMat Martineau if ((__chan_is_moving(chan) || 488502b0fbb9SMat Martineau chan->move_role != L2CAP_MOVE_ROLE_NONE) && 48866f59b904SMarcel Holtmann bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) { 488702b0fbb9SMat Martineau result = L2CAP_MR_COLLISION; 488802b0fbb9SMat Martineau goto send_move_response; 488902b0fbb9SMat Martineau } 489002b0fbb9SMat Martineau 489102b0fbb9SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; 489202b0fbb9SMat Martineau l2cap_move_setup(chan); 489302b0fbb9SMat Martineau chan->move_id = req->dest_amp_id; 489402b0fbb9SMat Martineau icid = chan->dcid; 489502b0fbb9SMat Martineau 48966ed971caSMarcel Holtmann if (req->dest_amp_id == AMP_ID_BREDR) { 489702b0fbb9SMat Martineau /* Moving to BR/EDR */ 489802b0fbb9SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 489902b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 490002b0fbb9SMat Martineau result = L2CAP_MR_PEND; 490102b0fbb9SMat Martineau } else { 490202b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 490302b0fbb9SMat Martineau result = L2CAP_MR_SUCCESS; 490402b0fbb9SMat Martineau } 490502b0fbb9SMat Martineau } else { 490602b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_PREPARE; 490702b0fbb9SMat Martineau /* Placeholder - uncomment when amp functions are available */ 490802b0fbb9SMat Martineau /*amp_accept_physical(chan, req->dest_amp_id);*/ 490902b0fbb9SMat Martineau result = L2CAP_MR_PEND; 491002b0fbb9SMat Martineau } 491102b0fbb9SMat Martineau 491202b0fbb9SMat Martineau send_move_response: 49131500109bSMat Martineau l2cap_send_move_chan_rsp(chan, result); 49148d5a04a1SMat Martineau 491502b0fbb9SMat Martineau l2cap_chan_unlock(chan); 491602b0fbb9SMat Martineau 49178d5a04a1SMat Martineau return 0; 49188d5a04a1SMat Martineau } 49198d5a04a1SMat Martineau 49205b155ef9SMat Martineau static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result) 49215b155ef9SMat Martineau { 49225b155ef9SMat Martineau struct l2cap_chan *chan; 49235b155ef9SMat Martineau struct hci_chan *hchan = NULL; 49245b155ef9SMat Martineau 49255b155ef9SMat Martineau chan = l2cap_get_chan_by_scid(conn, icid); 49265b155ef9SMat Martineau if (!chan) { 49275b155ef9SMat Martineau l2cap_send_move_chan_cfm_icid(conn, icid); 49285b155ef9SMat Martineau return; 49295b155ef9SMat Martineau } 49305b155ef9SMat Martineau 49315b155ef9SMat Martineau __clear_chan_timer(chan); 49325b155ef9SMat Martineau if (result == L2CAP_MR_PEND) 49335b155ef9SMat Martineau __set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT); 49345b155ef9SMat Martineau 49355b155ef9SMat Martineau switch (chan->move_state) { 49365b155ef9SMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_COMP: 49375b155ef9SMat Martineau /* Move confirm will be sent when logical link 49385b155ef9SMat Martineau * is complete. 49395b155ef9SMat Martineau */ 49405b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 49415b155ef9SMat Martineau break; 49425b155ef9SMat Martineau case L2CAP_MOVE_WAIT_RSP_SUCCESS: 49435b155ef9SMat Martineau if (result == L2CAP_MR_PEND) { 49445b155ef9SMat Martineau break; 49455b155ef9SMat Martineau } else if (test_bit(CONN_LOCAL_BUSY, 49465b155ef9SMat Martineau &chan->conn_state)) { 49475b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 49485b155ef9SMat Martineau } else { 49495b155ef9SMat Martineau /* Logical link is up or moving to BR/EDR, 49505b155ef9SMat Martineau * proceed with move 49515b155ef9SMat Martineau */ 49525b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; 49535b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 49545b155ef9SMat Martineau } 49555b155ef9SMat Martineau break; 49565b155ef9SMat Martineau case L2CAP_MOVE_WAIT_RSP: 49575b155ef9SMat Martineau /* Moving to AMP */ 49585b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS) { 49595b155ef9SMat Martineau /* Remote is ready, send confirm immediately 49605b155ef9SMat Martineau * after logical link is ready 49615b155ef9SMat Martineau */ 49625b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 49635b155ef9SMat Martineau } else { 49645b155ef9SMat Martineau /* Both logical link and move success 49655b155ef9SMat Martineau * are required to confirm 49665b155ef9SMat Martineau */ 49675b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP; 49685b155ef9SMat Martineau } 49695b155ef9SMat Martineau 49705b155ef9SMat Martineau /* Placeholder - get hci_chan for logical link */ 49715b155ef9SMat Martineau if (!hchan) { 49725b155ef9SMat Martineau /* Logical link not available */ 49735b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 49745b155ef9SMat Martineau break; 49755b155ef9SMat Martineau } 49765b155ef9SMat Martineau 49775b155ef9SMat Martineau /* If the logical link is not yet connected, do not 49785b155ef9SMat Martineau * send confirmation. 49795b155ef9SMat Martineau */ 49805b155ef9SMat Martineau if (hchan->state != BT_CONNECTED) 49815b155ef9SMat Martineau break; 49825b155ef9SMat Martineau 49835b155ef9SMat Martineau /* Logical link is already ready to go */ 49845b155ef9SMat Martineau 49855b155ef9SMat Martineau chan->hs_hcon = hchan->conn; 49865b155ef9SMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 49875b155ef9SMat Martineau 49885b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS) { 49895b155ef9SMat Martineau /* Can confirm now */ 49905b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 49915b155ef9SMat Martineau } else { 49925b155ef9SMat Martineau /* Now only need move success 49935b155ef9SMat Martineau * to confirm 49945b155ef9SMat Martineau */ 49955b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 49965b155ef9SMat Martineau } 49975b155ef9SMat Martineau 49985b155ef9SMat Martineau l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); 49995b155ef9SMat Martineau break; 50005b155ef9SMat Martineau default: 50015b155ef9SMat Martineau /* Any other amp move state means the move failed. */ 50025b155ef9SMat Martineau chan->move_id = chan->local_amp_id; 50035b155ef9SMat Martineau l2cap_move_done(chan); 50045b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 50055b155ef9SMat Martineau } 50065b155ef9SMat Martineau 50075b155ef9SMat Martineau l2cap_chan_unlock(chan); 50085b155ef9SMat Martineau } 50095b155ef9SMat Martineau 50105b155ef9SMat Martineau static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid, 50115b155ef9SMat Martineau u16 result) 50125b155ef9SMat Martineau { 50135b155ef9SMat Martineau struct l2cap_chan *chan; 50145b155ef9SMat Martineau 50155b155ef9SMat Martineau chan = l2cap_get_chan_by_ident(conn, ident); 50165b155ef9SMat Martineau if (!chan) { 50175b155ef9SMat Martineau /* Could not locate channel, icid is best guess */ 50185b155ef9SMat Martineau l2cap_send_move_chan_cfm_icid(conn, icid); 50195b155ef9SMat Martineau return; 50205b155ef9SMat Martineau } 50215b155ef9SMat Martineau 50225b155ef9SMat Martineau __clear_chan_timer(chan); 50235b155ef9SMat Martineau 50245b155ef9SMat Martineau if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { 50255b155ef9SMat Martineau if (result == L2CAP_MR_COLLISION) { 50265b155ef9SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; 50275b155ef9SMat Martineau } else { 50285b155ef9SMat Martineau /* Cleanup - cancel move */ 50295b155ef9SMat Martineau chan->move_id = chan->local_amp_id; 50305b155ef9SMat Martineau l2cap_move_done(chan); 50315b155ef9SMat Martineau } 50325b155ef9SMat Martineau } 50335b155ef9SMat Martineau 50345b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 50355b155ef9SMat Martineau 50365b155ef9SMat Martineau l2cap_chan_unlock(chan); 50375b155ef9SMat Martineau } 50385b155ef9SMat Martineau 50395b155ef9SMat Martineau static int l2cap_move_channel_rsp(struct l2cap_conn *conn, 5040ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5041ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 50428d5a04a1SMat Martineau { 50438d5a04a1SMat Martineau struct l2cap_move_chan_rsp *rsp = data; 50448d5a04a1SMat Martineau u16 icid, result; 50458d5a04a1SMat Martineau 50468d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 50478d5a04a1SMat Martineau return -EPROTO; 50488d5a04a1SMat Martineau 50498d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 50508d5a04a1SMat Martineau result = le16_to_cpu(rsp->result); 50518d5a04a1SMat Martineau 5052ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 50538d5a04a1SMat Martineau 50545b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND) 50555b155ef9SMat Martineau l2cap_move_continue(conn, icid, result); 50565b155ef9SMat Martineau else 50575b155ef9SMat Martineau l2cap_move_fail(conn, cmd->ident, icid, result); 50588d5a04a1SMat Martineau 50598d5a04a1SMat Martineau return 0; 50608d5a04a1SMat Martineau } 50618d5a04a1SMat Martineau 50625f3847a4SMat Martineau static int l2cap_move_channel_confirm(struct l2cap_conn *conn, 5063ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5064ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 50658d5a04a1SMat Martineau { 50668d5a04a1SMat Martineau struct l2cap_move_chan_cfm *cfm = data; 50675f3847a4SMat Martineau struct l2cap_chan *chan; 50688d5a04a1SMat Martineau u16 icid, result; 50698d5a04a1SMat Martineau 50708d5a04a1SMat Martineau if (cmd_len != sizeof(*cfm)) 50718d5a04a1SMat Martineau return -EPROTO; 50728d5a04a1SMat Martineau 50738d5a04a1SMat Martineau icid = le16_to_cpu(cfm->icid); 50748d5a04a1SMat Martineau result = le16_to_cpu(cfm->result); 50758d5a04a1SMat Martineau 5076ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 50778d5a04a1SMat Martineau 50785f3847a4SMat Martineau chan = l2cap_get_chan_by_dcid(conn, icid); 50795f3847a4SMat Martineau if (!chan) { 50805f3847a4SMat Martineau /* Spec requires a response even if the icid was not found */ 50818d5a04a1SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 50825f3847a4SMat Martineau return 0; 50835f3847a4SMat Martineau } 50845f3847a4SMat Martineau 50855f3847a4SMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) { 50865f3847a4SMat Martineau if (result == L2CAP_MC_CONFIRMED) { 50875f3847a4SMat Martineau chan->local_amp_id = chan->move_id; 50886ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR) 50895f3847a4SMat Martineau __release_logical_link(chan); 50905f3847a4SMat Martineau } else { 50915f3847a4SMat Martineau chan->move_id = chan->local_amp_id; 50925f3847a4SMat Martineau } 50935f3847a4SMat Martineau 50945f3847a4SMat Martineau l2cap_move_done(chan); 50955f3847a4SMat Martineau } 50965f3847a4SMat Martineau 50975f3847a4SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 50985f3847a4SMat Martineau 50995f3847a4SMat Martineau l2cap_chan_unlock(chan); 51008d5a04a1SMat Martineau 51018d5a04a1SMat Martineau return 0; 51028d5a04a1SMat Martineau } 51038d5a04a1SMat Martineau 51048d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, 5105ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5106ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 51078d5a04a1SMat Martineau { 51088d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp *rsp = data; 51093fd71a0aSMat Martineau struct l2cap_chan *chan; 51108d5a04a1SMat Martineau u16 icid; 51118d5a04a1SMat Martineau 51128d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 51138d5a04a1SMat Martineau return -EPROTO; 51148d5a04a1SMat Martineau 51158d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 51168d5a04a1SMat Martineau 5117ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 51188d5a04a1SMat Martineau 51193fd71a0aSMat Martineau chan = l2cap_get_chan_by_scid(conn, icid); 51203fd71a0aSMat Martineau if (!chan) 51213fd71a0aSMat Martineau return 0; 51223fd71a0aSMat Martineau 51233fd71a0aSMat Martineau __clear_chan_timer(chan); 51243fd71a0aSMat Martineau 51253fd71a0aSMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) { 51263fd71a0aSMat Martineau chan->local_amp_id = chan->move_id; 51273fd71a0aSMat Martineau 51286ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan) 51293fd71a0aSMat Martineau __release_logical_link(chan); 51303fd71a0aSMat Martineau 51313fd71a0aSMat Martineau l2cap_move_done(chan); 51323fd71a0aSMat Martineau } 51333fd71a0aSMat Martineau 51343fd71a0aSMat Martineau l2cap_chan_unlock(chan); 51353fd71a0aSMat Martineau 51368d5a04a1SMat Martineau return 0; 51378d5a04a1SMat Martineau } 51388d5a04a1SMat Martineau 5139e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency, 5140de73115aSClaudio Takahasi u16 to_multiplier) 5141de73115aSClaudio Takahasi { 5142de73115aSClaudio Takahasi u16 max_latency; 5143de73115aSClaudio Takahasi 5144de73115aSClaudio Takahasi if (min > max || min < 6 || max > 3200) 5145de73115aSClaudio Takahasi return -EINVAL; 5146de73115aSClaudio Takahasi 5147de73115aSClaudio Takahasi if (to_multiplier < 10 || to_multiplier > 3200) 5148de73115aSClaudio Takahasi return -EINVAL; 5149de73115aSClaudio Takahasi 5150de73115aSClaudio Takahasi if (max >= to_multiplier * 8) 5151de73115aSClaudio Takahasi return -EINVAL; 5152de73115aSClaudio Takahasi 5153de73115aSClaudio Takahasi max_latency = (to_multiplier * 8 / max) - 1; 5154de73115aSClaudio Takahasi if (latency > 499 || latency > max_latency) 5155de73115aSClaudio Takahasi return -EINVAL; 5156de73115aSClaudio Takahasi 5157de73115aSClaudio Takahasi return 0; 5158de73115aSClaudio Takahasi } 5159de73115aSClaudio Takahasi 5160de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, 51612d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, 51622d792818SGustavo Padovan u8 *data) 5163de73115aSClaudio Takahasi { 5164de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon; 5165de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req; 5166de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp; 5167de73115aSClaudio Takahasi u16 min, max, latency, to_multiplier, cmd_len; 51682ce603ebSClaudio Takahasi int err; 5169de73115aSClaudio Takahasi 5170de73115aSClaudio Takahasi if (!(hcon->link_mode & HCI_LM_MASTER)) 5171de73115aSClaudio Takahasi return -EINVAL; 5172de73115aSClaudio Takahasi 5173de73115aSClaudio Takahasi cmd_len = __le16_to_cpu(cmd->len); 5174de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) 5175de73115aSClaudio Takahasi return -EPROTO; 5176de73115aSClaudio Takahasi 5177de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data; 5178de73115aSClaudio Takahasi min = __le16_to_cpu(req->min); 5179de73115aSClaudio Takahasi max = __le16_to_cpu(req->max); 5180de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency); 5181de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier); 5182de73115aSClaudio Takahasi 5183de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", 5184de73115aSClaudio Takahasi min, max, latency, to_multiplier); 5185de73115aSClaudio Takahasi 5186de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp)); 51872ce603ebSClaudio Takahasi 51882ce603ebSClaudio Takahasi err = l2cap_check_conn_param(min, max, latency, to_multiplier); 51892ce603ebSClaudio Takahasi if (err) 5190ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); 5191de73115aSClaudio Takahasi else 5192ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); 5193de73115aSClaudio Takahasi 5194de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, 5195de73115aSClaudio Takahasi sizeof(rsp), &rsp); 5196de73115aSClaudio Takahasi 51972ce603ebSClaudio Takahasi if (!err) 51982ce603ebSClaudio Takahasi hci_le_conn_update(hcon, min, max, latency, to_multiplier); 51992ce603ebSClaudio Takahasi 5200de73115aSClaudio Takahasi return 0; 5201de73115aSClaudio Takahasi } 5202de73115aSClaudio Takahasi 52033300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, 52042d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len, 52052d792818SGustavo Padovan u8 *data) 52063300d9a9SClaudio Takahasi { 52073300d9a9SClaudio Takahasi int err = 0; 52083300d9a9SClaudio Takahasi 52093300d9a9SClaudio Takahasi switch (cmd->code) { 52103300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 5211cb3b3152SJohan Hedberg l2cap_command_rej(conn, cmd, cmd_len, data); 52123300d9a9SClaudio Takahasi break; 52133300d9a9SClaudio Takahasi 52143300d9a9SClaudio Takahasi case L2CAP_CONN_REQ: 5215cb3b3152SJohan Hedberg err = l2cap_connect_req(conn, cmd, cmd_len, data); 52163300d9a9SClaudio Takahasi break; 52173300d9a9SClaudio Takahasi 52183300d9a9SClaudio Takahasi case L2CAP_CONN_RSP: 5219f5a2598dSMat Martineau case L2CAP_CREATE_CHAN_RSP: 52209245e737SJohan Hedberg l2cap_connect_create_rsp(conn, cmd, cmd_len, data); 52213300d9a9SClaudio Takahasi break; 52223300d9a9SClaudio Takahasi 52233300d9a9SClaudio Takahasi case L2CAP_CONF_REQ: 52243300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data); 52253300d9a9SClaudio Takahasi break; 52263300d9a9SClaudio Takahasi 52273300d9a9SClaudio Takahasi case L2CAP_CONF_RSP: 52289245e737SJohan Hedberg l2cap_config_rsp(conn, cmd, cmd_len, data); 52293300d9a9SClaudio Takahasi break; 52303300d9a9SClaudio Takahasi 52313300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ: 5232cb3b3152SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data); 52333300d9a9SClaudio Takahasi break; 52343300d9a9SClaudio Takahasi 52353300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP: 52369245e737SJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data); 52373300d9a9SClaudio Takahasi break; 52383300d9a9SClaudio Takahasi 52393300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ: 52403300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data); 52413300d9a9SClaudio Takahasi break; 52423300d9a9SClaudio Takahasi 52433300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP: 52443300d9a9SClaudio Takahasi break; 52453300d9a9SClaudio Takahasi 52463300d9a9SClaudio Takahasi case L2CAP_INFO_REQ: 5247cb3b3152SJohan Hedberg err = l2cap_information_req(conn, cmd, cmd_len, data); 52483300d9a9SClaudio Takahasi break; 52493300d9a9SClaudio Takahasi 52503300d9a9SClaudio Takahasi case L2CAP_INFO_RSP: 52519245e737SJohan Hedberg l2cap_information_rsp(conn, cmd, cmd_len, data); 52523300d9a9SClaudio Takahasi break; 52533300d9a9SClaudio Takahasi 5254f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_REQ: 5255f94ff6ffSMat Martineau err = l2cap_create_channel_req(conn, cmd, cmd_len, data); 5256f94ff6ffSMat Martineau break; 5257f94ff6ffSMat Martineau 52588d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_REQ: 52598d5a04a1SMat Martineau err = l2cap_move_channel_req(conn, cmd, cmd_len, data); 52608d5a04a1SMat Martineau break; 52618d5a04a1SMat Martineau 52628d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_RSP: 52639245e737SJohan Hedberg l2cap_move_channel_rsp(conn, cmd, cmd_len, data); 52648d5a04a1SMat Martineau break; 52658d5a04a1SMat Martineau 52668d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM: 52678d5a04a1SMat Martineau err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data); 52688d5a04a1SMat Martineau break; 52698d5a04a1SMat Martineau 52708d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM_RSP: 52719245e737SJohan Hedberg l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data); 52728d5a04a1SMat Martineau break; 52738d5a04a1SMat Martineau 52743300d9a9SClaudio Takahasi default: 52753300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code); 52763300d9a9SClaudio Takahasi err = -EINVAL; 52773300d9a9SClaudio Takahasi break; 52783300d9a9SClaudio Takahasi } 52793300d9a9SClaudio Takahasi 52803300d9a9SClaudio Takahasi return err; 52813300d9a9SClaudio Takahasi } 52823300d9a9SClaudio Takahasi 52833300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, 52843300d9a9SClaudio Takahasi struct l2cap_cmd_hdr *cmd, u8 *data) 52853300d9a9SClaudio Takahasi { 52863300d9a9SClaudio Takahasi switch (cmd->code) { 52873300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 52883300d9a9SClaudio Takahasi return 0; 52893300d9a9SClaudio Takahasi 52903300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ: 5291de73115aSClaudio Takahasi return l2cap_conn_param_update_req(conn, cmd, data); 52923300d9a9SClaudio Takahasi 52933300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP: 52943300d9a9SClaudio Takahasi return 0; 52953300d9a9SClaudio Takahasi 52963300d9a9SClaudio Takahasi default: 52973300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code); 52983300d9a9SClaudio Takahasi return -EINVAL; 52993300d9a9SClaudio Takahasi } 53003300d9a9SClaudio Takahasi } 53013300d9a9SClaudio Takahasi 5302c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn, 5303c5623556SJohan Hedberg struct sk_buff *skb) 5304c5623556SJohan Hedberg { 530569c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon; 53064f3e219dSMarcel Holtmann struct l2cap_cmd_hdr *cmd; 53074f3e219dSMarcel Holtmann u16 len; 5308c5623556SJohan Hedberg int err; 5309c5623556SJohan Hedberg 531069c4e4e8SJohan Hedberg if (hcon->type != LE_LINK) 53113b166295SMarcel Holtmann goto drop; 531269c4e4e8SJohan Hedberg 53134f3e219dSMarcel Holtmann if (skb->len < L2CAP_CMD_HDR_SIZE) 53144f3e219dSMarcel Holtmann goto drop; 5315c5623556SJohan Hedberg 53164f3e219dSMarcel Holtmann cmd = (void *) skb->data; 53174f3e219dSMarcel Holtmann skb_pull(skb, L2CAP_CMD_HDR_SIZE); 5318c5623556SJohan Hedberg 53194f3e219dSMarcel Holtmann len = le16_to_cpu(cmd->len); 5320c5623556SJohan Hedberg 53214f3e219dSMarcel Holtmann BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident); 53224f3e219dSMarcel Holtmann 53234f3e219dSMarcel Holtmann if (len != skb->len || !cmd->ident) { 5324c5623556SJohan Hedberg BT_DBG("corrupted command"); 53254f3e219dSMarcel Holtmann goto drop; 5326c5623556SJohan Hedberg } 5327c5623556SJohan Hedberg 53284f3e219dSMarcel Holtmann err = l2cap_le_sig_cmd(conn, cmd, skb->data); 5329c5623556SJohan Hedberg if (err) { 5330c5623556SJohan Hedberg struct l2cap_cmd_rej_unk rej; 5331c5623556SJohan Hedberg 5332c5623556SJohan Hedberg BT_ERR("Wrong link type (%d)", err); 5333c5623556SJohan Hedberg 5334a521149aSJohan Hedberg rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 53354f3e219dSMarcel Holtmann l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 5336c5623556SJohan Hedberg sizeof(rej), &rej); 5337c5623556SJohan Hedberg } 5338c5623556SJohan Hedberg 53393b166295SMarcel Holtmann drop: 5340c5623556SJohan Hedberg kfree_skb(skb); 5341c5623556SJohan Hedberg } 5342c5623556SJohan Hedberg 53433300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn, 53443300d9a9SClaudio Takahasi struct sk_buff *skb) 53450a708f8fSGustavo F. Padovan { 534669c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon; 53470a708f8fSGustavo F. Padovan u8 *data = skb->data; 53480a708f8fSGustavo F. Padovan int len = skb->len; 53490a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr cmd; 53503300d9a9SClaudio Takahasi int err; 53510a708f8fSGustavo F. Padovan 53520a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb); 53530a708f8fSGustavo F. Padovan 535469c4e4e8SJohan Hedberg if (hcon->type != ACL_LINK) 53553b166295SMarcel Holtmann goto drop; 535669c4e4e8SJohan Hedberg 53570a708f8fSGustavo F. Padovan while (len >= L2CAP_CMD_HDR_SIZE) { 53580a708f8fSGustavo F. Padovan u16 cmd_len; 53590a708f8fSGustavo F. Padovan memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); 53600a708f8fSGustavo F. Padovan data += L2CAP_CMD_HDR_SIZE; 53610a708f8fSGustavo F. Padovan len -= L2CAP_CMD_HDR_SIZE; 53620a708f8fSGustavo F. Padovan 53630a708f8fSGustavo F. Padovan cmd_len = le16_to_cpu(cmd.len); 53640a708f8fSGustavo F. Padovan 53652d792818SGustavo Padovan BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, 53662d792818SGustavo Padovan cmd.ident); 53670a708f8fSGustavo F. Padovan 53680a708f8fSGustavo F. Padovan if (cmd_len > len || !cmd.ident) { 53690a708f8fSGustavo F. Padovan BT_DBG("corrupted command"); 53700a708f8fSGustavo F. Padovan break; 53710a708f8fSGustavo F. Padovan } 53720a708f8fSGustavo F. Padovan 53733300d9a9SClaudio Takahasi err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data); 53740a708f8fSGustavo F. Padovan if (err) { 5375e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk rej; 53762c6d1a2eSGustavo F. Padovan 53772c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err); 53780a708f8fSGustavo F. Padovan 5379a521149aSJohan Hedberg rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 53802d792818SGustavo Padovan l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, 53812d792818SGustavo Padovan sizeof(rej), &rej); 53820a708f8fSGustavo F. Padovan } 53830a708f8fSGustavo F. Padovan 53840a708f8fSGustavo F. Padovan data += cmd_len; 53850a708f8fSGustavo F. Padovan len -= cmd_len; 53860a708f8fSGustavo F. Padovan } 53870a708f8fSGustavo F. Padovan 53883b166295SMarcel Holtmann drop: 53890a708f8fSGustavo F. Padovan kfree_skb(skb); 53900a708f8fSGustavo F. Padovan } 53910a708f8fSGustavo F. Padovan 539247d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) 53930a708f8fSGustavo F. Padovan { 53940a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs; 5395e4ca6d98SAndrei Emeltchenko int hdr_size; 5396e4ca6d98SAndrei Emeltchenko 5397e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 5398e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE; 5399e4ca6d98SAndrei Emeltchenko else 5400e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE; 54010a708f8fSGustavo F. Padovan 540247d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 540303a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE); 54040a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len); 54050a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); 54060a708f8fSGustavo F. Padovan 54070a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs) 54080a708f8fSGustavo F. Padovan return -EBADMSG; 54090a708f8fSGustavo F. Padovan } 54100a708f8fSGustavo F. Padovan return 0; 54110a708f8fSGustavo F. Padovan } 54120a708f8fSGustavo F. Padovan 54136ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) 54140a708f8fSGustavo F. Padovan { 5415e31f7633SMat Martineau struct l2cap_ctrl control; 54160a708f8fSGustavo F. Padovan 5417e31f7633SMat Martineau BT_DBG("chan %p", chan); 54180a708f8fSGustavo F. Padovan 5419e31f7633SMat Martineau memset(&control, 0, sizeof(control)); 5420e31f7633SMat Martineau control.sframe = 1; 5421e31f7633SMat Martineau control.final = 1; 5422e31f7633SMat Martineau control.reqseq = chan->buffer_seq; 5423e31f7633SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 54240a708f8fSGustavo F. Padovan 5425e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 5426e31f7633SMat Martineau control.super = L2CAP_SUPER_RNR; 5427e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 54280a708f8fSGustavo F. Padovan } 54290a708f8fSGustavo F. Padovan 5430e31f7633SMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 5431e31f7633SMat Martineau chan->unacked_frames > 0) 5432e31f7633SMat Martineau __set_retrans_timer(chan); 54330a708f8fSGustavo F. Padovan 5434e31f7633SMat Martineau /* Send pending iframes */ 5435525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 54360a708f8fSGustavo F. Padovan 5437e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 5438e31f7633SMat Martineau test_bit(CONN_SEND_FBIT, &chan->conn_state)) { 5439e31f7633SMat Martineau /* F-bit wasn't sent in an s-frame or i-frame yet, so 5440e31f7633SMat Martineau * send it now. 5441e31f7633SMat Martineau */ 5442e31f7633SMat Martineau control.super = L2CAP_SUPER_RR; 5443e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 54440a708f8fSGustavo F. Padovan } 54450a708f8fSGustavo F. Padovan } 54460a708f8fSGustavo F. Padovan 54472d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag, 54482d792818SGustavo Padovan struct sk_buff **last_frag) 54490a708f8fSGustavo F. Padovan { 545084084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments 545184084a31SMat Martineau * skb->data_len reflects only data in fragments 545284084a31SMat Martineau */ 545384084a31SMat Martineau if (!skb_has_frag_list(skb)) 545484084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag; 545584084a31SMat Martineau 545684084a31SMat Martineau new_frag->next = NULL; 545784084a31SMat Martineau 545884084a31SMat Martineau (*last_frag)->next = new_frag; 545984084a31SMat Martineau *last_frag = new_frag; 546084084a31SMat Martineau 546184084a31SMat Martineau skb->len += new_frag->len; 546284084a31SMat Martineau skb->data_len += new_frag->len; 546384084a31SMat Martineau skb->truesize += new_frag->truesize; 546484084a31SMat Martineau } 546584084a31SMat Martineau 54664b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, 54674b51dae9SMat Martineau struct l2cap_ctrl *control) 546884084a31SMat Martineau { 546984084a31SMat Martineau int err = -EINVAL; 54700a708f8fSGustavo F. Padovan 54714b51dae9SMat Martineau switch (control->sar) { 54727e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED: 547384084a31SMat Martineau if (chan->sdu) 547484084a31SMat Martineau break; 54750a708f8fSGustavo F. Padovan 547680b98027SGustavo Padovan err = chan->ops->recv(chan, skb); 547784084a31SMat Martineau break; 54780a708f8fSGustavo F. Padovan 54797e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START: 548084084a31SMat Martineau if (chan->sdu) 548184084a31SMat Martineau break; 54820a708f8fSGustavo F. Padovan 54836f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data); 548403a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE); 54850a708f8fSGustavo F. Padovan 548684084a31SMat Martineau if (chan->sdu_len > chan->imtu) { 548784084a31SMat Martineau err = -EMSGSIZE; 548884084a31SMat Martineau break; 548984084a31SMat Martineau } 54900a708f8fSGustavo F. Padovan 549184084a31SMat Martineau if (skb->len >= chan->sdu_len) 549284084a31SMat Martineau break; 549384084a31SMat Martineau 549484084a31SMat Martineau chan->sdu = skb; 549584084a31SMat Martineau chan->sdu_last_frag = skb; 549684084a31SMat Martineau 549784084a31SMat Martineau skb = NULL; 549884084a31SMat Martineau err = 0; 54990a708f8fSGustavo F. Padovan break; 55000a708f8fSGustavo F. Padovan 55017e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE: 55026f61fd47SGustavo F. Padovan if (!chan->sdu) 550384084a31SMat Martineau break; 55040a708f8fSGustavo F. Padovan 550584084a31SMat Martineau append_skb_frag(chan->sdu, skb, 550684084a31SMat Martineau &chan->sdu_last_frag); 550784084a31SMat Martineau skb = NULL; 55080a708f8fSGustavo F. Padovan 550984084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len) 551084084a31SMat Martineau break; 55110a708f8fSGustavo F. Padovan 551284084a31SMat Martineau err = 0; 55130a708f8fSGustavo F. Padovan break; 55140a708f8fSGustavo F. Padovan 55157e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END: 55166f61fd47SGustavo F. Padovan if (!chan->sdu) 551784084a31SMat Martineau break; 55180a708f8fSGustavo F. Padovan 551984084a31SMat Martineau append_skb_frag(chan->sdu, skb, 552084084a31SMat Martineau &chan->sdu_last_frag); 552184084a31SMat Martineau skb = NULL; 55220a708f8fSGustavo F. Padovan 552384084a31SMat Martineau if (chan->sdu->len != chan->sdu_len) 552484084a31SMat Martineau break; 55250a708f8fSGustavo F. Padovan 552680b98027SGustavo Padovan err = chan->ops->recv(chan, chan->sdu); 55270a708f8fSGustavo F. Padovan 552884084a31SMat Martineau if (!err) { 552984084a31SMat Martineau /* Reassembly complete */ 553084084a31SMat Martineau chan->sdu = NULL; 553184084a31SMat Martineau chan->sdu_last_frag = NULL; 553284084a31SMat Martineau chan->sdu_len = 0; 55330a708f8fSGustavo F. Padovan } 55340a708f8fSGustavo F. Padovan break; 55350a708f8fSGustavo F. Padovan } 55360a708f8fSGustavo F. Padovan 553784084a31SMat Martineau if (err) { 55380a708f8fSGustavo F. Padovan kfree_skb(skb); 55396f61fd47SGustavo F. Padovan kfree_skb(chan->sdu); 55406f61fd47SGustavo F. Padovan chan->sdu = NULL; 554184084a31SMat Martineau chan->sdu_last_frag = NULL; 554284084a31SMat Martineau chan->sdu_len = 0; 554384084a31SMat Martineau } 55440a708f8fSGustavo F. Padovan 554584084a31SMat Martineau return err; 55460a708f8fSGustavo F. Padovan } 55470a708f8fSGustavo F. Padovan 554832b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan) 554932b32735SMat Martineau { 555032b32735SMat Martineau /* Placeholder */ 555132b32735SMat Martineau return 0; 555232b32735SMat Martineau } 555332b32735SMat Martineau 5554e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 55550a708f8fSGustavo F. Padovan { 555661aa4f5bSMat Martineau u8 event; 555761aa4f5bSMat Martineau 555861aa4f5bSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 555961aa4f5bSMat Martineau return; 556061aa4f5bSMat Martineau 556161aa4f5bSMat Martineau event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR; 5562401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, event); 55630a708f8fSGustavo F. Padovan } 55640a708f8fSGustavo F. Padovan 5565d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan) 5566d2a7ac5dSMat Martineau { 556763838725SMat Martineau int err = 0; 556863838725SMat Martineau /* Pass sequential frames to l2cap_reassemble_sdu() 556963838725SMat Martineau * until a gap is encountered. 557063838725SMat Martineau */ 557163838725SMat Martineau 557263838725SMat Martineau BT_DBG("chan %p", chan); 557363838725SMat Martineau 557463838725SMat Martineau while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 557563838725SMat Martineau struct sk_buff *skb; 557663838725SMat Martineau BT_DBG("Searching for skb with txseq %d (queue len %d)", 557763838725SMat Martineau chan->buffer_seq, skb_queue_len(&chan->srej_q)); 557863838725SMat Martineau 557963838725SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq); 558063838725SMat Martineau 558163838725SMat Martineau if (!skb) 558263838725SMat Martineau break; 558363838725SMat Martineau 558463838725SMat Martineau skb_unlink(skb, &chan->srej_q); 558563838725SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 558663838725SMat Martineau err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->control); 558763838725SMat Martineau if (err) 558863838725SMat Martineau break; 558963838725SMat Martineau } 559063838725SMat Martineau 559163838725SMat Martineau if (skb_queue_empty(&chan->srej_q)) { 559263838725SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 559363838725SMat Martineau l2cap_send_ack(chan); 559463838725SMat Martineau } 559563838725SMat Martineau 559663838725SMat Martineau return err; 5597d2a7ac5dSMat Martineau } 5598d2a7ac5dSMat Martineau 5599d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan, 5600d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 5601d2a7ac5dSMat Martineau { 5602f80842a8SMat Martineau struct sk_buff *skb; 5603f80842a8SMat Martineau 5604f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 5605f80842a8SMat Martineau 5606f80842a8SMat Martineau if (control->reqseq == chan->next_tx_seq) { 5607f80842a8SMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 56085e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 5609f80842a8SMat Martineau return; 5610f80842a8SMat Martineau } 5611f80842a8SMat Martineau 5612f80842a8SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 5613f80842a8SMat Martineau 5614f80842a8SMat Martineau if (skb == NULL) { 5615f80842a8SMat Martineau BT_DBG("Seq %d not available for retransmission", 5616f80842a8SMat Martineau control->reqseq); 5617f80842a8SMat Martineau return; 5618f80842a8SMat Martineau } 5619f80842a8SMat Martineau 5620f80842a8SMat Martineau if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) { 5621f80842a8SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 56225e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 5623f80842a8SMat Martineau return; 5624f80842a8SMat Martineau } 5625f80842a8SMat Martineau 5626f80842a8SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 5627f80842a8SMat Martineau 5628f80842a8SMat Martineau if (control->poll) { 5629f80842a8SMat Martineau l2cap_pass_to_tx(chan, control); 5630f80842a8SMat Martineau 5631f80842a8SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 5632f80842a8SMat Martineau l2cap_retransmit(chan, control); 5633f80842a8SMat Martineau l2cap_ertm_send(chan); 5634f80842a8SMat Martineau 5635f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 5636f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 5637f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 5638f80842a8SMat Martineau } 5639f80842a8SMat Martineau } else { 5640f80842a8SMat Martineau l2cap_pass_to_tx_fbit(chan, control); 5641f80842a8SMat Martineau 5642f80842a8SMat Martineau if (control->final) { 5643f80842a8SMat Martineau if (chan->srej_save_reqseq != control->reqseq || 5644f80842a8SMat Martineau !test_and_clear_bit(CONN_SREJ_ACT, 5645f80842a8SMat Martineau &chan->conn_state)) 5646f80842a8SMat Martineau l2cap_retransmit(chan, control); 5647f80842a8SMat Martineau } else { 5648f80842a8SMat Martineau l2cap_retransmit(chan, control); 5649f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 5650f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 5651f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 5652f80842a8SMat Martineau } 5653f80842a8SMat Martineau } 5654f80842a8SMat Martineau } 5655d2a7ac5dSMat Martineau } 5656d2a7ac5dSMat Martineau 5657d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan, 5658d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 5659d2a7ac5dSMat Martineau { 5660fcd289dfSMat Martineau struct sk_buff *skb; 5661fcd289dfSMat Martineau 5662fcd289dfSMat Martineau BT_DBG("chan %p, control %p", chan, control); 5663fcd289dfSMat Martineau 5664fcd289dfSMat Martineau if (control->reqseq == chan->next_tx_seq) { 5665fcd289dfSMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 56665e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 5667fcd289dfSMat Martineau return; 5668fcd289dfSMat Martineau } 5669fcd289dfSMat Martineau 5670fcd289dfSMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 5671fcd289dfSMat Martineau 5672fcd289dfSMat Martineau if (chan->max_tx && skb && 5673fcd289dfSMat Martineau bt_cb(skb)->control.retries >= chan->max_tx) { 5674fcd289dfSMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 56755e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 5676fcd289dfSMat Martineau return; 5677fcd289dfSMat Martineau } 5678fcd289dfSMat Martineau 5679fcd289dfSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 5680fcd289dfSMat Martineau 5681fcd289dfSMat Martineau l2cap_pass_to_tx(chan, control); 5682fcd289dfSMat Martineau 5683fcd289dfSMat Martineau if (control->final) { 5684fcd289dfSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 5685fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 5686fcd289dfSMat Martineau } else { 5687fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 5688fcd289dfSMat Martineau l2cap_ertm_send(chan); 5689fcd289dfSMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) 5690fcd289dfSMat Martineau set_bit(CONN_REJ_ACT, &chan->conn_state); 5691fcd289dfSMat Martineau } 5692d2a7ac5dSMat Martineau } 5693d2a7ac5dSMat Martineau 56944b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) 56954b51dae9SMat Martineau { 56964b51dae9SMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 56974b51dae9SMat Martineau 56984b51dae9SMat Martineau BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq, 56994b51dae9SMat Martineau chan->expected_tx_seq); 57004b51dae9SMat Martineau 57014b51dae9SMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 57024b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 57034b51dae9SMat Martineau chan->tx_win) { 57044b51dae9SMat Martineau /* See notes below regarding "double poll" and 57054b51dae9SMat Martineau * invalid packets. 57064b51dae9SMat Martineau */ 57074b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 57084b51dae9SMat Martineau BT_DBG("Invalid/Ignore - after SREJ"); 57094b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 57104b51dae9SMat Martineau } else { 57114b51dae9SMat Martineau BT_DBG("Invalid - in window after SREJ sent"); 57124b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 57134b51dae9SMat Martineau } 57144b51dae9SMat Martineau } 57154b51dae9SMat Martineau 57164b51dae9SMat Martineau if (chan->srej_list.head == txseq) { 57174b51dae9SMat Martineau BT_DBG("Expected SREJ"); 57184b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED_SREJ; 57194b51dae9SMat Martineau } 57204b51dae9SMat Martineau 57214b51dae9SMat Martineau if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) { 57224b51dae9SMat Martineau BT_DBG("Duplicate SREJ - txseq already stored"); 57234b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE_SREJ; 57244b51dae9SMat Martineau } 57254b51dae9SMat Martineau 57264b51dae9SMat Martineau if (l2cap_seq_list_contains(&chan->srej_list, txseq)) { 57274b51dae9SMat Martineau BT_DBG("Unexpected SREJ - not requested"); 57284b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED_SREJ; 57294b51dae9SMat Martineau } 57304b51dae9SMat Martineau } 57314b51dae9SMat Martineau 57324b51dae9SMat Martineau if (chan->expected_tx_seq == txseq) { 57334b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 57344b51dae9SMat Martineau chan->tx_win) { 57354b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 57364b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 57374b51dae9SMat Martineau } else { 57384b51dae9SMat Martineau BT_DBG("Expected"); 57394b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED; 57404b51dae9SMat Martineau } 57414b51dae9SMat Martineau } 57424b51dae9SMat Martineau 57434b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) < 57442d792818SGustavo Padovan __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) { 57454b51dae9SMat Martineau BT_DBG("Duplicate - expected_tx_seq later than txseq"); 57464b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE; 57474b51dae9SMat Martineau } 57484b51dae9SMat Martineau 57494b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) { 57504b51dae9SMat Martineau /* A source of invalid packets is a "double poll" condition, 57514b51dae9SMat Martineau * where delays cause us to send multiple poll packets. If 57524b51dae9SMat Martineau * the remote stack receives and processes both polls, 57534b51dae9SMat Martineau * sequence numbers can wrap around in such a way that a 57544b51dae9SMat Martineau * resent frame has a sequence number that looks like new data 57554b51dae9SMat Martineau * with a sequence gap. This would trigger an erroneous SREJ 57564b51dae9SMat Martineau * request. 57574b51dae9SMat Martineau * 57584b51dae9SMat Martineau * Fortunately, this is impossible with a tx window that's 57594b51dae9SMat Martineau * less than half of the maximum sequence number, which allows 57604b51dae9SMat Martineau * invalid frames to be safely ignored. 57614b51dae9SMat Martineau * 57624b51dae9SMat Martineau * With tx window sizes greater than half of the tx window 57634b51dae9SMat Martineau * maximum, the frame is invalid and cannot be ignored. This 57644b51dae9SMat Martineau * causes a disconnect. 57654b51dae9SMat Martineau */ 57664b51dae9SMat Martineau 57674b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 57684b51dae9SMat Martineau BT_DBG("Invalid/Ignore - txseq outside tx window"); 57694b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 57704b51dae9SMat Martineau } else { 57714b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 57724b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 57734b51dae9SMat Martineau } 57744b51dae9SMat Martineau } else { 57754b51dae9SMat Martineau BT_DBG("Unexpected - txseq indicates missing frames"); 57764b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED; 57774b51dae9SMat Martineau } 57784b51dae9SMat Martineau } 57794b51dae9SMat Martineau 5780d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan, 5781d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 5782d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 5783d2a7ac5dSMat Martineau { 5784d2a7ac5dSMat Martineau int err = 0; 5785941247f9SPeter Senna Tschudin bool skb_in_use = false; 5786d2a7ac5dSMat Martineau 5787d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 5788d2a7ac5dSMat Martineau event); 5789d2a7ac5dSMat Martineau 5790d2a7ac5dSMat Martineau switch (event) { 5791d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 5792d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, control->txseq)) { 5793d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 5794d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 5795d2a7ac5dSMat Martineau 5796d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 5797d2a7ac5dSMat Martineau BT_DBG("Busy, discarding expected seq %d", 5798d2a7ac5dSMat Martineau control->txseq); 5799d2a7ac5dSMat Martineau break; 5800d2a7ac5dSMat Martineau } 5801d2a7ac5dSMat Martineau 5802d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, 5803d2a7ac5dSMat Martineau control->txseq); 5804d2a7ac5dSMat Martineau 5805d2a7ac5dSMat Martineau chan->buffer_seq = chan->expected_tx_seq; 5806941247f9SPeter Senna Tschudin skb_in_use = true; 5807d2a7ac5dSMat Martineau 5808d2a7ac5dSMat Martineau err = l2cap_reassemble_sdu(chan, skb, control); 5809d2a7ac5dSMat Martineau if (err) 5810d2a7ac5dSMat Martineau break; 5811d2a7ac5dSMat Martineau 5812d2a7ac5dSMat Martineau if (control->final) { 5813d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 5814d2a7ac5dSMat Martineau &chan->conn_state)) { 5815d2a7ac5dSMat Martineau control->final = 0; 5816d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 5817d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 5818d2a7ac5dSMat Martineau } 5819d2a7ac5dSMat Martineau } 5820d2a7ac5dSMat Martineau 5821d2a7ac5dSMat Martineau if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 5822d2a7ac5dSMat Martineau l2cap_send_ack(chan); 5823d2a7ac5dSMat Martineau break; 5824d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 5825d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 5826d2a7ac5dSMat Martineau 5827d2a7ac5dSMat Martineau /* Can't issue SREJ frames in the local busy state. 5828d2a7ac5dSMat Martineau * Drop this frame, it will be seen as missing 5829d2a7ac5dSMat Martineau * when local busy is exited. 5830d2a7ac5dSMat Martineau */ 5831d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 5832d2a7ac5dSMat Martineau BT_DBG("Busy, discarding unexpected seq %d", 5833d2a7ac5dSMat Martineau control->txseq); 5834d2a7ac5dSMat Martineau break; 5835d2a7ac5dSMat Martineau } 5836d2a7ac5dSMat Martineau 5837d2a7ac5dSMat Martineau /* There was a gap in the sequence, so an SREJ 5838d2a7ac5dSMat Martineau * must be sent for each missing frame. The 5839d2a7ac5dSMat Martineau * current frame is stored for later use. 5840d2a7ac5dSMat Martineau */ 5841d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 5842941247f9SPeter Senna Tschudin skb_in_use = true; 5843d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 5844d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 5845d2a7ac5dSMat Martineau 5846d2a7ac5dSMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 5847d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 5848d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 5849d2a7ac5dSMat Martineau 5850d2a7ac5dSMat Martineau chan->rx_state = L2CAP_RX_STATE_SREJ_SENT; 5851d2a7ac5dSMat Martineau break; 5852d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 5853d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 5854d2a7ac5dSMat Martineau break; 5855d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 5856d2a7ac5dSMat Martineau break; 5857d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 5858d2a7ac5dSMat Martineau default: 58595e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 5860d2a7ac5dSMat Martineau break; 5861d2a7ac5dSMat Martineau } 5862d2a7ac5dSMat Martineau break; 5863d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 5864d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 5865d2a7ac5dSMat Martineau if (control->final) { 5866d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 5867d2a7ac5dSMat Martineau 5868e6a3ee6eSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) && 5869e6a3ee6eSMat Martineau !__chan_is_moving(chan)) { 5870d2a7ac5dSMat Martineau control->final = 0; 5871d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 5872d2a7ac5dSMat Martineau } 5873d2a7ac5dSMat Martineau 5874d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 5875d2a7ac5dSMat Martineau } else if (control->poll) { 5876d2a7ac5dSMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 5877d2a7ac5dSMat Martineau } else { 5878d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 5879d2a7ac5dSMat Martineau &chan->conn_state) && 5880d2a7ac5dSMat Martineau chan->unacked_frames) 5881d2a7ac5dSMat Martineau __set_retrans_timer(chan); 5882d2a7ac5dSMat Martineau 5883d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 5884d2a7ac5dSMat Martineau } 5885d2a7ac5dSMat Martineau break; 5886d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 5887d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 5888d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 5889d2a7ac5dSMat Martineau if (control && control->poll) { 5890d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 5891d2a7ac5dSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 5892d2a7ac5dSMat Martineau } 5893d2a7ac5dSMat Martineau __clear_retrans_timer(chan); 5894d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 5895d2a7ac5dSMat Martineau break; 5896d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 5897d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 5898d2a7ac5dSMat Martineau break; 5899d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 5900d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 5901d2a7ac5dSMat Martineau break; 5902d2a7ac5dSMat Martineau default: 5903d2a7ac5dSMat Martineau break; 5904d2a7ac5dSMat Martineau } 5905d2a7ac5dSMat Martineau 5906d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 5907d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 5908d2a7ac5dSMat Martineau kfree_skb(skb); 5909d2a7ac5dSMat Martineau } 5910d2a7ac5dSMat Martineau 5911d2a7ac5dSMat Martineau return err; 5912d2a7ac5dSMat Martineau } 5913d2a7ac5dSMat Martineau 5914d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, 5915d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 5916d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 5917d2a7ac5dSMat Martineau { 5918d2a7ac5dSMat Martineau int err = 0; 5919d2a7ac5dSMat Martineau u16 txseq = control->txseq; 5920941247f9SPeter Senna Tschudin bool skb_in_use = false; 5921d2a7ac5dSMat Martineau 5922d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 5923d2a7ac5dSMat Martineau event); 5924d2a7ac5dSMat Martineau 5925d2a7ac5dSMat Martineau switch (event) { 5926d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 5927d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, txseq)) { 5928d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 5929d2a7ac5dSMat Martineau /* Keep frame for reassembly later */ 5930d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 5931d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 5932941247f9SPeter Senna Tschudin skb_in_use = true; 5933d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 5934d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 5935d2a7ac5dSMat Martineau 5936d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 5937d2a7ac5dSMat Martineau break; 5938d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED_SREJ: 5939d2a7ac5dSMat Martineau l2cap_seq_list_pop(&chan->srej_list); 5940d2a7ac5dSMat Martineau 5941d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 5942d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 5943941247f9SPeter Senna Tschudin skb_in_use = true; 5944d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 5945d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 5946d2a7ac5dSMat Martineau 5947d2a7ac5dSMat Martineau err = l2cap_rx_queued_iframes(chan); 5948d2a7ac5dSMat Martineau if (err) 5949d2a7ac5dSMat Martineau break; 5950d2a7ac5dSMat Martineau 5951d2a7ac5dSMat Martineau break; 5952d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 5953d2a7ac5dSMat Martineau /* Got a frame that can't be reassembled yet. 5954d2a7ac5dSMat Martineau * Save it for later, and send SREJs to cover 5955d2a7ac5dSMat Martineau * the missing frames. 5956d2a7ac5dSMat Martineau */ 5957d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 5958941247f9SPeter Senna Tschudin skb_in_use = true; 5959d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 5960d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 5961d2a7ac5dSMat Martineau 5962d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 5963d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 5964d2a7ac5dSMat Martineau break; 5965d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED_SREJ: 5966d2a7ac5dSMat Martineau /* This frame was requested with an SREJ, but 5967d2a7ac5dSMat Martineau * some expected retransmitted frames are 5968d2a7ac5dSMat Martineau * missing. Request retransmission of missing 5969d2a7ac5dSMat Martineau * SREJ'd frames. 5970d2a7ac5dSMat Martineau */ 5971d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 5972941247f9SPeter Senna Tschudin skb_in_use = true; 5973d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 5974d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 5975d2a7ac5dSMat Martineau 5976d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 5977d2a7ac5dSMat Martineau l2cap_send_srej_list(chan, control->txseq); 5978d2a7ac5dSMat Martineau break; 5979d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE_SREJ: 5980d2a7ac5dSMat Martineau /* We've already queued this frame. Drop this copy. */ 5981d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 5982d2a7ac5dSMat Martineau break; 5983d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 5984d2a7ac5dSMat Martineau /* Expecting a later sequence number, so this frame 5985d2a7ac5dSMat Martineau * was already received. Ignore it completely. 5986d2a7ac5dSMat Martineau */ 5987d2a7ac5dSMat Martineau break; 5988d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 5989d2a7ac5dSMat Martineau break; 5990d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 5991d2a7ac5dSMat Martineau default: 59925e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 5993d2a7ac5dSMat Martineau break; 5994d2a7ac5dSMat Martineau } 5995d2a7ac5dSMat Martineau break; 5996d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 5997d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 5998d2a7ac5dSMat Martineau if (control->final) { 5999d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6000d2a7ac5dSMat Martineau 6001d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 6002d2a7ac5dSMat Martineau &chan->conn_state)) { 6003d2a7ac5dSMat Martineau control->final = 0; 6004d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6005d2a7ac5dSMat Martineau } 6006d2a7ac5dSMat Martineau 6007d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6008d2a7ac5dSMat Martineau } else if (control->poll) { 6009d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6010d2a7ac5dSMat Martineau &chan->conn_state) && 6011d2a7ac5dSMat Martineau chan->unacked_frames) { 6012d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6013d2a7ac5dSMat Martineau } 6014d2a7ac5dSMat Martineau 6015d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6016d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 6017d2a7ac5dSMat Martineau } else { 6018d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6019d2a7ac5dSMat Martineau &chan->conn_state) && 6020d2a7ac5dSMat Martineau chan->unacked_frames) 6021d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6022d2a7ac5dSMat Martineau 6023d2a7ac5dSMat Martineau l2cap_send_ack(chan); 6024d2a7ac5dSMat Martineau } 6025d2a7ac5dSMat Martineau break; 6026d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 6027d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6028d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6029d2a7ac5dSMat Martineau if (control->poll) { 6030d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 6031d2a7ac5dSMat Martineau } else { 6032d2a7ac5dSMat Martineau struct l2cap_ctrl rr_control; 6033d2a7ac5dSMat Martineau memset(&rr_control, 0, sizeof(rr_control)); 6034d2a7ac5dSMat Martineau rr_control.sframe = 1; 6035d2a7ac5dSMat Martineau rr_control.super = L2CAP_SUPER_RR; 6036d2a7ac5dSMat Martineau rr_control.reqseq = chan->buffer_seq; 6037d2a7ac5dSMat Martineau l2cap_send_sframe(chan, &rr_control); 6038d2a7ac5dSMat Martineau } 6039d2a7ac5dSMat Martineau 6040d2a7ac5dSMat Martineau break; 6041d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 6042d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 6043d2a7ac5dSMat Martineau break; 6044d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 6045d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 6046d2a7ac5dSMat Martineau break; 6047d2a7ac5dSMat Martineau } 6048d2a7ac5dSMat Martineau 6049d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 6050d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 6051d2a7ac5dSMat Martineau kfree_skb(skb); 6052d2a7ac5dSMat Martineau } 6053d2a7ac5dSMat Martineau 6054d2a7ac5dSMat Martineau return err; 6055d2a7ac5dSMat Martineau } 6056d2a7ac5dSMat Martineau 605732b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan) 605832b32735SMat Martineau { 605932b32735SMat Martineau BT_DBG("chan %p", chan); 606032b32735SMat Martineau 606132b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 606232b32735SMat Martineau 606332b32735SMat Martineau if (chan->hs_hcon) 606432b32735SMat Martineau chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; 606532b32735SMat Martineau else 606632b32735SMat Martineau chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; 606732b32735SMat Martineau 606832b32735SMat Martineau return l2cap_resegment(chan); 606932b32735SMat Martineau } 607032b32735SMat Martineau 607132b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan, 607232b32735SMat Martineau struct l2cap_ctrl *control, 607332b32735SMat Martineau struct sk_buff *skb, u8 event) 607432b32735SMat Martineau { 607532b32735SMat Martineau int err; 607632b32735SMat Martineau 607732b32735SMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 607832b32735SMat Martineau event); 607932b32735SMat Martineau 608032b32735SMat Martineau if (!control->poll) 608132b32735SMat Martineau return -EPROTO; 608232b32735SMat Martineau 608332b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq); 608432b32735SMat Martineau 608532b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q)) 608632b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q); 608732b32735SMat Martineau else 608832b32735SMat Martineau chan->tx_send_head = NULL; 608932b32735SMat Martineau 609032b32735SMat Martineau /* Rewind next_tx_seq to the point expected 609132b32735SMat Martineau * by the receiver. 609232b32735SMat Martineau */ 609332b32735SMat Martineau chan->next_tx_seq = control->reqseq; 609432b32735SMat Martineau chan->unacked_frames = 0; 609532b32735SMat Martineau 609632b32735SMat Martineau err = l2cap_finish_move(chan); 609732b32735SMat Martineau if (err) 609832b32735SMat Martineau return err; 609932b32735SMat Martineau 610032b32735SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 610132b32735SMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 610232b32735SMat Martineau 610332b32735SMat Martineau if (event == L2CAP_EV_RECV_IFRAME) 610432b32735SMat Martineau return -EPROTO; 610532b32735SMat Martineau 610632b32735SMat Martineau return l2cap_rx_state_recv(chan, control, NULL, event); 610732b32735SMat Martineau } 610832b32735SMat Martineau 610932b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan, 611032b32735SMat Martineau struct l2cap_ctrl *control, 611132b32735SMat Martineau struct sk_buff *skb, u8 event) 611232b32735SMat Martineau { 611332b32735SMat Martineau int err; 611432b32735SMat Martineau 611532b32735SMat Martineau if (!control->final) 611632b32735SMat Martineau return -EPROTO; 611732b32735SMat Martineau 611832b32735SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 611932b32735SMat Martineau 612032b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 612132b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq); 612232b32735SMat Martineau 612332b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q)) 612432b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q); 612532b32735SMat Martineau else 612632b32735SMat Martineau chan->tx_send_head = NULL; 612732b32735SMat Martineau 612832b32735SMat Martineau /* Rewind next_tx_seq to the point expected 612932b32735SMat Martineau * by the receiver. 613032b32735SMat Martineau */ 613132b32735SMat Martineau chan->next_tx_seq = control->reqseq; 613232b32735SMat Martineau chan->unacked_frames = 0; 613332b32735SMat Martineau 613432b32735SMat Martineau if (chan->hs_hcon) 613532b32735SMat Martineau chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; 613632b32735SMat Martineau else 613732b32735SMat Martineau chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; 613832b32735SMat Martineau 613932b32735SMat Martineau err = l2cap_resegment(chan); 614032b32735SMat Martineau 614132b32735SMat Martineau if (!err) 614232b32735SMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 614332b32735SMat Martineau 614432b32735SMat Martineau return err; 614532b32735SMat Martineau } 614632b32735SMat Martineau 6147d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq) 6148d2a7ac5dSMat Martineau { 6149d2a7ac5dSMat Martineau /* Make sure reqseq is for a packet that has been sent but not acked */ 6150d2a7ac5dSMat Martineau u16 unacked; 6151d2a7ac5dSMat Martineau 6152d2a7ac5dSMat Martineau unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq); 6153d2a7ac5dSMat Martineau return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked; 6154d2a7ac5dSMat Martineau } 6155d2a7ac5dSMat Martineau 6156cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 6157cec8ab6eSMat Martineau struct sk_buff *skb, u8 event) 61580a708f8fSGustavo F. Padovan { 6159d2a7ac5dSMat Martineau int err = 0; 6160d2a7ac5dSMat Martineau 6161d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan, 6162d2a7ac5dSMat Martineau control, skb, event, chan->rx_state); 6163d2a7ac5dSMat Martineau 6164d2a7ac5dSMat Martineau if (__valid_reqseq(chan, control->reqseq)) { 6165d2a7ac5dSMat Martineau switch (chan->rx_state) { 6166d2a7ac5dSMat Martineau case L2CAP_RX_STATE_RECV: 6167d2a7ac5dSMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 6168d2a7ac5dSMat Martineau break; 6169d2a7ac5dSMat Martineau case L2CAP_RX_STATE_SREJ_SENT: 6170d2a7ac5dSMat Martineau err = l2cap_rx_state_srej_sent(chan, control, skb, 6171d2a7ac5dSMat Martineau event); 6172d2a7ac5dSMat Martineau break; 617332b32735SMat Martineau case L2CAP_RX_STATE_WAIT_P: 617432b32735SMat Martineau err = l2cap_rx_state_wait_p(chan, control, skb, event); 617532b32735SMat Martineau break; 617632b32735SMat Martineau case L2CAP_RX_STATE_WAIT_F: 617732b32735SMat Martineau err = l2cap_rx_state_wait_f(chan, control, skb, event); 617832b32735SMat Martineau break; 6179d2a7ac5dSMat Martineau default: 6180d2a7ac5dSMat Martineau /* shut it down */ 6181d2a7ac5dSMat Martineau break; 6182d2a7ac5dSMat Martineau } 6183d2a7ac5dSMat Martineau } else { 6184d2a7ac5dSMat Martineau BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d", 6185d2a7ac5dSMat Martineau control->reqseq, chan->next_tx_seq, 6186d2a7ac5dSMat Martineau chan->expected_ack_seq); 61875e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6188d2a7ac5dSMat Martineau } 6189d2a7ac5dSMat Martineau 6190d2a7ac5dSMat Martineau return err; 6191cec8ab6eSMat Martineau } 6192cec8ab6eSMat Martineau 6193cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 6194cec8ab6eSMat Martineau struct sk_buff *skb) 6195cec8ab6eSMat Martineau { 61964b51dae9SMat Martineau int err = 0; 61974b51dae9SMat Martineau 61984b51dae9SMat Martineau BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb, 61994b51dae9SMat Martineau chan->rx_state); 62004b51dae9SMat Martineau 62014b51dae9SMat Martineau if (l2cap_classify_txseq(chan, control->txseq) == 62024b51dae9SMat Martineau L2CAP_TXSEQ_EXPECTED) { 62034b51dae9SMat Martineau l2cap_pass_to_tx(chan, control); 62044b51dae9SMat Martineau 62054b51dae9SMat Martineau BT_DBG("buffer_seq %d->%d", chan->buffer_seq, 62064b51dae9SMat Martineau __next_seq(chan, chan->buffer_seq)); 62074b51dae9SMat Martineau 62084b51dae9SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 62094b51dae9SMat Martineau 62104b51dae9SMat Martineau l2cap_reassemble_sdu(chan, skb, control); 62114b51dae9SMat Martineau } else { 62124b51dae9SMat Martineau if (chan->sdu) { 62134b51dae9SMat Martineau kfree_skb(chan->sdu); 62144b51dae9SMat Martineau chan->sdu = NULL; 62154b51dae9SMat Martineau } 62164b51dae9SMat Martineau chan->sdu_last_frag = NULL; 62174b51dae9SMat Martineau chan->sdu_len = 0; 62184b51dae9SMat Martineau 62194b51dae9SMat Martineau if (skb) { 62204b51dae9SMat Martineau BT_DBG("Freeing %p", skb); 62214b51dae9SMat Martineau kfree_skb(skb); 62224b51dae9SMat Martineau } 62234b51dae9SMat Martineau } 62244b51dae9SMat Martineau 62254b51dae9SMat Martineau chan->last_acked_seq = control->txseq; 62264b51dae9SMat Martineau chan->expected_tx_seq = __next_seq(chan, control->txseq); 62274b51dae9SMat Martineau 62284b51dae9SMat Martineau return err; 6229cec8ab6eSMat Martineau } 6230cec8ab6eSMat Martineau 6231cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 6232cec8ab6eSMat Martineau { 6233cec8ab6eSMat Martineau struct l2cap_ctrl *control = &bt_cb(skb)->control; 6234cec8ab6eSMat Martineau u16 len; 6235cec8ab6eSMat Martineau u8 event; 62360a708f8fSGustavo F. Padovan 6237b76bbd66SMat Martineau __unpack_control(chan, skb); 6238b76bbd66SMat Martineau 62390a708f8fSGustavo F. Padovan len = skb->len; 62400a708f8fSGustavo F. Padovan 62410a708f8fSGustavo F. Padovan /* 62420a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here. 62430a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery 6244cec8ab6eSMat Martineau * procedures and ask for retransmission. 62450a708f8fSGustavo F. Padovan */ 624647d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 62470a708f8fSGustavo F. Padovan goto drop; 62480a708f8fSGustavo F. Padovan 6249cec8ab6eSMat Martineau if (!control->sframe && control->sar == L2CAP_SAR_START) 625003a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 62510a708f8fSGustavo F. Padovan 625247d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 625303a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 62540a708f8fSGustavo F. Padovan 625547d1ec61SGustavo F. Padovan if (len > chan->mps) { 62565e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 62570a708f8fSGustavo F. Padovan goto drop; 62580a708f8fSGustavo F. Padovan } 62590a708f8fSGustavo F. Padovan 6260cec8ab6eSMat Martineau if (!control->sframe) { 6261cec8ab6eSMat Martineau int err; 62620a708f8fSGustavo F. Padovan 6263cec8ab6eSMat Martineau BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d", 6264cec8ab6eSMat Martineau control->sar, control->reqseq, control->final, 6265cec8ab6eSMat Martineau control->txseq); 6266836be934SAndrei Emeltchenko 6267cec8ab6eSMat Martineau /* Validate F-bit - F=0 always valid, F=1 only 6268cec8ab6eSMat Martineau * valid in TX WAIT_F 6269cec8ab6eSMat Martineau */ 6270cec8ab6eSMat Martineau if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F) 62710a708f8fSGustavo F. Padovan goto drop; 62720a708f8fSGustavo F. Padovan 6273cec8ab6eSMat Martineau if (chan->mode != L2CAP_MODE_STREAMING) { 6274cec8ab6eSMat Martineau event = L2CAP_EV_RECV_IFRAME; 6275cec8ab6eSMat Martineau err = l2cap_rx(chan, control, skb, event); 62760a708f8fSGustavo F. Padovan } else { 6277cec8ab6eSMat Martineau err = l2cap_stream_rx(chan, control, skb); 6278cec8ab6eSMat Martineau } 6279cec8ab6eSMat Martineau 6280cec8ab6eSMat Martineau if (err) 62815e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6282cec8ab6eSMat Martineau } else { 6283cec8ab6eSMat Martineau const u8 rx_func_to_event[4] = { 6284cec8ab6eSMat Martineau L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ, 6285cec8ab6eSMat Martineau L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ 6286cec8ab6eSMat Martineau }; 6287cec8ab6eSMat Martineau 6288cec8ab6eSMat Martineau /* Only I-frames are expected in streaming mode */ 6289cec8ab6eSMat Martineau if (chan->mode == L2CAP_MODE_STREAMING) 6290cec8ab6eSMat Martineau goto drop; 6291cec8ab6eSMat Martineau 6292cec8ab6eSMat Martineau BT_DBG("sframe reqseq %d, final %d, poll %d, super %d", 6293cec8ab6eSMat Martineau control->reqseq, control->final, control->poll, 6294cec8ab6eSMat Martineau control->super); 6295cec8ab6eSMat Martineau 62960a708f8fSGustavo F. Padovan if (len != 0) { 62971bb166e6SAndrei Emeltchenko BT_ERR("Trailing bytes: %d in sframe", len); 62985e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 62990a708f8fSGustavo F. Padovan goto drop; 63000a708f8fSGustavo F. Padovan } 63010a708f8fSGustavo F. Padovan 6302cec8ab6eSMat Martineau /* Validate F and P bits */ 6303cec8ab6eSMat Martineau if (control->final && (control->poll || 6304cec8ab6eSMat Martineau chan->tx_state != L2CAP_TX_STATE_WAIT_F)) 6305cec8ab6eSMat Martineau goto drop; 6306cec8ab6eSMat Martineau 6307cec8ab6eSMat Martineau event = rx_func_to_event[control->super]; 6308cec8ab6eSMat Martineau if (l2cap_rx(chan, control, skb, event)) 63095e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 63100a708f8fSGustavo F. Padovan } 63110a708f8fSGustavo F. Padovan 63120a708f8fSGustavo F. Padovan return 0; 63130a708f8fSGustavo F. Padovan 63140a708f8fSGustavo F. Padovan drop: 63150a708f8fSGustavo F. Padovan kfree_skb(skb); 63160a708f8fSGustavo F. Padovan return 0; 63170a708f8fSGustavo F. Padovan } 63180a708f8fSGustavo F. Padovan 631913ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid, 632013ca56e0SAndrei Emeltchenko struct sk_buff *skb) 63210a708f8fSGustavo F. Padovan { 632248454079SGustavo F. Padovan struct l2cap_chan *chan; 63230a708f8fSGustavo F. Padovan 6324baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 632548454079SGustavo F. Padovan if (!chan) { 632697e8e89dSAndrei Emeltchenko if (cid == L2CAP_CID_A2MP) { 632797e8e89dSAndrei Emeltchenko chan = a2mp_channel_create(conn, skb); 632897e8e89dSAndrei Emeltchenko if (!chan) { 632997e8e89dSAndrei Emeltchenko kfree_skb(skb); 633013ca56e0SAndrei Emeltchenko return; 633197e8e89dSAndrei Emeltchenko } 633297e8e89dSAndrei Emeltchenko 633397e8e89dSAndrei Emeltchenko l2cap_chan_lock(chan); 633497e8e89dSAndrei Emeltchenko } else { 63350a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid); 63366be36555SAndrei Emeltchenko /* Drop packet and return */ 63373379013bSDan Carpenter kfree_skb(skb); 633813ca56e0SAndrei Emeltchenko return; 63390a708f8fSGustavo F. Padovan } 634097e8e89dSAndrei Emeltchenko } 63410a708f8fSGustavo F. Padovan 634249208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len); 63430a708f8fSGustavo F. Padovan 634489bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 63450a708f8fSGustavo F. Padovan goto drop; 63460a708f8fSGustavo F. Padovan 63470c1bc5c6SGustavo F. Padovan switch (chan->mode) { 63480a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 63490a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here 63500a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable. 63510a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't 63520a708f8fSGustavo F. Padovan * provide flow control mechanism. */ 63530a708f8fSGustavo F. Padovan 63540c1bc5c6SGustavo F. Padovan if (chan->imtu < skb->len) 63550a708f8fSGustavo F. Padovan goto drop; 63560a708f8fSGustavo F. Padovan 635780b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 63580a708f8fSGustavo F. Padovan goto done; 63590a708f8fSGustavo F. Padovan break; 63600a708f8fSGustavo F. Padovan 63610a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 63620a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 6363cec8ab6eSMat Martineau l2cap_data_rcv(chan, skb); 63640a708f8fSGustavo F. Padovan goto done; 63650a708f8fSGustavo F. Padovan 63660a708f8fSGustavo F. Padovan default: 63670c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); 63680a708f8fSGustavo F. Padovan break; 63690a708f8fSGustavo F. Padovan } 63700a708f8fSGustavo F. Padovan 63710a708f8fSGustavo F. Padovan drop: 63720a708f8fSGustavo F. Padovan kfree_skb(skb); 63730a708f8fSGustavo F. Padovan 63740a708f8fSGustavo F. Padovan done: 63756be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 63760a708f8fSGustavo F. Padovan } 63770a708f8fSGustavo F. Padovan 637884104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, 637984104b24SAndrei Emeltchenko struct sk_buff *skb) 63800a708f8fSGustavo F. Padovan { 6381ae4fd2d3SMarcel Holtmann struct hci_conn *hcon = conn->hcon; 638223691d75SGustavo F. Padovan struct l2cap_chan *chan; 63830a708f8fSGustavo F. Padovan 6384ae4fd2d3SMarcel Holtmann if (hcon->type != ACL_LINK) 6385ae4fd2d3SMarcel Holtmann goto drop; 6386ae4fd2d3SMarcel Holtmann 638706ae3314SMarcel Holtmann chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst); 638823691d75SGustavo F. Padovan if (!chan) 63890a708f8fSGustavo F. Padovan goto drop; 63900a708f8fSGustavo F. Padovan 63915b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 63920a708f8fSGustavo F. Padovan 639389bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 63940a708f8fSGustavo F. Padovan goto drop; 63950a708f8fSGustavo F. Padovan 6396e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 63970a708f8fSGustavo F. Padovan goto drop; 63980a708f8fSGustavo F. Padovan 63992edf870dSMarcel Holtmann /* Store remote BD_ADDR and PSM for msg_name */ 640006ae3314SMarcel Holtmann bacpy(&bt_cb(skb)->bdaddr, &hcon->dst); 64012edf870dSMarcel Holtmann bt_cb(skb)->psm = psm; 64022edf870dSMarcel Holtmann 640380b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 640484104b24SAndrei Emeltchenko return; 64050a708f8fSGustavo F. Padovan 64060a708f8fSGustavo F. Padovan drop: 64070a708f8fSGustavo F. Padovan kfree_skb(skb); 64080a708f8fSGustavo F. Padovan } 64090a708f8fSGustavo F. Padovan 641072f78356SMarcel Holtmann static void l2cap_att_channel(struct l2cap_conn *conn, 6411d9b88702SAndrei Emeltchenko struct sk_buff *skb) 64129f69bda6SGustavo F. Padovan { 6413b99707d7SMarcel Holtmann struct hci_conn *hcon = conn->hcon; 641423691d75SGustavo F. Padovan struct l2cap_chan *chan; 64159f69bda6SGustavo F. Padovan 6416b99707d7SMarcel Holtmann if (hcon->type != LE_LINK) 6417b99707d7SMarcel Holtmann goto drop; 6418b99707d7SMarcel Holtmann 6419af1c0134SJohan Hedberg chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT, 642006ae3314SMarcel Holtmann &hcon->src, &hcon->dst); 642123691d75SGustavo F. Padovan if (!chan) 64229f69bda6SGustavo F. Padovan goto drop; 64239f69bda6SGustavo F. Padovan 64245b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 64259f69bda6SGustavo F. Padovan 6426cc8dba2bSMarcel Holtmann if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, hcon->dst_type)) 6427cc8dba2bSMarcel Holtmann goto drop; 6428cc8dba2bSMarcel Holtmann 6429e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 64309f69bda6SGustavo F. Padovan goto drop; 64319f69bda6SGustavo F. Padovan 643280b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 64336810fca7SAndrei Emeltchenko return; 64349f69bda6SGustavo F. Padovan 64359f69bda6SGustavo F. Padovan drop: 64369f69bda6SGustavo F. Padovan kfree_skb(skb); 64379f69bda6SGustavo F. Padovan } 64389f69bda6SGustavo F. Padovan 64390a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) 64400a708f8fSGustavo F. Padovan { 64410a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data; 64420a708f8fSGustavo F. Padovan u16 cid, len; 64430a708f8fSGustavo F. Padovan __le16 psm; 64440a708f8fSGustavo F. Padovan 64450a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE); 64460a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid); 64470a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len); 64480a708f8fSGustavo F. Padovan 64490a708f8fSGustavo F. Padovan if (len != skb->len) { 64500a708f8fSGustavo F. Padovan kfree_skb(skb); 64510a708f8fSGustavo F. Padovan return; 64520a708f8fSGustavo F. Padovan } 64530a708f8fSGustavo F. Padovan 64540a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid); 64550a708f8fSGustavo F. Padovan 64560a708f8fSGustavo F. Padovan switch (cid) { 64570a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING: 64580a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb); 64590a708f8fSGustavo F. Padovan break; 64600a708f8fSGustavo F. Padovan 64610a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS: 6462097db76cSAndrei Emeltchenko psm = get_unaligned((__le16 *) skb->data); 64630181a70fSAndrei Emeltchenko skb_pull(skb, L2CAP_PSMLEN_SIZE); 64640a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb); 64650a708f8fSGustavo F. Padovan break; 64660a708f8fSGustavo F. Padovan 6467073d1cf3SJohan Hedberg case L2CAP_CID_ATT: 646872f78356SMarcel Holtmann l2cap_att_channel(conn, skb); 64699f69bda6SGustavo F. Padovan break; 64709f69bda6SGustavo F. Padovan 6471a2877629SMarcel Holtmann case L2CAP_CID_LE_SIGNALING: 6472a2877629SMarcel Holtmann l2cap_le_sig_channel(conn, skb); 6473a2877629SMarcel Holtmann break; 6474a2877629SMarcel Holtmann 6475b501d6a1SAnderson Briglia case L2CAP_CID_SMP: 6476b501d6a1SAnderson Briglia if (smp_sig_channel(conn, skb)) 6477b501d6a1SAnderson Briglia l2cap_conn_del(conn->hcon, EACCES); 6478b501d6a1SAnderson Briglia break; 6479b501d6a1SAnderson Briglia 64800a708f8fSGustavo F. Padovan default: 64810a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb); 64820a708f8fSGustavo F. Padovan break; 64830a708f8fSGustavo F. Padovan } 64840a708f8fSGustavo F. Padovan } 64850a708f8fSGustavo F. Padovan 64860a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */ 64870a708f8fSGustavo F. Padovan 6488686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) 64890a708f8fSGustavo F. Padovan { 64900a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0; 649123691d75SGustavo F. Padovan struct l2cap_chan *c; 64920a708f8fSGustavo F. Padovan 64936ed93dc6SAndrei Emeltchenko BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr); 64940a708f8fSGustavo F. Padovan 64950a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */ 649623691d75SGustavo F. Padovan read_lock(&chan_list_lock); 649723691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 649889bc500eSGustavo F. Padovan if (c->state != BT_LISTEN) 64990a708f8fSGustavo F. Padovan continue; 65000a708f8fSGustavo F. Padovan 65017eafc59eSMarcel Holtmann if (!bacmp(&c->src, &hdev->bdaddr)) { 65020a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT; 650343bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 65040a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER; 65050a708f8fSGustavo F. Padovan exact++; 65067eafc59eSMarcel Holtmann } else if (!bacmp(&c->src, BDADDR_ANY)) { 65070a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT; 650843bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 65090a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER; 65100a708f8fSGustavo F. Padovan } 65110a708f8fSGustavo F. Padovan } 651223691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 65130a708f8fSGustavo F. Padovan 65140a708f8fSGustavo F. Padovan return exact ? lm1 : lm2; 65150a708f8fSGustavo F. Padovan } 65160a708f8fSGustavo F. Padovan 65179e664631SAndrei Emeltchenko void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) 65180a708f8fSGustavo F. Padovan { 65190a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 65200a708f8fSGustavo F. Padovan 65216ed93dc6SAndrei Emeltchenko BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status); 65220a708f8fSGustavo F. Padovan 65230a708f8fSGustavo F. Padovan if (!status) { 6524baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon); 65250a708f8fSGustavo F. Padovan if (conn) 65260a708f8fSGustavo F. Padovan l2cap_conn_ready(conn); 6527ba6fc317SAndrei Emeltchenko } else { 6528e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status)); 6529ba6fc317SAndrei Emeltchenko } 65300a708f8fSGustavo F. Padovan } 65310a708f8fSGustavo F. Padovan 6532686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon) 65330a708f8fSGustavo F. Padovan { 65340a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 65350a708f8fSGustavo F. Padovan 65360a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon); 65370a708f8fSGustavo F. Padovan 6538686ebf28SUlisses Furquim if (!conn) 65399f5a0d7bSAndrei Emeltchenko return HCI_ERROR_REMOTE_USER_TERM; 65400a708f8fSGustavo F. Padovan return conn->disc_reason; 65410a708f8fSGustavo F. Padovan } 65420a708f8fSGustavo F. Padovan 65439e664631SAndrei Emeltchenko void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) 65440a708f8fSGustavo F. Padovan { 65450a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason); 65460a708f8fSGustavo F. Padovan 6547e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason)); 65480a708f8fSGustavo F. Padovan } 65490a708f8fSGustavo F. Padovan 65504343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) 65510a708f8fSGustavo F. Padovan { 6552715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 65530a708f8fSGustavo F. Padovan return; 65540a708f8fSGustavo F. Padovan 65550a708f8fSGustavo F. Padovan if (encrypt == 0x00) { 65564343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) { 6557ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); 65584343478fSGustavo F. Padovan } else if (chan->sec_level == BT_SECURITY_HIGH) 65590f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED); 65600a708f8fSGustavo F. Padovan } else { 65614343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) 6562c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 65630a708f8fSGustavo F. Padovan } 65640a708f8fSGustavo F. Padovan } 65650a708f8fSGustavo F. Padovan 6566686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) 65670a708f8fSGustavo F. Padovan { 65680a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 656948454079SGustavo F. Padovan struct l2cap_chan *chan; 65700a708f8fSGustavo F. Padovan 65710a708f8fSGustavo F. Padovan if (!conn) 65720a708f8fSGustavo F. Padovan return 0; 65730a708f8fSGustavo F. Padovan 657489d8b407SAndrei Emeltchenko BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt); 65750a708f8fSGustavo F. Padovan 6576160dc6acSVinicius Costa Gomes if (hcon->type == LE_LINK) { 657735d4adccSHemant Gupta if (!status && encrypt) 6578160dc6acSVinicius Costa Gomes smp_distribute_keys(conn, 0); 657917cd3f37SUlisses Furquim cancel_delayed_work(&conn->security_timer); 6580160dc6acSVinicius Costa Gomes } 6581160dc6acSVinicius Costa Gomes 65823df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 65830a708f8fSGustavo F. Padovan 65843df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 65856be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 65860a708f8fSGustavo F. Padovan 658789d8b407SAndrei Emeltchenko BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, 658889d8b407SAndrei Emeltchenko state_to_string(chan->state)); 6589f1cb9af5SVinicius Costa Gomes 659078eb2f98SAndrei Emeltchenko if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { 659178eb2f98SAndrei Emeltchenko l2cap_chan_unlock(chan); 659278eb2f98SAndrei Emeltchenko continue; 659378eb2f98SAndrei Emeltchenko } 659478eb2f98SAndrei Emeltchenko 6595073d1cf3SJohan Hedberg if (chan->scid == L2CAP_CID_ATT) { 6596f1cb9af5SVinicius Costa Gomes if (!status && encrypt) { 6597f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level; 6598cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 6599f1cb9af5SVinicius Costa Gomes } 6600f1cb9af5SVinicius Costa Gomes 66016be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 6602f1cb9af5SVinicius Costa Gomes continue; 6603f1cb9af5SVinicius Costa Gomes } 6604f1cb9af5SVinicius Costa Gomes 660596eff46eSAndrei Emeltchenko if (!__l2cap_no_conn_pending(chan)) { 66066be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 66070a708f8fSGustavo F. Padovan continue; 66080a708f8fSGustavo F. Padovan } 66090a708f8fSGustavo F. Padovan 661089bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED || 661189bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) { 6612d97c899bSMarcel Holtmann chan->ops->resume(chan); 66134343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt); 66146be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 66150a708f8fSGustavo F. Padovan continue; 66160a708f8fSGustavo F. Padovan } 66170a708f8fSGustavo F. Padovan 661889bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 66190a708f8fSGustavo F. Padovan if (!status) { 662093c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 66210a708f8fSGustavo F. Padovan } else { 6622ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 66230a708f8fSGustavo F. Padovan } 662489bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 66250a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 6626df3c3931SJohan Hedberg __u16 res, stat; 66270a708f8fSGustavo F. Padovan 66280a708f8fSGustavo F. Padovan if (!status) { 6629bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 6630df3c3931SJohan Hedberg res = L2CAP_CR_PEND; 6631df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND; 66322dc4e510SGustavo Padovan chan->ops->defer(chan); 6633df3c3931SJohan Hedberg } else { 6634acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 6635df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS; 6636df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 6637df3c3931SJohan Hedberg } 66380a708f8fSGustavo F. Padovan } else { 6639acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_DISCONN); 6640ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 6641df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK; 6642df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 66430a708f8fSGustavo F. Padovan } 66440a708f8fSGustavo F. Padovan 6645fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 6646fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 6647df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res); 6648df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat); 6649fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 6650fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 66512d369359SMat Martineau 66522d369359SMat Martineau if (!test_bit(CONF_REQ_SENT, &chan->conf_state) && 66532d369359SMat Martineau res == L2CAP_CR_SUCCESS) { 66542d369359SMat Martineau char buf[128]; 66552d369359SMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 66562d369359SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), 66572d369359SMat Martineau L2CAP_CONF_REQ, 66582d369359SMat Martineau l2cap_build_conf_req(chan, buf), 66592d369359SMat Martineau buf); 66602d369359SMat Martineau chan->num_conf_req++; 66612d369359SMat Martineau } 66620a708f8fSGustavo F. Padovan } 66630a708f8fSGustavo F. Padovan 66646be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 66650a708f8fSGustavo F. Padovan } 66660a708f8fSGustavo F. Padovan 66673df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 66680a708f8fSGustavo F. Padovan 66690a708f8fSGustavo F. Padovan return 0; 66700a708f8fSGustavo F. Padovan } 66710a708f8fSGustavo F. Padovan 6672686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) 66730a708f8fSGustavo F. Padovan { 66740a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 6675d73a0988SAndrei Emeltchenko struct l2cap_hdr *hdr; 6676d73a0988SAndrei Emeltchenko int len; 66770a708f8fSGustavo F. Padovan 66781d13a254SAndrei Emeltchenko /* For AMP controller do not create l2cap conn */ 66791d13a254SAndrei Emeltchenko if (!conn && hcon->hdev->dev_type != HCI_BREDR) 66801d13a254SAndrei Emeltchenko goto drop; 66810a708f8fSGustavo F. Padovan 66820a708f8fSGustavo F. Padovan if (!conn) 6683baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon); 66840a708f8fSGustavo F. Padovan 66850a708f8fSGustavo F. Padovan if (!conn) 66860a708f8fSGustavo F. Padovan goto drop; 66870a708f8fSGustavo F. Padovan 66880a708f8fSGustavo F. Padovan BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); 66890a708f8fSGustavo F. Padovan 6690d73a0988SAndrei Emeltchenko switch (flags) { 6691d73a0988SAndrei Emeltchenko case ACL_START: 6692d73a0988SAndrei Emeltchenko case ACL_START_NO_FLUSH: 6693d73a0988SAndrei Emeltchenko case ACL_COMPLETE: 66940a708f8fSGustavo F. Padovan if (conn->rx_len) { 66950a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len); 66960a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 66970a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 66980a708f8fSGustavo F. Padovan conn->rx_len = 0; 66990a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 67000a708f8fSGustavo F. Padovan } 67010a708f8fSGustavo F. Padovan 67020a708f8fSGustavo F. Padovan /* Start fragment always begin with Basic L2CAP header */ 67030a708f8fSGustavo F. Padovan if (skb->len < L2CAP_HDR_SIZE) { 67040a708f8fSGustavo F. Padovan BT_ERR("Frame is too short (len %d)", skb->len); 67050a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 67060a708f8fSGustavo F. Padovan goto drop; 67070a708f8fSGustavo F. Padovan } 67080a708f8fSGustavo F. Padovan 67090a708f8fSGustavo F. Padovan hdr = (struct l2cap_hdr *) skb->data; 67100a708f8fSGustavo F. Padovan len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; 67110a708f8fSGustavo F. Padovan 67120a708f8fSGustavo F. Padovan if (len == skb->len) { 67130a708f8fSGustavo F. Padovan /* Complete frame received */ 67140a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb); 67150a708f8fSGustavo F. Padovan return 0; 67160a708f8fSGustavo F. Padovan } 67170a708f8fSGustavo F. Padovan 67180a708f8fSGustavo F. Padovan BT_DBG("Start: total len %d, frag len %d", len, skb->len); 67190a708f8fSGustavo F. Padovan 67200a708f8fSGustavo F. Padovan if (skb->len > len) { 67210a708f8fSGustavo F. Padovan BT_ERR("Frame is too long (len %d, expected len %d)", 67220a708f8fSGustavo F. Padovan skb->len, len); 67230a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 67240a708f8fSGustavo F. Padovan goto drop; 67250a708f8fSGustavo F. Padovan } 67260a708f8fSGustavo F. Padovan 67270a708f8fSGustavo F. Padovan /* Allocate skb for the complete frame (with header) */ 67288bcde1f2SGustavo Padovan conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL); 67290a708f8fSGustavo F. Padovan if (!conn->rx_skb) 67300a708f8fSGustavo F. Padovan goto drop; 67310a708f8fSGustavo F. Padovan 67320a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 67330a708f8fSGustavo F. Padovan skb->len); 67340a708f8fSGustavo F. Padovan conn->rx_len = len - skb->len; 6735d73a0988SAndrei Emeltchenko break; 6736d73a0988SAndrei Emeltchenko 6737d73a0988SAndrei Emeltchenko case ACL_CONT: 67380a708f8fSGustavo F. Padovan BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); 67390a708f8fSGustavo F. Padovan 67400a708f8fSGustavo F. Padovan if (!conn->rx_len) { 67410a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len); 67420a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 67430a708f8fSGustavo F. Padovan goto drop; 67440a708f8fSGustavo F. Padovan } 67450a708f8fSGustavo F. Padovan 67460a708f8fSGustavo F. Padovan if (skb->len > conn->rx_len) { 67470a708f8fSGustavo F. Padovan BT_ERR("Fragment is too long (len %d, expected %d)", 67480a708f8fSGustavo F. Padovan skb->len, conn->rx_len); 67490a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 67500a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 67510a708f8fSGustavo F. Padovan conn->rx_len = 0; 67520a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 67530a708f8fSGustavo F. Padovan goto drop; 67540a708f8fSGustavo F. Padovan } 67550a708f8fSGustavo F. Padovan 67560a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 67570a708f8fSGustavo F. Padovan skb->len); 67580a708f8fSGustavo F. Padovan conn->rx_len -= skb->len; 67590a708f8fSGustavo F. Padovan 67600a708f8fSGustavo F. Padovan if (!conn->rx_len) { 6761c4e5bafaSJohan Hedberg /* Complete frame received. l2cap_recv_frame 6762c4e5bafaSJohan Hedberg * takes ownership of the skb so set the global 6763c4e5bafaSJohan Hedberg * rx_skb pointer to NULL first. 6764c4e5bafaSJohan Hedberg */ 6765c4e5bafaSJohan Hedberg struct sk_buff *rx_skb = conn->rx_skb; 67660a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 6767c4e5bafaSJohan Hedberg l2cap_recv_frame(conn, rx_skb); 67680a708f8fSGustavo F. Padovan } 6769d73a0988SAndrei Emeltchenko break; 67700a708f8fSGustavo F. Padovan } 67710a708f8fSGustavo F. Padovan 67720a708f8fSGustavo F. Padovan drop: 67730a708f8fSGustavo F. Padovan kfree_skb(skb); 67740a708f8fSGustavo F. Padovan return 0; 67750a708f8fSGustavo F. Padovan } 67760a708f8fSGustavo F. Padovan 67770a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p) 67780a708f8fSGustavo F. Padovan { 677923691d75SGustavo F. Padovan struct l2cap_chan *c; 67800a708f8fSGustavo F. Padovan 6781333055f2SGustavo F. Padovan read_lock(&chan_list_lock); 67820a708f8fSGustavo F. Padovan 678323691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 6784fcb73338SAndrei Emeltchenko seq_printf(f, "%pMR %pMR %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", 67857eafc59eSMarcel Holtmann &c->src, &c->dst, 678689bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm), 678723691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu, 678823691d75SGustavo F. Padovan c->sec_level, c->mode); 67890a708f8fSGustavo F. Padovan } 67900a708f8fSGustavo F. Padovan 6791333055f2SGustavo F. Padovan read_unlock(&chan_list_lock); 67920a708f8fSGustavo F. Padovan 67930a708f8fSGustavo F. Padovan return 0; 67940a708f8fSGustavo F. Padovan } 67950a708f8fSGustavo F. Padovan 67960a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file) 67970a708f8fSGustavo F. Padovan { 67980a708f8fSGustavo F. Padovan return single_open(file, l2cap_debugfs_show, inode->i_private); 67990a708f8fSGustavo F. Padovan } 68000a708f8fSGustavo F. Padovan 68010a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = { 68020a708f8fSGustavo F. Padovan .open = l2cap_debugfs_open, 68030a708f8fSGustavo F. Padovan .read = seq_read, 68040a708f8fSGustavo F. Padovan .llseek = seq_lseek, 68050a708f8fSGustavo F. Padovan .release = single_release, 68060a708f8fSGustavo F. Padovan }; 68070a708f8fSGustavo F. Padovan 68080a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs; 68090a708f8fSGustavo F. Padovan 681064274518SGustavo F. Padovan int __init l2cap_init(void) 68110a708f8fSGustavo F. Padovan { 68120a708f8fSGustavo F. Padovan int err; 68130a708f8fSGustavo F. Padovan 6814bb58f747SGustavo F. Padovan err = l2cap_init_sockets(); 68150a708f8fSGustavo F. Padovan if (err < 0) 68160a708f8fSGustavo F. Padovan return err; 68170a708f8fSGustavo F. Padovan 68181120e4bfSMarcel Holtmann if (IS_ERR_OR_NULL(bt_debugfs)) 68191120e4bfSMarcel Holtmann return 0; 68201120e4bfSMarcel Holtmann 68212d792818SGustavo Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, 68222d792818SGustavo Padovan NULL, &l2cap_debugfs_fops); 68230a708f8fSGustavo F. Padovan 68240a708f8fSGustavo F. Padovan return 0; 68250a708f8fSGustavo F. Padovan } 68260a708f8fSGustavo F. Padovan 682764274518SGustavo F. Padovan void l2cap_exit(void) 68280a708f8fSGustavo F. Padovan { 68290a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs); 6830bb58f747SGustavo F. Padovan l2cap_cleanup_sockets(); 68310a708f8fSGustavo F. Padovan } 68320a708f8fSGustavo F. Padovan 68330a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644); 68340a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); 6835