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> 4097e8e89dSAndrei Emeltchenko #include <net/bluetooth/a2mp.h> 410a708f8fSGustavo F. Padovan 42d1de6d46SMat Martineau bool disable_ertm; 430a708f8fSGustavo F. Padovan 440a708f8fSGustavo F. Padovan static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; 4550a147cdSMat Martineau static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, }; 460a708f8fSGustavo F. Padovan 47b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list); 48b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock); 490a708f8fSGustavo F. Padovan 500a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 510a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data); 524519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 534519de9aSGustavo F. Padovan void *data); 54710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); 554519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, 564519de9aSGustavo F. Padovan struct l2cap_chan *chan, int err); 570a708f8fSGustavo F. Padovan 58d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 59608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event); 60608bcc6dSMat Martineau 610a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */ 6271ba0e56SGustavo F. Padovan 63baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid) 640a708f8fSGustavo F. Padovan { 653df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 66baa7e1faSGustavo F. Padovan 673df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 683df91ea2SAndrei Emeltchenko if (c->dcid == cid) 693df91ea2SAndrei Emeltchenko return c; 700a708f8fSGustavo F. Padovan } 713df91ea2SAndrei Emeltchenko return NULL; 72baa7e1faSGustavo F. Padovan } 730a708f8fSGustavo F. Padovan 74baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) 750a708f8fSGustavo F. Padovan { 763df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 77baa7e1faSGustavo F. Padovan 783df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 793df91ea2SAndrei Emeltchenko if (c->scid == cid) 803df91ea2SAndrei Emeltchenko return c; 810a708f8fSGustavo F. Padovan } 823df91ea2SAndrei Emeltchenko return NULL; 83baa7e1faSGustavo F. Padovan } 840a708f8fSGustavo F. Padovan 850a708f8fSGustavo F. Padovan /* Find channel with given SCID. 86ef191adeSMat Martineau * Returns locked channel. */ 87baa7e1faSGustavo F. Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) 880a708f8fSGustavo F. Padovan { 8948454079SGustavo F. Padovan struct l2cap_chan *c; 90baa7e1faSGustavo F. Padovan 913df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 92baa7e1faSGustavo F. Padovan c = __l2cap_get_chan_by_scid(conn, cid); 93ef191adeSMat Martineau if (c) 94ef191adeSMat Martineau l2cap_chan_lock(c); 953df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 963df91ea2SAndrei Emeltchenko 9748454079SGustavo F. Padovan return c; 980a708f8fSGustavo F. Padovan } 990a708f8fSGustavo F. Padovan 100baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident) 1010a708f8fSGustavo F. Padovan { 1023df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 103baa7e1faSGustavo F. Padovan 1043df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 1053df91ea2SAndrei Emeltchenko if (c->ident == ident) 1063df91ea2SAndrei Emeltchenko return c; 1070a708f8fSGustavo F. Padovan } 1083df91ea2SAndrei Emeltchenko return NULL; 109baa7e1faSGustavo F. Padovan } 1100a708f8fSGustavo F. Padovan 11123691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src) 1129e4425ffSGustavo F. Padovan { 11323691d75SGustavo F. Padovan struct l2cap_chan *c; 1149e4425ffSGustavo F. Padovan 11523691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 11623691d75SGustavo F. Padovan if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src)) 11723691d75SGustavo F. Padovan return c; 1189e4425ffSGustavo F. Padovan } 119250938cbSSzymon Janc return NULL; 120250938cbSSzymon Janc } 1219e4425ffSGustavo F. Padovan 1229e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) 1239e4425ffSGustavo F. Padovan { 12473b2ec18SGustavo F. Padovan int err; 12573b2ec18SGustavo F. Padovan 126333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 1279e4425ffSGustavo F. Padovan 12823691d75SGustavo F. Padovan if (psm && __l2cap_global_chan_by_addr(psm, src)) { 12973b2ec18SGustavo F. Padovan err = -EADDRINUSE; 13073b2ec18SGustavo F. Padovan goto done; 1319e4425ffSGustavo F. Padovan } 1329e4425ffSGustavo F. Padovan 13373b2ec18SGustavo F. Padovan if (psm) { 1349e4425ffSGustavo F. Padovan chan->psm = psm; 1359e4425ffSGustavo F. Padovan chan->sport = psm; 13673b2ec18SGustavo F. Padovan err = 0; 13773b2ec18SGustavo F. Padovan } else { 13873b2ec18SGustavo F. Padovan u16 p; 1399e4425ffSGustavo F. Padovan 14073b2ec18SGustavo F. Padovan err = -EINVAL; 14173b2ec18SGustavo F. Padovan for (p = 0x1001; p < 0x1100; p += 2) 14223691d75SGustavo F. Padovan if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) { 14373b2ec18SGustavo F. Padovan chan->psm = cpu_to_le16(p); 14473b2ec18SGustavo F. Padovan chan->sport = cpu_to_le16(p); 14573b2ec18SGustavo F. Padovan err = 0; 14673b2ec18SGustavo F. Padovan break; 14773b2ec18SGustavo F. Padovan } 14873b2ec18SGustavo F. Padovan } 14973b2ec18SGustavo F. Padovan 15073b2ec18SGustavo F. Padovan done: 151333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 15273b2ec18SGustavo F. Padovan return err; 1539e4425ffSGustavo F. Padovan } 1549e4425ffSGustavo F. Padovan 1559e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) 1569e4425ffSGustavo F. Padovan { 157333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 1589e4425ffSGustavo F. Padovan 1599e4425ffSGustavo F. Padovan chan->scid = scid; 1609e4425ffSGustavo F. Padovan 161333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 1629e4425ffSGustavo F. Padovan 1639e4425ffSGustavo F. Padovan return 0; 1649e4425ffSGustavo F. Padovan } 1659e4425ffSGustavo F. Padovan 166baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn) 1670a708f8fSGustavo F. Padovan { 1680a708f8fSGustavo F. Padovan u16 cid = L2CAP_CID_DYN_START; 1690a708f8fSGustavo F. Padovan 1700a708f8fSGustavo F. Padovan for (; cid < L2CAP_CID_DYN_END; cid++) { 171baa7e1faSGustavo F. Padovan if (!__l2cap_get_chan_by_scid(conn, cid)) 1720a708f8fSGustavo F. Padovan return cid; 1730a708f8fSGustavo F. Padovan } 1740a708f8fSGustavo F. Padovan 1750a708f8fSGustavo F. Padovan return 0; 1760a708f8fSGustavo F. Padovan } 1770a708f8fSGustavo F. Padovan 1780e587be7SAndrei Emeltchenko static void __l2cap_state_change(struct l2cap_chan *chan, int state) 17989bc500eSGustavo F. Padovan { 18042d2d87cSAndrei Emeltchenko BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state), 181badaaa00SGustavo F. Padovan state_to_string(state)); 182badaaa00SGustavo F. Padovan 18389bc500eSGustavo F. Padovan chan->state = state; 18480b98027SGustavo Padovan chan->ops->state_change(chan, state); 18589bc500eSGustavo F. Padovan } 18689bc500eSGustavo F. Padovan 1870e587be7SAndrei Emeltchenko static void l2cap_state_change(struct l2cap_chan *chan, int state) 1880e587be7SAndrei Emeltchenko { 1890e587be7SAndrei Emeltchenko struct sock *sk = chan->sk; 1900e587be7SAndrei Emeltchenko 1910e587be7SAndrei Emeltchenko lock_sock(sk); 1920e587be7SAndrei Emeltchenko __l2cap_state_change(chan, state); 1930e587be7SAndrei Emeltchenko release_sock(sk); 1940e587be7SAndrei Emeltchenko } 1950e587be7SAndrei Emeltchenko 1962e0052e4SAndrei Emeltchenko static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err) 1972e0052e4SAndrei Emeltchenko { 1982e0052e4SAndrei Emeltchenko struct sock *sk = chan->sk; 1992e0052e4SAndrei Emeltchenko 2002e0052e4SAndrei Emeltchenko sk->sk_err = err; 2012e0052e4SAndrei Emeltchenko } 2022e0052e4SAndrei Emeltchenko 2032e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err) 2042e0052e4SAndrei Emeltchenko { 2052e0052e4SAndrei Emeltchenko struct sock *sk = chan->sk; 2062e0052e4SAndrei Emeltchenko 2072e0052e4SAndrei Emeltchenko lock_sock(sk); 2082e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 2092e0052e4SAndrei Emeltchenko release_sock(sk); 2102e0052e4SAndrei Emeltchenko } 2112e0052e4SAndrei Emeltchenko 2124239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan) 2134239d16fSMat Martineau { 2144239d16fSMat Martineau if (!delayed_work_pending(&chan->monitor_timer) && 2154239d16fSMat Martineau chan->retrans_timeout) { 2164239d16fSMat Martineau l2cap_set_timer(chan, &chan->retrans_timer, 2174239d16fSMat Martineau msecs_to_jiffies(chan->retrans_timeout)); 2184239d16fSMat Martineau } 2194239d16fSMat Martineau } 2204239d16fSMat Martineau 2214239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan) 2224239d16fSMat Martineau { 2234239d16fSMat Martineau __clear_retrans_timer(chan); 2244239d16fSMat Martineau if (chan->monitor_timeout) { 2254239d16fSMat Martineau l2cap_set_timer(chan, &chan->monitor_timer, 2264239d16fSMat Martineau msecs_to_jiffies(chan->monitor_timeout)); 2274239d16fSMat Martineau } 2284239d16fSMat Martineau } 2294239d16fSMat Martineau 230608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head, 231608bcc6dSMat Martineau u16 seq) 232608bcc6dSMat Martineau { 233608bcc6dSMat Martineau struct sk_buff *skb; 234608bcc6dSMat Martineau 235608bcc6dSMat Martineau skb_queue_walk(head, skb) { 236608bcc6dSMat Martineau if (bt_cb(skb)->control.txseq == seq) 237608bcc6dSMat Martineau return skb; 238608bcc6dSMat Martineau } 239608bcc6dSMat Martineau 240608bcc6dSMat Martineau return NULL; 241608bcc6dSMat Martineau } 242608bcc6dSMat Martineau 2433c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */ 2443c588192SMat Martineau 2453c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for 2463c588192SMat Martineau * SREJ requests that are received and for frames that are to be 2473c588192SMat Martineau * retransmitted. These seq_list functions implement a singly-linked 2483c588192SMat Martineau * list in an array, where membership in the list can also be checked 2493c588192SMat Martineau * in constant time. Items can also be added to the tail of the list 2503c588192SMat Martineau * and removed from the head in constant time, without further memory 2513c588192SMat Martineau * allocs or frees. 2523c588192SMat Martineau */ 2533c588192SMat Martineau 2543c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size) 2553c588192SMat Martineau { 2563c588192SMat Martineau size_t alloc_size, i; 2573c588192SMat Martineau 2583c588192SMat Martineau /* Allocated size is a power of 2 to map sequence numbers 2593c588192SMat Martineau * (which may be up to 14 bits) in to a smaller array that is 2603c588192SMat Martineau * sized for the negotiated ERTM transmit windows. 2613c588192SMat Martineau */ 2623c588192SMat Martineau alloc_size = roundup_pow_of_two(size); 2633c588192SMat Martineau 2643c588192SMat Martineau seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL); 2653c588192SMat Martineau if (!seq_list->list) 2663c588192SMat Martineau return -ENOMEM; 2673c588192SMat Martineau 2683c588192SMat Martineau seq_list->mask = alloc_size - 1; 2693c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 2703c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 2713c588192SMat Martineau for (i = 0; i < alloc_size; i++) 2723c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 2733c588192SMat Martineau 2743c588192SMat Martineau return 0; 2753c588192SMat Martineau } 2763c588192SMat Martineau 2773c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list) 2783c588192SMat Martineau { 2793c588192SMat Martineau kfree(seq_list->list); 2803c588192SMat Martineau } 2813c588192SMat Martineau 2823c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list, 2833c588192SMat Martineau u16 seq) 2843c588192SMat Martineau { 2853c588192SMat Martineau /* Constant-time check for list membership */ 2863c588192SMat Martineau return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR; 2873c588192SMat Martineau } 2883c588192SMat Martineau 2893c588192SMat Martineau static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq) 2903c588192SMat Martineau { 2913c588192SMat Martineau u16 mask = seq_list->mask; 2923c588192SMat Martineau 2933c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) { 2943c588192SMat Martineau /* In case someone tries to pop the head of an empty list */ 2953c588192SMat Martineau return L2CAP_SEQ_LIST_CLEAR; 2963c588192SMat Martineau } else if (seq_list->head == seq) { 2973c588192SMat Martineau /* Head can be removed in constant time */ 2983c588192SMat Martineau seq_list->head = seq_list->list[seq & mask]; 2993c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; 3003c588192SMat Martineau 3013c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_TAIL) { 3023c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3033c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3043c588192SMat Martineau } 3053c588192SMat Martineau } else { 3063c588192SMat Martineau /* Walk the list to find the sequence number */ 3073c588192SMat Martineau u16 prev = seq_list->head; 3083c588192SMat Martineau while (seq_list->list[prev & mask] != seq) { 3093c588192SMat Martineau prev = seq_list->list[prev & mask]; 3103c588192SMat Martineau if (prev == L2CAP_SEQ_LIST_TAIL) 3113c588192SMat Martineau return L2CAP_SEQ_LIST_CLEAR; 3123c588192SMat Martineau } 3133c588192SMat Martineau 3143c588192SMat Martineau /* Unlink the number from the list and clear it */ 3153c588192SMat Martineau seq_list->list[prev & mask] = seq_list->list[seq & mask]; 3163c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; 3173c588192SMat Martineau if (seq_list->tail == seq) 3183c588192SMat Martineau seq_list->tail = prev; 3193c588192SMat Martineau } 3203c588192SMat Martineau return seq; 3213c588192SMat Martineau } 3223c588192SMat Martineau 3233c588192SMat Martineau static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list) 3243c588192SMat Martineau { 3253c588192SMat Martineau /* Remove the head in constant time */ 3263c588192SMat Martineau return l2cap_seq_list_remove(seq_list, seq_list->head); 3273c588192SMat Martineau } 3283c588192SMat Martineau 3293c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list) 3303c588192SMat Martineau { 3313c588192SMat Martineau u16 i; 332f522ae36SGustavo Padovan 333f522ae36SGustavo Padovan if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) 334f522ae36SGustavo Padovan return; 335f522ae36SGustavo Padovan 3363c588192SMat Martineau for (i = 0; i <= seq_list->mask; i++) 3373c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 3383c588192SMat Martineau 3393c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3403c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3413c588192SMat Martineau } 3423c588192SMat Martineau 3433c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq) 3443c588192SMat Martineau { 3453c588192SMat Martineau u16 mask = seq_list->mask; 3463c588192SMat Martineau 3473c588192SMat Martineau /* All appends happen in constant time */ 3483c588192SMat Martineau 349f522ae36SGustavo Padovan if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR) 350f522ae36SGustavo Padovan return; 351f522ae36SGustavo Padovan 3523c588192SMat Martineau if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR) 3533c588192SMat Martineau seq_list->head = seq; 3543c588192SMat Martineau else 3553c588192SMat Martineau seq_list->list[seq_list->tail & mask] = seq; 3563c588192SMat Martineau 3573c588192SMat Martineau seq_list->tail = seq; 3583c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL; 3593c588192SMat Martineau } 3603c588192SMat Martineau 361721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work) 362ab07801dSGustavo F. Padovan { 363721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 364721c4181SGustavo F. Padovan chan_timer.work); 3653df91ea2SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 366ab07801dSGustavo F. Padovan int reason; 367ab07801dSGustavo F. Padovan 368e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 369ab07801dSGustavo F. Padovan 3703df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 3716be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 372ab07801dSGustavo F. Padovan 37389bc500eSGustavo F. Padovan if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) 374ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 37589bc500eSGustavo F. Padovan else if (chan->state == BT_CONNECT && 376ab07801dSGustavo F. Padovan chan->sec_level != BT_SECURITY_SDP) 377ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 378ab07801dSGustavo F. Padovan else 379ab07801dSGustavo F. Padovan reason = ETIMEDOUT; 380ab07801dSGustavo F. Padovan 3810f852724SGustavo F. Padovan l2cap_chan_close(chan, reason); 382ab07801dSGustavo F. Padovan 3836be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 384ab07801dSGustavo F. Padovan 38580b98027SGustavo Padovan chan->ops->close(chan); 3863df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 3873df91ea2SAndrei Emeltchenko 388371fd835SUlisses Furquim l2cap_chan_put(chan); 389ab07801dSGustavo F. Padovan } 390ab07801dSGustavo F. Padovan 391eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void) 3920a708f8fSGustavo F. Padovan { 39348454079SGustavo F. Padovan struct l2cap_chan *chan; 3940a708f8fSGustavo F. Padovan 39548454079SGustavo F. Padovan chan = kzalloc(sizeof(*chan), GFP_ATOMIC); 39648454079SGustavo F. Padovan if (!chan) 39748454079SGustavo F. Padovan return NULL; 3980a708f8fSGustavo F. Padovan 399c03b355eSAndrei Emeltchenko mutex_init(&chan->lock); 400c03b355eSAndrei Emeltchenko 401333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 40223691d75SGustavo F. Padovan list_add(&chan->global_l, &chan_list); 403333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 40423691d75SGustavo F. Padovan 405721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout); 406ab07801dSGustavo F. Padovan 40789bc500eSGustavo F. Padovan chan->state = BT_OPEN; 40889bc500eSGustavo F. Padovan 40971ba0e56SGustavo F. Padovan atomic_set(&chan->refcnt, 1); 41071ba0e56SGustavo F. Padovan 4112827011fSMat Martineau /* This flag is cleared in l2cap_chan_ready() */ 4122827011fSMat Martineau set_bit(CONF_NOT_COMPLETE, &chan->conf_state); 4132827011fSMat Martineau 414eef1d9b6SGustavo Padovan BT_DBG("chan %p", chan); 415abc545b8SSzymon Janc 41648454079SGustavo F. Padovan return chan; 4170a708f8fSGustavo F. Padovan } 4180a708f8fSGustavo F. Padovan 41923691d75SGustavo F. Padovan void l2cap_chan_destroy(struct l2cap_chan *chan) 4206ff5abbfSGustavo F. Padovan { 421333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 42223691d75SGustavo F. Padovan list_del(&chan->global_l); 423333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 42423691d75SGustavo F. Padovan 425371fd835SUlisses Furquim l2cap_chan_put(chan); 4266ff5abbfSGustavo F. Padovan } 4276ff5abbfSGustavo F. Padovan 428*30648372SJaganath Kanakkassery void l2cap_chan_hold(struct l2cap_chan *c) 429*30648372SJaganath Kanakkassery { 430*30648372SJaganath Kanakkassery BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); 431*30648372SJaganath Kanakkassery 432*30648372SJaganath Kanakkassery atomic_inc(&c->refcnt); 433*30648372SJaganath Kanakkassery } 434*30648372SJaganath Kanakkassery 435*30648372SJaganath Kanakkassery void l2cap_chan_put(struct l2cap_chan *c) 436*30648372SJaganath Kanakkassery { 437*30648372SJaganath Kanakkassery BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); 438*30648372SJaganath Kanakkassery 439*30648372SJaganath Kanakkassery if (atomic_dec_and_test(&c->refcnt)) 440*30648372SJaganath Kanakkassery kfree(c); 441*30648372SJaganath Kanakkassery } 442*30648372SJaganath Kanakkassery 443bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan) 444bd4b1653SAndrei Emeltchenko { 445bd4b1653SAndrei Emeltchenko chan->fcs = L2CAP_FCS_CRC16; 446bd4b1653SAndrei Emeltchenko chan->max_tx = L2CAP_DEFAULT_MAX_TX; 447bd4b1653SAndrei Emeltchenko chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; 448bd4b1653SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 449c20f8e35SMat Martineau chan->ack_win = L2CAP_DEFAULT_TX_WINDOW; 450bd4b1653SAndrei Emeltchenko chan->sec_level = BT_SECURITY_LOW; 451bd4b1653SAndrei Emeltchenko 452bd4b1653SAndrei Emeltchenko set_bit(FLAG_FORCE_ACTIVE, &chan->flags); 453bd4b1653SAndrei Emeltchenko } 454bd4b1653SAndrei Emeltchenko 45514a28491SAndrei Emeltchenko static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 4560a708f8fSGustavo F. Padovan { 4570a708f8fSGustavo F. Padovan BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, 458097db76cSAndrei Emeltchenko __le16_to_cpu(chan->psm), chan->dcid); 4590a708f8fSGustavo F. Padovan 4609f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 4610a708f8fSGustavo F. Padovan 4628c1d787bSGustavo F. Padovan chan->conn = conn; 4630a708f8fSGustavo F. Padovan 4645491120eSAndrei Emeltchenko switch (chan->chan_type) { 4655491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_ORIENTED: 466b62f328bSVille Tervo if (conn->hcon->type == LE_LINK) { 467b62f328bSVille Tervo /* LE connection */ 4686fcb06a2SAndre Guedes chan->omtu = L2CAP_DEFAULT_MTU; 469fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_LE_DATA; 470fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_LE_DATA; 471b62f328bSVille Tervo } else { 4720a708f8fSGustavo F. Padovan /* Alloc CID for connection-oriented socket */ 473fe4128e0SGustavo F. Padovan chan->scid = l2cap_alloc_cid(conn); 4740c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 475b62f328bSVille Tervo } 4765491120eSAndrei Emeltchenko break; 4775491120eSAndrei Emeltchenko 4785491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_LESS: 4790a708f8fSGustavo F. Padovan /* Connectionless socket */ 480fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_CONN_LESS; 481fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_CONN_LESS; 4820c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 4835491120eSAndrei Emeltchenko break; 4845491120eSAndrei Emeltchenko 485416fa752SAndrei Emeltchenko case L2CAP_CHAN_CONN_FIX_A2MP: 486416fa752SAndrei Emeltchenko chan->scid = L2CAP_CID_A2MP; 487416fa752SAndrei Emeltchenko chan->dcid = L2CAP_CID_A2MP; 488416fa752SAndrei Emeltchenko chan->omtu = L2CAP_A2MP_DEFAULT_MTU; 489416fa752SAndrei Emeltchenko chan->imtu = L2CAP_A2MP_DEFAULT_MTU; 490416fa752SAndrei Emeltchenko break; 491416fa752SAndrei Emeltchenko 4925491120eSAndrei Emeltchenko default: 4930a708f8fSGustavo F. Padovan /* Raw socket can send/recv signalling messages only */ 494fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_SIGNALING; 495fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_SIGNALING; 4960c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 4970a708f8fSGustavo F. Padovan } 4980a708f8fSGustavo F. Padovan 4998f7975b1SAndrei Emeltchenko chan->local_id = L2CAP_BESTEFFORT_ID; 5008f7975b1SAndrei Emeltchenko chan->local_stype = L2CAP_SERV_BESTEFFORT; 5018f7975b1SAndrei Emeltchenko chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE; 5028f7975b1SAndrei Emeltchenko chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME; 5038f7975b1SAndrei Emeltchenko chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT; 5048f7975b1SAndrei Emeltchenko chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO; 5058f7975b1SAndrei Emeltchenko 506371fd835SUlisses Furquim l2cap_chan_hold(chan); 507baa7e1faSGustavo F. Padovan 5083df91ea2SAndrei Emeltchenko list_add(&chan->list, &conn->chan_l); 509643162a8SAndrei Emeltchenko } 510643162a8SAndrei Emeltchenko 511466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 512643162a8SAndrei Emeltchenko { 513643162a8SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 514643162a8SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 5153df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 5160a708f8fSGustavo F. Padovan } 5170a708f8fSGustavo F. Padovan 518466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err) 5190a708f8fSGustavo F. Padovan { 5208c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 5210a708f8fSGustavo F. Padovan 522c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 5230a708f8fSGustavo F. Padovan 52449208c9cSGustavo F. Padovan BT_DBG("chan %p, conn %p, err %d", chan, conn, err); 5250a708f8fSGustavo F. Padovan 5260a708f8fSGustavo F. Padovan if (conn) { 527baa7e1faSGustavo F. Padovan /* Delete from channel list */ 5283df91ea2SAndrei Emeltchenko list_del(&chan->list); 5293d57dc68SGustavo F. Padovan 530371fd835SUlisses Furquim l2cap_chan_put(chan); 531baa7e1faSGustavo F. Padovan 5328c1d787bSGustavo F. Padovan chan->conn = NULL; 5333cabbfdaSAndrei Emeltchenko 5343cabbfdaSAndrei Emeltchenko if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP) 5350a708f8fSGustavo F. Padovan hci_conn_put(conn->hcon); 5360a708f8fSGustavo F. Padovan } 5370a708f8fSGustavo F. Padovan 538c0df7f6eSAndrei Emeltchenko if (chan->ops->teardown) 539c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, err); 5406be36555SAndrei Emeltchenko 5412827011fSMat Martineau if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) 5426ff5abbfSGustavo F. Padovan return; 5432ead70b8SGustavo F. Padovan 544ee556f66SGustavo Padovan switch(chan->mode) { 545ee556f66SGustavo Padovan case L2CAP_MODE_BASIC: 546ee556f66SGustavo Padovan break; 5470a708f8fSGustavo F. Padovan 548ee556f66SGustavo Padovan case L2CAP_MODE_ERTM: 5491a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 5501a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 5511a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 5520a708f8fSGustavo F. Padovan 553f1c6775bSGustavo F. Padovan skb_queue_purge(&chan->srej_q); 5540a708f8fSGustavo F. Padovan 5553c588192SMat Martineau l2cap_seq_list_free(&chan->srej_list); 5563c588192SMat Martineau l2cap_seq_list_free(&chan->retrans_list); 557ee556f66SGustavo Padovan 558ee556f66SGustavo Padovan /* fall through */ 559ee556f66SGustavo Padovan 560ee556f66SGustavo Padovan case L2CAP_MODE_STREAMING: 561ee556f66SGustavo Padovan skb_queue_purge(&chan->tx_q); 562ee556f66SGustavo Padovan break; 5630a708f8fSGustavo F. Padovan } 564ee556f66SGustavo Padovan 565ee556f66SGustavo Padovan return; 5660a708f8fSGustavo F. Padovan } 5670a708f8fSGustavo F. Padovan 5680f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason) 5694519de9aSGustavo F. Padovan { 5704519de9aSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 5714519de9aSGustavo F. Padovan struct sock *sk = chan->sk; 5724519de9aSGustavo F. Padovan 573e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s sk %p", chan, 574e05dcc32SAndrei Emeltchenko state_to_string(chan->state), sk); 5754519de9aSGustavo F. Padovan 57689bc500eSGustavo F. Padovan switch (chan->state) { 5774519de9aSGustavo F. Padovan case BT_LISTEN: 578c0df7f6eSAndrei Emeltchenko if (chan->ops->teardown) 579c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 5804519de9aSGustavo F. Padovan break; 5814519de9aSGustavo F. Padovan 5824519de9aSGustavo F. Padovan case BT_CONNECTED: 5834519de9aSGustavo F. Padovan case BT_CONFIG: 584715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && 5854519de9aSGustavo F. Padovan conn->hcon->type == ACL_LINK) { 586c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 5874519de9aSGustavo F. Padovan l2cap_send_disconn_req(conn, chan, reason); 5884519de9aSGustavo F. Padovan } else 5894519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 5904519de9aSGustavo F. Padovan break; 5914519de9aSGustavo F. Padovan 5924519de9aSGustavo F. Padovan case BT_CONNECT2: 593715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && 5944519de9aSGustavo F. Padovan conn->hcon->type == ACL_LINK) { 5954519de9aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 5964519de9aSGustavo F. Padovan __u16 result; 5974519de9aSGustavo F. Padovan 598c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) 5994519de9aSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 6004519de9aSGustavo F. Padovan else 6014519de9aSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 60289bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_DISCONN); 6034519de9aSGustavo F. Padovan 6044519de9aSGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 6054519de9aSGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 6064519de9aSGustavo F. Padovan rsp.result = cpu_to_le16(result); 607ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 6084519de9aSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 6094519de9aSGustavo F. Padovan sizeof(rsp), &rsp); 6104519de9aSGustavo F. Padovan } 6114519de9aSGustavo F. Padovan 6124519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 6134519de9aSGustavo F. Padovan break; 6144519de9aSGustavo F. Padovan 6154519de9aSGustavo F. Padovan case BT_CONNECT: 6164519de9aSGustavo F. Padovan case BT_DISCONN: 6174519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 6184519de9aSGustavo F. Padovan break; 6194519de9aSGustavo F. Padovan 6204519de9aSGustavo F. Padovan default: 621c0df7f6eSAndrei Emeltchenko if (chan->ops->teardown) 622c0df7f6eSAndrei Emeltchenko chan->ops->teardown(chan, 0); 6234519de9aSGustavo F. Padovan break; 6244519de9aSGustavo F. Padovan } 6254519de9aSGustavo F. Padovan } 6264519de9aSGustavo F. Padovan 6274343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) 6280a708f8fSGustavo F. Padovan { 629715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_RAW) { 6304343478fSGustavo F. Padovan switch (chan->sec_level) { 6310a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 6320a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING_MITM; 6330a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 6340a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING; 6350a708f8fSGustavo F. Padovan default: 6360a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 6370a708f8fSGustavo F. Padovan } 6382983fd68SAndrei Emeltchenko } else if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) { 6394343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_LOW) 6404343478fSGustavo F. Padovan chan->sec_level = BT_SECURITY_SDP; 6410a708f8fSGustavo F. Padovan 6424343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_HIGH) 6430a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING_MITM; 6440a708f8fSGustavo F. Padovan else 6450a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 6460a708f8fSGustavo F. Padovan } else { 6474343478fSGustavo F. Padovan switch (chan->sec_level) { 6480a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 6490a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING_MITM; 6500a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 6510a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING; 6520a708f8fSGustavo F. Padovan default: 6530a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 6540a708f8fSGustavo F. Padovan } 6550a708f8fSGustavo F. Padovan } 6560a708f8fSGustavo F. Padovan } 6570a708f8fSGustavo F. Padovan 6580a708f8fSGustavo F. Padovan /* Service level security */ 659d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan) 6600a708f8fSGustavo F. Padovan { 6618c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 6620a708f8fSGustavo F. Padovan __u8 auth_type; 6630a708f8fSGustavo F. Padovan 6644343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 6650a708f8fSGustavo F. Padovan 6664343478fSGustavo F. Padovan return hci_conn_security(conn->hcon, chan->sec_level, auth_type); 6670a708f8fSGustavo F. Padovan } 6680a708f8fSGustavo F. Padovan 669b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn) 6700a708f8fSGustavo F. Padovan { 6710a708f8fSGustavo F. Padovan u8 id; 6720a708f8fSGustavo F. Padovan 6730a708f8fSGustavo F. Padovan /* Get next available identificator. 6740a708f8fSGustavo F. Padovan * 1 - 128 are used by kernel. 6750a708f8fSGustavo F. Padovan * 129 - 199 are reserved. 6760a708f8fSGustavo F. Padovan * 200 - 254 are used by utilities like l2ping, etc. 6770a708f8fSGustavo F. Padovan */ 6780a708f8fSGustavo F. Padovan 679333055f2SGustavo F. Padovan spin_lock(&conn->lock); 6800a708f8fSGustavo F. Padovan 6810a708f8fSGustavo F. Padovan if (++conn->tx_ident > 128) 6820a708f8fSGustavo F. Padovan conn->tx_ident = 1; 6830a708f8fSGustavo F. Padovan 6840a708f8fSGustavo F. Padovan id = conn->tx_ident; 6850a708f8fSGustavo F. Padovan 686333055f2SGustavo F. Padovan spin_unlock(&conn->lock); 6870a708f8fSGustavo F. Padovan 6880a708f8fSGustavo F. Padovan return id; 6890a708f8fSGustavo F. Padovan } 6900a708f8fSGustavo F. Padovan 6914519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) 6920a708f8fSGustavo F. Padovan { 6930a708f8fSGustavo F. Padovan struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); 6940a708f8fSGustavo F. Padovan u8 flags; 6950a708f8fSGustavo F. Padovan 6960a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x", code); 6970a708f8fSGustavo F. Padovan 6980a708f8fSGustavo F. Padovan if (!skb) 6990a708f8fSGustavo F. Padovan return; 7000a708f8fSGustavo F. Padovan 7010a708f8fSGustavo F. Padovan if (lmp_no_flush_capable(conn->hcon->hdev)) 7020a708f8fSGustavo F. Padovan flags = ACL_START_NO_FLUSH; 7030a708f8fSGustavo F. Padovan else 7040a708f8fSGustavo F. Padovan flags = ACL_START; 7050a708f8fSGustavo F. Padovan 70614b12d0bSJaikumar Ganesh bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON; 7075e59b791SLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 70814b12d0bSJaikumar Ganesh 70973d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, flags); 7100a708f8fSGustavo F. Padovan } 7110a708f8fSGustavo F. Padovan 71273d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) 71373d80debSLuiz Augusto von Dentz { 71473d80debSLuiz Augusto von Dentz struct hci_conn *hcon = chan->conn->hcon; 71573d80debSLuiz Augusto von Dentz u16 flags; 71673d80debSLuiz Augusto von Dentz 71773d80debSLuiz Augusto von Dentz BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, 71873d80debSLuiz Augusto von Dentz skb->priority); 71973d80debSLuiz Augusto von Dentz 72073d80debSLuiz Augusto von Dentz if (!test_bit(FLAG_FLUSHABLE, &chan->flags) && 72173d80debSLuiz Augusto von Dentz lmp_no_flush_capable(hcon->hdev)) 72273d80debSLuiz Augusto von Dentz flags = ACL_START_NO_FLUSH; 72373d80debSLuiz Augusto von Dentz else 72473d80debSLuiz Augusto von Dentz flags = ACL_START; 72573d80debSLuiz Augusto von Dentz 72673d80debSLuiz Augusto von Dentz bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); 72773d80debSLuiz Augusto von Dentz hci_send_acl(chan->conn->hchan, skb, flags); 7280a708f8fSGustavo F. Padovan } 7290a708f8fSGustavo F. Padovan 730b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control) 731b5c6aaedSMat Martineau { 732b5c6aaedSMat Martineau control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT; 733b5c6aaedSMat Martineau control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT; 734b5c6aaedSMat Martineau 735b5c6aaedSMat Martineau if (enh & L2CAP_CTRL_FRAME_TYPE) { 736b5c6aaedSMat Martineau /* S-Frame */ 737b5c6aaedSMat Martineau control->sframe = 1; 738b5c6aaedSMat Martineau control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT; 739b5c6aaedSMat Martineau control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT; 740b5c6aaedSMat Martineau 741b5c6aaedSMat Martineau control->sar = 0; 742b5c6aaedSMat Martineau control->txseq = 0; 743b5c6aaedSMat Martineau } else { 744b5c6aaedSMat Martineau /* I-Frame */ 745b5c6aaedSMat Martineau control->sframe = 0; 746b5c6aaedSMat Martineau control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT; 747b5c6aaedSMat Martineau control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT; 748b5c6aaedSMat Martineau 749b5c6aaedSMat Martineau control->poll = 0; 750b5c6aaedSMat Martineau control->super = 0; 751b5c6aaedSMat Martineau } 752b5c6aaedSMat Martineau } 753b5c6aaedSMat Martineau 754b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control) 755b5c6aaedSMat Martineau { 756b5c6aaedSMat Martineau control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT; 757b5c6aaedSMat Martineau control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT; 758b5c6aaedSMat Martineau 759b5c6aaedSMat Martineau if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) { 760b5c6aaedSMat Martineau /* S-Frame */ 761b5c6aaedSMat Martineau control->sframe = 1; 762b5c6aaedSMat Martineau control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT; 763b5c6aaedSMat Martineau control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT; 764b5c6aaedSMat Martineau 765b5c6aaedSMat Martineau control->sar = 0; 766b5c6aaedSMat Martineau control->txseq = 0; 767b5c6aaedSMat Martineau } else { 768b5c6aaedSMat Martineau /* I-Frame */ 769b5c6aaedSMat Martineau control->sframe = 0; 770b5c6aaedSMat Martineau control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT; 771b5c6aaedSMat Martineau control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT; 772b5c6aaedSMat Martineau 773b5c6aaedSMat Martineau control->poll = 0; 774b5c6aaedSMat Martineau control->super = 0; 775b5c6aaedSMat Martineau } 776b5c6aaedSMat Martineau } 777b5c6aaedSMat Martineau 778b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan, 779b5c6aaedSMat Martineau struct sk_buff *skb) 780b5c6aaedSMat Martineau { 781b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 782b5c6aaedSMat Martineau __unpack_extended_control(get_unaligned_le32(skb->data), 783b5c6aaedSMat Martineau &bt_cb(skb)->control); 784cec8ab6eSMat Martineau skb_pull(skb, L2CAP_EXT_CTRL_SIZE); 785b5c6aaedSMat Martineau } else { 786b5c6aaedSMat Martineau __unpack_enhanced_control(get_unaligned_le16(skb->data), 787b5c6aaedSMat Martineau &bt_cb(skb)->control); 788cec8ab6eSMat Martineau skb_pull(skb, L2CAP_ENH_CTRL_SIZE); 789b5c6aaedSMat Martineau } 790b5c6aaedSMat Martineau } 791b5c6aaedSMat Martineau 792b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control) 793b5c6aaedSMat Martineau { 794b5c6aaedSMat Martineau u32 packed; 795b5c6aaedSMat Martineau 796b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT; 797b5c6aaedSMat Martineau packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT; 798b5c6aaedSMat Martineau 799b5c6aaedSMat Martineau if (control->sframe) { 800b5c6aaedSMat Martineau packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT; 801b5c6aaedSMat Martineau packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT; 802b5c6aaedSMat Martineau packed |= L2CAP_EXT_CTRL_FRAME_TYPE; 803b5c6aaedSMat Martineau } else { 804b5c6aaedSMat Martineau packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT; 805b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT; 806b5c6aaedSMat Martineau } 807b5c6aaedSMat Martineau 808b5c6aaedSMat Martineau return packed; 809b5c6aaedSMat Martineau } 810b5c6aaedSMat Martineau 811b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control) 812b5c6aaedSMat Martineau { 813b5c6aaedSMat Martineau u16 packed; 814b5c6aaedSMat Martineau 815b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT; 816b5c6aaedSMat Martineau packed |= control->final << L2CAP_CTRL_FINAL_SHIFT; 817b5c6aaedSMat Martineau 818b5c6aaedSMat Martineau if (control->sframe) { 819b5c6aaedSMat Martineau packed |= control->poll << L2CAP_CTRL_POLL_SHIFT; 820b5c6aaedSMat Martineau packed |= control->super << L2CAP_CTRL_SUPER_SHIFT; 821b5c6aaedSMat Martineau packed |= L2CAP_CTRL_FRAME_TYPE; 822b5c6aaedSMat Martineau } else { 823b5c6aaedSMat Martineau packed |= control->sar << L2CAP_CTRL_SAR_SHIFT; 824b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT; 825b5c6aaedSMat Martineau } 826b5c6aaedSMat Martineau 827b5c6aaedSMat Martineau return packed; 828b5c6aaedSMat Martineau } 829b5c6aaedSMat Martineau 830b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan, 831b5c6aaedSMat Martineau struct l2cap_ctrl *control, 832b5c6aaedSMat Martineau struct sk_buff *skb) 833b5c6aaedSMat Martineau { 834b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 835b5c6aaedSMat Martineau put_unaligned_le32(__pack_extended_control(control), 836b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 837b5c6aaedSMat Martineau } else { 838b5c6aaedSMat Martineau put_unaligned_le16(__pack_enhanced_control(control), 839b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 840b5c6aaedSMat Martineau } 841b5c6aaedSMat Martineau } 842b5c6aaedSMat Martineau 843ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan) 844ba7aa64fSGustavo Padovan { 845ba7aa64fSGustavo Padovan if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 846ba7aa64fSGustavo Padovan return L2CAP_EXT_HDR_SIZE; 847ba7aa64fSGustavo Padovan else 848ba7aa64fSGustavo Padovan return L2CAP_ENH_HDR_SIZE; 849ba7aa64fSGustavo Padovan } 850ba7aa64fSGustavo Padovan 851a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan, 852a67d7f6fSMat Martineau u32 control) 8530a708f8fSGustavo F. Padovan { 8540a708f8fSGustavo F. Padovan struct sk_buff *skb; 8550a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 856ba7aa64fSGustavo Padovan int hlen = __ertm_hdr_size(chan); 8570a708f8fSGustavo F. Padovan 8580a708f8fSGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 85903a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 8600a708f8fSGustavo F. Padovan 861a67d7f6fSMat Martineau skb = bt_skb_alloc(hlen, GFP_KERNEL); 8620a708f8fSGustavo F. Padovan 8630a708f8fSGustavo F. Padovan if (!skb) 864a67d7f6fSMat Martineau return ERR_PTR(-ENOMEM); 8650a708f8fSGustavo F. Padovan 8660a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 8670a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); 868fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 86988843ab0SAndrei Emeltchenko 870a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 871a67d7f6fSMat Martineau put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 872a67d7f6fSMat Martineau else 873a67d7f6fSMat Martineau put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 8740a708f8fSGustavo F. Padovan 87547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 876a67d7f6fSMat Martineau u16 fcs = crc16(0, (u8 *)skb->data, skb->len); 87703a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 8780a708f8fSGustavo F. Padovan } 8790a708f8fSGustavo F. Padovan 88073d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 881a67d7f6fSMat Martineau return skb; 882a67d7f6fSMat Martineau } 883a67d7f6fSMat Martineau 884a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan, 885a67d7f6fSMat Martineau struct l2cap_ctrl *control) 886a67d7f6fSMat Martineau { 887a67d7f6fSMat Martineau struct sk_buff *skb; 888a67d7f6fSMat Martineau u32 control_field; 889a67d7f6fSMat Martineau 890a67d7f6fSMat Martineau BT_DBG("chan %p, control %p", chan, control); 891a67d7f6fSMat Martineau 892a67d7f6fSMat Martineau if (!control->sframe) 893a67d7f6fSMat Martineau return; 894a67d7f6fSMat Martineau 895a67d7f6fSMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) && 896a67d7f6fSMat Martineau !control->poll) 897a67d7f6fSMat Martineau control->final = 1; 898a67d7f6fSMat Martineau 899a67d7f6fSMat Martineau if (control->super == L2CAP_SUPER_RR) 900a67d7f6fSMat Martineau clear_bit(CONN_RNR_SENT, &chan->conn_state); 901a67d7f6fSMat Martineau else if (control->super == L2CAP_SUPER_RNR) 902a67d7f6fSMat Martineau set_bit(CONN_RNR_SENT, &chan->conn_state); 903a67d7f6fSMat Martineau 904a67d7f6fSMat Martineau if (control->super != L2CAP_SUPER_SREJ) { 905a67d7f6fSMat Martineau chan->last_acked_seq = control->reqseq; 906a67d7f6fSMat Martineau __clear_ack_timer(chan); 907a67d7f6fSMat Martineau } 908a67d7f6fSMat Martineau 909a67d7f6fSMat Martineau BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq, 910a67d7f6fSMat Martineau control->final, control->poll, control->super); 911a67d7f6fSMat Martineau 912a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 913a67d7f6fSMat Martineau control_field = __pack_extended_control(control); 914a67d7f6fSMat Martineau else 915a67d7f6fSMat Martineau control_field = __pack_enhanced_control(control); 916a67d7f6fSMat Martineau 917a67d7f6fSMat Martineau skb = l2cap_create_sframe_pdu(chan, control_field); 918a67d7f6fSMat Martineau if (!IS_ERR(skb)) 91973d80debSLuiz Augusto von Dentz l2cap_do_send(chan, skb); 9200a708f8fSGustavo F. Padovan } 9210a708f8fSGustavo F. Padovan 922c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll) 9230a708f8fSGustavo F. Padovan { 924c9e3d5e0SMat Martineau struct l2cap_ctrl control; 9250a708f8fSGustavo F. Padovan 926c9e3d5e0SMat Martineau BT_DBG("chan %p, poll %d", chan, poll); 927c9e3d5e0SMat Martineau 928c9e3d5e0SMat Martineau memset(&control, 0, sizeof(control)); 929c9e3d5e0SMat Martineau control.sframe = 1; 930c9e3d5e0SMat Martineau control.poll = poll; 931c9e3d5e0SMat Martineau 932c9e3d5e0SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 933c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RNR; 934c9e3d5e0SMat Martineau else 935c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RR; 936c9e3d5e0SMat Martineau 937c9e3d5e0SMat Martineau control.reqseq = chan->buffer_seq; 938c9e3d5e0SMat Martineau l2cap_send_sframe(chan, &control); 9390a708f8fSGustavo F. Padovan } 9400a708f8fSGustavo F. Padovan 941b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) 9420a708f8fSGustavo F. Padovan { 943c1360a1cSGustavo F. Padovan return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); 9440a708f8fSGustavo F. Padovan } 9450a708f8fSGustavo F. Padovan 9469b27f350SAndrei Emeltchenko static void l2cap_send_conn_req(struct l2cap_chan *chan) 9479b27f350SAndrei Emeltchenko { 9489b27f350SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 9499b27f350SAndrei Emeltchenko struct l2cap_conn_req req; 9509b27f350SAndrei Emeltchenko 9519b27f350SAndrei Emeltchenko req.scid = cpu_to_le16(chan->scid); 9529b27f350SAndrei Emeltchenko req.psm = chan->psm; 9539b27f350SAndrei Emeltchenko 9549b27f350SAndrei Emeltchenko chan->ident = l2cap_get_ident(conn); 9559b27f350SAndrei Emeltchenko 9569b27f350SAndrei Emeltchenko set_bit(CONF_CONNECT_PEND, &chan->conf_state); 9579b27f350SAndrei Emeltchenko 9589b27f350SAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); 9599b27f350SAndrei Emeltchenko } 9609b27f350SAndrei Emeltchenko 9619f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan) 9629f0caeb1SVinicius Costa Gomes { 9632827011fSMat Martineau /* This clears all conf flags, including CONF_NOT_COMPLETE */ 9649f0caeb1SVinicius Costa Gomes chan->conf_state = 0; 9659f0caeb1SVinicius Costa Gomes __clear_chan_timer(chan); 9669f0caeb1SVinicius Costa Gomes 96754a59aa2SAndrei Emeltchenko chan->state = BT_CONNECTED; 9689f0caeb1SVinicius Costa Gomes 96954a59aa2SAndrei Emeltchenko chan->ops->ready(chan); 9709f0caeb1SVinicius Costa Gomes } 9719f0caeb1SVinicius Costa Gomes 972fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan) 9730a708f8fSGustavo F. Padovan { 9748c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 9750a708f8fSGustavo F. Padovan 9769f0caeb1SVinicius Costa Gomes if (conn->hcon->type == LE_LINK) { 9779f0caeb1SVinicius Costa Gomes l2cap_chan_ready(chan); 9789f0caeb1SVinicius Costa Gomes return; 9799f0caeb1SVinicius Costa Gomes } 9809f0caeb1SVinicius Costa Gomes 9810a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { 9820a708f8fSGustavo F. Padovan if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) 9830a708f8fSGustavo F. Padovan return; 9840a708f8fSGustavo F. Padovan 985d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan) && 9869b27f350SAndrei Emeltchenko __l2cap_no_conn_pending(chan)) 9879b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 9880a708f8fSGustavo F. Padovan } else { 9890a708f8fSGustavo F. Padovan struct l2cap_info_req req; 990ac73498cSAndrei Emeltchenko req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); 9910a708f8fSGustavo F. Padovan 9920a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 9930a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 9940a708f8fSGustavo F. Padovan 995ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 9960a708f8fSGustavo F. Padovan 9970a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 9980a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 9990a708f8fSGustavo F. Padovan } 10000a708f8fSGustavo F. Padovan } 10010a708f8fSGustavo F. Padovan 10020a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) 10030a708f8fSGustavo F. Padovan { 10040a708f8fSGustavo F. Padovan u32 local_feat_mask = l2cap_feat_mask; 10050a708f8fSGustavo F. Padovan if (!disable_ertm) 10060a708f8fSGustavo F. Padovan local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING; 10070a708f8fSGustavo F. Padovan 10080a708f8fSGustavo F. Padovan switch (mode) { 10090a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 10100a708f8fSGustavo F. Padovan return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask; 10110a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 10120a708f8fSGustavo F. Padovan return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask; 10130a708f8fSGustavo F. Padovan default: 10140a708f8fSGustavo F. Padovan return 0x00; 10150a708f8fSGustavo F. Padovan } 10160a708f8fSGustavo F. Padovan } 10170a708f8fSGustavo F. Padovan 10184519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err) 10190a708f8fSGustavo F. Padovan { 10206be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 10210a708f8fSGustavo F. Padovan struct l2cap_disconn_req req; 10220a708f8fSGustavo F. Padovan 10230a708f8fSGustavo F. Padovan if (!conn) 10240a708f8fSGustavo F. Padovan return; 10250a708f8fSGustavo F. Padovan 10260c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_ERTM) { 10271a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 10281a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 10291a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 10300a708f8fSGustavo F. Padovan } 10310a708f8fSGustavo F. Padovan 1032416fa752SAndrei Emeltchenko if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { 1033416fa752SAndrei Emeltchenko __l2cap_state_change(chan, BT_DISCONN); 1034416fa752SAndrei Emeltchenko return; 1035416fa752SAndrei Emeltchenko } 1036416fa752SAndrei Emeltchenko 1037fe4128e0SGustavo F. Padovan req.dcid = cpu_to_le16(chan->dcid); 1038fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 10390a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 10400a708f8fSGustavo F. Padovan L2CAP_DISCONN_REQ, sizeof(req), &req); 10410a708f8fSGustavo F. Padovan 10426be36555SAndrei Emeltchenko lock_sock(sk); 10430e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_DISCONN); 10442e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 10456be36555SAndrei Emeltchenko release_sock(sk); 10460a708f8fSGustavo F. Padovan } 10470a708f8fSGustavo F. Padovan 10480a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */ 10490a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn) 10500a708f8fSGustavo F. Padovan { 10513df91ea2SAndrei Emeltchenko struct l2cap_chan *chan, *tmp; 10520a708f8fSGustavo F. Padovan 10530a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 10540a708f8fSGustavo F. Padovan 10553df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 10560a708f8fSGustavo F. Padovan 10573df91ea2SAndrei Emeltchenko list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 105848454079SGustavo F. Padovan struct sock *sk = chan->sk; 1059baa7e1faSGustavo F. Padovan 10606be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 10610a708f8fSGustavo F. Padovan 1062715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 10636be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10640a708f8fSGustavo F. Padovan continue; 10650a708f8fSGustavo F. Padovan } 10660a708f8fSGustavo F. Padovan 106789bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 1068d45fc423SGustavo F. Padovan if (!l2cap_chan_check_security(chan) || 1069b4450035SGustavo F. Padovan !__l2cap_no_conn_pending(chan)) { 10706be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10710a708f8fSGustavo F. Padovan continue; 10720a708f8fSGustavo F. Padovan } 10730a708f8fSGustavo F. Padovan 1074c1360a1cSGustavo F. Padovan if (!l2cap_mode_supported(chan->mode, conn->feat_mask) 1075c1360a1cSGustavo F. Padovan && test_bit(CONF_STATE2_DEVICE, 1076c1360a1cSGustavo F. Padovan &chan->conf_state)) { 10770f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 10786be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10790a708f8fSGustavo F. Padovan continue; 10800a708f8fSGustavo F. Padovan } 10810a708f8fSGustavo F. Padovan 10829b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 10830a708f8fSGustavo F. Padovan 108489bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 10850a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 10860a708f8fSGustavo F. Padovan char buf[128]; 1087fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 1088fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 10890a708f8fSGustavo F. Padovan 1090d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 10916be36555SAndrei Emeltchenko lock_sock(sk); 1092c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, 1093c5daa683SGustavo Padovan &bt_sk(sk)->flags)) { 10940a708f8fSGustavo F. Padovan struct sock *parent = bt_sk(sk)->parent; 1095ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); 1096ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND); 109705e9a2f6SIlia Kolomisnky if (parent) 10980a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 10990a708f8fSGustavo F. Padovan 11000a708f8fSGustavo F. Padovan } else { 11010e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 1102ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 1103ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 11040a708f8fSGustavo F. Padovan } 11056be36555SAndrei Emeltchenko release_sock(sk); 11060a708f8fSGustavo F. Padovan } else { 1107ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); 1108ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND); 11090a708f8fSGustavo F. Padovan } 11100a708f8fSGustavo F. Padovan 1111fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 1112fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 11130a708f8fSGustavo F. Padovan 1114c1360a1cSGustavo F. Padovan if (test_bit(CONF_REQ_SENT, &chan->conf_state) || 11150a708f8fSGustavo F. Padovan rsp.result != L2CAP_CR_SUCCESS) { 11166be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 11170a708f8fSGustavo F. Padovan continue; 11180a708f8fSGustavo F. Padovan } 11190a708f8fSGustavo F. Padovan 1120c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 11210a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 112273ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 112373ffa904SGustavo F. Padovan chan->num_conf_req++; 11240a708f8fSGustavo F. Padovan } 11250a708f8fSGustavo F. Padovan 11266be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 11270a708f8fSGustavo F. Padovan } 11280a708f8fSGustavo F. Padovan 11293df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 11300a708f8fSGustavo F. Padovan } 11310a708f8fSGustavo F. Padovan 1132c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr. 1133b62f328bSVille Tervo * Returns closest match, locked. 1134b62f328bSVille Tervo */ 1135d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, 1136c2287681SIdo Yariv bdaddr_t *src, 1137c2287681SIdo Yariv bdaddr_t *dst) 1138b62f328bSVille Tervo { 113923691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 1140b62f328bSVille Tervo 114123691d75SGustavo F. Padovan read_lock(&chan_list_lock); 1142b62f328bSVille Tervo 114323691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 114423691d75SGustavo F. Padovan struct sock *sk = c->sk; 1145fe4128e0SGustavo F. Padovan 114689bc500eSGustavo F. Padovan if (state && c->state != state) 1147b62f328bSVille Tervo continue; 1148b62f328bSVille Tervo 114923691d75SGustavo F. Padovan if (c->scid == cid) { 1150c2287681SIdo Yariv int src_match, dst_match; 1151c2287681SIdo Yariv int src_any, dst_any; 1152c2287681SIdo Yariv 1153b62f328bSVille Tervo /* Exact match. */ 1154c2287681SIdo Yariv src_match = !bacmp(&bt_sk(sk)->src, src); 1155c2287681SIdo Yariv dst_match = !bacmp(&bt_sk(sk)->dst, dst); 1156c2287681SIdo Yariv if (src_match && dst_match) { 115723691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 115823691d75SGustavo F. Padovan return c; 115923691d75SGustavo F. Padovan } 1160b62f328bSVille Tervo 1161b62f328bSVille Tervo /* Closest match */ 1162c2287681SIdo Yariv src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY); 1163c2287681SIdo Yariv dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY); 1164c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1165c2287681SIdo Yariv (src_any && dst_any)) 116623691d75SGustavo F. Padovan c1 = c; 1167b62f328bSVille Tervo } 1168b62f328bSVille Tervo } 1169280f294fSGustavo F. Padovan 117023691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 1171b62f328bSVille Tervo 117223691d75SGustavo F. Padovan return c1; 1173b62f328bSVille Tervo } 1174b62f328bSVille Tervo 1175b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn) 1176b62f328bSVille Tervo { 1177c916fbe4SGustavo F. Padovan struct sock *parent, *sk; 117823691d75SGustavo F. Padovan struct l2cap_chan *chan, *pchan; 1179b62f328bSVille Tervo 1180b62f328bSVille Tervo BT_DBG(""); 1181b62f328bSVille Tervo 1182b62f328bSVille Tervo /* Check if we have socket listening on cid */ 118323691d75SGustavo F. Padovan pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA, 1184c2287681SIdo Yariv conn->src, conn->dst); 118523691d75SGustavo F. Padovan if (!pchan) 1186b62f328bSVille Tervo return; 1187b62f328bSVille Tervo 118823691d75SGustavo F. Padovan parent = pchan->sk; 118923691d75SGustavo F. Padovan 1190aa2ac881SGustavo F. Padovan lock_sock(parent); 119162f3a2cfSGustavo F. Padovan 119280b98027SGustavo Padovan chan = pchan->ops->new_connection(pchan); 119380808e43SGustavo F. Padovan if (!chan) 1194b62f328bSVille Tervo goto clean; 1195b62f328bSVille Tervo 119680808e43SGustavo F. Padovan sk = chan->sk; 11975d41ce1dSGustavo F. Padovan 1198b62f328bSVille Tervo hci_conn_hold(conn->hcon); 1199b62f328bSVille Tervo 1200b62f328bSVille Tervo bacpy(&bt_sk(sk)->src, conn->src); 1201b62f328bSVille Tervo bacpy(&bt_sk(sk)->dst, conn->dst); 1202b62f328bSVille Tervo 1203d1010240SGustavo F. Padovan bt_accept_enqueue(parent, sk); 1204d1010240SGustavo F. Padovan 12053d57dc68SGustavo F. Padovan l2cap_chan_add(conn, chan); 120648454079SGustavo F. Padovan 12076754e0dfSGustavo Padovan l2cap_chan_ready(chan); 1208b62f328bSVille Tervo 1209b62f328bSVille Tervo clean: 1210aa2ac881SGustavo F. Padovan release_sock(parent); 1211b62f328bSVille Tervo } 1212b62f328bSVille Tervo 12130a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn) 12140a708f8fSGustavo F. Padovan { 121548454079SGustavo F. Padovan struct l2cap_chan *chan; 12160a708f8fSGustavo F. Padovan 12170a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 12180a708f8fSGustavo F. Padovan 1219b62f328bSVille Tervo if (!conn->hcon->out && conn->hcon->type == LE_LINK) 1220b62f328bSVille Tervo l2cap_le_conn_ready(conn); 1221b62f328bSVille Tervo 1222160dc6acSVinicius Costa Gomes if (conn->hcon->out && conn->hcon->type == LE_LINK) 1223160dc6acSVinicius Costa Gomes smp_conn_security(conn, conn->hcon->pending_sec_level); 1224160dc6acSVinicius Costa Gomes 12253df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 12260a708f8fSGustavo F. Padovan 12273df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1228baa7e1faSGustavo F. Padovan 12296be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 12300a708f8fSGustavo F. Padovan 1231416fa752SAndrei Emeltchenko if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { 1232416fa752SAndrei Emeltchenko l2cap_chan_unlock(chan); 1233416fa752SAndrei Emeltchenko continue; 1234416fa752SAndrei Emeltchenko } 1235416fa752SAndrei Emeltchenko 123663128451SVinicius Costa Gomes if (conn->hcon->type == LE_LINK) { 1237b501d6a1SAnderson Briglia if (smp_conn_security(conn, chan->sec_level)) 1238cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 1239acd7d370SVille Tervo 124063128451SVinicius Costa Gomes } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 12416be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 1242c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 12436be36555SAndrei Emeltchenko lock_sock(sk); 12440e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECTED); 12450a708f8fSGustavo F. Padovan sk->sk_state_change(sk); 12466be36555SAndrei Emeltchenko release_sock(sk); 1247b501d6a1SAnderson Briglia 124889bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT) 1249fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 12500a708f8fSGustavo F. Padovan 12516be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 12520a708f8fSGustavo F. Padovan } 12530a708f8fSGustavo F. Padovan 12543df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 12550a708f8fSGustavo F. Padovan } 12560a708f8fSGustavo F. Padovan 12570a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */ 12580a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) 12590a708f8fSGustavo F. Padovan { 126048454079SGustavo F. Padovan struct l2cap_chan *chan; 12610a708f8fSGustavo F. Padovan 12620a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 12630a708f8fSGustavo F. Padovan 12643df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 12650a708f8fSGustavo F. Padovan 12663df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1267ecf61bdbSAndrei Emeltchenko if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) 12682e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 12690a708f8fSGustavo F. Padovan } 12700a708f8fSGustavo F. Padovan 12713df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 12720a708f8fSGustavo F. Padovan } 12730a708f8fSGustavo F. Padovan 1274f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work) 12750a708f8fSGustavo F. Padovan { 1276f878fcadSGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 1277030013d8SGustavo F. Padovan info_timer.work); 12780a708f8fSGustavo F. Padovan 12790a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 12800a708f8fSGustavo F. Padovan conn->info_ident = 0; 12810a708f8fSGustavo F. Padovan 12820a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 12830a708f8fSGustavo F. Padovan } 12840a708f8fSGustavo F. Padovan 12855d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err) 12865d3de7dfSVinicius Costa Gomes { 12875d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 12885d3de7dfSVinicius Costa Gomes struct l2cap_chan *chan, *l; 12895d3de7dfSVinicius Costa Gomes 12905d3de7dfSVinicius Costa Gomes if (!conn) 12915d3de7dfSVinicius Costa Gomes return; 12925d3de7dfSVinicius Costa Gomes 12935d3de7dfSVinicius Costa Gomes BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); 12945d3de7dfSVinicius Costa Gomes 12955d3de7dfSVinicius Costa Gomes kfree_skb(conn->rx_skb); 12965d3de7dfSVinicius Costa Gomes 12973df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 12983df91ea2SAndrei Emeltchenko 12995d3de7dfSVinicius Costa Gomes /* Kill channels */ 13005d3de7dfSVinicius Costa Gomes list_for_each_entry_safe(chan, l, &conn->chan_l, list) { 130161d6ef3eSMat Martineau l2cap_chan_hold(chan); 13026be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 13036be36555SAndrei Emeltchenko 13045d3de7dfSVinicius Costa Gomes l2cap_chan_del(chan, err); 13056be36555SAndrei Emeltchenko 13066be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13076be36555SAndrei Emeltchenko 130880b98027SGustavo Padovan chan->ops->close(chan); 130961d6ef3eSMat Martineau l2cap_chan_put(chan); 13105d3de7dfSVinicius Costa Gomes } 13115d3de7dfSVinicius Costa Gomes 13123df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 13133df91ea2SAndrei Emeltchenko 131473d80debSLuiz Augusto von Dentz hci_chan_del(conn->hchan); 131573d80debSLuiz Augusto von Dentz 13165d3de7dfSVinicius Costa Gomes if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1317127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->info_timer); 13185d3de7dfSVinicius Costa Gomes 131951a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) { 1320127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->security_timer); 13218aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 1322d26a2345SVinicius Costa Gomes } 13235d3de7dfSVinicius Costa Gomes 13245d3de7dfSVinicius Costa Gomes hcon->l2cap_data = NULL; 13255d3de7dfSVinicius Costa Gomes kfree(conn); 13265d3de7dfSVinicius Costa Gomes } 13275d3de7dfSVinicius Costa Gomes 13286c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work) 13295d3de7dfSVinicius Costa Gomes { 13306c9d42a1SGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 13316c9d42a1SGustavo F. Padovan security_timer.work); 13325d3de7dfSVinicius Costa Gomes 1333d06cc416SJohan Hedberg BT_DBG("conn %p", conn); 1334d06cc416SJohan Hedberg 1335d06cc416SJohan Hedberg if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) { 1336d06cc416SJohan Hedberg smp_chan_destroy(conn); 13375d3de7dfSVinicius Costa Gomes l2cap_conn_del(conn->hcon, ETIMEDOUT); 13385d3de7dfSVinicius Costa Gomes } 1339d06cc416SJohan Hedberg } 13405d3de7dfSVinicius Costa Gomes 13410a708f8fSGustavo F. Padovan static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) 13420a708f8fSGustavo F. Padovan { 13430a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 134473d80debSLuiz Augusto von Dentz struct hci_chan *hchan; 13450a708f8fSGustavo F. Padovan 13460a708f8fSGustavo F. Padovan if (conn || status) 13470a708f8fSGustavo F. Padovan return conn; 13480a708f8fSGustavo F. Padovan 134973d80debSLuiz Augusto von Dentz hchan = hci_chan_create(hcon); 135073d80debSLuiz Augusto von Dentz if (!hchan) 13510a708f8fSGustavo F. Padovan return NULL; 13520a708f8fSGustavo F. Padovan 135373d80debSLuiz Augusto von Dentz conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC); 135473d80debSLuiz Augusto von Dentz if (!conn) { 135573d80debSLuiz Augusto von Dentz hci_chan_del(hchan); 135673d80debSLuiz Augusto von Dentz return NULL; 135773d80debSLuiz Augusto von Dentz } 135873d80debSLuiz Augusto von Dentz 13590a708f8fSGustavo F. Padovan hcon->l2cap_data = conn; 13600a708f8fSGustavo F. Padovan conn->hcon = hcon; 136173d80debSLuiz Augusto von Dentz conn->hchan = hchan; 13620a708f8fSGustavo F. Padovan 136373d80debSLuiz Augusto von Dentz BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); 13640a708f8fSGustavo F. Padovan 1365acd7d370SVille Tervo if (hcon->hdev->le_mtu && hcon->type == LE_LINK) 1366acd7d370SVille Tervo conn->mtu = hcon->hdev->le_mtu; 1367acd7d370SVille Tervo else 13680a708f8fSGustavo F. Padovan conn->mtu = hcon->hdev->acl_mtu; 1369acd7d370SVille Tervo 13700a708f8fSGustavo F. Padovan conn->src = &hcon->hdev->bdaddr; 13710a708f8fSGustavo F. Padovan conn->dst = &hcon->dst; 13720a708f8fSGustavo F. Padovan 13730a708f8fSGustavo F. Padovan conn->feat_mask = 0; 13740a708f8fSGustavo F. Padovan 13750a708f8fSGustavo F. Padovan spin_lock_init(&conn->lock); 13763df91ea2SAndrei Emeltchenko mutex_init(&conn->chan_lock); 1377baa7e1faSGustavo F. Padovan 1378baa7e1faSGustavo F. Padovan INIT_LIST_HEAD(&conn->chan_l); 13790a708f8fSGustavo F. Padovan 13805d3de7dfSVinicius Costa Gomes if (hcon->type == LE_LINK) 13816c9d42a1SGustavo F. Padovan INIT_DELAYED_WORK(&conn->security_timer, security_timeout); 13825d3de7dfSVinicius Costa Gomes else 1383030013d8SGustavo F. Padovan INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); 13840a708f8fSGustavo F. Padovan 13859f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 13860a708f8fSGustavo F. Padovan 13870a708f8fSGustavo F. Padovan return conn; 13880a708f8fSGustavo F. Padovan } 13890a708f8fSGustavo F. Padovan 13900a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */ 13910a708f8fSGustavo F. Padovan 1392c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr. 13930a708f8fSGustavo F. Padovan * Returns closest match. 13940a708f8fSGustavo F. Padovan */ 1395c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, 1396c2287681SIdo Yariv bdaddr_t *src, 1397c2287681SIdo Yariv bdaddr_t *dst) 13980a708f8fSGustavo F. Padovan { 139923691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 14000a708f8fSGustavo F. Padovan 140123691d75SGustavo F. Padovan read_lock(&chan_list_lock); 14020a708f8fSGustavo F. Padovan 140323691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 140423691d75SGustavo F. Padovan struct sock *sk = c->sk; 1405fe4128e0SGustavo F. Padovan 140689bc500eSGustavo F. Padovan if (state && c->state != state) 14070a708f8fSGustavo F. Padovan continue; 14080a708f8fSGustavo F. Padovan 140923691d75SGustavo F. Padovan if (c->psm == psm) { 1410c2287681SIdo Yariv int src_match, dst_match; 1411c2287681SIdo Yariv int src_any, dst_any; 1412c2287681SIdo Yariv 14130a708f8fSGustavo F. Padovan /* Exact match. */ 1414c2287681SIdo Yariv src_match = !bacmp(&bt_sk(sk)->src, src); 1415c2287681SIdo Yariv dst_match = !bacmp(&bt_sk(sk)->dst, dst); 1416c2287681SIdo Yariv if (src_match && dst_match) { 1417a7567b20SJohannes Berg read_unlock(&chan_list_lock); 141823691d75SGustavo F. Padovan return c; 141923691d75SGustavo F. Padovan } 14200a708f8fSGustavo F. Padovan 14210a708f8fSGustavo F. Padovan /* Closest match */ 1422c2287681SIdo Yariv src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY); 1423c2287681SIdo Yariv dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY); 1424c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1425c2287681SIdo Yariv (src_any && dst_any)) 142623691d75SGustavo F. Padovan c1 = c; 14270a708f8fSGustavo F. Padovan } 14280a708f8fSGustavo F. Padovan } 14290a708f8fSGustavo F. Padovan 143023691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 14310a708f8fSGustavo F. Padovan 143223691d75SGustavo F. Padovan return c1; 14330a708f8fSGustavo F. Padovan } 14340a708f8fSGustavo F. Padovan 14358e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, 14368e9f9892SAndre Guedes bdaddr_t *dst, u8 dst_type) 14370a708f8fSGustavo F. Padovan { 14385d41ce1dSGustavo F. Padovan struct sock *sk = chan->sk; 14390a708f8fSGustavo F. Padovan bdaddr_t *src = &bt_sk(sk)->src; 14400a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 14410a708f8fSGustavo F. Padovan struct hci_conn *hcon; 14420a708f8fSGustavo F. Padovan struct hci_dev *hdev; 14430a708f8fSGustavo F. Padovan __u8 auth_type; 14440a708f8fSGustavo F. Padovan int err; 14450a708f8fSGustavo F. Padovan 14468e9f9892SAndre Guedes BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst), 14478e9f9892SAndre Guedes dst_type, __le16_to_cpu(chan->psm)); 14480a708f8fSGustavo F. Padovan 14490a708f8fSGustavo F. Padovan hdev = hci_get_route(dst, src); 14500a708f8fSGustavo F. Padovan if (!hdev) 14510a708f8fSGustavo F. Padovan return -EHOSTUNREACH; 14520a708f8fSGustavo F. Padovan 145309fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 14540a708f8fSGustavo F. Padovan 14556be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 145603a00194SGustavo F. Padovan 145703a00194SGustavo F. Padovan /* PSM must be odd and lsb of upper byte must be 0 */ 145803a00194SGustavo F. Padovan if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid && 145903a00194SGustavo F. Padovan chan->chan_type != L2CAP_CHAN_RAW) { 146003a00194SGustavo F. Padovan err = -EINVAL; 146103a00194SGustavo F. Padovan goto done; 146203a00194SGustavo F. Padovan } 146303a00194SGustavo F. Padovan 146403a00194SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) { 146503a00194SGustavo F. Padovan err = -EINVAL; 146603a00194SGustavo F. Padovan goto done; 146703a00194SGustavo F. Padovan } 146803a00194SGustavo F. Padovan 146903a00194SGustavo F. Padovan switch (chan->mode) { 147003a00194SGustavo F. Padovan case L2CAP_MODE_BASIC: 147103a00194SGustavo F. Padovan break; 147203a00194SGustavo F. Padovan case L2CAP_MODE_ERTM: 147303a00194SGustavo F. Padovan case L2CAP_MODE_STREAMING: 147403a00194SGustavo F. Padovan if (!disable_ertm) 147503a00194SGustavo F. Padovan break; 147603a00194SGustavo F. Padovan /* fall through */ 147703a00194SGustavo F. Padovan default: 147803a00194SGustavo F. Padovan err = -ENOTSUPP; 147903a00194SGustavo F. Padovan goto done; 148003a00194SGustavo F. Padovan } 148103a00194SGustavo F. Padovan 14820797e01dSGustavo Padovan switch (chan->state) { 148303a00194SGustavo F. Padovan case BT_CONNECT: 148403a00194SGustavo F. Padovan case BT_CONNECT2: 148503a00194SGustavo F. Padovan case BT_CONFIG: 148603a00194SGustavo F. Padovan /* Already connecting */ 148703a00194SGustavo F. Padovan err = 0; 148803a00194SGustavo F. Padovan goto done; 148903a00194SGustavo F. Padovan 149003a00194SGustavo F. Padovan case BT_CONNECTED: 149103a00194SGustavo F. Padovan /* Already connected */ 149203a00194SGustavo F. Padovan err = -EISCONN; 149303a00194SGustavo F. Padovan goto done; 149403a00194SGustavo F. Padovan 149503a00194SGustavo F. Padovan case BT_OPEN: 149603a00194SGustavo F. Padovan case BT_BOUND: 149703a00194SGustavo F. Padovan /* Can connect */ 149803a00194SGustavo F. Padovan break; 149903a00194SGustavo F. Padovan 150003a00194SGustavo F. Padovan default: 150103a00194SGustavo F. Padovan err = -EBADFD; 150203a00194SGustavo F. Padovan goto done; 150303a00194SGustavo F. Padovan } 150403a00194SGustavo F. Padovan 150503a00194SGustavo F. Padovan /* Set destination address and psm */ 15060797e01dSGustavo Padovan lock_sock(sk); 15079219b2a0SGustavo F. Padovan bacpy(&bt_sk(sk)->dst, dst); 15086be36555SAndrei Emeltchenko release_sock(sk); 15096be36555SAndrei Emeltchenko 151003a00194SGustavo F. Padovan chan->psm = psm; 151103a00194SGustavo F. Padovan chan->dcid = cid; 15120a708f8fSGustavo F. Padovan 15134343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 15140a708f8fSGustavo F. Padovan 1515fe4128e0SGustavo F. Padovan if (chan->dcid == L2CAP_CID_LE_DATA) 15168e9f9892SAndre Guedes hcon = hci_connect(hdev, LE_LINK, dst, dst_type, 15174343478fSGustavo F. Padovan chan->sec_level, auth_type); 1518acd7d370SVille Tervo else 15198e9f9892SAndre Guedes hcon = hci_connect(hdev, ACL_LINK, dst, dst_type, 15204343478fSGustavo F. Padovan chan->sec_level, auth_type); 1521acd7d370SVille Tervo 152230e76272SVille Tervo if (IS_ERR(hcon)) { 152330e76272SVille Tervo err = PTR_ERR(hcon); 15240a708f8fSGustavo F. Padovan goto done; 152530e76272SVille Tervo } 15260a708f8fSGustavo F. Padovan 15270a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, 0); 15280a708f8fSGustavo F. Padovan if (!conn) { 15290a708f8fSGustavo F. Padovan hci_conn_put(hcon); 153030e76272SVille Tervo err = -ENOMEM; 15310a708f8fSGustavo F. Padovan goto done; 15320a708f8fSGustavo F. Padovan } 15330a708f8fSGustavo F. Padovan 15349f0caeb1SVinicius Costa Gomes if (hcon->type == LE_LINK) { 15359f0caeb1SVinicius Costa Gomes err = 0; 15369f0caeb1SVinicius Costa Gomes 15379f0caeb1SVinicius Costa Gomes if (!list_empty(&conn->chan_l)) { 15389f0caeb1SVinicius Costa Gomes err = -EBUSY; 15399f0caeb1SVinicius Costa Gomes hci_conn_put(hcon); 15409f0caeb1SVinicius Costa Gomes } 15419f0caeb1SVinicius Costa Gomes 15429f0caeb1SVinicius Costa Gomes if (err) 15439f0caeb1SVinicius Costa Gomes goto done; 15449f0caeb1SVinicius Costa Gomes } 15459f0caeb1SVinicius Costa Gomes 15460a708f8fSGustavo F. Padovan /* Update source addr of the socket */ 15470a708f8fSGustavo F. Padovan bacpy(src, conn->src); 15480a708f8fSGustavo F. Padovan 15496be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 155048454079SGustavo F. Padovan l2cap_chan_add(conn, chan); 15516be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 155248454079SGustavo F. Padovan 15536be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECT); 1554c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 15550a708f8fSGustavo F. Padovan 15560a708f8fSGustavo F. Padovan if (hcon->state == BT_CONNECTED) { 1557715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1558c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 1559d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) 15606be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECTED); 15610a708f8fSGustavo F. Padovan } else 1562fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 15630a708f8fSGustavo F. Padovan } 15640a708f8fSGustavo F. Padovan 156530e76272SVille Tervo err = 0; 156630e76272SVille Tervo 15670a708f8fSGustavo F. Padovan done: 15686be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 156909fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 15700a708f8fSGustavo F. Padovan hci_dev_put(hdev); 15710a708f8fSGustavo F. Padovan return err; 15720a708f8fSGustavo F. Padovan } 15730a708f8fSGustavo F. Padovan 1574dcba0dbaSGustavo F. Padovan int __l2cap_wait_ack(struct sock *sk) 15750a708f8fSGustavo F. Padovan { 15768c1d787bSGustavo F. Padovan struct l2cap_chan *chan = l2cap_pi(sk)->chan; 15770a708f8fSGustavo F. Padovan DECLARE_WAITQUEUE(wait, current); 15780a708f8fSGustavo F. Padovan int err = 0; 15790a708f8fSGustavo F. Padovan int timeo = HZ/5; 15800a708f8fSGustavo F. Padovan 15810a708f8fSGustavo F. Padovan add_wait_queue(sk_sleep(sk), &wait); 15820a708f8fSGustavo F. Padovan set_current_state(TASK_INTERRUPTIBLE); 1583a71a0cf4SPeter Hurley while (chan->unacked_frames > 0 && chan->conn) { 15840a708f8fSGustavo F. Padovan if (!timeo) 15850a708f8fSGustavo F. Padovan timeo = HZ/5; 15860a708f8fSGustavo F. Padovan 15870a708f8fSGustavo F. Padovan if (signal_pending(current)) { 15880a708f8fSGustavo F. Padovan err = sock_intr_errno(timeo); 15890a708f8fSGustavo F. Padovan break; 15900a708f8fSGustavo F. Padovan } 15910a708f8fSGustavo F. Padovan 15920a708f8fSGustavo F. Padovan release_sock(sk); 15930a708f8fSGustavo F. Padovan timeo = schedule_timeout(timeo); 15940a708f8fSGustavo F. Padovan lock_sock(sk); 1595a71a0cf4SPeter Hurley set_current_state(TASK_INTERRUPTIBLE); 15960a708f8fSGustavo F. Padovan 15970a708f8fSGustavo F. Padovan err = sock_error(sk); 15980a708f8fSGustavo F. Padovan if (err) 15990a708f8fSGustavo F. Padovan break; 16000a708f8fSGustavo F. Padovan } 16010a708f8fSGustavo F. Padovan set_current_state(TASK_RUNNING); 16020a708f8fSGustavo F. Padovan remove_wait_queue(sk_sleep(sk), &wait); 16030a708f8fSGustavo F. Padovan return err; 16040a708f8fSGustavo F. Padovan } 16050a708f8fSGustavo F. Padovan 1606721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work) 16070a708f8fSGustavo F. Padovan { 1608721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1609721c4181SGustavo F. Padovan monitor_timer.work); 16100a708f8fSGustavo F. Padovan 1611525cd185SGustavo F. Padovan BT_DBG("chan %p", chan); 16120a708f8fSGustavo F. Padovan 16136be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 16146be36555SAndrei Emeltchenko 161580909e04SMat Martineau if (!chan->conn) { 16166be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16178d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 16180a708f8fSGustavo F. Padovan return; 16190a708f8fSGustavo F. Padovan } 16200a708f8fSGustavo F. Padovan 1621401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO); 16220a708f8fSGustavo F. Padovan 16236be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16248d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 16250a708f8fSGustavo F. Padovan } 16260a708f8fSGustavo F. Padovan 1627721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work) 16280a708f8fSGustavo F. Padovan { 1629721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1630721c4181SGustavo F. Padovan retrans_timer.work); 16310a708f8fSGustavo F. Padovan 163249208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 16330a708f8fSGustavo F. Padovan 16346be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 16356be36555SAndrei Emeltchenko 163680909e04SMat Martineau if (!chan->conn) { 163780909e04SMat Martineau l2cap_chan_unlock(chan); 163880909e04SMat Martineau l2cap_chan_put(chan); 163980909e04SMat Martineau return; 164080909e04SMat Martineau } 16410a708f8fSGustavo F. Padovan 1642401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO); 16436be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16448d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 16450a708f8fSGustavo F. Padovan } 16460a708f8fSGustavo F. Padovan 1647d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan, 16483733937dSMat Martineau struct sk_buff_head *skbs) 16490a708f8fSGustavo F. Padovan { 16500a708f8fSGustavo F. Padovan struct sk_buff *skb; 16513733937dSMat Martineau struct l2cap_ctrl *control; 16520a708f8fSGustavo F. Padovan 16533733937dSMat Martineau BT_DBG("chan %p, skbs %p", chan, skbs); 16543733937dSMat Martineau 16553733937dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 16563733937dSMat Martineau 16573733937dSMat Martineau while (!skb_queue_empty(&chan->tx_q)) { 16583733937dSMat Martineau 16593733937dSMat Martineau skb = skb_dequeue(&chan->tx_q); 16603733937dSMat Martineau 16613733937dSMat Martineau bt_cb(skb)->control.retries = 1; 16623733937dSMat Martineau control = &bt_cb(skb)->control; 16633733937dSMat Martineau 16643733937dSMat Martineau control->reqseq = 0; 16653733937dSMat Martineau control->txseq = chan->next_tx_seq; 16663733937dSMat Martineau 16673733937dSMat Martineau __pack_control(chan, control, skb); 16680a708f8fSGustavo F. Padovan 166947d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 16703733937dSMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 16713733937dSMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 16720a708f8fSGustavo F. Padovan } 16730a708f8fSGustavo F. Padovan 16744343478fSGustavo F. Padovan l2cap_do_send(chan, skb); 16750a708f8fSGustavo F. Padovan 1676b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 16773733937dSMat Martineau 1678836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 16793733937dSMat Martineau chan->frames_sent++; 16800a708f8fSGustavo F. Padovan } 16810a708f8fSGustavo F. Padovan } 16820a708f8fSGustavo F. Padovan 168367c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan) 16840a708f8fSGustavo F. Padovan { 16850a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 168618a48e76SMat Martineau struct l2cap_ctrl *control; 168718a48e76SMat Martineau int sent = 0; 168818a48e76SMat Martineau 168918a48e76SMat Martineau BT_DBG("chan %p", chan); 16900a708f8fSGustavo F. Padovan 169189bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 16920a708f8fSGustavo F. Padovan return -ENOTCONN; 16930a708f8fSGustavo F. Padovan 169494122bbeSMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 169594122bbeSMat Martineau return 0; 169694122bbeSMat Martineau 169718a48e76SMat Martineau while (chan->tx_send_head && 169818a48e76SMat Martineau chan->unacked_frames < chan->remote_tx_win && 169918a48e76SMat Martineau chan->tx_state == L2CAP_TX_STATE_XMIT) { 17000a708f8fSGustavo F. Padovan 170118a48e76SMat Martineau skb = chan->tx_send_head; 17020a708f8fSGustavo F. Padovan 170318a48e76SMat Martineau bt_cb(skb)->control.retries = 1; 170418a48e76SMat Martineau control = &bt_cb(skb)->control; 17050a708f8fSGustavo F. Padovan 1706e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 170718a48e76SMat Martineau control->final = 1; 1708e2ab4353SGustavo F. Padovan 170918a48e76SMat Martineau control->reqseq = chan->buffer_seq; 171018a48e76SMat Martineau chan->last_acked_seq = chan->buffer_seq; 171118a48e76SMat Martineau control->txseq = chan->next_tx_seq; 17120a708f8fSGustavo F. Padovan 171318a48e76SMat Martineau __pack_control(chan, control, skb); 17140a708f8fSGustavo F. Padovan 171547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 171618a48e76SMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 171718a48e76SMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 17180a708f8fSGustavo F. Padovan } 17190a708f8fSGustavo F. Padovan 172018a48e76SMat Martineau /* Clone after data has been modified. Data is assumed to be 172118a48e76SMat Martineau read-only (for locking purposes) on cloned sk_buffs. 172218a48e76SMat Martineau */ 172318a48e76SMat Martineau tx_skb = skb_clone(skb, GFP_KERNEL); 172418a48e76SMat Martineau 172518a48e76SMat Martineau if (!tx_skb) 172618a48e76SMat Martineau break; 17270a708f8fSGustavo F. Padovan 17281a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 17290a708f8fSGustavo F. Padovan 1730836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 17316a026610SGustavo F. Padovan chan->unacked_frames++; 17326a026610SGustavo F. Padovan chan->frames_sent++; 173318a48e76SMat Martineau sent++; 17340a708f8fSGustavo F. Padovan 173558d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 173658d35f87SGustavo F. Padovan chan->tx_send_head = NULL; 17370a708f8fSGustavo F. Padovan else 173858d35f87SGustavo F. Padovan chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); 173918a48e76SMat Martineau 174018a48e76SMat Martineau l2cap_do_send(chan, tx_skb); 1741b4400672SAndrei Emeltchenko BT_DBG("Sent txseq %u", control->txseq); 17420a708f8fSGustavo F. Padovan } 17430a708f8fSGustavo F. Padovan 1744b4400672SAndrei Emeltchenko BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent, 1745b4400672SAndrei Emeltchenko chan->unacked_frames, skb_queue_len(&chan->tx_q)); 174618a48e76SMat Martineau 174718a48e76SMat Martineau return sent; 17480a708f8fSGustavo F. Padovan } 17490a708f8fSGustavo F. Padovan 1750e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan) 1751e1fbd4c1SMat Martineau { 1752e1fbd4c1SMat Martineau struct l2cap_ctrl control; 1753e1fbd4c1SMat Martineau struct sk_buff *skb; 1754e1fbd4c1SMat Martineau struct sk_buff *tx_skb; 1755e1fbd4c1SMat Martineau u16 seq; 1756e1fbd4c1SMat Martineau 1757e1fbd4c1SMat Martineau BT_DBG("chan %p", chan); 1758e1fbd4c1SMat Martineau 1759e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 1760e1fbd4c1SMat Martineau return; 1761e1fbd4c1SMat Martineau 1762e1fbd4c1SMat Martineau while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) { 1763e1fbd4c1SMat Martineau seq = l2cap_seq_list_pop(&chan->retrans_list); 1764e1fbd4c1SMat Martineau 1765e1fbd4c1SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq); 1766e1fbd4c1SMat Martineau if (!skb) { 1767e1fbd4c1SMat Martineau BT_DBG("Error: Can't retransmit seq %d, frame missing", 1768e1fbd4c1SMat Martineau seq); 1769e1fbd4c1SMat Martineau continue; 1770e1fbd4c1SMat Martineau } 1771e1fbd4c1SMat Martineau 1772e1fbd4c1SMat Martineau bt_cb(skb)->control.retries++; 1773e1fbd4c1SMat Martineau control = bt_cb(skb)->control; 1774e1fbd4c1SMat Martineau 1775e1fbd4c1SMat Martineau if (chan->max_tx != 0 && 1776e1fbd4c1SMat Martineau bt_cb(skb)->control.retries > chan->max_tx) { 1777e1fbd4c1SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 1778e1fbd4c1SMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 1779e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 1780e1fbd4c1SMat Martineau break; 1781e1fbd4c1SMat Martineau } 1782e1fbd4c1SMat Martineau 1783e1fbd4c1SMat Martineau control.reqseq = chan->buffer_seq; 1784e1fbd4c1SMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 1785e1fbd4c1SMat Martineau control.final = 1; 1786e1fbd4c1SMat Martineau else 1787e1fbd4c1SMat Martineau control.final = 0; 1788e1fbd4c1SMat Martineau 1789e1fbd4c1SMat Martineau if (skb_cloned(skb)) { 1790e1fbd4c1SMat Martineau /* Cloned sk_buffs are read-only, so we need a 1791e1fbd4c1SMat Martineau * writeable copy 1792e1fbd4c1SMat Martineau */ 1793e1fbd4c1SMat Martineau tx_skb = skb_copy(skb, GFP_ATOMIC); 1794e1fbd4c1SMat Martineau } else { 1795e1fbd4c1SMat Martineau tx_skb = skb_clone(skb, GFP_ATOMIC); 1796e1fbd4c1SMat Martineau } 1797e1fbd4c1SMat Martineau 1798e1fbd4c1SMat Martineau if (!tx_skb) { 1799e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 1800e1fbd4c1SMat Martineau break; 1801e1fbd4c1SMat Martineau } 1802e1fbd4c1SMat Martineau 1803e1fbd4c1SMat Martineau /* Update skb contents */ 1804e1fbd4c1SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 1805e1fbd4c1SMat Martineau put_unaligned_le32(__pack_extended_control(&control), 1806e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 1807e1fbd4c1SMat Martineau } else { 1808e1fbd4c1SMat Martineau put_unaligned_le16(__pack_enhanced_control(&control), 1809e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 1810e1fbd4c1SMat Martineau } 1811e1fbd4c1SMat Martineau 1812e1fbd4c1SMat Martineau if (chan->fcs == L2CAP_FCS_CRC16) { 1813e1fbd4c1SMat Martineau u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len); 1814e1fbd4c1SMat Martineau put_unaligned_le16(fcs, skb_put(tx_skb, 1815e1fbd4c1SMat Martineau L2CAP_FCS_SIZE)); 1816e1fbd4c1SMat Martineau } 1817e1fbd4c1SMat Martineau 1818e1fbd4c1SMat Martineau l2cap_do_send(chan, tx_skb); 1819e1fbd4c1SMat Martineau 1820e1fbd4c1SMat Martineau BT_DBG("Resent txseq %d", control.txseq); 1821e1fbd4c1SMat Martineau 1822e1fbd4c1SMat Martineau chan->last_acked_seq = chan->buffer_seq; 1823e1fbd4c1SMat Martineau } 1824e1fbd4c1SMat Martineau } 1825e1fbd4c1SMat Martineau 1826f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan, 1827f80842a8SMat Martineau struct l2cap_ctrl *control) 1828f80842a8SMat Martineau { 1829f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 1830f80842a8SMat Martineau 1831f80842a8SMat Martineau l2cap_seq_list_append(&chan->retrans_list, control->reqseq); 1832f80842a8SMat Martineau l2cap_ertm_resend(chan); 1833f80842a8SMat Martineau } 1834f80842a8SMat Martineau 1835d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan, 1836d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 1837d2a7ac5dSMat Martineau { 1838e1fbd4c1SMat Martineau struct sk_buff *skb; 1839e1fbd4c1SMat Martineau 1840e1fbd4c1SMat Martineau BT_DBG("chan %p, control %p", chan, control); 1841e1fbd4c1SMat Martineau 1842e1fbd4c1SMat Martineau if (control->poll) 1843e1fbd4c1SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 1844e1fbd4c1SMat Martineau 1845e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 1846e1fbd4c1SMat Martineau 1847e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 1848e1fbd4c1SMat Martineau return; 1849e1fbd4c1SMat Martineau 1850e1fbd4c1SMat Martineau if (chan->unacked_frames) { 1851e1fbd4c1SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 1852e1fbd4c1SMat Martineau if (bt_cb(skb)->control.txseq == control->reqseq || 1853e1fbd4c1SMat Martineau skb == chan->tx_send_head) 1854e1fbd4c1SMat Martineau break; 1855e1fbd4c1SMat Martineau } 1856e1fbd4c1SMat Martineau 1857e1fbd4c1SMat Martineau skb_queue_walk_from(&chan->tx_q, skb) { 1858e1fbd4c1SMat Martineau if (skb == chan->tx_send_head) 1859e1fbd4c1SMat Martineau break; 1860e1fbd4c1SMat Martineau 1861e1fbd4c1SMat Martineau l2cap_seq_list_append(&chan->retrans_list, 1862e1fbd4c1SMat Martineau bt_cb(skb)->control.txseq); 1863e1fbd4c1SMat Martineau } 1864e1fbd4c1SMat Martineau 1865e1fbd4c1SMat Martineau l2cap_ertm_resend(chan); 1866e1fbd4c1SMat Martineau } 1867d2a7ac5dSMat Martineau } 1868d2a7ac5dSMat Martineau 1869b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan) 1870b17e73bbSSzymon Janc { 18710a0aba42SMat Martineau struct l2cap_ctrl control; 18720a0aba42SMat Martineau u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq, 18730a0aba42SMat Martineau chan->last_acked_seq); 18740a0aba42SMat Martineau int threshold; 18750a0aba42SMat Martineau 18760a0aba42SMat Martineau BT_DBG("chan %p last_acked_seq %d buffer_seq %d", 18770a0aba42SMat Martineau chan, chan->last_acked_seq, chan->buffer_seq); 18780a0aba42SMat Martineau 18790a0aba42SMat Martineau memset(&control, 0, sizeof(control)); 18800a0aba42SMat Martineau control.sframe = 1; 18810a0aba42SMat Martineau 18820a0aba42SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 18830a0aba42SMat Martineau chan->rx_state == L2CAP_RX_STATE_RECV) { 1884b17e73bbSSzymon Janc __clear_ack_timer(chan); 18850a0aba42SMat Martineau control.super = L2CAP_SUPER_RNR; 18860a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 18870a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 18880a0aba42SMat Martineau } else { 18890a0aba42SMat Martineau if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) { 18900a0aba42SMat Martineau l2cap_ertm_send(chan); 18910a0aba42SMat Martineau /* If any i-frames were sent, they included an ack */ 18920a0aba42SMat Martineau if (chan->buffer_seq == chan->last_acked_seq) 18930a0aba42SMat Martineau frames_to_ack = 0; 18940a0aba42SMat Martineau } 18950a0aba42SMat Martineau 1896c20f8e35SMat Martineau /* Ack now if the window is 3/4ths full. 18970a0aba42SMat Martineau * Calculate without mul or div 18980a0aba42SMat Martineau */ 1899c20f8e35SMat Martineau threshold = chan->ack_win; 19000a0aba42SMat Martineau threshold += threshold << 1; 19010a0aba42SMat Martineau threshold >>= 2; 19020a0aba42SMat Martineau 1903b4400672SAndrei Emeltchenko BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack, 19040a0aba42SMat Martineau threshold); 19050a0aba42SMat Martineau 19060a0aba42SMat Martineau if (frames_to_ack >= threshold) { 19070a0aba42SMat Martineau __clear_ack_timer(chan); 19080a0aba42SMat Martineau control.super = L2CAP_SUPER_RR; 19090a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 19100a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 19110a0aba42SMat Martineau frames_to_ack = 0; 19120a0aba42SMat Martineau } 19130a0aba42SMat Martineau 19140a0aba42SMat Martineau if (frames_to_ack) 19150a0aba42SMat Martineau __set_ack_timer(chan); 19160a0aba42SMat Martineau } 1917b17e73bbSSzymon Janc } 1918b17e73bbSSzymon Janc 191904124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, 192004124681SGustavo F. Padovan struct msghdr *msg, int len, 192104124681SGustavo F. Padovan int count, struct sk_buff *skb) 19220a708f8fSGustavo F. Padovan { 19230952a57aSAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 19240a708f8fSGustavo F. Padovan struct sk_buff **frag; 192590338947SGustavo Padovan int sent = 0; 19260a708f8fSGustavo F. Padovan 19270a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) 19280a708f8fSGustavo F. Padovan return -EFAULT; 19290a708f8fSGustavo F. Padovan 19300a708f8fSGustavo F. Padovan sent += count; 19310a708f8fSGustavo F. Padovan len -= count; 19320a708f8fSGustavo F. Padovan 19330a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 19340a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 19350a708f8fSGustavo F. Padovan while (len) { 1936fbe00700SGustavo Padovan struct sk_buff *tmp; 1937fbe00700SGustavo Padovan 19380a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 19390a708f8fSGustavo F. Padovan 1940fbe00700SGustavo Padovan tmp = chan->ops->alloc_skb(chan, count, 194190338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 1942fbe00700SGustavo Padovan if (IS_ERR(tmp)) 1943fbe00700SGustavo Padovan return PTR_ERR(tmp); 19442f7719ceSAndrei Emeltchenko 1945fbe00700SGustavo Padovan *frag = tmp; 1946fbe00700SGustavo Padovan 19470a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) 19480a708f8fSGustavo F. Padovan return -EFAULT; 19490a708f8fSGustavo F. Padovan 19505e59b791SLuiz Augusto von Dentz (*frag)->priority = skb->priority; 19515e59b791SLuiz Augusto von Dentz 19520a708f8fSGustavo F. Padovan sent += count; 19530a708f8fSGustavo F. Padovan len -= count; 19540a708f8fSGustavo F. Padovan 19552d0ed3d5SGustavo Padovan skb->len += (*frag)->len; 19562d0ed3d5SGustavo Padovan skb->data_len += (*frag)->len; 19572d0ed3d5SGustavo Padovan 19580a708f8fSGustavo F. Padovan frag = &(*frag)->next; 19590a708f8fSGustavo F. Padovan } 19600a708f8fSGustavo F. Padovan 19610a708f8fSGustavo F. Padovan return sent; 19620a708f8fSGustavo F. Padovan } 19630a708f8fSGustavo F. Padovan 19645e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, 19655e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 19665e59b791SLuiz Augusto von Dentz u32 priority) 19670a708f8fSGustavo F. Padovan { 19688c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 19690a708f8fSGustavo F. Padovan struct sk_buff *skb; 197003a51213SAndrei Emeltchenko int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; 19710a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 19720a708f8fSGustavo F. Padovan 1973b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu priority %u", chan, len, priority); 19740a708f8fSGustavo F. Padovan 19750a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 19762f7719ceSAndrei Emeltchenko 19772f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 197890338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 197990338947SGustavo Padovan if (IS_ERR(skb)) 198090338947SGustavo Padovan return skb; 19810a708f8fSGustavo F. Padovan 19825e59b791SLuiz Augusto von Dentz skb->priority = priority; 19835e59b791SLuiz Augusto von Dentz 19840a708f8fSGustavo F. Padovan /* Create L2CAP header */ 19850a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 1986fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 1987daf6a78cSAndrei Emeltchenko lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); 1988daf6a78cSAndrei Emeltchenko put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE)); 19890a708f8fSGustavo F. Padovan 19900952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 19910a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 19920a708f8fSGustavo F. Padovan kfree_skb(skb); 19930a708f8fSGustavo F. Padovan return ERR_PTR(err); 19940a708f8fSGustavo F. Padovan } 19950a708f8fSGustavo F. Padovan return skb; 19960a708f8fSGustavo F. Padovan } 19970a708f8fSGustavo F. Padovan 19985e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, 19995e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 20005e59b791SLuiz Augusto von Dentz u32 priority) 20010a708f8fSGustavo F. Padovan { 20028c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 20030a708f8fSGustavo F. Padovan struct sk_buff *skb; 2004f2ba7faeSGustavo Padovan int err, count; 20050a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 20060a708f8fSGustavo F. Padovan 2007b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 20080a708f8fSGustavo F. Padovan 2009f2ba7faeSGustavo Padovan count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); 20102f7719ceSAndrei Emeltchenko 2011f2ba7faeSGustavo Padovan skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE, 201290338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 201390338947SGustavo Padovan if (IS_ERR(skb)) 201490338947SGustavo Padovan return skb; 20150a708f8fSGustavo F. Padovan 20165e59b791SLuiz Augusto von Dentz skb->priority = priority; 20175e59b791SLuiz Augusto von Dentz 20180a708f8fSGustavo F. Padovan /* Create L2CAP header */ 20190a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2020fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 20216ff9b5efSGustavo Padovan lh->len = cpu_to_le16(len); 20220a708f8fSGustavo F. Padovan 20230952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 20240a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 20250a708f8fSGustavo F. Padovan kfree_skb(skb); 20260a708f8fSGustavo F. Padovan return ERR_PTR(err); 20270a708f8fSGustavo F. Padovan } 20280a708f8fSGustavo F. Padovan return skb; 20290a708f8fSGustavo F. Padovan } 20300a708f8fSGustavo F. Padovan 2031ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, 2032ab0ff76dSLuiz Augusto von Dentz struct msghdr *msg, size_t len, 203394122bbeSMat Martineau u16 sdulen) 20340a708f8fSGustavo F. Padovan { 20358c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 20360a708f8fSGustavo F. Padovan struct sk_buff *skb; 2037e4ca6d98SAndrei Emeltchenko int err, count, hlen; 20380a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 20390a708f8fSGustavo F. Padovan 2040b4400672SAndrei Emeltchenko BT_DBG("chan %p len %zu", chan, len); 20410a708f8fSGustavo F. Padovan 20420a708f8fSGustavo F. Padovan if (!conn) 20430a708f8fSGustavo F. Padovan return ERR_PTR(-ENOTCONN); 20440a708f8fSGustavo F. Padovan 2045ba7aa64fSGustavo Padovan hlen = __ertm_hdr_size(chan); 2046e4ca6d98SAndrei Emeltchenko 20470a708f8fSGustavo F. Padovan if (sdulen) 204803a51213SAndrei Emeltchenko hlen += L2CAP_SDULEN_SIZE; 20490a708f8fSGustavo F. Padovan 205047d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 205103a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 20520a708f8fSGustavo F. Padovan 20530a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 20542f7719ceSAndrei Emeltchenko 20552f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 205690338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 205790338947SGustavo Padovan if (IS_ERR(skb)) 205890338947SGustavo Padovan return skb; 20590a708f8fSGustavo F. Padovan 20600a708f8fSGustavo F. Padovan /* Create L2CAP header */ 20610a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2062fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 20630a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 206488843ab0SAndrei Emeltchenko 206518a48e76SMat Martineau /* Control header is populated later */ 206618a48e76SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 206718a48e76SMat Martineau put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 206818a48e76SMat Martineau else 206918a48e76SMat Martineau put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 207088843ab0SAndrei Emeltchenko 20710a708f8fSGustavo F. Padovan if (sdulen) 207203a51213SAndrei Emeltchenko put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 20730a708f8fSGustavo F. Padovan 20740952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 20750a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 20760a708f8fSGustavo F. Padovan kfree_skb(skb); 20770a708f8fSGustavo F. Padovan return ERR_PTR(err); 20780a708f8fSGustavo F. Padovan } 20790a708f8fSGustavo F. Padovan 208018a48e76SMat Martineau bt_cb(skb)->control.fcs = chan->fcs; 20813ce3514fSMat Martineau bt_cb(skb)->control.retries = 0; 20820a708f8fSGustavo F. Padovan return skb; 20830a708f8fSGustavo F. Padovan } 20840a708f8fSGustavo F. Padovan 208594122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan, 208694122bbeSMat Martineau struct sk_buff_head *seg_queue, 208794122bbeSMat Martineau struct msghdr *msg, size_t len) 20880a708f8fSGustavo F. Padovan { 20890a708f8fSGustavo F. Padovan struct sk_buff *skb; 209094122bbeSMat Martineau u16 sdu_len; 209194122bbeSMat Martineau size_t pdu_len; 209294122bbeSMat Martineau u8 sar; 20930a708f8fSGustavo F. Padovan 2094b4400672SAndrei Emeltchenko BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); 20950a708f8fSGustavo F. Padovan 209694122bbeSMat Martineau /* It is critical that ERTM PDUs fit in a single HCI fragment, 209794122bbeSMat Martineau * so fragmented skbs are not used. The HCI layer's handling 209894122bbeSMat Martineau * of fragmented skbs is not compatible with ERTM's queueing. 209994122bbeSMat Martineau */ 210094122bbeSMat Martineau 210194122bbeSMat Martineau /* PDU size is derived from the HCI MTU */ 210294122bbeSMat Martineau pdu_len = chan->conn->mtu; 210394122bbeSMat Martineau 210494122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); 210594122bbeSMat Martineau 210694122bbeSMat Martineau /* Adjust for largest possible L2CAP overhead. */ 210735d401dfSGustavo Padovan if (chan->fcs) 210835d401dfSGustavo Padovan pdu_len -= L2CAP_FCS_SIZE; 210935d401dfSGustavo Padovan 2110ba7aa64fSGustavo Padovan pdu_len -= __ertm_hdr_size(chan); 211194122bbeSMat Martineau 211294122bbeSMat Martineau /* Remote device may have requested smaller PDUs */ 211394122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, chan->remote_mps); 211494122bbeSMat Martineau 211594122bbeSMat Martineau if (len <= pdu_len) { 211694122bbeSMat Martineau sar = L2CAP_SAR_UNSEGMENTED; 211794122bbeSMat Martineau sdu_len = 0; 211894122bbeSMat Martineau pdu_len = len; 211994122bbeSMat Martineau } else { 212094122bbeSMat Martineau sar = L2CAP_SAR_START; 212194122bbeSMat Martineau sdu_len = len; 212294122bbeSMat Martineau pdu_len -= L2CAP_SDULEN_SIZE; 212394122bbeSMat Martineau } 21240a708f8fSGustavo F. Padovan 21250a708f8fSGustavo F. Padovan while (len > 0) { 212694122bbeSMat Martineau skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len); 21270a708f8fSGustavo F. Padovan 21280a708f8fSGustavo F. Padovan if (IS_ERR(skb)) { 212994122bbeSMat Martineau __skb_queue_purge(seg_queue); 21300a708f8fSGustavo F. Padovan return PTR_ERR(skb); 21310a708f8fSGustavo F. Padovan } 21320a708f8fSGustavo F. Padovan 213394122bbeSMat Martineau bt_cb(skb)->control.sar = sar; 213494122bbeSMat Martineau __skb_queue_tail(seg_queue, skb); 21350a708f8fSGustavo F. Padovan 213694122bbeSMat Martineau len -= pdu_len; 213794122bbeSMat Martineau if (sdu_len) { 213894122bbeSMat Martineau sdu_len = 0; 213994122bbeSMat Martineau pdu_len += L2CAP_SDULEN_SIZE; 214094122bbeSMat Martineau } 214194122bbeSMat Martineau 214294122bbeSMat Martineau if (len <= pdu_len) { 214394122bbeSMat Martineau sar = L2CAP_SAR_END; 214494122bbeSMat Martineau pdu_len = len; 214594122bbeSMat Martineau } else { 214694122bbeSMat Martineau sar = L2CAP_SAR_CONTINUE; 214794122bbeSMat Martineau } 214894122bbeSMat Martineau } 214994122bbeSMat Martineau 2150f0f62799SGustavo Padovan return 0; 21510a708f8fSGustavo F. Padovan } 21520a708f8fSGustavo F. Padovan 21535e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, 21545e59b791SLuiz Augusto von Dentz u32 priority) 21559a91a04aSGustavo F. Padovan { 21569a91a04aSGustavo F. Padovan struct sk_buff *skb; 21579a91a04aSGustavo F. Padovan int err; 215894122bbeSMat Martineau struct sk_buff_head seg_queue; 21599a91a04aSGustavo F. Padovan 21609a91a04aSGustavo F. Padovan /* Connectionless channel */ 2161715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { 21625e59b791SLuiz Augusto von Dentz skb = l2cap_create_connless_pdu(chan, msg, len, priority); 21639a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 21649a91a04aSGustavo F. Padovan return PTR_ERR(skb); 21659a91a04aSGustavo F. Padovan 21669a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 21679a91a04aSGustavo F. Padovan return len; 21689a91a04aSGustavo F. Padovan } 21699a91a04aSGustavo F. Padovan 21709a91a04aSGustavo F. Padovan switch (chan->mode) { 21719a91a04aSGustavo F. Padovan case L2CAP_MODE_BASIC: 21729a91a04aSGustavo F. Padovan /* Check outgoing MTU */ 21739a91a04aSGustavo F. Padovan if (len > chan->omtu) 21749a91a04aSGustavo F. Padovan return -EMSGSIZE; 21759a91a04aSGustavo F. Padovan 21769a91a04aSGustavo F. Padovan /* Create a basic PDU */ 21775e59b791SLuiz Augusto von Dentz skb = l2cap_create_basic_pdu(chan, msg, len, priority); 21789a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 21799a91a04aSGustavo F. Padovan return PTR_ERR(skb); 21809a91a04aSGustavo F. Padovan 21819a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 21829a91a04aSGustavo F. Padovan err = len; 21839a91a04aSGustavo F. Padovan break; 21849a91a04aSGustavo F. Padovan 21859a91a04aSGustavo F. Padovan case L2CAP_MODE_ERTM: 21869a91a04aSGustavo F. Padovan case L2CAP_MODE_STREAMING: 218794122bbeSMat Martineau /* Check outgoing MTU */ 218894122bbeSMat Martineau if (len > chan->omtu) { 218994122bbeSMat Martineau err = -EMSGSIZE; 21909a91a04aSGustavo F. Padovan break; 21919a91a04aSGustavo F. Padovan } 21929a91a04aSGustavo F. Padovan 219394122bbeSMat Martineau __skb_queue_head_init(&seg_queue); 219494122bbeSMat Martineau 219594122bbeSMat Martineau /* Do segmentation before calling in to the state machine, 219694122bbeSMat Martineau * since it's possible to block while waiting for memory 219794122bbeSMat Martineau * allocation. 219894122bbeSMat Martineau */ 219994122bbeSMat Martineau err = l2cap_segment_sdu(chan, &seg_queue, msg, len); 220094122bbeSMat Martineau 220194122bbeSMat Martineau /* The channel could have been closed while segmenting, 220294122bbeSMat Martineau * check that it is still connected. 220394122bbeSMat Martineau */ 220494122bbeSMat Martineau if (chan->state != BT_CONNECTED) { 220594122bbeSMat Martineau __skb_queue_purge(&seg_queue); 220694122bbeSMat Martineau err = -ENOTCONN; 22079a91a04aSGustavo F. Padovan } 22089a91a04aSGustavo F. Padovan 220994122bbeSMat Martineau if (err) 221094122bbeSMat Martineau break; 221194122bbeSMat Martineau 22123733937dSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) 2213d660366dSGustavo Padovan l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST); 22143733937dSMat Martineau else 2215d660366dSGustavo Padovan l2cap_streaming_send(chan, &seg_queue); 221694122bbeSMat Martineau 22179a91a04aSGustavo F. Padovan err = len; 22189a91a04aSGustavo F. Padovan 221994122bbeSMat Martineau /* If the skbs were not queued for sending, they'll still be in 222094122bbeSMat Martineau * seg_queue and need to be purged. 222194122bbeSMat Martineau */ 222294122bbeSMat Martineau __skb_queue_purge(&seg_queue); 22239a91a04aSGustavo F. Padovan break; 22249a91a04aSGustavo F. Padovan 22259a91a04aSGustavo F. Padovan default: 22269a91a04aSGustavo F. Padovan BT_DBG("bad state %1.1x", chan->mode); 22279a91a04aSGustavo F. Padovan err = -EBADFD; 22289a91a04aSGustavo F. Padovan } 22299a91a04aSGustavo F. Padovan 22309a91a04aSGustavo F. Padovan return err; 22319a91a04aSGustavo F. Padovan } 22329a91a04aSGustavo F. Padovan 2233d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq) 2234d2a7ac5dSMat Martineau { 2235bed68bdeSMat Martineau struct l2cap_ctrl control; 2236bed68bdeSMat Martineau u16 seq; 2237bed68bdeSMat Martineau 2238b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2239bed68bdeSMat Martineau 2240bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2241bed68bdeSMat Martineau control.sframe = 1; 2242bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2243bed68bdeSMat Martineau 2244bed68bdeSMat Martineau for (seq = chan->expected_tx_seq; seq != txseq; 2245bed68bdeSMat Martineau seq = __next_seq(chan, seq)) { 2246bed68bdeSMat Martineau if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) { 2247bed68bdeSMat Martineau control.reqseq = seq; 2248bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2249bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2250bed68bdeSMat Martineau } 2251bed68bdeSMat Martineau } 2252bed68bdeSMat Martineau 2253bed68bdeSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 2254d2a7ac5dSMat Martineau } 2255d2a7ac5dSMat Martineau 2256d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan) 2257d2a7ac5dSMat Martineau { 2258bed68bdeSMat Martineau struct l2cap_ctrl control; 2259bed68bdeSMat Martineau 2260bed68bdeSMat Martineau BT_DBG("chan %p", chan); 2261bed68bdeSMat Martineau 2262bed68bdeSMat Martineau if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR) 2263bed68bdeSMat Martineau return; 2264bed68bdeSMat Martineau 2265bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2266bed68bdeSMat Martineau control.sframe = 1; 2267bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2268bed68bdeSMat Martineau control.reqseq = chan->srej_list.tail; 2269bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2270d2a7ac5dSMat Martineau } 2271d2a7ac5dSMat Martineau 2272d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq) 2273d2a7ac5dSMat Martineau { 2274bed68bdeSMat Martineau struct l2cap_ctrl control; 2275bed68bdeSMat Martineau u16 initial_head; 2276bed68bdeSMat Martineau u16 seq; 2277bed68bdeSMat Martineau 2278b4400672SAndrei Emeltchenko BT_DBG("chan %p, txseq %u", chan, txseq); 2279bed68bdeSMat Martineau 2280bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2281bed68bdeSMat Martineau control.sframe = 1; 2282bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2283bed68bdeSMat Martineau 2284bed68bdeSMat Martineau /* Capture initial list head to allow only one pass through the list. */ 2285bed68bdeSMat Martineau initial_head = chan->srej_list.head; 2286bed68bdeSMat Martineau 2287bed68bdeSMat Martineau do { 2288bed68bdeSMat Martineau seq = l2cap_seq_list_pop(&chan->srej_list); 2289bed68bdeSMat Martineau if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR) 2290bed68bdeSMat Martineau break; 2291bed68bdeSMat Martineau 2292bed68bdeSMat Martineau control.reqseq = seq; 2293bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2294bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2295bed68bdeSMat Martineau } while (chan->srej_list.head != initial_head); 2296d2a7ac5dSMat Martineau } 2297d2a7ac5dSMat Martineau 2298608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq) 2299608bcc6dSMat Martineau { 2300608bcc6dSMat Martineau struct sk_buff *acked_skb; 2301608bcc6dSMat Martineau u16 ackseq; 2302608bcc6dSMat Martineau 2303b4400672SAndrei Emeltchenko BT_DBG("chan %p, reqseq %u", chan, reqseq); 2304608bcc6dSMat Martineau 2305608bcc6dSMat Martineau if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq) 2306608bcc6dSMat Martineau return; 2307608bcc6dSMat Martineau 2308b4400672SAndrei Emeltchenko BT_DBG("expected_ack_seq %u, unacked_frames %u", 2309608bcc6dSMat Martineau chan->expected_ack_seq, chan->unacked_frames); 2310608bcc6dSMat Martineau 2311608bcc6dSMat Martineau for (ackseq = chan->expected_ack_seq; ackseq != reqseq; 2312608bcc6dSMat Martineau ackseq = __next_seq(chan, ackseq)) { 2313608bcc6dSMat Martineau 2314608bcc6dSMat Martineau acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq); 2315608bcc6dSMat Martineau if (acked_skb) { 2316608bcc6dSMat Martineau skb_unlink(acked_skb, &chan->tx_q); 2317608bcc6dSMat Martineau kfree_skb(acked_skb); 2318608bcc6dSMat Martineau chan->unacked_frames--; 2319608bcc6dSMat Martineau } 2320608bcc6dSMat Martineau } 2321608bcc6dSMat Martineau 2322608bcc6dSMat Martineau chan->expected_ack_seq = reqseq; 2323608bcc6dSMat Martineau 2324608bcc6dSMat Martineau if (chan->unacked_frames == 0) 2325608bcc6dSMat Martineau __clear_retrans_timer(chan); 2326608bcc6dSMat Martineau 2327b4400672SAndrei Emeltchenko BT_DBG("unacked_frames %u", chan->unacked_frames); 2328608bcc6dSMat Martineau } 2329608bcc6dSMat Martineau 2330608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan) 2331608bcc6dSMat Martineau { 2332608bcc6dSMat Martineau BT_DBG("chan %p", chan); 2333608bcc6dSMat Martineau 2334608bcc6dSMat Martineau chan->expected_tx_seq = chan->buffer_seq; 2335608bcc6dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 2336608bcc6dSMat Martineau skb_queue_purge(&chan->srej_q); 2337608bcc6dSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2338608bcc6dSMat Martineau } 2339608bcc6dSMat Martineau 2340d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan, 2341608bcc6dSMat Martineau struct l2cap_ctrl *control, 2342608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2343608bcc6dSMat Martineau { 2344608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2345608bcc6dSMat Martineau event); 2346608bcc6dSMat Martineau 2347608bcc6dSMat Martineau switch (event) { 2348608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2349608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2350608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2351608bcc6dSMat Martineau 2352608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2353608bcc6dSMat Martineau l2cap_ertm_send(chan); 2354608bcc6dSMat Martineau break; 2355608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2356608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2357608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2358608bcc6dSMat Martineau 2359608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2360608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2361608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2362608bcc6dSMat Martineau */ 2363608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2364608bcc6dSMat Martineau } 2365608bcc6dSMat Martineau 2366608bcc6dSMat Martineau l2cap_send_ack(chan); 2367608bcc6dSMat Martineau 2368608bcc6dSMat Martineau break; 2369608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2370608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2371608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2372608bcc6dSMat Martineau 2373608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2374608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2375608bcc6dSMat Martineau 2376608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2377608bcc6dSMat Martineau local_control.sframe = 1; 2378608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2379608bcc6dSMat Martineau local_control.poll = 1; 2380608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2381a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2382608bcc6dSMat Martineau 2383608bcc6dSMat Martineau chan->retry_count = 1; 2384608bcc6dSMat Martineau __set_monitor_timer(chan); 2385608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2386608bcc6dSMat Martineau } 2387608bcc6dSMat Martineau break; 2388608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2389608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2390608bcc6dSMat Martineau break; 2391608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2392608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2393608bcc6dSMat Martineau chan->retry_count = 1; 2394608bcc6dSMat Martineau __set_monitor_timer(chan); 2395608bcc6dSMat Martineau __clear_ack_timer(chan); 2396608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2397608bcc6dSMat Martineau break; 2398608bcc6dSMat Martineau case L2CAP_EV_RETRANS_TO: 2399608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2400608bcc6dSMat Martineau chan->retry_count = 1; 2401608bcc6dSMat Martineau __set_monitor_timer(chan); 2402608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2403608bcc6dSMat Martineau break; 2404608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2405608bcc6dSMat Martineau /* Nothing to process */ 2406608bcc6dSMat Martineau break; 2407608bcc6dSMat Martineau default: 2408608bcc6dSMat Martineau break; 2409608bcc6dSMat Martineau } 2410608bcc6dSMat Martineau } 2411608bcc6dSMat Martineau 2412d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan, 2413608bcc6dSMat Martineau struct l2cap_ctrl *control, 2414608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2415608bcc6dSMat Martineau { 2416608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2417608bcc6dSMat Martineau event); 2418608bcc6dSMat Martineau 2419608bcc6dSMat Martineau switch (event) { 2420608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2421608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2422608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2423608bcc6dSMat Martineau /* Queue data, but don't send. */ 2424608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2425608bcc6dSMat Martineau break; 2426608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2427608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2428608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2429608bcc6dSMat Martineau 2430608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2431608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2432608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2433608bcc6dSMat Martineau */ 2434608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2435608bcc6dSMat Martineau } 2436608bcc6dSMat Martineau 2437608bcc6dSMat Martineau l2cap_send_ack(chan); 2438608bcc6dSMat Martineau 2439608bcc6dSMat Martineau break; 2440608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2441608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2442608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2443608bcc6dSMat Martineau 2444608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2445608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2446608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2447608bcc6dSMat Martineau local_control.sframe = 1; 2448608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2449608bcc6dSMat Martineau local_control.poll = 1; 2450608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2451a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2452608bcc6dSMat Martineau 2453608bcc6dSMat Martineau chan->retry_count = 1; 2454608bcc6dSMat Martineau __set_monitor_timer(chan); 2455608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2456608bcc6dSMat Martineau } 2457608bcc6dSMat Martineau break; 2458608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2459608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2460608bcc6dSMat Martineau 2461608bcc6dSMat Martineau /* Fall through */ 2462608bcc6dSMat Martineau 2463608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2464608bcc6dSMat Martineau if (control && control->final) { 2465608bcc6dSMat Martineau __clear_monitor_timer(chan); 2466608bcc6dSMat Martineau if (chan->unacked_frames > 0) 2467608bcc6dSMat Martineau __set_retrans_timer(chan); 2468608bcc6dSMat Martineau chan->retry_count = 0; 2469608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 2470608bcc6dSMat Martineau BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state); 2471608bcc6dSMat Martineau } 2472608bcc6dSMat Martineau break; 2473608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2474608bcc6dSMat Martineau /* Ignore */ 2475608bcc6dSMat Martineau break; 2476608bcc6dSMat Martineau case L2CAP_EV_MONITOR_TO: 2477608bcc6dSMat Martineau if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) { 2478608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2479608bcc6dSMat Martineau __set_monitor_timer(chan); 2480608bcc6dSMat Martineau chan->retry_count++; 2481608bcc6dSMat Martineau } else { 2482608bcc6dSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); 2483608bcc6dSMat Martineau } 2484608bcc6dSMat Martineau break; 2485608bcc6dSMat Martineau default: 2486608bcc6dSMat Martineau break; 2487608bcc6dSMat Martineau } 2488608bcc6dSMat Martineau } 2489608bcc6dSMat Martineau 2490d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 2491608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2492608bcc6dSMat Martineau { 2493608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d, state %d", 2494608bcc6dSMat Martineau chan, control, skbs, event, chan->tx_state); 2495608bcc6dSMat Martineau 2496608bcc6dSMat Martineau switch (chan->tx_state) { 2497608bcc6dSMat Martineau case L2CAP_TX_STATE_XMIT: 2498d660366dSGustavo Padovan l2cap_tx_state_xmit(chan, control, skbs, event); 2499608bcc6dSMat Martineau break; 2500608bcc6dSMat Martineau case L2CAP_TX_STATE_WAIT_F: 2501d660366dSGustavo Padovan l2cap_tx_state_wait_f(chan, control, skbs, event); 2502608bcc6dSMat Martineau break; 2503608bcc6dSMat Martineau default: 2504608bcc6dSMat Martineau /* Ignore event */ 2505608bcc6dSMat Martineau break; 2506608bcc6dSMat Martineau } 2507608bcc6dSMat Martineau } 2508608bcc6dSMat Martineau 25094b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan, 25104b51dae9SMat Martineau struct l2cap_ctrl *control) 25114b51dae9SMat Martineau { 25124b51dae9SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2513401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT); 25144b51dae9SMat Martineau } 25154b51dae9SMat Martineau 2516f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan, 2517f80842a8SMat Martineau struct l2cap_ctrl *control) 2518f80842a8SMat Martineau { 2519f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2520401bb1f7SAndrei Emeltchenko l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT); 2521f80842a8SMat Martineau } 2522f80842a8SMat Martineau 25230a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */ 25240a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 25250a708f8fSGustavo F. Padovan { 25260a708f8fSGustavo F. Padovan struct sk_buff *nskb; 252748454079SGustavo F. Padovan struct l2cap_chan *chan; 25280a708f8fSGustavo F. Padovan 25290a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 25300a708f8fSGustavo F. Padovan 25313df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 25323d57dc68SGustavo F. Padovan 25333df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 253448454079SGustavo F. Padovan struct sock *sk = chan->sk; 2535715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW) 25360a708f8fSGustavo F. Padovan continue; 25370a708f8fSGustavo F. Padovan 25380a708f8fSGustavo F. Padovan /* Don't send frame to the socket it came from */ 25390a708f8fSGustavo F. Padovan if (skb->sk == sk) 25400a708f8fSGustavo F. Padovan continue; 25410a708f8fSGustavo F. Padovan nskb = skb_clone(skb, GFP_ATOMIC); 25420a708f8fSGustavo F. Padovan if (!nskb) 25430a708f8fSGustavo F. Padovan continue; 25440a708f8fSGustavo F. Padovan 254580b98027SGustavo Padovan if (chan->ops->recv(chan, nskb)) 25460a708f8fSGustavo F. Padovan kfree_skb(nskb); 25470a708f8fSGustavo F. Padovan } 25483d57dc68SGustavo F. Padovan 25493df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 25500a708f8fSGustavo F. Padovan } 25510a708f8fSGustavo F. Padovan 25520a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */ 2553b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, 2554b4400672SAndrei Emeltchenko u8 ident, u16 dlen, void *data) 25550a708f8fSGustavo F. Padovan { 25560a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag; 25570a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd; 25580a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 25590a708f8fSGustavo F. Padovan int len, count; 25600a708f8fSGustavo F. Padovan 2561b4400672SAndrei Emeltchenko BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u", 25620a708f8fSGustavo F. Padovan conn, code, ident, dlen); 25630a708f8fSGustavo F. Padovan 25640a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; 25650a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 25660a708f8fSGustavo F. Padovan 25670a708f8fSGustavo F. Padovan skb = bt_skb_alloc(count, GFP_ATOMIC); 25680a708f8fSGustavo F. Padovan if (!skb) 25690a708f8fSGustavo F. Padovan return NULL; 25700a708f8fSGustavo F. Padovan 25710a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 25720a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); 25733300d9a9SClaudio Takahasi 25743300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 2575ac73498cSAndrei Emeltchenko lh->cid = __constant_cpu_to_le16(L2CAP_CID_LE_SIGNALING); 25763300d9a9SClaudio Takahasi else 2577ac73498cSAndrei Emeltchenko lh->cid = __constant_cpu_to_le16(L2CAP_CID_SIGNALING); 25780a708f8fSGustavo F. Padovan 25790a708f8fSGustavo F. Padovan cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); 25800a708f8fSGustavo F. Padovan cmd->code = code; 25810a708f8fSGustavo F. Padovan cmd->ident = ident; 25820a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen); 25830a708f8fSGustavo F. Padovan 25840a708f8fSGustavo F. Padovan if (dlen) { 25850a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE; 25860a708f8fSGustavo F. Padovan memcpy(skb_put(skb, count), data, count); 25870a708f8fSGustavo F. Padovan data += count; 25880a708f8fSGustavo F. Padovan } 25890a708f8fSGustavo F. Padovan 25900a708f8fSGustavo F. Padovan len -= skb->len; 25910a708f8fSGustavo F. Padovan 25920a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 25930a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 25940a708f8fSGustavo F. Padovan while (len) { 25950a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 25960a708f8fSGustavo F. Padovan 25970a708f8fSGustavo F. Padovan *frag = bt_skb_alloc(count, GFP_ATOMIC); 25980a708f8fSGustavo F. Padovan if (!*frag) 25990a708f8fSGustavo F. Padovan goto fail; 26000a708f8fSGustavo F. Padovan 26010a708f8fSGustavo F. Padovan memcpy(skb_put(*frag, count), data, count); 26020a708f8fSGustavo F. Padovan 26030a708f8fSGustavo F. Padovan len -= count; 26040a708f8fSGustavo F. Padovan data += count; 26050a708f8fSGustavo F. Padovan 26060a708f8fSGustavo F. Padovan frag = &(*frag)->next; 26070a708f8fSGustavo F. Padovan } 26080a708f8fSGustavo F. Padovan 26090a708f8fSGustavo F. Padovan return skb; 26100a708f8fSGustavo F. Padovan 26110a708f8fSGustavo F. Padovan fail: 26120a708f8fSGustavo F. Padovan kfree_skb(skb); 26130a708f8fSGustavo F. Padovan return NULL; 26140a708f8fSGustavo F. Padovan } 26150a708f8fSGustavo F. Padovan 26160a708f8fSGustavo F. Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val) 26170a708f8fSGustavo F. Padovan { 26180a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 26190a708f8fSGustavo F. Padovan int len; 26200a708f8fSGustavo F. Padovan 26210a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len; 26220a708f8fSGustavo F. Padovan *ptr += len; 26230a708f8fSGustavo F. Padovan 26240a708f8fSGustavo F. Padovan *type = opt->type; 26250a708f8fSGustavo F. Padovan *olen = opt->len; 26260a708f8fSGustavo F. Padovan 26270a708f8fSGustavo F. Padovan switch (opt->len) { 26280a708f8fSGustavo F. Padovan case 1: 26290a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val); 26300a708f8fSGustavo F. Padovan break; 26310a708f8fSGustavo F. Padovan 26320a708f8fSGustavo F. Padovan case 2: 26330a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val); 26340a708f8fSGustavo F. Padovan break; 26350a708f8fSGustavo F. Padovan 26360a708f8fSGustavo F. Padovan case 4: 26370a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val); 26380a708f8fSGustavo F. Padovan break; 26390a708f8fSGustavo F. Padovan 26400a708f8fSGustavo F. Padovan default: 26410a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val; 26420a708f8fSGustavo F. Padovan break; 26430a708f8fSGustavo F. Padovan } 26440a708f8fSGustavo F. Padovan 2645b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val); 26460a708f8fSGustavo F. Padovan return len; 26470a708f8fSGustavo F. Padovan } 26480a708f8fSGustavo F. Padovan 26490a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) 26500a708f8fSGustavo F. Padovan { 26510a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 26520a708f8fSGustavo F. Padovan 2653b4400672SAndrei Emeltchenko BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val); 26540a708f8fSGustavo F. Padovan 26550a708f8fSGustavo F. Padovan opt->type = type; 26560a708f8fSGustavo F. Padovan opt->len = len; 26570a708f8fSGustavo F. Padovan 26580a708f8fSGustavo F. Padovan switch (len) { 26590a708f8fSGustavo F. Padovan case 1: 26600a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val; 26610a708f8fSGustavo F. Padovan break; 26620a708f8fSGustavo F. Padovan 26630a708f8fSGustavo F. Padovan case 2: 26640a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val); 26650a708f8fSGustavo F. Padovan break; 26660a708f8fSGustavo F. Padovan 26670a708f8fSGustavo F. Padovan case 4: 26680a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val); 26690a708f8fSGustavo F. Padovan break; 26700a708f8fSGustavo F. Padovan 26710a708f8fSGustavo F. Padovan default: 26720a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len); 26730a708f8fSGustavo F. Padovan break; 26740a708f8fSGustavo F. Padovan } 26750a708f8fSGustavo F. Padovan 26760a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len; 26770a708f8fSGustavo F. Padovan } 26780a708f8fSGustavo F. Padovan 2679f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) 2680f89cef09SAndrei Emeltchenko { 2681f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs; 2682f89cef09SAndrei Emeltchenko 2683f89cef09SAndrei Emeltchenko switch (chan->mode) { 2684f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM: 2685f89cef09SAndrei Emeltchenko efs.id = chan->local_id; 2686f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype; 2687f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 2688f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 2689ac73498cSAndrei Emeltchenko efs.acc_lat = __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); 2690ac73498cSAndrei Emeltchenko efs.flush_to = __constant_cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO); 2691f89cef09SAndrei Emeltchenko break; 2692f89cef09SAndrei Emeltchenko 2693f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING: 2694f89cef09SAndrei Emeltchenko efs.id = 1; 2695f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT; 2696f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 2697f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 2698f89cef09SAndrei Emeltchenko efs.acc_lat = 0; 2699f89cef09SAndrei Emeltchenko efs.flush_to = 0; 2700f89cef09SAndrei Emeltchenko break; 2701f89cef09SAndrei Emeltchenko 2702f89cef09SAndrei Emeltchenko default: 2703f89cef09SAndrei Emeltchenko return; 2704f89cef09SAndrei Emeltchenko } 2705f89cef09SAndrei Emeltchenko 2706f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), 2707f89cef09SAndrei Emeltchenko (unsigned long) &efs); 2708f89cef09SAndrei Emeltchenko } 2709f89cef09SAndrei Emeltchenko 2710721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work) 27110a708f8fSGustavo F. Padovan { 2712721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 2713721c4181SGustavo F. Padovan ack_timer.work); 27140362520bSMat Martineau u16 frames_to_ack; 27150a708f8fSGustavo F. Padovan 27162fb9b3d4SGustavo F. Padovan BT_DBG("chan %p", chan); 27172fb9b3d4SGustavo F. Padovan 27186be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 27196be36555SAndrei Emeltchenko 27200362520bSMat Martineau frames_to_ack = __seq_offset(chan, chan->buffer_seq, 27210362520bSMat Martineau chan->last_acked_seq); 27220362520bSMat Martineau 27230362520bSMat Martineau if (frames_to_ack) 27240362520bSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 27256be36555SAndrei Emeltchenko 27266be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 272709bfb2eeSSzymon Janc l2cap_chan_put(chan); 27280a708f8fSGustavo F. Padovan } 27290a708f8fSGustavo F. Padovan 2730466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan) 27310a708f8fSGustavo F. Padovan { 27323c588192SMat Martineau int err; 27333c588192SMat Martineau 2734105bdf9eSMat Martineau chan->next_tx_seq = 0; 2735105bdf9eSMat Martineau chan->expected_tx_seq = 0; 273642e5c802SGustavo F. Padovan chan->expected_ack_seq = 0; 27376a026610SGustavo F. Padovan chan->unacked_frames = 0; 273842e5c802SGustavo F. Padovan chan->buffer_seq = 0; 27396a026610SGustavo F. Padovan chan->frames_sent = 0; 2740105bdf9eSMat Martineau chan->last_acked_seq = 0; 2741105bdf9eSMat Martineau chan->sdu = NULL; 2742105bdf9eSMat Martineau chan->sdu_last_frag = NULL; 2743105bdf9eSMat Martineau chan->sdu_len = 0; 2744105bdf9eSMat Martineau 2745d34c34fbSMat Martineau skb_queue_head_init(&chan->tx_q); 2746d34c34fbSMat Martineau 2747105bdf9eSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 2748105bdf9eSMat Martineau return 0; 2749105bdf9eSMat Martineau 2750105bdf9eSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2751105bdf9eSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 27520a708f8fSGustavo F. Padovan 2753721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout); 2754721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout); 2755721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout); 27560a708f8fSGustavo F. Padovan 2757f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q); 27580a708f8fSGustavo F. Padovan 27593c588192SMat Martineau err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win); 27603c588192SMat Martineau if (err < 0) 27613c588192SMat Martineau return err; 27623c588192SMat Martineau 27639dc9affcSMat Martineau err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win); 27649dc9affcSMat Martineau if (err < 0) 27659dc9affcSMat Martineau l2cap_seq_list_free(&chan->srej_list); 27669dc9affcSMat Martineau 27679dc9affcSMat Martineau return err; 27680a708f8fSGustavo F. Padovan } 27690a708f8fSGustavo F. Padovan 27700a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) 27710a708f8fSGustavo F. Padovan { 27720a708f8fSGustavo F. Padovan switch (mode) { 27730a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 27740a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 27750a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask)) 27760a708f8fSGustavo F. Padovan return mode; 27770a708f8fSGustavo F. Padovan /* fall through */ 27780a708f8fSGustavo F. Padovan default: 27790a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC; 27800a708f8fSGustavo F. Padovan } 27810a708f8fSGustavo F. Padovan } 27820a708f8fSGustavo F. Padovan 27836327eb98SAndrei Emeltchenko static inline bool __l2cap_ews_supported(struct l2cap_chan *chan) 27846327eb98SAndrei Emeltchenko { 27856327eb98SAndrei Emeltchenko return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW; 27866327eb98SAndrei Emeltchenko } 27876327eb98SAndrei Emeltchenko 2788f89cef09SAndrei Emeltchenko static inline bool __l2cap_efs_supported(struct l2cap_chan *chan) 2789f89cef09SAndrei Emeltchenko { 2790f89cef09SAndrei Emeltchenko return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW; 2791f89cef09SAndrei Emeltchenko } 2792f89cef09SAndrei Emeltchenko 27936327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan) 27946327eb98SAndrei Emeltchenko { 27956327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && 2796836be934SAndrei Emeltchenko __l2cap_ews_supported(chan)) { 27976327eb98SAndrei Emeltchenko /* use extended control field */ 27986327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 2799836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 2800836be934SAndrei Emeltchenko } else { 28016327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win, 28026327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 2803836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 2804836be934SAndrei Emeltchenko } 2805c20f8e35SMat Martineau chan->ack_win = chan->tx_win; 28066327eb98SAndrei Emeltchenko } 28076327eb98SAndrei Emeltchenko 2808710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) 28090a708f8fSGustavo F. Padovan { 28100a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 28110c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode }; 28120a708f8fSGustavo F. Padovan void *ptr = req->data; 2813c8f79162SAndrei Emeltchenko u16 size; 28140a708f8fSGustavo F. Padovan 281549208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 28160a708f8fSGustavo F. Padovan 281773ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp) 28180a708f8fSGustavo F. Padovan goto done; 28190a708f8fSGustavo F. Padovan 28200c1bc5c6SGustavo F. Padovan switch (chan->mode) { 28210a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 28220a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 2823c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) 28240a708f8fSGustavo F. Padovan break; 28250a708f8fSGustavo F. Padovan 2826f89cef09SAndrei Emeltchenko if (__l2cap_efs_supported(chan)) 2827f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 2828f89cef09SAndrei Emeltchenko 28290a708f8fSGustavo F. Padovan /* fall through */ 28300a708f8fSGustavo F. Padovan default: 28318c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); 28320a708f8fSGustavo F. Padovan break; 28330a708f8fSGustavo F. Padovan } 28340a708f8fSGustavo F. Padovan 28350a708f8fSGustavo F. Padovan done: 28360c1bc5c6SGustavo F. Padovan if (chan->imtu != L2CAP_DEFAULT_MTU) 28370c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 28380a708f8fSGustavo F. Padovan 28390c1bc5c6SGustavo F. Padovan switch (chan->mode) { 28400a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 28418c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && 28428c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) 28430a708f8fSGustavo F. Padovan break; 28440a708f8fSGustavo F. Padovan 28450a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC; 28460a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 28470a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 28480a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 28490a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 28500a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0; 28510a708f8fSGustavo F. Padovan 28520a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 28530a708f8fSGustavo F. Padovan (unsigned long) &rfc); 28540a708f8fSGustavo F. Padovan break; 28550a708f8fSGustavo F. Padovan 28560a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 28570a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM; 285847d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx; 28590a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 28600a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 2861c8f79162SAndrei Emeltchenko 2862c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 2863c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2864c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2865c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2866c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 28670a708f8fSGustavo F. Padovan 28686327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan); 28696327eb98SAndrei Emeltchenko 28706327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win, 28716327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 28720a708f8fSGustavo F. Padovan 28730a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 28740a708f8fSGustavo F. Padovan (unsigned long) &rfc); 28750a708f8fSGustavo F. Padovan 2876f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 2877f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 2878f89cef09SAndrei Emeltchenko 28798c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) 28800a708f8fSGustavo F. Padovan break; 28810a708f8fSGustavo F. Padovan 288247d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 2883c1360a1cSGustavo F. Padovan test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { 288447d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 288547d1ec61SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); 28860a708f8fSGustavo F. Padovan } 28876327eb98SAndrei Emeltchenko 28886327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 28896327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 28906327eb98SAndrei Emeltchenko chan->tx_win); 28910a708f8fSGustavo F. Padovan break; 28920a708f8fSGustavo F. Padovan 28930a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 2894273759e2SMat Martineau l2cap_txwin_setup(chan); 28950a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING; 28960a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 28970a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 28980a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 28990a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 2900c8f79162SAndrei Emeltchenko 2901c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 2902c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2903c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2904c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2905c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 29060a708f8fSGustavo F. Padovan 29070a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 29080a708f8fSGustavo F. Padovan (unsigned long) &rfc); 29090a708f8fSGustavo F. Padovan 2910f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 2911f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 2912f89cef09SAndrei Emeltchenko 29138c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) 29140a708f8fSGustavo F. Padovan break; 29150a708f8fSGustavo F. Padovan 291647d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 2917c1360a1cSGustavo F. Padovan test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { 291847d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 291947d1ec61SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); 29200a708f8fSGustavo F. Padovan } 29210a708f8fSGustavo F. Padovan break; 29220a708f8fSGustavo F. Padovan } 29230a708f8fSGustavo F. Padovan 2924fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 292559e54bd1SAndrei Emeltchenko req->flags = __constant_cpu_to_le16(0); 29260a708f8fSGustavo F. Padovan 29270a708f8fSGustavo F. Padovan return ptr - data; 29280a708f8fSGustavo F. Padovan } 29290a708f8fSGustavo F. Padovan 293073ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) 29310a708f8fSGustavo F. Padovan { 29320a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 29330a708f8fSGustavo F. Padovan void *ptr = rsp->data; 293473ffa904SGustavo F. Padovan void *req = chan->conf_req; 293573ffa904SGustavo F. Padovan int len = chan->conf_len; 29360a708f8fSGustavo F. Padovan int type, hint, olen; 29370a708f8fSGustavo F. Padovan unsigned long val; 29380a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 293942dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs; 294042dceae2SAndrei Emeltchenko u8 remote_efs = 0; 29410a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU; 29420a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS; 2943c8f79162SAndrei Emeltchenko u16 size; 29440a708f8fSGustavo F. Padovan 294573ffa904SGustavo F. Padovan BT_DBG("chan %p", chan); 29460a708f8fSGustavo F. Padovan 29470a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 29480a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val); 29490a708f8fSGustavo F. Padovan 29500a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT; 29510a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK; 29520a708f8fSGustavo F. Padovan 29530a708f8fSGustavo F. Padovan switch (type) { 29540a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 29550a708f8fSGustavo F. Padovan mtu = val; 29560a708f8fSGustavo F. Padovan break; 29570a708f8fSGustavo F. Padovan 29580a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 29590c1bc5c6SGustavo F. Padovan chan->flush_to = val; 29600a708f8fSGustavo F. Padovan break; 29610a708f8fSGustavo F. Padovan 29620a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS: 29630a708f8fSGustavo F. Padovan break; 29640a708f8fSGustavo F. Padovan 29650a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 29660a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 29670a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen); 29680a708f8fSGustavo F. Padovan break; 29690a708f8fSGustavo F. Padovan 29700a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS: 29710a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE) 2972c1360a1cSGustavo F. Padovan set_bit(CONF_NO_FCS_RECV, &chan->conf_state); 297342dceae2SAndrei Emeltchenko break; 29740a708f8fSGustavo F. Padovan 297542dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS: 297642dceae2SAndrei Emeltchenko remote_efs = 1; 297742dceae2SAndrei Emeltchenko if (olen == sizeof(efs)) 297842dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen); 29790a708f8fSGustavo F. Padovan break; 29800a708f8fSGustavo F. Padovan 29816327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 29826327eb98SAndrei Emeltchenko if (!enable_hs) 29836327eb98SAndrei Emeltchenko return -ECONNREFUSED; 29846327eb98SAndrei Emeltchenko 29856327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 29866327eb98SAndrei Emeltchenko set_bit(CONF_EWS_RECV, &chan->conf_state); 2987836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 29886327eb98SAndrei Emeltchenko chan->remote_tx_win = val; 29890a708f8fSGustavo F. Padovan break; 29900a708f8fSGustavo F. Padovan 29910a708f8fSGustavo F. Padovan default: 29920a708f8fSGustavo F. Padovan if (hint) 29930a708f8fSGustavo F. Padovan break; 29940a708f8fSGustavo F. Padovan 29950a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN; 29960a708f8fSGustavo F. Padovan *((u8 *) ptr++) = type; 29970a708f8fSGustavo F. Padovan break; 29980a708f8fSGustavo F. Padovan } 29990a708f8fSGustavo F. Padovan } 30000a708f8fSGustavo F. Padovan 300173ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1) 30020a708f8fSGustavo F. Padovan goto done; 30030a708f8fSGustavo F. Padovan 30040c1bc5c6SGustavo F. Padovan switch (chan->mode) { 30050a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 30060a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3007c1360a1cSGustavo F. Padovan if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { 30080c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, 30098c1d787bSGustavo F. Padovan chan->conn->feat_mask); 30100a708f8fSGustavo F. Padovan break; 30110a708f8fSGustavo F. Padovan } 30120a708f8fSGustavo F. Padovan 301342dceae2SAndrei Emeltchenko if (remote_efs) { 301442dceae2SAndrei Emeltchenko if (__l2cap_efs_supported(chan)) 301542dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 301642dceae2SAndrei Emeltchenko else 301742dceae2SAndrei Emeltchenko return -ECONNREFUSED; 301842dceae2SAndrei Emeltchenko } 301942dceae2SAndrei Emeltchenko 30200c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) 30210a708f8fSGustavo F. Padovan return -ECONNREFUSED; 30220a708f8fSGustavo F. Padovan 30230a708f8fSGustavo F. Padovan break; 30240a708f8fSGustavo F. Padovan } 30250a708f8fSGustavo F. Padovan 30260a708f8fSGustavo F. Padovan done: 30270c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) { 30280a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 30290c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 30300a708f8fSGustavo F. Padovan 303173ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1) 30320a708f8fSGustavo F. Padovan return -ECONNREFUSED; 30330a708f8fSGustavo F. Padovan 30340a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 30350a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 30360a708f8fSGustavo F. Padovan } 30370a708f8fSGustavo F. Padovan 30380a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) { 30390a708f8fSGustavo F. Padovan /* Configure output options and let the other side know 30400a708f8fSGustavo F. Padovan * which ones we don't like. */ 30410a708f8fSGustavo F. Padovan 30420a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU) 30430a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 30440a708f8fSGustavo F. Padovan else { 30450c1bc5c6SGustavo F. Padovan chan->omtu = mtu; 3046c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state); 30470a708f8fSGustavo F. Padovan } 30480c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); 30490a708f8fSGustavo F. Padovan 305042dceae2SAndrei Emeltchenko if (remote_efs) { 305142dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 305242dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 305342dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) { 305442dceae2SAndrei Emeltchenko 305542dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT; 305642dceae2SAndrei Emeltchenko 305742dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1) 305842dceae2SAndrei Emeltchenko return -ECONNREFUSED; 305942dceae2SAndrei Emeltchenko 306042dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 306142dceae2SAndrei Emeltchenko sizeof(efs), 306242dceae2SAndrei Emeltchenko (unsigned long) &efs); 30630e8b207eSAndrei Emeltchenko } else { 30643e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */ 30650e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING; 30660e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 306742dceae2SAndrei Emeltchenko } 306842dceae2SAndrei Emeltchenko } 306942dceae2SAndrei Emeltchenko 30700a708f8fSGustavo F. Padovan switch (rfc.mode) { 30710a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 307247d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3073c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 30740a708f8fSGustavo F. Padovan break; 30750a708f8fSGustavo F. Padovan 30760a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 30776327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state)) 30782c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size; 30796327eb98SAndrei Emeltchenko else 30806327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; 30816327eb98SAndrei Emeltchenko 30822c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit; 30830a708f8fSGustavo F. Padovan 3084c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 3085c8f79162SAndrei Emeltchenko chan->conn->mtu - 3086c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 3087c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 3088c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3089c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3090c8f79162SAndrei Emeltchenko chan->remote_mps = size; 30910a708f8fSGustavo F. Padovan 30920a708f8fSGustavo F. Padovan rfc.retrans_timeout = 30934fd21a88SAndrei Emeltchenko __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 30940a708f8fSGustavo F. Padovan rfc.monitor_timeout = 30954fd21a88SAndrei Emeltchenko __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 30960a708f8fSGustavo F. Padovan 3097c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 30980a708f8fSGustavo F. Padovan 30990a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 31000a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 31010a708f8fSGustavo F. Padovan 310242dceae2SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 310342dceae2SAndrei Emeltchenko chan->remote_id = efs.id; 310442dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype; 310542dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu); 310642dceae2SAndrei Emeltchenko chan->remote_flush_to = 310742dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to); 310842dceae2SAndrei Emeltchenko chan->remote_acc_lat = 310942dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat); 311042dceae2SAndrei Emeltchenko chan->remote_sdu_itime = 311142dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 311242dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 311342dceae2SAndrei Emeltchenko sizeof(efs), (unsigned long) &efs); 311442dceae2SAndrei Emeltchenko } 31150a708f8fSGustavo F. Padovan break; 31160a708f8fSGustavo F. Padovan 31170a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3118c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 3119c8f79162SAndrei Emeltchenko chan->conn->mtu - 3120c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 3121c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 3122c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3123c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3124c8f79162SAndrei Emeltchenko chan->remote_mps = size; 31250a708f8fSGustavo F. Padovan 3126c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 31270a708f8fSGustavo F. Padovan 31280a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 31290a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 31300a708f8fSGustavo F. Padovan 31310a708f8fSGustavo F. Padovan break; 31320a708f8fSGustavo F. Padovan 31330a708f8fSGustavo F. Padovan default: 31340a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 31350a708f8fSGustavo F. Padovan 31360a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc)); 31370c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 31380a708f8fSGustavo F. Padovan } 31390a708f8fSGustavo F. Padovan 31400a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) 3141c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 31420a708f8fSGustavo F. Padovan } 3143fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 31440a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 314559e54bd1SAndrei Emeltchenko rsp->flags = __constant_cpu_to_le16(0); 31460a708f8fSGustavo F. Padovan 31470a708f8fSGustavo F. Padovan return ptr - data; 31480a708f8fSGustavo F. Padovan } 31490a708f8fSGustavo F. Padovan 3150b4450035SGustavo F. Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result) 31510a708f8fSGustavo F. Padovan { 31520a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 31530a708f8fSGustavo F. Padovan void *ptr = req->data; 31540a708f8fSGustavo F. Padovan int type, olen; 31550a708f8fSGustavo F. Padovan unsigned long val; 315636e999a8SMat Martineau struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 315766af7aafSAndrei Emeltchenko struct l2cap_conf_efs efs; 31580a708f8fSGustavo F. Padovan 3159fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); 31600a708f8fSGustavo F. Padovan 31610a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 31620a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 31630a708f8fSGustavo F. Padovan 31640a708f8fSGustavo F. Padovan switch (type) { 31650a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 31660a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) { 31670a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT; 31680c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU; 31690a708f8fSGustavo F. Padovan } else 31700c1bc5c6SGustavo F. Padovan chan->imtu = val; 31710c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 31720a708f8fSGustavo F. Padovan break; 31730a708f8fSGustavo F. Padovan 31740a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 31750c1bc5c6SGustavo F. Padovan chan->flush_to = val; 31760a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 31770c1bc5c6SGustavo F. Padovan 2, chan->flush_to); 31780a708f8fSGustavo F. Padovan break; 31790a708f8fSGustavo F. Padovan 31800a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 31810a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 31820a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 31830a708f8fSGustavo F. Padovan 3184c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && 31850c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode) 31860a708f8fSGustavo F. Padovan return -ECONNREFUSED; 31870a708f8fSGustavo F. Padovan 318847d1ec61SGustavo F. Padovan chan->fcs = 0; 31890a708f8fSGustavo F. Padovan 31900a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 31910a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 31920a708f8fSGustavo F. Padovan break; 31936327eb98SAndrei Emeltchenko 31946327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 3195c20f8e35SMat Martineau chan->ack_win = min_t(u16, val, chan->ack_win); 31963e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 31973e6b3b95SGustavo F. Padovan chan->tx_win); 31986327eb98SAndrei Emeltchenko break; 319966af7aafSAndrei Emeltchenko 320066af7aafSAndrei Emeltchenko case L2CAP_CONF_EFS: 320166af7aafSAndrei Emeltchenko if (olen == sizeof(efs)) 320266af7aafSAndrei Emeltchenko memcpy(&efs, (void *)val, olen); 320366af7aafSAndrei Emeltchenko 320466af7aafSAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 320566af7aafSAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 320666af7aafSAndrei Emeltchenko efs.stype != chan->local_stype) 320766af7aafSAndrei Emeltchenko return -ECONNREFUSED; 320866af7aafSAndrei Emeltchenko 320966af7aafSAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 321066af7aafSAndrei Emeltchenko sizeof(efs), (unsigned long) &efs); 321166af7aafSAndrei Emeltchenko break; 32120a708f8fSGustavo F. Padovan } 32130a708f8fSGustavo F. Padovan } 32140a708f8fSGustavo F. Padovan 32150c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) 32160a708f8fSGustavo F. Padovan return -ECONNREFUSED; 32170a708f8fSGustavo F. Padovan 32180c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode; 32190a708f8fSGustavo F. Padovan 32200e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) { 32210a708f8fSGustavo F. Padovan switch (rfc.mode) { 32220a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 322347d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 322447d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 322547d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 3226c20f8e35SMat Martineau if (!test_bit(FLAG_EXT_CTRL, &chan->flags)) 3227c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 3228c20f8e35SMat Martineau rfc.txwin_size); 322966af7aafSAndrei Emeltchenko 323066af7aafSAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 323166af7aafSAndrei Emeltchenko chan->local_msdu = le16_to_cpu(efs.msdu); 323266af7aafSAndrei Emeltchenko chan->local_sdu_itime = 323366af7aafSAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 323466af7aafSAndrei Emeltchenko chan->local_acc_lat = le32_to_cpu(efs.acc_lat); 323566af7aafSAndrei Emeltchenko chan->local_flush_to = 323666af7aafSAndrei Emeltchenko le32_to_cpu(efs.flush_to); 323766af7aafSAndrei Emeltchenko } 32380a708f8fSGustavo F. Padovan break; 323966af7aafSAndrei Emeltchenko 32400a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 324147d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 32420a708f8fSGustavo F. Padovan } 32430a708f8fSGustavo F. Padovan } 32440a708f8fSGustavo F. Padovan 3245fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 324659e54bd1SAndrei Emeltchenko req->flags = __constant_cpu_to_le16(0); 32470a708f8fSGustavo F. Padovan 32480a708f8fSGustavo F. Padovan return ptr - data; 32490a708f8fSGustavo F. Padovan } 32500a708f8fSGustavo F. Padovan 3251fe4128e0SGustavo F. Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags) 32520a708f8fSGustavo F. Padovan { 32530a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 32540a708f8fSGustavo F. Padovan void *ptr = rsp->data; 32550a708f8fSGustavo F. Padovan 3256fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan); 32570a708f8fSGustavo F. Padovan 3258fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 32590a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 32600a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags); 32610a708f8fSGustavo F. Padovan 32620a708f8fSGustavo F. Padovan return ptr - data; 32630a708f8fSGustavo F. Padovan } 32640a708f8fSGustavo F. Padovan 32658c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) 3266710f9b0aSGustavo F. Padovan { 3267710f9b0aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 32688c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 3269710f9b0aSGustavo F. Padovan u8 buf[128]; 3270710f9b0aSGustavo F. Padovan 3271fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 3272fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3273ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 3274ac73498cSAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 3275710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, 3276710f9b0aSGustavo F. Padovan L2CAP_CONN_RSP, sizeof(rsp), &rsp); 3277710f9b0aSGustavo F. Padovan 3278c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 3279710f9b0aSGustavo F. Padovan return; 3280710f9b0aSGustavo F. Padovan 3281710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 3282710f9b0aSGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 3283710f9b0aSGustavo F. Padovan chan->num_conf_req++; 3284710f9b0aSGustavo F. Padovan } 3285710f9b0aSGustavo F. Padovan 328647d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) 32870a708f8fSGustavo F. Padovan { 32880a708f8fSGustavo F. Padovan int type, olen; 32890a708f8fSGustavo F. Padovan unsigned long val; 3290c20f8e35SMat Martineau /* Use sane default values in case a misbehaving remote device 3291c20f8e35SMat Martineau * did not send an RFC or extended window size option. 3292c20f8e35SMat Martineau */ 3293c20f8e35SMat Martineau u16 txwin_ext = chan->ack_win; 3294c20f8e35SMat Martineau struct l2cap_conf_rfc rfc = { 3295c20f8e35SMat Martineau .mode = chan->mode, 3296c20f8e35SMat Martineau .retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO), 3297c20f8e35SMat Martineau .monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO), 3298c20f8e35SMat Martineau .max_pdu_size = cpu_to_le16(chan->imtu), 3299c20f8e35SMat Martineau .txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW), 3300c20f8e35SMat Martineau }; 33010a708f8fSGustavo F. Padovan 330247d1ec61SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); 33030a708f8fSGustavo F. Padovan 33040c1bc5c6SGustavo F. Padovan if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) 33050a708f8fSGustavo F. Padovan return; 33060a708f8fSGustavo F. Padovan 33070a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 33080a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 33090a708f8fSGustavo F. Padovan 3310c20f8e35SMat Martineau switch (type) { 3311c20f8e35SMat Martineau case L2CAP_CONF_RFC: 3312c20f8e35SMat Martineau if (olen == sizeof(rfc)) 33130a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 3314c20f8e35SMat Martineau break; 3315c20f8e35SMat Martineau case L2CAP_CONF_EWS: 3316c20f8e35SMat Martineau txwin_ext = val; 3317c20f8e35SMat Martineau break; 3318c20f8e35SMat Martineau } 33190a708f8fSGustavo F. Padovan } 33200a708f8fSGustavo F. Padovan 33210a708f8fSGustavo F. Padovan switch (rfc.mode) { 33220a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 332347d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 332447d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 332547d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 3326c20f8e35SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 3327c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, txwin_ext); 3328c20f8e35SMat Martineau else 3329c20f8e35SMat Martineau chan->ack_win = min_t(u16, chan->ack_win, 3330c20f8e35SMat Martineau rfc.txwin_size); 33310a708f8fSGustavo F. Padovan break; 33320a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 333347d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 33340a708f8fSGustavo F. Padovan } 33350a708f8fSGustavo F. Padovan } 33360a708f8fSGustavo F. Padovan 33370a708f8fSGustavo F. Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 33380a708f8fSGustavo F. Padovan { 3339e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 33400a708f8fSGustavo F. Padovan 3341e2fd318eSIlia Kolomisnky if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) 33420a708f8fSGustavo F. Padovan return 0; 33430a708f8fSGustavo F. Padovan 33440a708f8fSGustavo F. Padovan if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && 33450a708f8fSGustavo F. Padovan cmd->ident == conn->info_ident) { 334617cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 33470a708f8fSGustavo F. Padovan 33480a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 33490a708f8fSGustavo F. Padovan conn->info_ident = 0; 33500a708f8fSGustavo F. Padovan 33510a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 33520a708f8fSGustavo F. Padovan } 33530a708f8fSGustavo F. Padovan 33540a708f8fSGustavo F. Padovan return 0; 33550a708f8fSGustavo F. Padovan } 33560a708f8fSGustavo F. Padovan 33570a708f8fSGustavo F. Padovan static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 33580a708f8fSGustavo F. Padovan { 33590a708f8fSGustavo F. Padovan struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 33600a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 336123691d75SGustavo F. Padovan struct l2cap_chan *chan = NULL, *pchan; 33620a708f8fSGustavo F. Padovan struct sock *parent, *sk = NULL; 33630a708f8fSGustavo F. Padovan int result, status = L2CAP_CS_NO_INFO; 33640a708f8fSGustavo F. Padovan 33650a708f8fSGustavo F. Padovan u16 dcid = 0, scid = __le16_to_cpu(req->scid); 33660a708f8fSGustavo F. Padovan __le16 psm = req->psm; 33670a708f8fSGustavo F. Padovan 3368097db76cSAndrei Emeltchenko BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); 33690a708f8fSGustavo F. Padovan 33700a708f8fSGustavo F. Padovan /* Check if we have socket listening on psm */ 3371c2287681SIdo Yariv pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst); 337223691d75SGustavo F. Padovan if (!pchan) { 33730a708f8fSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 33740a708f8fSGustavo F. Padovan goto sendresp; 33750a708f8fSGustavo F. Padovan } 33760a708f8fSGustavo F. Padovan 337723691d75SGustavo F. Padovan parent = pchan->sk; 337823691d75SGustavo F. Padovan 33793df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 3380aa2ac881SGustavo F. Padovan lock_sock(parent); 33810a708f8fSGustavo F. Padovan 33820a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */ 33832983fd68SAndrei Emeltchenko if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) && 33840a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) { 33859f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_AUTH_FAILURE; 33860a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 33870a708f8fSGustavo F. Padovan goto response; 33880a708f8fSGustavo F. Padovan } 33890a708f8fSGustavo F. Padovan 33900a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM; 33910a708f8fSGustavo F. Padovan 33922dfa1003SGustavo Padovan /* Check if we already have channel with that dcid */ 33932dfa1003SGustavo Padovan if (__l2cap_get_chan_by_dcid(conn, scid)) 33942dfa1003SGustavo Padovan goto response; 33952dfa1003SGustavo Padovan 339680b98027SGustavo Padovan chan = pchan->ops->new_connection(pchan); 339780808e43SGustavo F. Padovan if (!chan) 33980a708f8fSGustavo F. Padovan goto response; 33990a708f8fSGustavo F. Padovan 340080808e43SGustavo F. Padovan sk = chan->sk; 340180808e43SGustavo F. Padovan 34020a708f8fSGustavo F. Padovan hci_conn_hold(conn->hcon); 34030a708f8fSGustavo F. Padovan 34040a708f8fSGustavo F. Padovan bacpy(&bt_sk(sk)->src, conn->src); 34050a708f8fSGustavo F. Padovan bacpy(&bt_sk(sk)->dst, conn->dst); 3406fe4128e0SGustavo F. Padovan chan->psm = psm; 3407fe4128e0SGustavo F. Padovan chan->dcid = scid; 34080a708f8fSGustavo F. Padovan 3409d1010240SGustavo F. Padovan bt_accept_enqueue(parent, sk); 3410d1010240SGustavo F. Padovan 34116be36555SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 341248454079SGustavo F. Padovan 3413fe4128e0SGustavo F. Padovan dcid = chan->scid; 34140a708f8fSGustavo F. Padovan 3415c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 34160a708f8fSGustavo F. Padovan 3417fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident; 34180a708f8fSGustavo F. Padovan 34190a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { 3420d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 3421c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) { 34220e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 34230a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 34240a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND; 34250a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 34260a708f8fSGustavo F. Padovan } else { 34270e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 34280a708f8fSGustavo F. Padovan result = L2CAP_CR_SUCCESS; 34290a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 34300a708f8fSGustavo F. Padovan } 34310a708f8fSGustavo F. Padovan } else { 34320e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 34330a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 34340a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND; 34350a708f8fSGustavo F. Padovan } 34360a708f8fSGustavo F. Padovan } else { 34370e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 34380a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 34390a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 34400a708f8fSGustavo F. Padovan } 34410a708f8fSGustavo F. Padovan 34420a708f8fSGustavo F. Padovan response: 3443aa2ac881SGustavo F. Padovan release_sock(parent); 34443df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 34450a708f8fSGustavo F. Padovan 34460a708f8fSGustavo F. Padovan sendresp: 34470a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid); 34480a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid); 34490a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result); 34500a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status); 34510a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); 34520a708f8fSGustavo F. Padovan 34530a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { 34540a708f8fSGustavo F. Padovan struct l2cap_info_req info; 3455ac73498cSAndrei Emeltchenko info.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); 34560a708f8fSGustavo F. Padovan 34570a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 34580a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 34590a708f8fSGustavo F. Padovan 3460ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 34610a708f8fSGustavo F. Padovan 34620a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 34630a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(info), &info); 34640a708f8fSGustavo F. Padovan } 34650a708f8fSGustavo F. Padovan 3466c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && 34670a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) { 34680a708f8fSGustavo F. Padovan u8 buf[128]; 3469c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 34700a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 347173ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 347273ffa904SGustavo F. Padovan chan->num_conf_req++; 34730a708f8fSGustavo F. Padovan } 34740a708f8fSGustavo F. Padovan 34750a708f8fSGustavo F. Padovan return 0; 34760a708f8fSGustavo F. Padovan } 34770a708f8fSGustavo F. Padovan 34780a708f8fSGustavo F. Padovan static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 34790a708f8fSGustavo F. Padovan { 34800a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; 34810a708f8fSGustavo F. Padovan u16 scid, dcid, result, status; 348248454079SGustavo F. Padovan struct l2cap_chan *chan; 34830a708f8fSGustavo F. Padovan u8 req[128]; 34843df91ea2SAndrei Emeltchenko int err; 34850a708f8fSGustavo F. Padovan 34860a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 34870a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 34880a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 34890a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status); 34900a708f8fSGustavo F. Padovan 34911b009c98SAndrei Emeltchenko BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", 34921b009c98SAndrei Emeltchenko dcid, scid, result, status); 34930a708f8fSGustavo F. Padovan 34943df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 34953df91ea2SAndrei Emeltchenko 34960a708f8fSGustavo F. Padovan if (scid) { 34973df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 34983df91ea2SAndrei Emeltchenko if (!chan) { 34993df91ea2SAndrei Emeltchenko err = -EFAULT; 35003df91ea2SAndrei Emeltchenko goto unlock; 35013df91ea2SAndrei Emeltchenko } 35020a708f8fSGustavo F. Padovan } else { 35033df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 35043df91ea2SAndrei Emeltchenko if (!chan) { 35053df91ea2SAndrei Emeltchenko err = -EFAULT; 35063df91ea2SAndrei Emeltchenko goto unlock; 35073df91ea2SAndrei Emeltchenko } 35080a708f8fSGustavo F. Padovan } 35090a708f8fSGustavo F. Padovan 35103df91ea2SAndrei Emeltchenko err = 0; 35113df91ea2SAndrei Emeltchenko 35126be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 351348454079SGustavo F. Padovan 35140a708f8fSGustavo F. Padovan switch (result) { 35150a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS: 351689bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 3517fc7f8a7eSGustavo F. Padovan chan->ident = 0; 3518fe4128e0SGustavo F. Padovan chan->dcid = dcid; 3519c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state); 35200a708f8fSGustavo F. Padovan 3521c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 35220a708f8fSGustavo F. Padovan break; 35230a708f8fSGustavo F. Padovan 35240a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 352573ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, req), req); 352673ffa904SGustavo F. Padovan chan->num_conf_req++; 35270a708f8fSGustavo F. Padovan break; 35280a708f8fSGustavo F. Padovan 35290a708f8fSGustavo F. Padovan case L2CAP_CR_PEND: 3530c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 35310a708f8fSGustavo F. Padovan break; 35320a708f8fSGustavo F. Padovan 35330a708f8fSGustavo F. Padovan default: 353448454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED); 35350a708f8fSGustavo F. Padovan break; 35360a708f8fSGustavo F. Padovan } 35370a708f8fSGustavo F. Padovan 35386be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 35393df91ea2SAndrei Emeltchenko 35403df91ea2SAndrei Emeltchenko unlock: 35413df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 35423df91ea2SAndrei Emeltchenko 35433df91ea2SAndrei Emeltchenko return err; 35440a708f8fSGustavo F. Padovan } 35450a708f8fSGustavo F. Padovan 354647d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan) 35470a708f8fSGustavo F. Padovan { 35480a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both 35490a708f8fSGustavo F. Padovan * sides request it. 35500a708f8fSGustavo F. Padovan */ 35510c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) 355247d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3553c1360a1cSGustavo F. Padovan else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) 355447d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16; 35550a708f8fSGustavo F. Padovan } 35560a708f8fSGustavo F. Padovan 35570a708f8fSGustavo F. Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 35580a708f8fSGustavo F. Padovan { 35590a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; 35600a708f8fSGustavo F. Padovan u16 dcid, flags; 35610a708f8fSGustavo F. Padovan u8 rsp[64]; 356248454079SGustavo F. Padovan struct l2cap_chan *chan; 35633c588192SMat Martineau int len, err = 0; 35640a708f8fSGustavo F. Padovan 35650a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 35660a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags); 35670a708f8fSGustavo F. Padovan 35680a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); 35690a708f8fSGustavo F. Padovan 3570baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid); 357148454079SGustavo F. Padovan if (!chan) 35720a708f8fSGustavo F. Padovan return -ENOENT; 35730a708f8fSGustavo F. Padovan 3574033b1142SDavid S. Miller if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { 3575e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_cid rej; 35760a708f8fSGustavo F. Padovan 3577ac73498cSAndrei Emeltchenko rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID); 3578e2fd318eSIlia Kolomisnky rej.scid = cpu_to_le16(chan->scid); 3579e2fd318eSIlia Kolomisnky rej.dcid = cpu_to_le16(chan->dcid); 3580e2fd318eSIlia Kolomisnky 35810a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 35820a708f8fSGustavo F. Padovan sizeof(rej), &rej); 35830a708f8fSGustavo F. Padovan goto unlock; 35840a708f8fSGustavo F. Padovan } 35850a708f8fSGustavo F. Padovan 35860a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */ 35870a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req); 35887ac28817SDan Rosenberg if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) { 35890a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 3590fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 35910a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp); 35920a708f8fSGustavo F. Padovan goto unlock; 35930a708f8fSGustavo F. Padovan } 35940a708f8fSGustavo F. Padovan 35950a708f8fSGustavo F. Padovan /* Store config. */ 359673ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len); 359773ffa904SGustavo F. Padovan chan->conf_len += len; 35980a708f8fSGustavo F. Padovan 359959e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) { 36000a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */ 36010a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 3602fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 36035325e5bbSAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), rsp); 36040a708f8fSGustavo F. Padovan goto unlock; 36050a708f8fSGustavo F. Padovan } 36060a708f8fSGustavo F. Padovan 36070a708f8fSGustavo F. Padovan /* Complete config. */ 360873ffa904SGustavo F. Padovan len = l2cap_parse_conf_req(chan, rsp); 36090a708f8fSGustavo F. Padovan if (len < 0) { 3610e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 36110a708f8fSGustavo F. Padovan goto unlock; 36120a708f8fSGustavo F. Padovan } 36130a708f8fSGustavo F. Padovan 36140a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); 361573ffa904SGustavo F. Padovan chan->num_conf_rsp++; 36160a708f8fSGustavo F. Padovan 36170a708f8fSGustavo F. Padovan /* Reset config buffer. */ 361873ffa904SGustavo F. Padovan chan->conf_len = 0; 36190a708f8fSGustavo F. Padovan 3620c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) 36210a708f8fSGustavo F. Padovan goto unlock; 36220a708f8fSGustavo F. Padovan 3623c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 362447d1ec61SGustavo F. Padovan set_default_fcs(chan); 36250a708f8fSGustavo F. Padovan 3626105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 3627105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 36283c588192SMat Martineau err = l2cap_ertm_init(chan); 36290a708f8fSGustavo F. Padovan 36303c588192SMat Martineau if (err < 0) 36313c588192SMat Martineau l2cap_send_disconn_req(chan->conn, chan, -err); 36323c588192SMat Martineau else 3633cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 36343c588192SMat Martineau 36350a708f8fSGustavo F. Padovan goto unlock; 36360a708f8fSGustavo F. Padovan } 36370a708f8fSGustavo F. Padovan 3638c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { 36390a708f8fSGustavo F. Padovan u8 buf[64]; 36400a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 364173ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 364273ffa904SGustavo F. Padovan chan->num_conf_req++; 36430a708f8fSGustavo F. Padovan } 36440a708f8fSGustavo F. Padovan 36450e8b207eSAndrei Emeltchenko /* Got Conf Rsp PENDING from remote side and asume we sent 36460e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */ 36470e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && 36480e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 36490e8b207eSAndrei Emeltchenko 36500e8b207eSAndrei Emeltchenko /* check compatibility */ 36510e8b207eSAndrei Emeltchenko 36520e8b207eSAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 36530e8b207eSAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 36540e8b207eSAndrei Emeltchenko 36550e8b207eSAndrei Emeltchenko l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 36560e8b207eSAndrei Emeltchenko l2cap_build_conf_rsp(chan, rsp, 36575325e5bbSAndrei Emeltchenko L2CAP_CONF_SUCCESS, flags), rsp); 36580e8b207eSAndrei Emeltchenko } 36590e8b207eSAndrei Emeltchenko 36600a708f8fSGustavo F. Padovan unlock: 36616be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 36623c588192SMat Martineau return err; 36630a708f8fSGustavo F. Padovan } 36640a708f8fSGustavo F. Padovan 36650a708f8fSGustavo F. Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 36660a708f8fSGustavo F. Padovan { 36670a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; 36680a708f8fSGustavo F. Padovan u16 scid, flags, result; 366948454079SGustavo F. Padovan struct l2cap_chan *chan; 367061386cbaSAndrei Emeltchenko int len = le16_to_cpu(cmd->len) - sizeof(*rsp); 36713c588192SMat Martineau int err = 0; 36720a708f8fSGustavo F. Padovan 36730a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 36740a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags); 36750a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 36760a708f8fSGustavo F. Padovan 367761386cbaSAndrei Emeltchenko BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags, 367861386cbaSAndrei Emeltchenko result, len); 36790a708f8fSGustavo F. Padovan 3680baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 368148454079SGustavo F. Padovan if (!chan) 36820a708f8fSGustavo F. Padovan return 0; 36830a708f8fSGustavo F. Padovan 36840a708f8fSGustavo F. Padovan switch (result) { 36850a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS: 368647d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len); 36870e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state); 36880a708f8fSGustavo F. Padovan break; 36890a708f8fSGustavo F. Padovan 36900e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING: 36910e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state); 36920e8b207eSAndrei Emeltchenko 36930e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 36940e8b207eSAndrei Emeltchenko char buf[64]; 36950e8b207eSAndrei Emeltchenko 36960e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len, 36970e8b207eSAndrei Emeltchenko buf, &result); 36980e8b207eSAndrei Emeltchenko if (len < 0) { 36990e8b207eSAndrei Emeltchenko l2cap_send_disconn_req(conn, chan, ECONNRESET); 37000e8b207eSAndrei Emeltchenko goto done; 37010e8b207eSAndrei Emeltchenko } 37020e8b207eSAndrei Emeltchenko 37030e8b207eSAndrei Emeltchenko /* check compatibility */ 37040e8b207eSAndrei Emeltchenko 37050e8b207eSAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 37060e8b207eSAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 37070e8b207eSAndrei Emeltchenko 37080e8b207eSAndrei Emeltchenko l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 37090e8b207eSAndrei Emeltchenko l2cap_build_conf_rsp(chan, buf, 37100e8b207eSAndrei Emeltchenko L2CAP_CONF_SUCCESS, 0x0000), buf); 37110e8b207eSAndrei Emeltchenko } 37120e8b207eSAndrei Emeltchenko goto done; 37130e8b207eSAndrei Emeltchenko 37140a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT: 371573ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { 37160a708f8fSGustavo F. Padovan char req[64]; 37170a708f8fSGustavo F. Padovan 37180a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { 3719e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 37200a708f8fSGustavo F. Padovan goto done; 37210a708f8fSGustavo F. Padovan } 37220a708f8fSGustavo F. Padovan 37230a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */ 37240a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS; 3725b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len, 3726b4450035SGustavo F. Padovan req, &result); 37270a708f8fSGustavo F. Padovan if (len < 0) { 3728e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 37290a708f8fSGustavo F. Padovan goto done; 37300a708f8fSGustavo F. Padovan } 37310a708f8fSGustavo F. Padovan 37320a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 37330a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req); 373473ffa904SGustavo F. Padovan chan->num_conf_req++; 37350a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS) 37360a708f8fSGustavo F. Padovan goto done; 37370a708f8fSGustavo F. Padovan break; 37380a708f8fSGustavo F. Padovan } 37390a708f8fSGustavo F. Padovan 37400a708f8fSGustavo F. Padovan default: 37416be36555SAndrei Emeltchenko l2cap_chan_set_err(chan, ECONNRESET); 37422e0052e4SAndrei Emeltchenko 3743ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); 3744e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 37450a708f8fSGustavo F. Padovan goto done; 37460a708f8fSGustavo F. Padovan } 37470a708f8fSGustavo F. Padovan 374859e54bd1SAndrei Emeltchenko if (flags & L2CAP_CONF_FLAG_CONTINUATION) 37490a708f8fSGustavo F. Padovan goto done; 37500a708f8fSGustavo F. Padovan 3751c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state); 37520a708f8fSGustavo F. Padovan 3753c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { 375447d1ec61SGustavo F. Padovan set_default_fcs(chan); 37550a708f8fSGustavo F. Padovan 3756105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 3757105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 37583c588192SMat Martineau err = l2cap_ertm_init(chan); 37590a708f8fSGustavo F. Padovan 37603c588192SMat Martineau if (err < 0) 37613c588192SMat Martineau l2cap_send_disconn_req(chan->conn, chan, -err); 37623c588192SMat Martineau else 3763cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 37640a708f8fSGustavo F. Padovan } 37650a708f8fSGustavo F. Padovan 37660a708f8fSGustavo F. Padovan done: 37676be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 37683c588192SMat Martineau return err; 37690a708f8fSGustavo F. Padovan } 37700a708f8fSGustavo F. Padovan 37710a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 37720a708f8fSGustavo F. Padovan { 37730a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; 37740a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp; 37750a708f8fSGustavo F. Padovan u16 dcid, scid; 377648454079SGustavo F. Padovan struct l2cap_chan *chan; 37770a708f8fSGustavo F. Padovan struct sock *sk; 37780a708f8fSGustavo F. Padovan 37790a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid); 37800a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 37810a708f8fSGustavo F. Padovan 37820a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); 37830a708f8fSGustavo F. Padovan 37843df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 37853df91ea2SAndrei Emeltchenko 37863df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, dcid); 37873df91ea2SAndrei Emeltchenko if (!chan) { 37883df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 37890a708f8fSGustavo F. Padovan return 0; 37903df91ea2SAndrei Emeltchenko } 37910a708f8fSGustavo F. Padovan 37926be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 37936be36555SAndrei Emeltchenko 379448454079SGustavo F. Padovan sk = chan->sk; 379548454079SGustavo F. Padovan 3796fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3797fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 37980a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); 37990a708f8fSGustavo F. Padovan 38006be36555SAndrei Emeltchenko lock_sock(sk); 38010a708f8fSGustavo F. Padovan sk->sk_shutdown = SHUTDOWN_MASK; 38026be36555SAndrei Emeltchenko release_sock(sk); 38030a708f8fSGustavo F. Padovan 380461d6ef3eSMat Martineau l2cap_chan_hold(chan); 380548454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET); 38066be36555SAndrei Emeltchenko 38076be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 38080a708f8fSGustavo F. Padovan 380980b98027SGustavo Padovan chan->ops->close(chan); 381061d6ef3eSMat Martineau l2cap_chan_put(chan); 38113df91ea2SAndrei Emeltchenko 38123df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 38133df91ea2SAndrei Emeltchenko 38140a708f8fSGustavo F. Padovan return 0; 38150a708f8fSGustavo F. Padovan } 38160a708f8fSGustavo F. Padovan 38170a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 38180a708f8fSGustavo F. Padovan { 38190a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; 38200a708f8fSGustavo F. Padovan u16 dcid, scid; 382148454079SGustavo F. Padovan struct l2cap_chan *chan; 38220a708f8fSGustavo F. Padovan 38230a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 38240a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 38250a708f8fSGustavo F. Padovan 38260a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); 38270a708f8fSGustavo F. Padovan 38283df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 38293df91ea2SAndrei Emeltchenko 38303df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 38313df91ea2SAndrei Emeltchenko if (!chan) { 38323df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 38330a708f8fSGustavo F. Padovan return 0; 38343df91ea2SAndrei Emeltchenko } 38350a708f8fSGustavo F. Padovan 38366be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 383748454079SGustavo F. Padovan 383861d6ef3eSMat Martineau l2cap_chan_hold(chan); 383948454079SGustavo F. Padovan l2cap_chan_del(chan, 0); 38406be36555SAndrei Emeltchenko 38416be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 38420a708f8fSGustavo F. Padovan 384380b98027SGustavo Padovan chan->ops->close(chan); 384461d6ef3eSMat Martineau l2cap_chan_put(chan); 38453df91ea2SAndrei Emeltchenko 38463df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 38473df91ea2SAndrei Emeltchenko 38480a708f8fSGustavo F. Padovan return 0; 38490a708f8fSGustavo F. Padovan } 38500a708f8fSGustavo F. Padovan 38510a708f8fSGustavo F. Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 38520a708f8fSGustavo F. Padovan { 38530a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data; 38540a708f8fSGustavo F. Padovan u16 type; 38550a708f8fSGustavo F. Padovan 38560a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type); 38570a708f8fSGustavo F. Padovan 38580a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type); 38590a708f8fSGustavo F. Padovan 38600a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) { 38610a708f8fSGustavo F. Padovan u8 buf[8]; 38620a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask; 38630a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 3864ac73498cSAndrei Emeltchenko rsp->type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); 3865ac73498cSAndrei Emeltchenko rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); 38660a708f8fSGustavo F. Padovan if (!disable_ertm) 38670a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING 38680a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS; 3869a5fd6f30SAndrei Emeltchenko if (enable_hs) 38706327eb98SAndrei Emeltchenko feat_mask |= L2CAP_FEAT_EXT_FLOW 38716327eb98SAndrei Emeltchenko | L2CAP_FEAT_EXT_WINDOW; 3872a5fd6f30SAndrei Emeltchenko 38730a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data); 38740a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 38750a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(buf), buf); 38760a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) { 38770a708f8fSGustavo F. Padovan u8 buf[12]; 38780a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 387950a147cdSMat Martineau 388050a147cdSMat Martineau if (enable_hs) 388150a147cdSMat Martineau l2cap_fixed_chan[0] |= L2CAP_FC_A2MP; 388250a147cdSMat Martineau else 388350a147cdSMat Martineau l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP; 388450a147cdSMat Martineau 3885ac73498cSAndrei Emeltchenko rsp->type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); 3886ac73498cSAndrei Emeltchenko rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); 3887c6337ea6SAndrei Emeltchenko memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); 38880a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 38890a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(buf), buf); 38900a708f8fSGustavo F. Padovan } else { 38910a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp; 38920a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type); 3893ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP); 38940a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 38950a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(rsp), &rsp); 38960a708f8fSGustavo F. Padovan } 38970a708f8fSGustavo F. Padovan 38980a708f8fSGustavo F. Padovan return 0; 38990a708f8fSGustavo F. Padovan } 39000a708f8fSGustavo F. Padovan 39010a708f8fSGustavo F. Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 39020a708f8fSGustavo F. Padovan { 39030a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; 39040a708f8fSGustavo F. Padovan u16 type, result; 39050a708f8fSGustavo F. Padovan 39060a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type); 39070a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 39080a708f8fSGustavo F. Padovan 39090a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); 39100a708f8fSGustavo F. Padovan 3911e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */ 3912e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident || 3913e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 3914e90165beSAndrei Emeltchenko return 0; 3915e90165beSAndrei Emeltchenko 391617cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 39170a708f8fSGustavo F. Padovan 39180a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) { 39190a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 39200a708f8fSGustavo F. Padovan conn->info_ident = 0; 39210a708f8fSGustavo F. Padovan 39220a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 39230a708f8fSGustavo F. Padovan 39240a708f8fSGustavo F. Padovan return 0; 39250a708f8fSGustavo F. Padovan } 39260a708f8fSGustavo F. Padovan 3927978c93b9SAndrei Emeltchenko switch (type) { 3928978c93b9SAndrei Emeltchenko case L2CAP_IT_FEAT_MASK: 39290a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data); 39300a708f8fSGustavo F. Padovan 39310a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { 39320a708f8fSGustavo F. Padovan struct l2cap_info_req req; 3933ac73498cSAndrei Emeltchenko req.type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); 39340a708f8fSGustavo F. Padovan 39350a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 39360a708f8fSGustavo F. Padovan 39370a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 39380a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 39390a708f8fSGustavo F. Padovan } else { 39400a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 39410a708f8fSGustavo F. Padovan conn->info_ident = 0; 39420a708f8fSGustavo F. Padovan 39430a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 39440a708f8fSGustavo F. Padovan } 3945978c93b9SAndrei Emeltchenko break; 3946978c93b9SAndrei Emeltchenko 3947978c93b9SAndrei Emeltchenko case L2CAP_IT_FIXED_CHAN: 3948978c93b9SAndrei Emeltchenko conn->fixed_chan_mask = rsp->data[0]; 39490a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 39500a708f8fSGustavo F. Padovan conn->info_ident = 0; 39510a708f8fSGustavo F. Padovan 39520a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 3953978c93b9SAndrei Emeltchenko break; 39540a708f8fSGustavo F. Padovan } 39550a708f8fSGustavo F. Padovan 39560a708f8fSGustavo F. Padovan return 0; 39570a708f8fSGustavo F. Padovan } 39580a708f8fSGustavo F. Padovan 3959f94ff6ffSMat Martineau static inline int l2cap_create_channel_req(struct l2cap_conn *conn, 3960f94ff6ffSMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, 3961f94ff6ffSMat Martineau void *data) 3962f94ff6ffSMat Martineau { 3963f94ff6ffSMat Martineau struct l2cap_create_chan_req *req = data; 3964f94ff6ffSMat Martineau struct l2cap_create_chan_rsp rsp; 3965f94ff6ffSMat Martineau u16 psm, scid; 3966f94ff6ffSMat Martineau 3967f94ff6ffSMat Martineau if (cmd_len != sizeof(*req)) 3968f94ff6ffSMat Martineau return -EPROTO; 3969f94ff6ffSMat Martineau 3970f94ff6ffSMat Martineau if (!enable_hs) 3971f94ff6ffSMat Martineau return -EINVAL; 3972f94ff6ffSMat Martineau 3973f94ff6ffSMat Martineau psm = le16_to_cpu(req->psm); 3974f94ff6ffSMat Martineau scid = le16_to_cpu(req->scid); 3975f94ff6ffSMat Martineau 3976ad0ac6caSAndrei Emeltchenko BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id); 3977f94ff6ffSMat Martineau 3978f94ff6ffSMat Martineau /* Placeholder: Always reject */ 3979f94ff6ffSMat Martineau rsp.dcid = 0; 3980f94ff6ffSMat Martineau rsp.scid = cpu_to_le16(scid); 39818ce0c498SAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM); 39828ce0c498SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 3983f94ff6ffSMat Martineau 3984f94ff6ffSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, 3985f94ff6ffSMat Martineau sizeof(rsp), &rsp); 3986f94ff6ffSMat Martineau 3987f94ff6ffSMat Martineau return 0; 3988f94ff6ffSMat Martineau } 3989f94ff6ffSMat Martineau 3990f94ff6ffSMat Martineau static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn, 3991f94ff6ffSMat Martineau struct l2cap_cmd_hdr *cmd, void *data) 3992f94ff6ffSMat Martineau { 3993f94ff6ffSMat Martineau BT_DBG("conn %p", conn); 3994f94ff6ffSMat Martineau 3995f94ff6ffSMat Martineau return l2cap_connect_rsp(conn, cmd, data); 3996f94ff6ffSMat Martineau } 3997f94ff6ffSMat Martineau 39988d5a04a1SMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident, 39998d5a04a1SMat Martineau u16 icid, u16 result) 40008d5a04a1SMat Martineau { 40018d5a04a1SMat Martineau struct l2cap_move_chan_rsp rsp; 40028d5a04a1SMat Martineau 4003ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 40048d5a04a1SMat Martineau 40058d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 40068d5a04a1SMat Martineau rsp.result = cpu_to_le16(result); 40078d5a04a1SMat Martineau 40088d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp); 40098d5a04a1SMat Martineau } 40108d5a04a1SMat Martineau 40118d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn, 4012ad0ac6caSAndrei Emeltchenko struct l2cap_chan *chan, 4013ad0ac6caSAndrei Emeltchenko u16 icid, u16 result) 40148d5a04a1SMat Martineau { 40158d5a04a1SMat Martineau struct l2cap_move_chan_cfm cfm; 40168d5a04a1SMat Martineau u8 ident; 40178d5a04a1SMat Martineau 4018ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 40198d5a04a1SMat Martineau 40208d5a04a1SMat Martineau ident = l2cap_get_ident(conn); 40218d5a04a1SMat Martineau if (chan) 40228d5a04a1SMat Martineau chan->ident = ident; 40238d5a04a1SMat Martineau 40248d5a04a1SMat Martineau cfm.icid = cpu_to_le16(icid); 40258d5a04a1SMat Martineau cfm.result = cpu_to_le16(result); 40268d5a04a1SMat Martineau 40278d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm); 40288d5a04a1SMat Martineau } 40298d5a04a1SMat Martineau 40308d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, 40318d5a04a1SMat Martineau u16 icid) 40328d5a04a1SMat Martineau { 40338d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp rsp; 40348d5a04a1SMat Martineau 4035ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 40368d5a04a1SMat Martineau 40378d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 40388d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp); 40398d5a04a1SMat Martineau } 40408d5a04a1SMat Martineau 40418d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn, 4042ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 4043ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 40448d5a04a1SMat Martineau { 40458d5a04a1SMat Martineau struct l2cap_move_chan_req *req = data; 40468d5a04a1SMat Martineau u16 icid = 0; 40478d5a04a1SMat Martineau u16 result = L2CAP_MR_NOT_ALLOWED; 40488d5a04a1SMat Martineau 40498d5a04a1SMat Martineau if (cmd_len != sizeof(*req)) 40508d5a04a1SMat Martineau return -EPROTO; 40518d5a04a1SMat Martineau 40528d5a04a1SMat Martineau icid = le16_to_cpu(req->icid); 40538d5a04a1SMat Martineau 4054ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id); 40558d5a04a1SMat Martineau 40568d5a04a1SMat Martineau if (!enable_hs) 40578d5a04a1SMat Martineau return -EINVAL; 40588d5a04a1SMat Martineau 40598d5a04a1SMat Martineau /* Placeholder: Always refuse */ 40608d5a04a1SMat Martineau l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result); 40618d5a04a1SMat Martineau 40628d5a04a1SMat Martineau return 0; 40638d5a04a1SMat Martineau } 40648d5a04a1SMat Martineau 40658d5a04a1SMat Martineau static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn, 4066ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 4067ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 40688d5a04a1SMat Martineau { 40698d5a04a1SMat Martineau struct l2cap_move_chan_rsp *rsp = data; 40708d5a04a1SMat Martineau u16 icid, result; 40718d5a04a1SMat Martineau 40728d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 40738d5a04a1SMat Martineau return -EPROTO; 40748d5a04a1SMat Martineau 40758d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 40768d5a04a1SMat Martineau result = le16_to_cpu(rsp->result); 40778d5a04a1SMat Martineau 4078ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 40798d5a04a1SMat Martineau 40808d5a04a1SMat Martineau /* Placeholder: Always unconfirmed */ 40818d5a04a1SMat Martineau l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED); 40828d5a04a1SMat Martineau 40838d5a04a1SMat Martineau return 0; 40848d5a04a1SMat Martineau } 40858d5a04a1SMat Martineau 40868d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn, 4087ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 4088ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 40898d5a04a1SMat Martineau { 40908d5a04a1SMat Martineau struct l2cap_move_chan_cfm *cfm = data; 40918d5a04a1SMat Martineau u16 icid, result; 40928d5a04a1SMat Martineau 40938d5a04a1SMat Martineau if (cmd_len != sizeof(*cfm)) 40948d5a04a1SMat Martineau return -EPROTO; 40958d5a04a1SMat Martineau 40968d5a04a1SMat Martineau icid = le16_to_cpu(cfm->icid); 40978d5a04a1SMat Martineau result = le16_to_cpu(cfm->result); 40988d5a04a1SMat Martineau 4099ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); 41008d5a04a1SMat Martineau 41018d5a04a1SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 41028d5a04a1SMat Martineau 41038d5a04a1SMat Martineau return 0; 41048d5a04a1SMat Martineau } 41058d5a04a1SMat Martineau 41068d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, 4107ad0ac6caSAndrei Emeltchenko struct l2cap_cmd_hdr *cmd, 4108ad0ac6caSAndrei Emeltchenko u16 cmd_len, void *data) 41098d5a04a1SMat Martineau { 41108d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp *rsp = data; 41118d5a04a1SMat Martineau u16 icid; 41128d5a04a1SMat Martineau 41138d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 41148d5a04a1SMat Martineau return -EPROTO; 41158d5a04a1SMat Martineau 41168d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 41178d5a04a1SMat Martineau 4118ad0ac6caSAndrei Emeltchenko BT_DBG("icid 0x%4.4x", icid); 41198d5a04a1SMat Martineau 41208d5a04a1SMat Martineau return 0; 41218d5a04a1SMat Martineau } 41228d5a04a1SMat Martineau 4123e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency, 4124de73115aSClaudio Takahasi u16 to_multiplier) 4125de73115aSClaudio Takahasi { 4126de73115aSClaudio Takahasi u16 max_latency; 4127de73115aSClaudio Takahasi 4128de73115aSClaudio Takahasi if (min > max || min < 6 || max > 3200) 4129de73115aSClaudio Takahasi return -EINVAL; 4130de73115aSClaudio Takahasi 4131de73115aSClaudio Takahasi if (to_multiplier < 10 || to_multiplier > 3200) 4132de73115aSClaudio Takahasi return -EINVAL; 4133de73115aSClaudio Takahasi 4134de73115aSClaudio Takahasi if (max >= to_multiplier * 8) 4135de73115aSClaudio Takahasi return -EINVAL; 4136de73115aSClaudio Takahasi 4137de73115aSClaudio Takahasi max_latency = (to_multiplier * 8 / max) - 1; 4138de73115aSClaudio Takahasi if (latency > 499 || latency > max_latency) 4139de73115aSClaudio Takahasi return -EINVAL; 4140de73115aSClaudio Takahasi 4141de73115aSClaudio Takahasi return 0; 4142de73115aSClaudio Takahasi } 4143de73115aSClaudio Takahasi 4144de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, 4145de73115aSClaudio Takahasi struct l2cap_cmd_hdr *cmd, u8 *data) 4146de73115aSClaudio Takahasi { 4147de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon; 4148de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req; 4149de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp; 4150de73115aSClaudio Takahasi u16 min, max, latency, to_multiplier, cmd_len; 41512ce603ebSClaudio Takahasi int err; 4152de73115aSClaudio Takahasi 4153de73115aSClaudio Takahasi if (!(hcon->link_mode & HCI_LM_MASTER)) 4154de73115aSClaudio Takahasi return -EINVAL; 4155de73115aSClaudio Takahasi 4156de73115aSClaudio Takahasi cmd_len = __le16_to_cpu(cmd->len); 4157de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) 4158de73115aSClaudio Takahasi return -EPROTO; 4159de73115aSClaudio Takahasi 4160de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data; 4161de73115aSClaudio Takahasi min = __le16_to_cpu(req->min); 4162de73115aSClaudio Takahasi max = __le16_to_cpu(req->max); 4163de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency); 4164de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier); 4165de73115aSClaudio Takahasi 4166de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", 4167de73115aSClaudio Takahasi min, max, latency, to_multiplier); 4168de73115aSClaudio Takahasi 4169de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp)); 41702ce603ebSClaudio Takahasi 41712ce603ebSClaudio Takahasi err = l2cap_check_conn_param(min, max, latency, to_multiplier); 41722ce603ebSClaudio Takahasi if (err) 4173ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); 4174de73115aSClaudio Takahasi else 4175ac73498cSAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); 4176de73115aSClaudio Takahasi 4177de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, 4178de73115aSClaudio Takahasi sizeof(rsp), &rsp); 4179de73115aSClaudio Takahasi 41802ce603ebSClaudio Takahasi if (!err) 41812ce603ebSClaudio Takahasi hci_le_conn_update(hcon, min, max, latency, to_multiplier); 41822ce603ebSClaudio Takahasi 4183de73115aSClaudio Takahasi return 0; 4184de73115aSClaudio Takahasi } 4185de73115aSClaudio Takahasi 41863300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, 41873300d9a9SClaudio Takahasi struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 41883300d9a9SClaudio Takahasi { 41893300d9a9SClaudio Takahasi int err = 0; 41903300d9a9SClaudio Takahasi 41913300d9a9SClaudio Takahasi switch (cmd->code) { 41923300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 41933300d9a9SClaudio Takahasi l2cap_command_rej(conn, cmd, data); 41943300d9a9SClaudio Takahasi break; 41953300d9a9SClaudio Takahasi 41963300d9a9SClaudio Takahasi case L2CAP_CONN_REQ: 41973300d9a9SClaudio Takahasi err = l2cap_connect_req(conn, cmd, data); 41983300d9a9SClaudio Takahasi break; 41993300d9a9SClaudio Takahasi 42003300d9a9SClaudio Takahasi case L2CAP_CONN_RSP: 42013300d9a9SClaudio Takahasi err = l2cap_connect_rsp(conn, cmd, data); 42023300d9a9SClaudio Takahasi break; 42033300d9a9SClaudio Takahasi 42043300d9a9SClaudio Takahasi case L2CAP_CONF_REQ: 42053300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data); 42063300d9a9SClaudio Takahasi break; 42073300d9a9SClaudio Takahasi 42083300d9a9SClaudio Takahasi case L2CAP_CONF_RSP: 42093300d9a9SClaudio Takahasi err = l2cap_config_rsp(conn, cmd, data); 42103300d9a9SClaudio Takahasi break; 42113300d9a9SClaudio Takahasi 42123300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ: 42133300d9a9SClaudio Takahasi err = l2cap_disconnect_req(conn, cmd, data); 42143300d9a9SClaudio Takahasi break; 42153300d9a9SClaudio Takahasi 42163300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP: 42173300d9a9SClaudio Takahasi err = l2cap_disconnect_rsp(conn, cmd, data); 42183300d9a9SClaudio Takahasi break; 42193300d9a9SClaudio Takahasi 42203300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ: 42213300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data); 42223300d9a9SClaudio Takahasi break; 42233300d9a9SClaudio Takahasi 42243300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP: 42253300d9a9SClaudio Takahasi break; 42263300d9a9SClaudio Takahasi 42273300d9a9SClaudio Takahasi case L2CAP_INFO_REQ: 42283300d9a9SClaudio Takahasi err = l2cap_information_req(conn, cmd, data); 42293300d9a9SClaudio Takahasi break; 42303300d9a9SClaudio Takahasi 42313300d9a9SClaudio Takahasi case L2CAP_INFO_RSP: 42323300d9a9SClaudio Takahasi err = l2cap_information_rsp(conn, cmd, data); 42333300d9a9SClaudio Takahasi break; 42343300d9a9SClaudio Takahasi 4235f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_REQ: 4236f94ff6ffSMat Martineau err = l2cap_create_channel_req(conn, cmd, cmd_len, data); 4237f94ff6ffSMat Martineau break; 4238f94ff6ffSMat Martineau 4239f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_RSP: 4240f94ff6ffSMat Martineau err = l2cap_create_channel_rsp(conn, cmd, data); 4241f94ff6ffSMat Martineau break; 4242f94ff6ffSMat Martineau 42438d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_REQ: 42448d5a04a1SMat Martineau err = l2cap_move_channel_req(conn, cmd, cmd_len, data); 42458d5a04a1SMat Martineau break; 42468d5a04a1SMat Martineau 42478d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_RSP: 42488d5a04a1SMat Martineau err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data); 42498d5a04a1SMat Martineau break; 42508d5a04a1SMat Martineau 42518d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM: 42528d5a04a1SMat Martineau err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data); 42538d5a04a1SMat Martineau break; 42548d5a04a1SMat Martineau 42558d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM_RSP: 42568d5a04a1SMat Martineau err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data); 42578d5a04a1SMat Martineau break; 42588d5a04a1SMat Martineau 42593300d9a9SClaudio Takahasi default: 42603300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code); 42613300d9a9SClaudio Takahasi err = -EINVAL; 42623300d9a9SClaudio Takahasi break; 42633300d9a9SClaudio Takahasi } 42643300d9a9SClaudio Takahasi 42653300d9a9SClaudio Takahasi return err; 42663300d9a9SClaudio Takahasi } 42673300d9a9SClaudio Takahasi 42683300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, 42693300d9a9SClaudio Takahasi struct l2cap_cmd_hdr *cmd, u8 *data) 42703300d9a9SClaudio Takahasi { 42713300d9a9SClaudio Takahasi switch (cmd->code) { 42723300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 42733300d9a9SClaudio Takahasi return 0; 42743300d9a9SClaudio Takahasi 42753300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ: 4276de73115aSClaudio Takahasi return l2cap_conn_param_update_req(conn, cmd, data); 42773300d9a9SClaudio Takahasi 42783300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP: 42793300d9a9SClaudio Takahasi return 0; 42803300d9a9SClaudio Takahasi 42813300d9a9SClaudio Takahasi default: 42823300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code); 42833300d9a9SClaudio Takahasi return -EINVAL; 42843300d9a9SClaudio Takahasi } 42853300d9a9SClaudio Takahasi } 42863300d9a9SClaudio Takahasi 42873300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn, 42883300d9a9SClaudio Takahasi struct sk_buff *skb) 42890a708f8fSGustavo F. Padovan { 42900a708f8fSGustavo F. Padovan u8 *data = skb->data; 42910a708f8fSGustavo F. Padovan int len = skb->len; 42920a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr cmd; 42933300d9a9SClaudio Takahasi int err; 42940a708f8fSGustavo F. Padovan 42950a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb); 42960a708f8fSGustavo F. Padovan 42970a708f8fSGustavo F. Padovan while (len >= L2CAP_CMD_HDR_SIZE) { 42980a708f8fSGustavo F. Padovan u16 cmd_len; 42990a708f8fSGustavo F. Padovan memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); 43000a708f8fSGustavo F. Padovan data += L2CAP_CMD_HDR_SIZE; 43010a708f8fSGustavo F. Padovan len -= L2CAP_CMD_HDR_SIZE; 43020a708f8fSGustavo F. Padovan 43030a708f8fSGustavo F. Padovan cmd_len = le16_to_cpu(cmd.len); 43040a708f8fSGustavo F. Padovan 43050a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident); 43060a708f8fSGustavo F. Padovan 43070a708f8fSGustavo F. Padovan if (cmd_len > len || !cmd.ident) { 43080a708f8fSGustavo F. Padovan BT_DBG("corrupted command"); 43090a708f8fSGustavo F. Padovan break; 43100a708f8fSGustavo F. Padovan } 43110a708f8fSGustavo F. Padovan 43123300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 43133300d9a9SClaudio Takahasi err = l2cap_le_sig_cmd(conn, &cmd, data); 43143300d9a9SClaudio Takahasi else 43153300d9a9SClaudio Takahasi err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data); 43160a708f8fSGustavo F. Padovan 43170a708f8fSGustavo F. Padovan if (err) { 4318e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk rej; 43192c6d1a2eSGustavo F. Padovan 43202c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err); 43210a708f8fSGustavo F. Padovan 43220a708f8fSGustavo F. Padovan /* FIXME: Map err to a valid reason */ 4323ac73498cSAndrei Emeltchenko rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 43240a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); 43250a708f8fSGustavo F. Padovan } 43260a708f8fSGustavo F. Padovan 43270a708f8fSGustavo F. Padovan data += cmd_len; 43280a708f8fSGustavo F. Padovan len -= cmd_len; 43290a708f8fSGustavo F. Padovan } 43300a708f8fSGustavo F. Padovan 43310a708f8fSGustavo F. Padovan kfree_skb(skb); 43320a708f8fSGustavo F. Padovan } 43330a708f8fSGustavo F. Padovan 433447d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) 43350a708f8fSGustavo F. Padovan { 43360a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs; 4337e4ca6d98SAndrei Emeltchenko int hdr_size; 4338e4ca6d98SAndrei Emeltchenko 4339e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 4340e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE; 4341e4ca6d98SAndrei Emeltchenko else 4342e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE; 43430a708f8fSGustavo F. Padovan 434447d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 434503a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE); 43460a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len); 43470a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); 43480a708f8fSGustavo F. Padovan 43490a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs) 43500a708f8fSGustavo F. Padovan return -EBADMSG; 43510a708f8fSGustavo F. Padovan } 43520a708f8fSGustavo F. Padovan return 0; 43530a708f8fSGustavo F. Padovan } 43540a708f8fSGustavo F. Padovan 43556ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) 43560a708f8fSGustavo F. Padovan { 4357e31f7633SMat Martineau struct l2cap_ctrl control; 43580a708f8fSGustavo F. Padovan 4359e31f7633SMat Martineau BT_DBG("chan %p", chan); 43600a708f8fSGustavo F. Padovan 4361e31f7633SMat Martineau memset(&control, 0, sizeof(control)); 4362e31f7633SMat Martineau control.sframe = 1; 4363e31f7633SMat Martineau control.final = 1; 4364e31f7633SMat Martineau control.reqseq = chan->buffer_seq; 4365e31f7633SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 43660a708f8fSGustavo F. Padovan 4367e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 4368e31f7633SMat Martineau control.super = L2CAP_SUPER_RNR; 4369e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 43700a708f8fSGustavo F. Padovan } 43710a708f8fSGustavo F. Padovan 4372e31f7633SMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 4373e31f7633SMat Martineau chan->unacked_frames > 0) 4374e31f7633SMat Martineau __set_retrans_timer(chan); 43750a708f8fSGustavo F. Padovan 4376e31f7633SMat Martineau /* Send pending iframes */ 4377525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 43780a708f8fSGustavo F. Padovan 4379e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 4380e31f7633SMat Martineau test_bit(CONN_SEND_FBIT, &chan->conn_state)) { 4381e31f7633SMat Martineau /* F-bit wasn't sent in an s-frame or i-frame yet, so 4382e31f7633SMat Martineau * send it now. 4383e31f7633SMat Martineau */ 4384e31f7633SMat Martineau control.super = L2CAP_SUPER_RR; 4385e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 43860a708f8fSGustavo F. Padovan } 43870a708f8fSGustavo F. Padovan } 43880a708f8fSGustavo F. Padovan 438984084a31SMat Martineau static void append_skb_frag(struct sk_buff *skb, 439084084a31SMat Martineau struct sk_buff *new_frag, struct sk_buff **last_frag) 43910a708f8fSGustavo F. Padovan { 439284084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments 439384084a31SMat Martineau * skb->data_len reflects only data in fragments 439484084a31SMat Martineau */ 439584084a31SMat Martineau if (!skb_has_frag_list(skb)) 439684084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag; 439784084a31SMat Martineau 439884084a31SMat Martineau new_frag->next = NULL; 439984084a31SMat Martineau 440084084a31SMat Martineau (*last_frag)->next = new_frag; 440184084a31SMat Martineau *last_frag = new_frag; 440284084a31SMat Martineau 440384084a31SMat Martineau skb->len += new_frag->len; 440484084a31SMat Martineau skb->data_len += new_frag->len; 440584084a31SMat Martineau skb->truesize += new_frag->truesize; 440684084a31SMat Martineau } 440784084a31SMat Martineau 44084b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, 44094b51dae9SMat Martineau struct l2cap_ctrl *control) 441084084a31SMat Martineau { 441184084a31SMat Martineau int err = -EINVAL; 44120a708f8fSGustavo F. Padovan 44134b51dae9SMat Martineau switch (control->sar) { 44147e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED: 441584084a31SMat Martineau if (chan->sdu) 441684084a31SMat Martineau break; 44170a708f8fSGustavo F. Padovan 441880b98027SGustavo Padovan err = chan->ops->recv(chan, skb); 441984084a31SMat Martineau break; 44200a708f8fSGustavo F. Padovan 44217e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START: 442284084a31SMat Martineau if (chan->sdu) 442384084a31SMat Martineau break; 44240a708f8fSGustavo F. Padovan 44256f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data); 442603a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE); 44270a708f8fSGustavo F. Padovan 442884084a31SMat Martineau if (chan->sdu_len > chan->imtu) { 442984084a31SMat Martineau err = -EMSGSIZE; 443084084a31SMat Martineau break; 443184084a31SMat Martineau } 44320a708f8fSGustavo F. Padovan 443384084a31SMat Martineau if (skb->len >= chan->sdu_len) 443484084a31SMat Martineau break; 443584084a31SMat Martineau 443684084a31SMat Martineau chan->sdu = skb; 443784084a31SMat Martineau chan->sdu_last_frag = skb; 443884084a31SMat Martineau 443984084a31SMat Martineau skb = NULL; 444084084a31SMat Martineau err = 0; 44410a708f8fSGustavo F. Padovan break; 44420a708f8fSGustavo F. Padovan 44437e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE: 44446f61fd47SGustavo F. Padovan if (!chan->sdu) 444584084a31SMat Martineau break; 44460a708f8fSGustavo F. Padovan 444784084a31SMat Martineau append_skb_frag(chan->sdu, skb, 444884084a31SMat Martineau &chan->sdu_last_frag); 444984084a31SMat Martineau skb = NULL; 44500a708f8fSGustavo F. Padovan 445184084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len) 445284084a31SMat Martineau break; 44530a708f8fSGustavo F. Padovan 445484084a31SMat Martineau err = 0; 44550a708f8fSGustavo F. Padovan break; 44560a708f8fSGustavo F. Padovan 44577e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END: 44586f61fd47SGustavo F. Padovan if (!chan->sdu) 445984084a31SMat Martineau break; 44600a708f8fSGustavo F. Padovan 446184084a31SMat Martineau append_skb_frag(chan->sdu, skb, 446284084a31SMat Martineau &chan->sdu_last_frag); 446384084a31SMat Martineau skb = NULL; 44640a708f8fSGustavo F. Padovan 446584084a31SMat Martineau if (chan->sdu->len != chan->sdu_len) 446684084a31SMat Martineau break; 44670a708f8fSGustavo F. Padovan 446880b98027SGustavo Padovan err = chan->ops->recv(chan, chan->sdu); 44690a708f8fSGustavo F. Padovan 447084084a31SMat Martineau if (!err) { 447184084a31SMat Martineau /* Reassembly complete */ 447284084a31SMat Martineau chan->sdu = NULL; 447384084a31SMat Martineau chan->sdu_last_frag = NULL; 447484084a31SMat Martineau chan->sdu_len = 0; 44750a708f8fSGustavo F. Padovan } 44760a708f8fSGustavo F. Padovan break; 44770a708f8fSGustavo F. Padovan } 44780a708f8fSGustavo F. Padovan 447984084a31SMat Martineau if (err) { 44800a708f8fSGustavo F. Padovan kfree_skb(skb); 44816f61fd47SGustavo F. Padovan kfree_skb(chan->sdu); 44826f61fd47SGustavo F. Padovan chan->sdu = NULL; 448384084a31SMat Martineau chan->sdu_last_frag = NULL; 448484084a31SMat Martineau chan->sdu_len = 0; 448584084a31SMat Martineau } 44860a708f8fSGustavo F. Padovan 448784084a31SMat Martineau return err; 44880a708f8fSGustavo F. Padovan } 44890a708f8fSGustavo F. Padovan 4490e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 44910a708f8fSGustavo F. Padovan { 449261aa4f5bSMat Martineau u8 event; 449361aa4f5bSMat Martineau 449461aa4f5bSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 449561aa4f5bSMat Martineau return; 449661aa4f5bSMat Martineau 449761aa4f5bSMat Martineau event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR; 4498401bb1f7SAndrei Emeltchenko l2cap_tx(chan, NULL, NULL, event); 44990a708f8fSGustavo F. Padovan } 45000a708f8fSGustavo F. Padovan 4501d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan) 4502d2a7ac5dSMat Martineau { 450363838725SMat Martineau int err = 0; 450463838725SMat Martineau /* Pass sequential frames to l2cap_reassemble_sdu() 450563838725SMat Martineau * until a gap is encountered. 450663838725SMat Martineau */ 450763838725SMat Martineau 450863838725SMat Martineau BT_DBG("chan %p", chan); 450963838725SMat Martineau 451063838725SMat Martineau while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 451163838725SMat Martineau struct sk_buff *skb; 451263838725SMat Martineau BT_DBG("Searching for skb with txseq %d (queue len %d)", 451363838725SMat Martineau chan->buffer_seq, skb_queue_len(&chan->srej_q)); 451463838725SMat Martineau 451563838725SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq); 451663838725SMat Martineau 451763838725SMat Martineau if (!skb) 451863838725SMat Martineau break; 451963838725SMat Martineau 452063838725SMat Martineau skb_unlink(skb, &chan->srej_q); 452163838725SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 452263838725SMat Martineau err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->control); 452363838725SMat Martineau if (err) 452463838725SMat Martineau break; 452563838725SMat Martineau } 452663838725SMat Martineau 452763838725SMat Martineau if (skb_queue_empty(&chan->srej_q)) { 452863838725SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 452963838725SMat Martineau l2cap_send_ack(chan); 453063838725SMat Martineau } 453163838725SMat Martineau 453263838725SMat Martineau return err; 4533d2a7ac5dSMat Martineau } 4534d2a7ac5dSMat Martineau 4535d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan, 4536d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 4537d2a7ac5dSMat Martineau { 4538f80842a8SMat Martineau struct sk_buff *skb; 4539f80842a8SMat Martineau 4540f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 4541f80842a8SMat Martineau 4542f80842a8SMat Martineau if (control->reqseq == chan->next_tx_seq) { 4543f80842a8SMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 4544f80842a8SMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 4545f80842a8SMat Martineau return; 4546f80842a8SMat Martineau } 4547f80842a8SMat Martineau 4548f80842a8SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 4549f80842a8SMat Martineau 4550f80842a8SMat Martineau if (skb == NULL) { 4551f80842a8SMat Martineau BT_DBG("Seq %d not available for retransmission", 4552f80842a8SMat Martineau control->reqseq); 4553f80842a8SMat Martineau return; 4554f80842a8SMat Martineau } 4555f80842a8SMat Martineau 4556f80842a8SMat Martineau if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) { 4557f80842a8SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 4558f80842a8SMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 4559f80842a8SMat Martineau return; 4560f80842a8SMat Martineau } 4561f80842a8SMat Martineau 4562f80842a8SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4563f80842a8SMat Martineau 4564f80842a8SMat Martineau if (control->poll) { 4565f80842a8SMat Martineau l2cap_pass_to_tx(chan, control); 4566f80842a8SMat Martineau 4567f80842a8SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 4568f80842a8SMat Martineau l2cap_retransmit(chan, control); 4569f80842a8SMat Martineau l2cap_ertm_send(chan); 4570f80842a8SMat Martineau 4571f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 4572f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 4573f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 4574f80842a8SMat Martineau } 4575f80842a8SMat Martineau } else { 4576f80842a8SMat Martineau l2cap_pass_to_tx_fbit(chan, control); 4577f80842a8SMat Martineau 4578f80842a8SMat Martineau if (control->final) { 4579f80842a8SMat Martineau if (chan->srej_save_reqseq != control->reqseq || 4580f80842a8SMat Martineau !test_and_clear_bit(CONN_SREJ_ACT, 4581f80842a8SMat Martineau &chan->conn_state)) 4582f80842a8SMat Martineau l2cap_retransmit(chan, control); 4583f80842a8SMat Martineau } else { 4584f80842a8SMat Martineau l2cap_retransmit(chan, control); 4585f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 4586f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 4587f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 4588f80842a8SMat Martineau } 4589f80842a8SMat Martineau } 4590f80842a8SMat Martineau } 4591d2a7ac5dSMat Martineau } 4592d2a7ac5dSMat Martineau 4593d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan, 4594d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 4595d2a7ac5dSMat Martineau { 4596fcd289dfSMat Martineau struct sk_buff *skb; 4597fcd289dfSMat Martineau 4598fcd289dfSMat Martineau BT_DBG("chan %p, control %p", chan, control); 4599fcd289dfSMat Martineau 4600fcd289dfSMat Martineau if (control->reqseq == chan->next_tx_seq) { 4601fcd289dfSMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 4602fcd289dfSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 4603fcd289dfSMat Martineau return; 4604fcd289dfSMat Martineau } 4605fcd289dfSMat Martineau 4606fcd289dfSMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 4607fcd289dfSMat Martineau 4608fcd289dfSMat Martineau if (chan->max_tx && skb && 4609fcd289dfSMat Martineau bt_cb(skb)->control.retries >= chan->max_tx) { 4610fcd289dfSMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 4611fcd289dfSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 4612fcd289dfSMat Martineau return; 4613fcd289dfSMat Martineau } 4614fcd289dfSMat Martineau 4615fcd289dfSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4616fcd289dfSMat Martineau 4617fcd289dfSMat Martineau l2cap_pass_to_tx(chan, control); 4618fcd289dfSMat Martineau 4619fcd289dfSMat Martineau if (control->final) { 4620fcd289dfSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 4621fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 4622fcd289dfSMat Martineau } else { 4623fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 4624fcd289dfSMat Martineau l2cap_ertm_send(chan); 4625fcd289dfSMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) 4626fcd289dfSMat Martineau set_bit(CONN_REJ_ACT, &chan->conn_state); 4627fcd289dfSMat Martineau } 4628d2a7ac5dSMat Martineau } 4629d2a7ac5dSMat Martineau 46304b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) 46314b51dae9SMat Martineau { 46324b51dae9SMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 46334b51dae9SMat Martineau 46344b51dae9SMat Martineau BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq, 46354b51dae9SMat Martineau chan->expected_tx_seq); 46364b51dae9SMat Martineau 46374b51dae9SMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 46384b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 46394b51dae9SMat Martineau chan->tx_win) { 46404b51dae9SMat Martineau /* See notes below regarding "double poll" and 46414b51dae9SMat Martineau * invalid packets. 46424b51dae9SMat Martineau */ 46434b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 46444b51dae9SMat Martineau BT_DBG("Invalid/Ignore - after SREJ"); 46454b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 46464b51dae9SMat Martineau } else { 46474b51dae9SMat Martineau BT_DBG("Invalid - in window after SREJ sent"); 46484b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 46494b51dae9SMat Martineau } 46504b51dae9SMat Martineau } 46514b51dae9SMat Martineau 46524b51dae9SMat Martineau if (chan->srej_list.head == txseq) { 46534b51dae9SMat Martineau BT_DBG("Expected SREJ"); 46544b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED_SREJ; 46554b51dae9SMat Martineau } 46564b51dae9SMat Martineau 46574b51dae9SMat Martineau if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) { 46584b51dae9SMat Martineau BT_DBG("Duplicate SREJ - txseq already stored"); 46594b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE_SREJ; 46604b51dae9SMat Martineau } 46614b51dae9SMat Martineau 46624b51dae9SMat Martineau if (l2cap_seq_list_contains(&chan->srej_list, txseq)) { 46634b51dae9SMat Martineau BT_DBG("Unexpected SREJ - not requested"); 46644b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED_SREJ; 46654b51dae9SMat Martineau } 46664b51dae9SMat Martineau } 46674b51dae9SMat Martineau 46684b51dae9SMat Martineau if (chan->expected_tx_seq == txseq) { 46694b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 46704b51dae9SMat Martineau chan->tx_win) { 46714b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 46724b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 46734b51dae9SMat Martineau } else { 46744b51dae9SMat Martineau BT_DBG("Expected"); 46754b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED; 46764b51dae9SMat Martineau } 46774b51dae9SMat Martineau } 46784b51dae9SMat Martineau 46794b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) < 46804b51dae9SMat Martineau __seq_offset(chan, chan->expected_tx_seq, 46814b51dae9SMat Martineau chan->last_acked_seq)){ 46824b51dae9SMat Martineau BT_DBG("Duplicate - expected_tx_seq later than txseq"); 46834b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE; 46844b51dae9SMat Martineau } 46854b51dae9SMat Martineau 46864b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) { 46874b51dae9SMat Martineau /* A source of invalid packets is a "double poll" condition, 46884b51dae9SMat Martineau * where delays cause us to send multiple poll packets. If 46894b51dae9SMat Martineau * the remote stack receives and processes both polls, 46904b51dae9SMat Martineau * sequence numbers can wrap around in such a way that a 46914b51dae9SMat Martineau * resent frame has a sequence number that looks like new data 46924b51dae9SMat Martineau * with a sequence gap. This would trigger an erroneous SREJ 46934b51dae9SMat Martineau * request. 46944b51dae9SMat Martineau * 46954b51dae9SMat Martineau * Fortunately, this is impossible with a tx window that's 46964b51dae9SMat Martineau * less than half of the maximum sequence number, which allows 46974b51dae9SMat Martineau * invalid frames to be safely ignored. 46984b51dae9SMat Martineau * 46994b51dae9SMat Martineau * With tx window sizes greater than half of the tx window 47004b51dae9SMat Martineau * maximum, the frame is invalid and cannot be ignored. This 47014b51dae9SMat Martineau * causes a disconnect. 47024b51dae9SMat Martineau */ 47034b51dae9SMat Martineau 47044b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 47054b51dae9SMat Martineau BT_DBG("Invalid/Ignore - txseq outside tx window"); 47064b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 47074b51dae9SMat Martineau } else { 47084b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 47094b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 47104b51dae9SMat Martineau } 47114b51dae9SMat Martineau } else { 47124b51dae9SMat Martineau BT_DBG("Unexpected - txseq indicates missing frames"); 47134b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED; 47144b51dae9SMat Martineau } 47154b51dae9SMat Martineau } 47164b51dae9SMat Martineau 4717d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan, 4718d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 4719d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 4720d2a7ac5dSMat Martineau { 4721d2a7ac5dSMat Martineau int err = 0; 4722d2a7ac5dSMat Martineau bool skb_in_use = 0; 4723d2a7ac5dSMat Martineau 4724d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 4725d2a7ac5dSMat Martineau event); 4726d2a7ac5dSMat Martineau 4727d2a7ac5dSMat Martineau switch (event) { 4728d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 4729d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, control->txseq)) { 4730d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 4731d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4732d2a7ac5dSMat Martineau 4733d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 4734d2a7ac5dSMat Martineau BT_DBG("Busy, discarding expected seq %d", 4735d2a7ac5dSMat Martineau control->txseq); 4736d2a7ac5dSMat Martineau break; 4737d2a7ac5dSMat Martineau } 4738d2a7ac5dSMat Martineau 4739d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, 4740d2a7ac5dSMat Martineau control->txseq); 4741d2a7ac5dSMat Martineau 4742d2a7ac5dSMat Martineau chan->buffer_seq = chan->expected_tx_seq; 4743d2a7ac5dSMat Martineau skb_in_use = 1; 4744d2a7ac5dSMat Martineau 4745d2a7ac5dSMat Martineau err = l2cap_reassemble_sdu(chan, skb, control); 4746d2a7ac5dSMat Martineau if (err) 4747d2a7ac5dSMat Martineau break; 4748d2a7ac5dSMat Martineau 4749d2a7ac5dSMat Martineau if (control->final) { 4750d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 4751d2a7ac5dSMat Martineau &chan->conn_state)) { 4752d2a7ac5dSMat Martineau control->final = 0; 4753d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 4754d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 4755d2a7ac5dSMat Martineau } 4756d2a7ac5dSMat Martineau } 4757d2a7ac5dSMat Martineau 4758d2a7ac5dSMat Martineau if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 4759d2a7ac5dSMat Martineau l2cap_send_ack(chan); 4760d2a7ac5dSMat Martineau break; 4761d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 4762d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4763d2a7ac5dSMat Martineau 4764d2a7ac5dSMat Martineau /* Can't issue SREJ frames in the local busy state. 4765d2a7ac5dSMat Martineau * Drop this frame, it will be seen as missing 4766d2a7ac5dSMat Martineau * when local busy is exited. 4767d2a7ac5dSMat Martineau */ 4768d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 4769d2a7ac5dSMat Martineau BT_DBG("Busy, discarding unexpected seq %d", 4770d2a7ac5dSMat Martineau control->txseq); 4771d2a7ac5dSMat Martineau break; 4772d2a7ac5dSMat Martineau } 4773d2a7ac5dSMat Martineau 4774d2a7ac5dSMat Martineau /* There was a gap in the sequence, so an SREJ 4775d2a7ac5dSMat Martineau * must be sent for each missing frame. The 4776d2a7ac5dSMat Martineau * current frame is stored for later use. 4777d2a7ac5dSMat Martineau */ 4778d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4779d2a7ac5dSMat Martineau skb_in_use = 1; 4780d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4781d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4782d2a7ac5dSMat Martineau 4783d2a7ac5dSMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 4784d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 4785d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 4786d2a7ac5dSMat Martineau 4787d2a7ac5dSMat Martineau chan->rx_state = L2CAP_RX_STATE_SREJ_SENT; 4788d2a7ac5dSMat Martineau break; 4789d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 4790d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4791d2a7ac5dSMat Martineau break; 4792d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 4793d2a7ac5dSMat Martineau break; 4794d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 4795d2a7ac5dSMat Martineau default: 4796d2a7ac5dSMat Martineau l2cap_send_disconn_req(chan->conn, chan, 4797d2a7ac5dSMat Martineau ECONNRESET); 4798d2a7ac5dSMat Martineau break; 4799d2a7ac5dSMat Martineau } 4800d2a7ac5dSMat Martineau break; 4801d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 4802d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4803d2a7ac5dSMat Martineau if (control->final) { 4804d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4805d2a7ac5dSMat Martineau 4806d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 4807d2a7ac5dSMat Martineau &chan->conn_state)) { 4808d2a7ac5dSMat Martineau control->final = 0; 4809d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 4810d2a7ac5dSMat Martineau } 4811d2a7ac5dSMat Martineau 4812d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 4813d2a7ac5dSMat Martineau } else if (control->poll) { 4814d2a7ac5dSMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 4815d2a7ac5dSMat Martineau } else { 4816d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 4817d2a7ac5dSMat Martineau &chan->conn_state) && 4818d2a7ac5dSMat Martineau chan->unacked_frames) 4819d2a7ac5dSMat Martineau __set_retrans_timer(chan); 4820d2a7ac5dSMat Martineau 4821d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 4822d2a7ac5dSMat Martineau } 4823d2a7ac5dSMat Martineau break; 4824d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 4825d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4826d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4827d2a7ac5dSMat Martineau if (control && control->poll) { 4828d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 4829d2a7ac5dSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 4830d2a7ac5dSMat Martineau } 4831d2a7ac5dSMat Martineau __clear_retrans_timer(chan); 4832d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 4833d2a7ac5dSMat Martineau break; 4834d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 4835d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 4836d2a7ac5dSMat Martineau break; 4837d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 4838d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 4839d2a7ac5dSMat Martineau break; 4840d2a7ac5dSMat Martineau default: 4841d2a7ac5dSMat Martineau break; 4842d2a7ac5dSMat Martineau } 4843d2a7ac5dSMat Martineau 4844d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 4845d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 4846d2a7ac5dSMat Martineau kfree_skb(skb); 4847d2a7ac5dSMat Martineau } 4848d2a7ac5dSMat Martineau 4849d2a7ac5dSMat Martineau return err; 4850d2a7ac5dSMat Martineau } 4851d2a7ac5dSMat Martineau 4852d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, 4853d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 4854d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 4855d2a7ac5dSMat Martineau { 4856d2a7ac5dSMat Martineau int err = 0; 4857d2a7ac5dSMat Martineau u16 txseq = control->txseq; 4858d2a7ac5dSMat Martineau bool skb_in_use = 0; 4859d2a7ac5dSMat Martineau 4860d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 4861d2a7ac5dSMat Martineau event); 4862d2a7ac5dSMat Martineau 4863d2a7ac5dSMat Martineau switch (event) { 4864d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 4865d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, txseq)) { 4866d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 4867d2a7ac5dSMat Martineau /* Keep frame for reassembly later */ 4868d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4869d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4870d2a7ac5dSMat Martineau skb_in_use = 1; 4871d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4872d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4873d2a7ac5dSMat Martineau 4874d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 4875d2a7ac5dSMat Martineau break; 4876d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED_SREJ: 4877d2a7ac5dSMat Martineau l2cap_seq_list_pop(&chan->srej_list); 4878d2a7ac5dSMat Martineau 4879d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4880d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4881d2a7ac5dSMat Martineau skb_in_use = 1; 4882d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4883d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4884d2a7ac5dSMat Martineau 4885d2a7ac5dSMat Martineau err = l2cap_rx_queued_iframes(chan); 4886d2a7ac5dSMat Martineau if (err) 4887d2a7ac5dSMat Martineau break; 4888d2a7ac5dSMat Martineau 4889d2a7ac5dSMat Martineau break; 4890d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 4891d2a7ac5dSMat Martineau /* Got a frame that can't be reassembled yet. 4892d2a7ac5dSMat Martineau * Save it for later, and send SREJs to cover 4893d2a7ac5dSMat Martineau * the missing frames. 4894d2a7ac5dSMat Martineau */ 4895d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4896d2a7ac5dSMat Martineau skb_in_use = 1; 4897d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4898d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4899d2a7ac5dSMat Martineau 4900d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4901d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 4902d2a7ac5dSMat Martineau break; 4903d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED_SREJ: 4904d2a7ac5dSMat Martineau /* This frame was requested with an SREJ, but 4905d2a7ac5dSMat Martineau * some expected retransmitted frames are 4906d2a7ac5dSMat Martineau * missing. Request retransmission of missing 4907d2a7ac5dSMat Martineau * SREJ'd frames. 4908d2a7ac5dSMat Martineau */ 4909d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4910d2a7ac5dSMat Martineau skb_in_use = 1; 4911d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4912d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4913d2a7ac5dSMat Martineau 4914d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4915d2a7ac5dSMat Martineau l2cap_send_srej_list(chan, control->txseq); 4916d2a7ac5dSMat Martineau break; 4917d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE_SREJ: 4918d2a7ac5dSMat Martineau /* We've already queued this frame. Drop this copy. */ 4919d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4920d2a7ac5dSMat Martineau break; 4921d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 4922d2a7ac5dSMat Martineau /* Expecting a later sequence number, so this frame 4923d2a7ac5dSMat Martineau * was already received. Ignore it completely. 4924d2a7ac5dSMat Martineau */ 4925d2a7ac5dSMat Martineau break; 4926d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 4927d2a7ac5dSMat Martineau break; 4928d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 4929d2a7ac5dSMat Martineau default: 4930d2a7ac5dSMat Martineau l2cap_send_disconn_req(chan->conn, chan, 4931d2a7ac5dSMat Martineau ECONNRESET); 4932d2a7ac5dSMat Martineau break; 4933d2a7ac5dSMat Martineau } 4934d2a7ac5dSMat Martineau break; 4935d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 4936d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4937d2a7ac5dSMat Martineau if (control->final) { 4938d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4939d2a7ac5dSMat Martineau 4940d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 4941d2a7ac5dSMat Martineau &chan->conn_state)) { 4942d2a7ac5dSMat Martineau control->final = 0; 4943d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 4944d2a7ac5dSMat Martineau } 4945d2a7ac5dSMat Martineau 4946d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 4947d2a7ac5dSMat Martineau } else if (control->poll) { 4948d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 4949d2a7ac5dSMat Martineau &chan->conn_state) && 4950d2a7ac5dSMat Martineau chan->unacked_frames) { 4951d2a7ac5dSMat Martineau __set_retrans_timer(chan); 4952d2a7ac5dSMat Martineau } 4953d2a7ac5dSMat Martineau 4954d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 4955d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 4956d2a7ac5dSMat Martineau } else { 4957d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 4958d2a7ac5dSMat Martineau &chan->conn_state) && 4959d2a7ac5dSMat Martineau chan->unacked_frames) 4960d2a7ac5dSMat Martineau __set_retrans_timer(chan); 4961d2a7ac5dSMat Martineau 4962d2a7ac5dSMat Martineau l2cap_send_ack(chan); 4963d2a7ac5dSMat Martineau } 4964d2a7ac5dSMat Martineau break; 4965d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 4966d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4967d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4968d2a7ac5dSMat Martineau if (control->poll) { 4969d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 4970d2a7ac5dSMat Martineau } else { 4971d2a7ac5dSMat Martineau struct l2cap_ctrl rr_control; 4972d2a7ac5dSMat Martineau memset(&rr_control, 0, sizeof(rr_control)); 4973d2a7ac5dSMat Martineau rr_control.sframe = 1; 4974d2a7ac5dSMat Martineau rr_control.super = L2CAP_SUPER_RR; 4975d2a7ac5dSMat Martineau rr_control.reqseq = chan->buffer_seq; 4976d2a7ac5dSMat Martineau l2cap_send_sframe(chan, &rr_control); 4977d2a7ac5dSMat Martineau } 4978d2a7ac5dSMat Martineau 4979d2a7ac5dSMat Martineau break; 4980d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 4981d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 4982d2a7ac5dSMat Martineau break; 4983d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 4984d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 4985d2a7ac5dSMat Martineau break; 4986d2a7ac5dSMat Martineau } 4987d2a7ac5dSMat Martineau 4988d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 4989d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 4990d2a7ac5dSMat Martineau kfree_skb(skb); 4991d2a7ac5dSMat Martineau } 4992d2a7ac5dSMat Martineau 4993d2a7ac5dSMat Martineau return err; 4994d2a7ac5dSMat Martineau } 4995d2a7ac5dSMat Martineau 4996d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq) 4997d2a7ac5dSMat Martineau { 4998d2a7ac5dSMat Martineau /* Make sure reqseq is for a packet that has been sent but not acked */ 4999d2a7ac5dSMat Martineau u16 unacked; 5000d2a7ac5dSMat Martineau 5001d2a7ac5dSMat Martineau unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq); 5002d2a7ac5dSMat Martineau return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked; 5003d2a7ac5dSMat Martineau } 5004d2a7ac5dSMat Martineau 5005cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 5006cec8ab6eSMat Martineau struct sk_buff *skb, u8 event) 50070a708f8fSGustavo F. Padovan { 5008d2a7ac5dSMat Martineau int err = 0; 5009d2a7ac5dSMat Martineau 5010d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan, 5011d2a7ac5dSMat Martineau control, skb, event, chan->rx_state); 5012d2a7ac5dSMat Martineau 5013d2a7ac5dSMat Martineau if (__valid_reqseq(chan, control->reqseq)) { 5014d2a7ac5dSMat Martineau switch (chan->rx_state) { 5015d2a7ac5dSMat Martineau case L2CAP_RX_STATE_RECV: 5016d2a7ac5dSMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 5017d2a7ac5dSMat Martineau break; 5018d2a7ac5dSMat Martineau case L2CAP_RX_STATE_SREJ_SENT: 5019d2a7ac5dSMat Martineau err = l2cap_rx_state_srej_sent(chan, control, skb, 5020d2a7ac5dSMat Martineau event); 5021d2a7ac5dSMat Martineau break; 5022d2a7ac5dSMat Martineau default: 5023d2a7ac5dSMat Martineau /* shut it down */ 5024d2a7ac5dSMat Martineau break; 5025d2a7ac5dSMat Martineau } 5026d2a7ac5dSMat Martineau } else { 5027d2a7ac5dSMat Martineau BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d", 5028d2a7ac5dSMat Martineau control->reqseq, chan->next_tx_seq, 5029d2a7ac5dSMat Martineau chan->expected_ack_seq); 5030d2a7ac5dSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 5031d2a7ac5dSMat Martineau } 5032d2a7ac5dSMat Martineau 5033d2a7ac5dSMat Martineau return err; 5034cec8ab6eSMat Martineau } 5035cec8ab6eSMat Martineau 5036cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 5037cec8ab6eSMat Martineau struct sk_buff *skb) 5038cec8ab6eSMat Martineau { 50394b51dae9SMat Martineau int err = 0; 50404b51dae9SMat Martineau 50414b51dae9SMat Martineau BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb, 50424b51dae9SMat Martineau chan->rx_state); 50434b51dae9SMat Martineau 50444b51dae9SMat Martineau if (l2cap_classify_txseq(chan, control->txseq) == 50454b51dae9SMat Martineau L2CAP_TXSEQ_EXPECTED) { 50464b51dae9SMat Martineau l2cap_pass_to_tx(chan, control); 50474b51dae9SMat Martineau 50484b51dae9SMat Martineau BT_DBG("buffer_seq %d->%d", chan->buffer_seq, 50494b51dae9SMat Martineau __next_seq(chan, chan->buffer_seq)); 50504b51dae9SMat Martineau 50514b51dae9SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 50524b51dae9SMat Martineau 50534b51dae9SMat Martineau l2cap_reassemble_sdu(chan, skb, control); 50544b51dae9SMat Martineau } else { 50554b51dae9SMat Martineau if (chan->sdu) { 50564b51dae9SMat Martineau kfree_skb(chan->sdu); 50574b51dae9SMat Martineau chan->sdu = NULL; 50584b51dae9SMat Martineau } 50594b51dae9SMat Martineau chan->sdu_last_frag = NULL; 50604b51dae9SMat Martineau chan->sdu_len = 0; 50614b51dae9SMat Martineau 50624b51dae9SMat Martineau if (skb) { 50634b51dae9SMat Martineau BT_DBG("Freeing %p", skb); 50644b51dae9SMat Martineau kfree_skb(skb); 50654b51dae9SMat Martineau } 50664b51dae9SMat Martineau } 50674b51dae9SMat Martineau 50684b51dae9SMat Martineau chan->last_acked_seq = control->txseq; 50694b51dae9SMat Martineau chan->expected_tx_seq = __next_seq(chan, control->txseq); 50704b51dae9SMat Martineau 50714b51dae9SMat Martineau return err; 5072cec8ab6eSMat Martineau } 5073cec8ab6eSMat Martineau 5074cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 5075cec8ab6eSMat Martineau { 5076cec8ab6eSMat Martineau struct l2cap_ctrl *control = &bt_cb(skb)->control; 5077cec8ab6eSMat Martineau u16 len; 5078cec8ab6eSMat Martineau u8 event; 50790a708f8fSGustavo F. Padovan 5080b76bbd66SMat Martineau __unpack_control(chan, skb); 5081b76bbd66SMat Martineau 50820a708f8fSGustavo F. Padovan len = skb->len; 50830a708f8fSGustavo F. Padovan 50840a708f8fSGustavo F. Padovan /* 50850a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here. 50860a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery 5087cec8ab6eSMat Martineau * procedures and ask for retransmission. 50880a708f8fSGustavo F. Padovan */ 508947d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 50900a708f8fSGustavo F. Padovan goto drop; 50910a708f8fSGustavo F. Padovan 5092cec8ab6eSMat Martineau if (!control->sframe && control->sar == L2CAP_SAR_START) 509303a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 50940a708f8fSGustavo F. Padovan 509547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 509603a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 50970a708f8fSGustavo F. Padovan 509847d1ec61SGustavo F. Padovan if (len > chan->mps) { 50998c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 51000a708f8fSGustavo F. Padovan goto drop; 51010a708f8fSGustavo F. Padovan } 51020a708f8fSGustavo F. Padovan 5103cec8ab6eSMat Martineau if (!control->sframe) { 5104cec8ab6eSMat Martineau int err; 51050a708f8fSGustavo F. Padovan 5106cec8ab6eSMat Martineau BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d", 5107cec8ab6eSMat Martineau control->sar, control->reqseq, control->final, 5108cec8ab6eSMat Martineau control->txseq); 5109836be934SAndrei Emeltchenko 5110cec8ab6eSMat Martineau /* Validate F-bit - F=0 always valid, F=1 only 5111cec8ab6eSMat Martineau * valid in TX WAIT_F 5112cec8ab6eSMat Martineau */ 5113cec8ab6eSMat Martineau if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F) 51140a708f8fSGustavo F. Padovan goto drop; 51150a708f8fSGustavo F. Padovan 5116cec8ab6eSMat Martineau if (chan->mode != L2CAP_MODE_STREAMING) { 5117cec8ab6eSMat Martineau event = L2CAP_EV_RECV_IFRAME; 5118cec8ab6eSMat Martineau err = l2cap_rx(chan, control, skb, event); 51190a708f8fSGustavo F. Padovan } else { 5120cec8ab6eSMat Martineau err = l2cap_stream_rx(chan, control, skb); 5121cec8ab6eSMat Martineau } 5122cec8ab6eSMat Martineau 5123cec8ab6eSMat Martineau if (err) 5124cec8ab6eSMat Martineau l2cap_send_disconn_req(chan->conn, chan, 5125cec8ab6eSMat Martineau ECONNRESET); 5126cec8ab6eSMat Martineau } else { 5127cec8ab6eSMat Martineau const u8 rx_func_to_event[4] = { 5128cec8ab6eSMat Martineau L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ, 5129cec8ab6eSMat Martineau L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ 5130cec8ab6eSMat Martineau }; 5131cec8ab6eSMat Martineau 5132cec8ab6eSMat Martineau /* Only I-frames are expected in streaming mode */ 5133cec8ab6eSMat Martineau if (chan->mode == L2CAP_MODE_STREAMING) 5134cec8ab6eSMat Martineau goto drop; 5135cec8ab6eSMat Martineau 5136cec8ab6eSMat Martineau BT_DBG("sframe reqseq %d, final %d, poll %d, super %d", 5137cec8ab6eSMat Martineau control->reqseq, control->final, control->poll, 5138cec8ab6eSMat Martineau control->super); 5139cec8ab6eSMat Martineau 51400a708f8fSGustavo F. Padovan if (len != 0) { 51410a708f8fSGustavo F. Padovan BT_ERR("%d", len); 51428c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 51430a708f8fSGustavo F. Padovan goto drop; 51440a708f8fSGustavo F. Padovan } 51450a708f8fSGustavo F. Padovan 5146cec8ab6eSMat Martineau /* Validate F and P bits */ 5147cec8ab6eSMat Martineau if (control->final && (control->poll || 5148cec8ab6eSMat Martineau chan->tx_state != L2CAP_TX_STATE_WAIT_F)) 5149cec8ab6eSMat Martineau goto drop; 5150cec8ab6eSMat Martineau 5151cec8ab6eSMat Martineau event = rx_func_to_event[control->super]; 5152cec8ab6eSMat Martineau if (l2cap_rx(chan, control, skb, event)) 5153cec8ab6eSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 51540a708f8fSGustavo F. Padovan } 51550a708f8fSGustavo F. Padovan 51560a708f8fSGustavo F. Padovan return 0; 51570a708f8fSGustavo F. Padovan 51580a708f8fSGustavo F. Padovan drop: 51590a708f8fSGustavo F. Padovan kfree_skb(skb); 51600a708f8fSGustavo F. Padovan return 0; 51610a708f8fSGustavo F. Padovan } 51620a708f8fSGustavo F. Padovan 516313ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid, 516413ca56e0SAndrei Emeltchenko struct sk_buff *skb) 51650a708f8fSGustavo F. Padovan { 516648454079SGustavo F. Padovan struct l2cap_chan *chan; 51670a708f8fSGustavo F. Padovan 5168baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 516948454079SGustavo F. Padovan if (!chan) { 517097e8e89dSAndrei Emeltchenko if (cid == L2CAP_CID_A2MP) { 517197e8e89dSAndrei Emeltchenko chan = a2mp_channel_create(conn, skb); 517297e8e89dSAndrei Emeltchenko if (!chan) { 517397e8e89dSAndrei Emeltchenko kfree_skb(skb); 517413ca56e0SAndrei Emeltchenko return; 517597e8e89dSAndrei Emeltchenko } 517697e8e89dSAndrei Emeltchenko 517797e8e89dSAndrei Emeltchenko l2cap_chan_lock(chan); 517897e8e89dSAndrei Emeltchenko } else { 51790a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid); 51806be36555SAndrei Emeltchenko /* Drop packet and return */ 51813379013bSDan Carpenter kfree_skb(skb); 518213ca56e0SAndrei Emeltchenko return; 51830a708f8fSGustavo F. Padovan } 518497e8e89dSAndrei Emeltchenko } 51850a708f8fSGustavo F. Padovan 518649208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len); 51870a708f8fSGustavo F. Padovan 518889bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 51890a708f8fSGustavo F. Padovan goto drop; 51900a708f8fSGustavo F. Padovan 51910c1bc5c6SGustavo F. Padovan switch (chan->mode) { 51920a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 51930a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here 51940a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable. 51950a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't 51960a708f8fSGustavo F. Padovan * provide flow control mechanism. */ 51970a708f8fSGustavo F. Padovan 51980c1bc5c6SGustavo F. Padovan if (chan->imtu < skb->len) 51990a708f8fSGustavo F. Padovan goto drop; 52000a708f8fSGustavo F. Padovan 520180b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 52020a708f8fSGustavo F. Padovan goto done; 52030a708f8fSGustavo F. Padovan break; 52040a708f8fSGustavo F. Padovan 52050a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 52060a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 5207cec8ab6eSMat Martineau l2cap_data_rcv(chan, skb); 52080a708f8fSGustavo F. Padovan goto done; 52090a708f8fSGustavo F. Padovan 52100a708f8fSGustavo F. Padovan default: 52110c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); 52120a708f8fSGustavo F. Padovan break; 52130a708f8fSGustavo F. Padovan } 52140a708f8fSGustavo F. Padovan 52150a708f8fSGustavo F. Padovan drop: 52160a708f8fSGustavo F. Padovan kfree_skb(skb); 52170a708f8fSGustavo F. Padovan 52180a708f8fSGustavo F. Padovan done: 52196be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 52200a708f8fSGustavo F. Padovan } 52210a708f8fSGustavo F. Padovan 522284104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, 522384104b24SAndrei Emeltchenko struct sk_buff *skb) 52240a708f8fSGustavo F. Padovan { 522523691d75SGustavo F. Padovan struct l2cap_chan *chan; 52260a708f8fSGustavo F. Padovan 5227c2287681SIdo Yariv chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst); 522823691d75SGustavo F. Padovan if (!chan) 52290a708f8fSGustavo F. Padovan goto drop; 52300a708f8fSGustavo F. Padovan 52315b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 52320a708f8fSGustavo F. Padovan 523389bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 52340a708f8fSGustavo F. Padovan goto drop; 52350a708f8fSGustavo F. Padovan 5236e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 52370a708f8fSGustavo F. Padovan goto drop; 52380a708f8fSGustavo F. Padovan 523980b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 524084104b24SAndrei Emeltchenko return; 52410a708f8fSGustavo F. Padovan 52420a708f8fSGustavo F. Padovan drop: 52430a708f8fSGustavo F. Padovan kfree_skb(skb); 52440a708f8fSGustavo F. Padovan } 52450a708f8fSGustavo F. Padovan 52466810fca7SAndrei Emeltchenko static void l2cap_att_channel(struct l2cap_conn *conn, u16 cid, 5247d9b88702SAndrei Emeltchenko struct sk_buff *skb) 52489f69bda6SGustavo F. Padovan { 524923691d75SGustavo F. Padovan struct l2cap_chan *chan; 52509f69bda6SGustavo F. Padovan 5251c2287681SIdo Yariv chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst); 525223691d75SGustavo F. Padovan if (!chan) 52539f69bda6SGustavo F. Padovan goto drop; 52549f69bda6SGustavo F. Padovan 52555b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 52569f69bda6SGustavo F. Padovan 525789bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 52589f69bda6SGustavo F. Padovan goto drop; 52599f69bda6SGustavo F. Padovan 5260e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 52619f69bda6SGustavo F. Padovan goto drop; 52629f69bda6SGustavo F. Padovan 526380b98027SGustavo Padovan if (!chan->ops->recv(chan, skb)) 52646810fca7SAndrei Emeltchenko return; 52659f69bda6SGustavo F. Padovan 52669f69bda6SGustavo F. Padovan drop: 52679f69bda6SGustavo F. Padovan kfree_skb(skb); 52689f69bda6SGustavo F. Padovan } 52699f69bda6SGustavo F. Padovan 52700a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) 52710a708f8fSGustavo F. Padovan { 52720a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data; 52730a708f8fSGustavo F. Padovan u16 cid, len; 52740a708f8fSGustavo F. Padovan __le16 psm; 52750a708f8fSGustavo F. Padovan 52760a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE); 52770a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid); 52780a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len); 52790a708f8fSGustavo F. Padovan 52800a708f8fSGustavo F. Padovan if (len != skb->len) { 52810a708f8fSGustavo F. Padovan kfree_skb(skb); 52820a708f8fSGustavo F. Padovan return; 52830a708f8fSGustavo F. Padovan } 52840a708f8fSGustavo F. Padovan 52850a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid); 52860a708f8fSGustavo F. Padovan 52870a708f8fSGustavo F. Padovan switch (cid) { 52883300d9a9SClaudio Takahasi case L2CAP_CID_LE_SIGNALING: 52890a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING: 52900a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb); 52910a708f8fSGustavo F. Padovan break; 52920a708f8fSGustavo F. Padovan 52930a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS: 5294097db76cSAndrei Emeltchenko psm = get_unaligned((__le16 *) skb->data); 52950181a70fSAndrei Emeltchenko skb_pull(skb, L2CAP_PSMLEN_SIZE); 52960a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb); 52970a708f8fSGustavo F. Padovan break; 52980a708f8fSGustavo F. Padovan 52999f69bda6SGustavo F. Padovan case L2CAP_CID_LE_DATA: 53009f69bda6SGustavo F. Padovan l2cap_att_channel(conn, cid, skb); 53019f69bda6SGustavo F. Padovan break; 53029f69bda6SGustavo F. Padovan 5303b501d6a1SAnderson Briglia case L2CAP_CID_SMP: 5304b501d6a1SAnderson Briglia if (smp_sig_channel(conn, skb)) 5305b501d6a1SAnderson Briglia l2cap_conn_del(conn->hcon, EACCES); 5306b501d6a1SAnderson Briglia break; 5307b501d6a1SAnderson Briglia 53080a708f8fSGustavo F. Padovan default: 53090a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb); 53100a708f8fSGustavo F. Padovan break; 53110a708f8fSGustavo F. Padovan } 53120a708f8fSGustavo F. Padovan } 53130a708f8fSGustavo F. Padovan 53140a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */ 53150a708f8fSGustavo F. Padovan 5316686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) 53170a708f8fSGustavo F. Padovan { 53180a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0; 531923691d75SGustavo F. Padovan struct l2cap_chan *c; 53200a708f8fSGustavo F. Padovan 53210a708f8fSGustavo F. Padovan BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); 53220a708f8fSGustavo F. Padovan 53230a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */ 532423691d75SGustavo F. Padovan read_lock(&chan_list_lock); 532523691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 532623691d75SGustavo F. Padovan struct sock *sk = c->sk; 53274343478fSGustavo F. Padovan 532889bc500eSGustavo F. Padovan if (c->state != BT_LISTEN) 53290a708f8fSGustavo F. Padovan continue; 53300a708f8fSGustavo F. Padovan 53310a708f8fSGustavo F. Padovan if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { 53320a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT; 533343bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 53340a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER; 53350a708f8fSGustavo F. Padovan exact++; 53360a708f8fSGustavo F. Padovan } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { 53370a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT; 533843bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 53390a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER; 53400a708f8fSGustavo F. Padovan } 53410a708f8fSGustavo F. Padovan } 534223691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 53430a708f8fSGustavo F. Padovan 53440a708f8fSGustavo F. Padovan return exact ? lm1 : lm2; 53450a708f8fSGustavo F. Padovan } 53460a708f8fSGustavo F. Padovan 53479e664631SAndrei Emeltchenko void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) 53480a708f8fSGustavo F. Padovan { 53490a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 53500a708f8fSGustavo F. Padovan 53510a708f8fSGustavo F. Padovan BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); 53520a708f8fSGustavo F. Padovan 53530a708f8fSGustavo F. Padovan if (!status) { 53540a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, status); 53550a708f8fSGustavo F. Padovan if (conn) 53560a708f8fSGustavo F. Padovan l2cap_conn_ready(conn); 53570a708f8fSGustavo F. Padovan } else 5358e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status)); 53590a708f8fSGustavo F. Padovan 53600a708f8fSGustavo F. Padovan } 53610a708f8fSGustavo F. Padovan 5362686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon) 53630a708f8fSGustavo F. Padovan { 53640a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 53650a708f8fSGustavo F. Padovan 53660a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon); 53670a708f8fSGustavo F. Padovan 5368686ebf28SUlisses Furquim if (!conn) 53699f5a0d7bSAndrei Emeltchenko return HCI_ERROR_REMOTE_USER_TERM; 53700a708f8fSGustavo F. Padovan return conn->disc_reason; 53710a708f8fSGustavo F. Padovan } 53720a708f8fSGustavo F. Padovan 53739e664631SAndrei Emeltchenko void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) 53740a708f8fSGustavo F. Padovan { 53750a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason); 53760a708f8fSGustavo F. Padovan 5377e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason)); 53780a708f8fSGustavo F. Padovan } 53790a708f8fSGustavo F. Padovan 53804343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) 53810a708f8fSGustavo F. Padovan { 5382715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 53830a708f8fSGustavo F. Padovan return; 53840a708f8fSGustavo F. Padovan 53850a708f8fSGustavo F. Padovan if (encrypt == 0x00) { 53864343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) { 5387ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); 53884343478fSGustavo F. Padovan } else if (chan->sec_level == BT_SECURITY_HIGH) 53890f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED); 53900a708f8fSGustavo F. Padovan } else { 53914343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) 5392c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 53930a708f8fSGustavo F. Padovan } 53940a708f8fSGustavo F. Padovan } 53950a708f8fSGustavo F. Padovan 5396686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) 53970a708f8fSGustavo F. Padovan { 53980a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 539948454079SGustavo F. Padovan struct l2cap_chan *chan; 54000a708f8fSGustavo F. Padovan 54010a708f8fSGustavo F. Padovan if (!conn) 54020a708f8fSGustavo F. Padovan return 0; 54030a708f8fSGustavo F. Padovan 540489d8b407SAndrei Emeltchenko BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt); 54050a708f8fSGustavo F. Padovan 5406160dc6acSVinicius Costa Gomes if (hcon->type == LE_LINK) { 540735d4adccSHemant Gupta if (!status && encrypt) 5408160dc6acSVinicius Costa Gomes smp_distribute_keys(conn, 0); 540917cd3f37SUlisses Furquim cancel_delayed_work(&conn->security_timer); 5410160dc6acSVinicius Costa Gomes } 5411160dc6acSVinicius Costa Gomes 54123df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 54130a708f8fSGustavo F. Padovan 54143df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 54156be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 54160a708f8fSGustavo F. Padovan 541789d8b407SAndrei Emeltchenko BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, 541889d8b407SAndrei Emeltchenko state_to_string(chan->state)); 5419f1cb9af5SVinicius Costa Gomes 542078eb2f98SAndrei Emeltchenko if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { 542178eb2f98SAndrei Emeltchenko l2cap_chan_unlock(chan); 542278eb2f98SAndrei Emeltchenko continue; 542378eb2f98SAndrei Emeltchenko } 542478eb2f98SAndrei Emeltchenko 5425f1cb9af5SVinicius Costa Gomes if (chan->scid == L2CAP_CID_LE_DATA) { 5426f1cb9af5SVinicius Costa Gomes if (!status && encrypt) { 5427f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level; 5428cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 5429f1cb9af5SVinicius Costa Gomes } 5430f1cb9af5SVinicius Costa Gomes 54316be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 5432f1cb9af5SVinicius Costa Gomes continue; 5433f1cb9af5SVinicius Costa Gomes } 5434f1cb9af5SVinicius Costa Gomes 5435c1360a1cSGustavo F. Padovan if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) { 54366be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 54370a708f8fSGustavo F. Padovan continue; 54380a708f8fSGustavo F. Padovan } 54390a708f8fSGustavo F. Padovan 544089bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED || 544189bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) { 5442a7d7723aSGustavo Padovan struct sock *sk = chan->sk; 5443a7d7723aSGustavo Padovan 5444c5daa683SGustavo Padovan clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); 5445a7d7723aSGustavo Padovan sk->sk_state_change(sk); 5446a7d7723aSGustavo Padovan 54474343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt); 54486be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 54490a708f8fSGustavo F. Padovan continue; 54500a708f8fSGustavo F. Padovan } 54510a708f8fSGustavo F. Padovan 545289bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 54530a708f8fSGustavo F. Padovan if (!status) { 54549b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 54550a708f8fSGustavo F. Padovan } else { 5456ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 54570a708f8fSGustavo F. Padovan } 545889bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 54596be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 54600a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 5461df3c3931SJohan Hedberg __u16 res, stat; 54620a708f8fSGustavo F. Padovan 54636be36555SAndrei Emeltchenko lock_sock(sk); 54646be36555SAndrei Emeltchenko 54650a708f8fSGustavo F. Padovan if (!status) { 5466c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, 5467c5daa683SGustavo Padovan &bt_sk(sk)->flags)) { 5468df3c3931SJohan Hedberg struct sock *parent = bt_sk(sk)->parent; 5469df3c3931SJohan Hedberg res = L2CAP_CR_PEND; 5470df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND; 547105e9a2f6SIlia Kolomisnky if (parent) 5472df3c3931SJohan Hedberg parent->sk_data_ready(parent, 0); 5473df3c3931SJohan Hedberg } else { 54740e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 5475df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS; 5476df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 5477df3c3931SJohan Hedberg } 54780a708f8fSGustavo F. Padovan } else { 54790e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_DISCONN); 5480ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 5481df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK; 5482df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 54830a708f8fSGustavo F. Padovan } 54840a708f8fSGustavo F. Padovan 54856be36555SAndrei Emeltchenko release_sock(sk); 54866be36555SAndrei Emeltchenko 5487fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 5488fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 5489df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res); 5490df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat); 5491fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 5492fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 54932d369359SMat Martineau 54942d369359SMat Martineau if (!test_bit(CONF_REQ_SENT, &chan->conf_state) && 54952d369359SMat Martineau res == L2CAP_CR_SUCCESS) { 54962d369359SMat Martineau char buf[128]; 54972d369359SMat Martineau set_bit(CONF_REQ_SENT, &chan->conf_state); 54982d369359SMat Martineau l2cap_send_cmd(conn, l2cap_get_ident(conn), 54992d369359SMat Martineau L2CAP_CONF_REQ, 55002d369359SMat Martineau l2cap_build_conf_req(chan, buf), 55012d369359SMat Martineau buf); 55022d369359SMat Martineau chan->num_conf_req++; 55032d369359SMat Martineau } 55040a708f8fSGustavo F. Padovan } 55050a708f8fSGustavo F. Padovan 55066be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 55070a708f8fSGustavo F. Padovan } 55080a708f8fSGustavo F. Padovan 55093df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 55100a708f8fSGustavo F. Padovan 55110a708f8fSGustavo F. Padovan return 0; 55120a708f8fSGustavo F. Padovan } 55130a708f8fSGustavo F. Padovan 5514686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) 55150a708f8fSGustavo F. Padovan { 55160a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 55170a708f8fSGustavo F. Padovan 55180a708f8fSGustavo F. Padovan if (!conn) 55190a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, 0); 55200a708f8fSGustavo F. Padovan 55210a708f8fSGustavo F. Padovan if (!conn) 55220a708f8fSGustavo F. Padovan goto drop; 55230a708f8fSGustavo F. Padovan 55240a708f8fSGustavo F. Padovan BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); 55250a708f8fSGustavo F. Padovan 55260a708f8fSGustavo F. Padovan if (!(flags & ACL_CONT)) { 55270a708f8fSGustavo F. Padovan struct l2cap_hdr *hdr; 55280a708f8fSGustavo F. Padovan int len; 55290a708f8fSGustavo F. Padovan 55300a708f8fSGustavo F. Padovan if (conn->rx_len) { 55310a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len); 55320a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 55330a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 55340a708f8fSGustavo F. Padovan conn->rx_len = 0; 55350a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 55360a708f8fSGustavo F. Padovan } 55370a708f8fSGustavo F. Padovan 55380a708f8fSGustavo F. Padovan /* Start fragment always begin with Basic L2CAP header */ 55390a708f8fSGustavo F. Padovan if (skb->len < L2CAP_HDR_SIZE) { 55400a708f8fSGustavo F. Padovan BT_ERR("Frame is too short (len %d)", skb->len); 55410a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 55420a708f8fSGustavo F. Padovan goto drop; 55430a708f8fSGustavo F. Padovan } 55440a708f8fSGustavo F. Padovan 55450a708f8fSGustavo F. Padovan hdr = (struct l2cap_hdr *) skb->data; 55460a708f8fSGustavo F. Padovan len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; 55470a708f8fSGustavo F. Padovan 55480a708f8fSGustavo F. Padovan if (len == skb->len) { 55490a708f8fSGustavo F. Padovan /* Complete frame received */ 55500a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb); 55510a708f8fSGustavo F. Padovan return 0; 55520a708f8fSGustavo F. Padovan } 55530a708f8fSGustavo F. Padovan 55540a708f8fSGustavo F. Padovan BT_DBG("Start: total len %d, frag len %d", len, skb->len); 55550a708f8fSGustavo F. Padovan 55560a708f8fSGustavo F. Padovan if (skb->len > len) { 55570a708f8fSGustavo F. Padovan BT_ERR("Frame is too long (len %d, expected len %d)", 55580a708f8fSGustavo F. Padovan skb->len, len); 55590a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 55600a708f8fSGustavo F. Padovan goto drop; 55610a708f8fSGustavo F. Padovan } 55620a708f8fSGustavo F. Padovan 55630a708f8fSGustavo F. Padovan /* Allocate skb for the complete frame (with header) */ 55640a708f8fSGustavo F. Padovan conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC); 55650a708f8fSGustavo F. Padovan if (!conn->rx_skb) 55660a708f8fSGustavo F. Padovan goto drop; 55670a708f8fSGustavo F. Padovan 55680a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 55690a708f8fSGustavo F. Padovan skb->len); 55700a708f8fSGustavo F. Padovan conn->rx_len = len - skb->len; 55710a708f8fSGustavo F. Padovan } else { 55720a708f8fSGustavo F. Padovan BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); 55730a708f8fSGustavo F. Padovan 55740a708f8fSGustavo F. Padovan if (!conn->rx_len) { 55750a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len); 55760a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 55770a708f8fSGustavo F. Padovan goto drop; 55780a708f8fSGustavo F. Padovan } 55790a708f8fSGustavo F. Padovan 55800a708f8fSGustavo F. Padovan if (skb->len > conn->rx_len) { 55810a708f8fSGustavo F. Padovan BT_ERR("Fragment is too long (len %d, expected %d)", 55820a708f8fSGustavo F. Padovan skb->len, conn->rx_len); 55830a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 55840a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 55850a708f8fSGustavo F. Padovan conn->rx_len = 0; 55860a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 55870a708f8fSGustavo F. Padovan goto drop; 55880a708f8fSGustavo F. Padovan } 55890a708f8fSGustavo F. Padovan 55900a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 55910a708f8fSGustavo F. Padovan skb->len); 55920a708f8fSGustavo F. Padovan conn->rx_len -= skb->len; 55930a708f8fSGustavo F. Padovan 55940a708f8fSGustavo F. Padovan if (!conn->rx_len) { 55950a708f8fSGustavo F. Padovan /* Complete frame received */ 55960a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, conn->rx_skb); 55970a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 55980a708f8fSGustavo F. Padovan } 55990a708f8fSGustavo F. Padovan } 56000a708f8fSGustavo F. Padovan 56010a708f8fSGustavo F. Padovan drop: 56020a708f8fSGustavo F. Padovan kfree_skb(skb); 56030a708f8fSGustavo F. Padovan return 0; 56040a708f8fSGustavo F. Padovan } 56050a708f8fSGustavo F. Padovan 56060a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p) 56070a708f8fSGustavo F. Padovan { 560823691d75SGustavo F. Padovan struct l2cap_chan *c; 56090a708f8fSGustavo F. Padovan 5610333055f2SGustavo F. Padovan read_lock(&chan_list_lock); 56110a708f8fSGustavo F. Padovan 561223691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 561323691d75SGustavo F. Padovan struct sock *sk = c->sk; 56140a708f8fSGustavo F. Padovan 5615903d343eSGustavo F. Padovan seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", 56160a708f8fSGustavo F. Padovan batostr(&bt_sk(sk)->src), 56170a708f8fSGustavo F. Padovan batostr(&bt_sk(sk)->dst), 561889bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm), 561923691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu, 562023691d75SGustavo F. Padovan c->sec_level, c->mode); 56210a708f8fSGustavo F. Padovan } 56220a708f8fSGustavo F. Padovan 5623333055f2SGustavo F. Padovan read_unlock(&chan_list_lock); 56240a708f8fSGustavo F. Padovan 56250a708f8fSGustavo F. Padovan return 0; 56260a708f8fSGustavo F. Padovan } 56270a708f8fSGustavo F. Padovan 56280a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file) 56290a708f8fSGustavo F. Padovan { 56300a708f8fSGustavo F. Padovan return single_open(file, l2cap_debugfs_show, inode->i_private); 56310a708f8fSGustavo F. Padovan } 56320a708f8fSGustavo F. Padovan 56330a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = { 56340a708f8fSGustavo F. Padovan .open = l2cap_debugfs_open, 56350a708f8fSGustavo F. Padovan .read = seq_read, 56360a708f8fSGustavo F. Padovan .llseek = seq_lseek, 56370a708f8fSGustavo F. Padovan .release = single_release, 56380a708f8fSGustavo F. Padovan }; 56390a708f8fSGustavo F. Padovan 56400a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs; 56410a708f8fSGustavo F. Padovan 564264274518SGustavo F. Padovan int __init l2cap_init(void) 56430a708f8fSGustavo F. Padovan { 56440a708f8fSGustavo F. Padovan int err; 56450a708f8fSGustavo F. Padovan 5646bb58f747SGustavo F. Padovan err = l2cap_init_sockets(); 56470a708f8fSGustavo F. Padovan if (err < 0) 56480a708f8fSGustavo F. Padovan return err; 56490a708f8fSGustavo F. Padovan 56500a708f8fSGustavo F. Padovan if (bt_debugfs) { 56510a708f8fSGustavo F. Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, 56520a708f8fSGustavo F. Padovan bt_debugfs, NULL, &l2cap_debugfs_fops); 56530a708f8fSGustavo F. Padovan if (!l2cap_debugfs) 56540a708f8fSGustavo F. Padovan BT_ERR("Failed to create L2CAP debug file"); 56550a708f8fSGustavo F. Padovan } 56560a708f8fSGustavo F. Padovan 56570a708f8fSGustavo F. Padovan return 0; 56580a708f8fSGustavo F. Padovan } 56590a708f8fSGustavo F. Padovan 566064274518SGustavo F. Padovan void l2cap_exit(void) 56610a708f8fSGustavo F. Padovan { 56620a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs); 5663bb58f747SGustavo F. Padovan l2cap_cleanup_sockets(); 56640a708f8fSGustavo F. Padovan } 56650a708f8fSGustavo F. Padovan 56660a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644); 56670a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); 5668