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> 39b501d6a1SAnderson Briglia #include <net/bluetooth/smp.h> 400a708f8fSGustavo F. Padovan 41d1de6d46SMat Martineau bool disable_ertm; 420a708f8fSGustavo F. Padovan 430a708f8fSGustavo F. Padovan static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; 4450a147cdSMat Martineau static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, }; 450a708f8fSGustavo F. Padovan 46b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list); 47b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock); 480a708f8fSGustavo F. Padovan 490a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 500a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data); 514519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 524519de9aSGustavo F. Padovan void *data); 53710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); 544519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, 554519de9aSGustavo F. Padovan struct l2cap_chan *chan, int err); 560a708f8fSGustavo F. Padovan 57d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 58608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event); 59608bcc6dSMat Martineau 600a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */ 6171ba0e56SGustavo F. Padovan 62baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid) 630a708f8fSGustavo F. Padovan { 643df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 65baa7e1faSGustavo F. Padovan 663df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 673df91ea2SAndrei Emeltchenko if (c->dcid == cid) 683df91ea2SAndrei Emeltchenko return c; 690a708f8fSGustavo F. Padovan } 703df91ea2SAndrei Emeltchenko return NULL; 71baa7e1faSGustavo F. Padovan } 720a708f8fSGustavo F. Padovan 73baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) 740a708f8fSGustavo F. Padovan { 753df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 76baa7e1faSGustavo F. Padovan 773df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 783df91ea2SAndrei Emeltchenko if (c->scid == cid) 793df91ea2SAndrei Emeltchenko return c; 800a708f8fSGustavo F. Padovan } 813df91ea2SAndrei Emeltchenko return NULL; 82baa7e1faSGustavo F. Padovan } 830a708f8fSGustavo F. Padovan 840a708f8fSGustavo F. Padovan /* Find channel with given SCID. 85ef191adeSMat Martineau * Returns locked channel. */ 86baa7e1faSGustavo F. Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) 870a708f8fSGustavo F. Padovan { 8848454079SGustavo F. Padovan struct l2cap_chan *c; 89baa7e1faSGustavo F. Padovan 903df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 91baa7e1faSGustavo F. Padovan c = __l2cap_get_chan_by_scid(conn, cid); 92ef191adeSMat Martineau if (c) 93ef191adeSMat Martineau l2cap_chan_lock(c); 943df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 953df91ea2SAndrei Emeltchenko 9648454079SGustavo F. Padovan return c; 970a708f8fSGustavo F. Padovan } 980a708f8fSGustavo F. Padovan 99baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident) 1000a708f8fSGustavo F. Padovan { 1013df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 102baa7e1faSGustavo F. Padovan 1033df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 1043df91ea2SAndrei Emeltchenko if (c->ident == ident) 1053df91ea2SAndrei Emeltchenko return c; 1060a708f8fSGustavo F. Padovan } 1073df91ea2SAndrei Emeltchenko return NULL; 108baa7e1faSGustavo F. Padovan } 1090a708f8fSGustavo F. Padovan 11023691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src) 1119e4425ffSGustavo F. Padovan { 11223691d75SGustavo F. Padovan struct l2cap_chan *c; 1139e4425ffSGustavo F. Padovan 11423691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 11523691d75SGustavo F. Padovan if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src)) 11623691d75SGustavo F. Padovan return c; 1179e4425ffSGustavo F. Padovan } 118250938cbSSzymon Janc return NULL; 119250938cbSSzymon Janc } 1209e4425ffSGustavo F. Padovan 1219e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) 1229e4425ffSGustavo F. Padovan { 12373b2ec18SGustavo F. Padovan int err; 12473b2ec18SGustavo F. Padovan 125333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 1269e4425ffSGustavo F. Padovan 12723691d75SGustavo F. Padovan if (psm && __l2cap_global_chan_by_addr(psm, src)) { 12873b2ec18SGustavo F. Padovan err = -EADDRINUSE; 12973b2ec18SGustavo F. Padovan goto done; 1309e4425ffSGustavo F. Padovan } 1319e4425ffSGustavo F. Padovan 13273b2ec18SGustavo F. Padovan if (psm) { 1339e4425ffSGustavo F. Padovan chan->psm = psm; 1349e4425ffSGustavo F. Padovan chan->sport = psm; 13573b2ec18SGustavo F. Padovan err = 0; 13673b2ec18SGustavo F. Padovan } else { 13773b2ec18SGustavo F. Padovan u16 p; 1389e4425ffSGustavo F. Padovan 13973b2ec18SGustavo F. Padovan err = -EINVAL; 14073b2ec18SGustavo F. Padovan for (p = 0x1001; p < 0x1100; p += 2) 14123691d75SGustavo F. Padovan if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) { 14273b2ec18SGustavo F. Padovan chan->psm = cpu_to_le16(p); 14373b2ec18SGustavo F. Padovan chan->sport = cpu_to_le16(p); 14473b2ec18SGustavo F. Padovan err = 0; 14573b2ec18SGustavo F. Padovan break; 14673b2ec18SGustavo F. Padovan } 14773b2ec18SGustavo F. Padovan } 14873b2ec18SGustavo F. Padovan 14973b2ec18SGustavo F. Padovan done: 150333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 15173b2ec18SGustavo F. Padovan return err; 1529e4425ffSGustavo F. Padovan } 1539e4425ffSGustavo F. Padovan 1549e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) 1559e4425ffSGustavo F. Padovan { 156333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 1579e4425ffSGustavo F. Padovan 1589e4425ffSGustavo F. Padovan chan->scid = scid; 1599e4425ffSGustavo F. Padovan 160333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 1619e4425ffSGustavo F. Padovan 1629e4425ffSGustavo F. Padovan return 0; 1639e4425ffSGustavo F. Padovan } 1649e4425ffSGustavo F. Padovan 165baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn) 1660a708f8fSGustavo F. Padovan { 1670a708f8fSGustavo F. Padovan u16 cid = L2CAP_CID_DYN_START; 1680a708f8fSGustavo F. Padovan 1690a708f8fSGustavo F. Padovan for (; cid < L2CAP_CID_DYN_END; cid++) { 170baa7e1faSGustavo F. Padovan if (!__l2cap_get_chan_by_scid(conn, cid)) 1710a708f8fSGustavo F. Padovan return cid; 1720a708f8fSGustavo F. Padovan } 1730a708f8fSGustavo F. Padovan 1740a708f8fSGustavo F. Padovan return 0; 1750a708f8fSGustavo F. Padovan } 1760a708f8fSGustavo F. Padovan 1770e587be7SAndrei Emeltchenko static void __l2cap_state_change(struct l2cap_chan *chan, int state) 17889bc500eSGustavo F. Padovan { 17942d2d87cSAndrei Emeltchenko BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state), 180badaaa00SGustavo F. Padovan state_to_string(state)); 181badaaa00SGustavo F. Padovan 18289bc500eSGustavo F. Padovan chan->state = state; 18389bc500eSGustavo F. Padovan chan->ops->state_change(chan->data, state); 18489bc500eSGustavo F. Padovan } 18589bc500eSGustavo F. Padovan 1860e587be7SAndrei Emeltchenko static void l2cap_state_change(struct l2cap_chan *chan, int state) 1870e587be7SAndrei Emeltchenko { 1880e587be7SAndrei Emeltchenko struct sock *sk = chan->sk; 1890e587be7SAndrei Emeltchenko 1900e587be7SAndrei Emeltchenko lock_sock(sk); 1910e587be7SAndrei Emeltchenko __l2cap_state_change(chan, state); 1920e587be7SAndrei Emeltchenko release_sock(sk); 1930e587be7SAndrei Emeltchenko } 1940e587be7SAndrei Emeltchenko 1952e0052e4SAndrei Emeltchenko static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err) 1962e0052e4SAndrei Emeltchenko { 1972e0052e4SAndrei Emeltchenko struct sock *sk = chan->sk; 1982e0052e4SAndrei Emeltchenko 1992e0052e4SAndrei Emeltchenko sk->sk_err = err; 2002e0052e4SAndrei Emeltchenko } 2012e0052e4SAndrei Emeltchenko 2022e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err) 2032e0052e4SAndrei Emeltchenko { 2042e0052e4SAndrei Emeltchenko struct sock *sk = chan->sk; 2052e0052e4SAndrei Emeltchenko 2062e0052e4SAndrei Emeltchenko lock_sock(sk); 2072e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 2082e0052e4SAndrei Emeltchenko release_sock(sk); 2092e0052e4SAndrei Emeltchenko } 2102e0052e4SAndrei Emeltchenko 2114239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan) 2124239d16fSMat Martineau { 2134239d16fSMat Martineau if (!delayed_work_pending(&chan->monitor_timer) && 2144239d16fSMat Martineau chan->retrans_timeout) { 2154239d16fSMat Martineau l2cap_set_timer(chan, &chan->retrans_timer, 2164239d16fSMat Martineau msecs_to_jiffies(chan->retrans_timeout)); 2174239d16fSMat Martineau } 2184239d16fSMat Martineau } 2194239d16fSMat Martineau 2204239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan) 2214239d16fSMat Martineau { 2224239d16fSMat Martineau __clear_retrans_timer(chan); 2234239d16fSMat Martineau if (chan->monitor_timeout) { 2244239d16fSMat Martineau l2cap_set_timer(chan, &chan->monitor_timer, 2254239d16fSMat Martineau msecs_to_jiffies(chan->monitor_timeout)); 2264239d16fSMat Martineau } 2274239d16fSMat Martineau } 2284239d16fSMat Martineau 229608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head, 230608bcc6dSMat Martineau u16 seq) 231608bcc6dSMat Martineau { 232608bcc6dSMat Martineau struct sk_buff *skb; 233608bcc6dSMat Martineau 234608bcc6dSMat Martineau skb_queue_walk(head, skb) { 235608bcc6dSMat Martineau if (bt_cb(skb)->control.txseq == seq) 236608bcc6dSMat Martineau return skb; 237608bcc6dSMat Martineau } 238608bcc6dSMat Martineau 239608bcc6dSMat Martineau return NULL; 240608bcc6dSMat Martineau } 241608bcc6dSMat Martineau 2423c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */ 2433c588192SMat Martineau 2443c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for 2453c588192SMat Martineau * SREJ requests that are received and for frames that are to be 2463c588192SMat Martineau * retransmitted. These seq_list functions implement a singly-linked 2473c588192SMat Martineau * list in an array, where membership in the list can also be checked 2483c588192SMat Martineau * in constant time. Items can also be added to the tail of the list 2493c588192SMat Martineau * and removed from the head in constant time, without further memory 2503c588192SMat Martineau * allocs or frees. 2513c588192SMat Martineau */ 2523c588192SMat Martineau 2533c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size) 2543c588192SMat Martineau { 2553c588192SMat Martineau size_t alloc_size, i; 2563c588192SMat Martineau 2573c588192SMat Martineau /* Allocated size is a power of 2 to map sequence numbers 2583c588192SMat Martineau * (which may be up to 14 bits) in to a smaller array that is 2593c588192SMat Martineau * sized for the negotiated ERTM transmit windows. 2603c588192SMat Martineau */ 2613c588192SMat Martineau alloc_size = roundup_pow_of_two(size); 2623c588192SMat Martineau 2633c588192SMat Martineau seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL); 2643c588192SMat Martineau if (!seq_list->list) 2653c588192SMat Martineau return -ENOMEM; 2663c588192SMat Martineau 2673c588192SMat Martineau seq_list->mask = alloc_size - 1; 2683c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 2693c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 2703c588192SMat Martineau for (i = 0; i < alloc_size; i++) 2713c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 2723c588192SMat Martineau 2733c588192SMat Martineau return 0; 2743c588192SMat Martineau } 2753c588192SMat Martineau 2763c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list) 2773c588192SMat Martineau { 2783c588192SMat Martineau kfree(seq_list->list); 2793c588192SMat Martineau } 2803c588192SMat Martineau 2813c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list, 2823c588192SMat Martineau u16 seq) 2833c588192SMat Martineau { 2843c588192SMat Martineau /* Constant-time check for list membership */ 2853c588192SMat Martineau return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR; 2863c588192SMat Martineau } 2873c588192SMat Martineau 2883c588192SMat Martineau static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq) 2893c588192SMat Martineau { 2903c588192SMat Martineau u16 mask = seq_list->mask; 2913c588192SMat Martineau 2923c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) { 2933c588192SMat Martineau /* In case someone tries to pop the head of an empty list */ 2943c588192SMat Martineau return L2CAP_SEQ_LIST_CLEAR; 2953c588192SMat Martineau } else if (seq_list->head == seq) { 2963c588192SMat Martineau /* Head can be removed in constant time */ 2973c588192SMat Martineau seq_list->head = seq_list->list[seq & mask]; 2983c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; 2993c588192SMat Martineau 3003c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_TAIL) { 3013c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3023c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3033c588192SMat Martineau } 3043c588192SMat Martineau } else { 3053c588192SMat Martineau /* Walk the list to find the sequence number */ 3063c588192SMat Martineau u16 prev = seq_list->head; 3073c588192SMat Martineau while (seq_list->list[prev & mask] != seq) { 3083c588192SMat Martineau prev = seq_list->list[prev & mask]; 3093c588192SMat Martineau if (prev == L2CAP_SEQ_LIST_TAIL) 3103c588192SMat Martineau return L2CAP_SEQ_LIST_CLEAR; 3113c588192SMat Martineau } 3123c588192SMat Martineau 3133c588192SMat Martineau /* Unlink the number from the list and clear it */ 3143c588192SMat Martineau seq_list->list[prev & mask] = seq_list->list[seq & mask]; 3153c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; 3163c588192SMat Martineau if (seq_list->tail == seq) 3173c588192SMat Martineau seq_list->tail = prev; 3183c588192SMat Martineau } 3193c588192SMat Martineau return seq; 3203c588192SMat Martineau } 3213c588192SMat Martineau 3223c588192SMat Martineau static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list) 3233c588192SMat Martineau { 3243c588192SMat Martineau /* Remove the head in constant time */ 3253c588192SMat Martineau return l2cap_seq_list_remove(seq_list, seq_list->head); 3263c588192SMat Martineau } 3273c588192SMat Martineau 3283c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list) 3293c588192SMat Martineau { 3303c588192SMat Martineau u16 i; 331f522ae36SGustavo Padovan 332f522ae36SGustavo Padovan if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) 333f522ae36SGustavo Padovan return; 334f522ae36SGustavo Padovan 3353c588192SMat Martineau for (i = 0; i <= seq_list->mask; i++) 3363c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 3373c588192SMat Martineau 3383c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3393c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3403c588192SMat Martineau } 3413c588192SMat Martineau 3423c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq) 3433c588192SMat Martineau { 3443c588192SMat Martineau u16 mask = seq_list->mask; 3453c588192SMat Martineau 3463c588192SMat Martineau /* All appends happen in constant time */ 3473c588192SMat Martineau 348f522ae36SGustavo Padovan if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR) 349f522ae36SGustavo Padovan return; 350f522ae36SGustavo Padovan 3513c588192SMat Martineau if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR) 3523c588192SMat Martineau seq_list->head = seq; 3533c588192SMat Martineau else 3543c588192SMat Martineau seq_list->list[seq_list->tail & mask] = seq; 3553c588192SMat Martineau 3563c588192SMat Martineau seq_list->tail = seq; 3573c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL; 3583c588192SMat Martineau } 3593c588192SMat Martineau 360721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work) 361ab07801dSGustavo F. Padovan { 362721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 363721c4181SGustavo F. Padovan chan_timer.work); 3643df91ea2SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 365ab07801dSGustavo F. Padovan int reason; 366ab07801dSGustavo F. Padovan 367e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 368ab07801dSGustavo F. Padovan 3693df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 3706be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 371ab07801dSGustavo F. Padovan 37289bc500eSGustavo F. Padovan if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) 373ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 37489bc500eSGustavo F. Padovan else if (chan->state == BT_CONNECT && 375ab07801dSGustavo F. Padovan chan->sec_level != BT_SECURITY_SDP) 376ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 377ab07801dSGustavo F. Padovan else 378ab07801dSGustavo F. Padovan reason = ETIMEDOUT; 379ab07801dSGustavo F. Padovan 3800f852724SGustavo F. Padovan l2cap_chan_close(chan, reason); 381ab07801dSGustavo F. Padovan 3826be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 383ab07801dSGustavo F. Padovan 384ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 3853df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 3863df91ea2SAndrei Emeltchenko 387371fd835SUlisses Furquim l2cap_chan_put(chan); 388ab07801dSGustavo F. Padovan } 389ab07801dSGustavo F. Padovan 390eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void) 3910a708f8fSGustavo F. Padovan { 39248454079SGustavo F. Padovan struct l2cap_chan *chan; 3930a708f8fSGustavo F. Padovan 39448454079SGustavo F. Padovan chan = kzalloc(sizeof(*chan), GFP_ATOMIC); 39548454079SGustavo F. Padovan if (!chan) 39648454079SGustavo F. Padovan return NULL; 3970a708f8fSGustavo F. Padovan 398c03b355eSAndrei Emeltchenko mutex_init(&chan->lock); 399c03b355eSAndrei Emeltchenko 400333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 40123691d75SGustavo F. Padovan list_add(&chan->global_l, &chan_list); 402333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 40323691d75SGustavo F. Padovan 404721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout); 405ab07801dSGustavo F. Padovan 40689bc500eSGustavo F. Padovan chan->state = BT_OPEN; 40789bc500eSGustavo F. Padovan 40871ba0e56SGustavo F. Padovan atomic_set(&chan->refcnt, 1); 40971ba0e56SGustavo F. Padovan 4102827011fSMat Martineau /* This flag is cleared in l2cap_chan_ready() */ 4112827011fSMat Martineau set_bit(CONF_NOT_COMPLETE, &chan->conf_state); 4122827011fSMat Martineau 413eef1d9b6SGustavo Padovan BT_DBG("chan %p", chan); 414abc545b8SSzymon Janc 41548454079SGustavo F. Padovan return chan; 4160a708f8fSGustavo F. Padovan } 4170a708f8fSGustavo F. Padovan 41823691d75SGustavo F. Padovan void l2cap_chan_destroy(struct l2cap_chan *chan) 4196ff5abbfSGustavo F. Padovan { 420333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 42123691d75SGustavo F. Padovan list_del(&chan->global_l); 422333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 42323691d75SGustavo F. Padovan 424371fd835SUlisses Furquim l2cap_chan_put(chan); 4256ff5abbfSGustavo F. Padovan } 4266ff5abbfSGustavo F. Padovan 427bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan) 428bd4b1653SAndrei Emeltchenko { 429bd4b1653SAndrei Emeltchenko chan->fcs = L2CAP_FCS_CRC16; 430bd4b1653SAndrei Emeltchenko chan->max_tx = L2CAP_DEFAULT_MAX_TX; 431bd4b1653SAndrei Emeltchenko chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; 432bd4b1653SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 433bd4b1653SAndrei Emeltchenko chan->sec_level = BT_SECURITY_LOW; 434bd4b1653SAndrei Emeltchenko 435bd4b1653SAndrei Emeltchenko set_bit(FLAG_FORCE_ACTIVE, &chan->flags); 436bd4b1653SAndrei Emeltchenko } 437bd4b1653SAndrei Emeltchenko 43814a28491SAndrei Emeltchenko static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 4390a708f8fSGustavo F. Padovan { 4400a708f8fSGustavo F. Padovan BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, 441097db76cSAndrei Emeltchenko __le16_to_cpu(chan->psm), chan->dcid); 4420a708f8fSGustavo F. Padovan 4439f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 4440a708f8fSGustavo F. Padovan 4458c1d787bSGustavo F. Padovan chan->conn = conn; 4460a708f8fSGustavo F. Padovan 4475491120eSAndrei Emeltchenko switch (chan->chan_type) { 4485491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_ORIENTED: 449b62f328bSVille Tervo if (conn->hcon->type == LE_LINK) { 450b62f328bSVille Tervo /* LE connection */ 4510c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_LE_DEFAULT_MTU; 452fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_LE_DATA; 453fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_LE_DATA; 454b62f328bSVille Tervo } else { 4550a708f8fSGustavo F. Padovan /* Alloc CID for connection-oriented socket */ 456fe4128e0SGustavo F. Padovan chan->scid = l2cap_alloc_cid(conn); 4570c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 458b62f328bSVille Tervo } 4595491120eSAndrei Emeltchenko break; 4605491120eSAndrei Emeltchenko 4615491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_LESS: 4620a708f8fSGustavo F. Padovan /* Connectionless socket */ 463fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_CONN_LESS; 464fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_CONN_LESS; 4650c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 4665491120eSAndrei Emeltchenko break; 4675491120eSAndrei Emeltchenko 4685491120eSAndrei Emeltchenko default: 4690a708f8fSGustavo F. Padovan /* Raw socket can send/recv signalling messages only */ 470fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_SIGNALING; 471fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_SIGNALING; 4720c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 4730a708f8fSGustavo F. Padovan } 4740a708f8fSGustavo F. Padovan 4758f7975b1SAndrei Emeltchenko chan->local_id = L2CAP_BESTEFFORT_ID; 4768f7975b1SAndrei Emeltchenko chan->local_stype = L2CAP_SERV_BESTEFFORT; 4778f7975b1SAndrei Emeltchenko chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE; 4788f7975b1SAndrei Emeltchenko chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME; 4798f7975b1SAndrei Emeltchenko chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT; 4808f7975b1SAndrei Emeltchenko chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO; 4818f7975b1SAndrei Emeltchenko 482371fd835SUlisses Furquim l2cap_chan_hold(chan); 483baa7e1faSGustavo F. Padovan 4843df91ea2SAndrei Emeltchenko list_add(&chan->list, &conn->chan_l); 485643162a8SAndrei Emeltchenko } 486643162a8SAndrei Emeltchenko 48714a28491SAndrei Emeltchenko static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 488643162a8SAndrei Emeltchenko { 489643162a8SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 490643162a8SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 4913df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4920a708f8fSGustavo F. Padovan } 4930a708f8fSGustavo F. Padovan 4944519de9aSGustavo F. Padovan static void l2cap_chan_del(struct l2cap_chan *chan, int err) 4950a708f8fSGustavo F. Padovan { 49648454079SGustavo F. Padovan struct sock *sk = chan->sk; 4978c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 4980a708f8fSGustavo F. Padovan struct sock *parent = bt_sk(sk)->parent; 4990a708f8fSGustavo F. Padovan 500c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 5010a708f8fSGustavo F. Padovan 50249208c9cSGustavo F. Padovan BT_DBG("chan %p, conn %p, err %d", chan, conn, err); 5030a708f8fSGustavo F. Padovan 5040a708f8fSGustavo F. Padovan if (conn) { 505baa7e1faSGustavo F. Padovan /* Delete from channel list */ 5063df91ea2SAndrei Emeltchenko list_del(&chan->list); 5073d57dc68SGustavo F. Padovan 508371fd835SUlisses Furquim l2cap_chan_put(chan); 509baa7e1faSGustavo F. Padovan 5108c1d787bSGustavo F. Padovan chan->conn = NULL; 5110a708f8fSGustavo F. Padovan hci_conn_put(conn->hcon); 5120a708f8fSGustavo F. Padovan } 5130a708f8fSGustavo F. Padovan 5146be36555SAndrei Emeltchenko lock_sock(sk); 5156be36555SAndrei Emeltchenko 5160e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CLOSED); 5170a708f8fSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 5180a708f8fSGustavo F. Padovan 5190a708f8fSGustavo F. Padovan if (err) 5202e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 5210a708f8fSGustavo F. Padovan 5220a708f8fSGustavo F. Padovan if (parent) { 5230a708f8fSGustavo F. Padovan bt_accept_unlink(sk); 5240a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 5250a708f8fSGustavo F. Padovan } else 5260a708f8fSGustavo F. Padovan sk->sk_state_change(sk); 5270a708f8fSGustavo F. Padovan 5286be36555SAndrei Emeltchenko release_sock(sk); 5296be36555SAndrei Emeltchenko 5302827011fSMat Martineau if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) 5316ff5abbfSGustavo F. Padovan return; 5322ead70b8SGustavo F. Padovan 533ee556f66SGustavo Padovan switch(chan->mode) { 534ee556f66SGustavo Padovan case L2CAP_MODE_BASIC: 535ee556f66SGustavo Padovan break; 5360a708f8fSGustavo F. Padovan 537ee556f66SGustavo Padovan case L2CAP_MODE_ERTM: 5381a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 5391a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 5401a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 5410a708f8fSGustavo F. Padovan 542f1c6775bSGustavo F. Padovan skb_queue_purge(&chan->srej_q); 5430a708f8fSGustavo F. Padovan 5443c588192SMat Martineau l2cap_seq_list_free(&chan->srej_list); 5453c588192SMat Martineau l2cap_seq_list_free(&chan->retrans_list); 546ee556f66SGustavo Padovan 547ee556f66SGustavo Padovan /* fall through */ 548ee556f66SGustavo Padovan 549ee556f66SGustavo Padovan case L2CAP_MODE_STREAMING: 550ee556f66SGustavo Padovan skb_queue_purge(&chan->tx_q); 551ee556f66SGustavo Padovan break; 5520a708f8fSGustavo F. Padovan } 553ee556f66SGustavo Padovan 554ee556f66SGustavo Padovan return; 5550a708f8fSGustavo F. Padovan } 5560a708f8fSGustavo F. Padovan 5574519de9aSGustavo F. Padovan static void l2cap_chan_cleanup_listen(struct sock *parent) 5584519de9aSGustavo F. Padovan { 5594519de9aSGustavo F. Padovan struct sock *sk; 5604519de9aSGustavo F. Padovan 5614519de9aSGustavo F. Padovan BT_DBG("parent %p", parent); 5624519de9aSGustavo F. Padovan 5634519de9aSGustavo F. Padovan /* Close not yet accepted channels */ 5640f852724SGustavo F. Padovan while ((sk = bt_accept_dequeue(parent, NULL))) { 565ba3bd0eeSGustavo F. Padovan struct l2cap_chan *chan = l2cap_pi(sk)->chan; 5663df91ea2SAndrei Emeltchenko 5676be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 568c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 569ba3bd0eeSGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 5706be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 5713df91ea2SAndrei Emeltchenko 572ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 5730f852724SGustavo F. Padovan } 5744519de9aSGustavo F. Padovan } 5754519de9aSGustavo F. Padovan 5760f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason) 5774519de9aSGustavo F. Padovan { 5784519de9aSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 5794519de9aSGustavo F. Padovan struct sock *sk = chan->sk; 5804519de9aSGustavo F. Padovan 581e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s sk %p", chan, 582e05dcc32SAndrei Emeltchenko state_to_string(chan->state), sk); 5834519de9aSGustavo F. Padovan 58489bc500eSGustavo F. Padovan switch (chan->state) { 5854519de9aSGustavo F. Padovan case BT_LISTEN: 5866be36555SAndrei Emeltchenko lock_sock(sk); 5874519de9aSGustavo F. Padovan l2cap_chan_cleanup_listen(sk); 58889bc500eSGustavo F. Padovan 5890e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CLOSED); 59089bc500eSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 5916be36555SAndrei Emeltchenko release_sock(sk); 5924519de9aSGustavo F. Padovan break; 5934519de9aSGustavo F. Padovan 5944519de9aSGustavo F. Padovan case BT_CONNECTED: 5954519de9aSGustavo F. Padovan case BT_CONFIG: 596715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && 5974519de9aSGustavo F. Padovan conn->hcon->type == ACL_LINK) { 598c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 5994519de9aSGustavo F. Padovan l2cap_send_disconn_req(conn, chan, reason); 6004519de9aSGustavo F. Padovan } else 6014519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 6024519de9aSGustavo F. Padovan break; 6034519de9aSGustavo F. Padovan 6044519de9aSGustavo F. Padovan case BT_CONNECT2: 605715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && 6064519de9aSGustavo F. Padovan conn->hcon->type == ACL_LINK) { 6074519de9aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 6084519de9aSGustavo F. Padovan __u16 result; 6094519de9aSGustavo F. Padovan 610c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) 6114519de9aSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 6124519de9aSGustavo F. Padovan else 6134519de9aSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 61489bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_DISCONN); 6154519de9aSGustavo F. Padovan 6164519de9aSGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 6174519de9aSGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 6184519de9aSGustavo F. Padovan rsp.result = cpu_to_le16(result); 6194519de9aSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 6204519de9aSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 6214519de9aSGustavo F. Padovan sizeof(rsp), &rsp); 6224519de9aSGustavo F. Padovan } 6234519de9aSGustavo F. Padovan 6244519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 6254519de9aSGustavo F. Padovan break; 6264519de9aSGustavo F. Padovan 6274519de9aSGustavo F. Padovan case BT_CONNECT: 6284519de9aSGustavo F. Padovan case BT_DISCONN: 6294519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 6304519de9aSGustavo F. Padovan break; 6314519de9aSGustavo F. Padovan 6324519de9aSGustavo F. Padovan default: 6336be36555SAndrei Emeltchenko lock_sock(sk); 6344519de9aSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 6356be36555SAndrei Emeltchenko release_sock(sk); 6364519de9aSGustavo F. Padovan break; 6374519de9aSGustavo F. Padovan } 6384519de9aSGustavo F. Padovan } 6394519de9aSGustavo F. Padovan 6404343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) 6410a708f8fSGustavo F. Padovan { 642715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_RAW) { 6434343478fSGustavo F. Padovan switch (chan->sec_level) { 6440a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 6450a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING_MITM; 6460a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 6470a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING; 6480a708f8fSGustavo F. Padovan default: 6490a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 6500a708f8fSGustavo F. Padovan } 651*2983fd68SAndrei Emeltchenko } else if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) { 6524343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_LOW) 6534343478fSGustavo F. Padovan chan->sec_level = BT_SECURITY_SDP; 6540a708f8fSGustavo F. Padovan 6554343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_HIGH) 6560a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING_MITM; 6570a708f8fSGustavo F. Padovan else 6580a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 6590a708f8fSGustavo F. Padovan } else { 6604343478fSGustavo F. Padovan switch (chan->sec_level) { 6610a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 6620a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING_MITM; 6630a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 6640a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING; 6650a708f8fSGustavo F. Padovan default: 6660a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 6670a708f8fSGustavo F. Padovan } 6680a708f8fSGustavo F. Padovan } 6690a708f8fSGustavo F. Padovan } 6700a708f8fSGustavo F. Padovan 6710a708f8fSGustavo F. Padovan /* Service level security */ 672d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan) 6730a708f8fSGustavo F. Padovan { 6748c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 6750a708f8fSGustavo F. Padovan __u8 auth_type; 6760a708f8fSGustavo F. Padovan 6774343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 6780a708f8fSGustavo F. Padovan 6794343478fSGustavo F. Padovan return hci_conn_security(conn->hcon, chan->sec_level, auth_type); 6800a708f8fSGustavo F. Padovan } 6810a708f8fSGustavo F. Padovan 682b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn) 6830a708f8fSGustavo F. Padovan { 6840a708f8fSGustavo F. Padovan u8 id; 6850a708f8fSGustavo F. Padovan 6860a708f8fSGustavo F. Padovan /* Get next available identificator. 6870a708f8fSGustavo F. Padovan * 1 - 128 are used by kernel. 6880a708f8fSGustavo F. Padovan * 129 - 199 are reserved. 6890a708f8fSGustavo F. Padovan * 200 - 254 are used by utilities like l2ping, etc. 6900a708f8fSGustavo F. Padovan */ 6910a708f8fSGustavo F. Padovan 692333055f2SGustavo F. Padovan spin_lock(&conn->lock); 6930a708f8fSGustavo F. Padovan 6940a708f8fSGustavo F. Padovan if (++conn->tx_ident > 128) 6950a708f8fSGustavo F. Padovan conn->tx_ident = 1; 6960a708f8fSGustavo F. Padovan 6970a708f8fSGustavo F. Padovan id = conn->tx_ident; 6980a708f8fSGustavo F. Padovan 699333055f2SGustavo F. Padovan spin_unlock(&conn->lock); 7000a708f8fSGustavo F. Padovan 7010a708f8fSGustavo F. Padovan return id; 7020a708f8fSGustavo F. Padovan } 7030a708f8fSGustavo F. Padovan 7044519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) 7050a708f8fSGustavo F. Padovan { 7060a708f8fSGustavo F. Padovan struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); 7070a708f8fSGustavo F. Padovan u8 flags; 7080a708f8fSGustavo F. Padovan 7090a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x", code); 7100a708f8fSGustavo F. Padovan 7110a708f8fSGustavo F. Padovan if (!skb) 7120a708f8fSGustavo F. Padovan return; 7130a708f8fSGustavo F. Padovan 7140a708f8fSGustavo F. Padovan if (lmp_no_flush_capable(conn->hcon->hdev)) 7150a708f8fSGustavo F. Padovan flags = ACL_START_NO_FLUSH; 7160a708f8fSGustavo F. Padovan else 7170a708f8fSGustavo F. Padovan flags = ACL_START; 7180a708f8fSGustavo F. Padovan 71914b12d0bSJaikumar Ganesh bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON; 7205e59b791SLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 72114b12d0bSJaikumar Ganesh 72273d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, flags); 7230a708f8fSGustavo F. Padovan } 7240a708f8fSGustavo F. Padovan 72573d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) 72673d80debSLuiz Augusto von Dentz { 72773d80debSLuiz Augusto von Dentz struct hci_conn *hcon = chan->conn->hcon; 72873d80debSLuiz Augusto von Dentz u16 flags; 72973d80debSLuiz Augusto von Dentz 73073d80debSLuiz Augusto von Dentz BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, 73173d80debSLuiz Augusto von Dentz skb->priority); 73273d80debSLuiz Augusto von Dentz 73373d80debSLuiz Augusto von Dentz if (!test_bit(FLAG_FLUSHABLE, &chan->flags) && 73473d80debSLuiz Augusto von Dentz lmp_no_flush_capable(hcon->hdev)) 73573d80debSLuiz Augusto von Dentz flags = ACL_START_NO_FLUSH; 73673d80debSLuiz Augusto von Dentz else 73773d80debSLuiz Augusto von Dentz flags = ACL_START; 73873d80debSLuiz Augusto von Dentz 73973d80debSLuiz Augusto von Dentz bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); 74073d80debSLuiz Augusto von Dentz hci_send_acl(chan->conn->hchan, skb, flags); 7410a708f8fSGustavo F. Padovan } 7420a708f8fSGustavo F. Padovan 743b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control) 744b5c6aaedSMat Martineau { 745b5c6aaedSMat Martineau control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT; 746b5c6aaedSMat Martineau control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT; 747b5c6aaedSMat Martineau 748b5c6aaedSMat Martineau if (enh & L2CAP_CTRL_FRAME_TYPE) { 749b5c6aaedSMat Martineau /* S-Frame */ 750b5c6aaedSMat Martineau control->sframe = 1; 751b5c6aaedSMat Martineau control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT; 752b5c6aaedSMat Martineau control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT; 753b5c6aaedSMat Martineau 754b5c6aaedSMat Martineau control->sar = 0; 755b5c6aaedSMat Martineau control->txseq = 0; 756b5c6aaedSMat Martineau } else { 757b5c6aaedSMat Martineau /* I-Frame */ 758b5c6aaedSMat Martineau control->sframe = 0; 759b5c6aaedSMat Martineau control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT; 760b5c6aaedSMat Martineau control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT; 761b5c6aaedSMat Martineau 762b5c6aaedSMat Martineau control->poll = 0; 763b5c6aaedSMat Martineau control->super = 0; 764b5c6aaedSMat Martineau } 765b5c6aaedSMat Martineau } 766b5c6aaedSMat Martineau 767b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control) 768b5c6aaedSMat Martineau { 769b5c6aaedSMat Martineau control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT; 770b5c6aaedSMat Martineau control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT; 771b5c6aaedSMat Martineau 772b5c6aaedSMat Martineau if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) { 773b5c6aaedSMat Martineau /* S-Frame */ 774b5c6aaedSMat Martineau control->sframe = 1; 775b5c6aaedSMat Martineau control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT; 776b5c6aaedSMat Martineau control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT; 777b5c6aaedSMat Martineau 778b5c6aaedSMat Martineau control->sar = 0; 779b5c6aaedSMat Martineau control->txseq = 0; 780b5c6aaedSMat Martineau } else { 781b5c6aaedSMat Martineau /* I-Frame */ 782b5c6aaedSMat Martineau control->sframe = 0; 783b5c6aaedSMat Martineau control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT; 784b5c6aaedSMat Martineau control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT; 785b5c6aaedSMat Martineau 786b5c6aaedSMat Martineau control->poll = 0; 787b5c6aaedSMat Martineau control->super = 0; 788b5c6aaedSMat Martineau } 789b5c6aaedSMat Martineau } 790b5c6aaedSMat Martineau 791b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan, 792b5c6aaedSMat Martineau struct sk_buff *skb) 793b5c6aaedSMat Martineau { 794b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 795b5c6aaedSMat Martineau __unpack_extended_control(get_unaligned_le32(skb->data), 796b5c6aaedSMat Martineau &bt_cb(skb)->control); 797cec8ab6eSMat Martineau skb_pull(skb, L2CAP_EXT_CTRL_SIZE); 798b5c6aaedSMat Martineau } else { 799b5c6aaedSMat Martineau __unpack_enhanced_control(get_unaligned_le16(skb->data), 800b5c6aaedSMat Martineau &bt_cb(skb)->control); 801cec8ab6eSMat Martineau skb_pull(skb, L2CAP_ENH_CTRL_SIZE); 802b5c6aaedSMat Martineau } 803b5c6aaedSMat Martineau } 804b5c6aaedSMat Martineau 805b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control) 806b5c6aaedSMat Martineau { 807b5c6aaedSMat Martineau u32 packed; 808b5c6aaedSMat Martineau 809b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT; 810b5c6aaedSMat Martineau packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT; 811b5c6aaedSMat Martineau 812b5c6aaedSMat Martineau if (control->sframe) { 813b5c6aaedSMat Martineau packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT; 814b5c6aaedSMat Martineau packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT; 815b5c6aaedSMat Martineau packed |= L2CAP_EXT_CTRL_FRAME_TYPE; 816b5c6aaedSMat Martineau } else { 817b5c6aaedSMat Martineau packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT; 818b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT; 819b5c6aaedSMat Martineau } 820b5c6aaedSMat Martineau 821b5c6aaedSMat Martineau return packed; 822b5c6aaedSMat Martineau } 823b5c6aaedSMat Martineau 824b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control) 825b5c6aaedSMat Martineau { 826b5c6aaedSMat Martineau u16 packed; 827b5c6aaedSMat Martineau 828b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT; 829b5c6aaedSMat Martineau packed |= control->final << L2CAP_CTRL_FINAL_SHIFT; 830b5c6aaedSMat Martineau 831b5c6aaedSMat Martineau if (control->sframe) { 832b5c6aaedSMat Martineau packed |= control->poll << L2CAP_CTRL_POLL_SHIFT; 833b5c6aaedSMat Martineau packed |= control->super << L2CAP_CTRL_SUPER_SHIFT; 834b5c6aaedSMat Martineau packed |= L2CAP_CTRL_FRAME_TYPE; 835b5c6aaedSMat Martineau } else { 836b5c6aaedSMat Martineau packed |= control->sar << L2CAP_CTRL_SAR_SHIFT; 837b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT; 838b5c6aaedSMat Martineau } 839b5c6aaedSMat Martineau 840b5c6aaedSMat Martineau return packed; 841b5c6aaedSMat Martineau } 842b5c6aaedSMat Martineau 843b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan, 844b5c6aaedSMat Martineau struct l2cap_ctrl *control, 845b5c6aaedSMat Martineau struct sk_buff *skb) 846b5c6aaedSMat Martineau { 847b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 848b5c6aaedSMat Martineau put_unaligned_le32(__pack_extended_control(control), 849b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 850b5c6aaedSMat Martineau } else { 851b5c6aaedSMat Martineau put_unaligned_le16(__pack_enhanced_control(control), 852b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 853b5c6aaedSMat Martineau } 854b5c6aaedSMat Martineau } 855b5c6aaedSMat Martineau 856a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan, 857a67d7f6fSMat Martineau u32 control) 8580a708f8fSGustavo F. Padovan { 8590a708f8fSGustavo F. Padovan struct sk_buff *skb; 8600a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 861a67d7f6fSMat Martineau int hlen; 8620a708f8fSGustavo F. Padovan 863e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 864e4ca6d98SAndrei Emeltchenko hlen = L2CAP_EXT_HDR_SIZE; 865e4ca6d98SAndrei Emeltchenko else 866e4ca6d98SAndrei Emeltchenko hlen = L2CAP_ENH_HDR_SIZE; 8670a708f8fSGustavo F. Padovan 8680a708f8fSGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 86903a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 8700a708f8fSGustavo F. Padovan 871a67d7f6fSMat Martineau skb = bt_skb_alloc(hlen, GFP_KERNEL); 8720a708f8fSGustavo F. Padovan 8730a708f8fSGustavo F. Padovan if (!skb) 874a67d7f6fSMat Martineau return ERR_PTR(-ENOMEM); 8750a708f8fSGustavo F. Padovan 8760a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 8770a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); 878fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 87988843ab0SAndrei Emeltchenko 880a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 881a67d7f6fSMat Martineau put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 882a67d7f6fSMat Martineau else 883a67d7f6fSMat Martineau put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 8840a708f8fSGustavo F. Padovan 88547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 886a67d7f6fSMat Martineau u16 fcs = crc16(0, (u8 *)skb->data, skb->len); 88703a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 8880a708f8fSGustavo F. Padovan } 8890a708f8fSGustavo F. Padovan 89073d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 891a67d7f6fSMat Martineau return skb; 892a67d7f6fSMat Martineau } 893a67d7f6fSMat Martineau 894a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan, 895a67d7f6fSMat Martineau struct l2cap_ctrl *control) 896a67d7f6fSMat Martineau { 897a67d7f6fSMat Martineau struct sk_buff *skb; 898a67d7f6fSMat Martineau u32 control_field; 899a67d7f6fSMat Martineau 900a67d7f6fSMat Martineau BT_DBG("chan %p, control %p", chan, control); 901a67d7f6fSMat Martineau 902a67d7f6fSMat Martineau if (!control->sframe) 903a67d7f6fSMat Martineau return; 904a67d7f6fSMat Martineau 905a67d7f6fSMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) && 906a67d7f6fSMat Martineau !control->poll) 907a67d7f6fSMat Martineau control->final = 1; 908a67d7f6fSMat Martineau 909a67d7f6fSMat Martineau if (control->super == L2CAP_SUPER_RR) 910a67d7f6fSMat Martineau clear_bit(CONN_RNR_SENT, &chan->conn_state); 911a67d7f6fSMat Martineau else if (control->super == L2CAP_SUPER_RNR) 912a67d7f6fSMat Martineau set_bit(CONN_RNR_SENT, &chan->conn_state); 913a67d7f6fSMat Martineau 914a67d7f6fSMat Martineau if (control->super != L2CAP_SUPER_SREJ) { 915a67d7f6fSMat Martineau chan->last_acked_seq = control->reqseq; 916a67d7f6fSMat Martineau __clear_ack_timer(chan); 917a67d7f6fSMat Martineau } 918a67d7f6fSMat Martineau 919a67d7f6fSMat Martineau BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq, 920a67d7f6fSMat Martineau control->final, control->poll, control->super); 921a67d7f6fSMat Martineau 922a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 923a67d7f6fSMat Martineau control_field = __pack_extended_control(control); 924a67d7f6fSMat Martineau else 925a67d7f6fSMat Martineau control_field = __pack_enhanced_control(control); 926a67d7f6fSMat Martineau 927a67d7f6fSMat Martineau skb = l2cap_create_sframe_pdu(chan, control_field); 928a67d7f6fSMat Martineau if (!IS_ERR(skb)) 92973d80debSLuiz Augusto von Dentz l2cap_do_send(chan, skb); 9300a708f8fSGustavo F. Padovan } 9310a708f8fSGustavo F. Padovan 932c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll) 9330a708f8fSGustavo F. Padovan { 934c9e3d5e0SMat Martineau struct l2cap_ctrl control; 9350a708f8fSGustavo F. Padovan 936c9e3d5e0SMat Martineau BT_DBG("chan %p, poll %d", chan, poll); 937c9e3d5e0SMat Martineau 938c9e3d5e0SMat Martineau memset(&control, 0, sizeof(control)); 939c9e3d5e0SMat Martineau control.sframe = 1; 940c9e3d5e0SMat Martineau control.poll = poll; 941c9e3d5e0SMat Martineau 942c9e3d5e0SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 943c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RNR; 944c9e3d5e0SMat Martineau else 945c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RR; 946c9e3d5e0SMat Martineau 947c9e3d5e0SMat Martineau control.reqseq = chan->buffer_seq; 948c9e3d5e0SMat Martineau l2cap_send_sframe(chan, &control); 9490a708f8fSGustavo F. Padovan } 9500a708f8fSGustavo F. Padovan 951b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) 9520a708f8fSGustavo F. Padovan { 953c1360a1cSGustavo F. Padovan return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); 9540a708f8fSGustavo F. Padovan } 9550a708f8fSGustavo F. Padovan 9569b27f350SAndrei Emeltchenko static void l2cap_send_conn_req(struct l2cap_chan *chan) 9579b27f350SAndrei Emeltchenko { 9589b27f350SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 9599b27f350SAndrei Emeltchenko struct l2cap_conn_req req; 9609b27f350SAndrei Emeltchenko 9619b27f350SAndrei Emeltchenko req.scid = cpu_to_le16(chan->scid); 9629b27f350SAndrei Emeltchenko req.psm = chan->psm; 9639b27f350SAndrei Emeltchenko 9649b27f350SAndrei Emeltchenko chan->ident = l2cap_get_ident(conn); 9659b27f350SAndrei Emeltchenko 9669b27f350SAndrei Emeltchenko set_bit(CONF_CONNECT_PEND, &chan->conf_state); 9679b27f350SAndrei Emeltchenko 9689b27f350SAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); 9699b27f350SAndrei Emeltchenko } 9709b27f350SAndrei Emeltchenko 9719f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan) 9729f0caeb1SVinicius Costa Gomes { 9739f0caeb1SVinicius Costa Gomes struct sock *sk = chan->sk; 9749f0caeb1SVinicius Costa Gomes struct sock *parent; 9759f0caeb1SVinicius Costa Gomes 9769f0caeb1SVinicius Costa Gomes lock_sock(sk); 9779f0caeb1SVinicius Costa Gomes 9789f0caeb1SVinicius Costa Gomes parent = bt_sk(sk)->parent; 9799f0caeb1SVinicius Costa Gomes 9809f0caeb1SVinicius Costa Gomes BT_DBG("sk %p, parent %p", sk, parent); 9819f0caeb1SVinicius Costa Gomes 9822827011fSMat Martineau /* This clears all conf flags, including CONF_NOT_COMPLETE */ 9839f0caeb1SVinicius Costa Gomes chan->conf_state = 0; 9849f0caeb1SVinicius Costa Gomes __clear_chan_timer(chan); 9859f0caeb1SVinicius Costa Gomes 9869f0caeb1SVinicius Costa Gomes __l2cap_state_change(chan, BT_CONNECTED); 9879f0caeb1SVinicius Costa Gomes sk->sk_state_change(sk); 9889f0caeb1SVinicius Costa Gomes 9899f0caeb1SVinicius Costa Gomes if (parent) 9909f0caeb1SVinicius Costa Gomes parent->sk_data_ready(parent, 0); 9919f0caeb1SVinicius Costa Gomes 9929f0caeb1SVinicius Costa Gomes release_sock(sk); 9939f0caeb1SVinicius Costa Gomes } 9949f0caeb1SVinicius Costa Gomes 995fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan) 9960a708f8fSGustavo F. Padovan { 9978c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 9980a708f8fSGustavo F. Padovan 9999f0caeb1SVinicius Costa Gomes if (conn->hcon->type == LE_LINK) { 10009f0caeb1SVinicius Costa Gomes l2cap_chan_ready(chan); 10019f0caeb1SVinicius Costa Gomes return; 10029f0caeb1SVinicius Costa Gomes } 10039f0caeb1SVinicius Costa Gomes 10040a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { 10050a708f8fSGustavo F. Padovan if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) 10060a708f8fSGustavo F. Padovan return; 10070a708f8fSGustavo F. Padovan 1008d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan) && 10099b27f350SAndrei Emeltchenko __l2cap_no_conn_pending(chan)) 10109b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 10110a708f8fSGustavo F. Padovan } else { 10120a708f8fSGustavo F. Padovan struct l2cap_info_req req; 10130a708f8fSGustavo F. Padovan req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 10140a708f8fSGustavo F. Padovan 10150a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 10160a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 10170a708f8fSGustavo F. Padovan 1018ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 10190a708f8fSGustavo F. Padovan 10200a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 10210a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 10220a708f8fSGustavo F. Padovan } 10230a708f8fSGustavo F. Padovan } 10240a708f8fSGustavo F. Padovan 10250a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) 10260a708f8fSGustavo F. Padovan { 10270a708f8fSGustavo F. Padovan u32 local_feat_mask = l2cap_feat_mask; 10280a708f8fSGustavo F. Padovan if (!disable_ertm) 10290a708f8fSGustavo F. Padovan local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING; 10300a708f8fSGustavo F. Padovan 10310a708f8fSGustavo F. Padovan switch (mode) { 10320a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 10330a708f8fSGustavo F. Padovan return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask; 10340a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 10350a708f8fSGustavo F. Padovan return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask; 10360a708f8fSGustavo F. Padovan default: 10370a708f8fSGustavo F. Padovan return 0x00; 10380a708f8fSGustavo F. Padovan } 10390a708f8fSGustavo F. Padovan } 10400a708f8fSGustavo F. Padovan 10414519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err) 10420a708f8fSGustavo F. Padovan { 10436be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 10440a708f8fSGustavo F. Padovan struct l2cap_disconn_req req; 10450a708f8fSGustavo F. Padovan 10460a708f8fSGustavo F. Padovan if (!conn) 10470a708f8fSGustavo F. Padovan return; 10480a708f8fSGustavo F. Padovan 10490c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_ERTM) { 10501a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 10511a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 10521a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 10530a708f8fSGustavo F. Padovan } 10540a708f8fSGustavo F. Padovan 1055fe4128e0SGustavo F. Padovan req.dcid = cpu_to_le16(chan->dcid); 1056fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 10570a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 10580a708f8fSGustavo F. Padovan L2CAP_DISCONN_REQ, sizeof(req), &req); 10590a708f8fSGustavo F. Padovan 10606be36555SAndrei Emeltchenko lock_sock(sk); 10610e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_DISCONN); 10622e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 10636be36555SAndrei Emeltchenko release_sock(sk); 10640a708f8fSGustavo F. Padovan } 10650a708f8fSGustavo F. Padovan 10660a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */ 10670a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn) 10680a708f8fSGustavo F. Padovan { 10693df91ea2SAndrei Emeltchenko struct l2cap_chan *chan, *tmp; 10700a708f8fSGustavo F. Padovan 10710a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 10720a708f8fSGustavo F. Padovan 10733df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 10740a708f8fSGustavo F. Padovan 10753df91ea2SAndrei Emeltchenko list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 107648454079SGustavo F. Padovan struct sock *sk = chan->sk; 1077baa7e1faSGustavo F. Padovan 10786be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 10790a708f8fSGustavo F. Padovan 1080715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 10816be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10820a708f8fSGustavo F. Padovan continue; 10830a708f8fSGustavo F. Padovan } 10840a708f8fSGustavo F. Padovan 108589bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 1086d45fc423SGustavo F. Padovan if (!l2cap_chan_check_security(chan) || 1087b4450035SGustavo F. Padovan !__l2cap_no_conn_pending(chan)) { 10886be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10890a708f8fSGustavo F. Padovan continue; 10900a708f8fSGustavo F. Padovan } 10910a708f8fSGustavo F. Padovan 1092c1360a1cSGustavo F. Padovan if (!l2cap_mode_supported(chan->mode, conn->feat_mask) 1093c1360a1cSGustavo F. Padovan && test_bit(CONF_STATE2_DEVICE, 1094c1360a1cSGustavo F. Padovan &chan->conf_state)) { 10950f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 10966be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10970a708f8fSGustavo F. Padovan continue; 10980a708f8fSGustavo F. Padovan } 10990a708f8fSGustavo F. Padovan 11009b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 11010a708f8fSGustavo F. Padovan 110289bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 11030a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 11040a708f8fSGustavo F. Padovan char buf[128]; 1105fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 1106fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 11070a708f8fSGustavo F. Padovan 1108d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 11096be36555SAndrei Emeltchenko lock_sock(sk); 1110c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, 1111c5daa683SGustavo Padovan &bt_sk(sk)->flags)) { 11120a708f8fSGustavo F. Padovan struct sock *parent = bt_sk(sk)->parent; 11130a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_PEND); 11140a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND); 111505e9a2f6SIlia Kolomisnky if (parent) 11160a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 11170a708f8fSGustavo F. Padovan 11180a708f8fSGustavo F. Padovan } else { 11190e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 11200a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 11210a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 11220a708f8fSGustavo F. Padovan } 11236be36555SAndrei Emeltchenko release_sock(sk); 11240a708f8fSGustavo F. Padovan } else { 11250a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_PEND); 11260a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND); 11270a708f8fSGustavo F. Padovan } 11280a708f8fSGustavo F. Padovan 1129fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 1130fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 11310a708f8fSGustavo F. Padovan 1132c1360a1cSGustavo F. Padovan if (test_bit(CONF_REQ_SENT, &chan->conf_state) || 11330a708f8fSGustavo F. Padovan rsp.result != L2CAP_CR_SUCCESS) { 11346be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 11350a708f8fSGustavo F. Padovan continue; 11360a708f8fSGustavo F. Padovan } 11370a708f8fSGustavo F. Padovan 1138c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 11390a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 114073ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 114173ffa904SGustavo F. Padovan chan->num_conf_req++; 11420a708f8fSGustavo F. Padovan } 11430a708f8fSGustavo F. Padovan 11446be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 11450a708f8fSGustavo F. Padovan } 11460a708f8fSGustavo F. Padovan 11473df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 11480a708f8fSGustavo F. Padovan } 11490a708f8fSGustavo F. Padovan 1150c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr. 1151b62f328bSVille Tervo * Returns closest match, locked. 1152b62f328bSVille Tervo */ 1153d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, 1154c2287681SIdo Yariv bdaddr_t *src, 1155c2287681SIdo Yariv bdaddr_t *dst) 1156b62f328bSVille Tervo { 115723691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 1158b62f328bSVille Tervo 115923691d75SGustavo F. Padovan read_lock(&chan_list_lock); 1160b62f328bSVille Tervo 116123691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 116223691d75SGustavo F. Padovan struct sock *sk = c->sk; 1163fe4128e0SGustavo F. Padovan 116489bc500eSGustavo F. Padovan if (state && c->state != state) 1165b62f328bSVille Tervo continue; 1166b62f328bSVille Tervo 116723691d75SGustavo F. Padovan if (c->scid == cid) { 1168c2287681SIdo Yariv int src_match, dst_match; 1169c2287681SIdo Yariv int src_any, dst_any; 1170c2287681SIdo Yariv 1171b62f328bSVille Tervo /* Exact match. */ 1172c2287681SIdo Yariv src_match = !bacmp(&bt_sk(sk)->src, src); 1173c2287681SIdo Yariv dst_match = !bacmp(&bt_sk(sk)->dst, dst); 1174c2287681SIdo Yariv if (src_match && dst_match) { 117523691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 117623691d75SGustavo F. Padovan return c; 117723691d75SGustavo F. Padovan } 1178b62f328bSVille Tervo 1179b62f328bSVille Tervo /* Closest match */ 1180c2287681SIdo Yariv src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY); 1181c2287681SIdo Yariv dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY); 1182c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1183c2287681SIdo Yariv (src_any && dst_any)) 118423691d75SGustavo F. Padovan c1 = c; 1185b62f328bSVille Tervo } 1186b62f328bSVille Tervo } 1187280f294fSGustavo F. Padovan 118823691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 1189b62f328bSVille Tervo 119023691d75SGustavo F. Padovan return c1; 1191b62f328bSVille Tervo } 1192b62f328bSVille Tervo 1193b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn) 1194b62f328bSVille Tervo { 1195c916fbe4SGustavo F. Padovan struct sock *parent, *sk; 119623691d75SGustavo F. Padovan struct l2cap_chan *chan, *pchan; 1197b62f328bSVille Tervo 1198b62f328bSVille Tervo BT_DBG(""); 1199b62f328bSVille Tervo 1200b62f328bSVille Tervo /* Check if we have socket listening on cid */ 120123691d75SGustavo F. Padovan pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA, 1202c2287681SIdo Yariv conn->src, conn->dst); 120323691d75SGustavo F. Padovan if (!pchan) 1204b62f328bSVille Tervo return; 1205b62f328bSVille Tervo 120623691d75SGustavo F. Padovan parent = pchan->sk; 120723691d75SGustavo F. Padovan 1208aa2ac881SGustavo F. Padovan lock_sock(parent); 120962f3a2cfSGustavo F. Padovan 1210b62f328bSVille Tervo /* Check for backlog size */ 1211b62f328bSVille Tervo if (sk_acceptq_is_full(parent)) { 1212b62f328bSVille Tervo BT_DBG("backlog full %d", parent->sk_ack_backlog); 1213b62f328bSVille Tervo goto clean; 1214b62f328bSVille Tervo } 1215b62f328bSVille Tervo 121680808e43SGustavo F. Padovan chan = pchan->ops->new_connection(pchan->data); 121780808e43SGustavo F. Padovan if (!chan) 1218b62f328bSVille Tervo goto clean; 1219b62f328bSVille Tervo 122080808e43SGustavo F. Padovan sk = chan->sk; 12215d41ce1dSGustavo F. Padovan 1222b62f328bSVille Tervo hci_conn_hold(conn->hcon); 1223b62f328bSVille Tervo 1224b62f328bSVille Tervo bacpy(&bt_sk(sk)->src, conn->src); 1225b62f328bSVille Tervo bacpy(&bt_sk(sk)->dst, conn->dst); 1226b62f328bSVille Tervo 1227d1010240SGustavo F. Padovan bt_accept_enqueue(parent, sk); 1228d1010240SGustavo F. Padovan 12293d57dc68SGustavo F. Padovan l2cap_chan_add(conn, chan); 123048454079SGustavo F. Padovan 1231c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 1232b62f328bSVille Tervo 12330e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECTED); 1234b62f328bSVille Tervo parent->sk_data_ready(parent, 0); 1235b62f328bSVille Tervo 1236b62f328bSVille Tervo clean: 1237aa2ac881SGustavo F. Padovan release_sock(parent); 1238b62f328bSVille Tervo } 1239b62f328bSVille Tervo 12400a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn) 12410a708f8fSGustavo F. Padovan { 124248454079SGustavo F. Padovan struct l2cap_chan *chan; 12430a708f8fSGustavo F. Padovan 12440a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 12450a708f8fSGustavo F. Padovan 1246b62f328bSVille Tervo if (!conn->hcon->out && conn->hcon->type == LE_LINK) 1247b62f328bSVille Tervo l2cap_le_conn_ready(conn); 1248b62f328bSVille Tervo 1249160dc6acSVinicius Costa Gomes if (conn->hcon->out && conn->hcon->type == LE_LINK) 1250160dc6acSVinicius Costa Gomes smp_conn_security(conn, conn->hcon->pending_sec_level); 1251160dc6acSVinicius Costa Gomes 12523df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 12530a708f8fSGustavo F. Padovan 12543df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1255baa7e1faSGustavo F. Padovan 12566be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 12570a708f8fSGustavo F. Padovan 125863128451SVinicius Costa Gomes if (conn->hcon->type == LE_LINK) { 1259b501d6a1SAnderson Briglia if (smp_conn_security(conn, chan->sec_level)) 1260cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 1261acd7d370SVille Tervo 126263128451SVinicius Costa Gomes } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 12636be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 1264c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 12656be36555SAndrei Emeltchenko lock_sock(sk); 12660e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECTED); 12670a708f8fSGustavo F. Padovan sk->sk_state_change(sk); 12686be36555SAndrei Emeltchenko release_sock(sk); 1269b501d6a1SAnderson Briglia 127089bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT) 1271fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 12720a708f8fSGustavo F. Padovan 12736be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 12740a708f8fSGustavo F. Padovan } 12750a708f8fSGustavo F. Padovan 12763df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 12770a708f8fSGustavo F. Padovan } 12780a708f8fSGustavo F. Padovan 12790a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */ 12800a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) 12810a708f8fSGustavo F. Padovan { 128248454079SGustavo F. Padovan struct l2cap_chan *chan; 12830a708f8fSGustavo F. Padovan 12840a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 12850a708f8fSGustavo F. Padovan 12863df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 12870a708f8fSGustavo F. Padovan 12883df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1289ecf61bdbSAndrei Emeltchenko if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) 12902e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 12910a708f8fSGustavo F. Padovan } 12920a708f8fSGustavo F. Padovan 12933df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 12940a708f8fSGustavo F. Padovan } 12950a708f8fSGustavo F. Padovan 1296f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work) 12970a708f8fSGustavo F. Padovan { 1298f878fcadSGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 1299030013d8SGustavo F. Padovan info_timer.work); 13000a708f8fSGustavo F. Padovan 13010a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 13020a708f8fSGustavo F. Padovan conn->info_ident = 0; 13030a708f8fSGustavo F. Padovan 13040a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 13050a708f8fSGustavo F. Padovan } 13060a708f8fSGustavo F. Padovan 13075d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err) 13085d3de7dfSVinicius Costa Gomes { 13095d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 13105d3de7dfSVinicius Costa Gomes struct l2cap_chan *chan, *l; 13115d3de7dfSVinicius Costa Gomes 13125d3de7dfSVinicius Costa Gomes if (!conn) 13135d3de7dfSVinicius Costa Gomes return; 13145d3de7dfSVinicius Costa Gomes 13155d3de7dfSVinicius Costa Gomes BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); 13165d3de7dfSVinicius Costa Gomes 13175d3de7dfSVinicius Costa Gomes kfree_skb(conn->rx_skb); 13185d3de7dfSVinicius Costa Gomes 13193df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 13203df91ea2SAndrei Emeltchenko 13215d3de7dfSVinicius Costa Gomes /* Kill channels */ 13225d3de7dfSVinicius Costa Gomes list_for_each_entry_safe(chan, l, &conn->chan_l, list) { 132361d6ef3eSMat Martineau l2cap_chan_hold(chan); 13246be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 13256be36555SAndrei Emeltchenko 13265d3de7dfSVinicius Costa Gomes l2cap_chan_del(chan, err); 13276be36555SAndrei Emeltchenko 13286be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13296be36555SAndrei Emeltchenko 13305d3de7dfSVinicius Costa Gomes chan->ops->close(chan->data); 133161d6ef3eSMat Martineau l2cap_chan_put(chan); 13325d3de7dfSVinicius Costa Gomes } 13335d3de7dfSVinicius Costa Gomes 13343df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 13353df91ea2SAndrei Emeltchenko 133673d80debSLuiz Augusto von Dentz hci_chan_del(conn->hchan); 133773d80debSLuiz Augusto von Dentz 13385d3de7dfSVinicius Costa Gomes if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1339127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->info_timer); 13405d3de7dfSVinicius Costa Gomes 134151a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) { 1342127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->security_timer); 13438aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 1344d26a2345SVinicius Costa Gomes } 13455d3de7dfSVinicius Costa Gomes 13465d3de7dfSVinicius Costa Gomes hcon->l2cap_data = NULL; 13475d3de7dfSVinicius Costa Gomes kfree(conn); 13485d3de7dfSVinicius Costa Gomes } 13495d3de7dfSVinicius Costa Gomes 13506c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work) 13515d3de7dfSVinicius Costa Gomes { 13526c9d42a1SGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 13536c9d42a1SGustavo F. Padovan security_timer.work); 13545d3de7dfSVinicius Costa Gomes 13555d3de7dfSVinicius Costa Gomes l2cap_conn_del(conn->hcon, ETIMEDOUT); 13565d3de7dfSVinicius Costa Gomes } 13575d3de7dfSVinicius Costa Gomes 13580a708f8fSGustavo F. Padovan static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) 13590a708f8fSGustavo F. Padovan { 13600a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 136173d80debSLuiz Augusto von Dentz struct hci_chan *hchan; 13620a708f8fSGustavo F. Padovan 13630a708f8fSGustavo F. Padovan if (conn || status) 13640a708f8fSGustavo F. Padovan return conn; 13650a708f8fSGustavo F. Padovan 136673d80debSLuiz Augusto von Dentz hchan = hci_chan_create(hcon); 136773d80debSLuiz Augusto von Dentz if (!hchan) 13680a708f8fSGustavo F. Padovan return NULL; 13690a708f8fSGustavo F. Padovan 137073d80debSLuiz Augusto von Dentz conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC); 137173d80debSLuiz Augusto von Dentz if (!conn) { 137273d80debSLuiz Augusto von Dentz hci_chan_del(hchan); 137373d80debSLuiz Augusto von Dentz return NULL; 137473d80debSLuiz Augusto von Dentz } 137573d80debSLuiz Augusto von Dentz 13760a708f8fSGustavo F. Padovan hcon->l2cap_data = conn; 13770a708f8fSGustavo F. Padovan conn->hcon = hcon; 137873d80debSLuiz Augusto von Dentz conn->hchan = hchan; 13790a708f8fSGustavo F. Padovan 138073d80debSLuiz Augusto von Dentz BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); 13810a708f8fSGustavo F. Padovan 1382acd7d370SVille Tervo if (hcon->hdev->le_mtu && hcon->type == LE_LINK) 1383acd7d370SVille Tervo conn->mtu = hcon->hdev->le_mtu; 1384acd7d370SVille Tervo else 13850a708f8fSGustavo F. Padovan conn->mtu = hcon->hdev->acl_mtu; 1386acd7d370SVille Tervo 13870a708f8fSGustavo F. Padovan conn->src = &hcon->hdev->bdaddr; 13880a708f8fSGustavo F. Padovan conn->dst = &hcon->dst; 13890a708f8fSGustavo F. Padovan 13900a708f8fSGustavo F. Padovan conn->feat_mask = 0; 13910a708f8fSGustavo F. Padovan 13920a708f8fSGustavo F. Padovan spin_lock_init(&conn->lock); 13933df91ea2SAndrei Emeltchenko mutex_init(&conn->chan_lock); 1394baa7e1faSGustavo F. Padovan 1395baa7e1faSGustavo F. Padovan INIT_LIST_HEAD(&conn->chan_l); 13960a708f8fSGustavo F. Padovan 13975d3de7dfSVinicius Costa Gomes if (hcon->type == LE_LINK) 13986c9d42a1SGustavo F. Padovan INIT_DELAYED_WORK(&conn->security_timer, security_timeout); 13995d3de7dfSVinicius Costa Gomes else 1400030013d8SGustavo F. Padovan INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); 14010a708f8fSGustavo F. Padovan 14029f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 14030a708f8fSGustavo F. Padovan 14040a708f8fSGustavo F. Padovan return conn; 14050a708f8fSGustavo F. Padovan } 14060a708f8fSGustavo F. Padovan 14070a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */ 14080a708f8fSGustavo F. Padovan 1409c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr. 14100a708f8fSGustavo F. Padovan * Returns closest match. 14110a708f8fSGustavo F. Padovan */ 1412c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, 1413c2287681SIdo Yariv bdaddr_t *src, 1414c2287681SIdo Yariv bdaddr_t *dst) 14150a708f8fSGustavo F. Padovan { 141623691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 14170a708f8fSGustavo F. Padovan 141823691d75SGustavo F. Padovan read_lock(&chan_list_lock); 14190a708f8fSGustavo F. Padovan 142023691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 142123691d75SGustavo F. Padovan struct sock *sk = c->sk; 1422fe4128e0SGustavo F. Padovan 142389bc500eSGustavo F. Padovan if (state && c->state != state) 14240a708f8fSGustavo F. Padovan continue; 14250a708f8fSGustavo F. Padovan 142623691d75SGustavo F. Padovan if (c->psm == psm) { 1427c2287681SIdo Yariv int src_match, dst_match; 1428c2287681SIdo Yariv int src_any, dst_any; 1429c2287681SIdo Yariv 14300a708f8fSGustavo F. Padovan /* Exact match. */ 1431c2287681SIdo Yariv src_match = !bacmp(&bt_sk(sk)->src, src); 1432c2287681SIdo Yariv dst_match = !bacmp(&bt_sk(sk)->dst, dst); 1433c2287681SIdo Yariv if (src_match && dst_match) { 1434a7567b20SJohannes Berg read_unlock(&chan_list_lock); 143523691d75SGustavo F. Padovan return c; 143623691d75SGustavo F. Padovan } 14370a708f8fSGustavo F. Padovan 14380a708f8fSGustavo F. Padovan /* Closest match */ 1439c2287681SIdo Yariv src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY); 1440c2287681SIdo Yariv dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY); 1441c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1442c2287681SIdo Yariv (src_any && dst_any)) 144323691d75SGustavo F. Padovan c1 = c; 14440a708f8fSGustavo F. Padovan } 14450a708f8fSGustavo F. Padovan } 14460a708f8fSGustavo F. Padovan 144723691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 14480a708f8fSGustavo F. Padovan 144923691d75SGustavo F. Padovan return c1; 14500a708f8fSGustavo F. Padovan } 14510a708f8fSGustavo F. Padovan 14528e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, 14538e9f9892SAndre Guedes bdaddr_t *dst, u8 dst_type) 14540a708f8fSGustavo F. Padovan { 14555d41ce1dSGustavo F. Padovan struct sock *sk = chan->sk; 14560a708f8fSGustavo F. Padovan bdaddr_t *src = &bt_sk(sk)->src; 14570a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 14580a708f8fSGustavo F. Padovan struct hci_conn *hcon; 14590a708f8fSGustavo F. Padovan struct hci_dev *hdev; 14600a708f8fSGustavo F. Padovan __u8 auth_type; 14610a708f8fSGustavo F. Padovan int err; 14620a708f8fSGustavo F. Padovan 14638e9f9892SAndre Guedes BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst), 14648e9f9892SAndre Guedes dst_type, __le16_to_cpu(chan->psm)); 14650a708f8fSGustavo F. Padovan 14660a708f8fSGustavo F. Padovan hdev = hci_get_route(dst, src); 14670a708f8fSGustavo F. Padovan if (!hdev) 14680a708f8fSGustavo F. Padovan return -EHOSTUNREACH; 14690a708f8fSGustavo F. Padovan 147009fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 14710a708f8fSGustavo F. Padovan 14726be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 147303a00194SGustavo F. Padovan 147403a00194SGustavo F. Padovan /* PSM must be odd and lsb of upper byte must be 0 */ 147503a00194SGustavo F. Padovan if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid && 147603a00194SGustavo F. Padovan chan->chan_type != L2CAP_CHAN_RAW) { 147703a00194SGustavo F. Padovan err = -EINVAL; 147803a00194SGustavo F. Padovan goto done; 147903a00194SGustavo F. Padovan } 148003a00194SGustavo F. Padovan 148103a00194SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) { 148203a00194SGustavo F. Padovan err = -EINVAL; 148303a00194SGustavo F. Padovan goto done; 148403a00194SGustavo F. Padovan } 148503a00194SGustavo F. Padovan 148603a00194SGustavo F. Padovan switch (chan->mode) { 148703a00194SGustavo F. Padovan case L2CAP_MODE_BASIC: 148803a00194SGustavo F. Padovan break; 148903a00194SGustavo F. Padovan case L2CAP_MODE_ERTM: 149003a00194SGustavo F. Padovan case L2CAP_MODE_STREAMING: 149103a00194SGustavo F. Padovan if (!disable_ertm) 149203a00194SGustavo F. Padovan break; 149303a00194SGustavo F. Padovan /* fall through */ 149403a00194SGustavo F. Padovan default: 149503a00194SGustavo F. Padovan err = -ENOTSUPP; 149603a00194SGustavo F. Padovan goto done; 149703a00194SGustavo F. Padovan } 149803a00194SGustavo F. Padovan 14996be36555SAndrei Emeltchenko lock_sock(sk); 15006be36555SAndrei Emeltchenko 150103a00194SGustavo F. Padovan switch (sk->sk_state) { 150203a00194SGustavo F. Padovan case BT_CONNECT: 150303a00194SGustavo F. Padovan case BT_CONNECT2: 150403a00194SGustavo F. Padovan case BT_CONFIG: 150503a00194SGustavo F. Padovan /* Already connecting */ 150603a00194SGustavo F. Padovan err = 0; 15076be36555SAndrei Emeltchenko release_sock(sk); 150803a00194SGustavo F. Padovan goto done; 150903a00194SGustavo F. Padovan 151003a00194SGustavo F. Padovan case BT_CONNECTED: 151103a00194SGustavo F. Padovan /* Already connected */ 151203a00194SGustavo F. Padovan err = -EISCONN; 15136be36555SAndrei Emeltchenko release_sock(sk); 151403a00194SGustavo F. Padovan goto done; 151503a00194SGustavo F. Padovan 151603a00194SGustavo F. Padovan case BT_OPEN: 151703a00194SGustavo F. Padovan case BT_BOUND: 151803a00194SGustavo F. Padovan /* Can connect */ 151903a00194SGustavo F. Padovan break; 152003a00194SGustavo F. Padovan 152103a00194SGustavo F. Padovan default: 152203a00194SGustavo F. Padovan err = -EBADFD; 15236be36555SAndrei Emeltchenko release_sock(sk); 152403a00194SGustavo F. Padovan goto done; 152503a00194SGustavo F. Padovan } 152603a00194SGustavo F. Padovan 152703a00194SGustavo F. Padovan /* Set destination address and psm */ 15289219b2a0SGustavo F. Padovan bacpy(&bt_sk(sk)->dst, dst); 15296be36555SAndrei Emeltchenko 15306be36555SAndrei Emeltchenko release_sock(sk); 15316be36555SAndrei Emeltchenko 153203a00194SGustavo F. Padovan chan->psm = psm; 153303a00194SGustavo F. Padovan chan->dcid = cid; 15340a708f8fSGustavo F. Padovan 15354343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 15360a708f8fSGustavo F. Padovan 1537fe4128e0SGustavo F. Padovan if (chan->dcid == L2CAP_CID_LE_DATA) 15388e9f9892SAndre Guedes hcon = hci_connect(hdev, LE_LINK, dst, dst_type, 15394343478fSGustavo F. Padovan chan->sec_level, auth_type); 1540acd7d370SVille Tervo else 15418e9f9892SAndre Guedes hcon = hci_connect(hdev, ACL_LINK, dst, dst_type, 15424343478fSGustavo F. Padovan chan->sec_level, auth_type); 1543acd7d370SVille Tervo 154430e76272SVille Tervo if (IS_ERR(hcon)) { 154530e76272SVille Tervo err = PTR_ERR(hcon); 15460a708f8fSGustavo F. Padovan goto done; 154730e76272SVille Tervo } 15480a708f8fSGustavo F. Padovan 15490a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, 0); 15500a708f8fSGustavo F. Padovan if (!conn) { 15510a708f8fSGustavo F. Padovan hci_conn_put(hcon); 155230e76272SVille Tervo err = -ENOMEM; 15530a708f8fSGustavo F. Padovan goto done; 15540a708f8fSGustavo F. Padovan } 15550a708f8fSGustavo F. Padovan 15569f0caeb1SVinicius Costa Gomes if (hcon->type == LE_LINK) { 15579f0caeb1SVinicius Costa Gomes err = 0; 15589f0caeb1SVinicius Costa Gomes 15599f0caeb1SVinicius Costa Gomes if (!list_empty(&conn->chan_l)) { 15609f0caeb1SVinicius Costa Gomes err = -EBUSY; 15619f0caeb1SVinicius Costa Gomes hci_conn_put(hcon); 15629f0caeb1SVinicius Costa Gomes } 15639f0caeb1SVinicius Costa Gomes 15649f0caeb1SVinicius Costa Gomes if (err) 15659f0caeb1SVinicius Costa Gomes goto done; 15669f0caeb1SVinicius Costa Gomes } 15679f0caeb1SVinicius Costa Gomes 15680a708f8fSGustavo F. Padovan /* Update source addr of the socket */ 15690a708f8fSGustavo F. Padovan bacpy(src, conn->src); 15700a708f8fSGustavo F. Padovan 15716be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 157248454079SGustavo F. Padovan l2cap_chan_add(conn, chan); 15736be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 157448454079SGustavo F. Padovan 15756be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECT); 1576c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 15770a708f8fSGustavo F. Padovan 15780a708f8fSGustavo F. Padovan if (hcon->state == BT_CONNECTED) { 1579715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1580c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 1581d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) 15826be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECTED); 15830a708f8fSGustavo F. Padovan } else 1584fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 15850a708f8fSGustavo F. Padovan } 15860a708f8fSGustavo F. Padovan 158730e76272SVille Tervo err = 0; 158830e76272SVille Tervo 15890a708f8fSGustavo F. Padovan done: 15906be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 159109fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 15920a708f8fSGustavo F. Padovan hci_dev_put(hdev); 15930a708f8fSGustavo F. Padovan return err; 15940a708f8fSGustavo F. Padovan } 15950a708f8fSGustavo F. Padovan 1596dcba0dbaSGustavo F. Padovan int __l2cap_wait_ack(struct sock *sk) 15970a708f8fSGustavo F. Padovan { 15988c1d787bSGustavo F. Padovan struct l2cap_chan *chan = l2cap_pi(sk)->chan; 15990a708f8fSGustavo F. Padovan DECLARE_WAITQUEUE(wait, current); 16000a708f8fSGustavo F. Padovan int err = 0; 16010a708f8fSGustavo F. Padovan int timeo = HZ/5; 16020a708f8fSGustavo F. Padovan 16030a708f8fSGustavo F. Padovan add_wait_queue(sk_sleep(sk), &wait); 16040a708f8fSGustavo F. Padovan set_current_state(TASK_INTERRUPTIBLE); 1605a71a0cf4SPeter Hurley while (chan->unacked_frames > 0 && chan->conn) { 16060a708f8fSGustavo F. Padovan if (!timeo) 16070a708f8fSGustavo F. Padovan timeo = HZ/5; 16080a708f8fSGustavo F. Padovan 16090a708f8fSGustavo F. Padovan if (signal_pending(current)) { 16100a708f8fSGustavo F. Padovan err = sock_intr_errno(timeo); 16110a708f8fSGustavo F. Padovan break; 16120a708f8fSGustavo F. Padovan } 16130a708f8fSGustavo F. Padovan 16140a708f8fSGustavo F. Padovan release_sock(sk); 16150a708f8fSGustavo F. Padovan timeo = schedule_timeout(timeo); 16160a708f8fSGustavo F. Padovan lock_sock(sk); 1617a71a0cf4SPeter Hurley set_current_state(TASK_INTERRUPTIBLE); 16180a708f8fSGustavo F. Padovan 16190a708f8fSGustavo F. Padovan err = sock_error(sk); 16200a708f8fSGustavo F. Padovan if (err) 16210a708f8fSGustavo F. Padovan break; 16220a708f8fSGustavo F. Padovan } 16230a708f8fSGustavo F. Padovan set_current_state(TASK_RUNNING); 16240a708f8fSGustavo F. Padovan remove_wait_queue(sk_sleep(sk), &wait); 16250a708f8fSGustavo F. Padovan return err; 16260a708f8fSGustavo F. Padovan } 16270a708f8fSGustavo F. Padovan 1628721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work) 16290a708f8fSGustavo F. Padovan { 1630721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1631721c4181SGustavo F. Padovan monitor_timer.work); 16320a708f8fSGustavo F. Padovan 1633525cd185SGustavo F. Padovan BT_DBG("chan %p", chan); 16340a708f8fSGustavo F. Padovan 16356be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 16366be36555SAndrei Emeltchenko 163780909e04SMat Martineau if (!chan->conn) { 16386be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16398d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 16400a708f8fSGustavo F. Padovan return; 16410a708f8fSGustavo F. Padovan } 16420a708f8fSGustavo F. Padovan 1643401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO); 16440a708f8fSGustavo F. Padovan 16456be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16468d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 16470a708f8fSGustavo F. Padovan } 16480a708f8fSGustavo F. Padovan 1649721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work) 16500a708f8fSGustavo F. Padovan { 1651721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1652721c4181SGustavo F. Padovan retrans_timer.work); 16530a708f8fSGustavo F. Padovan 165449208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 16550a708f8fSGustavo F. Padovan 16566be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 16576be36555SAndrei Emeltchenko 165880909e04SMat Martineau if (!chan->conn) { 165980909e04SMat Martineau l2cap_chan_unlock(chan); 166080909e04SMat Martineau l2cap_chan_put(chan); 166180909e04SMat Martineau return; 166280909e04SMat Martineau } 16630a708f8fSGustavo F. Padovan 1664401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO); 16656be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16668d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 16670a708f8fSGustavo F. Padovan } 16680a708f8fSGustavo F. Padovan 1669d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan, 16703733937dSMat Martineau struct sk_buff_head *skbs) 16710a708f8fSGustavo F. Padovan { 16720a708f8fSGustavo F. Padovan struct sk_buff *skb; 16733733937dSMat Martineau struct l2cap_ctrl *control; 16740a708f8fSGustavo F. Padovan 16753733937dSMat Martineau BT_DBG("chan %p, skbs %p", chan, skbs); 16763733937dSMat Martineau 16773733937dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 16783733937dSMat Martineau 16793733937dSMat Martineau while (!skb_queue_empty(&chan->tx_q)) { 16803733937dSMat Martineau 16813733937dSMat Martineau skb = skb_dequeue(&chan->tx_q); 16823733937dSMat Martineau 16833733937dSMat Martineau bt_cb(skb)->control.retries = 1; 16843733937dSMat Martineau control = &bt_cb(skb)->control; 16853733937dSMat Martineau 16863733937dSMat Martineau control->reqseq = 0; 16873733937dSMat Martineau control->txseq = chan->next_tx_seq; 16883733937dSMat Martineau 16893733937dSMat Martineau __pack_control(chan, control, skb); 16900a708f8fSGustavo F. Padovan 169147d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 16923733937dSMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 16933733937dSMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 16940a708f8fSGustavo F. Padovan } 16950a708f8fSGustavo F. Padovan 16964343478fSGustavo F. Padovan l2cap_do_send(chan, skb); 16970a708f8fSGustavo F. Padovan 16983733937dSMat Martineau BT_DBG("Sent txseq %d", (int)control->txseq); 16993733937dSMat Martineau 1700836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 17013733937dSMat Martineau chan->frames_sent++; 17020a708f8fSGustavo F. Padovan } 17030a708f8fSGustavo F. Padovan } 17040a708f8fSGustavo F. Padovan 170567c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan) 17060a708f8fSGustavo F. Padovan { 17070a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 170818a48e76SMat Martineau struct l2cap_ctrl *control; 170918a48e76SMat Martineau int sent = 0; 171018a48e76SMat Martineau 171118a48e76SMat Martineau BT_DBG("chan %p", chan); 17120a708f8fSGustavo F. Padovan 171389bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 17140a708f8fSGustavo F. Padovan return -ENOTCONN; 17150a708f8fSGustavo F. Padovan 171694122bbeSMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 171794122bbeSMat Martineau return 0; 171894122bbeSMat Martineau 171918a48e76SMat Martineau while (chan->tx_send_head && 172018a48e76SMat Martineau chan->unacked_frames < chan->remote_tx_win && 172118a48e76SMat Martineau chan->tx_state == L2CAP_TX_STATE_XMIT) { 17220a708f8fSGustavo F. Padovan 172318a48e76SMat Martineau skb = chan->tx_send_head; 17240a708f8fSGustavo F. Padovan 172518a48e76SMat Martineau bt_cb(skb)->control.retries = 1; 172618a48e76SMat Martineau control = &bt_cb(skb)->control; 17270a708f8fSGustavo F. Padovan 1728e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 172918a48e76SMat Martineau control->final = 1; 1730e2ab4353SGustavo F. Padovan 173118a48e76SMat Martineau control->reqseq = chan->buffer_seq; 173218a48e76SMat Martineau chan->last_acked_seq = chan->buffer_seq; 173318a48e76SMat Martineau control->txseq = chan->next_tx_seq; 17340a708f8fSGustavo F. Padovan 173518a48e76SMat Martineau __pack_control(chan, control, skb); 17360a708f8fSGustavo F. Padovan 173747d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 173818a48e76SMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 173918a48e76SMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 17400a708f8fSGustavo F. Padovan } 17410a708f8fSGustavo F. Padovan 174218a48e76SMat Martineau /* Clone after data has been modified. Data is assumed to be 174318a48e76SMat Martineau read-only (for locking purposes) on cloned sk_buffs. 174418a48e76SMat Martineau */ 174518a48e76SMat Martineau tx_skb = skb_clone(skb, GFP_KERNEL); 174618a48e76SMat Martineau 174718a48e76SMat Martineau if (!tx_skb) 174818a48e76SMat Martineau break; 17490a708f8fSGustavo F. Padovan 17501a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 17510a708f8fSGustavo F. Padovan 1752836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 17536a026610SGustavo F. Padovan chan->unacked_frames++; 17546a026610SGustavo F. Padovan chan->frames_sent++; 175518a48e76SMat Martineau sent++; 17560a708f8fSGustavo F. Padovan 175758d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 175858d35f87SGustavo F. Padovan chan->tx_send_head = NULL; 17590a708f8fSGustavo F. Padovan else 176058d35f87SGustavo F. Padovan chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); 176118a48e76SMat Martineau 176218a48e76SMat Martineau l2cap_do_send(chan, tx_skb); 176318a48e76SMat Martineau BT_DBG("Sent txseq %d", (int)control->txseq); 17640a708f8fSGustavo F. Padovan } 17650a708f8fSGustavo F. Padovan 176618a48e76SMat Martineau BT_DBG("Sent %d, %d unacked, %d in ERTM queue", sent, 176718a48e76SMat Martineau (int) chan->unacked_frames, skb_queue_len(&chan->tx_q)); 176818a48e76SMat Martineau 176918a48e76SMat Martineau return sent; 17700a708f8fSGustavo F. Padovan } 17710a708f8fSGustavo F. Padovan 1772e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan) 1773e1fbd4c1SMat Martineau { 1774e1fbd4c1SMat Martineau struct l2cap_ctrl control; 1775e1fbd4c1SMat Martineau struct sk_buff *skb; 1776e1fbd4c1SMat Martineau struct sk_buff *tx_skb; 1777e1fbd4c1SMat Martineau u16 seq; 1778e1fbd4c1SMat Martineau 1779e1fbd4c1SMat Martineau BT_DBG("chan %p", chan); 1780e1fbd4c1SMat Martineau 1781e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 1782e1fbd4c1SMat Martineau return; 1783e1fbd4c1SMat Martineau 1784e1fbd4c1SMat Martineau while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) { 1785e1fbd4c1SMat Martineau seq = l2cap_seq_list_pop(&chan->retrans_list); 1786e1fbd4c1SMat Martineau 1787e1fbd4c1SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq); 1788e1fbd4c1SMat Martineau if (!skb) { 1789e1fbd4c1SMat Martineau BT_DBG("Error: Can't retransmit seq %d, frame missing", 1790e1fbd4c1SMat Martineau seq); 1791e1fbd4c1SMat Martineau continue; 1792e1fbd4c1SMat Martineau } 1793e1fbd4c1SMat Martineau 1794e1fbd4c1SMat Martineau bt_cb(skb)->control.retries++; 1795e1fbd4c1SMat Martineau control = bt_cb(skb)->control; 1796e1fbd4c1SMat Martineau 1797e1fbd4c1SMat Martineau if (chan->max_tx != 0 && 1798e1fbd4c1SMat Martineau bt_cb(skb)->control.retries > chan->max_tx) { 1799e1fbd4c1SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 1800e1fbd4c1SMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 1801e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 1802e1fbd4c1SMat Martineau break; 1803e1fbd4c1SMat Martineau } 1804e1fbd4c1SMat Martineau 1805e1fbd4c1SMat Martineau control.reqseq = chan->buffer_seq; 1806e1fbd4c1SMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 1807e1fbd4c1SMat Martineau control.final = 1; 1808e1fbd4c1SMat Martineau else 1809e1fbd4c1SMat Martineau control.final = 0; 1810e1fbd4c1SMat Martineau 1811e1fbd4c1SMat Martineau if (skb_cloned(skb)) { 1812e1fbd4c1SMat Martineau /* Cloned sk_buffs are read-only, so we need a 1813e1fbd4c1SMat Martineau * writeable copy 1814e1fbd4c1SMat Martineau */ 1815e1fbd4c1SMat Martineau tx_skb = skb_copy(skb, GFP_ATOMIC); 1816e1fbd4c1SMat Martineau } else { 1817e1fbd4c1SMat Martineau tx_skb = skb_clone(skb, GFP_ATOMIC); 1818e1fbd4c1SMat Martineau } 1819e1fbd4c1SMat Martineau 1820e1fbd4c1SMat Martineau if (!tx_skb) { 1821e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 1822e1fbd4c1SMat Martineau break; 1823e1fbd4c1SMat Martineau } 1824e1fbd4c1SMat Martineau 1825e1fbd4c1SMat Martineau /* Update skb contents */ 1826e1fbd4c1SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 1827e1fbd4c1SMat Martineau put_unaligned_le32(__pack_extended_control(&control), 1828e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 1829e1fbd4c1SMat Martineau } else { 1830e1fbd4c1SMat Martineau put_unaligned_le16(__pack_enhanced_control(&control), 1831e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 1832e1fbd4c1SMat Martineau } 1833e1fbd4c1SMat Martineau 1834e1fbd4c1SMat Martineau if (chan->fcs == L2CAP_FCS_CRC16) { 1835e1fbd4c1SMat Martineau u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len); 1836e1fbd4c1SMat Martineau put_unaligned_le16(fcs, skb_put(tx_skb, 1837e1fbd4c1SMat Martineau L2CAP_FCS_SIZE)); 1838e1fbd4c1SMat Martineau } 1839e1fbd4c1SMat Martineau 1840e1fbd4c1SMat Martineau l2cap_do_send(chan, tx_skb); 1841e1fbd4c1SMat Martineau 1842e1fbd4c1SMat Martineau BT_DBG("Resent txseq %d", control.txseq); 1843e1fbd4c1SMat Martineau 1844e1fbd4c1SMat Martineau chan->last_acked_seq = chan->buffer_seq; 1845e1fbd4c1SMat Martineau } 1846e1fbd4c1SMat Martineau } 1847e1fbd4c1SMat Martineau 1848f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan, 1849f80842a8SMat Martineau struct l2cap_ctrl *control) 1850f80842a8SMat Martineau { 1851f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 1852f80842a8SMat Martineau 1853f80842a8SMat Martineau l2cap_seq_list_append(&chan->retrans_list, control->reqseq); 1854f80842a8SMat Martineau l2cap_ertm_resend(chan); 1855f80842a8SMat Martineau } 1856f80842a8SMat Martineau 1857d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan, 1858d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 1859d2a7ac5dSMat Martineau { 1860e1fbd4c1SMat Martineau struct sk_buff *skb; 1861e1fbd4c1SMat Martineau 1862e1fbd4c1SMat Martineau BT_DBG("chan %p, control %p", chan, control); 1863e1fbd4c1SMat Martineau 1864e1fbd4c1SMat Martineau if (control->poll) 1865e1fbd4c1SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 1866e1fbd4c1SMat Martineau 1867e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 1868e1fbd4c1SMat Martineau 1869e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 1870e1fbd4c1SMat Martineau return; 1871e1fbd4c1SMat Martineau 1872e1fbd4c1SMat Martineau if (chan->unacked_frames) { 1873e1fbd4c1SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 1874e1fbd4c1SMat Martineau if (bt_cb(skb)->control.txseq == control->reqseq || 1875e1fbd4c1SMat Martineau skb == chan->tx_send_head) 1876e1fbd4c1SMat Martineau break; 1877e1fbd4c1SMat Martineau } 1878e1fbd4c1SMat Martineau 1879e1fbd4c1SMat Martineau skb_queue_walk_from(&chan->tx_q, skb) { 1880e1fbd4c1SMat Martineau if (skb == chan->tx_send_head) 1881e1fbd4c1SMat Martineau break; 1882e1fbd4c1SMat Martineau 1883e1fbd4c1SMat Martineau l2cap_seq_list_append(&chan->retrans_list, 1884e1fbd4c1SMat Martineau bt_cb(skb)->control.txseq); 1885e1fbd4c1SMat Martineau } 1886e1fbd4c1SMat Martineau 1887e1fbd4c1SMat Martineau l2cap_ertm_resend(chan); 1888e1fbd4c1SMat Martineau } 1889d2a7ac5dSMat Martineau } 1890d2a7ac5dSMat Martineau 1891b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan) 1892b17e73bbSSzymon Janc { 18930a0aba42SMat Martineau struct l2cap_ctrl control; 18940a0aba42SMat Martineau u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq, 18950a0aba42SMat Martineau chan->last_acked_seq); 18960a0aba42SMat Martineau int threshold; 18970a0aba42SMat Martineau 18980a0aba42SMat Martineau BT_DBG("chan %p last_acked_seq %d buffer_seq %d", 18990a0aba42SMat Martineau chan, chan->last_acked_seq, chan->buffer_seq); 19000a0aba42SMat Martineau 19010a0aba42SMat Martineau memset(&control, 0, sizeof(control)); 19020a0aba42SMat Martineau control.sframe = 1; 19030a0aba42SMat Martineau 19040a0aba42SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 19050a0aba42SMat Martineau chan->rx_state == L2CAP_RX_STATE_RECV) { 1906b17e73bbSSzymon Janc __clear_ack_timer(chan); 19070a0aba42SMat Martineau control.super = L2CAP_SUPER_RNR; 19080a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 19090a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 19100a0aba42SMat Martineau } else { 19110a0aba42SMat Martineau if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) { 19120a0aba42SMat Martineau l2cap_ertm_send(chan); 19130a0aba42SMat Martineau /* If any i-frames were sent, they included an ack */ 19140a0aba42SMat Martineau if (chan->buffer_seq == chan->last_acked_seq) 19150a0aba42SMat Martineau frames_to_ack = 0; 19160a0aba42SMat Martineau } 19170a0aba42SMat Martineau 19180a0aba42SMat Martineau /* Ack now if the tx window is 3/4ths full. 19190a0aba42SMat Martineau * Calculate without mul or div 19200a0aba42SMat Martineau */ 19210a0aba42SMat Martineau threshold = chan->tx_win; 19220a0aba42SMat Martineau threshold += threshold << 1; 19230a0aba42SMat Martineau threshold >>= 2; 19240a0aba42SMat Martineau 19250a0aba42SMat Martineau BT_DBG("frames_to_ack %d, threshold %d", (int)frames_to_ack, 19260a0aba42SMat Martineau threshold); 19270a0aba42SMat Martineau 19280a0aba42SMat Martineau if (frames_to_ack >= threshold) { 19290a0aba42SMat Martineau __clear_ack_timer(chan); 19300a0aba42SMat Martineau control.super = L2CAP_SUPER_RR; 19310a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 19320a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 19330a0aba42SMat Martineau frames_to_ack = 0; 19340a0aba42SMat Martineau } 19350a0aba42SMat Martineau 19360a0aba42SMat Martineau if (frames_to_ack) 19370a0aba42SMat Martineau __set_ack_timer(chan); 19380a0aba42SMat Martineau } 1939b17e73bbSSzymon Janc } 1940b17e73bbSSzymon Janc 194104124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, 194204124681SGustavo F. Padovan struct msghdr *msg, int len, 194304124681SGustavo F. Padovan int count, struct sk_buff *skb) 19440a708f8fSGustavo F. Padovan { 19450952a57aSAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 19460a708f8fSGustavo F. Padovan struct sk_buff **frag; 194790338947SGustavo Padovan int sent = 0; 19480a708f8fSGustavo F. Padovan 19490a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) 19500a708f8fSGustavo F. Padovan return -EFAULT; 19510a708f8fSGustavo F. Padovan 19520a708f8fSGustavo F. Padovan sent += count; 19530a708f8fSGustavo F. Padovan len -= count; 19540a708f8fSGustavo F. Padovan 19550a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 19560a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 19570a708f8fSGustavo F. Padovan while (len) { 1958fbe00700SGustavo Padovan struct sk_buff *tmp; 1959fbe00700SGustavo Padovan 19600a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 19610a708f8fSGustavo F. Padovan 1962fbe00700SGustavo Padovan tmp = chan->ops->alloc_skb(chan, count, 196390338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 1964fbe00700SGustavo Padovan if (IS_ERR(tmp)) 1965fbe00700SGustavo Padovan return PTR_ERR(tmp); 19662f7719ceSAndrei Emeltchenko 1967fbe00700SGustavo Padovan *frag = tmp; 1968fbe00700SGustavo Padovan 19690a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) 19700a708f8fSGustavo F. Padovan return -EFAULT; 19710a708f8fSGustavo F. Padovan 19725e59b791SLuiz Augusto von Dentz (*frag)->priority = skb->priority; 19735e59b791SLuiz Augusto von Dentz 19740a708f8fSGustavo F. Padovan sent += count; 19750a708f8fSGustavo F. Padovan len -= count; 19760a708f8fSGustavo F. Padovan 19772d0ed3d5SGustavo Padovan skb->len += (*frag)->len; 19782d0ed3d5SGustavo Padovan skb->data_len += (*frag)->len; 19792d0ed3d5SGustavo Padovan 19800a708f8fSGustavo F. Padovan frag = &(*frag)->next; 19810a708f8fSGustavo F. Padovan } 19820a708f8fSGustavo F. Padovan 19830a708f8fSGustavo F. Padovan return sent; 19840a708f8fSGustavo F. Padovan } 19850a708f8fSGustavo F. Padovan 19865e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, 19875e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 19885e59b791SLuiz Augusto von Dentz u32 priority) 19890a708f8fSGustavo F. Padovan { 19908c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 19910a708f8fSGustavo F. Padovan struct sk_buff *skb; 199203a51213SAndrei Emeltchenko int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; 19930a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 19940a708f8fSGustavo F. Padovan 19956d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d priority %u", chan, (int)len, priority); 19960a708f8fSGustavo F. Padovan 19970a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 19982f7719ceSAndrei Emeltchenko 19992f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 200090338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 200190338947SGustavo Padovan if (IS_ERR(skb)) 200290338947SGustavo Padovan return skb; 20030a708f8fSGustavo F. Padovan 20045e59b791SLuiz Augusto von Dentz skb->priority = priority; 20055e59b791SLuiz Augusto von Dentz 20060a708f8fSGustavo F. Padovan /* Create L2CAP header */ 20070a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2008fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 2009daf6a78cSAndrei Emeltchenko lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); 2010daf6a78cSAndrei Emeltchenko put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE)); 20110a708f8fSGustavo F. Padovan 20120952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 20130a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 20140a708f8fSGustavo F. Padovan kfree_skb(skb); 20150a708f8fSGustavo F. Padovan return ERR_PTR(err); 20160a708f8fSGustavo F. Padovan } 20170a708f8fSGustavo F. Padovan return skb; 20180a708f8fSGustavo F. Padovan } 20190a708f8fSGustavo F. Padovan 20205e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, 20215e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 20225e59b791SLuiz Augusto von Dentz u32 priority) 20230a708f8fSGustavo F. Padovan { 20248c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 20250a708f8fSGustavo F. Padovan struct sk_buff *skb; 2026f2ba7faeSGustavo Padovan int err, count; 20270a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 20280a708f8fSGustavo F. Padovan 20296d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d", chan, (int)len); 20300a708f8fSGustavo F. Padovan 2031f2ba7faeSGustavo Padovan count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); 20322f7719ceSAndrei Emeltchenko 2033f2ba7faeSGustavo Padovan skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE, 203490338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 203590338947SGustavo Padovan if (IS_ERR(skb)) 203690338947SGustavo Padovan return skb; 20370a708f8fSGustavo F. Padovan 20385e59b791SLuiz Augusto von Dentz skb->priority = priority; 20395e59b791SLuiz Augusto von Dentz 20400a708f8fSGustavo F. Padovan /* Create L2CAP header */ 20410a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2042fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 20436ff9b5efSGustavo Padovan lh->len = cpu_to_le16(len); 20440a708f8fSGustavo F. Padovan 20450952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 20460a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 20470a708f8fSGustavo F. Padovan kfree_skb(skb); 20480a708f8fSGustavo F. Padovan return ERR_PTR(err); 20490a708f8fSGustavo F. Padovan } 20500a708f8fSGustavo F. Padovan return skb; 20510a708f8fSGustavo F. Padovan } 20520a708f8fSGustavo F. Padovan 2053ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, 2054ab0ff76dSLuiz Augusto von Dentz struct msghdr *msg, size_t len, 205594122bbeSMat Martineau u16 sdulen) 20560a708f8fSGustavo F. Padovan { 20578c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 20580a708f8fSGustavo F. Padovan struct sk_buff *skb; 2059e4ca6d98SAndrei Emeltchenko int err, count, hlen; 20600a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 20610a708f8fSGustavo F. Padovan 20626d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d", chan, (int)len); 20630a708f8fSGustavo F. Padovan 20640a708f8fSGustavo F. Padovan if (!conn) 20650a708f8fSGustavo F. Padovan return ERR_PTR(-ENOTCONN); 20660a708f8fSGustavo F. Padovan 2067e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 2068e4ca6d98SAndrei Emeltchenko hlen = L2CAP_EXT_HDR_SIZE; 2069e4ca6d98SAndrei Emeltchenko else 2070e4ca6d98SAndrei Emeltchenko hlen = L2CAP_ENH_HDR_SIZE; 2071e4ca6d98SAndrei Emeltchenko 20720a708f8fSGustavo F. Padovan if (sdulen) 207303a51213SAndrei Emeltchenko hlen += L2CAP_SDULEN_SIZE; 20740a708f8fSGustavo F. Padovan 207547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 207603a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 20770a708f8fSGustavo F. Padovan 20780a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 20792f7719ceSAndrei Emeltchenko 20802f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 208190338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 208290338947SGustavo Padovan if (IS_ERR(skb)) 208390338947SGustavo Padovan return skb; 20840a708f8fSGustavo F. Padovan 20850a708f8fSGustavo F. Padovan /* Create L2CAP header */ 20860a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2087fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 20880a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 208988843ab0SAndrei Emeltchenko 209018a48e76SMat Martineau /* Control header is populated later */ 209118a48e76SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 209218a48e76SMat Martineau put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 209318a48e76SMat Martineau else 209418a48e76SMat Martineau put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 209588843ab0SAndrei Emeltchenko 20960a708f8fSGustavo F. Padovan if (sdulen) 209703a51213SAndrei Emeltchenko put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 20980a708f8fSGustavo F. Padovan 20990952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 21000a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 21010a708f8fSGustavo F. Padovan kfree_skb(skb); 21020a708f8fSGustavo F. Padovan return ERR_PTR(err); 21030a708f8fSGustavo F. Padovan } 21040a708f8fSGustavo F. Padovan 210518a48e76SMat Martineau bt_cb(skb)->control.fcs = chan->fcs; 21063ce3514fSMat Martineau bt_cb(skb)->control.retries = 0; 21070a708f8fSGustavo F. Padovan return skb; 21080a708f8fSGustavo F. Padovan } 21090a708f8fSGustavo F. Padovan 211094122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan, 211194122bbeSMat Martineau struct sk_buff_head *seg_queue, 211294122bbeSMat Martineau struct msghdr *msg, size_t len) 21130a708f8fSGustavo F. Padovan { 21140a708f8fSGustavo F. Padovan struct sk_buff *skb; 211594122bbeSMat Martineau u16 sdu_len; 211694122bbeSMat Martineau size_t pdu_len; 211794122bbeSMat Martineau int err = 0; 211894122bbeSMat Martineau u8 sar; 21190a708f8fSGustavo F. Padovan 212094122bbeSMat Martineau BT_DBG("chan %p, msg %p, len %d", chan, msg, (int)len); 21210a708f8fSGustavo F. Padovan 212294122bbeSMat Martineau /* It is critical that ERTM PDUs fit in a single HCI fragment, 212394122bbeSMat Martineau * so fragmented skbs are not used. The HCI layer's handling 212494122bbeSMat Martineau * of fragmented skbs is not compatible with ERTM's queueing. 212594122bbeSMat Martineau */ 212694122bbeSMat Martineau 212794122bbeSMat Martineau /* PDU size is derived from the HCI MTU */ 212894122bbeSMat Martineau pdu_len = chan->conn->mtu; 212994122bbeSMat Martineau 213094122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); 213194122bbeSMat Martineau 213294122bbeSMat Martineau /* Adjust for largest possible L2CAP overhead. */ 213394122bbeSMat Martineau pdu_len -= L2CAP_EXT_HDR_SIZE + L2CAP_FCS_SIZE; 213494122bbeSMat Martineau 213594122bbeSMat Martineau /* Remote device may have requested smaller PDUs */ 213694122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, chan->remote_mps); 213794122bbeSMat Martineau 213894122bbeSMat Martineau if (len <= pdu_len) { 213994122bbeSMat Martineau sar = L2CAP_SAR_UNSEGMENTED; 214094122bbeSMat Martineau sdu_len = 0; 214194122bbeSMat Martineau pdu_len = len; 214294122bbeSMat Martineau } else { 214394122bbeSMat Martineau sar = L2CAP_SAR_START; 214494122bbeSMat Martineau sdu_len = len; 214594122bbeSMat Martineau pdu_len -= L2CAP_SDULEN_SIZE; 214694122bbeSMat Martineau } 21470a708f8fSGustavo F. Padovan 21480a708f8fSGustavo F. Padovan while (len > 0) { 214994122bbeSMat Martineau skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len); 21500a708f8fSGustavo F. Padovan 21510a708f8fSGustavo F. Padovan if (IS_ERR(skb)) { 215294122bbeSMat Martineau __skb_queue_purge(seg_queue); 21530a708f8fSGustavo F. Padovan return PTR_ERR(skb); 21540a708f8fSGustavo F. Padovan } 21550a708f8fSGustavo F. Padovan 215694122bbeSMat Martineau bt_cb(skb)->control.sar = sar; 215794122bbeSMat Martineau __skb_queue_tail(seg_queue, skb); 21580a708f8fSGustavo F. Padovan 215994122bbeSMat Martineau len -= pdu_len; 216094122bbeSMat Martineau if (sdu_len) { 216194122bbeSMat Martineau sdu_len = 0; 216294122bbeSMat Martineau pdu_len += L2CAP_SDULEN_SIZE; 216394122bbeSMat Martineau } 216494122bbeSMat Martineau 216594122bbeSMat Martineau if (len <= pdu_len) { 216694122bbeSMat Martineau sar = L2CAP_SAR_END; 216794122bbeSMat Martineau pdu_len = len; 216894122bbeSMat Martineau } else { 216994122bbeSMat Martineau sar = L2CAP_SAR_CONTINUE; 217094122bbeSMat Martineau } 217194122bbeSMat Martineau } 217294122bbeSMat Martineau 217394122bbeSMat Martineau return err; 21740a708f8fSGustavo F. Padovan } 21750a708f8fSGustavo F. Padovan 21765e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, 21775e59b791SLuiz Augusto von Dentz u32 priority) 21789a91a04aSGustavo F. Padovan { 21799a91a04aSGustavo F. Padovan struct sk_buff *skb; 21809a91a04aSGustavo F. Padovan int err; 218194122bbeSMat Martineau struct sk_buff_head seg_queue; 21829a91a04aSGustavo F. Padovan 21839a91a04aSGustavo F. Padovan /* Connectionless channel */ 2184715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { 21855e59b791SLuiz Augusto von Dentz skb = l2cap_create_connless_pdu(chan, msg, len, priority); 21869a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 21879a91a04aSGustavo F. Padovan return PTR_ERR(skb); 21889a91a04aSGustavo F. Padovan 21899a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 21909a91a04aSGustavo F. Padovan return len; 21919a91a04aSGustavo F. Padovan } 21929a91a04aSGustavo F. Padovan 21939a91a04aSGustavo F. Padovan switch (chan->mode) { 21949a91a04aSGustavo F. Padovan case L2CAP_MODE_BASIC: 21959a91a04aSGustavo F. Padovan /* Check outgoing MTU */ 21969a91a04aSGustavo F. Padovan if (len > chan->omtu) 21979a91a04aSGustavo F. Padovan return -EMSGSIZE; 21989a91a04aSGustavo F. Padovan 21999a91a04aSGustavo F. Padovan /* Create a basic PDU */ 22005e59b791SLuiz Augusto von Dentz skb = l2cap_create_basic_pdu(chan, msg, len, priority); 22019a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 22029a91a04aSGustavo F. Padovan return PTR_ERR(skb); 22039a91a04aSGustavo F. Padovan 22049a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 22059a91a04aSGustavo F. Padovan err = len; 22069a91a04aSGustavo F. Padovan break; 22079a91a04aSGustavo F. Padovan 22089a91a04aSGustavo F. Padovan case L2CAP_MODE_ERTM: 22099a91a04aSGustavo F. Padovan case L2CAP_MODE_STREAMING: 221094122bbeSMat Martineau /* Check outgoing MTU */ 221194122bbeSMat Martineau if (len > chan->omtu) { 221294122bbeSMat Martineau err = -EMSGSIZE; 22139a91a04aSGustavo F. Padovan break; 22149a91a04aSGustavo F. Padovan } 22159a91a04aSGustavo F. Padovan 221694122bbeSMat Martineau __skb_queue_head_init(&seg_queue); 221794122bbeSMat Martineau 221894122bbeSMat Martineau /* Do segmentation before calling in to the state machine, 221994122bbeSMat Martineau * since it's possible to block while waiting for memory 222094122bbeSMat Martineau * allocation. 222194122bbeSMat Martineau */ 222294122bbeSMat Martineau err = l2cap_segment_sdu(chan, &seg_queue, msg, len); 222394122bbeSMat Martineau 222494122bbeSMat Martineau /* The channel could have been closed while segmenting, 222594122bbeSMat Martineau * check that it is still connected. 222694122bbeSMat Martineau */ 222794122bbeSMat Martineau if (chan->state != BT_CONNECTED) { 222894122bbeSMat Martineau __skb_queue_purge(&seg_queue); 222994122bbeSMat Martineau err = -ENOTCONN; 22309a91a04aSGustavo F. Padovan } 22319a91a04aSGustavo F. Padovan 223294122bbeSMat Martineau if (err) 223394122bbeSMat Martineau break; 223494122bbeSMat Martineau 22353733937dSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) 2236d660366dSGustavo Padovan l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST); 22373733937dSMat Martineau else 2238d660366dSGustavo Padovan l2cap_streaming_send(chan, &seg_queue); 223994122bbeSMat Martineau 22409a91a04aSGustavo F. Padovan err = len; 22419a91a04aSGustavo F. Padovan 224294122bbeSMat Martineau /* If the skbs were not queued for sending, they'll still be in 224394122bbeSMat Martineau * seg_queue and need to be purged. 224494122bbeSMat Martineau */ 224594122bbeSMat Martineau __skb_queue_purge(&seg_queue); 22469a91a04aSGustavo F. Padovan break; 22479a91a04aSGustavo F. Padovan 22489a91a04aSGustavo F. Padovan default: 22499a91a04aSGustavo F. Padovan BT_DBG("bad state %1.1x", chan->mode); 22509a91a04aSGustavo F. Padovan err = -EBADFD; 22519a91a04aSGustavo F. Padovan } 22529a91a04aSGustavo F. Padovan 22539a91a04aSGustavo F. Padovan return err; 22549a91a04aSGustavo F. Padovan } 22559a91a04aSGustavo F. Padovan 2256d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq) 2257d2a7ac5dSMat Martineau { 2258bed68bdeSMat Martineau struct l2cap_ctrl control; 2259bed68bdeSMat Martineau u16 seq; 2260bed68bdeSMat Martineau 2261bed68bdeSMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 2262bed68bdeSMat Martineau 2263bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2264bed68bdeSMat Martineau control.sframe = 1; 2265bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2266bed68bdeSMat Martineau 2267bed68bdeSMat Martineau for (seq = chan->expected_tx_seq; seq != txseq; 2268bed68bdeSMat Martineau seq = __next_seq(chan, seq)) { 2269bed68bdeSMat Martineau if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) { 2270bed68bdeSMat Martineau control.reqseq = seq; 2271bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2272bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2273bed68bdeSMat Martineau } 2274bed68bdeSMat Martineau } 2275bed68bdeSMat Martineau 2276bed68bdeSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 2277d2a7ac5dSMat Martineau } 2278d2a7ac5dSMat Martineau 2279d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan) 2280d2a7ac5dSMat Martineau { 2281bed68bdeSMat Martineau struct l2cap_ctrl control; 2282bed68bdeSMat Martineau 2283bed68bdeSMat Martineau BT_DBG("chan %p", chan); 2284bed68bdeSMat Martineau 2285bed68bdeSMat Martineau if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR) 2286bed68bdeSMat Martineau return; 2287bed68bdeSMat Martineau 2288bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2289bed68bdeSMat Martineau control.sframe = 1; 2290bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2291bed68bdeSMat Martineau control.reqseq = chan->srej_list.tail; 2292bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2293d2a7ac5dSMat Martineau } 2294d2a7ac5dSMat Martineau 2295d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq) 2296d2a7ac5dSMat Martineau { 2297bed68bdeSMat Martineau struct l2cap_ctrl control; 2298bed68bdeSMat Martineau u16 initial_head; 2299bed68bdeSMat Martineau u16 seq; 2300bed68bdeSMat Martineau 2301bed68bdeSMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 2302bed68bdeSMat Martineau 2303bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2304bed68bdeSMat Martineau control.sframe = 1; 2305bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2306bed68bdeSMat Martineau 2307bed68bdeSMat Martineau /* Capture initial list head to allow only one pass through the list. */ 2308bed68bdeSMat Martineau initial_head = chan->srej_list.head; 2309bed68bdeSMat Martineau 2310bed68bdeSMat Martineau do { 2311bed68bdeSMat Martineau seq = l2cap_seq_list_pop(&chan->srej_list); 2312bed68bdeSMat Martineau if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR) 2313bed68bdeSMat Martineau break; 2314bed68bdeSMat Martineau 2315bed68bdeSMat Martineau control.reqseq = seq; 2316bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2317bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2318bed68bdeSMat Martineau } while (chan->srej_list.head != initial_head); 2319d2a7ac5dSMat Martineau } 2320d2a7ac5dSMat Martineau 2321608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq) 2322608bcc6dSMat Martineau { 2323608bcc6dSMat Martineau struct sk_buff *acked_skb; 2324608bcc6dSMat Martineau u16 ackseq; 2325608bcc6dSMat Martineau 2326608bcc6dSMat Martineau BT_DBG("chan %p, reqseq %d", chan, reqseq); 2327608bcc6dSMat Martineau 2328608bcc6dSMat Martineau if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq) 2329608bcc6dSMat Martineau return; 2330608bcc6dSMat Martineau 2331608bcc6dSMat Martineau BT_DBG("expected_ack_seq %d, unacked_frames %d", 2332608bcc6dSMat Martineau chan->expected_ack_seq, chan->unacked_frames); 2333608bcc6dSMat Martineau 2334608bcc6dSMat Martineau for (ackseq = chan->expected_ack_seq; ackseq != reqseq; 2335608bcc6dSMat Martineau ackseq = __next_seq(chan, ackseq)) { 2336608bcc6dSMat Martineau 2337608bcc6dSMat Martineau acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq); 2338608bcc6dSMat Martineau if (acked_skb) { 2339608bcc6dSMat Martineau skb_unlink(acked_skb, &chan->tx_q); 2340608bcc6dSMat Martineau kfree_skb(acked_skb); 2341608bcc6dSMat Martineau chan->unacked_frames--; 2342608bcc6dSMat Martineau } 2343608bcc6dSMat Martineau } 2344608bcc6dSMat Martineau 2345608bcc6dSMat Martineau chan->expected_ack_seq = reqseq; 2346608bcc6dSMat Martineau 2347608bcc6dSMat Martineau if (chan->unacked_frames == 0) 2348608bcc6dSMat Martineau __clear_retrans_timer(chan); 2349608bcc6dSMat Martineau 2350608bcc6dSMat Martineau BT_DBG("unacked_frames %d", (int) chan->unacked_frames); 2351608bcc6dSMat Martineau } 2352608bcc6dSMat Martineau 2353608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan) 2354608bcc6dSMat Martineau { 2355608bcc6dSMat Martineau BT_DBG("chan %p", chan); 2356608bcc6dSMat Martineau 2357608bcc6dSMat Martineau chan->expected_tx_seq = chan->buffer_seq; 2358608bcc6dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 2359608bcc6dSMat Martineau skb_queue_purge(&chan->srej_q); 2360608bcc6dSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2361608bcc6dSMat Martineau } 2362608bcc6dSMat Martineau 2363d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan, 2364608bcc6dSMat Martineau struct l2cap_ctrl *control, 2365608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2366608bcc6dSMat Martineau { 2367608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2368608bcc6dSMat Martineau event); 2369608bcc6dSMat Martineau 2370608bcc6dSMat Martineau switch (event) { 2371608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2372608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2373608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2374608bcc6dSMat Martineau 2375608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2376608bcc6dSMat Martineau l2cap_ertm_send(chan); 2377608bcc6dSMat Martineau break; 2378608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2379608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2380608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2381608bcc6dSMat Martineau 2382608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2383608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2384608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2385608bcc6dSMat Martineau */ 2386608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2387608bcc6dSMat Martineau } 2388608bcc6dSMat Martineau 2389608bcc6dSMat Martineau l2cap_send_ack(chan); 2390608bcc6dSMat Martineau 2391608bcc6dSMat Martineau break; 2392608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2393608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2394608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2395608bcc6dSMat Martineau 2396608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2397608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2398608bcc6dSMat Martineau 2399608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2400608bcc6dSMat Martineau local_control.sframe = 1; 2401608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2402608bcc6dSMat Martineau local_control.poll = 1; 2403608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2404a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2405608bcc6dSMat Martineau 2406608bcc6dSMat Martineau chan->retry_count = 1; 2407608bcc6dSMat Martineau __set_monitor_timer(chan); 2408608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2409608bcc6dSMat Martineau } 2410608bcc6dSMat Martineau break; 2411608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2412608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2413608bcc6dSMat Martineau break; 2414608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2415608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2416608bcc6dSMat Martineau chan->retry_count = 1; 2417608bcc6dSMat Martineau __set_monitor_timer(chan); 2418608bcc6dSMat Martineau __clear_ack_timer(chan); 2419608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2420608bcc6dSMat Martineau break; 2421608bcc6dSMat Martineau case L2CAP_EV_RETRANS_TO: 2422608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2423608bcc6dSMat Martineau chan->retry_count = 1; 2424608bcc6dSMat Martineau __set_monitor_timer(chan); 2425608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2426608bcc6dSMat Martineau break; 2427608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2428608bcc6dSMat Martineau /* Nothing to process */ 2429608bcc6dSMat Martineau break; 2430608bcc6dSMat Martineau default: 2431608bcc6dSMat Martineau break; 2432608bcc6dSMat Martineau } 2433608bcc6dSMat Martineau } 2434608bcc6dSMat Martineau 2435d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan, 2436608bcc6dSMat Martineau struct l2cap_ctrl *control, 2437608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2438608bcc6dSMat Martineau { 2439608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2440608bcc6dSMat Martineau event); 2441608bcc6dSMat Martineau 2442608bcc6dSMat Martineau switch (event) { 2443608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2444608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2445608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2446608bcc6dSMat Martineau /* Queue data, but don't send. */ 2447608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2448608bcc6dSMat Martineau break; 2449608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2450608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2451608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2452608bcc6dSMat Martineau 2453608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2454608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2455608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2456608bcc6dSMat Martineau */ 2457608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2458608bcc6dSMat Martineau } 2459608bcc6dSMat Martineau 2460608bcc6dSMat Martineau l2cap_send_ack(chan); 2461608bcc6dSMat Martineau 2462608bcc6dSMat Martineau break; 2463608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2464608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2465608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2466608bcc6dSMat Martineau 2467608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2468608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2469608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2470608bcc6dSMat Martineau local_control.sframe = 1; 2471608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2472608bcc6dSMat Martineau local_control.poll = 1; 2473608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2474a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2475608bcc6dSMat Martineau 2476608bcc6dSMat Martineau chan->retry_count = 1; 2477608bcc6dSMat Martineau __set_monitor_timer(chan); 2478608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2479608bcc6dSMat Martineau } 2480608bcc6dSMat Martineau break; 2481608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2482608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2483608bcc6dSMat Martineau 2484608bcc6dSMat Martineau /* Fall through */ 2485608bcc6dSMat Martineau 2486608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2487608bcc6dSMat Martineau if (control && control->final) { 2488608bcc6dSMat Martineau __clear_monitor_timer(chan); 2489608bcc6dSMat Martineau if (chan->unacked_frames > 0) 2490608bcc6dSMat Martineau __set_retrans_timer(chan); 2491608bcc6dSMat Martineau chan->retry_count = 0; 2492608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 2493608bcc6dSMat Martineau BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state); 2494608bcc6dSMat Martineau } 2495608bcc6dSMat Martineau break; 2496608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2497608bcc6dSMat Martineau /* Ignore */ 2498608bcc6dSMat Martineau break; 2499608bcc6dSMat Martineau case L2CAP_EV_MONITOR_TO: 2500608bcc6dSMat Martineau if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) { 2501608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2502608bcc6dSMat Martineau __set_monitor_timer(chan); 2503608bcc6dSMat Martineau chan->retry_count++; 2504608bcc6dSMat Martineau } else { 2505608bcc6dSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); 2506608bcc6dSMat Martineau } 2507608bcc6dSMat Martineau break; 2508608bcc6dSMat Martineau default: 2509608bcc6dSMat Martineau break; 2510608bcc6dSMat Martineau } 2511608bcc6dSMat Martineau } 2512608bcc6dSMat Martineau 2513d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 2514608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2515608bcc6dSMat Martineau { 2516608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d, state %d", 2517608bcc6dSMat Martineau chan, control, skbs, event, chan->tx_state); 2518608bcc6dSMat Martineau 2519608bcc6dSMat Martineau switch (chan->tx_state) { 2520608bcc6dSMat Martineau case L2CAP_TX_STATE_XMIT: 2521d660366dSGustavo Padovan l2cap_tx_state_xmit(chan, control, skbs, event); 2522608bcc6dSMat Martineau break; 2523608bcc6dSMat Martineau case L2CAP_TX_STATE_WAIT_F: 2524d660366dSGustavo Padovan l2cap_tx_state_wait_f(chan, control, skbs, event); 2525608bcc6dSMat Martineau break; 2526608bcc6dSMat Martineau default: 2527608bcc6dSMat Martineau /* Ignore event */ 2528608bcc6dSMat Martineau break; 2529608bcc6dSMat Martineau } 2530608bcc6dSMat Martineau } 2531608bcc6dSMat Martineau 25324b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan, 25334b51dae9SMat Martineau struct l2cap_ctrl *control) 25344b51dae9SMat Martineau { 25354b51dae9SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2536401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT); 25374b51dae9SMat Martineau } 25384b51dae9SMat Martineau 2539f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan, 2540f80842a8SMat Martineau struct l2cap_ctrl *control) 2541f80842a8SMat Martineau { 2542f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2543401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT); 2544f80842a8SMat Martineau } 2545f80842a8SMat Martineau 25460a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */ 25470a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 25480a708f8fSGustavo F. Padovan { 25490a708f8fSGustavo F. Padovan struct sk_buff *nskb; 255048454079SGustavo F. Padovan struct l2cap_chan *chan; 25510a708f8fSGustavo F. Padovan 25520a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 25530a708f8fSGustavo F. Padovan 25543df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 25553d57dc68SGustavo F. Padovan 25563df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 255748454079SGustavo F. Padovan struct sock *sk = chan->sk; 2558715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW) 25590a708f8fSGustavo F. Padovan continue; 25600a708f8fSGustavo F. Padovan 25610a708f8fSGustavo F. Padovan /* Don't send frame to the socket it came from */ 25620a708f8fSGustavo F. Padovan if (skb->sk == sk) 25630a708f8fSGustavo F. Padovan continue; 25640a708f8fSGustavo F. Padovan nskb = skb_clone(skb, GFP_ATOMIC); 25650a708f8fSGustavo F. Padovan if (!nskb) 25660a708f8fSGustavo F. Padovan continue; 25670a708f8fSGustavo F. Padovan 256823070494SGustavo F. Padovan if (chan->ops->recv(chan->data, nskb)) 25690a708f8fSGustavo F. Padovan kfree_skb(nskb); 25700a708f8fSGustavo F. Padovan } 25713d57dc68SGustavo F. Padovan 25723df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 25730a708f8fSGustavo F. Padovan } 25740a708f8fSGustavo F. Padovan 25750a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */ 25760a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 25770a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data) 25780a708f8fSGustavo F. Padovan { 25790a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag; 25800a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd; 25810a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 25820a708f8fSGustavo F. Padovan int len, count; 25830a708f8fSGustavo F. Padovan 25840a708f8fSGustavo F. Padovan BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d", 25850a708f8fSGustavo F. Padovan conn, code, ident, dlen); 25860a708f8fSGustavo F. Padovan 25870a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; 25880a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 25890a708f8fSGustavo F. Padovan 25900a708f8fSGustavo F. Padovan skb = bt_skb_alloc(count, GFP_ATOMIC); 25910a708f8fSGustavo F. Padovan if (!skb) 25920a708f8fSGustavo F. Padovan return NULL; 25930a708f8fSGustavo F. Padovan 25940a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 25950a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); 25963300d9a9SClaudio Takahasi 25973300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 25983300d9a9SClaudio Takahasi lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING); 25993300d9a9SClaudio Takahasi else 26000a708f8fSGustavo F. Padovan lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING); 26010a708f8fSGustavo F. Padovan 26020a708f8fSGustavo F. Padovan cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); 26030a708f8fSGustavo F. Padovan cmd->code = code; 26040a708f8fSGustavo F. Padovan cmd->ident = ident; 26050a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen); 26060a708f8fSGustavo F. Padovan 26070a708f8fSGustavo F. Padovan if (dlen) { 26080a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE; 26090a708f8fSGustavo F. Padovan memcpy(skb_put(skb, count), data, count); 26100a708f8fSGustavo F. Padovan data += count; 26110a708f8fSGustavo F. Padovan } 26120a708f8fSGustavo F. Padovan 26130a708f8fSGustavo F. Padovan len -= skb->len; 26140a708f8fSGustavo F. Padovan 26150a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 26160a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 26170a708f8fSGustavo F. Padovan while (len) { 26180a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 26190a708f8fSGustavo F. Padovan 26200a708f8fSGustavo F. Padovan *frag = bt_skb_alloc(count, GFP_ATOMIC); 26210a708f8fSGustavo F. Padovan if (!*frag) 26220a708f8fSGustavo F. Padovan goto fail; 26230a708f8fSGustavo F. Padovan 26240a708f8fSGustavo F. Padovan memcpy(skb_put(*frag, count), data, count); 26250a708f8fSGustavo F. Padovan 26260a708f8fSGustavo F. Padovan len -= count; 26270a708f8fSGustavo F. Padovan data += count; 26280a708f8fSGustavo F. Padovan 26290a708f8fSGustavo F. Padovan frag = &(*frag)->next; 26300a708f8fSGustavo F. Padovan } 26310a708f8fSGustavo F. Padovan 26320a708f8fSGustavo F. Padovan return skb; 26330a708f8fSGustavo F. Padovan 26340a708f8fSGustavo F. Padovan fail: 26350a708f8fSGustavo F. Padovan kfree_skb(skb); 26360a708f8fSGustavo F. Padovan return NULL; 26370a708f8fSGustavo F. Padovan } 26380a708f8fSGustavo F. Padovan 26390a708f8fSGustavo F. Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val) 26400a708f8fSGustavo F. Padovan { 26410a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 26420a708f8fSGustavo F. Padovan int len; 26430a708f8fSGustavo F. Padovan 26440a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len; 26450a708f8fSGustavo F. Padovan *ptr += len; 26460a708f8fSGustavo F. Padovan 26470a708f8fSGustavo F. Padovan *type = opt->type; 26480a708f8fSGustavo F. Padovan *olen = opt->len; 26490a708f8fSGustavo F. Padovan 26500a708f8fSGustavo F. Padovan switch (opt->len) { 26510a708f8fSGustavo F. Padovan case 1: 26520a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val); 26530a708f8fSGustavo F. Padovan break; 26540a708f8fSGustavo F. Padovan 26550a708f8fSGustavo F. Padovan case 2: 26560a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val); 26570a708f8fSGustavo F. Padovan break; 26580a708f8fSGustavo F. Padovan 26590a708f8fSGustavo F. Padovan case 4: 26600a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val); 26610a708f8fSGustavo F. Padovan break; 26620a708f8fSGustavo F. Padovan 26630a708f8fSGustavo F. Padovan default: 26640a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val; 26650a708f8fSGustavo F. Padovan break; 26660a708f8fSGustavo F. Padovan } 26670a708f8fSGustavo F. Padovan 26680a708f8fSGustavo F. Padovan BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val); 26690a708f8fSGustavo F. Padovan return len; 26700a708f8fSGustavo F. Padovan } 26710a708f8fSGustavo F. Padovan 26720a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) 26730a708f8fSGustavo F. Padovan { 26740a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 26750a708f8fSGustavo F. Padovan 26760a708f8fSGustavo F. Padovan BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val); 26770a708f8fSGustavo F. Padovan 26780a708f8fSGustavo F. Padovan opt->type = type; 26790a708f8fSGustavo F. Padovan opt->len = len; 26800a708f8fSGustavo F. Padovan 26810a708f8fSGustavo F. Padovan switch (len) { 26820a708f8fSGustavo F. Padovan case 1: 26830a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val; 26840a708f8fSGustavo F. Padovan break; 26850a708f8fSGustavo F. Padovan 26860a708f8fSGustavo F. Padovan case 2: 26870a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val); 26880a708f8fSGustavo F. Padovan break; 26890a708f8fSGustavo F. Padovan 26900a708f8fSGustavo F. Padovan case 4: 26910a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val); 26920a708f8fSGustavo F. Padovan break; 26930a708f8fSGustavo F. Padovan 26940a708f8fSGustavo F. Padovan default: 26950a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len); 26960a708f8fSGustavo F. Padovan break; 26970a708f8fSGustavo F. Padovan } 26980a708f8fSGustavo F. Padovan 26990a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len; 27000a708f8fSGustavo F. Padovan } 27010a708f8fSGustavo F. Padovan 2702f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) 2703f89cef09SAndrei Emeltchenko { 2704f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs; 2705f89cef09SAndrei Emeltchenko 2706f89cef09SAndrei Emeltchenko switch (chan->mode) { 2707f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM: 2708f89cef09SAndrei Emeltchenko efs.id = chan->local_id; 2709f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype; 2710f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 2711f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 2712f89cef09SAndrei Emeltchenko efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); 2713f89cef09SAndrei Emeltchenko efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO); 2714f89cef09SAndrei Emeltchenko break; 2715f89cef09SAndrei Emeltchenko 2716f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING: 2717f89cef09SAndrei Emeltchenko efs.id = 1; 2718f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT; 2719f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 2720f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 2721f89cef09SAndrei Emeltchenko efs.acc_lat = 0; 2722f89cef09SAndrei Emeltchenko efs.flush_to = 0; 2723f89cef09SAndrei Emeltchenko break; 2724f89cef09SAndrei Emeltchenko 2725f89cef09SAndrei Emeltchenko default: 2726f89cef09SAndrei Emeltchenko return; 2727f89cef09SAndrei Emeltchenko } 2728f89cef09SAndrei Emeltchenko 2729f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), 2730f89cef09SAndrei Emeltchenko (unsigned long) &efs); 2731f89cef09SAndrei Emeltchenko } 2732f89cef09SAndrei Emeltchenko 2733721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work) 27340a708f8fSGustavo F. Padovan { 2735721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 2736721c4181SGustavo F. Padovan ack_timer.work); 27370362520bSMat Martineau u16 frames_to_ack; 27380a708f8fSGustavo F. Padovan 27392fb9b3d4SGustavo F. Padovan BT_DBG("chan %p", chan); 27402fb9b3d4SGustavo F. Padovan 27416be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 27426be36555SAndrei Emeltchenko 27430362520bSMat Martineau frames_to_ack = __seq_offset(chan, chan->buffer_seq, 27440362520bSMat Martineau chan->last_acked_seq); 27450362520bSMat Martineau 27460362520bSMat Martineau if (frames_to_ack) 27470362520bSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 27486be36555SAndrei Emeltchenko 27496be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 275009bfb2eeSSzymon Janc l2cap_chan_put(chan); 27510a708f8fSGustavo F. Padovan } 27520a708f8fSGustavo F. Padovan 27533c588192SMat Martineau static inline int l2cap_ertm_init(struct l2cap_chan *chan) 27540a708f8fSGustavo F. Padovan { 27553c588192SMat Martineau int err; 27563c588192SMat Martineau 2757105bdf9eSMat Martineau chan->next_tx_seq = 0; 2758105bdf9eSMat Martineau chan->expected_tx_seq = 0; 275942e5c802SGustavo F. Padovan chan->expected_ack_seq = 0; 27606a026610SGustavo F. Padovan chan->unacked_frames = 0; 276142e5c802SGustavo F. Padovan chan->buffer_seq = 0; 27626a026610SGustavo F. Padovan chan->frames_sent = 0; 2763105bdf9eSMat Martineau chan->last_acked_seq = 0; 2764105bdf9eSMat Martineau chan->sdu = NULL; 2765105bdf9eSMat Martineau chan->sdu_last_frag = NULL; 2766105bdf9eSMat Martineau chan->sdu_len = 0; 2767105bdf9eSMat Martineau 2768d34c34fbSMat Martineau skb_queue_head_init(&chan->tx_q); 2769d34c34fbSMat Martineau 2770105bdf9eSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 2771105bdf9eSMat Martineau return 0; 2772105bdf9eSMat Martineau 2773105bdf9eSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2774105bdf9eSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 27750a708f8fSGustavo F. Padovan 2776721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout); 2777721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout); 2778721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout); 27790a708f8fSGustavo F. Padovan 2780f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q); 27810a708f8fSGustavo F. Padovan 27823c588192SMat Martineau err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win); 27833c588192SMat Martineau if (err < 0) 27843c588192SMat Martineau return err; 27853c588192SMat Martineau 27869dc9affcSMat Martineau err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win); 27879dc9affcSMat Martineau if (err < 0) 27889dc9affcSMat Martineau l2cap_seq_list_free(&chan->srej_list); 27899dc9affcSMat Martineau 27909dc9affcSMat Martineau return err; 27910a708f8fSGustavo F. Padovan } 27920a708f8fSGustavo F. Padovan 27930a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) 27940a708f8fSGustavo F. Padovan { 27950a708f8fSGustavo F. Padovan switch (mode) { 27960a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 27970a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 27980a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask)) 27990a708f8fSGustavo F. Padovan return mode; 28000a708f8fSGustavo F. Padovan /* fall through */ 28010a708f8fSGustavo F. Padovan default: 28020a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC; 28030a708f8fSGustavo F. Padovan } 28040a708f8fSGustavo F. Padovan } 28050a708f8fSGustavo F. Padovan 28066327eb98SAndrei Emeltchenko static inline bool __l2cap_ews_supported(struct l2cap_chan *chan) 28076327eb98SAndrei Emeltchenko { 28086327eb98SAndrei Emeltchenko return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW; 28096327eb98SAndrei Emeltchenko } 28106327eb98SAndrei Emeltchenko 2811f89cef09SAndrei Emeltchenko static inline bool __l2cap_efs_supported(struct l2cap_chan *chan) 2812f89cef09SAndrei Emeltchenko { 2813f89cef09SAndrei Emeltchenko return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW; 2814f89cef09SAndrei Emeltchenko } 2815f89cef09SAndrei Emeltchenko 28166327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan) 28176327eb98SAndrei Emeltchenko { 28186327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && 2819836be934SAndrei Emeltchenko __l2cap_ews_supported(chan)) { 28206327eb98SAndrei Emeltchenko /* use extended control field */ 28216327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 2822836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 2823836be934SAndrei Emeltchenko } else { 28246327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win, 28256327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 2826836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 2827836be934SAndrei Emeltchenko } 28286327eb98SAndrei Emeltchenko } 28296327eb98SAndrei Emeltchenko 2830710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) 28310a708f8fSGustavo F. Padovan { 28320a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 28330c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode }; 28340a708f8fSGustavo F. Padovan void *ptr = req->data; 2835c8f79162SAndrei Emeltchenko u16 size; 28360a708f8fSGustavo F. Padovan 283749208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 28380a708f8fSGustavo F. Padovan 283973ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp) 28400a708f8fSGustavo F. Padovan goto done; 28410a708f8fSGustavo F. Padovan 28420c1bc5c6SGustavo F. Padovan switch (chan->mode) { 28430a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 28440a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 2845c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) 28460a708f8fSGustavo F. Padovan break; 28470a708f8fSGustavo F. Padovan 2848f89cef09SAndrei Emeltchenko if (__l2cap_efs_supported(chan)) 2849f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 2850f89cef09SAndrei Emeltchenko 28510a708f8fSGustavo F. Padovan /* fall through */ 28520a708f8fSGustavo F. Padovan default: 28538c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); 28540a708f8fSGustavo F. Padovan break; 28550a708f8fSGustavo F. Padovan } 28560a708f8fSGustavo F. Padovan 28570a708f8fSGustavo F. Padovan done: 28580c1bc5c6SGustavo F. Padovan if (chan->imtu != L2CAP_DEFAULT_MTU) 28590c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 28600a708f8fSGustavo F. Padovan 28610c1bc5c6SGustavo F. Padovan switch (chan->mode) { 28620a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 28638c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && 28648c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) 28650a708f8fSGustavo F. Padovan break; 28660a708f8fSGustavo F. Padovan 28670a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC; 28680a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 28690a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 28700a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 28710a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 28720a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0; 28730a708f8fSGustavo F. Padovan 28740a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 28750a708f8fSGustavo F. Padovan (unsigned long) &rfc); 28760a708f8fSGustavo F. Padovan break; 28770a708f8fSGustavo F. Padovan 28780a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 28790a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM; 288047d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx; 28810a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 28820a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 2883c8f79162SAndrei Emeltchenko 2884c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 2885c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2886c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2887c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2888c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 28890a708f8fSGustavo F. Padovan 28906327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan); 28916327eb98SAndrei Emeltchenko 28926327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win, 28936327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 28940a708f8fSGustavo F. Padovan 28950a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 28960a708f8fSGustavo F. Padovan (unsigned long) &rfc); 28970a708f8fSGustavo F. Padovan 2898f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 2899f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 2900f89cef09SAndrei Emeltchenko 29018c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) 29020a708f8fSGustavo F. Padovan break; 29030a708f8fSGustavo F. Padovan 290447d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 2905c1360a1cSGustavo F. Padovan test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { 290647d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 290747d1ec61SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); 29080a708f8fSGustavo F. Padovan } 29096327eb98SAndrei Emeltchenko 29106327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 29116327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 29126327eb98SAndrei Emeltchenko chan->tx_win); 29130a708f8fSGustavo F. Padovan break; 29140a708f8fSGustavo F. Padovan 29150a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 2916273759e2SMat Martineau l2cap_txwin_setup(chan); 29170a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING; 29180a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 29190a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 29200a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 29210a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 2922c8f79162SAndrei Emeltchenko 2923c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 2924c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2925c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2926c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2927c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 29280a708f8fSGustavo F. Padovan 29290a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 29300a708f8fSGustavo F. Padovan (unsigned long) &rfc); 29310a708f8fSGustavo F. Padovan 2932f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 2933f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 2934f89cef09SAndrei Emeltchenko 29358c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) 29360a708f8fSGustavo F. Padovan break; 29370a708f8fSGustavo F. Padovan 293847d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 2939c1360a1cSGustavo F. Padovan test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { 294047d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 294147d1ec61SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); 29420a708f8fSGustavo F. Padovan } 29430a708f8fSGustavo F. Padovan break; 29440a708f8fSGustavo F. Padovan } 29450a708f8fSGustavo F. Padovan 2946fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 294759e54bd1SAndrei Emeltchenko req->flags = __constant_cpu_to_le16(0); 29480a708f8fSGustavo F. Padovan 29490a708f8fSGustavo F. Padovan return ptr - data; 29500a708f8fSGustavo F. Padovan } 29510a708f8fSGustavo F. Padovan 295273ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) 29530a708f8fSGustavo F. Padovan { 29540a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 29550a708f8fSGustavo F. Padovan void *ptr = rsp->data; 295673ffa904SGustavo F. Padovan void *req = chan->conf_req; 295773ffa904SGustavo F. Padovan int len = chan->conf_len; 29580a708f8fSGustavo F. Padovan int type, hint, olen; 29590a708f8fSGustavo F. Padovan unsigned long val; 29600a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 296142dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs; 296242dceae2SAndrei Emeltchenko u8 remote_efs = 0; 29630a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU; 29640a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS; 2965c8f79162SAndrei Emeltchenko u16 size; 29660a708f8fSGustavo F. Padovan 296773ffa904SGustavo F. Padovan BT_DBG("chan %p", chan); 29680a708f8fSGustavo F. Padovan 29690a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 29700a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val); 29710a708f8fSGustavo F. Padovan 29720a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT; 29730a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK; 29740a708f8fSGustavo F. Padovan 29750a708f8fSGustavo F. Padovan switch (type) { 29760a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 29770a708f8fSGustavo F. Padovan mtu = val; 29780a708f8fSGustavo F. Padovan break; 29790a708f8fSGustavo F. Padovan 29800a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 29810c1bc5c6SGustavo F. Padovan chan->flush_to = val; 29820a708f8fSGustavo F. Padovan break; 29830a708f8fSGustavo F. Padovan 29840a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS: 29850a708f8fSGustavo F. Padovan break; 29860a708f8fSGustavo F. Padovan 29870a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 29880a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 29890a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen); 29900a708f8fSGustavo F. Padovan break; 29910a708f8fSGustavo F. Padovan 29920a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS: 29930a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE) 2994c1360a1cSGustavo F. Padovan set_bit(CONF_NO_FCS_RECV, &chan->conf_state); 299542dceae2SAndrei Emeltchenko break; 29960a708f8fSGustavo F. Padovan 299742dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS: 299842dceae2SAndrei Emeltchenko remote_efs = 1; 299942dceae2SAndrei Emeltchenko if (olen == sizeof(efs)) 300042dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen); 30010a708f8fSGustavo F. Padovan break; 30020a708f8fSGustavo F. Padovan 30036327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 30046327eb98SAndrei Emeltchenko if (!enable_hs) 30056327eb98SAndrei Emeltchenko return -ECONNREFUSED; 30066327eb98SAndrei Emeltchenko 30076327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 30086327eb98SAndrei Emeltchenko set_bit(CONF_EWS_RECV, &chan->conf_state); 3009836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 30106327eb98SAndrei Emeltchenko chan->remote_tx_win = val; 30110a708f8fSGustavo F. Padovan break; 30120a708f8fSGustavo F. Padovan 30130a708f8fSGustavo F. Padovan default: 30140a708f8fSGustavo F. Padovan if (hint) 30150a708f8fSGustavo F. Padovan break; 30160a708f8fSGustavo F. Padovan 30170a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN; 30180a708f8fSGustavo F. Padovan *((u8 *) ptr++) = type; 30190a708f8fSGustavo F. Padovan break; 30200a708f8fSGustavo F. Padovan } 30210a708f8fSGustavo F. Padovan } 30220a708f8fSGustavo F. Padovan 302373ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1) 30240a708f8fSGustavo F. Padovan goto done; 30250a708f8fSGustavo F. Padovan 30260c1bc5c6SGustavo F. Padovan switch (chan->mode) { 30270a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 30280a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3029c1360a1cSGustavo F. Padovan if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { 30300c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, 30318c1d787bSGustavo F. Padovan chan->conn->feat_mask); 30320a708f8fSGustavo F. Padovan break; 30330a708f8fSGustavo F. Padovan } 30340a708f8fSGustavo F. Padovan 303542dceae2SAndrei Emeltchenko if (remote_efs) { 303642dceae2SAndrei Emeltchenko if (__l2cap_efs_supported(chan)) 303742dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 303842dceae2SAndrei Emeltchenko else 303942dceae2SAndrei Emeltchenko return -ECONNREFUSED; 304042dceae2SAndrei Emeltchenko } 304142dceae2SAndrei Emeltchenko 30420c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) 30430a708f8fSGustavo F. Padovan return -ECONNREFUSED; 30440a708f8fSGustavo F. Padovan 30450a708f8fSGustavo F. Padovan break; 30460a708f8fSGustavo F. Padovan } 30470a708f8fSGustavo F. Padovan 30480a708f8fSGustavo F. Padovan done: 30490c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) { 30500a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 30510c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 30520a708f8fSGustavo F. Padovan 305373ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1) 30540a708f8fSGustavo F. Padovan return -ECONNREFUSED; 30550a708f8fSGustavo F. Padovan 30560a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 30570a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 30580a708f8fSGustavo F. Padovan } 30590a708f8fSGustavo F. Padovan 30600a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) { 30610a708f8fSGustavo F. Padovan /* Configure output options and let the other side know 30620a708f8fSGustavo F. Padovan * which ones we don't like. */ 30630a708f8fSGustavo F. Padovan 30640a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU) 30650a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 30660a708f8fSGustavo F. Padovan else { 30670c1bc5c6SGustavo F. Padovan chan->omtu = mtu; 3068c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state); 30690a708f8fSGustavo F. Padovan } 30700c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); 30710a708f8fSGustavo F. Padovan 307242dceae2SAndrei Emeltchenko if (remote_efs) { 307342dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 307442dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 307542dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) { 307642dceae2SAndrei Emeltchenko 307742dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT; 307842dceae2SAndrei Emeltchenko 307942dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1) 308042dceae2SAndrei Emeltchenko return -ECONNREFUSED; 308142dceae2SAndrei Emeltchenko 308242dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 308342dceae2SAndrei Emeltchenko sizeof(efs), 308442dceae2SAndrei Emeltchenko (unsigned long) &efs); 30850e8b207eSAndrei Emeltchenko } else { 30863e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */ 30870e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING; 30880e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 308942dceae2SAndrei Emeltchenko } 309042dceae2SAndrei Emeltchenko } 309142dceae2SAndrei Emeltchenko 30920a708f8fSGustavo F. Padovan switch (rfc.mode) { 30930a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 309447d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3095c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 30960a708f8fSGustavo F. Padovan break; 30970a708f8fSGustavo F. Padovan 30980a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 30996327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state)) 31002c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size; 31016327eb98SAndrei Emeltchenko else 31026327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; 31036327eb98SAndrei Emeltchenko 31042c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit; 31050a708f8fSGustavo F. Padovan 3106c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 3107c8f79162SAndrei Emeltchenko chan->conn->mtu - 3108c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 3109c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 3110c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3111c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3112c8f79162SAndrei Emeltchenko chan->remote_mps = size; 31130a708f8fSGustavo F. Padovan 31140a708f8fSGustavo F. Padovan rfc.retrans_timeout = 31154fd21a88SAndrei Emeltchenko __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 31160a708f8fSGustavo F. Padovan rfc.monitor_timeout = 31174fd21a88SAndrei Emeltchenko __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 31180a708f8fSGustavo F. Padovan 3119c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 31200a708f8fSGustavo F. Padovan 31210a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 31220a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 31230a708f8fSGustavo F. Padovan 312442dceae2SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 312542dceae2SAndrei Emeltchenko chan->remote_id = efs.id; 312642dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype; 312742dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu); 312842dceae2SAndrei Emeltchenko chan->remote_flush_to = 312942dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to); 313042dceae2SAndrei Emeltchenko chan->remote_acc_lat = 313142dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat); 313242dceae2SAndrei Emeltchenko chan->remote_sdu_itime = 313342dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 313442dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 313542dceae2SAndrei Emeltchenko sizeof(efs), (unsigned long) &efs); 313642dceae2SAndrei Emeltchenko } 31370a708f8fSGustavo F. Padovan break; 31380a708f8fSGustavo F. Padovan 31390a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3140c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 3141c8f79162SAndrei Emeltchenko chan->conn->mtu - 3142c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 3143c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 3144c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3145c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3146c8f79162SAndrei Emeltchenko chan->remote_mps = size; 31470a708f8fSGustavo F. Padovan 3148c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 31490a708f8fSGustavo F. Padovan 31500a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 31510a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 31520a708f8fSGustavo F. Padovan 31530a708f8fSGustavo F. Padovan break; 31540a708f8fSGustavo F. Padovan 31550a708f8fSGustavo F. Padovan default: 31560a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 31570a708f8fSGustavo F. Padovan 31580a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc)); 31590c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 31600a708f8fSGustavo F. Padovan } 31610a708f8fSGustavo F. Padovan 31620a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) 3163c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 31640a708f8fSGustavo F. Padovan } 3165fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 31660a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 316759e54bd1SAndrei Emeltchenko rsp->flags = __constant_cpu_to_le16(0); 31680a708f8fSGustavo F. Padovan 31690a708f8fSGustavo F. Padovan return ptr - data; 31700a708f8fSGustavo F. Padovan } 31710a708f8fSGustavo F. Padovan 3172b4450035SGustavo F. Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result) 31730a708f8fSGustavo F. Padovan { 31740a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 31750a708f8fSGustavo F. Padovan void *ptr = req->data; 31760a708f8fSGustavo F. Padovan int type, olen; 31770a708f8fSGustavo F. Padovan unsigned long val; 317836e999a8SMat Martineau struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 317966af7aafSAndrei Emeltchenko struct l2cap_conf_efs efs; 31800a708f8fSGustavo F. Padovan 3181fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); 31820a708f8fSGustavo F. Padovan 31830a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 31840a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 31850a708f8fSGustavo F. Padovan 31860a708f8fSGustavo F. Padovan switch (type) { 31870a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 31880a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) { 31890a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT; 31900c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU; 31910a708f8fSGustavo F. Padovan } else 31920c1bc5c6SGustavo F. Padovan chan->imtu = val; 31930c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 31940a708f8fSGustavo F. Padovan break; 31950a708f8fSGustavo F. Padovan 31960a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 31970c1bc5c6SGustavo F. Padovan chan->flush_to = val; 31980a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 31990c1bc5c6SGustavo F. Padovan 2, chan->flush_to); 32000a708f8fSGustavo F. Padovan break; 32010a708f8fSGustavo F. Padovan 32020a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 32030a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 32040a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 32050a708f8fSGustavo F. Padovan 3206c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && 32070c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode) 32080a708f8fSGustavo F. Padovan return -ECONNREFUSED; 32090a708f8fSGustavo F. Padovan 321047d1ec61SGustavo F. Padovan chan->fcs = 0; 32110a708f8fSGustavo F. Padovan 32120a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 32130a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 32140a708f8fSGustavo F. Padovan break; 32156327eb98SAndrei Emeltchenko 32166327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 32176327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, val, 32186327eb98SAndrei Emeltchenko L2CAP_DEFAULT_EXT_WINDOW); 32193e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 32203e6b3b95SGustavo F. Padovan chan->tx_win); 32216327eb98SAndrei Emeltchenko break; 322266af7aafSAndrei Emeltchenko 322366af7aafSAndrei Emeltchenko case L2CAP_CONF_EFS: 322466af7aafSAndrei Emeltchenko if (olen == sizeof(efs)) 322566af7aafSAndrei Emeltchenko memcpy(&efs, (void *)val, olen); 322666af7aafSAndrei Emeltchenko 322766af7aafSAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 322866af7aafSAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 322966af7aafSAndrei Emeltchenko efs.stype != chan->local_stype) 323066af7aafSAndrei Emeltchenko return -ECONNREFUSED; 323166af7aafSAndrei Emeltchenko 323266af7aafSAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 323366af7aafSAndrei Emeltchenko sizeof(efs), (unsigned long) &efs); 323466af7aafSAndrei Emeltchenko break; 32350a708f8fSGustavo F. Padovan } 32360a708f8fSGustavo F. Padovan } 32370a708f8fSGustavo F. Padovan 32380c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) 32390a708f8fSGustavo F. Padovan return -ECONNREFUSED; 32400a708f8fSGustavo F. Padovan 32410c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode; 32420a708f8fSGustavo F. Padovan 32430e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) { 32440a708f8fSGustavo F. Padovan switch (rfc.mode) { 32450a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 324647d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 324747d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 324847d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 324966af7aafSAndrei Emeltchenko 325066af7aafSAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 325166af7aafSAndrei Emeltchenko chan->local_msdu = le16_to_cpu(efs.msdu); 325266af7aafSAndrei Emeltchenko chan->local_sdu_itime = 325366af7aafSAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 325466af7aafSAndrei Emeltchenko chan->local_acc_lat = le32_to_cpu(efs.acc_lat); 325566af7aafSAndrei Emeltchenko chan->local_flush_to = 325666af7aafSAndrei Emeltchenko le32_to_cpu(efs.flush_to); 325766af7aafSAndrei Emeltchenko } 32580a708f8fSGustavo F. Padovan break; 325966af7aafSAndrei Emeltchenko 32600a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 326147d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 32620a708f8fSGustavo F. Padovan } 32630a708f8fSGustavo F. Padovan } 32640a708f8fSGustavo F. Padovan 3265fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 326659e54bd1SAndrei Emeltchenko req->flags = __constant_cpu_to_le16(0); 32670a708f8fSGustavo F. Padovan 32680a708f8fSGustavo F. Padovan return ptr - data; 32690a708f8fSGustavo F. Padovan } 32700a708f8fSGustavo F. Padovan 3271fe4128e0SGustavo F. Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags) 32720a708f8fSGustavo F. Padovan { 32730a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 32740a708f8fSGustavo F. Padovan void *ptr = rsp->data; 32750a708f8fSGustavo F. Padovan 3276fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan); 32770a708f8fSGustavo F. Padovan 3278fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 32790a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 32800a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags); 32810a708f8fSGustavo F. Padovan 32820a708f8fSGustavo F. Padovan return ptr - data; 32830a708f8fSGustavo F. Padovan } 32840a708f8fSGustavo F. Padovan 32858c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) 3286710f9b0aSGustavo F. Padovan { 3287710f9b0aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 32888c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 3289710f9b0aSGustavo F. Padovan u8 buf[128]; 3290710f9b0aSGustavo F. Padovan 3291fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 3292fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3293710f9b0aSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 3294710f9b0aSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 3295710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, 3296710f9b0aSGustavo F. Padovan L2CAP_CONN_RSP, sizeof(rsp), &rsp); 3297710f9b0aSGustavo F. Padovan 3298c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 3299710f9b0aSGustavo F. Padovan return; 3300710f9b0aSGustavo F. Padovan 3301710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 3302710f9b0aSGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 3303710f9b0aSGustavo F. Padovan chan->num_conf_req++; 3304710f9b0aSGustavo F. Padovan } 3305710f9b0aSGustavo F. Padovan 330647d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) 33070a708f8fSGustavo F. Padovan { 33080a708f8fSGustavo F. Padovan int type, olen; 33090a708f8fSGustavo F. Padovan unsigned long val; 33100a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc; 33110a708f8fSGustavo F. Padovan 331247d1ec61SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); 33130a708f8fSGustavo F. Padovan 33140c1bc5c6SGustavo F. Padovan if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) 33150a708f8fSGustavo F. Padovan return; 33160a708f8fSGustavo F. Padovan 33170a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 33180a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 33190a708f8fSGustavo F. Padovan 33200a708f8fSGustavo F. Padovan switch (type) { 33210a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 33220a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 33230a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 33240a708f8fSGustavo F. Padovan goto done; 33250a708f8fSGustavo F. Padovan } 33260a708f8fSGustavo F. Padovan } 33270a708f8fSGustavo F. Padovan 332836e999a8SMat Martineau /* Use sane default values in case a misbehaving remote device 332936e999a8SMat Martineau * did not send an RFC option. 333036e999a8SMat Martineau */ 333136e999a8SMat Martineau rfc.mode = chan->mode; 333236e999a8SMat Martineau rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 333336e999a8SMat Martineau rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 333436e999a8SMat Martineau rfc.max_pdu_size = cpu_to_le16(chan->imtu); 333536e999a8SMat Martineau 333636e999a8SMat Martineau BT_ERR("Expected RFC option was not found, using defaults"); 333736e999a8SMat Martineau 33380a708f8fSGustavo F. Padovan done: 33390a708f8fSGustavo F. Padovan switch (rfc.mode) { 33400a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 334147d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 334247d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 334347d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 33440a708f8fSGustavo F. Padovan break; 33450a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 334647d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 33470a708f8fSGustavo F. Padovan } 33480a708f8fSGustavo F. Padovan } 33490a708f8fSGustavo F. Padovan 33500a708f8fSGustavo F. Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 33510a708f8fSGustavo F. Padovan { 3352e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 33530a708f8fSGustavo F. Padovan 3354e2fd318eSIlia Kolomisnky if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) 33550a708f8fSGustavo F. Padovan return 0; 33560a708f8fSGustavo F. Padovan 33570a708f8fSGustavo F. Padovan if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && 33580a708f8fSGustavo F. Padovan cmd->ident == conn->info_ident) { 335917cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 33600a708f8fSGustavo F. Padovan 33610a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 33620a708f8fSGustavo F. Padovan conn->info_ident = 0; 33630a708f8fSGustavo F. Padovan 33640a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 33650a708f8fSGustavo F. Padovan } 33660a708f8fSGustavo F. Padovan 33670a708f8fSGustavo F. Padovan return 0; 33680a708f8fSGustavo F. Padovan } 33690a708f8fSGustavo F. Padovan 33700a708f8fSGustavo F. Padovan static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 33710a708f8fSGustavo F. Padovan { 33720a708f8fSGustavo F. Padovan struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 33730a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 337423691d75SGustavo F. Padovan struct l2cap_chan *chan = NULL, *pchan; 33750a708f8fSGustavo F. Padovan struct sock *parent, *sk = NULL; 33760a708f8fSGustavo F. Padovan int result, status = L2CAP_CS_NO_INFO; 33770a708f8fSGustavo F. Padovan 33780a708f8fSGustavo F. Padovan u16 dcid = 0, scid = __le16_to_cpu(req->scid); 33790a708f8fSGustavo F. Padovan __le16 psm = req->psm; 33800a708f8fSGustavo F. Padovan 3381097db76cSAndrei Emeltchenko BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); 33820a708f8fSGustavo F. Padovan 33830a708f8fSGustavo F. Padovan /* Check if we have socket listening on psm */ 3384c2287681SIdo Yariv pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst); 338523691d75SGustavo F. Padovan if (!pchan) { 33860a708f8fSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 33870a708f8fSGustavo F. Padovan goto sendresp; 33880a708f8fSGustavo F. Padovan } 33890a708f8fSGustavo F. Padovan 339023691d75SGustavo F. Padovan parent = pchan->sk; 339123691d75SGustavo F. Padovan 33923df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 3393aa2ac881SGustavo F. Padovan lock_sock(parent); 33940a708f8fSGustavo F. Padovan 33950a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */ 3396*2983fd68SAndrei Emeltchenko if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) && 33970a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) { 33989f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_AUTH_FAILURE; 33990a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 34000a708f8fSGustavo F. Padovan goto response; 34010a708f8fSGustavo F. Padovan } 34020a708f8fSGustavo F. Padovan 34030a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM; 34040a708f8fSGustavo F. Padovan 34050a708f8fSGustavo F. Padovan /* Check for backlog size */ 34060a708f8fSGustavo F. Padovan if (sk_acceptq_is_full(parent)) { 34070a708f8fSGustavo F. Padovan BT_DBG("backlog full %d", parent->sk_ack_backlog); 34080a708f8fSGustavo F. Padovan goto response; 34090a708f8fSGustavo F. Padovan } 34100a708f8fSGustavo F. Padovan 341180808e43SGustavo F. Padovan chan = pchan->ops->new_connection(pchan->data); 341280808e43SGustavo F. Padovan if (!chan) 34130a708f8fSGustavo F. Padovan goto response; 34140a708f8fSGustavo F. Padovan 341580808e43SGustavo F. Padovan sk = chan->sk; 341680808e43SGustavo F. Padovan 34170a708f8fSGustavo F. Padovan /* Check if we already have channel with that dcid */ 3418baa7e1faSGustavo F. Padovan if (__l2cap_get_chan_by_dcid(conn, scid)) { 34190a708f8fSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 3420ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 34210a708f8fSGustavo F. Padovan goto response; 34220a708f8fSGustavo F. Padovan } 34230a708f8fSGustavo F. Padovan 34240a708f8fSGustavo F. Padovan hci_conn_hold(conn->hcon); 34250a708f8fSGustavo F. Padovan 34260a708f8fSGustavo F. Padovan bacpy(&bt_sk(sk)->src, conn->src); 34270a708f8fSGustavo F. Padovan bacpy(&bt_sk(sk)->dst, conn->dst); 3428fe4128e0SGustavo F. Padovan chan->psm = psm; 3429fe4128e0SGustavo F. Padovan chan->dcid = scid; 34300a708f8fSGustavo F. Padovan 3431d1010240SGustavo F. Padovan bt_accept_enqueue(parent, sk); 3432d1010240SGustavo F. Padovan 34336be36555SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 343448454079SGustavo F. Padovan 3435fe4128e0SGustavo F. Padovan dcid = chan->scid; 34360a708f8fSGustavo F. Padovan 3437c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 34380a708f8fSGustavo F. Padovan 3439fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident; 34400a708f8fSGustavo F. Padovan 34410a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { 3442d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 3443c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) { 34440e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 34450a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 34460a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND; 34470a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 34480a708f8fSGustavo F. Padovan } else { 34490e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 34500a708f8fSGustavo F. Padovan result = L2CAP_CR_SUCCESS; 34510a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 34520a708f8fSGustavo F. Padovan } 34530a708f8fSGustavo F. Padovan } else { 34540e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 34550a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 34560a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND; 34570a708f8fSGustavo F. Padovan } 34580a708f8fSGustavo F. Padovan } else { 34590e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 34600a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 34610a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 34620a708f8fSGustavo F. Padovan } 34630a708f8fSGustavo F. Padovan 34640a708f8fSGustavo F. Padovan response: 3465aa2ac881SGustavo F. Padovan release_sock(parent); 34663df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 34670a708f8fSGustavo F. Padovan 34680a708f8fSGustavo F. Padovan sendresp: 34690a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid); 34700a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid); 34710a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result); 34720a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status); 34730a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); 34740a708f8fSGustavo F. Padovan 34750a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { 34760a708f8fSGustavo F. Padovan struct l2cap_info_req info; 34770a708f8fSGustavo F. Padovan info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 34780a708f8fSGustavo F. Padovan 34790a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 34800a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 34810a708f8fSGustavo F. Padovan 3482ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 34830a708f8fSGustavo F. Padovan 34840a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 34850a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(info), &info); 34860a708f8fSGustavo F. Padovan } 34870a708f8fSGustavo F. Padovan 3488c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && 34890a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) { 34900a708f8fSGustavo F. Padovan u8 buf[128]; 3491c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 34920a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 349373ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 349473ffa904SGustavo F. Padovan chan->num_conf_req++; 34950a708f8fSGustavo F. Padovan } 34960a708f8fSGustavo F. Padovan 34970a708f8fSGustavo F. Padovan return 0; 34980a708f8fSGustavo F. Padovan } 34990a708f8fSGustavo F. Padovan 35000a708f8fSGustavo F. Padovan static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 35010a708f8fSGustavo F. Padovan { 35020a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; 35030a708f8fSGustavo F. Padovan u16 scid, dcid, result, status; 350448454079SGustavo F. Padovan struct l2cap_chan *chan; 35050a708f8fSGustavo F. Padovan u8 req[128]; 35063df91ea2SAndrei Emeltchenko int err; 35070a708f8fSGustavo F. Padovan 35080a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 35090a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 35100a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 35110a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status); 35120a708f8fSGustavo F. Padovan 35131b009c98SAndrei Emeltchenko BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", 35141b009c98SAndrei Emeltchenko dcid, scid, result, status); 35150a708f8fSGustavo F. Padovan 35163df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 35173df91ea2SAndrei Emeltchenko 35180a708f8fSGustavo F. Padovan if (scid) { 35193df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 35203df91ea2SAndrei Emeltchenko if (!chan) { 35213df91ea2SAndrei Emeltchenko err = -EFAULT; 35223df91ea2SAndrei Emeltchenko goto unlock; 35233df91ea2SAndrei Emeltchenko } 35240a708f8fSGustavo F. Padovan } else { 35253df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 35263df91ea2SAndrei Emeltchenko if (!chan) { 35273df91ea2SAndrei Emeltchenko err = -EFAULT; 35283df91ea2SAndrei Emeltchenko goto unlock; 35293df91ea2SAndrei Emeltchenko } 35300a708f8fSGustavo F. Padovan } 35310a708f8fSGustavo F. Padovan 35323df91ea2SAndrei Emeltchenko err = 0; 35333df91ea2SAndrei Emeltchenko 35346be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 353548454079SGustavo F. Padovan 35360a708f8fSGustavo F. Padovan switch (result) { 35370a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS: 353889bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 3539fc7f8a7eSGustavo F. Padovan chan->ident = 0; 3540fe4128e0SGustavo F. Padovan chan->dcid = dcid; 3541c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state); 35420a708f8fSGustavo F. Padovan 3543c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 35440a708f8fSGustavo F. Padovan break; 35450a708f8fSGustavo F. Padovan 35460a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 354773ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, req), req); 354873ffa904SGustavo F. Padovan chan->num_conf_req++; 35490a708f8fSGustavo F. Padovan break; 35500a708f8fSGustavo F. Padovan 35510a708f8fSGustavo F. Padovan case L2CAP_CR_PEND: 3552c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 35530a708f8fSGustavo F. Padovan break; 35540a708f8fSGustavo F. Padovan 35550a708f8fSGustavo F. Padovan default: 355648454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED); 35570a708f8fSGustavo F. Padovan break; 35580a708f8fSGustavo F. Padovan } 35590a708f8fSGustavo F. Padovan 35606be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 35613df91ea2SAndrei Emeltchenko 35623df91ea2SAndrei Emeltchenko unlock: 35633df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 35643df91ea2SAndrei Emeltchenko 35653df91ea2SAndrei Emeltchenko return err; 35660a708f8fSGustavo F. Padovan } 35670a708f8fSGustavo F. Padovan 356847d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan) 35690a708f8fSGustavo F. Padovan { 35700a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both 35710a708f8fSGustavo F. Padovan * sides request it. 35720a708f8fSGustavo F. Padovan */ 35730c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) 357447d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3575c1360a1cSGustavo F. Padovan else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) 357647d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16; 35770a708f8fSGustavo F. Padovan } 35780a708f8fSGustavo F. Padovan 35790a708f8fSGustavo F. Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 35800a708f8fSGustavo F. Padovan { 35810a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; 35820a708f8fSGustavo F. Padovan u16 dcid, flags; 35830a708f8fSGustavo F. Padovan u8 rsp[64]; 358448454079SGustavo F. Padovan struct l2cap_chan *chan; 35853c588192SMat Martineau int len, err = 0; 35860a708f8fSGustavo F. Padovan 35870a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 35880a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags); 35890a708f8fSGustavo F. Padovan 35900a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); 35910a708f8fSGustavo F. Padovan 3592baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid); 359348454079SGustavo F. Padovan if (!chan) 35940a708f8fSGustavo F. Padovan return -ENOENT; 35950a708f8fSGustavo F. Padovan 3596033b1142SDavid S. Miller if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { 3597e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_cid rej; 35980a708f8fSGustavo F. Padovan 3599e2fd318eSIlia Kolomisnky rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID); 3600e2fd318eSIlia Kolomisnky rej.scid = cpu_to_le16(chan->scid); 3601e2fd318eSIlia Kolomisnky rej.dcid = cpu_to_le16(chan->dcid); 3602e2fd318eSIlia Kolomisnky 36030a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 36040a708f8fSGustavo F. Padovan sizeof(rej), &rej); 36050a708f8fSGustavo F. Padovan goto unlock; 36060a708f8fSGustavo F. Padovan } 36070a708f8fSGustavo F. Padovan 36080a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */ 36090a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req); 36107ac28817SDan Rosenberg if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) { 36110a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 3612fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 36130a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp); 36140a708f8fSGustavo F. Padovan goto unlock; 36150a708f8fSGustavo F. Padovan } 36160a708f8fSGustavo F. Padovan 36170a708f8fSGustavo F. Padovan /* Store config. */ 361873ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len); 361973ffa904SGustavo F. Padovan chan->conf_len += len; 36200a708f8fSGustavo F. Padovan 362159e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) { 36220a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */ 36230a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 3624fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 36255325e5bbSAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), rsp); 36260a708f8fSGustavo F. Padovan goto unlock; 36270a708f8fSGustavo F. Padovan } 36280a708f8fSGustavo F. Padovan 36290a708f8fSGustavo F. Padovan /* Complete config. */ 363073ffa904SGustavo F. Padovan len = l2cap_parse_conf_req(chan, rsp); 36310a708f8fSGustavo F. Padovan if (len < 0) { 3632e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 36330a708f8fSGustavo F. Padovan goto unlock; 36340a708f8fSGustavo F. Padovan } 36350a708f8fSGustavo F. Padovan 36360a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); 363773ffa904SGustavo F. Padovan chan->num_conf_rsp++; 36380a708f8fSGustavo F. Padovan 36390a708f8fSGustavo F. Padovan /* Reset config buffer. */ 364073ffa904SGustavo F. Padovan chan->conf_len = 0; 36410a708f8fSGustavo F. Padovan 3642c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) 36430a708f8fSGustavo F. Padovan goto unlock; 36440a708f8fSGustavo F. Padovan 3645c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 364647d1ec61SGustavo F. Padovan set_default_fcs(chan); 36470a708f8fSGustavo F. Padovan 364889bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECTED); 36490a708f8fSGustavo F. Padovan 3650105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 3651105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 36523c588192SMat Martineau err = l2cap_ertm_init(chan); 36530a708f8fSGustavo F. Padovan 36543c588192SMat Martineau if (err < 0) 36553c588192SMat Martineau l2cap_send_disconn_req(chan->conn, chan, -err); 36563c588192SMat Martineau else 3657cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 36583c588192SMat Martineau 36590a708f8fSGustavo F. Padovan goto unlock; 36600a708f8fSGustavo F. Padovan } 36610a708f8fSGustavo F. Padovan 3662c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { 36630a708f8fSGustavo F. Padovan u8 buf[64]; 36640a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 366573ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 366673ffa904SGustavo F. Padovan chan->num_conf_req++; 36670a708f8fSGustavo F. Padovan } 36680a708f8fSGustavo F. Padovan 36690e8b207eSAndrei Emeltchenko /* Got Conf Rsp PENDING from remote side and asume we sent 36700e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */ 36710e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && 36720e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 36730e8b207eSAndrei Emeltchenko 36740e8b207eSAndrei Emeltchenko /* check compatibility */ 36750e8b207eSAndrei Emeltchenko 36760e8b207eSAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 36770e8b207eSAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 36780e8b207eSAndrei Emeltchenko 36790e8b207eSAndrei Emeltchenko l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 36800e8b207eSAndrei Emeltchenko l2cap_build_conf_rsp(chan, rsp, 36815325e5bbSAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), rsp); 36820e8b207eSAndrei Emeltchenko } 36830e8b207eSAndrei Emeltchenko 36840a708f8fSGustavo F. Padovan unlock: 36856be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 36863c588192SMat Martineau return err; 36870a708f8fSGustavo F. Padovan } 36880a708f8fSGustavo F. Padovan 36890a708f8fSGustavo F. Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 36900a708f8fSGustavo F. Padovan { 36910a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; 36920a708f8fSGustavo F. Padovan u16 scid, flags, result; 369348454079SGustavo F. Padovan struct l2cap_chan *chan; 369461386cbaSAndrei Emeltchenko int len = le16_to_cpu(cmd->len) - sizeof(*rsp); 36953c588192SMat Martineau int err = 0; 36960a708f8fSGustavo F. Padovan 36970a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 36980a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags); 36990a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 37000a708f8fSGustavo F. Padovan 370161386cbaSAndrei Emeltchenko BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags, 370261386cbaSAndrei Emeltchenko result, len); 37030a708f8fSGustavo F. Padovan 3704baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 370548454079SGustavo F. Padovan if (!chan) 37060a708f8fSGustavo F. Padovan return 0; 37070a708f8fSGustavo F. Padovan 37080a708f8fSGustavo F. Padovan switch (result) { 37090a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS: 371047d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len); 37110e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state); 37120a708f8fSGustavo F. Padovan break; 37130a708f8fSGustavo F. Padovan 37140e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING: 37150e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state); 37160e8b207eSAndrei Emeltchenko 37170e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 37180e8b207eSAndrei Emeltchenko char buf[64]; 37190e8b207eSAndrei Emeltchenko 37200e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len, 37210e8b207eSAndrei Emeltchenko buf, &result); 37220e8b207eSAndrei Emeltchenko if (len < 0) { 37230e8b207eSAndrei Emeltchenko l2cap_send_disconn_req(conn, chan, ECONNRESET); 37240e8b207eSAndrei Emeltchenko goto done; 37250e8b207eSAndrei Emeltchenko } 37260e8b207eSAndrei Emeltchenko 37270e8b207eSAndrei Emeltchenko /* check compatibility */ 37280e8b207eSAndrei Emeltchenko 37290e8b207eSAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 37300e8b207eSAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 37310e8b207eSAndrei Emeltchenko 37320e8b207eSAndrei Emeltchenko l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 37330e8b207eSAndrei Emeltchenko l2cap_build_conf_rsp(chan, buf, 37340e8b207eSAndrei Emeltchenko L2CAP_CONF_SUCCESS, 0x0000), buf); 37350e8b207eSAndrei Emeltchenko } 37360e8b207eSAndrei Emeltchenko goto done; 37370e8b207eSAndrei Emeltchenko 37380a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT: 373973ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { 37400a708f8fSGustavo F. Padovan char req[64]; 37410a708f8fSGustavo F. Padovan 37420a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { 3743e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 37440a708f8fSGustavo F. Padovan goto done; 37450a708f8fSGustavo F. Padovan } 37460a708f8fSGustavo F. Padovan 37470a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */ 37480a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS; 3749b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len, 3750b4450035SGustavo F. Padovan req, &result); 37510a708f8fSGustavo F. Padovan if (len < 0) { 3752e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 37530a708f8fSGustavo F. Padovan goto done; 37540a708f8fSGustavo F. Padovan } 37550a708f8fSGustavo F. Padovan 37560a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 37570a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req); 375873ffa904SGustavo F. Padovan chan->num_conf_req++; 37590a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS) 37600a708f8fSGustavo F. Padovan goto done; 37610a708f8fSGustavo F. Padovan break; 37620a708f8fSGustavo F. Padovan } 37630a708f8fSGustavo F. Padovan 37640a708f8fSGustavo F. Padovan default: 37656be36555SAndrei Emeltchenko l2cap_chan_set_err(chan, ECONNRESET); 37662e0052e4SAndrei Emeltchenko 3767ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); 3768e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 37690a708f8fSGustavo F. Padovan goto done; 37700a708f8fSGustavo F. Padovan } 37710a708f8fSGustavo F. Padovan 377259e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) 37730a708f8fSGustavo F. Padovan goto done; 37740a708f8fSGustavo F. Padovan 3775c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state); 37760a708f8fSGustavo F. Padovan 3777c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { 377847d1ec61SGustavo F. Padovan set_default_fcs(chan); 37790a708f8fSGustavo F. Padovan 378089bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECTED); 3781105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 3782105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 37833c588192SMat Martineau err = l2cap_ertm_init(chan); 37840a708f8fSGustavo F. Padovan 37853c588192SMat Martineau if (err < 0) 37863c588192SMat Martineau l2cap_send_disconn_req(chan->conn, chan, -err); 37873c588192SMat Martineau else 3788cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 37890a708f8fSGustavo F. Padovan } 37900a708f8fSGustavo F. Padovan 37910a708f8fSGustavo F. Padovan done: 37926be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 37933c588192SMat Martineau return err; 37940a708f8fSGustavo F. Padovan } 37950a708f8fSGustavo F. Padovan 37960a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 37970a708f8fSGustavo F. Padovan { 37980a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; 37990a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp; 38000a708f8fSGustavo F. Padovan u16 dcid, scid; 380148454079SGustavo F. Padovan struct l2cap_chan *chan; 38020a708f8fSGustavo F. Padovan struct sock *sk; 38030a708f8fSGustavo F. Padovan 38040a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid); 38050a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 38060a708f8fSGustavo F. Padovan 38070a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); 38080a708f8fSGustavo F. Padovan 38093df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 38103df91ea2SAndrei Emeltchenko 38113df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, dcid); 38123df91ea2SAndrei Emeltchenko if (!chan) { 38133df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 38140a708f8fSGustavo F. Padovan return 0; 38153df91ea2SAndrei Emeltchenko } 38160a708f8fSGustavo F. Padovan 38176be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 38186be36555SAndrei Emeltchenko 381948454079SGustavo F. Padovan sk = chan->sk; 382048454079SGustavo F. Padovan 3821fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3822fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 38230a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); 38240a708f8fSGustavo F. Padovan 38256be36555SAndrei Emeltchenko lock_sock(sk); 38260a708f8fSGustavo F. Padovan sk->sk_shutdown = SHUTDOWN_MASK; 38276be36555SAndrei Emeltchenko release_sock(sk); 38280a708f8fSGustavo F. Padovan 382961d6ef3eSMat Martineau l2cap_chan_hold(chan); 383048454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET); 38316be36555SAndrei Emeltchenko 38326be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 38330a708f8fSGustavo F. Padovan 3834ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 383561d6ef3eSMat Martineau l2cap_chan_put(chan); 38363df91ea2SAndrei Emeltchenko 38373df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 38383df91ea2SAndrei Emeltchenko 38390a708f8fSGustavo F. Padovan return 0; 38400a708f8fSGustavo F. Padovan } 38410a708f8fSGustavo F. Padovan 38420a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 38430a708f8fSGustavo F. Padovan { 38440a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; 38450a708f8fSGustavo F. Padovan u16 dcid, scid; 384648454079SGustavo F. Padovan struct l2cap_chan *chan; 38470a708f8fSGustavo F. Padovan 38480a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 38490a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 38500a708f8fSGustavo F. Padovan 38510a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); 38520a708f8fSGustavo F. Padovan 38533df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 38543df91ea2SAndrei Emeltchenko 38553df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 38563df91ea2SAndrei Emeltchenko if (!chan) { 38573df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 38580a708f8fSGustavo F. Padovan return 0; 38593df91ea2SAndrei Emeltchenko } 38600a708f8fSGustavo F. Padovan 38616be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 386248454079SGustavo F. Padovan 386361d6ef3eSMat Martineau l2cap_chan_hold(chan); 386448454079SGustavo F. Padovan l2cap_chan_del(chan, 0); 38656be36555SAndrei Emeltchenko 38666be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 38670a708f8fSGustavo F. Padovan 3868ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 386961d6ef3eSMat Martineau l2cap_chan_put(chan); 38703df91ea2SAndrei Emeltchenko 38713df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 38723df91ea2SAndrei Emeltchenko 38730a708f8fSGustavo F. Padovan return 0; 38740a708f8fSGustavo F. Padovan } 38750a708f8fSGustavo F. Padovan 38760a708f8fSGustavo F. Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 38770a708f8fSGustavo F. Padovan { 38780a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data; 38790a708f8fSGustavo F. Padovan u16 type; 38800a708f8fSGustavo F. Padovan 38810a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type); 38820a708f8fSGustavo F. Padovan 38830a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type); 38840a708f8fSGustavo F. Padovan 38850a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) { 38860a708f8fSGustavo F. Padovan u8 buf[8]; 38870a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask; 38880a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 38890a708f8fSGustavo F. Padovan rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 38900a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 38910a708f8fSGustavo F. Padovan if (!disable_ertm) 38920a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING 38930a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS; 3894a5fd6f30SAndrei Emeltchenko if (enable_hs) 38956327eb98SAndrei Emeltchenko feat_mask |= L2CAP_FEAT_EXT_FLOW 38966327eb98SAndrei Emeltchenko | L2CAP_FEAT_EXT_WINDOW; 3897a5fd6f30SAndrei Emeltchenko 38980a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data); 38990a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 39000a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(buf), buf); 39010a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) { 39020a708f8fSGustavo F. Padovan u8 buf[12]; 39030a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 390450a147cdSMat Martineau 390550a147cdSMat Martineau if (enable_hs) 390650a147cdSMat Martineau l2cap_fixed_chan[0] |= L2CAP_FC_A2MP; 390750a147cdSMat Martineau else 390850a147cdSMat Martineau l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP; 390950a147cdSMat Martineau 39100a708f8fSGustavo F. Padovan rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 39110a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 3912c6337ea6SAndrei Emeltchenko memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); 39130a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 39140a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(buf), buf); 39150a708f8fSGustavo F. Padovan } else { 39160a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp; 39170a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type); 39180a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP); 39190a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 39200a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(rsp), &rsp); 39210a708f8fSGustavo F. Padovan } 39220a708f8fSGustavo F. Padovan 39230a708f8fSGustavo F. Padovan return 0; 39240a708f8fSGustavo F. Padovan } 39250a708f8fSGustavo F. Padovan 39260a708f8fSGustavo F. Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 39270a708f8fSGustavo F. Padovan { 39280a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; 39290a708f8fSGustavo F. Padovan u16 type, result; 39300a708f8fSGustavo F. Padovan 39310a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type); 39320a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 39330a708f8fSGustavo F. Padovan 39340a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); 39350a708f8fSGustavo F. Padovan 3936e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */ 3937e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident || 3938e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 3939e90165beSAndrei Emeltchenko return 0; 3940e90165beSAndrei Emeltchenko 394117cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 39420a708f8fSGustavo F. Padovan 39430a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) { 39440a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 39450a708f8fSGustavo F. Padovan conn->info_ident = 0; 39460a708f8fSGustavo F. Padovan 39470a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 39480a708f8fSGustavo F. Padovan 39490a708f8fSGustavo F. Padovan return 0; 39500a708f8fSGustavo F. Padovan } 39510a708f8fSGustavo F. Padovan 3952978c93b9SAndrei Emeltchenko switch (type) { 3953978c93b9SAndrei Emeltchenko case L2CAP_IT_FEAT_MASK: 39540a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data); 39550a708f8fSGustavo F. Padovan 39560a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { 39570a708f8fSGustavo F. Padovan struct l2cap_info_req req; 39580a708f8fSGustavo F. Padovan req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 39590a708f8fSGustavo F. Padovan 39600a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 39610a708f8fSGustavo F. Padovan 39620a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 39630a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 39640a708f8fSGustavo F. Padovan } else { 39650a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 39660a708f8fSGustavo F. Padovan conn->info_ident = 0; 39670a708f8fSGustavo F. Padovan 39680a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 39690a708f8fSGustavo F. Padovan } 3970978c93b9SAndrei Emeltchenko break; 3971978c93b9SAndrei Emeltchenko 3972978c93b9SAndrei Emeltchenko case L2CAP_IT_FIXED_CHAN: 3973978c93b9SAndrei Emeltchenko conn->fixed_chan_mask = rsp->data[0]; 39740a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 39750a708f8fSGustavo F. Padovan conn->info_ident = 0; 39760a708f8fSGustavo F. Padovan 39770a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 3978978c93b9SAndrei Emeltchenko break; 39790a708f8fSGustavo F. Padovan } 39800a708f8fSGustavo F. Padovan 39810a708f8fSGustavo F. Padovan return 0; 39820a708f8fSGustavo F. Padovan } 39830a708f8fSGustavo F. Padovan 3984f94ff6ffSMat Martineau static inline int l2cap_create_channel_req(struct l2cap_conn *conn, 3985f94ff6ffSMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, 3986f94ff6ffSMat Martineau void *data) 3987f94ff6ffSMat Martineau { 3988f94ff6ffSMat Martineau struct l2cap_create_chan_req *req = data; 3989f94ff6ffSMat Martineau struct l2cap_create_chan_rsp rsp; 3990f94ff6ffSMat Martineau u16 psm, scid; 3991f94ff6ffSMat Martineau 3992f94ff6ffSMat Martineau if (cmd_len != sizeof(*req)) 3993f94ff6ffSMat Martineau return -EPROTO; 3994f94ff6ffSMat Martineau 3995f94ff6ffSMat Martineau if (!enable_hs) 3996f94ff6ffSMat Martineau return -EINVAL; 3997f94ff6ffSMat Martineau 3998f94ff6ffSMat Martineau psm = le16_to_cpu(req->psm); 3999f94ff6ffSMat Martineau scid = le16_to_cpu(req->scid); 4000f94ff6ffSMat Martineau 4001f94ff6ffSMat Martineau BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id); 4002f94ff6ffSMat Martineau 4003f94ff6ffSMat Martineau /* Placeholder: Always reject */ 4004f94ff6ffSMat Martineau rsp.dcid = 0; 4005f94ff6ffSMat Martineau rsp.scid = cpu_to_le16(scid); 40068ce0c498SAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM); 40078ce0c498SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 4008f94ff6ffSMat Martineau 4009f94ff6ffSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, 4010f94ff6ffSMat Martineau sizeof(rsp), &rsp); 4011f94ff6ffSMat Martineau 4012f94ff6ffSMat Martineau return 0; 4013f94ff6ffSMat Martineau } 4014f94ff6ffSMat Martineau 4015f94ff6ffSMat Martineau static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn, 4016f94ff6ffSMat Martineau struct l2cap_cmd_hdr *cmd, void *data) 4017f94ff6ffSMat Martineau { 4018f94ff6ffSMat Martineau BT_DBG("conn %p", conn); 4019f94ff6ffSMat Martineau 4020f94ff6ffSMat Martineau return l2cap_connect_rsp(conn, cmd, data); 4021f94ff6ffSMat Martineau } 4022f94ff6ffSMat Martineau 40238d5a04a1SMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident, 40248d5a04a1SMat Martineau u16 icid, u16 result) 40258d5a04a1SMat Martineau { 40268d5a04a1SMat Martineau struct l2cap_move_chan_rsp rsp; 40278d5a04a1SMat Martineau 40288d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 40298d5a04a1SMat Martineau 40308d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 40318d5a04a1SMat Martineau rsp.result = cpu_to_le16(result); 40328d5a04a1SMat Martineau 40338d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp); 40348d5a04a1SMat Martineau } 40358d5a04a1SMat Martineau 40368d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn, 40378d5a04a1SMat Martineau struct l2cap_chan *chan, u16 icid, u16 result) 40388d5a04a1SMat Martineau { 40398d5a04a1SMat Martineau struct l2cap_move_chan_cfm cfm; 40408d5a04a1SMat Martineau u8 ident; 40418d5a04a1SMat Martineau 40428d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 40438d5a04a1SMat Martineau 40448d5a04a1SMat Martineau ident = l2cap_get_ident(conn); 40458d5a04a1SMat Martineau if (chan) 40468d5a04a1SMat Martineau chan->ident = ident; 40478d5a04a1SMat Martineau 40488d5a04a1SMat Martineau cfm.icid = cpu_to_le16(icid); 40498d5a04a1SMat Martineau cfm.result = cpu_to_le16(result); 40508d5a04a1SMat Martineau 40518d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm); 40528d5a04a1SMat Martineau } 40538d5a04a1SMat Martineau 40548d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, 40558d5a04a1SMat Martineau u16 icid) 40568d5a04a1SMat Martineau { 40578d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp rsp; 40588d5a04a1SMat Martineau 40598d5a04a1SMat Martineau BT_DBG("icid %d", icid); 40608d5a04a1SMat Martineau 40618d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 40628d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp); 40638d5a04a1SMat Martineau } 40648d5a04a1SMat Martineau 40658d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn, 40668d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 40678d5a04a1SMat Martineau { 40688d5a04a1SMat Martineau struct l2cap_move_chan_req *req = data; 40698d5a04a1SMat Martineau u16 icid = 0; 40708d5a04a1SMat Martineau u16 result = L2CAP_MR_NOT_ALLOWED; 40718d5a04a1SMat Martineau 40728d5a04a1SMat Martineau if (cmd_len != sizeof(*req)) 40738d5a04a1SMat Martineau return -EPROTO; 40748d5a04a1SMat Martineau 40758d5a04a1SMat Martineau icid = le16_to_cpu(req->icid); 40768d5a04a1SMat Martineau 40778d5a04a1SMat Martineau BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id); 40788d5a04a1SMat Martineau 40798d5a04a1SMat Martineau if (!enable_hs) 40808d5a04a1SMat Martineau return -EINVAL; 40818d5a04a1SMat Martineau 40828d5a04a1SMat Martineau /* Placeholder: Always refuse */ 40838d5a04a1SMat Martineau l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result); 40848d5a04a1SMat Martineau 40858d5a04a1SMat Martineau return 0; 40868d5a04a1SMat Martineau } 40878d5a04a1SMat Martineau 40888d5a04a1SMat Martineau static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn, 40898d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 40908d5a04a1SMat Martineau { 40918d5a04a1SMat Martineau struct l2cap_move_chan_rsp *rsp = data; 40928d5a04a1SMat Martineau u16 icid, result; 40938d5a04a1SMat Martineau 40948d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 40958d5a04a1SMat Martineau return -EPROTO; 40968d5a04a1SMat Martineau 40978d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 40988d5a04a1SMat Martineau result = le16_to_cpu(rsp->result); 40998d5a04a1SMat Martineau 41008d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 41018d5a04a1SMat Martineau 41028d5a04a1SMat Martineau /* Placeholder: Always unconfirmed */ 41038d5a04a1SMat Martineau l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED); 41048d5a04a1SMat Martineau 41058d5a04a1SMat Martineau return 0; 41068d5a04a1SMat Martineau } 41078d5a04a1SMat Martineau 41088d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn, 41098d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 41108d5a04a1SMat Martineau { 41118d5a04a1SMat Martineau struct l2cap_move_chan_cfm *cfm = data; 41128d5a04a1SMat Martineau u16 icid, result; 41138d5a04a1SMat Martineau 41148d5a04a1SMat Martineau if (cmd_len != sizeof(*cfm)) 41158d5a04a1SMat Martineau return -EPROTO; 41168d5a04a1SMat Martineau 41178d5a04a1SMat Martineau icid = le16_to_cpu(cfm->icid); 41188d5a04a1SMat Martineau result = le16_to_cpu(cfm->result); 41198d5a04a1SMat Martineau 41208d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 41218d5a04a1SMat Martineau 41228d5a04a1SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 41238d5a04a1SMat Martineau 41248d5a04a1SMat Martineau return 0; 41258d5a04a1SMat Martineau } 41268d5a04a1SMat Martineau 41278d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, 41288d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 41298d5a04a1SMat Martineau { 41308d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp *rsp = data; 41318d5a04a1SMat Martineau u16 icid; 41328d5a04a1SMat Martineau 41338d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 41348d5a04a1SMat Martineau return -EPROTO; 41358d5a04a1SMat Martineau 41368d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 41378d5a04a1SMat Martineau 41388d5a04a1SMat Martineau BT_DBG("icid %d", icid); 41398d5a04a1SMat Martineau 41408d5a04a1SMat Martineau return 0; 41418d5a04a1SMat Martineau } 41428d5a04a1SMat Martineau 4143e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency, 4144de73115aSClaudio Takahasi u16 to_multiplier) 4145de73115aSClaudio Takahasi { 4146de73115aSClaudio Takahasi u16 max_latency; 4147de73115aSClaudio Takahasi 4148de73115aSClaudio Takahasi if (min > max || min < 6 || max > 3200) 4149de73115aSClaudio Takahasi return -EINVAL; 4150de73115aSClaudio Takahasi 4151de73115aSClaudio Takahasi if (to_multiplier < 10 || to_multiplier > 3200) 4152de73115aSClaudio Takahasi return -EINVAL; 4153de73115aSClaudio Takahasi 4154de73115aSClaudio Takahasi if (max >= to_multiplier * 8) 4155de73115aSClaudio Takahasi return -EINVAL; 4156de73115aSClaudio Takahasi 4157de73115aSClaudio Takahasi max_latency = (to_multiplier * 8 / max) - 1; 4158de73115aSClaudio Takahasi if (latency > 499 || latency > max_latency) 4159de73115aSClaudio Takahasi return -EINVAL; 4160de73115aSClaudio Takahasi 4161de73115aSClaudio Takahasi return 0; 4162de73115aSClaudio Takahasi } 4163de73115aSClaudio Takahasi 4164de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, 4165de73115aSClaudio Takahasi struct l2cap_cmd_hdr *cmd, u8 *data) 4166de73115aSClaudio Takahasi { 4167de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon; 4168de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req; 4169de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp; 4170de73115aSClaudio Takahasi u16 min, max, latency, to_multiplier, cmd_len; 41712ce603ebSClaudio Takahasi int err; 4172de73115aSClaudio Takahasi 4173de73115aSClaudio Takahasi if (!(hcon->link_mode & HCI_LM_MASTER)) 4174de73115aSClaudio Takahasi return -EINVAL; 4175de73115aSClaudio Takahasi 4176de73115aSClaudio Takahasi cmd_len = __le16_to_cpu(cmd->len); 4177de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) 4178de73115aSClaudio Takahasi return -EPROTO; 4179de73115aSClaudio Takahasi 4180de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data; 4181de73115aSClaudio Takahasi min = __le16_to_cpu(req->min); 4182de73115aSClaudio Takahasi max = __le16_to_cpu(req->max); 4183de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency); 4184de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier); 4185de73115aSClaudio Takahasi 4186de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", 4187de73115aSClaudio Takahasi min, max, latency, to_multiplier); 4188de73115aSClaudio Takahasi 4189de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp)); 41902ce603ebSClaudio Takahasi 41912ce603ebSClaudio Takahasi err = l2cap_check_conn_param(min, max, latency, to_multiplier); 41922ce603ebSClaudio Takahasi if (err) 4193de73115aSClaudio Takahasi rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); 4194de73115aSClaudio Takahasi else 4195de73115aSClaudio Takahasi rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); 4196de73115aSClaudio Takahasi 4197de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, 4198de73115aSClaudio Takahasi sizeof(rsp), &rsp); 4199de73115aSClaudio Takahasi 42002ce603ebSClaudio Takahasi if (!err) 42012ce603ebSClaudio Takahasi hci_le_conn_update(hcon, min, max, latency, to_multiplier); 42022ce603ebSClaudio Takahasi 4203de73115aSClaudio Takahasi return 0; 4204de73115aSClaudio Takahasi } 4205de73115aSClaudio Takahasi 42063300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, 42073300d9a9SClaudio Takahasi struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 42083300d9a9SClaudio Takahasi { 42093300d9a9SClaudio Takahasi int err = 0; 42103300d9a9SClaudio Takahasi 42113300d9a9SClaudio Takahasi switch (cmd->code) { 42123300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 42133300d9a9SClaudio Takahasi l2cap_command_rej(conn, cmd, data); 42143300d9a9SClaudio Takahasi break; 42153300d9a9SClaudio Takahasi 42163300d9a9SClaudio Takahasi case L2CAP_CONN_REQ: 42173300d9a9SClaudio Takahasi err = l2cap_connect_req(conn, cmd, data); 42183300d9a9SClaudio Takahasi break; 42193300d9a9SClaudio Takahasi 42203300d9a9SClaudio Takahasi case L2CAP_CONN_RSP: 42213300d9a9SClaudio Takahasi err = l2cap_connect_rsp(conn, cmd, data); 42223300d9a9SClaudio Takahasi break; 42233300d9a9SClaudio Takahasi 42243300d9a9SClaudio Takahasi case L2CAP_CONF_REQ: 42253300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data); 42263300d9a9SClaudio Takahasi break; 42273300d9a9SClaudio Takahasi 42283300d9a9SClaudio Takahasi case L2CAP_CONF_RSP: 42293300d9a9SClaudio Takahasi err = l2cap_config_rsp(conn, cmd, data); 42303300d9a9SClaudio Takahasi break; 42313300d9a9SClaudio Takahasi 42323300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ: 42333300d9a9SClaudio Takahasi err = l2cap_disconnect_req(conn, cmd, data); 42343300d9a9SClaudio Takahasi break; 42353300d9a9SClaudio Takahasi 42363300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP: 42373300d9a9SClaudio Takahasi err = l2cap_disconnect_rsp(conn, cmd, data); 42383300d9a9SClaudio Takahasi break; 42393300d9a9SClaudio Takahasi 42403300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ: 42413300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data); 42423300d9a9SClaudio Takahasi break; 42433300d9a9SClaudio Takahasi 42443300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP: 42453300d9a9SClaudio Takahasi break; 42463300d9a9SClaudio Takahasi 42473300d9a9SClaudio Takahasi case L2CAP_INFO_REQ: 42483300d9a9SClaudio Takahasi err = l2cap_information_req(conn, cmd, data); 42493300d9a9SClaudio Takahasi break; 42503300d9a9SClaudio Takahasi 42513300d9a9SClaudio Takahasi case L2CAP_INFO_RSP: 42523300d9a9SClaudio Takahasi err = l2cap_information_rsp(conn, cmd, data); 42533300d9a9SClaudio Takahasi break; 42543300d9a9SClaudio Takahasi 4255f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_REQ: 4256f94ff6ffSMat Martineau err = l2cap_create_channel_req(conn, cmd, cmd_len, data); 4257f94ff6ffSMat Martineau break; 4258f94ff6ffSMat Martineau 4259f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_RSP: 4260f94ff6ffSMat Martineau err = l2cap_create_channel_rsp(conn, cmd, data); 4261f94ff6ffSMat Martineau break; 4262f94ff6ffSMat Martineau 42638d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_REQ: 42648d5a04a1SMat Martineau err = l2cap_move_channel_req(conn, cmd, cmd_len, data); 42658d5a04a1SMat Martineau break; 42668d5a04a1SMat Martineau 42678d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_RSP: 42688d5a04a1SMat Martineau err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data); 42698d5a04a1SMat Martineau break; 42708d5a04a1SMat Martineau 42718d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM: 42728d5a04a1SMat Martineau err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data); 42738d5a04a1SMat Martineau break; 42748d5a04a1SMat Martineau 42758d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM_RSP: 42768d5a04a1SMat Martineau err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data); 42778d5a04a1SMat Martineau break; 42788d5a04a1SMat Martineau 42793300d9a9SClaudio Takahasi default: 42803300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code); 42813300d9a9SClaudio Takahasi err = -EINVAL; 42823300d9a9SClaudio Takahasi break; 42833300d9a9SClaudio Takahasi } 42843300d9a9SClaudio Takahasi 42853300d9a9SClaudio Takahasi return err; 42863300d9a9SClaudio Takahasi } 42873300d9a9SClaudio Takahasi 42883300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, 42893300d9a9SClaudio Takahasi struct l2cap_cmd_hdr *cmd, u8 *data) 42903300d9a9SClaudio Takahasi { 42913300d9a9SClaudio Takahasi switch (cmd->code) { 42923300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 42933300d9a9SClaudio Takahasi return 0; 42943300d9a9SClaudio Takahasi 42953300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ: 4296de73115aSClaudio Takahasi return l2cap_conn_param_update_req(conn, cmd, data); 42973300d9a9SClaudio Takahasi 42983300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP: 42993300d9a9SClaudio Takahasi return 0; 43003300d9a9SClaudio Takahasi 43013300d9a9SClaudio Takahasi default: 43023300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code); 43033300d9a9SClaudio Takahasi return -EINVAL; 43043300d9a9SClaudio Takahasi } 43053300d9a9SClaudio Takahasi } 43063300d9a9SClaudio Takahasi 43073300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn, 43083300d9a9SClaudio Takahasi struct sk_buff *skb) 43090a708f8fSGustavo F. Padovan { 43100a708f8fSGustavo F. Padovan u8 *data = skb->data; 43110a708f8fSGustavo F. Padovan int len = skb->len; 43120a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr cmd; 43133300d9a9SClaudio Takahasi int err; 43140a708f8fSGustavo F. Padovan 43150a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb); 43160a708f8fSGustavo F. Padovan 43170a708f8fSGustavo F. Padovan while (len >= L2CAP_CMD_HDR_SIZE) { 43180a708f8fSGustavo F. Padovan u16 cmd_len; 43190a708f8fSGustavo F. Padovan memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); 43200a708f8fSGustavo F. Padovan data += L2CAP_CMD_HDR_SIZE; 43210a708f8fSGustavo F. Padovan len -= L2CAP_CMD_HDR_SIZE; 43220a708f8fSGustavo F. Padovan 43230a708f8fSGustavo F. Padovan cmd_len = le16_to_cpu(cmd.len); 43240a708f8fSGustavo F. Padovan 43250a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident); 43260a708f8fSGustavo F. Padovan 43270a708f8fSGustavo F. Padovan if (cmd_len > len || !cmd.ident) { 43280a708f8fSGustavo F. Padovan BT_DBG("corrupted command"); 43290a708f8fSGustavo F. Padovan break; 43300a708f8fSGustavo F. Padovan } 43310a708f8fSGustavo F. Padovan 43323300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 43333300d9a9SClaudio Takahasi err = l2cap_le_sig_cmd(conn, &cmd, data); 43343300d9a9SClaudio Takahasi else 43353300d9a9SClaudio Takahasi err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data); 43360a708f8fSGustavo F. Padovan 43370a708f8fSGustavo F. Padovan if (err) { 4338e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk rej; 43392c6d1a2eSGustavo F. Padovan 43402c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err); 43410a708f8fSGustavo F. Padovan 43420a708f8fSGustavo F. Padovan /* FIXME: Map err to a valid reason */ 4343e2fd318eSIlia Kolomisnky rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 43440a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); 43450a708f8fSGustavo F. Padovan } 43460a708f8fSGustavo F. Padovan 43470a708f8fSGustavo F. Padovan data += cmd_len; 43480a708f8fSGustavo F. Padovan len -= cmd_len; 43490a708f8fSGustavo F. Padovan } 43500a708f8fSGustavo F. Padovan 43510a708f8fSGustavo F. Padovan kfree_skb(skb); 43520a708f8fSGustavo F. Padovan } 43530a708f8fSGustavo F. Padovan 435447d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) 43550a708f8fSGustavo F. Padovan { 43560a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs; 4357e4ca6d98SAndrei Emeltchenko int hdr_size; 4358e4ca6d98SAndrei Emeltchenko 4359e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 4360e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE; 4361e4ca6d98SAndrei Emeltchenko else 4362e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE; 43630a708f8fSGustavo F. Padovan 436447d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 436503a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE); 43660a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len); 43670a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); 43680a708f8fSGustavo F. Padovan 43690a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs) 43700a708f8fSGustavo F. Padovan return -EBADMSG; 43710a708f8fSGustavo F. Padovan } 43720a708f8fSGustavo F. Padovan return 0; 43730a708f8fSGustavo F. Padovan } 43740a708f8fSGustavo F. Padovan 43756ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) 43760a708f8fSGustavo F. Padovan { 4377e31f7633SMat Martineau struct l2cap_ctrl control; 43780a708f8fSGustavo F. Padovan 4379e31f7633SMat Martineau BT_DBG("chan %p", chan); 43800a708f8fSGustavo F. Padovan 4381e31f7633SMat Martineau memset(&control, 0, sizeof(control)); 4382e31f7633SMat Martineau control.sframe = 1; 4383e31f7633SMat Martineau control.final = 1; 4384e31f7633SMat Martineau control.reqseq = chan->buffer_seq; 4385e31f7633SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 43860a708f8fSGustavo F. Padovan 4387e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 4388e31f7633SMat Martineau control.super = L2CAP_SUPER_RNR; 4389e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 43900a708f8fSGustavo F. Padovan } 43910a708f8fSGustavo F. Padovan 4392e31f7633SMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 4393e31f7633SMat Martineau chan->unacked_frames > 0) 4394e31f7633SMat Martineau __set_retrans_timer(chan); 43950a708f8fSGustavo F. Padovan 4396e31f7633SMat Martineau /* Send pending iframes */ 4397525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 43980a708f8fSGustavo F. Padovan 4399e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 4400e31f7633SMat Martineau test_bit(CONN_SEND_FBIT, &chan->conn_state)) { 4401e31f7633SMat Martineau /* F-bit wasn't sent in an s-frame or i-frame yet, so 4402e31f7633SMat Martineau * send it now. 4403e31f7633SMat Martineau */ 4404e31f7633SMat Martineau control.super = L2CAP_SUPER_RR; 4405e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 44060a708f8fSGustavo F. Padovan } 44070a708f8fSGustavo F. Padovan } 44080a708f8fSGustavo F. Padovan 440984084a31SMat Martineau static void append_skb_frag(struct sk_buff *skb, 441084084a31SMat Martineau struct sk_buff *new_frag, struct sk_buff **last_frag) 44110a708f8fSGustavo F. Padovan { 441284084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments 441384084a31SMat Martineau * skb->data_len reflects only data in fragments 441484084a31SMat Martineau */ 441584084a31SMat Martineau if (!skb_has_frag_list(skb)) 441684084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag; 441784084a31SMat Martineau 441884084a31SMat Martineau new_frag->next = NULL; 441984084a31SMat Martineau 442084084a31SMat Martineau (*last_frag)->next = new_frag; 442184084a31SMat Martineau *last_frag = new_frag; 442284084a31SMat Martineau 442384084a31SMat Martineau skb->len += new_frag->len; 442484084a31SMat Martineau skb->data_len += new_frag->len; 442584084a31SMat Martineau skb->truesize += new_frag->truesize; 442684084a31SMat Martineau } 442784084a31SMat Martineau 44284b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, 44294b51dae9SMat Martineau struct l2cap_ctrl *control) 443084084a31SMat Martineau { 443184084a31SMat Martineau int err = -EINVAL; 44320a708f8fSGustavo F. Padovan 44334b51dae9SMat Martineau switch (control->sar) { 44347e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED: 443584084a31SMat Martineau if (chan->sdu) 443684084a31SMat Martineau break; 44370a708f8fSGustavo F. Padovan 443884084a31SMat Martineau err = chan->ops->recv(chan->data, skb); 443984084a31SMat Martineau break; 44400a708f8fSGustavo F. Padovan 44417e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START: 444284084a31SMat Martineau if (chan->sdu) 444384084a31SMat Martineau break; 44440a708f8fSGustavo F. Padovan 44456f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data); 444603a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE); 44470a708f8fSGustavo F. Padovan 444884084a31SMat Martineau if (chan->sdu_len > chan->imtu) { 444984084a31SMat Martineau err = -EMSGSIZE; 445084084a31SMat Martineau break; 445184084a31SMat Martineau } 44520a708f8fSGustavo F. Padovan 445384084a31SMat Martineau if (skb->len >= chan->sdu_len) 445484084a31SMat Martineau break; 445584084a31SMat Martineau 445684084a31SMat Martineau chan->sdu = skb; 445784084a31SMat Martineau chan->sdu_last_frag = skb; 445884084a31SMat Martineau 445984084a31SMat Martineau skb = NULL; 446084084a31SMat Martineau err = 0; 44610a708f8fSGustavo F. Padovan break; 44620a708f8fSGustavo F. Padovan 44637e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE: 44646f61fd47SGustavo F. Padovan if (!chan->sdu) 446584084a31SMat Martineau break; 44660a708f8fSGustavo F. Padovan 446784084a31SMat Martineau append_skb_frag(chan->sdu, skb, 446884084a31SMat Martineau &chan->sdu_last_frag); 446984084a31SMat Martineau skb = NULL; 44700a708f8fSGustavo F. Padovan 447184084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len) 447284084a31SMat Martineau break; 44730a708f8fSGustavo F. Padovan 447484084a31SMat Martineau err = 0; 44750a708f8fSGustavo F. Padovan break; 44760a708f8fSGustavo F. Padovan 44777e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END: 44786f61fd47SGustavo F. Padovan if (!chan->sdu) 447984084a31SMat Martineau break; 44800a708f8fSGustavo F. Padovan 448184084a31SMat Martineau append_skb_frag(chan->sdu, skb, 448284084a31SMat Martineau &chan->sdu_last_frag); 448384084a31SMat Martineau skb = NULL; 44840a708f8fSGustavo F. Padovan 448584084a31SMat Martineau if (chan->sdu->len != chan->sdu_len) 448684084a31SMat Martineau break; 44870a708f8fSGustavo F. Padovan 448884084a31SMat Martineau err = chan->ops->recv(chan->data, chan->sdu); 44890a708f8fSGustavo F. Padovan 449084084a31SMat Martineau if (!err) { 449184084a31SMat Martineau /* Reassembly complete */ 449284084a31SMat Martineau chan->sdu = NULL; 449384084a31SMat Martineau chan->sdu_last_frag = NULL; 449484084a31SMat Martineau chan->sdu_len = 0; 44950a708f8fSGustavo F. Padovan } 44960a708f8fSGustavo F. Padovan break; 44970a708f8fSGustavo F. Padovan } 44980a708f8fSGustavo F. Padovan 449984084a31SMat Martineau if (err) { 45000a708f8fSGustavo F. Padovan kfree_skb(skb); 45016f61fd47SGustavo F. Padovan kfree_skb(chan->sdu); 45026f61fd47SGustavo F. Padovan chan->sdu = NULL; 450384084a31SMat Martineau chan->sdu_last_frag = NULL; 450484084a31SMat Martineau chan->sdu_len = 0; 450584084a31SMat Martineau } 45060a708f8fSGustavo F. Padovan 450784084a31SMat Martineau return err; 45080a708f8fSGustavo F. Padovan } 45090a708f8fSGustavo F. Padovan 4510e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 45110a708f8fSGustavo F. Padovan { 451261aa4f5bSMat Martineau u8 event; 451361aa4f5bSMat Martineau 451461aa4f5bSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 451561aa4f5bSMat Martineau return; 451661aa4f5bSMat Martineau 451761aa4f5bSMat Martineau event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR; 4518401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, event); 45190a708f8fSGustavo F. Padovan } 45200a708f8fSGustavo F. Padovan 4521d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan) 4522d2a7ac5dSMat Martineau { 452363838725SMat Martineau int err = 0; 452463838725SMat Martineau /* Pass sequential frames to l2cap_reassemble_sdu() 452563838725SMat Martineau * until a gap is encountered. 452663838725SMat Martineau */ 452763838725SMat Martineau 452863838725SMat Martineau BT_DBG("chan %p", chan); 452963838725SMat Martineau 453063838725SMat Martineau while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 453163838725SMat Martineau struct sk_buff *skb; 453263838725SMat Martineau BT_DBG("Searching for skb with txseq %d (queue len %d)", 453363838725SMat Martineau chan->buffer_seq, skb_queue_len(&chan->srej_q)); 453463838725SMat Martineau 453563838725SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq); 453663838725SMat Martineau 453763838725SMat Martineau if (!skb) 453863838725SMat Martineau break; 453963838725SMat Martineau 454063838725SMat Martineau skb_unlink(skb, &chan->srej_q); 454163838725SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 454263838725SMat Martineau err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->control); 454363838725SMat Martineau if (err) 454463838725SMat Martineau break; 454563838725SMat Martineau } 454663838725SMat Martineau 454763838725SMat Martineau if (skb_queue_empty(&chan->srej_q)) { 454863838725SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 454963838725SMat Martineau l2cap_send_ack(chan); 455063838725SMat Martineau } 455163838725SMat Martineau 455263838725SMat Martineau return err; 4553d2a7ac5dSMat Martineau } 4554d2a7ac5dSMat Martineau 4555d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan, 4556d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 4557d2a7ac5dSMat Martineau { 4558f80842a8SMat Martineau struct sk_buff *skb; 4559f80842a8SMat Martineau 4560f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 4561f80842a8SMat Martineau 4562f80842a8SMat Martineau if (control->reqseq == chan->next_tx_seq) { 4563f80842a8SMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 4564f80842a8SMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 4565f80842a8SMat Martineau return; 4566f80842a8SMat Martineau } 4567f80842a8SMat Martineau 4568f80842a8SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 4569f80842a8SMat Martineau 4570f80842a8SMat Martineau if (skb == NULL) { 4571f80842a8SMat Martineau BT_DBG("Seq %d not available for retransmission", 4572f80842a8SMat Martineau control->reqseq); 4573f80842a8SMat Martineau return; 4574f80842a8SMat Martineau } 4575f80842a8SMat Martineau 4576f80842a8SMat Martineau if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) { 4577f80842a8SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 4578f80842a8SMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 4579f80842a8SMat Martineau return; 4580f80842a8SMat Martineau } 4581f80842a8SMat Martineau 4582f80842a8SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4583f80842a8SMat Martineau 4584f80842a8SMat Martineau if (control->poll) { 4585f80842a8SMat Martineau l2cap_pass_to_tx(chan, control); 4586f80842a8SMat Martineau 4587f80842a8SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 4588f80842a8SMat Martineau l2cap_retransmit(chan, control); 4589f80842a8SMat Martineau l2cap_ertm_send(chan); 4590f80842a8SMat Martineau 4591f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 4592f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 4593f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 4594f80842a8SMat Martineau } 4595f80842a8SMat Martineau } else { 4596f80842a8SMat Martineau l2cap_pass_to_tx_fbit(chan, control); 4597f80842a8SMat Martineau 4598f80842a8SMat Martineau if (control->final) { 4599f80842a8SMat Martineau if (chan->srej_save_reqseq != control->reqseq || 4600f80842a8SMat Martineau !test_and_clear_bit(CONN_SREJ_ACT, 4601f80842a8SMat Martineau &chan->conn_state)) 4602f80842a8SMat Martineau l2cap_retransmit(chan, control); 4603f80842a8SMat Martineau } else { 4604f80842a8SMat Martineau l2cap_retransmit(chan, control); 4605f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 4606f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 4607f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 4608f80842a8SMat Martineau } 4609f80842a8SMat Martineau } 4610f80842a8SMat Martineau } 4611d2a7ac5dSMat Martineau } 4612d2a7ac5dSMat Martineau 4613d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan, 4614d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 4615d2a7ac5dSMat Martineau { 4616fcd289dfSMat Martineau struct sk_buff *skb; 4617fcd289dfSMat Martineau 4618fcd289dfSMat Martineau BT_DBG("chan %p, control %p", chan, control); 4619fcd289dfSMat Martineau 4620fcd289dfSMat Martineau if (control->reqseq == chan->next_tx_seq) { 4621fcd289dfSMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 4622fcd289dfSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 4623fcd289dfSMat Martineau return; 4624fcd289dfSMat Martineau } 4625fcd289dfSMat Martineau 4626fcd289dfSMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 4627fcd289dfSMat Martineau 4628fcd289dfSMat Martineau if (chan->max_tx && skb && 4629fcd289dfSMat Martineau bt_cb(skb)->control.retries >= chan->max_tx) { 4630fcd289dfSMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 4631fcd289dfSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 4632fcd289dfSMat Martineau return; 4633fcd289dfSMat Martineau } 4634fcd289dfSMat Martineau 4635fcd289dfSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4636fcd289dfSMat Martineau 4637fcd289dfSMat Martineau l2cap_pass_to_tx(chan, control); 4638fcd289dfSMat Martineau 4639fcd289dfSMat Martineau if (control->final) { 4640fcd289dfSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 4641fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 4642fcd289dfSMat Martineau } else { 4643fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 4644fcd289dfSMat Martineau l2cap_ertm_send(chan); 4645fcd289dfSMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) 4646fcd289dfSMat Martineau set_bit(CONN_REJ_ACT, &chan->conn_state); 4647fcd289dfSMat Martineau } 4648d2a7ac5dSMat Martineau } 4649d2a7ac5dSMat Martineau 46504b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) 46514b51dae9SMat Martineau { 46524b51dae9SMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 46534b51dae9SMat Martineau 46544b51dae9SMat Martineau BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq, 46554b51dae9SMat Martineau chan->expected_tx_seq); 46564b51dae9SMat Martineau 46574b51dae9SMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 46584b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 46594b51dae9SMat Martineau chan->tx_win) { 46604b51dae9SMat Martineau /* See notes below regarding "double poll" and 46614b51dae9SMat Martineau * invalid packets. 46624b51dae9SMat Martineau */ 46634b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 46644b51dae9SMat Martineau BT_DBG("Invalid/Ignore - after SREJ"); 46654b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 46664b51dae9SMat Martineau } else { 46674b51dae9SMat Martineau BT_DBG("Invalid - in window after SREJ sent"); 46684b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 46694b51dae9SMat Martineau } 46704b51dae9SMat Martineau } 46714b51dae9SMat Martineau 46724b51dae9SMat Martineau if (chan->srej_list.head == txseq) { 46734b51dae9SMat Martineau BT_DBG("Expected SREJ"); 46744b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED_SREJ; 46754b51dae9SMat Martineau } 46764b51dae9SMat Martineau 46774b51dae9SMat Martineau if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) { 46784b51dae9SMat Martineau BT_DBG("Duplicate SREJ - txseq already stored"); 46794b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE_SREJ; 46804b51dae9SMat Martineau } 46814b51dae9SMat Martineau 46824b51dae9SMat Martineau if (l2cap_seq_list_contains(&chan->srej_list, txseq)) { 46834b51dae9SMat Martineau BT_DBG("Unexpected SREJ - not requested"); 46844b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED_SREJ; 46854b51dae9SMat Martineau } 46864b51dae9SMat Martineau } 46874b51dae9SMat Martineau 46884b51dae9SMat Martineau if (chan->expected_tx_seq == txseq) { 46894b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 46904b51dae9SMat Martineau chan->tx_win) { 46914b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 46924b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 46934b51dae9SMat Martineau } else { 46944b51dae9SMat Martineau BT_DBG("Expected"); 46954b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED; 46964b51dae9SMat Martineau } 46974b51dae9SMat Martineau } 46984b51dae9SMat Martineau 46994b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) < 47004b51dae9SMat Martineau __seq_offset(chan, chan->expected_tx_seq, 47014b51dae9SMat Martineau chan->last_acked_seq)){ 47024b51dae9SMat Martineau BT_DBG("Duplicate - expected_tx_seq later than txseq"); 47034b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE; 47044b51dae9SMat Martineau } 47054b51dae9SMat Martineau 47064b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) { 47074b51dae9SMat Martineau /* A source of invalid packets is a "double poll" condition, 47084b51dae9SMat Martineau * where delays cause us to send multiple poll packets. If 47094b51dae9SMat Martineau * the remote stack receives and processes both polls, 47104b51dae9SMat Martineau * sequence numbers can wrap around in such a way that a 47114b51dae9SMat Martineau * resent frame has a sequence number that looks like new data 47124b51dae9SMat Martineau * with a sequence gap. This would trigger an erroneous SREJ 47134b51dae9SMat Martineau * request. 47144b51dae9SMat Martineau * 47154b51dae9SMat Martineau * Fortunately, this is impossible with a tx window that's 47164b51dae9SMat Martineau * less than half of the maximum sequence number, which allows 47174b51dae9SMat Martineau * invalid frames to be safely ignored. 47184b51dae9SMat Martineau * 47194b51dae9SMat Martineau * With tx window sizes greater than half of the tx window 47204b51dae9SMat Martineau * maximum, the frame is invalid and cannot be ignored. This 47214b51dae9SMat Martineau * causes a disconnect. 47224b51dae9SMat Martineau */ 47234b51dae9SMat Martineau 47244b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 47254b51dae9SMat Martineau BT_DBG("Invalid/Ignore - txseq outside tx window"); 47264b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 47274b51dae9SMat Martineau } else { 47284b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 47294b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 47304b51dae9SMat Martineau } 47314b51dae9SMat Martineau } else { 47324b51dae9SMat Martineau BT_DBG("Unexpected - txseq indicates missing frames"); 47334b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED; 47344b51dae9SMat Martineau } 47354b51dae9SMat Martineau } 47364b51dae9SMat Martineau 4737d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan, 4738d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 4739d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 4740d2a7ac5dSMat Martineau { 4741d2a7ac5dSMat Martineau int err = 0; 4742d2a7ac5dSMat Martineau bool skb_in_use = 0; 4743d2a7ac5dSMat Martineau 4744d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 4745d2a7ac5dSMat Martineau event); 4746d2a7ac5dSMat Martineau 4747d2a7ac5dSMat Martineau switch (event) { 4748d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 4749d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, control->txseq)) { 4750d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 4751d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4752d2a7ac5dSMat Martineau 4753d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 4754d2a7ac5dSMat Martineau BT_DBG("Busy, discarding expected seq %d", 4755d2a7ac5dSMat Martineau control->txseq); 4756d2a7ac5dSMat Martineau break; 4757d2a7ac5dSMat Martineau } 4758d2a7ac5dSMat Martineau 4759d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, 4760d2a7ac5dSMat Martineau control->txseq); 4761d2a7ac5dSMat Martineau 4762d2a7ac5dSMat Martineau chan->buffer_seq = chan->expected_tx_seq; 4763d2a7ac5dSMat Martineau skb_in_use = 1; 4764d2a7ac5dSMat Martineau 4765d2a7ac5dSMat Martineau err = l2cap_reassemble_sdu(chan, skb, control); 4766d2a7ac5dSMat Martineau if (err) 4767d2a7ac5dSMat Martineau break; 4768d2a7ac5dSMat Martineau 4769d2a7ac5dSMat Martineau if (control->final) { 4770d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 4771d2a7ac5dSMat Martineau &chan->conn_state)) { 4772d2a7ac5dSMat Martineau control->final = 0; 4773d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 4774d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 4775d2a7ac5dSMat Martineau } 4776d2a7ac5dSMat Martineau } 4777d2a7ac5dSMat Martineau 4778d2a7ac5dSMat Martineau if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 4779d2a7ac5dSMat Martineau l2cap_send_ack(chan); 4780d2a7ac5dSMat Martineau break; 4781d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 4782d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4783d2a7ac5dSMat Martineau 4784d2a7ac5dSMat Martineau /* Can't issue SREJ frames in the local busy state. 4785d2a7ac5dSMat Martineau * Drop this frame, it will be seen as missing 4786d2a7ac5dSMat Martineau * when local busy is exited. 4787d2a7ac5dSMat Martineau */ 4788d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 4789d2a7ac5dSMat Martineau BT_DBG("Busy, discarding unexpected seq %d", 4790d2a7ac5dSMat Martineau control->txseq); 4791d2a7ac5dSMat Martineau break; 4792d2a7ac5dSMat Martineau } 4793d2a7ac5dSMat Martineau 4794d2a7ac5dSMat Martineau /* There was a gap in the sequence, so an SREJ 4795d2a7ac5dSMat Martineau * must be sent for each missing frame. The 4796d2a7ac5dSMat Martineau * current frame is stored for later use. 4797d2a7ac5dSMat Martineau */ 4798d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4799d2a7ac5dSMat Martineau skb_in_use = 1; 4800d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4801d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4802d2a7ac5dSMat Martineau 4803d2a7ac5dSMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 4804d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 4805d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 4806d2a7ac5dSMat Martineau 4807d2a7ac5dSMat Martineau chan->rx_state = L2CAP_RX_STATE_SREJ_SENT; 4808d2a7ac5dSMat Martineau break; 4809d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 4810d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4811d2a7ac5dSMat Martineau break; 4812d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 4813d2a7ac5dSMat Martineau break; 4814d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 4815d2a7ac5dSMat Martineau default: 4816d2a7ac5dSMat Martineau l2cap_send_disconn_req(chan->conn, chan, 4817d2a7ac5dSMat Martineau ECONNRESET); 4818d2a7ac5dSMat Martineau break; 4819d2a7ac5dSMat Martineau } 4820d2a7ac5dSMat Martineau break; 4821d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 4822d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4823d2a7ac5dSMat Martineau if (control->final) { 4824d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4825d2a7ac5dSMat Martineau 4826d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 4827d2a7ac5dSMat Martineau &chan->conn_state)) { 4828d2a7ac5dSMat Martineau control->final = 0; 4829d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 4830d2a7ac5dSMat Martineau } 4831d2a7ac5dSMat Martineau 4832d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 4833d2a7ac5dSMat Martineau } else if (control->poll) { 4834d2a7ac5dSMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 4835d2a7ac5dSMat Martineau } else { 4836d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 4837d2a7ac5dSMat Martineau &chan->conn_state) && 4838d2a7ac5dSMat Martineau chan->unacked_frames) 4839d2a7ac5dSMat Martineau __set_retrans_timer(chan); 4840d2a7ac5dSMat Martineau 4841d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 4842d2a7ac5dSMat Martineau } 4843d2a7ac5dSMat Martineau break; 4844d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 4845d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4846d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4847d2a7ac5dSMat Martineau if (control && control->poll) { 4848d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 4849d2a7ac5dSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 4850d2a7ac5dSMat Martineau } 4851d2a7ac5dSMat Martineau __clear_retrans_timer(chan); 4852d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 4853d2a7ac5dSMat Martineau break; 4854d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 4855d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 4856d2a7ac5dSMat Martineau break; 4857d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 4858d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 4859d2a7ac5dSMat Martineau break; 4860d2a7ac5dSMat Martineau default: 4861d2a7ac5dSMat Martineau break; 4862d2a7ac5dSMat Martineau } 4863d2a7ac5dSMat Martineau 4864d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 4865d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 4866d2a7ac5dSMat Martineau kfree_skb(skb); 4867d2a7ac5dSMat Martineau } 4868d2a7ac5dSMat Martineau 4869d2a7ac5dSMat Martineau return err; 4870d2a7ac5dSMat Martineau } 4871d2a7ac5dSMat Martineau 4872d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, 4873d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 4874d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 4875d2a7ac5dSMat Martineau { 4876d2a7ac5dSMat Martineau int err = 0; 4877d2a7ac5dSMat Martineau u16 txseq = control->txseq; 4878d2a7ac5dSMat Martineau bool skb_in_use = 0; 4879d2a7ac5dSMat Martineau 4880d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 4881d2a7ac5dSMat Martineau event); 4882d2a7ac5dSMat Martineau 4883d2a7ac5dSMat Martineau switch (event) { 4884d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 4885d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, txseq)) { 4886d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 4887d2a7ac5dSMat Martineau /* Keep frame for reassembly later */ 4888d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4889d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4890d2a7ac5dSMat Martineau skb_in_use = 1; 4891d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4892d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4893d2a7ac5dSMat Martineau 4894d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 4895d2a7ac5dSMat Martineau break; 4896d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED_SREJ: 4897d2a7ac5dSMat Martineau l2cap_seq_list_pop(&chan->srej_list); 4898d2a7ac5dSMat Martineau 4899d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4900d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4901d2a7ac5dSMat Martineau skb_in_use = 1; 4902d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4903d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4904d2a7ac5dSMat Martineau 4905d2a7ac5dSMat Martineau err = l2cap_rx_queued_iframes(chan); 4906d2a7ac5dSMat Martineau if (err) 4907d2a7ac5dSMat Martineau break; 4908d2a7ac5dSMat Martineau 4909d2a7ac5dSMat Martineau break; 4910d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 4911d2a7ac5dSMat Martineau /* Got a frame that can't be reassembled yet. 4912d2a7ac5dSMat Martineau * Save it for later, and send SREJs to cover 4913d2a7ac5dSMat Martineau * the missing frames. 4914d2a7ac5dSMat Martineau */ 4915d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4916d2a7ac5dSMat Martineau skb_in_use = 1; 4917d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4918d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4919d2a7ac5dSMat Martineau 4920d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4921d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 4922d2a7ac5dSMat Martineau break; 4923d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED_SREJ: 4924d2a7ac5dSMat Martineau /* This frame was requested with an SREJ, but 4925d2a7ac5dSMat Martineau * some expected retransmitted frames are 4926d2a7ac5dSMat Martineau * missing. Request retransmission of missing 4927d2a7ac5dSMat Martineau * SREJ'd frames. 4928d2a7ac5dSMat Martineau */ 4929d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4930d2a7ac5dSMat Martineau skb_in_use = 1; 4931d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4932d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4933d2a7ac5dSMat Martineau 4934d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4935d2a7ac5dSMat Martineau l2cap_send_srej_list(chan, control->txseq); 4936d2a7ac5dSMat Martineau break; 4937d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE_SREJ: 4938d2a7ac5dSMat Martineau /* We've already queued this frame. Drop this copy. */ 4939d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4940d2a7ac5dSMat Martineau break; 4941d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 4942d2a7ac5dSMat Martineau /* Expecting a later sequence number, so this frame 4943d2a7ac5dSMat Martineau * was already received. Ignore it completely. 4944d2a7ac5dSMat Martineau */ 4945d2a7ac5dSMat Martineau break; 4946d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 4947d2a7ac5dSMat Martineau break; 4948d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 4949d2a7ac5dSMat Martineau default: 4950d2a7ac5dSMat Martineau l2cap_send_disconn_req(chan->conn, chan, 4951d2a7ac5dSMat Martineau ECONNRESET); 4952d2a7ac5dSMat Martineau break; 4953d2a7ac5dSMat Martineau } 4954d2a7ac5dSMat Martineau break; 4955d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 4956d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4957d2a7ac5dSMat Martineau if (control->final) { 4958d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4959d2a7ac5dSMat Martineau 4960d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 4961d2a7ac5dSMat Martineau &chan->conn_state)) { 4962d2a7ac5dSMat Martineau control->final = 0; 4963d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 4964d2a7ac5dSMat Martineau } 4965d2a7ac5dSMat Martineau 4966d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 4967d2a7ac5dSMat Martineau } else if (control->poll) { 4968d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 4969d2a7ac5dSMat Martineau &chan->conn_state) && 4970d2a7ac5dSMat Martineau chan->unacked_frames) { 4971d2a7ac5dSMat Martineau __set_retrans_timer(chan); 4972d2a7ac5dSMat Martineau } 4973d2a7ac5dSMat Martineau 4974d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 4975d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 4976d2a7ac5dSMat Martineau } else { 4977d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 4978d2a7ac5dSMat Martineau &chan->conn_state) && 4979d2a7ac5dSMat Martineau chan->unacked_frames) 4980d2a7ac5dSMat Martineau __set_retrans_timer(chan); 4981d2a7ac5dSMat Martineau 4982d2a7ac5dSMat Martineau l2cap_send_ack(chan); 4983d2a7ac5dSMat Martineau } 4984d2a7ac5dSMat Martineau break; 4985d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 4986d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4987d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4988d2a7ac5dSMat Martineau if (control->poll) { 4989d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 4990d2a7ac5dSMat Martineau } else { 4991d2a7ac5dSMat Martineau struct l2cap_ctrl rr_control; 4992d2a7ac5dSMat Martineau memset(&rr_control, 0, sizeof(rr_control)); 4993d2a7ac5dSMat Martineau rr_control.sframe = 1; 4994d2a7ac5dSMat Martineau rr_control.super = L2CAP_SUPER_RR; 4995d2a7ac5dSMat Martineau rr_control.reqseq = chan->buffer_seq; 4996d2a7ac5dSMat Martineau l2cap_send_sframe(chan, &rr_control); 4997d2a7ac5dSMat Martineau } 4998d2a7ac5dSMat Martineau 4999d2a7ac5dSMat Martineau break; 5000d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 5001d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 5002d2a7ac5dSMat Martineau break; 5003d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 5004d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 5005d2a7ac5dSMat Martineau break; 5006d2a7ac5dSMat Martineau } 5007d2a7ac5dSMat Martineau 5008d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 5009d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 5010d2a7ac5dSMat Martineau kfree_skb(skb); 5011d2a7ac5dSMat Martineau } 5012d2a7ac5dSMat Martineau 5013d2a7ac5dSMat Martineau return err; 5014d2a7ac5dSMat Martineau } 5015d2a7ac5dSMat Martineau 5016d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq) 5017d2a7ac5dSMat Martineau { 5018d2a7ac5dSMat Martineau /* Make sure reqseq is for a packet that has been sent but not acked */ 5019d2a7ac5dSMat Martineau u16 unacked; 5020d2a7ac5dSMat Martineau 5021d2a7ac5dSMat Martineau unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq); 5022d2a7ac5dSMat Martineau return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked; 5023d2a7ac5dSMat Martineau } 5024d2a7ac5dSMat Martineau 5025cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 5026cec8ab6eSMat Martineau struct sk_buff *skb, u8 event) 50270a708f8fSGustavo F. Padovan { 5028d2a7ac5dSMat Martineau int err = 0; 5029d2a7ac5dSMat Martineau 5030d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan, 5031d2a7ac5dSMat Martineau control, skb, event, chan->rx_state); 5032d2a7ac5dSMat Martineau 5033d2a7ac5dSMat Martineau if (__valid_reqseq(chan, control->reqseq)) { 5034d2a7ac5dSMat Martineau switch (chan->rx_state) { 5035d2a7ac5dSMat Martineau case L2CAP_RX_STATE_RECV: 5036d2a7ac5dSMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 5037d2a7ac5dSMat Martineau break; 5038d2a7ac5dSMat Martineau case L2CAP_RX_STATE_SREJ_SENT: 5039d2a7ac5dSMat Martineau err = l2cap_rx_state_srej_sent(chan, control, skb, 5040d2a7ac5dSMat Martineau event); 5041d2a7ac5dSMat Martineau break; 5042d2a7ac5dSMat Martineau default: 5043d2a7ac5dSMat Martineau /* shut it down */ 5044d2a7ac5dSMat Martineau break; 5045d2a7ac5dSMat Martineau } 5046d2a7ac5dSMat Martineau } else { 5047d2a7ac5dSMat Martineau BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d", 5048d2a7ac5dSMat Martineau control->reqseq, chan->next_tx_seq, 5049d2a7ac5dSMat Martineau chan->expected_ack_seq); 5050d2a7ac5dSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 5051d2a7ac5dSMat Martineau } 5052d2a7ac5dSMat Martineau 5053d2a7ac5dSMat Martineau return err; 5054cec8ab6eSMat Martineau } 5055cec8ab6eSMat Martineau 5056cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 5057cec8ab6eSMat Martineau struct sk_buff *skb) 5058cec8ab6eSMat Martineau { 50594b51dae9SMat Martineau int err = 0; 50604b51dae9SMat Martineau 50614b51dae9SMat Martineau BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb, 50624b51dae9SMat Martineau chan->rx_state); 50634b51dae9SMat Martineau 50644b51dae9SMat Martineau if (l2cap_classify_txseq(chan, control->txseq) == 50654b51dae9SMat Martineau L2CAP_TXSEQ_EXPECTED) { 50664b51dae9SMat Martineau l2cap_pass_to_tx(chan, control); 50674b51dae9SMat Martineau 50684b51dae9SMat Martineau BT_DBG("buffer_seq %d->%d", chan->buffer_seq, 50694b51dae9SMat Martineau __next_seq(chan, chan->buffer_seq)); 50704b51dae9SMat Martineau 50714b51dae9SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 50724b51dae9SMat Martineau 50734b51dae9SMat Martineau l2cap_reassemble_sdu(chan, skb, control); 50744b51dae9SMat Martineau } else { 50754b51dae9SMat Martineau if (chan->sdu) { 50764b51dae9SMat Martineau kfree_skb(chan->sdu); 50774b51dae9SMat Martineau chan->sdu = NULL; 50784b51dae9SMat Martineau } 50794b51dae9SMat Martineau chan->sdu_last_frag = NULL; 50804b51dae9SMat Martineau chan->sdu_len = 0; 50814b51dae9SMat Martineau 50824b51dae9SMat Martineau if (skb) { 50834b51dae9SMat Martineau BT_DBG("Freeing %p", skb); 50844b51dae9SMat Martineau kfree_skb(skb); 50854b51dae9SMat Martineau } 50864b51dae9SMat Martineau } 50874b51dae9SMat Martineau 50884b51dae9SMat Martineau chan->last_acked_seq = control->txseq; 50894b51dae9SMat Martineau chan->expected_tx_seq = __next_seq(chan, control->txseq); 50904b51dae9SMat Martineau 50914b51dae9SMat Martineau return err; 5092cec8ab6eSMat Martineau } 5093cec8ab6eSMat Martineau 5094cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 5095cec8ab6eSMat Martineau { 5096cec8ab6eSMat Martineau struct l2cap_ctrl *control = &bt_cb(skb)->control; 5097cec8ab6eSMat Martineau u16 len; 5098cec8ab6eSMat Martineau u8 event; 50990a708f8fSGustavo F. Padovan 5100b76bbd66SMat Martineau __unpack_control(chan, skb); 5101b76bbd66SMat Martineau 51020a708f8fSGustavo F. Padovan len = skb->len; 51030a708f8fSGustavo F. Padovan 51040a708f8fSGustavo F. Padovan /* 51050a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here. 51060a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery 5107cec8ab6eSMat Martineau * procedures and ask for retransmission. 51080a708f8fSGustavo F. Padovan */ 510947d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 51100a708f8fSGustavo F. Padovan goto drop; 51110a708f8fSGustavo F. Padovan 5112cec8ab6eSMat Martineau if (!control->sframe && control->sar == L2CAP_SAR_START) 511303a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 51140a708f8fSGustavo F. Padovan 511547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 511603a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 51170a708f8fSGustavo F. Padovan 511847d1ec61SGustavo F. Padovan if (len > chan->mps) { 51198c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 51200a708f8fSGustavo F. Padovan goto drop; 51210a708f8fSGustavo F. Padovan } 51220a708f8fSGustavo F. Padovan 5123cec8ab6eSMat Martineau if (!control->sframe) { 5124cec8ab6eSMat Martineau int err; 51250a708f8fSGustavo F. Padovan 5126cec8ab6eSMat Martineau BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d", 5127cec8ab6eSMat Martineau control->sar, control->reqseq, control->final, 5128cec8ab6eSMat Martineau control->txseq); 5129836be934SAndrei Emeltchenko 5130cec8ab6eSMat Martineau /* Validate F-bit - F=0 always valid, F=1 only 5131cec8ab6eSMat Martineau * valid in TX WAIT_F 5132cec8ab6eSMat Martineau */ 5133cec8ab6eSMat Martineau if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F) 51340a708f8fSGustavo F. Padovan goto drop; 51350a708f8fSGustavo F. Padovan 5136cec8ab6eSMat Martineau if (chan->mode != L2CAP_MODE_STREAMING) { 5137cec8ab6eSMat Martineau event = L2CAP_EV_RECV_IFRAME; 5138cec8ab6eSMat Martineau err = l2cap_rx(chan, control, skb, event); 51390a708f8fSGustavo F. Padovan } else { 5140cec8ab6eSMat Martineau err = l2cap_stream_rx(chan, control, skb); 5141cec8ab6eSMat Martineau } 5142cec8ab6eSMat Martineau 5143cec8ab6eSMat Martineau if (err) 5144cec8ab6eSMat Martineau l2cap_send_disconn_req(chan->conn, chan, 5145cec8ab6eSMat Martineau ECONNRESET); 5146cec8ab6eSMat Martineau } else { 5147cec8ab6eSMat Martineau const u8 rx_func_to_event[4] = { 5148cec8ab6eSMat Martineau L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ, 5149cec8ab6eSMat Martineau L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ 5150cec8ab6eSMat Martineau }; 5151cec8ab6eSMat Martineau 5152cec8ab6eSMat Martineau /* Only I-frames are expected in streaming mode */ 5153cec8ab6eSMat Martineau if (chan->mode == L2CAP_MODE_STREAMING) 5154cec8ab6eSMat Martineau goto drop; 5155cec8ab6eSMat Martineau 5156cec8ab6eSMat Martineau BT_DBG("sframe reqseq %d, final %d, poll %d, super %d", 5157cec8ab6eSMat Martineau control->reqseq, control->final, control->poll, 5158cec8ab6eSMat Martineau control->super); 5159cec8ab6eSMat Martineau 51600a708f8fSGustavo F. Padovan if (len != 0) { 51610a708f8fSGustavo F. Padovan BT_ERR("%d", len); 51628c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 51630a708f8fSGustavo F. Padovan goto drop; 51640a708f8fSGustavo F. Padovan } 51650a708f8fSGustavo F. Padovan 5166cec8ab6eSMat Martineau /* Validate F and P bits */ 5167cec8ab6eSMat Martineau if (control->final && (control->poll || 5168cec8ab6eSMat Martineau chan->tx_state != L2CAP_TX_STATE_WAIT_F)) 5169cec8ab6eSMat Martineau goto drop; 5170cec8ab6eSMat Martineau 5171cec8ab6eSMat Martineau event = rx_func_to_event[control->super]; 5172cec8ab6eSMat Martineau if (l2cap_rx(chan, control, skb, event)) 5173cec8ab6eSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 51740a708f8fSGustavo F. Padovan } 51750a708f8fSGustavo F. Padovan 51760a708f8fSGustavo F. Padovan return 0; 51770a708f8fSGustavo F. Padovan 51780a708f8fSGustavo F. Padovan drop: 51790a708f8fSGustavo F. Padovan kfree_skb(skb); 51800a708f8fSGustavo F. Padovan return 0; 51810a708f8fSGustavo F. Padovan } 51820a708f8fSGustavo F. Padovan 51830a708f8fSGustavo F. Padovan static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb) 51840a708f8fSGustavo F. Padovan { 518548454079SGustavo F. Padovan struct l2cap_chan *chan; 51860a708f8fSGustavo F. Padovan 5187baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 518848454079SGustavo F. Padovan if (!chan) { 51890a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid); 51906be36555SAndrei Emeltchenko /* Drop packet and return */ 51913379013bSDan Carpenter kfree_skb(skb); 51926be36555SAndrei Emeltchenko return 0; 51930a708f8fSGustavo F. Padovan } 51940a708f8fSGustavo F. Padovan 519549208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len); 51960a708f8fSGustavo F. Padovan 519789bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 51980a708f8fSGustavo F. Padovan goto drop; 51990a708f8fSGustavo F. Padovan 52000c1bc5c6SGustavo F. Padovan switch (chan->mode) { 52010a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 52020a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here 52030a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable. 52040a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't 52050a708f8fSGustavo F. Padovan * provide flow control mechanism. */ 52060a708f8fSGustavo F. Padovan 52070c1bc5c6SGustavo F. Padovan if (chan->imtu < skb->len) 52080a708f8fSGustavo F. Padovan goto drop; 52090a708f8fSGustavo F. Padovan 521023070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 52110a708f8fSGustavo F. Padovan goto done; 52120a708f8fSGustavo F. Padovan break; 52130a708f8fSGustavo F. Padovan 52140a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 52150a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 5216cec8ab6eSMat Martineau l2cap_data_rcv(chan, skb); 52170a708f8fSGustavo F. Padovan goto done; 52180a708f8fSGustavo F. Padovan 52190a708f8fSGustavo F. Padovan default: 52200c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); 52210a708f8fSGustavo F. Padovan break; 52220a708f8fSGustavo F. Padovan } 52230a708f8fSGustavo F. Padovan 52240a708f8fSGustavo F. Padovan drop: 52250a708f8fSGustavo F. Padovan kfree_skb(skb); 52260a708f8fSGustavo F. Padovan 52270a708f8fSGustavo F. Padovan done: 52286be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 52290a708f8fSGustavo F. Padovan 52300a708f8fSGustavo F. Padovan return 0; 52310a708f8fSGustavo F. Padovan } 52320a708f8fSGustavo F. Padovan 52330a708f8fSGustavo F. Padovan static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb) 52340a708f8fSGustavo F. Padovan { 523523691d75SGustavo F. Padovan struct l2cap_chan *chan; 52360a708f8fSGustavo F. Padovan 5237c2287681SIdo Yariv chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst); 523823691d75SGustavo F. Padovan if (!chan) 52390a708f8fSGustavo F. Padovan goto drop; 52400a708f8fSGustavo F. Padovan 52415b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 52420a708f8fSGustavo F. Padovan 524389bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 52440a708f8fSGustavo F. Padovan goto drop; 52450a708f8fSGustavo F. Padovan 5246e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 52470a708f8fSGustavo F. Padovan goto drop; 52480a708f8fSGustavo F. Padovan 524923070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 52505b4cedaaSAndrei Emeltchenko return 0; 52510a708f8fSGustavo F. Padovan 52520a708f8fSGustavo F. Padovan drop: 52530a708f8fSGustavo F. Padovan kfree_skb(skb); 52540a708f8fSGustavo F. Padovan 52550a708f8fSGustavo F. Padovan return 0; 52560a708f8fSGustavo F. Padovan } 52570a708f8fSGustavo F. Padovan 5258d9b88702SAndrei Emeltchenko static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid, 5259d9b88702SAndrei Emeltchenko struct sk_buff *skb) 52609f69bda6SGustavo F. Padovan { 526123691d75SGustavo F. Padovan struct l2cap_chan *chan; 52629f69bda6SGustavo F. Padovan 5263c2287681SIdo Yariv chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst); 526423691d75SGustavo F. Padovan if (!chan) 52659f69bda6SGustavo F. Padovan goto drop; 52669f69bda6SGustavo F. Padovan 52675b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 52689f69bda6SGustavo F. Padovan 526989bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 52709f69bda6SGustavo F. Padovan goto drop; 52719f69bda6SGustavo F. Padovan 5272e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 52739f69bda6SGustavo F. Padovan goto drop; 52749f69bda6SGustavo F. Padovan 527523070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 52765b4cedaaSAndrei Emeltchenko return 0; 52779f69bda6SGustavo F. Padovan 52789f69bda6SGustavo F. Padovan drop: 52799f69bda6SGustavo F. Padovan kfree_skb(skb); 52809f69bda6SGustavo F. Padovan 52819f69bda6SGustavo F. Padovan return 0; 52829f69bda6SGustavo F. Padovan } 52839f69bda6SGustavo F. Padovan 52840a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) 52850a708f8fSGustavo F. Padovan { 52860a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data; 52870a708f8fSGustavo F. Padovan u16 cid, len; 52880a708f8fSGustavo F. Padovan __le16 psm; 52890a708f8fSGustavo F. Padovan 52900a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE); 52910a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid); 52920a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len); 52930a708f8fSGustavo F. Padovan 52940a708f8fSGustavo F. Padovan if (len != skb->len) { 52950a708f8fSGustavo F. Padovan kfree_skb(skb); 52960a708f8fSGustavo F. Padovan return; 52970a708f8fSGustavo F. Padovan } 52980a708f8fSGustavo F. Padovan 52990a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid); 53000a708f8fSGustavo F. Padovan 53010a708f8fSGustavo F. Padovan switch (cid) { 53023300d9a9SClaudio Takahasi case L2CAP_CID_LE_SIGNALING: 53030a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING: 53040a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb); 53050a708f8fSGustavo F. Padovan break; 53060a708f8fSGustavo F. Padovan 53070a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS: 5308097db76cSAndrei Emeltchenko psm = get_unaligned((__le16 *) skb->data); 53090a708f8fSGustavo F. Padovan skb_pull(skb, 2); 53100a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb); 53110a708f8fSGustavo F. Padovan break; 53120a708f8fSGustavo F. Padovan 53139f69bda6SGustavo F. Padovan case L2CAP_CID_LE_DATA: 53149f69bda6SGustavo F. Padovan l2cap_att_channel(conn, cid, skb); 53159f69bda6SGustavo F. Padovan break; 53169f69bda6SGustavo F. Padovan 5317b501d6a1SAnderson Briglia case L2CAP_CID_SMP: 5318b501d6a1SAnderson Briglia if (smp_sig_channel(conn, skb)) 5319b501d6a1SAnderson Briglia l2cap_conn_del(conn->hcon, EACCES); 5320b501d6a1SAnderson Briglia break; 5321b501d6a1SAnderson Briglia 53220a708f8fSGustavo F. Padovan default: 53230a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb); 53240a708f8fSGustavo F. Padovan break; 53250a708f8fSGustavo F. Padovan } 53260a708f8fSGustavo F. Padovan } 53270a708f8fSGustavo F. Padovan 53280a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */ 53290a708f8fSGustavo F. Padovan 5330686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) 53310a708f8fSGustavo F. Padovan { 53320a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0; 533323691d75SGustavo F. Padovan struct l2cap_chan *c; 53340a708f8fSGustavo F. Padovan 53350a708f8fSGustavo F. Padovan BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); 53360a708f8fSGustavo F. Padovan 53370a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */ 533823691d75SGustavo F. Padovan read_lock(&chan_list_lock); 533923691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 534023691d75SGustavo F. Padovan struct sock *sk = c->sk; 53414343478fSGustavo F. Padovan 534289bc500eSGustavo F. Padovan if (c->state != BT_LISTEN) 53430a708f8fSGustavo F. Padovan continue; 53440a708f8fSGustavo F. Padovan 53450a708f8fSGustavo F. Padovan if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { 53460a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT; 534743bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 53480a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER; 53490a708f8fSGustavo F. Padovan exact++; 53500a708f8fSGustavo F. Padovan } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { 53510a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT; 535243bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 53530a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER; 53540a708f8fSGustavo F. Padovan } 53550a708f8fSGustavo F. Padovan } 535623691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 53570a708f8fSGustavo F. Padovan 53580a708f8fSGustavo F. Padovan return exact ? lm1 : lm2; 53590a708f8fSGustavo F. Padovan } 53600a708f8fSGustavo F. Padovan 5361686ebf28SUlisses Furquim int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) 53620a708f8fSGustavo F. Padovan { 53630a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 53640a708f8fSGustavo F. Padovan 53650a708f8fSGustavo F. Padovan BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); 53660a708f8fSGustavo F. Padovan 53670a708f8fSGustavo F. Padovan if (!status) { 53680a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, status); 53690a708f8fSGustavo F. Padovan if (conn) 53700a708f8fSGustavo F. Padovan l2cap_conn_ready(conn); 53710a708f8fSGustavo F. Padovan } else 5372e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status)); 53730a708f8fSGustavo F. Padovan 53740a708f8fSGustavo F. Padovan return 0; 53750a708f8fSGustavo F. Padovan } 53760a708f8fSGustavo F. Padovan 5377686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon) 53780a708f8fSGustavo F. Padovan { 53790a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 53800a708f8fSGustavo F. Padovan 53810a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon); 53820a708f8fSGustavo F. Padovan 5383686ebf28SUlisses Furquim if (!conn) 53849f5a0d7bSAndrei Emeltchenko return HCI_ERROR_REMOTE_USER_TERM; 53850a708f8fSGustavo F. Padovan return conn->disc_reason; 53860a708f8fSGustavo F. Padovan } 53870a708f8fSGustavo F. Padovan 5388686ebf28SUlisses Furquim int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) 53890a708f8fSGustavo F. Padovan { 53900a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason); 53910a708f8fSGustavo F. Padovan 5392e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason)); 53930a708f8fSGustavo F. Padovan return 0; 53940a708f8fSGustavo F. Padovan } 53950a708f8fSGustavo F. Padovan 53964343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) 53970a708f8fSGustavo F. Padovan { 5398715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 53990a708f8fSGustavo F. Padovan return; 54000a708f8fSGustavo F. Padovan 54010a708f8fSGustavo F. Padovan if (encrypt == 0x00) { 54024343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) { 5403ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); 54044343478fSGustavo F. Padovan } else if (chan->sec_level == BT_SECURITY_HIGH) 54050f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED); 54060a708f8fSGustavo F. Padovan } else { 54074343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) 5408c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 54090a708f8fSGustavo F. Padovan } 54100a708f8fSGustavo F. Padovan } 54110a708f8fSGustavo F. Padovan 5412686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) 54130a708f8fSGustavo F. Padovan { 54140a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 541548454079SGustavo F. Padovan struct l2cap_chan *chan; 54160a708f8fSGustavo F. Padovan 54170a708f8fSGustavo F. Padovan if (!conn) 54180a708f8fSGustavo F. Padovan return 0; 54190a708f8fSGustavo F. Padovan 54200a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 54210a708f8fSGustavo F. Padovan 5422160dc6acSVinicius Costa Gomes if (hcon->type == LE_LINK) { 542335d4adccSHemant Gupta if (!status && encrypt) 5424160dc6acSVinicius Costa Gomes smp_distribute_keys(conn, 0); 542517cd3f37SUlisses Furquim cancel_delayed_work(&conn->security_timer); 5426160dc6acSVinicius Costa Gomes } 5427160dc6acSVinicius Costa Gomes 54283df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 54290a708f8fSGustavo F. Padovan 54303df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 54316be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 54320a708f8fSGustavo F. Padovan 5433f1cb9af5SVinicius Costa Gomes BT_DBG("chan->scid %d", chan->scid); 5434f1cb9af5SVinicius Costa Gomes 5435f1cb9af5SVinicius Costa Gomes if (chan->scid == L2CAP_CID_LE_DATA) { 5436f1cb9af5SVinicius Costa Gomes if (!status && encrypt) { 5437f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level; 5438cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 5439f1cb9af5SVinicius Costa Gomes } 5440f1cb9af5SVinicius Costa Gomes 54416be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 5442f1cb9af5SVinicius Costa Gomes continue; 5443f1cb9af5SVinicius Costa Gomes } 5444f1cb9af5SVinicius Costa Gomes 5445c1360a1cSGustavo F. Padovan if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) { 54466be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 54470a708f8fSGustavo F. Padovan continue; 54480a708f8fSGustavo F. Padovan } 54490a708f8fSGustavo F. Padovan 545089bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED || 545189bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) { 5452a7d7723aSGustavo Padovan struct sock *sk = chan->sk; 5453a7d7723aSGustavo Padovan 5454c5daa683SGustavo Padovan clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); 5455a7d7723aSGustavo Padovan sk->sk_state_change(sk); 5456a7d7723aSGustavo Padovan 54574343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt); 54586be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 54590a708f8fSGustavo F. Padovan continue; 54600a708f8fSGustavo F. Padovan } 54610a708f8fSGustavo F. Padovan 546289bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 54630a708f8fSGustavo F. Padovan if (!status) { 54649b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 54650a708f8fSGustavo F. Padovan } else { 5466ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 54670a708f8fSGustavo F. Padovan } 546889bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 54696be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 54700a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 5471df3c3931SJohan Hedberg __u16 res, stat; 54720a708f8fSGustavo F. Padovan 54736be36555SAndrei Emeltchenko lock_sock(sk); 54746be36555SAndrei Emeltchenko 54750a708f8fSGustavo F. Padovan if (!status) { 5476c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, 5477c5daa683SGustavo Padovan &bt_sk(sk)->flags)) { 5478df3c3931SJohan Hedberg struct sock *parent = bt_sk(sk)->parent; 5479df3c3931SJohan Hedberg res = L2CAP_CR_PEND; 5480df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND; 548105e9a2f6SIlia Kolomisnky if (parent) 5482df3c3931SJohan Hedberg parent->sk_data_ready(parent, 0); 5483df3c3931SJohan Hedberg } else { 54840e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 5485df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS; 5486df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 5487df3c3931SJohan Hedberg } 54880a708f8fSGustavo F. Padovan } else { 54890e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_DISCONN); 5490ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 5491df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK; 5492df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 54930a708f8fSGustavo F. Padovan } 54940a708f8fSGustavo F. Padovan 54956be36555SAndrei Emeltchenko release_sock(sk); 54966be36555SAndrei Emeltchenko 5497fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 5498fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 5499df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res); 5500df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat); 5501fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 5502fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 55032d369359SMat Martineau 55042d369359SMat Martineau if (!test_bit(CONF_REQ_SENT, &chan->conf_state) && 55052d369359SMat Martineau res == L2CAP_CR_SUCCESS) { 55062d369359SMat Martineau char buf[128]; 55072d369359SMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 55082d369359SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), 55092d369359SMat Martineau L2CAP_CONF_REQ, 55102d369359SMat Martineau l2cap_build_conf_req(chan, buf), 55112d369359SMat Martineau buf); 55122d369359SMat Martineau chan->num_conf_req++; 55132d369359SMat Martineau } 55140a708f8fSGustavo F. Padovan } 55150a708f8fSGustavo F. Padovan 55166be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 55170a708f8fSGustavo F. Padovan } 55180a708f8fSGustavo F. Padovan 55193df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 55200a708f8fSGustavo F. Padovan 55210a708f8fSGustavo F. Padovan return 0; 55220a708f8fSGustavo F. Padovan } 55230a708f8fSGustavo F. Padovan 5524686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) 55250a708f8fSGustavo F. Padovan { 55260a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 55270a708f8fSGustavo F. Padovan 55280a708f8fSGustavo F. Padovan if (!conn) 55290a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, 0); 55300a708f8fSGustavo F. Padovan 55310a708f8fSGustavo F. Padovan if (!conn) 55320a708f8fSGustavo F. Padovan goto drop; 55330a708f8fSGustavo F. Padovan 55340a708f8fSGustavo F. Padovan BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); 55350a708f8fSGustavo F. Padovan 55360a708f8fSGustavo F. Padovan if (!(flags & ACL_CONT)) { 55370a708f8fSGustavo F. Padovan struct l2cap_hdr *hdr; 55380a708f8fSGustavo F. Padovan int len; 55390a708f8fSGustavo F. Padovan 55400a708f8fSGustavo F. Padovan if (conn->rx_len) { 55410a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len); 55420a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 55430a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 55440a708f8fSGustavo F. Padovan conn->rx_len = 0; 55450a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 55460a708f8fSGustavo F. Padovan } 55470a708f8fSGustavo F. Padovan 55480a708f8fSGustavo F. Padovan /* Start fragment always begin with Basic L2CAP header */ 55490a708f8fSGustavo F. Padovan if (skb->len < L2CAP_HDR_SIZE) { 55500a708f8fSGustavo F. Padovan BT_ERR("Frame is too short (len %d)", skb->len); 55510a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 55520a708f8fSGustavo F. Padovan goto drop; 55530a708f8fSGustavo F. Padovan } 55540a708f8fSGustavo F. Padovan 55550a708f8fSGustavo F. Padovan hdr = (struct l2cap_hdr *) skb->data; 55560a708f8fSGustavo F. Padovan len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; 55570a708f8fSGustavo F. Padovan 55580a708f8fSGustavo F. Padovan if (len == skb->len) { 55590a708f8fSGustavo F. Padovan /* Complete frame received */ 55600a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb); 55610a708f8fSGustavo F. Padovan return 0; 55620a708f8fSGustavo F. Padovan } 55630a708f8fSGustavo F. Padovan 55640a708f8fSGustavo F. Padovan BT_DBG("Start: total len %d, frag len %d", len, skb->len); 55650a708f8fSGustavo F. Padovan 55660a708f8fSGustavo F. Padovan if (skb->len > len) { 55670a708f8fSGustavo F. Padovan BT_ERR("Frame is too long (len %d, expected len %d)", 55680a708f8fSGustavo F. Padovan skb->len, len); 55690a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 55700a708f8fSGustavo F. Padovan goto drop; 55710a708f8fSGustavo F. Padovan } 55720a708f8fSGustavo F. Padovan 55730a708f8fSGustavo F. Padovan /* Allocate skb for the complete frame (with header) */ 55740a708f8fSGustavo F. Padovan conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC); 55750a708f8fSGustavo F. Padovan if (!conn->rx_skb) 55760a708f8fSGustavo F. Padovan goto drop; 55770a708f8fSGustavo F. Padovan 55780a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 55790a708f8fSGustavo F. Padovan skb->len); 55800a708f8fSGustavo F. Padovan conn->rx_len = len - skb->len; 55810a708f8fSGustavo F. Padovan } else { 55820a708f8fSGustavo F. Padovan BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); 55830a708f8fSGustavo F. Padovan 55840a708f8fSGustavo F. Padovan if (!conn->rx_len) { 55850a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len); 55860a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 55870a708f8fSGustavo F. Padovan goto drop; 55880a708f8fSGustavo F. Padovan } 55890a708f8fSGustavo F. Padovan 55900a708f8fSGustavo F. Padovan if (skb->len > conn->rx_len) { 55910a708f8fSGustavo F. Padovan BT_ERR("Fragment is too long (len %d, expected %d)", 55920a708f8fSGustavo F. Padovan skb->len, conn->rx_len); 55930a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 55940a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 55950a708f8fSGustavo F. Padovan conn->rx_len = 0; 55960a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 55970a708f8fSGustavo F. Padovan goto drop; 55980a708f8fSGustavo F. Padovan } 55990a708f8fSGustavo F. Padovan 56000a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 56010a708f8fSGustavo F. Padovan skb->len); 56020a708f8fSGustavo F. Padovan conn->rx_len -= skb->len; 56030a708f8fSGustavo F. Padovan 56040a708f8fSGustavo F. Padovan if (!conn->rx_len) { 56050a708f8fSGustavo F. Padovan /* Complete frame received */ 56060a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, conn->rx_skb); 56070a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 56080a708f8fSGustavo F. Padovan } 56090a708f8fSGustavo F. Padovan } 56100a708f8fSGustavo F. Padovan 56110a708f8fSGustavo F. Padovan drop: 56120a708f8fSGustavo F. Padovan kfree_skb(skb); 56130a708f8fSGustavo F. Padovan return 0; 56140a708f8fSGustavo F. Padovan } 56150a708f8fSGustavo F. Padovan 56160a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p) 56170a708f8fSGustavo F. Padovan { 561823691d75SGustavo F. Padovan struct l2cap_chan *c; 56190a708f8fSGustavo F. Padovan 5620333055f2SGustavo F. Padovan read_lock(&chan_list_lock); 56210a708f8fSGustavo F. Padovan 562223691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 562323691d75SGustavo F. Padovan struct sock *sk = c->sk; 56240a708f8fSGustavo F. Padovan 5625903d343eSGustavo F. Padovan seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", 56260a708f8fSGustavo F. Padovan batostr(&bt_sk(sk)->src), 56270a708f8fSGustavo F. Padovan batostr(&bt_sk(sk)->dst), 562889bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm), 562923691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu, 563023691d75SGustavo F. Padovan c->sec_level, c->mode); 56310a708f8fSGustavo F. Padovan } 56320a708f8fSGustavo F. Padovan 5633333055f2SGustavo F. Padovan read_unlock(&chan_list_lock); 56340a708f8fSGustavo F. Padovan 56350a708f8fSGustavo F. Padovan return 0; 56360a708f8fSGustavo F. Padovan } 56370a708f8fSGustavo F. Padovan 56380a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file) 56390a708f8fSGustavo F. Padovan { 56400a708f8fSGustavo F. Padovan return single_open(file, l2cap_debugfs_show, inode->i_private); 56410a708f8fSGustavo F. Padovan } 56420a708f8fSGustavo F. Padovan 56430a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = { 56440a708f8fSGustavo F. Padovan .open = l2cap_debugfs_open, 56450a708f8fSGustavo F. Padovan .read = seq_read, 56460a708f8fSGustavo F. Padovan .llseek = seq_lseek, 56470a708f8fSGustavo F. Padovan .release = single_release, 56480a708f8fSGustavo F. Padovan }; 56490a708f8fSGustavo F. Padovan 56500a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs; 56510a708f8fSGustavo F. Padovan 565264274518SGustavo F. Padovan int __init l2cap_init(void) 56530a708f8fSGustavo F. Padovan { 56540a708f8fSGustavo F. Padovan int err; 56550a708f8fSGustavo F. Padovan 5656bb58f747SGustavo F. Padovan err = l2cap_init_sockets(); 56570a708f8fSGustavo F. Padovan if (err < 0) 56580a708f8fSGustavo F. Padovan return err; 56590a708f8fSGustavo F. Padovan 56600a708f8fSGustavo F. Padovan if (bt_debugfs) { 56610a708f8fSGustavo F. Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, 56620a708f8fSGustavo F. Padovan bt_debugfs, NULL, &l2cap_debugfs_fops); 56630a708f8fSGustavo F. Padovan if (!l2cap_debugfs) 56640a708f8fSGustavo F. Padovan BT_ERR("Failed to create L2CAP debug file"); 56650a708f8fSGustavo F. Padovan } 56660a708f8fSGustavo F. Padovan 56670a708f8fSGustavo F. Padovan return 0; 56680a708f8fSGustavo F. Padovan } 56690a708f8fSGustavo F. Padovan 567064274518SGustavo F. Padovan void l2cap_exit(void) 56710a708f8fSGustavo F. Padovan { 56720a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs); 5673bb58f747SGustavo F. Padovan l2cap_cleanup_sockets(); 56740a708f8fSGustavo F. Padovan } 56750a708f8fSGustavo F. Padovan 56760a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644); 56770a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); 5678