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/types.h> 340a708f8fSGustavo F. Padovan #include <linux/capability.h> 350a708f8fSGustavo F. Padovan #include <linux/errno.h> 360a708f8fSGustavo F. Padovan #include <linux/kernel.h> 370a708f8fSGustavo F. Padovan #include <linux/sched.h> 380a708f8fSGustavo F. Padovan #include <linux/slab.h> 390a708f8fSGustavo F. Padovan #include <linux/poll.h> 400a708f8fSGustavo F. Padovan #include <linux/fcntl.h> 410a708f8fSGustavo F. Padovan #include <linux/init.h> 420a708f8fSGustavo F. Padovan #include <linux/interrupt.h> 430a708f8fSGustavo F. Padovan #include <linux/socket.h> 440a708f8fSGustavo F. Padovan #include <linux/skbuff.h> 450a708f8fSGustavo F. Padovan #include <linux/list.h> 460a708f8fSGustavo F. Padovan #include <linux/device.h> 470a708f8fSGustavo F. Padovan #include <linux/debugfs.h> 480a708f8fSGustavo F. Padovan #include <linux/seq_file.h> 490a708f8fSGustavo F. Padovan #include <linux/uaccess.h> 500a708f8fSGustavo F. Padovan #include <linux/crc16.h> 510a708f8fSGustavo F. Padovan #include <net/sock.h> 520a708f8fSGustavo F. Padovan 530a708f8fSGustavo F. Padovan #include <asm/unaligned.h> 540a708f8fSGustavo F. Padovan 550a708f8fSGustavo F. Padovan #include <net/bluetooth/bluetooth.h> 560a708f8fSGustavo F. Padovan #include <net/bluetooth/hci_core.h> 570a708f8fSGustavo F. Padovan #include <net/bluetooth/l2cap.h> 58b501d6a1SAnderson Briglia #include <net/bluetooth/smp.h> 590a708f8fSGustavo F. Padovan 60b191e031SMat Martineau bool disable_ertm = 1; 610a708f8fSGustavo F. Padovan 620a708f8fSGustavo F. Padovan static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; 6350a147cdSMat Martineau static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, }; 640a708f8fSGustavo F. Padovan 65b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list); 66b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock); 670a708f8fSGustavo F. Padovan 680a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 690a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data); 704519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 714519de9aSGustavo F. Padovan void *data); 72710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); 734519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, 744519de9aSGustavo F. Padovan struct l2cap_chan *chan, int err); 750a708f8fSGustavo F. Padovan 76608bcc6dSMat Martineau static int l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 77608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event); 78608bcc6dSMat Martineau 790a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */ 8071ba0e56SGustavo F. Padovan 81baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid) 820a708f8fSGustavo F. Padovan { 833df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 84baa7e1faSGustavo F. Padovan 853df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 863df91ea2SAndrei Emeltchenko if (c->dcid == cid) 873df91ea2SAndrei Emeltchenko return c; 880a708f8fSGustavo F. Padovan } 893df91ea2SAndrei Emeltchenko return NULL; 90baa7e1faSGustavo F. Padovan } 910a708f8fSGustavo F. Padovan 92baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) 930a708f8fSGustavo F. Padovan { 943df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 95baa7e1faSGustavo F. Padovan 963df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 973df91ea2SAndrei Emeltchenko if (c->scid == cid) 983df91ea2SAndrei Emeltchenko return c; 990a708f8fSGustavo F. Padovan } 1003df91ea2SAndrei Emeltchenko return NULL; 101baa7e1faSGustavo F. Padovan } 1020a708f8fSGustavo F. Padovan 1030a708f8fSGustavo F. Padovan /* Find channel with given SCID. 104ef191adeSMat Martineau * Returns locked channel. */ 105baa7e1faSGustavo F. Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) 1060a708f8fSGustavo F. Padovan { 10748454079SGustavo F. Padovan struct l2cap_chan *c; 108baa7e1faSGustavo F. Padovan 1093df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 110baa7e1faSGustavo F. Padovan c = __l2cap_get_chan_by_scid(conn, cid); 111ef191adeSMat Martineau if (c) 112ef191adeSMat Martineau l2cap_chan_lock(c); 1133df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 1143df91ea2SAndrei Emeltchenko 11548454079SGustavo F. Padovan return c; 1160a708f8fSGustavo F. Padovan } 1170a708f8fSGustavo F. Padovan 118baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident) 1190a708f8fSGustavo F. Padovan { 1203df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 121baa7e1faSGustavo F. Padovan 1223df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 1233df91ea2SAndrei Emeltchenko if (c->ident == ident) 1243df91ea2SAndrei Emeltchenko return c; 1250a708f8fSGustavo F. Padovan } 1263df91ea2SAndrei Emeltchenko return NULL; 127baa7e1faSGustavo F. Padovan } 1280a708f8fSGustavo F. Padovan 12923691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src) 1309e4425ffSGustavo F. Padovan { 13123691d75SGustavo F. Padovan struct l2cap_chan *c; 1329e4425ffSGustavo F. Padovan 13323691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 13423691d75SGustavo F. Padovan if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src)) 13523691d75SGustavo F. Padovan return c; 1369e4425ffSGustavo F. Padovan } 137250938cbSSzymon Janc return NULL; 138250938cbSSzymon Janc } 1399e4425ffSGustavo F. Padovan 1409e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) 1419e4425ffSGustavo F. Padovan { 14273b2ec18SGustavo F. Padovan int err; 14373b2ec18SGustavo F. Padovan 144333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 1459e4425ffSGustavo F. Padovan 14623691d75SGustavo F. Padovan if (psm && __l2cap_global_chan_by_addr(psm, src)) { 14773b2ec18SGustavo F. Padovan err = -EADDRINUSE; 14873b2ec18SGustavo F. Padovan goto done; 1499e4425ffSGustavo F. Padovan } 1509e4425ffSGustavo F. Padovan 15173b2ec18SGustavo F. Padovan if (psm) { 1529e4425ffSGustavo F. Padovan chan->psm = psm; 1539e4425ffSGustavo F. Padovan chan->sport = psm; 15473b2ec18SGustavo F. Padovan err = 0; 15573b2ec18SGustavo F. Padovan } else { 15673b2ec18SGustavo F. Padovan u16 p; 1579e4425ffSGustavo F. Padovan 15873b2ec18SGustavo F. Padovan err = -EINVAL; 15973b2ec18SGustavo F. Padovan for (p = 0x1001; p < 0x1100; p += 2) 16023691d75SGustavo F. Padovan if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) { 16173b2ec18SGustavo F. Padovan chan->psm = cpu_to_le16(p); 16273b2ec18SGustavo F. Padovan chan->sport = cpu_to_le16(p); 16373b2ec18SGustavo F. Padovan err = 0; 16473b2ec18SGustavo F. Padovan break; 16573b2ec18SGustavo F. Padovan } 16673b2ec18SGustavo F. Padovan } 16773b2ec18SGustavo F. Padovan 16873b2ec18SGustavo F. Padovan done: 169333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 17073b2ec18SGustavo F. Padovan return err; 1719e4425ffSGustavo F. Padovan } 1729e4425ffSGustavo F. Padovan 1739e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) 1749e4425ffSGustavo F. Padovan { 175333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 1769e4425ffSGustavo F. Padovan 1779e4425ffSGustavo F. Padovan chan->scid = scid; 1789e4425ffSGustavo F. Padovan 179333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 1809e4425ffSGustavo F. Padovan 1819e4425ffSGustavo F. Padovan return 0; 1829e4425ffSGustavo F. Padovan } 1839e4425ffSGustavo F. Padovan 184baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn) 1850a708f8fSGustavo F. Padovan { 1860a708f8fSGustavo F. Padovan u16 cid = L2CAP_CID_DYN_START; 1870a708f8fSGustavo F. Padovan 1880a708f8fSGustavo F. Padovan for (; cid < L2CAP_CID_DYN_END; cid++) { 189baa7e1faSGustavo F. Padovan if (!__l2cap_get_chan_by_scid(conn, cid)) 1900a708f8fSGustavo F. Padovan return cid; 1910a708f8fSGustavo F. Padovan } 1920a708f8fSGustavo F. Padovan 1930a708f8fSGustavo F. Padovan return 0; 1940a708f8fSGustavo F. Padovan } 1950a708f8fSGustavo F. Padovan 1960e587be7SAndrei Emeltchenko static void __l2cap_state_change(struct l2cap_chan *chan, int state) 19789bc500eSGustavo F. Padovan { 19842d2d87cSAndrei Emeltchenko BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state), 199badaaa00SGustavo F. Padovan state_to_string(state)); 200badaaa00SGustavo F. Padovan 20189bc500eSGustavo F. Padovan chan->state = state; 20289bc500eSGustavo F. Padovan chan->ops->state_change(chan->data, state); 20389bc500eSGustavo F. Padovan } 20489bc500eSGustavo F. Padovan 2050e587be7SAndrei Emeltchenko static void l2cap_state_change(struct l2cap_chan *chan, int state) 2060e587be7SAndrei Emeltchenko { 2070e587be7SAndrei Emeltchenko struct sock *sk = chan->sk; 2080e587be7SAndrei Emeltchenko 2090e587be7SAndrei Emeltchenko lock_sock(sk); 2100e587be7SAndrei Emeltchenko __l2cap_state_change(chan, state); 2110e587be7SAndrei Emeltchenko release_sock(sk); 2120e587be7SAndrei Emeltchenko } 2130e587be7SAndrei Emeltchenko 2142e0052e4SAndrei Emeltchenko static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err) 2152e0052e4SAndrei Emeltchenko { 2162e0052e4SAndrei Emeltchenko struct sock *sk = chan->sk; 2172e0052e4SAndrei Emeltchenko 2182e0052e4SAndrei Emeltchenko sk->sk_err = err; 2192e0052e4SAndrei Emeltchenko } 2202e0052e4SAndrei Emeltchenko 2212e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err) 2222e0052e4SAndrei Emeltchenko { 2232e0052e4SAndrei Emeltchenko struct sock *sk = chan->sk; 2242e0052e4SAndrei Emeltchenko 2252e0052e4SAndrei Emeltchenko lock_sock(sk); 2262e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 2272e0052e4SAndrei Emeltchenko release_sock(sk); 2282e0052e4SAndrei Emeltchenko } 2292e0052e4SAndrei Emeltchenko 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 385ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 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 428bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan) 429bd4b1653SAndrei Emeltchenko { 430bd4b1653SAndrei Emeltchenko chan->fcs = L2CAP_FCS_CRC16; 431bd4b1653SAndrei Emeltchenko chan->max_tx = L2CAP_DEFAULT_MAX_TX; 432bd4b1653SAndrei Emeltchenko chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; 433bd4b1653SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 434bd4b1653SAndrei Emeltchenko chan->sec_level = BT_SECURITY_LOW; 435bd4b1653SAndrei Emeltchenko 436bd4b1653SAndrei Emeltchenko set_bit(FLAG_FORCE_ACTIVE, &chan->flags); 437bd4b1653SAndrei Emeltchenko } 438bd4b1653SAndrei Emeltchenko 43914a28491SAndrei Emeltchenko static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 4400a708f8fSGustavo F. Padovan { 4410a708f8fSGustavo F. Padovan BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, 442097db76cSAndrei Emeltchenko __le16_to_cpu(chan->psm), chan->dcid); 4430a708f8fSGustavo F. Padovan 4449f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 4450a708f8fSGustavo F. Padovan 4468c1d787bSGustavo F. Padovan chan->conn = conn; 4470a708f8fSGustavo F. Padovan 4485491120eSAndrei Emeltchenko switch (chan->chan_type) { 4495491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_ORIENTED: 450b62f328bSVille Tervo if (conn->hcon->type == LE_LINK) { 451b62f328bSVille Tervo /* LE connection */ 4520c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_LE_DEFAULT_MTU; 453fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_LE_DATA; 454fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_LE_DATA; 455b62f328bSVille Tervo } else { 4560a708f8fSGustavo F. Padovan /* Alloc CID for connection-oriented socket */ 457fe4128e0SGustavo F. Padovan chan->scid = l2cap_alloc_cid(conn); 4580c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 459b62f328bSVille Tervo } 4605491120eSAndrei Emeltchenko break; 4615491120eSAndrei Emeltchenko 4625491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_LESS: 4630a708f8fSGustavo F. Padovan /* Connectionless socket */ 464fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_CONN_LESS; 465fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_CONN_LESS; 4660c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 4675491120eSAndrei Emeltchenko break; 4685491120eSAndrei Emeltchenko 4695491120eSAndrei Emeltchenko default: 4700a708f8fSGustavo F. Padovan /* Raw socket can send/recv signalling messages only */ 471fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_SIGNALING; 472fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_SIGNALING; 4730c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 4740a708f8fSGustavo F. Padovan } 4750a708f8fSGustavo F. Padovan 4768f7975b1SAndrei Emeltchenko chan->local_id = L2CAP_BESTEFFORT_ID; 4778f7975b1SAndrei Emeltchenko chan->local_stype = L2CAP_SERV_BESTEFFORT; 4788f7975b1SAndrei Emeltchenko chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE; 4798f7975b1SAndrei Emeltchenko chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME; 4808f7975b1SAndrei Emeltchenko chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT; 4818f7975b1SAndrei Emeltchenko chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO; 4828f7975b1SAndrei Emeltchenko 483371fd835SUlisses Furquim l2cap_chan_hold(chan); 484baa7e1faSGustavo F. Padovan 4853df91ea2SAndrei Emeltchenko list_add(&chan->list, &conn->chan_l); 486643162a8SAndrei Emeltchenko } 487643162a8SAndrei Emeltchenko 48814a28491SAndrei Emeltchenko static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 489643162a8SAndrei Emeltchenko { 490643162a8SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 491643162a8SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 4923df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4930a708f8fSGustavo F. Padovan } 4940a708f8fSGustavo F. Padovan 4954519de9aSGustavo F. Padovan static void l2cap_chan_del(struct l2cap_chan *chan, int err) 4960a708f8fSGustavo F. Padovan { 49748454079SGustavo F. Padovan struct sock *sk = chan->sk; 4988c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 4990a708f8fSGustavo F. Padovan struct sock *parent = bt_sk(sk)->parent; 5000a708f8fSGustavo F. Padovan 501c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 5020a708f8fSGustavo F. Padovan 50349208c9cSGustavo F. Padovan BT_DBG("chan %p, conn %p, err %d", chan, conn, err); 5040a708f8fSGustavo F. Padovan 5050a708f8fSGustavo F. Padovan if (conn) { 506baa7e1faSGustavo F. Padovan /* Delete from channel list */ 5073df91ea2SAndrei Emeltchenko list_del(&chan->list); 5083d57dc68SGustavo F. Padovan 509371fd835SUlisses Furquim l2cap_chan_put(chan); 510baa7e1faSGustavo F. Padovan 5118c1d787bSGustavo F. Padovan chan->conn = NULL; 5120a708f8fSGustavo F. Padovan hci_conn_put(conn->hcon); 5130a708f8fSGustavo F. Padovan } 5140a708f8fSGustavo F. Padovan 5156be36555SAndrei Emeltchenko lock_sock(sk); 5166be36555SAndrei Emeltchenko 5170e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CLOSED); 5180a708f8fSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 5190a708f8fSGustavo F. Padovan 5200a708f8fSGustavo F. Padovan if (err) 5212e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 5220a708f8fSGustavo F. Padovan 5230a708f8fSGustavo F. Padovan if (parent) { 5240a708f8fSGustavo F. Padovan bt_accept_unlink(sk); 5250a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 5260a708f8fSGustavo F. Padovan } else 5270a708f8fSGustavo F. Padovan sk->sk_state_change(sk); 5280a708f8fSGustavo F. Padovan 5296be36555SAndrei Emeltchenko release_sock(sk); 5306be36555SAndrei Emeltchenko 5312827011fSMat Martineau if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) 5326ff5abbfSGustavo F. Padovan return; 5332ead70b8SGustavo F. Padovan 53458d35f87SGustavo F. Padovan skb_queue_purge(&chan->tx_q); 5350a708f8fSGustavo F. Padovan 5360c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_ERTM) { 5371a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 5381a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 5391a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 5400a708f8fSGustavo F. Padovan 541f1c6775bSGustavo F. Padovan skb_queue_purge(&chan->srej_q); 5420a708f8fSGustavo F. Padovan 5433c588192SMat Martineau l2cap_seq_list_free(&chan->srej_list); 5443c588192SMat Martineau l2cap_seq_list_free(&chan->retrans_list); 5450a708f8fSGustavo F. Padovan } 5460a708f8fSGustavo F. Padovan } 5470a708f8fSGustavo F. Padovan 5484519de9aSGustavo F. Padovan static void l2cap_chan_cleanup_listen(struct sock *parent) 5494519de9aSGustavo F. Padovan { 5504519de9aSGustavo F. Padovan struct sock *sk; 5514519de9aSGustavo F. Padovan 5524519de9aSGustavo F. Padovan BT_DBG("parent %p", parent); 5534519de9aSGustavo F. Padovan 5544519de9aSGustavo F. Padovan /* Close not yet accepted channels */ 5550f852724SGustavo F. Padovan while ((sk = bt_accept_dequeue(parent, NULL))) { 556ba3bd0eeSGustavo F. Padovan struct l2cap_chan *chan = l2cap_pi(sk)->chan; 5573df91ea2SAndrei Emeltchenko 5586be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 559c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 560ba3bd0eeSGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 5616be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 5623df91ea2SAndrei Emeltchenko 563ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 5640f852724SGustavo F. Padovan } 5654519de9aSGustavo F. Padovan } 5664519de9aSGustavo F. Padovan 5670f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason) 5684519de9aSGustavo F. Padovan { 5694519de9aSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 5704519de9aSGustavo F. Padovan struct sock *sk = chan->sk; 5714519de9aSGustavo F. Padovan 572e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s sk %p", chan, 573e05dcc32SAndrei Emeltchenko state_to_string(chan->state), sk); 5744519de9aSGustavo F. Padovan 57589bc500eSGustavo F. Padovan switch (chan->state) { 5764519de9aSGustavo F. Padovan case BT_LISTEN: 5776be36555SAndrei Emeltchenko lock_sock(sk); 5784519de9aSGustavo F. Padovan l2cap_chan_cleanup_listen(sk); 57989bc500eSGustavo F. Padovan 5800e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CLOSED); 58189bc500eSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 5826be36555SAndrei Emeltchenko release_sock(sk); 5834519de9aSGustavo F. Padovan break; 5844519de9aSGustavo F. Padovan 5854519de9aSGustavo F. Padovan case BT_CONNECTED: 5864519de9aSGustavo F. Padovan case BT_CONFIG: 587715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && 5884519de9aSGustavo F. Padovan conn->hcon->type == ACL_LINK) { 589c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 5904519de9aSGustavo F. Padovan l2cap_send_disconn_req(conn, chan, reason); 5914519de9aSGustavo F. Padovan } else 5924519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 5934519de9aSGustavo F. Padovan break; 5944519de9aSGustavo F. Padovan 5954519de9aSGustavo F. Padovan case BT_CONNECT2: 596715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && 5974519de9aSGustavo F. Padovan conn->hcon->type == ACL_LINK) { 5984519de9aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 5994519de9aSGustavo F. Padovan __u16 result; 6004519de9aSGustavo F. Padovan 601c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) 6024519de9aSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 6034519de9aSGustavo F. Padovan else 6044519de9aSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 60589bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_DISCONN); 6064519de9aSGustavo F. Padovan 6074519de9aSGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 6084519de9aSGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 6094519de9aSGustavo F. Padovan rsp.result = cpu_to_le16(result); 6104519de9aSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 6114519de9aSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 6124519de9aSGustavo F. Padovan sizeof(rsp), &rsp); 6134519de9aSGustavo F. Padovan } 6144519de9aSGustavo F. Padovan 6154519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 6164519de9aSGustavo F. Padovan break; 6174519de9aSGustavo F. Padovan 6184519de9aSGustavo F. Padovan case BT_CONNECT: 6194519de9aSGustavo F. Padovan case BT_DISCONN: 6204519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 6214519de9aSGustavo F. Padovan break; 6224519de9aSGustavo F. Padovan 6234519de9aSGustavo F. Padovan default: 6246be36555SAndrei Emeltchenko lock_sock(sk); 6254519de9aSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 6266be36555SAndrei Emeltchenko release_sock(sk); 6274519de9aSGustavo F. Padovan break; 6284519de9aSGustavo F. Padovan } 6294519de9aSGustavo F. Padovan } 6304519de9aSGustavo F. Padovan 6314343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) 6320a708f8fSGustavo F. Padovan { 633715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_RAW) { 6344343478fSGustavo F. Padovan switch (chan->sec_level) { 6350a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 6360a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING_MITM; 6370a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 6380a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING; 6390a708f8fSGustavo F. Padovan default: 6400a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 6410a708f8fSGustavo F. Padovan } 642fe4128e0SGustavo F. Padovan } else if (chan->psm == cpu_to_le16(0x0001)) { 6434343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_LOW) 6444343478fSGustavo F. Padovan chan->sec_level = BT_SECURITY_SDP; 6450a708f8fSGustavo F. Padovan 6464343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_HIGH) 6470a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING_MITM; 6480a708f8fSGustavo F. Padovan else 6490a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 6500a708f8fSGustavo F. Padovan } else { 6514343478fSGustavo F. Padovan switch (chan->sec_level) { 6520a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 6530a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING_MITM; 6540a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 6550a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING; 6560a708f8fSGustavo F. Padovan default: 6570a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 6580a708f8fSGustavo F. Padovan } 6590a708f8fSGustavo F. Padovan } 6600a708f8fSGustavo F. Padovan } 6610a708f8fSGustavo F. Padovan 6620a708f8fSGustavo F. Padovan /* Service level security */ 663d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan) 6640a708f8fSGustavo F. Padovan { 6658c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 6660a708f8fSGustavo F. Padovan __u8 auth_type; 6670a708f8fSGustavo F. Padovan 6684343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 6690a708f8fSGustavo F. Padovan 6704343478fSGustavo F. Padovan return hci_conn_security(conn->hcon, chan->sec_level, auth_type); 6710a708f8fSGustavo F. Padovan } 6720a708f8fSGustavo F. Padovan 673b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn) 6740a708f8fSGustavo F. Padovan { 6750a708f8fSGustavo F. Padovan u8 id; 6760a708f8fSGustavo F. Padovan 6770a708f8fSGustavo F. Padovan /* Get next available identificator. 6780a708f8fSGustavo F. Padovan * 1 - 128 are used by kernel. 6790a708f8fSGustavo F. Padovan * 129 - 199 are reserved. 6800a708f8fSGustavo F. Padovan * 200 - 254 are used by utilities like l2ping, etc. 6810a708f8fSGustavo F. Padovan */ 6820a708f8fSGustavo F. Padovan 683333055f2SGustavo F. Padovan spin_lock(&conn->lock); 6840a708f8fSGustavo F. Padovan 6850a708f8fSGustavo F. Padovan if (++conn->tx_ident > 128) 6860a708f8fSGustavo F. Padovan conn->tx_ident = 1; 6870a708f8fSGustavo F. Padovan 6880a708f8fSGustavo F. Padovan id = conn->tx_ident; 6890a708f8fSGustavo F. Padovan 690333055f2SGustavo F. Padovan spin_unlock(&conn->lock); 6910a708f8fSGustavo F. Padovan 6920a708f8fSGustavo F. Padovan return id; 6930a708f8fSGustavo F. Padovan } 6940a708f8fSGustavo F. Padovan 6954519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) 6960a708f8fSGustavo F. Padovan { 6970a708f8fSGustavo F. Padovan struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); 6980a708f8fSGustavo F. Padovan u8 flags; 6990a708f8fSGustavo F. Padovan 7000a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x", code); 7010a708f8fSGustavo F. Padovan 7020a708f8fSGustavo F. Padovan if (!skb) 7030a708f8fSGustavo F. Padovan return; 7040a708f8fSGustavo F. Padovan 7050a708f8fSGustavo F. Padovan if (lmp_no_flush_capable(conn->hcon->hdev)) 7060a708f8fSGustavo F. Padovan flags = ACL_START_NO_FLUSH; 7070a708f8fSGustavo F. Padovan else 7080a708f8fSGustavo F. Padovan flags = ACL_START; 7090a708f8fSGustavo F. Padovan 71014b12d0bSJaikumar Ganesh bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON; 7115e59b791SLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 71214b12d0bSJaikumar Ganesh 71373d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, flags); 7140a708f8fSGustavo F. Padovan } 7150a708f8fSGustavo F. Padovan 71673d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) 71773d80debSLuiz Augusto von Dentz { 71873d80debSLuiz Augusto von Dentz struct hci_conn *hcon = chan->conn->hcon; 71973d80debSLuiz Augusto von Dentz u16 flags; 72073d80debSLuiz Augusto von Dentz 72173d80debSLuiz Augusto von Dentz BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, 72273d80debSLuiz Augusto von Dentz skb->priority); 72373d80debSLuiz Augusto von Dentz 72473d80debSLuiz Augusto von Dentz if (!test_bit(FLAG_FLUSHABLE, &chan->flags) && 72573d80debSLuiz Augusto von Dentz lmp_no_flush_capable(hcon->hdev)) 72673d80debSLuiz Augusto von Dentz flags = ACL_START_NO_FLUSH; 72773d80debSLuiz Augusto von Dentz else 72873d80debSLuiz Augusto von Dentz flags = ACL_START; 72973d80debSLuiz Augusto von Dentz 73073d80debSLuiz Augusto von Dentz bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); 73173d80debSLuiz Augusto von Dentz hci_send_acl(chan->conn->hchan, skb, flags); 7320a708f8fSGustavo F. Padovan } 7330a708f8fSGustavo F. Padovan 734b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control) 735b5c6aaedSMat Martineau { 736b5c6aaedSMat Martineau control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT; 737b5c6aaedSMat Martineau control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT; 738b5c6aaedSMat Martineau 739b5c6aaedSMat Martineau if (enh & L2CAP_CTRL_FRAME_TYPE) { 740b5c6aaedSMat Martineau /* S-Frame */ 741b5c6aaedSMat Martineau control->sframe = 1; 742b5c6aaedSMat Martineau control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT; 743b5c6aaedSMat Martineau control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT; 744b5c6aaedSMat Martineau 745b5c6aaedSMat Martineau control->sar = 0; 746b5c6aaedSMat Martineau control->txseq = 0; 747b5c6aaedSMat Martineau } else { 748b5c6aaedSMat Martineau /* I-Frame */ 749b5c6aaedSMat Martineau control->sframe = 0; 750b5c6aaedSMat Martineau control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT; 751b5c6aaedSMat Martineau control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT; 752b5c6aaedSMat Martineau 753b5c6aaedSMat Martineau control->poll = 0; 754b5c6aaedSMat Martineau control->super = 0; 755b5c6aaedSMat Martineau } 756b5c6aaedSMat Martineau } 757b5c6aaedSMat Martineau 758b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control) 759b5c6aaedSMat Martineau { 760b5c6aaedSMat Martineau control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT; 761b5c6aaedSMat Martineau control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT; 762b5c6aaedSMat Martineau 763b5c6aaedSMat Martineau if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) { 764b5c6aaedSMat Martineau /* S-Frame */ 765b5c6aaedSMat Martineau control->sframe = 1; 766b5c6aaedSMat Martineau control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT; 767b5c6aaedSMat Martineau control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT; 768b5c6aaedSMat Martineau 769b5c6aaedSMat Martineau control->sar = 0; 770b5c6aaedSMat Martineau control->txseq = 0; 771b5c6aaedSMat Martineau } else { 772b5c6aaedSMat Martineau /* I-Frame */ 773b5c6aaedSMat Martineau control->sframe = 0; 774b5c6aaedSMat Martineau control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT; 775b5c6aaedSMat Martineau control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT; 776b5c6aaedSMat Martineau 777b5c6aaedSMat Martineau control->poll = 0; 778b5c6aaedSMat Martineau control->super = 0; 779b5c6aaedSMat Martineau } 780b5c6aaedSMat Martineau } 781b5c6aaedSMat Martineau 782b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan, 783b5c6aaedSMat Martineau struct sk_buff *skb) 784b5c6aaedSMat Martineau { 785b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 786b5c6aaedSMat Martineau __unpack_extended_control(get_unaligned_le32(skb->data), 787b5c6aaedSMat Martineau &bt_cb(skb)->control); 788cec8ab6eSMat Martineau skb_pull(skb, L2CAP_EXT_CTRL_SIZE); 789b5c6aaedSMat Martineau } else { 790b5c6aaedSMat Martineau __unpack_enhanced_control(get_unaligned_le16(skb->data), 791b5c6aaedSMat Martineau &bt_cb(skb)->control); 792cec8ab6eSMat Martineau skb_pull(skb, L2CAP_ENH_CTRL_SIZE); 793b5c6aaedSMat Martineau } 794b5c6aaedSMat Martineau } 795b5c6aaedSMat Martineau 796b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control) 797b5c6aaedSMat Martineau { 798b5c6aaedSMat Martineau u32 packed; 799b5c6aaedSMat Martineau 800b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT; 801b5c6aaedSMat Martineau packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT; 802b5c6aaedSMat Martineau 803b5c6aaedSMat Martineau if (control->sframe) { 804b5c6aaedSMat Martineau packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT; 805b5c6aaedSMat Martineau packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT; 806b5c6aaedSMat Martineau packed |= L2CAP_EXT_CTRL_FRAME_TYPE; 807b5c6aaedSMat Martineau } else { 808b5c6aaedSMat Martineau packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT; 809b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT; 810b5c6aaedSMat Martineau } 811b5c6aaedSMat Martineau 812b5c6aaedSMat Martineau return packed; 813b5c6aaedSMat Martineau } 814b5c6aaedSMat Martineau 815b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control) 816b5c6aaedSMat Martineau { 817b5c6aaedSMat Martineau u16 packed; 818b5c6aaedSMat Martineau 819b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT; 820b5c6aaedSMat Martineau packed |= control->final << L2CAP_CTRL_FINAL_SHIFT; 821b5c6aaedSMat Martineau 822b5c6aaedSMat Martineau if (control->sframe) { 823b5c6aaedSMat Martineau packed |= control->poll << L2CAP_CTRL_POLL_SHIFT; 824b5c6aaedSMat Martineau packed |= control->super << L2CAP_CTRL_SUPER_SHIFT; 825b5c6aaedSMat Martineau packed |= L2CAP_CTRL_FRAME_TYPE; 826b5c6aaedSMat Martineau } else { 827b5c6aaedSMat Martineau packed |= control->sar << L2CAP_CTRL_SAR_SHIFT; 828b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT; 829b5c6aaedSMat Martineau } 830b5c6aaedSMat Martineau 831b5c6aaedSMat Martineau return packed; 832b5c6aaedSMat Martineau } 833b5c6aaedSMat Martineau 834b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan, 835b5c6aaedSMat Martineau struct l2cap_ctrl *control, 836b5c6aaedSMat Martineau struct sk_buff *skb) 837b5c6aaedSMat Martineau { 838b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 839b5c6aaedSMat Martineau put_unaligned_le32(__pack_extended_control(control), 840b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 841b5c6aaedSMat Martineau } else { 842b5c6aaedSMat Martineau put_unaligned_le16(__pack_enhanced_control(control), 843b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 844b5c6aaedSMat Martineau } 845b5c6aaedSMat Martineau } 846b5c6aaedSMat Martineau 847a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan, 848a67d7f6fSMat Martineau u32 control) 8490a708f8fSGustavo F. Padovan { 8500a708f8fSGustavo F. Padovan struct sk_buff *skb; 8510a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 852a67d7f6fSMat Martineau int hlen; 8530a708f8fSGustavo F. Padovan 854e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 855e4ca6d98SAndrei Emeltchenko hlen = L2CAP_EXT_HDR_SIZE; 856e4ca6d98SAndrei Emeltchenko else 857e4ca6d98SAndrei Emeltchenko hlen = L2CAP_ENH_HDR_SIZE; 8580a708f8fSGustavo F. Padovan 8590a708f8fSGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 86003a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 8610a708f8fSGustavo F. Padovan 862a67d7f6fSMat Martineau skb = bt_skb_alloc(hlen, GFP_KERNEL); 8630a708f8fSGustavo F. Padovan 8640a708f8fSGustavo F. Padovan if (!skb) 865a67d7f6fSMat Martineau return ERR_PTR(-ENOMEM); 8660a708f8fSGustavo F. Padovan 8670a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 8680a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); 869fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 87088843ab0SAndrei Emeltchenko 871a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 872a67d7f6fSMat Martineau put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 873a67d7f6fSMat Martineau else 874a67d7f6fSMat Martineau put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 8750a708f8fSGustavo F. Padovan 87647d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 877a67d7f6fSMat Martineau u16 fcs = crc16(0, (u8 *)skb->data, skb->len); 87803a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 8790a708f8fSGustavo F. Padovan } 8800a708f8fSGustavo F. Padovan 88173d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 882a67d7f6fSMat Martineau return skb; 883a67d7f6fSMat Martineau } 884a67d7f6fSMat Martineau 885a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan, 886a67d7f6fSMat Martineau struct l2cap_ctrl *control) 887a67d7f6fSMat Martineau { 888a67d7f6fSMat Martineau struct sk_buff *skb; 889a67d7f6fSMat Martineau u32 control_field; 890a67d7f6fSMat Martineau 891a67d7f6fSMat Martineau BT_DBG("chan %p, control %p", chan, control); 892a67d7f6fSMat Martineau 893a67d7f6fSMat Martineau if (!control->sframe) 894a67d7f6fSMat Martineau return; 895a67d7f6fSMat Martineau 896a67d7f6fSMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) && 897a67d7f6fSMat Martineau !control->poll) 898a67d7f6fSMat Martineau control->final = 1; 899a67d7f6fSMat Martineau 900a67d7f6fSMat Martineau if (control->super == L2CAP_SUPER_RR) 901a67d7f6fSMat Martineau clear_bit(CONN_RNR_SENT, &chan->conn_state); 902a67d7f6fSMat Martineau else if (control->super == L2CAP_SUPER_RNR) 903a67d7f6fSMat Martineau set_bit(CONN_RNR_SENT, &chan->conn_state); 904a67d7f6fSMat Martineau 905a67d7f6fSMat Martineau if (control->super != L2CAP_SUPER_SREJ) { 906a67d7f6fSMat Martineau chan->last_acked_seq = control->reqseq; 907a67d7f6fSMat Martineau __clear_ack_timer(chan); 908a67d7f6fSMat Martineau } 909a67d7f6fSMat Martineau 910a67d7f6fSMat Martineau BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq, 911a67d7f6fSMat Martineau control->final, control->poll, control->super); 912a67d7f6fSMat Martineau 913a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 914a67d7f6fSMat Martineau control_field = __pack_extended_control(control); 915a67d7f6fSMat Martineau else 916a67d7f6fSMat Martineau control_field = __pack_enhanced_control(control); 917a67d7f6fSMat Martineau 918a67d7f6fSMat Martineau skb = l2cap_create_sframe_pdu(chan, control_field); 919a67d7f6fSMat Martineau if (!IS_ERR(skb)) 92073d80debSLuiz Augusto von Dentz l2cap_do_send(chan, skb); 9210a708f8fSGustavo F. Padovan } 9220a708f8fSGustavo F. Padovan 92388843ab0SAndrei Emeltchenko static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control) 9240a708f8fSGustavo F. Padovan { 925e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 926ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); 927e2ab4353SGustavo F. Padovan set_bit(CONN_RNR_SENT, &chan->conn_state); 9280a708f8fSGustavo F. Padovan } else 929ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 9300a708f8fSGustavo F. Padovan 9310b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 9320a708f8fSGustavo F. Padovan } 9330a708f8fSGustavo F. Padovan 934b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) 9350a708f8fSGustavo F. Padovan { 936c1360a1cSGustavo F. Padovan return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); 9370a708f8fSGustavo F. Padovan } 9380a708f8fSGustavo F. Padovan 9399b27f350SAndrei Emeltchenko static void l2cap_send_conn_req(struct l2cap_chan *chan) 9409b27f350SAndrei Emeltchenko { 9419b27f350SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 9429b27f350SAndrei Emeltchenko struct l2cap_conn_req req; 9439b27f350SAndrei Emeltchenko 9449b27f350SAndrei Emeltchenko req.scid = cpu_to_le16(chan->scid); 9459b27f350SAndrei Emeltchenko req.psm = chan->psm; 9469b27f350SAndrei Emeltchenko 9479b27f350SAndrei Emeltchenko chan->ident = l2cap_get_ident(conn); 9489b27f350SAndrei Emeltchenko 9499b27f350SAndrei Emeltchenko set_bit(CONF_CONNECT_PEND, &chan->conf_state); 9509b27f350SAndrei Emeltchenko 9519b27f350SAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); 9529b27f350SAndrei Emeltchenko } 9539b27f350SAndrei Emeltchenko 9549f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan) 9559f0caeb1SVinicius Costa Gomes { 9569f0caeb1SVinicius Costa Gomes struct sock *sk = chan->sk; 9579f0caeb1SVinicius Costa Gomes struct sock *parent; 9589f0caeb1SVinicius Costa Gomes 9599f0caeb1SVinicius Costa Gomes lock_sock(sk); 9609f0caeb1SVinicius Costa Gomes 9619f0caeb1SVinicius Costa Gomes parent = bt_sk(sk)->parent; 9629f0caeb1SVinicius Costa Gomes 9639f0caeb1SVinicius Costa Gomes BT_DBG("sk %p, parent %p", sk, parent); 9649f0caeb1SVinicius Costa Gomes 9652827011fSMat Martineau /* This clears all conf flags, including CONF_NOT_COMPLETE */ 9669f0caeb1SVinicius Costa Gomes chan->conf_state = 0; 9679f0caeb1SVinicius Costa Gomes __clear_chan_timer(chan); 9689f0caeb1SVinicius Costa Gomes 9699f0caeb1SVinicius Costa Gomes __l2cap_state_change(chan, BT_CONNECTED); 9709f0caeb1SVinicius Costa Gomes sk->sk_state_change(sk); 9719f0caeb1SVinicius Costa Gomes 9729f0caeb1SVinicius Costa Gomes if (parent) 9739f0caeb1SVinicius Costa Gomes parent->sk_data_ready(parent, 0); 9749f0caeb1SVinicius Costa Gomes 9759f0caeb1SVinicius Costa Gomes release_sock(sk); 9769f0caeb1SVinicius Costa Gomes } 9779f0caeb1SVinicius Costa Gomes 978fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan) 9790a708f8fSGustavo F. Padovan { 9808c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 9810a708f8fSGustavo F. Padovan 9829f0caeb1SVinicius Costa Gomes if (conn->hcon->type == LE_LINK) { 9839f0caeb1SVinicius Costa Gomes l2cap_chan_ready(chan); 9849f0caeb1SVinicius Costa Gomes return; 9859f0caeb1SVinicius Costa Gomes } 9869f0caeb1SVinicius Costa Gomes 9870a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { 9880a708f8fSGustavo F. Padovan if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) 9890a708f8fSGustavo F. Padovan return; 9900a708f8fSGustavo F. Padovan 991d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan) && 9929b27f350SAndrei Emeltchenko __l2cap_no_conn_pending(chan)) 9939b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 9940a708f8fSGustavo F. Padovan } else { 9950a708f8fSGustavo F. Padovan struct l2cap_info_req req; 9960a708f8fSGustavo F. Padovan req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 9970a708f8fSGustavo F. Padovan 9980a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 9990a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 10000a708f8fSGustavo F. Padovan 1001ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 10020a708f8fSGustavo F. Padovan 10030a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 10040a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 10050a708f8fSGustavo F. Padovan } 10060a708f8fSGustavo F. Padovan } 10070a708f8fSGustavo F. Padovan 10080a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) 10090a708f8fSGustavo F. Padovan { 10100a708f8fSGustavo F. Padovan u32 local_feat_mask = l2cap_feat_mask; 10110a708f8fSGustavo F. Padovan if (!disable_ertm) 10120a708f8fSGustavo F. Padovan local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING; 10130a708f8fSGustavo F. Padovan 10140a708f8fSGustavo F. Padovan switch (mode) { 10150a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 10160a708f8fSGustavo F. Padovan return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask; 10170a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 10180a708f8fSGustavo F. Padovan return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask; 10190a708f8fSGustavo F. Padovan default: 10200a708f8fSGustavo F. Padovan return 0x00; 10210a708f8fSGustavo F. Padovan } 10220a708f8fSGustavo F. Padovan } 10230a708f8fSGustavo F. Padovan 10244519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err) 10250a708f8fSGustavo F. Padovan { 10266be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 10270a708f8fSGustavo F. Padovan struct l2cap_disconn_req req; 10280a708f8fSGustavo F. Padovan 10290a708f8fSGustavo F. Padovan if (!conn) 10300a708f8fSGustavo F. Padovan return; 10310a708f8fSGustavo F. Padovan 10320c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_ERTM) { 10331a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 10341a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 10351a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 10360a708f8fSGustavo F. Padovan } 10370a708f8fSGustavo F. Padovan 1038fe4128e0SGustavo F. Padovan req.dcid = cpu_to_le16(chan->dcid); 1039fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 10400a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 10410a708f8fSGustavo F. Padovan L2CAP_DISCONN_REQ, sizeof(req), &req); 10420a708f8fSGustavo F. Padovan 10436be36555SAndrei Emeltchenko lock_sock(sk); 10440e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_DISCONN); 10452e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 10466be36555SAndrei Emeltchenko release_sock(sk); 10470a708f8fSGustavo F. Padovan } 10480a708f8fSGustavo F. Padovan 10490a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */ 10500a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn) 10510a708f8fSGustavo F. Padovan { 10523df91ea2SAndrei Emeltchenko struct l2cap_chan *chan, *tmp; 10530a708f8fSGustavo F. Padovan 10540a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 10550a708f8fSGustavo F. Padovan 10563df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 10570a708f8fSGustavo F. Padovan 10583df91ea2SAndrei Emeltchenko list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 105948454079SGustavo F. Padovan struct sock *sk = chan->sk; 1060baa7e1faSGustavo F. Padovan 10616be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 10620a708f8fSGustavo F. Padovan 1063715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 10646be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10650a708f8fSGustavo F. Padovan continue; 10660a708f8fSGustavo F. Padovan } 10670a708f8fSGustavo F. Padovan 106889bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 1069d45fc423SGustavo F. Padovan if (!l2cap_chan_check_security(chan) || 1070b4450035SGustavo F. Padovan !__l2cap_no_conn_pending(chan)) { 10716be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10720a708f8fSGustavo F. Padovan continue; 10730a708f8fSGustavo F. Padovan } 10740a708f8fSGustavo F. Padovan 1075c1360a1cSGustavo F. Padovan if (!l2cap_mode_supported(chan->mode, conn->feat_mask) 1076c1360a1cSGustavo F. Padovan && test_bit(CONF_STATE2_DEVICE, 1077c1360a1cSGustavo F. Padovan &chan->conf_state)) { 10780f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 10796be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10800a708f8fSGustavo F. Padovan continue; 10810a708f8fSGustavo F. Padovan } 10820a708f8fSGustavo F. Padovan 10839b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 10840a708f8fSGustavo F. Padovan 108589bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 10860a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 10870a708f8fSGustavo F. Padovan char buf[128]; 1088fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 1089fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 10900a708f8fSGustavo F. Padovan 1091d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 10926be36555SAndrei Emeltchenko lock_sock(sk); 1093c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, 1094c5daa683SGustavo Padovan &bt_sk(sk)->flags)) { 10950a708f8fSGustavo F. Padovan struct sock *parent = bt_sk(sk)->parent; 10960a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_PEND); 10970a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND); 109805e9a2f6SIlia Kolomisnky if (parent) 10990a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 11000a708f8fSGustavo F. Padovan 11010a708f8fSGustavo F. Padovan } else { 11020e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 11030a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 11040a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 11050a708f8fSGustavo F. Padovan } 11066be36555SAndrei Emeltchenko release_sock(sk); 11070a708f8fSGustavo F. Padovan } else { 11080a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_PEND); 11090a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND); 11100a708f8fSGustavo F. Padovan } 11110a708f8fSGustavo F. Padovan 1112fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 1113fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 11140a708f8fSGustavo F. Padovan 1115c1360a1cSGustavo F. Padovan if (test_bit(CONF_REQ_SENT, &chan->conf_state) || 11160a708f8fSGustavo F. Padovan rsp.result != L2CAP_CR_SUCCESS) { 11176be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 11180a708f8fSGustavo F. Padovan continue; 11190a708f8fSGustavo F. Padovan } 11200a708f8fSGustavo F. Padovan 1121c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 11220a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 112373ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 112473ffa904SGustavo F. Padovan chan->num_conf_req++; 11250a708f8fSGustavo F. Padovan } 11260a708f8fSGustavo F. Padovan 11276be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 11280a708f8fSGustavo F. Padovan } 11290a708f8fSGustavo F. Padovan 11303df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 11310a708f8fSGustavo F. Padovan } 11320a708f8fSGustavo F. Padovan 1133c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr. 1134b62f328bSVille Tervo * Returns closest match, locked. 1135b62f328bSVille Tervo */ 1136d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, 1137c2287681SIdo Yariv bdaddr_t *src, 1138c2287681SIdo Yariv bdaddr_t *dst) 1139b62f328bSVille Tervo { 114023691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 1141b62f328bSVille Tervo 114223691d75SGustavo F. Padovan read_lock(&chan_list_lock); 1143b62f328bSVille Tervo 114423691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 114523691d75SGustavo F. Padovan struct sock *sk = c->sk; 1146fe4128e0SGustavo F. Padovan 114789bc500eSGustavo F. Padovan if (state && c->state != state) 1148b62f328bSVille Tervo continue; 1149b62f328bSVille Tervo 115023691d75SGustavo F. Padovan if (c->scid == cid) { 1151c2287681SIdo Yariv int src_match, dst_match; 1152c2287681SIdo Yariv int src_any, dst_any; 1153c2287681SIdo Yariv 1154b62f328bSVille Tervo /* Exact match. */ 1155c2287681SIdo Yariv src_match = !bacmp(&bt_sk(sk)->src, src); 1156c2287681SIdo Yariv dst_match = !bacmp(&bt_sk(sk)->dst, dst); 1157c2287681SIdo Yariv if (src_match && dst_match) { 115823691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 115923691d75SGustavo F. Padovan return c; 116023691d75SGustavo F. Padovan } 1161b62f328bSVille Tervo 1162b62f328bSVille Tervo /* Closest match */ 1163c2287681SIdo Yariv src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY); 1164c2287681SIdo Yariv dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY); 1165c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1166c2287681SIdo Yariv (src_any && dst_any)) 116723691d75SGustavo F. Padovan c1 = c; 1168b62f328bSVille Tervo } 1169b62f328bSVille Tervo } 1170280f294fSGustavo F. Padovan 117123691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 1172b62f328bSVille Tervo 117323691d75SGustavo F. Padovan return c1; 1174b62f328bSVille Tervo } 1175b62f328bSVille Tervo 1176b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn) 1177b62f328bSVille Tervo { 1178c916fbe4SGustavo F. Padovan struct sock *parent, *sk; 117923691d75SGustavo F. Padovan struct l2cap_chan *chan, *pchan; 1180b62f328bSVille Tervo 1181b62f328bSVille Tervo BT_DBG(""); 1182b62f328bSVille Tervo 1183b62f328bSVille Tervo /* Check if we have socket listening on cid */ 118423691d75SGustavo F. Padovan pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA, 1185c2287681SIdo Yariv conn->src, conn->dst); 118623691d75SGustavo F. Padovan if (!pchan) 1187b62f328bSVille Tervo return; 1188b62f328bSVille Tervo 118923691d75SGustavo F. Padovan parent = pchan->sk; 119023691d75SGustavo F. Padovan 1191aa2ac881SGustavo F. Padovan lock_sock(parent); 119262f3a2cfSGustavo F. Padovan 1193b62f328bSVille Tervo /* Check for backlog size */ 1194b62f328bSVille Tervo if (sk_acceptq_is_full(parent)) { 1195b62f328bSVille Tervo BT_DBG("backlog full %d", parent->sk_ack_backlog); 1196b62f328bSVille Tervo goto clean; 1197b62f328bSVille Tervo } 1198b62f328bSVille Tervo 119980808e43SGustavo F. Padovan chan = pchan->ops->new_connection(pchan->data); 120080808e43SGustavo F. Padovan if (!chan) 1201b62f328bSVille Tervo goto clean; 1202b62f328bSVille Tervo 120380808e43SGustavo F. Padovan sk = chan->sk; 12045d41ce1dSGustavo F. Padovan 1205b62f328bSVille Tervo hci_conn_hold(conn->hcon); 1206b62f328bSVille Tervo 1207b62f328bSVille Tervo bacpy(&bt_sk(sk)->src, conn->src); 1208b62f328bSVille Tervo bacpy(&bt_sk(sk)->dst, conn->dst); 1209b62f328bSVille Tervo 1210d1010240SGustavo F. Padovan bt_accept_enqueue(parent, sk); 1211d1010240SGustavo F. Padovan 12123d57dc68SGustavo F. Padovan l2cap_chan_add(conn, chan); 121348454079SGustavo F. Padovan 1214c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 1215b62f328bSVille Tervo 12160e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECTED); 1217b62f328bSVille Tervo parent->sk_data_ready(parent, 0); 1218b62f328bSVille Tervo 1219b62f328bSVille Tervo clean: 1220aa2ac881SGustavo F. Padovan release_sock(parent); 1221b62f328bSVille Tervo } 1222b62f328bSVille Tervo 12230a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn) 12240a708f8fSGustavo F. Padovan { 122548454079SGustavo F. Padovan struct l2cap_chan *chan; 12260a708f8fSGustavo F. Padovan 12270a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 12280a708f8fSGustavo F. Padovan 1229b62f328bSVille Tervo if (!conn->hcon->out && conn->hcon->type == LE_LINK) 1230b62f328bSVille Tervo l2cap_le_conn_ready(conn); 1231b62f328bSVille Tervo 1232160dc6acSVinicius Costa Gomes if (conn->hcon->out && conn->hcon->type == LE_LINK) 1233160dc6acSVinicius Costa Gomes smp_conn_security(conn, conn->hcon->pending_sec_level); 1234160dc6acSVinicius Costa Gomes 12353df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 12360a708f8fSGustavo F. Padovan 12373df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1238baa7e1faSGustavo F. Padovan 12396be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 12400a708f8fSGustavo F. Padovan 124163128451SVinicius Costa Gomes if (conn->hcon->type == LE_LINK) { 1242b501d6a1SAnderson Briglia if (smp_conn_security(conn, chan->sec_level)) 1243cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 1244acd7d370SVille Tervo 124563128451SVinicius Costa Gomes } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 12466be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 1247c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 12486be36555SAndrei Emeltchenko lock_sock(sk); 12490e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECTED); 12500a708f8fSGustavo F. Padovan sk->sk_state_change(sk); 12516be36555SAndrei Emeltchenko release_sock(sk); 1252b501d6a1SAnderson Briglia 125389bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT) 1254fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 12550a708f8fSGustavo F. Padovan 12566be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 12570a708f8fSGustavo F. Padovan } 12580a708f8fSGustavo F. Padovan 12593df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 12600a708f8fSGustavo F. Padovan } 12610a708f8fSGustavo F. Padovan 12620a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */ 12630a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) 12640a708f8fSGustavo F. Padovan { 126548454079SGustavo F. Padovan struct l2cap_chan *chan; 12660a708f8fSGustavo F. Padovan 12670a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 12680a708f8fSGustavo F. Padovan 12693df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 12700a708f8fSGustavo F. Padovan 12713df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1272ecf61bdbSAndrei Emeltchenko if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) 12732e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 12740a708f8fSGustavo F. Padovan } 12750a708f8fSGustavo F. Padovan 12763df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 12770a708f8fSGustavo F. Padovan } 12780a708f8fSGustavo F. Padovan 1279f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work) 12800a708f8fSGustavo F. Padovan { 1281f878fcadSGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 1282030013d8SGustavo F. Padovan info_timer.work); 12830a708f8fSGustavo F. Padovan 12840a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 12850a708f8fSGustavo F. Padovan conn->info_ident = 0; 12860a708f8fSGustavo F. Padovan 12870a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 12880a708f8fSGustavo F. Padovan } 12890a708f8fSGustavo F. Padovan 12905d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err) 12915d3de7dfSVinicius Costa Gomes { 12925d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 12935d3de7dfSVinicius Costa Gomes struct l2cap_chan *chan, *l; 12945d3de7dfSVinicius Costa Gomes 12955d3de7dfSVinicius Costa Gomes if (!conn) 12965d3de7dfSVinicius Costa Gomes return; 12975d3de7dfSVinicius Costa Gomes 12985d3de7dfSVinicius Costa Gomes BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); 12995d3de7dfSVinicius Costa Gomes 13005d3de7dfSVinicius Costa Gomes kfree_skb(conn->rx_skb); 13015d3de7dfSVinicius Costa Gomes 13023df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 13033df91ea2SAndrei Emeltchenko 13045d3de7dfSVinicius Costa Gomes /* Kill channels */ 13055d3de7dfSVinicius Costa Gomes list_for_each_entry_safe(chan, l, &conn->chan_l, list) { 130661d6ef3eSMat Martineau l2cap_chan_hold(chan); 13076be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 13086be36555SAndrei Emeltchenko 13095d3de7dfSVinicius Costa Gomes l2cap_chan_del(chan, err); 13106be36555SAndrei Emeltchenko 13116be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13126be36555SAndrei Emeltchenko 13135d3de7dfSVinicius Costa Gomes chan->ops->close(chan->data); 131461d6ef3eSMat Martineau l2cap_chan_put(chan); 13155d3de7dfSVinicius Costa Gomes } 13165d3de7dfSVinicius Costa Gomes 13173df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 13183df91ea2SAndrei Emeltchenko 131973d80debSLuiz Augusto von Dentz hci_chan_del(conn->hchan); 132073d80debSLuiz Augusto von Dentz 13215d3de7dfSVinicius Costa Gomes if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1322127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->info_timer); 13235d3de7dfSVinicius Costa Gomes 132451a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) { 1325127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->security_timer); 13268aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 1327d26a2345SVinicius Costa Gomes } 13285d3de7dfSVinicius Costa Gomes 13295d3de7dfSVinicius Costa Gomes hcon->l2cap_data = NULL; 13305d3de7dfSVinicius Costa Gomes kfree(conn); 13315d3de7dfSVinicius Costa Gomes } 13325d3de7dfSVinicius Costa Gomes 13336c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work) 13345d3de7dfSVinicius Costa Gomes { 13356c9d42a1SGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 13366c9d42a1SGustavo F. Padovan security_timer.work); 13375d3de7dfSVinicius Costa Gomes 13385d3de7dfSVinicius Costa Gomes l2cap_conn_del(conn->hcon, ETIMEDOUT); 13395d3de7dfSVinicius Costa Gomes } 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 14826be36555SAndrei Emeltchenko lock_sock(sk); 14836be36555SAndrei Emeltchenko 148403a00194SGustavo F. Padovan switch (sk->sk_state) { 148503a00194SGustavo F. Padovan case BT_CONNECT: 148603a00194SGustavo F. Padovan case BT_CONNECT2: 148703a00194SGustavo F. Padovan case BT_CONFIG: 148803a00194SGustavo F. Padovan /* Already connecting */ 148903a00194SGustavo F. Padovan err = 0; 14906be36555SAndrei Emeltchenko release_sock(sk); 149103a00194SGustavo F. Padovan goto done; 149203a00194SGustavo F. Padovan 149303a00194SGustavo F. Padovan case BT_CONNECTED: 149403a00194SGustavo F. Padovan /* Already connected */ 149503a00194SGustavo F. Padovan err = -EISCONN; 14966be36555SAndrei Emeltchenko release_sock(sk); 149703a00194SGustavo F. Padovan goto done; 149803a00194SGustavo F. Padovan 149903a00194SGustavo F. Padovan case BT_OPEN: 150003a00194SGustavo F. Padovan case BT_BOUND: 150103a00194SGustavo F. Padovan /* Can connect */ 150203a00194SGustavo F. Padovan break; 150303a00194SGustavo F. Padovan 150403a00194SGustavo F. Padovan default: 150503a00194SGustavo F. Padovan err = -EBADFD; 15066be36555SAndrei Emeltchenko release_sock(sk); 150703a00194SGustavo F. Padovan goto done; 150803a00194SGustavo F. Padovan } 150903a00194SGustavo F. Padovan 151003a00194SGustavo F. Padovan /* Set destination address and psm */ 15119219b2a0SGustavo F. Padovan bacpy(&bt_sk(sk)->dst, dst); 15126be36555SAndrei Emeltchenko 15136be36555SAndrei Emeltchenko release_sock(sk); 15146be36555SAndrei Emeltchenko 151503a00194SGustavo F. Padovan chan->psm = psm; 151603a00194SGustavo F. Padovan chan->dcid = cid; 15170a708f8fSGustavo F. Padovan 15184343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 15190a708f8fSGustavo F. Padovan 1520fe4128e0SGustavo F. Padovan if (chan->dcid == L2CAP_CID_LE_DATA) 15218e9f9892SAndre Guedes hcon = hci_connect(hdev, LE_LINK, dst, dst_type, 15224343478fSGustavo F. Padovan chan->sec_level, auth_type); 1523acd7d370SVille Tervo else 15248e9f9892SAndre Guedes hcon = hci_connect(hdev, ACL_LINK, dst, dst_type, 15254343478fSGustavo F. Padovan chan->sec_level, auth_type); 1526acd7d370SVille Tervo 152730e76272SVille Tervo if (IS_ERR(hcon)) { 152830e76272SVille Tervo err = PTR_ERR(hcon); 15290a708f8fSGustavo F. Padovan goto done; 153030e76272SVille Tervo } 15310a708f8fSGustavo F. Padovan 15320a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, 0); 15330a708f8fSGustavo F. Padovan if (!conn) { 15340a708f8fSGustavo F. Padovan hci_conn_put(hcon); 153530e76272SVille Tervo err = -ENOMEM; 15360a708f8fSGustavo F. Padovan goto done; 15370a708f8fSGustavo F. Padovan } 15380a708f8fSGustavo F. Padovan 15399f0caeb1SVinicius Costa Gomes if (hcon->type == LE_LINK) { 15409f0caeb1SVinicius Costa Gomes err = 0; 15419f0caeb1SVinicius Costa Gomes 15429f0caeb1SVinicius Costa Gomes if (!list_empty(&conn->chan_l)) { 15439f0caeb1SVinicius Costa Gomes err = -EBUSY; 15449f0caeb1SVinicius Costa Gomes hci_conn_put(hcon); 15459f0caeb1SVinicius Costa Gomes } 15469f0caeb1SVinicius Costa Gomes 15479f0caeb1SVinicius Costa Gomes if (err) 15489f0caeb1SVinicius Costa Gomes goto done; 15499f0caeb1SVinicius Costa Gomes } 15509f0caeb1SVinicius Costa Gomes 15510a708f8fSGustavo F. Padovan /* Update source addr of the socket */ 15520a708f8fSGustavo F. Padovan bacpy(src, conn->src); 15530a708f8fSGustavo F. Padovan 15546be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 155548454079SGustavo F. Padovan l2cap_chan_add(conn, chan); 15566be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 155748454079SGustavo F. Padovan 15586be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECT); 1559c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 15600a708f8fSGustavo F. Padovan 15610a708f8fSGustavo F. Padovan if (hcon->state == BT_CONNECTED) { 1562715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1563c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 1564d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) 15656be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECTED); 15660a708f8fSGustavo F. Padovan } else 1567fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 15680a708f8fSGustavo F. Padovan } 15690a708f8fSGustavo F. Padovan 157030e76272SVille Tervo err = 0; 157130e76272SVille Tervo 15720a708f8fSGustavo F. Padovan done: 15736be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 157409fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 15750a708f8fSGustavo F. Padovan hci_dev_put(hdev); 15760a708f8fSGustavo F. Padovan return err; 15770a708f8fSGustavo F. Padovan } 15780a708f8fSGustavo F. Padovan 1579dcba0dbaSGustavo F. Padovan int __l2cap_wait_ack(struct sock *sk) 15800a708f8fSGustavo F. Padovan { 15818c1d787bSGustavo F. Padovan struct l2cap_chan *chan = l2cap_pi(sk)->chan; 15820a708f8fSGustavo F. Padovan DECLARE_WAITQUEUE(wait, current); 15830a708f8fSGustavo F. Padovan int err = 0; 15840a708f8fSGustavo F. Padovan int timeo = HZ/5; 15850a708f8fSGustavo F. Padovan 15860a708f8fSGustavo F. Padovan add_wait_queue(sk_sleep(sk), &wait); 15870a708f8fSGustavo F. Padovan set_current_state(TASK_INTERRUPTIBLE); 1588a71a0cf4SPeter Hurley while (chan->unacked_frames > 0 && chan->conn) { 15890a708f8fSGustavo F. Padovan if (!timeo) 15900a708f8fSGustavo F. Padovan timeo = HZ/5; 15910a708f8fSGustavo F. Padovan 15920a708f8fSGustavo F. Padovan if (signal_pending(current)) { 15930a708f8fSGustavo F. Padovan err = sock_intr_errno(timeo); 15940a708f8fSGustavo F. Padovan break; 15950a708f8fSGustavo F. Padovan } 15960a708f8fSGustavo F. Padovan 15970a708f8fSGustavo F. Padovan release_sock(sk); 15980a708f8fSGustavo F. Padovan timeo = schedule_timeout(timeo); 15990a708f8fSGustavo F. Padovan lock_sock(sk); 1600a71a0cf4SPeter Hurley set_current_state(TASK_INTERRUPTIBLE); 16010a708f8fSGustavo F. Padovan 16020a708f8fSGustavo F. Padovan err = sock_error(sk); 16030a708f8fSGustavo F. Padovan if (err) 16040a708f8fSGustavo F. Padovan break; 16050a708f8fSGustavo F. Padovan } 16060a708f8fSGustavo F. Padovan set_current_state(TASK_RUNNING); 16070a708f8fSGustavo F. Padovan remove_wait_queue(sk_sleep(sk), &wait); 16080a708f8fSGustavo F. Padovan return err; 16090a708f8fSGustavo F. Padovan } 16100a708f8fSGustavo F. Padovan 1611721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work) 16120a708f8fSGustavo F. Padovan { 1613721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1614721c4181SGustavo F. Padovan monitor_timer.work); 16150a708f8fSGustavo F. Padovan 1616525cd185SGustavo F. Padovan BT_DBG("chan %p", chan); 16170a708f8fSGustavo F. Padovan 16186be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 16196be36555SAndrei Emeltchenko 16202c03a7a4SGustavo F. Padovan if (chan->retry_count >= chan->remote_max_tx) { 16218c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); 16226be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16238d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 16240a708f8fSGustavo F. Padovan return; 16250a708f8fSGustavo F. Padovan } 16260a708f8fSGustavo F. Padovan 16276a026610SGustavo F. Padovan chan->retry_count++; 16281a09bcb9SGustavo F. Padovan __set_monitor_timer(chan); 16290a708f8fSGustavo F. Padovan 1630525cd185SGustavo F. Padovan l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); 16316be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16328d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 16330a708f8fSGustavo F. Padovan } 16340a708f8fSGustavo F. Padovan 1635721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work) 16360a708f8fSGustavo F. Padovan { 1637721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1638721c4181SGustavo F. Padovan retrans_timer.work); 16390a708f8fSGustavo F. Padovan 164049208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 16410a708f8fSGustavo F. Padovan 16426be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 16436be36555SAndrei Emeltchenko 16446a026610SGustavo F. Padovan chan->retry_count = 1; 16451a09bcb9SGustavo F. Padovan __set_monitor_timer(chan); 16460a708f8fSGustavo F. Padovan 1647e2ab4353SGustavo F. Padovan set_bit(CONN_WAIT_F, &chan->conn_state); 16480a708f8fSGustavo F. Padovan 1649525cd185SGustavo F. Padovan l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); 16506be36555SAndrei Emeltchenko 16516be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16528d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 16530a708f8fSGustavo F. Padovan } 16540a708f8fSGustavo F. Padovan 16553733937dSMat Martineau static int l2cap_streaming_send(struct l2cap_chan *chan, 16563733937dSMat Martineau struct sk_buff_head *skbs) 16570a708f8fSGustavo F. Padovan { 16580a708f8fSGustavo F. Padovan struct sk_buff *skb; 16593733937dSMat Martineau struct l2cap_ctrl *control; 16600a708f8fSGustavo F. Padovan 16613733937dSMat Martineau BT_DBG("chan %p, skbs %p", chan, skbs); 16623733937dSMat Martineau 16633733937dSMat Martineau if (chan->state != BT_CONNECTED) 16643733937dSMat Martineau return -ENOTCONN; 16653733937dSMat Martineau 16663733937dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 16673733937dSMat Martineau 16683733937dSMat Martineau while (!skb_queue_empty(&chan->tx_q)) { 16693733937dSMat Martineau 16703733937dSMat Martineau skb = skb_dequeue(&chan->tx_q); 16713733937dSMat Martineau 16723733937dSMat Martineau bt_cb(skb)->control.retries = 1; 16733733937dSMat Martineau control = &bt_cb(skb)->control; 16743733937dSMat Martineau 16753733937dSMat Martineau control->reqseq = 0; 16763733937dSMat Martineau control->txseq = chan->next_tx_seq; 16773733937dSMat Martineau 16783733937dSMat Martineau __pack_control(chan, control, skb); 16790a708f8fSGustavo F. Padovan 168047d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 16813733937dSMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 16823733937dSMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 16830a708f8fSGustavo F. Padovan } 16840a708f8fSGustavo F. Padovan 16854343478fSGustavo F. Padovan l2cap_do_send(chan, skb); 16860a708f8fSGustavo F. Padovan 16873733937dSMat Martineau BT_DBG("Sent txseq %d", (int)control->txseq); 16883733937dSMat Martineau 1689836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 16903733937dSMat Martineau chan->frames_sent++; 16910a708f8fSGustavo F. Padovan } 16923733937dSMat Martineau 16933733937dSMat Martineau return 0; 16940a708f8fSGustavo F. Padovan } 16950a708f8fSGustavo F. Padovan 169667c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan) 16970a708f8fSGustavo F. Padovan { 16980a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 169918a48e76SMat Martineau struct l2cap_ctrl *control; 170018a48e76SMat Martineau int sent = 0; 170118a48e76SMat Martineau 170218a48e76SMat Martineau BT_DBG("chan %p", chan); 17030a708f8fSGustavo F. Padovan 170489bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 17050a708f8fSGustavo F. Padovan return -ENOTCONN; 17060a708f8fSGustavo F. Padovan 170794122bbeSMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 170894122bbeSMat Martineau return 0; 170994122bbeSMat Martineau 171018a48e76SMat Martineau while (chan->tx_send_head && 171118a48e76SMat Martineau chan->unacked_frames < chan->remote_tx_win && 171218a48e76SMat Martineau chan->tx_state == L2CAP_TX_STATE_XMIT) { 17130a708f8fSGustavo F. Padovan 171418a48e76SMat Martineau skb = chan->tx_send_head; 17150a708f8fSGustavo F. Padovan 171618a48e76SMat Martineau bt_cb(skb)->control.retries = 1; 171718a48e76SMat Martineau control = &bt_cb(skb)->control; 17180a708f8fSGustavo F. Padovan 1719e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 172018a48e76SMat Martineau control->final = 1; 1721e2ab4353SGustavo F. Padovan 172218a48e76SMat Martineau control->reqseq = chan->buffer_seq; 172318a48e76SMat Martineau chan->last_acked_seq = chan->buffer_seq; 172418a48e76SMat Martineau control->txseq = chan->next_tx_seq; 17250a708f8fSGustavo F. Padovan 172618a48e76SMat Martineau __pack_control(chan, control, skb); 17270a708f8fSGustavo F. Padovan 172847d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 172918a48e76SMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 173018a48e76SMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 17310a708f8fSGustavo F. Padovan } 17320a708f8fSGustavo F. Padovan 173318a48e76SMat Martineau /* Clone after data has been modified. Data is assumed to be 173418a48e76SMat Martineau read-only (for locking purposes) on cloned sk_buffs. 173518a48e76SMat Martineau */ 173618a48e76SMat Martineau tx_skb = skb_clone(skb, GFP_KERNEL); 173718a48e76SMat Martineau 173818a48e76SMat Martineau if (!tx_skb) 173918a48e76SMat Martineau break; 17400a708f8fSGustavo F. Padovan 17411a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 17420a708f8fSGustavo F. Padovan 1743836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 17446a026610SGustavo F. Padovan chan->unacked_frames++; 17456a026610SGustavo F. Padovan chan->frames_sent++; 174618a48e76SMat Martineau sent++; 17470a708f8fSGustavo F. Padovan 174858d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 174958d35f87SGustavo F. Padovan chan->tx_send_head = NULL; 17500a708f8fSGustavo F. Padovan else 175158d35f87SGustavo F. Padovan chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); 175218a48e76SMat Martineau 175318a48e76SMat Martineau l2cap_do_send(chan, tx_skb); 175418a48e76SMat Martineau BT_DBG("Sent txseq %d", (int)control->txseq); 17550a708f8fSGustavo F. Padovan } 17560a708f8fSGustavo F. Padovan 175718a48e76SMat Martineau BT_DBG("Sent %d, %d unacked, %d in ERTM queue", sent, 175818a48e76SMat Martineau (int) chan->unacked_frames, skb_queue_len(&chan->tx_q)); 175918a48e76SMat Martineau 176018a48e76SMat Martineau return sent; 17610a708f8fSGustavo F. Padovan } 17620a708f8fSGustavo F. Padovan 1763e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan) 1764e1fbd4c1SMat Martineau { 1765e1fbd4c1SMat Martineau struct l2cap_ctrl control; 1766e1fbd4c1SMat Martineau struct sk_buff *skb; 1767e1fbd4c1SMat Martineau struct sk_buff *tx_skb; 1768e1fbd4c1SMat Martineau u16 seq; 1769e1fbd4c1SMat Martineau 1770e1fbd4c1SMat Martineau BT_DBG("chan %p", chan); 1771e1fbd4c1SMat Martineau 1772e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 1773e1fbd4c1SMat Martineau return; 1774e1fbd4c1SMat Martineau 1775e1fbd4c1SMat Martineau while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) { 1776e1fbd4c1SMat Martineau seq = l2cap_seq_list_pop(&chan->retrans_list); 1777e1fbd4c1SMat Martineau 1778e1fbd4c1SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq); 1779e1fbd4c1SMat Martineau if (!skb) { 1780e1fbd4c1SMat Martineau BT_DBG("Error: Can't retransmit seq %d, frame missing", 1781e1fbd4c1SMat Martineau seq); 1782e1fbd4c1SMat Martineau continue; 1783e1fbd4c1SMat Martineau } 1784e1fbd4c1SMat Martineau 1785e1fbd4c1SMat Martineau bt_cb(skb)->control.retries++; 1786e1fbd4c1SMat Martineau control = bt_cb(skb)->control; 1787e1fbd4c1SMat Martineau 1788e1fbd4c1SMat Martineau if (chan->max_tx != 0 && 1789e1fbd4c1SMat Martineau bt_cb(skb)->control.retries > chan->max_tx) { 1790e1fbd4c1SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 1791e1fbd4c1SMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 1792e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 1793e1fbd4c1SMat Martineau break; 1794e1fbd4c1SMat Martineau } 1795e1fbd4c1SMat Martineau 1796e1fbd4c1SMat Martineau control.reqseq = chan->buffer_seq; 1797e1fbd4c1SMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 1798e1fbd4c1SMat Martineau control.final = 1; 1799e1fbd4c1SMat Martineau else 1800e1fbd4c1SMat Martineau control.final = 0; 1801e1fbd4c1SMat Martineau 1802e1fbd4c1SMat Martineau if (skb_cloned(skb)) { 1803e1fbd4c1SMat Martineau /* Cloned sk_buffs are read-only, so we need a 1804e1fbd4c1SMat Martineau * writeable copy 1805e1fbd4c1SMat Martineau */ 1806e1fbd4c1SMat Martineau tx_skb = skb_copy(skb, GFP_ATOMIC); 1807e1fbd4c1SMat Martineau } else { 1808e1fbd4c1SMat Martineau tx_skb = skb_clone(skb, GFP_ATOMIC); 1809e1fbd4c1SMat Martineau } 1810e1fbd4c1SMat Martineau 1811e1fbd4c1SMat Martineau if (!tx_skb) { 1812e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 1813e1fbd4c1SMat Martineau break; 1814e1fbd4c1SMat Martineau } 1815e1fbd4c1SMat Martineau 1816e1fbd4c1SMat Martineau /* Update skb contents */ 1817e1fbd4c1SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 1818e1fbd4c1SMat Martineau put_unaligned_le32(__pack_extended_control(&control), 1819e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 1820e1fbd4c1SMat Martineau } else { 1821e1fbd4c1SMat Martineau put_unaligned_le16(__pack_enhanced_control(&control), 1822e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 1823e1fbd4c1SMat Martineau } 1824e1fbd4c1SMat Martineau 1825e1fbd4c1SMat Martineau if (chan->fcs == L2CAP_FCS_CRC16) { 1826e1fbd4c1SMat Martineau u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len); 1827e1fbd4c1SMat Martineau put_unaligned_le16(fcs, skb_put(tx_skb, 1828e1fbd4c1SMat Martineau L2CAP_FCS_SIZE)); 1829e1fbd4c1SMat Martineau } 1830e1fbd4c1SMat Martineau 1831e1fbd4c1SMat Martineau l2cap_do_send(chan, tx_skb); 1832e1fbd4c1SMat Martineau 1833e1fbd4c1SMat Martineau BT_DBG("Resent txseq %d", control.txseq); 1834e1fbd4c1SMat Martineau 1835e1fbd4c1SMat Martineau chan->last_acked_seq = chan->buffer_seq; 1836e1fbd4c1SMat Martineau } 1837e1fbd4c1SMat Martineau } 1838e1fbd4c1SMat Martineau 1839d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan, 1840d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 1841d2a7ac5dSMat Martineau { 1842e1fbd4c1SMat Martineau struct sk_buff *skb; 1843e1fbd4c1SMat Martineau 1844e1fbd4c1SMat Martineau BT_DBG("chan %p, control %p", chan, control); 1845e1fbd4c1SMat Martineau 1846e1fbd4c1SMat Martineau if (control->poll) 1847e1fbd4c1SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 1848e1fbd4c1SMat Martineau 1849e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 1850e1fbd4c1SMat Martineau 1851e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 1852e1fbd4c1SMat Martineau return; 1853e1fbd4c1SMat Martineau 1854e1fbd4c1SMat Martineau if (chan->unacked_frames) { 1855e1fbd4c1SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 1856e1fbd4c1SMat Martineau if (bt_cb(skb)->control.txseq == control->reqseq || 1857e1fbd4c1SMat Martineau skb == chan->tx_send_head) 1858e1fbd4c1SMat Martineau break; 1859e1fbd4c1SMat Martineau } 1860e1fbd4c1SMat Martineau 1861e1fbd4c1SMat Martineau skb_queue_walk_from(&chan->tx_q, skb) { 1862e1fbd4c1SMat Martineau if (skb == chan->tx_send_head) 1863e1fbd4c1SMat Martineau break; 1864e1fbd4c1SMat Martineau 1865e1fbd4c1SMat Martineau l2cap_seq_list_append(&chan->retrans_list, 1866e1fbd4c1SMat Martineau bt_cb(skb)->control.txseq); 1867e1fbd4c1SMat Martineau } 1868e1fbd4c1SMat Martineau 1869e1fbd4c1SMat Martineau l2cap_ertm_resend(chan); 1870e1fbd4c1SMat Martineau } 1871d2a7ac5dSMat Martineau } 1872d2a7ac5dSMat Martineau 1873b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan) 1874b17e73bbSSzymon Janc { 18750a0aba42SMat Martineau struct l2cap_ctrl control; 18760a0aba42SMat Martineau u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq, 18770a0aba42SMat Martineau chan->last_acked_seq); 18780a0aba42SMat Martineau int threshold; 18790a0aba42SMat Martineau 18800a0aba42SMat Martineau BT_DBG("chan %p last_acked_seq %d buffer_seq %d", 18810a0aba42SMat Martineau chan, chan->last_acked_seq, chan->buffer_seq); 18820a0aba42SMat Martineau 18830a0aba42SMat Martineau memset(&control, 0, sizeof(control)); 18840a0aba42SMat Martineau control.sframe = 1; 18850a0aba42SMat Martineau 18860a0aba42SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 18870a0aba42SMat Martineau chan->rx_state == L2CAP_RX_STATE_RECV) { 1888b17e73bbSSzymon Janc __clear_ack_timer(chan); 18890a0aba42SMat Martineau control.super = L2CAP_SUPER_RNR; 18900a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 18910a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 18920a0aba42SMat Martineau } else { 18930a0aba42SMat Martineau if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) { 18940a0aba42SMat Martineau l2cap_ertm_send(chan); 18950a0aba42SMat Martineau /* If any i-frames were sent, they included an ack */ 18960a0aba42SMat Martineau if (chan->buffer_seq == chan->last_acked_seq) 18970a0aba42SMat Martineau frames_to_ack = 0; 18980a0aba42SMat Martineau } 18990a0aba42SMat Martineau 19000a0aba42SMat Martineau /* Ack now if the tx window is 3/4ths full. 19010a0aba42SMat Martineau * Calculate without mul or div 19020a0aba42SMat Martineau */ 19030a0aba42SMat Martineau threshold = chan->tx_win; 19040a0aba42SMat Martineau threshold += threshold << 1; 19050a0aba42SMat Martineau threshold >>= 2; 19060a0aba42SMat Martineau 19070a0aba42SMat Martineau BT_DBG("frames_to_ack %d, threshold %d", (int)frames_to_ack, 19080a0aba42SMat Martineau threshold); 19090a0aba42SMat Martineau 19100a0aba42SMat Martineau if (frames_to_ack >= threshold) { 19110a0aba42SMat Martineau __clear_ack_timer(chan); 19120a0aba42SMat Martineau control.super = L2CAP_SUPER_RR; 19130a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 19140a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 19150a0aba42SMat Martineau frames_to_ack = 0; 19160a0aba42SMat Martineau } 19170a0aba42SMat Martineau 19180a0aba42SMat Martineau if (frames_to_ack) 19190a0aba42SMat Martineau __set_ack_timer(chan); 19200a0aba42SMat Martineau } 1921b17e73bbSSzymon Janc } 1922b17e73bbSSzymon Janc 192304124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, 192404124681SGustavo F. Padovan struct msghdr *msg, int len, 192504124681SGustavo F. Padovan int count, struct sk_buff *skb) 19260a708f8fSGustavo F. Padovan { 19270952a57aSAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 19280a708f8fSGustavo F. Padovan struct sk_buff **frag; 192990338947SGustavo Padovan int sent = 0; 19300a708f8fSGustavo F. Padovan 19310a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) 19320a708f8fSGustavo F. Padovan return -EFAULT; 19330a708f8fSGustavo F. Padovan 19340a708f8fSGustavo F. Padovan sent += count; 19350a708f8fSGustavo F. Padovan len -= count; 19360a708f8fSGustavo F. Padovan 19370a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 19380a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 19390a708f8fSGustavo F. Padovan while (len) { 1940fbe00700SGustavo Padovan struct sk_buff *tmp; 1941fbe00700SGustavo Padovan 19420a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 19430a708f8fSGustavo F. Padovan 1944fbe00700SGustavo Padovan tmp = chan->ops->alloc_skb(chan, count, 194590338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 1946fbe00700SGustavo Padovan if (IS_ERR(tmp)) 1947fbe00700SGustavo Padovan return PTR_ERR(tmp); 19482f7719ceSAndrei Emeltchenko 1949fbe00700SGustavo Padovan *frag = tmp; 1950fbe00700SGustavo Padovan 19510a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) 19520a708f8fSGustavo F. Padovan return -EFAULT; 19530a708f8fSGustavo F. Padovan 19545e59b791SLuiz Augusto von Dentz (*frag)->priority = skb->priority; 19555e59b791SLuiz Augusto von Dentz 19560a708f8fSGustavo F. Padovan sent += count; 19570a708f8fSGustavo F. Padovan len -= count; 19580a708f8fSGustavo F. Padovan 19592d0ed3d5SGustavo Padovan skb->len += (*frag)->len; 19602d0ed3d5SGustavo Padovan skb->data_len += (*frag)->len; 19612d0ed3d5SGustavo Padovan 19620a708f8fSGustavo F. Padovan frag = &(*frag)->next; 19630a708f8fSGustavo F. Padovan } 19640a708f8fSGustavo F. Padovan 19650a708f8fSGustavo F. Padovan return sent; 19660a708f8fSGustavo F. Padovan } 19670a708f8fSGustavo F. Padovan 19685e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, 19695e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 19705e59b791SLuiz Augusto von Dentz u32 priority) 19710a708f8fSGustavo F. Padovan { 19728c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 19730a708f8fSGustavo F. Padovan struct sk_buff *skb; 197403a51213SAndrei Emeltchenko int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; 19750a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 19760a708f8fSGustavo F. Padovan 19776d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d priority %u", chan, (int)len, priority); 19780a708f8fSGustavo F. Padovan 19790a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 19802f7719ceSAndrei Emeltchenko 19812f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 198290338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 198390338947SGustavo Padovan if (IS_ERR(skb)) 198490338947SGustavo Padovan return skb; 19850a708f8fSGustavo F. Padovan 19865e59b791SLuiz Augusto von Dentz skb->priority = priority; 19875e59b791SLuiz Augusto von Dentz 19880a708f8fSGustavo F. Padovan /* Create L2CAP header */ 19890a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 1990fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 1991daf6a78cSAndrei Emeltchenko lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); 1992daf6a78cSAndrei Emeltchenko put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE)); 19930a708f8fSGustavo F. Padovan 19940952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 19950a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 19960a708f8fSGustavo F. Padovan kfree_skb(skb); 19970a708f8fSGustavo F. Padovan return ERR_PTR(err); 19980a708f8fSGustavo F. Padovan } 19990a708f8fSGustavo F. Padovan return skb; 20000a708f8fSGustavo F. Padovan } 20010a708f8fSGustavo F. Padovan 20025e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, 20035e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 20045e59b791SLuiz Augusto von Dentz u32 priority) 20050a708f8fSGustavo F. Padovan { 20068c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 20070a708f8fSGustavo F. Padovan struct sk_buff *skb; 2008f2ba7faeSGustavo Padovan int err, count; 20090a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 20100a708f8fSGustavo F. Padovan 20116d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d", chan, (int)len); 20120a708f8fSGustavo F. Padovan 2013f2ba7faeSGustavo Padovan count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); 20142f7719ceSAndrei Emeltchenko 2015f2ba7faeSGustavo Padovan skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE, 201690338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 201790338947SGustavo Padovan if (IS_ERR(skb)) 201890338947SGustavo Padovan return skb; 20190a708f8fSGustavo F. Padovan 20205e59b791SLuiz Augusto von Dentz skb->priority = priority; 20215e59b791SLuiz Augusto von Dentz 20220a708f8fSGustavo F. Padovan /* Create L2CAP header */ 20230a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2024fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 20256ff9b5efSGustavo Padovan lh->len = cpu_to_le16(len); 20260a708f8fSGustavo F. Padovan 20270952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 20280a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 20290a708f8fSGustavo F. Padovan kfree_skb(skb); 20300a708f8fSGustavo F. Padovan return ERR_PTR(err); 20310a708f8fSGustavo F. Padovan } 20320a708f8fSGustavo F. Padovan return skb; 20330a708f8fSGustavo F. Padovan } 20340a708f8fSGustavo F. Padovan 2035ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, 2036ab0ff76dSLuiz Augusto von Dentz struct msghdr *msg, size_t len, 203794122bbeSMat Martineau u16 sdulen) 20380a708f8fSGustavo F. Padovan { 20398c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 20400a708f8fSGustavo F. Padovan struct sk_buff *skb; 2041e4ca6d98SAndrei Emeltchenko int err, count, hlen; 20420a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 20430a708f8fSGustavo F. Padovan 20446d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d", chan, (int)len); 20450a708f8fSGustavo F. Padovan 20460a708f8fSGustavo F. Padovan if (!conn) 20470a708f8fSGustavo F. Padovan return ERR_PTR(-ENOTCONN); 20480a708f8fSGustavo F. Padovan 2049e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 2050e4ca6d98SAndrei Emeltchenko hlen = L2CAP_EXT_HDR_SIZE; 2051e4ca6d98SAndrei Emeltchenko else 2052e4ca6d98SAndrei Emeltchenko hlen = L2CAP_ENH_HDR_SIZE; 2053e4ca6d98SAndrei Emeltchenko 20540a708f8fSGustavo F. Padovan if (sdulen) 205503a51213SAndrei Emeltchenko hlen += L2CAP_SDULEN_SIZE; 20560a708f8fSGustavo F. Padovan 205747d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 205803a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 20590a708f8fSGustavo F. Padovan 20600a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 20612f7719ceSAndrei Emeltchenko 20622f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 206390338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 206490338947SGustavo Padovan if (IS_ERR(skb)) 206590338947SGustavo Padovan return skb; 20660a708f8fSGustavo F. Padovan 20670a708f8fSGustavo F. Padovan /* Create L2CAP header */ 20680a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2069fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 20700a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 207188843ab0SAndrei Emeltchenko 207218a48e76SMat Martineau /* Control header is populated later */ 207318a48e76SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 207418a48e76SMat Martineau put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 207518a48e76SMat Martineau else 207618a48e76SMat Martineau put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 207788843ab0SAndrei Emeltchenko 20780a708f8fSGustavo F. Padovan if (sdulen) 207903a51213SAndrei Emeltchenko put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 20800a708f8fSGustavo F. Padovan 20810952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 20820a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 20830a708f8fSGustavo F. Padovan kfree_skb(skb); 20840a708f8fSGustavo F. Padovan return ERR_PTR(err); 20850a708f8fSGustavo F. Padovan } 20860a708f8fSGustavo F. Padovan 208718a48e76SMat Martineau bt_cb(skb)->control.fcs = chan->fcs; 20883ce3514fSMat Martineau bt_cb(skb)->control.retries = 0; 20890a708f8fSGustavo F. Padovan return skb; 20900a708f8fSGustavo F. Padovan } 20910a708f8fSGustavo F. Padovan 209294122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan, 209394122bbeSMat Martineau struct sk_buff_head *seg_queue, 209494122bbeSMat Martineau struct msghdr *msg, size_t len) 20950a708f8fSGustavo F. Padovan { 20960a708f8fSGustavo F. Padovan struct sk_buff *skb; 209794122bbeSMat Martineau u16 sdu_len; 209894122bbeSMat Martineau size_t pdu_len; 209994122bbeSMat Martineau int err = 0; 210094122bbeSMat Martineau u8 sar; 21010a708f8fSGustavo F. Padovan 210294122bbeSMat Martineau BT_DBG("chan %p, msg %p, len %d", chan, msg, (int)len); 21030a708f8fSGustavo F. Padovan 210494122bbeSMat Martineau /* It is critical that ERTM PDUs fit in a single HCI fragment, 210594122bbeSMat Martineau * so fragmented skbs are not used. The HCI layer's handling 210694122bbeSMat Martineau * of fragmented skbs is not compatible with ERTM's queueing. 210794122bbeSMat Martineau */ 210894122bbeSMat Martineau 210994122bbeSMat Martineau /* PDU size is derived from the HCI MTU */ 211094122bbeSMat Martineau pdu_len = chan->conn->mtu; 211194122bbeSMat Martineau 211294122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); 211394122bbeSMat Martineau 211494122bbeSMat Martineau /* Adjust for largest possible L2CAP overhead. */ 211594122bbeSMat Martineau pdu_len -= L2CAP_EXT_HDR_SIZE + L2CAP_FCS_SIZE; 211694122bbeSMat Martineau 211794122bbeSMat Martineau /* Remote device may have requested smaller PDUs */ 211894122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, chan->remote_mps); 211994122bbeSMat Martineau 212094122bbeSMat Martineau if (len <= pdu_len) { 212194122bbeSMat Martineau sar = L2CAP_SAR_UNSEGMENTED; 212294122bbeSMat Martineau sdu_len = 0; 212394122bbeSMat Martineau pdu_len = len; 212494122bbeSMat Martineau } else { 212594122bbeSMat Martineau sar = L2CAP_SAR_START; 212694122bbeSMat Martineau sdu_len = len; 212794122bbeSMat Martineau pdu_len -= L2CAP_SDULEN_SIZE; 212894122bbeSMat Martineau } 21290a708f8fSGustavo F. Padovan 21300a708f8fSGustavo F. Padovan while (len > 0) { 213194122bbeSMat Martineau skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len); 21320a708f8fSGustavo F. Padovan 21330a708f8fSGustavo F. Padovan if (IS_ERR(skb)) { 213494122bbeSMat Martineau __skb_queue_purge(seg_queue); 21350a708f8fSGustavo F. Padovan return PTR_ERR(skb); 21360a708f8fSGustavo F. Padovan } 21370a708f8fSGustavo F. Padovan 213894122bbeSMat Martineau bt_cb(skb)->control.sar = sar; 213994122bbeSMat Martineau __skb_queue_tail(seg_queue, skb); 21400a708f8fSGustavo F. Padovan 214194122bbeSMat Martineau len -= pdu_len; 214294122bbeSMat Martineau if (sdu_len) { 214394122bbeSMat Martineau sdu_len = 0; 214494122bbeSMat Martineau pdu_len += L2CAP_SDULEN_SIZE; 214594122bbeSMat Martineau } 214694122bbeSMat Martineau 214794122bbeSMat Martineau if (len <= pdu_len) { 214894122bbeSMat Martineau sar = L2CAP_SAR_END; 214994122bbeSMat Martineau pdu_len = len; 215094122bbeSMat Martineau } else { 215194122bbeSMat Martineau sar = L2CAP_SAR_CONTINUE; 215294122bbeSMat Martineau } 215394122bbeSMat Martineau } 215494122bbeSMat Martineau 215594122bbeSMat Martineau return err; 21560a708f8fSGustavo F. Padovan } 21570a708f8fSGustavo F. Padovan 21585e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, 21595e59b791SLuiz Augusto von Dentz u32 priority) 21609a91a04aSGustavo F. Padovan { 21619a91a04aSGustavo F. Padovan struct sk_buff *skb; 21629a91a04aSGustavo F. Padovan int err; 216394122bbeSMat Martineau struct sk_buff_head seg_queue; 21649a91a04aSGustavo F. Padovan 21659a91a04aSGustavo F. Padovan /* Connectionless channel */ 2166715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { 21675e59b791SLuiz Augusto von Dentz skb = l2cap_create_connless_pdu(chan, msg, len, priority); 21689a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 21699a91a04aSGustavo F. Padovan return PTR_ERR(skb); 21709a91a04aSGustavo F. Padovan 21719a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 21729a91a04aSGustavo F. Padovan return len; 21739a91a04aSGustavo F. Padovan } 21749a91a04aSGustavo F. Padovan 21759a91a04aSGustavo F. Padovan switch (chan->mode) { 21769a91a04aSGustavo F. Padovan case L2CAP_MODE_BASIC: 21779a91a04aSGustavo F. Padovan /* Check outgoing MTU */ 21789a91a04aSGustavo F. Padovan if (len > chan->omtu) 21799a91a04aSGustavo F. Padovan return -EMSGSIZE; 21809a91a04aSGustavo F. Padovan 21819a91a04aSGustavo F. Padovan /* Create a basic PDU */ 21825e59b791SLuiz Augusto von Dentz skb = l2cap_create_basic_pdu(chan, msg, len, priority); 21839a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 21849a91a04aSGustavo F. Padovan return PTR_ERR(skb); 21859a91a04aSGustavo F. Padovan 21869a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 21879a91a04aSGustavo F. Padovan err = len; 21889a91a04aSGustavo F. Padovan break; 21899a91a04aSGustavo F. Padovan 21909a91a04aSGustavo F. Padovan case L2CAP_MODE_ERTM: 21919a91a04aSGustavo F. Padovan case L2CAP_MODE_STREAMING: 219294122bbeSMat Martineau /* Check outgoing MTU */ 219394122bbeSMat Martineau if (len > chan->omtu) { 219494122bbeSMat Martineau err = -EMSGSIZE; 21959a91a04aSGustavo F. Padovan break; 21969a91a04aSGustavo F. Padovan } 21979a91a04aSGustavo F. Padovan 219894122bbeSMat Martineau __skb_queue_head_init(&seg_queue); 219994122bbeSMat Martineau 220094122bbeSMat Martineau /* Do segmentation before calling in to the state machine, 220194122bbeSMat Martineau * since it's possible to block while waiting for memory 220294122bbeSMat Martineau * allocation. 220394122bbeSMat Martineau */ 220494122bbeSMat Martineau err = l2cap_segment_sdu(chan, &seg_queue, msg, len); 220594122bbeSMat Martineau 220694122bbeSMat Martineau /* The channel could have been closed while segmenting, 220794122bbeSMat Martineau * check that it is still connected. 220894122bbeSMat Martineau */ 220994122bbeSMat Martineau if (chan->state != BT_CONNECTED) { 221094122bbeSMat Martineau __skb_queue_purge(&seg_queue); 221194122bbeSMat Martineau err = -ENOTCONN; 22129a91a04aSGustavo F. Padovan } 22139a91a04aSGustavo F. Padovan 221494122bbeSMat Martineau if (err) 221594122bbeSMat Martineau break; 221694122bbeSMat Martineau 22173733937dSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) 2218608bcc6dSMat Martineau err = l2cap_tx(chan, 0, &seg_queue, 2219608bcc6dSMat Martineau L2CAP_EV_DATA_REQUEST); 22203733937dSMat Martineau else 22213733937dSMat Martineau err = l2cap_streaming_send(chan, &seg_queue); 222294122bbeSMat Martineau 2223608bcc6dSMat Martineau if (!err) 22249a91a04aSGustavo F. Padovan err = len; 22259a91a04aSGustavo F. Padovan 222694122bbeSMat Martineau /* If the skbs were not queued for sending, they'll still be in 222794122bbeSMat Martineau * seg_queue and need to be purged. 222894122bbeSMat Martineau */ 222994122bbeSMat Martineau __skb_queue_purge(&seg_queue); 22309a91a04aSGustavo F. Padovan break; 22319a91a04aSGustavo F. Padovan 22329a91a04aSGustavo F. Padovan default: 22339a91a04aSGustavo F. Padovan BT_DBG("bad state %1.1x", chan->mode); 22349a91a04aSGustavo F. Padovan err = -EBADFD; 22359a91a04aSGustavo F. Padovan } 22369a91a04aSGustavo F. Padovan 22379a91a04aSGustavo F. Padovan return err; 22389a91a04aSGustavo F. Padovan } 22399a91a04aSGustavo F. Padovan 2240d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq) 2241d2a7ac5dSMat Martineau { 2242bed68bdeSMat Martineau struct l2cap_ctrl control; 2243bed68bdeSMat Martineau u16 seq; 2244bed68bdeSMat Martineau 2245bed68bdeSMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 2246bed68bdeSMat Martineau 2247bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2248bed68bdeSMat Martineau control.sframe = 1; 2249bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2250bed68bdeSMat Martineau 2251bed68bdeSMat Martineau for (seq = chan->expected_tx_seq; seq != txseq; 2252bed68bdeSMat Martineau seq = __next_seq(chan, seq)) { 2253bed68bdeSMat Martineau if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) { 2254bed68bdeSMat Martineau control.reqseq = seq; 2255bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2256bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2257bed68bdeSMat Martineau } 2258bed68bdeSMat Martineau } 2259bed68bdeSMat Martineau 2260bed68bdeSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 2261d2a7ac5dSMat Martineau } 2262d2a7ac5dSMat Martineau 2263d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan) 2264d2a7ac5dSMat Martineau { 2265bed68bdeSMat Martineau struct l2cap_ctrl control; 2266bed68bdeSMat Martineau 2267bed68bdeSMat Martineau BT_DBG("chan %p", chan); 2268bed68bdeSMat Martineau 2269bed68bdeSMat Martineau if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR) 2270bed68bdeSMat Martineau return; 2271bed68bdeSMat Martineau 2272bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2273bed68bdeSMat Martineau control.sframe = 1; 2274bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2275bed68bdeSMat Martineau control.reqseq = chan->srej_list.tail; 2276bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2277d2a7ac5dSMat Martineau } 2278d2a7ac5dSMat Martineau 2279d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq) 2280d2a7ac5dSMat Martineau { 2281bed68bdeSMat Martineau struct l2cap_ctrl control; 2282bed68bdeSMat Martineau u16 initial_head; 2283bed68bdeSMat Martineau u16 seq; 2284bed68bdeSMat Martineau 2285bed68bdeSMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 2286bed68bdeSMat Martineau 2287bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2288bed68bdeSMat Martineau control.sframe = 1; 2289bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2290bed68bdeSMat Martineau 2291bed68bdeSMat Martineau /* Capture initial list head to allow only one pass through the list. */ 2292bed68bdeSMat Martineau initial_head = chan->srej_list.head; 2293bed68bdeSMat Martineau 2294bed68bdeSMat Martineau do { 2295bed68bdeSMat Martineau seq = l2cap_seq_list_pop(&chan->srej_list); 2296bed68bdeSMat Martineau if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR) 2297bed68bdeSMat Martineau break; 2298bed68bdeSMat Martineau 2299bed68bdeSMat Martineau control.reqseq = seq; 2300bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2301bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2302bed68bdeSMat Martineau } while (chan->srej_list.head != initial_head); 2303d2a7ac5dSMat Martineau } 2304d2a7ac5dSMat Martineau 2305608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq) 2306608bcc6dSMat Martineau { 2307608bcc6dSMat Martineau struct sk_buff *acked_skb; 2308608bcc6dSMat Martineau u16 ackseq; 2309608bcc6dSMat Martineau 2310608bcc6dSMat Martineau BT_DBG("chan %p, reqseq %d", chan, reqseq); 2311608bcc6dSMat Martineau 2312608bcc6dSMat Martineau if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq) 2313608bcc6dSMat Martineau return; 2314608bcc6dSMat Martineau 2315608bcc6dSMat Martineau BT_DBG("expected_ack_seq %d, unacked_frames %d", 2316608bcc6dSMat Martineau chan->expected_ack_seq, chan->unacked_frames); 2317608bcc6dSMat Martineau 2318608bcc6dSMat Martineau for (ackseq = chan->expected_ack_seq; ackseq != reqseq; 2319608bcc6dSMat Martineau ackseq = __next_seq(chan, ackseq)) { 2320608bcc6dSMat Martineau 2321608bcc6dSMat Martineau acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq); 2322608bcc6dSMat Martineau if (acked_skb) { 2323608bcc6dSMat Martineau skb_unlink(acked_skb, &chan->tx_q); 2324608bcc6dSMat Martineau kfree_skb(acked_skb); 2325608bcc6dSMat Martineau chan->unacked_frames--; 2326608bcc6dSMat Martineau } 2327608bcc6dSMat Martineau } 2328608bcc6dSMat Martineau 2329608bcc6dSMat Martineau chan->expected_ack_seq = reqseq; 2330608bcc6dSMat Martineau 2331608bcc6dSMat Martineau if (chan->unacked_frames == 0) 2332608bcc6dSMat Martineau __clear_retrans_timer(chan); 2333608bcc6dSMat Martineau 2334608bcc6dSMat Martineau BT_DBG("unacked_frames %d", (int) chan->unacked_frames); 2335608bcc6dSMat Martineau } 2336608bcc6dSMat Martineau 2337608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan) 2338608bcc6dSMat Martineau { 2339608bcc6dSMat Martineau BT_DBG("chan %p", chan); 2340608bcc6dSMat Martineau 2341608bcc6dSMat Martineau chan->expected_tx_seq = chan->buffer_seq; 2342608bcc6dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 2343608bcc6dSMat Martineau skb_queue_purge(&chan->srej_q); 2344608bcc6dSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2345608bcc6dSMat Martineau } 2346608bcc6dSMat Martineau 2347608bcc6dSMat Martineau static int l2cap_tx_state_xmit(struct l2cap_chan *chan, 2348608bcc6dSMat Martineau struct l2cap_ctrl *control, 2349608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2350608bcc6dSMat Martineau { 2351608bcc6dSMat Martineau int err = 0; 2352608bcc6dSMat Martineau 2353608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2354608bcc6dSMat Martineau event); 2355608bcc6dSMat Martineau 2356608bcc6dSMat Martineau switch (event) { 2357608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2358608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2359608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2360608bcc6dSMat Martineau 2361608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2362608bcc6dSMat Martineau l2cap_ertm_send(chan); 2363608bcc6dSMat Martineau break; 2364608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2365608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2366608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2367608bcc6dSMat Martineau 2368608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2369608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2370608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2371608bcc6dSMat Martineau */ 2372608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2373608bcc6dSMat Martineau } 2374608bcc6dSMat Martineau 2375608bcc6dSMat Martineau l2cap_send_ack(chan); 2376608bcc6dSMat Martineau 2377608bcc6dSMat Martineau break; 2378608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2379608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2380608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2381608bcc6dSMat Martineau 2382608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2383608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2384608bcc6dSMat Martineau 2385608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2386608bcc6dSMat Martineau local_control.sframe = 1; 2387608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2388608bcc6dSMat Martineau local_control.poll = 1; 2389608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2390a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2391608bcc6dSMat Martineau 2392608bcc6dSMat Martineau chan->retry_count = 1; 2393608bcc6dSMat Martineau __set_monitor_timer(chan); 2394608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2395608bcc6dSMat Martineau } 2396608bcc6dSMat Martineau break; 2397608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2398608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2399608bcc6dSMat Martineau break; 2400608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2401608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2402608bcc6dSMat Martineau chan->retry_count = 1; 2403608bcc6dSMat Martineau __set_monitor_timer(chan); 2404608bcc6dSMat Martineau __clear_ack_timer(chan); 2405608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2406608bcc6dSMat Martineau break; 2407608bcc6dSMat Martineau case L2CAP_EV_RETRANS_TO: 2408608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2409608bcc6dSMat Martineau chan->retry_count = 1; 2410608bcc6dSMat Martineau __set_monitor_timer(chan); 2411608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2412608bcc6dSMat Martineau break; 2413608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2414608bcc6dSMat Martineau /* Nothing to process */ 2415608bcc6dSMat Martineau break; 2416608bcc6dSMat Martineau default: 2417608bcc6dSMat Martineau break; 2418608bcc6dSMat Martineau } 2419608bcc6dSMat Martineau 2420608bcc6dSMat Martineau return err; 2421608bcc6dSMat Martineau } 2422608bcc6dSMat Martineau 2423608bcc6dSMat Martineau static int l2cap_tx_state_wait_f(struct l2cap_chan *chan, 2424608bcc6dSMat Martineau struct l2cap_ctrl *control, 2425608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2426608bcc6dSMat Martineau { 2427608bcc6dSMat Martineau int err = 0; 2428608bcc6dSMat Martineau 2429608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2430608bcc6dSMat Martineau event); 2431608bcc6dSMat Martineau 2432608bcc6dSMat Martineau switch (event) { 2433608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2434608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2435608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2436608bcc6dSMat Martineau /* Queue data, but don't send. */ 2437608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2438608bcc6dSMat Martineau break; 2439608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2440608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2441608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2442608bcc6dSMat Martineau 2443608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2444608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2445608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2446608bcc6dSMat Martineau */ 2447608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2448608bcc6dSMat Martineau } 2449608bcc6dSMat Martineau 2450608bcc6dSMat Martineau l2cap_send_ack(chan); 2451608bcc6dSMat Martineau 2452608bcc6dSMat Martineau break; 2453608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2454608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2455608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2456608bcc6dSMat Martineau 2457608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2458608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2459608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2460608bcc6dSMat Martineau local_control.sframe = 1; 2461608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2462608bcc6dSMat Martineau local_control.poll = 1; 2463608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2464a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2465608bcc6dSMat Martineau 2466608bcc6dSMat Martineau chan->retry_count = 1; 2467608bcc6dSMat Martineau __set_monitor_timer(chan); 2468608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2469608bcc6dSMat Martineau } 2470608bcc6dSMat Martineau break; 2471608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2472608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2473608bcc6dSMat Martineau 2474608bcc6dSMat Martineau /* Fall through */ 2475608bcc6dSMat Martineau 2476608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2477608bcc6dSMat Martineau if (control && control->final) { 2478608bcc6dSMat Martineau __clear_monitor_timer(chan); 2479608bcc6dSMat Martineau if (chan->unacked_frames > 0) 2480608bcc6dSMat Martineau __set_retrans_timer(chan); 2481608bcc6dSMat Martineau chan->retry_count = 0; 2482608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 2483608bcc6dSMat Martineau BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state); 2484608bcc6dSMat Martineau } 2485608bcc6dSMat Martineau break; 2486608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2487608bcc6dSMat Martineau /* Ignore */ 2488608bcc6dSMat Martineau break; 2489608bcc6dSMat Martineau case L2CAP_EV_MONITOR_TO: 2490608bcc6dSMat Martineau if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) { 2491608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2492608bcc6dSMat Martineau __set_monitor_timer(chan); 2493608bcc6dSMat Martineau chan->retry_count++; 2494608bcc6dSMat Martineau } else { 2495608bcc6dSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); 2496608bcc6dSMat Martineau } 2497608bcc6dSMat Martineau break; 2498608bcc6dSMat Martineau default: 2499608bcc6dSMat Martineau break; 2500608bcc6dSMat Martineau } 2501608bcc6dSMat Martineau 2502608bcc6dSMat Martineau return err; 2503608bcc6dSMat Martineau } 2504608bcc6dSMat Martineau 2505608bcc6dSMat Martineau static int l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 2506608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2507608bcc6dSMat Martineau { 2508608bcc6dSMat Martineau int err = 0; 2509608bcc6dSMat Martineau 2510608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d, state %d", 2511608bcc6dSMat Martineau chan, control, skbs, event, chan->tx_state); 2512608bcc6dSMat Martineau 2513608bcc6dSMat Martineau switch (chan->tx_state) { 2514608bcc6dSMat Martineau case L2CAP_TX_STATE_XMIT: 2515608bcc6dSMat Martineau err = l2cap_tx_state_xmit(chan, control, skbs, event); 2516608bcc6dSMat Martineau break; 2517608bcc6dSMat Martineau case L2CAP_TX_STATE_WAIT_F: 2518608bcc6dSMat Martineau err = l2cap_tx_state_wait_f(chan, control, skbs, event); 2519608bcc6dSMat Martineau break; 2520608bcc6dSMat Martineau default: 2521608bcc6dSMat Martineau /* Ignore event */ 2522608bcc6dSMat Martineau break; 2523608bcc6dSMat Martineau } 2524608bcc6dSMat Martineau 2525608bcc6dSMat Martineau return err; 2526608bcc6dSMat Martineau } 2527608bcc6dSMat Martineau 25284b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan, 25294b51dae9SMat Martineau struct l2cap_ctrl *control) 25304b51dae9SMat Martineau { 25314b51dae9SMat Martineau BT_DBG("chan %p, control %p", chan, control); 25324b51dae9SMat Martineau l2cap_tx(chan, control, 0, L2CAP_EV_RECV_REQSEQ_AND_FBIT); 25334b51dae9SMat Martineau } 25344b51dae9SMat Martineau 25350a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */ 25360a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 25370a708f8fSGustavo F. Padovan { 25380a708f8fSGustavo F. Padovan struct sk_buff *nskb; 253948454079SGustavo F. Padovan struct l2cap_chan *chan; 25400a708f8fSGustavo F. Padovan 25410a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 25420a708f8fSGustavo F. Padovan 25433df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 25443d57dc68SGustavo F. Padovan 25453df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 254648454079SGustavo F. Padovan struct sock *sk = chan->sk; 2547715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW) 25480a708f8fSGustavo F. Padovan continue; 25490a708f8fSGustavo F. Padovan 25500a708f8fSGustavo F. Padovan /* Don't send frame to the socket it came from */ 25510a708f8fSGustavo F. Padovan if (skb->sk == sk) 25520a708f8fSGustavo F. Padovan continue; 25530a708f8fSGustavo F. Padovan nskb = skb_clone(skb, GFP_ATOMIC); 25540a708f8fSGustavo F. Padovan if (!nskb) 25550a708f8fSGustavo F. Padovan continue; 25560a708f8fSGustavo F. Padovan 255723070494SGustavo F. Padovan if (chan->ops->recv(chan->data, nskb)) 25580a708f8fSGustavo F. Padovan kfree_skb(nskb); 25590a708f8fSGustavo F. Padovan } 25603d57dc68SGustavo F. Padovan 25613df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 25620a708f8fSGustavo F. Padovan } 25630a708f8fSGustavo F. Padovan 25640a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */ 25650a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 25660a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data) 25670a708f8fSGustavo F. Padovan { 25680a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag; 25690a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd; 25700a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 25710a708f8fSGustavo F. Padovan int len, count; 25720a708f8fSGustavo F. Padovan 25730a708f8fSGustavo F. Padovan BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d", 25740a708f8fSGustavo F. Padovan conn, code, ident, dlen); 25750a708f8fSGustavo F. Padovan 25760a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; 25770a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 25780a708f8fSGustavo F. Padovan 25790a708f8fSGustavo F. Padovan skb = bt_skb_alloc(count, GFP_ATOMIC); 25800a708f8fSGustavo F. Padovan if (!skb) 25810a708f8fSGustavo F. Padovan return NULL; 25820a708f8fSGustavo F. Padovan 25830a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 25840a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); 25853300d9a9SClaudio Takahasi 25863300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 25873300d9a9SClaudio Takahasi lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING); 25883300d9a9SClaudio Takahasi else 25890a708f8fSGustavo F. Padovan lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING); 25900a708f8fSGustavo F. Padovan 25910a708f8fSGustavo F. Padovan cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); 25920a708f8fSGustavo F. Padovan cmd->code = code; 25930a708f8fSGustavo F. Padovan cmd->ident = ident; 25940a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen); 25950a708f8fSGustavo F. Padovan 25960a708f8fSGustavo F. Padovan if (dlen) { 25970a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE; 25980a708f8fSGustavo F. Padovan memcpy(skb_put(skb, count), data, count); 25990a708f8fSGustavo F. Padovan data += count; 26000a708f8fSGustavo F. Padovan } 26010a708f8fSGustavo F. Padovan 26020a708f8fSGustavo F. Padovan len -= skb->len; 26030a708f8fSGustavo F. Padovan 26040a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 26050a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 26060a708f8fSGustavo F. Padovan while (len) { 26070a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 26080a708f8fSGustavo F. Padovan 26090a708f8fSGustavo F. Padovan *frag = bt_skb_alloc(count, GFP_ATOMIC); 26100a708f8fSGustavo F. Padovan if (!*frag) 26110a708f8fSGustavo F. Padovan goto fail; 26120a708f8fSGustavo F. Padovan 26130a708f8fSGustavo F. Padovan memcpy(skb_put(*frag, count), data, count); 26140a708f8fSGustavo F. Padovan 26150a708f8fSGustavo F. Padovan len -= count; 26160a708f8fSGustavo F. Padovan data += count; 26170a708f8fSGustavo F. Padovan 26180a708f8fSGustavo F. Padovan frag = &(*frag)->next; 26190a708f8fSGustavo F. Padovan } 26200a708f8fSGustavo F. Padovan 26210a708f8fSGustavo F. Padovan return skb; 26220a708f8fSGustavo F. Padovan 26230a708f8fSGustavo F. Padovan fail: 26240a708f8fSGustavo F. Padovan kfree_skb(skb); 26250a708f8fSGustavo F. Padovan return NULL; 26260a708f8fSGustavo F. Padovan } 26270a708f8fSGustavo F. Padovan 26280a708f8fSGustavo F. Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val) 26290a708f8fSGustavo F. Padovan { 26300a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 26310a708f8fSGustavo F. Padovan int len; 26320a708f8fSGustavo F. Padovan 26330a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len; 26340a708f8fSGustavo F. Padovan *ptr += len; 26350a708f8fSGustavo F. Padovan 26360a708f8fSGustavo F. Padovan *type = opt->type; 26370a708f8fSGustavo F. Padovan *olen = opt->len; 26380a708f8fSGustavo F. Padovan 26390a708f8fSGustavo F. Padovan switch (opt->len) { 26400a708f8fSGustavo F. Padovan case 1: 26410a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val); 26420a708f8fSGustavo F. Padovan break; 26430a708f8fSGustavo F. Padovan 26440a708f8fSGustavo F. Padovan case 2: 26450a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val); 26460a708f8fSGustavo F. Padovan break; 26470a708f8fSGustavo F. Padovan 26480a708f8fSGustavo F. Padovan case 4: 26490a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val); 26500a708f8fSGustavo F. Padovan break; 26510a708f8fSGustavo F. Padovan 26520a708f8fSGustavo F. Padovan default: 26530a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val; 26540a708f8fSGustavo F. Padovan break; 26550a708f8fSGustavo F. Padovan } 26560a708f8fSGustavo F. Padovan 26570a708f8fSGustavo F. Padovan BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val); 26580a708f8fSGustavo F. Padovan return len; 26590a708f8fSGustavo F. Padovan } 26600a708f8fSGustavo F. Padovan 26610a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) 26620a708f8fSGustavo F. Padovan { 26630a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 26640a708f8fSGustavo F. Padovan 26650a708f8fSGustavo F. Padovan BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val); 26660a708f8fSGustavo F. Padovan 26670a708f8fSGustavo F. Padovan opt->type = type; 26680a708f8fSGustavo F. Padovan opt->len = len; 26690a708f8fSGustavo F. Padovan 26700a708f8fSGustavo F. Padovan switch (len) { 26710a708f8fSGustavo F. Padovan case 1: 26720a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val; 26730a708f8fSGustavo F. Padovan break; 26740a708f8fSGustavo F. Padovan 26750a708f8fSGustavo F. Padovan case 2: 26760a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val); 26770a708f8fSGustavo F. Padovan break; 26780a708f8fSGustavo F. Padovan 26790a708f8fSGustavo F. Padovan case 4: 26800a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val); 26810a708f8fSGustavo F. Padovan break; 26820a708f8fSGustavo F. Padovan 26830a708f8fSGustavo F. Padovan default: 26840a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len); 26850a708f8fSGustavo F. Padovan break; 26860a708f8fSGustavo F. Padovan } 26870a708f8fSGustavo F. Padovan 26880a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len; 26890a708f8fSGustavo F. Padovan } 26900a708f8fSGustavo F. Padovan 2691f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) 2692f89cef09SAndrei Emeltchenko { 2693f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs; 2694f89cef09SAndrei Emeltchenko 2695f89cef09SAndrei Emeltchenko switch (chan->mode) { 2696f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM: 2697f89cef09SAndrei Emeltchenko efs.id = chan->local_id; 2698f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype; 2699f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 2700f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 2701f89cef09SAndrei Emeltchenko efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); 2702f89cef09SAndrei Emeltchenko efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO); 2703f89cef09SAndrei Emeltchenko break; 2704f89cef09SAndrei Emeltchenko 2705f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING: 2706f89cef09SAndrei Emeltchenko efs.id = 1; 2707f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT; 2708f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 2709f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 2710f89cef09SAndrei Emeltchenko efs.acc_lat = 0; 2711f89cef09SAndrei Emeltchenko efs.flush_to = 0; 2712f89cef09SAndrei Emeltchenko break; 2713f89cef09SAndrei Emeltchenko 2714f89cef09SAndrei Emeltchenko default: 2715f89cef09SAndrei Emeltchenko return; 2716f89cef09SAndrei Emeltchenko } 2717f89cef09SAndrei Emeltchenko 2718f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), 2719f89cef09SAndrei Emeltchenko (unsigned long) &efs); 2720f89cef09SAndrei Emeltchenko } 2721f89cef09SAndrei Emeltchenko 2722721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work) 27230a708f8fSGustavo F. Padovan { 2724721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 2725721c4181SGustavo F. Padovan ack_timer.work); 27260a708f8fSGustavo F. Padovan 27272fb9b3d4SGustavo F. Padovan BT_DBG("chan %p", chan); 27282fb9b3d4SGustavo F. Padovan 27296be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 27306be36555SAndrei Emeltchenko 27310a0aba42SMat Martineau l2cap_send_ack(chan); 27326be36555SAndrei Emeltchenko 27336be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 273409bfb2eeSSzymon Janc 273509bfb2eeSSzymon Janc l2cap_chan_put(chan); 27360a708f8fSGustavo F. Padovan } 27370a708f8fSGustavo F. Padovan 27383c588192SMat Martineau static inline int l2cap_ertm_init(struct l2cap_chan *chan) 27390a708f8fSGustavo F. Padovan { 27403c588192SMat Martineau int err; 27413c588192SMat Martineau 2742105bdf9eSMat Martineau chan->next_tx_seq = 0; 2743105bdf9eSMat Martineau chan->expected_tx_seq = 0; 274442e5c802SGustavo F. Padovan chan->expected_ack_seq = 0; 27456a026610SGustavo F. Padovan chan->unacked_frames = 0; 274642e5c802SGustavo F. Padovan chan->buffer_seq = 0; 27476a026610SGustavo F. Padovan chan->frames_sent = 0; 2748105bdf9eSMat Martineau chan->last_acked_seq = 0; 2749105bdf9eSMat Martineau chan->sdu = NULL; 2750105bdf9eSMat Martineau chan->sdu_last_frag = NULL; 2751105bdf9eSMat Martineau chan->sdu_len = 0; 2752105bdf9eSMat Martineau 2753d34c34fbSMat Martineau skb_queue_head_init(&chan->tx_q); 2754d34c34fbSMat Martineau 2755105bdf9eSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 2756105bdf9eSMat Martineau return 0; 2757105bdf9eSMat Martineau 2758105bdf9eSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2759105bdf9eSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 27600a708f8fSGustavo F. Padovan 2761721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout); 2762721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout); 2763721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout); 27640a708f8fSGustavo F. Padovan 2765f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q); 27660a708f8fSGustavo F. Padovan 27673c588192SMat Martineau err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win); 27683c588192SMat Martineau if (err < 0) 27693c588192SMat Martineau return err; 27703c588192SMat Martineau 27719dc9affcSMat Martineau err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win); 27729dc9affcSMat Martineau if (err < 0) 27739dc9affcSMat Martineau l2cap_seq_list_free(&chan->srej_list); 27749dc9affcSMat Martineau 27759dc9affcSMat Martineau return err; 27760a708f8fSGustavo F. Padovan } 27770a708f8fSGustavo F. Padovan 27780a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) 27790a708f8fSGustavo F. Padovan { 27800a708f8fSGustavo F. Padovan switch (mode) { 27810a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 27820a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 27830a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask)) 27840a708f8fSGustavo F. Padovan return mode; 27850a708f8fSGustavo F. Padovan /* fall through */ 27860a708f8fSGustavo F. Padovan default: 27870a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC; 27880a708f8fSGustavo F. Padovan } 27890a708f8fSGustavo F. Padovan } 27900a708f8fSGustavo F. Padovan 27916327eb98SAndrei Emeltchenko static inline bool __l2cap_ews_supported(struct l2cap_chan *chan) 27926327eb98SAndrei Emeltchenko { 27936327eb98SAndrei Emeltchenko return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW; 27946327eb98SAndrei Emeltchenko } 27956327eb98SAndrei Emeltchenko 2796f89cef09SAndrei Emeltchenko static inline bool __l2cap_efs_supported(struct l2cap_chan *chan) 2797f89cef09SAndrei Emeltchenko { 2798f89cef09SAndrei Emeltchenko return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW; 2799f89cef09SAndrei Emeltchenko } 2800f89cef09SAndrei Emeltchenko 28016327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan) 28026327eb98SAndrei Emeltchenko { 28036327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && 2804836be934SAndrei Emeltchenko __l2cap_ews_supported(chan)) { 28056327eb98SAndrei Emeltchenko /* use extended control field */ 28066327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 2807836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 2808836be934SAndrei Emeltchenko } else { 28096327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win, 28106327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 2811836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 2812836be934SAndrei Emeltchenko } 28136327eb98SAndrei Emeltchenko } 28146327eb98SAndrei Emeltchenko 2815710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) 28160a708f8fSGustavo F. Padovan { 28170a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 28180c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode }; 28190a708f8fSGustavo F. Padovan void *ptr = req->data; 2820c8f79162SAndrei Emeltchenko u16 size; 28210a708f8fSGustavo F. Padovan 282249208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 28230a708f8fSGustavo F. Padovan 282473ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp) 28250a708f8fSGustavo F. Padovan goto done; 28260a708f8fSGustavo F. Padovan 28270c1bc5c6SGustavo F. Padovan switch (chan->mode) { 28280a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 28290a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 2830c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) 28310a708f8fSGustavo F. Padovan break; 28320a708f8fSGustavo F. Padovan 2833f89cef09SAndrei Emeltchenko if (__l2cap_efs_supported(chan)) 2834f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 2835f89cef09SAndrei Emeltchenko 28360a708f8fSGustavo F. Padovan /* fall through */ 28370a708f8fSGustavo F. Padovan default: 28388c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); 28390a708f8fSGustavo F. Padovan break; 28400a708f8fSGustavo F. Padovan } 28410a708f8fSGustavo F. Padovan 28420a708f8fSGustavo F. Padovan done: 28430c1bc5c6SGustavo F. Padovan if (chan->imtu != L2CAP_DEFAULT_MTU) 28440c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 28450a708f8fSGustavo F. Padovan 28460c1bc5c6SGustavo F. Padovan switch (chan->mode) { 28470a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 28488c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && 28498c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) 28500a708f8fSGustavo F. Padovan break; 28510a708f8fSGustavo F. Padovan 28520a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC; 28530a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 28540a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 28550a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 28560a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 28570a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0; 28580a708f8fSGustavo F. Padovan 28590a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 28600a708f8fSGustavo F. Padovan (unsigned long) &rfc); 28610a708f8fSGustavo F. Padovan break; 28620a708f8fSGustavo F. Padovan 28630a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 28640a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM; 286547d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx; 28660a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 28670a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 2868c8f79162SAndrei Emeltchenko 2869c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 2870c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2871c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2872c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2873c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 28740a708f8fSGustavo F. Padovan 28756327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan); 28766327eb98SAndrei Emeltchenko 28776327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win, 28786327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 28790a708f8fSGustavo F. Padovan 28800a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 28810a708f8fSGustavo F. Padovan (unsigned long) &rfc); 28820a708f8fSGustavo F. Padovan 2883f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 2884f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 2885f89cef09SAndrei Emeltchenko 28868c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) 28870a708f8fSGustavo F. Padovan break; 28880a708f8fSGustavo F. Padovan 288947d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 2890c1360a1cSGustavo F. Padovan test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { 289147d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 289247d1ec61SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); 28930a708f8fSGustavo F. Padovan } 28946327eb98SAndrei Emeltchenko 28956327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 28966327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 28976327eb98SAndrei Emeltchenko chan->tx_win); 28980a708f8fSGustavo F. Padovan break; 28990a708f8fSGustavo F. Padovan 29000a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 29010a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING; 29020a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 29030a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 29040a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 29050a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 2906c8f79162SAndrei Emeltchenko 2907c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 2908c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2909c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2910c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2911c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 29120a708f8fSGustavo F. Padovan 29130a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 29140a708f8fSGustavo F. Padovan (unsigned long) &rfc); 29150a708f8fSGustavo F. Padovan 2916f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 2917f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 2918f89cef09SAndrei Emeltchenko 29198c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) 29200a708f8fSGustavo F. Padovan break; 29210a708f8fSGustavo F. Padovan 292247d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 2923c1360a1cSGustavo F. Padovan test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { 292447d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 292547d1ec61SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); 29260a708f8fSGustavo F. Padovan } 29270a708f8fSGustavo F. Padovan break; 29280a708f8fSGustavo F. Padovan } 29290a708f8fSGustavo F. Padovan 2930fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 29310a708f8fSGustavo F. Padovan req->flags = cpu_to_le16(0); 29320a708f8fSGustavo F. Padovan 29330a708f8fSGustavo F. Padovan return ptr - data; 29340a708f8fSGustavo F. Padovan } 29350a708f8fSGustavo F. Padovan 293673ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) 29370a708f8fSGustavo F. Padovan { 29380a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 29390a708f8fSGustavo F. Padovan void *ptr = rsp->data; 294073ffa904SGustavo F. Padovan void *req = chan->conf_req; 294173ffa904SGustavo F. Padovan int len = chan->conf_len; 29420a708f8fSGustavo F. Padovan int type, hint, olen; 29430a708f8fSGustavo F. Padovan unsigned long val; 29440a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 294542dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs; 294642dceae2SAndrei Emeltchenko u8 remote_efs = 0; 29470a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU; 29480a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS; 2949c8f79162SAndrei Emeltchenko u16 size; 29500a708f8fSGustavo F. Padovan 295173ffa904SGustavo F. Padovan BT_DBG("chan %p", chan); 29520a708f8fSGustavo F. Padovan 29530a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 29540a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val); 29550a708f8fSGustavo F. Padovan 29560a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT; 29570a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK; 29580a708f8fSGustavo F. Padovan 29590a708f8fSGustavo F. Padovan switch (type) { 29600a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 29610a708f8fSGustavo F. Padovan mtu = val; 29620a708f8fSGustavo F. Padovan break; 29630a708f8fSGustavo F. Padovan 29640a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 29650c1bc5c6SGustavo F. Padovan chan->flush_to = val; 29660a708f8fSGustavo F. Padovan break; 29670a708f8fSGustavo F. Padovan 29680a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS: 29690a708f8fSGustavo F. Padovan break; 29700a708f8fSGustavo F. Padovan 29710a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 29720a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 29730a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen); 29740a708f8fSGustavo F. Padovan break; 29750a708f8fSGustavo F. Padovan 29760a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS: 29770a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE) 2978c1360a1cSGustavo F. Padovan set_bit(CONF_NO_FCS_RECV, &chan->conf_state); 297942dceae2SAndrei Emeltchenko break; 29800a708f8fSGustavo F. Padovan 298142dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS: 298242dceae2SAndrei Emeltchenko remote_efs = 1; 298342dceae2SAndrei Emeltchenko if (olen == sizeof(efs)) 298442dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen); 29850a708f8fSGustavo F. Padovan break; 29860a708f8fSGustavo F. Padovan 29876327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 29886327eb98SAndrei Emeltchenko if (!enable_hs) 29896327eb98SAndrei Emeltchenko return -ECONNREFUSED; 29906327eb98SAndrei Emeltchenko 29916327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 29926327eb98SAndrei Emeltchenko set_bit(CONF_EWS_RECV, &chan->conf_state); 2993836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 29946327eb98SAndrei Emeltchenko chan->remote_tx_win = val; 29950a708f8fSGustavo F. Padovan break; 29960a708f8fSGustavo F. Padovan 29970a708f8fSGustavo F. Padovan default: 29980a708f8fSGustavo F. Padovan if (hint) 29990a708f8fSGustavo F. Padovan break; 30000a708f8fSGustavo F. Padovan 30010a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN; 30020a708f8fSGustavo F. Padovan *((u8 *) ptr++) = type; 30030a708f8fSGustavo F. Padovan break; 30040a708f8fSGustavo F. Padovan } 30050a708f8fSGustavo F. Padovan } 30060a708f8fSGustavo F. Padovan 300773ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1) 30080a708f8fSGustavo F. Padovan goto done; 30090a708f8fSGustavo F. Padovan 30100c1bc5c6SGustavo F. Padovan switch (chan->mode) { 30110a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 30120a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3013c1360a1cSGustavo F. Padovan if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { 30140c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, 30158c1d787bSGustavo F. Padovan chan->conn->feat_mask); 30160a708f8fSGustavo F. Padovan break; 30170a708f8fSGustavo F. Padovan } 30180a708f8fSGustavo F. Padovan 301942dceae2SAndrei Emeltchenko if (remote_efs) { 302042dceae2SAndrei Emeltchenko if (__l2cap_efs_supported(chan)) 302142dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 302242dceae2SAndrei Emeltchenko else 302342dceae2SAndrei Emeltchenko return -ECONNREFUSED; 302442dceae2SAndrei Emeltchenko } 302542dceae2SAndrei Emeltchenko 30260c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) 30270a708f8fSGustavo F. Padovan return -ECONNREFUSED; 30280a708f8fSGustavo F. Padovan 30290a708f8fSGustavo F. Padovan break; 30300a708f8fSGustavo F. Padovan } 30310a708f8fSGustavo F. Padovan 30320a708f8fSGustavo F. Padovan done: 30330c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) { 30340a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 30350c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 30360a708f8fSGustavo F. Padovan 303773ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1) 30380a708f8fSGustavo F. Padovan return -ECONNREFUSED; 30390a708f8fSGustavo F. Padovan 30400a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 30410a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 30420a708f8fSGustavo F. Padovan } 30430a708f8fSGustavo F. Padovan 30440a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) { 30450a708f8fSGustavo F. Padovan /* Configure output options and let the other side know 30460a708f8fSGustavo F. Padovan * which ones we don't like. */ 30470a708f8fSGustavo F. Padovan 30480a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU) 30490a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 30500a708f8fSGustavo F. Padovan else { 30510c1bc5c6SGustavo F. Padovan chan->omtu = mtu; 3052c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state); 30530a708f8fSGustavo F. Padovan } 30540c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); 30550a708f8fSGustavo F. Padovan 305642dceae2SAndrei Emeltchenko if (remote_efs) { 305742dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 305842dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 305942dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) { 306042dceae2SAndrei Emeltchenko 306142dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT; 306242dceae2SAndrei Emeltchenko 306342dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1) 306442dceae2SAndrei Emeltchenko return -ECONNREFUSED; 306542dceae2SAndrei Emeltchenko 306642dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 306742dceae2SAndrei Emeltchenko sizeof(efs), 306842dceae2SAndrei Emeltchenko (unsigned long) &efs); 30690e8b207eSAndrei Emeltchenko } else { 30703e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */ 30710e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING; 30720e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 307342dceae2SAndrei Emeltchenko } 307442dceae2SAndrei Emeltchenko } 307542dceae2SAndrei Emeltchenko 30760a708f8fSGustavo F. Padovan switch (rfc.mode) { 30770a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 307847d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3079c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 30800a708f8fSGustavo F. Padovan break; 30810a708f8fSGustavo F. Padovan 30820a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 30836327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state)) 30842c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size; 30856327eb98SAndrei Emeltchenko else 30866327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; 30876327eb98SAndrei Emeltchenko 30882c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit; 30890a708f8fSGustavo F. Padovan 3090c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 3091c8f79162SAndrei Emeltchenko chan->conn->mtu - 3092c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 3093c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 3094c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3095c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3096c8f79162SAndrei Emeltchenko chan->remote_mps = size; 30970a708f8fSGustavo F. Padovan 30980a708f8fSGustavo F. Padovan rfc.retrans_timeout = 30994fd21a88SAndrei Emeltchenko __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 31000a708f8fSGustavo F. Padovan rfc.monitor_timeout = 31014fd21a88SAndrei Emeltchenko __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 31020a708f8fSGustavo F. Padovan 3103c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 31040a708f8fSGustavo F. Padovan 31050a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 31060a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 31070a708f8fSGustavo F. Padovan 310842dceae2SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 310942dceae2SAndrei Emeltchenko chan->remote_id = efs.id; 311042dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype; 311142dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu); 311242dceae2SAndrei Emeltchenko chan->remote_flush_to = 311342dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to); 311442dceae2SAndrei Emeltchenko chan->remote_acc_lat = 311542dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat); 311642dceae2SAndrei Emeltchenko chan->remote_sdu_itime = 311742dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 311842dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 311942dceae2SAndrei Emeltchenko sizeof(efs), (unsigned long) &efs); 312042dceae2SAndrei Emeltchenko } 31210a708f8fSGustavo F. Padovan break; 31220a708f8fSGustavo F. Padovan 31230a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3124c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 3125c8f79162SAndrei Emeltchenko chan->conn->mtu - 3126c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 3127c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 3128c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3129c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3130c8f79162SAndrei Emeltchenko chan->remote_mps = size; 31310a708f8fSGustavo F. Padovan 3132c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 31330a708f8fSGustavo F. Padovan 31340a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 31350a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 31360a708f8fSGustavo F. Padovan 31370a708f8fSGustavo F. Padovan break; 31380a708f8fSGustavo F. Padovan 31390a708f8fSGustavo F. Padovan default: 31400a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 31410a708f8fSGustavo F. Padovan 31420a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc)); 31430c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 31440a708f8fSGustavo F. Padovan } 31450a708f8fSGustavo F. Padovan 31460a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) 3147c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 31480a708f8fSGustavo F. Padovan } 3149fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 31500a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 31510a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(0x0000); 31520a708f8fSGustavo F. Padovan 31530a708f8fSGustavo F. Padovan return ptr - data; 31540a708f8fSGustavo F. Padovan } 31550a708f8fSGustavo F. Padovan 3156b4450035SGustavo F. Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result) 31570a708f8fSGustavo F. Padovan { 31580a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 31590a708f8fSGustavo F. Padovan void *ptr = req->data; 31600a708f8fSGustavo F. Padovan int type, olen; 31610a708f8fSGustavo F. Padovan unsigned long val; 316236e999a8SMat Martineau struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 316366af7aafSAndrei Emeltchenko struct l2cap_conf_efs efs; 31640a708f8fSGustavo F. Padovan 3165fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); 31660a708f8fSGustavo F. Padovan 31670a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 31680a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 31690a708f8fSGustavo F. Padovan 31700a708f8fSGustavo F. Padovan switch (type) { 31710a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 31720a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) { 31730a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT; 31740c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU; 31750a708f8fSGustavo F. Padovan } else 31760c1bc5c6SGustavo F. Padovan chan->imtu = val; 31770c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 31780a708f8fSGustavo F. Padovan break; 31790a708f8fSGustavo F. Padovan 31800a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 31810c1bc5c6SGustavo F. Padovan chan->flush_to = val; 31820a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 31830c1bc5c6SGustavo F. Padovan 2, chan->flush_to); 31840a708f8fSGustavo F. Padovan break; 31850a708f8fSGustavo F. Padovan 31860a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 31870a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 31880a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 31890a708f8fSGustavo F. Padovan 3190c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && 31910c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode) 31920a708f8fSGustavo F. Padovan return -ECONNREFUSED; 31930a708f8fSGustavo F. Padovan 319447d1ec61SGustavo F. Padovan chan->fcs = 0; 31950a708f8fSGustavo F. Padovan 31960a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 31970a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 31980a708f8fSGustavo F. Padovan break; 31996327eb98SAndrei Emeltchenko 32006327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 32016327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, val, 32026327eb98SAndrei Emeltchenko L2CAP_DEFAULT_EXT_WINDOW); 32033e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 32043e6b3b95SGustavo F. Padovan chan->tx_win); 32056327eb98SAndrei Emeltchenko break; 320666af7aafSAndrei Emeltchenko 320766af7aafSAndrei Emeltchenko case L2CAP_CONF_EFS: 320866af7aafSAndrei Emeltchenko if (olen == sizeof(efs)) 320966af7aafSAndrei Emeltchenko memcpy(&efs, (void *)val, olen); 321066af7aafSAndrei Emeltchenko 321166af7aafSAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 321266af7aafSAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 321366af7aafSAndrei Emeltchenko efs.stype != chan->local_stype) 321466af7aafSAndrei Emeltchenko return -ECONNREFUSED; 321566af7aafSAndrei Emeltchenko 321666af7aafSAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 321766af7aafSAndrei Emeltchenko sizeof(efs), (unsigned long) &efs); 321866af7aafSAndrei Emeltchenko break; 32190a708f8fSGustavo F. Padovan } 32200a708f8fSGustavo F. Padovan } 32210a708f8fSGustavo F. Padovan 32220c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) 32230a708f8fSGustavo F. Padovan return -ECONNREFUSED; 32240a708f8fSGustavo F. Padovan 32250c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode; 32260a708f8fSGustavo F. Padovan 32270e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) { 32280a708f8fSGustavo F. Padovan switch (rfc.mode) { 32290a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 323047d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 323147d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 323247d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 323366af7aafSAndrei Emeltchenko 323466af7aafSAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 323566af7aafSAndrei Emeltchenko chan->local_msdu = le16_to_cpu(efs.msdu); 323666af7aafSAndrei Emeltchenko chan->local_sdu_itime = 323766af7aafSAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 323866af7aafSAndrei Emeltchenko chan->local_acc_lat = le32_to_cpu(efs.acc_lat); 323966af7aafSAndrei Emeltchenko chan->local_flush_to = 324066af7aafSAndrei Emeltchenko le32_to_cpu(efs.flush_to); 324166af7aafSAndrei Emeltchenko } 32420a708f8fSGustavo F. Padovan break; 324366af7aafSAndrei Emeltchenko 32440a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 324547d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 32460a708f8fSGustavo F. Padovan } 32470a708f8fSGustavo F. Padovan } 32480a708f8fSGustavo F. Padovan 3249fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 32500a708f8fSGustavo F. Padovan req->flags = cpu_to_le16(0x0000); 32510a708f8fSGustavo F. Padovan 32520a708f8fSGustavo F. Padovan return ptr - data; 32530a708f8fSGustavo F. Padovan } 32540a708f8fSGustavo F. Padovan 3255fe4128e0SGustavo F. Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags) 32560a708f8fSGustavo F. Padovan { 32570a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 32580a708f8fSGustavo F. Padovan void *ptr = rsp->data; 32590a708f8fSGustavo F. Padovan 3260fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan); 32610a708f8fSGustavo F. Padovan 3262fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 32630a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 32640a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags); 32650a708f8fSGustavo F. Padovan 32660a708f8fSGustavo F. Padovan return ptr - data; 32670a708f8fSGustavo F. Padovan } 32680a708f8fSGustavo F. Padovan 32698c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) 3270710f9b0aSGustavo F. Padovan { 3271710f9b0aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 32728c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 3273710f9b0aSGustavo F. Padovan u8 buf[128]; 3274710f9b0aSGustavo F. Padovan 3275fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 3276fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3277710f9b0aSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 3278710f9b0aSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 3279710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, 3280710f9b0aSGustavo F. Padovan L2CAP_CONN_RSP, sizeof(rsp), &rsp); 3281710f9b0aSGustavo F. Padovan 3282c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 3283710f9b0aSGustavo F. Padovan return; 3284710f9b0aSGustavo F. Padovan 3285710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 3286710f9b0aSGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 3287710f9b0aSGustavo F. Padovan chan->num_conf_req++; 3288710f9b0aSGustavo F. Padovan } 3289710f9b0aSGustavo F. Padovan 329047d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) 32910a708f8fSGustavo F. Padovan { 32920a708f8fSGustavo F. Padovan int type, olen; 32930a708f8fSGustavo F. Padovan unsigned long val; 32940a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc; 32950a708f8fSGustavo F. Padovan 329647d1ec61SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); 32970a708f8fSGustavo F. Padovan 32980c1bc5c6SGustavo F. Padovan if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) 32990a708f8fSGustavo F. Padovan return; 33000a708f8fSGustavo F. Padovan 33010a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 33020a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 33030a708f8fSGustavo F. Padovan 33040a708f8fSGustavo F. Padovan switch (type) { 33050a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 33060a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 33070a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 33080a708f8fSGustavo F. Padovan goto done; 33090a708f8fSGustavo F. Padovan } 33100a708f8fSGustavo F. Padovan } 33110a708f8fSGustavo F. Padovan 331236e999a8SMat Martineau /* Use sane default values in case a misbehaving remote device 331336e999a8SMat Martineau * did not send an RFC option. 331436e999a8SMat Martineau */ 331536e999a8SMat Martineau rfc.mode = chan->mode; 331636e999a8SMat Martineau rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 331736e999a8SMat Martineau rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 331836e999a8SMat Martineau rfc.max_pdu_size = cpu_to_le16(chan->imtu); 331936e999a8SMat Martineau 332036e999a8SMat Martineau BT_ERR("Expected RFC option was not found, using defaults"); 332136e999a8SMat Martineau 33220a708f8fSGustavo F. Padovan done: 33230a708f8fSGustavo F. Padovan switch (rfc.mode) { 33240a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 332547d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 332647d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 332747d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 33280a708f8fSGustavo F. Padovan break; 33290a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 333047d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 33310a708f8fSGustavo F. Padovan } 33320a708f8fSGustavo F. Padovan } 33330a708f8fSGustavo F. Padovan 33340a708f8fSGustavo F. Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 33350a708f8fSGustavo F. Padovan { 3336e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 33370a708f8fSGustavo F. Padovan 3338e2fd318eSIlia Kolomisnky if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) 33390a708f8fSGustavo F. Padovan return 0; 33400a708f8fSGustavo F. Padovan 33410a708f8fSGustavo F. Padovan if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && 33420a708f8fSGustavo F. Padovan cmd->ident == conn->info_ident) { 334317cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 33440a708f8fSGustavo F. Padovan 33450a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 33460a708f8fSGustavo F. Padovan conn->info_ident = 0; 33470a708f8fSGustavo F. Padovan 33480a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 33490a708f8fSGustavo F. Padovan } 33500a708f8fSGustavo F. Padovan 33510a708f8fSGustavo F. Padovan return 0; 33520a708f8fSGustavo F. Padovan } 33530a708f8fSGustavo F. Padovan 33540a708f8fSGustavo F. Padovan static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 33550a708f8fSGustavo F. Padovan { 33560a708f8fSGustavo F. Padovan struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 33570a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 335823691d75SGustavo F. Padovan struct l2cap_chan *chan = NULL, *pchan; 33590a708f8fSGustavo F. Padovan struct sock *parent, *sk = NULL; 33600a708f8fSGustavo F. Padovan int result, status = L2CAP_CS_NO_INFO; 33610a708f8fSGustavo F. Padovan 33620a708f8fSGustavo F. Padovan u16 dcid = 0, scid = __le16_to_cpu(req->scid); 33630a708f8fSGustavo F. Padovan __le16 psm = req->psm; 33640a708f8fSGustavo F. Padovan 3365097db76cSAndrei Emeltchenko BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); 33660a708f8fSGustavo F. Padovan 33670a708f8fSGustavo F. Padovan /* Check if we have socket listening on psm */ 3368c2287681SIdo Yariv pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst); 336923691d75SGustavo F. Padovan if (!pchan) { 33700a708f8fSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 33710a708f8fSGustavo F. Padovan goto sendresp; 33720a708f8fSGustavo F. Padovan } 33730a708f8fSGustavo F. Padovan 337423691d75SGustavo F. Padovan parent = pchan->sk; 337523691d75SGustavo F. Padovan 33763df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 3377aa2ac881SGustavo F. Padovan lock_sock(parent); 33780a708f8fSGustavo F. Padovan 33790a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */ 33800a708f8fSGustavo F. Padovan if (psm != cpu_to_le16(0x0001) && 33810a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) { 33829f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_AUTH_FAILURE; 33830a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 33840a708f8fSGustavo F. Padovan goto response; 33850a708f8fSGustavo F. Padovan } 33860a708f8fSGustavo F. Padovan 33870a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM; 33880a708f8fSGustavo F. Padovan 33890a708f8fSGustavo F. Padovan /* Check for backlog size */ 33900a708f8fSGustavo F. Padovan if (sk_acceptq_is_full(parent)) { 33910a708f8fSGustavo F. Padovan BT_DBG("backlog full %d", parent->sk_ack_backlog); 33920a708f8fSGustavo F. Padovan goto response; 33930a708f8fSGustavo F. Padovan } 33940a708f8fSGustavo F. Padovan 339580808e43SGustavo F. Padovan chan = pchan->ops->new_connection(pchan->data); 339680808e43SGustavo F. Padovan if (!chan) 33970a708f8fSGustavo F. Padovan goto response; 33980a708f8fSGustavo F. Padovan 339980808e43SGustavo F. Padovan sk = chan->sk; 340080808e43SGustavo F. Padovan 34010a708f8fSGustavo F. Padovan /* Check if we already have channel with that dcid */ 3402baa7e1faSGustavo F. Padovan if (__l2cap_get_chan_by_dcid(conn, scid)) { 34030a708f8fSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 3404ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 34050a708f8fSGustavo F. Padovan goto response; 34060a708f8fSGustavo F. Padovan } 34070a708f8fSGustavo F. Padovan 34080a708f8fSGustavo F. Padovan hci_conn_hold(conn->hcon); 34090a708f8fSGustavo F. Padovan 34100a708f8fSGustavo F. Padovan bacpy(&bt_sk(sk)->src, conn->src); 34110a708f8fSGustavo F. Padovan bacpy(&bt_sk(sk)->dst, conn->dst); 3412fe4128e0SGustavo F. Padovan chan->psm = psm; 3413fe4128e0SGustavo F. Padovan chan->dcid = scid; 34140a708f8fSGustavo F. Padovan 3415d1010240SGustavo F. Padovan bt_accept_enqueue(parent, sk); 3416d1010240SGustavo F. Padovan 34176be36555SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 341848454079SGustavo F. Padovan 3419fe4128e0SGustavo F. Padovan dcid = chan->scid; 34200a708f8fSGustavo F. Padovan 3421c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 34220a708f8fSGustavo F. Padovan 3423fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident; 34240a708f8fSGustavo F. Padovan 34250a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { 3426d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 3427c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) { 34280e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 34290a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 34300a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND; 34310a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 34320a708f8fSGustavo F. Padovan } else { 34330e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 34340a708f8fSGustavo F. Padovan result = L2CAP_CR_SUCCESS; 34350a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 34360a708f8fSGustavo F. Padovan } 34370a708f8fSGustavo F. Padovan } else { 34380e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 34390a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 34400a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND; 34410a708f8fSGustavo F. Padovan } 34420a708f8fSGustavo F. Padovan } else { 34430e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 34440a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 34450a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 34460a708f8fSGustavo F. Padovan } 34470a708f8fSGustavo F. Padovan 34480a708f8fSGustavo F. Padovan response: 3449aa2ac881SGustavo F. Padovan release_sock(parent); 34503df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 34510a708f8fSGustavo F. Padovan 34520a708f8fSGustavo F. Padovan sendresp: 34530a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid); 34540a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid); 34550a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result); 34560a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status); 34570a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); 34580a708f8fSGustavo F. Padovan 34590a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { 34600a708f8fSGustavo F. Padovan struct l2cap_info_req info; 34610a708f8fSGustavo F. Padovan info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 34620a708f8fSGustavo F. Padovan 34630a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 34640a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 34650a708f8fSGustavo F. Padovan 3466ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 34670a708f8fSGustavo F. Padovan 34680a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 34690a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(info), &info); 34700a708f8fSGustavo F. Padovan } 34710a708f8fSGustavo F. Padovan 3472c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && 34730a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) { 34740a708f8fSGustavo F. Padovan u8 buf[128]; 3475c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 34760a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 347773ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 347873ffa904SGustavo F. Padovan chan->num_conf_req++; 34790a708f8fSGustavo F. Padovan } 34800a708f8fSGustavo F. Padovan 34810a708f8fSGustavo F. Padovan return 0; 34820a708f8fSGustavo F. Padovan } 34830a708f8fSGustavo F. Padovan 34840a708f8fSGustavo F. Padovan static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 34850a708f8fSGustavo F. Padovan { 34860a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; 34870a708f8fSGustavo F. Padovan u16 scid, dcid, result, status; 348848454079SGustavo F. Padovan struct l2cap_chan *chan; 34890a708f8fSGustavo F. Padovan u8 req[128]; 34903df91ea2SAndrei Emeltchenko int err; 34910a708f8fSGustavo F. Padovan 34920a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 34930a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 34940a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 34950a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status); 34960a708f8fSGustavo F. Padovan 34971b009c98SAndrei Emeltchenko BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", 34981b009c98SAndrei Emeltchenko dcid, scid, result, status); 34990a708f8fSGustavo F. Padovan 35003df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 35013df91ea2SAndrei Emeltchenko 35020a708f8fSGustavo F. Padovan if (scid) { 35033df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 35043df91ea2SAndrei Emeltchenko if (!chan) { 35053df91ea2SAndrei Emeltchenko err = -EFAULT; 35063df91ea2SAndrei Emeltchenko goto unlock; 35073df91ea2SAndrei Emeltchenko } 35080a708f8fSGustavo F. Padovan } else { 35093df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 35103df91ea2SAndrei Emeltchenko if (!chan) { 35113df91ea2SAndrei Emeltchenko err = -EFAULT; 35123df91ea2SAndrei Emeltchenko goto unlock; 35133df91ea2SAndrei Emeltchenko } 35140a708f8fSGustavo F. Padovan } 35150a708f8fSGustavo F. Padovan 35163df91ea2SAndrei Emeltchenko err = 0; 35173df91ea2SAndrei Emeltchenko 35186be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 351948454079SGustavo F. Padovan 35200a708f8fSGustavo F. Padovan switch (result) { 35210a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS: 352289bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 3523fc7f8a7eSGustavo F. Padovan chan->ident = 0; 3524fe4128e0SGustavo F. Padovan chan->dcid = dcid; 3525c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state); 35260a708f8fSGustavo F. Padovan 3527c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 35280a708f8fSGustavo F. Padovan break; 35290a708f8fSGustavo F. Padovan 35300a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 353173ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, req), req); 353273ffa904SGustavo F. Padovan chan->num_conf_req++; 35330a708f8fSGustavo F. Padovan break; 35340a708f8fSGustavo F. Padovan 35350a708f8fSGustavo F. Padovan case L2CAP_CR_PEND: 3536c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 35370a708f8fSGustavo F. Padovan break; 35380a708f8fSGustavo F. Padovan 35390a708f8fSGustavo F. Padovan default: 354048454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED); 35410a708f8fSGustavo F. Padovan break; 35420a708f8fSGustavo F. Padovan } 35430a708f8fSGustavo F. Padovan 35446be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 35453df91ea2SAndrei Emeltchenko 35463df91ea2SAndrei Emeltchenko unlock: 35473df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 35483df91ea2SAndrei Emeltchenko 35493df91ea2SAndrei Emeltchenko return err; 35500a708f8fSGustavo F. Padovan } 35510a708f8fSGustavo F. Padovan 355247d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan) 35530a708f8fSGustavo F. Padovan { 35540a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both 35550a708f8fSGustavo F. Padovan * sides request it. 35560a708f8fSGustavo F. Padovan */ 35570c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) 355847d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3559c1360a1cSGustavo F. Padovan else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) 356047d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16; 35610a708f8fSGustavo F. Padovan } 35620a708f8fSGustavo F. Padovan 35630a708f8fSGustavo F. Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 35640a708f8fSGustavo F. Padovan { 35650a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; 35660a708f8fSGustavo F. Padovan u16 dcid, flags; 35670a708f8fSGustavo F. Padovan u8 rsp[64]; 356848454079SGustavo F. Padovan struct l2cap_chan *chan; 35693c588192SMat Martineau int len, err = 0; 35700a708f8fSGustavo F. Padovan 35710a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 35720a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags); 35730a708f8fSGustavo F. Padovan 35740a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); 35750a708f8fSGustavo F. Padovan 3576baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid); 357748454079SGustavo F. Padovan if (!chan) 35780a708f8fSGustavo F. Padovan return -ENOENT; 35790a708f8fSGustavo F. Padovan 3580033b1142SDavid S. Miller if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { 3581e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_cid rej; 35820a708f8fSGustavo F. Padovan 3583e2fd318eSIlia Kolomisnky rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID); 3584e2fd318eSIlia Kolomisnky rej.scid = cpu_to_le16(chan->scid); 3585e2fd318eSIlia Kolomisnky rej.dcid = cpu_to_le16(chan->dcid); 3586e2fd318eSIlia Kolomisnky 35870a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 35880a708f8fSGustavo F. Padovan sizeof(rej), &rej); 35890a708f8fSGustavo F. Padovan goto unlock; 35900a708f8fSGustavo F. Padovan } 35910a708f8fSGustavo F. Padovan 35920a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */ 35930a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req); 35947ac28817SDan Rosenberg if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) { 35950a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 3596fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 35970a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp); 35980a708f8fSGustavo F. Padovan goto unlock; 35990a708f8fSGustavo F. Padovan } 36000a708f8fSGustavo F. Padovan 36010a708f8fSGustavo F. Padovan /* Store config. */ 360273ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len); 360373ffa904SGustavo F. Padovan chan->conf_len += len; 36040a708f8fSGustavo F. Padovan 36050a708f8fSGustavo F. Padovan if (flags & 0x0001) { 36060a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */ 36070a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 3608fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 36090a708f8fSGustavo F. Padovan L2CAP_CONF_SUCCESS, 0x0001), rsp); 36100a708f8fSGustavo F. Padovan goto unlock; 36110a708f8fSGustavo F. Padovan } 36120a708f8fSGustavo F. Padovan 36130a708f8fSGustavo F. Padovan /* Complete config. */ 361473ffa904SGustavo F. Padovan len = l2cap_parse_conf_req(chan, rsp); 36150a708f8fSGustavo F. Padovan if (len < 0) { 3616e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 36170a708f8fSGustavo F. Padovan goto unlock; 36180a708f8fSGustavo F. Padovan } 36190a708f8fSGustavo F. Padovan 36200a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); 362173ffa904SGustavo F. Padovan chan->num_conf_rsp++; 36220a708f8fSGustavo F. Padovan 36230a708f8fSGustavo F. Padovan /* Reset config buffer. */ 362473ffa904SGustavo F. Padovan chan->conf_len = 0; 36250a708f8fSGustavo F. Padovan 3626c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) 36270a708f8fSGustavo F. Padovan goto unlock; 36280a708f8fSGustavo F. Padovan 3629c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 363047d1ec61SGustavo F. Padovan set_default_fcs(chan); 36310a708f8fSGustavo F. Padovan 363289bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECTED); 36330a708f8fSGustavo F. Padovan 3634105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 3635105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 36363c588192SMat Martineau err = l2cap_ertm_init(chan); 36370a708f8fSGustavo F. Padovan 36383c588192SMat Martineau if (err < 0) 36393c588192SMat Martineau l2cap_send_disconn_req(chan->conn, chan, -err); 36403c588192SMat Martineau else 3641cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 36423c588192SMat Martineau 36430a708f8fSGustavo F. Padovan goto unlock; 36440a708f8fSGustavo F. Padovan } 36450a708f8fSGustavo F. Padovan 3646c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { 36470a708f8fSGustavo F. Padovan u8 buf[64]; 36480a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 364973ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 365073ffa904SGustavo F. Padovan chan->num_conf_req++; 36510a708f8fSGustavo F. Padovan } 36520a708f8fSGustavo F. Padovan 36530e8b207eSAndrei Emeltchenko /* Got Conf Rsp PENDING from remote side and asume we sent 36540e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */ 36550e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && 36560e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 36570e8b207eSAndrei Emeltchenko 36580e8b207eSAndrei Emeltchenko /* check compatibility */ 36590e8b207eSAndrei Emeltchenko 36600e8b207eSAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 36610e8b207eSAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 36620e8b207eSAndrei Emeltchenko 36630e8b207eSAndrei Emeltchenko l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 36640e8b207eSAndrei Emeltchenko l2cap_build_conf_rsp(chan, rsp, 36650e8b207eSAndrei Emeltchenko L2CAP_CONF_SUCCESS, 0x0000), rsp); 36660e8b207eSAndrei Emeltchenko } 36670e8b207eSAndrei Emeltchenko 36680a708f8fSGustavo F. Padovan unlock: 36696be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 36703c588192SMat Martineau return err; 36710a708f8fSGustavo F. Padovan } 36720a708f8fSGustavo F. Padovan 36730a708f8fSGustavo F. Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 36740a708f8fSGustavo F. Padovan { 36750a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; 36760a708f8fSGustavo F. Padovan u16 scid, flags, result; 367748454079SGustavo F. Padovan struct l2cap_chan *chan; 367861386cbaSAndrei Emeltchenko int len = le16_to_cpu(cmd->len) - sizeof(*rsp); 36793c588192SMat Martineau int err = 0; 36800a708f8fSGustavo F. Padovan 36810a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 36820a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags); 36830a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 36840a708f8fSGustavo F. Padovan 368561386cbaSAndrei Emeltchenko BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags, 368661386cbaSAndrei Emeltchenko result, len); 36870a708f8fSGustavo F. Padovan 3688baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 368948454079SGustavo F. Padovan if (!chan) 36900a708f8fSGustavo F. Padovan return 0; 36910a708f8fSGustavo F. Padovan 36920a708f8fSGustavo F. Padovan switch (result) { 36930a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS: 369447d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len); 36950e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state); 36960a708f8fSGustavo F. Padovan break; 36970a708f8fSGustavo F. Padovan 36980e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING: 36990e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state); 37000e8b207eSAndrei Emeltchenko 37010e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 37020e8b207eSAndrei Emeltchenko char buf[64]; 37030e8b207eSAndrei Emeltchenko 37040e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len, 37050e8b207eSAndrei Emeltchenko buf, &result); 37060e8b207eSAndrei Emeltchenko if (len < 0) { 37070e8b207eSAndrei Emeltchenko l2cap_send_disconn_req(conn, chan, ECONNRESET); 37080e8b207eSAndrei Emeltchenko goto done; 37090e8b207eSAndrei Emeltchenko } 37100e8b207eSAndrei Emeltchenko 37110e8b207eSAndrei Emeltchenko /* check compatibility */ 37120e8b207eSAndrei Emeltchenko 37130e8b207eSAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 37140e8b207eSAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 37150e8b207eSAndrei Emeltchenko 37160e8b207eSAndrei Emeltchenko l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 37170e8b207eSAndrei Emeltchenko l2cap_build_conf_rsp(chan, buf, 37180e8b207eSAndrei Emeltchenko L2CAP_CONF_SUCCESS, 0x0000), buf); 37190e8b207eSAndrei Emeltchenko } 37200e8b207eSAndrei Emeltchenko goto done; 37210e8b207eSAndrei Emeltchenko 37220a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT: 372373ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { 37240a708f8fSGustavo F. Padovan char req[64]; 37250a708f8fSGustavo F. Padovan 37260a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { 3727e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 37280a708f8fSGustavo F. Padovan goto done; 37290a708f8fSGustavo F. Padovan } 37300a708f8fSGustavo F. Padovan 37310a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */ 37320a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS; 3733b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len, 3734b4450035SGustavo F. Padovan req, &result); 37350a708f8fSGustavo F. Padovan if (len < 0) { 3736e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 37370a708f8fSGustavo F. Padovan goto done; 37380a708f8fSGustavo F. Padovan } 37390a708f8fSGustavo F. Padovan 37400a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 37410a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req); 374273ffa904SGustavo F. Padovan chan->num_conf_req++; 37430a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS) 37440a708f8fSGustavo F. Padovan goto done; 37450a708f8fSGustavo F. Padovan break; 37460a708f8fSGustavo F. Padovan } 37470a708f8fSGustavo F. Padovan 37480a708f8fSGustavo F. Padovan default: 37496be36555SAndrei Emeltchenko l2cap_chan_set_err(chan, ECONNRESET); 37502e0052e4SAndrei Emeltchenko 3751ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); 3752e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 37530a708f8fSGustavo F. Padovan goto done; 37540a708f8fSGustavo F. Padovan } 37550a708f8fSGustavo F. Padovan 37560a708f8fSGustavo F. Padovan if (flags & 0x01) 37570a708f8fSGustavo F. Padovan goto done; 37580a708f8fSGustavo F. Padovan 3759c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state); 37600a708f8fSGustavo F. Padovan 3761c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { 376247d1ec61SGustavo F. Padovan set_default_fcs(chan); 37630a708f8fSGustavo F. Padovan 376489bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECTED); 3765105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 3766105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 37673c588192SMat Martineau err = l2cap_ertm_init(chan); 37680a708f8fSGustavo F. Padovan 37693c588192SMat Martineau if (err < 0) 37703c588192SMat Martineau l2cap_send_disconn_req(chan->conn, chan, -err); 37713c588192SMat Martineau else 3772cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 37730a708f8fSGustavo F. Padovan } 37740a708f8fSGustavo F. Padovan 37750a708f8fSGustavo F. Padovan done: 37766be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 37773c588192SMat Martineau return err; 37780a708f8fSGustavo F. Padovan } 37790a708f8fSGustavo F. Padovan 37800a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 37810a708f8fSGustavo F. Padovan { 37820a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; 37830a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp; 37840a708f8fSGustavo F. Padovan u16 dcid, scid; 378548454079SGustavo F. Padovan struct l2cap_chan *chan; 37860a708f8fSGustavo F. Padovan struct sock *sk; 37870a708f8fSGustavo F. Padovan 37880a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid); 37890a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 37900a708f8fSGustavo F. Padovan 37910a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); 37920a708f8fSGustavo F. Padovan 37933df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 37943df91ea2SAndrei Emeltchenko 37953df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, dcid); 37963df91ea2SAndrei Emeltchenko if (!chan) { 37973df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 37980a708f8fSGustavo F. Padovan return 0; 37993df91ea2SAndrei Emeltchenko } 38000a708f8fSGustavo F. Padovan 38016be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 38026be36555SAndrei Emeltchenko 380348454079SGustavo F. Padovan sk = chan->sk; 380448454079SGustavo F. Padovan 3805fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3806fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 38070a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); 38080a708f8fSGustavo F. Padovan 38096be36555SAndrei Emeltchenko lock_sock(sk); 38100a708f8fSGustavo F. Padovan sk->sk_shutdown = SHUTDOWN_MASK; 38116be36555SAndrei Emeltchenko release_sock(sk); 38120a708f8fSGustavo F. Padovan 381361d6ef3eSMat Martineau l2cap_chan_hold(chan); 381448454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET); 38156be36555SAndrei Emeltchenko 38166be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 38170a708f8fSGustavo F. Padovan 3818ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 381961d6ef3eSMat Martineau l2cap_chan_put(chan); 38203df91ea2SAndrei Emeltchenko 38213df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 38223df91ea2SAndrei Emeltchenko 38230a708f8fSGustavo F. Padovan return 0; 38240a708f8fSGustavo F. Padovan } 38250a708f8fSGustavo F. Padovan 38260a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 38270a708f8fSGustavo F. Padovan { 38280a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; 38290a708f8fSGustavo F. Padovan u16 dcid, scid; 383048454079SGustavo F. Padovan struct l2cap_chan *chan; 38310a708f8fSGustavo F. Padovan 38320a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 38330a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 38340a708f8fSGustavo F. Padovan 38350a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); 38360a708f8fSGustavo F. Padovan 38373df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 38383df91ea2SAndrei Emeltchenko 38393df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 38403df91ea2SAndrei Emeltchenko if (!chan) { 38413df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 38420a708f8fSGustavo F. Padovan return 0; 38433df91ea2SAndrei Emeltchenko } 38440a708f8fSGustavo F. Padovan 38456be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 384648454079SGustavo F. Padovan 384761d6ef3eSMat Martineau l2cap_chan_hold(chan); 384848454079SGustavo F. Padovan l2cap_chan_del(chan, 0); 38496be36555SAndrei Emeltchenko 38506be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 38510a708f8fSGustavo F. Padovan 3852ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 385361d6ef3eSMat Martineau l2cap_chan_put(chan); 38543df91ea2SAndrei Emeltchenko 38553df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 38563df91ea2SAndrei Emeltchenko 38570a708f8fSGustavo F. Padovan return 0; 38580a708f8fSGustavo F. Padovan } 38590a708f8fSGustavo F. Padovan 38600a708f8fSGustavo F. Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 38610a708f8fSGustavo F. Padovan { 38620a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data; 38630a708f8fSGustavo F. Padovan u16 type; 38640a708f8fSGustavo F. Padovan 38650a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type); 38660a708f8fSGustavo F. Padovan 38670a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type); 38680a708f8fSGustavo F. Padovan 38690a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) { 38700a708f8fSGustavo F. Padovan u8 buf[8]; 38710a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask; 38720a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 38730a708f8fSGustavo F. Padovan rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 38740a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 38750a708f8fSGustavo F. Padovan if (!disable_ertm) 38760a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING 38770a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS; 3878a5fd6f30SAndrei Emeltchenko if (enable_hs) 38796327eb98SAndrei Emeltchenko feat_mask |= L2CAP_FEAT_EXT_FLOW 38806327eb98SAndrei Emeltchenko | L2CAP_FEAT_EXT_WINDOW; 3881a5fd6f30SAndrei Emeltchenko 38820a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data); 38830a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 38840a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(buf), buf); 38850a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) { 38860a708f8fSGustavo F. Padovan u8 buf[12]; 38870a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 388850a147cdSMat Martineau 388950a147cdSMat Martineau if (enable_hs) 389050a147cdSMat Martineau l2cap_fixed_chan[0] |= L2CAP_FC_A2MP; 389150a147cdSMat Martineau else 389250a147cdSMat Martineau l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP; 389350a147cdSMat Martineau 38940a708f8fSGustavo F. Padovan rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 38950a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 3896c6337ea6SAndrei Emeltchenko memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); 38970a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 38980a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(buf), buf); 38990a708f8fSGustavo F. Padovan } else { 39000a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp; 39010a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type); 39020a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP); 39030a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 39040a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(rsp), &rsp); 39050a708f8fSGustavo F. Padovan } 39060a708f8fSGustavo F. Padovan 39070a708f8fSGustavo F. Padovan return 0; 39080a708f8fSGustavo F. Padovan } 39090a708f8fSGustavo F. Padovan 39100a708f8fSGustavo F. Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 39110a708f8fSGustavo F. Padovan { 39120a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; 39130a708f8fSGustavo F. Padovan u16 type, result; 39140a708f8fSGustavo F. Padovan 39150a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type); 39160a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 39170a708f8fSGustavo F. Padovan 39180a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); 39190a708f8fSGustavo F. Padovan 3920e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */ 3921e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident || 3922e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 3923e90165beSAndrei Emeltchenko return 0; 3924e90165beSAndrei Emeltchenko 392517cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 39260a708f8fSGustavo F. Padovan 39270a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) { 39280a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 39290a708f8fSGustavo F. Padovan conn->info_ident = 0; 39300a708f8fSGustavo F. Padovan 39310a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 39320a708f8fSGustavo F. Padovan 39330a708f8fSGustavo F. Padovan return 0; 39340a708f8fSGustavo F. Padovan } 39350a708f8fSGustavo F. Padovan 3936978c93b9SAndrei Emeltchenko switch (type) { 3937978c93b9SAndrei Emeltchenko case L2CAP_IT_FEAT_MASK: 39380a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data); 39390a708f8fSGustavo F. Padovan 39400a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { 39410a708f8fSGustavo F. Padovan struct l2cap_info_req req; 39420a708f8fSGustavo F. Padovan req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 39430a708f8fSGustavo F. Padovan 39440a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 39450a708f8fSGustavo F. Padovan 39460a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 39470a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 39480a708f8fSGustavo F. Padovan } else { 39490a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 39500a708f8fSGustavo F. Padovan conn->info_ident = 0; 39510a708f8fSGustavo F. Padovan 39520a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 39530a708f8fSGustavo F. Padovan } 3954978c93b9SAndrei Emeltchenko break; 3955978c93b9SAndrei Emeltchenko 3956978c93b9SAndrei Emeltchenko case L2CAP_IT_FIXED_CHAN: 3957978c93b9SAndrei Emeltchenko conn->fixed_chan_mask = rsp->data[0]; 39580a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 39590a708f8fSGustavo F. Padovan conn->info_ident = 0; 39600a708f8fSGustavo F. Padovan 39610a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 3962978c93b9SAndrei Emeltchenko break; 39630a708f8fSGustavo F. Padovan } 39640a708f8fSGustavo F. Padovan 39650a708f8fSGustavo F. Padovan return 0; 39660a708f8fSGustavo F. Padovan } 39670a708f8fSGustavo F. Padovan 3968f94ff6ffSMat Martineau static inline int l2cap_create_channel_req(struct l2cap_conn *conn, 3969f94ff6ffSMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, 3970f94ff6ffSMat Martineau void *data) 3971f94ff6ffSMat Martineau { 3972f94ff6ffSMat Martineau struct l2cap_create_chan_req *req = data; 3973f94ff6ffSMat Martineau struct l2cap_create_chan_rsp rsp; 3974f94ff6ffSMat Martineau u16 psm, scid; 3975f94ff6ffSMat Martineau 3976f94ff6ffSMat Martineau if (cmd_len != sizeof(*req)) 3977f94ff6ffSMat Martineau return -EPROTO; 3978f94ff6ffSMat Martineau 3979f94ff6ffSMat Martineau if (!enable_hs) 3980f94ff6ffSMat Martineau return -EINVAL; 3981f94ff6ffSMat Martineau 3982f94ff6ffSMat Martineau psm = le16_to_cpu(req->psm); 3983f94ff6ffSMat Martineau scid = le16_to_cpu(req->scid); 3984f94ff6ffSMat Martineau 3985f94ff6ffSMat Martineau BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id); 3986f94ff6ffSMat Martineau 3987f94ff6ffSMat Martineau /* Placeholder: Always reject */ 3988f94ff6ffSMat Martineau rsp.dcid = 0; 3989f94ff6ffSMat Martineau rsp.scid = cpu_to_le16(scid); 39908ce0c498SAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM); 39918ce0c498SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 3992f94ff6ffSMat Martineau 3993f94ff6ffSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, 3994f94ff6ffSMat Martineau sizeof(rsp), &rsp); 3995f94ff6ffSMat Martineau 3996f94ff6ffSMat Martineau return 0; 3997f94ff6ffSMat Martineau } 3998f94ff6ffSMat Martineau 3999f94ff6ffSMat Martineau static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn, 4000f94ff6ffSMat Martineau struct l2cap_cmd_hdr *cmd, void *data) 4001f94ff6ffSMat Martineau { 4002f94ff6ffSMat Martineau BT_DBG("conn %p", conn); 4003f94ff6ffSMat Martineau 4004f94ff6ffSMat Martineau return l2cap_connect_rsp(conn, cmd, data); 4005f94ff6ffSMat Martineau } 4006f94ff6ffSMat Martineau 40078d5a04a1SMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident, 40088d5a04a1SMat Martineau u16 icid, u16 result) 40098d5a04a1SMat Martineau { 40108d5a04a1SMat Martineau struct l2cap_move_chan_rsp rsp; 40118d5a04a1SMat Martineau 40128d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 40138d5a04a1SMat Martineau 40148d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 40158d5a04a1SMat Martineau rsp.result = cpu_to_le16(result); 40168d5a04a1SMat Martineau 40178d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp); 40188d5a04a1SMat Martineau } 40198d5a04a1SMat Martineau 40208d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn, 40218d5a04a1SMat Martineau struct l2cap_chan *chan, u16 icid, u16 result) 40228d5a04a1SMat Martineau { 40238d5a04a1SMat Martineau struct l2cap_move_chan_cfm cfm; 40248d5a04a1SMat Martineau u8 ident; 40258d5a04a1SMat Martineau 40268d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 40278d5a04a1SMat Martineau 40288d5a04a1SMat Martineau ident = l2cap_get_ident(conn); 40298d5a04a1SMat Martineau if (chan) 40308d5a04a1SMat Martineau chan->ident = ident; 40318d5a04a1SMat Martineau 40328d5a04a1SMat Martineau cfm.icid = cpu_to_le16(icid); 40338d5a04a1SMat Martineau cfm.result = cpu_to_le16(result); 40348d5a04a1SMat Martineau 40358d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm); 40368d5a04a1SMat Martineau } 40378d5a04a1SMat Martineau 40388d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, 40398d5a04a1SMat Martineau u16 icid) 40408d5a04a1SMat Martineau { 40418d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp rsp; 40428d5a04a1SMat Martineau 40438d5a04a1SMat Martineau BT_DBG("icid %d", icid); 40448d5a04a1SMat Martineau 40458d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 40468d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp); 40478d5a04a1SMat Martineau } 40488d5a04a1SMat Martineau 40498d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn, 40508d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 40518d5a04a1SMat Martineau { 40528d5a04a1SMat Martineau struct l2cap_move_chan_req *req = data; 40538d5a04a1SMat Martineau u16 icid = 0; 40548d5a04a1SMat Martineau u16 result = L2CAP_MR_NOT_ALLOWED; 40558d5a04a1SMat Martineau 40568d5a04a1SMat Martineau if (cmd_len != sizeof(*req)) 40578d5a04a1SMat Martineau return -EPROTO; 40588d5a04a1SMat Martineau 40598d5a04a1SMat Martineau icid = le16_to_cpu(req->icid); 40608d5a04a1SMat Martineau 40618d5a04a1SMat Martineau BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id); 40628d5a04a1SMat Martineau 40638d5a04a1SMat Martineau if (!enable_hs) 40648d5a04a1SMat Martineau return -EINVAL; 40658d5a04a1SMat Martineau 40668d5a04a1SMat Martineau /* Placeholder: Always refuse */ 40678d5a04a1SMat Martineau l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result); 40688d5a04a1SMat Martineau 40698d5a04a1SMat Martineau return 0; 40708d5a04a1SMat Martineau } 40718d5a04a1SMat Martineau 40728d5a04a1SMat Martineau static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn, 40738d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 40748d5a04a1SMat Martineau { 40758d5a04a1SMat Martineau struct l2cap_move_chan_rsp *rsp = data; 40768d5a04a1SMat Martineau u16 icid, result; 40778d5a04a1SMat Martineau 40788d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 40798d5a04a1SMat Martineau return -EPROTO; 40808d5a04a1SMat Martineau 40818d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 40828d5a04a1SMat Martineau result = le16_to_cpu(rsp->result); 40838d5a04a1SMat Martineau 40848d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 40858d5a04a1SMat Martineau 40868d5a04a1SMat Martineau /* Placeholder: Always unconfirmed */ 40878d5a04a1SMat Martineau l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED); 40888d5a04a1SMat Martineau 40898d5a04a1SMat Martineau return 0; 40908d5a04a1SMat Martineau } 40918d5a04a1SMat Martineau 40928d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn, 40938d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 40948d5a04a1SMat Martineau { 40958d5a04a1SMat Martineau struct l2cap_move_chan_cfm *cfm = data; 40968d5a04a1SMat Martineau u16 icid, result; 40978d5a04a1SMat Martineau 40988d5a04a1SMat Martineau if (cmd_len != sizeof(*cfm)) 40998d5a04a1SMat Martineau return -EPROTO; 41008d5a04a1SMat Martineau 41018d5a04a1SMat Martineau icid = le16_to_cpu(cfm->icid); 41028d5a04a1SMat Martineau result = le16_to_cpu(cfm->result); 41038d5a04a1SMat Martineau 41048d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 41058d5a04a1SMat Martineau 41068d5a04a1SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 41078d5a04a1SMat Martineau 41088d5a04a1SMat Martineau return 0; 41098d5a04a1SMat Martineau } 41108d5a04a1SMat Martineau 41118d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, 41128d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 41138d5a04a1SMat Martineau { 41148d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp *rsp = data; 41158d5a04a1SMat Martineau u16 icid; 41168d5a04a1SMat Martineau 41178d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 41188d5a04a1SMat Martineau return -EPROTO; 41198d5a04a1SMat Martineau 41208d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 41218d5a04a1SMat Martineau 41228d5a04a1SMat Martineau BT_DBG("icid %d", icid); 41238d5a04a1SMat Martineau 41248d5a04a1SMat Martineau return 0; 41258d5a04a1SMat Martineau } 41268d5a04a1SMat Martineau 4127e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency, 4128de73115aSClaudio Takahasi u16 to_multiplier) 4129de73115aSClaudio Takahasi { 4130de73115aSClaudio Takahasi u16 max_latency; 4131de73115aSClaudio Takahasi 4132de73115aSClaudio Takahasi if (min > max || min < 6 || max > 3200) 4133de73115aSClaudio Takahasi return -EINVAL; 4134de73115aSClaudio Takahasi 4135de73115aSClaudio Takahasi if (to_multiplier < 10 || to_multiplier > 3200) 4136de73115aSClaudio Takahasi return -EINVAL; 4137de73115aSClaudio Takahasi 4138de73115aSClaudio Takahasi if (max >= to_multiplier * 8) 4139de73115aSClaudio Takahasi return -EINVAL; 4140de73115aSClaudio Takahasi 4141de73115aSClaudio Takahasi max_latency = (to_multiplier * 8 / max) - 1; 4142de73115aSClaudio Takahasi if (latency > 499 || latency > max_latency) 4143de73115aSClaudio Takahasi return -EINVAL; 4144de73115aSClaudio Takahasi 4145de73115aSClaudio Takahasi return 0; 4146de73115aSClaudio Takahasi } 4147de73115aSClaudio Takahasi 4148de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, 4149de73115aSClaudio Takahasi struct l2cap_cmd_hdr *cmd, u8 *data) 4150de73115aSClaudio Takahasi { 4151de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon; 4152de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req; 4153de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp; 4154de73115aSClaudio Takahasi u16 min, max, latency, to_multiplier, cmd_len; 41552ce603ebSClaudio Takahasi int err; 4156de73115aSClaudio Takahasi 4157de73115aSClaudio Takahasi if (!(hcon->link_mode & HCI_LM_MASTER)) 4158de73115aSClaudio Takahasi return -EINVAL; 4159de73115aSClaudio Takahasi 4160de73115aSClaudio Takahasi cmd_len = __le16_to_cpu(cmd->len); 4161de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) 4162de73115aSClaudio Takahasi return -EPROTO; 4163de73115aSClaudio Takahasi 4164de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data; 4165de73115aSClaudio Takahasi min = __le16_to_cpu(req->min); 4166de73115aSClaudio Takahasi max = __le16_to_cpu(req->max); 4167de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency); 4168de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier); 4169de73115aSClaudio Takahasi 4170de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", 4171de73115aSClaudio Takahasi min, max, latency, to_multiplier); 4172de73115aSClaudio Takahasi 4173de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp)); 41742ce603ebSClaudio Takahasi 41752ce603ebSClaudio Takahasi err = l2cap_check_conn_param(min, max, latency, to_multiplier); 41762ce603ebSClaudio Takahasi if (err) 4177de73115aSClaudio Takahasi rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); 4178de73115aSClaudio Takahasi else 4179de73115aSClaudio Takahasi rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); 4180de73115aSClaudio Takahasi 4181de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, 4182de73115aSClaudio Takahasi sizeof(rsp), &rsp); 4183de73115aSClaudio Takahasi 41842ce603ebSClaudio Takahasi if (!err) 41852ce603ebSClaudio Takahasi hci_le_conn_update(hcon, min, max, latency, to_multiplier); 41862ce603ebSClaudio Takahasi 4187de73115aSClaudio Takahasi return 0; 4188de73115aSClaudio Takahasi } 4189de73115aSClaudio Takahasi 41903300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, 41913300d9a9SClaudio Takahasi struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 41923300d9a9SClaudio Takahasi { 41933300d9a9SClaudio Takahasi int err = 0; 41943300d9a9SClaudio Takahasi 41953300d9a9SClaudio Takahasi switch (cmd->code) { 41963300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 41973300d9a9SClaudio Takahasi l2cap_command_rej(conn, cmd, data); 41983300d9a9SClaudio Takahasi break; 41993300d9a9SClaudio Takahasi 42003300d9a9SClaudio Takahasi case L2CAP_CONN_REQ: 42013300d9a9SClaudio Takahasi err = l2cap_connect_req(conn, cmd, data); 42023300d9a9SClaudio Takahasi break; 42033300d9a9SClaudio Takahasi 42043300d9a9SClaudio Takahasi case L2CAP_CONN_RSP: 42053300d9a9SClaudio Takahasi err = l2cap_connect_rsp(conn, cmd, data); 42063300d9a9SClaudio Takahasi break; 42073300d9a9SClaudio Takahasi 42083300d9a9SClaudio Takahasi case L2CAP_CONF_REQ: 42093300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data); 42103300d9a9SClaudio Takahasi break; 42113300d9a9SClaudio Takahasi 42123300d9a9SClaudio Takahasi case L2CAP_CONF_RSP: 42133300d9a9SClaudio Takahasi err = l2cap_config_rsp(conn, cmd, data); 42143300d9a9SClaudio Takahasi break; 42153300d9a9SClaudio Takahasi 42163300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ: 42173300d9a9SClaudio Takahasi err = l2cap_disconnect_req(conn, cmd, data); 42183300d9a9SClaudio Takahasi break; 42193300d9a9SClaudio Takahasi 42203300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP: 42213300d9a9SClaudio Takahasi err = l2cap_disconnect_rsp(conn, cmd, data); 42223300d9a9SClaudio Takahasi break; 42233300d9a9SClaudio Takahasi 42243300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ: 42253300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data); 42263300d9a9SClaudio Takahasi break; 42273300d9a9SClaudio Takahasi 42283300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP: 42293300d9a9SClaudio Takahasi break; 42303300d9a9SClaudio Takahasi 42313300d9a9SClaudio Takahasi case L2CAP_INFO_REQ: 42323300d9a9SClaudio Takahasi err = l2cap_information_req(conn, cmd, data); 42333300d9a9SClaudio Takahasi break; 42343300d9a9SClaudio Takahasi 42353300d9a9SClaudio Takahasi case L2CAP_INFO_RSP: 42363300d9a9SClaudio Takahasi err = l2cap_information_rsp(conn, cmd, data); 42373300d9a9SClaudio Takahasi break; 42383300d9a9SClaudio Takahasi 4239f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_REQ: 4240f94ff6ffSMat Martineau err = l2cap_create_channel_req(conn, cmd, cmd_len, data); 4241f94ff6ffSMat Martineau break; 4242f94ff6ffSMat Martineau 4243f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_RSP: 4244f94ff6ffSMat Martineau err = l2cap_create_channel_rsp(conn, cmd, data); 4245f94ff6ffSMat Martineau break; 4246f94ff6ffSMat Martineau 42478d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_REQ: 42488d5a04a1SMat Martineau err = l2cap_move_channel_req(conn, cmd, cmd_len, data); 42498d5a04a1SMat Martineau break; 42508d5a04a1SMat Martineau 42518d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_RSP: 42528d5a04a1SMat Martineau err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data); 42538d5a04a1SMat Martineau break; 42548d5a04a1SMat Martineau 42558d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM: 42568d5a04a1SMat Martineau err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data); 42578d5a04a1SMat Martineau break; 42588d5a04a1SMat Martineau 42598d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM_RSP: 42608d5a04a1SMat Martineau err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data); 42618d5a04a1SMat Martineau break; 42628d5a04a1SMat Martineau 42633300d9a9SClaudio Takahasi default: 42643300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code); 42653300d9a9SClaudio Takahasi err = -EINVAL; 42663300d9a9SClaudio Takahasi break; 42673300d9a9SClaudio Takahasi } 42683300d9a9SClaudio Takahasi 42693300d9a9SClaudio Takahasi return err; 42703300d9a9SClaudio Takahasi } 42713300d9a9SClaudio Takahasi 42723300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, 42733300d9a9SClaudio Takahasi struct l2cap_cmd_hdr *cmd, u8 *data) 42743300d9a9SClaudio Takahasi { 42753300d9a9SClaudio Takahasi switch (cmd->code) { 42763300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 42773300d9a9SClaudio Takahasi return 0; 42783300d9a9SClaudio Takahasi 42793300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ: 4280de73115aSClaudio Takahasi return l2cap_conn_param_update_req(conn, cmd, data); 42813300d9a9SClaudio Takahasi 42823300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP: 42833300d9a9SClaudio Takahasi return 0; 42843300d9a9SClaudio Takahasi 42853300d9a9SClaudio Takahasi default: 42863300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code); 42873300d9a9SClaudio Takahasi return -EINVAL; 42883300d9a9SClaudio Takahasi } 42893300d9a9SClaudio Takahasi } 42903300d9a9SClaudio Takahasi 42913300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn, 42923300d9a9SClaudio Takahasi struct sk_buff *skb) 42930a708f8fSGustavo F. Padovan { 42940a708f8fSGustavo F. Padovan u8 *data = skb->data; 42950a708f8fSGustavo F. Padovan int len = skb->len; 42960a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr cmd; 42973300d9a9SClaudio Takahasi int err; 42980a708f8fSGustavo F. Padovan 42990a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb); 43000a708f8fSGustavo F. Padovan 43010a708f8fSGustavo F. Padovan while (len >= L2CAP_CMD_HDR_SIZE) { 43020a708f8fSGustavo F. Padovan u16 cmd_len; 43030a708f8fSGustavo F. Padovan memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); 43040a708f8fSGustavo F. Padovan data += L2CAP_CMD_HDR_SIZE; 43050a708f8fSGustavo F. Padovan len -= L2CAP_CMD_HDR_SIZE; 43060a708f8fSGustavo F. Padovan 43070a708f8fSGustavo F. Padovan cmd_len = le16_to_cpu(cmd.len); 43080a708f8fSGustavo F. Padovan 43090a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident); 43100a708f8fSGustavo F. Padovan 43110a708f8fSGustavo F. Padovan if (cmd_len > len || !cmd.ident) { 43120a708f8fSGustavo F. Padovan BT_DBG("corrupted command"); 43130a708f8fSGustavo F. Padovan break; 43140a708f8fSGustavo F. Padovan } 43150a708f8fSGustavo F. Padovan 43163300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 43173300d9a9SClaudio Takahasi err = l2cap_le_sig_cmd(conn, &cmd, data); 43183300d9a9SClaudio Takahasi else 43193300d9a9SClaudio Takahasi err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data); 43200a708f8fSGustavo F. Padovan 43210a708f8fSGustavo F. Padovan if (err) { 4322e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk rej; 43232c6d1a2eSGustavo F. Padovan 43242c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err); 43250a708f8fSGustavo F. Padovan 43260a708f8fSGustavo F. Padovan /* FIXME: Map err to a valid reason */ 4327e2fd318eSIlia Kolomisnky rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 43280a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); 43290a708f8fSGustavo F. Padovan } 43300a708f8fSGustavo F. Padovan 43310a708f8fSGustavo F. Padovan data += cmd_len; 43320a708f8fSGustavo F. Padovan len -= cmd_len; 43330a708f8fSGustavo F. Padovan } 43340a708f8fSGustavo F. Padovan 43350a708f8fSGustavo F. Padovan kfree_skb(skb); 43360a708f8fSGustavo F. Padovan } 43370a708f8fSGustavo F. Padovan 433847d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) 43390a708f8fSGustavo F. Padovan { 43400a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs; 4341e4ca6d98SAndrei Emeltchenko int hdr_size; 4342e4ca6d98SAndrei Emeltchenko 4343e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 4344e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE; 4345e4ca6d98SAndrei Emeltchenko else 4346e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE; 43470a708f8fSGustavo F. Padovan 434847d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 434903a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE); 43500a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len); 43510a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); 43520a708f8fSGustavo F. Padovan 43530a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs) 43540a708f8fSGustavo F. Padovan return -EBADMSG; 43550a708f8fSGustavo F. Padovan } 43560a708f8fSGustavo F. Padovan return 0; 43570a708f8fSGustavo F. Padovan } 43580a708f8fSGustavo F. Padovan 4359525cd185SGustavo F. Padovan static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) 43600a708f8fSGustavo F. Padovan { 4361e31f7633SMat Martineau struct l2cap_ctrl control; 43620a708f8fSGustavo F. Padovan 4363e31f7633SMat Martineau BT_DBG("chan %p", chan); 43640a708f8fSGustavo F. Padovan 4365e31f7633SMat Martineau memset(&control, 0, sizeof(control)); 4366e31f7633SMat Martineau control.sframe = 1; 4367e31f7633SMat Martineau control.final = 1; 4368e31f7633SMat Martineau control.reqseq = chan->buffer_seq; 4369e31f7633SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 43700a708f8fSGustavo F. Padovan 4371e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 4372e31f7633SMat Martineau control.super = L2CAP_SUPER_RNR; 4373e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 43740a708f8fSGustavo F. Padovan } 43750a708f8fSGustavo F. Padovan 4376e31f7633SMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 4377e31f7633SMat Martineau chan->unacked_frames > 0) 4378e31f7633SMat Martineau __set_retrans_timer(chan); 43790a708f8fSGustavo F. Padovan 4380e31f7633SMat Martineau /* Send pending iframes */ 4381525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 43820a708f8fSGustavo F. Padovan 4383e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 4384e31f7633SMat Martineau test_bit(CONN_SEND_FBIT, &chan->conn_state)) { 4385e31f7633SMat Martineau /* F-bit wasn't sent in an s-frame or i-frame yet, so 4386e31f7633SMat Martineau * send it now. 4387e31f7633SMat Martineau */ 4388e31f7633SMat Martineau control.super = L2CAP_SUPER_RR; 4389e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 43900a708f8fSGustavo F. Padovan } 43910a708f8fSGustavo F. Padovan } 43920a708f8fSGustavo F. Padovan 439384084a31SMat Martineau static void append_skb_frag(struct sk_buff *skb, 439484084a31SMat Martineau struct sk_buff *new_frag, struct sk_buff **last_frag) 43950a708f8fSGustavo F. Padovan { 439684084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments 439784084a31SMat Martineau * skb->data_len reflects only data in fragments 439884084a31SMat Martineau */ 439984084a31SMat Martineau if (!skb_has_frag_list(skb)) 440084084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag; 440184084a31SMat Martineau 440284084a31SMat Martineau new_frag->next = NULL; 440384084a31SMat Martineau 440484084a31SMat Martineau (*last_frag)->next = new_frag; 440584084a31SMat Martineau *last_frag = new_frag; 440684084a31SMat Martineau 440784084a31SMat Martineau skb->len += new_frag->len; 440884084a31SMat Martineau skb->data_len += new_frag->len; 440984084a31SMat Martineau skb->truesize += new_frag->truesize; 441084084a31SMat Martineau } 441184084a31SMat Martineau 44124b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, 44134b51dae9SMat Martineau struct l2cap_ctrl *control) 441484084a31SMat Martineau { 441584084a31SMat Martineau int err = -EINVAL; 44160a708f8fSGustavo F. Padovan 44174b51dae9SMat Martineau switch (control->sar) { 44187e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED: 441984084a31SMat Martineau if (chan->sdu) 442084084a31SMat Martineau break; 44210a708f8fSGustavo F. Padovan 442284084a31SMat Martineau err = chan->ops->recv(chan->data, skb); 442384084a31SMat Martineau break; 44240a708f8fSGustavo F. Padovan 44257e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START: 442684084a31SMat Martineau if (chan->sdu) 442784084a31SMat Martineau break; 44280a708f8fSGustavo F. Padovan 44296f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data); 443003a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE); 44310a708f8fSGustavo F. Padovan 443284084a31SMat Martineau if (chan->sdu_len > chan->imtu) { 443384084a31SMat Martineau err = -EMSGSIZE; 443484084a31SMat Martineau break; 443584084a31SMat Martineau } 44360a708f8fSGustavo F. Padovan 443784084a31SMat Martineau if (skb->len >= chan->sdu_len) 443884084a31SMat Martineau break; 443984084a31SMat Martineau 444084084a31SMat Martineau chan->sdu = skb; 444184084a31SMat Martineau chan->sdu_last_frag = skb; 444284084a31SMat Martineau 444384084a31SMat Martineau skb = NULL; 444484084a31SMat Martineau err = 0; 44450a708f8fSGustavo F. Padovan break; 44460a708f8fSGustavo F. Padovan 44477e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE: 44486f61fd47SGustavo F. Padovan if (!chan->sdu) 444984084a31SMat Martineau break; 44500a708f8fSGustavo F. Padovan 445184084a31SMat Martineau append_skb_frag(chan->sdu, skb, 445284084a31SMat Martineau &chan->sdu_last_frag); 445384084a31SMat Martineau skb = NULL; 44540a708f8fSGustavo F. Padovan 445584084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len) 445684084a31SMat Martineau break; 44570a708f8fSGustavo F. Padovan 445884084a31SMat Martineau err = 0; 44590a708f8fSGustavo F. Padovan break; 44600a708f8fSGustavo F. Padovan 44617e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END: 44626f61fd47SGustavo F. Padovan if (!chan->sdu) 446384084a31SMat Martineau break; 44640a708f8fSGustavo F. Padovan 446584084a31SMat Martineau append_skb_frag(chan->sdu, skb, 446684084a31SMat Martineau &chan->sdu_last_frag); 446784084a31SMat Martineau skb = NULL; 44680a708f8fSGustavo F. Padovan 446984084a31SMat Martineau if (chan->sdu->len != chan->sdu_len) 447084084a31SMat Martineau break; 44710a708f8fSGustavo F. Padovan 447284084a31SMat Martineau err = chan->ops->recv(chan->data, chan->sdu); 44730a708f8fSGustavo F. Padovan 447484084a31SMat Martineau if (!err) { 447584084a31SMat Martineau /* Reassembly complete */ 447684084a31SMat Martineau chan->sdu = NULL; 447784084a31SMat Martineau chan->sdu_last_frag = NULL; 447884084a31SMat Martineau chan->sdu_len = 0; 44790a708f8fSGustavo F. Padovan } 44800a708f8fSGustavo F. Padovan break; 44810a708f8fSGustavo F. Padovan } 44820a708f8fSGustavo F. Padovan 448384084a31SMat Martineau if (err) { 44840a708f8fSGustavo F. Padovan kfree_skb(skb); 44856f61fd47SGustavo F. Padovan kfree_skb(chan->sdu); 44866f61fd47SGustavo F. Padovan chan->sdu = NULL; 448784084a31SMat Martineau chan->sdu_last_frag = NULL; 448884084a31SMat Martineau chan->sdu_len = 0; 448984084a31SMat Martineau } 44900a708f8fSGustavo F. Padovan 449184084a31SMat Martineau return err; 44920a708f8fSGustavo F. Padovan } 44930a708f8fSGustavo F. Padovan 4494e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 44950a708f8fSGustavo F. Padovan { 449661aa4f5bSMat Martineau u8 event; 449761aa4f5bSMat Martineau 449861aa4f5bSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 449961aa4f5bSMat Martineau return; 450061aa4f5bSMat Martineau 450161aa4f5bSMat Martineau event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR; 450261aa4f5bSMat Martineau l2cap_tx(chan, 0, 0, event); 45030a708f8fSGustavo F. Padovan } 45040a708f8fSGustavo F. Padovan 4505d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan) 4506d2a7ac5dSMat Martineau { 450763838725SMat Martineau int err = 0; 450863838725SMat Martineau /* Pass sequential frames to l2cap_reassemble_sdu() 450963838725SMat Martineau * until a gap is encountered. 451063838725SMat Martineau */ 451163838725SMat Martineau 451263838725SMat Martineau BT_DBG("chan %p", chan); 451363838725SMat Martineau 451463838725SMat Martineau while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 451563838725SMat Martineau struct sk_buff *skb; 451663838725SMat Martineau BT_DBG("Searching for skb with txseq %d (queue len %d)", 451763838725SMat Martineau chan->buffer_seq, skb_queue_len(&chan->srej_q)); 451863838725SMat Martineau 451963838725SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq); 452063838725SMat Martineau 452163838725SMat Martineau if (!skb) 452263838725SMat Martineau break; 452363838725SMat Martineau 452463838725SMat Martineau skb_unlink(skb, &chan->srej_q); 452563838725SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 452663838725SMat Martineau err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->control); 452763838725SMat Martineau if (err) 452863838725SMat Martineau break; 452963838725SMat Martineau } 453063838725SMat Martineau 453163838725SMat Martineau if (skb_queue_empty(&chan->srej_q)) { 453263838725SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 453363838725SMat Martineau l2cap_send_ack(chan); 453463838725SMat Martineau } 453563838725SMat Martineau 453663838725SMat Martineau return err; 4537d2a7ac5dSMat Martineau } 4538d2a7ac5dSMat Martineau 4539d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan, 4540d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 4541d2a7ac5dSMat Martineau { 4542d2a7ac5dSMat Martineau /* Placeholder */ 4543d2a7ac5dSMat Martineau } 4544d2a7ac5dSMat Martineau 4545d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan, 4546d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 4547d2a7ac5dSMat Martineau { 4548d2a7ac5dSMat Martineau /* Placeholder */ 4549d2a7ac5dSMat Martineau } 4550d2a7ac5dSMat Martineau 45514b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) 45524b51dae9SMat Martineau { 45534b51dae9SMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 45544b51dae9SMat Martineau 45554b51dae9SMat Martineau BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq, 45564b51dae9SMat Martineau chan->expected_tx_seq); 45574b51dae9SMat Martineau 45584b51dae9SMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 45594b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 45604b51dae9SMat Martineau chan->tx_win) { 45614b51dae9SMat Martineau /* See notes below regarding "double poll" and 45624b51dae9SMat Martineau * invalid packets. 45634b51dae9SMat Martineau */ 45644b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 45654b51dae9SMat Martineau BT_DBG("Invalid/Ignore - after SREJ"); 45664b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 45674b51dae9SMat Martineau } else { 45684b51dae9SMat Martineau BT_DBG("Invalid - in window after SREJ sent"); 45694b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 45704b51dae9SMat Martineau } 45714b51dae9SMat Martineau } 45724b51dae9SMat Martineau 45734b51dae9SMat Martineau if (chan->srej_list.head == txseq) { 45744b51dae9SMat Martineau BT_DBG("Expected SREJ"); 45754b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED_SREJ; 45764b51dae9SMat Martineau } 45774b51dae9SMat Martineau 45784b51dae9SMat Martineau if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) { 45794b51dae9SMat Martineau BT_DBG("Duplicate SREJ - txseq already stored"); 45804b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE_SREJ; 45814b51dae9SMat Martineau } 45824b51dae9SMat Martineau 45834b51dae9SMat Martineau if (l2cap_seq_list_contains(&chan->srej_list, txseq)) { 45844b51dae9SMat Martineau BT_DBG("Unexpected SREJ - not requested"); 45854b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED_SREJ; 45864b51dae9SMat Martineau } 45874b51dae9SMat Martineau } 45884b51dae9SMat Martineau 45894b51dae9SMat Martineau if (chan->expected_tx_seq == txseq) { 45904b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 45914b51dae9SMat Martineau chan->tx_win) { 45924b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 45934b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 45944b51dae9SMat Martineau } else { 45954b51dae9SMat Martineau BT_DBG("Expected"); 45964b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED; 45974b51dae9SMat Martineau } 45984b51dae9SMat Martineau } 45994b51dae9SMat Martineau 46004b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) < 46014b51dae9SMat Martineau __seq_offset(chan, chan->expected_tx_seq, 46024b51dae9SMat Martineau chan->last_acked_seq)){ 46034b51dae9SMat Martineau BT_DBG("Duplicate - expected_tx_seq later than txseq"); 46044b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE; 46054b51dae9SMat Martineau } 46064b51dae9SMat Martineau 46074b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) { 46084b51dae9SMat Martineau /* A source of invalid packets is a "double poll" condition, 46094b51dae9SMat Martineau * where delays cause us to send multiple poll packets. If 46104b51dae9SMat Martineau * the remote stack receives and processes both polls, 46114b51dae9SMat Martineau * sequence numbers can wrap around in such a way that a 46124b51dae9SMat Martineau * resent frame has a sequence number that looks like new data 46134b51dae9SMat Martineau * with a sequence gap. This would trigger an erroneous SREJ 46144b51dae9SMat Martineau * request. 46154b51dae9SMat Martineau * 46164b51dae9SMat Martineau * Fortunately, this is impossible with a tx window that's 46174b51dae9SMat Martineau * less than half of the maximum sequence number, which allows 46184b51dae9SMat Martineau * invalid frames to be safely ignored. 46194b51dae9SMat Martineau * 46204b51dae9SMat Martineau * With tx window sizes greater than half of the tx window 46214b51dae9SMat Martineau * maximum, the frame is invalid and cannot be ignored. This 46224b51dae9SMat Martineau * causes a disconnect. 46234b51dae9SMat Martineau */ 46244b51dae9SMat Martineau 46254b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 46264b51dae9SMat Martineau BT_DBG("Invalid/Ignore - txseq outside tx window"); 46274b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 46284b51dae9SMat Martineau } else { 46294b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 46304b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 46314b51dae9SMat Martineau } 46324b51dae9SMat Martineau } else { 46334b51dae9SMat Martineau BT_DBG("Unexpected - txseq indicates missing frames"); 46344b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED; 46354b51dae9SMat Martineau } 46364b51dae9SMat Martineau } 46374b51dae9SMat Martineau 4638d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan, 4639d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 4640d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 4641d2a7ac5dSMat Martineau { 4642d2a7ac5dSMat Martineau int err = 0; 4643d2a7ac5dSMat Martineau bool skb_in_use = 0; 4644d2a7ac5dSMat Martineau 4645d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 4646d2a7ac5dSMat Martineau event); 4647d2a7ac5dSMat Martineau 4648d2a7ac5dSMat Martineau switch (event) { 4649d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 4650d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, control->txseq)) { 4651d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 4652d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4653d2a7ac5dSMat Martineau 4654d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 4655d2a7ac5dSMat Martineau BT_DBG("Busy, discarding expected seq %d", 4656d2a7ac5dSMat Martineau control->txseq); 4657d2a7ac5dSMat Martineau break; 4658d2a7ac5dSMat Martineau } 4659d2a7ac5dSMat Martineau 4660d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, 4661d2a7ac5dSMat Martineau control->txseq); 4662d2a7ac5dSMat Martineau 4663d2a7ac5dSMat Martineau chan->buffer_seq = chan->expected_tx_seq; 4664d2a7ac5dSMat Martineau skb_in_use = 1; 4665d2a7ac5dSMat Martineau 4666d2a7ac5dSMat Martineau err = l2cap_reassemble_sdu(chan, skb, control); 4667d2a7ac5dSMat Martineau if (err) 4668d2a7ac5dSMat Martineau break; 4669d2a7ac5dSMat Martineau 4670d2a7ac5dSMat Martineau if (control->final) { 4671d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 4672d2a7ac5dSMat Martineau &chan->conn_state)) { 4673d2a7ac5dSMat Martineau control->final = 0; 4674d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 4675d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 4676d2a7ac5dSMat Martineau } 4677d2a7ac5dSMat Martineau } 4678d2a7ac5dSMat Martineau 4679d2a7ac5dSMat Martineau if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 4680d2a7ac5dSMat Martineau l2cap_send_ack(chan); 4681d2a7ac5dSMat Martineau break; 4682d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 4683d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4684d2a7ac5dSMat Martineau 4685d2a7ac5dSMat Martineau /* Can't issue SREJ frames in the local busy state. 4686d2a7ac5dSMat Martineau * Drop this frame, it will be seen as missing 4687d2a7ac5dSMat Martineau * when local busy is exited. 4688d2a7ac5dSMat Martineau */ 4689d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 4690d2a7ac5dSMat Martineau BT_DBG("Busy, discarding unexpected seq %d", 4691d2a7ac5dSMat Martineau control->txseq); 4692d2a7ac5dSMat Martineau break; 4693d2a7ac5dSMat Martineau } 4694d2a7ac5dSMat Martineau 4695d2a7ac5dSMat Martineau /* There was a gap in the sequence, so an SREJ 4696d2a7ac5dSMat Martineau * must be sent for each missing frame. The 4697d2a7ac5dSMat Martineau * current frame is stored for later use. 4698d2a7ac5dSMat Martineau */ 4699d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4700d2a7ac5dSMat Martineau skb_in_use = 1; 4701d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4702d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4703d2a7ac5dSMat Martineau 4704d2a7ac5dSMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 4705d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 4706d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 4707d2a7ac5dSMat Martineau 4708d2a7ac5dSMat Martineau chan->rx_state = L2CAP_RX_STATE_SREJ_SENT; 4709d2a7ac5dSMat Martineau break; 4710d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 4711d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4712d2a7ac5dSMat Martineau break; 4713d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 4714d2a7ac5dSMat Martineau break; 4715d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 4716d2a7ac5dSMat Martineau default: 4717d2a7ac5dSMat Martineau l2cap_send_disconn_req(chan->conn, chan, 4718d2a7ac5dSMat Martineau ECONNRESET); 4719d2a7ac5dSMat Martineau break; 4720d2a7ac5dSMat Martineau } 4721d2a7ac5dSMat Martineau break; 4722d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 4723d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4724d2a7ac5dSMat Martineau if (control->final) { 4725d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4726d2a7ac5dSMat Martineau 4727d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 4728d2a7ac5dSMat Martineau &chan->conn_state)) { 4729d2a7ac5dSMat Martineau control->final = 0; 4730d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 4731d2a7ac5dSMat Martineau } 4732d2a7ac5dSMat Martineau 4733d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 4734d2a7ac5dSMat Martineau } else if (control->poll) { 4735d2a7ac5dSMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 4736d2a7ac5dSMat Martineau } else { 4737d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 4738d2a7ac5dSMat Martineau &chan->conn_state) && 4739d2a7ac5dSMat Martineau chan->unacked_frames) 4740d2a7ac5dSMat Martineau __set_retrans_timer(chan); 4741d2a7ac5dSMat Martineau 4742d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 4743d2a7ac5dSMat Martineau } 4744d2a7ac5dSMat Martineau break; 4745d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 4746d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4747d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4748d2a7ac5dSMat Martineau if (control && control->poll) { 4749d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 4750d2a7ac5dSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 4751d2a7ac5dSMat Martineau } 4752d2a7ac5dSMat Martineau __clear_retrans_timer(chan); 4753d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 4754d2a7ac5dSMat Martineau break; 4755d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 4756d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 4757d2a7ac5dSMat Martineau break; 4758d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 4759d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 4760d2a7ac5dSMat Martineau break; 4761d2a7ac5dSMat Martineau default: 4762d2a7ac5dSMat Martineau break; 4763d2a7ac5dSMat Martineau } 4764d2a7ac5dSMat Martineau 4765d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 4766d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 4767d2a7ac5dSMat Martineau kfree_skb(skb); 4768d2a7ac5dSMat Martineau } 4769d2a7ac5dSMat Martineau 4770d2a7ac5dSMat Martineau return err; 4771d2a7ac5dSMat Martineau } 4772d2a7ac5dSMat Martineau 4773d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, 4774d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 4775d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 4776d2a7ac5dSMat Martineau { 4777d2a7ac5dSMat Martineau int err = 0; 4778d2a7ac5dSMat Martineau u16 txseq = control->txseq; 4779d2a7ac5dSMat Martineau bool skb_in_use = 0; 4780d2a7ac5dSMat Martineau 4781d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 4782d2a7ac5dSMat Martineau event); 4783d2a7ac5dSMat Martineau 4784d2a7ac5dSMat Martineau switch (event) { 4785d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 4786d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, txseq)) { 4787d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 4788d2a7ac5dSMat Martineau /* Keep frame for reassembly later */ 4789d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4790d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4791d2a7ac5dSMat Martineau skb_in_use = 1; 4792d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4793d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4794d2a7ac5dSMat Martineau 4795d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 4796d2a7ac5dSMat Martineau break; 4797d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED_SREJ: 4798d2a7ac5dSMat Martineau l2cap_seq_list_pop(&chan->srej_list); 4799d2a7ac5dSMat Martineau 4800d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4801d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4802d2a7ac5dSMat Martineau skb_in_use = 1; 4803d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4804d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4805d2a7ac5dSMat Martineau 4806d2a7ac5dSMat Martineau err = l2cap_rx_queued_iframes(chan); 4807d2a7ac5dSMat Martineau if (err) 4808d2a7ac5dSMat Martineau break; 4809d2a7ac5dSMat Martineau 4810d2a7ac5dSMat Martineau break; 4811d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 4812d2a7ac5dSMat Martineau /* Got a frame that can't be reassembled yet. 4813d2a7ac5dSMat Martineau * Save it for later, and send SREJs to cover 4814d2a7ac5dSMat Martineau * the missing frames. 4815d2a7ac5dSMat Martineau */ 4816d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4817d2a7ac5dSMat Martineau skb_in_use = 1; 4818d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4819d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4820d2a7ac5dSMat Martineau 4821d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4822d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 4823d2a7ac5dSMat Martineau break; 4824d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED_SREJ: 4825d2a7ac5dSMat Martineau /* This frame was requested with an SREJ, but 4826d2a7ac5dSMat Martineau * some expected retransmitted frames are 4827d2a7ac5dSMat Martineau * missing. Request retransmission of missing 4828d2a7ac5dSMat Martineau * SREJ'd frames. 4829d2a7ac5dSMat Martineau */ 4830d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4831d2a7ac5dSMat Martineau skb_in_use = 1; 4832d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4833d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4834d2a7ac5dSMat Martineau 4835d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4836d2a7ac5dSMat Martineau l2cap_send_srej_list(chan, control->txseq); 4837d2a7ac5dSMat Martineau break; 4838d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE_SREJ: 4839d2a7ac5dSMat Martineau /* We've already queued this frame. Drop this copy. */ 4840d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4841d2a7ac5dSMat Martineau break; 4842d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 4843d2a7ac5dSMat Martineau /* Expecting a later sequence number, so this frame 4844d2a7ac5dSMat Martineau * was already received. Ignore it completely. 4845d2a7ac5dSMat Martineau */ 4846d2a7ac5dSMat Martineau break; 4847d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 4848d2a7ac5dSMat Martineau break; 4849d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 4850d2a7ac5dSMat Martineau default: 4851d2a7ac5dSMat Martineau l2cap_send_disconn_req(chan->conn, chan, 4852d2a7ac5dSMat Martineau ECONNRESET); 4853d2a7ac5dSMat Martineau break; 4854d2a7ac5dSMat Martineau } 4855d2a7ac5dSMat Martineau break; 4856d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 4857d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4858d2a7ac5dSMat Martineau if (control->final) { 4859d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4860d2a7ac5dSMat Martineau 4861d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 4862d2a7ac5dSMat Martineau &chan->conn_state)) { 4863d2a7ac5dSMat Martineau control->final = 0; 4864d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 4865d2a7ac5dSMat Martineau } 4866d2a7ac5dSMat Martineau 4867d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 4868d2a7ac5dSMat Martineau } else if (control->poll) { 4869d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 4870d2a7ac5dSMat Martineau &chan->conn_state) && 4871d2a7ac5dSMat Martineau chan->unacked_frames) { 4872d2a7ac5dSMat Martineau __set_retrans_timer(chan); 4873d2a7ac5dSMat Martineau } 4874d2a7ac5dSMat Martineau 4875d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 4876d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 4877d2a7ac5dSMat Martineau } else { 4878d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 4879d2a7ac5dSMat Martineau &chan->conn_state) && 4880d2a7ac5dSMat Martineau chan->unacked_frames) 4881d2a7ac5dSMat Martineau __set_retrans_timer(chan); 4882d2a7ac5dSMat Martineau 4883d2a7ac5dSMat Martineau l2cap_send_ack(chan); 4884d2a7ac5dSMat Martineau } 4885d2a7ac5dSMat Martineau break; 4886d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 4887d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4888d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4889d2a7ac5dSMat Martineau if (control->poll) { 4890d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 4891d2a7ac5dSMat Martineau } else { 4892d2a7ac5dSMat Martineau struct l2cap_ctrl rr_control; 4893d2a7ac5dSMat Martineau memset(&rr_control, 0, sizeof(rr_control)); 4894d2a7ac5dSMat Martineau rr_control.sframe = 1; 4895d2a7ac5dSMat Martineau rr_control.super = L2CAP_SUPER_RR; 4896d2a7ac5dSMat Martineau rr_control.reqseq = chan->buffer_seq; 4897d2a7ac5dSMat Martineau l2cap_send_sframe(chan, &rr_control); 4898d2a7ac5dSMat Martineau } 4899d2a7ac5dSMat Martineau 4900d2a7ac5dSMat Martineau break; 4901d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 4902d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 4903d2a7ac5dSMat Martineau break; 4904d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 4905d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 4906d2a7ac5dSMat Martineau break; 4907d2a7ac5dSMat Martineau } 4908d2a7ac5dSMat Martineau 4909d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 4910d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 4911d2a7ac5dSMat Martineau kfree_skb(skb); 4912d2a7ac5dSMat Martineau } 4913d2a7ac5dSMat Martineau 4914d2a7ac5dSMat Martineau return err; 4915d2a7ac5dSMat Martineau } 4916d2a7ac5dSMat Martineau 4917d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq) 4918d2a7ac5dSMat Martineau { 4919d2a7ac5dSMat Martineau /* Make sure reqseq is for a packet that has been sent but not acked */ 4920d2a7ac5dSMat Martineau u16 unacked; 4921d2a7ac5dSMat Martineau 4922d2a7ac5dSMat Martineau unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq); 4923d2a7ac5dSMat Martineau return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked; 4924d2a7ac5dSMat Martineau } 4925d2a7ac5dSMat Martineau 4926cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 4927cec8ab6eSMat Martineau struct sk_buff *skb, u8 event) 49280a708f8fSGustavo F. Padovan { 4929d2a7ac5dSMat Martineau int err = 0; 4930d2a7ac5dSMat Martineau 4931d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan, 4932d2a7ac5dSMat Martineau control, skb, event, chan->rx_state); 4933d2a7ac5dSMat Martineau 4934d2a7ac5dSMat Martineau if (__valid_reqseq(chan, control->reqseq)) { 4935d2a7ac5dSMat Martineau switch (chan->rx_state) { 4936d2a7ac5dSMat Martineau case L2CAP_RX_STATE_RECV: 4937d2a7ac5dSMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 4938d2a7ac5dSMat Martineau break; 4939d2a7ac5dSMat Martineau case L2CAP_RX_STATE_SREJ_SENT: 4940d2a7ac5dSMat Martineau err = l2cap_rx_state_srej_sent(chan, control, skb, 4941d2a7ac5dSMat Martineau event); 4942d2a7ac5dSMat Martineau break; 4943d2a7ac5dSMat Martineau default: 4944d2a7ac5dSMat Martineau /* shut it down */ 4945d2a7ac5dSMat Martineau break; 4946d2a7ac5dSMat Martineau } 4947d2a7ac5dSMat Martineau } else { 4948d2a7ac5dSMat Martineau BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d", 4949d2a7ac5dSMat Martineau control->reqseq, chan->next_tx_seq, 4950d2a7ac5dSMat Martineau chan->expected_ack_seq); 4951d2a7ac5dSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 4952d2a7ac5dSMat Martineau } 4953d2a7ac5dSMat Martineau 4954d2a7ac5dSMat Martineau return err; 4955cec8ab6eSMat Martineau } 4956cec8ab6eSMat Martineau 4957cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 4958cec8ab6eSMat Martineau struct sk_buff *skb) 4959cec8ab6eSMat Martineau { 49604b51dae9SMat Martineau int err = 0; 49614b51dae9SMat Martineau 49624b51dae9SMat Martineau BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb, 49634b51dae9SMat Martineau chan->rx_state); 49644b51dae9SMat Martineau 49654b51dae9SMat Martineau if (l2cap_classify_txseq(chan, control->txseq) == 49664b51dae9SMat Martineau L2CAP_TXSEQ_EXPECTED) { 49674b51dae9SMat Martineau l2cap_pass_to_tx(chan, control); 49684b51dae9SMat Martineau 49694b51dae9SMat Martineau BT_DBG("buffer_seq %d->%d", chan->buffer_seq, 49704b51dae9SMat Martineau __next_seq(chan, chan->buffer_seq)); 49714b51dae9SMat Martineau 49724b51dae9SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 49734b51dae9SMat Martineau 49744b51dae9SMat Martineau l2cap_reassemble_sdu(chan, skb, control); 49754b51dae9SMat Martineau } else { 49764b51dae9SMat Martineau if (chan->sdu) { 49774b51dae9SMat Martineau kfree_skb(chan->sdu); 49784b51dae9SMat Martineau chan->sdu = NULL; 49794b51dae9SMat Martineau } 49804b51dae9SMat Martineau chan->sdu_last_frag = NULL; 49814b51dae9SMat Martineau chan->sdu_len = 0; 49824b51dae9SMat Martineau 49834b51dae9SMat Martineau if (skb) { 49844b51dae9SMat Martineau BT_DBG("Freeing %p", skb); 49854b51dae9SMat Martineau kfree_skb(skb); 49864b51dae9SMat Martineau } 49874b51dae9SMat Martineau } 49884b51dae9SMat Martineau 49894b51dae9SMat Martineau chan->last_acked_seq = control->txseq; 49904b51dae9SMat Martineau chan->expected_tx_seq = __next_seq(chan, control->txseq); 49914b51dae9SMat Martineau 49924b51dae9SMat Martineau return err; 4993cec8ab6eSMat Martineau } 4994cec8ab6eSMat Martineau 4995cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 4996cec8ab6eSMat Martineau { 4997cec8ab6eSMat Martineau struct l2cap_ctrl *control = &bt_cb(skb)->control; 4998cec8ab6eSMat Martineau u16 len; 4999cec8ab6eSMat Martineau u8 event; 50000a708f8fSGustavo F. Padovan 5001b76bbd66SMat Martineau __unpack_control(chan, skb); 5002b76bbd66SMat Martineau 50030a708f8fSGustavo F. Padovan len = skb->len; 50040a708f8fSGustavo F. Padovan 50050a708f8fSGustavo F. Padovan /* 50060a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here. 50070a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery 5008cec8ab6eSMat Martineau * procedures and ask for retransmission. 50090a708f8fSGustavo F. Padovan */ 501047d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 50110a708f8fSGustavo F. Padovan goto drop; 50120a708f8fSGustavo F. Padovan 5013cec8ab6eSMat Martineau if (!control->sframe && control->sar == L2CAP_SAR_START) 501403a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 50150a708f8fSGustavo F. Padovan 501647d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 501703a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 50180a708f8fSGustavo F. Padovan 501947d1ec61SGustavo F. Padovan if (len > chan->mps) { 50208c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 50210a708f8fSGustavo F. Padovan goto drop; 50220a708f8fSGustavo F. Padovan } 50230a708f8fSGustavo F. Padovan 5024cec8ab6eSMat Martineau if (!control->sframe) { 5025cec8ab6eSMat Martineau int err; 50260a708f8fSGustavo F. Padovan 5027cec8ab6eSMat Martineau BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d", 5028cec8ab6eSMat Martineau control->sar, control->reqseq, control->final, 5029cec8ab6eSMat Martineau control->txseq); 5030836be934SAndrei Emeltchenko 5031cec8ab6eSMat Martineau /* Validate F-bit - F=0 always valid, F=1 only 5032cec8ab6eSMat Martineau * valid in TX WAIT_F 5033cec8ab6eSMat Martineau */ 5034cec8ab6eSMat Martineau if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F) 50350a708f8fSGustavo F. Padovan goto drop; 50360a708f8fSGustavo F. Padovan 5037cec8ab6eSMat Martineau if (chan->mode != L2CAP_MODE_STREAMING) { 5038cec8ab6eSMat Martineau event = L2CAP_EV_RECV_IFRAME; 5039cec8ab6eSMat Martineau err = l2cap_rx(chan, control, skb, event); 50400a708f8fSGustavo F. Padovan } else { 5041cec8ab6eSMat Martineau err = l2cap_stream_rx(chan, control, skb); 5042cec8ab6eSMat Martineau } 5043cec8ab6eSMat Martineau 5044cec8ab6eSMat Martineau if (err) 5045cec8ab6eSMat Martineau l2cap_send_disconn_req(chan->conn, chan, 5046cec8ab6eSMat Martineau ECONNRESET); 5047cec8ab6eSMat Martineau } else { 5048cec8ab6eSMat Martineau const u8 rx_func_to_event[4] = { 5049cec8ab6eSMat Martineau L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ, 5050cec8ab6eSMat Martineau L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ 5051cec8ab6eSMat Martineau }; 5052cec8ab6eSMat Martineau 5053cec8ab6eSMat Martineau /* Only I-frames are expected in streaming mode */ 5054cec8ab6eSMat Martineau if (chan->mode == L2CAP_MODE_STREAMING) 5055cec8ab6eSMat Martineau goto drop; 5056cec8ab6eSMat Martineau 5057cec8ab6eSMat Martineau BT_DBG("sframe reqseq %d, final %d, poll %d, super %d", 5058cec8ab6eSMat Martineau control->reqseq, control->final, control->poll, 5059cec8ab6eSMat Martineau control->super); 5060cec8ab6eSMat Martineau 50610a708f8fSGustavo F. Padovan if (len != 0) { 50620a708f8fSGustavo F. Padovan BT_ERR("%d", len); 50638c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 50640a708f8fSGustavo F. Padovan goto drop; 50650a708f8fSGustavo F. Padovan } 50660a708f8fSGustavo F. Padovan 5067cec8ab6eSMat Martineau /* Validate F and P bits */ 5068cec8ab6eSMat Martineau if (control->final && (control->poll || 5069cec8ab6eSMat Martineau chan->tx_state != L2CAP_TX_STATE_WAIT_F)) 5070cec8ab6eSMat Martineau goto drop; 5071cec8ab6eSMat Martineau 5072cec8ab6eSMat Martineau event = rx_func_to_event[control->super]; 5073cec8ab6eSMat Martineau if (l2cap_rx(chan, control, skb, event)) 5074cec8ab6eSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 50750a708f8fSGustavo F. Padovan } 50760a708f8fSGustavo F. Padovan 50770a708f8fSGustavo F. Padovan return 0; 50780a708f8fSGustavo F. Padovan 50790a708f8fSGustavo F. Padovan drop: 50800a708f8fSGustavo F. Padovan kfree_skb(skb); 50810a708f8fSGustavo F. Padovan return 0; 50820a708f8fSGustavo F. Padovan } 50830a708f8fSGustavo F. Padovan 50840a708f8fSGustavo F. Padovan static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb) 50850a708f8fSGustavo F. Padovan { 508648454079SGustavo F. Padovan struct l2cap_chan *chan; 50870a708f8fSGustavo F. Padovan 5088baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 508948454079SGustavo F. Padovan if (!chan) { 50900a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid); 50916be36555SAndrei Emeltchenko /* Drop packet and return */ 50923379013bSDan Carpenter kfree_skb(skb); 50936be36555SAndrei Emeltchenko return 0; 50940a708f8fSGustavo F. Padovan } 50950a708f8fSGustavo F. Padovan 509649208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len); 50970a708f8fSGustavo F. Padovan 509889bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 50990a708f8fSGustavo F. Padovan goto drop; 51000a708f8fSGustavo F. Padovan 51010c1bc5c6SGustavo F. Padovan switch (chan->mode) { 51020a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 51030a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here 51040a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable. 51050a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't 51060a708f8fSGustavo F. Padovan * provide flow control mechanism. */ 51070a708f8fSGustavo F. Padovan 51080c1bc5c6SGustavo F. Padovan if (chan->imtu < skb->len) 51090a708f8fSGustavo F. Padovan goto drop; 51100a708f8fSGustavo F. Padovan 511123070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 51120a708f8fSGustavo F. Padovan goto done; 51130a708f8fSGustavo F. Padovan break; 51140a708f8fSGustavo F. Padovan 51150a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 51160a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 5117cec8ab6eSMat Martineau l2cap_data_rcv(chan, skb); 51180a708f8fSGustavo F. Padovan goto done; 51190a708f8fSGustavo F. Padovan 51200a708f8fSGustavo F. Padovan default: 51210c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); 51220a708f8fSGustavo F. Padovan break; 51230a708f8fSGustavo F. Padovan } 51240a708f8fSGustavo F. Padovan 51250a708f8fSGustavo F. Padovan drop: 51260a708f8fSGustavo F. Padovan kfree_skb(skb); 51270a708f8fSGustavo F. Padovan 51280a708f8fSGustavo F. Padovan done: 51296be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 51300a708f8fSGustavo F. Padovan 51310a708f8fSGustavo F. Padovan return 0; 51320a708f8fSGustavo F. Padovan } 51330a708f8fSGustavo F. Padovan 51340a708f8fSGustavo F. Padovan static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb) 51350a708f8fSGustavo F. Padovan { 513623691d75SGustavo F. Padovan struct l2cap_chan *chan; 51370a708f8fSGustavo F. Padovan 5138c2287681SIdo Yariv chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst); 513923691d75SGustavo F. Padovan if (!chan) 51400a708f8fSGustavo F. Padovan goto drop; 51410a708f8fSGustavo F. Padovan 51425b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 51430a708f8fSGustavo F. Padovan 514489bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 51450a708f8fSGustavo F. Padovan goto drop; 51460a708f8fSGustavo F. Padovan 5147e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 51480a708f8fSGustavo F. Padovan goto drop; 51490a708f8fSGustavo F. Padovan 515023070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 51515b4cedaaSAndrei Emeltchenko return 0; 51520a708f8fSGustavo F. Padovan 51530a708f8fSGustavo F. Padovan drop: 51540a708f8fSGustavo F. Padovan kfree_skb(skb); 51550a708f8fSGustavo F. Padovan 51560a708f8fSGustavo F. Padovan return 0; 51570a708f8fSGustavo F. Padovan } 51580a708f8fSGustavo F. Padovan 5159d9b88702SAndrei Emeltchenko static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid, 5160d9b88702SAndrei Emeltchenko struct sk_buff *skb) 51619f69bda6SGustavo F. Padovan { 516223691d75SGustavo F. Padovan struct l2cap_chan *chan; 51639f69bda6SGustavo F. Padovan 5164c2287681SIdo Yariv chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst); 516523691d75SGustavo F. Padovan if (!chan) 51669f69bda6SGustavo F. Padovan goto drop; 51679f69bda6SGustavo F. Padovan 51685b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 51699f69bda6SGustavo F. Padovan 517089bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 51719f69bda6SGustavo F. Padovan goto drop; 51729f69bda6SGustavo F. Padovan 5173e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 51749f69bda6SGustavo F. Padovan goto drop; 51759f69bda6SGustavo F. Padovan 517623070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 51775b4cedaaSAndrei Emeltchenko return 0; 51789f69bda6SGustavo F. Padovan 51799f69bda6SGustavo F. Padovan drop: 51809f69bda6SGustavo F. Padovan kfree_skb(skb); 51819f69bda6SGustavo F. Padovan 51829f69bda6SGustavo F. Padovan return 0; 51839f69bda6SGustavo F. Padovan } 51849f69bda6SGustavo F. Padovan 51850a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) 51860a708f8fSGustavo F. Padovan { 51870a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data; 51880a708f8fSGustavo F. Padovan u16 cid, len; 51890a708f8fSGustavo F. Padovan __le16 psm; 51900a708f8fSGustavo F. Padovan 51910a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE); 51920a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid); 51930a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len); 51940a708f8fSGustavo F. Padovan 51950a708f8fSGustavo F. Padovan if (len != skb->len) { 51960a708f8fSGustavo F. Padovan kfree_skb(skb); 51970a708f8fSGustavo F. Padovan return; 51980a708f8fSGustavo F. Padovan } 51990a708f8fSGustavo F. Padovan 52000a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid); 52010a708f8fSGustavo F. Padovan 52020a708f8fSGustavo F. Padovan switch (cid) { 52033300d9a9SClaudio Takahasi case L2CAP_CID_LE_SIGNALING: 52040a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING: 52050a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb); 52060a708f8fSGustavo F. Padovan break; 52070a708f8fSGustavo F. Padovan 52080a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS: 5209097db76cSAndrei Emeltchenko psm = get_unaligned((__le16 *) skb->data); 52100a708f8fSGustavo F. Padovan skb_pull(skb, 2); 52110a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb); 52120a708f8fSGustavo F. Padovan break; 52130a708f8fSGustavo F. Padovan 52149f69bda6SGustavo F. Padovan case L2CAP_CID_LE_DATA: 52159f69bda6SGustavo F. Padovan l2cap_att_channel(conn, cid, skb); 52169f69bda6SGustavo F. Padovan break; 52179f69bda6SGustavo F. Padovan 5218b501d6a1SAnderson Briglia case L2CAP_CID_SMP: 5219b501d6a1SAnderson Briglia if (smp_sig_channel(conn, skb)) 5220b501d6a1SAnderson Briglia l2cap_conn_del(conn->hcon, EACCES); 5221b501d6a1SAnderson Briglia break; 5222b501d6a1SAnderson Briglia 52230a708f8fSGustavo F. Padovan default: 52240a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb); 52250a708f8fSGustavo F. Padovan break; 52260a708f8fSGustavo F. Padovan } 52270a708f8fSGustavo F. Padovan } 52280a708f8fSGustavo F. Padovan 52290a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */ 52300a708f8fSGustavo F. Padovan 5231686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) 52320a708f8fSGustavo F. Padovan { 52330a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0; 523423691d75SGustavo F. Padovan struct l2cap_chan *c; 52350a708f8fSGustavo F. Padovan 52360a708f8fSGustavo F. Padovan BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); 52370a708f8fSGustavo F. Padovan 52380a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */ 523923691d75SGustavo F. Padovan read_lock(&chan_list_lock); 524023691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 524123691d75SGustavo F. Padovan struct sock *sk = c->sk; 52424343478fSGustavo F. Padovan 524389bc500eSGustavo F. Padovan if (c->state != BT_LISTEN) 52440a708f8fSGustavo F. Padovan continue; 52450a708f8fSGustavo F. Padovan 52460a708f8fSGustavo F. Padovan if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { 52470a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT; 524843bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 52490a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER; 52500a708f8fSGustavo F. Padovan exact++; 52510a708f8fSGustavo F. Padovan } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { 52520a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT; 525343bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 52540a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER; 52550a708f8fSGustavo F. Padovan } 52560a708f8fSGustavo F. Padovan } 525723691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 52580a708f8fSGustavo F. Padovan 52590a708f8fSGustavo F. Padovan return exact ? lm1 : lm2; 52600a708f8fSGustavo F. Padovan } 52610a708f8fSGustavo F. Padovan 5262686ebf28SUlisses Furquim int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) 52630a708f8fSGustavo F. Padovan { 52640a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 52650a708f8fSGustavo F. Padovan 52660a708f8fSGustavo F. Padovan BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); 52670a708f8fSGustavo F. Padovan 52680a708f8fSGustavo F. Padovan if (!status) { 52690a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, status); 52700a708f8fSGustavo F. Padovan if (conn) 52710a708f8fSGustavo F. Padovan l2cap_conn_ready(conn); 52720a708f8fSGustavo F. Padovan } else 5273e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status)); 52740a708f8fSGustavo F. Padovan 52750a708f8fSGustavo F. Padovan return 0; 52760a708f8fSGustavo F. Padovan } 52770a708f8fSGustavo F. Padovan 5278686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon) 52790a708f8fSGustavo F. Padovan { 52800a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 52810a708f8fSGustavo F. Padovan 52820a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon); 52830a708f8fSGustavo F. Padovan 5284686ebf28SUlisses Furquim if (!conn) 52859f5a0d7bSAndrei Emeltchenko return HCI_ERROR_REMOTE_USER_TERM; 52860a708f8fSGustavo F. Padovan return conn->disc_reason; 52870a708f8fSGustavo F. Padovan } 52880a708f8fSGustavo F. Padovan 5289686ebf28SUlisses Furquim int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) 52900a708f8fSGustavo F. Padovan { 52910a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason); 52920a708f8fSGustavo F. Padovan 5293e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason)); 52940a708f8fSGustavo F. Padovan return 0; 52950a708f8fSGustavo F. Padovan } 52960a708f8fSGustavo F. Padovan 52974343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) 52980a708f8fSGustavo F. Padovan { 5299715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 53000a708f8fSGustavo F. Padovan return; 53010a708f8fSGustavo F. Padovan 53020a708f8fSGustavo F. Padovan if (encrypt == 0x00) { 53034343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) { 5304ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); 53054343478fSGustavo F. Padovan } else if (chan->sec_level == BT_SECURITY_HIGH) 53060f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED); 53070a708f8fSGustavo F. Padovan } else { 53084343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) 5309c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 53100a708f8fSGustavo F. Padovan } 53110a708f8fSGustavo F. Padovan } 53120a708f8fSGustavo F. Padovan 5313686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) 53140a708f8fSGustavo F. Padovan { 53150a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 531648454079SGustavo F. Padovan struct l2cap_chan *chan; 53170a708f8fSGustavo F. Padovan 53180a708f8fSGustavo F. Padovan if (!conn) 53190a708f8fSGustavo F. Padovan return 0; 53200a708f8fSGustavo F. Padovan 53210a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 53220a708f8fSGustavo F. Padovan 5323160dc6acSVinicius Costa Gomes if (hcon->type == LE_LINK) { 532435d4adccSHemant Gupta if (!status && encrypt) 5325160dc6acSVinicius Costa Gomes smp_distribute_keys(conn, 0); 532617cd3f37SUlisses Furquim cancel_delayed_work(&conn->security_timer); 5327160dc6acSVinicius Costa Gomes } 5328160dc6acSVinicius Costa Gomes 53293df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 53300a708f8fSGustavo F. Padovan 53313df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 53326be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 53330a708f8fSGustavo F. Padovan 5334f1cb9af5SVinicius Costa Gomes BT_DBG("chan->scid %d", chan->scid); 5335f1cb9af5SVinicius Costa Gomes 5336f1cb9af5SVinicius Costa Gomes if (chan->scid == L2CAP_CID_LE_DATA) { 5337f1cb9af5SVinicius Costa Gomes if (!status && encrypt) { 5338f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level; 5339cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 5340f1cb9af5SVinicius Costa Gomes } 5341f1cb9af5SVinicius Costa Gomes 53426be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 5343f1cb9af5SVinicius Costa Gomes continue; 5344f1cb9af5SVinicius Costa Gomes } 5345f1cb9af5SVinicius Costa Gomes 5346c1360a1cSGustavo F. Padovan if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) { 53476be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 53480a708f8fSGustavo F. Padovan continue; 53490a708f8fSGustavo F. Padovan } 53500a708f8fSGustavo F. Padovan 535189bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED || 535289bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) { 5353a7d7723aSGustavo Padovan struct sock *sk = chan->sk; 5354a7d7723aSGustavo Padovan 5355c5daa683SGustavo Padovan clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); 5356a7d7723aSGustavo Padovan sk->sk_state_change(sk); 5357a7d7723aSGustavo Padovan 53584343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt); 53596be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 53600a708f8fSGustavo F. Padovan continue; 53610a708f8fSGustavo F. Padovan } 53620a708f8fSGustavo F. Padovan 536389bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 53640a708f8fSGustavo F. Padovan if (!status) { 53659b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 53660a708f8fSGustavo F. Padovan } else { 5367ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 53680a708f8fSGustavo F. Padovan } 536989bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 53706be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 53710a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 5372df3c3931SJohan Hedberg __u16 res, stat; 53730a708f8fSGustavo F. Padovan 53746be36555SAndrei Emeltchenko lock_sock(sk); 53756be36555SAndrei Emeltchenko 53760a708f8fSGustavo F. Padovan if (!status) { 5377c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, 5378c5daa683SGustavo Padovan &bt_sk(sk)->flags)) { 5379df3c3931SJohan Hedberg struct sock *parent = bt_sk(sk)->parent; 5380df3c3931SJohan Hedberg res = L2CAP_CR_PEND; 5381df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND; 538205e9a2f6SIlia Kolomisnky if (parent) 5383df3c3931SJohan Hedberg parent->sk_data_ready(parent, 0); 5384df3c3931SJohan Hedberg } else { 53850e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 5386df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS; 5387df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 5388df3c3931SJohan Hedberg } 53890a708f8fSGustavo F. Padovan } else { 53900e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_DISCONN); 5391ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 5392df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK; 5393df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 53940a708f8fSGustavo F. Padovan } 53950a708f8fSGustavo F. Padovan 53966be36555SAndrei Emeltchenko release_sock(sk); 53976be36555SAndrei Emeltchenko 5398fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 5399fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 5400df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res); 5401df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat); 5402fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 5403fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 54040a708f8fSGustavo F. Padovan } 54050a708f8fSGustavo F. Padovan 54066be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 54070a708f8fSGustavo F. Padovan } 54080a708f8fSGustavo F. Padovan 54093df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 54100a708f8fSGustavo F. Padovan 54110a708f8fSGustavo F. Padovan return 0; 54120a708f8fSGustavo F. Padovan } 54130a708f8fSGustavo F. Padovan 5414686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) 54150a708f8fSGustavo F. Padovan { 54160a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 54170a708f8fSGustavo F. Padovan 54180a708f8fSGustavo F. Padovan if (!conn) 54190a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, 0); 54200a708f8fSGustavo F. Padovan 54210a708f8fSGustavo F. Padovan if (!conn) 54220a708f8fSGustavo F. Padovan goto drop; 54230a708f8fSGustavo F. Padovan 54240a708f8fSGustavo F. Padovan BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); 54250a708f8fSGustavo F. Padovan 54260a708f8fSGustavo F. Padovan if (!(flags & ACL_CONT)) { 54270a708f8fSGustavo F. Padovan struct l2cap_hdr *hdr; 54280a708f8fSGustavo F. Padovan int len; 54290a708f8fSGustavo F. Padovan 54300a708f8fSGustavo F. Padovan if (conn->rx_len) { 54310a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len); 54320a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 54330a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 54340a708f8fSGustavo F. Padovan conn->rx_len = 0; 54350a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 54360a708f8fSGustavo F. Padovan } 54370a708f8fSGustavo F. Padovan 54380a708f8fSGustavo F. Padovan /* Start fragment always begin with Basic L2CAP header */ 54390a708f8fSGustavo F. Padovan if (skb->len < L2CAP_HDR_SIZE) { 54400a708f8fSGustavo F. Padovan BT_ERR("Frame is too short (len %d)", skb->len); 54410a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 54420a708f8fSGustavo F. Padovan goto drop; 54430a708f8fSGustavo F. Padovan } 54440a708f8fSGustavo F. Padovan 54450a708f8fSGustavo F. Padovan hdr = (struct l2cap_hdr *) skb->data; 54460a708f8fSGustavo F. Padovan len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; 54470a708f8fSGustavo F. Padovan 54480a708f8fSGustavo F. Padovan if (len == skb->len) { 54490a708f8fSGustavo F. Padovan /* Complete frame received */ 54500a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb); 54510a708f8fSGustavo F. Padovan return 0; 54520a708f8fSGustavo F. Padovan } 54530a708f8fSGustavo F. Padovan 54540a708f8fSGustavo F. Padovan BT_DBG("Start: total len %d, frag len %d", len, skb->len); 54550a708f8fSGustavo F. Padovan 54560a708f8fSGustavo F. Padovan if (skb->len > len) { 54570a708f8fSGustavo F. Padovan BT_ERR("Frame is too long (len %d, expected len %d)", 54580a708f8fSGustavo F. Padovan skb->len, len); 54590a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 54600a708f8fSGustavo F. Padovan goto drop; 54610a708f8fSGustavo F. Padovan } 54620a708f8fSGustavo F. Padovan 54630a708f8fSGustavo F. Padovan /* Allocate skb for the complete frame (with header) */ 54640a708f8fSGustavo F. Padovan conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC); 54650a708f8fSGustavo F. Padovan if (!conn->rx_skb) 54660a708f8fSGustavo F. Padovan goto drop; 54670a708f8fSGustavo F. Padovan 54680a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 54690a708f8fSGustavo F. Padovan skb->len); 54700a708f8fSGustavo F. Padovan conn->rx_len = len - skb->len; 54710a708f8fSGustavo F. Padovan } else { 54720a708f8fSGustavo F. Padovan BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); 54730a708f8fSGustavo F. Padovan 54740a708f8fSGustavo F. Padovan if (!conn->rx_len) { 54750a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len); 54760a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 54770a708f8fSGustavo F. Padovan goto drop; 54780a708f8fSGustavo F. Padovan } 54790a708f8fSGustavo F. Padovan 54800a708f8fSGustavo F. Padovan if (skb->len > conn->rx_len) { 54810a708f8fSGustavo F. Padovan BT_ERR("Fragment is too long (len %d, expected %d)", 54820a708f8fSGustavo F. Padovan skb->len, conn->rx_len); 54830a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 54840a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 54850a708f8fSGustavo F. Padovan conn->rx_len = 0; 54860a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 54870a708f8fSGustavo F. Padovan goto drop; 54880a708f8fSGustavo F. Padovan } 54890a708f8fSGustavo F. Padovan 54900a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 54910a708f8fSGustavo F. Padovan skb->len); 54920a708f8fSGustavo F. Padovan conn->rx_len -= skb->len; 54930a708f8fSGustavo F. Padovan 54940a708f8fSGustavo F. Padovan if (!conn->rx_len) { 54950a708f8fSGustavo F. Padovan /* Complete frame received */ 54960a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, conn->rx_skb); 54970a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 54980a708f8fSGustavo F. Padovan } 54990a708f8fSGustavo F. Padovan } 55000a708f8fSGustavo F. Padovan 55010a708f8fSGustavo F. Padovan drop: 55020a708f8fSGustavo F. Padovan kfree_skb(skb); 55030a708f8fSGustavo F. Padovan return 0; 55040a708f8fSGustavo F. Padovan } 55050a708f8fSGustavo F. Padovan 55060a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p) 55070a708f8fSGustavo F. Padovan { 550823691d75SGustavo F. Padovan struct l2cap_chan *c; 55090a708f8fSGustavo F. Padovan 5510333055f2SGustavo F. Padovan read_lock(&chan_list_lock); 55110a708f8fSGustavo F. Padovan 551223691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 551323691d75SGustavo F. Padovan struct sock *sk = c->sk; 55140a708f8fSGustavo F. Padovan 5515903d343eSGustavo F. Padovan seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", 55160a708f8fSGustavo F. Padovan batostr(&bt_sk(sk)->src), 55170a708f8fSGustavo F. Padovan batostr(&bt_sk(sk)->dst), 551889bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm), 551923691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu, 552023691d75SGustavo F. Padovan c->sec_level, c->mode); 55210a708f8fSGustavo F. Padovan } 55220a708f8fSGustavo F. Padovan 5523333055f2SGustavo F. Padovan read_unlock(&chan_list_lock); 55240a708f8fSGustavo F. Padovan 55250a708f8fSGustavo F. Padovan return 0; 55260a708f8fSGustavo F. Padovan } 55270a708f8fSGustavo F. Padovan 55280a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file) 55290a708f8fSGustavo F. Padovan { 55300a708f8fSGustavo F. Padovan return single_open(file, l2cap_debugfs_show, inode->i_private); 55310a708f8fSGustavo F. Padovan } 55320a708f8fSGustavo F. Padovan 55330a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = { 55340a708f8fSGustavo F. Padovan .open = l2cap_debugfs_open, 55350a708f8fSGustavo F. Padovan .read = seq_read, 55360a708f8fSGustavo F. Padovan .llseek = seq_lseek, 55370a708f8fSGustavo F. Padovan .release = single_release, 55380a708f8fSGustavo F. Padovan }; 55390a708f8fSGustavo F. Padovan 55400a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs; 55410a708f8fSGustavo F. Padovan 554264274518SGustavo F. Padovan int __init l2cap_init(void) 55430a708f8fSGustavo F. Padovan { 55440a708f8fSGustavo F. Padovan int err; 55450a708f8fSGustavo F. Padovan 5546bb58f747SGustavo F. Padovan err = l2cap_init_sockets(); 55470a708f8fSGustavo F. Padovan if (err < 0) 55480a708f8fSGustavo F. Padovan return err; 55490a708f8fSGustavo F. Padovan 55500a708f8fSGustavo F. Padovan if (bt_debugfs) { 55510a708f8fSGustavo F. Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, 55520a708f8fSGustavo F. Padovan bt_debugfs, NULL, &l2cap_debugfs_fops); 55530a708f8fSGustavo F. Padovan if (!l2cap_debugfs) 55540a708f8fSGustavo F. Padovan BT_ERR("Failed to create L2CAP debug file"); 55550a708f8fSGustavo F. Padovan } 55560a708f8fSGustavo F. Padovan 55570a708f8fSGustavo F. Padovan return 0; 55580a708f8fSGustavo F. Padovan } 55590a708f8fSGustavo F. Padovan 556064274518SGustavo F. Padovan void l2cap_exit(void) 55610a708f8fSGustavo F. Padovan { 55620a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs); 5563bb58f747SGustavo F. Padovan l2cap_cleanup_sockets(); 55640a708f8fSGustavo F. Padovan } 55650a708f8fSGustavo F. Padovan 55660a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644); 55670a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); 5568