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 52f15b8ecfSJohan Hedberg static u16 le_max_credits = L2CAP_LE_MAX_CREDITS; 53f15b8ecfSJohan Hedberg static u16 le_default_mps = L2CAP_LE_DEFAULT_MPS; 54f15b8ecfSJohan Hedberg 550a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 560a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data); 574519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 584519de9aSGustavo F. Padovan void *data); 59710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); 605e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err); 610a708f8fSGustavo F. Padovan 62d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 63608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event); 64608bcc6dSMat Martineau 654f1654e0SMarcel Holtmann static inline __u8 bdaddr_type(struct hci_conn *hcon, __u8 type) 664f1654e0SMarcel Holtmann { 674f1654e0SMarcel Holtmann if (hcon->type == LE_LINK) { 684f1654e0SMarcel Holtmann if (type == ADDR_LE_DEV_PUBLIC) 694f1654e0SMarcel Holtmann return BDADDR_LE_PUBLIC; 704f1654e0SMarcel Holtmann else 714f1654e0SMarcel Holtmann return BDADDR_LE_RANDOM; 724f1654e0SMarcel Holtmann } 734f1654e0SMarcel Holtmann 744f1654e0SMarcel Holtmann return BDADDR_BREDR; 754f1654e0SMarcel Holtmann } 764f1654e0SMarcel Holtmann 770a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */ 7871ba0e56SGustavo F. Padovan 792d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, 802d792818SGustavo Padovan u16 cid) 810a708f8fSGustavo F. Padovan { 823df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 83baa7e1faSGustavo F. Padovan 843df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 853df91ea2SAndrei Emeltchenko if (c->dcid == cid) 863df91ea2SAndrei Emeltchenko return c; 870a708f8fSGustavo F. Padovan } 883df91ea2SAndrei Emeltchenko return NULL; 89baa7e1faSGustavo F. Padovan } 900a708f8fSGustavo F. Padovan 912d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, 922d792818SGustavo Padovan u16 cid) 930a708f8fSGustavo F. Padovan { 943df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 95baa7e1faSGustavo F. Padovan 963df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 973df91ea2SAndrei Emeltchenko if (c->scid == cid) 983df91ea2SAndrei Emeltchenko return c; 990a708f8fSGustavo F. Padovan } 1003df91ea2SAndrei Emeltchenko return NULL; 101baa7e1faSGustavo F. Padovan } 1020a708f8fSGustavo F. Padovan 1030a708f8fSGustavo F. Padovan /* Find channel with given SCID. 104ef191adeSMat Martineau * Returns locked channel. */ 1052d792818SGustavo Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, 1062d792818SGustavo Padovan u16 cid) 1070a708f8fSGustavo F. Padovan { 10848454079SGustavo F. Padovan struct l2cap_chan *c; 109baa7e1faSGustavo F. Padovan 1103df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 111baa7e1faSGustavo F. Padovan c = __l2cap_get_chan_by_scid(conn, cid); 112ef191adeSMat Martineau if (c) 113ef191adeSMat Martineau l2cap_chan_lock(c); 1143df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 1153df91ea2SAndrei Emeltchenko 11648454079SGustavo F. Padovan return c; 1170a708f8fSGustavo F. Padovan } 1180a708f8fSGustavo F. Padovan 119b1a130b7SMat Martineau /* Find channel with given DCID. 120b1a130b7SMat Martineau * Returns locked channel. 121b1a130b7SMat Martineau */ 122b1a130b7SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn, 123b1a130b7SMat Martineau u16 cid) 124b1a130b7SMat Martineau { 125b1a130b7SMat Martineau struct l2cap_chan *c; 126b1a130b7SMat Martineau 127b1a130b7SMat Martineau mutex_lock(&conn->chan_lock); 128b1a130b7SMat Martineau c = __l2cap_get_chan_by_dcid(conn, cid); 129b1a130b7SMat Martineau if (c) 130b1a130b7SMat Martineau l2cap_chan_lock(c); 131b1a130b7SMat Martineau mutex_unlock(&conn->chan_lock); 132b1a130b7SMat Martineau 133b1a130b7SMat Martineau return c; 134b1a130b7SMat Martineau } 135b1a130b7SMat Martineau 1362d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, 1372d792818SGustavo Padovan u8 ident) 1380a708f8fSGustavo F. Padovan { 1393df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 140baa7e1faSGustavo F. Padovan 1413df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 1423df91ea2SAndrei Emeltchenko if (c->ident == ident) 1433df91ea2SAndrei Emeltchenko return c; 1440a708f8fSGustavo F. Padovan } 1453df91ea2SAndrei Emeltchenko return NULL; 146baa7e1faSGustavo F. Padovan } 1470a708f8fSGustavo F. Padovan 1485b155ef9SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, 1495b155ef9SMat Martineau u8 ident) 1505b155ef9SMat Martineau { 1515b155ef9SMat Martineau struct l2cap_chan *c; 1525b155ef9SMat Martineau 1535b155ef9SMat Martineau mutex_lock(&conn->chan_lock); 1545b155ef9SMat Martineau c = __l2cap_get_chan_by_ident(conn, ident); 1555b155ef9SMat Martineau if (c) 1565b155ef9SMat Martineau l2cap_chan_lock(c); 1575b155ef9SMat Martineau mutex_unlock(&conn->chan_lock); 1585b155ef9SMat Martineau 1595b155ef9SMat Martineau return c; 1605b155ef9SMat Martineau } 1615b155ef9SMat Martineau 16223691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src) 1639e4425ffSGustavo F. Padovan { 16423691d75SGustavo F. Padovan struct l2cap_chan *c; 1659e4425ffSGustavo F. Padovan 16623691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 1677eafc59eSMarcel Holtmann if (c->sport == psm && !bacmp(&c->src, src)) 16823691d75SGustavo F. Padovan return c; 1699e4425ffSGustavo F. Padovan } 170250938cbSSzymon Janc return NULL; 171250938cbSSzymon Janc } 1729e4425ffSGustavo F. Padovan 1739e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) 1749e4425ffSGustavo F. Padovan { 17573b2ec18SGustavo F. Padovan int err; 17673b2ec18SGustavo F. Padovan 177333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 1789e4425ffSGustavo F. Padovan 17923691d75SGustavo F. Padovan if (psm && __l2cap_global_chan_by_addr(psm, src)) { 18073b2ec18SGustavo F. Padovan err = -EADDRINUSE; 18173b2ec18SGustavo F. Padovan goto done; 1829e4425ffSGustavo F. Padovan } 1839e4425ffSGustavo F. Padovan 18473b2ec18SGustavo F. Padovan if (psm) { 1859e4425ffSGustavo F. Padovan chan->psm = psm; 1869e4425ffSGustavo F. Padovan chan->sport = psm; 18773b2ec18SGustavo F. Padovan err = 0; 18873b2ec18SGustavo F. Padovan } else { 18973b2ec18SGustavo F. Padovan u16 p; 1909e4425ffSGustavo F. Padovan 19173b2ec18SGustavo F. Padovan err = -EINVAL; 19273b2ec18SGustavo F. Padovan for (p = 0x1001; p < 0x1100; p += 2) 19323691d75SGustavo F. Padovan if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) { 19473b2ec18SGustavo F. Padovan chan->psm = cpu_to_le16(p); 19573b2ec18SGustavo F. Padovan chan->sport = cpu_to_le16(p); 19673b2ec18SGustavo F. Padovan err = 0; 19773b2ec18SGustavo F. Padovan break; 19873b2ec18SGustavo F. Padovan } 19973b2ec18SGustavo F. Padovan } 20073b2ec18SGustavo F. Padovan 20173b2ec18SGustavo F. Padovan done: 202333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 20373b2ec18SGustavo F. Padovan return err; 2049e4425ffSGustavo F. Padovan } 2059e4425ffSGustavo F. Padovan 2069e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) 2079e4425ffSGustavo F. Padovan { 208333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 2099e4425ffSGustavo F. Padovan 2109e4425ffSGustavo F. Padovan chan->scid = scid; 2119e4425ffSGustavo F. Padovan 212333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 2139e4425ffSGustavo F. Padovan 2149e4425ffSGustavo F. Padovan return 0; 2159e4425ffSGustavo F. Padovan } 2169e4425ffSGustavo F. Padovan 217baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn) 2180a708f8fSGustavo F. Padovan { 219e77af755SJohan Hedberg u16 cid, dyn_end; 2200a708f8fSGustavo F. Padovan 221e77af755SJohan Hedberg if (conn->hcon->type == LE_LINK) 222e77af755SJohan Hedberg dyn_end = L2CAP_CID_LE_DYN_END; 223e77af755SJohan Hedberg else 224e77af755SJohan Hedberg dyn_end = L2CAP_CID_DYN_END; 225e77af755SJohan Hedberg 226e77af755SJohan Hedberg for (cid = L2CAP_CID_DYN_START; cid < dyn_end; cid++) { 227baa7e1faSGustavo F. Padovan if (!__l2cap_get_chan_by_scid(conn, cid)) 2280a708f8fSGustavo F. Padovan return cid; 2290a708f8fSGustavo F. Padovan } 2300a708f8fSGustavo F. Padovan 2310a708f8fSGustavo F. Padovan return 0; 2320a708f8fSGustavo F. Padovan } 2330a708f8fSGustavo F. Padovan 234f93fa273SGustavo Padovan static void l2cap_state_change(struct l2cap_chan *chan, int state) 23589bc500eSGustavo F. Padovan { 23642d2d87cSAndrei Emeltchenko BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state), 237badaaa00SGustavo F. Padovan state_to_string(state)); 238badaaa00SGustavo F. Padovan 23989bc500eSGustavo F. Padovan chan->state = state; 24053f52121SGustavo Padovan chan->ops->state_change(chan, state, 0); 24189bc500eSGustavo F. Padovan } 24289bc500eSGustavo F. Padovan 243f8e73017SGustavo Padovan static inline void l2cap_state_change_and_error(struct l2cap_chan *chan, 244f8e73017SGustavo Padovan int state, int err) 2452e0052e4SAndrei Emeltchenko { 246f8e73017SGustavo Padovan chan->state = state; 24753f52121SGustavo Padovan chan->ops->state_change(chan, chan->state, err); 2482e0052e4SAndrei Emeltchenko } 2492e0052e4SAndrei Emeltchenko 2502e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err) 2512e0052e4SAndrei Emeltchenko { 252f8e73017SGustavo Padovan chan->ops->state_change(chan, chan->state, err); 2532e0052e4SAndrei Emeltchenko } 2542e0052e4SAndrei Emeltchenko 2554239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan) 2564239d16fSMat Martineau { 2574239d16fSMat Martineau if (!delayed_work_pending(&chan->monitor_timer) && 2584239d16fSMat Martineau chan->retrans_timeout) { 2594239d16fSMat Martineau l2cap_set_timer(chan, &chan->retrans_timer, 2604239d16fSMat Martineau msecs_to_jiffies(chan->retrans_timeout)); 2614239d16fSMat Martineau } 2624239d16fSMat Martineau } 2634239d16fSMat Martineau 2644239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan) 2654239d16fSMat Martineau { 2664239d16fSMat Martineau __clear_retrans_timer(chan); 2674239d16fSMat Martineau if (chan->monitor_timeout) { 2684239d16fSMat Martineau l2cap_set_timer(chan, &chan->monitor_timer, 2694239d16fSMat Martineau msecs_to_jiffies(chan->monitor_timeout)); 2704239d16fSMat Martineau } 2714239d16fSMat Martineau } 2724239d16fSMat Martineau 273608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head, 274608bcc6dSMat Martineau u16 seq) 275608bcc6dSMat Martineau { 276608bcc6dSMat Martineau struct sk_buff *skb; 277608bcc6dSMat Martineau 278608bcc6dSMat Martineau skb_queue_walk(head, skb) { 279608bcc6dSMat Martineau if (bt_cb(skb)->control.txseq == seq) 280608bcc6dSMat Martineau return skb; 281608bcc6dSMat Martineau } 282608bcc6dSMat Martineau 283608bcc6dSMat Martineau return NULL; 284608bcc6dSMat Martineau } 285608bcc6dSMat Martineau 2863c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */ 2873c588192SMat Martineau 2883c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for 2893c588192SMat Martineau * SREJ requests that are received and for frames that are to be 2903c588192SMat Martineau * retransmitted. These seq_list functions implement a singly-linked 2913c588192SMat Martineau * list in an array, where membership in the list can also be checked 2923c588192SMat Martineau * in constant time. Items can also be added to the tail of the list 2933c588192SMat Martineau * and removed from the head in constant time, without further memory 2943c588192SMat Martineau * allocs or frees. 2953c588192SMat Martineau */ 2963c588192SMat Martineau 2973c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size) 2983c588192SMat Martineau { 2993c588192SMat Martineau size_t alloc_size, i; 3003c588192SMat Martineau 3013c588192SMat Martineau /* Allocated size is a power of 2 to map sequence numbers 3023c588192SMat Martineau * (which may be up to 14 bits) in to a smaller array that is 3033c588192SMat Martineau * sized for the negotiated ERTM transmit windows. 3043c588192SMat Martineau */ 3053c588192SMat Martineau alloc_size = roundup_pow_of_two(size); 3063c588192SMat Martineau 3073c588192SMat Martineau seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL); 3083c588192SMat Martineau if (!seq_list->list) 3093c588192SMat Martineau return -ENOMEM; 3103c588192SMat Martineau 3113c588192SMat Martineau seq_list->mask = alloc_size - 1; 3123c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3133c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3143c588192SMat Martineau for (i = 0; i < alloc_size; i++) 3153c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 3163c588192SMat Martineau 3173c588192SMat Martineau return 0; 3183c588192SMat Martineau } 3193c588192SMat Martineau 3203c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list) 3213c588192SMat Martineau { 3223c588192SMat Martineau kfree(seq_list->list); 3233c588192SMat Martineau } 3243c588192SMat Martineau 3253c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list, 3263c588192SMat Martineau u16 seq) 3273c588192SMat Martineau { 3283c588192SMat Martineau /* Constant-time check for list membership */ 3293c588192SMat Martineau return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR; 3303c588192SMat Martineau } 3313c588192SMat Martineau 3323c588192SMat Martineau static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq) 3333c588192SMat Martineau { 3343c588192SMat Martineau u16 mask = seq_list->mask; 3353c588192SMat Martineau 3363c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) { 3373c588192SMat Martineau /* In case someone tries to pop the head of an empty list */ 3383c588192SMat Martineau return L2CAP_SEQ_LIST_CLEAR; 3393c588192SMat Martineau } else if (seq_list->head == seq) { 3403c588192SMat Martineau /* Head can be removed in constant time */ 3413c588192SMat Martineau seq_list->head = seq_list->list[seq & mask]; 3423c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; 3433c588192SMat Martineau 3443c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_TAIL) { 3453c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3463c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3473c588192SMat Martineau } 3483c588192SMat Martineau } else { 3493c588192SMat Martineau /* Walk the list to find the sequence number */ 3503c588192SMat Martineau u16 prev = seq_list->head; 3513c588192SMat Martineau while (seq_list->list[prev & mask] != seq) { 3523c588192SMat Martineau prev = seq_list->list[prev & mask]; 3533c588192SMat Martineau if (prev == L2CAP_SEQ_LIST_TAIL) 3543c588192SMat Martineau return L2CAP_SEQ_LIST_CLEAR; 3553c588192SMat Martineau } 3563c588192SMat Martineau 3573c588192SMat Martineau /* Unlink the number from the list and clear it */ 3583c588192SMat Martineau seq_list->list[prev & mask] = seq_list->list[seq & mask]; 3593c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; 3603c588192SMat Martineau if (seq_list->tail == seq) 3613c588192SMat Martineau seq_list->tail = prev; 3623c588192SMat Martineau } 3633c588192SMat Martineau return seq; 3643c588192SMat Martineau } 3653c588192SMat Martineau 3663c588192SMat Martineau static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list) 3673c588192SMat Martineau { 3683c588192SMat Martineau /* Remove the head in constant time */ 3693c588192SMat Martineau return l2cap_seq_list_remove(seq_list, seq_list->head); 3703c588192SMat Martineau } 3713c588192SMat Martineau 3723c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list) 3733c588192SMat Martineau { 3743c588192SMat Martineau u16 i; 375f522ae36SGustavo Padovan 376f522ae36SGustavo Padovan if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) 377f522ae36SGustavo Padovan return; 378f522ae36SGustavo Padovan 3793c588192SMat Martineau for (i = 0; i <= seq_list->mask; i++) 3803c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 3813c588192SMat Martineau 3823c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3833c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3843c588192SMat Martineau } 3853c588192SMat Martineau 3863c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq) 3873c588192SMat Martineau { 3883c588192SMat Martineau u16 mask = seq_list->mask; 3893c588192SMat Martineau 3903c588192SMat Martineau /* All appends happen in constant time */ 3913c588192SMat Martineau 392f522ae36SGustavo Padovan if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR) 393f522ae36SGustavo Padovan return; 394f522ae36SGustavo Padovan 3953c588192SMat Martineau if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR) 3963c588192SMat Martineau seq_list->head = seq; 3973c588192SMat Martineau else 3983c588192SMat Martineau seq_list->list[seq_list->tail & mask] = seq; 3993c588192SMat Martineau 4003c588192SMat Martineau seq_list->tail = seq; 4013c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL; 4023c588192SMat Martineau } 4033c588192SMat Martineau 404721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work) 405ab07801dSGustavo F. Padovan { 406721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 407721c4181SGustavo F. Padovan chan_timer.work); 4083df91ea2SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 409ab07801dSGustavo F. Padovan int reason; 410ab07801dSGustavo F. Padovan 411e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 412ab07801dSGustavo F. Padovan 4133df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 4146be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 415ab07801dSGustavo F. Padovan 41689bc500eSGustavo F. Padovan if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) 417ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 41889bc500eSGustavo F. Padovan else if (chan->state == BT_CONNECT && 419ab07801dSGustavo F. Padovan chan->sec_level != BT_SECURITY_SDP) 420ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 421ab07801dSGustavo F. Padovan else 422ab07801dSGustavo F. Padovan reason = ETIMEDOUT; 423ab07801dSGustavo F. Padovan 4240f852724SGustavo F. Padovan l2cap_chan_close(chan, reason); 425ab07801dSGustavo F. Padovan 4266be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 427ab07801dSGustavo F. Padovan 42880b98027SGustavo Padovan chan->ops->close(chan); 4293df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4303df91ea2SAndrei Emeltchenko 431371fd835SUlisses Furquim l2cap_chan_put(chan); 432ab07801dSGustavo F. Padovan } 433ab07801dSGustavo F. Padovan 434eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void) 4350a708f8fSGustavo F. Padovan { 43648454079SGustavo F. Padovan struct l2cap_chan *chan; 4370a708f8fSGustavo F. Padovan 43848454079SGustavo F. Padovan chan = kzalloc(sizeof(*chan), GFP_ATOMIC); 43948454079SGustavo F. Padovan if (!chan) 44048454079SGustavo F. Padovan return NULL; 4410a708f8fSGustavo F. Padovan 442c03b355eSAndrei Emeltchenko mutex_init(&chan->lock); 443c03b355eSAndrei Emeltchenko 444333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 44523691d75SGustavo F. Padovan list_add(&chan->global_l, &chan_list); 446333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 44723691d75SGustavo F. Padovan 448721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout); 449ab07801dSGustavo F. Padovan 45089bc500eSGustavo F. Padovan chan->state = BT_OPEN; 45189bc500eSGustavo F. Padovan 452144ad330SSyam Sidhardhan kref_init(&chan->kref); 45371ba0e56SGustavo F. Padovan 4542827011fSMat Martineau /* This flag is cleared in l2cap_chan_ready() */ 4552827011fSMat Martineau set_bit(CONF_NOT_COMPLETE, &chan->conf_state); 4562827011fSMat Martineau 457eef1d9b6SGustavo Padovan BT_DBG("chan %p", chan); 458abc545b8SSzymon Janc 45948454079SGustavo F. Padovan return chan; 4600a708f8fSGustavo F. Padovan } 4610a708f8fSGustavo F. Padovan 462144ad330SSyam Sidhardhan static void l2cap_chan_destroy(struct kref *kref) 4636ff5abbfSGustavo F. Padovan { 464144ad330SSyam Sidhardhan struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref); 465144ad330SSyam Sidhardhan 4664af66c69SJaganath Kanakkassery BT_DBG("chan %p", chan); 4674af66c69SJaganath Kanakkassery 468333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 46923691d75SGustavo F. Padovan list_del(&chan->global_l); 470333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 47123691d75SGustavo F. Padovan 4724af66c69SJaganath Kanakkassery kfree(chan); 4736ff5abbfSGustavo F. Padovan } 4746ff5abbfSGustavo F. Padovan 47530648372SJaganath Kanakkassery void l2cap_chan_hold(struct l2cap_chan *c) 47630648372SJaganath Kanakkassery { 477144ad330SSyam Sidhardhan BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount)); 47830648372SJaganath Kanakkassery 479144ad330SSyam Sidhardhan kref_get(&c->kref); 48030648372SJaganath Kanakkassery } 48130648372SJaganath Kanakkassery 48230648372SJaganath Kanakkassery void l2cap_chan_put(struct l2cap_chan *c) 48330648372SJaganath Kanakkassery { 484144ad330SSyam Sidhardhan BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount)); 48530648372SJaganath Kanakkassery 486144ad330SSyam Sidhardhan kref_put(&c->kref, l2cap_chan_destroy); 48730648372SJaganath Kanakkassery } 48830648372SJaganath Kanakkassery 489bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan) 490bd4b1653SAndrei Emeltchenko { 491bd4b1653SAndrei Emeltchenko chan->fcs = L2CAP_FCS_CRC16; 492bd4b1653SAndrei Emeltchenko chan->max_tx = L2CAP_DEFAULT_MAX_TX; 493bd4b1653SAndrei Emeltchenko chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; 494bd4b1653SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 495c20f8e35SMat Martineau chan->ack_win = L2CAP_DEFAULT_TX_WINDOW; 496bd4b1653SAndrei Emeltchenko chan->sec_level = BT_SECURITY_LOW; 497bd4b1653SAndrei Emeltchenko 498bd4b1653SAndrei Emeltchenko set_bit(FLAG_FORCE_ACTIVE, &chan->flags); 499bd4b1653SAndrei Emeltchenko } 500bd4b1653SAndrei Emeltchenko 5010ce43ce6SJohan Hedberg static void l2cap_le_flowctl_init(struct l2cap_chan *chan) 50238319713SJohan Hedberg { 5030ce43ce6SJohan Hedberg chan->sdu = NULL; 5040ce43ce6SJohan Hedberg chan->sdu_last_frag = NULL; 5050ce43ce6SJohan Hedberg chan->sdu_len = 0; 5060cd75f7eSJohan Hedberg chan->tx_credits = 0; 507f15b8ecfSJohan Hedberg chan->rx_credits = le_max_credits; 5083916aed8SJohan Hedberg 5093916aed8SJohan Hedberg if (chan->imtu < L2CAP_LE_DEFAULT_MPS) 5103916aed8SJohan Hedberg chan->mps = chan->imtu; 5113916aed8SJohan Hedberg else 5123916aed8SJohan Hedberg chan->mps = L2CAP_LE_DEFAULT_MPS; 5130ce43ce6SJohan Hedberg 5140ce43ce6SJohan Hedberg skb_queue_head_init(&chan->tx_q); 51538319713SJohan Hedberg } 51638319713SJohan Hedberg 51793c3e8f5SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 5180a708f8fSGustavo F. Padovan { 5190a708f8fSGustavo F. Padovan BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, 520097db76cSAndrei Emeltchenko __le16_to_cpu(chan->psm), chan->dcid); 5210a708f8fSGustavo F. Padovan 5229f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 5230a708f8fSGustavo F. Padovan 5248c1d787bSGustavo F. Padovan chan->conn = conn; 5250a708f8fSGustavo F. Padovan 5265491120eSAndrei Emeltchenko switch (chan->chan_type) { 5275491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_ORIENTED: 528b62f328bSVille Tervo if (conn->hcon->type == LE_LINK) { 529aeddd075SJohan Hedberg if (chan->dcid == L2CAP_CID_ATT) { 5306fcb06a2SAndre Guedes chan->omtu = L2CAP_DEFAULT_MTU; 531073d1cf3SJohan Hedberg chan->scid = L2CAP_CID_ATT; 532aeddd075SJohan Hedberg } else { 5339f22398cSJohan Hedberg chan->scid = l2cap_alloc_cid(conn); 534aeddd075SJohan Hedberg } 535b62f328bSVille Tervo } else { 5360a708f8fSGustavo F. Padovan /* Alloc CID for connection-oriented socket */ 537fe4128e0SGustavo F. Padovan chan->scid = l2cap_alloc_cid(conn); 5380c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 539b62f328bSVille Tervo } 5405491120eSAndrei Emeltchenko break; 5415491120eSAndrei Emeltchenko 5425491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_LESS: 5430a708f8fSGustavo F. Padovan /* Connectionless socket */ 544fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_CONN_LESS; 545fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_CONN_LESS; 5460c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 5475491120eSAndrei Emeltchenko break; 5485491120eSAndrei Emeltchenko 549416fa752SAndrei Emeltchenko case L2CAP_CHAN_CONN_FIX_A2MP: 550416fa752SAndrei Emeltchenko chan->scid = L2CAP_CID_A2MP; 551416fa752SAndrei Emeltchenko chan->dcid = L2CAP_CID_A2MP; 552416fa752SAndrei Emeltchenko chan->omtu = L2CAP_A2MP_DEFAULT_MTU; 553416fa752SAndrei Emeltchenko chan->imtu = L2CAP_A2MP_DEFAULT_MTU; 554416fa752SAndrei Emeltchenko break; 555416fa752SAndrei Emeltchenko 5565491120eSAndrei Emeltchenko default: 5570a708f8fSGustavo F. Padovan /* Raw socket can send/recv signalling messages only */ 558fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_SIGNALING; 559fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_SIGNALING; 5600c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 5610a708f8fSGustavo F. Padovan } 5620a708f8fSGustavo F. Padovan 5638f7975b1SAndrei Emeltchenko chan->local_id = L2CAP_BESTEFFORT_ID; 5648f7975b1SAndrei Emeltchenko chan->local_stype = L2CAP_SERV_BESTEFFORT; 5658f7975b1SAndrei Emeltchenko chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE; 5668f7975b1SAndrei Emeltchenko chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME; 5678f7975b1SAndrei Emeltchenko chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT; 5688936fa6dSAndrei Emeltchenko chan->local_flush_to = L2CAP_EFS_DEFAULT_FLUSH_TO; 5698f7975b1SAndrei Emeltchenko 570371fd835SUlisses Furquim l2cap_chan_hold(chan); 571baa7e1faSGustavo F. Padovan 5725ee9891dSJohan Hedberg hci_conn_hold(conn->hcon); 5735ee9891dSJohan Hedberg 5743df91ea2SAndrei Emeltchenko list_add(&chan->list, &conn->chan_l); 575643162a8SAndrei Emeltchenko } 576643162a8SAndrei Emeltchenko 577466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 578643162a8SAndrei Emeltchenko { 579643162a8SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 580643162a8SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 5813df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 5820a708f8fSGustavo F. Padovan } 5830a708f8fSGustavo F. Padovan 584466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err) 5850a708f8fSGustavo F. Padovan { 5868c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 5870a708f8fSGustavo F. Padovan 588c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 5890a708f8fSGustavo F. Padovan 59049208c9cSGustavo F. Padovan BT_DBG("chan %p, conn %p, err %d", chan, conn, err); 5910a708f8fSGustavo F. Padovan 5920a708f8fSGustavo F. Padovan if (conn) { 59356f60984SAndrei Emeltchenko struct amp_mgr *mgr = conn->hcon->amp_mgr; 594baa7e1faSGustavo F. Padovan /* Delete from channel list */ 5953df91ea2SAndrei Emeltchenko list_del(&chan->list); 5963d57dc68SGustavo F. Padovan 597371fd835SUlisses Furquim l2cap_chan_put(chan); 598baa7e1faSGustavo F. Padovan 5998c1d787bSGustavo F. Padovan chan->conn = NULL; 6003cabbfdaSAndrei Emeltchenko 6013cabbfdaSAndrei Emeltchenko if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP) 60276a68ba0SDavid Herrmann hci_conn_drop(conn->hcon); 60356f60984SAndrei Emeltchenko 60456f60984SAndrei Emeltchenko if (mgr && mgr->bredr_chan == chan) 60556f60984SAndrei Emeltchenko mgr->bredr_chan = NULL; 6060a708f8fSGustavo F. Padovan } 6070a708f8fSGustavo F. Padovan 608419e08c1SAndrei Emeltchenko if (chan->hs_hchan) { 609419e08c1SAndrei Emeltchenko struct hci_chan *hs_hchan = chan->hs_hchan; 610419e08c1SAndrei Emeltchenko 611419e08c1SAndrei Emeltchenko BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan); 612419e08c1SAndrei Emeltchenko amp_disconnect_logical_link(hs_hchan); 613419e08c1SAndrei Emeltchenko } 614419e08c1SAndrei Emeltchenko 615c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, err); 6166be36555SAndrei Emeltchenko 6172827011fSMat Martineau if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) 6186ff5abbfSGustavo F. Padovan return; 6192ead70b8SGustavo F. Padovan 620ee556f66SGustavo Padovan switch(chan->mode) { 621ee556f66SGustavo Padovan case L2CAP_MODE_BASIC: 622ee556f66SGustavo Padovan break; 6230a708f8fSGustavo F. Padovan 62438319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 625177f8f2bSJohan Hedberg skb_queue_purge(&chan->tx_q); 62638319713SJohan Hedberg break; 62738319713SJohan Hedberg 628ee556f66SGustavo Padovan case L2CAP_MODE_ERTM: 6291a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 6301a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 6311a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 6320a708f8fSGustavo F. Padovan 633f1c6775bSGustavo F. Padovan skb_queue_purge(&chan->srej_q); 6340a708f8fSGustavo F. Padovan 6353c588192SMat Martineau l2cap_seq_list_free(&chan->srej_list); 6363c588192SMat Martineau l2cap_seq_list_free(&chan->retrans_list); 637ee556f66SGustavo Padovan 638ee556f66SGustavo Padovan /* fall through */ 639ee556f66SGustavo Padovan 640ee556f66SGustavo Padovan case L2CAP_MODE_STREAMING: 641ee556f66SGustavo Padovan skb_queue_purge(&chan->tx_q); 642ee556f66SGustavo Padovan break; 6430a708f8fSGustavo F. Padovan } 644ee556f66SGustavo Padovan 645ee556f66SGustavo Padovan return; 6460a708f8fSGustavo F. Padovan } 6470a708f8fSGustavo F. Padovan 64827e2d4c8SJohan Hedberg static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan) 64927e2d4c8SJohan Hedberg { 65027e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn; 65127e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 65227e2d4c8SJohan Hedberg u16 result; 65327e2d4c8SJohan Hedberg 65427e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 65527e2d4c8SJohan Hedberg result = L2CAP_CR_AUTHORIZATION; 65627e2d4c8SJohan Hedberg else 65727e2d4c8SJohan Hedberg result = L2CAP_CR_BAD_PSM; 65827e2d4c8SJohan Hedberg 65927e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_DISCONN); 66027e2d4c8SJohan Hedberg 66127e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 66227e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 6633916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps); 6640cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits); 66527e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result); 66627e2d4c8SJohan Hedberg 66727e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), 66827e2d4c8SJohan Hedberg &rsp); 66927e2d4c8SJohan Hedberg } 67027e2d4c8SJohan Hedberg 671791d60f7SJohan Hedberg static void l2cap_chan_connect_reject(struct l2cap_chan *chan) 672791d60f7SJohan Hedberg { 673791d60f7SJohan Hedberg struct l2cap_conn *conn = chan->conn; 674791d60f7SJohan Hedberg struct l2cap_conn_rsp rsp; 675791d60f7SJohan Hedberg u16 result; 676791d60f7SJohan Hedberg 677791d60f7SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) 678791d60f7SJohan Hedberg result = L2CAP_CR_SEC_BLOCK; 679791d60f7SJohan Hedberg else 680791d60f7SJohan Hedberg result = L2CAP_CR_BAD_PSM; 681791d60f7SJohan Hedberg 682791d60f7SJohan Hedberg l2cap_state_change(chan, BT_DISCONN); 683791d60f7SJohan Hedberg 684791d60f7SJohan Hedberg rsp.scid = cpu_to_le16(chan->dcid); 685791d60f7SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 686791d60f7SJohan Hedberg rsp.result = cpu_to_le16(result); 687791d60f7SJohan Hedberg rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 688791d60f7SJohan Hedberg 689791d60f7SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); 690791d60f7SJohan Hedberg } 691791d60f7SJohan Hedberg 6920f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason) 6934519de9aSGustavo F. Padovan { 6944519de9aSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 6954519de9aSGustavo F. Padovan 6967eafc59eSMarcel Holtmann BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 6974519de9aSGustavo F. Padovan 69889bc500eSGustavo F. Padovan switch (chan->state) { 6994519de9aSGustavo F. Padovan case BT_LISTEN: 700c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 7014519de9aSGustavo F. Padovan break; 7024519de9aSGustavo F. Padovan 7034519de9aSGustavo F. Padovan case BT_CONNECTED: 7044519de9aSGustavo F. Padovan case BT_CONFIG: 705cea04ce3SJohan Hedberg /* ATT uses L2CAP_CHAN_CONN_ORIENTED so we must also 706cea04ce3SJohan Hedberg * check for chan->psm. 707cea04ce3SJohan Hedberg */ 708cea04ce3SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && chan->psm) { 7098d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 7105e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, reason); 7114519de9aSGustavo F. Padovan } else 7124519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 7134519de9aSGustavo F. Padovan break; 7144519de9aSGustavo F. Padovan 7154519de9aSGustavo F. Padovan case BT_CONNECT2: 716791d60f7SJohan Hedberg if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) { 717791d60f7SJohan Hedberg if (conn->hcon->type == ACL_LINK) 718791d60f7SJohan Hedberg l2cap_chan_connect_reject(chan); 71927e2d4c8SJohan Hedberg else if (conn->hcon->type == LE_LINK) 72027e2d4c8SJohan Hedberg l2cap_chan_le_connect_reject(chan); 7214519de9aSGustavo F. Padovan } 7224519de9aSGustavo F. Padovan 7234519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 7244519de9aSGustavo F. Padovan break; 7254519de9aSGustavo F. Padovan 7264519de9aSGustavo F. Padovan case BT_CONNECT: 7274519de9aSGustavo F. Padovan case BT_DISCONN: 7284519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 7294519de9aSGustavo F. Padovan break; 7304519de9aSGustavo F. Padovan 7314519de9aSGustavo F. Padovan default: 732c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 7334519de9aSGustavo F. Padovan break; 7344519de9aSGustavo F. Padovan } 7354519de9aSGustavo F. Padovan } 7364519de9aSGustavo F. Padovan 7374343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) 7380a708f8fSGustavo F. Padovan { 7396a974b50SMarcel Holtmann switch (chan->chan_type) { 7406a974b50SMarcel Holtmann case L2CAP_CHAN_RAW: 7414343478fSGustavo F. Padovan switch (chan->sec_level) { 7420a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 7430a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING_MITM; 7440a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 7450a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING; 7460a708f8fSGustavo F. Padovan default: 7470a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 7480a708f8fSGustavo F. Padovan } 7496a974b50SMarcel Holtmann break; 7503124b843SMarcel Holtmann case L2CAP_CHAN_CONN_LESS: 7513124b843SMarcel Holtmann if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_3DSP)) { 7523124b843SMarcel Holtmann if (chan->sec_level == BT_SECURITY_LOW) 7533124b843SMarcel Holtmann chan->sec_level = BT_SECURITY_SDP; 7543124b843SMarcel Holtmann } 7553124b843SMarcel Holtmann if (chan->sec_level == BT_SECURITY_HIGH) 7563124b843SMarcel Holtmann return HCI_AT_NO_BONDING_MITM; 7573124b843SMarcel Holtmann else 7583124b843SMarcel Holtmann return HCI_AT_NO_BONDING; 7593124b843SMarcel Holtmann break; 7606a974b50SMarcel Holtmann case L2CAP_CHAN_CONN_ORIENTED: 7616a974b50SMarcel Holtmann if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) { 7624343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_LOW) 7634343478fSGustavo F. Padovan chan->sec_level = BT_SECURITY_SDP; 7640a708f8fSGustavo F. Padovan 7654343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_HIGH) 7660a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING_MITM; 7670a708f8fSGustavo F. Padovan else 7680a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 7696a974b50SMarcel Holtmann } 7706a974b50SMarcel Holtmann /* fall through */ 7716a974b50SMarcel Holtmann default: 7724343478fSGustavo F. Padovan switch (chan->sec_level) { 7730a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 7740a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING_MITM; 7750a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 7760a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING; 7770a708f8fSGustavo F. Padovan default: 7780a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 7790a708f8fSGustavo F. Padovan } 7806a974b50SMarcel Holtmann break; 7810a708f8fSGustavo F. Padovan } 7820a708f8fSGustavo F. Padovan } 7830a708f8fSGustavo F. Padovan 7840a708f8fSGustavo F. Padovan /* Service level security */ 785d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan) 7860a708f8fSGustavo F. Padovan { 7878c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 7880a708f8fSGustavo F. Padovan __u8 auth_type; 7890a708f8fSGustavo F. Padovan 790a17de2feSJohan Hedberg if (conn->hcon->type == LE_LINK) 791a17de2feSJohan Hedberg return smp_conn_security(conn->hcon, chan->sec_level); 792a17de2feSJohan Hedberg 7934343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 7940a708f8fSGustavo F. Padovan 7954343478fSGustavo F. Padovan return hci_conn_security(conn->hcon, chan->sec_level, auth_type); 7960a708f8fSGustavo F. Padovan } 7970a708f8fSGustavo F. Padovan 798b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn) 7990a708f8fSGustavo F. Padovan { 8000a708f8fSGustavo F. Padovan u8 id; 8010a708f8fSGustavo F. Padovan 8020a708f8fSGustavo F. Padovan /* Get next available identificator. 8030a708f8fSGustavo F. Padovan * 1 - 128 are used by kernel. 8040a708f8fSGustavo F. Padovan * 129 - 199 are reserved. 8050a708f8fSGustavo F. Padovan * 200 - 254 are used by utilities like l2ping, etc. 8060a708f8fSGustavo F. Padovan */ 8070a708f8fSGustavo F. Padovan 808333055f2SGustavo F. Padovan spin_lock(&conn->lock); 8090a708f8fSGustavo F. Padovan 8100a708f8fSGustavo F. Padovan if (++conn->tx_ident > 128) 8110a708f8fSGustavo F. Padovan conn->tx_ident = 1; 8120a708f8fSGustavo F. Padovan 8130a708f8fSGustavo F. Padovan id = conn->tx_ident; 8140a708f8fSGustavo F. Padovan 815333055f2SGustavo F. Padovan spin_unlock(&conn->lock); 8160a708f8fSGustavo F. Padovan 8170a708f8fSGustavo F. Padovan return id; 8180a708f8fSGustavo F. Padovan } 8190a708f8fSGustavo F. Padovan 8202d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 8212d792818SGustavo Padovan void *data) 8220a708f8fSGustavo F. Padovan { 8230a708f8fSGustavo F. Padovan struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); 8240a708f8fSGustavo F. Padovan u8 flags; 8250a708f8fSGustavo F. Padovan 8260a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x", code); 8270a708f8fSGustavo F. Padovan 8280a708f8fSGustavo F. Padovan if (!skb) 8290a708f8fSGustavo F. Padovan return; 8300a708f8fSGustavo F. Padovan 8310a708f8fSGustavo F. Padovan if (lmp_no_flush_capable(conn->hcon->hdev)) 8320a708f8fSGustavo F. Padovan flags = ACL_START_NO_FLUSH; 8330a708f8fSGustavo F. Padovan else 8340a708f8fSGustavo F. Padovan flags = ACL_START; 8350a708f8fSGustavo F. Padovan 83614b12d0bSJaikumar Ganesh bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON; 8375e59b791SLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 83814b12d0bSJaikumar Ganesh 83973d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, flags); 8400a708f8fSGustavo F. Padovan } 8410a708f8fSGustavo F. Padovan 84202b0fbb9SMat Martineau static bool __chan_is_moving(struct l2cap_chan *chan) 84302b0fbb9SMat Martineau { 84402b0fbb9SMat Martineau return chan->move_state != L2CAP_MOVE_STABLE && 84502b0fbb9SMat Martineau chan->move_state != L2CAP_MOVE_WAIT_PREPARE; 84602b0fbb9SMat Martineau } 84702b0fbb9SMat Martineau 84873d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) 84973d80debSLuiz Augusto von Dentz { 85073d80debSLuiz Augusto von Dentz struct hci_conn *hcon = chan->conn->hcon; 85173d80debSLuiz Augusto von Dentz u16 flags; 85273d80debSLuiz Augusto von Dentz 85373d80debSLuiz Augusto von Dentz BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, 85473d80debSLuiz Augusto von Dentz skb->priority); 85573d80debSLuiz Augusto von Dentz 856d5f8a75dSMat Martineau if (chan->hs_hcon && !__chan_is_moving(chan)) { 857d5f8a75dSMat Martineau if (chan->hs_hchan) 858d5f8a75dSMat Martineau hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE); 859d5f8a75dSMat Martineau else 860d5f8a75dSMat Martineau kfree_skb(skb); 861d5f8a75dSMat Martineau 862d5f8a75dSMat Martineau return; 863d5f8a75dSMat Martineau } 864d5f8a75dSMat Martineau 86573d80debSLuiz Augusto von Dentz if (!test_bit(FLAG_FLUSHABLE, &chan->flags) && 86673d80debSLuiz Augusto von Dentz lmp_no_flush_capable(hcon->hdev)) 86773d80debSLuiz Augusto von Dentz flags = ACL_START_NO_FLUSH; 86873d80debSLuiz Augusto von Dentz else 86973d80debSLuiz Augusto von Dentz flags = ACL_START; 87073d80debSLuiz Augusto von Dentz 87173d80debSLuiz Augusto von Dentz bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); 87273d80debSLuiz Augusto von Dentz hci_send_acl(chan->conn->hchan, skb, flags); 8730a708f8fSGustavo F. Padovan } 8740a708f8fSGustavo F. Padovan 875b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control) 876b5c6aaedSMat Martineau { 877b5c6aaedSMat Martineau control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT; 878b5c6aaedSMat Martineau control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT; 879b5c6aaedSMat Martineau 880b5c6aaedSMat Martineau if (enh & L2CAP_CTRL_FRAME_TYPE) { 881b5c6aaedSMat Martineau /* S-Frame */ 882b5c6aaedSMat Martineau control->sframe = 1; 883b5c6aaedSMat Martineau control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT; 884b5c6aaedSMat Martineau control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT; 885b5c6aaedSMat Martineau 886b5c6aaedSMat Martineau control->sar = 0; 887b5c6aaedSMat Martineau control->txseq = 0; 888b5c6aaedSMat Martineau } else { 889b5c6aaedSMat Martineau /* I-Frame */ 890b5c6aaedSMat Martineau control->sframe = 0; 891b5c6aaedSMat Martineau control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT; 892b5c6aaedSMat Martineau control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT; 893b5c6aaedSMat Martineau 894b5c6aaedSMat Martineau control->poll = 0; 895b5c6aaedSMat Martineau control->super = 0; 896b5c6aaedSMat Martineau } 897b5c6aaedSMat Martineau } 898b5c6aaedSMat Martineau 899b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control) 900b5c6aaedSMat Martineau { 901b5c6aaedSMat Martineau control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT; 902b5c6aaedSMat Martineau control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT; 903b5c6aaedSMat Martineau 904b5c6aaedSMat Martineau if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) { 905b5c6aaedSMat Martineau /* S-Frame */ 906b5c6aaedSMat Martineau control->sframe = 1; 907b5c6aaedSMat Martineau control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT; 908b5c6aaedSMat Martineau control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT; 909b5c6aaedSMat Martineau 910b5c6aaedSMat Martineau control->sar = 0; 911b5c6aaedSMat Martineau control->txseq = 0; 912b5c6aaedSMat Martineau } else { 913b5c6aaedSMat Martineau /* I-Frame */ 914b5c6aaedSMat Martineau control->sframe = 0; 915b5c6aaedSMat Martineau control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT; 916b5c6aaedSMat Martineau control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT; 917b5c6aaedSMat Martineau 918b5c6aaedSMat Martineau control->poll = 0; 919b5c6aaedSMat Martineau control->super = 0; 920b5c6aaedSMat Martineau } 921b5c6aaedSMat Martineau } 922b5c6aaedSMat Martineau 923b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan, 924b5c6aaedSMat Martineau struct sk_buff *skb) 925b5c6aaedSMat Martineau { 926b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 927b5c6aaedSMat Martineau __unpack_extended_control(get_unaligned_le32(skb->data), 928b5c6aaedSMat Martineau &bt_cb(skb)->control); 929cec8ab6eSMat Martineau skb_pull(skb, L2CAP_EXT_CTRL_SIZE); 930b5c6aaedSMat Martineau } else { 931b5c6aaedSMat Martineau __unpack_enhanced_control(get_unaligned_le16(skb->data), 932b5c6aaedSMat Martineau &bt_cb(skb)->control); 933cec8ab6eSMat Martineau skb_pull(skb, L2CAP_ENH_CTRL_SIZE); 934b5c6aaedSMat Martineau } 935b5c6aaedSMat Martineau } 936b5c6aaedSMat Martineau 937b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control) 938b5c6aaedSMat Martineau { 939b5c6aaedSMat Martineau u32 packed; 940b5c6aaedSMat Martineau 941b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT; 942b5c6aaedSMat Martineau packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT; 943b5c6aaedSMat Martineau 944b5c6aaedSMat Martineau if (control->sframe) { 945b5c6aaedSMat Martineau packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT; 946b5c6aaedSMat Martineau packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT; 947b5c6aaedSMat Martineau packed |= L2CAP_EXT_CTRL_FRAME_TYPE; 948b5c6aaedSMat Martineau } else { 949b5c6aaedSMat Martineau packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT; 950b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT; 951b5c6aaedSMat Martineau } 952b5c6aaedSMat Martineau 953b5c6aaedSMat Martineau return packed; 954b5c6aaedSMat Martineau } 955b5c6aaedSMat Martineau 956b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control) 957b5c6aaedSMat Martineau { 958b5c6aaedSMat Martineau u16 packed; 959b5c6aaedSMat Martineau 960b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT; 961b5c6aaedSMat Martineau packed |= control->final << L2CAP_CTRL_FINAL_SHIFT; 962b5c6aaedSMat Martineau 963b5c6aaedSMat Martineau if (control->sframe) { 964b5c6aaedSMat Martineau packed |= control->poll << L2CAP_CTRL_POLL_SHIFT; 965b5c6aaedSMat Martineau packed |= control->super << L2CAP_CTRL_SUPER_SHIFT; 966b5c6aaedSMat Martineau packed |= L2CAP_CTRL_FRAME_TYPE; 967b5c6aaedSMat Martineau } else { 968b5c6aaedSMat Martineau packed |= control->sar << L2CAP_CTRL_SAR_SHIFT; 969b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT; 970b5c6aaedSMat Martineau } 971b5c6aaedSMat Martineau 972b5c6aaedSMat Martineau return packed; 973b5c6aaedSMat Martineau } 974b5c6aaedSMat Martineau 975b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan, 976b5c6aaedSMat Martineau struct l2cap_ctrl *control, 977b5c6aaedSMat Martineau struct sk_buff *skb) 978b5c6aaedSMat Martineau { 979b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 980b5c6aaedSMat Martineau put_unaligned_le32(__pack_extended_control(control), 981b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 982b5c6aaedSMat Martineau } else { 983b5c6aaedSMat Martineau put_unaligned_le16(__pack_enhanced_control(control), 984b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 985b5c6aaedSMat Martineau } 986b5c6aaedSMat Martineau } 987b5c6aaedSMat Martineau 988ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan) 989ba7aa64fSGustavo Padovan { 990ba7aa64fSGustavo Padovan if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 991ba7aa64fSGustavo Padovan return L2CAP_EXT_HDR_SIZE; 992ba7aa64fSGustavo Padovan else 993ba7aa64fSGustavo Padovan return L2CAP_ENH_HDR_SIZE; 994ba7aa64fSGustavo Padovan } 995ba7aa64fSGustavo Padovan 996a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan, 997a67d7f6fSMat Martineau u32 control) 9980a708f8fSGustavo F. Padovan { 9990a708f8fSGustavo F. Padovan struct sk_buff *skb; 10000a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 1001ba7aa64fSGustavo Padovan int hlen = __ertm_hdr_size(chan); 10020a708f8fSGustavo F. Padovan 10030a708f8fSGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 100403a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 10050a708f8fSGustavo F. Padovan 1006a67d7f6fSMat Martineau skb = bt_skb_alloc(hlen, GFP_KERNEL); 10070a708f8fSGustavo F. Padovan 10080a708f8fSGustavo F. Padovan if (!skb) 1009a67d7f6fSMat Martineau return ERR_PTR(-ENOMEM); 10100a708f8fSGustavo F. Padovan 10110a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 10120a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); 1013fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 101488843ab0SAndrei Emeltchenko 1015a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1016a67d7f6fSMat Martineau put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 1017a67d7f6fSMat Martineau else 1018a67d7f6fSMat Martineau put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 10190a708f8fSGustavo F. Padovan 102047d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 1021a67d7f6fSMat Martineau u16 fcs = crc16(0, (u8 *)skb->data, skb->len); 102203a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 10230a708f8fSGustavo F. Padovan } 10240a708f8fSGustavo F. Padovan 102573d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 1026a67d7f6fSMat Martineau return skb; 1027a67d7f6fSMat Martineau } 1028a67d7f6fSMat Martineau 1029a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan, 1030a67d7f6fSMat Martineau struct l2cap_ctrl *control) 1031a67d7f6fSMat Martineau { 1032a67d7f6fSMat Martineau struct sk_buff *skb; 1033a67d7f6fSMat Martineau u32 control_field; 1034a67d7f6fSMat Martineau 1035a67d7f6fSMat Martineau BT_DBG("chan %p, control %p", chan, control); 1036a67d7f6fSMat Martineau 1037a67d7f6fSMat Martineau if (!control->sframe) 1038a67d7f6fSMat Martineau return; 1039a67d7f6fSMat Martineau 1040b99e13adSMat Martineau if (__chan_is_moving(chan)) 1041b99e13adSMat Martineau return; 1042b99e13adSMat Martineau 1043a67d7f6fSMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) && 1044a67d7f6fSMat Martineau !control->poll) 1045a67d7f6fSMat Martineau control->final = 1; 1046a67d7f6fSMat Martineau 1047a67d7f6fSMat Martineau if (control->super == L2CAP_SUPER_RR) 1048a67d7f6fSMat Martineau clear_bit(CONN_RNR_SENT, &chan->conn_state); 1049a67d7f6fSMat Martineau else if (control->super == L2CAP_SUPER_RNR) 1050a67d7f6fSMat Martineau set_bit(CONN_RNR_SENT, &chan->conn_state); 1051a67d7f6fSMat Martineau 1052a67d7f6fSMat Martineau if (control->super != L2CAP_SUPER_SREJ) { 1053a67d7f6fSMat Martineau chan->last_acked_seq = control->reqseq; 1054a67d7f6fSMat Martineau __clear_ack_timer(chan); 1055a67d7f6fSMat Martineau } 1056a67d7f6fSMat Martineau 1057a67d7f6fSMat Martineau BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq, 1058a67d7f6fSMat Martineau control->final, control->poll, control->super); 1059a67d7f6fSMat Martineau 1060a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1061a67d7f6fSMat Martineau control_field = __pack_extended_control(control); 1062a67d7f6fSMat Martineau else 1063a67d7f6fSMat Martineau control_field = __pack_enhanced_control(control); 1064a67d7f6fSMat Martineau 1065a67d7f6fSMat Martineau skb = l2cap_create_sframe_pdu(chan, control_field); 1066a67d7f6fSMat Martineau if (!IS_ERR(skb)) 106773d80debSLuiz Augusto von Dentz l2cap_do_send(chan, skb); 10680a708f8fSGustavo F. Padovan } 10690a708f8fSGustavo F. Padovan 1070c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll) 10710a708f8fSGustavo F. Padovan { 1072c9e3d5e0SMat Martineau struct l2cap_ctrl control; 10730a708f8fSGustavo F. Padovan 1074c9e3d5e0SMat Martineau BT_DBG("chan %p, poll %d", chan, poll); 1075c9e3d5e0SMat Martineau 1076c9e3d5e0SMat Martineau memset(&control, 0, sizeof(control)); 1077c9e3d5e0SMat Martineau control.sframe = 1; 1078c9e3d5e0SMat Martineau control.poll = poll; 1079c9e3d5e0SMat Martineau 1080c9e3d5e0SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 1081c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RNR; 1082c9e3d5e0SMat Martineau else 1083c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RR; 1084c9e3d5e0SMat Martineau 1085c9e3d5e0SMat Martineau control.reqseq = chan->buffer_seq; 1086c9e3d5e0SMat Martineau l2cap_send_sframe(chan, &control); 10870a708f8fSGustavo F. Padovan } 10880a708f8fSGustavo F. Padovan 1089b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) 10900a708f8fSGustavo F. Padovan { 1091c1360a1cSGustavo F. Padovan return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); 10920a708f8fSGustavo F. Padovan } 10930a708f8fSGustavo F. Padovan 109493c3e8f5SAndrei Emeltchenko static bool __amp_capable(struct l2cap_chan *chan) 109593c3e8f5SAndrei Emeltchenko { 109693c3e8f5SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 10971df7b17aSMarcel Holtmann struct hci_dev *hdev; 10981df7b17aSMarcel Holtmann bool amp_available = false; 109993c3e8f5SAndrei Emeltchenko 11001df7b17aSMarcel Holtmann if (!conn->hs_enabled) 11011df7b17aSMarcel Holtmann return false; 11021df7b17aSMarcel Holtmann 11031df7b17aSMarcel Holtmann if (!(conn->fixed_chan_mask & L2CAP_FC_A2MP)) 11041df7b17aSMarcel Holtmann return false; 11051df7b17aSMarcel Holtmann 11061df7b17aSMarcel Holtmann read_lock(&hci_dev_list_lock); 11071df7b17aSMarcel Holtmann list_for_each_entry(hdev, &hci_dev_list, list) { 11081df7b17aSMarcel Holtmann if (hdev->amp_type != AMP_TYPE_BREDR && 11091df7b17aSMarcel Holtmann test_bit(HCI_UP, &hdev->flags)) { 11101df7b17aSMarcel Holtmann amp_available = true; 11111df7b17aSMarcel Holtmann break; 11121df7b17aSMarcel Holtmann } 11131df7b17aSMarcel Holtmann } 11141df7b17aSMarcel Holtmann read_unlock(&hci_dev_list_lock); 11151df7b17aSMarcel Holtmann 11161df7b17aSMarcel Holtmann if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED) 11171df7b17aSMarcel Holtmann return amp_available; 1118848566b3SMarcel Holtmann 111993c3e8f5SAndrei Emeltchenko return false; 112093c3e8f5SAndrei Emeltchenko } 112193c3e8f5SAndrei Emeltchenko 11225ce66b59SAndrei Emeltchenko static bool l2cap_check_efs(struct l2cap_chan *chan) 11235ce66b59SAndrei Emeltchenko { 11245ce66b59SAndrei Emeltchenko /* Check EFS parameters */ 11255ce66b59SAndrei Emeltchenko return true; 11265ce66b59SAndrei Emeltchenko } 11275ce66b59SAndrei Emeltchenko 11282766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan) 11299b27f350SAndrei Emeltchenko { 11309b27f350SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 11319b27f350SAndrei Emeltchenko struct l2cap_conn_req req; 11329b27f350SAndrei Emeltchenko 11339b27f350SAndrei Emeltchenko req.scid = cpu_to_le16(chan->scid); 11349b27f350SAndrei Emeltchenko req.psm = chan->psm; 11359b27f350SAndrei Emeltchenko 11369b27f350SAndrei Emeltchenko chan->ident = l2cap_get_ident(conn); 11379b27f350SAndrei Emeltchenko 11389b27f350SAndrei Emeltchenko set_bit(CONF_CONNECT_PEND, &chan->conf_state); 11399b27f350SAndrei Emeltchenko 11409b27f350SAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); 11419b27f350SAndrei Emeltchenko } 11429b27f350SAndrei Emeltchenko 11438eb200bdSMat Martineau static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id) 11448eb200bdSMat Martineau { 11458eb200bdSMat Martineau struct l2cap_create_chan_req req; 11468eb200bdSMat Martineau req.scid = cpu_to_le16(chan->scid); 11478eb200bdSMat Martineau req.psm = chan->psm; 11488eb200bdSMat Martineau req.amp_id = amp_id; 11498eb200bdSMat Martineau 11508eb200bdSMat Martineau chan->ident = l2cap_get_ident(chan->conn); 11518eb200bdSMat Martineau 11528eb200bdSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ, 11538eb200bdSMat Martineau sizeof(req), &req); 11548eb200bdSMat Martineau } 11558eb200bdSMat Martineau 115602b0fbb9SMat Martineau static void l2cap_move_setup(struct l2cap_chan *chan) 115702b0fbb9SMat Martineau { 115802b0fbb9SMat Martineau struct sk_buff *skb; 115902b0fbb9SMat Martineau 116002b0fbb9SMat Martineau BT_DBG("chan %p", chan); 116102b0fbb9SMat Martineau 116202b0fbb9SMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 116302b0fbb9SMat Martineau return; 116402b0fbb9SMat Martineau 116502b0fbb9SMat Martineau __clear_retrans_timer(chan); 116602b0fbb9SMat Martineau __clear_monitor_timer(chan); 116702b0fbb9SMat Martineau __clear_ack_timer(chan); 116802b0fbb9SMat Martineau 116902b0fbb9SMat Martineau chan->retry_count = 0; 117002b0fbb9SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 117102b0fbb9SMat Martineau if (bt_cb(skb)->control.retries) 117202b0fbb9SMat Martineau bt_cb(skb)->control.retries = 1; 117302b0fbb9SMat Martineau else 117402b0fbb9SMat Martineau break; 117502b0fbb9SMat Martineau } 117602b0fbb9SMat Martineau 117702b0fbb9SMat Martineau chan->expected_tx_seq = chan->buffer_seq; 117802b0fbb9SMat Martineau 117902b0fbb9SMat Martineau clear_bit(CONN_REJ_ACT, &chan->conn_state); 118002b0fbb9SMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 118102b0fbb9SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 118202b0fbb9SMat Martineau l2cap_seq_list_clear(&chan->srej_list); 118302b0fbb9SMat Martineau skb_queue_purge(&chan->srej_q); 118402b0fbb9SMat Martineau 118502b0fbb9SMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 118602b0fbb9SMat Martineau chan->rx_state = L2CAP_RX_STATE_MOVE; 118702b0fbb9SMat Martineau 118802b0fbb9SMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 118902b0fbb9SMat Martineau } 119002b0fbb9SMat Martineau 11915f3847a4SMat Martineau static void l2cap_move_done(struct l2cap_chan *chan) 11925f3847a4SMat Martineau { 11935f3847a4SMat Martineau u8 move_role = chan->move_role; 11945f3847a4SMat Martineau BT_DBG("chan %p", chan); 11955f3847a4SMat Martineau 11965f3847a4SMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 11975f3847a4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 11985f3847a4SMat Martineau 11995f3847a4SMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 12005f3847a4SMat Martineau return; 12015f3847a4SMat Martineau 12025f3847a4SMat Martineau switch (move_role) { 12035f3847a4SMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 12045f3847a4SMat Martineau l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL); 12055f3847a4SMat Martineau chan->rx_state = L2CAP_RX_STATE_WAIT_F; 12065f3847a4SMat Martineau break; 12075f3847a4SMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 12085f3847a4SMat Martineau chan->rx_state = L2CAP_RX_STATE_WAIT_P; 12095f3847a4SMat Martineau break; 12105f3847a4SMat Martineau } 12115f3847a4SMat Martineau } 12125f3847a4SMat Martineau 12139f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan) 12149f0caeb1SVinicius Costa Gomes { 12152827011fSMat Martineau /* This clears all conf flags, including CONF_NOT_COMPLETE */ 12169f0caeb1SVinicius Costa Gomes chan->conf_state = 0; 12179f0caeb1SVinicius Costa Gomes __clear_chan_timer(chan); 12189f0caeb1SVinicius Costa Gomes 12190ce43ce6SJohan Hedberg if (chan->mode == L2CAP_MODE_LE_FLOWCTL && !chan->tx_credits) 12200ce43ce6SJohan Hedberg chan->ops->suspend(chan); 1221177f8f2bSJohan Hedberg 122254a59aa2SAndrei Emeltchenko chan->state = BT_CONNECTED; 12239f0caeb1SVinicius Costa Gomes 122454a59aa2SAndrei Emeltchenko chan->ops->ready(chan); 12259f0caeb1SVinicius Costa Gomes } 12269f0caeb1SVinicius Costa Gomes 1227f1496deeSJohan Hedberg static void l2cap_le_connect(struct l2cap_chan *chan) 1228f1496deeSJohan Hedberg { 1229f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1230f1496deeSJohan Hedberg struct l2cap_le_conn_req req; 1231f1496deeSJohan Hedberg 1232595177f3SJohan Hedberg if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags)) 1233595177f3SJohan Hedberg return; 1234595177f3SJohan Hedberg 1235f1496deeSJohan Hedberg req.psm = chan->psm; 1236f1496deeSJohan Hedberg req.scid = cpu_to_le16(chan->scid); 1237f1496deeSJohan Hedberg req.mtu = cpu_to_le16(chan->imtu); 12383916aed8SJohan Hedberg req.mps = cpu_to_le16(chan->mps); 12390cd75f7eSJohan Hedberg req.credits = cpu_to_le16(chan->rx_credits); 1240f1496deeSJohan Hedberg 1241f1496deeSJohan Hedberg chan->ident = l2cap_get_ident(conn); 1242f1496deeSJohan Hedberg 1243f1496deeSJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ, 1244f1496deeSJohan Hedberg sizeof(req), &req); 1245f1496deeSJohan Hedberg } 1246f1496deeSJohan Hedberg 1247f1496deeSJohan Hedberg static void l2cap_le_start(struct l2cap_chan *chan) 1248f1496deeSJohan Hedberg { 1249f1496deeSJohan Hedberg struct l2cap_conn *conn = chan->conn; 1250f1496deeSJohan Hedberg 1251f1496deeSJohan Hedberg if (!smp_conn_security(conn->hcon, chan->sec_level)) 1252f1496deeSJohan Hedberg return; 1253f1496deeSJohan Hedberg 1254f1496deeSJohan Hedberg if (!chan->psm) { 1255f1496deeSJohan Hedberg l2cap_chan_ready(chan); 1256f1496deeSJohan Hedberg return; 1257f1496deeSJohan Hedberg } 1258f1496deeSJohan Hedberg 1259f1496deeSJohan Hedberg if (chan->state == BT_CONNECT) 1260f1496deeSJohan Hedberg l2cap_le_connect(chan); 1261f1496deeSJohan Hedberg } 1262f1496deeSJohan Hedberg 126393c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan) 126493c3e8f5SAndrei Emeltchenko { 126593c3e8f5SAndrei Emeltchenko if (__amp_capable(chan)) { 126693c3e8f5SAndrei Emeltchenko BT_DBG("chan %p AMP capable: discover AMPs", chan); 126793c3e8f5SAndrei Emeltchenko a2mp_discover_amp(chan); 1268f1496deeSJohan Hedberg } else if (chan->conn->hcon->type == LE_LINK) { 1269f1496deeSJohan Hedberg l2cap_le_start(chan); 127093c3e8f5SAndrei Emeltchenko } else { 127193c3e8f5SAndrei Emeltchenko l2cap_send_conn_req(chan); 127293c3e8f5SAndrei Emeltchenko } 127393c3e8f5SAndrei Emeltchenko } 127493c3e8f5SAndrei Emeltchenko 1275fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan) 12760a708f8fSGustavo F. Padovan { 12778c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 12780a708f8fSGustavo F. Padovan 12799f0caeb1SVinicius Costa Gomes if (conn->hcon->type == LE_LINK) { 128096ac34fbSJohan Hedberg l2cap_le_start(chan); 12819f0caeb1SVinicius Costa Gomes return; 12829f0caeb1SVinicius Costa Gomes } 12839f0caeb1SVinicius Costa Gomes 12840a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { 12850a708f8fSGustavo F. Padovan if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) 12860a708f8fSGustavo F. Padovan return; 12870a708f8fSGustavo F. Padovan 1288d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan) && 128993c3e8f5SAndrei Emeltchenko __l2cap_no_conn_pending(chan)) { 129093c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 129193c3e8f5SAndrei Emeltchenko } 12920a708f8fSGustavo F. Padovan } else { 12930a708f8fSGustavo F. Padovan struct l2cap_info_req req; 1294ac73498cSAndrei Emeltchenko req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); 12950a708f8fSGustavo F. Padovan 12960a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 12970a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 12980a708f8fSGustavo F. Padovan 1299ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 13000a708f8fSGustavo F. Padovan 13012d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, 13022d792818SGustavo Padovan sizeof(req), &req); 13030a708f8fSGustavo F. Padovan } 13040a708f8fSGustavo F. Padovan } 13050a708f8fSGustavo F. Padovan 13060a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) 13070a708f8fSGustavo F. Padovan { 13080a708f8fSGustavo F. Padovan u32 local_feat_mask = l2cap_feat_mask; 13090a708f8fSGustavo F. Padovan if (!disable_ertm) 13100a708f8fSGustavo F. Padovan local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING; 13110a708f8fSGustavo F. Padovan 13120a708f8fSGustavo F. Padovan switch (mode) { 13130a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 13140a708f8fSGustavo F. Padovan return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask; 13150a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 13160a708f8fSGustavo F. Padovan return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask; 13170a708f8fSGustavo F. Padovan default: 13180a708f8fSGustavo F. Padovan return 0x00; 13190a708f8fSGustavo F. Padovan } 13200a708f8fSGustavo F. Padovan } 13210a708f8fSGustavo F. Padovan 13225e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err) 13230a708f8fSGustavo F. Padovan { 13245e4e3972SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 13250a708f8fSGustavo F. Padovan struct l2cap_disconn_req req; 13260a708f8fSGustavo F. Padovan 13270a708f8fSGustavo F. Padovan if (!conn) 13280a708f8fSGustavo F. Padovan return; 13290a708f8fSGustavo F. Padovan 1330aad3d0e3SAndrei Emeltchenko if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) { 13311a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 13321a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 13331a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 13340a708f8fSGustavo F. Padovan } 13350a708f8fSGustavo F. Padovan 1336416fa752SAndrei Emeltchenko if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { 1337d117773cSGustavo Padovan l2cap_state_change(chan, BT_DISCONN); 1338416fa752SAndrei Emeltchenko return; 1339416fa752SAndrei Emeltchenko } 1340416fa752SAndrei Emeltchenko 1341fe4128e0SGustavo F. Padovan req.dcid = cpu_to_le16(chan->dcid); 1342fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 13432d792818SGustavo Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ, 13442d792818SGustavo Padovan sizeof(req), &req); 13450a708f8fSGustavo F. Padovan 1346f8e73017SGustavo Padovan l2cap_state_change_and_error(chan, BT_DISCONN, err); 13470a708f8fSGustavo F. Padovan } 13480a708f8fSGustavo F. Padovan 13490a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */ 13500a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn) 13510a708f8fSGustavo F. Padovan { 13523df91ea2SAndrei Emeltchenko struct l2cap_chan *chan, *tmp; 13530a708f8fSGustavo F. Padovan 13540a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 13550a708f8fSGustavo F. Padovan 13563df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 13570a708f8fSGustavo F. Padovan 13583df91ea2SAndrei Emeltchenko list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 13596be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 13600a708f8fSGustavo F. Padovan 1361715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 13626be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13630a708f8fSGustavo F. Padovan continue; 13640a708f8fSGustavo F. Padovan } 13650a708f8fSGustavo F. Padovan 136689bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 1367d45fc423SGustavo F. Padovan if (!l2cap_chan_check_security(chan) || 1368b4450035SGustavo F. Padovan !__l2cap_no_conn_pending(chan)) { 13696be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13700a708f8fSGustavo F. Padovan continue; 13710a708f8fSGustavo F. Padovan } 13720a708f8fSGustavo F. Padovan 1373c1360a1cSGustavo F. Padovan if (!l2cap_mode_supported(chan->mode, conn->feat_mask) 1374c1360a1cSGustavo F. Padovan && test_bit(CONF_STATE2_DEVICE, 1375c1360a1cSGustavo F. Padovan &chan->conf_state)) { 13760f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 13776be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13780a708f8fSGustavo F. Padovan continue; 13790a708f8fSGustavo F. Padovan } 13800a708f8fSGustavo F. Padovan 138193c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 13820a708f8fSGustavo F. Padovan 138389bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 13840a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 13850a708f8fSGustavo F. Padovan char buf[128]; 1386fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 1387fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 13880a708f8fSGustavo F. Padovan 1389d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 1390bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 1391ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); 1392ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND); 13932dc4e510SGustavo Padovan chan->ops->defer(chan); 13940a708f8fSGustavo F. Padovan 13950a708f8fSGustavo F. Padovan } else { 1396acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 1397ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 1398ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 13990a708f8fSGustavo F. Padovan } 14000a708f8fSGustavo F. Padovan } else { 1401ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); 1402ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND); 14030a708f8fSGustavo F. Padovan } 14040a708f8fSGustavo F. Padovan 1405fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 1406fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 14070a708f8fSGustavo F. Padovan 1408c1360a1cSGustavo F. Padovan if (test_bit(CONF_REQ_SENT, &chan->conf_state) || 14090a708f8fSGustavo F. Padovan rsp.result != L2CAP_CR_SUCCESS) { 14106be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 14110a708f8fSGustavo F. Padovan continue; 14120a708f8fSGustavo F. Padovan } 14130a708f8fSGustavo F. Padovan 1414c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 14150a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 141673ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 141773ffa904SGustavo F. Padovan chan->num_conf_req++; 14180a708f8fSGustavo F. Padovan } 14190a708f8fSGustavo F. Padovan 14206be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 14210a708f8fSGustavo F. Padovan } 14220a708f8fSGustavo F. Padovan 14233df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 14240a708f8fSGustavo F. Padovan } 14250a708f8fSGustavo F. Padovan 1426c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr. 1427b62f328bSVille Tervo * Returns closest match, locked. 1428b62f328bSVille Tervo */ 1429d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, 1430c2287681SIdo Yariv bdaddr_t *src, 1431c2287681SIdo Yariv bdaddr_t *dst) 1432b62f328bSVille Tervo { 143323691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 1434b62f328bSVille Tervo 143523691d75SGustavo F. Padovan read_lock(&chan_list_lock); 1436b62f328bSVille Tervo 143723691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 143889bc500eSGustavo F. Padovan if (state && c->state != state) 1439b62f328bSVille Tervo continue; 1440b62f328bSVille Tervo 144123691d75SGustavo F. Padovan if (c->scid == cid) { 1442c2287681SIdo Yariv int src_match, dst_match; 1443c2287681SIdo Yariv int src_any, dst_any; 1444c2287681SIdo Yariv 1445b62f328bSVille Tervo /* Exact match. */ 14467eafc59eSMarcel Holtmann src_match = !bacmp(&c->src, src); 14477eafc59eSMarcel Holtmann dst_match = !bacmp(&c->dst, dst); 1448c2287681SIdo Yariv if (src_match && dst_match) { 144923691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 145023691d75SGustavo F. Padovan return c; 145123691d75SGustavo F. Padovan } 1452b62f328bSVille Tervo 1453b62f328bSVille Tervo /* Closest match */ 14547eafc59eSMarcel Holtmann src_any = !bacmp(&c->src, BDADDR_ANY); 14557eafc59eSMarcel Holtmann dst_any = !bacmp(&c->dst, BDADDR_ANY); 1456c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1457c2287681SIdo Yariv (src_any && dst_any)) 145823691d75SGustavo F. Padovan c1 = c; 1459b62f328bSVille Tervo } 1460b62f328bSVille Tervo } 1461280f294fSGustavo F. Padovan 146223691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 1463b62f328bSVille Tervo 146423691d75SGustavo F. Padovan return c1; 1465b62f328bSVille Tervo } 1466b62f328bSVille Tervo 1467b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn) 1468b62f328bSVille Tervo { 1469cc8dba2bSMarcel Holtmann struct hci_conn *hcon = conn->hcon; 147023691d75SGustavo F. Padovan struct l2cap_chan *chan, *pchan; 1471cc8dba2bSMarcel Holtmann u8 dst_type; 1472b62f328bSVille Tervo 1473b62f328bSVille Tervo BT_DBG(""); 1474b62f328bSVille Tervo 1475b62f328bSVille Tervo /* Check if we have socket listening on cid */ 1476073d1cf3SJohan Hedberg pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT, 1477cc8dba2bSMarcel Holtmann &hcon->src, &hcon->dst); 147823691d75SGustavo F. Padovan if (!pchan) 1479b62f328bSVille Tervo return; 1480b62f328bSVille Tervo 148144f3b0fbSJohan Hedberg /* Client ATT sockets should override the server one */ 148244f3b0fbSJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, L2CAP_CID_ATT)) 148344f3b0fbSJohan Hedberg return; 148444f3b0fbSJohan Hedberg 1485cc8dba2bSMarcel Holtmann dst_type = bdaddr_type(hcon, hcon->dst_type); 1486cc8dba2bSMarcel Holtmann 1487cc8dba2bSMarcel Holtmann /* If device is blocked, do not create a channel for it */ 1488cc8dba2bSMarcel Holtmann if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, dst_type)) 1489cc8dba2bSMarcel Holtmann return; 1490cc8dba2bSMarcel Holtmann 14918ffb9290SGustavo Padovan l2cap_chan_lock(pchan); 149262f3a2cfSGustavo F. Padovan 149380b98027SGustavo Padovan chan = pchan->ops->new_connection(pchan); 149480808e43SGustavo F. Padovan if (!chan) 1495b62f328bSVille Tervo goto clean; 1496b62f328bSVille Tervo 14979f22398cSJohan Hedberg chan->dcid = L2CAP_CID_ATT; 14989f22398cSJohan Hedberg 1499cc8dba2bSMarcel Holtmann bacpy(&chan->src, &hcon->src); 1500cc8dba2bSMarcel Holtmann bacpy(&chan->dst, &hcon->dst); 1501cc8dba2bSMarcel Holtmann chan->src_type = bdaddr_type(hcon, hcon->src_type); 1502cc8dba2bSMarcel Holtmann chan->dst_type = dst_type; 1503b62f328bSVille Tervo 150444f3b0fbSJohan Hedberg __l2cap_chan_add(conn, chan); 150548454079SGustavo F. Padovan 1506b62f328bSVille Tervo clean: 15078ffb9290SGustavo Padovan l2cap_chan_unlock(pchan); 1508b62f328bSVille Tervo } 1509b62f328bSVille Tervo 15100a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn) 15110a708f8fSGustavo F. Padovan { 151248454079SGustavo F. Padovan struct l2cap_chan *chan; 1513cc110922SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 15140a708f8fSGustavo F. Padovan 15150a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 15160a708f8fSGustavo F. Padovan 1517d8729922SJohan Hedberg /* For outgoing pairing which doesn't necessarily have an 1518d8729922SJohan Hedberg * associated socket (e.g. mgmt_pair_device). 1519d8729922SJohan Hedberg */ 1520cc110922SVinicius Costa Gomes if (hcon->out && hcon->type == LE_LINK) 1521cc110922SVinicius Costa Gomes smp_conn_security(hcon, hcon->pending_sec_level); 1522160dc6acSVinicius Costa Gomes 15233df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 15240a708f8fSGustavo F. Padovan 152544f3b0fbSJohan Hedberg if (hcon->type == LE_LINK) 152644f3b0fbSJohan Hedberg l2cap_le_conn_ready(conn); 152744f3b0fbSJohan Hedberg 15283df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1529baa7e1faSGustavo F. Padovan 15306be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 15310a708f8fSGustavo F. Padovan 1532416fa752SAndrei Emeltchenko if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { 1533416fa752SAndrei Emeltchenko l2cap_chan_unlock(chan); 1534416fa752SAndrei Emeltchenko continue; 1535416fa752SAndrei Emeltchenko } 1536416fa752SAndrei Emeltchenko 1537cc110922SVinicius Costa Gomes if (hcon->type == LE_LINK) { 1538f1496deeSJohan Hedberg l2cap_le_start(chan); 153963128451SVinicius Costa Gomes } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 154074e75740SGustavo Padovan l2cap_chan_ready(chan); 1541b501d6a1SAnderson Briglia 15421c244f79SGustavo Padovan } else if (chan->state == BT_CONNECT) { 1543fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 15441c244f79SGustavo Padovan } 15450a708f8fSGustavo F. Padovan 15466be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 15470a708f8fSGustavo F. Padovan } 15480a708f8fSGustavo F. Padovan 15493df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 15500a708f8fSGustavo F. Padovan } 15510a708f8fSGustavo F. Padovan 15520a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */ 15530a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) 15540a708f8fSGustavo F. Padovan { 155548454079SGustavo F. Padovan struct l2cap_chan *chan; 15560a708f8fSGustavo F. Padovan 15570a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 15580a708f8fSGustavo F. Padovan 15593df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 15600a708f8fSGustavo F. Padovan 15613df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1562ecf61bdbSAndrei Emeltchenko if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) 15631d8b1fd5SGustavo Padovan l2cap_chan_set_err(chan, err); 15640a708f8fSGustavo F. Padovan } 15650a708f8fSGustavo F. Padovan 15663df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 15670a708f8fSGustavo F. Padovan } 15680a708f8fSGustavo F. Padovan 1569f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work) 15700a708f8fSGustavo F. Padovan { 1571f878fcadSGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 1572030013d8SGustavo F. Padovan info_timer.work); 15730a708f8fSGustavo F. Padovan 15740a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 15750a708f8fSGustavo F. Padovan conn->info_ident = 0; 15760a708f8fSGustavo F. Padovan 15770a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 15780a708f8fSGustavo F. Padovan } 15790a708f8fSGustavo F. Padovan 15802c8e1411SDavid Herrmann /* 15812c8e1411SDavid Herrmann * l2cap_user 15822c8e1411SDavid Herrmann * External modules can register l2cap_user objects on l2cap_conn. The ->probe 15832c8e1411SDavid Herrmann * callback is called during registration. The ->remove callback is called 15842c8e1411SDavid Herrmann * during unregistration. 15852c8e1411SDavid Herrmann * An l2cap_user object can either be explicitly unregistered or when the 15862c8e1411SDavid Herrmann * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon, 15872c8e1411SDavid Herrmann * l2cap->hchan, .. are valid as long as the remove callback hasn't been called. 15882c8e1411SDavid Herrmann * External modules must own a reference to the l2cap_conn object if they intend 15892c8e1411SDavid Herrmann * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at 15902c8e1411SDavid Herrmann * any time if they don't. 15912c8e1411SDavid Herrmann */ 15922c8e1411SDavid Herrmann 15932c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) 15942c8e1411SDavid Herrmann { 15952c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev; 15962c8e1411SDavid Herrmann int ret; 15972c8e1411SDavid Herrmann 15982c8e1411SDavid Herrmann /* We need to check whether l2cap_conn is registered. If it is not, we 15992c8e1411SDavid Herrmann * must not register the l2cap_user. l2cap_conn_del() is unregisters 16002c8e1411SDavid Herrmann * l2cap_conn objects, but doesn't provide its own locking. Instead, it 16012c8e1411SDavid Herrmann * relies on the parent hci_conn object to be locked. This itself relies 16022c8e1411SDavid Herrmann * on the hci_dev object to be locked. So we must lock the hci device 16032c8e1411SDavid Herrmann * here, too. */ 16042c8e1411SDavid Herrmann 16052c8e1411SDavid Herrmann hci_dev_lock(hdev); 16062c8e1411SDavid Herrmann 16072c8e1411SDavid Herrmann if (user->list.next || user->list.prev) { 16082c8e1411SDavid Herrmann ret = -EINVAL; 16092c8e1411SDavid Herrmann goto out_unlock; 16102c8e1411SDavid Herrmann } 16112c8e1411SDavid Herrmann 16122c8e1411SDavid Herrmann /* conn->hchan is NULL after l2cap_conn_del() was called */ 16132c8e1411SDavid Herrmann if (!conn->hchan) { 16142c8e1411SDavid Herrmann ret = -ENODEV; 16152c8e1411SDavid Herrmann goto out_unlock; 16162c8e1411SDavid Herrmann } 16172c8e1411SDavid Herrmann 16182c8e1411SDavid Herrmann ret = user->probe(conn, user); 16192c8e1411SDavid Herrmann if (ret) 16202c8e1411SDavid Herrmann goto out_unlock; 16212c8e1411SDavid Herrmann 16222c8e1411SDavid Herrmann list_add(&user->list, &conn->users); 16232c8e1411SDavid Herrmann ret = 0; 16242c8e1411SDavid Herrmann 16252c8e1411SDavid Herrmann out_unlock: 16262c8e1411SDavid Herrmann hci_dev_unlock(hdev); 16272c8e1411SDavid Herrmann return ret; 16282c8e1411SDavid Herrmann } 16292c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user); 16302c8e1411SDavid Herrmann 16312c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) 16322c8e1411SDavid Herrmann { 16332c8e1411SDavid Herrmann struct hci_dev *hdev = conn->hcon->hdev; 16342c8e1411SDavid Herrmann 16352c8e1411SDavid Herrmann hci_dev_lock(hdev); 16362c8e1411SDavid Herrmann 16372c8e1411SDavid Herrmann if (!user->list.next || !user->list.prev) 16382c8e1411SDavid Herrmann goto out_unlock; 16392c8e1411SDavid Herrmann 16402c8e1411SDavid Herrmann list_del(&user->list); 16412c8e1411SDavid Herrmann user->list.next = NULL; 16422c8e1411SDavid Herrmann user->list.prev = NULL; 16432c8e1411SDavid Herrmann user->remove(conn, user); 16442c8e1411SDavid Herrmann 16452c8e1411SDavid Herrmann out_unlock: 16462c8e1411SDavid Herrmann hci_dev_unlock(hdev); 16472c8e1411SDavid Herrmann } 16482c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user); 16492c8e1411SDavid Herrmann 16502c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn) 16512c8e1411SDavid Herrmann { 16522c8e1411SDavid Herrmann struct l2cap_user *user; 16532c8e1411SDavid Herrmann 16542c8e1411SDavid Herrmann while (!list_empty(&conn->users)) { 16552c8e1411SDavid Herrmann user = list_first_entry(&conn->users, struct l2cap_user, list); 16562c8e1411SDavid Herrmann list_del(&user->list); 16572c8e1411SDavid Herrmann user->list.next = NULL; 16582c8e1411SDavid Herrmann user->list.prev = NULL; 16592c8e1411SDavid Herrmann user->remove(conn, user); 16602c8e1411SDavid Herrmann } 16612c8e1411SDavid Herrmann } 16622c8e1411SDavid Herrmann 16635d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err) 16645d3de7dfSVinicius Costa Gomes { 16655d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 16665d3de7dfSVinicius Costa Gomes struct l2cap_chan *chan, *l; 16675d3de7dfSVinicius Costa Gomes 16685d3de7dfSVinicius Costa Gomes if (!conn) 16695d3de7dfSVinicius Costa Gomes return; 16705d3de7dfSVinicius Costa Gomes 16715d3de7dfSVinicius Costa Gomes BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); 16725d3de7dfSVinicius Costa Gomes 16735d3de7dfSVinicius Costa Gomes kfree_skb(conn->rx_skb); 16745d3de7dfSVinicius Costa Gomes 16752c8e1411SDavid Herrmann l2cap_unregister_all_users(conn); 16762c8e1411SDavid Herrmann 16773df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 16783df91ea2SAndrei Emeltchenko 16795d3de7dfSVinicius Costa Gomes /* Kill channels */ 16805d3de7dfSVinicius Costa Gomes list_for_each_entry_safe(chan, l, &conn->chan_l, list) { 168161d6ef3eSMat Martineau l2cap_chan_hold(chan); 16826be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 16836be36555SAndrei Emeltchenko 16845d3de7dfSVinicius Costa Gomes l2cap_chan_del(chan, err); 16856be36555SAndrei Emeltchenko 16866be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16876be36555SAndrei Emeltchenko 168880b98027SGustavo Padovan chan->ops->close(chan); 168961d6ef3eSMat Martineau l2cap_chan_put(chan); 16905d3de7dfSVinicius Costa Gomes } 16915d3de7dfSVinicius Costa Gomes 16923df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 16933df91ea2SAndrei Emeltchenko 169473d80debSLuiz Augusto von Dentz hci_chan_del(conn->hchan); 169573d80debSLuiz Augusto von Dentz 16965d3de7dfSVinicius Costa Gomes if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1697127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->info_timer); 16985d3de7dfSVinicius Costa Gomes 169951a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) { 1700127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->security_timer); 17018aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 1702d26a2345SVinicius Costa Gomes } 17035d3de7dfSVinicius Costa Gomes 17045d3de7dfSVinicius Costa Gomes hcon->l2cap_data = NULL; 17059c903e37SDavid Herrmann conn->hchan = NULL; 17069c903e37SDavid Herrmann l2cap_conn_put(conn); 17075d3de7dfSVinicius Costa Gomes } 17085d3de7dfSVinicius Costa Gomes 17096c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work) 17105d3de7dfSVinicius Costa Gomes { 17116c9d42a1SGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 17126c9d42a1SGustavo F. Padovan security_timer.work); 17135d3de7dfSVinicius Costa Gomes 1714d06cc416SJohan Hedberg BT_DBG("conn %p", conn); 1715d06cc416SJohan Hedberg 1716d06cc416SJohan Hedberg if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) { 1717d06cc416SJohan Hedberg smp_chan_destroy(conn); 17185d3de7dfSVinicius Costa Gomes l2cap_conn_del(conn->hcon, ETIMEDOUT); 17195d3de7dfSVinicius Costa Gomes } 1720d06cc416SJohan Hedberg } 17215d3de7dfSVinicius Costa Gomes 1722baf43251SClaudio Takahasi static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) 17230a708f8fSGustavo F. Padovan { 17240a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 172573d80debSLuiz Augusto von Dentz struct hci_chan *hchan; 17260a708f8fSGustavo F. Padovan 1727baf43251SClaudio Takahasi if (conn) 17280a708f8fSGustavo F. Padovan return conn; 17290a708f8fSGustavo F. Padovan 173073d80debSLuiz Augusto von Dentz hchan = hci_chan_create(hcon); 173173d80debSLuiz Augusto von Dentz if (!hchan) 17320a708f8fSGustavo F. Padovan return NULL; 17330a708f8fSGustavo F. Padovan 17348bcde1f2SGustavo Padovan conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL); 173573d80debSLuiz Augusto von Dentz if (!conn) { 173673d80debSLuiz Augusto von Dentz hci_chan_del(hchan); 173773d80debSLuiz Augusto von Dentz return NULL; 173873d80debSLuiz Augusto von Dentz } 173973d80debSLuiz Augusto von Dentz 17409c903e37SDavid Herrmann kref_init(&conn->ref); 17410a708f8fSGustavo F. Padovan hcon->l2cap_data = conn; 17420a708f8fSGustavo F. Padovan conn->hcon = hcon; 17439c903e37SDavid Herrmann hci_conn_get(conn->hcon); 174473d80debSLuiz Augusto von Dentz conn->hchan = hchan; 17450a708f8fSGustavo F. Padovan 174673d80debSLuiz Augusto von Dentz BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); 17470a708f8fSGustavo F. Padovan 1748dcc042d5SAndrei Emeltchenko switch (hcon->type) { 1749dcc042d5SAndrei Emeltchenko case LE_LINK: 1750dcc042d5SAndrei Emeltchenko if (hcon->hdev->le_mtu) { 1751acd7d370SVille Tervo conn->mtu = hcon->hdev->le_mtu; 1752dcc042d5SAndrei Emeltchenko break; 1753dcc042d5SAndrei Emeltchenko } 1754dcc042d5SAndrei Emeltchenko /* fall through */ 1755dcc042d5SAndrei Emeltchenko default: 17560a708f8fSGustavo F. Padovan conn->mtu = hcon->hdev->acl_mtu; 1757dcc042d5SAndrei Emeltchenko break; 1758dcc042d5SAndrei Emeltchenko } 1759acd7d370SVille Tervo 17600a708f8fSGustavo F. Padovan conn->feat_mask = 0; 17610a708f8fSGustavo F. Padovan 1762848566b3SMarcel Holtmann if (hcon->type == ACL_LINK) 1763848566b3SMarcel Holtmann conn->hs_enabled = test_bit(HCI_HS_ENABLED, 1764848566b3SMarcel Holtmann &hcon->hdev->dev_flags); 1765848566b3SMarcel Holtmann 17660a708f8fSGustavo F. Padovan spin_lock_init(&conn->lock); 17673df91ea2SAndrei Emeltchenko mutex_init(&conn->chan_lock); 1768baa7e1faSGustavo F. Padovan 1769baa7e1faSGustavo F. Padovan INIT_LIST_HEAD(&conn->chan_l); 17702c8e1411SDavid Herrmann INIT_LIST_HEAD(&conn->users); 17710a708f8fSGustavo F. Padovan 17725d3de7dfSVinicius Costa Gomes if (hcon->type == LE_LINK) 17736c9d42a1SGustavo F. Padovan INIT_DELAYED_WORK(&conn->security_timer, security_timeout); 17745d3de7dfSVinicius Costa Gomes else 1775030013d8SGustavo F. Padovan INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); 17760a708f8fSGustavo F. Padovan 17779f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 17780a708f8fSGustavo F. Padovan 17790a708f8fSGustavo F. Padovan return conn; 17800a708f8fSGustavo F. Padovan } 17810a708f8fSGustavo F. Padovan 17829c903e37SDavid Herrmann static void l2cap_conn_free(struct kref *ref) 17839c903e37SDavid Herrmann { 17849c903e37SDavid Herrmann struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref); 17859c903e37SDavid Herrmann 17869c903e37SDavid Herrmann hci_conn_put(conn->hcon); 17879c903e37SDavid Herrmann kfree(conn); 17889c903e37SDavid Herrmann } 17899c903e37SDavid Herrmann 17909c903e37SDavid Herrmann void l2cap_conn_get(struct l2cap_conn *conn) 17919c903e37SDavid Herrmann { 17929c903e37SDavid Herrmann kref_get(&conn->ref); 17939c903e37SDavid Herrmann } 17949c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_get); 17959c903e37SDavid Herrmann 17969c903e37SDavid Herrmann void l2cap_conn_put(struct l2cap_conn *conn) 17979c903e37SDavid Herrmann { 17989c903e37SDavid Herrmann kref_put(&conn->ref, l2cap_conn_free); 17999c903e37SDavid Herrmann } 18009c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_put); 18019c903e37SDavid Herrmann 18020a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */ 18030a708f8fSGustavo F. Padovan 1804c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr. 18050a708f8fSGustavo F. Padovan * Returns closest match. 18060a708f8fSGustavo F. Padovan */ 1807c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, 1808c2287681SIdo Yariv bdaddr_t *src, 1809bf20fd4eSJohan Hedberg bdaddr_t *dst, 1810bf20fd4eSJohan Hedberg u8 link_type) 18110a708f8fSGustavo F. Padovan { 181223691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 18130a708f8fSGustavo F. Padovan 181423691d75SGustavo F. Padovan read_lock(&chan_list_lock); 18150a708f8fSGustavo F. Padovan 181623691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 181789bc500eSGustavo F. Padovan if (state && c->state != state) 18180a708f8fSGustavo F. Padovan continue; 18190a708f8fSGustavo F. Padovan 1820bf20fd4eSJohan Hedberg if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR) 1821bf20fd4eSJohan Hedberg continue; 1822bf20fd4eSJohan Hedberg 1823bf20fd4eSJohan Hedberg if (link_type == LE_LINK && c->src_type == BDADDR_BREDR) 1824bf20fd4eSJohan Hedberg continue; 1825bf20fd4eSJohan Hedberg 182623691d75SGustavo F. Padovan if (c->psm == psm) { 1827c2287681SIdo Yariv int src_match, dst_match; 1828c2287681SIdo Yariv int src_any, dst_any; 1829c2287681SIdo Yariv 18300a708f8fSGustavo F. Padovan /* Exact match. */ 18317eafc59eSMarcel Holtmann src_match = !bacmp(&c->src, src); 18327eafc59eSMarcel Holtmann dst_match = !bacmp(&c->dst, dst); 1833c2287681SIdo Yariv if (src_match && dst_match) { 1834a7567b20SJohannes Berg read_unlock(&chan_list_lock); 183523691d75SGustavo F. Padovan return c; 183623691d75SGustavo F. Padovan } 18370a708f8fSGustavo F. Padovan 18380a708f8fSGustavo F. Padovan /* Closest match */ 18397eafc59eSMarcel Holtmann src_any = !bacmp(&c->src, BDADDR_ANY); 18407eafc59eSMarcel Holtmann dst_any = !bacmp(&c->dst, BDADDR_ANY); 1841c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1842c2287681SIdo Yariv (src_any && dst_any)) 184323691d75SGustavo F. Padovan c1 = c; 18440a708f8fSGustavo F. Padovan } 18450a708f8fSGustavo F. Padovan } 18460a708f8fSGustavo F. Padovan 184723691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 18480a708f8fSGustavo F. Padovan 184923691d75SGustavo F. Padovan return c1; 18500a708f8fSGustavo F. Padovan } 18510a708f8fSGustavo F. Padovan 18524946096dSJohan Hedberg static bool is_valid_psm(u16 psm, u8 dst_type) 18534946096dSJohan Hedberg { 18544946096dSJohan Hedberg if (!psm) 18554946096dSJohan Hedberg return false; 18564946096dSJohan Hedberg 18574946096dSJohan Hedberg if (bdaddr_type_is_le(dst_type)) 18584946096dSJohan Hedberg return (psm < 0x00ff); 18594946096dSJohan Hedberg 18604946096dSJohan Hedberg /* PSM must be odd and lsb of upper byte must be 0 */ 18614946096dSJohan Hedberg return ((psm & 0x0101) == 0x0001); 18624946096dSJohan Hedberg } 18634946096dSJohan Hedberg 18648e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, 18658e9f9892SAndre Guedes bdaddr_t *dst, u8 dst_type) 18660a708f8fSGustavo F. Padovan { 18670a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 18680a708f8fSGustavo F. Padovan struct hci_conn *hcon; 18690a708f8fSGustavo F. Padovan struct hci_dev *hdev; 18700a708f8fSGustavo F. Padovan __u8 auth_type; 18710a708f8fSGustavo F. Padovan int err; 18720a708f8fSGustavo F. Padovan 18737eafc59eSMarcel Holtmann BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst, 1874ab19516aSSyam Sidhardhan dst_type, __le16_to_cpu(psm)); 18750a708f8fSGustavo F. Padovan 18767eafc59eSMarcel Holtmann hdev = hci_get_route(dst, &chan->src); 18770a708f8fSGustavo F. Padovan if (!hdev) 18780a708f8fSGustavo F. Padovan return -EHOSTUNREACH; 18790a708f8fSGustavo F. Padovan 188009fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 18810a708f8fSGustavo F. Padovan 18826be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 188303a00194SGustavo F. Padovan 18844946096dSJohan Hedberg if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid && 188503a00194SGustavo F. Padovan chan->chan_type != L2CAP_CHAN_RAW) { 188603a00194SGustavo F. Padovan err = -EINVAL; 188703a00194SGustavo F. Padovan goto done; 188803a00194SGustavo F. Padovan } 188903a00194SGustavo F. Padovan 189003a00194SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) { 189103a00194SGustavo F. Padovan err = -EINVAL; 189203a00194SGustavo F. Padovan goto done; 189303a00194SGustavo F. Padovan } 189403a00194SGustavo F. Padovan 189503a00194SGustavo F. Padovan switch (chan->mode) { 189603a00194SGustavo F. Padovan case L2CAP_MODE_BASIC: 18970ce43ce6SJohan Hedberg break; 189838319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 18990ce43ce6SJohan Hedberg l2cap_le_flowctl_init(chan); 190003a00194SGustavo F. Padovan break; 190103a00194SGustavo F. Padovan case L2CAP_MODE_ERTM: 190203a00194SGustavo F. Padovan case L2CAP_MODE_STREAMING: 190303a00194SGustavo F. Padovan if (!disable_ertm) 190403a00194SGustavo F. Padovan break; 190503a00194SGustavo F. Padovan /* fall through */ 190603a00194SGustavo F. Padovan default: 190703a00194SGustavo F. Padovan err = -ENOTSUPP; 190803a00194SGustavo F. Padovan goto done; 190903a00194SGustavo F. Padovan } 191003a00194SGustavo F. Padovan 19110797e01dSGustavo Padovan switch (chan->state) { 191203a00194SGustavo F. Padovan case BT_CONNECT: 191303a00194SGustavo F. Padovan case BT_CONNECT2: 191403a00194SGustavo F. Padovan case BT_CONFIG: 191503a00194SGustavo F. Padovan /* Already connecting */ 191603a00194SGustavo F. Padovan err = 0; 191703a00194SGustavo F. Padovan goto done; 191803a00194SGustavo F. Padovan 191903a00194SGustavo F. Padovan case BT_CONNECTED: 192003a00194SGustavo F. Padovan /* Already connected */ 192103a00194SGustavo F. Padovan err = -EISCONN; 192203a00194SGustavo F. Padovan goto done; 192303a00194SGustavo F. Padovan 192403a00194SGustavo F. Padovan case BT_OPEN: 192503a00194SGustavo F. Padovan case BT_BOUND: 192603a00194SGustavo F. Padovan /* Can connect */ 192703a00194SGustavo F. Padovan break; 192803a00194SGustavo F. Padovan 192903a00194SGustavo F. Padovan default: 193003a00194SGustavo F. Padovan err = -EBADFD; 193103a00194SGustavo F. Padovan goto done; 193203a00194SGustavo F. Padovan } 193303a00194SGustavo F. Padovan 193403a00194SGustavo F. Padovan /* Set destination address and psm */ 19357eafc59eSMarcel Holtmann bacpy(&chan->dst, dst); 19364f1654e0SMarcel Holtmann chan->dst_type = dst_type; 19376be36555SAndrei Emeltchenko 193803a00194SGustavo F. Padovan chan->psm = psm; 193903a00194SGustavo F. Padovan chan->dcid = cid; 19400a708f8fSGustavo F. Padovan 19414343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 19420a708f8fSGustavo F. Padovan 1943f224ca5fSJohan Hedberg if (bdaddr_type_is_le(dst_type)) 19448e9f9892SAndre Guedes hcon = hci_connect(hdev, LE_LINK, dst, dst_type, 19454343478fSGustavo F. Padovan chan->sec_level, auth_type); 1946acd7d370SVille Tervo else 19478e9f9892SAndre Guedes hcon = hci_connect(hdev, ACL_LINK, dst, dst_type, 19484343478fSGustavo F. Padovan chan->sec_level, auth_type); 1949acd7d370SVille Tervo 195030e76272SVille Tervo if (IS_ERR(hcon)) { 195130e76272SVille Tervo err = PTR_ERR(hcon); 19520a708f8fSGustavo F. Padovan goto done; 195330e76272SVille Tervo } 19540a708f8fSGustavo F. Padovan 1955baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon); 19560a708f8fSGustavo F. Padovan if (!conn) { 195776a68ba0SDavid Herrmann hci_conn_drop(hcon); 195830e76272SVille Tervo err = -ENOMEM; 19590a708f8fSGustavo F. Padovan goto done; 19600a708f8fSGustavo F. Padovan } 19610a708f8fSGustavo F. Padovan 1962141d5706SJohan Hedberg if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { 196376a68ba0SDavid Herrmann hci_conn_drop(hcon); 1964141d5706SJohan Hedberg err = -EBUSY; 19659f0caeb1SVinicius Costa Gomes goto done; 19669f0caeb1SVinicius Costa Gomes } 19679f0caeb1SVinicius Costa Gomes 19680a708f8fSGustavo F. Padovan /* Update source addr of the socket */ 19697eafc59eSMarcel Holtmann bacpy(&chan->src, &hcon->src); 19704f1654e0SMarcel Holtmann chan->src_type = bdaddr_type(hcon, hcon->src_type); 19710a708f8fSGustavo F. Padovan 19726be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 197348454079SGustavo F. Padovan l2cap_chan_add(conn, chan); 19746be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 197548454079SGustavo F. Padovan 19765ee9891dSJohan Hedberg /* l2cap_chan_add takes its own ref so we can drop this one */ 19775ee9891dSJohan Hedberg hci_conn_drop(hcon); 19785ee9891dSJohan Hedberg 19796be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECT); 19808d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 19810a708f8fSGustavo F. Padovan 19820a708f8fSGustavo F. Padovan if (hcon->state == BT_CONNECTED) { 1983715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1984c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 1985d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) 19866be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECTED); 19870a708f8fSGustavo F. Padovan } else 1988fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 19890a708f8fSGustavo F. Padovan } 19900a708f8fSGustavo F. Padovan 199130e76272SVille Tervo err = 0; 199230e76272SVille Tervo 19930a708f8fSGustavo F. Padovan done: 19946be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 199509fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 19960a708f8fSGustavo F. Padovan hci_dev_put(hdev); 19970a708f8fSGustavo F. Padovan return err; 19980a708f8fSGustavo F. Padovan } 19990a708f8fSGustavo F. Padovan 2000721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work) 20010a708f8fSGustavo F. Padovan { 2002721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 2003721c4181SGustavo F. Padovan monitor_timer.work); 20040a708f8fSGustavo F. Padovan 2005525cd185SGustavo F. Padovan BT_DBG("chan %p", chan); 20060a708f8fSGustavo F. Padovan 20076be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 20086be36555SAndrei Emeltchenko 200980909e04SMat Martineau if (!chan->conn) { 20106be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 20118d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 20120a708f8fSGustavo F. Padovan return; 20130a708f8fSGustavo F. Padovan } 20140a708f8fSGustavo F. Padovan 2015401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO); 20160a708f8fSGustavo F. Padovan 20176be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 20188d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 20190a708f8fSGustavo F. Padovan } 20200a708f8fSGustavo F. Padovan 2021721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work) 20220a708f8fSGustavo F. Padovan { 2023721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 2024721c4181SGustavo F. Padovan retrans_timer.work); 20250a708f8fSGustavo F. Padovan 202649208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 20270a708f8fSGustavo F. Padovan 20286be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 20296be36555SAndrei Emeltchenko 203080909e04SMat Martineau if (!chan->conn) { 203180909e04SMat Martineau l2cap_chan_unlock(chan); 203280909e04SMat Martineau l2cap_chan_put(chan); 203380909e04SMat Martineau return; 203480909e04SMat Martineau } 20350a708f8fSGustavo F. Padovan 2036401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO); 20376be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 20388d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 20390a708f8fSGustavo F. Padovan } 20400a708f8fSGustavo F. Padovan 2041d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan, 20423733937dSMat Martineau struct sk_buff_head *skbs) 20430a708f8fSGustavo F. Padovan { 20440a708f8fSGustavo F. Padovan struct sk_buff *skb; 20453733937dSMat Martineau struct l2cap_ctrl *control; 20460a708f8fSGustavo F. Padovan 20473733937dSMat Martineau BT_DBG("chan %p, skbs %p", chan, skbs); 20483733937dSMat Martineau 2049b99e13adSMat Martineau if (__chan_is_moving(chan)) 2050b99e13adSMat Martineau return; 2051b99e13adSMat Martineau 20523733937dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 20533733937dSMat Martineau 20543733937dSMat Martineau while (!skb_queue_empty(&chan->tx_q)) { 20553733937dSMat Martineau 20563733937dSMat Martineau skb = skb_dequeue(&chan->tx_q); 20573733937dSMat Martineau 20583733937dSMat Martineau bt_cb(skb)->control.retries = 1; 20593733937dSMat Martineau control = &bt_cb(skb)->control; 20603733937dSMat Martineau 20613733937dSMat Martineau control->reqseq = 0; 20623733937dSMat Martineau control->txseq = chan->next_tx_seq; 20633733937dSMat Martineau 20643733937dSMat Martineau __pack_control(chan, control, skb); 20650a708f8fSGustavo F. Padovan 206647d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 20673733937dSMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 20683733937dSMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 20690a708f8fSGustavo F. Padovan } 20700a708f8fSGustavo F. Padovan 20714343478fSGustavo F. Padovan l2cap_do_send(chan, skb); 20720a708f8fSGustavo F. Padovan 2073b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 20743733937dSMat Martineau 2075836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 20763733937dSMat Martineau chan->frames_sent++; 20770a708f8fSGustavo F. Padovan } 20780a708f8fSGustavo F. Padovan } 20790a708f8fSGustavo F. Padovan 208067c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan) 20810a708f8fSGustavo F. Padovan { 20820a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 208318a48e76SMat Martineau struct l2cap_ctrl *control; 208418a48e76SMat Martineau int sent = 0; 208518a48e76SMat Martineau 208618a48e76SMat Martineau BT_DBG("chan %p", chan); 20870a708f8fSGustavo F. Padovan 208889bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 20890a708f8fSGustavo F. Padovan return -ENOTCONN; 20900a708f8fSGustavo F. Padovan 209194122bbeSMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 209294122bbeSMat Martineau return 0; 209394122bbeSMat Martineau 2094b99e13adSMat Martineau if (__chan_is_moving(chan)) 2095b99e13adSMat Martineau return 0; 2096b99e13adSMat Martineau 209718a48e76SMat Martineau while (chan->tx_send_head && 209818a48e76SMat Martineau chan->unacked_frames < chan->remote_tx_win && 209918a48e76SMat Martineau chan->tx_state == L2CAP_TX_STATE_XMIT) { 21000a708f8fSGustavo F. Padovan 210118a48e76SMat Martineau skb = chan->tx_send_head; 21020a708f8fSGustavo F. Padovan 210318a48e76SMat Martineau bt_cb(skb)->control.retries = 1; 210418a48e76SMat Martineau control = &bt_cb(skb)->control; 21050a708f8fSGustavo F. Padovan 2106e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 210718a48e76SMat Martineau control->final = 1; 2108e2ab4353SGustavo F. Padovan 210918a48e76SMat Martineau control->reqseq = chan->buffer_seq; 211018a48e76SMat Martineau chan->last_acked_seq = chan->buffer_seq; 211118a48e76SMat Martineau control->txseq = chan->next_tx_seq; 21120a708f8fSGustavo F. Padovan 211318a48e76SMat Martineau __pack_control(chan, control, skb); 21140a708f8fSGustavo F. Padovan 211547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 211618a48e76SMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 211718a48e76SMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 21180a708f8fSGustavo F. Padovan } 21190a708f8fSGustavo F. Padovan 212018a48e76SMat Martineau /* Clone after data has been modified. Data is assumed to be 212118a48e76SMat Martineau read-only (for locking purposes) on cloned sk_buffs. 212218a48e76SMat Martineau */ 212318a48e76SMat Martineau tx_skb = skb_clone(skb, GFP_KERNEL); 212418a48e76SMat Martineau 212518a48e76SMat Martineau if (!tx_skb) 212618a48e76SMat Martineau break; 21270a708f8fSGustavo F. Padovan 21281a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 21290a708f8fSGustavo F. Padovan 2130836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 21316a026610SGustavo F. Padovan chan->unacked_frames++; 21326a026610SGustavo F. Padovan chan->frames_sent++; 213318a48e76SMat Martineau sent++; 21340a708f8fSGustavo F. Padovan 213558d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 213658d35f87SGustavo F. Padovan chan->tx_send_head = NULL; 21370a708f8fSGustavo F. Padovan else 213858d35f87SGustavo F. Padovan chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); 213918a48e76SMat Martineau 214018a48e76SMat Martineau l2cap_do_send(chan, tx_skb); 2141b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 21420a708f8fSGustavo F. Padovan } 21430a708f8fSGustavo F. Padovan 2144b4400672SAndrei Emeltchenko BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent, 2145b4400672SAndrei Emeltchenko chan->unacked_frames, skb_queue_len(&chan->tx_q)); 214618a48e76SMat Martineau 214718a48e76SMat Martineau return sent; 21480a708f8fSGustavo F. Padovan } 21490a708f8fSGustavo F. Padovan 2150e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan) 2151e1fbd4c1SMat Martineau { 2152e1fbd4c1SMat Martineau struct l2cap_ctrl control; 2153e1fbd4c1SMat Martineau struct sk_buff *skb; 2154e1fbd4c1SMat Martineau struct sk_buff *tx_skb; 2155e1fbd4c1SMat Martineau u16 seq; 2156e1fbd4c1SMat Martineau 2157e1fbd4c1SMat Martineau BT_DBG("chan %p", chan); 2158e1fbd4c1SMat Martineau 2159e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 2160e1fbd4c1SMat Martineau return; 2161e1fbd4c1SMat Martineau 2162b99e13adSMat Martineau if (__chan_is_moving(chan)) 2163b99e13adSMat Martineau return; 2164b99e13adSMat Martineau 2165e1fbd4c1SMat Martineau while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) { 2166e1fbd4c1SMat Martineau seq = l2cap_seq_list_pop(&chan->retrans_list); 2167e1fbd4c1SMat Martineau 2168e1fbd4c1SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq); 2169e1fbd4c1SMat Martineau if (!skb) { 2170e1fbd4c1SMat Martineau BT_DBG("Error: Can't retransmit seq %d, frame missing", 2171e1fbd4c1SMat Martineau seq); 2172e1fbd4c1SMat Martineau continue; 2173e1fbd4c1SMat Martineau } 2174e1fbd4c1SMat Martineau 2175e1fbd4c1SMat Martineau bt_cb(skb)->control.retries++; 2176e1fbd4c1SMat Martineau control = bt_cb(skb)->control; 2177e1fbd4c1SMat Martineau 2178e1fbd4c1SMat Martineau if (chan->max_tx != 0 && 2179e1fbd4c1SMat Martineau bt_cb(skb)->control.retries > chan->max_tx) { 2180e1fbd4c1SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 21815e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 2182e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2183e1fbd4c1SMat Martineau break; 2184e1fbd4c1SMat Martineau } 2185e1fbd4c1SMat Martineau 2186e1fbd4c1SMat Martineau control.reqseq = chan->buffer_seq; 2187e1fbd4c1SMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 2188e1fbd4c1SMat Martineau control.final = 1; 2189e1fbd4c1SMat Martineau else 2190e1fbd4c1SMat Martineau control.final = 0; 2191e1fbd4c1SMat Martineau 2192e1fbd4c1SMat Martineau if (skb_cloned(skb)) { 2193e1fbd4c1SMat Martineau /* Cloned sk_buffs are read-only, so we need a 2194e1fbd4c1SMat Martineau * writeable copy 2195e1fbd4c1SMat Martineau */ 21968bcde1f2SGustavo Padovan tx_skb = skb_copy(skb, GFP_KERNEL); 2197e1fbd4c1SMat Martineau } else { 21988bcde1f2SGustavo Padovan tx_skb = skb_clone(skb, GFP_KERNEL); 2199e1fbd4c1SMat Martineau } 2200e1fbd4c1SMat Martineau 2201e1fbd4c1SMat Martineau if (!tx_skb) { 2202e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2203e1fbd4c1SMat Martineau break; 2204e1fbd4c1SMat Martineau } 2205e1fbd4c1SMat Martineau 2206e1fbd4c1SMat Martineau /* Update skb contents */ 2207e1fbd4c1SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 2208e1fbd4c1SMat Martineau put_unaligned_le32(__pack_extended_control(&control), 2209e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 2210e1fbd4c1SMat Martineau } else { 2211e1fbd4c1SMat Martineau put_unaligned_le16(__pack_enhanced_control(&control), 2212e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 2213e1fbd4c1SMat Martineau } 2214e1fbd4c1SMat Martineau 2215e1fbd4c1SMat Martineau if (chan->fcs == L2CAP_FCS_CRC16) { 2216e1fbd4c1SMat Martineau u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len); 2217e1fbd4c1SMat Martineau put_unaligned_le16(fcs, skb_put(tx_skb, 2218e1fbd4c1SMat Martineau L2CAP_FCS_SIZE)); 2219e1fbd4c1SMat Martineau } 2220e1fbd4c1SMat Martineau 2221e1fbd4c1SMat Martineau l2cap_do_send(chan, tx_skb); 2222e1fbd4c1SMat Martineau 2223e1fbd4c1SMat Martineau BT_DBG("Resent txseq %d", control.txseq); 2224e1fbd4c1SMat Martineau 2225e1fbd4c1SMat Martineau chan->last_acked_seq = chan->buffer_seq; 2226e1fbd4c1SMat Martineau } 2227e1fbd4c1SMat Martineau } 2228e1fbd4c1SMat Martineau 2229f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan, 2230f80842a8SMat Martineau struct l2cap_ctrl *control) 2231f80842a8SMat Martineau { 2232f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2233f80842a8SMat Martineau 2234f80842a8SMat Martineau l2cap_seq_list_append(&chan->retrans_list, control->reqseq); 2235f80842a8SMat Martineau l2cap_ertm_resend(chan); 2236f80842a8SMat Martineau } 2237f80842a8SMat Martineau 2238d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan, 2239d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 2240d2a7ac5dSMat Martineau { 2241e1fbd4c1SMat Martineau struct sk_buff *skb; 2242e1fbd4c1SMat Martineau 2243e1fbd4c1SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2244e1fbd4c1SMat Martineau 2245e1fbd4c1SMat Martineau if (control->poll) 2246e1fbd4c1SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 2247e1fbd4c1SMat Martineau 2248e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 2249e1fbd4c1SMat Martineau 2250e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 2251e1fbd4c1SMat Martineau return; 2252e1fbd4c1SMat Martineau 2253e1fbd4c1SMat Martineau if (chan->unacked_frames) { 2254e1fbd4c1SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 2255e1fbd4c1SMat Martineau if (bt_cb(skb)->control.txseq == control->reqseq || 2256e1fbd4c1SMat Martineau skb == chan->tx_send_head) 2257e1fbd4c1SMat Martineau break; 2258e1fbd4c1SMat Martineau } 2259e1fbd4c1SMat Martineau 2260e1fbd4c1SMat Martineau skb_queue_walk_from(&chan->tx_q, skb) { 2261e1fbd4c1SMat Martineau if (skb == chan->tx_send_head) 2262e1fbd4c1SMat Martineau break; 2263e1fbd4c1SMat Martineau 2264e1fbd4c1SMat Martineau l2cap_seq_list_append(&chan->retrans_list, 2265e1fbd4c1SMat Martineau bt_cb(skb)->control.txseq); 2266e1fbd4c1SMat Martineau } 2267e1fbd4c1SMat Martineau 2268e1fbd4c1SMat Martineau l2cap_ertm_resend(chan); 2269e1fbd4c1SMat Martineau } 2270d2a7ac5dSMat Martineau } 2271d2a7ac5dSMat Martineau 2272b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan) 2273b17e73bbSSzymon Janc { 22740a0aba42SMat Martineau struct l2cap_ctrl control; 22750a0aba42SMat Martineau u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq, 22760a0aba42SMat Martineau chan->last_acked_seq); 22770a0aba42SMat Martineau int threshold; 22780a0aba42SMat Martineau 22790a0aba42SMat Martineau BT_DBG("chan %p last_acked_seq %d buffer_seq %d", 22800a0aba42SMat Martineau chan, chan->last_acked_seq, chan->buffer_seq); 22810a0aba42SMat Martineau 22820a0aba42SMat Martineau memset(&control, 0, sizeof(control)); 22830a0aba42SMat Martineau control.sframe = 1; 22840a0aba42SMat Martineau 22850a0aba42SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 22860a0aba42SMat Martineau chan->rx_state == L2CAP_RX_STATE_RECV) { 2287b17e73bbSSzymon Janc __clear_ack_timer(chan); 22880a0aba42SMat Martineau control.super = L2CAP_SUPER_RNR; 22890a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 22900a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 22910a0aba42SMat Martineau } else { 22920a0aba42SMat Martineau if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) { 22930a0aba42SMat Martineau l2cap_ertm_send(chan); 22940a0aba42SMat Martineau /* If any i-frames were sent, they included an ack */ 22950a0aba42SMat Martineau if (chan->buffer_seq == chan->last_acked_seq) 22960a0aba42SMat Martineau frames_to_ack = 0; 22970a0aba42SMat Martineau } 22980a0aba42SMat Martineau 2299c20f8e35SMat Martineau /* Ack now if the window is 3/4ths full. 23000a0aba42SMat Martineau * Calculate without mul or div 23010a0aba42SMat Martineau */ 2302c20f8e35SMat Martineau threshold = chan->ack_win; 23030a0aba42SMat Martineau threshold += threshold << 1; 23040a0aba42SMat Martineau threshold >>= 2; 23050a0aba42SMat Martineau 2306b4400672SAndrei Emeltchenko BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack, 23070a0aba42SMat Martineau threshold); 23080a0aba42SMat Martineau 23090a0aba42SMat Martineau if (frames_to_ack >= threshold) { 23100a0aba42SMat Martineau __clear_ack_timer(chan); 23110a0aba42SMat Martineau control.super = L2CAP_SUPER_RR; 23120a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 23130a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 23140a0aba42SMat Martineau frames_to_ack = 0; 23150a0aba42SMat Martineau } 23160a0aba42SMat Martineau 23170a0aba42SMat Martineau if (frames_to_ack) 23180a0aba42SMat Martineau __set_ack_timer(chan); 23190a0aba42SMat Martineau } 2320b17e73bbSSzymon Janc } 2321b17e73bbSSzymon Janc 232204124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, 232304124681SGustavo F. Padovan struct msghdr *msg, int len, 232404124681SGustavo F. Padovan int count, struct sk_buff *skb) 23250a708f8fSGustavo F. Padovan { 23260952a57aSAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 23270a708f8fSGustavo F. Padovan struct sk_buff **frag; 232890338947SGustavo Padovan int sent = 0; 23290a708f8fSGustavo F. Padovan 23300a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) 23310a708f8fSGustavo F. Padovan return -EFAULT; 23320a708f8fSGustavo F. Padovan 23330a708f8fSGustavo F. Padovan sent += count; 23340a708f8fSGustavo F. Padovan len -= count; 23350a708f8fSGustavo F. Padovan 23360a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 23370a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 23380a708f8fSGustavo F. Padovan while (len) { 2339fbe00700SGustavo Padovan struct sk_buff *tmp; 2340fbe00700SGustavo Padovan 23410a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 23420a708f8fSGustavo F. Padovan 2343fbe00700SGustavo Padovan tmp = chan->ops->alloc_skb(chan, count, 234490338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 2345fbe00700SGustavo Padovan if (IS_ERR(tmp)) 2346fbe00700SGustavo Padovan return PTR_ERR(tmp); 23472f7719ceSAndrei Emeltchenko 2348fbe00700SGustavo Padovan *frag = tmp; 2349fbe00700SGustavo Padovan 23500a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) 23510a708f8fSGustavo F. Padovan return -EFAULT; 23520a708f8fSGustavo F. Padovan 23535e59b791SLuiz Augusto von Dentz (*frag)->priority = skb->priority; 23545e59b791SLuiz Augusto von Dentz 23550a708f8fSGustavo F. Padovan sent += count; 23560a708f8fSGustavo F. Padovan len -= count; 23570a708f8fSGustavo F. Padovan 23582d0ed3d5SGustavo Padovan skb->len += (*frag)->len; 23592d0ed3d5SGustavo Padovan skb->data_len += (*frag)->len; 23602d0ed3d5SGustavo Padovan 23610a708f8fSGustavo F. Padovan frag = &(*frag)->next; 23620a708f8fSGustavo F. Padovan } 23630a708f8fSGustavo F. Padovan 23640a708f8fSGustavo F. Padovan return sent; 23650a708f8fSGustavo F. Padovan } 23660a708f8fSGustavo F. Padovan 23675e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, 23685e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 23695e59b791SLuiz Augusto von Dentz u32 priority) 23700a708f8fSGustavo F. Padovan { 23718c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 23720a708f8fSGustavo F. Padovan struct sk_buff *skb; 237303a51213SAndrei Emeltchenko int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; 23740a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 23750a708f8fSGustavo F. Padovan 237643b1b8dfSMarcel Holtmann BT_DBG("chan %p psm 0x%2.2x len %zu priority %u", chan, 237743b1b8dfSMarcel Holtmann __le16_to_cpu(chan->psm), len, priority); 23780a708f8fSGustavo F. Padovan 23790a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 23802f7719ceSAndrei Emeltchenko 23812f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 238290338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 238390338947SGustavo Padovan if (IS_ERR(skb)) 238490338947SGustavo Padovan return skb; 23850a708f8fSGustavo F. Padovan 23865e59b791SLuiz Augusto von Dentz skb->priority = priority; 23875e59b791SLuiz Augusto von Dentz 23880a708f8fSGustavo F. Padovan /* Create L2CAP header */ 23890a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2390fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 2391daf6a78cSAndrei Emeltchenko lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); 239243b1b8dfSMarcel Holtmann put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE)); 23930a708f8fSGustavo F. Padovan 23940952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 23950a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 23960a708f8fSGustavo F. Padovan kfree_skb(skb); 23970a708f8fSGustavo F. Padovan return ERR_PTR(err); 23980a708f8fSGustavo F. Padovan } 23990a708f8fSGustavo F. Padovan return skb; 24000a708f8fSGustavo F. Padovan } 24010a708f8fSGustavo F. Padovan 24025e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, 24035e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 24045e59b791SLuiz Augusto von Dentz u32 priority) 24050a708f8fSGustavo F. Padovan { 24068c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 24070a708f8fSGustavo F. Padovan struct sk_buff *skb; 2408f2ba7faeSGustavo Padovan int err, count; 24090a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 24100a708f8fSGustavo F. Padovan 2411b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 24120a708f8fSGustavo F. Padovan 2413f2ba7faeSGustavo Padovan count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); 24142f7719ceSAndrei Emeltchenko 2415f2ba7faeSGustavo Padovan skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE, 241690338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 241790338947SGustavo Padovan if (IS_ERR(skb)) 241890338947SGustavo Padovan return skb; 24190a708f8fSGustavo F. Padovan 24205e59b791SLuiz Augusto von Dentz skb->priority = priority; 24215e59b791SLuiz Augusto von Dentz 24220a708f8fSGustavo F. Padovan /* Create L2CAP header */ 24230a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2424fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 24256ff9b5efSGustavo Padovan lh->len = cpu_to_le16(len); 24260a708f8fSGustavo F. Padovan 24270952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 24280a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 24290a708f8fSGustavo F. Padovan kfree_skb(skb); 24300a708f8fSGustavo F. Padovan return ERR_PTR(err); 24310a708f8fSGustavo F. Padovan } 24320a708f8fSGustavo F. Padovan return skb; 24330a708f8fSGustavo F. Padovan } 24340a708f8fSGustavo F. Padovan 2435ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, 2436ab0ff76dSLuiz Augusto von Dentz struct msghdr *msg, size_t len, 243794122bbeSMat Martineau u16 sdulen) 24380a708f8fSGustavo F. Padovan { 24398c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 24400a708f8fSGustavo F. Padovan struct sk_buff *skb; 2441e4ca6d98SAndrei Emeltchenko int err, count, hlen; 24420a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 24430a708f8fSGustavo F. Padovan 2444b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 24450a708f8fSGustavo F. Padovan 24460a708f8fSGustavo F. Padovan if (!conn) 24470a708f8fSGustavo F. Padovan return ERR_PTR(-ENOTCONN); 24480a708f8fSGustavo F. Padovan 2449ba7aa64fSGustavo Padovan hlen = __ertm_hdr_size(chan); 2450e4ca6d98SAndrei Emeltchenko 24510a708f8fSGustavo F. Padovan if (sdulen) 245203a51213SAndrei Emeltchenko hlen += L2CAP_SDULEN_SIZE; 24530a708f8fSGustavo F. Padovan 245447d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 245503a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 24560a708f8fSGustavo F. Padovan 24570a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 24582f7719ceSAndrei Emeltchenko 24592f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 246090338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 246190338947SGustavo Padovan if (IS_ERR(skb)) 246290338947SGustavo Padovan return skb; 24630a708f8fSGustavo F. Padovan 24640a708f8fSGustavo F. Padovan /* Create L2CAP header */ 24650a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2466fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 24670a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 246888843ab0SAndrei Emeltchenko 246918a48e76SMat Martineau /* Control header is populated later */ 247018a48e76SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 247118a48e76SMat Martineau put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 247218a48e76SMat Martineau else 247318a48e76SMat Martineau put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 247488843ab0SAndrei Emeltchenko 24750a708f8fSGustavo F. Padovan if (sdulen) 247603a51213SAndrei Emeltchenko put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 24770a708f8fSGustavo F. Padovan 24780952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 24790a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 24800a708f8fSGustavo F. Padovan kfree_skb(skb); 24810a708f8fSGustavo F. Padovan return ERR_PTR(err); 24820a708f8fSGustavo F. Padovan } 24830a708f8fSGustavo F. Padovan 248418a48e76SMat Martineau bt_cb(skb)->control.fcs = chan->fcs; 24853ce3514fSMat Martineau bt_cb(skb)->control.retries = 0; 24860a708f8fSGustavo F. Padovan return skb; 24870a708f8fSGustavo F. Padovan } 24880a708f8fSGustavo F. Padovan 248994122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan, 249094122bbeSMat Martineau struct sk_buff_head *seg_queue, 249194122bbeSMat Martineau struct msghdr *msg, size_t len) 24920a708f8fSGustavo F. Padovan { 24930a708f8fSGustavo F. Padovan struct sk_buff *skb; 249494122bbeSMat Martineau u16 sdu_len; 249594122bbeSMat Martineau size_t pdu_len; 249694122bbeSMat Martineau u8 sar; 24970a708f8fSGustavo F. Padovan 2498b4400672SAndrei Emeltchenko BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); 24990a708f8fSGustavo F. Padovan 250094122bbeSMat Martineau /* It is critical that ERTM PDUs fit in a single HCI fragment, 250194122bbeSMat Martineau * so fragmented skbs are not used. The HCI layer's handling 250294122bbeSMat Martineau * of fragmented skbs is not compatible with ERTM's queueing. 250394122bbeSMat Martineau */ 250494122bbeSMat Martineau 250594122bbeSMat Martineau /* PDU size is derived from the HCI MTU */ 250694122bbeSMat Martineau pdu_len = chan->conn->mtu; 250794122bbeSMat Martineau 2508a549574dSMat Martineau /* Constrain PDU size for BR/EDR connections */ 2509a549574dSMat Martineau if (!chan->hs_hcon) 251094122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); 251194122bbeSMat Martineau 251294122bbeSMat Martineau /* Adjust for largest possible L2CAP overhead. */ 251335d401dfSGustavo Padovan if (chan->fcs) 251435d401dfSGustavo Padovan pdu_len -= L2CAP_FCS_SIZE; 251535d401dfSGustavo Padovan 2516ba7aa64fSGustavo Padovan pdu_len -= __ertm_hdr_size(chan); 251794122bbeSMat Martineau 251894122bbeSMat Martineau /* Remote device may have requested smaller PDUs */ 251994122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, chan->remote_mps); 252094122bbeSMat Martineau 252194122bbeSMat Martineau if (len <= pdu_len) { 252294122bbeSMat Martineau sar = L2CAP_SAR_UNSEGMENTED; 252394122bbeSMat Martineau sdu_len = 0; 252494122bbeSMat Martineau pdu_len = len; 252594122bbeSMat Martineau } else { 252694122bbeSMat Martineau sar = L2CAP_SAR_START; 252794122bbeSMat Martineau sdu_len = len; 252894122bbeSMat Martineau pdu_len -= L2CAP_SDULEN_SIZE; 252994122bbeSMat Martineau } 25300a708f8fSGustavo F. Padovan 25310a708f8fSGustavo F. Padovan while (len > 0) { 253294122bbeSMat Martineau skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len); 25330a708f8fSGustavo F. Padovan 25340a708f8fSGustavo F. Padovan if (IS_ERR(skb)) { 253594122bbeSMat Martineau __skb_queue_purge(seg_queue); 25360a708f8fSGustavo F. Padovan return PTR_ERR(skb); 25370a708f8fSGustavo F. Padovan } 25380a708f8fSGustavo F. Padovan 253994122bbeSMat Martineau bt_cb(skb)->control.sar = sar; 254094122bbeSMat Martineau __skb_queue_tail(seg_queue, skb); 25410a708f8fSGustavo F. Padovan 254294122bbeSMat Martineau len -= pdu_len; 254394122bbeSMat Martineau if (sdu_len) { 254494122bbeSMat Martineau sdu_len = 0; 254594122bbeSMat Martineau pdu_len += L2CAP_SDULEN_SIZE; 254694122bbeSMat Martineau } 254794122bbeSMat Martineau 254894122bbeSMat Martineau if (len <= pdu_len) { 254994122bbeSMat Martineau sar = L2CAP_SAR_END; 255094122bbeSMat Martineau pdu_len = len; 255194122bbeSMat Martineau } else { 255294122bbeSMat Martineau sar = L2CAP_SAR_CONTINUE; 255394122bbeSMat Martineau } 255494122bbeSMat Martineau } 255594122bbeSMat Martineau 2556f0f62799SGustavo Padovan return 0; 25570a708f8fSGustavo F. Padovan } 25580a708f8fSGustavo F. Padovan 2559177f8f2bSJohan Hedberg static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan, 2560177f8f2bSJohan Hedberg struct msghdr *msg, 2561177f8f2bSJohan Hedberg size_t len, u16 sdulen) 2562177f8f2bSJohan Hedberg { 2563177f8f2bSJohan Hedberg struct l2cap_conn *conn = chan->conn; 2564177f8f2bSJohan Hedberg struct sk_buff *skb; 2565177f8f2bSJohan Hedberg int err, count, hlen; 2566177f8f2bSJohan Hedberg struct l2cap_hdr *lh; 2567177f8f2bSJohan Hedberg 2568177f8f2bSJohan Hedberg BT_DBG("chan %p len %zu", chan, len); 2569177f8f2bSJohan Hedberg 2570177f8f2bSJohan Hedberg if (!conn) 2571177f8f2bSJohan Hedberg return ERR_PTR(-ENOTCONN); 2572177f8f2bSJohan Hedberg 2573177f8f2bSJohan Hedberg hlen = L2CAP_HDR_SIZE; 2574177f8f2bSJohan Hedberg 2575177f8f2bSJohan Hedberg if (sdulen) 2576177f8f2bSJohan Hedberg hlen += L2CAP_SDULEN_SIZE; 2577177f8f2bSJohan Hedberg 2578177f8f2bSJohan Hedberg count = min_t(unsigned int, (conn->mtu - hlen), len); 2579177f8f2bSJohan Hedberg 2580177f8f2bSJohan Hedberg skb = chan->ops->alloc_skb(chan, count + hlen, 2581177f8f2bSJohan Hedberg msg->msg_flags & MSG_DONTWAIT); 2582177f8f2bSJohan Hedberg if (IS_ERR(skb)) 2583177f8f2bSJohan Hedberg return skb; 2584177f8f2bSJohan Hedberg 2585177f8f2bSJohan Hedberg /* Create L2CAP header */ 2586177f8f2bSJohan Hedberg lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2587177f8f2bSJohan Hedberg lh->cid = cpu_to_le16(chan->dcid); 2588177f8f2bSJohan Hedberg lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 2589177f8f2bSJohan Hedberg 2590177f8f2bSJohan Hedberg if (sdulen) 2591177f8f2bSJohan Hedberg put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 2592177f8f2bSJohan Hedberg 2593177f8f2bSJohan Hedberg err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 2594177f8f2bSJohan Hedberg if (unlikely(err < 0)) { 2595177f8f2bSJohan Hedberg kfree_skb(skb); 2596177f8f2bSJohan Hedberg return ERR_PTR(err); 2597177f8f2bSJohan Hedberg } 2598177f8f2bSJohan Hedberg 2599177f8f2bSJohan Hedberg return skb; 2600177f8f2bSJohan Hedberg } 2601177f8f2bSJohan Hedberg 2602177f8f2bSJohan Hedberg static int l2cap_segment_le_sdu(struct l2cap_chan *chan, 2603177f8f2bSJohan Hedberg struct sk_buff_head *seg_queue, 2604177f8f2bSJohan Hedberg struct msghdr *msg, size_t len) 2605177f8f2bSJohan Hedberg { 2606177f8f2bSJohan Hedberg struct sk_buff *skb; 2607177f8f2bSJohan Hedberg size_t pdu_len; 2608177f8f2bSJohan Hedberg u16 sdu_len; 2609177f8f2bSJohan Hedberg 2610177f8f2bSJohan Hedberg BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); 2611177f8f2bSJohan Hedberg 2612177f8f2bSJohan Hedberg pdu_len = chan->conn->mtu - L2CAP_HDR_SIZE; 2613177f8f2bSJohan Hedberg 2614177f8f2bSJohan Hedberg pdu_len = min_t(size_t, pdu_len, chan->remote_mps); 2615177f8f2bSJohan Hedberg 2616177f8f2bSJohan Hedberg sdu_len = len; 2617177f8f2bSJohan Hedberg pdu_len -= L2CAP_SDULEN_SIZE; 2618177f8f2bSJohan Hedberg 2619177f8f2bSJohan Hedberg while (len > 0) { 2620177f8f2bSJohan Hedberg if (len <= pdu_len) 2621177f8f2bSJohan Hedberg pdu_len = len; 2622177f8f2bSJohan Hedberg 2623177f8f2bSJohan Hedberg skb = l2cap_create_le_flowctl_pdu(chan, msg, pdu_len, sdu_len); 2624177f8f2bSJohan Hedberg if (IS_ERR(skb)) { 2625177f8f2bSJohan Hedberg __skb_queue_purge(seg_queue); 2626177f8f2bSJohan Hedberg return PTR_ERR(skb); 2627177f8f2bSJohan Hedberg } 2628177f8f2bSJohan Hedberg 2629177f8f2bSJohan Hedberg __skb_queue_tail(seg_queue, skb); 2630177f8f2bSJohan Hedberg 2631177f8f2bSJohan Hedberg len -= pdu_len; 2632177f8f2bSJohan Hedberg 2633177f8f2bSJohan Hedberg if (sdu_len) { 2634177f8f2bSJohan Hedberg sdu_len = 0; 2635177f8f2bSJohan Hedberg pdu_len += L2CAP_SDULEN_SIZE; 2636177f8f2bSJohan Hedberg } 2637177f8f2bSJohan Hedberg } 2638177f8f2bSJohan Hedberg 2639177f8f2bSJohan Hedberg return 0; 2640177f8f2bSJohan Hedberg } 2641177f8f2bSJohan Hedberg 26425e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, 26435e59b791SLuiz Augusto von Dentz u32 priority) 26449a91a04aSGustavo F. Padovan { 26459a91a04aSGustavo F. Padovan struct sk_buff *skb; 26469a91a04aSGustavo F. Padovan int err; 264794122bbeSMat Martineau struct sk_buff_head seg_queue; 26489a91a04aSGustavo F. Padovan 264931e8ce80SSeung-Woo Kim if (!chan->conn) 265031e8ce80SSeung-Woo Kim return -ENOTCONN; 265131e8ce80SSeung-Woo Kim 26529a91a04aSGustavo F. Padovan /* Connectionless channel */ 2653715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { 26545e59b791SLuiz Augusto von Dentz skb = l2cap_create_connless_pdu(chan, msg, len, priority); 26559a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 26569a91a04aSGustavo F. Padovan return PTR_ERR(skb); 26579a91a04aSGustavo F. Padovan 26589a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 26599a91a04aSGustavo F. Padovan return len; 26609a91a04aSGustavo F. Padovan } 26619a91a04aSGustavo F. Padovan 26629a91a04aSGustavo F. Padovan switch (chan->mode) { 266338319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 2664177f8f2bSJohan Hedberg /* Check outgoing MTU */ 2665177f8f2bSJohan Hedberg if (len > chan->omtu) 2666177f8f2bSJohan Hedberg return -EMSGSIZE; 2667177f8f2bSJohan Hedberg 2668fad5fc89SJohan Hedberg if (!chan->tx_credits) 2669fad5fc89SJohan Hedberg return -EAGAIN; 2670fad5fc89SJohan Hedberg 2671177f8f2bSJohan Hedberg __skb_queue_head_init(&seg_queue); 2672177f8f2bSJohan Hedberg 2673177f8f2bSJohan Hedberg err = l2cap_segment_le_sdu(chan, &seg_queue, msg, len); 2674177f8f2bSJohan Hedberg 2675177f8f2bSJohan Hedberg if (chan->state != BT_CONNECTED) { 2676177f8f2bSJohan Hedberg __skb_queue_purge(&seg_queue); 2677177f8f2bSJohan Hedberg err = -ENOTCONN; 2678177f8f2bSJohan Hedberg } 2679177f8f2bSJohan Hedberg 2680177f8f2bSJohan Hedberg if (err) 2681177f8f2bSJohan Hedberg return err; 2682177f8f2bSJohan Hedberg 2683177f8f2bSJohan Hedberg skb_queue_splice_tail_init(&seg_queue, &chan->tx_q); 2684177f8f2bSJohan Hedberg 2685177f8f2bSJohan Hedberg while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) { 2686177f8f2bSJohan Hedberg l2cap_do_send(chan, skb_dequeue(&chan->tx_q)); 2687177f8f2bSJohan Hedberg chan->tx_credits--; 2688177f8f2bSJohan Hedberg } 2689177f8f2bSJohan Hedberg 2690177f8f2bSJohan Hedberg if (!chan->tx_credits) 2691177f8f2bSJohan Hedberg chan->ops->suspend(chan); 2692177f8f2bSJohan Hedberg 2693177f8f2bSJohan Hedberg err = len; 2694177f8f2bSJohan Hedberg 2695177f8f2bSJohan Hedberg break; 2696177f8f2bSJohan Hedberg 2697fad5fc89SJohan Hedberg case L2CAP_MODE_BASIC: 26989a91a04aSGustavo F. Padovan /* Check outgoing MTU */ 26999a91a04aSGustavo F. Padovan if (len > chan->omtu) 27009a91a04aSGustavo F. Padovan return -EMSGSIZE; 27019a91a04aSGustavo F. Padovan 27029a91a04aSGustavo F. Padovan /* Create a basic PDU */ 27035e59b791SLuiz Augusto von Dentz skb = l2cap_create_basic_pdu(chan, msg, len, priority); 27049a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 27059a91a04aSGustavo F. Padovan return PTR_ERR(skb); 27069a91a04aSGustavo F. Padovan 27079a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 27089a91a04aSGustavo F. Padovan err = len; 27099a91a04aSGustavo F. Padovan break; 27109a91a04aSGustavo F. Padovan 27119a91a04aSGustavo F. Padovan case L2CAP_MODE_ERTM: 27129a91a04aSGustavo F. Padovan case L2CAP_MODE_STREAMING: 271394122bbeSMat Martineau /* Check outgoing MTU */ 271494122bbeSMat Martineau if (len > chan->omtu) { 271594122bbeSMat Martineau err = -EMSGSIZE; 27169a91a04aSGustavo F. Padovan break; 27179a91a04aSGustavo F. Padovan } 27189a91a04aSGustavo F. Padovan 271994122bbeSMat Martineau __skb_queue_head_init(&seg_queue); 272094122bbeSMat Martineau 272194122bbeSMat Martineau /* Do segmentation before calling in to the state machine, 272294122bbeSMat Martineau * since it's possible to block while waiting for memory 272394122bbeSMat Martineau * allocation. 272494122bbeSMat Martineau */ 272594122bbeSMat Martineau err = l2cap_segment_sdu(chan, &seg_queue, msg, len); 272694122bbeSMat Martineau 272794122bbeSMat Martineau /* The channel could have been closed while segmenting, 272894122bbeSMat Martineau * check that it is still connected. 272994122bbeSMat Martineau */ 273094122bbeSMat Martineau if (chan->state != BT_CONNECTED) { 273194122bbeSMat Martineau __skb_queue_purge(&seg_queue); 273294122bbeSMat Martineau err = -ENOTCONN; 27339a91a04aSGustavo F. Padovan } 27349a91a04aSGustavo F. Padovan 273594122bbeSMat Martineau if (err) 273694122bbeSMat Martineau break; 273794122bbeSMat Martineau 27383733937dSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) 2739d660366dSGustavo Padovan l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST); 27403733937dSMat Martineau else 2741d660366dSGustavo Padovan l2cap_streaming_send(chan, &seg_queue); 274294122bbeSMat Martineau 27439a91a04aSGustavo F. Padovan err = len; 27449a91a04aSGustavo F. Padovan 274594122bbeSMat Martineau /* If the skbs were not queued for sending, they'll still be in 274694122bbeSMat Martineau * seg_queue and need to be purged. 274794122bbeSMat Martineau */ 274894122bbeSMat Martineau __skb_queue_purge(&seg_queue); 27499a91a04aSGustavo F. Padovan break; 27509a91a04aSGustavo F. Padovan 27519a91a04aSGustavo F. Padovan default: 27529a91a04aSGustavo F. Padovan BT_DBG("bad state %1.1x", chan->mode); 27539a91a04aSGustavo F. Padovan err = -EBADFD; 27549a91a04aSGustavo F. Padovan } 27559a91a04aSGustavo F. Padovan 27569a91a04aSGustavo F. Padovan return err; 27579a91a04aSGustavo F. Padovan } 27589a91a04aSGustavo F. Padovan 2759d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq) 2760d2a7ac5dSMat Martineau { 2761bed68bdeSMat Martineau struct l2cap_ctrl control; 2762bed68bdeSMat Martineau u16 seq; 2763bed68bdeSMat Martineau 2764b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2765bed68bdeSMat Martineau 2766bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2767bed68bdeSMat Martineau control.sframe = 1; 2768bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2769bed68bdeSMat Martineau 2770bed68bdeSMat Martineau for (seq = chan->expected_tx_seq; seq != txseq; 2771bed68bdeSMat Martineau seq = __next_seq(chan, seq)) { 2772bed68bdeSMat Martineau if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) { 2773bed68bdeSMat Martineau control.reqseq = seq; 2774bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2775bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2776bed68bdeSMat Martineau } 2777bed68bdeSMat Martineau } 2778bed68bdeSMat Martineau 2779bed68bdeSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 2780d2a7ac5dSMat Martineau } 2781d2a7ac5dSMat Martineau 2782d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan) 2783d2a7ac5dSMat Martineau { 2784bed68bdeSMat Martineau struct l2cap_ctrl control; 2785bed68bdeSMat Martineau 2786bed68bdeSMat Martineau BT_DBG("chan %p", chan); 2787bed68bdeSMat Martineau 2788bed68bdeSMat Martineau if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR) 2789bed68bdeSMat Martineau return; 2790bed68bdeSMat Martineau 2791bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2792bed68bdeSMat Martineau control.sframe = 1; 2793bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2794bed68bdeSMat Martineau control.reqseq = chan->srej_list.tail; 2795bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2796d2a7ac5dSMat Martineau } 2797d2a7ac5dSMat Martineau 2798d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq) 2799d2a7ac5dSMat Martineau { 2800bed68bdeSMat Martineau struct l2cap_ctrl control; 2801bed68bdeSMat Martineau u16 initial_head; 2802bed68bdeSMat Martineau u16 seq; 2803bed68bdeSMat Martineau 2804b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2805bed68bdeSMat Martineau 2806bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2807bed68bdeSMat Martineau control.sframe = 1; 2808bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2809bed68bdeSMat Martineau 2810bed68bdeSMat Martineau /* Capture initial list head to allow only one pass through the list. */ 2811bed68bdeSMat Martineau initial_head = chan->srej_list.head; 2812bed68bdeSMat Martineau 2813bed68bdeSMat Martineau do { 2814bed68bdeSMat Martineau seq = l2cap_seq_list_pop(&chan->srej_list); 2815bed68bdeSMat Martineau if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR) 2816bed68bdeSMat Martineau break; 2817bed68bdeSMat Martineau 2818bed68bdeSMat Martineau control.reqseq = seq; 2819bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2820bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2821bed68bdeSMat Martineau } while (chan->srej_list.head != initial_head); 2822d2a7ac5dSMat Martineau } 2823d2a7ac5dSMat Martineau 2824608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq) 2825608bcc6dSMat Martineau { 2826608bcc6dSMat Martineau struct sk_buff *acked_skb; 2827608bcc6dSMat Martineau u16 ackseq; 2828608bcc6dSMat Martineau 2829b4400672SAndrei Emeltchenko BT_DBG("chan %p, reqseq %u", chan, reqseq); 2830608bcc6dSMat Martineau 2831608bcc6dSMat Martineau if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq) 2832608bcc6dSMat Martineau return; 2833608bcc6dSMat Martineau 2834b4400672SAndrei Emeltchenko BT_DBG("expected_ack_seq %u, unacked_frames %u", 2835608bcc6dSMat Martineau chan->expected_ack_seq, chan->unacked_frames); 2836608bcc6dSMat Martineau 2837608bcc6dSMat Martineau for (ackseq = chan->expected_ack_seq; ackseq != reqseq; 2838608bcc6dSMat Martineau ackseq = __next_seq(chan, ackseq)) { 2839608bcc6dSMat Martineau 2840608bcc6dSMat Martineau acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq); 2841608bcc6dSMat Martineau if (acked_skb) { 2842608bcc6dSMat Martineau skb_unlink(acked_skb, &chan->tx_q); 2843608bcc6dSMat Martineau kfree_skb(acked_skb); 2844608bcc6dSMat Martineau chan->unacked_frames--; 2845608bcc6dSMat Martineau } 2846608bcc6dSMat Martineau } 2847608bcc6dSMat Martineau 2848608bcc6dSMat Martineau chan->expected_ack_seq = reqseq; 2849608bcc6dSMat Martineau 2850608bcc6dSMat Martineau if (chan->unacked_frames == 0) 2851608bcc6dSMat Martineau __clear_retrans_timer(chan); 2852608bcc6dSMat Martineau 2853b4400672SAndrei Emeltchenko BT_DBG("unacked_frames %u", chan->unacked_frames); 2854608bcc6dSMat Martineau } 2855608bcc6dSMat Martineau 2856608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan) 2857608bcc6dSMat Martineau { 2858608bcc6dSMat Martineau BT_DBG("chan %p", chan); 2859608bcc6dSMat Martineau 2860608bcc6dSMat Martineau chan->expected_tx_seq = chan->buffer_seq; 2861608bcc6dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 2862608bcc6dSMat Martineau skb_queue_purge(&chan->srej_q); 2863608bcc6dSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2864608bcc6dSMat Martineau } 2865608bcc6dSMat Martineau 2866d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan, 2867608bcc6dSMat Martineau struct l2cap_ctrl *control, 2868608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2869608bcc6dSMat Martineau { 2870608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2871608bcc6dSMat Martineau event); 2872608bcc6dSMat Martineau 2873608bcc6dSMat Martineau switch (event) { 2874608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2875608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2876608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2877608bcc6dSMat Martineau 2878608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2879608bcc6dSMat Martineau l2cap_ertm_send(chan); 2880608bcc6dSMat Martineau break; 2881608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2882608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2883608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2884608bcc6dSMat Martineau 2885608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2886608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2887608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2888608bcc6dSMat Martineau */ 2889608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2890608bcc6dSMat Martineau } 2891608bcc6dSMat Martineau 2892608bcc6dSMat Martineau l2cap_send_ack(chan); 2893608bcc6dSMat Martineau 2894608bcc6dSMat Martineau break; 2895608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2896608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2897608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2898608bcc6dSMat Martineau 2899608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2900608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2901608bcc6dSMat Martineau 2902608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2903608bcc6dSMat Martineau local_control.sframe = 1; 2904608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2905608bcc6dSMat Martineau local_control.poll = 1; 2906608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2907a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2908608bcc6dSMat Martineau 2909608bcc6dSMat Martineau chan->retry_count = 1; 2910608bcc6dSMat Martineau __set_monitor_timer(chan); 2911608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2912608bcc6dSMat Martineau } 2913608bcc6dSMat Martineau break; 2914608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2915608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2916608bcc6dSMat Martineau break; 2917608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2918608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2919608bcc6dSMat Martineau chan->retry_count = 1; 2920608bcc6dSMat Martineau __set_monitor_timer(chan); 2921608bcc6dSMat Martineau __clear_ack_timer(chan); 2922608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2923608bcc6dSMat Martineau break; 2924608bcc6dSMat Martineau case L2CAP_EV_RETRANS_TO: 2925608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2926608bcc6dSMat Martineau chan->retry_count = 1; 2927608bcc6dSMat Martineau __set_monitor_timer(chan); 2928608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2929608bcc6dSMat Martineau break; 2930608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2931608bcc6dSMat Martineau /* Nothing to process */ 2932608bcc6dSMat Martineau break; 2933608bcc6dSMat Martineau default: 2934608bcc6dSMat Martineau break; 2935608bcc6dSMat Martineau } 2936608bcc6dSMat Martineau } 2937608bcc6dSMat Martineau 2938d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan, 2939608bcc6dSMat Martineau struct l2cap_ctrl *control, 2940608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2941608bcc6dSMat Martineau { 2942608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2943608bcc6dSMat Martineau event); 2944608bcc6dSMat Martineau 2945608bcc6dSMat Martineau switch (event) { 2946608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2947608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2948608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2949608bcc6dSMat Martineau /* Queue data, but don't send. */ 2950608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2951608bcc6dSMat Martineau break; 2952608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2953608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2954608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2955608bcc6dSMat Martineau 2956608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2957608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2958608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2959608bcc6dSMat Martineau */ 2960608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2961608bcc6dSMat Martineau } 2962608bcc6dSMat Martineau 2963608bcc6dSMat Martineau l2cap_send_ack(chan); 2964608bcc6dSMat Martineau 2965608bcc6dSMat Martineau break; 2966608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2967608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2968608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2969608bcc6dSMat Martineau 2970608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2971608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2972608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2973608bcc6dSMat Martineau local_control.sframe = 1; 2974608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2975608bcc6dSMat Martineau local_control.poll = 1; 2976608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2977a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2978608bcc6dSMat Martineau 2979608bcc6dSMat Martineau chan->retry_count = 1; 2980608bcc6dSMat Martineau __set_monitor_timer(chan); 2981608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2982608bcc6dSMat Martineau } 2983608bcc6dSMat Martineau break; 2984608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2985608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2986608bcc6dSMat Martineau 2987608bcc6dSMat Martineau /* Fall through */ 2988608bcc6dSMat Martineau 2989608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2990608bcc6dSMat Martineau if (control && control->final) { 2991608bcc6dSMat Martineau __clear_monitor_timer(chan); 2992608bcc6dSMat Martineau if (chan->unacked_frames > 0) 2993608bcc6dSMat Martineau __set_retrans_timer(chan); 2994608bcc6dSMat Martineau chan->retry_count = 0; 2995608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 2996608bcc6dSMat Martineau BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state); 2997608bcc6dSMat Martineau } 2998608bcc6dSMat Martineau break; 2999608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 3000608bcc6dSMat Martineau /* Ignore */ 3001608bcc6dSMat Martineau break; 3002608bcc6dSMat Martineau case L2CAP_EV_MONITOR_TO: 3003608bcc6dSMat Martineau if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) { 3004608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 3005608bcc6dSMat Martineau __set_monitor_timer(chan); 3006608bcc6dSMat Martineau chan->retry_count++; 3007608bcc6dSMat Martineau } else { 30085e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNABORTED); 3009608bcc6dSMat Martineau } 3010608bcc6dSMat Martineau break; 3011608bcc6dSMat Martineau default: 3012608bcc6dSMat Martineau break; 3013608bcc6dSMat Martineau } 3014608bcc6dSMat Martineau } 3015608bcc6dSMat Martineau 3016d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 3017608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 3018608bcc6dSMat Martineau { 3019608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d, state %d", 3020608bcc6dSMat Martineau chan, control, skbs, event, chan->tx_state); 3021608bcc6dSMat Martineau 3022608bcc6dSMat Martineau switch (chan->tx_state) { 3023608bcc6dSMat Martineau case L2CAP_TX_STATE_XMIT: 3024d660366dSGustavo Padovan l2cap_tx_state_xmit(chan, control, skbs, event); 3025608bcc6dSMat Martineau break; 3026608bcc6dSMat Martineau case L2CAP_TX_STATE_WAIT_F: 3027d660366dSGustavo Padovan l2cap_tx_state_wait_f(chan, control, skbs, event); 3028608bcc6dSMat Martineau break; 3029608bcc6dSMat Martineau default: 3030608bcc6dSMat Martineau /* Ignore event */ 3031608bcc6dSMat Martineau break; 3032608bcc6dSMat Martineau } 3033608bcc6dSMat Martineau } 3034608bcc6dSMat Martineau 30354b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan, 30364b51dae9SMat Martineau struct l2cap_ctrl *control) 30374b51dae9SMat Martineau { 30384b51dae9SMat Martineau BT_DBG("chan %p, control %p", chan, control); 3039401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT); 30404b51dae9SMat Martineau } 30414b51dae9SMat Martineau 3042f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan, 3043f80842a8SMat Martineau struct l2cap_ctrl *control) 3044f80842a8SMat Martineau { 3045f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 3046401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT); 3047f80842a8SMat Martineau } 3048f80842a8SMat Martineau 30490a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */ 30500a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 30510a708f8fSGustavo F. Padovan { 30520a708f8fSGustavo F. Padovan struct sk_buff *nskb; 305348454079SGustavo F. Padovan struct l2cap_chan *chan; 30540a708f8fSGustavo F. Padovan 30550a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 30560a708f8fSGustavo F. Padovan 30573df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 30583d57dc68SGustavo F. Padovan 30593df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 3060715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW) 30610a708f8fSGustavo F. Padovan continue; 30620a708f8fSGustavo F. Padovan 30637f5396a7SGustavo Padovan /* Don't send frame to the channel it came from */ 30647f5396a7SGustavo Padovan if (bt_cb(skb)->chan == chan) 30650a708f8fSGustavo F. Padovan continue; 30667f5396a7SGustavo Padovan 30678bcde1f2SGustavo Padovan nskb = skb_clone(skb, GFP_KERNEL); 30680a708f8fSGustavo F. Padovan if (!nskb) 30690a708f8fSGustavo F. Padovan continue; 307080b98027SGustavo Padovan if (chan->ops->recv(chan, nskb)) 30710a708f8fSGustavo F. Padovan kfree_skb(nskb); 30720a708f8fSGustavo F. Padovan } 30733d57dc68SGustavo F. Padovan 30743df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 30750a708f8fSGustavo F. Padovan } 30760a708f8fSGustavo F. Padovan 30770a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */ 3078b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, 3079b4400672SAndrei Emeltchenko u8 ident, u16 dlen, void *data) 30800a708f8fSGustavo F. Padovan { 30810a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag; 30820a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd; 30830a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 30840a708f8fSGustavo F. Padovan int len, count; 30850a708f8fSGustavo F. Padovan 3086b4400672SAndrei Emeltchenko BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u", 30870a708f8fSGustavo F. Padovan conn, code, ident, dlen); 30880a708f8fSGustavo F. Padovan 3089300b962eSAnderson Lizardo if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE) 3090300b962eSAnderson Lizardo return NULL; 3091300b962eSAnderson Lizardo 30920a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; 30930a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 30940a708f8fSGustavo F. Padovan 30958bcde1f2SGustavo Padovan skb = bt_skb_alloc(count, GFP_KERNEL); 30960a708f8fSGustavo F. Padovan if (!skb) 30970a708f8fSGustavo F. Padovan return NULL; 30980a708f8fSGustavo F. Padovan 30990a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 31000a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); 31013300d9a9SClaudio Takahasi 31023300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 3103ac73498cSAndrei Emeltchenko lh->cid = __constant_cpu_to_le16(L2CAP_CID_LE_SIGNALING); 31043300d9a9SClaudio Takahasi else 3105ac73498cSAndrei Emeltchenko lh->cid = __constant_cpu_to_le16(L2CAP_CID_SIGNALING); 31060a708f8fSGustavo F. Padovan 31070a708f8fSGustavo F. Padovan cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); 31080a708f8fSGustavo F. Padovan cmd->code = code; 31090a708f8fSGustavo F. Padovan cmd->ident = ident; 31100a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen); 31110a708f8fSGustavo F. Padovan 31120a708f8fSGustavo F. Padovan if (dlen) { 31130a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE; 31140a708f8fSGustavo F. Padovan memcpy(skb_put(skb, count), data, count); 31150a708f8fSGustavo F. Padovan data += count; 31160a708f8fSGustavo F. Padovan } 31170a708f8fSGustavo F. Padovan 31180a708f8fSGustavo F. Padovan len -= skb->len; 31190a708f8fSGustavo F. Padovan 31200a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 31210a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 31220a708f8fSGustavo F. Padovan while (len) { 31230a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 31240a708f8fSGustavo F. Padovan 31258bcde1f2SGustavo Padovan *frag = bt_skb_alloc(count, GFP_KERNEL); 31260a708f8fSGustavo F. Padovan if (!*frag) 31270a708f8fSGustavo F. Padovan goto fail; 31280a708f8fSGustavo F. Padovan 31290a708f8fSGustavo F. Padovan memcpy(skb_put(*frag, count), data, count); 31300a708f8fSGustavo F. Padovan 31310a708f8fSGustavo F. Padovan len -= count; 31320a708f8fSGustavo F. Padovan data += count; 31330a708f8fSGustavo F. Padovan 31340a708f8fSGustavo F. Padovan frag = &(*frag)->next; 31350a708f8fSGustavo F. Padovan } 31360a708f8fSGustavo F. Padovan 31370a708f8fSGustavo F. Padovan return skb; 31380a708f8fSGustavo F. Padovan 31390a708f8fSGustavo F. Padovan fail: 31400a708f8fSGustavo F. Padovan kfree_skb(skb); 31410a708f8fSGustavo F. Padovan return NULL; 31420a708f8fSGustavo F. Padovan } 31430a708f8fSGustavo F. Padovan 31442d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, 31452d792818SGustavo Padovan unsigned long *val) 31460a708f8fSGustavo F. Padovan { 31470a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 31480a708f8fSGustavo F. Padovan int len; 31490a708f8fSGustavo F. Padovan 31500a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len; 31510a708f8fSGustavo F. Padovan *ptr += len; 31520a708f8fSGustavo F. Padovan 31530a708f8fSGustavo F. Padovan *type = opt->type; 31540a708f8fSGustavo F. Padovan *olen = opt->len; 31550a708f8fSGustavo F. Padovan 31560a708f8fSGustavo F. Padovan switch (opt->len) { 31570a708f8fSGustavo F. Padovan case 1: 31580a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val); 31590a708f8fSGustavo F. Padovan break; 31600a708f8fSGustavo F. Padovan 31610a708f8fSGustavo F. Padovan case 2: 31620a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val); 31630a708f8fSGustavo F. Padovan break; 31640a708f8fSGustavo F. Padovan 31650a708f8fSGustavo F. Padovan case 4: 31660a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val); 31670a708f8fSGustavo F. Padovan break; 31680a708f8fSGustavo F. Padovan 31690a708f8fSGustavo F. Padovan default: 31700a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val; 31710a708f8fSGustavo F. Padovan break; 31720a708f8fSGustavo F. Padovan } 31730a708f8fSGustavo F. Padovan 3174b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val); 31750a708f8fSGustavo F. Padovan return len; 31760a708f8fSGustavo F. Padovan } 31770a708f8fSGustavo F. Padovan 31780a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) 31790a708f8fSGustavo F. Padovan { 31800a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 31810a708f8fSGustavo F. Padovan 3182b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val); 31830a708f8fSGustavo F. Padovan 31840a708f8fSGustavo F. Padovan opt->type = type; 31850a708f8fSGustavo F. Padovan opt->len = len; 31860a708f8fSGustavo F. Padovan 31870a708f8fSGustavo F. Padovan switch (len) { 31880a708f8fSGustavo F. Padovan case 1: 31890a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val; 31900a708f8fSGustavo F. Padovan break; 31910a708f8fSGustavo F. Padovan 31920a708f8fSGustavo F. Padovan case 2: 31930a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val); 31940a708f8fSGustavo F. Padovan break; 31950a708f8fSGustavo F. Padovan 31960a708f8fSGustavo F. Padovan case 4: 31970a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val); 31980a708f8fSGustavo F. Padovan break; 31990a708f8fSGustavo F. Padovan 32000a708f8fSGustavo F. Padovan default: 32010a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len); 32020a708f8fSGustavo F. Padovan break; 32030a708f8fSGustavo F. Padovan } 32040a708f8fSGustavo F. Padovan 32050a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len; 32060a708f8fSGustavo F. Padovan } 32070a708f8fSGustavo F. Padovan 3208f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) 3209f89cef09SAndrei Emeltchenko { 3210f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs; 3211f89cef09SAndrei Emeltchenko 3212f89cef09SAndrei Emeltchenko switch (chan->mode) { 3213f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM: 3214f89cef09SAndrei Emeltchenko efs.id = chan->local_id; 3215f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype; 3216f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 3217f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 3218ac73498cSAndrei Emeltchenko efs.acc_lat = __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); 32198936fa6dSAndrei Emeltchenko efs.flush_to = __constant_cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO); 3220f89cef09SAndrei Emeltchenko break; 3221f89cef09SAndrei Emeltchenko 3222f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING: 3223f89cef09SAndrei Emeltchenko efs.id = 1; 3224f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT; 3225f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 3226f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 3227f89cef09SAndrei Emeltchenko efs.acc_lat = 0; 3228f89cef09SAndrei Emeltchenko efs.flush_to = 0; 3229f89cef09SAndrei Emeltchenko break; 3230f89cef09SAndrei Emeltchenko 3231f89cef09SAndrei Emeltchenko default: 3232f89cef09SAndrei Emeltchenko return; 3233f89cef09SAndrei Emeltchenko } 3234f89cef09SAndrei Emeltchenko 3235f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), 3236f89cef09SAndrei Emeltchenko (unsigned long) &efs); 3237f89cef09SAndrei Emeltchenko } 3238f89cef09SAndrei Emeltchenko 3239721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work) 32400a708f8fSGustavo F. Padovan { 3241721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 3242721c4181SGustavo F. Padovan ack_timer.work); 32430362520bSMat Martineau u16 frames_to_ack; 32440a708f8fSGustavo F. Padovan 32452fb9b3d4SGustavo F. Padovan BT_DBG("chan %p", chan); 32462fb9b3d4SGustavo F. Padovan 32476be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 32486be36555SAndrei Emeltchenko 32490362520bSMat Martineau frames_to_ack = __seq_offset(chan, chan->buffer_seq, 32500362520bSMat Martineau chan->last_acked_seq); 32510362520bSMat Martineau 32520362520bSMat Martineau if (frames_to_ack) 32530362520bSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 32546be36555SAndrei Emeltchenko 32556be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 325609bfb2eeSSzymon Janc l2cap_chan_put(chan); 32570a708f8fSGustavo F. Padovan } 32580a708f8fSGustavo F. Padovan 3259466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan) 32600a708f8fSGustavo F. Padovan { 32613c588192SMat Martineau int err; 32623c588192SMat Martineau 3263105bdf9eSMat Martineau chan->next_tx_seq = 0; 3264105bdf9eSMat Martineau chan->expected_tx_seq = 0; 326542e5c802SGustavo F. Padovan chan->expected_ack_seq = 0; 32666a026610SGustavo F. Padovan chan->unacked_frames = 0; 326742e5c802SGustavo F. Padovan chan->buffer_seq = 0; 32686a026610SGustavo F. Padovan chan->frames_sent = 0; 3269105bdf9eSMat Martineau chan->last_acked_seq = 0; 3270105bdf9eSMat Martineau chan->sdu = NULL; 3271105bdf9eSMat Martineau chan->sdu_last_frag = NULL; 3272105bdf9eSMat Martineau chan->sdu_len = 0; 3273105bdf9eSMat Martineau 3274d34c34fbSMat Martineau skb_queue_head_init(&chan->tx_q); 3275d34c34fbSMat Martineau 32766ed971caSMarcel Holtmann chan->local_amp_id = AMP_ID_BREDR; 32776ed971caSMarcel Holtmann chan->move_id = AMP_ID_BREDR; 327808333283SMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 327908333283SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 328008333283SMat Martineau 3281105bdf9eSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 3282105bdf9eSMat Martineau return 0; 3283105bdf9eSMat Martineau 3284105bdf9eSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 3285105bdf9eSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 32860a708f8fSGustavo F. Padovan 3287721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout); 3288721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout); 3289721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout); 32900a708f8fSGustavo F. Padovan 3291f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q); 32920a708f8fSGustavo F. Padovan 32933c588192SMat Martineau err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win); 32943c588192SMat Martineau if (err < 0) 32953c588192SMat Martineau return err; 32963c588192SMat Martineau 32979dc9affcSMat Martineau err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win); 32989dc9affcSMat Martineau if (err < 0) 32999dc9affcSMat Martineau l2cap_seq_list_free(&chan->srej_list); 33009dc9affcSMat Martineau 33019dc9affcSMat Martineau return err; 33020a708f8fSGustavo F. Padovan } 33030a708f8fSGustavo F. Padovan 33040a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) 33050a708f8fSGustavo F. Padovan { 33060a708f8fSGustavo F. Padovan switch (mode) { 33070a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 33080a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 33090a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask)) 33100a708f8fSGustavo F. Padovan return mode; 33110a708f8fSGustavo F. Padovan /* fall through */ 33120a708f8fSGustavo F. Padovan default: 33130a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC; 33140a708f8fSGustavo F. Padovan } 33150a708f8fSGustavo F. Padovan } 33160a708f8fSGustavo F. Padovan 3317848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn) 33186327eb98SAndrei Emeltchenko { 3319848566b3SMarcel Holtmann return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_WINDOW; 33206327eb98SAndrei Emeltchenko } 33216327eb98SAndrei Emeltchenko 3322848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn) 3323f89cef09SAndrei Emeltchenko { 3324848566b3SMarcel Holtmann return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_FLOW; 3325f89cef09SAndrei Emeltchenko } 3326f89cef09SAndrei Emeltchenko 332736c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan, 332836c86c85SMat Martineau struct l2cap_conf_rfc *rfc) 332936c86c85SMat Martineau { 33306ed971caSMarcel Holtmann if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) { 333136c86c85SMat Martineau u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to; 333236c86c85SMat Martineau 333336c86c85SMat Martineau /* Class 1 devices have must have ERTM timeouts 333436c86c85SMat Martineau * exceeding the Link Supervision Timeout. The 333536c86c85SMat Martineau * default Link Supervision Timeout for AMP 333636c86c85SMat Martineau * controllers is 10 seconds. 333736c86c85SMat Martineau * 333836c86c85SMat Martineau * Class 1 devices use 0xffffffff for their 333936c86c85SMat Martineau * best-effort flush timeout, so the clamping logic 334036c86c85SMat Martineau * will result in a timeout that meets the above 334136c86c85SMat Martineau * requirement. ERTM timeouts are 16-bit values, so 334236c86c85SMat Martineau * the maximum timeout is 65.535 seconds. 334336c86c85SMat Martineau */ 334436c86c85SMat Martineau 334536c86c85SMat Martineau /* Convert timeout to milliseconds and round */ 334636c86c85SMat Martineau ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000); 334736c86c85SMat Martineau 334836c86c85SMat Martineau /* This is the recommended formula for class 2 devices 334936c86c85SMat Martineau * that start ERTM timers when packets are sent to the 335036c86c85SMat Martineau * controller. 335136c86c85SMat Martineau */ 335236c86c85SMat Martineau ertm_to = 3 * ertm_to + 500; 335336c86c85SMat Martineau 335436c86c85SMat Martineau if (ertm_to > 0xffff) 335536c86c85SMat Martineau ertm_to = 0xffff; 335636c86c85SMat Martineau 335736c86c85SMat Martineau rfc->retrans_timeout = cpu_to_le16((u16) ertm_to); 335836c86c85SMat Martineau rfc->monitor_timeout = rfc->retrans_timeout; 335936c86c85SMat Martineau } else { 336036c86c85SMat Martineau rfc->retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 336136c86c85SMat Martineau rfc->monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 336236c86c85SMat Martineau } 336336c86c85SMat Martineau } 336436c86c85SMat Martineau 33656327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan) 33666327eb98SAndrei Emeltchenko { 33676327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && 3368848566b3SMarcel Holtmann __l2cap_ews_supported(chan->conn)) { 33696327eb98SAndrei Emeltchenko /* use extended control field */ 33706327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 3371836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 3372836be934SAndrei Emeltchenko } else { 33736327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win, 33746327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 3375836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 3376836be934SAndrei Emeltchenko } 3377c20f8e35SMat Martineau chan->ack_win = chan->tx_win; 33786327eb98SAndrei Emeltchenko } 33796327eb98SAndrei Emeltchenko 3380710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) 33810a708f8fSGustavo F. Padovan { 33820a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 33830c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode }; 33840a708f8fSGustavo F. Padovan void *ptr = req->data; 3385c8f79162SAndrei Emeltchenko u16 size; 33860a708f8fSGustavo F. Padovan 338749208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 33880a708f8fSGustavo F. Padovan 338973ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp) 33900a708f8fSGustavo F. Padovan goto done; 33910a708f8fSGustavo F. Padovan 33920c1bc5c6SGustavo F. Padovan switch (chan->mode) { 33930a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 33940a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3395c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) 33960a708f8fSGustavo F. Padovan break; 33970a708f8fSGustavo F. Padovan 3398848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn)) 3399f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 3400f89cef09SAndrei Emeltchenko 34010a708f8fSGustavo F. Padovan /* fall through */ 34020a708f8fSGustavo F. Padovan default: 34038c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); 34040a708f8fSGustavo F. Padovan break; 34050a708f8fSGustavo F. Padovan } 34060a708f8fSGustavo F. Padovan 34070a708f8fSGustavo F. Padovan done: 34080c1bc5c6SGustavo F. Padovan if (chan->imtu != L2CAP_DEFAULT_MTU) 34090c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 34100a708f8fSGustavo F. Padovan 34110c1bc5c6SGustavo F. Padovan switch (chan->mode) { 34120a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 34138c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && 34148c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) 34150a708f8fSGustavo F. Padovan break; 34160a708f8fSGustavo F. Padovan 34170a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC; 34180a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 34190a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 34200a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 34210a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 34220a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0; 34230a708f8fSGustavo F. Padovan 34240a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 34250a708f8fSGustavo F. Padovan (unsigned long) &rfc); 34260a708f8fSGustavo F. Padovan break; 34270a708f8fSGustavo F. Padovan 34280a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 34290a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM; 343047d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx; 343136c86c85SMat Martineau 343236c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc); 3433c8f79162SAndrei Emeltchenko 3434c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 34352d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - 3436c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3437c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 34380a708f8fSGustavo F. Padovan 34396327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan); 34406327eb98SAndrei Emeltchenko 34416327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win, 34426327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 34430a708f8fSGustavo F. Padovan 34440a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 34450a708f8fSGustavo F. Padovan (unsigned long) &rfc); 34460a708f8fSGustavo F. Padovan 3447f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 3448f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 3449f89cef09SAndrei Emeltchenko 34506327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 34516327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 34526327eb98SAndrei Emeltchenko chan->tx_win); 345360918918SAndrei Emeltchenko 345460918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS) 345560918918SAndrei Emeltchenko if (chan->fcs == L2CAP_FCS_NONE || 3456f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { 345760918918SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 345860918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, 345960918918SAndrei Emeltchenko chan->fcs); 346060918918SAndrei Emeltchenko } 34610a708f8fSGustavo F. Padovan break; 34620a708f8fSGustavo F. Padovan 34630a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3464273759e2SMat Martineau l2cap_txwin_setup(chan); 34650a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING; 34660a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 34670a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 34680a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 34690a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 3470c8f79162SAndrei Emeltchenko 3471c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 34722d792818SGustavo Padovan L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - 3473c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3474c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 34750a708f8fSGustavo F. Padovan 34760a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 34770a708f8fSGustavo F. Padovan (unsigned long) &rfc); 34780a708f8fSGustavo F. Padovan 3479f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 3480f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 3481f89cef09SAndrei Emeltchenko 348260918918SAndrei Emeltchenko if (chan->conn->feat_mask & L2CAP_FEAT_FCS) 348347d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 3484f2592d3eSAndrei Emeltchenko test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { 348547d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 348660918918SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, 348760918918SAndrei Emeltchenko chan->fcs); 34880a708f8fSGustavo F. Padovan } 34890a708f8fSGustavo F. Padovan break; 34900a708f8fSGustavo F. Padovan } 34910a708f8fSGustavo F. Padovan 3492fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 349359e54bd1SAndrei Emeltchenko req->flags = __constant_cpu_to_le16(0); 34940a708f8fSGustavo F. Padovan 34950a708f8fSGustavo F. Padovan return ptr - data; 34960a708f8fSGustavo F. Padovan } 34970a708f8fSGustavo F. Padovan 349873ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) 34990a708f8fSGustavo F. Padovan { 35000a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 35010a708f8fSGustavo F. Padovan void *ptr = rsp->data; 350273ffa904SGustavo F. Padovan void *req = chan->conf_req; 350373ffa904SGustavo F. Padovan int len = chan->conf_len; 35040a708f8fSGustavo F. Padovan int type, hint, olen; 35050a708f8fSGustavo F. Padovan unsigned long val; 35060a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 350742dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs; 350842dceae2SAndrei Emeltchenko u8 remote_efs = 0; 35090a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU; 35100a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS; 3511c8f79162SAndrei Emeltchenko u16 size; 35120a708f8fSGustavo F. Padovan 351373ffa904SGustavo F. Padovan BT_DBG("chan %p", chan); 35140a708f8fSGustavo F. Padovan 35150a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 35160a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val); 35170a708f8fSGustavo F. Padovan 35180a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT; 35190a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK; 35200a708f8fSGustavo F. Padovan 35210a708f8fSGustavo F. Padovan switch (type) { 35220a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 35230a708f8fSGustavo F. Padovan mtu = val; 35240a708f8fSGustavo F. Padovan break; 35250a708f8fSGustavo F. Padovan 35260a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 35270c1bc5c6SGustavo F. Padovan chan->flush_to = val; 35280a708f8fSGustavo F. Padovan break; 35290a708f8fSGustavo F. Padovan 35300a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS: 35310a708f8fSGustavo F. Padovan break; 35320a708f8fSGustavo F. Padovan 35330a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 35340a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 35350a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen); 35360a708f8fSGustavo F. Padovan break; 35370a708f8fSGustavo F. Padovan 35380a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS: 35390a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE) 3540f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, &chan->conf_state); 354142dceae2SAndrei Emeltchenko break; 35420a708f8fSGustavo F. Padovan 354342dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS: 354442dceae2SAndrei Emeltchenko remote_efs = 1; 354542dceae2SAndrei Emeltchenko if (olen == sizeof(efs)) 354642dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen); 35470a708f8fSGustavo F. Padovan break; 35480a708f8fSGustavo F. Padovan 35496327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 3550848566b3SMarcel Holtmann if (!chan->conn->hs_enabled) 35516327eb98SAndrei Emeltchenko return -ECONNREFUSED; 35526327eb98SAndrei Emeltchenko 35536327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 35546327eb98SAndrei Emeltchenko set_bit(CONF_EWS_RECV, &chan->conf_state); 3555836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 35566327eb98SAndrei Emeltchenko chan->remote_tx_win = val; 35570a708f8fSGustavo F. Padovan break; 35580a708f8fSGustavo F. Padovan 35590a708f8fSGustavo F. Padovan default: 35600a708f8fSGustavo F. Padovan if (hint) 35610a708f8fSGustavo F. Padovan break; 35620a708f8fSGustavo F. Padovan 35630a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN; 35640a708f8fSGustavo F. Padovan *((u8 *) ptr++) = type; 35650a708f8fSGustavo F. Padovan break; 35660a708f8fSGustavo F. Padovan } 35670a708f8fSGustavo F. Padovan } 35680a708f8fSGustavo F. Padovan 356973ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1) 35700a708f8fSGustavo F. Padovan goto done; 35710a708f8fSGustavo F. Padovan 35720c1bc5c6SGustavo F. Padovan switch (chan->mode) { 35730a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 35740a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3575c1360a1cSGustavo F. Padovan if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { 35760c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, 35778c1d787bSGustavo F. Padovan chan->conn->feat_mask); 35780a708f8fSGustavo F. Padovan break; 35790a708f8fSGustavo F. Padovan } 35800a708f8fSGustavo F. Padovan 358142dceae2SAndrei Emeltchenko if (remote_efs) { 3582848566b3SMarcel Holtmann if (__l2cap_efs_supported(chan->conn)) 358342dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 358442dceae2SAndrei Emeltchenko else 358542dceae2SAndrei Emeltchenko return -ECONNREFUSED; 358642dceae2SAndrei Emeltchenko } 358742dceae2SAndrei Emeltchenko 35880c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) 35890a708f8fSGustavo F. Padovan return -ECONNREFUSED; 35900a708f8fSGustavo F. Padovan 35910a708f8fSGustavo F. Padovan break; 35920a708f8fSGustavo F. Padovan } 35930a708f8fSGustavo F. Padovan 35940a708f8fSGustavo F. Padovan done: 35950c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) { 35960a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 35970c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 35980a708f8fSGustavo F. Padovan 359973ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1) 36000a708f8fSGustavo F. Padovan return -ECONNREFUSED; 36010a708f8fSGustavo F. Padovan 36022d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 36032d792818SGustavo Padovan (unsigned long) &rfc); 36040a708f8fSGustavo F. Padovan } 36050a708f8fSGustavo F. Padovan 36060a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) { 36070a708f8fSGustavo F. Padovan /* Configure output options and let the other side know 36080a708f8fSGustavo F. Padovan * which ones we don't like. */ 36090a708f8fSGustavo F. Padovan 36100a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU) 36110a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 36120a708f8fSGustavo F. Padovan else { 36130c1bc5c6SGustavo F. Padovan chan->omtu = mtu; 3614c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state); 36150a708f8fSGustavo F. Padovan } 36160c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); 36170a708f8fSGustavo F. Padovan 361842dceae2SAndrei Emeltchenko if (remote_efs) { 361942dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 362042dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 362142dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) { 362242dceae2SAndrei Emeltchenko 362342dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT; 362442dceae2SAndrei Emeltchenko 362542dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1) 362642dceae2SAndrei Emeltchenko return -ECONNREFUSED; 362742dceae2SAndrei Emeltchenko 362842dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 362942dceae2SAndrei Emeltchenko sizeof(efs), 363042dceae2SAndrei Emeltchenko (unsigned long) &efs); 36310e8b207eSAndrei Emeltchenko } else { 36323e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */ 36330e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING; 36340e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 363542dceae2SAndrei Emeltchenko } 363642dceae2SAndrei Emeltchenko } 363742dceae2SAndrei Emeltchenko 36380a708f8fSGustavo F. Padovan switch (rfc.mode) { 36390a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 364047d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3641c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 36420a708f8fSGustavo F. Padovan break; 36430a708f8fSGustavo F. Padovan 36440a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 36456327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state)) 36462c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size; 36476327eb98SAndrei Emeltchenko else 36486327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; 36496327eb98SAndrei Emeltchenko 36502c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit; 36510a708f8fSGustavo F. Padovan 3652c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 36532d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE - 36542d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); 3655c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3656c8f79162SAndrei Emeltchenko chan->remote_mps = size; 36570a708f8fSGustavo F. Padovan 365836c86c85SMat Martineau __l2cap_set_ertm_timeouts(chan, &rfc); 36590a708f8fSGustavo F. Padovan 3660c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 36610a708f8fSGustavo F. Padovan 36620a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 36630a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 36640a708f8fSGustavo F. Padovan 366542dceae2SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 366642dceae2SAndrei Emeltchenko chan->remote_id = efs.id; 366742dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype; 366842dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu); 366942dceae2SAndrei Emeltchenko chan->remote_flush_to = 367042dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to); 367142dceae2SAndrei Emeltchenko chan->remote_acc_lat = 367242dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat); 367342dceae2SAndrei Emeltchenko chan->remote_sdu_itime = 367442dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 367542dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 36762d792818SGustavo Padovan sizeof(efs), 36772d792818SGustavo Padovan (unsigned long) &efs); 367842dceae2SAndrei Emeltchenko } 36790a708f8fSGustavo F. Padovan break; 36800a708f8fSGustavo F. Padovan 36810a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3682c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 36832d792818SGustavo Padovan chan->conn->mtu - L2CAP_EXT_HDR_SIZE - 36842d792818SGustavo Padovan L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); 3685c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3686c8f79162SAndrei Emeltchenko chan->remote_mps = size; 36870a708f8fSGustavo F. Padovan 3688c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 36890a708f8fSGustavo F. Padovan 36902d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 36912d792818SGustavo Padovan (unsigned long) &rfc); 36920a708f8fSGustavo F. Padovan 36930a708f8fSGustavo F. Padovan break; 36940a708f8fSGustavo F. Padovan 36950a708f8fSGustavo F. Padovan default: 36960a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 36970a708f8fSGustavo F. Padovan 36980a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc)); 36990c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 37000a708f8fSGustavo F. Padovan } 37010a708f8fSGustavo F. Padovan 37020a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) 3703c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 37040a708f8fSGustavo F. Padovan } 3705fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 37060a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 370759e54bd1SAndrei Emeltchenko rsp->flags = __constant_cpu_to_le16(0); 37080a708f8fSGustavo F. Padovan 37090a708f8fSGustavo F. Padovan return ptr - data; 37100a708f8fSGustavo F. Padovan } 37110a708f8fSGustavo F. Padovan 37122d792818SGustavo Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, 37132d792818SGustavo Padovan void *data, u16 *result) 37140a708f8fSGustavo F. Padovan { 37150a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 37160a708f8fSGustavo F. Padovan void *ptr = req->data; 37170a708f8fSGustavo F. Padovan int type, olen; 37180a708f8fSGustavo F. Padovan unsigned long val; 371936e999a8SMat Martineau struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 372066af7aafSAndrei Emeltchenko struct l2cap_conf_efs efs; 37210a708f8fSGustavo F. Padovan 3722fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); 37230a708f8fSGustavo F. Padovan 37240a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 37250a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 37260a708f8fSGustavo F. Padovan 37270a708f8fSGustavo F. Padovan switch (type) { 37280a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 37290a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) { 37300a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT; 37310c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU; 37320a708f8fSGustavo F. Padovan } else 37330c1bc5c6SGustavo F. Padovan chan->imtu = val; 37340c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 37350a708f8fSGustavo F. Padovan break; 37360a708f8fSGustavo F. Padovan 37370a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 37380c1bc5c6SGustavo F. Padovan chan->flush_to = val; 37390a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 37400c1bc5c6SGustavo F. Padovan 2, chan->flush_to); 37410a708f8fSGustavo F. Padovan break; 37420a708f8fSGustavo F. Padovan 37430a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 37440a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 37450a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 37460a708f8fSGustavo F. Padovan 3747c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && 37480c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode) 37490a708f8fSGustavo F. Padovan return -ECONNREFUSED; 37500a708f8fSGustavo F. Padovan 375147d1ec61SGustavo F. Padovan chan->fcs = 0; 37520a708f8fSGustavo F. Padovan 37530a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 37540a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 37550a708f8fSGustavo F. Padovan break; 37566327eb98SAndrei Emeltchenko 37576327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 3758c20f8e35SMat Martineau chan->ack_win = min_t(u16, val, chan->ack_win); 37593e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 37603e6b3b95SGustavo F. Padovan chan->tx_win); 37616327eb98SAndrei Emeltchenko break; 376266af7aafSAndrei Emeltchenko 376366af7aafSAndrei Emeltchenko case L2CAP_CONF_EFS: 376466af7aafSAndrei Emeltchenko if (olen == sizeof(efs)) 376566af7aafSAndrei Emeltchenko memcpy(&efs, (void *)val, olen); 376666af7aafSAndrei Emeltchenko 376766af7aafSAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 376866af7aafSAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 376966af7aafSAndrei Emeltchenko efs.stype != chan->local_stype) 377066af7aafSAndrei Emeltchenko return -ECONNREFUSED; 377166af7aafSAndrei Emeltchenko 37722d792818SGustavo Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), 37732d792818SGustavo Padovan (unsigned long) &efs); 377466af7aafSAndrei Emeltchenko break; 3775cbabee78SAndrei Emeltchenko 3776cbabee78SAndrei Emeltchenko case L2CAP_CONF_FCS: 3777cbabee78SAndrei Emeltchenko if (*result == L2CAP_CONF_PENDING) 3778cbabee78SAndrei Emeltchenko if (val == L2CAP_FCS_NONE) 3779f2592d3eSAndrei Emeltchenko set_bit(CONF_RECV_NO_FCS, 3780cbabee78SAndrei Emeltchenko &chan->conf_state); 3781cbabee78SAndrei Emeltchenko break; 37820a708f8fSGustavo F. Padovan } 37830a708f8fSGustavo F. Padovan } 37840a708f8fSGustavo F. Padovan 37850c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) 37860a708f8fSGustavo F. Padovan return -ECONNREFUSED; 37870a708f8fSGustavo F. Padovan 37880c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode; 37890a708f8fSGustavo F. Padovan 37900e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) { 37910a708f8fSGustavo F. Padovan switch (rfc.mode) { 37920a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 379347d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 379447d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 379547d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 3796c20f8e35SMat Martineau if (!test_bit(FLAG_EXT_CTRL, &chan->flags)) 3797c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 3798c20f8e35SMat Martineau rfc.txwin_size); 379966af7aafSAndrei Emeltchenko 380066af7aafSAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 380166af7aafSAndrei Emeltchenko chan->local_msdu = le16_to_cpu(efs.msdu); 380266af7aafSAndrei Emeltchenko chan->local_sdu_itime = 380366af7aafSAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 380466af7aafSAndrei Emeltchenko chan->local_acc_lat = le32_to_cpu(efs.acc_lat); 380566af7aafSAndrei Emeltchenko chan->local_flush_to = 380666af7aafSAndrei Emeltchenko le32_to_cpu(efs.flush_to); 380766af7aafSAndrei Emeltchenko } 38080a708f8fSGustavo F. Padovan break; 380966af7aafSAndrei Emeltchenko 38100a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 381147d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 38120a708f8fSGustavo F. Padovan } 38130a708f8fSGustavo F. Padovan } 38140a708f8fSGustavo F. Padovan 3815fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 381659e54bd1SAndrei Emeltchenko req->flags = __constant_cpu_to_le16(0); 38170a708f8fSGustavo F. Padovan 38180a708f8fSGustavo F. Padovan return ptr - data; 38190a708f8fSGustavo F. Padovan } 38200a708f8fSGustavo F. Padovan 38212d792818SGustavo Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, 38222d792818SGustavo Padovan u16 result, u16 flags) 38230a708f8fSGustavo F. Padovan { 38240a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 38250a708f8fSGustavo F. Padovan void *ptr = rsp->data; 38260a708f8fSGustavo F. Padovan 3827fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan); 38280a708f8fSGustavo F. Padovan 3829fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 38300a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 38310a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags); 38320a708f8fSGustavo F. Padovan 38330a708f8fSGustavo F. Padovan return ptr - data; 38340a708f8fSGustavo F. Padovan } 38350a708f8fSGustavo F. Padovan 383627e2d4c8SJohan Hedberg void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan) 383727e2d4c8SJohan Hedberg { 383827e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 383927e2d4c8SJohan Hedberg struct l2cap_conn *conn = chan->conn; 384027e2d4c8SJohan Hedberg 384127e2d4c8SJohan Hedberg BT_DBG("chan %p", chan); 384227e2d4c8SJohan Hedberg 384327e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(chan->scid); 384427e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 38453916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps); 38460cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(chan->rx_credits); 384727e2d4c8SJohan Hedberg rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 384827e2d4c8SJohan Hedberg 384927e2d4c8SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), 385027e2d4c8SJohan Hedberg &rsp); 385127e2d4c8SJohan Hedberg } 385227e2d4c8SJohan Hedberg 38538c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) 3854710f9b0aSGustavo F. Padovan { 3855710f9b0aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 38568c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 3857710f9b0aSGustavo F. Padovan u8 buf[128]; 3858439f34acSAndrei Emeltchenko u8 rsp_code; 3859710f9b0aSGustavo F. Padovan 3860fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 3861fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3862ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 3863ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 3864439f34acSAndrei Emeltchenko 3865439f34acSAndrei Emeltchenko if (chan->hs_hcon) 3866439f34acSAndrei Emeltchenko rsp_code = L2CAP_CREATE_CHAN_RSP; 3867439f34acSAndrei Emeltchenko else 3868439f34acSAndrei Emeltchenko rsp_code = L2CAP_CONN_RSP; 3869439f34acSAndrei Emeltchenko 3870439f34acSAndrei Emeltchenko BT_DBG("chan %p rsp_code %u", chan, rsp_code); 3871439f34acSAndrei Emeltchenko 3872439f34acSAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp); 3873710f9b0aSGustavo F. Padovan 3874c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 3875710f9b0aSGustavo F. Padovan return; 3876710f9b0aSGustavo F. Padovan 3877710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 3878710f9b0aSGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 3879710f9b0aSGustavo F. Padovan chan->num_conf_req++; 3880710f9b0aSGustavo F. Padovan } 3881710f9b0aSGustavo F. Padovan 388247d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) 38830a708f8fSGustavo F. Padovan { 38840a708f8fSGustavo F. Padovan int type, olen; 38850a708f8fSGustavo F. Padovan unsigned long val; 3886c20f8e35SMat Martineau /* Use sane default values in case a misbehaving remote device 3887c20f8e35SMat Martineau * did not send an RFC or extended window size option. 3888c20f8e35SMat Martineau */ 3889c20f8e35SMat Martineau u16 txwin_ext = chan->ack_win; 3890c20f8e35SMat Martineau struct l2cap_conf_rfc rfc = { 3891c20f8e35SMat Martineau .mode = chan->mode, 3892c20f8e35SMat Martineau .retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO), 3893c20f8e35SMat Martineau .monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO), 3894c20f8e35SMat Martineau .max_pdu_size = cpu_to_le16(chan->imtu), 3895c20f8e35SMat Martineau .txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW), 3896c20f8e35SMat Martineau }; 38970a708f8fSGustavo F. Padovan 389847d1ec61SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); 38990a708f8fSGustavo F. Padovan 39000c1bc5c6SGustavo F. Padovan if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) 39010a708f8fSGustavo F. Padovan return; 39020a708f8fSGustavo F. Padovan 39030a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 39040a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 39050a708f8fSGustavo F. Padovan 3906c20f8e35SMat Martineau switch (type) { 3907c20f8e35SMat Martineau case L2CAP_CONF_RFC: 3908c20f8e35SMat Martineau if (olen == sizeof(rfc)) 39090a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 3910c20f8e35SMat Martineau break; 3911c20f8e35SMat Martineau case L2CAP_CONF_EWS: 3912c20f8e35SMat Martineau txwin_ext = val; 3913c20f8e35SMat Martineau break; 3914c20f8e35SMat Martineau } 39150a708f8fSGustavo F. Padovan } 39160a708f8fSGustavo F. Padovan 39170a708f8fSGustavo F. Padovan switch (rfc.mode) { 39180a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 391947d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 392047d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 392147d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 3922c20f8e35SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 3923c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, txwin_ext); 3924c20f8e35SMat Martineau else 3925c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 3926c20f8e35SMat Martineau rfc.txwin_size); 39270a708f8fSGustavo F. Padovan break; 39280a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 392947d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 39300a708f8fSGustavo F. Padovan } 39310a708f8fSGustavo F. Padovan } 39320a708f8fSGustavo F. Padovan 39332d792818SGustavo Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, 3934cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 3935cb3b3152SJohan Hedberg u8 *data) 39360a708f8fSGustavo F. Padovan { 3937e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 39380a708f8fSGustavo F. Padovan 3939cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rej)) 3940cb3b3152SJohan Hedberg return -EPROTO; 3941cb3b3152SJohan Hedberg 3942e2fd318eSIlia Kolomisnky if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) 39430a708f8fSGustavo F. Padovan return 0; 39440a708f8fSGustavo F. Padovan 39450a708f8fSGustavo F. Padovan if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && 39460a708f8fSGustavo F. Padovan cmd->ident == conn->info_ident) { 394717cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 39480a708f8fSGustavo F. Padovan 39490a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 39500a708f8fSGustavo F. Padovan conn->info_ident = 0; 39510a708f8fSGustavo F. Padovan 39520a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 39530a708f8fSGustavo F. Padovan } 39540a708f8fSGustavo F. Padovan 39550a708f8fSGustavo F. Padovan return 0; 39560a708f8fSGustavo F. Padovan } 39570a708f8fSGustavo F. Padovan 39581700915fSMat Martineau static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, 39591700915fSMat Martineau struct l2cap_cmd_hdr *cmd, 39604c89b6aaSMat Martineau u8 *data, u8 rsp_code, u8 amp_id) 39610a708f8fSGustavo F. Padovan { 39620a708f8fSGustavo F. Padovan struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 39630a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 396423691d75SGustavo F. Padovan struct l2cap_chan *chan = NULL, *pchan; 39650a708f8fSGustavo F. Padovan int result, status = L2CAP_CS_NO_INFO; 39660a708f8fSGustavo F. Padovan 39670a708f8fSGustavo F. Padovan u16 dcid = 0, scid = __le16_to_cpu(req->scid); 39680a708f8fSGustavo F. Padovan __le16 psm = req->psm; 39690a708f8fSGustavo F. Padovan 3970097db76cSAndrei Emeltchenko BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); 39710a708f8fSGustavo F. Padovan 39720a708f8fSGustavo F. Padovan /* Check if we have socket listening on psm */ 39736f59b904SMarcel Holtmann pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 3974bf20fd4eSJohan Hedberg &conn->hcon->dst, ACL_LINK); 397523691d75SGustavo F. Padovan if (!pchan) { 39760a708f8fSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 39770a708f8fSGustavo F. Padovan goto sendresp; 39780a708f8fSGustavo F. Padovan } 39790a708f8fSGustavo F. Padovan 39803df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 39818ffb9290SGustavo Padovan l2cap_chan_lock(pchan); 39820a708f8fSGustavo F. Padovan 39830a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */ 39842983fd68SAndrei Emeltchenko if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) && 39850a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) { 39869f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_AUTH_FAILURE; 39870a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 39880a708f8fSGustavo F. Padovan goto response; 39890a708f8fSGustavo F. Padovan } 39900a708f8fSGustavo F. Padovan 39910a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM; 39920a708f8fSGustavo F. Padovan 39932dfa1003SGustavo Padovan /* Check if we already have channel with that dcid */ 39942dfa1003SGustavo Padovan if (__l2cap_get_chan_by_dcid(conn, scid)) 39952dfa1003SGustavo Padovan goto response; 39962dfa1003SGustavo Padovan 399780b98027SGustavo Padovan chan = pchan->ops->new_connection(pchan); 399880808e43SGustavo F. Padovan if (!chan) 39990a708f8fSGustavo F. Padovan goto response; 40000a708f8fSGustavo F. Padovan 4001330b6c15SSyam Sidhardhan /* For certain devices (ex: HID mouse), support for authentication, 4002330b6c15SSyam Sidhardhan * pairing and bonding is optional. For such devices, inorder to avoid 4003330b6c15SSyam Sidhardhan * the ACL alive for too long after L2CAP disconnection, reset the ACL 4004330b6c15SSyam Sidhardhan * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect. 4005330b6c15SSyam Sidhardhan */ 4006330b6c15SSyam Sidhardhan conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 4007330b6c15SSyam Sidhardhan 40087eafc59eSMarcel Holtmann bacpy(&chan->src, &conn->hcon->src); 40097eafc59eSMarcel Holtmann bacpy(&chan->dst, &conn->hcon->dst); 40104f1654e0SMarcel Holtmann chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type); 40114f1654e0SMarcel Holtmann chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type); 4012fe4128e0SGustavo F. Padovan chan->psm = psm; 4013fe4128e0SGustavo F. Padovan chan->dcid = scid; 40141700915fSMat Martineau chan->local_amp_id = amp_id; 40150a708f8fSGustavo F. Padovan 40166be36555SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 401748454079SGustavo F. Padovan 4018fe4128e0SGustavo F. Padovan dcid = chan->scid; 40190a708f8fSGustavo F. Padovan 40208d836d71SGustavo Padovan __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 40210a708f8fSGustavo F. Padovan 4022fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident; 40230a708f8fSGustavo F. Padovan 40240a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { 4025d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 4026bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 4027f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 40280a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 40290a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND; 40302dc4e510SGustavo Padovan chan->ops->defer(chan); 40310a708f8fSGustavo F. Padovan } else { 40321700915fSMat Martineau /* Force pending result for AMP controllers. 40331700915fSMat Martineau * The connection will succeed after the 40341700915fSMat Martineau * physical link is up. 40351700915fSMat Martineau */ 40366ed971caSMarcel Holtmann if (amp_id == AMP_ID_BREDR) { 4037f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 40380a708f8fSGustavo F. Padovan result = L2CAP_CR_SUCCESS; 40396ed971caSMarcel Holtmann } else { 4040f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 40416ed971caSMarcel Holtmann result = L2CAP_CR_PEND; 40421700915fSMat Martineau } 40430a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 40440a708f8fSGustavo F. Padovan } 40450a708f8fSGustavo F. Padovan } else { 4046f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 40470a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 40480a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND; 40490a708f8fSGustavo F. Padovan } 40500a708f8fSGustavo F. Padovan } else { 4051f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONNECT2); 40520a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 40530a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 40540a708f8fSGustavo F. Padovan } 40550a708f8fSGustavo F. Padovan 40560a708f8fSGustavo F. Padovan response: 40578ffb9290SGustavo Padovan l2cap_chan_unlock(pchan); 40583df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 40590a708f8fSGustavo F. Padovan 40600a708f8fSGustavo F. Padovan sendresp: 40610a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid); 40620a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid); 40630a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result); 40640a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status); 40654c89b6aaSMat Martineau l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp); 40660a708f8fSGustavo F. Padovan 40670a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { 40680a708f8fSGustavo F. Padovan struct l2cap_info_req info; 4069ac73498cSAndrei Emeltchenko info.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); 40700a708f8fSGustavo F. Padovan 40710a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 40720a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 40730a708f8fSGustavo F. Padovan 4074ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 40750a708f8fSGustavo F. Padovan 40762d792818SGustavo Padovan l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, 40772d792818SGustavo Padovan sizeof(info), &info); 40780a708f8fSGustavo F. Padovan } 40790a708f8fSGustavo F. Padovan 4080c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && 40810a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) { 40820a708f8fSGustavo F. Padovan u8 buf[128]; 4083c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 40840a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 408573ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 408673ffa904SGustavo F. Padovan chan->num_conf_req++; 40870a708f8fSGustavo F. Padovan } 40881700915fSMat Martineau 40891700915fSMat Martineau return chan; 40904c89b6aaSMat Martineau } 40910a708f8fSGustavo F. Padovan 40924c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn, 4093cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 40944c89b6aaSMat Martineau { 40957b064edaSJaganath Kanakkassery struct hci_dev *hdev = conn->hcon->hdev; 40967b064edaSJaganath Kanakkassery struct hci_conn *hcon = conn->hcon; 40977b064edaSJaganath Kanakkassery 4098cb3b3152SJohan Hedberg if (cmd_len < sizeof(struct l2cap_conn_req)) 4099cb3b3152SJohan Hedberg return -EPROTO; 4100cb3b3152SJohan Hedberg 41017b064edaSJaganath Kanakkassery hci_dev_lock(hdev); 41027b064edaSJaganath Kanakkassery if (test_bit(HCI_MGMT, &hdev->dev_flags) && 41037b064edaSJaganath Kanakkassery !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags)) 41047b064edaSJaganath Kanakkassery mgmt_device_connected(hdev, &hcon->dst, hcon->type, 41057b064edaSJaganath Kanakkassery hcon->dst_type, 0, NULL, 0, 41067b064edaSJaganath Kanakkassery hcon->dev_class); 41077b064edaSJaganath Kanakkassery hci_dev_unlock(hdev); 41087b064edaSJaganath Kanakkassery 4109300229f9SGustavo Padovan l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0); 41100a708f8fSGustavo F. Padovan return 0; 41110a708f8fSGustavo F. Padovan } 41120a708f8fSGustavo F. Padovan 41135909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn, 4114cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4115cb3b3152SJohan Hedberg u8 *data) 41160a708f8fSGustavo F. Padovan { 41170a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; 41180a708f8fSGustavo F. Padovan u16 scid, dcid, result, status; 411948454079SGustavo F. Padovan struct l2cap_chan *chan; 41200a708f8fSGustavo F. Padovan u8 req[128]; 41213df91ea2SAndrei Emeltchenko int err; 41220a708f8fSGustavo F. Padovan 4123cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp)) 4124cb3b3152SJohan Hedberg return -EPROTO; 4125cb3b3152SJohan Hedberg 41260a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 41270a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 41280a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 41290a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status); 41300a708f8fSGustavo F. Padovan 41311b009c98SAndrei Emeltchenko BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", 41321b009c98SAndrei Emeltchenko dcid, scid, result, status); 41330a708f8fSGustavo F. Padovan 41343df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 41353df91ea2SAndrei Emeltchenko 41360a708f8fSGustavo F. Padovan if (scid) { 41373df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 41383df91ea2SAndrei Emeltchenko if (!chan) { 413921870b52SJohan Hedberg err = -EBADSLT; 41403df91ea2SAndrei Emeltchenko goto unlock; 41413df91ea2SAndrei Emeltchenko } 41420a708f8fSGustavo F. Padovan } else { 41433df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 41443df91ea2SAndrei Emeltchenko if (!chan) { 414521870b52SJohan Hedberg err = -EBADSLT; 41463df91ea2SAndrei Emeltchenko goto unlock; 41473df91ea2SAndrei Emeltchenko } 41480a708f8fSGustavo F. Padovan } 41490a708f8fSGustavo F. Padovan 41503df91ea2SAndrei Emeltchenko err = 0; 41513df91ea2SAndrei Emeltchenko 41526be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 415348454079SGustavo F. Padovan 41540a708f8fSGustavo F. Padovan switch (result) { 41550a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS: 415689bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 4157fc7f8a7eSGustavo F. Padovan chan->ident = 0; 4158fe4128e0SGustavo F. Padovan chan->dcid = dcid; 4159c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state); 41600a708f8fSGustavo F. Padovan 4161c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 41620a708f8fSGustavo F. Padovan break; 41630a708f8fSGustavo F. Padovan 41640a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 416573ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, req), req); 416673ffa904SGustavo F. Padovan chan->num_conf_req++; 41670a708f8fSGustavo F. Padovan break; 41680a708f8fSGustavo F. Padovan 41690a708f8fSGustavo F. Padovan case L2CAP_CR_PEND: 4170c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 41710a708f8fSGustavo F. Padovan break; 41720a708f8fSGustavo F. Padovan 41730a708f8fSGustavo F. Padovan default: 417448454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED); 41750a708f8fSGustavo F. Padovan break; 41760a708f8fSGustavo F. Padovan } 41770a708f8fSGustavo F. Padovan 41786be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 41793df91ea2SAndrei Emeltchenko 41803df91ea2SAndrei Emeltchenko unlock: 41813df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 41823df91ea2SAndrei Emeltchenko 41833df91ea2SAndrei Emeltchenko return err; 41840a708f8fSGustavo F. Padovan } 41850a708f8fSGustavo F. Padovan 418647d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan) 41870a708f8fSGustavo F. Padovan { 41880a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both 41890a708f8fSGustavo F. Padovan * sides request it. 41900a708f8fSGustavo F. Padovan */ 41910c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) 419247d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 4193f2592d3eSAndrei Emeltchenko else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) 419447d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16; 41950a708f8fSGustavo F. Padovan } 41960a708f8fSGustavo F. Padovan 419729d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data, 419829d8a590SAndrei Emeltchenko u8 ident, u16 flags) 419929d8a590SAndrei Emeltchenko { 420029d8a590SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 420129d8a590SAndrei Emeltchenko 420229d8a590SAndrei Emeltchenko BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident, 420329d8a590SAndrei Emeltchenko flags); 420429d8a590SAndrei Emeltchenko 420529d8a590SAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 420629d8a590SAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 420729d8a590SAndrei Emeltchenko 420829d8a590SAndrei Emeltchenko l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP, 420929d8a590SAndrei Emeltchenko l2cap_build_conf_rsp(chan, data, 421029d8a590SAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), data); 421129d8a590SAndrei Emeltchenko } 421229d8a590SAndrei Emeltchenko 4213662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident, 4214662d652dSJohan Hedberg u16 scid, u16 dcid) 4215662d652dSJohan Hedberg { 4216662d652dSJohan Hedberg struct l2cap_cmd_rej_cid rej; 4217662d652dSJohan Hedberg 4218662d652dSJohan Hedberg rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID); 4219662d652dSJohan Hedberg rej.scid = __cpu_to_le16(scid); 4220662d652dSJohan Hedberg rej.dcid = __cpu_to_le16(dcid); 4221662d652dSJohan Hedberg 4222662d652dSJohan Hedberg l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); 4223662d652dSJohan Hedberg } 4224662d652dSJohan Hedberg 42252d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, 42262d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len, 42272d792818SGustavo Padovan u8 *data) 42280a708f8fSGustavo F. Padovan { 42290a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; 42300a708f8fSGustavo F. Padovan u16 dcid, flags; 42310a708f8fSGustavo F. Padovan u8 rsp[64]; 423248454079SGustavo F. Padovan struct l2cap_chan *chan; 42333c588192SMat Martineau int len, err = 0; 42340a708f8fSGustavo F. Padovan 4235cb3b3152SJohan Hedberg if (cmd_len < sizeof(*req)) 4236cb3b3152SJohan Hedberg return -EPROTO; 4237cb3b3152SJohan Hedberg 42380a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 42390a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags); 42400a708f8fSGustavo F. Padovan 42410a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); 42420a708f8fSGustavo F. Padovan 4243baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid); 4244662d652dSJohan Hedberg if (!chan) { 4245662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0); 4246662d652dSJohan Hedberg return 0; 4247662d652dSJohan Hedberg } 42480a708f8fSGustavo F. Padovan 4249033b1142SDavid S. Miller if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { 4250662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, 4251662d652dSJohan Hedberg chan->dcid); 42520a708f8fSGustavo F. Padovan goto unlock; 42530a708f8fSGustavo F. Padovan } 42540a708f8fSGustavo F. Padovan 42550a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */ 42560a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req); 4257cb3b3152SJohan Hedberg if (chan->conf_len + len > sizeof(chan->conf_req)) { 42580a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 4259fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 42600a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp); 42610a708f8fSGustavo F. Padovan goto unlock; 42620a708f8fSGustavo F. Padovan } 42630a708f8fSGustavo F. Padovan 42640a708f8fSGustavo F. Padovan /* Store config. */ 426573ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len); 426673ffa904SGustavo F. Padovan chan->conf_len += len; 42670a708f8fSGustavo F. Padovan 426859e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) { 42690a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */ 42700a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 4271fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 42725325e5bbSAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), rsp); 42730a708f8fSGustavo F. Padovan goto unlock; 42740a708f8fSGustavo F. Padovan } 42750a708f8fSGustavo F. Padovan 42760a708f8fSGustavo F. Padovan /* Complete config. */ 427773ffa904SGustavo F. Padovan len = l2cap_parse_conf_req(chan, rsp); 42780a708f8fSGustavo F. Padovan if (len < 0) { 42795e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 42800a708f8fSGustavo F. Padovan goto unlock; 42810a708f8fSGustavo F. Padovan } 42820a708f8fSGustavo F. Padovan 42831500109bSMat Martineau chan->ident = cmd->ident; 42840a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); 428573ffa904SGustavo F. Padovan chan->num_conf_rsp++; 42860a708f8fSGustavo F. Padovan 42870a708f8fSGustavo F. Padovan /* Reset config buffer. */ 428873ffa904SGustavo F. Padovan chan->conf_len = 0; 42890a708f8fSGustavo F. Padovan 4290c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) 42910a708f8fSGustavo F. Padovan goto unlock; 42920a708f8fSGustavo F. Padovan 4293c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 429447d1ec61SGustavo F. Padovan set_default_fcs(chan); 42950a708f8fSGustavo F. Padovan 4296105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 4297105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 42983c588192SMat Martineau err = l2cap_ertm_init(chan); 42990a708f8fSGustavo F. Padovan 43003c588192SMat Martineau if (err < 0) 43015e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 43023c588192SMat Martineau else 4303cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 43043c588192SMat Martineau 43050a708f8fSGustavo F. Padovan goto unlock; 43060a708f8fSGustavo F. Padovan } 43070a708f8fSGustavo F. Padovan 4308c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { 43090a708f8fSGustavo F. Padovan u8 buf[64]; 43100a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 431173ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 431273ffa904SGustavo F. Padovan chan->num_conf_req++; 43130a708f8fSGustavo F. Padovan } 43140a708f8fSGustavo F. Padovan 43150e8b207eSAndrei Emeltchenko /* Got Conf Rsp PENDING from remote side and asume we sent 43160e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */ 43170e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && 43180e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 43190e8b207eSAndrei Emeltchenko 43200e8b207eSAndrei Emeltchenko /* check compatibility */ 43210e8b207eSAndrei Emeltchenko 432279de886dSAndrei Emeltchenko /* Send rsp for BR/EDR channel */ 4323f351bc72SAndrei Emeltchenko if (!chan->hs_hcon) 432429d8a590SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags); 432579de886dSAndrei Emeltchenko else 432679de886dSAndrei Emeltchenko chan->ident = cmd->ident; 43270e8b207eSAndrei Emeltchenko } 43280e8b207eSAndrei Emeltchenko 43290a708f8fSGustavo F. Padovan unlock: 43306be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 43313c588192SMat Martineau return err; 43320a708f8fSGustavo F. Padovan } 43330a708f8fSGustavo F. Padovan 43342d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, 4335cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4336cb3b3152SJohan Hedberg u8 *data) 43370a708f8fSGustavo F. Padovan { 43380a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; 43390a708f8fSGustavo F. Padovan u16 scid, flags, result; 434048454079SGustavo F. Padovan struct l2cap_chan *chan; 4341cb3b3152SJohan Hedberg int len = cmd_len - sizeof(*rsp); 43423c588192SMat Martineau int err = 0; 43430a708f8fSGustavo F. Padovan 4344cb3b3152SJohan Hedberg if (cmd_len < sizeof(*rsp)) 4345cb3b3152SJohan Hedberg return -EPROTO; 4346cb3b3152SJohan Hedberg 43470a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 43480a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags); 43490a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 43500a708f8fSGustavo F. Padovan 435161386cbaSAndrei Emeltchenko BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags, 435261386cbaSAndrei Emeltchenko result, len); 43530a708f8fSGustavo F. Padovan 4354baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 435548454079SGustavo F. Padovan if (!chan) 43560a708f8fSGustavo F. Padovan return 0; 43570a708f8fSGustavo F. Padovan 43580a708f8fSGustavo F. Padovan switch (result) { 43590a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS: 436047d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len); 43610e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state); 43620a708f8fSGustavo F. Padovan break; 43630a708f8fSGustavo F. Padovan 43640e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING: 43650e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state); 43660e8b207eSAndrei Emeltchenko 43670e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 43680e8b207eSAndrei Emeltchenko char buf[64]; 43690e8b207eSAndrei Emeltchenko 43700e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len, 43710e8b207eSAndrei Emeltchenko buf, &result); 43720e8b207eSAndrei Emeltchenko if (len < 0) { 43735e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 43740e8b207eSAndrei Emeltchenko goto done; 43750e8b207eSAndrei Emeltchenko } 43760e8b207eSAndrei Emeltchenko 4377f351bc72SAndrei Emeltchenko if (!chan->hs_hcon) { 437879de886dSAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, buf, cmd->ident, 437979de886dSAndrei Emeltchenko 0); 43805ce66b59SAndrei Emeltchenko } else { 43815ce66b59SAndrei Emeltchenko if (l2cap_check_efs(chan)) { 43825ce66b59SAndrei Emeltchenko amp_create_logical_link(chan); 438379de886dSAndrei Emeltchenko chan->ident = cmd->ident; 43840e8b207eSAndrei Emeltchenko } 43855ce66b59SAndrei Emeltchenko } 43865ce66b59SAndrei Emeltchenko } 43870e8b207eSAndrei Emeltchenko goto done; 43880e8b207eSAndrei Emeltchenko 43890a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT: 439073ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { 43910a708f8fSGustavo F. Padovan char req[64]; 43920a708f8fSGustavo F. Padovan 43930a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { 43945e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 43950a708f8fSGustavo F. Padovan goto done; 43960a708f8fSGustavo F. Padovan } 43970a708f8fSGustavo F. Padovan 43980a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */ 43990a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS; 4400b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len, 4401b4450035SGustavo F. Padovan req, &result); 44020a708f8fSGustavo F. Padovan if (len < 0) { 44035e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 44040a708f8fSGustavo F. Padovan goto done; 44050a708f8fSGustavo F. Padovan } 44060a708f8fSGustavo F. Padovan 44070a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 44080a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req); 440973ffa904SGustavo F. Padovan chan->num_conf_req++; 44100a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS) 44110a708f8fSGustavo F. Padovan goto done; 44120a708f8fSGustavo F. Padovan break; 44130a708f8fSGustavo F. Padovan } 44140a708f8fSGustavo F. Padovan 44150a708f8fSGustavo F. Padovan default: 44166be36555SAndrei Emeltchenko l2cap_chan_set_err(chan, ECONNRESET); 44172e0052e4SAndrei Emeltchenko 4418ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); 44195e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 44200a708f8fSGustavo F. Padovan goto done; 44210a708f8fSGustavo F. Padovan } 44220a708f8fSGustavo F. Padovan 442359e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) 44240a708f8fSGustavo F. Padovan goto done; 44250a708f8fSGustavo F. Padovan 4426c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state); 44270a708f8fSGustavo F. Padovan 4428c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { 442947d1ec61SGustavo F. Padovan set_default_fcs(chan); 44300a708f8fSGustavo F. Padovan 4431105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 4432105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 44333c588192SMat Martineau err = l2cap_ertm_init(chan); 44340a708f8fSGustavo F. Padovan 44353c588192SMat Martineau if (err < 0) 44365e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 44373c588192SMat Martineau else 4438cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 44390a708f8fSGustavo F. Padovan } 44400a708f8fSGustavo F. Padovan 44410a708f8fSGustavo F. Padovan done: 44426be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 44433c588192SMat Martineau return err; 44440a708f8fSGustavo F. Padovan } 44450a708f8fSGustavo F. Padovan 44462d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, 4447cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4448cb3b3152SJohan Hedberg u8 *data) 44490a708f8fSGustavo F. Padovan { 44500a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; 44510a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp; 44520a708f8fSGustavo F. Padovan u16 dcid, scid; 445348454079SGustavo F. Padovan struct l2cap_chan *chan; 44540a708f8fSGustavo F. Padovan 4455cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req)) 4456cb3b3152SJohan Hedberg return -EPROTO; 4457cb3b3152SJohan Hedberg 44580a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid); 44590a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 44600a708f8fSGustavo F. Padovan 44610a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); 44620a708f8fSGustavo F. Padovan 44633df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 44643df91ea2SAndrei Emeltchenko 44653df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, dcid); 44663df91ea2SAndrei Emeltchenko if (!chan) { 44673df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4468662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid); 4469662d652dSJohan Hedberg return 0; 44703df91ea2SAndrei Emeltchenko } 44710a708f8fSGustavo F. Padovan 44726be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 44736be36555SAndrei Emeltchenko 4474fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 4475fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 44760a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); 44770a708f8fSGustavo F. Padovan 44785ec1bbe5SGustavo Padovan chan->ops->set_shutdown(chan); 44790a708f8fSGustavo F. Padovan 448061d6ef3eSMat Martineau l2cap_chan_hold(chan); 448148454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET); 44826be36555SAndrei Emeltchenko 44836be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 44840a708f8fSGustavo F. Padovan 448580b98027SGustavo Padovan chan->ops->close(chan); 448661d6ef3eSMat Martineau l2cap_chan_put(chan); 44873df91ea2SAndrei Emeltchenko 44883df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 44893df91ea2SAndrei Emeltchenko 44900a708f8fSGustavo F. Padovan return 0; 44910a708f8fSGustavo F. Padovan } 44920a708f8fSGustavo F. Padovan 44932d792818SGustavo Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, 4494cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4495cb3b3152SJohan Hedberg u8 *data) 44960a708f8fSGustavo F. Padovan { 44970a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; 44980a708f8fSGustavo F. Padovan u16 dcid, scid; 449948454079SGustavo F. Padovan struct l2cap_chan *chan; 45000a708f8fSGustavo F. Padovan 4501cb3b3152SJohan Hedberg if (cmd_len != sizeof(*rsp)) 4502cb3b3152SJohan Hedberg return -EPROTO; 4503cb3b3152SJohan Hedberg 45040a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 45050a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 45060a708f8fSGustavo F. Padovan 45070a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); 45080a708f8fSGustavo F. Padovan 45093df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 45103df91ea2SAndrei Emeltchenko 45113df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 45123df91ea2SAndrei Emeltchenko if (!chan) { 45133df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 45140a708f8fSGustavo F. Padovan return 0; 45153df91ea2SAndrei Emeltchenko } 45160a708f8fSGustavo F. Padovan 45176be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 451848454079SGustavo F. Padovan 451961d6ef3eSMat Martineau l2cap_chan_hold(chan); 452048454079SGustavo F. Padovan l2cap_chan_del(chan, 0); 45216be36555SAndrei Emeltchenko 45226be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 45230a708f8fSGustavo F. Padovan 452480b98027SGustavo Padovan chan->ops->close(chan); 452561d6ef3eSMat Martineau l2cap_chan_put(chan); 45263df91ea2SAndrei Emeltchenko 45273df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 45283df91ea2SAndrei Emeltchenko 45290a708f8fSGustavo F. Padovan return 0; 45300a708f8fSGustavo F. Padovan } 45310a708f8fSGustavo F. Padovan 45322d792818SGustavo Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, 4533cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4534cb3b3152SJohan Hedberg u8 *data) 45350a708f8fSGustavo F. Padovan { 45360a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data; 45370a708f8fSGustavo F. Padovan u16 type; 45380a708f8fSGustavo F. Padovan 4539cb3b3152SJohan Hedberg if (cmd_len != sizeof(*req)) 4540cb3b3152SJohan Hedberg return -EPROTO; 4541cb3b3152SJohan Hedberg 45420a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type); 45430a708f8fSGustavo F. Padovan 45440a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type); 45450a708f8fSGustavo F. Padovan 45460a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) { 45470a708f8fSGustavo F. Padovan u8 buf[8]; 45480a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask; 45490a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 4550ac73498cSAndrei Emeltchenko rsp->type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); 4551ac73498cSAndrei Emeltchenko rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); 45520a708f8fSGustavo F. Padovan if (!disable_ertm) 45530a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING 45540a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS; 4555848566b3SMarcel Holtmann if (conn->hs_enabled) 45566327eb98SAndrei Emeltchenko feat_mask |= L2CAP_FEAT_EXT_FLOW 45576327eb98SAndrei Emeltchenko | L2CAP_FEAT_EXT_WINDOW; 4558a5fd6f30SAndrei Emeltchenko 45590a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data); 45602d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), 45612d792818SGustavo Padovan buf); 45620a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) { 45630a708f8fSGustavo F. Padovan u8 buf[12]; 45640a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 456550a147cdSMat Martineau 4566848566b3SMarcel Holtmann if (conn->hs_enabled) 456750a147cdSMat Martineau l2cap_fixed_chan[0] |= L2CAP_FC_A2MP; 456850a147cdSMat Martineau else 456950a147cdSMat Martineau l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP; 457050a147cdSMat Martineau 4571ac73498cSAndrei Emeltchenko rsp->type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); 4572ac73498cSAndrei Emeltchenko rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); 4573c6337ea6SAndrei Emeltchenko memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); 45742d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), 45752d792818SGustavo Padovan buf); 45760a708f8fSGustavo F. Padovan } else { 45770a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp; 45780a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type); 4579ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP); 45802d792818SGustavo Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), 45812d792818SGustavo Padovan &rsp); 45820a708f8fSGustavo F. Padovan } 45830a708f8fSGustavo F. Padovan 45840a708f8fSGustavo F. Padovan return 0; 45850a708f8fSGustavo F. Padovan } 45860a708f8fSGustavo F. Padovan 45872d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, 4588cb3b3152SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 4589cb3b3152SJohan Hedberg u8 *data) 45900a708f8fSGustavo F. Padovan { 45910a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; 45920a708f8fSGustavo F. Padovan u16 type, result; 45930a708f8fSGustavo F. Padovan 45943f6fa3d4SJaganath Kanakkassery if (cmd_len < sizeof(*rsp)) 4595cb3b3152SJohan Hedberg return -EPROTO; 4596cb3b3152SJohan Hedberg 45970a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type); 45980a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 45990a708f8fSGustavo F. Padovan 46000a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); 46010a708f8fSGustavo F. Padovan 4602e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */ 4603e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident || 4604e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 4605e90165beSAndrei Emeltchenko return 0; 4606e90165beSAndrei Emeltchenko 460717cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 46080a708f8fSGustavo F. Padovan 46090a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) { 46100a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 46110a708f8fSGustavo F. Padovan conn->info_ident = 0; 46120a708f8fSGustavo F. Padovan 46130a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 46140a708f8fSGustavo F. Padovan 46150a708f8fSGustavo F. Padovan return 0; 46160a708f8fSGustavo F. Padovan } 46170a708f8fSGustavo F. Padovan 4618978c93b9SAndrei Emeltchenko switch (type) { 4619978c93b9SAndrei Emeltchenko case L2CAP_IT_FEAT_MASK: 46200a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data); 46210a708f8fSGustavo F. Padovan 46220a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { 46230a708f8fSGustavo F. Padovan struct l2cap_info_req req; 4624ac73498cSAndrei Emeltchenko req.type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); 46250a708f8fSGustavo F. Padovan 46260a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 46270a708f8fSGustavo F. Padovan 46280a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 46290a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 46300a708f8fSGustavo F. Padovan } else { 46310a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 46320a708f8fSGustavo F. Padovan conn->info_ident = 0; 46330a708f8fSGustavo F. Padovan 46340a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 46350a708f8fSGustavo F. Padovan } 4636978c93b9SAndrei Emeltchenko break; 4637978c93b9SAndrei Emeltchenko 4638978c93b9SAndrei Emeltchenko case L2CAP_IT_FIXED_CHAN: 4639978c93b9SAndrei Emeltchenko conn->fixed_chan_mask = rsp->data[0]; 46400a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 46410a708f8fSGustavo F. Padovan conn->info_ident = 0; 46420a708f8fSGustavo F. Padovan 46430a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 4644978c93b9SAndrei Emeltchenko break; 46450a708f8fSGustavo F. Padovan } 46460a708f8fSGustavo F. Padovan 46470a708f8fSGustavo F. Padovan return 0; 46480a708f8fSGustavo F. Padovan } 46490a708f8fSGustavo F. Padovan 46501700915fSMat Martineau static int l2cap_create_channel_req(struct l2cap_conn *conn, 46512d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, 46522d792818SGustavo Padovan u16 cmd_len, void *data) 4653f94ff6ffSMat Martineau { 4654f94ff6ffSMat Martineau struct l2cap_create_chan_req *req = data; 46556e1df6a6SAndrei Emeltchenko struct l2cap_create_chan_rsp rsp; 46561700915fSMat Martineau struct l2cap_chan *chan; 46576e1df6a6SAndrei Emeltchenko struct hci_dev *hdev; 4658f94ff6ffSMat Martineau u16 psm, scid; 4659f94ff6ffSMat Martineau 4660f94ff6ffSMat Martineau if (cmd_len != sizeof(*req)) 4661f94ff6ffSMat Martineau return -EPROTO; 4662f94ff6ffSMat Martineau 4663848566b3SMarcel Holtmann if (!conn->hs_enabled) 4664f94ff6ffSMat Martineau return -EINVAL; 4665f94ff6ffSMat Martineau 4666f94ff6ffSMat Martineau psm = le16_to_cpu(req->psm); 4667f94ff6ffSMat Martineau scid = le16_to_cpu(req->scid); 4668f94ff6ffSMat Martineau 4669ad0ac6caSAndrei Emeltchenko BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id); 4670f94ff6ffSMat Martineau 46716e1df6a6SAndrei Emeltchenko /* For controller id 0 make BR/EDR connection */ 46726ed971caSMarcel Holtmann if (req->amp_id == AMP_ID_BREDR) { 46736e1df6a6SAndrei Emeltchenko l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, 46746e1df6a6SAndrei Emeltchenko req->amp_id); 46756e1df6a6SAndrei Emeltchenko return 0; 46766e1df6a6SAndrei Emeltchenko } 46771700915fSMat Martineau 46781700915fSMat Martineau /* Validate AMP controller id */ 46791700915fSMat Martineau hdev = hci_dev_get(req->amp_id); 46806e1df6a6SAndrei Emeltchenko if (!hdev) 46816e1df6a6SAndrei Emeltchenko goto error; 46821700915fSMat Martineau 46836e1df6a6SAndrei Emeltchenko if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) { 46846e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 46856e1df6a6SAndrei Emeltchenko goto error; 46866e1df6a6SAndrei Emeltchenko } 46876e1df6a6SAndrei Emeltchenko 46886e1df6a6SAndrei Emeltchenko chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, 46896e1df6a6SAndrei Emeltchenko req->amp_id); 46906e1df6a6SAndrei Emeltchenko if (chan) { 46916e1df6a6SAndrei Emeltchenko struct amp_mgr *mgr = conn->hcon->amp_mgr; 46926e1df6a6SAndrei Emeltchenko struct hci_conn *hs_hcon; 46936e1df6a6SAndrei Emeltchenko 469498e0f7eaSMarcel Holtmann hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, 469598e0f7eaSMarcel Holtmann &conn->hcon->dst); 46966e1df6a6SAndrei Emeltchenko if (!hs_hcon) { 46976e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 4698662d652dSJohan Hedberg cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, 4699662d652dSJohan Hedberg chan->dcid); 4700662d652dSJohan Hedberg return 0; 47016e1df6a6SAndrei Emeltchenko } 47026e1df6a6SAndrei Emeltchenko 47036e1df6a6SAndrei Emeltchenko BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon); 47046e1df6a6SAndrei Emeltchenko 47056e1df6a6SAndrei Emeltchenko mgr->bredr_chan = chan; 47066e1df6a6SAndrei Emeltchenko chan->hs_hcon = hs_hcon; 4707fd45bf4cSAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 47086e1df6a6SAndrei Emeltchenko conn->mtu = hdev->block_mtu; 47096e1df6a6SAndrei Emeltchenko } 47106e1df6a6SAndrei Emeltchenko 47116e1df6a6SAndrei Emeltchenko hci_dev_put(hdev); 47126e1df6a6SAndrei Emeltchenko 47136e1df6a6SAndrei Emeltchenko return 0; 47146e1df6a6SAndrei Emeltchenko 47156e1df6a6SAndrei Emeltchenko error: 4716f94ff6ffSMat Martineau rsp.dcid = 0; 4717f94ff6ffSMat Martineau rsp.scid = cpu_to_le16(scid); 47181700915fSMat Martineau rsp.result = __constant_cpu_to_le16(L2CAP_CR_BAD_AMP); 47198ce0c498SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 4720f94ff6ffSMat Martineau 4721f94ff6ffSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, 4722f94ff6ffSMat Martineau sizeof(rsp), &rsp); 4723f94ff6ffSMat Martineau 4724dc280801SJohan Hedberg return 0; 4725f94ff6ffSMat Martineau } 4726f94ff6ffSMat Martineau 47278eb200bdSMat Martineau static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id) 47288eb200bdSMat Martineau { 47298eb200bdSMat Martineau struct l2cap_move_chan_req req; 47308eb200bdSMat Martineau u8 ident; 47318eb200bdSMat Martineau 47328eb200bdSMat Martineau BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id); 47338eb200bdSMat Martineau 47348eb200bdSMat Martineau ident = l2cap_get_ident(chan->conn); 47358eb200bdSMat Martineau chan->ident = ident; 47368eb200bdSMat Martineau 47378eb200bdSMat Martineau req.icid = cpu_to_le16(chan->scid); 47388eb200bdSMat Martineau req.dest_amp_id = dest_amp_id; 47398eb200bdSMat Martineau 47408eb200bdSMat Martineau l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req), 47418eb200bdSMat Martineau &req); 47428eb200bdSMat Martineau 47438eb200bdSMat Martineau __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); 47448eb200bdSMat Martineau } 47458eb200bdSMat Martineau 47461500109bSMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result) 47478d5a04a1SMat Martineau { 47488d5a04a1SMat Martineau struct l2cap_move_chan_rsp rsp; 47498d5a04a1SMat Martineau 47501500109bSMat Martineau BT_DBG("chan %p, result 0x%4.4x", chan, result); 47518d5a04a1SMat Martineau 47521500109bSMat Martineau rsp.icid = cpu_to_le16(chan->dcid); 47538d5a04a1SMat Martineau rsp.result = cpu_to_le16(result); 47548d5a04a1SMat Martineau 47551500109bSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP, 47561500109bSMat Martineau sizeof(rsp), &rsp); 47578d5a04a1SMat Martineau } 47588d5a04a1SMat Martineau 47595b155ef9SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result) 47608d5a04a1SMat Martineau { 47618d5a04a1SMat Martineau struct l2cap_move_chan_cfm cfm; 47628d5a04a1SMat Martineau 47635b155ef9SMat Martineau BT_DBG("chan %p, result 0x%4.4x", chan, result); 47648d5a04a1SMat Martineau 47655b155ef9SMat Martineau chan->ident = l2cap_get_ident(chan->conn); 47668d5a04a1SMat Martineau 47675b155ef9SMat Martineau cfm.icid = cpu_to_le16(chan->scid); 47688d5a04a1SMat Martineau cfm.result = cpu_to_le16(result); 47698d5a04a1SMat Martineau 47705b155ef9SMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM, 47715b155ef9SMat Martineau sizeof(cfm), &cfm); 47725b155ef9SMat Martineau 47735b155ef9SMat Martineau __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); 47745b155ef9SMat Martineau } 47755b155ef9SMat Martineau 47765b155ef9SMat Martineau static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid) 47775b155ef9SMat Martineau { 47785b155ef9SMat Martineau struct l2cap_move_chan_cfm cfm; 47795b155ef9SMat Martineau 47805b155ef9SMat Martineau BT_DBG("conn %p, icid 0x%4.4x", conn, icid); 47815b155ef9SMat Martineau 47825b155ef9SMat Martineau cfm.icid = cpu_to_le16(icid); 47835b155ef9SMat Martineau cfm.result = __constant_cpu_to_le16(L2CAP_MC_UNCONFIRMED); 47845b155ef9SMat Martineau 47855b155ef9SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM, 47865b155ef9SMat Martineau sizeof(cfm), &cfm); 47878d5a04a1SMat Martineau } 47888d5a04a1SMat Martineau 47898d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, 47908d5a04a1SMat Martineau u16 icid) 47918d5a04a1SMat Martineau { 47928d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp rsp; 47938d5a04a1SMat Martineau 4794ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 47958d5a04a1SMat Martineau 47968d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 47978d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp); 47988d5a04a1SMat Martineau } 47998d5a04a1SMat Martineau 48005f3847a4SMat Martineau static void __release_logical_link(struct l2cap_chan *chan) 48015f3847a4SMat Martineau { 48025f3847a4SMat Martineau chan->hs_hchan = NULL; 48035f3847a4SMat Martineau chan->hs_hcon = NULL; 48045f3847a4SMat Martineau 48055f3847a4SMat Martineau /* Placeholder - release the logical link */ 48065f3847a4SMat Martineau } 48075f3847a4SMat Martineau 48081500109bSMat Martineau static void l2cap_logical_fail(struct l2cap_chan *chan) 48091500109bSMat Martineau { 48101500109bSMat Martineau /* Logical link setup failed */ 48111500109bSMat Martineau if (chan->state != BT_CONNECTED) { 48121500109bSMat Martineau /* Create channel failure, disconnect */ 48135e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 48141500109bSMat Martineau return; 48151500109bSMat Martineau } 48161500109bSMat Martineau 48171500109bSMat Martineau switch (chan->move_role) { 48181500109bSMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 48191500109bSMat Martineau l2cap_move_done(chan); 48201500109bSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP); 48211500109bSMat Martineau break; 48221500109bSMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 48231500109bSMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP || 48241500109bSMat Martineau chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) { 48251500109bSMat Martineau /* Remote has only sent pending or 48261500109bSMat Martineau * success responses, clean up 48271500109bSMat Martineau */ 48281500109bSMat Martineau l2cap_move_done(chan); 48291500109bSMat Martineau } 48301500109bSMat Martineau 48311500109bSMat Martineau /* Other amp move states imply that the move 48321500109bSMat Martineau * has already aborted 48331500109bSMat Martineau */ 48341500109bSMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 48351500109bSMat Martineau break; 48361500109bSMat Martineau } 48371500109bSMat Martineau } 48381500109bSMat Martineau 48391500109bSMat Martineau static void l2cap_logical_finish_create(struct l2cap_chan *chan, 48401500109bSMat Martineau struct hci_chan *hchan) 48411500109bSMat Martineau { 48421500109bSMat Martineau struct l2cap_conf_rsp rsp; 48431500109bSMat Martineau 4844336178a3SAndrei Emeltchenko chan->hs_hchan = hchan; 48451500109bSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 48461500109bSMat Martineau 484735ba9561SAndrei Emeltchenko l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0); 48481500109bSMat Martineau 48491500109bSMat Martineau if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 4850fe79c6feSAndrei Emeltchenko int err; 48511500109bSMat Martineau 48521500109bSMat Martineau set_default_fcs(chan); 48531500109bSMat Martineau 48541500109bSMat Martineau err = l2cap_ertm_init(chan); 48551500109bSMat Martineau if (err < 0) 48565e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, -err); 48571500109bSMat Martineau else 48581500109bSMat Martineau l2cap_chan_ready(chan); 48591500109bSMat Martineau } 48601500109bSMat Martineau } 48611500109bSMat Martineau 48621500109bSMat Martineau static void l2cap_logical_finish_move(struct l2cap_chan *chan, 48631500109bSMat Martineau struct hci_chan *hchan) 48641500109bSMat Martineau { 48651500109bSMat Martineau chan->hs_hcon = hchan->conn; 48661500109bSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 48671500109bSMat Martineau 48681500109bSMat Martineau BT_DBG("move_state %d", chan->move_state); 48691500109bSMat Martineau 48701500109bSMat Martineau switch (chan->move_state) { 48711500109bSMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_COMP: 48721500109bSMat Martineau /* Move confirm will be sent after a success 48731500109bSMat Martineau * response is received 48741500109bSMat Martineau */ 48751500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 48761500109bSMat Martineau break; 48771500109bSMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_CFM: 48781500109bSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 48791500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 48801500109bSMat Martineau } else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { 48811500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; 48821500109bSMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 48831500109bSMat Martineau } else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { 48841500109bSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 48851500109bSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); 48861500109bSMat Martineau } 48871500109bSMat Martineau break; 48881500109bSMat Martineau default: 48891500109bSMat Martineau /* Move was not in expected state, free the channel */ 48901500109bSMat Martineau __release_logical_link(chan); 48911500109bSMat Martineau 48921500109bSMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 48931500109bSMat Martineau } 48941500109bSMat Martineau } 48951500109bSMat Martineau 48961500109bSMat Martineau /* Call with chan locked */ 489727695fb4SAndrei Emeltchenko void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan, 48985b155ef9SMat Martineau u8 status) 48995b155ef9SMat Martineau { 49001500109bSMat Martineau BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status); 49011500109bSMat Martineau 49021500109bSMat Martineau if (status) { 49031500109bSMat Martineau l2cap_logical_fail(chan); 49041500109bSMat Martineau __release_logical_link(chan); 49055b155ef9SMat Martineau return; 49065b155ef9SMat Martineau } 49075b155ef9SMat Martineau 49081500109bSMat Martineau if (chan->state != BT_CONNECTED) { 49091500109bSMat Martineau /* Ignore logical link if channel is on BR/EDR */ 49106ed971caSMarcel Holtmann if (chan->local_amp_id != AMP_ID_BREDR) 49111500109bSMat Martineau l2cap_logical_finish_create(chan, hchan); 49121500109bSMat Martineau } else { 49131500109bSMat Martineau l2cap_logical_finish_move(chan, hchan); 49141500109bSMat Martineau } 49151500109bSMat Martineau } 49161500109bSMat Martineau 49173f7a56c4SMat Martineau void l2cap_move_start(struct l2cap_chan *chan) 49183f7a56c4SMat Martineau { 49193f7a56c4SMat Martineau BT_DBG("chan %p", chan); 49203f7a56c4SMat Martineau 49216ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR) { 49223f7a56c4SMat Martineau if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED) 49233f7a56c4SMat Martineau return; 49243f7a56c4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; 49253f7a56c4SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_PREPARE; 49263f7a56c4SMat Martineau /* Placeholder - start physical link setup */ 49273f7a56c4SMat Martineau } else { 49283f7a56c4SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; 49293f7a56c4SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 49303f7a56c4SMat Martineau chan->move_id = 0; 49313f7a56c4SMat Martineau l2cap_move_setup(chan); 49323f7a56c4SMat Martineau l2cap_send_move_chan_req(chan, 0); 49333f7a56c4SMat Martineau } 49343f7a56c4SMat Martineau } 49353f7a56c4SMat Martineau 49368eb200bdSMat Martineau static void l2cap_do_create(struct l2cap_chan *chan, int result, 49378eb200bdSMat Martineau u8 local_amp_id, u8 remote_amp_id) 49388eb200bdSMat Martineau { 493962748ca1SAndrei Emeltchenko BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state), 494062748ca1SAndrei Emeltchenko local_amp_id, remote_amp_id); 494162748ca1SAndrei Emeltchenko 494212d6cc60SAndrei Emeltchenko chan->fcs = L2CAP_FCS_NONE; 494312d6cc60SAndrei Emeltchenko 494462748ca1SAndrei Emeltchenko /* Outgoing channel on AMP */ 494562748ca1SAndrei Emeltchenko if (chan->state == BT_CONNECT) { 494662748ca1SAndrei Emeltchenko if (result == L2CAP_CR_SUCCESS) { 494762748ca1SAndrei Emeltchenko chan->local_amp_id = local_amp_id; 494862748ca1SAndrei Emeltchenko l2cap_send_create_chan_req(chan, remote_amp_id); 494962748ca1SAndrei Emeltchenko } else { 495062748ca1SAndrei Emeltchenko /* Revert to BR/EDR connect */ 495162748ca1SAndrei Emeltchenko l2cap_send_conn_req(chan); 495262748ca1SAndrei Emeltchenko } 495362748ca1SAndrei Emeltchenko 495462748ca1SAndrei Emeltchenko return; 495562748ca1SAndrei Emeltchenko } 495662748ca1SAndrei Emeltchenko 495762748ca1SAndrei Emeltchenko /* Incoming channel on AMP */ 495862748ca1SAndrei Emeltchenko if (__l2cap_no_conn_pending(chan)) { 49598eb200bdSMat Martineau struct l2cap_conn_rsp rsp; 49608eb200bdSMat Martineau char buf[128]; 49618eb200bdSMat Martineau rsp.scid = cpu_to_le16(chan->dcid); 49628eb200bdSMat Martineau rsp.dcid = cpu_to_le16(chan->scid); 49638eb200bdSMat Martineau 49648eb200bdSMat Martineau if (result == L2CAP_CR_SUCCESS) { 49658eb200bdSMat Martineau /* Send successful response */ 496662cd50e2SAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 496762cd50e2SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 49688eb200bdSMat Martineau } else { 49698eb200bdSMat Martineau /* Send negative response */ 497062cd50e2SAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM); 497162cd50e2SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 49728eb200bdSMat Martineau } 49738eb200bdSMat Martineau 49748eb200bdSMat Martineau l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP, 49758eb200bdSMat Martineau sizeof(rsp), &rsp); 49768eb200bdSMat Martineau 49778eb200bdSMat Martineau if (result == L2CAP_CR_SUCCESS) { 4978f93fa273SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 49798eb200bdSMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 49808eb200bdSMat Martineau l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn), 49818eb200bdSMat Martineau L2CAP_CONF_REQ, 49828eb200bdSMat Martineau l2cap_build_conf_req(chan, buf), buf); 49838eb200bdSMat Martineau chan->num_conf_req++; 49848eb200bdSMat Martineau } 49858eb200bdSMat Martineau } 49868eb200bdSMat Martineau } 49878eb200bdSMat Martineau 49888eb200bdSMat Martineau static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id, 49898eb200bdSMat Martineau u8 remote_amp_id) 49908eb200bdSMat Martineau { 49918eb200bdSMat Martineau l2cap_move_setup(chan); 49928eb200bdSMat Martineau chan->move_id = local_amp_id; 49938eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP; 49948eb200bdSMat Martineau 49958eb200bdSMat Martineau l2cap_send_move_chan_req(chan, remote_amp_id); 49968eb200bdSMat Martineau } 49978eb200bdSMat Martineau 49988eb200bdSMat Martineau static void l2cap_do_move_respond(struct l2cap_chan *chan, int result) 49998eb200bdSMat Martineau { 50008eb200bdSMat Martineau struct hci_chan *hchan = NULL; 50018eb200bdSMat Martineau 50028eb200bdSMat Martineau /* Placeholder - get hci_chan for logical link */ 50038eb200bdSMat Martineau 50048eb200bdSMat Martineau if (hchan) { 50058eb200bdSMat Martineau if (hchan->state == BT_CONNECTED) { 50068eb200bdSMat Martineau /* Logical link is ready to go */ 50078eb200bdSMat Martineau chan->hs_hcon = hchan->conn; 50088eb200bdSMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 50098eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 50108eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); 50118eb200bdSMat Martineau 50128eb200bdSMat Martineau l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); 50138eb200bdSMat Martineau } else { 50148eb200bdSMat Martineau /* Wait for logical link to be ready */ 50158eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 50168eb200bdSMat Martineau } 50178eb200bdSMat Martineau } else { 50188eb200bdSMat Martineau /* Logical link not available */ 50198eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED); 50208eb200bdSMat Martineau } 50218eb200bdSMat Martineau } 50228eb200bdSMat Martineau 50238eb200bdSMat Martineau static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result) 50248eb200bdSMat Martineau { 50258eb200bdSMat Martineau if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { 50268eb200bdSMat Martineau u8 rsp_result; 50278eb200bdSMat Martineau if (result == -EINVAL) 50288eb200bdSMat Martineau rsp_result = L2CAP_MR_BAD_ID; 50298eb200bdSMat Martineau else 50308eb200bdSMat Martineau rsp_result = L2CAP_MR_NOT_ALLOWED; 50318eb200bdSMat Martineau 50328eb200bdSMat Martineau l2cap_send_move_chan_rsp(chan, rsp_result); 50338eb200bdSMat Martineau } 50348eb200bdSMat Martineau 50358eb200bdSMat Martineau chan->move_role = L2CAP_MOVE_ROLE_NONE; 50368eb200bdSMat Martineau chan->move_state = L2CAP_MOVE_STABLE; 50378eb200bdSMat Martineau 50388eb200bdSMat Martineau /* Restart data transmission */ 50398eb200bdSMat Martineau l2cap_ertm_send(chan); 50408eb200bdSMat Martineau } 50418eb200bdSMat Martineau 5042a514b17fSAndrei Emeltchenko /* Invoke with locked chan */ 5043a514b17fSAndrei Emeltchenko void __l2cap_physical_cfm(struct l2cap_chan *chan, int result) 50448eb200bdSMat Martineau { 5045770bfefaSAndrei Emeltchenko u8 local_amp_id = chan->local_amp_id; 5046fffadc08SAndrei Emeltchenko u8 remote_amp_id = chan->remote_amp_id; 5047770bfefaSAndrei Emeltchenko 50488eb200bdSMat Martineau BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d", 50498eb200bdSMat Martineau chan, result, local_amp_id, remote_amp_id); 50508eb200bdSMat Martineau 50518eb200bdSMat Martineau if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) { 50528eb200bdSMat Martineau l2cap_chan_unlock(chan); 50538eb200bdSMat Martineau return; 50548eb200bdSMat Martineau } 50558eb200bdSMat Martineau 50568eb200bdSMat Martineau if (chan->state != BT_CONNECTED) { 50578eb200bdSMat Martineau l2cap_do_create(chan, result, local_amp_id, remote_amp_id); 50588eb200bdSMat Martineau } else if (result != L2CAP_MR_SUCCESS) { 50598eb200bdSMat Martineau l2cap_do_move_cancel(chan, result); 50608eb200bdSMat Martineau } else { 50618eb200bdSMat Martineau switch (chan->move_role) { 50628eb200bdSMat Martineau case L2CAP_MOVE_ROLE_INITIATOR: 50638eb200bdSMat Martineau l2cap_do_move_initiate(chan, local_amp_id, 50648eb200bdSMat Martineau remote_amp_id); 50658eb200bdSMat Martineau break; 50668eb200bdSMat Martineau case L2CAP_MOVE_ROLE_RESPONDER: 50678eb200bdSMat Martineau l2cap_do_move_respond(chan, result); 50688eb200bdSMat Martineau break; 50698eb200bdSMat Martineau default: 50708eb200bdSMat Martineau l2cap_do_move_cancel(chan, result); 50718eb200bdSMat Martineau break; 50728eb200bdSMat Martineau } 50738eb200bdSMat Martineau } 50748eb200bdSMat Martineau } 50758eb200bdSMat Martineau 50768d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn, 5077ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5078ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 50798d5a04a1SMat Martineau { 50808d5a04a1SMat Martineau struct l2cap_move_chan_req *req = data; 50811500109bSMat Martineau struct l2cap_move_chan_rsp rsp; 508202b0fbb9SMat Martineau struct l2cap_chan *chan; 50838d5a04a1SMat Martineau u16 icid = 0; 50848d5a04a1SMat Martineau u16 result = L2CAP_MR_NOT_ALLOWED; 50858d5a04a1SMat Martineau 50868d5a04a1SMat Martineau if (cmd_len != sizeof(*req)) 50878d5a04a1SMat Martineau return -EPROTO; 50888d5a04a1SMat Martineau 50898d5a04a1SMat Martineau icid = le16_to_cpu(req->icid); 50908d5a04a1SMat Martineau 5091ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id); 50928d5a04a1SMat Martineau 5093848566b3SMarcel Holtmann if (!conn->hs_enabled) 50948d5a04a1SMat Martineau return -EINVAL; 50958d5a04a1SMat Martineau 509602b0fbb9SMat Martineau chan = l2cap_get_chan_by_dcid(conn, icid); 509702b0fbb9SMat Martineau if (!chan) { 50981500109bSMat Martineau rsp.icid = cpu_to_le16(icid); 50991500109bSMat Martineau rsp.result = __constant_cpu_to_le16(L2CAP_MR_NOT_ALLOWED); 51001500109bSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP, 51011500109bSMat Martineau sizeof(rsp), &rsp); 510202b0fbb9SMat Martineau return 0; 510302b0fbb9SMat Martineau } 510402b0fbb9SMat Martineau 51051500109bSMat Martineau chan->ident = cmd->ident; 51061500109bSMat Martineau 510702b0fbb9SMat Martineau if (chan->scid < L2CAP_CID_DYN_START || 510802b0fbb9SMat Martineau chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY || 510902b0fbb9SMat Martineau (chan->mode != L2CAP_MODE_ERTM && 511002b0fbb9SMat Martineau chan->mode != L2CAP_MODE_STREAMING)) { 511102b0fbb9SMat Martineau result = L2CAP_MR_NOT_ALLOWED; 511202b0fbb9SMat Martineau goto send_move_response; 511302b0fbb9SMat Martineau } 511402b0fbb9SMat Martineau 511502b0fbb9SMat Martineau if (chan->local_amp_id == req->dest_amp_id) { 511602b0fbb9SMat Martineau result = L2CAP_MR_SAME_ID; 511702b0fbb9SMat Martineau goto send_move_response; 511802b0fbb9SMat Martineau } 511902b0fbb9SMat Martineau 51206ed971caSMarcel Holtmann if (req->dest_amp_id != AMP_ID_BREDR) { 512102b0fbb9SMat Martineau struct hci_dev *hdev; 512202b0fbb9SMat Martineau hdev = hci_dev_get(req->dest_amp_id); 512302b0fbb9SMat Martineau if (!hdev || hdev->dev_type != HCI_AMP || 512402b0fbb9SMat Martineau !test_bit(HCI_UP, &hdev->flags)) { 512502b0fbb9SMat Martineau if (hdev) 512602b0fbb9SMat Martineau hci_dev_put(hdev); 512702b0fbb9SMat Martineau 512802b0fbb9SMat Martineau result = L2CAP_MR_BAD_ID; 512902b0fbb9SMat Martineau goto send_move_response; 513002b0fbb9SMat Martineau } 513102b0fbb9SMat Martineau hci_dev_put(hdev); 513202b0fbb9SMat Martineau } 513302b0fbb9SMat Martineau 513402b0fbb9SMat Martineau /* Detect a move collision. Only send a collision response 513502b0fbb9SMat Martineau * if this side has "lost", otherwise proceed with the move. 513602b0fbb9SMat Martineau * The winner has the larger bd_addr. 513702b0fbb9SMat Martineau */ 513802b0fbb9SMat Martineau if ((__chan_is_moving(chan) || 513902b0fbb9SMat Martineau chan->move_role != L2CAP_MOVE_ROLE_NONE) && 51406f59b904SMarcel Holtmann bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) { 514102b0fbb9SMat Martineau result = L2CAP_MR_COLLISION; 514202b0fbb9SMat Martineau goto send_move_response; 514302b0fbb9SMat Martineau } 514402b0fbb9SMat Martineau 514502b0fbb9SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; 514602b0fbb9SMat Martineau l2cap_move_setup(chan); 514702b0fbb9SMat Martineau chan->move_id = req->dest_amp_id; 514802b0fbb9SMat Martineau icid = chan->dcid; 514902b0fbb9SMat Martineau 51506ed971caSMarcel Holtmann if (req->dest_amp_id == AMP_ID_BREDR) { 515102b0fbb9SMat Martineau /* Moving to BR/EDR */ 515202b0fbb9SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 515302b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 515402b0fbb9SMat Martineau result = L2CAP_MR_PEND; 515502b0fbb9SMat Martineau } else { 515602b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; 515702b0fbb9SMat Martineau result = L2CAP_MR_SUCCESS; 515802b0fbb9SMat Martineau } 515902b0fbb9SMat Martineau } else { 516002b0fbb9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_PREPARE; 516102b0fbb9SMat Martineau /* Placeholder - uncomment when amp functions are available */ 516202b0fbb9SMat Martineau /*amp_accept_physical(chan, req->dest_amp_id);*/ 516302b0fbb9SMat Martineau result = L2CAP_MR_PEND; 516402b0fbb9SMat Martineau } 516502b0fbb9SMat Martineau 516602b0fbb9SMat Martineau send_move_response: 51671500109bSMat Martineau l2cap_send_move_chan_rsp(chan, result); 51688d5a04a1SMat Martineau 516902b0fbb9SMat Martineau l2cap_chan_unlock(chan); 517002b0fbb9SMat Martineau 51718d5a04a1SMat Martineau return 0; 51728d5a04a1SMat Martineau } 51738d5a04a1SMat Martineau 51745b155ef9SMat Martineau static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result) 51755b155ef9SMat Martineau { 51765b155ef9SMat Martineau struct l2cap_chan *chan; 51775b155ef9SMat Martineau struct hci_chan *hchan = NULL; 51785b155ef9SMat Martineau 51795b155ef9SMat Martineau chan = l2cap_get_chan_by_scid(conn, icid); 51805b155ef9SMat Martineau if (!chan) { 51815b155ef9SMat Martineau l2cap_send_move_chan_cfm_icid(conn, icid); 51825b155ef9SMat Martineau return; 51835b155ef9SMat Martineau } 51845b155ef9SMat Martineau 51855b155ef9SMat Martineau __clear_chan_timer(chan); 51865b155ef9SMat Martineau if (result == L2CAP_MR_PEND) 51875b155ef9SMat Martineau __set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT); 51885b155ef9SMat Martineau 51895b155ef9SMat Martineau switch (chan->move_state) { 51905b155ef9SMat Martineau case L2CAP_MOVE_WAIT_LOGICAL_COMP: 51915b155ef9SMat Martineau /* Move confirm will be sent when logical link 51925b155ef9SMat Martineau * is complete. 51935b155ef9SMat Martineau */ 51945b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 51955b155ef9SMat Martineau break; 51965b155ef9SMat Martineau case L2CAP_MOVE_WAIT_RSP_SUCCESS: 51975b155ef9SMat Martineau if (result == L2CAP_MR_PEND) { 51985b155ef9SMat Martineau break; 51995b155ef9SMat Martineau } else if (test_bit(CONN_LOCAL_BUSY, 52005b155ef9SMat Martineau &chan->conn_state)) { 52015b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; 52025b155ef9SMat Martineau } else { 52035b155ef9SMat Martineau /* Logical link is up or moving to BR/EDR, 52045b155ef9SMat Martineau * proceed with move 52055b155ef9SMat Martineau */ 52065b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; 52075b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 52085b155ef9SMat Martineau } 52095b155ef9SMat Martineau break; 52105b155ef9SMat Martineau case L2CAP_MOVE_WAIT_RSP: 52115b155ef9SMat Martineau /* Moving to AMP */ 52125b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS) { 52135b155ef9SMat Martineau /* Remote is ready, send confirm immediately 52145b155ef9SMat Martineau * after logical link is ready 52155b155ef9SMat Martineau */ 52165b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; 52175b155ef9SMat Martineau } else { 52185b155ef9SMat Martineau /* Both logical link and move success 52195b155ef9SMat Martineau * are required to confirm 52205b155ef9SMat Martineau */ 52215b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP; 52225b155ef9SMat Martineau } 52235b155ef9SMat Martineau 52245b155ef9SMat Martineau /* Placeholder - get hci_chan for logical link */ 52255b155ef9SMat Martineau if (!hchan) { 52265b155ef9SMat Martineau /* Logical link not available */ 52275b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 52285b155ef9SMat Martineau break; 52295b155ef9SMat Martineau } 52305b155ef9SMat Martineau 52315b155ef9SMat Martineau /* If the logical link is not yet connected, do not 52325b155ef9SMat Martineau * send confirmation. 52335b155ef9SMat Martineau */ 52345b155ef9SMat Martineau if (hchan->state != BT_CONNECTED) 52355b155ef9SMat Martineau break; 52365b155ef9SMat Martineau 52375b155ef9SMat Martineau /* Logical link is already ready to go */ 52385b155ef9SMat Martineau 52395b155ef9SMat Martineau chan->hs_hcon = hchan->conn; 52405b155ef9SMat Martineau chan->hs_hcon->l2cap_data = chan->conn; 52415b155ef9SMat Martineau 52425b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS) { 52435b155ef9SMat Martineau /* Can confirm now */ 52445b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); 52455b155ef9SMat Martineau } else { 52465b155ef9SMat Martineau /* Now only need move success 52475b155ef9SMat Martineau * to confirm 52485b155ef9SMat Martineau */ 52495b155ef9SMat Martineau chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; 52505b155ef9SMat Martineau } 52515b155ef9SMat Martineau 52525b155ef9SMat Martineau l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); 52535b155ef9SMat Martineau break; 52545b155ef9SMat Martineau default: 52555b155ef9SMat Martineau /* Any other amp move state means the move failed. */ 52565b155ef9SMat Martineau chan->move_id = chan->local_amp_id; 52575b155ef9SMat Martineau l2cap_move_done(chan); 52585b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 52595b155ef9SMat Martineau } 52605b155ef9SMat Martineau 52615b155ef9SMat Martineau l2cap_chan_unlock(chan); 52625b155ef9SMat Martineau } 52635b155ef9SMat Martineau 52645b155ef9SMat Martineau static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid, 52655b155ef9SMat Martineau u16 result) 52665b155ef9SMat Martineau { 52675b155ef9SMat Martineau struct l2cap_chan *chan; 52685b155ef9SMat Martineau 52695b155ef9SMat Martineau chan = l2cap_get_chan_by_ident(conn, ident); 52705b155ef9SMat Martineau if (!chan) { 52715b155ef9SMat Martineau /* Could not locate channel, icid is best guess */ 52725b155ef9SMat Martineau l2cap_send_move_chan_cfm_icid(conn, icid); 52735b155ef9SMat Martineau return; 52745b155ef9SMat Martineau } 52755b155ef9SMat Martineau 52765b155ef9SMat Martineau __clear_chan_timer(chan); 52775b155ef9SMat Martineau 52785b155ef9SMat Martineau if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { 52795b155ef9SMat Martineau if (result == L2CAP_MR_COLLISION) { 52805b155ef9SMat Martineau chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; 52815b155ef9SMat Martineau } else { 52825b155ef9SMat Martineau /* Cleanup - cancel move */ 52835b155ef9SMat Martineau chan->move_id = chan->local_amp_id; 52845b155ef9SMat Martineau l2cap_move_done(chan); 52855b155ef9SMat Martineau } 52865b155ef9SMat Martineau } 52875b155ef9SMat Martineau 52885b155ef9SMat Martineau l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); 52895b155ef9SMat Martineau 52905b155ef9SMat Martineau l2cap_chan_unlock(chan); 52915b155ef9SMat Martineau } 52925b155ef9SMat Martineau 52935b155ef9SMat Martineau static int l2cap_move_channel_rsp(struct l2cap_conn *conn, 5294ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5295ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 52968d5a04a1SMat Martineau { 52978d5a04a1SMat Martineau struct l2cap_move_chan_rsp *rsp = data; 52988d5a04a1SMat Martineau u16 icid, result; 52998d5a04a1SMat Martineau 53008d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 53018d5a04a1SMat Martineau return -EPROTO; 53028d5a04a1SMat Martineau 53038d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 53048d5a04a1SMat Martineau result = le16_to_cpu(rsp->result); 53058d5a04a1SMat Martineau 5306ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 53078d5a04a1SMat Martineau 53085b155ef9SMat Martineau if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND) 53095b155ef9SMat Martineau l2cap_move_continue(conn, icid, result); 53105b155ef9SMat Martineau else 53115b155ef9SMat Martineau l2cap_move_fail(conn, cmd->ident, icid, result); 53128d5a04a1SMat Martineau 53138d5a04a1SMat Martineau return 0; 53148d5a04a1SMat Martineau } 53158d5a04a1SMat Martineau 53165f3847a4SMat Martineau static int l2cap_move_channel_confirm(struct l2cap_conn *conn, 5317ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5318ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 53198d5a04a1SMat Martineau { 53208d5a04a1SMat Martineau struct l2cap_move_chan_cfm *cfm = data; 53215f3847a4SMat Martineau struct l2cap_chan *chan; 53228d5a04a1SMat Martineau u16 icid, result; 53238d5a04a1SMat Martineau 53248d5a04a1SMat Martineau if (cmd_len != sizeof(*cfm)) 53258d5a04a1SMat Martineau return -EPROTO; 53268d5a04a1SMat Martineau 53278d5a04a1SMat Martineau icid = le16_to_cpu(cfm->icid); 53288d5a04a1SMat Martineau result = le16_to_cpu(cfm->result); 53298d5a04a1SMat Martineau 5330ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 53318d5a04a1SMat Martineau 53325f3847a4SMat Martineau chan = l2cap_get_chan_by_dcid(conn, icid); 53335f3847a4SMat Martineau if (!chan) { 53345f3847a4SMat Martineau /* Spec requires a response even if the icid was not found */ 53358d5a04a1SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 53365f3847a4SMat Martineau return 0; 53375f3847a4SMat Martineau } 53385f3847a4SMat Martineau 53395f3847a4SMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) { 53405f3847a4SMat Martineau if (result == L2CAP_MC_CONFIRMED) { 53415f3847a4SMat Martineau chan->local_amp_id = chan->move_id; 53426ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR) 53435f3847a4SMat Martineau __release_logical_link(chan); 53445f3847a4SMat Martineau } else { 53455f3847a4SMat Martineau chan->move_id = chan->local_amp_id; 53465f3847a4SMat Martineau } 53475f3847a4SMat Martineau 53485f3847a4SMat Martineau l2cap_move_done(chan); 53495f3847a4SMat Martineau } 53505f3847a4SMat Martineau 53515f3847a4SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 53525f3847a4SMat Martineau 53535f3847a4SMat Martineau l2cap_chan_unlock(chan); 53548d5a04a1SMat Martineau 53558d5a04a1SMat Martineau return 0; 53568d5a04a1SMat Martineau } 53578d5a04a1SMat Martineau 53588d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, 5359ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 5360ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 53618d5a04a1SMat Martineau { 53628d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp *rsp = data; 53633fd71a0aSMat Martineau struct l2cap_chan *chan; 53648d5a04a1SMat Martineau u16 icid; 53658d5a04a1SMat Martineau 53668d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 53678d5a04a1SMat Martineau return -EPROTO; 53688d5a04a1SMat Martineau 53698d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 53708d5a04a1SMat Martineau 5371ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 53728d5a04a1SMat Martineau 53733fd71a0aSMat Martineau chan = l2cap_get_chan_by_scid(conn, icid); 53743fd71a0aSMat Martineau if (!chan) 53753fd71a0aSMat Martineau return 0; 53763fd71a0aSMat Martineau 53773fd71a0aSMat Martineau __clear_chan_timer(chan); 53783fd71a0aSMat Martineau 53793fd71a0aSMat Martineau if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) { 53803fd71a0aSMat Martineau chan->local_amp_id = chan->move_id; 53813fd71a0aSMat Martineau 53826ed971caSMarcel Holtmann if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan) 53833fd71a0aSMat Martineau __release_logical_link(chan); 53843fd71a0aSMat Martineau 53853fd71a0aSMat Martineau l2cap_move_done(chan); 53863fd71a0aSMat Martineau } 53873fd71a0aSMat Martineau 53883fd71a0aSMat Martineau l2cap_chan_unlock(chan); 53893fd71a0aSMat Martineau 53908d5a04a1SMat Martineau return 0; 53918d5a04a1SMat Martineau } 53928d5a04a1SMat Martineau 5393e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency, 5394de73115aSClaudio Takahasi u16 to_multiplier) 5395de73115aSClaudio Takahasi { 5396de73115aSClaudio Takahasi u16 max_latency; 5397de73115aSClaudio Takahasi 5398de73115aSClaudio Takahasi if (min > max || min < 6 || max > 3200) 5399de73115aSClaudio Takahasi return -EINVAL; 5400de73115aSClaudio Takahasi 5401de73115aSClaudio Takahasi if (to_multiplier < 10 || to_multiplier > 3200) 5402de73115aSClaudio Takahasi return -EINVAL; 5403de73115aSClaudio Takahasi 5404de73115aSClaudio Takahasi if (max >= to_multiplier * 8) 5405de73115aSClaudio Takahasi return -EINVAL; 5406de73115aSClaudio Takahasi 5407de73115aSClaudio Takahasi max_latency = (to_multiplier * 8 / max) - 1; 5408de73115aSClaudio Takahasi if (latency > 499 || latency > max_latency) 5409de73115aSClaudio Takahasi return -EINVAL; 5410de73115aSClaudio Takahasi 5411de73115aSClaudio Takahasi return 0; 5412de73115aSClaudio Takahasi } 5413de73115aSClaudio Takahasi 5414de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, 54152d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, 5416203e639eSJohan Hedberg u16 cmd_len, u8 *data) 5417de73115aSClaudio Takahasi { 5418de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon; 5419de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req; 5420de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp; 5421203e639eSJohan Hedberg u16 min, max, latency, to_multiplier; 54222ce603ebSClaudio Takahasi int err; 5423de73115aSClaudio Takahasi 5424de73115aSClaudio Takahasi if (!(hcon->link_mode & HCI_LM_MASTER)) 5425de73115aSClaudio Takahasi return -EINVAL; 5426de73115aSClaudio Takahasi 5427de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) 5428de73115aSClaudio Takahasi return -EPROTO; 5429de73115aSClaudio Takahasi 5430de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data; 5431de73115aSClaudio Takahasi min = __le16_to_cpu(req->min); 5432de73115aSClaudio Takahasi max = __le16_to_cpu(req->max); 5433de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency); 5434de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier); 5435de73115aSClaudio Takahasi 5436de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", 5437de73115aSClaudio Takahasi min, max, latency, to_multiplier); 5438de73115aSClaudio Takahasi 5439de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp)); 54402ce603ebSClaudio Takahasi 54412ce603ebSClaudio Takahasi err = l2cap_check_conn_param(min, max, latency, to_multiplier); 54422ce603ebSClaudio Takahasi if (err) 5443ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); 5444de73115aSClaudio Takahasi else 5445ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); 5446de73115aSClaudio Takahasi 5447de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, 5448de73115aSClaudio Takahasi sizeof(rsp), &rsp); 5449de73115aSClaudio Takahasi 54502ce603ebSClaudio Takahasi if (!err) 54512ce603ebSClaudio Takahasi hci_le_conn_update(hcon, min, max, latency, to_multiplier); 54522ce603ebSClaudio Takahasi 5453de73115aSClaudio Takahasi return 0; 5454de73115aSClaudio Takahasi } 5455de73115aSClaudio Takahasi 5456f1496deeSJohan Hedberg static int l2cap_le_connect_rsp(struct l2cap_conn *conn, 5457f1496deeSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5458f1496deeSJohan Hedberg u8 *data) 5459f1496deeSJohan Hedberg { 5460f1496deeSJohan Hedberg struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data; 5461f1496deeSJohan Hedberg u16 dcid, mtu, mps, credits, result; 5462f1496deeSJohan Hedberg struct l2cap_chan *chan; 5463f1496deeSJohan Hedberg int err; 5464f1496deeSJohan Hedberg 5465f1496deeSJohan Hedberg if (cmd_len < sizeof(*rsp)) 5466f1496deeSJohan Hedberg return -EPROTO; 5467f1496deeSJohan Hedberg 5468f1496deeSJohan Hedberg dcid = __le16_to_cpu(rsp->dcid); 5469f1496deeSJohan Hedberg mtu = __le16_to_cpu(rsp->mtu); 5470f1496deeSJohan Hedberg mps = __le16_to_cpu(rsp->mps); 5471f1496deeSJohan Hedberg credits = __le16_to_cpu(rsp->credits); 5472f1496deeSJohan Hedberg result = __le16_to_cpu(rsp->result); 5473f1496deeSJohan Hedberg 5474f1496deeSJohan Hedberg if (result == L2CAP_CR_SUCCESS && (mtu < 23 || mps < 23)) 5475f1496deeSJohan Hedberg return -EPROTO; 5476f1496deeSJohan Hedberg 5477f1496deeSJohan Hedberg BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x", 5478f1496deeSJohan Hedberg dcid, mtu, mps, credits, result); 5479f1496deeSJohan Hedberg 5480f1496deeSJohan Hedberg mutex_lock(&conn->chan_lock); 5481f1496deeSJohan Hedberg 5482f1496deeSJohan Hedberg chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 5483f1496deeSJohan Hedberg if (!chan) { 5484f1496deeSJohan Hedberg err = -EBADSLT; 5485f1496deeSJohan Hedberg goto unlock; 5486f1496deeSJohan Hedberg } 5487f1496deeSJohan Hedberg 5488f1496deeSJohan Hedberg err = 0; 5489f1496deeSJohan Hedberg 5490f1496deeSJohan Hedberg l2cap_chan_lock(chan); 5491f1496deeSJohan Hedberg 5492f1496deeSJohan Hedberg switch (result) { 5493f1496deeSJohan Hedberg case L2CAP_CR_SUCCESS: 5494f1496deeSJohan Hedberg chan->ident = 0; 5495f1496deeSJohan Hedberg chan->dcid = dcid; 5496f1496deeSJohan Hedberg chan->omtu = mtu; 5497f1496deeSJohan Hedberg chan->remote_mps = mps; 54980cd75f7eSJohan Hedberg chan->tx_credits = credits; 5499f1496deeSJohan Hedberg l2cap_chan_ready(chan); 5500f1496deeSJohan Hedberg break; 5501f1496deeSJohan Hedberg 5502f1496deeSJohan Hedberg default: 5503f1496deeSJohan Hedberg l2cap_chan_del(chan, ECONNREFUSED); 5504f1496deeSJohan Hedberg break; 5505f1496deeSJohan Hedberg } 5506f1496deeSJohan Hedberg 5507f1496deeSJohan Hedberg l2cap_chan_unlock(chan); 5508f1496deeSJohan Hedberg 5509f1496deeSJohan Hedberg unlock: 5510f1496deeSJohan Hedberg mutex_unlock(&conn->chan_lock); 5511f1496deeSJohan Hedberg 5512f1496deeSJohan Hedberg return err; 5513f1496deeSJohan Hedberg } 5514f1496deeSJohan Hedberg 55153300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, 55162d792818SGustavo Padovan struct l2cap_cmd_hdr *cmd, u16 cmd_len, 55172d792818SGustavo Padovan u8 *data) 55183300d9a9SClaudio Takahasi { 55193300d9a9SClaudio Takahasi int err = 0; 55203300d9a9SClaudio Takahasi 55213300d9a9SClaudio Takahasi switch (cmd->code) { 55223300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 5523cb3b3152SJohan Hedberg l2cap_command_rej(conn, cmd, cmd_len, data); 55243300d9a9SClaudio Takahasi break; 55253300d9a9SClaudio Takahasi 55263300d9a9SClaudio Takahasi case L2CAP_CONN_REQ: 5527cb3b3152SJohan Hedberg err = l2cap_connect_req(conn, cmd, cmd_len, data); 55283300d9a9SClaudio Takahasi break; 55293300d9a9SClaudio Takahasi 55303300d9a9SClaudio Takahasi case L2CAP_CONN_RSP: 5531f5a2598dSMat Martineau case L2CAP_CREATE_CHAN_RSP: 55329245e737SJohan Hedberg l2cap_connect_create_rsp(conn, cmd, cmd_len, data); 55333300d9a9SClaudio Takahasi break; 55343300d9a9SClaudio Takahasi 55353300d9a9SClaudio Takahasi case L2CAP_CONF_REQ: 55363300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data); 55373300d9a9SClaudio Takahasi break; 55383300d9a9SClaudio Takahasi 55393300d9a9SClaudio Takahasi case L2CAP_CONF_RSP: 55409245e737SJohan Hedberg l2cap_config_rsp(conn, cmd, cmd_len, data); 55413300d9a9SClaudio Takahasi break; 55423300d9a9SClaudio Takahasi 55433300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ: 5544cb3b3152SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data); 55453300d9a9SClaudio Takahasi break; 55463300d9a9SClaudio Takahasi 55473300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP: 55489245e737SJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data); 55493300d9a9SClaudio Takahasi break; 55503300d9a9SClaudio Takahasi 55513300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ: 55523300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data); 55533300d9a9SClaudio Takahasi break; 55543300d9a9SClaudio Takahasi 55553300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP: 55563300d9a9SClaudio Takahasi break; 55573300d9a9SClaudio Takahasi 55583300d9a9SClaudio Takahasi case L2CAP_INFO_REQ: 5559cb3b3152SJohan Hedberg err = l2cap_information_req(conn, cmd, cmd_len, data); 55603300d9a9SClaudio Takahasi break; 55613300d9a9SClaudio Takahasi 55623300d9a9SClaudio Takahasi case L2CAP_INFO_RSP: 55639245e737SJohan Hedberg l2cap_information_rsp(conn, cmd, cmd_len, data); 55643300d9a9SClaudio Takahasi break; 55653300d9a9SClaudio Takahasi 5566f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_REQ: 5567f94ff6ffSMat Martineau err = l2cap_create_channel_req(conn, cmd, cmd_len, data); 5568f94ff6ffSMat Martineau break; 5569f94ff6ffSMat Martineau 55708d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_REQ: 55718d5a04a1SMat Martineau err = l2cap_move_channel_req(conn, cmd, cmd_len, data); 55728d5a04a1SMat Martineau break; 55738d5a04a1SMat Martineau 55748d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_RSP: 55759245e737SJohan Hedberg l2cap_move_channel_rsp(conn, cmd, cmd_len, data); 55768d5a04a1SMat Martineau break; 55778d5a04a1SMat Martineau 55788d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM: 55798d5a04a1SMat Martineau err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data); 55808d5a04a1SMat Martineau break; 55818d5a04a1SMat Martineau 55828d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM_RSP: 55839245e737SJohan Hedberg l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data); 55848d5a04a1SMat Martineau break; 55858d5a04a1SMat Martineau 55863300d9a9SClaudio Takahasi default: 55873300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code); 55883300d9a9SClaudio Takahasi err = -EINVAL; 55893300d9a9SClaudio Takahasi break; 55903300d9a9SClaudio Takahasi } 55913300d9a9SClaudio Takahasi 55923300d9a9SClaudio Takahasi return err; 55933300d9a9SClaudio Takahasi } 55943300d9a9SClaudio Takahasi 559527e2d4c8SJohan Hedberg static int l2cap_le_connect_req(struct l2cap_conn *conn, 559627e2d4c8SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 559727e2d4c8SJohan Hedberg u8 *data) 559827e2d4c8SJohan Hedberg { 559927e2d4c8SJohan Hedberg struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data; 560027e2d4c8SJohan Hedberg struct l2cap_le_conn_rsp rsp; 560127e2d4c8SJohan Hedberg struct l2cap_chan *chan, *pchan; 56020cd75f7eSJohan Hedberg u16 dcid, scid, credits, mtu, mps; 560327e2d4c8SJohan Hedberg __le16 psm; 560427e2d4c8SJohan Hedberg u8 result; 560527e2d4c8SJohan Hedberg 560627e2d4c8SJohan Hedberg if (cmd_len != sizeof(*req)) 560727e2d4c8SJohan Hedberg return -EPROTO; 560827e2d4c8SJohan Hedberg 560927e2d4c8SJohan Hedberg scid = __le16_to_cpu(req->scid); 561027e2d4c8SJohan Hedberg mtu = __le16_to_cpu(req->mtu); 561127e2d4c8SJohan Hedberg mps = __le16_to_cpu(req->mps); 561227e2d4c8SJohan Hedberg psm = req->psm; 561327e2d4c8SJohan Hedberg dcid = 0; 56140cd75f7eSJohan Hedberg credits = 0; 561527e2d4c8SJohan Hedberg 561627e2d4c8SJohan Hedberg if (mtu < 23 || mps < 23) 561727e2d4c8SJohan Hedberg return -EPROTO; 561827e2d4c8SJohan Hedberg 561927e2d4c8SJohan Hedberg BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm), 562027e2d4c8SJohan Hedberg scid, mtu, mps); 562127e2d4c8SJohan Hedberg 562227e2d4c8SJohan Hedberg /* Check if we have socket listening on psm */ 562327e2d4c8SJohan Hedberg pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 562427e2d4c8SJohan Hedberg &conn->hcon->dst, LE_LINK); 562527e2d4c8SJohan Hedberg if (!pchan) { 562627e2d4c8SJohan Hedberg result = L2CAP_CR_BAD_PSM; 562727e2d4c8SJohan Hedberg chan = NULL; 562827e2d4c8SJohan Hedberg goto response; 562927e2d4c8SJohan Hedberg } 563027e2d4c8SJohan Hedberg 563127e2d4c8SJohan Hedberg mutex_lock(&conn->chan_lock); 563227e2d4c8SJohan Hedberg l2cap_chan_lock(pchan); 563327e2d4c8SJohan Hedberg 563427e2d4c8SJohan Hedberg if (!smp_sufficient_security(conn->hcon, pchan->sec_level)) { 563527e2d4c8SJohan Hedberg result = L2CAP_CR_AUTHENTICATION; 563627e2d4c8SJohan Hedberg chan = NULL; 563727e2d4c8SJohan Hedberg goto response_unlock; 563827e2d4c8SJohan Hedberg } 563927e2d4c8SJohan Hedberg 564027e2d4c8SJohan Hedberg /* Check if we already have channel with that dcid */ 564127e2d4c8SJohan Hedberg if (__l2cap_get_chan_by_dcid(conn, scid)) { 564227e2d4c8SJohan Hedberg result = L2CAP_CR_NO_MEM; 564327e2d4c8SJohan Hedberg chan = NULL; 564427e2d4c8SJohan Hedberg goto response_unlock; 564527e2d4c8SJohan Hedberg } 564627e2d4c8SJohan Hedberg 564727e2d4c8SJohan Hedberg chan = pchan->ops->new_connection(pchan); 564827e2d4c8SJohan Hedberg if (!chan) { 564927e2d4c8SJohan Hedberg result = L2CAP_CR_NO_MEM; 565027e2d4c8SJohan Hedberg goto response_unlock; 565127e2d4c8SJohan Hedberg } 565227e2d4c8SJohan Hedberg 56530ce43ce6SJohan Hedberg l2cap_le_flowctl_init(chan); 56540ce43ce6SJohan Hedberg 565527e2d4c8SJohan Hedberg bacpy(&chan->src, &conn->hcon->src); 565627e2d4c8SJohan Hedberg bacpy(&chan->dst, &conn->hcon->dst); 565727e2d4c8SJohan Hedberg chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type); 565827e2d4c8SJohan Hedberg chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type); 565927e2d4c8SJohan Hedberg chan->psm = psm; 566027e2d4c8SJohan Hedberg chan->dcid = scid; 566127e2d4c8SJohan Hedberg chan->omtu = mtu; 566227e2d4c8SJohan Hedberg chan->remote_mps = mps; 56630cd75f7eSJohan Hedberg chan->tx_credits = __le16_to_cpu(req->credits); 566427e2d4c8SJohan Hedberg 566527e2d4c8SJohan Hedberg __l2cap_chan_add(conn, chan); 566627e2d4c8SJohan Hedberg dcid = chan->scid; 56670cd75f7eSJohan Hedberg credits = chan->rx_credits; 566827e2d4c8SJohan Hedberg 566927e2d4c8SJohan Hedberg __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); 567027e2d4c8SJohan Hedberg 567127e2d4c8SJohan Hedberg chan->ident = cmd->ident; 567227e2d4c8SJohan Hedberg 567327e2d4c8SJohan Hedberg if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 567427e2d4c8SJohan Hedberg l2cap_state_change(chan, BT_CONNECT2); 567527e2d4c8SJohan Hedberg result = L2CAP_CR_PEND; 567627e2d4c8SJohan Hedberg chan->ops->defer(chan); 567727e2d4c8SJohan Hedberg } else { 567827e2d4c8SJohan Hedberg l2cap_chan_ready(chan); 567927e2d4c8SJohan Hedberg result = L2CAP_CR_SUCCESS; 568027e2d4c8SJohan Hedberg } 568127e2d4c8SJohan Hedberg 568227e2d4c8SJohan Hedberg response_unlock: 568327e2d4c8SJohan Hedberg l2cap_chan_unlock(pchan); 568427e2d4c8SJohan Hedberg mutex_unlock(&conn->chan_lock); 568527e2d4c8SJohan Hedberg 568627e2d4c8SJohan Hedberg if (result == L2CAP_CR_PEND) 568727e2d4c8SJohan Hedberg return 0; 568827e2d4c8SJohan Hedberg 568927e2d4c8SJohan Hedberg response: 569027e2d4c8SJohan Hedberg if (chan) { 569127e2d4c8SJohan Hedberg rsp.mtu = cpu_to_le16(chan->imtu); 56923916aed8SJohan Hedberg rsp.mps = cpu_to_le16(chan->mps); 569327e2d4c8SJohan Hedberg } else { 569427e2d4c8SJohan Hedberg rsp.mtu = 0; 569527e2d4c8SJohan Hedberg rsp.mps = 0; 569627e2d4c8SJohan Hedberg } 569727e2d4c8SJohan Hedberg 569827e2d4c8SJohan Hedberg rsp.dcid = cpu_to_le16(dcid); 56990cd75f7eSJohan Hedberg rsp.credits = cpu_to_le16(credits); 570027e2d4c8SJohan Hedberg rsp.result = cpu_to_le16(result); 570127e2d4c8SJohan Hedberg 570227e2d4c8SJohan Hedberg l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp); 570327e2d4c8SJohan Hedberg 570427e2d4c8SJohan Hedberg return 0; 570527e2d4c8SJohan Hedberg } 570627e2d4c8SJohan Hedberg 5707fad5fc89SJohan Hedberg static inline int l2cap_le_credits(struct l2cap_conn *conn, 5708fad5fc89SJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5709fad5fc89SJohan Hedberg u8 *data) 5710fad5fc89SJohan Hedberg { 5711fad5fc89SJohan Hedberg struct l2cap_le_credits *pkt; 5712fad5fc89SJohan Hedberg struct l2cap_chan *chan; 5713fad5fc89SJohan Hedberg u16 cid, credits; 5714fad5fc89SJohan Hedberg 5715fad5fc89SJohan Hedberg if (cmd_len != sizeof(*pkt)) 5716fad5fc89SJohan Hedberg return -EPROTO; 5717fad5fc89SJohan Hedberg 5718fad5fc89SJohan Hedberg pkt = (struct l2cap_le_credits *) data; 5719fad5fc89SJohan Hedberg cid = __le16_to_cpu(pkt->cid); 5720fad5fc89SJohan Hedberg credits = __le16_to_cpu(pkt->credits); 5721fad5fc89SJohan Hedberg 5722fad5fc89SJohan Hedberg BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits); 5723fad5fc89SJohan Hedberg 5724fad5fc89SJohan Hedberg chan = l2cap_get_chan_by_dcid(conn, cid); 5725fad5fc89SJohan Hedberg if (!chan) 5726fad5fc89SJohan Hedberg return -EBADSLT; 5727fad5fc89SJohan Hedberg 5728fad5fc89SJohan Hedberg chan->tx_credits += credits; 5729fad5fc89SJohan Hedberg 5730fad5fc89SJohan Hedberg while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) { 5731fad5fc89SJohan Hedberg l2cap_do_send(chan, skb_dequeue(&chan->tx_q)); 5732fad5fc89SJohan Hedberg chan->tx_credits--; 5733fad5fc89SJohan Hedberg } 5734fad5fc89SJohan Hedberg 5735fad5fc89SJohan Hedberg if (chan->tx_credits) 5736fad5fc89SJohan Hedberg chan->ops->resume(chan); 5737fad5fc89SJohan Hedberg 5738fad5fc89SJohan Hedberg l2cap_chan_unlock(chan); 5739fad5fc89SJohan Hedberg 5740fad5fc89SJohan Hedberg return 0; 5741fad5fc89SJohan Hedberg } 5742fad5fc89SJohan Hedberg 57433300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, 5744203e639eSJohan Hedberg struct l2cap_cmd_hdr *cmd, u16 cmd_len, 5745203e639eSJohan Hedberg u8 *data) 57463300d9a9SClaudio Takahasi { 5747b5ecba64SJohan Hedberg int err = 0; 5748b5ecba64SJohan Hedberg 57493af8ace6SJohan Hedberg if (!enable_lecoc) { 57503af8ace6SJohan Hedberg switch (cmd->code) { 57513af8ace6SJohan Hedberg case L2CAP_LE_CONN_REQ: 57523af8ace6SJohan Hedberg case L2CAP_LE_CONN_RSP: 57533af8ace6SJohan Hedberg case L2CAP_LE_CREDITS: 57543af8ace6SJohan Hedberg case L2CAP_DISCONN_REQ: 57553af8ace6SJohan Hedberg case L2CAP_DISCONN_RSP: 57563af8ace6SJohan Hedberg return -EINVAL; 57573af8ace6SJohan Hedberg } 57583af8ace6SJohan Hedberg } 57593af8ace6SJohan Hedberg 57603300d9a9SClaudio Takahasi switch (cmd->code) { 57613300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 5762b5ecba64SJohan Hedberg break; 57633300d9a9SClaudio Takahasi 57643300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ: 5765b5ecba64SJohan Hedberg err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data); 5766b5ecba64SJohan Hedberg break; 57673300d9a9SClaudio Takahasi 57683300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP: 5769b5ecba64SJohan Hedberg break; 57703300d9a9SClaudio Takahasi 5771f1496deeSJohan Hedberg case L2CAP_LE_CONN_RSP: 5772f1496deeSJohan Hedberg l2cap_le_connect_rsp(conn, cmd, cmd_len, data); 5773b5ecba64SJohan Hedberg break; 5774f1496deeSJohan Hedberg 577527e2d4c8SJohan Hedberg case L2CAP_LE_CONN_REQ: 5776b5ecba64SJohan Hedberg err = l2cap_le_connect_req(conn, cmd, cmd_len, data); 5777b5ecba64SJohan Hedberg break; 577827e2d4c8SJohan Hedberg 5779fad5fc89SJohan Hedberg case L2CAP_LE_CREDITS: 5780fad5fc89SJohan Hedberg err = l2cap_le_credits(conn, cmd, cmd_len, data); 5781fad5fc89SJohan Hedberg break; 5782fad5fc89SJohan Hedberg 57833defe01aSJohan Hedberg case L2CAP_DISCONN_REQ: 5784b5ecba64SJohan Hedberg err = l2cap_disconnect_req(conn, cmd, cmd_len, data); 5785b5ecba64SJohan Hedberg break; 57863defe01aSJohan Hedberg 57873defe01aSJohan Hedberg case L2CAP_DISCONN_RSP: 57883defe01aSJohan Hedberg l2cap_disconnect_rsp(conn, cmd, cmd_len, data); 5789b5ecba64SJohan Hedberg break; 57903defe01aSJohan Hedberg 57913300d9a9SClaudio Takahasi default: 57923300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code); 5793b5ecba64SJohan Hedberg err = -EINVAL; 5794b5ecba64SJohan Hedberg break; 57953300d9a9SClaudio Takahasi } 5796b5ecba64SJohan Hedberg 5797b5ecba64SJohan Hedberg return err; 57983300d9a9SClaudio Takahasi } 57993300d9a9SClaudio Takahasi 5800c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn, 5801c5623556SJohan Hedberg struct sk_buff *skb) 5802c5623556SJohan Hedberg { 580369c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon; 58044f3e219dSMarcel Holtmann struct l2cap_cmd_hdr *cmd; 58054f3e219dSMarcel Holtmann u16 len; 5806c5623556SJohan Hedberg int err; 5807c5623556SJohan Hedberg 580869c4e4e8SJohan Hedberg if (hcon->type != LE_LINK) 58093b166295SMarcel Holtmann goto drop; 581069c4e4e8SJohan Hedberg 58114f3e219dSMarcel Holtmann if (skb->len < L2CAP_CMD_HDR_SIZE) 58124f3e219dSMarcel Holtmann goto drop; 5813c5623556SJohan Hedberg 58144f3e219dSMarcel Holtmann cmd = (void *) skb->data; 58154f3e219dSMarcel Holtmann skb_pull(skb, L2CAP_CMD_HDR_SIZE); 5816c5623556SJohan Hedberg 58174f3e219dSMarcel Holtmann len = le16_to_cpu(cmd->len); 5818c5623556SJohan Hedberg 58194f3e219dSMarcel Holtmann BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident); 58204f3e219dSMarcel Holtmann 58214f3e219dSMarcel Holtmann if (len != skb->len || !cmd->ident) { 5822c5623556SJohan Hedberg BT_DBG("corrupted command"); 58234f3e219dSMarcel Holtmann goto drop; 5824c5623556SJohan Hedberg } 5825c5623556SJohan Hedberg 5826203e639eSJohan Hedberg err = l2cap_le_sig_cmd(conn, cmd, len, skb->data); 5827c5623556SJohan Hedberg if (err) { 5828c5623556SJohan Hedberg struct l2cap_cmd_rej_unk rej; 5829c5623556SJohan Hedberg 5830c5623556SJohan Hedberg BT_ERR("Wrong link type (%d)", err); 5831c5623556SJohan Hedberg 5832a521149aSJohan Hedberg rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 58334f3e219dSMarcel Holtmann l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 5834c5623556SJohan Hedberg sizeof(rej), &rej); 5835c5623556SJohan Hedberg } 5836c5623556SJohan Hedberg 58373b166295SMarcel Holtmann drop: 5838c5623556SJohan Hedberg kfree_skb(skb); 5839c5623556SJohan Hedberg } 5840c5623556SJohan Hedberg 58413300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn, 58423300d9a9SClaudio Takahasi struct sk_buff *skb) 58430a708f8fSGustavo F. Padovan { 584469c4e4e8SJohan Hedberg struct hci_conn *hcon = conn->hcon; 58450a708f8fSGustavo F. Padovan u8 *data = skb->data; 58460a708f8fSGustavo F. Padovan int len = skb->len; 58470a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr cmd; 58483300d9a9SClaudio Takahasi int err; 58490a708f8fSGustavo F. Padovan 58500a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb); 58510a708f8fSGustavo F. Padovan 585269c4e4e8SJohan Hedberg if (hcon->type != ACL_LINK) 58533b166295SMarcel Holtmann goto drop; 585469c4e4e8SJohan Hedberg 58550a708f8fSGustavo F. Padovan while (len >= L2CAP_CMD_HDR_SIZE) { 58560a708f8fSGustavo F. Padovan u16 cmd_len; 58570a708f8fSGustavo F. Padovan memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); 58580a708f8fSGustavo F. Padovan data += L2CAP_CMD_HDR_SIZE; 58590a708f8fSGustavo F. Padovan len -= L2CAP_CMD_HDR_SIZE; 58600a708f8fSGustavo F. Padovan 58610a708f8fSGustavo F. Padovan cmd_len = le16_to_cpu(cmd.len); 58620a708f8fSGustavo F. Padovan 58632d792818SGustavo Padovan BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, 58642d792818SGustavo Padovan cmd.ident); 58650a708f8fSGustavo F. Padovan 58660a708f8fSGustavo F. Padovan if (cmd_len > len || !cmd.ident) { 58670a708f8fSGustavo F. Padovan BT_DBG("corrupted command"); 58680a708f8fSGustavo F. Padovan break; 58690a708f8fSGustavo F. Padovan } 58700a708f8fSGustavo F. Padovan 58713300d9a9SClaudio Takahasi err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data); 58720a708f8fSGustavo F. Padovan if (err) { 5873e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk rej; 58742c6d1a2eSGustavo F. Padovan 58752c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err); 58760a708f8fSGustavo F. Padovan 5877a521149aSJohan Hedberg rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 58782d792818SGustavo Padovan l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, 58792d792818SGustavo Padovan sizeof(rej), &rej); 58800a708f8fSGustavo F. Padovan } 58810a708f8fSGustavo F. Padovan 58820a708f8fSGustavo F. Padovan data += cmd_len; 58830a708f8fSGustavo F. Padovan len -= cmd_len; 58840a708f8fSGustavo F. Padovan } 58850a708f8fSGustavo F. Padovan 58863b166295SMarcel Holtmann drop: 58870a708f8fSGustavo F. Padovan kfree_skb(skb); 58880a708f8fSGustavo F. Padovan } 58890a708f8fSGustavo F. Padovan 589047d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) 58910a708f8fSGustavo F. Padovan { 58920a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs; 5893e4ca6d98SAndrei Emeltchenko int hdr_size; 5894e4ca6d98SAndrei Emeltchenko 5895e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 5896e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE; 5897e4ca6d98SAndrei Emeltchenko else 5898e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE; 58990a708f8fSGustavo F. Padovan 590047d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 590103a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE); 59020a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len); 59030a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); 59040a708f8fSGustavo F. Padovan 59050a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs) 59060a708f8fSGustavo F. Padovan return -EBADMSG; 59070a708f8fSGustavo F. Padovan } 59080a708f8fSGustavo F. Padovan return 0; 59090a708f8fSGustavo F. Padovan } 59100a708f8fSGustavo F. Padovan 59116ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) 59120a708f8fSGustavo F. Padovan { 5913e31f7633SMat Martineau struct l2cap_ctrl control; 59140a708f8fSGustavo F. Padovan 5915e31f7633SMat Martineau BT_DBG("chan %p", chan); 59160a708f8fSGustavo F. Padovan 5917e31f7633SMat Martineau memset(&control, 0, sizeof(control)); 5918e31f7633SMat Martineau control.sframe = 1; 5919e31f7633SMat Martineau control.final = 1; 5920e31f7633SMat Martineau control.reqseq = chan->buffer_seq; 5921e31f7633SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 59220a708f8fSGustavo F. Padovan 5923e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 5924e31f7633SMat Martineau control.super = L2CAP_SUPER_RNR; 5925e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 59260a708f8fSGustavo F. Padovan } 59270a708f8fSGustavo F. Padovan 5928e31f7633SMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 5929e31f7633SMat Martineau chan->unacked_frames > 0) 5930e31f7633SMat Martineau __set_retrans_timer(chan); 59310a708f8fSGustavo F. Padovan 5932e31f7633SMat Martineau /* Send pending iframes */ 5933525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 59340a708f8fSGustavo F. Padovan 5935e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 5936e31f7633SMat Martineau test_bit(CONN_SEND_FBIT, &chan->conn_state)) { 5937e31f7633SMat Martineau /* F-bit wasn't sent in an s-frame or i-frame yet, so 5938e31f7633SMat Martineau * send it now. 5939e31f7633SMat Martineau */ 5940e31f7633SMat Martineau control.super = L2CAP_SUPER_RR; 5941e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 59420a708f8fSGustavo F. Padovan } 59430a708f8fSGustavo F. Padovan } 59440a708f8fSGustavo F. Padovan 59452d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag, 59462d792818SGustavo Padovan struct sk_buff **last_frag) 59470a708f8fSGustavo F. Padovan { 594884084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments 594984084a31SMat Martineau * skb->data_len reflects only data in fragments 595084084a31SMat Martineau */ 595184084a31SMat Martineau if (!skb_has_frag_list(skb)) 595284084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag; 595384084a31SMat Martineau 595484084a31SMat Martineau new_frag->next = NULL; 595584084a31SMat Martineau 595684084a31SMat Martineau (*last_frag)->next = new_frag; 595784084a31SMat Martineau *last_frag = new_frag; 595884084a31SMat Martineau 595984084a31SMat Martineau skb->len += new_frag->len; 596084084a31SMat Martineau skb->data_len += new_frag->len; 596184084a31SMat Martineau skb->truesize += new_frag->truesize; 596284084a31SMat Martineau } 596384084a31SMat Martineau 59644b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, 59654b51dae9SMat Martineau struct l2cap_ctrl *control) 596684084a31SMat Martineau { 596784084a31SMat Martineau int err = -EINVAL; 59680a708f8fSGustavo F. Padovan 59694b51dae9SMat Martineau switch (control->sar) { 59707e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED: 597184084a31SMat Martineau if (chan->sdu) 597284084a31SMat Martineau break; 59730a708f8fSGustavo F. Padovan 597480b98027SGustavo Padovan err = chan->ops->recv(chan, skb); 597584084a31SMat Martineau break; 59760a708f8fSGustavo F. Padovan 59777e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START: 597884084a31SMat Martineau if (chan->sdu) 597984084a31SMat Martineau break; 59800a708f8fSGustavo F. Padovan 59816f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data); 598203a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE); 59830a708f8fSGustavo F. Padovan 598484084a31SMat Martineau if (chan->sdu_len > chan->imtu) { 598584084a31SMat Martineau err = -EMSGSIZE; 598684084a31SMat Martineau break; 598784084a31SMat Martineau } 59880a708f8fSGustavo F. Padovan 598984084a31SMat Martineau if (skb->len >= chan->sdu_len) 599084084a31SMat Martineau break; 599184084a31SMat Martineau 599284084a31SMat Martineau chan->sdu = skb; 599384084a31SMat Martineau chan->sdu_last_frag = skb; 599484084a31SMat Martineau 599584084a31SMat Martineau skb = NULL; 599684084a31SMat Martineau err = 0; 59970a708f8fSGustavo F. Padovan break; 59980a708f8fSGustavo F. Padovan 59997e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE: 60006f61fd47SGustavo F. Padovan if (!chan->sdu) 600184084a31SMat Martineau break; 60020a708f8fSGustavo F. Padovan 600384084a31SMat Martineau append_skb_frag(chan->sdu, skb, 600484084a31SMat Martineau &chan->sdu_last_frag); 600584084a31SMat Martineau skb = NULL; 60060a708f8fSGustavo F. Padovan 600784084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len) 600884084a31SMat Martineau break; 60090a708f8fSGustavo F. Padovan 601084084a31SMat Martineau err = 0; 60110a708f8fSGustavo F. Padovan break; 60120a708f8fSGustavo F. Padovan 60137e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END: 60146f61fd47SGustavo F. Padovan if (!chan->sdu) 601584084a31SMat Martineau break; 60160a708f8fSGustavo F. Padovan 601784084a31SMat Martineau append_skb_frag(chan->sdu, skb, 601884084a31SMat Martineau &chan->sdu_last_frag); 601984084a31SMat Martineau skb = NULL; 60200a708f8fSGustavo F. Padovan 602184084a31SMat Martineau if (chan->sdu->len != chan->sdu_len) 602284084a31SMat Martineau break; 60230a708f8fSGustavo F. Padovan 602480b98027SGustavo Padovan err = chan->ops->recv(chan, chan->sdu); 60250a708f8fSGustavo F. Padovan 602684084a31SMat Martineau if (!err) { 602784084a31SMat Martineau /* Reassembly complete */ 602884084a31SMat Martineau chan->sdu = NULL; 602984084a31SMat Martineau chan->sdu_last_frag = NULL; 603084084a31SMat Martineau chan->sdu_len = 0; 60310a708f8fSGustavo F. Padovan } 60320a708f8fSGustavo F. Padovan break; 60330a708f8fSGustavo F. Padovan } 60340a708f8fSGustavo F. Padovan 603584084a31SMat Martineau if (err) { 60360a708f8fSGustavo F. Padovan kfree_skb(skb); 60376f61fd47SGustavo F. Padovan kfree_skb(chan->sdu); 60386f61fd47SGustavo F. Padovan chan->sdu = NULL; 603984084a31SMat Martineau chan->sdu_last_frag = NULL; 604084084a31SMat Martineau chan->sdu_len = 0; 604184084a31SMat Martineau } 60420a708f8fSGustavo F. Padovan 604384084a31SMat Martineau return err; 60440a708f8fSGustavo F. Padovan } 60450a708f8fSGustavo F. Padovan 604632b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan) 604732b32735SMat Martineau { 604832b32735SMat Martineau /* Placeholder */ 604932b32735SMat Martineau return 0; 605032b32735SMat Martineau } 605132b32735SMat Martineau 6052e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 60530a708f8fSGustavo F. Padovan { 605461aa4f5bSMat Martineau u8 event; 605561aa4f5bSMat Martineau 605661aa4f5bSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 605761aa4f5bSMat Martineau return; 605861aa4f5bSMat Martineau 605961aa4f5bSMat Martineau event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR; 6060401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, event); 60610a708f8fSGustavo F. Padovan } 60620a708f8fSGustavo F. Padovan 6063d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan) 6064d2a7ac5dSMat Martineau { 606563838725SMat Martineau int err = 0; 606663838725SMat Martineau /* Pass sequential frames to l2cap_reassemble_sdu() 606763838725SMat Martineau * until a gap is encountered. 606863838725SMat Martineau */ 606963838725SMat Martineau 607063838725SMat Martineau BT_DBG("chan %p", chan); 607163838725SMat Martineau 607263838725SMat Martineau while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 607363838725SMat Martineau struct sk_buff *skb; 607463838725SMat Martineau BT_DBG("Searching for skb with txseq %d (queue len %d)", 607563838725SMat Martineau chan->buffer_seq, skb_queue_len(&chan->srej_q)); 607663838725SMat Martineau 607763838725SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq); 607863838725SMat Martineau 607963838725SMat Martineau if (!skb) 608063838725SMat Martineau break; 608163838725SMat Martineau 608263838725SMat Martineau skb_unlink(skb, &chan->srej_q); 608363838725SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 608463838725SMat Martineau err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->control); 608563838725SMat Martineau if (err) 608663838725SMat Martineau break; 608763838725SMat Martineau } 608863838725SMat Martineau 608963838725SMat Martineau if (skb_queue_empty(&chan->srej_q)) { 609063838725SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 609163838725SMat Martineau l2cap_send_ack(chan); 609263838725SMat Martineau } 609363838725SMat Martineau 609463838725SMat Martineau return err; 6095d2a7ac5dSMat Martineau } 6096d2a7ac5dSMat Martineau 6097d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan, 6098d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 6099d2a7ac5dSMat Martineau { 6100f80842a8SMat Martineau struct sk_buff *skb; 6101f80842a8SMat Martineau 6102f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 6103f80842a8SMat Martineau 6104f80842a8SMat Martineau if (control->reqseq == chan->next_tx_seq) { 6105f80842a8SMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 61065e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6107f80842a8SMat Martineau return; 6108f80842a8SMat Martineau } 6109f80842a8SMat Martineau 6110f80842a8SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 6111f80842a8SMat Martineau 6112f80842a8SMat Martineau if (skb == NULL) { 6113f80842a8SMat Martineau BT_DBG("Seq %d not available for retransmission", 6114f80842a8SMat Martineau control->reqseq); 6115f80842a8SMat Martineau return; 6116f80842a8SMat Martineau } 6117f80842a8SMat Martineau 6118f80842a8SMat Martineau if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) { 6119f80842a8SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 61205e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6121f80842a8SMat Martineau return; 6122f80842a8SMat Martineau } 6123f80842a8SMat Martineau 6124f80842a8SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6125f80842a8SMat Martineau 6126f80842a8SMat Martineau if (control->poll) { 6127f80842a8SMat Martineau l2cap_pass_to_tx(chan, control); 6128f80842a8SMat Martineau 6129f80842a8SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6130f80842a8SMat Martineau l2cap_retransmit(chan, control); 6131f80842a8SMat Martineau l2cap_ertm_send(chan); 6132f80842a8SMat Martineau 6133f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 6134f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 6135f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 6136f80842a8SMat Martineau } 6137f80842a8SMat Martineau } else { 6138f80842a8SMat Martineau l2cap_pass_to_tx_fbit(chan, control); 6139f80842a8SMat Martineau 6140f80842a8SMat Martineau if (control->final) { 6141f80842a8SMat Martineau if (chan->srej_save_reqseq != control->reqseq || 6142f80842a8SMat Martineau !test_and_clear_bit(CONN_SREJ_ACT, 6143f80842a8SMat Martineau &chan->conn_state)) 6144f80842a8SMat Martineau l2cap_retransmit(chan, control); 6145f80842a8SMat Martineau } else { 6146f80842a8SMat Martineau l2cap_retransmit(chan, control); 6147f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 6148f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 6149f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 6150f80842a8SMat Martineau } 6151f80842a8SMat Martineau } 6152f80842a8SMat Martineau } 6153d2a7ac5dSMat Martineau } 6154d2a7ac5dSMat Martineau 6155d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan, 6156d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 6157d2a7ac5dSMat Martineau { 6158fcd289dfSMat Martineau struct sk_buff *skb; 6159fcd289dfSMat Martineau 6160fcd289dfSMat Martineau BT_DBG("chan %p, control %p", chan, control); 6161fcd289dfSMat Martineau 6162fcd289dfSMat Martineau if (control->reqseq == chan->next_tx_seq) { 6163fcd289dfSMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 61645e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6165fcd289dfSMat Martineau return; 6166fcd289dfSMat Martineau } 6167fcd289dfSMat Martineau 6168fcd289dfSMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 6169fcd289dfSMat Martineau 6170fcd289dfSMat Martineau if (chan->max_tx && skb && 6171fcd289dfSMat Martineau bt_cb(skb)->control.retries >= chan->max_tx) { 6172fcd289dfSMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 61735e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6174fcd289dfSMat Martineau return; 6175fcd289dfSMat Martineau } 6176fcd289dfSMat Martineau 6177fcd289dfSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6178fcd289dfSMat Martineau 6179fcd289dfSMat Martineau l2cap_pass_to_tx(chan, control); 6180fcd289dfSMat Martineau 6181fcd289dfSMat Martineau if (control->final) { 6182fcd289dfSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 6183fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 6184fcd289dfSMat Martineau } else { 6185fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 6186fcd289dfSMat Martineau l2cap_ertm_send(chan); 6187fcd289dfSMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) 6188fcd289dfSMat Martineau set_bit(CONN_REJ_ACT, &chan->conn_state); 6189fcd289dfSMat Martineau } 6190d2a7ac5dSMat Martineau } 6191d2a7ac5dSMat Martineau 61924b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) 61934b51dae9SMat Martineau { 61944b51dae9SMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 61954b51dae9SMat Martineau 61964b51dae9SMat Martineau BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq, 61974b51dae9SMat Martineau chan->expected_tx_seq); 61984b51dae9SMat Martineau 61994b51dae9SMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 62004b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 62014b51dae9SMat Martineau chan->tx_win) { 62024b51dae9SMat Martineau /* See notes below regarding "double poll" and 62034b51dae9SMat Martineau * invalid packets. 62044b51dae9SMat Martineau */ 62054b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 62064b51dae9SMat Martineau BT_DBG("Invalid/Ignore - after SREJ"); 62074b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 62084b51dae9SMat Martineau } else { 62094b51dae9SMat Martineau BT_DBG("Invalid - in window after SREJ sent"); 62104b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 62114b51dae9SMat Martineau } 62124b51dae9SMat Martineau } 62134b51dae9SMat Martineau 62144b51dae9SMat Martineau if (chan->srej_list.head == txseq) { 62154b51dae9SMat Martineau BT_DBG("Expected SREJ"); 62164b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED_SREJ; 62174b51dae9SMat Martineau } 62184b51dae9SMat Martineau 62194b51dae9SMat Martineau if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) { 62204b51dae9SMat Martineau BT_DBG("Duplicate SREJ - txseq already stored"); 62214b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE_SREJ; 62224b51dae9SMat Martineau } 62234b51dae9SMat Martineau 62244b51dae9SMat Martineau if (l2cap_seq_list_contains(&chan->srej_list, txseq)) { 62254b51dae9SMat Martineau BT_DBG("Unexpected SREJ - not requested"); 62264b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED_SREJ; 62274b51dae9SMat Martineau } 62284b51dae9SMat Martineau } 62294b51dae9SMat Martineau 62304b51dae9SMat Martineau if (chan->expected_tx_seq == txseq) { 62314b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 62324b51dae9SMat Martineau chan->tx_win) { 62334b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 62344b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 62354b51dae9SMat Martineau } else { 62364b51dae9SMat Martineau BT_DBG("Expected"); 62374b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED; 62384b51dae9SMat Martineau } 62394b51dae9SMat Martineau } 62404b51dae9SMat Martineau 62414b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) < 62422d792818SGustavo Padovan __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) { 62434b51dae9SMat Martineau BT_DBG("Duplicate - expected_tx_seq later than txseq"); 62444b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE; 62454b51dae9SMat Martineau } 62464b51dae9SMat Martineau 62474b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) { 62484b51dae9SMat Martineau /* A source of invalid packets is a "double poll" condition, 62494b51dae9SMat Martineau * where delays cause us to send multiple poll packets. If 62504b51dae9SMat Martineau * the remote stack receives and processes both polls, 62514b51dae9SMat Martineau * sequence numbers can wrap around in such a way that a 62524b51dae9SMat Martineau * resent frame has a sequence number that looks like new data 62534b51dae9SMat Martineau * with a sequence gap. This would trigger an erroneous SREJ 62544b51dae9SMat Martineau * request. 62554b51dae9SMat Martineau * 62564b51dae9SMat Martineau * Fortunately, this is impossible with a tx window that's 62574b51dae9SMat Martineau * less than half of the maximum sequence number, which allows 62584b51dae9SMat Martineau * invalid frames to be safely ignored. 62594b51dae9SMat Martineau * 62604b51dae9SMat Martineau * With tx window sizes greater than half of the tx window 62614b51dae9SMat Martineau * maximum, the frame is invalid and cannot be ignored. This 62624b51dae9SMat Martineau * causes a disconnect. 62634b51dae9SMat Martineau */ 62644b51dae9SMat Martineau 62654b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 62664b51dae9SMat Martineau BT_DBG("Invalid/Ignore - txseq outside tx window"); 62674b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 62684b51dae9SMat Martineau } else { 62694b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 62704b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 62714b51dae9SMat Martineau } 62724b51dae9SMat Martineau } else { 62734b51dae9SMat Martineau BT_DBG("Unexpected - txseq indicates missing frames"); 62744b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED; 62754b51dae9SMat Martineau } 62764b51dae9SMat Martineau } 62774b51dae9SMat Martineau 6278d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan, 6279d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 6280d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 6281d2a7ac5dSMat Martineau { 6282d2a7ac5dSMat Martineau int err = 0; 6283941247f9SPeter Senna Tschudin bool skb_in_use = false; 6284d2a7ac5dSMat Martineau 6285d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 6286d2a7ac5dSMat Martineau event); 6287d2a7ac5dSMat Martineau 6288d2a7ac5dSMat Martineau switch (event) { 6289d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 6290d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, control->txseq)) { 6291d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 6292d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6293d2a7ac5dSMat Martineau 6294d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 6295d2a7ac5dSMat Martineau BT_DBG("Busy, discarding expected seq %d", 6296d2a7ac5dSMat Martineau control->txseq); 6297d2a7ac5dSMat Martineau break; 6298d2a7ac5dSMat Martineau } 6299d2a7ac5dSMat Martineau 6300d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, 6301d2a7ac5dSMat Martineau control->txseq); 6302d2a7ac5dSMat Martineau 6303d2a7ac5dSMat Martineau chan->buffer_seq = chan->expected_tx_seq; 6304941247f9SPeter Senna Tschudin skb_in_use = true; 6305d2a7ac5dSMat Martineau 6306d2a7ac5dSMat Martineau err = l2cap_reassemble_sdu(chan, skb, control); 6307d2a7ac5dSMat Martineau if (err) 6308d2a7ac5dSMat Martineau break; 6309d2a7ac5dSMat Martineau 6310d2a7ac5dSMat Martineau if (control->final) { 6311d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 6312d2a7ac5dSMat Martineau &chan->conn_state)) { 6313d2a7ac5dSMat Martineau control->final = 0; 6314d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6315d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6316d2a7ac5dSMat Martineau } 6317d2a7ac5dSMat Martineau } 6318d2a7ac5dSMat Martineau 6319d2a7ac5dSMat Martineau if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 6320d2a7ac5dSMat Martineau l2cap_send_ack(chan); 6321d2a7ac5dSMat Martineau break; 6322d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 6323d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6324d2a7ac5dSMat Martineau 6325d2a7ac5dSMat Martineau /* Can't issue SREJ frames in the local busy state. 6326d2a7ac5dSMat Martineau * Drop this frame, it will be seen as missing 6327d2a7ac5dSMat Martineau * when local busy is exited. 6328d2a7ac5dSMat Martineau */ 6329d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 6330d2a7ac5dSMat Martineau BT_DBG("Busy, discarding unexpected seq %d", 6331d2a7ac5dSMat Martineau control->txseq); 6332d2a7ac5dSMat Martineau break; 6333d2a7ac5dSMat Martineau } 6334d2a7ac5dSMat Martineau 6335d2a7ac5dSMat Martineau /* There was a gap in the sequence, so an SREJ 6336d2a7ac5dSMat Martineau * must be sent for each missing frame. The 6337d2a7ac5dSMat Martineau * current frame is stored for later use. 6338d2a7ac5dSMat Martineau */ 6339d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6340941247f9SPeter Senna Tschudin skb_in_use = true; 6341d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6342d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6343d2a7ac5dSMat Martineau 6344d2a7ac5dSMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 6345d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 6346d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 6347d2a7ac5dSMat Martineau 6348d2a7ac5dSMat Martineau chan->rx_state = L2CAP_RX_STATE_SREJ_SENT; 6349d2a7ac5dSMat Martineau break; 6350d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 6351d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6352d2a7ac5dSMat Martineau break; 6353d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 6354d2a7ac5dSMat Martineau break; 6355d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 6356d2a7ac5dSMat Martineau default: 63575e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6358d2a7ac5dSMat Martineau break; 6359d2a7ac5dSMat Martineau } 6360d2a7ac5dSMat Martineau break; 6361d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 6362d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6363d2a7ac5dSMat Martineau if (control->final) { 6364d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6365d2a7ac5dSMat Martineau 6366e6a3ee6eSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) && 6367e6a3ee6eSMat Martineau !__chan_is_moving(chan)) { 6368d2a7ac5dSMat Martineau control->final = 0; 6369d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6370d2a7ac5dSMat Martineau } 6371d2a7ac5dSMat Martineau 6372d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6373d2a7ac5dSMat Martineau } else if (control->poll) { 6374d2a7ac5dSMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 6375d2a7ac5dSMat Martineau } else { 6376d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6377d2a7ac5dSMat Martineau &chan->conn_state) && 6378d2a7ac5dSMat Martineau chan->unacked_frames) 6379d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6380d2a7ac5dSMat Martineau 6381d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6382d2a7ac5dSMat Martineau } 6383d2a7ac5dSMat Martineau break; 6384d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 6385d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6386d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6387d2a7ac5dSMat Martineau if (control && control->poll) { 6388d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6389d2a7ac5dSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 6390d2a7ac5dSMat Martineau } 6391d2a7ac5dSMat Martineau __clear_retrans_timer(chan); 6392d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 6393d2a7ac5dSMat Martineau break; 6394d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 6395d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 6396d2a7ac5dSMat Martineau break; 6397d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 6398d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 6399d2a7ac5dSMat Martineau break; 6400d2a7ac5dSMat Martineau default: 6401d2a7ac5dSMat Martineau break; 6402d2a7ac5dSMat Martineau } 6403d2a7ac5dSMat Martineau 6404d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 6405d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 6406d2a7ac5dSMat Martineau kfree_skb(skb); 6407d2a7ac5dSMat Martineau } 6408d2a7ac5dSMat Martineau 6409d2a7ac5dSMat Martineau return err; 6410d2a7ac5dSMat Martineau } 6411d2a7ac5dSMat Martineau 6412d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, 6413d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 6414d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 6415d2a7ac5dSMat Martineau { 6416d2a7ac5dSMat Martineau int err = 0; 6417d2a7ac5dSMat Martineau u16 txseq = control->txseq; 6418941247f9SPeter Senna Tschudin bool skb_in_use = false; 6419d2a7ac5dSMat Martineau 6420d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 6421d2a7ac5dSMat Martineau event); 6422d2a7ac5dSMat Martineau 6423d2a7ac5dSMat Martineau switch (event) { 6424d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 6425d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, txseq)) { 6426d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 6427d2a7ac5dSMat Martineau /* Keep frame for reassembly later */ 6428d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6429d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6430941247f9SPeter Senna Tschudin skb_in_use = true; 6431d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6432d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6433d2a7ac5dSMat Martineau 6434d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 6435d2a7ac5dSMat Martineau break; 6436d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED_SREJ: 6437d2a7ac5dSMat Martineau l2cap_seq_list_pop(&chan->srej_list); 6438d2a7ac5dSMat Martineau 6439d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6440d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6441941247f9SPeter Senna Tschudin skb_in_use = true; 6442d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6443d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6444d2a7ac5dSMat Martineau 6445d2a7ac5dSMat Martineau err = l2cap_rx_queued_iframes(chan); 6446d2a7ac5dSMat Martineau if (err) 6447d2a7ac5dSMat Martineau break; 6448d2a7ac5dSMat Martineau 6449d2a7ac5dSMat Martineau break; 6450d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 6451d2a7ac5dSMat Martineau /* Got a frame that can't be reassembled yet. 6452d2a7ac5dSMat Martineau * Save it for later, and send SREJs to cover 6453d2a7ac5dSMat Martineau * the missing frames. 6454d2a7ac5dSMat Martineau */ 6455d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6456941247f9SPeter Senna Tschudin skb_in_use = true; 6457d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6458d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6459d2a7ac5dSMat Martineau 6460d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6461d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 6462d2a7ac5dSMat Martineau break; 6463d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED_SREJ: 6464d2a7ac5dSMat Martineau /* This frame was requested with an SREJ, but 6465d2a7ac5dSMat Martineau * some expected retransmitted frames are 6466d2a7ac5dSMat Martineau * missing. Request retransmission of missing 6467d2a7ac5dSMat Martineau * SREJ'd frames. 6468d2a7ac5dSMat Martineau */ 6469d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 6470941247f9SPeter Senna Tschudin skb_in_use = true; 6471d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 6472d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 6473d2a7ac5dSMat Martineau 6474d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6475d2a7ac5dSMat Martineau l2cap_send_srej_list(chan, control->txseq); 6476d2a7ac5dSMat Martineau break; 6477d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE_SREJ: 6478d2a7ac5dSMat Martineau /* We've already queued this frame. Drop this copy. */ 6479d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6480d2a7ac5dSMat Martineau break; 6481d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 6482d2a7ac5dSMat Martineau /* Expecting a later sequence number, so this frame 6483d2a7ac5dSMat Martineau * was already received. Ignore it completely. 6484d2a7ac5dSMat Martineau */ 6485d2a7ac5dSMat Martineau break; 6486d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 6487d2a7ac5dSMat Martineau break; 6488d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 6489d2a7ac5dSMat Martineau default: 64905e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6491d2a7ac5dSMat Martineau break; 6492d2a7ac5dSMat Martineau } 6493d2a7ac5dSMat Martineau break; 6494d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 6495d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6496d2a7ac5dSMat Martineau if (control->final) { 6497d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6498d2a7ac5dSMat Martineau 6499d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 6500d2a7ac5dSMat Martineau &chan->conn_state)) { 6501d2a7ac5dSMat Martineau control->final = 0; 6502d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 6503d2a7ac5dSMat Martineau } 6504d2a7ac5dSMat Martineau 6505d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 6506d2a7ac5dSMat Martineau } else if (control->poll) { 6507d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6508d2a7ac5dSMat Martineau &chan->conn_state) && 6509d2a7ac5dSMat Martineau chan->unacked_frames) { 6510d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6511d2a7ac5dSMat Martineau } 6512d2a7ac5dSMat Martineau 6513d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 6514d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 6515d2a7ac5dSMat Martineau } else { 6516d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 6517d2a7ac5dSMat Martineau &chan->conn_state) && 6518d2a7ac5dSMat Martineau chan->unacked_frames) 6519d2a7ac5dSMat Martineau __set_retrans_timer(chan); 6520d2a7ac5dSMat Martineau 6521d2a7ac5dSMat Martineau l2cap_send_ack(chan); 6522d2a7ac5dSMat Martineau } 6523d2a7ac5dSMat Martineau break; 6524d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 6525d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 6526d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 6527d2a7ac5dSMat Martineau if (control->poll) { 6528d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 6529d2a7ac5dSMat Martineau } else { 6530d2a7ac5dSMat Martineau struct l2cap_ctrl rr_control; 6531d2a7ac5dSMat Martineau memset(&rr_control, 0, sizeof(rr_control)); 6532d2a7ac5dSMat Martineau rr_control.sframe = 1; 6533d2a7ac5dSMat Martineau rr_control.super = L2CAP_SUPER_RR; 6534d2a7ac5dSMat Martineau rr_control.reqseq = chan->buffer_seq; 6535d2a7ac5dSMat Martineau l2cap_send_sframe(chan, &rr_control); 6536d2a7ac5dSMat Martineau } 6537d2a7ac5dSMat Martineau 6538d2a7ac5dSMat Martineau break; 6539d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 6540d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 6541d2a7ac5dSMat Martineau break; 6542d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 6543d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 6544d2a7ac5dSMat Martineau break; 6545d2a7ac5dSMat Martineau } 6546d2a7ac5dSMat Martineau 6547d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 6548d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 6549d2a7ac5dSMat Martineau kfree_skb(skb); 6550d2a7ac5dSMat Martineau } 6551d2a7ac5dSMat Martineau 6552d2a7ac5dSMat Martineau return err; 6553d2a7ac5dSMat Martineau } 6554d2a7ac5dSMat Martineau 655532b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan) 655632b32735SMat Martineau { 655732b32735SMat Martineau BT_DBG("chan %p", chan); 655832b32735SMat Martineau 655932b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 656032b32735SMat Martineau 656132b32735SMat Martineau if (chan->hs_hcon) 656232b32735SMat Martineau chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; 656332b32735SMat Martineau else 656432b32735SMat Martineau chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; 656532b32735SMat Martineau 656632b32735SMat Martineau return l2cap_resegment(chan); 656732b32735SMat Martineau } 656832b32735SMat Martineau 656932b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan, 657032b32735SMat Martineau struct l2cap_ctrl *control, 657132b32735SMat Martineau struct sk_buff *skb, u8 event) 657232b32735SMat Martineau { 657332b32735SMat Martineau int err; 657432b32735SMat Martineau 657532b32735SMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 657632b32735SMat Martineau event); 657732b32735SMat Martineau 657832b32735SMat Martineau if (!control->poll) 657932b32735SMat Martineau return -EPROTO; 658032b32735SMat Martineau 658132b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq); 658232b32735SMat Martineau 658332b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q)) 658432b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q); 658532b32735SMat Martineau else 658632b32735SMat Martineau chan->tx_send_head = NULL; 658732b32735SMat Martineau 658832b32735SMat Martineau /* Rewind next_tx_seq to the point expected 658932b32735SMat Martineau * by the receiver. 659032b32735SMat Martineau */ 659132b32735SMat Martineau chan->next_tx_seq = control->reqseq; 659232b32735SMat Martineau chan->unacked_frames = 0; 659332b32735SMat Martineau 659432b32735SMat Martineau err = l2cap_finish_move(chan); 659532b32735SMat Martineau if (err) 659632b32735SMat Martineau return err; 659732b32735SMat Martineau 659832b32735SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 659932b32735SMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 660032b32735SMat Martineau 660132b32735SMat Martineau if (event == L2CAP_EV_RECV_IFRAME) 660232b32735SMat Martineau return -EPROTO; 660332b32735SMat Martineau 660432b32735SMat Martineau return l2cap_rx_state_recv(chan, control, NULL, event); 660532b32735SMat Martineau } 660632b32735SMat Martineau 660732b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan, 660832b32735SMat Martineau struct l2cap_ctrl *control, 660932b32735SMat Martineau struct sk_buff *skb, u8 event) 661032b32735SMat Martineau { 661132b32735SMat Martineau int err; 661232b32735SMat Martineau 661332b32735SMat Martineau if (!control->final) 661432b32735SMat Martineau return -EPROTO; 661532b32735SMat Martineau 661632b32735SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 661732b32735SMat Martineau 661832b32735SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 661932b32735SMat Martineau l2cap_process_reqseq(chan, control->reqseq); 662032b32735SMat Martineau 662132b32735SMat Martineau if (!skb_queue_empty(&chan->tx_q)) 662232b32735SMat Martineau chan->tx_send_head = skb_peek(&chan->tx_q); 662332b32735SMat Martineau else 662432b32735SMat Martineau chan->tx_send_head = NULL; 662532b32735SMat Martineau 662632b32735SMat Martineau /* Rewind next_tx_seq to the point expected 662732b32735SMat Martineau * by the receiver. 662832b32735SMat Martineau */ 662932b32735SMat Martineau chan->next_tx_seq = control->reqseq; 663032b32735SMat Martineau chan->unacked_frames = 0; 663132b32735SMat Martineau 663232b32735SMat Martineau if (chan->hs_hcon) 663332b32735SMat Martineau chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; 663432b32735SMat Martineau else 663532b32735SMat Martineau chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; 663632b32735SMat Martineau 663732b32735SMat Martineau err = l2cap_resegment(chan); 663832b32735SMat Martineau 663932b32735SMat Martineau if (!err) 664032b32735SMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 664132b32735SMat Martineau 664232b32735SMat Martineau return err; 664332b32735SMat Martineau } 664432b32735SMat Martineau 6645d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq) 6646d2a7ac5dSMat Martineau { 6647d2a7ac5dSMat Martineau /* Make sure reqseq is for a packet that has been sent but not acked */ 6648d2a7ac5dSMat Martineau u16 unacked; 6649d2a7ac5dSMat Martineau 6650d2a7ac5dSMat Martineau unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq); 6651d2a7ac5dSMat Martineau return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked; 6652d2a7ac5dSMat Martineau } 6653d2a7ac5dSMat Martineau 6654cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 6655cec8ab6eSMat Martineau struct sk_buff *skb, u8 event) 66560a708f8fSGustavo F. Padovan { 6657d2a7ac5dSMat Martineau int err = 0; 6658d2a7ac5dSMat Martineau 6659d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan, 6660d2a7ac5dSMat Martineau control, skb, event, chan->rx_state); 6661d2a7ac5dSMat Martineau 6662d2a7ac5dSMat Martineau if (__valid_reqseq(chan, control->reqseq)) { 6663d2a7ac5dSMat Martineau switch (chan->rx_state) { 6664d2a7ac5dSMat Martineau case L2CAP_RX_STATE_RECV: 6665d2a7ac5dSMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 6666d2a7ac5dSMat Martineau break; 6667d2a7ac5dSMat Martineau case L2CAP_RX_STATE_SREJ_SENT: 6668d2a7ac5dSMat Martineau err = l2cap_rx_state_srej_sent(chan, control, skb, 6669d2a7ac5dSMat Martineau event); 6670d2a7ac5dSMat Martineau break; 667132b32735SMat Martineau case L2CAP_RX_STATE_WAIT_P: 667232b32735SMat Martineau err = l2cap_rx_state_wait_p(chan, control, skb, event); 667332b32735SMat Martineau break; 667432b32735SMat Martineau case L2CAP_RX_STATE_WAIT_F: 667532b32735SMat Martineau err = l2cap_rx_state_wait_f(chan, control, skb, event); 667632b32735SMat Martineau break; 6677d2a7ac5dSMat Martineau default: 6678d2a7ac5dSMat Martineau /* shut it down */ 6679d2a7ac5dSMat Martineau break; 6680d2a7ac5dSMat Martineau } 6681d2a7ac5dSMat Martineau } else { 6682d2a7ac5dSMat Martineau BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d", 6683d2a7ac5dSMat Martineau control->reqseq, chan->next_tx_seq, 6684d2a7ac5dSMat Martineau chan->expected_ack_seq); 66855e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6686d2a7ac5dSMat Martineau } 6687d2a7ac5dSMat Martineau 6688d2a7ac5dSMat Martineau return err; 6689cec8ab6eSMat Martineau } 6690cec8ab6eSMat Martineau 6691cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 6692cec8ab6eSMat Martineau struct sk_buff *skb) 6693cec8ab6eSMat Martineau { 66944b51dae9SMat Martineau int err = 0; 66954b51dae9SMat Martineau 66964b51dae9SMat Martineau BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb, 66974b51dae9SMat Martineau chan->rx_state); 66984b51dae9SMat Martineau 66994b51dae9SMat Martineau if (l2cap_classify_txseq(chan, control->txseq) == 67004b51dae9SMat Martineau L2CAP_TXSEQ_EXPECTED) { 67014b51dae9SMat Martineau l2cap_pass_to_tx(chan, control); 67024b51dae9SMat Martineau 67034b51dae9SMat Martineau BT_DBG("buffer_seq %d->%d", chan->buffer_seq, 67044b51dae9SMat Martineau __next_seq(chan, chan->buffer_seq)); 67054b51dae9SMat Martineau 67064b51dae9SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 67074b51dae9SMat Martineau 67084b51dae9SMat Martineau l2cap_reassemble_sdu(chan, skb, control); 67094b51dae9SMat Martineau } else { 67104b51dae9SMat Martineau if (chan->sdu) { 67114b51dae9SMat Martineau kfree_skb(chan->sdu); 67124b51dae9SMat Martineau chan->sdu = NULL; 67134b51dae9SMat Martineau } 67144b51dae9SMat Martineau chan->sdu_last_frag = NULL; 67154b51dae9SMat Martineau chan->sdu_len = 0; 67164b51dae9SMat Martineau 67174b51dae9SMat Martineau if (skb) { 67184b51dae9SMat Martineau BT_DBG("Freeing %p", skb); 67194b51dae9SMat Martineau kfree_skb(skb); 67204b51dae9SMat Martineau } 67214b51dae9SMat Martineau } 67224b51dae9SMat Martineau 67234b51dae9SMat Martineau chan->last_acked_seq = control->txseq; 67244b51dae9SMat Martineau chan->expected_tx_seq = __next_seq(chan, control->txseq); 67254b51dae9SMat Martineau 67264b51dae9SMat Martineau return err; 6727cec8ab6eSMat Martineau } 6728cec8ab6eSMat Martineau 6729cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 6730cec8ab6eSMat Martineau { 6731cec8ab6eSMat Martineau struct l2cap_ctrl *control = &bt_cb(skb)->control; 6732cec8ab6eSMat Martineau u16 len; 6733cec8ab6eSMat Martineau u8 event; 67340a708f8fSGustavo F. Padovan 6735b76bbd66SMat Martineau __unpack_control(chan, skb); 6736b76bbd66SMat Martineau 67370a708f8fSGustavo F. Padovan len = skb->len; 67380a708f8fSGustavo F. Padovan 67390a708f8fSGustavo F. Padovan /* 67400a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here. 67410a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery 6742cec8ab6eSMat Martineau * procedures and ask for retransmission. 67430a708f8fSGustavo F. Padovan */ 674447d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 67450a708f8fSGustavo F. Padovan goto drop; 67460a708f8fSGustavo F. Padovan 6747cec8ab6eSMat Martineau if (!control->sframe && control->sar == L2CAP_SAR_START) 674803a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 67490a708f8fSGustavo F. Padovan 675047d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 675103a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 67520a708f8fSGustavo F. Padovan 675347d1ec61SGustavo F. Padovan if (len > chan->mps) { 67545e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 67550a708f8fSGustavo F. Padovan goto drop; 67560a708f8fSGustavo F. Padovan } 67570a708f8fSGustavo F. Padovan 6758cec8ab6eSMat Martineau if (!control->sframe) { 6759cec8ab6eSMat Martineau int err; 67600a708f8fSGustavo F. Padovan 6761cec8ab6eSMat Martineau BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d", 6762cec8ab6eSMat Martineau control->sar, control->reqseq, control->final, 6763cec8ab6eSMat Martineau control->txseq); 6764836be934SAndrei Emeltchenko 6765cec8ab6eSMat Martineau /* Validate F-bit - F=0 always valid, F=1 only 6766cec8ab6eSMat Martineau * valid in TX WAIT_F 6767cec8ab6eSMat Martineau */ 6768cec8ab6eSMat Martineau if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F) 67690a708f8fSGustavo F. Padovan goto drop; 67700a708f8fSGustavo F. Padovan 6771cec8ab6eSMat Martineau if (chan->mode != L2CAP_MODE_STREAMING) { 6772cec8ab6eSMat Martineau event = L2CAP_EV_RECV_IFRAME; 6773cec8ab6eSMat Martineau err = l2cap_rx(chan, control, skb, event); 67740a708f8fSGustavo F. Padovan } else { 6775cec8ab6eSMat Martineau err = l2cap_stream_rx(chan, control, skb); 6776cec8ab6eSMat Martineau } 6777cec8ab6eSMat Martineau 6778cec8ab6eSMat Martineau if (err) 67795e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 6780cec8ab6eSMat Martineau } else { 6781cec8ab6eSMat Martineau const u8 rx_func_to_event[4] = { 6782cec8ab6eSMat Martineau L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ, 6783cec8ab6eSMat Martineau L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ 6784cec8ab6eSMat Martineau }; 6785cec8ab6eSMat Martineau 6786cec8ab6eSMat Martineau /* Only I-frames are expected in streaming mode */ 6787cec8ab6eSMat Martineau if (chan->mode == L2CAP_MODE_STREAMING) 6788cec8ab6eSMat Martineau goto drop; 6789cec8ab6eSMat Martineau 6790cec8ab6eSMat Martineau BT_DBG("sframe reqseq %d, final %d, poll %d, super %d", 6791cec8ab6eSMat Martineau control->reqseq, control->final, control->poll, 6792cec8ab6eSMat Martineau control->super); 6793cec8ab6eSMat Martineau 67940a708f8fSGustavo F. Padovan if (len != 0) { 67951bb166e6SAndrei Emeltchenko BT_ERR("Trailing bytes: %d in sframe", len); 67965e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 67970a708f8fSGustavo F. Padovan goto drop; 67980a708f8fSGustavo F. Padovan } 67990a708f8fSGustavo F. Padovan 6800cec8ab6eSMat Martineau /* Validate F and P bits */ 6801cec8ab6eSMat Martineau if (control->final && (control->poll || 6802cec8ab6eSMat Martineau chan->tx_state != L2CAP_TX_STATE_WAIT_F)) 6803cec8ab6eSMat Martineau goto drop; 6804cec8ab6eSMat Martineau 6805cec8ab6eSMat Martineau event = rx_func_to_event[control->super]; 6806cec8ab6eSMat Martineau if (l2cap_rx(chan, control, skb, event)) 68075e4e3972SAndrei Emeltchenko l2cap_send_disconn_req(chan, ECONNRESET); 68080a708f8fSGustavo F. Padovan } 68090a708f8fSGustavo F. Padovan 68100a708f8fSGustavo F. Padovan return 0; 68110a708f8fSGustavo F. Padovan 68120a708f8fSGustavo F. Padovan drop: 68130a708f8fSGustavo F. Padovan kfree_skb(skb); 68140a708f8fSGustavo F. Padovan return 0; 68150a708f8fSGustavo F. Padovan } 68160a708f8fSGustavo F. Padovan 6817b1c325c2SJohan Hedberg static void l2cap_chan_le_send_credits(struct l2cap_chan *chan) 6818b1c325c2SJohan Hedberg { 6819b1c325c2SJohan Hedberg struct l2cap_conn *conn = chan->conn; 6820b1c325c2SJohan Hedberg struct l2cap_le_credits pkt; 6821b1c325c2SJohan Hedberg u16 return_credits; 6822b1c325c2SJohan Hedberg 6823b1c325c2SJohan Hedberg /* We return more credits to the sender only after the amount of 6824b1c325c2SJohan Hedberg * credits falls below half of the initial amount. 6825b1c325c2SJohan Hedberg */ 6826f15b8ecfSJohan Hedberg if (chan->rx_credits >= (le_max_credits + 1) / 2) 6827b1c325c2SJohan Hedberg return; 6828b1c325c2SJohan Hedberg 6829f15b8ecfSJohan Hedberg return_credits = le_max_credits - chan->rx_credits; 6830b1c325c2SJohan Hedberg 6831b1c325c2SJohan Hedberg BT_DBG("chan %p returning %u credits to sender", chan, return_credits); 6832b1c325c2SJohan Hedberg 6833b1c325c2SJohan Hedberg chan->rx_credits += return_credits; 6834b1c325c2SJohan Hedberg 6835b1c325c2SJohan Hedberg pkt.cid = cpu_to_le16(chan->scid); 6836b1c325c2SJohan Hedberg pkt.credits = cpu_to_le16(return_credits); 6837b1c325c2SJohan Hedberg 6838b1c325c2SJohan Hedberg chan->ident = l2cap_get_ident(conn); 6839b1c325c2SJohan Hedberg 6840b1c325c2SJohan Hedberg l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt); 6841b1c325c2SJohan Hedberg } 6842b1c325c2SJohan Hedberg 6843fad5fc89SJohan Hedberg static int l2cap_le_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 6844fad5fc89SJohan Hedberg { 6845aac23bf6SJohan Hedberg int err; 6846fad5fc89SJohan Hedberg 6847aac23bf6SJohan Hedberg if (!chan->rx_credits) { 6848aac23bf6SJohan Hedberg BT_ERR("No credits to receive LE L2CAP data"); 6849fad5fc89SJohan Hedberg return -ENOBUFS; 6850aac23bf6SJohan Hedberg } 6851aac23bf6SJohan Hedberg 6852aac23bf6SJohan Hedberg if (chan->imtu < skb->len) { 6853aac23bf6SJohan Hedberg BT_ERR("Too big LE L2CAP PDU"); 6854aac23bf6SJohan Hedberg return -ENOBUFS; 6855aac23bf6SJohan Hedberg } 6856fad5fc89SJohan Hedberg 6857fad5fc89SJohan Hedberg chan->rx_credits--; 6858fad5fc89SJohan Hedberg BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits); 6859fad5fc89SJohan Hedberg 6860fad5fc89SJohan Hedberg l2cap_chan_le_send_credits(chan); 6861fad5fc89SJohan Hedberg 6862aac23bf6SJohan Hedberg err = 0; 6863aac23bf6SJohan Hedberg 6864aac23bf6SJohan Hedberg if (!chan->sdu) { 6865aac23bf6SJohan Hedberg u16 sdu_len; 6866aac23bf6SJohan Hedberg 6867aac23bf6SJohan Hedberg sdu_len = get_unaligned_le16(skb->data); 6868aac23bf6SJohan Hedberg skb_pull(skb, L2CAP_SDULEN_SIZE); 6869aac23bf6SJohan Hedberg 6870aac23bf6SJohan Hedberg BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u", 6871aac23bf6SJohan Hedberg sdu_len, skb->len, chan->imtu); 6872aac23bf6SJohan Hedberg 6873aac23bf6SJohan Hedberg if (sdu_len > chan->imtu) { 6874aac23bf6SJohan Hedberg BT_ERR("Too big LE L2CAP SDU length received"); 6875aac23bf6SJohan Hedberg err = -EMSGSIZE; 6876aac23bf6SJohan Hedberg goto failed; 6877aac23bf6SJohan Hedberg } 6878aac23bf6SJohan Hedberg 6879aac23bf6SJohan Hedberg if (skb->len > sdu_len) { 6880aac23bf6SJohan Hedberg BT_ERR("Too much LE L2CAP data received"); 6881aac23bf6SJohan Hedberg err = -EINVAL; 6882aac23bf6SJohan Hedberg goto failed; 6883aac23bf6SJohan Hedberg } 6884aac23bf6SJohan Hedberg 6885aac23bf6SJohan Hedberg if (skb->len == sdu_len) 6886fad5fc89SJohan Hedberg return chan->ops->recv(chan, skb); 6887aac23bf6SJohan Hedberg 6888aac23bf6SJohan Hedberg chan->sdu = skb; 6889aac23bf6SJohan Hedberg chan->sdu_len = sdu_len; 6890aac23bf6SJohan Hedberg chan->sdu_last_frag = skb; 6891aac23bf6SJohan Hedberg 6892aac23bf6SJohan Hedberg return 0; 6893aac23bf6SJohan Hedberg } 6894aac23bf6SJohan Hedberg 6895aac23bf6SJohan Hedberg BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u", 6896aac23bf6SJohan Hedberg chan->sdu->len, skb->len, chan->sdu_len); 6897aac23bf6SJohan Hedberg 6898aac23bf6SJohan Hedberg if (chan->sdu->len + skb->len > chan->sdu_len) { 6899aac23bf6SJohan Hedberg BT_ERR("Too much LE L2CAP data received"); 6900aac23bf6SJohan Hedberg err = -EINVAL; 6901aac23bf6SJohan Hedberg goto failed; 6902aac23bf6SJohan Hedberg } 6903aac23bf6SJohan Hedberg 6904aac23bf6SJohan Hedberg append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag); 6905aac23bf6SJohan Hedberg skb = NULL; 6906aac23bf6SJohan Hedberg 6907aac23bf6SJohan Hedberg if (chan->sdu->len == chan->sdu_len) { 6908aac23bf6SJohan Hedberg err = chan->ops->recv(chan, chan->sdu); 6909aac23bf6SJohan Hedberg if (!err) { 6910aac23bf6SJohan Hedberg chan->sdu = NULL; 6911aac23bf6SJohan Hedberg chan->sdu_last_frag = NULL; 6912aac23bf6SJohan Hedberg chan->sdu_len = 0; 6913aac23bf6SJohan Hedberg } 6914aac23bf6SJohan Hedberg } 6915aac23bf6SJohan Hedberg 6916aac23bf6SJohan Hedberg failed: 6917aac23bf6SJohan Hedberg if (err) { 6918aac23bf6SJohan Hedberg kfree_skb(skb); 6919aac23bf6SJohan Hedberg kfree_skb(chan->sdu); 6920aac23bf6SJohan Hedberg chan->sdu = NULL; 6921aac23bf6SJohan Hedberg chan->sdu_last_frag = NULL; 6922aac23bf6SJohan Hedberg chan->sdu_len = 0; 6923aac23bf6SJohan Hedberg } 6924aac23bf6SJohan Hedberg 6925aac23bf6SJohan Hedberg /* We can't return an error here since we took care of the skb 6926aac23bf6SJohan Hedberg * freeing internally. An error return would cause the caller to 6927aac23bf6SJohan Hedberg * do a double-free of the skb. 6928aac23bf6SJohan Hedberg */ 6929aac23bf6SJohan Hedberg return 0; 6930fad5fc89SJohan Hedberg } 6931fad5fc89SJohan Hedberg 693213ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid, 693313ca56e0SAndrei Emeltchenko struct sk_buff *skb) 69340a708f8fSGustavo F. Padovan { 693548454079SGustavo F. Padovan struct l2cap_chan *chan; 69360a708f8fSGustavo F. Padovan 6937baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 693848454079SGustavo F. Padovan if (!chan) { 693997e8e89dSAndrei Emeltchenko if (cid == L2CAP_CID_A2MP) { 694097e8e89dSAndrei Emeltchenko chan = a2mp_channel_create(conn, skb); 694197e8e89dSAndrei Emeltchenko if (!chan) { 694297e8e89dSAndrei Emeltchenko kfree_skb(skb); 694313ca56e0SAndrei Emeltchenko return; 694497e8e89dSAndrei Emeltchenko } 694597e8e89dSAndrei Emeltchenko 694697e8e89dSAndrei Emeltchenko l2cap_chan_lock(chan); 694797e8e89dSAndrei Emeltchenko } else { 69480a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid); 69496be36555SAndrei Emeltchenko /* Drop packet and return */ 69503379013bSDan Carpenter kfree_skb(skb); 695113ca56e0SAndrei Emeltchenko return; 69520a708f8fSGustavo F. Padovan } 695397e8e89dSAndrei Emeltchenko } 69540a708f8fSGustavo F. Padovan 695549208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len); 69560a708f8fSGustavo F. Padovan 695789bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 69580a708f8fSGustavo F. Padovan goto drop; 69590a708f8fSGustavo F. Padovan 69600c1bc5c6SGustavo F. Padovan switch (chan->mode) { 696138319713SJohan Hedberg case L2CAP_MODE_LE_FLOWCTL: 6962fad5fc89SJohan Hedberg if (l2cap_le_data_rcv(chan, skb) < 0) 6963fad5fc89SJohan Hedberg goto drop; 6964fad5fc89SJohan Hedberg 6965fad5fc89SJohan Hedberg goto done; 6966fad5fc89SJohan Hedberg 69670a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 69680a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here 69690a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable. 69700a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't 69710a708f8fSGustavo F. Padovan * provide flow control mechanism. */ 69720a708f8fSGustavo F. Padovan 69730c1bc5c6SGustavo F. Padovan if (chan->imtu < skb->len) 69740a708f8fSGustavo F. Padovan goto drop; 69750a708f8fSGustavo F. Padovan 697680b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 69770a708f8fSGustavo F. Padovan goto done; 69780a708f8fSGustavo F. Padovan break; 69790a708f8fSGustavo F. Padovan 69800a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 69810a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 6982cec8ab6eSMat Martineau l2cap_data_rcv(chan, skb); 69830a708f8fSGustavo F. Padovan goto done; 69840a708f8fSGustavo F. Padovan 69850a708f8fSGustavo F. Padovan default: 69860c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); 69870a708f8fSGustavo F. Padovan break; 69880a708f8fSGustavo F. Padovan } 69890a708f8fSGustavo F. Padovan 69900a708f8fSGustavo F. Padovan drop: 69910a708f8fSGustavo F. Padovan kfree_skb(skb); 69920a708f8fSGustavo F. Padovan 69930a708f8fSGustavo F. Padovan done: 69946be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 69950a708f8fSGustavo F. Padovan } 69960a708f8fSGustavo F. Padovan 699784104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, 699884104b24SAndrei Emeltchenko struct sk_buff *skb) 69990a708f8fSGustavo F. Padovan { 7000ae4fd2d3SMarcel Holtmann struct hci_conn *hcon = conn->hcon; 700123691d75SGustavo F. Padovan struct l2cap_chan *chan; 70020a708f8fSGustavo F. Padovan 7003ae4fd2d3SMarcel Holtmann if (hcon->type != ACL_LINK) 7004ae4fd2d3SMarcel Holtmann goto drop; 7005ae4fd2d3SMarcel Holtmann 7006bf20fd4eSJohan Hedberg chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst, 7007bf20fd4eSJohan Hedberg ACL_LINK); 700823691d75SGustavo F. Padovan if (!chan) 70090a708f8fSGustavo F. Padovan goto drop; 70100a708f8fSGustavo F. Padovan 70115b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 70120a708f8fSGustavo F. Padovan 701389bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 70140a708f8fSGustavo F. Padovan goto drop; 70150a708f8fSGustavo F. Padovan 7016e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 70170a708f8fSGustavo F. Padovan goto drop; 70180a708f8fSGustavo F. Padovan 70192edf870dSMarcel Holtmann /* Store remote BD_ADDR and PSM for msg_name */ 702006ae3314SMarcel Holtmann bacpy(&bt_cb(skb)->bdaddr, &hcon->dst); 70212edf870dSMarcel Holtmann bt_cb(skb)->psm = psm; 70222edf870dSMarcel Holtmann 702380b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 702484104b24SAndrei Emeltchenko return; 70250a708f8fSGustavo F. Padovan 70260a708f8fSGustavo F. Padovan drop: 70270a708f8fSGustavo F. Padovan kfree_skb(skb); 70280a708f8fSGustavo F. Padovan } 70290a708f8fSGustavo F. Padovan 703072f78356SMarcel Holtmann static void l2cap_att_channel(struct l2cap_conn *conn, 7031d9b88702SAndrei Emeltchenko struct sk_buff *skb) 70329f69bda6SGustavo F. Padovan { 7033b99707d7SMarcel Holtmann struct hci_conn *hcon = conn->hcon; 703423691d75SGustavo F. Padovan struct l2cap_chan *chan; 70359f69bda6SGustavo F. Padovan 7036b99707d7SMarcel Holtmann if (hcon->type != LE_LINK) 7037b99707d7SMarcel Holtmann goto drop; 7038b99707d7SMarcel Holtmann 7039af1c0134SJohan Hedberg chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT, 704006ae3314SMarcel Holtmann &hcon->src, &hcon->dst); 704123691d75SGustavo F. Padovan if (!chan) 70429f69bda6SGustavo F. Padovan goto drop; 70439f69bda6SGustavo F. Padovan 70445b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 70459f69bda6SGustavo F. Padovan 7046cc8dba2bSMarcel Holtmann if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, hcon->dst_type)) 7047cc8dba2bSMarcel Holtmann goto drop; 7048cc8dba2bSMarcel Holtmann 7049e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 70509f69bda6SGustavo F. Padovan goto drop; 70519f69bda6SGustavo F. Padovan 705280b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 70536810fca7SAndrei Emeltchenko return; 70549f69bda6SGustavo F. Padovan 70559f69bda6SGustavo F. Padovan drop: 70569f69bda6SGustavo F. Padovan kfree_skb(skb); 70579f69bda6SGustavo F. Padovan } 70589f69bda6SGustavo F. Padovan 70590a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) 70600a708f8fSGustavo F. Padovan { 70610a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data; 70620a708f8fSGustavo F. Padovan u16 cid, len; 70630a708f8fSGustavo F. Padovan __le16 psm; 70640a708f8fSGustavo F. Padovan 70650a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE); 70660a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid); 70670a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len); 70680a708f8fSGustavo F. Padovan 70690a708f8fSGustavo F. Padovan if (len != skb->len) { 70700a708f8fSGustavo F. Padovan kfree_skb(skb); 70710a708f8fSGustavo F. Padovan return; 70720a708f8fSGustavo F. Padovan } 70730a708f8fSGustavo F. Padovan 70740a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid); 70750a708f8fSGustavo F. Padovan 70760a708f8fSGustavo F. Padovan switch (cid) { 70770a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING: 70780a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb); 70790a708f8fSGustavo F. Padovan break; 70800a708f8fSGustavo F. Padovan 70810a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS: 7082097db76cSAndrei Emeltchenko psm = get_unaligned((__le16 *) skb->data); 70830181a70fSAndrei Emeltchenko skb_pull(skb, L2CAP_PSMLEN_SIZE); 70840a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb); 70850a708f8fSGustavo F. Padovan break; 70860a708f8fSGustavo F. Padovan 7087073d1cf3SJohan Hedberg case L2CAP_CID_ATT: 708872f78356SMarcel Holtmann l2cap_att_channel(conn, skb); 70899f69bda6SGustavo F. Padovan break; 70909f69bda6SGustavo F. Padovan 7091a2877629SMarcel Holtmann case L2CAP_CID_LE_SIGNALING: 7092a2877629SMarcel Holtmann l2cap_le_sig_channel(conn, skb); 7093a2877629SMarcel Holtmann break; 7094a2877629SMarcel Holtmann 7095b501d6a1SAnderson Briglia case L2CAP_CID_SMP: 7096b501d6a1SAnderson Briglia if (smp_sig_channel(conn, skb)) 7097b501d6a1SAnderson Briglia l2cap_conn_del(conn->hcon, EACCES); 7098b501d6a1SAnderson Briglia break; 7099b501d6a1SAnderson Briglia 71000a708f8fSGustavo F. Padovan default: 71010a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb); 71020a708f8fSGustavo F. Padovan break; 71030a708f8fSGustavo F. Padovan } 71040a708f8fSGustavo F. Padovan } 71050a708f8fSGustavo F. Padovan 71060a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */ 71070a708f8fSGustavo F. Padovan 7108686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) 71090a708f8fSGustavo F. Padovan { 71100a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0; 711123691d75SGustavo F. Padovan struct l2cap_chan *c; 71120a708f8fSGustavo F. Padovan 71136ed93dc6SAndrei Emeltchenko BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr); 71140a708f8fSGustavo F. Padovan 71150a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */ 711623691d75SGustavo F. Padovan read_lock(&chan_list_lock); 711723691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 711889bc500eSGustavo F. Padovan if (c->state != BT_LISTEN) 71190a708f8fSGustavo F. Padovan continue; 71200a708f8fSGustavo F. Padovan 71217eafc59eSMarcel Holtmann if (!bacmp(&c->src, &hdev->bdaddr)) { 71220a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT; 712343bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 71240a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER; 71250a708f8fSGustavo F. Padovan exact++; 71267eafc59eSMarcel Holtmann } else if (!bacmp(&c->src, BDADDR_ANY)) { 71270a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT; 712843bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 71290a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER; 71300a708f8fSGustavo F. Padovan } 71310a708f8fSGustavo F. Padovan } 713223691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 71330a708f8fSGustavo F. Padovan 71340a708f8fSGustavo F. Padovan return exact ? lm1 : lm2; 71350a708f8fSGustavo F. Padovan } 71360a708f8fSGustavo F. Padovan 71379e664631SAndrei Emeltchenko void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) 71380a708f8fSGustavo F. Padovan { 71390a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 71400a708f8fSGustavo F. Padovan 71416ed93dc6SAndrei Emeltchenko BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status); 71420a708f8fSGustavo F. Padovan 71430a708f8fSGustavo F. Padovan if (!status) { 7144baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon); 71450a708f8fSGustavo F. Padovan if (conn) 71460a708f8fSGustavo F. Padovan l2cap_conn_ready(conn); 7147ba6fc317SAndrei Emeltchenko } else { 7148e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status)); 7149ba6fc317SAndrei Emeltchenko } 71500a708f8fSGustavo F. Padovan } 71510a708f8fSGustavo F. Padovan 7152686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon) 71530a708f8fSGustavo F. Padovan { 71540a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 71550a708f8fSGustavo F. Padovan 71560a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon); 71570a708f8fSGustavo F. Padovan 7158686ebf28SUlisses Furquim if (!conn) 71599f5a0d7bSAndrei Emeltchenko return HCI_ERROR_REMOTE_USER_TERM; 71600a708f8fSGustavo F. Padovan return conn->disc_reason; 71610a708f8fSGustavo F. Padovan } 71620a708f8fSGustavo F. Padovan 71639e664631SAndrei Emeltchenko void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) 71640a708f8fSGustavo F. Padovan { 71650a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason); 71660a708f8fSGustavo F. Padovan 7167e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason)); 71680a708f8fSGustavo F. Padovan } 71690a708f8fSGustavo F. Padovan 71704343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) 71710a708f8fSGustavo F. Padovan { 7172715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 71730a708f8fSGustavo F. Padovan return; 71740a708f8fSGustavo F. Padovan 71750a708f8fSGustavo F. Padovan if (encrypt == 0x00) { 71764343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) { 7177ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); 71784343478fSGustavo F. Padovan } else if (chan->sec_level == BT_SECURITY_HIGH) 71790f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED); 71800a708f8fSGustavo F. Padovan } else { 71814343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) 7182c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 71830a708f8fSGustavo F. Padovan } 71840a708f8fSGustavo F. Padovan } 71850a708f8fSGustavo F. Padovan 7186686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) 71870a708f8fSGustavo F. Padovan { 71880a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 718948454079SGustavo F. Padovan struct l2cap_chan *chan; 71900a708f8fSGustavo F. Padovan 71910a708f8fSGustavo F. Padovan if (!conn) 71920a708f8fSGustavo F. Padovan return 0; 71930a708f8fSGustavo F. Padovan 719489d8b407SAndrei Emeltchenko BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt); 71950a708f8fSGustavo F. Padovan 7196160dc6acSVinicius Costa Gomes if (hcon->type == LE_LINK) { 719735d4adccSHemant Gupta if (!status && encrypt) 7198160dc6acSVinicius Costa Gomes smp_distribute_keys(conn, 0); 719917cd3f37SUlisses Furquim cancel_delayed_work(&conn->security_timer); 7200160dc6acSVinicius Costa Gomes } 7201160dc6acSVinicius Costa Gomes 72023df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 72030a708f8fSGustavo F. Padovan 72043df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 72056be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 72060a708f8fSGustavo F. Padovan 720789d8b407SAndrei Emeltchenko BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, 720889d8b407SAndrei Emeltchenko state_to_string(chan->state)); 7209f1cb9af5SVinicius Costa Gomes 721078eb2f98SAndrei Emeltchenko if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { 721178eb2f98SAndrei Emeltchenko l2cap_chan_unlock(chan); 721278eb2f98SAndrei Emeltchenko continue; 721378eb2f98SAndrei Emeltchenko } 721478eb2f98SAndrei Emeltchenko 7215073d1cf3SJohan Hedberg if (chan->scid == L2CAP_CID_ATT) { 7216f1cb9af5SVinicius Costa Gomes if (!status && encrypt) { 7217f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level; 7218cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 7219f1cb9af5SVinicius Costa Gomes } 7220f1cb9af5SVinicius Costa Gomes 72216be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 7222f1cb9af5SVinicius Costa Gomes continue; 7223f1cb9af5SVinicius Costa Gomes } 7224f1cb9af5SVinicius Costa Gomes 722596eff46eSAndrei Emeltchenko if (!__l2cap_no_conn_pending(chan)) { 72266be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 72270a708f8fSGustavo F. Padovan continue; 72280a708f8fSGustavo F. Padovan } 72290a708f8fSGustavo F. Padovan 723089bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED || 723189bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) { 7232d97c899bSMarcel Holtmann chan->ops->resume(chan); 72334343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt); 72346be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 72350a708f8fSGustavo F. Padovan continue; 72360a708f8fSGustavo F. Padovan } 72370a708f8fSGustavo F. Padovan 723889bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 72396d3c15daSJohan Hedberg if (!status) 724093c3e8f5SAndrei Emeltchenko l2cap_start_connection(chan); 72416d3c15daSJohan Hedberg else 7242ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 724389bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 72440a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 7245df3c3931SJohan Hedberg __u16 res, stat; 72460a708f8fSGustavo F. Padovan 72470a708f8fSGustavo F. Padovan if (!status) { 7248bdc25783SMarcel Holtmann if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 7249df3c3931SJohan Hedberg res = L2CAP_CR_PEND; 7250df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND; 72512dc4e510SGustavo Padovan chan->ops->defer(chan); 7252df3c3931SJohan Hedberg } else { 7253acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_CONFIG); 7254df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS; 7255df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 7256df3c3931SJohan Hedberg } 72570a708f8fSGustavo F. Padovan } else { 7258acdcabf5SGustavo Padovan l2cap_state_change(chan, BT_DISCONN); 7259ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 7260df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK; 7261df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 72620a708f8fSGustavo F. Padovan } 72630a708f8fSGustavo F. Padovan 7264fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 7265fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 7266df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res); 7267df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat); 7268fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 7269fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 72702d369359SMat Martineau 72712d369359SMat Martineau if (!test_bit(CONF_REQ_SENT, &chan->conf_state) && 72722d369359SMat Martineau res == L2CAP_CR_SUCCESS) { 72732d369359SMat Martineau char buf[128]; 72742d369359SMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 72752d369359SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), 72762d369359SMat Martineau L2CAP_CONF_REQ, 72772d369359SMat Martineau l2cap_build_conf_req(chan, buf), 72782d369359SMat Martineau buf); 72792d369359SMat Martineau chan->num_conf_req++; 72802d369359SMat Martineau } 72810a708f8fSGustavo F. Padovan } 72820a708f8fSGustavo F. Padovan 72836be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 72840a708f8fSGustavo F. Padovan } 72850a708f8fSGustavo F. Padovan 72863df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 72870a708f8fSGustavo F. Padovan 72880a708f8fSGustavo F. Padovan return 0; 72890a708f8fSGustavo F. Padovan } 72900a708f8fSGustavo F. Padovan 7291686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) 72920a708f8fSGustavo F. Padovan { 72930a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 7294d73a0988SAndrei Emeltchenko struct l2cap_hdr *hdr; 7295d73a0988SAndrei Emeltchenko int len; 72960a708f8fSGustavo F. Padovan 72971d13a254SAndrei Emeltchenko /* For AMP controller do not create l2cap conn */ 72981d13a254SAndrei Emeltchenko if (!conn && hcon->hdev->dev_type != HCI_BREDR) 72991d13a254SAndrei Emeltchenko goto drop; 73000a708f8fSGustavo F. Padovan 73010a708f8fSGustavo F. Padovan if (!conn) 7302baf43251SClaudio Takahasi conn = l2cap_conn_add(hcon); 73030a708f8fSGustavo F. Padovan 73040a708f8fSGustavo F. Padovan if (!conn) 73050a708f8fSGustavo F. Padovan goto drop; 73060a708f8fSGustavo F. Padovan 73070a708f8fSGustavo F. Padovan BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); 73080a708f8fSGustavo F. Padovan 7309d73a0988SAndrei Emeltchenko switch (flags) { 7310d73a0988SAndrei Emeltchenko case ACL_START: 7311d73a0988SAndrei Emeltchenko case ACL_START_NO_FLUSH: 7312d73a0988SAndrei Emeltchenko case ACL_COMPLETE: 73130a708f8fSGustavo F. Padovan if (conn->rx_len) { 73140a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len); 73150a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 73160a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 73170a708f8fSGustavo F. Padovan conn->rx_len = 0; 73180a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 73190a708f8fSGustavo F. Padovan } 73200a708f8fSGustavo F. Padovan 73210a708f8fSGustavo F. Padovan /* Start fragment always begin with Basic L2CAP header */ 73220a708f8fSGustavo F. Padovan if (skb->len < L2CAP_HDR_SIZE) { 73230a708f8fSGustavo F. Padovan BT_ERR("Frame is too short (len %d)", skb->len); 73240a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 73250a708f8fSGustavo F. Padovan goto drop; 73260a708f8fSGustavo F. Padovan } 73270a708f8fSGustavo F. Padovan 73280a708f8fSGustavo F. Padovan hdr = (struct l2cap_hdr *) skb->data; 73290a708f8fSGustavo F. Padovan len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; 73300a708f8fSGustavo F. Padovan 73310a708f8fSGustavo F. Padovan if (len == skb->len) { 73320a708f8fSGustavo F. Padovan /* Complete frame received */ 73330a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb); 73340a708f8fSGustavo F. Padovan return 0; 73350a708f8fSGustavo F. Padovan } 73360a708f8fSGustavo F. Padovan 73370a708f8fSGustavo F. Padovan BT_DBG("Start: total len %d, frag len %d", len, skb->len); 73380a708f8fSGustavo F. Padovan 73390a708f8fSGustavo F. Padovan if (skb->len > len) { 73400a708f8fSGustavo F. Padovan BT_ERR("Frame is too long (len %d, expected len %d)", 73410a708f8fSGustavo F. Padovan skb->len, len); 73420a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 73430a708f8fSGustavo F. Padovan goto drop; 73440a708f8fSGustavo F. Padovan } 73450a708f8fSGustavo F. Padovan 73460a708f8fSGustavo F. Padovan /* Allocate skb for the complete frame (with header) */ 73478bcde1f2SGustavo Padovan conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL); 73480a708f8fSGustavo F. Padovan if (!conn->rx_skb) 73490a708f8fSGustavo F. Padovan goto drop; 73500a708f8fSGustavo F. Padovan 73510a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 73520a708f8fSGustavo F. Padovan skb->len); 73530a708f8fSGustavo F. Padovan conn->rx_len = len - skb->len; 7354d73a0988SAndrei Emeltchenko break; 7355d73a0988SAndrei Emeltchenko 7356d73a0988SAndrei Emeltchenko case ACL_CONT: 73570a708f8fSGustavo F. Padovan BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); 73580a708f8fSGustavo F. Padovan 73590a708f8fSGustavo F. Padovan if (!conn->rx_len) { 73600a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len); 73610a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 73620a708f8fSGustavo F. Padovan goto drop; 73630a708f8fSGustavo F. Padovan } 73640a708f8fSGustavo F. Padovan 73650a708f8fSGustavo F. Padovan if (skb->len > conn->rx_len) { 73660a708f8fSGustavo F. Padovan BT_ERR("Fragment is too long (len %d, expected %d)", 73670a708f8fSGustavo F. Padovan skb->len, conn->rx_len); 73680a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 73690a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 73700a708f8fSGustavo F. Padovan conn->rx_len = 0; 73710a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 73720a708f8fSGustavo F. Padovan goto drop; 73730a708f8fSGustavo F. Padovan } 73740a708f8fSGustavo F. Padovan 73750a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 73760a708f8fSGustavo F. Padovan skb->len); 73770a708f8fSGustavo F. Padovan conn->rx_len -= skb->len; 73780a708f8fSGustavo F. Padovan 73790a708f8fSGustavo F. Padovan if (!conn->rx_len) { 7380c4e5bafaSJohan Hedberg /* Complete frame received. l2cap_recv_frame 7381c4e5bafaSJohan Hedberg * takes ownership of the skb so set the global 7382c4e5bafaSJohan Hedberg * rx_skb pointer to NULL first. 7383c4e5bafaSJohan Hedberg */ 7384c4e5bafaSJohan Hedberg struct sk_buff *rx_skb = conn->rx_skb; 73850a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 7386c4e5bafaSJohan Hedberg l2cap_recv_frame(conn, rx_skb); 73870a708f8fSGustavo F. Padovan } 7388d73a0988SAndrei Emeltchenko break; 73890a708f8fSGustavo F. Padovan } 73900a708f8fSGustavo F. Padovan 73910a708f8fSGustavo F. Padovan drop: 73920a708f8fSGustavo F. Padovan kfree_skb(skb); 73930a708f8fSGustavo F. Padovan return 0; 73940a708f8fSGustavo F. Padovan } 73950a708f8fSGustavo F. Padovan 73960a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p) 73970a708f8fSGustavo F. Padovan { 739823691d75SGustavo F. Padovan struct l2cap_chan *c; 73990a708f8fSGustavo F. Padovan 7400333055f2SGustavo F. Padovan read_lock(&chan_list_lock); 74010a708f8fSGustavo F. Padovan 740223691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 7403fcb73338SAndrei Emeltchenko seq_printf(f, "%pMR %pMR %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", 74047eafc59eSMarcel Holtmann &c->src, &c->dst, 740589bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm), 740623691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu, 740723691d75SGustavo F. Padovan c->sec_level, c->mode); 74080a708f8fSGustavo F. Padovan } 74090a708f8fSGustavo F. Padovan 7410333055f2SGustavo F. Padovan read_unlock(&chan_list_lock); 74110a708f8fSGustavo F. Padovan 74120a708f8fSGustavo F. Padovan return 0; 74130a708f8fSGustavo F. Padovan } 74140a708f8fSGustavo F. Padovan 74150a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file) 74160a708f8fSGustavo F. Padovan { 74170a708f8fSGustavo F. Padovan return single_open(file, l2cap_debugfs_show, inode->i_private); 74180a708f8fSGustavo F. Padovan } 74190a708f8fSGustavo F. Padovan 74200a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = { 74210a708f8fSGustavo F. Padovan .open = l2cap_debugfs_open, 74220a708f8fSGustavo F. Padovan .read = seq_read, 74230a708f8fSGustavo F. Padovan .llseek = seq_lseek, 74240a708f8fSGustavo F. Padovan .release = single_release, 74250a708f8fSGustavo F. Padovan }; 74260a708f8fSGustavo F. Padovan 74270a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs; 74280a708f8fSGustavo F. Padovan 742964274518SGustavo F. Padovan int __init l2cap_init(void) 74300a708f8fSGustavo F. Padovan { 74310a708f8fSGustavo F. Padovan int err; 74320a708f8fSGustavo F. Padovan 7433bb58f747SGustavo F. Padovan err = l2cap_init_sockets(); 74340a708f8fSGustavo F. Padovan if (err < 0) 74350a708f8fSGustavo F. Padovan return err; 74360a708f8fSGustavo F. Padovan 74371120e4bfSMarcel Holtmann if (IS_ERR_OR_NULL(bt_debugfs)) 74381120e4bfSMarcel Holtmann return 0; 74391120e4bfSMarcel Holtmann 74402d792818SGustavo Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, 74412d792818SGustavo Padovan NULL, &l2cap_debugfs_fops); 74420a708f8fSGustavo F. Padovan 7443f15b8ecfSJohan Hedberg debugfs_create_u16("l2cap_le_max_credits", 0466, bt_debugfs, 7444f15b8ecfSJohan Hedberg &le_max_credits); 7445f15b8ecfSJohan Hedberg debugfs_create_u16("l2cap_le_default_mps", 0466, bt_debugfs, 7446f15b8ecfSJohan Hedberg &le_default_mps); 7447f15b8ecfSJohan Hedberg 74480a708f8fSGustavo F. Padovan return 0; 74490a708f8fSGustavo F. Padovan } 74500a708f8fSGustavo F. Padovan 745164274518SGustavo F. Padovan void l2cap_exit(void) 74520a708f8fSGustavo F. Padovan { 74530a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs); 7454bb58f747SGustavo F. Padovan l2cap_cleanup_sockets(); 74550a708f8fSGustavo F. Padovan } 74560a708f8fSGustavo F. Padovan 74570a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644); 74580a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); 7459