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 923*c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll) 9240a708f8fSGustavo F. Padovan { 925*c9e3d5e0SMat Martineau struct l2cap_ctrl control; 9260a708f8fSGustavo F. Padovan 927*c9e3d5e0SMat Martineau BT_DBG("chan %p, poll %d", chan, poll); 928*c9e3d5e0SMat Martineau 929*c9e3d5e0SMat Martineau memset(&control, 0, sizeof(control)); 930*c9e3d5e0SMat Martineau control.sframe = 1; 931*c9e3d5e0SMat Martineau control.poll = poll; 932*c9e3d5e0SMat Martineau 933*c9e3d5e0SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 934*c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RNR; 935*c9e3d5e0SMat Martineau else 936*c9e3d5e0SMat Martineau control.super = L2CAP_SUPER_RR; 937*c9e3d5e0SMat Martineau 938*c9e3d5e0SMat Martineau control.reqseq = chan->buffer_seq; 939*c9e3d5e0SMat Martineau l2cap_send_sframe(chan, &control); 9400a708f8fSGustavo F. Padovan } 9410a708f8fSGustavo F. Padovan 942b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) 9430a708f8fSGustavo F. Padovan { 944c1360a1cSGustavo F. Padovan return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); 9450a708f8fSGustavo F. Padovan } 9460a708f8fSGustavo F. Padovan 9479b27f350SAndrei Emeltchenko static void l2cap_send_conn_req(struct l2cap_chan *chan) 9489b27f350SAndrei Emeltchenko { 9499b27f350SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 9509b27f350SAndrei Emeltchenko struct l2cap_conn_req req; 9519b27f350SAndrei Emeltchenko 9529b27f350SAndrei Emeltchenko req.scid = cpu_to_le16(chan->scid); 9539b27f350SAndrei Emeltchenko req.psm = chan->psm; 9549b27f350SAndrei Emeltchenko 9559b27f350SAndrei Emeltchenko chan->ident = l2cap_get_ident(conn); 9569b27f350SAndrei Emeltchenko 9579b27f350SAndrei Emeltchenko set_bit(CONF_CONNECT_PEND, &chan->conf_state); 9589b27f350SAndrei Emeltchenko 9599b27f350SAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); 9609b27f350SAndrei Emeltchenko } 9619b27f350SAndrei Emeltchenko 9629f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan) 9639f0caeb1SVinicius Costa Gomes { 9649f0caeb1SVinicius Costa Gomes struct sock *sk = chan->sk; 9659f0caeb1SVinicius Costa Gomes struct sock *parent; 9669f0caeb1SVinicius Costa Gomes 9679f0caeb1SVinicius Costa Gomes lock_sock(sk); 9689f0caeb1SVinicius Costa Gomes 9699f0caeb1SVinicius Costa Gomes parent = bt_sk(sk)->parent; 9709f0caeb1SVinicius Costa Gomes 9719f0caeb1SVinicius Costa Gomes BT_DBG("sk %p, parent %p", sk, parent); 9729f0caeb1SVinicius Costa Gomes 9732827011fSMat Martineau /* This clears all conf flags, including CONF_NOT_COMPLETE */ 9749f0caeb1SVinicius Costa Gomes chan->conf_state = 0; 9759f0caeb1SVinicius Costa Gomes __clear_chan_timer(chan); 9769f0caeb1SVinicius Costa Gomes 9779f0caeb1SVinicius Costa Gomes __l2cap_state_change(chan, BT_CONNECTED); 9789f0caeb1SVinicius Costa Gomes sk->sk_state_change(sk); 9799f0caeb1SVinicius Costa Gomes 9809f0caeb1SVinicius Costa Gomes if (parent) 9819f0caeb1SVinicius Costa Gomes parent->sk_data_ready(parent, 0); 9829f0caeb1SVinicius Costa Gomes 9839f0caeb1SVinicius Costa Gomes release_sock(sk); 9849f0caeb1SVinicius Costa Gomes } 9859f0caeb1SVinicius Costa Gomes 986fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan) 9870a708f8fSGustavo F. Padovan { 9888c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 9890a708f8fSGustavo F. Padovan 9909f0caeb1SVinicius Costa Gomes if (conn->hcon->type == LE_LINK) { 9919f0caeb1SVinicius Costa Gomes l2cap_chan_ready(chan); 9929f0caeb1SVinicius Costa Gomes return; 9939f0caeb1SVinicius Costa Gomes } 9949f0caeb1SVinicius Costa Gomes 9950a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { 9960a708f8fSGustavo F. Padovan if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) 9970a708f8fSGustavo F. Padovan return; 9980a708f8fSGustavo F. Padovan 999d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan) && 10009b27f350SAndrei Emeltchenko __l2cap_no_conn_pending(chan)) 10019b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 10020a708f8fSGustavo F. Padovan } else { 10030a708f8fSGustavo F. Padovan struct l2cap_info_req req; 10040a708f8fSGustavo F. Padovan req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 10050a708f8fSGustavo F. Padovan 10060a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 10070a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 10080a708f8fSGustavo F. Padovan 1009ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 10100a708f8fSGustavo F. Padovan 10110a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 10120a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 10130a708f8fSGustavo F. Padovan } 10140a708f8fSGustavo F. Padovan } 10150a708f8fSGustavo F. Padovan 10160a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) 10170a708f8fSGustavo F. Padovan { 10180a708f8fSGustavo F. Padovan u32 local_feat_mask = l2cap_feat_mask; 10190a708f8fSGustavo F. Padovan if (!disable_ertm) 10200a708f8fSGustavo F. Padovan local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING; 10210a708f8fSGustavo F. Padovan 10220a708f8fSGustavo F. Padovan switch (mode) { 10230a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 10240a708f8fSGustavo F. Padovan return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask; 10250a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 10260a708f8fSGustavo F. Padovan return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask; 10270a708f8fSGustavo F. Padovan default: 10280a708f8fSGustavo F. Padovan return 0x00; 10290a708f8fSGustavo F. Padovan } 10300a708f8fSGustavo F. Padovan } 10310a708f8fSGustavo F. Padovan 10324519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err) 10330a708f8fSGustavo F. Padovan { 10346be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 10350a708f8fSGustavo F. Padovan struct l2cap_disconn_req req; 10360a708f8fSGustavo F. Padovan 10370a708f8fSGustavo F. Padovan if (!conn) 10380a708f8fSGustavo F. Padovan return; 10390a708f8fSGustavo F. Padovan 10400c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_ERTM) { 10411a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 10421a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 10431a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 10440a708f8fSGustavo F. Padovan } 10450a708f8fSGustavo F. Padovan 1046fe4128e0SGustavo F. Padovan req.dcid = cpu_to_le16(chan->dcid); 1047fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 10480a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 10490a708f8fSGustavo F. Padovan L2CAP_DISCONN_REQ, sizeof(req), &req); 10500a708f8fSGustavo F. Padovan 10516be36555SAndrei Emeltchenko lock_sock(sk); 10520e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_DISCONN); 10532e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 10546be36555SAndrei Emeltchenko release_sock(sk); 10550a708f8fSGustavo F. Padovan } 10560a708f8fSGustavo F. Padovan 10570a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */ 10580a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn) 10590a708f8fSGustavo F. Padovan { 10603df91ea2SAndrei Emeltchenko struct l2cap_chan *chan, *tmp; 10610a708f8fSGustavo F. Padovan 10620a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 10630a708f8fSGustavo F. Padovan 10643df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 10650a708f8fSGustavo F. Padovan 10663df91ea2SAndrei Emeltchenko list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 106748454079SGustavo F. Padovan struct sock *sk = chan->sk; 1068baa7e1faSGustavo F. Padovan 10696be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 10700a708f8fSGustavo F. Padovan 1071715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 10726be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10730a708f8fSGustavo F. Padovan continue; 10740a708f8fSGustavo F. Padovan } 10750a708f8fSGustavo F. Padovan 107689bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 1077d45fc423SGustavo F. Padovan if (!l2cap_chan_check_security(chan) || 1078b4450035SGustavo F. Padovan !__l2cap_no_conn_pending(chan)) { 10796be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10800a708f8fSGustavo F. Padovan continue; 10810a708f8fSGustavo F. Padovan } 10820a708f8fSGustavo F. Padovan 1083c1360a1cSGustavo F. Padovan if (!l2cap_mode_supported(chan->mode, conn->feat_mask) 1084c1360a1cSGustavo F. Padovan && test_bit(CONF_STATE2_DEVICE, 1085c1360a1cSGustavo F. Padovan &chan->conf_state)) { 10860f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 10876be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10880a708f8fSGustavo F. Padovan continue; 10890a708f8fSGustavo F. Padovan } 10900a708f8fSGustavo F. Padovan 10919b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 10920a708f8fSGustavo F. Padovan 109389bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 10940a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 10950a708f8fSGustavo F. Padovan char buf[128]; 1096fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 1097fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 10980a708f8fSGustavo F. Padovan 1099d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 11006be36555SAndrei Emeltchenko lock_sock(sk); 1101c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, 1102c5daa683SGustavo Padovan &bt_sk(sk)->flags)) { 11030a708f8fSGustavo F. Padovan struct sock *parent = bt_sk(sk)->parent; 11040a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_PEND); 11050a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND); 110605e9a2f6SIlia Kolomisnky if (parent) 11070a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 11080a708f8fSGustavo F. Padovan 11090a708f8fSGustavo F. Padovan } else { 11100e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 11110a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 11120a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 11130a708f8fSGustavo F. Padovan } 11146be36555SAndrei Emeltchenko release_sock(sk); 11150a708f8fSGustavo F. Padovan } else { 11160a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_PEND); 11170a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND); 11180a708f8fSGustavo F. Padovan } 11190a708f8fSGustavo F. Padovan 1120fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 1121fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 11220a708f8fSGustavo F. Padovan 1123c1360a1cSGustavo F. Padovan if (test_bit(CONF_REQ_SENT, &chan->conf_state) || 11240a708f8fSGustavo F. Padovan rsp.result != L2CAP_CR_SUCCESS) { 11256be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 11260a708f8fSGustavo F. Padovan continue; 11270a708f8fSGustavo F. Padovan } 11280a708f8fSGustavo F. Padovan 1129c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 11300a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 113173ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 113273ffa904SGustavo F. Padovan chan->num_conf_req++; 11330a708f8fSGustavo F. Padovan } 11340a708f8fSGustavo F. Padovan 11356be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 11360a708f8fSGustavo F. Padovan } 11370a708f8fSGustavo F. Padovan 11383df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 11390a708f8fSGustavo F. Padovan } 11400a708f8fSGustavo F. Padovan 1141c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr. 1142b62f328bSVille Tervo * Returns closest match, locked. 1143b62f328bSVille Tervo */ 1144d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, 1145c2287681SIdo Yariv bdaddr_t *src, 1146c2287681SIdo Yariv bdaddr_t *dst) 1147b62f328bSVille Tervo { 114823691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 1149b62f328bSVille Tervo 115023691d75SGustavo F. Padovan read_lock(&chan_list_lock); 1151b62f328bSVille Tervo 115223691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 115323691d75SGustavo F. Padovan struct sock *sk = c->sk; 1154fe4128e0SGustavo F. Padovan 115589bc500eSGustavo F. Padovan if (state && c->state != state) 1156b62f328bSVille Tervo continue; 1157b62f328bSVille Tervo 115823691d75SGustavo F. Padovan if (c->scid == cid) { 1159c2287681SIdo Yariv int src_match, dst_match; 1160c2287681SIdo Yariv int src_any, dst_any; 1161c2287681SIdo Yariv 1162b62f328bSVille Tervo /* Exact match. */ 1163c2287681SIdo Yariv src_match = !bacmp(&bt_sk(sk)->src, src); 1164c2287681SIdo Yariv dst_match = !bacmp(&bt_sk(sk)->dst, dst); 1165c2287681SIdo Yariv if (src_match && dst_match) { 116623691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 116723691d75SGustavo F. Padovan return c; 116823691d75SGustavo F. Padovan } 1169b62f328bSVille Tervo 1170b62f328bSVille Tervo /* Closest match */ 1171c2287681SIdo Yariv src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY); 1172c2287681SIdo Yariv dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY); 1173c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1174c2287681SIdo Yariv (src_any && dst_any)) 117523691d75SGustavo F. Padovan c1 = c; 1176b62f328bSVille Tervo } 1177b62f328bSVille Tervo } 1178280f294fSGustavo F. Padovan 117923691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 1180b62f328bSVille Tervo 118123691d75SGustavo F. Padovan return c1; 1182b62f328bSVille Tervo } 1183b62f328bSVille Tervo 1184b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn) 1185b62f328bSVille Tervo { 1186c916fbe4SGustavo F. Padovan struct sock *parent, *sk; 118723691d75SGustavo F. Padovan struct l2cap_chan *chan, *pchan; 1188b62f328bSVille Tervo 1189b62f328bSVille Tervo BT_DBG(""); 1190b62f328bSVille Tervo 1191b62f328bSVille Tervo /* Check if we have socket listening on cid */ 119223691d75SGustavo F. Padovan pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA, 1193c2287681SIdo Yariv conn->src, conn->dst); 119423691d75SGustavo F. Padovan if (!pchan) 1195b62f328bSVille Tervo return; 1196b62f328bSVille Tervo 119723691d75SGustavo F. Padovan parent = pchan->sk; 119823691d75SGustavo F. Padovan 1199aa2ac881SGustavo F. Padovan lock_sock(parent); 120062f3a2cfSGustavo F. Padovan 1201b62f328bSVille Tervo /* Check for backlog size */ 1202b62f328bSVille Tervo if (sk_acceptq_is_full(parent)) { 1203b62f328bSVille Tervo BT_DBG("backlog full %d", parent->sk_ack_backlog); 1204b62f328bSVille Tervo goto clean; 1205b62f328bSVille Tervo } 1206b62f328bSVille Tervo 120780808e43SGustavo F. Padovan chan = pchan->ops->new_connection(pchan->data); 120880808e43SGustavo F. Padovan if (!chan) 1209b62f328bSVille Tervo goto clean; 1210b62f328bSVille Tervo 121180808e43SGustavo F. Padovan sk = chan->sk; 12125d41ce1dSGustavo F. Padovan 1213b62f328bSVille Tervo hci_conn_hold(conn->hcon); 1214b62f328bSVille Tervo 1215b62f328bSVille Tervo bacpy(&bt_sk(sk)->src, conn->src); 1216b62f328bSVille Tervo bacpy(&bt_sk(sk)->dst, conn->dst); 1217b62f328bSVille Tervo 1218d1010240SGustavo F. Padovan bt_accept_enqueue(parent, sk); 1219d1010240SGustavo F. Padovan 12203d57dc68SGustavo F. Padovan l2cap_chan_add(conn, chan); 122148454079SGustavo F. Padovan 1222c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 1223b62f328bSVille Tervo 12240e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECTED); 1225b62f328bSVille Tervo parent->sk_data_ready(parent, 0); 1226b62f328bSVille Tervo 1227b62f328bSVille Tervo clean: 1228aa2ac881SGustavo F. Padovan release_sock(parent); 1229b62f328bSVille Tervo } 1230b62f328bSVille Tervo 12310a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn) 12320a708f8fSGustavo F. Padovan { 123348454079SGustavo F. Padovan struct l2cap_chan *chan; 12340a708f8fSGustavo F. Padovan 12350a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 12360a708f8fSGustavo F. Padovan 1237b62f328bSVille Tervo if (!conn->hcon->out && conn->hcon->type == LE_LINK) 1238b62f328bSVille Tervo l2cap_le_conn_ready(conn); 1239b62f328bSVille Tervo 1240160dc6acSVinicius Costa Gomes if (conn->hcon->out && conn->hcon->type == LE_LINK) 1241160dc6acSVinicius Costa Gomes smp_conn_security(conn, conn->hcon->pending_sec_level); 1242160dc6acSVinicius Costa Gomes 12433df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 12440a708f8fSGustavo F. Padovan 12453df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1246baa7e1faSGustavo F. Padovan 12476be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 12480a708f8fSGustavo F. Padovan 124963128451SVinicius Costa Gomes if (conn->hcon->type == LE_LINK) { 1250b501d6a1SAnderson Briglia if (smp_conn_security(conn, chan->sec_level)) 1251cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 1252acd7d370SVille Tervo 125363128451SVinicius Costa Gomes } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 12546be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 1255c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 12566be36555SAndrei Emeltchenko lock_sock(sk); 12570e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECTED); 12580a708f8fSGustavo F. Padovan sk->sk_state_change(sk); 12596be36555SAndrei Emeltchenko release_sock(sk); 1260b501d6a1SAnderson Briglia 126189bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT) 1262fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 12630a708f8fSGustavo F. Padovan 12646be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 12650a708f8fSGustavo F. Padovan } 12660a708f8fSGustavo F. Padovan 12673df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 12680a708f8fSGustavo F. Padovan } 12690a708f8fSGustavo F. Padovan 12700a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */ 12710a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) 12720a708f8fSGustavo F. Padovan { 127348454079SGustavo F. Padovan struct l2cap_chan *chan; 12740a708f8fSGustavo F. Padovan 12750a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 12760a708f8fSGustavo F. Padovan 12773df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 12780a708f8fSGustavo F. Padovan 12793df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1280ecf61bdbSAndrei Emeltchenko if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) 12812e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 12820a708f8fSGustavo F. Padovan } 12830a708f8fSGustavo F. Padovan 12843df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 12850a708f8fSGustavo F. Padovan } 12860a708f8fSGustavo F. Padovan 1287f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work) 12880a708f8fSGustavo F. Padovan { 1289f878fcadSGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 1290030013d8SGustavo F. Padovan info_timer.work); 12910a708f8fSGustavo F. Padovan 12920a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 12930a708f8fSGustavo F. Padovan conn->info_ident = 0; 12940a708f8fSGustavo F. Padovan 12950a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 12960a708f8fSGustavo F. Padovan } 12970a708f8fSGustavo F. Padovan 12985d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err) 12995d3de7dfSVinicius Costa Gomes { 13005d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 13015d3de7dfSVinicius Costa Gomes struct l2cap_chan *chan, *l; 13025d3de7dfSVinicius Costa Gomes 13035d3de7dfSVinicius Costa Gomes if (!conn) 13045d3de7dfSVinicius Costa Gomes return; 13055d3de7dfSVinicius Costa Gomes 13065d3de7dfSVinicius Costa Gomes BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); 13075d3de7dfSVinicius Costa Gomes 13085d3de7dfSVinicius Costa Gomes kfree_skb(conn->rx_skb); 13095d3de7dfSVinicius Costa Gomes 13103df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 13113df91ea2SAndrei Emeltchenko 13125d3de7dfSVinicius Costa Gomes /* Kill channels */ 13135d3de7dfSVinicius Costa Gomes list_for_each_entry_safe(chan, l, &conn->chan_l, list) { 131461d6ef3eSMat Martineau l2cap_chan_hold(chan); 13156be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 13166be36555SAndrei Emeltchenko 13175d3de7dfSVinicius Costa Gomes l2cap_chan_del(chan, err); 13186be36555SAndrei Emeltchenko 13196be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13206be36555SAndrei Emeltchenko 13215d3de7dfSVinicius Costa Gomes chan->ops->close(chan->data); 132261d6ef3eSMat Martineau l2cap_chan_put(chan); 13235d3de7dfSVinicius Costa Gomes } 13245d3de7dfSVinicius Costa Gomes 13253df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 13263df91ea2SAndrei Emeltchenko 132773d80debSLuiz Augusto von Dentz hci_chan_del(conn->hchan); 132873d80debSLuiz Augusto von Dentz 13295d3de7dfSVinicius Costa Gomes if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1330127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->info_timer); 13315d3de7dfSVinicius Costa Gomes 133251a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) { 1333127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->security_timer); 13348aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 1335d26a2345SVinicius Costa Gomes } 13365d3de7dfSVinicius Costa Gomes 13375d3de7dfSVinicius Costa Gomes hcon->l2cap_data = NULL; 13385d3de7dfSVinicius Costa Gomes kfree(conn); 13395d3de7dfSVinicius Costa Gomes } 13405d3de7dfSVinicius Costa Gomes 13416c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work) 13425d3de7dfSVinicius Costa Gomes { 13436c9d42a1SGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 13446c9d42a1SGustavo F. Padovan security_timer.work); 13455d3de7dfSVinicius Costa Gomes 13465d3de7dfSVinicius Costa Gomes l2cap_conn_del(conn->hcon, ETIMEDOUT); 13475d3de7dfSVinicius Costa Gomes } 13485d3de7dfSVinicius Costa Gomes 13490a708f8fSGustavo F. Padovan static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) 13500a708f8fSGustavo F. Padovan { 13510a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 135273d80debSLuiz Augusto von Dentz struct hci_chan *hchan; 13530a708f8fSGustavo F. Padovan 13540a708f8fSGustavo F. Padovan if (conn || status) 13550a708f8fSGustavo F. Padovan return conn; 13560a708f8fSGustavo F. Padovan 135773d80debSLuiz Augusto von Dentz hchan = hci_chan_create(hcon); 135873d80debSLuiz Augusto von Dentz if (!hchan) 13590a708f8fSGustavo F. Padovan return NULL; 13600a708f8fSGustavo F. Padovan 136173d80debSLuiz Augusto von Dentz conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC); 136273d80debSLuiz Augusto von Dentz if (!conn) { 136373d80debSLuiz Augusto von Dentz hci_chan_del(hchan); 136473d80debSLuiz Augusto von Dentz return NULL; 136573d80debSLuiz Augusto von Dentz } 136673d80debSLuiz Augusto von Dentz 13670a708f8fSGustavo F. Padovan hcon->l2cap_data = conn; 13680a708f8fSGustavo F. Padovan conn->hcon = hcon; 136973d80debSLuiz Augusto von Dentz conn->hchan = hchan; 13700a708f8fSGustavo F. Padovan 137173d80debSLuiz Augusto von Dentz BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); 13720a708f8fSGustavo F. Padovan 1373acd7d370SVille Tervo if (hcon->hdev->le_mtu && hcon->type == LE_LINK) 1374acd7d370SVille Tervo conn->mtu = hcon->hdev->le_mtu; 1375acd7d370SVille Tervo else 13760a708f8fSGustavo F. Padovan conn->mtu = hcon->hdev->acl_mtu; 1377acd7d370SVille Tervo 13780a708f8fSGustavo F. Padovan conn->src = &hcon->hdev->bdaddr; 13790a708f8fSGustavo F. Padovan conn->dst = &hcon->dst; 13800a708f8fSGustavo F. Padovan 13810a708f8fSGustavo F. Padovan conn->feat_mask = 0; 13820a708f8fSGustavo F. Padovan 13830a708f8fSGustavo F. Padovan spin_lock_init(&conn->lock); 13843df91ea2SAndrei Emeltchenko mutex_init(&conn->chan_lock); 1385baa7e1faSGustavo F. Padovan 1386baa7e1faSGustavo F. Padovan INIT_LIST_HEAD(&conn->chan_l); 13870a708f8fSGustavo F. Padovan 13885d3de7dfSVinicius Costa Gomes if (hcon->type == LE_LINK) 13896c9d42a1SGustavo F. Padovan INIT_DELAYED_WORK(&conn->security_timer, security_timeout); 13905d3de7dfSVinicius Costa Gomes else 1391030013d8SGustavo F. Padovan INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); 13920a708f8fSGustavo F. Padovan 13939f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 13940a708f8fSGustavo F. Padovan 13950a708f8fSGustavo F. Padovan return conn; 13960a708f8fSGustavo F. Padovan } 13970a708f8fSGustavo F. Padovan 13980a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */ 13990a708f8fSGustavo F. Padovan 1400c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr. 14010a708f8fSGustavo F. Padovan * Returns closest match. 14020a708f8fSGustavo F. Padovan */ 1403c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, 1404c2287681SIdo Yariv bdaddr_t *src, 1405c2287681SIdo Yariv bdaddr_t *dst) 14060a708f8fSGustavo F. Padovan { 140723691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 14080a708f8fSGustavo F. Padovan 140923691d75SGustavo F. Padovan read_lock(&chan_list_lock); 14100a708f8fSGustavo F. Padovan 141123691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 141223691d75SGustavo F. Padovan struct sock *sk = c->sk; 1413fe4128e0SGustavo F. Padovan 141489bc500eSGustavo F. Padovan if (state && c->state != state) 14150a708f8fSGustavo F. Padovan continue; 14160a708f8fSGustavo F. Padovan 141723691d75SGustavo F. Padovan if (c->psm == psm) { 1418c2287681SIdo Yariv int src_match, dst_match; 1419c2287681SIdo Yariv int src_any, dst_any; 1420c2287681SIdo Yariv 14210a708f8fSGustavo F. Padovan /* Exact match. */ 1422c2287681SIdo Yariv src_match = !bacmp(&bt_sk(sk)->src, src); 1423c2287681SIdo Yariv dst_match = !bacmp(&bt_sk(sk)->dst, dst); 1424c2287681SIdo Yariv if (src_match && dst_match) { 1425a7567b20SJohannes Berg read_unlock(&chan_list_lock); 142623691d75SGustavo F. Padovan return c; 142723691d75SGustavo F. Padovan } 14280a708f8fSGustavo F. Padovan 14290a708f8fSGustavo F. Padovan /* Closest match */ 1430c2287681SIdo Yariv src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY); 1431c2287681SIdo Yariv dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY); 1432c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1433c2287681SIdo Yariv (src_any && dst_any)) 143423691d75SGustavo F. Padovan c1 = c; 14350a708f8fSGustavo F. Padovan } 14360a708f8fSGustavo F. Padovan } 14370a708f8fSGustavo F. Padovan 143823691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 14390a708f8fSGustavo F. Padovan 144023691d75SGustavo F. Padovan return c1; 14410a708f8fSGustavo F. Padovan } 14420a708f8fSGustavo F. Padovan 14438e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, 14448e9f9892SAndre Guedes bdaddr_t *dst, u8 dst_type) 14450a708f8fSGustavo F. Padovan { 14465d41ce1dSGustavo F. Padovan struct sock *sk = chan->sk; 14470a708f8fSGustavo F. Padovan bdaddr_t *src = &bt_sk(sk)->src; 14480a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 14490a708f8fSGustavo F. Padovan struct hci_conn *hcon; 14500a708f8fSGustavo F. Padovan struct hci_dev *hdev; 14510a708f8fSGustavo F. Padovan __u8 auth_type; 14520a708f8fSGustavo F. Padovan int err; 14530a708f8fSGustavo F. Padovan 14548e9f9892SAndre Guedes BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst), 14558e9f9892SAndre Guedes dst_type, __le16_to_cpu(chan->psm)); 14560a708f8fSGustavo F. Padovan 14570a708f8fSGustavo F. Padovan hdev = hci_get_route(dst, src); 14580a708f8fSGustavo F. Padovan if (!hdev) 14590a708f8fSGustavo F. Padovan return -EHOSTUNREACH; 14600a708f8fSGustavo F. Padovan 146109fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 14620a708f8fSGustavo F. Padovan 14636be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 146403a00194SGustavo F. Padovan 146503a00194SGustavo F. Padovan /* PSM must be odd and lsb of upper byte must be 0 */ 146603a00194SGustavo F. Padovan if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid && 146703a00194SGustavo F. Padovan chan->chan_type != L2CAP_CHAN_RAW) { 146803a00194SGustavo F. Padovan err = -EINVAL; 146903a00194SGustavo F. Padovan goto done; 147003a00194SGustavo F. Padovan } 147103a00194SGustavo F. Padovan 147203a00194SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) { 147303a00194SGustavo F. Padovan err = -EINVAL; 147403a00194SGustavo F. Padovan goto done; 147503a00194SGustavo F. Padovan } 147603a00194SGustavo F. Padovan 147703a00194SGustavo F. Padovan switch (chan->mode) { 147803a00194SGustavo F. Padovan case L2CAP_MODE_BASIC: 147903a00194SGustavo F. Padovan break; 148003a00194SGustavo F. Padovan case L2CAP_MODE_ERTM: 148103a00194SGustavo F. Padovan case L2CAP_MODE_STREAMING: 148203a00194SGustavo F. Padovan if (!disable_ertm) 148303a00194SGustavo F. Padovan break; 148403a00194SGustavo F. Padovan /* fall through */ 148503a00194SGustavo F. Padovan default: 148603a00194SGustavo F. Padovan err = -ENOTSUPP; 148703a00194SGustavo F. Padovan goto done; 148803a00194SGustavo F. Padovan } 148903a00194SGustavo F. Padovan 14906be36555SAndrei Emeltchenko lock_sock(sk); 14916be36555SAndrei Emeltchenko 149203a00194SGustavo F. Padovan switch (sk->sk_state) { 149303a00194SGustavo F. Padovan case BT_CONNECT: 149403a00194SGustavo F. Padovan case BT_CONNECT2: 149503a00194SGustavo F. Padovan case BT_CONFIG: 149603a00194SGustavo F. Padovan /* Already connecting */ 149703a00194SGustavo F. Padovan err = 0; 14986be36555SAndrei Emeltchenko release_sock(sk); 149903a00194SGustavo F. Padovan goto done; 150003a00194SGustavo F. Padovan 150103a00194SGustavo F. Padovan case BT_CONNECTED: 150203a00194SGustavo F. Padovan /* Already connected */ 150303a00194SGustavo F. Padovan err = -EISCONN; 15046be36555SAndrei Emeltchenko release_sock(sk); 150503a00194SGustavo F. Padovan goto done; 150603a00194SGustavo F. Padovan 150703a00194SGustavo F. Padovan case BT_OPEN: 150803a00194SGustavo F. Padovan case BT_BOUND: 150903a00194SGustavo F. Padovan /* Can connect */ 151003a00194SGustavo F. Padovan break; 151103a00194SGustavo F. Padovan 151203a00194SGustavo F. Padovan default: 151303a00194SGustavo F. Padovan err = -EBADFD; 15146be36555SAndrei Emeltchenko release_sock(sk); 151503a00194SGustavo F. Padovan goto done; 151603a00194SGustavo F. Padovan } 151703a00194SGustavo F. Padovan 151803a00194SGustavo F. Padovan /* Set destination address and psm */ 15199219b2a0SGustavo F. Padovan bacpy(&bt_sk(sk)->dst, dst); 15206be36555SAndrei Emeltchenko 15216be36555SAndrei Emeltchenko release_sock(sk); 15226be36555SAndrei Emeltchenko 152303a00194SGustavo F. Padovan chan->psm = psm; 152403a00194SGustavo F. Padovan chan->dcid = cid; 15250a708f8fSGustavo F. Padovan 15264343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 15270a708f8fSGustavo F. Padovan 1528fe4128e0SGustavo F. Padovan if (chan->dcid == L2CAP_CID_LE_DATA) 15298e9f9892SAndre Guedes hcon = hci_connect(hdev, LE_LINK, dst, dst_type, 15304343478fSGustavo F. Padovan chan->sec_level, auth_type); 1531acd7d370SVille Tervo else 15328e9f9892SAndre Guedes hcon = hci_connect(hdev, ACL_LINK, dst, dst_type, 15334343478fSGustavo F. Padovan chan->sec_level, auth_type); 1534acd7d370SVille Tervo 153530e76272SVille Tervo if (IS_ERR(hcon)) { 153630e76272SVille Tervo err = PTR_ERR(hcon); 15370a708f8fSGustavo F. Padovan goto done; 153830e76272SVille Tervo } 15390a708f8fSGustavo F. Padovan 15400a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, 0); 15410a708f8fSGustavo F. Padovan if (!conn) { 15420a708f8fSGustavo F. Padovan hci_conn_put(hcon); 154330e76272SVille Tervo err = -ENOMEM; 15440a708f8fSGustavo F. Padovan goto done; 15450a708f8fSGustavo F. Padovan } 15460a708f8fSGustavo F. Padovan 15479f0caeb1SVinicius Costa Gomes if (hcon->type == LE_LINK) { 15489f0caeb1SVinicius Costa Gomes err = 0; 15499f0caeb1SVinicius Costa Gomes 15509f0caeb1SVinicius Costa Gomes if (!list_empty(&conn->chan_l)) { 15519f0caeb1SVinicius Costa Gomes err = -EBUSY; 15529f0caeb1SVinicius Costa Gomes hci_conn_put(hcon); 15539f0caeb1SVinicius Costa Gomes } 15549f0caeb1SVinicius Costa Gomes 15559f0caeb1SVinicius Costa Gomes if (err) 15569f0caeb1SVinicius Costa Gomes goto done; 15579f0caeb1SVinicius Costa Gomes } 15589f0caeb1SVinicius Costa Gomes 15590a708f8fSGustavo F. Padovan /* Update source addr of the socket */ 15600a708f8fSGustavo F. Padovan bacpy(src, conn->src); 15610a708f8fSGustavo F. Padovan 15626be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 156348454079SGustavo F. Padovan l2cap_chan_add(conn, chan); 15646be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 156548454079SGustavo F. Padovan 15666be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECT); 1567c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 15680a708f8fSGustavo F. Padovan 15690a708f8fSGustavo F. Padovan if (hcon->state == BT_CONNECTED) { 1570715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1571c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 1572d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) 15736be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECTED); 15740a708f8fSGustavo F. Padovan } else 1575fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 15760a708f8fSGustavo F. Padovan } 15770a708f8fSGustavo F. Padovan 157830e76272SVille Tervo err = 0; 157930e76272SVille Tervo 15800a708f8fSGustavo F. Padovan done: 15816be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 158209fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 15830a708f8fSGustavo F. Padovan hci_dev_put(hdev); 15840a708f8fSGustavo F. Padovan return err; 15850a708f8fSGustavo F. Padovan } 15860a708f8fSGustavo F. Padovan 1587dcba0dbaSGustavo F. Padovan int __l2cap_wait_ack(struct sock *sk) 15880a708f8fSGustavo F. Padovan { 15898c1d787bSGustavo F. Padovan struct l2cap_chan *chan = l2cap_pi(sk)->chan; 15900a708f8fSGustavo F. Padovan DECLARE_WAITQUEUE(wait, current); 15910a708f8fSGustavo F. Padovan int err = 0; 15920a708f8fSGustavo F. Padovan int timeo = HZ/5; 15930a708f8fSGustavo F. Padovan 15940a708f8fSGustavo F. Padovan add_wait_queue(sk_sleep(sk), &wait); 15950a708f8fSGustavo F. Padovan set_current_state(TASK_INTERRUPTIBLE); 1596a71a0cf4SPeter Hurley while (chan->unacked_frames > 0 && chan->conn) { 15970a708f8fSGustavo F. Padovan if (!timeo) 15980a708f8fSGustavo F. Padovan timeo = HZ/5; 15990a708f8fSGustavo F. Padovan 16000a708f8fSGustavo F. Padovan if (signal_pending(current)) { 16010a708f8fSGustavo F. Padovan err = sock_intr_errno(timeo); 16020a708f8fSGustavo F. Padovan break; 16030a708f8fSGustavo F. Padovan } 16040a708f8fSGustavo F. Padovan 16050a708f8fSGustavo F. Padovan release_sock(sk); 16060a708f8fSGustavo F. Padovan timeo = schedule_timeout(timeo); 16070a708f8fSGustavo F. Padovan lock_sock(sk); 1608a71a0cf4SPeter Hurley set_current_state(TASK_INTERRUPTIBLE); 16090a708f8fSGustavo F. Padovan 16100a708f8fSGustavo F. Padovan err = sock_error(sk); 16110a708f8fSGustavo F. Padovan if (err) 16120a708f8fSGustavo F. Padovan break; 16130a708f8fSGustavo F. Padovan } 16140a708f8fSGustavo F. Padovan set_current_state(TASK_RUNNING); 16150a708f8fSGustavo F. Padovan remove_wait_queue(sk_sleep(sk), &wait); 16160a708f8fSGustavo F. Padovan return err; 16170a708f8fSGustavo F. Padovan } 16180a708f8fSGustavo F. Padovan 1619721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work) 16200a708f8fSGustavo F. Padovan { 1621721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1622721c4181SGustavo F. Padovan monitor_timer.work); 16230a708f8fSGustavo F. Padovan 1624525cd185SGustavo F. Padovan BT_DBG("chan %p", chan); 16250a708f8fSGustavo F. Padovan 16266be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 16276be36555SAndrei Emeltchenko 16282c03a7a4SGustavo F. Padovan if (chan->retry_count >= chan->remote_max_tx) { 16298c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); 16306be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16318d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 16320a708f8fSGustavo F. Padovan return; 16330a708f8fSGustavo F. Padovan } 16340a708f8fSGustavo F. Padovan 16356a026610SGustavo F. Padovan chan->retry_count++; 16361a09bcb9SGustavo F. Padovan __set_monitor_timer(chan); 16370a708f8fSGustavo F. Padovan 1638525cd185SGustavo F. Padovan l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); 16396be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16408d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 16410a708f8fSGustavo F. Padovan } 16420a708f8fSGustavo F. Padovan 1643721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work) 16440a708f8fSGustavo F. Padovan { 1645721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1646721c4181SGustavo F. Padovan retrans_timer.work); 16470a708f8fSGustavo F. Padovan 164849208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 16490a708f8fSGustavo F. Padovan 16506be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 16516be36555SAndrei Emeltchenko 16526a026610SGustavo F. Padovan chan->retry_count = 1; 16531a09bcb9SGustavo F. Padovan __set_monitor_timer(chan); 16540a708f8fSGustavo F. Padovan 1655e2ab4353SGustavo F. Padovan set_bit(CONN_WAIT_F, &chan->conn_state); 16560a708f8fSGustavo F. Padovan 1657525cd185SGustavo F. Padovan l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); 16586be36555SAndrei Emeltchenko 16596be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16608d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 16610a708f8fSGustavo F. Padovan } 16620a708f8fSGustavo F. Padovan 16633733937dSMat Martineau static int l2cap_streaming_send(struct l2cap_chan *chan, 16643733937dSMat Martineau struct sk_buff_head *skbs) 16650a708f8fSGustavo F. Padovan { 16660a708f8fSGustavo F. Padovan struct sk_buff *skb; 16673733937dSMat Martineau struct l2cap_ctrl *control; 16680a708f8fSGustavo F. Padovan 16693733937dSMat Martineau BT_DBG("chan %p, skbs %p", chan, skbs); 16703733937dSMat Martineau 16713733937dSMat Martineau if (chan->state != BT_CONNECTED) 16723733937dSMat Martineau return -ENOTCONN; 16733733937dSMat Martineau 16743733937dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 16753733937dSMat Martineau 16763733937dSMat Martineau while (!skb_queue_empty(&chan->tx_q)) { 16773733937dSMat Martineau 16783733937dSMat Martineau skb = skb_dequeue(&chan->tx_q); 16793733937dSMat Martineau 16803733937dSMat Martineau bt_cb(skb)->control.retries = 1; 16813733937dSMat Martineau control = &bt_cb(skb)->control; 16823733937dSMat Martineau 16833733937dSMat Martineau control->reqseq = 0; 16843733937dSMat Martineau control->txseq = chan->next_tx_seq; 16853733937dSMat Martineau 16863733937dSMat Martineau __pack_control(chan, control, skb); 16870a708f8fSGustavo F. Padovan 168847d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 16893733937dSMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 16903733937dSMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 16910a708f8fSGustavo F. Padovan } 16920a708f8fSGustavo F. Padovan 16934343478fSGustavo F. Padovan l2cap_do_send(chan, skb); 16940a708f8fSGustavo F. Padovan 16953733937dSMat Martineau BT_DBG("Sent txseq %d", (int)control->txseq); 16963733937dSMat Martineau 1697836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 16983733937dSMat Martineau chan->frames_sent++; 16990a708f8fSGustavo F. Padovan } 17003733937dSMat Martineau 17013733937dSMat Martineau return 0; 17020a708f8fSGustavo F. Padovan } 17030a708f8fSGustavo F. Padovan 170467c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan) 17050a708f8fSGustavo F. Padovan { 17060a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 170718a48e76SMat Martineau struct l2cap_ctrl *control; 170818a48e76SMat Martineau int sent = 0; 170918a48e76SMat Martineau 171018a48e76SMat Martineau BT_DBG("chan %p", chan); 17110a708f8fSGustavo F. Padovan 171289bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 17130a708f8fSGustavo F. Padovan return -ENOTCONN; 17140a708f8fSGustavo F. Padovan 171594122bbeSMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 171694122bbeSMat Martineau return 0; 171794122bbeSMat Martineau 171818a48e76SMat Martineau while (chan->tx_send_head && 171918a48e76SMat Martineau chan->unacked_frames < chan->remote_tx_win && 172018a48e76SMat Martineau chan->tx_state == L2CAP_TX_STATE_XMIT) { 17210a708f8fSGustavo F. Padovan 172218a48e76SMat Martineau skb = chan->tx_send_head; 17230a708f8fSGustavo F. Padovan 172418a48e76SMat Martineau bt_cb(skb)->control.retries = 1; 172518a48e76SMat Martineau control = &bt_cb(skb)->control; 17260a708f8fSGustavo F. Padovan 1727e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 172818a48e76SMat Martineau control->final = 1; 1729e2ab4353SGustavo F. Padovan 173018a48e76SMat Martineau control->reqseq = chan->buffer_seq; 173118a48e76SMat Martineau chan->last_acked_seq = chan->buffer_seq; 173218a48e76SMat Martineau control->txseq = chan->next_tx_seq; 17330a708f8fSGustavo F. Padovan 173418a48e76SMat Martineau __pack_control(chan, control, skb); 17350a708f8fSGustavo F. Padovan 173647d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 173718a48e76SMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 173818a48e76SMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 17390a708f8fSGustavo F. Padovan } 17400a708f8fSGustavo F. Padovan 174118a48e76SMat Martineau /* Clone after data has been modified. Data is assumed to be 174218a48e76SMat Martineau read-only (for locking purposes) on cloned sk_buffs. 174318a48e76SMat Martineau */ 174418a48e76SMat Martineau tx_skb = skb_clone(skb, GFP_KERNEL); 174518a48e76SMat Martineau 174618a48e76SMat Martineau if (!tx_skb) 174718a48e76SMat Martineau break; 17480a708f8fSGustavo F. Padovan 17491a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 17500a708f8fSGustavo F. Padovan 1751836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 17526a026610SGustavo F. Padovan chan->unacked_frames++; 17536a026610SGustavo F. Padovan chan->frames_sent++; 175418a48e76SMat Martineau sent++; 17550a708f8fSGustavo F. Padovan 175658d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 175758d35f87SGustavo F. Padovan chan->tx_send_head = NULL; 17580a708f8fSGustavo F. Padovan else 175958d35f87SGustavo F. Padovan chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); 176018a48e76SMat Martineau 176118a48e76SMat Martineau l2cap_do_send(chan, tx_skb); 176218a48e76SMat Martineau BT_DBG("Sent txseq %d", (int)control->txseq); 17630a708f8fSGustavo F. Padovan } 17640a708f8fSGustavo F. Padovan 176518a48e76SMat Martineau BT_DBG("Sent %d, %d unacked, %d in ERTM queue", sent, 176618a48e76SMat Martineau (int) chan->unacked_frames, skb_queue_len(&chan->tx_q)); 176718a48e76SMat Martineau 176818a48e76SMat Martineau return sent; 17690a708f8fSGustavo F. Padovan } 17700a708f8fSGustavo F. Padovan 1771e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan) 1772e1fbd4c1SMat Martineau { 1773e1fbd4c1SMat Martineau struct l2cap_ctrl control; 1774e1fbd4c1SMat Martineau struct sk_buff *skb; 1775e1fbd4c1SMat Martineau struct sk_buff *tx_skb; 1776e1fbd4c1SMat Martineau u16 seq; 1777e1fbd4c1SMat Martineau 1778e1fbd4c1SMat Martineau BT_DBG("chan %p", chan); 1779e1fbd4c1SMat Martineau 1780e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 1781e1fbd4c1SMat Martineau return; 1782e1fbd4c1SMat Martineau 1783e1fbd4c1SMat Martineau while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) { 1784e1fbd4c1SMat Martineau seq = l2cap_seq_list_pop(&chan->retrans_list); 1785e1fbd4c1SMat Martineau 1786e1fbd4c1SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq); 1787e1fbd4c1SMat Martineau if (!skb) { 1788e1fbd4c1SMat Martineau BT_DBG("Error: Can't retransmit seq %d, frame missing", 1789e1fbd4c1SMat Martineau seq); 1790e1fbd4c1SMat Martineau continue; 1791e1fbd4c1SMat Martineau } 1792e1fbd4c1SMat Martineau 1793e1fbd4c1SMat Martineau bt_cb(skb)->control.retries++; 1794e1fbd4c1SMat Martineau control = bt_cb(skb)->control; 1795e1fbd4c1SMat Martineau 1796e1fbd4c1SMat Martineau if (chan->max_tx != 0 && 1797e1fbd4c1SMat Martineau bt_cb(skb)->control.retries > chan->max_tx) { 1798e1fbd4c1SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 1799e1fbd4c1SMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 1800e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 1801e1fbd4c1SMat Martineau break; 1802e1fbd4c1SMat Martineau } 1803e1fbd4c1SMat Martineau 1804e1fbd4c1SMat Martineau control.reqseq = chan->buffer_seq; 1805e1fbd4c1SMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 1806e1fbd4c1SMat Martineau control.final = 1; 1807e1fbd4c1SMat Martineau else 1808e1fbd4c1SMat Martineau control.final = 0; 1809e1fbd4c1SMat Martineau 1810e1fbd4c1SMat Martineau if (skb_cloned(skb)) { 1811e1fbd4c1SMat Martineau /* Cloned sk_buffs are read-only, so we need a 1812e1fbd4c1SMat Martineau * writeable copy 1813e1fbd4c1SMat Martineau */ 1814e1fbd4c1SMat Martineau tx_skb = skb_copy(skb, GFP_ATOMIC); 1815e1fbd4c1SMat Martineau } else { 1816e1fbd4c1SMat Martineau tx_skb = skb_clone(skb, GFP_ATOMIC); 1817e1fbd4c1SMat Martineau } 1818e1fbd4c1SMat Martineau 1819e1fbd4c1SMat Martineau if (!tx_skb) { 1820e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 1821e1fbd4c1SMat Martineau break; 1822e1fbd4c1SMat Martineau } 1823e1fbd4c1SMat Martineau 1824e1fbd4c1SMat Martineau /* Update skb contents */ 1825e1fbd4c1SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 1826e1fbd4c1SMat Martineau put_unaligned_le32(__pack_extended_control(&control), 1827e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 1828e1fbd4c1SMat Martineau } else { 1829e1fbd4c1SMat Martineau put_unaligned_le16(__pack_enhanced_control(&control), 1830e1fbd4c1SMat Martineau tx_skb->data + L2CAP_HDR_SIZE); 1831e1fbd4c1SMat Martineau } 1832e1fbd4c1SMat Martineau 1833e1fbd4c1SMat Martineau if (chan->fcs == L2CAP_FCS_CRC16) { 1834e1fbd4c1SMat Martineau u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len); 1835e1fbd4c1SMat Martineau put_unaligned_le16(fcs, skb_put(tx_skb, 1836e1fbd4c1SMat Martineau L2CAP_FCS_SIZE)); 1837e1fbd4c1SMat Martineau } 1838e1fbd4c1SMat Martineau 1839e1fbd4c1SMat Martineau l2cap_do_send(chan, tx_skb); 1840e1fbd4c1SMat Martineau 1841e1fbd4c1SMat Martineau BT_DBG("Resent txseq %d", control.txseq); 1842e1fbd4c1SMat Martineau 1843e1fbd4c1SMat Martineau chan->last_acked_seq = chan->buffer_seq; 1844e1fbd4c1SMat Martineau } 1845e1fbd4c1SMat Martineau } 1846e1fbd4c1SMat Martineau 1847f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan, 1848f80842a8SMat Martineau struct l2cap_ctrl *control) 1849f80842a8SMat Martineau { 1850f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 1851f80842a8SMat Martineau 1852f80842a8SMat Martineau l2cap_seq_list_append(&chan->retrans_list, control->reqseq); 1853f80842a8SMat Martineau l2cap_ertm_resend(chan); 1854f80842a8SMat Martineau } 1855f80842a8SMat Martineau 1856d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan, 1857d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 1858d2a7ac5dSMat Martineau { 1859e1fbd4c1SMat Martineau struct sk_buff *skb; 1860e1fbd4c1SMat Martineau 1861e1fbd4c1SMat Martineau BT_DBG("chan %p, control %p", chan, control); 1862e1fbd4c1SMat Martineau 1863e1fbd4c1SMat Martineau if (control->poll) 1864e1fbd4c1SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 1865e1fbd4c1SMat Martineau 1866e1fbd4c1SMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 1867e1fbd4c1SMat Martineau 1868e1fbd4c1SMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 1869e1fbd4c1SMat Martineau return; 1870e1fbd4c1SMat Martineau 1871e1fbd4c1SMat Martineau if (chan->unacked_frames) { 1872e1fbd4c1SMat Martineau skb_queue_walk(&chan->tx_q, skb) { 1873e1fbd4c1SMat Martineau if (bt_cb(skb)->control.txseq == control->reqseq || 1874e1fbd4c1SMat Martineau skb == chan->tx_send_head) 1875e1fbd4c1SMat Martineau break; 1876e1fbd4c1SMat Martineau } 1877e1fbd4c1SMat Martineau 1878e1fbd4c1SMat Martineau skb_queue_walk_from(&chan->tx_q, skb) { 1879e1fbd4c1SMat Martineau if (skb == chan->tx_send_head) 1880e1fbd4c1SMat Martineau break; 1881e1fbd4c1SMat Martineau 1882e1fbd4c1SMat Martineau l2cap_seq_list_append(&chan->retrans_list, 1883e1fbd4c1SMat Martineau bt_cb(skb)->control.txseq); 1884e1fbd4c1SMat Martineau } 1885e1fbd4c1SMat Martineau 1886e1fbd4c1SMat Martineau l2cap_ertm_resend(chan); 1887e1fbd4c1SMat Martineau } 1888d2a7ac5dSMat Martineau } 1889d2a7ac5dSMat Martineau 1890b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan) 1891b17e73bbSSzymon Janc { 18920a0aba42SMat Martineau struct l2cap_ctrl control; 18930a0aba42SMat Martineau u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq, 18940a0aba42SMat Martineau chan->last_acked_seq); 18950a0aba42SMat Martineau int threshold; 18960a0aba42SMat Martineau 18970a0aba42SMat Martineau BT_DBG("chan %p last_acked_seq %d buffer_seq %d", 18980a0aba42SMat Martineau chan, chan->last_acked_seq, chan->buffer_seq); 18990a0aba42SMat Martineau 19000a0aba42SMat Martineau memset(&control, 0, sizeof(control)); 19010a0aba42SMat Martineau control.sframe = 1; 19020a0aba42SMat Martineau 19030a0aba42SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 19040a0aba42SMat Martineau chan->rx_state == L2CAP_RX_STATE_RECV) { 1905b17e73bbSSzymon Janc __clear_ack_timer(chan); 19060a0aba42SMat Martineau control.super = L2CAP_SUPER_RNR; 19070a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 19080a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 19090a0aba42SMat Martineau } else { 19100a0aba42SMat Martineau if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) { 19110a0aba42SMat Martineau l2cap_ertm_send(chan); 19120a0aba42SMat Martineau /* If any i-frames were sent, they included an ack */ 19130a0aba42SMat Martineau if (chan->buffer_seq == chan->last_acked_seq) 19140a0aba42SMat Martineau frames_to_ack = 0; 19150a0aba42SMat Martineau } 19160a0aba42SMat Martineau 19170a0aba42SMat Martineau /* Ack now if the tx window is 3/4ths full. 19180a0aba42SMat Martineau * Calculate without mul or div 19190a0aba42SMat Martineau */ 19200a0aba42SMat Martineau threshold = chan->tx_win; 19210a0aba42SMat Martineau threshold += threshold << 1; 19220a0aba42SMat Martineau threshold >>= 2; 19230a0aba42SMat Martineau 19240a0aba42SMat Martineau BT_DBG("frames_to_ack %d, threshold %d", (int)frames_to_ack, 19250a0aba42SMat Martineau threshold); 19260a0aba42SMat Martineau 19270a0aba42SMat Martineau if (frames_to_ack >= threshold) { 19280a0aba42SMat Martineau __clear_ack_timer(chan); 19290a0aba42SMat Martineau control.super = L2CAP_SUPER_RR; 19300a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 19310a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 19320a0aba42SMat Martineau frames_to_ack = 0; 19330a0aba42SMat Martineau } 19340a0aba42SMat Martineau 19350a0aba42SMat Martineau if (frames_to_ack) 19360a0aba42SMat Martineau __set_ack_timer(chan); 19370a0aba42SMat Martineau } 1938b17e73bbSSzymon Janc } 1939b17e73bbSSzymon Janc 194004124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, 194104124681SGustavo F. Padovan struct msghdr *msg, int len, 194204124681SGustavo F. Padovan int count, struct sk_buff *skb) 19430a708f8fSGustavo F. Padovan { 19440952a57aSAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 19450a708f8fSGustavo F. Padovan struct sk_buff **frag; 194690338947SGustavo Padovan int sent = 0; 19470a708f8fSGustavo F. Padovan 19480a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) 19490a708f8fSGustavo F. Padovan return -EFAULT; 19500a708f8fSGustavo F. Padovan 19510a708f8fSGustavo F. Padovan sent += count; 19520a708f8fSGustavo F. Padovan len -= count; 19530a708f8fSGustavo F. Padovan 19540a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 19550a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 19560a708f8fSGustavo F. Padovan while (len) { 1957fbe00700SGustavo Padovan struct sk_buff *tmp; 1958fbe00700SGustavo Padovan 19590a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 19600a708f8fSGustavo F. Padovan 1961fbe00700SGustavo Padovan tmp = chan->ops->alloc_skb(chan, count, 196290338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 1963fbe00700SGustavo Padovan if (IS_ERR(tmp)) 1964fbe00700SGustavo Padovan return PTR_ERR(tmp); 19652f7719ceSAndrei Emeltchenko 1966fbe00700SGustavo Padovan *frag = tmp; 1967fbe00700SGustavo Padovan 19680a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) 19690a708f8fSGustavo F. Padovan return -EFAULT; 19700a708f8fSGustavo F. Padovan 19715e59b791SLuiz Augusto von Dentz (*frag)->priority = skb->priority; 19725e59b791SLuiz Augusto von Dentz 19730a708f8fSGustavo F. Padovan sent += count; 19740a708f8fSGustavo F. Padovan len -= count; 19750a708f8fSGustavo F. Padovan 19762d0ed3d5SGustavo Padovan skb->len += (*frag)->len; 19772d0ed3d5SGustavo Padovan skb->data_len += (*frag)->len; 19782d0ed3d5SGustavo Padovan 19790a708f8fSGustavo F. Padovan frag = &(*frag)->next; 19800a708f8fSGustavo F. Padovan } 19810a708f8fSGustavo F. Padovan 19820a708f8fSGustavo F. Padovan return sent; 19830a708f8fSGustavo F. Padovan } 19840a708f8fSGustavo F. Padovan 19855e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, 19865e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 19875e59b791SLuiz Augusto von Dentz u32 priority) 19880a708f8fSGustavo F. Padovan { 19898c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 19900a708f8fSGustavo F. Padovan struct sk_buff *skb; 199103a51213SAndrei Emeltchenko int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; 19920a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 19930a708f8fSGustavo F. Padovan 19946d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d priority %u", chan, (int)len, priority); 19950a708f8fSGustavo F. Padovan 19960a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 19972f7719ceSAndrei Emeltchenko 19982f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 199990338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 200090338947SGustavo Padovan if (IS_ERR(skb)) 200190338947SGustavo Padovan return skb; 20020a708f8fSGustavo F. Padovan 20035e59b791SLuiz Augusto von Dentz skb->priority = priority; 20045e59b791SLuiz Augusto von Dentz 20050a708f8fSGustavo F. Padovan /* Create L2CAP header */ 20060a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2007fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 2008daf6a78cSAndrei Emeltchenko lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); 2009daf6a78cSAndrei Emeltchenko put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE)); 20100a708f8fSGustavo F. Padovan 20110952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 20120a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 20130a708f8fSGustavo F. Padovan kfree_skb(skb); 20140a708f8fSGustavo F. Padovan return ERR_PTR(err); 20150a708f8fSGustavo F. Padovan } 20160a708f8fSGustavo F. Padovan return skb; 20170a708f8fSGustavo F. Padovan } 20180a708f8fSGustavo F. Padovan 20195e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, 20205e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 20215e59b791SLuiz Augusto von Dentz u32 priority) 20220a708f8fSGustavo F. Padovan { 20238c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 20240a708f8fSGustavo F. Padovan struct sk_buff *skb; 2025f2ba7faeSGustavo Padovan int err, count; 20260a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 20270a708f8fSGustavo F. Padovan 20286d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d", chan, (int)len); 20290a708f8fSGustavo F. Padovan 2030f2ba7faeSGustavo Padovan count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); 20312f7719ceSAndrei Emeltchenko 2032f2ba7faeSGustavo Padovan skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE, 203390338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 203490338947SGustavo Padovan if (IS_ERR(skb)) 203590338947SGustavo Padovan return skb; 20360a708f8fSGustavo F. Padovan 20375e59b791SLuiz Augusto von Dentz skb->priority = priority; 20385e59b791SLuiz Augusto von Dentz 20390a708f8fSGustavo F. Padovan /* Create L2CAP header */ 20400a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2041fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 20426ff9b5efSGustavo Padovan lh->len = cpu_to_le16(len); 20430a708f8fSGustavo F. Padovan 20440952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 20450a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 20460a708f8fSGustavo F. Padovan kfree_skb(skb); 20470a708f8fSGustavo F. Padovan return ERR_PTR(err); 20480a708f8fSGustavo F. Padovan } 20490a708f8fSGustavo F. Padovan return skb; 20500a708f8fSGustavo F. Padovan } 20510a708f8fSGustavo F. Padovan 2052ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, 2053ab0ff76dSLuiz Augusto von Dentz struct msghdr *msg, size_t len, 205494122bbeSMat Martineau u16 sdulen) 20550a708f8fSGustavo F. Padovan { 20568c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 20570a708f8fSGustavo F. Padovan struct sk_buff *skb; 2058e4ca6d98SAndrei Emeltchenko int err, count, hlen; 20590a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 20600a708f8fSGustavo F. Padovan 20616d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d", chan, (int)len); 20620a708f8fSGustavo F. Padovan 20630a708f8fSGustavo F. Padovan if (!conn) 20640a708f8fSGustavo F. Padovan return ERR_PTR(-ENOTCONN); 20650a708f8fSGustavo F. Padovan 2066e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 2067e4ca6d98SAndrei Emeltchenko hlen = L2CAP_EXT_HDR_SIZE; 2068e4ca6d98SAndrei Emeltchenko else 2069e4ca6d98SAndrei Emeltchenko hlen = L2CAP_ENH_HDR_SIZE; 2070e4ca6d98SAndrei Emeltchenko 20710a708f8fSGustavo F. Padovan if (sdulen) 207203a51213SAndrei Emeltchenko hlen += L2CAP_SDULEN_SIZE; 20730a708f8fSGustavo F. Padovan 207447d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 207503a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 20760a708f8fSGustavo F. Padovan 20770a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 20782f7719ceSAndrei Emeltchenko 20792f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 208090338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 208190338947SGustavo Padovan if (IS_ERR(skb)) 208290338947SGustavo Padovan return skb; 20830a708f8fSGustavo F. Padovan 20840a708f8fSGustavo F. Padovan /* Create L2CAP header */ 20850a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 2086fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 20870a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 208888843ab0SAndrei Emeltchenko 208918a48e76SMat Martineau /* Control header is populated later */ 209018a48e76SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 209118a48e76SMat Martineau put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 209218a48e76SMat Martineau else 209318a48e76SMat Martineau put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 209488843ab0SAndrei Emeltchenko 20950a708f8fSGustavo F. Padovan if (sdulen) 209603a51213SAndrei Emeltchenko put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 20970a708f8fSGustavo F. Padovan 20980952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 20990a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 21000a708f8fSGustavo F. Padovan kfree_skb(skb); 21010a708f8fSGustavo F. Padovan return ERR_PTR(err); 21020a708f8fSGustavo F. Padovan } 21030a708f8fSGustavo F. Padovan 210418a48e76SMat Martineau bt_cb(skb)->control.fcs = chan->fcs; 21053ce3514fSMat Martineau bt_cb(skb)->control.retries = 0; 21060a708f8fSGustavo F. Padovan return skb; 21070a708f8fSGustavo F. Padovan } 21080a708f8fSGustavo F. Padovan 210994122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan, 211094122bbeSMat Martineau struct sk_buff_head *seg_queue, 211194122bbeSMat Martineau struct msghdr *msg, size_t len) 21120a708f8fSGustavo F. Padovan { 21130a708f8fSGustavo F. Padovan struct sk_buff *skb; 211494122bbeSMat Martineau u16 sdu_len; 211594122bbeSMat Martineau size_t pdu_len; 211694122bbeSMat Martineau int err = 0; 211794122bbeSMat Martineau u8 sar; 21180a708f8fSGustavo F. Padovan 211994122bbeSMat Martineau BT_DBG("chan %p, msg %p, len %d", chan, msg, (int)len); 21200a708f8fSGustavo F. Padovan 212194122bbeSMat Martineau /* It is critical that ERTM PDUs fit in a single HCI fragment, 212294122bbeSMat Martineau * so fragmented skbs are not used. The HCI layer's handling 212394122bbeSMat Martineau * of fragmented skbs is not compatible with ERTM's queueing. 212494122bbeSMat Martineau */ 212594122bbeSMat Martineau 212694122bbeSMat Martineau /* PDU size is derived from the HCI MTU */ 212794122bbeSMat Martineau pdu_len = chan->conn->mtu; 212894122bbeSMat Martineau 212994122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); 213094122bbeSMat Martineau 213194122bbeSMat Martineau /* Adjust for largest possible L2CAP overhead. */ 213294122bbeSMat Martineau pdu_len -= L2CAP_EXT_HDR_SIZE + L2CAP_FCS_SIZE; 213394122bbeSMat Martineau 213494122bbeSMat Martineau /* Remote device may have requested smaller PDUs */ 213594122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, chan->remote_mps); 213694122bbeSMat Martineau 213794122bbeSMat Martineau if (len <= pdu_len) { 213894122bbeSMat Martineau sar = L2CAP_SAR_UNSEGMENTED; 213994122bbeSMat Martineau sdu_len = 0; 214094122bbeSMat Martineau pdu_len = len; 214194122bbeSMat Martineau } else { 214294122bbeSMat Martineau sar = L2CAP_SAR_START; 214394122bbeSMat Martineau sdu_len = len; 214494122bbeSMat Martineau pdu_len -= L2CAP_SDULEN_SIZE; 214594122bbeSMat Martineau } 21460a708f8fSGustavo F. Padovan 21470a708f8fSGustavo F. Padovan while (len > 0) { 214894122bbeSMat Martineau skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len); 21490a708f8fSGustavo F. Padovan 21500a708f8fSGustavo F. Padovan if (IS_ERR(skb)) { 215194122bbeSMat Martineau __skb_queue_purge(seg_queue); 21520a708f8fSGustavo F. Padovan return PTR_ERR(skb); 21530a708f8fSGustavo F. Padovan } 21540a708f8fSGustavo F. Padovan 215594122bbeSMat Martineau bt_cb(skb)->control.sar = sar; 215694122bbeSMat Martineau __skb_queue_tail(seg_queue, skb); 21570a708f8fSGustavo F. Padovan 215894122bbeSMat Martineau len -= pdu_len; 215994122bbeSMat Martineau if (sdu_len) { 216094122bbeSMat Martineau sdu_len = 0; 216194122bbeSMat Martineau pdu_len += L2CAP_SDULEN_SIZE; 216294122bbeSMat Martineau } 216394122bbeSMat Martineau 216494122bbeSMat Martineau if (len <= pdu_len) { 216594122bbeSMat Martineau sar = L2CAP_SAR_END; 216694122bbeSMat Martineau pdu_len = len; 216794122bbeSMat Martineau } else { 216894122bbeSMat Martineau sar = L2CAP_SAR_CONTINUE; 216994122bbeSMat Martineau } 217094122bbeSMat Martineau } 217194122bbeSMat Martineau 217294122bbeSMat Martineau return err; 21730a708f8fSGustavo F. Padovan } 21740a708f8fSGustavo F. Padovan 21755e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, 21765e59b791SLuiz Augusto von Dentz u32 priority) 21779a91a04aSGustavo F. Padovan { 21789a91a04aSGustavo F. Padovan struct sk_buff *skb; 21799a91a04aSGustavo F. Padovan int err; 218094122bbeSMat Martineau struct sk_buff_head seg_queue; 21819a91a04aSGustavo F. Padovan 21829a91a04aSGustavo F. Padovan /* Connectionless channel */ 2183715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { 21845e59b791SLuiz Augusto von Dentz skb = l2cap_create_connless_pdu(chan, msg, len, priority); 21859a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 21869a91a04aSGustavo F. Padovan return PTR_ERR(skb); 21879a91a04aSGustavo F. Padovan 21889a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 21899a91a04aSGustavo F. Padovan return len; 21909a91a04aSGustavo F. Padovan } 21919a91a04aSGustavo F. Padovan 21929a91a04aSGustavo F. Padovan switch (chan->mode) { 21939a91a04aSGustavo F. Padovan case L2CAP_MODE_BASIC: 21949a91a04aSGustavo F. Padovan /* Check outgoing MTU */ 21959a91a04aSGustavo F. Padovan if (len > chan->omtu) 21969a91a04aSGustavo F. Padovan return -EMSGSIZE; 21979a91a04aSGustavo F. Padovan 21989a91a04aSGustavo F. Padovan /* Create a basic PDU */ 21995e59b791SLuiz Augusto von Dentz skb = l2cap_create_basic_pdu(chan, msg, len, priority); 22009a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 22019a91a04aSGustavo F. Padovan return PTR_ERR(skb); 22029a91a04aSGustavo F. Padovan 22039a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 22049a91a04aSGustavo F. Padovan err = len; 22059a91a04aSGustavo F. Padovan break; 22069a91a04aSGustavo F. Padovan 22079a91a04aSGustavo F. Padovan case L2CAP_MODE_ERTM: 22089a91a04aSGustavo F. Padovan case L2CAP_MODE_STREAMING: 220994122bbeSMat Martineau /* Check outgoing MTU */ 221094122bbeSMat Martineau if (len > chan->omtu) { 221194122bbeSMat Martineau err = -EMSGSIZE; 22129a91a04aSGustavo F. Padovan break; 22139a91a04aSGustavo F. Padovan } 22149a91a04aSGustavo F. Padovan 221594122bbeSMat Martineau __skb_queue_head_init(&seg_queue); 221694122bbeSMat Martineau 221794122bbeSMat Martineau /* Do segmentation before calling in to the state machine, 221894122bbeSMat Martineau * since it's possible to block while waiting for memory 221994122bbeSMat Martineau * allocation. 222094122bbeSMat Martineau */ 222194122bbeSMat Martineau err = l2cap_segment_sdu(chan, &seg_queue, msg, len); 222294122bbeSMat Martineau 222394122bbeSMat Martineau /* The channel could have been closed while segmenting, 222494122bbeSMat Martineau * check that it is still connected. 222594122bbeSMat Martineau */ 222694122bbeSMat Martineau if (chan->state != BT_CONNECTED) { 222794122bbeSMat Martineau __skb_queue_purge(&seg_queue); 222894122bbeSMat Martineau err = -ENOTCONN; 22299a91a04aSGustavo F. Padovan } 22309a91a04aSGustavo F. Padovan 223194122bbeSMat Martineau if (err) 223294122bbeSMat Martineau break; 223394122bbeSMat Martineau 22343733937dSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) 2235608bcc6dSMat Martineau err = l2cap_tx(chan, 0, &seg_queue, 2236608bcc6dSMat Martineau L2CAP_EV_DATA_REQUEST); 22373733937dSMat Martineau else 22383733937dSMat Martineau err = l2cap_streaming_send(chan, &seg_queue); 223994122bbeSMat Martineau 2240608bcc6dSMat Martineau if (!err) 22419a91a04aSGustavo F. Padovan err = len; 22429a91a04aSGustavo F. Padovan 224394122bbeSMat Martineau /* If the skbs were not queued for sending, they'll still be in 224494122bbeSMat Martineau * seg_queue and need to be purged. 224594122bbeSMat Martineau */ 224694122bbeSMat Martineau __skb_queue_purge(&seg_queue); 22479a91a04aSGustavo F. Padovan break; 22489a91a04aSGustavo F. Padovan 22499a91a04aSGustavo F. Padovan default: 22509a91a04aSGustavo F. Padovan BT_DBG("bad state %1.1x", chan->mode); 22519a91a04aSGustavo F. Padovan err = -EBADFD; 22529a91a04aSGustavo F. Padovan } 22539a91a04aSGustavo F. Padovan 22549a91a04aSGustavo F. Padovan return err; 22559a91a04aSGustavo F. Padovan } 22569a91a04aSGustavo F. Padovan 2257d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq) 2258d2a7ac5dSMat Martineau { 2259bed68bdeSMat Martineau struct l2cap_ctrl control; 2260bed68bdeSMat Martineau u16 seq; 2261bed68bdeSMat Martineau 2262bed68bdeSMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 2263bed68bdeSMat Martineau 2264bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2265bed68bdeSMat Martineau control.sframe = 1; 2266bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2267bed68bdeSMat Martineau 2268bed68bdeSMat Martineau for (seq = chan->expected_tx_seq; seq != txseq; 2269bed68bdeSMat Martineau seq = __next_seq(chan, seq)) { 2270bed68bdeSMat Martineau if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) { 2271bed68bdeSMat Martineau control.reqseq = seq; 2272bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2273bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2274bed68bdeSMat Martineau } 2275bed68bdeSMat Martineau } 2276bed68bdeSMat Martineau 2277bed68bdeSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 2278d2a7ac5dSMat Martineau } 2279d2a7ac5dSMat Martineau 2280d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan) 2281d2a7ac5dSMat Martineau { 2282bed68bdeSMat Martineau struct l2cap_ctrl control; 2283bed68bdeSMat Martineau 2284bed68bdeSMat Martineau BT_DBG("chan %p", chan); 2285bed68bdeSMat Martineau 2286bed68bdeSMat Martineau if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR) 2287bed68bdeSMat Martineau return; 2288bed68bdeSMat Martineau 2289bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2290bed68bdeSMat Martineau control.sframe = 1; 2291bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2292bed68bdeSMat Martineau control.reqseq = chan->srej_list.tail; 2293bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2294d2a7ac5dSMat Martineau } 2295d2a7ac5dSMat Martineau 2296d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq) 2297d2a7ac5dSMat Martineau { 2298bed68bdeSMat Martineau struct l2cap_ctrl control; 2299bed68bdeSMat Martineau u16 initial_head; 2300bed68bdeSMat Martineau u16 seq; 2301bed68bdeSMat Martineau 2302bed68bdeSMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 2303bed68bdeSMat Martineau 2304bed68bdeSMat Martineau memset(&control, 0, sizeof(control)); 2305bed68bdeSMat Martineau control.sframe = 1; 2306bed68bdeSMat Martineau control.super = L2CAP_SUPER_SREJ; 2307bed68bdeSMat Martineau 2308bed68bdeSMat Martineau /* Capture initial list head to allow only one pass through the list. */ 2309bed68bdeSMat Martineau initial_head = chan->srej_list.head; 2310bed68bdeSMat Martineau 2311bed68bdeSMat Martineau do { 2312bed68bdeSMat Martineau seq = l2cap_seq_list_pop(&chan->srej_list); 2313bed68bdeSMat Martineau if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR) 2314bed68bdeSMat Martineau break; 2315bed68bdeSMat Martineau 2316bed68bdeSMat Martineau control.reqseq = seq; 2317bed68bdeSMat Martineau l2cap_send_sframe(chan, &control); 2318bed68bdeSMat Martineau l2cap_seq_list_append(&chan->srej_list, seq); 2319bed68bdeSMat Martineau } while (chan->srej_list.head != initial_head); 2320d2a7ac5dSMat Martineau } 2321d2a7ac5dSMat Martineau 2322608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq) 2323608bcc6dSMat Martineau { 2324608bcc6dSMat Martineau struct sk_buff *acked_skb; 2325608bcc6dSMat Martineau u16 ackseq; 2326608bcc6dSMat Martineau 2327608bcc6dSMat Martineau BT_DBG("chan %p, reqseq %d", chan, reqseq); 2328608bcc6dSMat Martineau 2329608bcc6dSMat Martineau if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq) 2330608bcc6dSMat Martineau return; 2331608bcc6dSMat Martineau 2332608bcc6dSMat Martineau BT_DBG("expected_ack_seq %d, unacked_frames %d", 2333608bcc6dSMat Martineau chan->expected_ack_seq, chan->unacked_frames); 2334608bcc6dSMat Martineau 2335608bcc6dSMat Martineau for (ackseq = chan->expected_ack_seq; ackseq != reqseq; 2336608bcc6dSMat Martineau ackseq = __next_seq(chan, ackseq)) { 2337608bcc6dSMat Martineau 2338608bcc6dSMat Martineau acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq); 2339608bcc6dSMat Martineau if (acked_skb) { 2340608bcc6dSMat Martineau skb_unlink(acked_skb, &chan->tx_q); 2341608bcc6dSMat Martineau kfree_skb(acked_skb); 2342608bcc6dSMat Martineau chan->unacked_frames--; 2343608bcc6dSMat Martineau } 2344608bcc6dSMat Martineau } 2345608bcc6dSMat Martineau 2346608bcc6dSMat Martineau chan->expected_ack_seq = reqseq; 2347608bcc6dSMat Martineau 2348608bcc6dSMat Martineau if (chan->unacked_frames == 0) 2349608bcc6dSMat Martineau __clear_retrans_timer(chan); 2350608bcc6dSMat Martineau 2351608bcc6dSMat Martineau BT_DBG("unacked_frames %d", (int) chan->unacked_frames); 2352608bcc6dSMat Martineau } 2353608bcc6dSMat Martineau 2354608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan) 2355608bcc6dSMat Martineau { 2356608bcc6dSMat Martineau BT_DBG("chan %p", chan); 2357608bcc6dSMat Martineau 2358608bcc6dSMat Martineau chan->expected_tx_seq = chan->buffer_seq; 2359608bcc6dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 2360608bcc6dSMat Martineau skb_queue_purge(&chan->srej_q); 2361608bcc6dSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2362608bcc6dSMat Martineau } 2363608bcc6dSMat Martineau 2364608bcc6dSMat Martineau static int l2cap_tx_state_xmit(struct l2cap_chan *chan, 2365608bcc6dSMat Martineau struct l2cap_ctrl *control, 2366608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2367608bcc6dSMat Martineau { 2368608bcc6dSMat Martineau int err = 0; 2369608bcc6dSMat Martineau 2370608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2371608bcc6dSMat Martineau event); 2372608bcc6dSMat Martineau 2373608bcc6dSMat Martineau switch (event) { 2374608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2375608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2376608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2377608bcc6dSMat Martineau 2378608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2379608bcc6dSMat Martineau l2cap_ertm_send(chan); 2380608bcc6dSMat Martineau break; 2381608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2382608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2383608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2384608bcc6dSMat Martineau 2385608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2386608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2387608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2388608bcc6dSMat Martineau */ 2389608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2390608bcc6dSMat Martineau } 2391608bcc6dSMat Martineau 2392608bcc6dSMat Martineau l2cap_send_ack(chan); 2393608bcc6dSMat Martineau 2394608bcc6dSMat Martineau break; 2395608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2396608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2397608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2398608bcc6dSMat Martineau 2399608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2400608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2401608bcc6dSMat Martineau 2402608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2403608bcc6dSMat Martineau local_control.sframe = 1; 2404608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2405608bcc6dSMat Martineau local_control.poll = 1; 2406608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2407a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2408608bcc6dSMat Martineau 2409608bcc6dSMat Martineau chan->retry_count = 1; 2410608bcc6dSMat Martineau __set_monitor_timer(chan); 2411608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2412608bcc6dSMat Martineau } 2413608bcc6dSMat Martineau break; 2414608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2415608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2416608bcc6dSMat Martineau break; 2417608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2418608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2419608bcc6dSMat Martineau chan->retry_count = 1; 2420608bcc6dSMat Martineau __set_monitor_timer(chan); 2421608bcc6dSMat Martineau __clear_ack_timer(chan); 2422608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2423608bcc6dSMat Martineau break; 2424608bcc6dSMat Martineau case L2CAP_EV_RETRANS_TO: 2425608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2426608bcc6dSMat Martineau chan->retry_count = 1; 2427608bcc6dSMat Martineau __set_monitor_timer(chan); 2428608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2429608bcc6dSMat Martineau break; 2430608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2431608bcc6dSMat Martineau /* Nothing to process */ 2432608bcc6dSMat Martineau break; 2433608bcc6dSMat Martineau default: 2434608bcc6dSMat Martineau break; 2435608bcc6dSMat Martineau } 2436608bcc6dSMat Martineau 2437608bcc6dSMat Martineau return err; 2438608bcc6dSMat Martineau } 2439608bcc6dSMat Martineau 2440608bcc6dSMat Martineau static int l2cap_tx_state_wait_f(struct l2cap_chan *chan, 2441608bcc6dSMat Martineau struct l2cap_ctrl *control, 2442608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2443608bcc6dSMat Martineau { 2444608bcc6dSMat Martineau int err = 0; 2445608bcc6dSMat Martineau 2446608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2447608bcc6dSMat Martineau event); 2448608bcc6dSMat Martineau 2449608bcc6dSMat Martineau switch (event) { 2450608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2451608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2452608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2453608bcc6dSMat Martineau /* Queue data, but don't send. */ 2454608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2455608bcc6dSMat Martineau break; 2456608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2457608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2458608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2459608bcc6dSMat Martineau 2460608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2461608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2462608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2463608bcc6dSMat Martineau */ 2464608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2465608bcc6dSMat Martineau } 2466608bcc6dSMat Martineau 2467608bcc6dSMat Martineau l2cap_send_ack(chan); 2468608bcc6dSMat Martineau 2469608bcc6dSMat Martineau break; 2470608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2471608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2472608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2473608bcc6dSMat Martineau 2474608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2475608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2476608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2477608bcc6dSMat Martineau local_control.sframe = 1; 2478608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2479608bcc6dSMat Martineau local_control.poll = 1; 2480608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2481a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2482608bcc6dSMat Martineau 2483608bcc6dSMat Martineau chan->retry_count = 1; 2484608bcc6dSMat Martineau __set_monitor_timer(chan); 2485608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2486608bcc6dSMat Martineau } 2487608bcc6dSMat Martineau break; 2488608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2489608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2490608bcc6dSMat Martineau 2491608bcc6dSMat Martineau /* Fall through */ 2492608bcc6dSMat Martineau 2493608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2494608bcc6dSMat Martineau if (control && control->final) { 2495608bcc6dSMat Martineau __clear_monitor_timer(chan); 2496608bcc6dSMat Martineau if (chan->unacked_frames > 0) 2497608bcc6dSMat Martineau __set_retrans_timer(chan); 2498608bcc6dSMat Martineau chan->retry_count = 0; 2499608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 2500608bcc6dSMat Martineau BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state); 2501608bcc6dSMat Martineau } 2502608bcc6dSMat Martineau break; 2503608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2504608bcc6dSMat Martineau /* Ignore */ 2505608bcc6dSMat Martineau break; 2506608bcc6dSMat Martineau case L2CAP_EV_MONITOR_TO: 2507608bcc6dSMat Martineau if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) { 2508608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2509608bcc6dSMat Martineau __set_monitor_timer(chan); 2510608bcc6dSMat Martineau chan->retry_count++; 2511608bcc6dSMat Martineau } else { 2512608bcc6dSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); 2513608bcc6dSMat Martineau } 2514608bcc6dSMat Martineau break; 2515608bcc6dSMat Martineau default: 2516608bcc6dSMat Martineau break; 2517608bcc6dSMat Martineau } 2518608bcc6dSMat Martineau 2519608bcc6dSMat Martineau return err; 2520608bcc6dSMat Martineau } 2521608bcc6dSMat Martineau 2522608bcc6dSMat Martineau static int l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 2523608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2524608bcc6dSMat Martineau { 2525608bcc6dSMat Martineau int err = 0; 2526608bcc6dSMat Martineau 2527608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d, state %d", 2528608bcc6dSMat Martineau chan, control, skbs, event, chan->tx_state); 2529608bcc6dSMat Martineau 2530608bcc6dSMat Martineau switch (chan->tx_state) { 2531608bcc6dSMat Martineau case L2CAP_TX_STATE_XMIT: 2532608bcc6dSMat Martineau err = l2cap_tx_state_xmit(chan, control, skbs, event); 2533608bcc6dSMat Martineau break; 2534608bcc6dSMat Martineau case L2CAP_TX_STATE_WAIT_F: 2535608bcc6dSMat Martineau err = l2cap_tx_state_wait_f(chan, control, skbs, event); 2536608bcc6dSMat Martineau break; 2537608bcc6dSMat Martineau default: 2538608bcc6dSMat Martineau /* Ignore event */ 2539608bcc6dSMat Martineau break; 2540608bcc6dSMat Martineau } 2541608bcc6dSMat Martineau 2542608bcc6dSMat Martineau return err; 2543608bcc6dSMat Martineau } 2544608bcc6dSMat Martineau 25454b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan, 25464b51dae9SMat Martineau struct l2cap_ctrl *control) 25474b51dae9SMat Martineau { 25484b51dae9SMat Martineau BT_DBG("chan %p, control %p", chan, control); 25494b51dae9SMat Martineau l2cap_tx(chan, control, 0, L2CAP_EV_RECV_REQSEQ_AND_FBIT); 25504b51dae9SMat Martineau } 25514b51dae9SMat Martineau 2552f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan, 2553f80842a8SMat Martineau struct l2cap_ctrl *control) 2554f80842a8SMat Martineau { 2555f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 2556f80842a8SMat Martineau l2cap_tx(chan, control, 0, L2CAP_EV_RECV_FBIT); 2557f80842a8SMat Martineau } 2558f80842a8SMat Martineau 25590a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */ 25600a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 25610a708f8fSGustavo F. Padovan { 25620a708f8fSGustavo F. Padovan struct sk_buff *nskb; 256348454079SGustavo F. Padovan struct l2cap_chan *chan; 25640a708f8fSGustavo F. Padovan 25650a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 25660a708f8fSGustavo F. Padovan 25673df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 25683d57dc68SGustavo F. Padovan 25693df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 257048454079SGustavo F. Padovan struct sock *sk = chan->sk; 2571715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW) 25720a708f8fSGustavo F. Padovan continue; 25730a708f8fSGustavo F. Padovan 25740a708f8fSGustavo F. Padovan /* Don't send frame to the socket it came from */ 25750a708f8fSGustavo F. Padovan if (skb->sk == sk) 25760a708f8fSGustavo F. Padovan continue; 25770a708f8fSGustavo F. Padovan nskb = skb_clone(skb, GFP_ATOMIC); 25780a708f8fSGustavo F. Padovan if (!nskb) 25790a708f8fSGustavo F. Padovan continue; 25800a708f8fSGustavo F. Padovan 258123070494SGustavo F. Padovan if (chan->ops->recv(chan->data, nskb)) 25820a708f8fSGustavo F. Padovan kfree_skb(nskb); 25830a708f8fSGustavo F. Padovan } 25843d57dc68SGustavo F. Padovan 25853df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 25860a708f8fSGustavo F. Padovan } 25870a708f8fSGustavo F. Padovan 25880a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */ 25890a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 25900a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data) 25910a708f8fSGustavo F. Padovan { 25920a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag; 25930a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd; 25940a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 25950a708f8fSGustavo F. Padovan int len, count; 25960a708f8fSGustavo F. Padovan 25970a708f8fSGustavo F. Padovan BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d", 25980a708f8fSGustavo F. Padovan conn, code, ident, dlen); 25990a708f8fSGustavo F. Padovan 26000a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; 26010a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 26020a708f8fSGustavo F. Padovan 26030a708f8fSGustavo F. Padovan skb = bt_skb_alloc(count, GFP_ATOMIC); 26040a708f8fSGustavo F. Padovan if (!skb) 26050a708f8fSGustavo F. Padovan return NULL; 26060a708f8fSGustavo F. Padovan 26070a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 26080a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); 26093300d9a9SClaudio Takahasi 26103300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 26113300d9a9SClaudio Takahasi lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING); 26123300d9a9SClaudio Takahasi else 26130a708f8fSGustavo F. Padovan lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING); 26140a708f8fSGustavo F. Padovan 26150a708f8fSGustavo F. Padovan cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); 26160a708f8fSGustavo F. Padovan cmd->code = code; 26170a708f8fSGustavo F. Padovan cmd->ident = ident; 26180a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen); 26190a708f8fSGustavo F. Padovan 26200a708f8fSGustavo F. Padovan if (dlen) { 26210a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE; 26220a708f8fSGustavo F. Padovan memcpy(skb_put(skb, count), data, count); 26230a708f8fSGustavo F. Padovan data += count; 26240a708f8fSGustavo F. Padovan } 26250a708f8fSGustavo F. Padovan 26260a708f8fSGustavo F. Padovan len -= skb->len; 26270a708f8fSGustavo F. Padovan 26280a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 26290a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 26300a708f8fSGustavo F. Padovan while (len) { 26310a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 26320a708f8fSGustavo F. Padovan 26330a708f8fSGustavo F. Padovan *frag = bt_skb_alloc(count, GFP_ATOMIC); 26340a708f8fSGustavo F. Padovan if (!*frag) 26350a708f8fSGustavo F. Padovan goto fail; 26360a708f8fSGustavo F. Padovan 26370a708f8fSGustavo F. Padovan memcpy(skb_put(*frag, count), data, count); 26380a708f8fSGustavo F. Padovan 26390a708f8fSGustavo F. Padovan len -= count; 26400a708f8fSGustavo F. Padovan data += count; 26410a708f8fSGustavo F. Padovan 26420a708f8fSGustavo F. Padovan frag = &(*frag)->next; 26430a708f8fSGustavo F. Padovan } 26440a708f8fSGustavo F. Padovan 26450a708f8fSGustavo F. Padovan return skb; 26460a708f8fSGustavo F. Padovan 26470a708f8fSGustavo F. Padovan fail: 26480a708f8fSGustavo F. Padovan kfree_skb(skb); 26490a708f8fSGustavo F. Padovan return NULL; 26500a708f8fSGustavo F. Padovan } 26510a708f8fSGustavo F. Padovan 26520a708f8fSGustavo F. Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val) 26530a708f8fSGustavo F. Padovan { 26540a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 26550a708f8fSGustavo F. Padovan int len; 26560a708f8fSGustavo F. Padovan 26570a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len; 26580a708f8fSGustavo F. Padovan *ptr += len; 26590a708f8fSGustavo F. Padovan 26600a708f8fSGustavo F. Padovan *type = opt->type; 26610a708f8fSGustavo F. Padovan *olen = opt->len; 26620a708f8fSGustavo F. Padovan 26630a708f8fSGustavo F. Padovan switch (opt->len) { 26640a708f8fSGustavo F. Padovan case 1: 26650a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val); 26660a708f8fSGustavo F. Padovan break; 26670a708f8fSGustavo F. Padovan 26680a708f8fSGustavo F. Padovan case 2: 26690a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val); 26700a708f8fSGustavo F. Padovan break; 26710a708f8fSGustavo F. Padovan 26720a708f8fSGustavo F. Padovan case 4: 26730a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val); 26740a708f8fSGustavo F. Padovan break; 26750a708f8fSGustavo F. Padovan 26760a708f8fSGustavo F. Padovan default: 26770a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val; 26780a708f8fSGustavo F. Padovan break; 26790a708f8fSGustavo F. Padovan } 26800a708f8fSGustavo F. Padovan 26810a708f8fSGustavo F. Padovan BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val); 26820a708f8fSGustavo F. Padovan return len; 26830a708f8fSGustavo F. Padovan } 26840a708f8fSGustavo F. Padovan 26850a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) 26860a708f8fSGustavo F. Padovan { 26870a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 26880a708f8fSGustavo F. Padovan 26890a708f8fSGustavo F. Padovan BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val); 26900a708f8fSGustavo F. Padovan 26910a708f8fSGustavo F. Padovan opt->type = type; 26920a708f8fSGustavo F. Padovan opt->len = len; 26930a708f8fSGustavo F. Padovan 26940a708f8fSGustavo F. Padovan switch (len) { 26950a708f8fSGustavo F. Padovan case 1: 26960a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val; 26970a708f8fSGustavo F. Padovan break; 26980a708f8fSGustavo F. Padovan 26990a708f8fSGustavo F. Padovan case 2: 27000a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val); 27010a708f8fSGustavo F. Padovan break; 27020a708f8fSGustavo F. Padovan 27030a708f8fSGustavo F. Padovan case 4: 27040a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val); 27050a708f8fSGustavo F. Padovan break; 27060a708f8fSGustavo F. Padovan 27070a708f8fSGustavo F. Padovan default: 27080a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len); 27090a708f8fSGustavo F. Padovan break; 27100a708f8fSGustavo F. Padovan } 27110a708f8fSGustavo F. Padovan 27120a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len; 27130a708f8fSGustavo F. Padovan } 27140a708f8fSGustavo F. Padovan 2715f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) 2716f89cef09SAndrei Emeltchenko { 2717f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs; 2718f89cef09SAndrei Emeltchenko 2719f89cef09SAndrei Emeltchenko switch (chan->mode) { 2720f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM: 2721f89cef09SAndrei Emeltchenko efs.id = chan->local_id; 2722f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype; 2723f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 2724f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 2725f89cef09SAndrei Emeltchenko efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); 2726f89cef09SAndrei Emeltchenko efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO); 2727f89cef09SAndrei Emeltchenko break; 2728f89cef09SAndrei Emeltchenko 2729f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING: 2730f89cef09SAndrei Emeltchenko efs.id = 1; 2731f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT; 2732f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 2733f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 2734f89cef09SAndrei Emeltchenko efs.acc_lat = 0; 2735f89cef09SAndrei Emeltchenko efs.flush_to = 0; 2736f89cef09SAndrei Emeltchenko break; 2737f89cef09SAndrei Emeltchenko 2738f89cef09SAndrei Emeltchenko default: 2739f89cef09SAndrei Emeltchenko return; 2740f89cef09SAndrei Emeltchenko } 2741f89cef09SAndrei Emeltchenko 2742f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), 2743f89cef09SAndrei Emeltchenko (unsigned long) &efs); 2744f89cef09SAndrei Emeltchenko } 2745f89cef09SAndrei Emeltchenko 2746721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work) 27470a708f8fSGustavo F. Padovan { 2748721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 2749721c4181SGustavo F. Padovan ack_timer.work); 27500a708f8fSGustavo F. Padovan 27512fb9b3d4SGustavo F. Padovan BT_DBG("chan %p", chan); 27522fb9b3d4SGustavo F. Padovan 27536be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 27546be36555SAndrei Emeltchenko 27550a0aba42SMat Martineau l2cap_send_ack(chan); 27566be36555SAndrei Emeltchenko 27576be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 275809bfb2eeSSzymon Janc 275909bfb2eeSSzymon Janc l2cap_chan_put(chan); 27600a708f8fSGustavo F. Padovan } 27610a708f8fSGustavo F. Padovan 27623c588192SMat Martineau static inline int l2cap_ertm_init(struct l2cap_chan *chan) 27630a708f8fSGustavo F. Padovan { 27643c588192SMat Martineau int err; 27653c588192SMat Martineau 2766105bdf9eSMat Martineau chan->next_tx_seq = 0; 2767105bdf9eSMat Martineau chan->expected_tx_seq = 0; 276842e5c802SGustavo F. Padovan chan->expected_ack_seq = 0; 27696a026610SGustavo F. Padovan chan->unacked_frames = 0; 277042e5c802SGustavo F. Padovan chan->buffer_seq = 0; 27716a026610SGustavo F. Padovan chan->frames_sent = 0; 2772105bdf9eSMat Martineau chan->last_acked_seq = 0; 2773105bdf9eSMat Martineau chan->sdu = NULL; 2774105bdf9eSMat Martineau chan->sdu_last_frag = NULL; 2775105bdf9eSMat Martineau chan->sdu_len = 0; 2776105bdf9eSMat Martineau 2777d34c34fbSMat Martineau skb_queue_head_init(&chan->tx_q); 2778d34c34fbSMat Martineau 2779105bdf9eSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 2780105bdf9eSMat Martineau return 0; 2781105bdf9eSMat Martineau 2782105bdf9eSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2783105bdf9eSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 27840a708f8fSGustavo F. Padovan 2785721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout); 2786721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout); 2787721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout); 27880a708f8fSGustavo F. Padovan 2789f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q); 27900a708f8fSGustavo F. Padovan 27913c588192SMat Martineau err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win); 27923c588192SMat Martineau if (err < 0) 27933c588192SMat Martineau return err; 27943c588192SMat Martineau 27959dc9affcSMat Martineau err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win); 27969dc9affcSMat Martineau if (err < 0) 27979dc9affcSMat Martineau l2cap_seq_list_free(&chan->srej_list); 27989dc9affcSMat Martineau 27999dc9affcSMat Martineau return err; 28000a708f8fSGustavo F. Padovan } 28010a708f8fSGustavo F. Padovan 28020a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) 28030a708f8fSGustavo F. Padovan { 28040a708f8fSGustavo F. Padovan switch (mode) { 28050a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 28060a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 28070a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask)) 28080a708f8fSGustavo F. Padovan return mode; 28090a708f8fSGustavo F. Padovan /* fall through */ 28100a708f8fSGustavo F. Padovan default: 28110a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC; 28120a708f8fSGustavo F. Padovan } 28130a708f8fSGustavo F. Padovan } 28140a708f8fSGustavo F. Padovan 28156327eb98SAndrei Emeltchenko static inline bool __l2cap_ews_supported(struct l2cap_chan *chan) 28166327eb98SAndrei Emeltchenko { 28176327eb98SAndrei Emeltchenko return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW; 28186327eb98SAndrei Emeltchenko } 28196327eb98SAndrei Emeltchenko 2820f89cef09SAndrei Emeltchenko static inline bool __l2cap_efs_supported(struct l2cap_chan *chan) 2821f89cef09SAndrei Emeltchenko { 2822f89cef09SAndrei Emeltchenko return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW; 2823f89cef09SAndrei Emeltchenko } 2824f89cef09SAndrei Emeltchenko 28256327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan) 28266327eb98SAndrei Emeltchenko { 28276327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && 2828836be934SAndrei Emeltchenko __l2cap_ews_supported(chan)) { 28296327eb98SAndrei Emeltchenko /* use extended control field */ 28306327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 2831836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 2832836be934SAndrei Emeltchenko } else { 28336327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win, 28346327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 2835836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 2836836be934SAndrei Emeltchenko } 28376327eb98SAndrei Emeltchenko } 28386327eb98SAndrei Emeltchenko 2839710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) 28400a708f8fSGustavo F. Padovan { 28410a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 28420c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode }; 28430a708f8fSGustavo F. Padovan void *ptr = req->data; 2844c8f79162SAndrei Emeltchenko u16 size; 28450a708f8fSGustavo F. Padovan 284649208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 28470a708f8fSGustavo F. Padovan 284873ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp) 28490a708f8fSGustavo F. Padovan goto done; 28500a708f8fSGustavo F. Padovan 28510c1bc5c6SGustavo F. Padovan switch (chan->mode) { 28520a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 28530a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 2854c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) 28550a708f8fSGustavo F. Padovan break; 28560a708f8fSGustavo F. Padovan 2857f89cef09SAndrei Emeltchenko if (__l2cap_efs_supported(chan)) 2858f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 2859f89cef09SAndrei Emeltchenko 28600a708f8fSGustavo F. Padovan /* fall through */ 28610a708f8fSGustavo F. Padovan default: 28628c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); 28630a708f8fSGustavo F. Padovan break; 28640a708f8fSGustavo F. Padovan } 28650a708f8fSGustavo F. Padovan 28660a708f8fSGustavo F. Padovan done: 28670c1bc5c6SGustavo F. Padovan if (chan->imtu != L2CAP_DEFAULT_MTU) 28680c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 28690a708f8fSGustavo F. Padovan 28700c1bc5c6SGustavo F. Padovan switch (chan->mode) { 28710a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 28728c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && 28738c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) 28740a708f8fSGustavo F. Padovan break; 28750a708f8fSGustavo F. Padovan 28760a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC; 28770a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 28780a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 28790a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 28800a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 28810a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0; 28820a708f8fSGustavo F. Padovan 28830a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 28840a708f8fSGustavo F. Padovan (unsigned long) &rfc); 28850a708f8fSGustavo F. Padovan break; 28860a708f8fSGustavo F. Padovan 28870a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 28880a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM; 288947d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx; 28900a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 28910a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 2892c8f79162SAndrei Emeltchenko 2893c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 2894c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2895c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2896c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2897c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 28980a708f8fSGustavo F. Padovan 28996327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan); 29006327eb98SAndrei Emeltchenko 29016327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win, 29026327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 29030a708f8fSGustavo F. Padovan 29040a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 29050a708f8fSGustavo F. Padovan (unsigned long) &rfc); 29060a708f8fSGustavo F. Padovan 2907f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 2908f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 2909f89cef09SAndrei Emeltchenko 29108c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) 29110a708f8fSGustavo F. Padovan break; 29120a708f8fSGustavo F. Padovan 291347d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 2914c1360a1cSGustavo F. Padovan test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { 291547d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 291647d1ec61SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); 29170a708f8fSGustavo F. Padovan } 29186327eb98SAndrei Emeltchenko 29196327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 29206327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 29216327eb98SAndrei Emeltchenko chan->tx_win); 29220a708f8fSGustavo F. Padovan break; 29230a708f8fSGustavo F. Padovan 29240a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 29250a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING; 29260a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 29270a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 29280a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 29290a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 2930c8f79162SAndrei Emeltchenko 2931c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 2932c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2933c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2934c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2935c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 29360a708f8fSGustavo F. Padovan 29370a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 29380a708f8fSGustavo F. Padovan (unsigned long) &rfc); 29390a708f8fSGustavo F. Padovan 2940f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 2941f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 2942f89cef09SAndrei Emeltchenko 29438c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) 29440a708f8fSGustavo F. Padovan break; 29450a708f8fSGustavo F. Padovan 294647d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 2947c1360a1cSGustavo F. Padovan test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { 294847d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 294947d1ec61SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); 29500a708f8fSGustavo F. Padovan } 29510a708f8fSGustavo F. Padovan break; 29520a708f8fSGustavo F. Padovan } 29530a708f8fSGustavo F. Padovan 2954fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 29550a708f8fSGustavo F. Padovan req->flags = cpu_to_le16(0); 29560a708f8fSGustavo F. Padovan 29570a708f8fSGustavo F. Padovan return ptr - data; 29580a708f8fSGustavo F. Padovan } 29590a708f8fSGustavo F. Padovan 296073ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) 29610a708f8fSGustavo F. Padovan { 29620a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 29630a708f8fSGustavo F. Padovan void *ptr = rsp->data; 296473ffa904SGustavo F. Padovan void *req = chan->conf_req; 296573ffa904SGustavo F. Padovan int len = chan->conf_len; 29660a708f8fSGustavo F. Padovan int type, hint, olen; 29670a708f8fSGustavo F. Padovan unsigned long val; 29680a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 296942dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs; 297042dceae2SAndrei Emeltchenko u8 remote_efs = 0; 29710a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU; 29720a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS; 2973c8f79162SAndrei Emeltchenko u16 size; 29740a708f8fSGustavo F. Padovan 297573ffa904SGustavo F. Padovan BT_DBG("chan %p", chan); 29760a708f8fSGustavo F. Padovan 29770a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 29780a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val); 29790a708f8fSGustavo F. Padovan 29800a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT; 29810a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK; 29820a708f8fSGustavo F. Padovan 29830a708f8fSGustavo F. Padovan switch (type) { 29840a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 29850a708f8fSGustavo F. Padovan mtu = val; 29860a708f8fSGustavo F. Padovan break; 29870a708f8fSGustavo F. Padovan 29880a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 29890c1bc5c6SGustavo F. Padovan chan->flush_to = val; 29900a708f8fSGustavo F. Padovan break; 29910a708f8fSGustavo F. Padovan 29920a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS: 29930a708f8fSGustavo F. Padovan break; 29940a708f8fSGustavo F. Padovan 29950a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 29960a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 29970a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen); 29980a708f8fSGustavo F. Padovan break; 29990a708f8fSGustavo F. Padovan 30000a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS: 30010a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE) 3002c1360a1cSGustavo F. Padovan set_bit(CONF_NO_FCS_RECV, &chan->conf_state); 300342dceae2SAndrei Emeltchenko break; 30040a708f8fSGustavo F. Padovan 300542dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS: 300642dceae2SAndrei Emeltchenko remote_efs = 1; 300742dceae2SAndrei Emeltchenko if (olen == sizeof(efs)) 300842dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen); 30090a708f8fSGustavo F. Padovan break; 30100a708f8fSGustavo F. Padovan 30116327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 30126327eb98SAndrei Emeltchenko if (!enable_hs) 30136327eb98SAndrei Emeltchenko return -ECONNREFUSED; 30146327eb98SAndrei Emeltchenko 30156327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 30166327eb98SAndrei Emeltchenko set_bit(CONF_EWS_RECV, &chan->conf_state); 3017836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 30186327eb98SAndrei Emeltchenko chan->remote_tx_win = val; 30190a708f8fSGustavo F. Padovan break; 30200a708f8fSGustavo F. Padovan 30210a708f8fSGustavo F. Padovan default: 30220a708f8fSGustavo F. Padovan if (hint) 30230a708f8fSGustavo F. Padovan break; 30240a708f8fSGustavo F. Padovan 30250a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN; 30260a708f8fSGustavo F. Padovan *((u8 *) ptr++) = type; 30270a708f8fSGustavo F. Padovan break; 30280a708f8fSGustavo F. Padovan } 30290a708f8fSGustavo F. Padovan } 30300a708f8fSGustavo F. Padovan 303173ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1) 30320a708f8fSGustavo F. Padovan goto done; 30330a708f8fSGustavo F. Padovan 30340c1bc5c6SGustavo F. Padovan switch (chan->mode) { 30350a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 30360a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 3037c1360a1cSGustavo F. Padovan if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { 30380c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, 30398c1d787bSGustavo F. Padovan chan->conn->feat_mask); 30400a708f8fSGustavo F. Padovan break; 30410a708f8fSGustavo F. Padovan } 30420a708f8fSGustavo F. Padovan 304342dceae2SAndrei Emeltchenko if (remote_efs) { 304442dceae2SAndrei Emeltchenko if (__l2cap_efs_supported(chan)) 304542dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 304642dceae2SAndrei Emeltchenko else 304742dceae2SAndrei Emeltchenko return -ECONNREFUSED; 304842dceae2SAndrei Emeltchenko } 304942dceae2SAndrei Emeltchenko 30500c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) 30510a708f8fSGustavo F. Padovan return -ECONNREFUSED; 30520a708f8fSGustavo F. Padovan 30530a708f8fSGustavo F. Padovan break; 30540a708f8fSGustavo F. Padovan } 30550a708f8fSGustavo F. Padovan 30560a708f8fSGustavo F. Padovan done: 30570c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) { 30580a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 30590c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 30600a708f8fSGustavo F. Padovan 306173ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1) 30620a708f8fSGustavo F. Padovan return -ECONNREFUSED; 30630a708f8fSGustavo F. Padovan 30640a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 30650a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 30660a708f8fSGustavo F. Padovan } 30670a708f8fSGustavo F. Padovan 30680a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) { 30690a708f8fSGustavo F. Padovan /* Configure output options and let the other side know 30700a708f8fSGustavo F. Padovan * which ones we don't like. */ 30710a708f8fSGustavo F. Padovan 30720a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU) 30730a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 30740a708f8fSGustavo F. Padovan else { 30750c1bc5c6SGustavo F. Padovan chan->omtu = mtu; 3076c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state); 30770a708f8fSGustavo F. Padovan } 30780c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); 30790a708f8fSGustavo F. Padovan 308042dceae2SAndrei Emeltchenko if (remote_efs) { 308142dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 308242dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 308342dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) { 308442dceae2SAndrei Emeltchenko 308542dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT; 308642dceae2SAndrei Emeltchenko 308742dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1) 308842dceae2SAndrei Emeltchenko return -ECONNREFUSED; 308942dceae2SAndrei Emeltchenko 309042dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 309142dceae2SAndrei Emeltchenko sizeof(efs), 309242dceae2SAndrei Emeltchenko (unsigned long) &efs); 30930e8b207eSAndrei Emeltchenko } else { 30943e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */ 30950e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING; 30960e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 309742dceae2SAndrei Emeltchenko } 309842dceae2SAndrei Emeltchenko } 309942dceae2SAndrei Emeltchenko 31000a708f8fSGustavo F. Padovan switch (rfc.mode) { 31010a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 310247d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3103c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 31040a708f8fSGustavo F. Padovan break; 31050a708f8fSGustavo F. Padovan 31060a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 31076327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state)) 31082c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size; 31096327eb98SAndrei Emeltchenko else 31106327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; 31116327eb98SAndrei Emeltchenko 31122c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit; 31130a708f8fSGustavo F. Padovan 3114c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 3115c8f79162SAndrei Emeltchenko chan->conn->mtu - 3116c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 3117c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 3118c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3119c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3120c8f79162SAndrei Emeltchenko chan->remote_mps = size; 31210a708f8fSGustavo F. Padovan 31220a708f8fSGustavo F. Padovan rfc.retrans_timeout = 31234fd21a88SAndrei Emeltchenko __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 31240a708f8fSGustavo F. Padovan rfc.monitor_timeout = 31254fd21a88SAndrei Emeltchenko __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 31260a708f8fSGustavo F. Padovan 3127c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 31280a708f8fSGustavo F. Padovan 31290a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 31300a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 31310a708f8fSGustavo F. Padovan 313242dceae2SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 313342dceae2SAndrei Emeltchenko chan->remote_id = efs.id; 313442dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype; 313542dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu); 313642dceae2SAndrei Emeltchenko chan->remote_flush_to = 313742dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to); 313842dceae2SAndrei Emeltchenko chan->remote_acc_lat = 313942dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat); 314042dceae2SAndrei Emeltchenko chan->remote_sdu_itime = 314142dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 314242dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 314342dceae2SAndrei Emeltchenko sizeof(efs), (unsigned long) &efs); 314442dceae2SAndrei Emeltchenko } 31450a708f8fSGustavo F. Padovan break; 31460a708f8fSGustavo F. Padovan 31470a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 3148c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 3149c8f79162SAndrei Emeltchenko chan->conn->mtu - 3150c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 3151c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 3152c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 3153c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 3154c8f79162SAndrei Emeltchenko chan->remote_mps = size; 31550a708f8fSGustavo F. Padovan 3156c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 31570a708f8fSGustavo F. Padovan 31580a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 31590a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 31600a708f8fSGustavo F. Padovan 31610a708f8fSGustavo F. Padovan break; 31620a708f8fSGustavo F. Padovan 31630a708f8fSGustavo F. Padovan default: 31640a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 31650a708f8fSGustavo F. Padovan 31660a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc)); 31670c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 31680a708f8fSGustavo F. Padovan } 31690a708f8fSGustavo F. Padovan 31700a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) 3171c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 31720a708f8fSGustavo F. Padovan } 3173fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 31740a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 31750a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(0x0000); 31760a708f8fSGustavo F. Padovan 31770a708f8fSGustavo F. Padovan return ptr - data; 31780a708f8fSGustavo F. Padovan } 31790a708f8fSGustavo F. Padovan 3180b4450035SGustavo F. Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result) 31810a708f8fSGustavo F. Padovan { 31820a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 31830a708f8fSGustavo F. Padovan void *ptr = req->data; 31840a708f8fSGustavo F. Padovan int type, olen; 31850a708f8fSGustavo F. Padovan unsigned long val; 318636e999a8SMat Martineau struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 318766af7aafSAndrei Emeltchenko struct l2cap_conf_efs efs; 31880a708f8fSGustavo F. Padovan 3189fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); 31900a708f8fSGustavo F. Padovan 31910a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 31920a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 31930a708f8fSGustavo F. Padovan 31940a708f8fSGustavo F. Padovan switch (type) { 31950a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 31960a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) { 31970a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT; 31980c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU; 31990a708f8fSGustavo F. Padovan } else 32000c1bc5c6SGustavo F. Padovan chan->imtu = val; 32010c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 32020a708f8fSGustavo F. Padovan break; 32030a708f8fSGustavo F. Padovan 32040a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 32050c1bc5c6SGustavo F. Padovan chan->flush_to = val; 32060a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 32070c1bc5c6SGustavo F. Padovan 2, chan->flush_to); 32080a708f8fSGustavo F. Padovan break; 32090a708f8fSGustavo F. Padovan 32100a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 32110a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 32120a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 32130a708f8fSGustavo F. Padovan 3214c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && 32150c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode) 32160a708f8fSGustavo F. Padovan return -ECONNREFUSED; 32170a708f8fSGustavo F. Padovan 321847d1ec61SGustavo F. Padovan chan->fcs = 0; 32190a708f8fSGustavo F. Padovan 32200a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 32210a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 32220a708f8fSGustavo F. Padovan break; 32236327eb98SAndrei Emeltchenko 32246327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 32256327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, val, 32266327eb98SAndrei Emeltchenko L2CAP_DEFAULT_EXT_WINDOW); 32273e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 32283e6b3b95SGustavo F. Padovan chan->tx_win); 32296327eb98SAndrei Emeltchenko break; 323066af7aafSAndrei Emeltchenko 323166af7aafSAndrei Emeltchenko case L2CAP_CONF_EFS: 323266af7aafSAndrei Emeltchenko if (olen == sizeof(efs)) 323366af7aafSAndrei Emeltchenko memcpy(&efs, (void *)val, olen); 323466af7aafSAndrei Emeltchenko 323566af7aafSAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 323666af7aafSAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 323766af7aafSAndrei Emeltchenko efs.stype != chan->local_stype) 323866af7aafSAndrei Emeltchenko return -ECONNREFUSED; 323966af7aafSAndrei Emeltchenko 324066af7aafSAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 324166af7aafSAndrei Emeltchenko sizeof(efs), (unsigned long) &efs); 324266af7aafSAndrei Emeltchenko break; 32430a708f8fSGustavo F. Padovan } 32440a708f8fSGustavo F. Padovan } 32450a708f8fSGustavo F. Padovan 32460c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) 32470a708f8fSGustavo F. Padovan return -ECONNREFUSED; 32480a708f8fSGustavo F. Padovan 32490c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode; 32500a708f8fSGustavo F. Padovan 32510e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) { 32520a708f8fSGustavo F. Padovan switch (rfc.mode) { 32530a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 325447d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 325547d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 325647d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 325766af7aafSAndrei Emeltchenko 325866af7aafSAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 325966af7aafSAndrei Emeltchenko chan->local_msdu = le16_to_cpu(efs.msdu); 326066af7aafSAndrei Emeltchenko chan->local_sdu_itime = 326166af7aafSAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 326266af7aafSAndrei Emeltchenko chan->local_acc_lat = le32_to_cpu(efs.acc_lat); 326366af7aafSAndrei Emeltchenko chan->local_flush_to = 326466af7aafSAndrei Emeltchenko le32_to_cpu(efs.flush_to); 326566af7aafSAndrei Emeltchenko } 32660a708f8fSGustavo F. Padovan break; 326766af7aafSAndrei Emeltchenko 32680a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 326947d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 32700a708f8fSGustavo F. Padovan } 32710a708f8fSGustavo F. Padovan } 32720a708f8fSGustavo F. Padovan 3273fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 32740a708f8fSGustavo F. Padovan req->flags = cpu_to_le16(0x0000); 32750a708f8fSGustavo F. Padovan 32760a708f8fSGustavo F. Padovan return ptr - data; 32770a708f8fSGustavo F. Padovan } 32780a708f8fSGustavo F. Padovan 3279fe4128e0SGustavo F. Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags) 32800a708f8fSGustavo F. Padovan { 32810a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 32820a708f8fSGustavo F. Padovan void *ptr = rsp->data; 32830a708f8fSGustavo F. Padovan 3284fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan); 32850a708f8fSGustavo F. Padovan 3286fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 32870a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 32880a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags); 32890a708f8fSGustavo F. Padovan 32900a708f8fSGustavo F. Padovan return ptr - data; 32910a708f8fSGustavo F. Padovan } 32920a708f8fSGustavo F. Padovan 32938c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) 3294710f9b0aSGustavo F. Padovan { 3295710f9b0aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 32968c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 3297710f9b0aSGustavo F. Padovan u8 buf[128]; 3298710f9b0aSGustavo F. Padovan 3299fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 3300fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3301710f9b0aSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 3302710f9b0aSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 3303710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, 3304710f9b0aSGustavo F. Padovan L2CAP_CONN_RSP, sizeof(rsp), &rsp); 3305710f9b0aSGustavo F. Padovan 3306c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 3307710f9b0aSGustavo F. Padovan return; 3308710f9b0aSGustavo F. Padovan 3309710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 3310710f9b0aSGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 3311710f9b0aSGustavo F. Padovan chan->num_conf_req++; 3312710f9b0aSGustavo F. Padovan } 3313710f9b0aSGustavo F. Padovan 331447d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) 33150a708f8fSGustavo F. Padovan { 33160a708f8fSGustavo F. Padovan int type, olen; 33170a708f8fSGustavo F. Padovan unsigned long val; 33180a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc; 33190a708f8fSGustavo F. Padovan 332047d1ec61SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); 33210a708f8fSGustavo F. Padovan 33220c1bc5c6SGustavo F. Padovan if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) 33230a708f8fSGustavo F. Padovan return; 33240a708f8fSGustavo F. Padovan 33250a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 33260a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 33270a708f8fSGustavo F. Padovan 33280a708f8fSGustavo F. Padovan switch (type) { 33290a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 33300a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 33310a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 33320a708f8fSGustavo F. Padovan goto done; 33330a708f8fSGustavo F. Padovan } 33340a708f8fSGustavo F. Padovan } 33350a708f8fSGustavo F. Padovan 333636e999a8SMat Martineau /* Use sane default values in case a misbehaving remote device 333736e999a8SMat Martineau * did not send an RFC option. 333836e999a8SMat Martineau */ 333936e999a8SMat Martineau rfc.mode = chan->mode; 334036e999a8SMat Martineau rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 334136e999a8SMat Martineau rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 334236e999a8SMat Martineau rfc.max_pdu_size = cpu_to_le16(chan->imtu); 334336e999a8SMat Martineau 334436e999a8SMat Martineau BT_ERR("Expected RFC option was not found, using defaults"); 334536e999a8SMat Martineau 33460a708f8fSGustavo F. Padovan done: 33470a708f8fSGustavo F. Padovan switch (rfc.mode) { 33480a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 334947d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 335047d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 335147d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 33520a708f8fSGustavo F. Padovan break; 33530a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 335447d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 33550a708f8fSGustavo F. Padovan } 33560a708f8fSGustavo F. Padovan } 33570a708f8fSGustavo F. Padovan 33580a708f8fSGustavo F. Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 33590a708f8fSGustavo F. Padovan { 3360e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 33610a708f8fSGustavo F. Padovan 3362e2fd318eSIlia Kolomisnky if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) 33630a708f8fSGustavo F. Padovan return 0; 33640a708f8fSGustavo F. Padovan 33650a708f8fSGustavo F. Padovan if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && 33660a708f8fSGustavo F. Padovan cmd->ident == conn->info_ident) { 336717cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 33680a708f8fSGustavo F. Padovan 33690a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 33700a708f8fSGustavo F. Padovan conn->info_ident = 0; 33710a708f8fSGustavo F. Padovan 33720a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 33730a708f8fSGustavo F. Padovan } 33740a708f8fSGustavo F. Padovan 33750a708f8fSGustavo F. Padovan return 0; 33760a708f8fSGustavo F. Padovan } 33770a708f8fSGustavo F. Padovan 33780a708f8fSGustavo F. Padovan static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 33790a708f8fSGustavo F. Padovan { 33800a708f8fSGustavo F. Padovan struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 33810a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 338223691d75SGustavo F. Padovan struct l2cap_chan *chan = NULL, *pchan; 33830a708f8fSGustavo F. Padovan struct sock *parent, *sk = NULL; 33840a708f8fSGustavo F. Padovan int result, status = L2CAP_CS_NO_INFO; 33850a708f8fSGustavo F. Padovan 33860a708f8fSGustavo F. Padovan u16 dcid = 0, scid = __le16_to_cpu(req->scid); 33870a708f8fSGustavo F. Padovan __le16 psm = req->psm; 33880a708f8fSGustavo F. Padovan 3389097db76cSAndrei Emeltchenko BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); 33900a708f8fSGustavo F. Padovan 33910a708f8fSGustavo F. Padovan /* Check if we have socket listening on psm */ 3392c2287681SIdo Yariv pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst); 339323691d75SGustavo F. Padovan if (!pchan) { 33940a708f8fSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 33950a708f8fSGustavo F. Padovan goto sendresp; 33960a708f8fSGustavo F. Padovan } 33970a708f8fSGustavo F. Padovan 339823691d75SGustavo F. Padovan parent = pchan->sk; 339923691d75SGustavo F. Padovan 34003df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 3401aa2ac881SGustavo F. Padovan lock_sock(parent); 34020a708f8fSGustavo F. Padovan 34030a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */ 34040a708f8fSGustavo F. Padovan if (psm != cpu_to_le16(0x0001) && 34050a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) { 34069f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_AUTH_FAILURE; 34070a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 34080a708f8fSGustavo F. Padovan goto response; 34090a708f8fSGustavo F. Padovan } 34100a708f8fSGustavo F. Padovan 34110a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM; 34120a708f8fSGustavo F. Padovan 34130a708f8fSGustavo F. Padovan /* Check for backlog size */ 34140a708f8fSGustavo F. Padovan if (sk_acceptq_is_full(parent)) { 34150a708f8fSGustavo F. Padovan BT_DBG("backlog full %d", parent->sk_ack_backlog); 34160a708f8fSGustavo F. Padovan goto response; 34170a708f8fSGustavo F. Padovan } 34180a708f8fSGustavo F. Padovan 341980808e43SGustavo F. Padovan chan = pchan->ops->new_connection(pchan->data); 342080808e43SGustavo F. Padovan if (!chan) 34210a708f8fSGustavo F. Padovan goto response; 34220a708f8fSGustavo F. Padovan 342380808e43SGustavo F. Padovan sk = chan->sk; 342480808e43SGustavo F. Padovan 34250a708f8fSGustavo F. Padovan /* Check if we already have channel with that dcid */ 3426baa7e1faSGustavo F. Padovan if (__l2cap_get_chan_by_dcid(conn, scid)) { 34270a708f8fSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 3428ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 34290a708f8fSGustavo F. Padovan goto response; 34300a708f8fSGustavo F. Padovan } 34310a708f8fSGustavo F. Padovan 34320a708f8fSGustavo F. Padovan hci_conn_hold(conn->hcon); 34330a708f8fSGustavo F. Padovan 34340a708f8fSGustavo F. Padovan bacpy(&bt_sk(sk)->src, conn->src); 34350a708f8fSGustavo F. Padovan bacpy(&bt_sk(sk)->dst, conn->dst); 3436fe4128e0SGustavo F. Padovan chan->psm = psm; 3437fe4128e0SGustavo F. Padovan chan->dcid = scid; 34380a708f8fSGustavo F. Padovan 3439d1010240SGustavo F. Padovan bt_accept_enqueue(parent, sk); 3440d1010240SGustavo F. Padovan 34416be36555SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 344248454079SGustavo F. Padovan 3443fe4128e0SGustavo F. Padovan dcid = chan->scid; 34440a708f8fSGustavo F. Padovan 3445c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 34460a708f8fSGustavo F. Padovan 3447fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident; 34480a708f8fSGustavo F. Padovan 34490a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { 3450d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 3451c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) { 34520e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 34530a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 34540a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND; 34550a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 34560a708f8fSGustavo F. Padovan } else { 34570e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 34580a708f8fSGustavo F. Padovan result = L2CAP_CR_SUCCESS; 34590a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 34600a708f8fSGustavo F. Padovan } 34610a708f8fSGustavo F. Padovan } else { 34620e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 34630a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 34640a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND; 34650a708f8fSGustavo F. Padovan } 34660a708f8fSGustavo F. Padovan } else { 34670e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 34680a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 34690a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 34700a708f8fSGustavo F. Padovan } 34710a708f8fSGustavo F. Padovan 34720a708f8fSGustavo F. Padovan response: 3473aa2ac881SGustavo F. Padovan release_sock(parent); 34743df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 34750a708f8fSGustavo F. Padovan 34760a708f8fSGustavo F. Padovan sendresp: 34770a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid); 34780a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid); 34790a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result); 34800a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status); 34810a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); 34820a708f8fSGustavo F. Padovan 34830a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { 34840a708f8fSGustavo F. Padovan struct l2cap_info_req info; 34850a708f8fSGustavo F. Padovan info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 34860a708f8fSGustavo F. Padovan 34870a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 34880a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 34890a708f8fSGustavo F. Padovan 3490ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 34910a708f8fSGustavo F. Padovan 34920a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 34930a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(info), &info); 34940a708f8fSGustavo F. Padovan } 34950a708f8fSGustavo F. Padovan 3496c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && 34970a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) { 34980a708f8fSGustavo F. Padovan u8 buf[128]; 3499c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 35000a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 350173ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 350273ffa904SGustavo F. Padovan chan->num_conf_req++; 35030a708f8fSGustavo F. Padovan } 35040a708f8fSGustavo F. Padovan 35050a708f8fSGustavo F. Padovan return 0; 35060a708f8fSGustavo F. Padovan } 35070a708f8fSGustavo F. Padovan 35080a708f8fSGustavo F. Padovan static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 35090a708f8fSGustavo F. Padovan { 35100a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; 35110a708f8fSGustavo F. Padovan u16 scid, dcid, result, status; 351248454079SGustavo F. Padovan struct l2cap_chan *chan; 35130a708f8fSGustavo F. Padovan u8 req[128]; 35143df91ea2SAndrei Emeltchenko int err; 35150a708f8fSGustavo F. Padovan 35160a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 35170a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 35180a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 35190a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status); 35200a708f8fSGustavo F. Padovan 35211b009c98SAndrei Emeltchenko BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", 35221b009c98SAndrei Emeltchenko dcid, scid, result, status); 35230a708f8fSGustavo F. Padovan 35243df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 35253df91ea2SAndrei Emeltchenko 35260a708f8fSGustavo F. Padovan if (scid) { 35273df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 35283df91ea2SAndrei Emeltchenko if (!chan) { 35293df91ea2SAndrei Emeltchenko err = -EFAULT; 35303df91ea2SAndrei Emeltchenko goto unlock; 35313df91ea2SAndrei Emeltchenko } 35320a708f8fSGustavo F. Padovan } else { 35333df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 35343df91ea2SAndrei Emeltchenko if (!chan) { 35353df91ea2SAndrei Emeltchenko err = -EFAULT; 35363df91ea2SAndrei Emeltchenko goto unlock; 35373df91ea2SAndrei Emeltchenko } 35380a708f8fSGustavo F. Padovan } 35390a708f8fSGustavo F. Padovan 35403df91ea2SAndrei Emeltchenko err = 0; 35413df91ea2SAndrei Emeltchenko 35426be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 354348454079SGustavo F. Padovan 35440a708f8fSGustavo F. Padovan switch (result) { 35450a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS: 354689bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 3547fc7f8a7eSGustavo F. Padovan chan->ident = 0; 3548fe4128e0SGustavo F. Padovan chan->dcid = dcid; 3549c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state); 35500a708f8fSGustavo F. Padovan 3551c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 35520a708f8fSGustavo F. Padovan break; 35530a708f8fSGustavo F. Padovan 35540a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 355573ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, req), req); 355673ffa904SGustavo F. Padovan chan->num_conf_req++; 35570a708f8fSGustavo F. Padovan break; 35580a708f8fSGustavo F. Padovan 35590a708f8fSGustavo F. Padovan case L2CAP_CR_PEND: 3560c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 35610a708f8fSGustavo F. Padovan break; 35620a708f8fSGustavo F. Padovan 35630a708f8fSGustavo F. Padovan default: 356448454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED); 35650a708f8fSGustavo F. Padovan break; 35660a708f8fSGustavo F. Padovan } 35670a708f8fSGustavo F. Padovan 35686be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 35693df91ea2SAndrei Emeltchenko 35703df91ea2SAndrei Emeltchenko unlock: 35713df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 35723df91ea2SAndrei Emeltchenko 35733df91ea2SAndrei Emeltchenko return err; 35740a708f8fSGustavo F. Padovan } 35750a708f8fSGustavo F. Padovan 357647d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan) 35770a708f8fSGustavo F. Padovan { 35780a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both 35790a708f8fSGustavo F. Padovan * sides request it. 35800a708f8fSGustavo F. Padovan */ 35810c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) 358247d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3583c1360a1cSGustavo F. Padovan else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) 358447d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16; 35850a708f8fSGustavo F. Padovan } 35860a708f8fSGustavo F. Padovan 35870a708f8fSGustavo F. Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 35880a708f8fSGustavo F. Padovan { 35890a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; 35900a708f8fSGustavo F. Padovan u16 dcid, flags; 35910a708f8fSGustavo F. Padovan u8 rsp[64]; 359248454079SGustavo F. Padovan struct l2cap_chan *chan; 35933c588192SMat Martineau int len, err = 0; 35940a708f8fSGustavo F. Padovan 35950a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 35960a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags); 35970a708f8fSGustavo F. Padovan 35980a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); 35990a708f8fSGustavo F. Padovan 3600baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid); 360148454079SGustavo F. Padovan if (!chan) 36020a708f8fSGustavo F. Padovan return -ENOENT; 36030a708f8fSGustavo F. Padovan 3604033b1142SDavid S. Miller if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { 3605e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_cid rej; 36060a708f8fSGustavo F. Padovan 3607e2fd318eSIlia Kolomisnky rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID); 3608e2fd318eSIlia Kolomisnky rej.scid = cpu_to_le16(chan->scid); 3609e2fd318eSIlia Kolomisnky rej.dcid = cpu_to_le16(chan->dcid); 3610e2fd318eSIlia Kolomisnky 36110a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 36120a708f8fSGustavo F. Padovan sizeof(rej), &rej); 36130a708f8fSGustavo F. Padovan goto unlock; 36140a708f8fSGustavo F. Padovan } 36150a708f8fSGustavo F. Padovan 36160a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */ 36170a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req); 36187ac28817SDan Rosenberg if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) { 36190a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 3620fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 36210a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp); 36220a708f8fSGustavo F. Padovan goto unlock; 36230a708f8fSGustavo F. Padovan } 36240a708f8fSGustavo F. Padovan 36250a708f8fSGustavo F. Padovan /* Store config. */ 362673ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len); 362773ffa904SGustavo F. Padovan chan->conf_len += len; 36280a708f8fSGustavo F. Padovan 36290a708f8fSGustavo F. Padovan if (flags & 0x0001) { 36300a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */ 36310a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 3632fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 36330a708f8fSGustavo F. Padovan L2CAP_CONF_SUCCESS, 0x0001), rsp); 36340a708f8fSGustavo F. Padovan goto unlock; 36350a708f8fSGustavo F. Padovan } 36360a708f8fSGustavo F. Padovan 36370a708f8fSGustavo F. Padovan /* Complete config. */ 363873ffa904SGustavo F. Padovan len = l2cap_parse_conf_req(chan, rsp); 36390a708f8fSGustavo F. Padovan if (len < 0) { 3640e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 36410a708f8fSGustavo F. Padovan goto unlock; 36420a708f8fSGustavo F. Padovan } 36430a708f8fSGustavo F. Padovan 36440a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); 364573ffa904SGustavo F. Padovan chan->num_conf_rsp++; 36460a708f8fSGustavo F. Padovan 36470a708f8fSGustavo F. Padovan /* Reset config buffer. */ 364873ffa904SGustavo F. Padovan chan->conf_len = 0; 36490a708f8fSGustavo F. Padovan 3650c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) 36510a708f8fSGustavo F. Padovan goto unlock; 36520a708f8fSGustavo F. Padovan 3653c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 365447d1ec61SGustavo F. Padovan set_default_fcs(chan); 36550a708f8fSGustavo F. Padovan 365689bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECTED); 36570a708f8fSGustavo F. Padovan 3658105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 3659105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 36603c588192SMat Martineau err = l2cap_ertm_init(chan); 36610a708f8fSGustavo F. Padovan 36623c588192SMat Martineau if (err < 0) 36633c588192SMat Martineau l2cap_send_disconn_req(chan->conn, chan, -err); 36643c588192SMat Martineau else 3665cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 36663c588192SMat Martineau 36670a708f8fSGustavo F. Padovan goto unlock; 36680a708f8fSGustavo F. Padovan } 36690a708f8fSGustavo F. Padovan 3670c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { 36710a708f8fSGustavo F. Padovan u8 buf[64]; 36720a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 367373ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 367473ffa904SGustavo F. Padovan chan->num_conf_req++; 36750a708f8fSGustavo F. Padovan } 36760a708f8fSGustavo F. Padovan 36770e8b207eSAndrei Emeltchenko /* Got Conf Rsp PENDING from remote side and asume we sent 36780e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */ 36790e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && 36800e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 36810e8b207eSAndrei Emeltchenko 36820e8b207eSAndrei Emeltchenko /* check compatibility */ 36830e8b207eSAndrei Emeltchenko 36840e8b207eSAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 36850e8b207eSAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 36860e8b207eSAndrei Emeltchenko 36870e8b207eSAndrei Emeltchenko l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 36880e8b207eSAndrei Emeltchenko l2cap_build_conf_rsp(chan, rsp, 36890e8b207eSAndrei Emeltchenko L2CAP_CONF_SUCCESS, 0x0000), rsp); 36900e8b207eSAndrei Emeltchenko } 36910e8b207eSAndrei Emeltchenko 36920a708f8fSGustavo F. Padovan unlock: 36936be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 36943c588192SMat Martineau return err; 36950a708f8fSGustavo F. Padovan } 36960a708f8fSGustavo F. Padovan 36970a708f8fSGustavo F. Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 36980a708f8fSGustavo F. Padovan { 36990a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; 37000a708f8fSGustavo F. Padovan u16 scid, flags, result; 370148454079SGustavo F. Padovan struct l2cap_chan *chan; 370261386cbaSAndrei Emeltchenko int len = le16_to_cpu(cmd->len) - sizeof(*rsp); 37033c588192SMat Martineau int err = 0; 37040a708f8fSGustavo F. Padovan 37050a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 37060a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags); 37070a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 37080a708f8fSGustavo F. Padovan 370961386cbaSAndrei Emeltchenko BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags, 371061386cbaSAndrei Emeltchenko result, len); 37110a708f8fSGustavo F. Padovan 3712baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 371348454079SGustavo F. Padovan if (!chan) 37140a708f8fSGustavo F. Padovan return 0; 37150a708f8fSGustavo F. Padovan 37160a708f8fSGustavo F. Padovan switch (result) { 37170a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS: 371847d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len); 37190e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state); 37200a708f8fSGustavo F. Padovan break; 37210a708f8fSGustavo F. Padovan 37220e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING: 37230e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state); 37240e8b207eSAndrei Emeltchenko 37250e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 37260e8b207eSAndrei Emeltchenko char buf[64]; 37270e8b207eSAndrei Emeltchenko 37280e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len, 37290e8b207eSAndrei Emeltchenko buf, &result); 37300e8b207eSAndrei Emeltchenko if (len < 0) { 37310e8b207eSAndrei Emeltchenko l2cap_send_disconn_req(conn, chan, ECONNRESET); 37320e8b207eSAndrei Emeltchenko goto done; 37330e8b207eSAndrei Emeltchenko } 37340e8b207eSAndrei Emeltchenko 37350e8b207eSAndrei Emeltchenko /* check compatibility */ 37360e8b207eSAndrei Emeltchenko 37370e8b207eSAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 37380e8b207eSAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 37390e8b207eSAndrei Emeltchenko 37400e8b207eSAndrei Emeltchenko l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 37410e8b207eSAndrei Emeltchenko l2cap_build_conf_rsp(chan, buf, 37420e8b207eSAndrei Emeltchenko L2CAP_CONF_SUCCESS, 0x0000), buf); 37430e8b207eSAndrei Emeltchenko } 37440e8b207eSAndrei Emeltchenko goto done; 37450e8b207eSAndrei Emeltchenko 37460a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT: 374773ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { 37480a708f8fSGustavo F. Padovan char req[64]; 37490a708f8fSGustavo F. Padovan 37500a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { 3751e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 37520a708f8fSGustavo F. Padovan goto done; 37530a708f8fSGustavo F. Padovan } 37540a708f8fSGustavo F. Padovan 37550a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */ 37560a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS; 3757b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len, 3758b4450035SGustavo F. Padovan req, &result); 37590a708f8fSGustavo F. Padovan if (len < 0) { 3760e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 37610a708f8fSGustavo F. Padovan goto done; 37620a708f8fSGustavo F. Padovan } 37630a708f8fSGustavo F. Padovan 37640a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 37650a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req); 376673ffa904SGustavo F. Padovan chan->num_conf_req++; 37670a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS) 37680a708f8fSGustavo F. Padovan goto done; 37690a708f8fSGustavo F. Padovan break; 37700a708f8fSGustavo F. Padovan } 37710a708f8fSGustavo F. Padovan 37720a708f8fSGustavo F. Padovan default: 37736be36555SAndrei Emeltchenko l2cap_chan_set_err(chan, ECONNRESET); 37742e0052e4SAndrei Emeltchenko 3775ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); 3776e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 37770a708f8fSGustavo F. Padovan goto done; 37780a708f8fSGustavo F. Padovan } 37790a708f8fSGustavo F. Padovan 37800a708f8fSGustavo F. Padovan if (flags & 0x01) 37810a708f8fSGustavo F. Padovan goto done; 37820a708f8fSGustavo F. Padovan 3783c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state); 37840a708f8fSGustavo F. Padovan 3785c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { 378647d1ec61SGustavo F. Padovan set_default_fcs(chan); 37870a708f8fSGustavo F. Padovan 378889bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECTED); 3789105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 3790105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 37913c588192SMat Martineau err = l2cap_ertm_init(chan); 37920a708f8fSGustavo F. Padovan 37933c588192SMat Martineau if (err < 0) 37943c588192SMat Martineau l2cap_send_disconn_req(chan->conn, chan, -err); 37953c588192SMat Martineau else 3796cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 37970a708f8fSGustavo F. Padovan } 37980a708f8fSGustavo F. Padovan 37990a708f8fSGustavo F. Padovan done: 38006be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 38013c588192SMat Martineau return err; 38020a708f8fSGustavo F. Padovan } 38030a708f8fSGustavo F. Padovan 38040a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 38050a708f8fSGustavo F. Padovan { 38060a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; 38070a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp; 38080a708f8fSGustavo F. Padovan u16 dcid, scid; 380948454079SGustavo F. Padovan struct l2cap_chan *chan; 38100a708f8fSGustavo F. Padovan struct sock *sk; 38110a708f8fSGustavo F. Padovan 38120a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid); 38130a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 38140a708f8fSGustavo F. Padovan 38150a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); 38160a708f8fSGustavo F. Padovan 38173df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 38183df91ea2SAndrei Emeltchenko 38193df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, dcid); 38203df91ea2SAndrei Emeltchenko if (!chan) { 38213df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 38220a708f8fSGustavo F. Padovan return 0; 38233df91ea2SAndrei Emeltchenko } 38240a708f8fSGustavo F. Padovan 38256be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 38266be36555SAndrei Emeltchenko 382748454079SGustavo F. Padovan sk = chan->sk; 382848454079SGustavo F. Padovan 3829fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3830fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 38310a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); 38320a708f8fSGustavo F. Padovan 38336be36555SAndrei Emeltchenko lock_sock(sk); 38340a708f8fSGustavo F. Padovan sk->sk_shutdown = SHUTDOWN_MASK; 38356be36555SAndrei Emeltchenko release_sock(sk); 38360a708f8fSGustavo F. Padovan 383761d6ef3eSMat Martineau l2cap_chan_hold(chan); 383848454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET); 38396be36555SAndrei Emeltchenko 38406be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 38410a708f8fSGustavo F. Padovan 3842ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 384361d6ef3eSMat Martineau l2cap_chan_put(chan); 38443df91ea2SAndrei Emeltchenko 38453df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 38463df91ea2SAndrei Emeltchenko 38470a708f8fSGustavo F. Padovan return 0; 38480a708f8fSGustavo F. Padovan } 38490a708f8fSGustavo F. Padovan 38500a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 38510a708f8fSGustavo F. Padovan { 38520a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; 38530a708f8fSGustavo F. Padovan u16 dcid, scid; 385448454079SGustavo F. Padovan struct l2cap_chan *chan; 38550a708f8fSGustavo F. Padovan 38560a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 38570a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 38580a708f8fSGustavo F. Padovan 38590a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); 38600a708f8fSGustavo F. Padovan 38613df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 38623df91ea2SAndrei Emeltchenko 38633df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 38643df91ea2SAndrei Emeltchenko if (!chan) { 38653df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 38660a708f8fSGustavo F. Padovan return 0; 38673df91ea2SAndrei Emeltchenko } 38680a708f8fSGustavo F. Padovan 38696be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 387048454079SGustavo F. Padovan 387161d6ef3eSMat Martineau l2cap_chan_hold(chan); 387248454079SGustavo F. Padovan l2cap_chan_del(chan, 0); 38736be36555SAndrei Emeltchenko 38746be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 38750a708f8fSGustavo F. Padovan 3876ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 387761d6ef3eSMat Martineau l2cap_chan_put(chan); 38783df91ea2SAndrei Emeltchenko 38793df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 38803df91ea2SAndrei Emeltchenko 38810a708f8fSGustavo F. Padovan return 0; 38820a708f8fSGustavo F. Padovan } 38830a708f8fSGustavo F. Padovan 38840a708f8fSGustavo F. Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 38850a708f8fSGustavo F. Padovan { 38860a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data; 38870a708f8fSGustavo F. Padovan u16 type; 38880a708f8fSGustavo F. Padovan 38890a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type); 38900a708f8fSGustavo F. Padovan 38910a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type); 38920a708f8fSGustavo F. Padovan 38930a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) { 38940a708f8fSGustavo F. Padovan u8 buf[8]; 38950a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask; 38960a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 38970a708f8fSGustavo F. Padovan rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 38980a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 38990a708f8fSGustavo F. Padovan if (!disable_ertm) 39000a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING 39010a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS; 3902a5fd6f30SAndrei Emeltchenko if (enable_hs) 39036327eb98SAndrei Emeltchenko feat_mask |= L2CAP_FEAT_EXT_FLOW 39046327eb98SAndrei Emeltchenko | L2CAP_FEAT_EXT_WINDOW; 3905a5fd6f30SAndrei Emeltchenko 39060a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data); 39070a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 39080a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(buf), buf); 39090a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) { 39100a708f8fSGustavo F. Padovan u8 buf[12]; 39110a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 391250a147cdSMat Martineau 391350a147cdSMat Martineau if (enable_hs) 391450a147cdSMat Martineau l2cap_fixed_chan[0] |= L2CAP_FC_A2MP; 391550a147cdSMat Martineau else 391650a147cdSMat Martineau l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP; 391750a147cdSMat Martineau 39180a708f8fSGustavo F. Padovan rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 39190a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 3920c6337ea6SAndrei Emeltchenko memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); 39210a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 39220a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(buf), buf); 39230a708f8fSGustavo F. Padovan } else { 39240a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp; 39250a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type); 39260a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP); 39270a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 39280a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(rsp), &rsp); 39290a708f8fSGustavo F. Padovan } 39300a708f8fSGustavo F. Padovan 39310a708f8fSGustavo F. Padovan return 0; 39320a708f8fSGustavo F. Padovan } 39330a708f8fSGustavo F. Padovan 39340a708f8fSGustavo F. Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 39350a708f8fSGustavo F. Padovan { 39360a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; 39370a708f8fSGustavo F. Padovan u16 type, result; 39380a708f8fSGustavo F. Padovan 39390a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type); 39400a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 39410a708f8fSGustavo F. Padovan 39420a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); 39430a708f8fSGustavo F. Padovan 3944e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */ 3945e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident || 3946e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 3947e90165beSAndrei Emeltchenko return 0; 3948e90165beSAndrei Emeltchenko 394917cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 39500a708f8fSGustavo F. Padovan 39510a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) { 39520a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 39530a708f8fSGustavo F. Padovan conn->info_ident = 0; 39540a708f8fSGustavo F. Padovan 39550a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 39560a708f8fSGustavo F. Padovan 39570a708f8fSGustavo F. Padovan return 0; 39580a708f8fSGustavo F. Padovan } 39590a708f8fSGustavo F. Padovan 3960978c93b9SAndrei Emeltchenko switch (type) { 3961978c93b9SAndrei Emeltchenko case L2CAP_IT_FEAT_MASK: 39620a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data); 39630a708f8fSGustavo F. Padovan 39640a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { 39650a708f8fSGustavo F. Padovan struct l2cap_info_req req; 39660a708f8fSGustavo F. Padovan req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 39670a708f8fSGustavo F. Padovan 39680a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 39690a708f8fSGustavo F. Padovan 39700a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 39710a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 39720a708f8fSGustavo F. Padovan } else { 39730a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 39740a708f8fSGustavo F. Padovan conn->info_ident = 0; 39750a708f8fSGustavo F. Padovan 39760a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 39770a708f8fSGustavo F. Padovan } 3978978c93b9SAndrei Emeltchenko break; 3979978c93b9SAndrei Emeltchenko 3980978c93b9SAndrei Emeltchenko case L2CAP_IT_FIXED_CHAN: 3981978c93b9SAndrei Emeltchenko conn->fixed_chan_mask = rsp->data[0]; 39820a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 39830a708f8fSGustavo F. Padovan conn->info_ident = 0; 39840a708f8fSGustavo F. Padovan 39850a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 3986978c93b9SAndrei Emeltchenko break; 39870a708f8fSGustavo F. Padovan } 39880a708f8fSGustavo F. Padovan 39890a708f8fSGustavo F. Padovan return 0; 39900a708f8fSGustavo F. Padovan } 39910a708f8fSGustavo F. Padovan 3992f94ff6ffSMat Martineau static inline int l2cap_create_channel_req(struct l2cap_conn *conn, 3993f94ff6ffSMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, 3994f94ff6ffSMat Martineau void *data) 3995f94ff6ffSMat Martineau { 3996f94ff6ffSMat Martineau struct l2cap_create_chan_req *req = data; 3997f94ff6ffSMat Martineau struct l2cap_create_chan_rsp rsp; 3998f94ff6ffSMat Martineau u16 psm, scid; 3999f94ff6ffSMat Martineau 4000f94ff6ffSMat Martineau if (cmd_len != sizeof(*req)) 4001f94ff6ffSMat Martineau return -EPROTO; 4002f94ff6ffSMat Martineau 4003f94ff6ffSMat Martineau if (!enable_hs) 4004f94ff6ffSMat Martineau return -EINVAL; 4005f94ff6ffSMat Martineau 4006f94ff6ffSMat Martineau psm = le16_to_cpu(req->psm); 4007f94ff6ffSMat Martineau scid = le16_to_cpu(req->scid); 4008f94ff6ffSMat Martineau 4009f94ff6ffSMat Martineau BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id); 4010f94ff6ffSMat Martineau 4011f94ff6ffSMat Martineau /* Placeholder: Always reject */ 4012f94ff6ffSMat Martineau rsp.dcid = 0; 4013f94ff6ffSMat Martineau rsp.scid = cpu_to_le16(scid); 40148ce0c498SAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM); 40158ce0c498SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 4016f94ff6ffSMat Martineau 4017f94ff6ffSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, 4018f94ff6ffSMat Martineau sizeof(rsp), &rsp); 4019f94ff6ffSMat Martineau 4020f94ff6ffSMat Martineau return 0; 4021f94ff6ffSMat Martineau } 4022f94ff6ffSMat Martineau 4023f94ff6ffSMat Martineau static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn, 4024f94ff6ffSMat Martineau struct l2cap_cmd_hdr *cmd, void *data) 4025f94ff6ffSMat Martineau { 4026f94ff6ffSMat Martineau BT_DBG("conn %p", conn); 4027f94ff6ffSMat Martineau 4028f94ff6ffSMat Martineau return l2cap_connect_rsp(conn, cmd, data); 4029f94ff6ffSMat Martineau } 4030f94ff6ffSMat Martineau 40318d5a04a1SMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident, 40328d5a04a1SMat Martineau u16 icid, u16 result) 40338d5a04a1SMat Martineau { 40348d5a04a1SMat Martineau struct l2cap_move_chan_rsp rsp; 40358d5a04a1SMat Martineau 40368d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 40378d5a04a1SMat Martineau 40388d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 40398d5a04a1SMat Martineau rsp.result = cpu_to_le16(result); 40408d5a04a1SMat Martineau 40418d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp); 40428d5a04a1SMat Martineau } 40438d5a04a1SMat Martineau 40448d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn, 40458d5a04a1SMat Martineau struct l2cap_chan *chan, u16 icid, u16 result) 40468d5a04a1SMat Martineau { 40478d5a04a1SMat Martineau struct l2cap_move_chan_cfm cfm; 40488d5a04a1SMat Martineau u8 ident; 40498d5a04a1SMat Martineau 40508d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 40518d5a04a1SMat Martineau 40528d5a04a1SMat Martineau ident = l2cap_get_ident(conn); 40538d5a04a1SMat Martineau if (chan) 40548d5a04a1SMat Martineau chan->ident = ident; 40558d5a04a1SMat Martineau 40568d5a04a1SMat Martineau cfm.icid = cpu_to_le16(icid); 40578d5a04a1SMat Martineau cfm.result = cpu_to_le16(result); 40588d5a04a1SMat Martineau 40598d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm); 40608d5a04a1SMat Martineau } 40618d5a04a1SMat Martineau 40628d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, 40638d5a04a1SMat Martineau u16 icid) 40648d5a04a1SMat Martineau { 40658d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp rsp; 40668d5a04a1SMat Martineau 40678d5a04a1SMat Martineau BT_DBG("icid %d", icid); 40688d5a04a1SMat Martineau 40698d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 40708d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp); 40718d5a04a1SMat Martineau } 40728d5a04a1SMat Martineau 40738d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn, 40748d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 40758d5a04a1SMat Martineau { 40768d5a04a1SMat Martineau struct l2cap_move_chan_req *req = data; 40778d5a04a1SMat Martineau u16 icid = 0; 40788d5a04a1SMat Martineau u16 result = L2CAP_MR_NOT_ALLOWED; 40798d5a04a1SMat Martineau 40808d5a04a1SMat Martineau if (cmd_len != sizeof(*req)) 40818d5a04a1SMat Martineau return -EPROTO; 40828d5a04a1SMat Martineau 40838d5a04a1SMat Martineau icid = le16_to_cpu(req->icid); 40848d5a04a1SMat Martineau 40858d5a04a1SMat Martineau BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id); 40868d5a04a1SMat Martineau 40878d5a04a1SMat Martineau if (!enable_hs) 40888d5a04a1SMat Martineau return -EINVAL; 40898d5a04a1SMat Martineau 40908d5a04a1SMat Martineau /* Placeholder: Always refuse */ 40918d5a04a1SMat Martineau l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result); 40928d5a04a1SMat Martineau 40938d5a04a1SMat Martineau return 0; 40948d5a04a1SMat Martineau } 40958d5a04a1SMat Martineau 40968d5a04a1SMat Martineau static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn, 40978d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 40988d5a04a1SMat Martineau { 40998d5a04a1SMat Martineau struct l2cap_move_chan_rsp *rsp = data; 41008d5a04a1SMat Martineau u16 icid, result; 41018d5a04a1SMat Martineau 41028d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 41038d5a04a1SMat Martineau return -EPROTO; 41048d5a04a1SMat Martineau 41058d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 41068d5a04a1SMat Martineau result = le16_to_cpu(rsp->result); 41078d5a04a1SMat Martineau 41088d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 41098d5a04a1SMat Martineau 41108d5a04a1SMat Martineau /* Placeholder: Always unconfirmed */ 41118d5a04a1SMat Martineau l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED); 41128d5a04a1SMat Martineau 41138d5a04a1SMat Martineau return 0; 41148d5a04a1SMat Martineau } 41158d5a04a1SMat Martineau 41168d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn, 41178d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 41188d5a04a1SMat Martineau { 41198d5a04a1SMat Martineau struct l2cap_move_chan_cfm *cfm = data; 41208d5a04a1SMat Martineau u16 icid, result; 41218d5a04a1SMat Martineau 41228d5a04a1SMat Martineau if (cmd_len != sizeof(*cfm)) 41238d5a04a1SMat Martineau return -EPROTO; 41248d5a04a1SMat Martineau 41258d5a04a1SMat Martineau icid = le16_to_cpu(cfm->icid); 41268d5a04a1SMat Martineau result = le16_to_cpu(cfm->result); 41278d5a04a1SMat Martineau 41288d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 41298d5a04a1SMat Martineau 41308d5a04a1SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 41318d5a04a1SMat Martineau 41328d5a04a1SMat Martineau return 0; 41338d5a04a1SMat Martineau } 41348d5a04a1SMat Martineau 41358d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, 41368d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 41378d5a04a1SMat Martineau { 41388d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp *rsp = data; 41398d5a04a1SMat Martineau u16 icid; 41408d5a04a1SMat Martineau 41418d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 41428d5a04a1SMat Martineau return -EPROTO; 41438d5a04a1SMat Martineau 41448d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 41458d5a04a1SMat Martineau 41468d5a04a1SMat Martineau BT_DBG("icid %d", icid); 41478d5a04a1SMat Martineau 41488d5a04a1SMat Martineau return 0; 41498d5a04a1SMat Martineau } 41508d5a04a1SMat Martineau 4151e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency, 4152de73115aSClaudio Takahasi u16 to_multiplier) 4153de73115aSClaudio Takahasi { 4154de73115aSClaudio Takahasi u16 max_latency; 4155de73115aSClaudio Takahasi 4156de73115aSClaudio Takahasi if (min > max || min < 6 || max > 3200) 4157de73115aSClaudio Takahasi return -EINVAL; 4158de73115aSClaudio Takahasi 4159de73115aSClaudio Takahasi if (to_multiplier < 10 || to_multiplier > 3200) 4160de73115aSClaudio Takahasi return -EINVAL; 4161de73115aSClaudio Takahasi 4162de73115aSClaudio Takahasi if (max >= to_multiplier * 8) 4163de73115aSClaudio Takahasi return -EINVAL; 4164de73115aSClaudio Takahasi 4165de73115aSClaudio Takahasi max_latency = (to_multiplier * 8 / max) - 1; 4166de73115aSClaudio Takahasi if (latency > 499 || latency > max_latency) 4167de73115aSClaudio Takahasi return -EINVAL; 4168de73115aSClaudio Takahasi 4169de73115aSClaudio Takahasi return 0; 4170de73115aSClaudio Takahasi } 4171de73115aSClaudio Takahasi 4172de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, 4173de73115aSClaudio Takahasi struct l2cap_cmd_hdr *cmd, u8 *data) 4174de73115aSClaudio Takahasi { 4175de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon; 4176de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req; 4177de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp; 4178de73115aSClaudio Takahasi u16 min, max, latency, to_multiplier, cmd_len; 41792ce603ebSClaudio Takahasi int err; 4180de73115aSClaudio Takahasi 4181de73115aSClaudio Takahasi if (!(hcon->link_mode & HCI_LM_MASTER)) 4182de73115aSClaudio Takahasi return -EINVAL; 4183de73115aSClaudio Takahasi 4184de73115aSClaudio Takahasi cmd_len = __le16_to_cpu(cmd->len); 4185de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) 4186de73115aSClaudio Takahasi return -EPROTO; 4187de73115aSClaudio Takahasi 4188de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data; 4189de73115aSClaudio Takahasi min = __le16_to_cpu(req->min); 4190de73115aSClaudio Takahasi max = __le16_to_cpu(req->max); 4191de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency); 4192de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier); 4193de73115aSClaudio Takahasi 4194de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", 4195de73115aSClaudio Takahasi min, max, latency, to_multiplier); 4196de73115aSClaudio Takahasi 4197de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp)); 41982ce603ebSClaudio Takahasi 41992ce603ebSClaudio Takahasi err = l2cap_check_conn_param(min, max, latency, to_multiplier); 42002ce603ebSClaudio Takahasi if (err) 4201de73115aSClaudio Takahasi rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); 4202de73115aSClaudio Takahasi else 4203de73115aSClaudio Takahasi rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); 4204de73115aSClaudio Takahasi 4205de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, 4206de73115aSClaudio Takahasi sizeof(rsp), &rsp); 4207de73115aSClaudio Takahasi 42082ce603ebSClaudio Takahasi if (!err) 42092ce603ebSClaudio Takahasi hci_le_conn_update(hcon, min, max, latency, to_multiplier); 42102ce603ebSClaudio Takahasi 4211de73115aSClaudio Takahasi return 0; 4212de73115aSClaudio Takahasi } 4213de73115aSClaudio Takahasi 42143300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, 42153300d9a9SClaudio Takahasi struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 42163300d9a9SClaudio Takahasi { 42173300d9a9SClaudio Takahasi int err = 0; 42183300d9a9SClaudio Takahasi 42193300d9a9SClaudio Takahasi switch (cmd->code) { 42203300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 42213300d9a9SClaudio Takahasi l2cap_command_rej(conn, cmd, data); 42223300d9a9SClaudio Takahasi break; 42233300d9a9SClaudio Takahasi 42243300d9a9SClaudio Takahasi case L2CAP_CONN_REQ: 42253300d9a9SClaudio Takahasi err = l2cap_connect_req(conn, cmd, data); 42263300d9a9SClaudio Takahasi break; 42273300d9a9SClaudio Takahasi 42283300d9a9SClaudio Takahasi case L2CAP_CONN_RSP: 42293300d9a9SClaudio Takahasi err = l2cap_connect_rsp(conn, cmd, data); 42303300d9a9SClaudio Takahasi break; 42313300d9a9SClaudio Takahasi 42323300d9a9SClaudio Takahasi case L2CAP_CONF_REQ: 42333300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data); 42343300d9a9SClaudio Takahasi break; 42353300d9a9SClaudio Takahasi 42363300d9a9SClaudio Takahasi case L2CAP_CONF_RSP: 42373300d9a9SClaudio Takahasi err = l2cap_config_rsp(conn, cmd, data); 42383300d9a9SClaudio Takahasi break; 42393300d9a9SClaudio Takahasi 42403300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ: 42413300d9a9SClaudio Takahasi err = l2cap_disconnect_req(conn, cmd, data); 42423300d9a9SClaudio Takahasi break; 42433300d9a9SClaudio Takahasi 42443300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP: 42453300d9a9SClaudio Takahasi err = l2cap_disconnect_rsp(conn, cmd, data); 42463300d9a9SClaudio Takahasi break; 42473300d9a9SClaudio Takahasi 42483300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ: 42493300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data); 42503300d9a9SClaudio Takahasi break; 42513300d9a9SClaudio Takahasi 42523300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP: 42533300d9a9SClaudio Takahasi break; 42543300d9a9SClaudio Takahasi 42553300d9a9SClaudio Takahasi case L2CAP_INFO_REQ: 42563300d9a9SClaudio Takahasi err = l2cap_information_req(conn, cmd, data); 42573300d9a9SClaudio Takahasi break; 42583300d9a9SClaudio Takahasi 42593300d9a9SClaudio Takahasi case L2CAP_INFO_RSP: 42603300d9a9SClaudio Takahasi err = l2cap_information_rsp(conn, cmd, data); 42613300d9a9SClaudio Takahasi break; 42623300d9a9SClaudio Takahasi 4263f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_REQ: 4264f94ff6ffSMat Martineau err = l2cap_create_channel_req(conn, cmd, cmd_len, data); 4265f94ff6ffSMat Martineau break; 4266f94ff6ffSMat Martineau 4267f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_RSP: 4268f94ff6ffSMat Martineau err = l2cap_create_channel_rsp(conn, cmd, data); 4269f94ff6ffSMat Martineau break; 4270f94ff6ffSMat Martineau 42718d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_REQ: 42728d5a04a1SMat Martineau err = l2cap_move_channel_req(conn, cmd, cmd_len, data); 42738d5a04a1SMat Martineau break; 42748d5a04a1SMat Martineau 42758d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_RSP: 42768d5a04a1SMat Martineau err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data); 42778d5a04a1SMat Martineau break; 42788d5a04a1SMat Martineau 42798d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM: 42808d5a04a1SMat Martineau err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data); 42818d5a04a1SMat Martineau break; 42828d5a04a1SMat Martineau 42838d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM_RSP: 42848d5a04a1SMat Martineau err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data); 42858d5a04a1SMat Martineau break; 42868d5a04a1SMat Martineau 42873300d9a9SClaudio Takahasi default: 42883300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code); 42893300d9a9SClaudio Takahasi err = -EINVAL; 42903300d9a9SClaudio Takahasi break; 42913300d9a9SClaudio Takahasi } 42923300d9a9SClaudio Takahasi 42933300d9a9SClaudio Takahasi return err; 42943300d9a9SClaudio Takahasi } 42953300d9a9SClaudio Takahasi 42963300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, 42973300d9a9SClaudio Takahasi struct l2cap_cmd_hdr *cmd, u8 *data) 42983300d9a9SClaudio Takahasi { 42993300d9a9SClaudio Takahasi switch (cmd->code) { 43003300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 43013300d9a9SClaudio Takahasi return 0; 43023300d9a9SClaudio Takahasi 43033300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ: 4304de73115aSClaudio Takahasi return l2cap_conn_param_update_req(conn, cmd, data); 43053300d9a9SClaudio Takahasi 43063300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP: 43073300d9a9SClaudio Takahasi return 0; 43083300d9a9SClaudio Takahasi 43093300d9a9SClaudio Takahasi default: 43103300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code); 43113300d9a9SClaudio Takahasi return -EINVAL; 43123300d9a9SClaudio Takahasi } 43133300d9a9SClaudio Takahasi } 43143300d9a9SClaudio Takahasi 43153300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn, 43163300d9a9SClaudio Takahasi struct sk_buff *skb) 43170a708f8fSGustavo F. Padovan { 43180a708f8fSGustavo F. Padovan u8 *data = skb->data; 43190a708f8fSGustavo F. Padovan int len = skb->len; 43200a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr cmd; 43213300d9a9SClaudio Takahasi int err; 43220a708f8fSGustavo F. Padovan 43230a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb); 43240a708f8fSGustavo F. Padovan 43250a708f8fSGustavo F. Padovan while (len >= L2CAP_CMD_HDR_SIZE) { 43260a708f8fSGustavo F. Padovan u16 cmd_len; 43270a708f8fSGustavo F. Padovan memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); 43280a708f8fSGustavo F. Padovan data += L2CAP_CMD_HDR_SIZE; 43290a708f8fSGustavo F. Padovan len -= L2CAP_CMD_HDR_SIZE; 43300a708f8fSGustavo F. Padovan 43310a708f8fSGustavo F. Padovan cmd_len = le16_to_cpu(cmd.len); 43320a708f8fSGustavo F. Padovan 43330a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident); 43340a708f8fSGustavo F. Padovan 43350a708f8fSGustavo F. Padovan if (cmd_len > len || !cmd.ident) { 43360a708f8fSGustavo F. Padovan BT_DBG("corrupted command"); 43370a708f8fSGustavo F. Padovan break; 43380a708f8fSGustavo F. Padovan } 43390a708f8fSGustavo F. Padovan 43403300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 43413300d9a9SClaudio Takahasi err = l2cap_le_sig_cmd(conn, &cmd, data); 43423300d9a9SClaudio Takahasi else 43433300d9a9SClaudio Takahasi err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data); 43440a708f8fSGustavo F. Padovan 43450a708f8fSGustavo F. Padovan if (err) { 4346e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk rej; 43472c6d1a2eSGustavo F. Padovan 43482c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err); 43490a708f8fSGustavo F. Padovan 43500a708f8fSGustavo F. Padovan /* FIXME: Map err to a valid reason */ 4351e2fd318eSIlia Kolomisnky rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 43520a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); 43530a708f8fSGustavo F. Padovan } 43540a708f8fSGustavo F. Padovan 43550a708f8fSGustavo F. Padovan data += cmd_len; 43560a708f8fSGustavo F. Padovan len -= cmd_len; 43570a708f8fSGustavo F. Padovan } 43580a708f8fSGustavo F. Padovan 43590a708f8fSGustavo F. Padovan kfree_skb(skb); 43600a708f8fSGustavo F. Padovan } 43610a708f8fSGustavo F. Padovan 436247d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) 43630a708f8fSGustavo F. Padovan { 43640a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs; 4365e4ca6d98SAndrei Emeltchenko int hdr_size; 4366e4ca6d98SAndrei Emeltchenko 4367e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 4368e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE; 4369e4ca6d98SAndrei Emeltchenko else 4370e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE; 43710a708f8fSGustavo F. Padovan 437247d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 437303a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE); 43740a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len); 43750a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); 43760a708f8fSGustavo F. Padovan 43770a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs) 43780a708f8fSGustavo F. Padovan return -EBADMSG; 43790a708f8fSGustavo F. Padovan } 43800a708f8fSGustavo F. Padovan return 0; 43810a708f8fSGustavo F. Padovan } 43820a708f8fSGustavo F. Padovan 4383525cd185SGustavo F. Padovan static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) 43840a708f8fSGustavo F. Padovan { 4385e31f7633SMat Martineau struct l2cap_ctrl control; 43860a708f8fSGustavo F. Padovan 4387e31f7633SMat Martineau BT_DBG("chan %p", chan); 43880a708f8fSGustavo F. Padovan 4389e31f7633SMat Martineau memset(&control, 0, sizeof(control)); 4390e31f7633SMat Martineau control.sframe = 1; 4391e31f7633SMat Martineau control.final = 1; 4392e31f7633SMat Martineau control.reqseq = chan->buffer_seq; 4393e31f7633SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 43940a708f8fSGustavo F. Padovan 4395e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 4396e31f7633SMat Martineau control.super = L2CAP_SUPER_RNR; 4397e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 43980a708f8fSGustavo F. Padovan } 43990a708f8fSGustavo F. Padovan 4400e31f7633SMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 4401e31f7633SMat Martineau chan->unacked_frames > 0) 4402e31f7633SMat Martineau __set_retrans_timer(chan); 44030a708f8fSGustavo F. Padovan 4404e31f7633SMat Martineau /* Send pending iframes */ 4405525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 44060a708f8fSGustavo F. Padovan 4407e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 4408e31f7633SMat Martineau test_bit(CONN_SEND_FBIT, &chan->conn_state)) { 4409e31f7633SMat Martineau /* F-bit wasn't sent in an s-frame or i-frame yet, so 4410e31f7633SMat Martineau * send it now. 4411e31f7633SMat Martineau */ 4412e31f7633SMat Martineau control.super = L2CAP_SUPER_RR; 4413e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 44140a708f8fSGustavo F. Padovan } 44150a708f8fSGustavo F. Padovan } 44160a708f8fSGustavo F. Padovan 441784084a31SMat Martineau static void append_skb_frag(struct sk_buff *skb, 441884084a31SMat Martineau struct sk_buff *new_frag, struct sk_buff **last_frag) 44190a708f8fSGustavo F. Padovan { 442084084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments 442184084a31SMat Martineau * skb->data_len reflects only data in fragments 442284084a31SMat Martineau */ 442384084a31SMat Martineau if (!skb_has_frag_list(skb)) 442484084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag; 442584084a31SMat Martineau 442684084a31SMat Martineau new_frag->next = NULL; 442784084a31SMat Martineau 442884084a31SMat Martineau (*last_frag)->next = new_frag; 442984084a31SMat Martineau *last_frag = new_frag; 443084084a31SMat Martineau 443184084a31SMat Martineau skb->len += new_frag->len; 443284084a31SMat Martineau skb->data_len += new_frag->len; 443384084a31SMat Martineau skb->truesize += new_frag->truesize; 443484084a31SMat Martineau } 443584084a31SMat Martineau 44364b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, 44374b51dae9SMat Martineau struct l2cap_ctrl *control) 443884084a31SMat Martineau { 443984084a31SMat Martineau int err = -EINVAL; 44400a708f8fSGustavo F. Padovan 44414b51dae9SMat Martineau switch (control->sar) { 44427e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED: 444384084a31SMat Martineau if (chan->sdu) 444484084a31SMat Martineau break; 44450a708f8fSGustavo F. Padovan 444684084a31SMat Martineau err = chan->ops->recv(chan->data, skb); 444784084a31SMat Martineau break; 44480a708f8fSGustavo F. Padovan 44497e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START: 445084084a31SMat Martineau if (chan->sdu) 445184084a31SMat Martineau break; 44520a708f8fSGustavo F. Padovan 44536f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data); 445403a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE); 44550a708f8fSGustavo F. Padovan 445684084a31SMat Martineau if (chan->sdu_len > chan->imtu) { 445784084a31SMat Martineau err = -EMSGSIZE; 445884084a31SMat Martineau break; 445984084a31SMat Martineau } 44600a708f8fSGustavo F. Padovan 446184084a31SMat Martineau if (skb->len >= chan->sdu_len) 446284084a31SMat Martineau break; 446384084a31SMat Martineau 446484084a31SMat Martineau chan->sdu = skb; 446584084a31SMat Martineau chan->sdu_last_frag = skb; 446684084a31SMat Martineau 446784084a31SMat Martineau skb = NULL; 446884084a31SMat Martineau err = 0; 44690a708f8fSGustavo F. Padovan break; 44700a708f8fSGustavo F. Padovan 44717e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE: 44726f61fd47SGustavo F. Padovan if (!chan->sdu) 447384084a31SMat Martineau break; 44740a708f8fSGustavo F. Padovan 447584084a31SMat Martineau append_skb_frag(chan->sdu, skb, 447684084a31SMat Martineau &chan->sdu_last_frag); 447784084a31SMat Martineau skb = NULL; 44780a708f8fSGustavo F. Padovan 447984084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len) 448084084a31SMat Martineau break; 44810a708f8fSGustavo F. Padovan 448284084a31SMat Martineau err = 0; 44830a708f8fSGustavo F. Padovan break; 44840a708f8fSGustavo F. Padovan 44857e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END: 44866f61fd47SGustavo F. Padovan if (!chan->sdu) 448784084a31SMat Martineau break; 44880a708f8fSGustavo F. Padovan 448984084a31SMat Martineau append_skb_frag(chan->sdu, skb, 449084084a31SMat Martineau &chan->sdu_last_frag); 449184084a31SMat Martineau skb = NULL; 44920a708f8fSGustavo F. Padovan 449384084a31SMat Martineau if (chan->sdu->len != chan->sdu_len) 449484084a31SMat Martineau break; 44950a708f8fSGustavo F. Padovan 449684084a31SMat Martineau err = chan->ops->recv(chan->data, chan->sdu); 44970a708f8fSGustavo F. Padovan 449884084a31SMat Martineau if (!err) { 449984084a31SMat Martineau /* Reassembly complete */ 450084084a31SMat Martineau chan->sdu = NULL; 450184084a31SMat Martineau chan->sdu_last_frag = NULL; 450284084a31SMat Martineau chan->sdu_len = 0; 45030a708f8fSGustavo F. Padovan } 45040a708f8fSGustavo F. Padovan break; 45050a708f8fSGustavo F. Padovan } 45060a708f8fSGustavo F. Padovan 450784084a31SMat Martineau if (err) { 45080a708f8fSGustavo F. Padovan kfree_skb(skb); 45096f61fd47SGustavo F. Padovan kfree_skb(chan->sdu); 45106f61fd47SGustavo F. Padovan chan->sdu = NULL; 451184084a31SMat Martineau chan->sdu_last_frag = NULL; 451284084a31SMat Martineau chan->sdu_len = 0; 451384084a31SMat Martineau } 45140a708f8fSGustavo F. Padovan 451584084a31SMat Martineau return err; 45160a708f8fSGustavo F. Padovan } 45170a708f8fSGustavo F. Padovan 4518e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 45190a708f8fSGustavo F. Padovan { 452061aa4f5bSMat Martineau u8 event; 452161aa4f5bSMat Martineau 452261aa4f5bSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 452361aa4f5bSMat Martineau return; 452461aa4f5bSMat Martineau 452561aa4f5bSMat Martineau event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR; 452661aa4f5bSMat Martineau l2cap_tx(chan, 0, 0, event); 45270a708f8fSGustavo F. Padovan } 45280a708f8fSGustavo F. Padovan 4529d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan) 4530d2a7ac5dSMat Martineau { 453163838725SMat Martineau int err = 0; 453263838725SMat Martineau /* Pass sequential frames to l2cap_reassemble_sdu() 453363838725SMat Martineau * until a gap is encountered. 453463838725SMat Martineau */ 453563838725SMat Martineau 453663838725SMat Martineau BT_DBG("chan %p", chan); 453763838725SMat Martineau 453863838725SMat Martineau while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 453963838725SMat Martineau struct sk_buff *skb; 454063838725SMat Martineau BT_DBG("Searching for skb with txseq %d (queue len %d)", 454163838725SMat Martineau chan->buffer_seq, skb_queue_len(&chan->srej_q)); 454263838725SMat Martineau 454363838725SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq); 454463838725SMat Martineau 454563838725SMat Martineau if (!skb) 454663838725SMat Martineau break; 454763838725SMat Martineau 454863838725SMat Martineau skb_unlink(skb, &chan->srej_q); 454963838725SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 455063838725SMat Martineau err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->control); 455163838725SMat Martineau if (err) 455263838725SMat Martineau break; 455363838725SMat Martineau } 455463838725SMat Martineau 455563838725SMat Martineau if (skb_queue_empty(&chan->srej_q)) { 455663838725SMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 455763838725SMat Martineau l2cap_send_ack(chan); 455863838725SMat Martineau } 455963838725SMat Martineau 456063838725SMat Martineau return err; 4561d2a7ac5dSMat Martineau } 4562d2a7ac5dSMat Martineau 4563d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan, 4564d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 4565d2a7ac5dSMat Martineau { 4566f80842a8SMat Martineau struct sk_buff *skb; 4567f80842a8SMat Martineau 4568f80842a8SMat Martineau BT_DBG("chan %p, control %p", chan, control); 4569f80842a8SMat Martineau 4570f80842a8SMat Martineau if (control->reqseq == chan->next_tx_seq) { 4571f80842a8SMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 4572f80842a8SMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 4573f80842a8SMat Martineau return; 4574f80842a8SMat Martineau } 4575f80842a8SMat Martineau 4576f80842a8SMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 4577f80842a8SMat Martineau 4578f80842a8SMat Martineau if (skb == NULL) { 4579f80842a8SMat Martineau BT_DBG("Seq %d not available for retransmission", 4580f80842a8SMat Martineau control->reqseq); 4581f80842a8SMat Martineau return; 4582f80842a8SMat Martineau } 4583f80842a8SMat Martineau 4584f80842a8SMat Martineau if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) { 4585f80842a8SMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 4586f80842a8SMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 4587f80842a8SMat Martineau return; 4588f80842a8SMat Martineau } 4589f80842a8SMat Martineau 4590f80842a8SMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4591f80842a8SMat Martineau 4592f80842a8SMat Martineau if (control->poll) { 4593f80842a8SMat Martineau l2cap_pass_to_tx(chan, control); 4594f80842a8SMat Martineau 4595f80842a8SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 4596f80842a8SMat Martineau l2cap_retransmit(chan, control); 4597f80842a8SMat Martineau l2cap_ertm_send(chan); 4598f80842a8SMat Martineau 4599f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 4600f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 4601f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 4602f80842a8SMat Martineau } 4603f80842a8SMat Martineau } else { 4604f80842a8SMat Martineau l2cap_pass_to_tx_fbit(chan, control); 4605f80842a8SMat Martineau 4606f80842a8SMat Martineau if (control->final) { 4607f80842a8SMat Martineau if (chan->srej_save_reqseq != control->reqseq || 4608f80842a8SMat Martineau !test_and_clear_bit(CONN_SREJ_ACT, 4609f80842a8SMat Martineau &chan->conn_state)) 4610f80842a8SMat Martineau l2cap_retransmit(chan, control); 4611f80842a8SMat Martineau } else { 4612f80842a8SMat Martineau l2cap_retransmit(chan, control); 4613f80842a8SMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { 4614f80842a8SMat Martineau set_bit(CONN_SREJ_ACT, &chan->conn_state); 4615f80842a8SMat Martineau chan->srej_save_reqseq = control->reqseq; 4616f80842a8SMat Martineau } 4617f80842a8SMat Martineau } 4618f80842a8SMat Martineau } 4619d2a7ac5dSMat Martineau } 4620d2a7ac5dSMat Martineau 4621d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan, 4622d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 4623d2a7ac5dSMat Martineau { 4624fcd289dfSMat Martineau struct sk_buff *skb; 4625fcd289dfSMat Martineau 4626fcd289dfSMat Martineau BT_DBG("chan %p, control %p", chan, control); 4627fcd289dfSMat Martineau 4628fcd289dfSMat Martineau if (control->reqseq == chan->next_tx_seq) { 4629fcd289dfSMat Martineau BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); 4630fcd289dfSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 4631fcd289dfSMat Martineau return; 4632fcd289dfSMat Martineau } 4633fcd289dfSMat Martineau 4634fcd289dfSMat Martineau skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); 4635fcd289dfSMat Martineau 4636fcd289dfSMat Martineau if (chan->max_tx && skb && 4637fcd289dfSMat Martineau bt_cb(skb)->control.retries >= chan->max_tx) { 4638fcd289dfSMat Martineau BT_DBG("Retry limit exceeded (%d)", chan->max_tx); 4639fcd289dfSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 4640fcd289dfSMat Martineau return; 4641fcd289dfSMat Martineau } 4642fcd289dfSMat Martineau 4643fcd289dfSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4644fcd289dfSMat Martineau 4645fcd289dfSMat Martineau l2cap_pass_to_tx(chan, control); 4646fcd289dfSMat Martineau 4647fcd289dfSMat Martineau if (control->final) { 4648fcd289dfSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 4649fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 4650fcd289dfSMat Martineau } else { 4651fcd289dfSMat Martineau l2cap_retransmit_all(chan, control); 4652fcd289dfSMat Martineau l2cap_ertm_send(chan); 4653fcd289dfSMat Martineau if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) 4654fcd289dfSMat Martineau set_bit(CONN_REJ_ACT, &chan->conn_state); 4655fcd289dfSMat Martineau } 4656d2a7ac5dSMat Martineau } 4657d2a7ac5dSMat Martineau 46584b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) 46594b51dae9SMat Martineau { 46604b51dae9SMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 46614b51dae9SMat Martineau 46624b51dae9SMat Martineau BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq, 46634b51dae9SMat Martineau chan->expected_tx_seq); 46644b51dae9SMat Martineau 46654b51dae9SMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 46664b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 46674b51dae9SMat Martineau chan->tx_win) { 46684b51dae9SMat Martineau /* See notes below regarding "double poll" and 46694b51dae9SMat Martineau * invalid packets. 46704b51dae9SMat Martineau */ 46714b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 46724b51dae9SMat Martineau BT_DBG("Invalid/Ignore - after SREJ"); 46734b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 46744b51dae9SMat Martineau } else { 46754b51dae9SMat Martineau BT_DBG("Invalid - in window after SREJ sent"); 46764b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 46774b51dae9SMat Martineau } 46784b51dae9SMat Martineau } 46794b51dae9SMat Martineau 46804b51dae9SMat Martineau if (chan->srej_list.head == txseq) { 46814b51dae9SMat Martineau BT_DBG("Expected SREJ"); 46824b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED_SREJ; 46834b51dae9SMat Martineau } 46844b51dae9SMat Martineau 46854b51dae9SMat Martineau if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) { 46864b51dae9SMat Martineau BT_DBG("Duplicate SREJ - txseq already stored"); 46874b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE_SREJ; 46884b51dae9SMat Martineau } 46894b51dae9SMat Martineau 46904b51dae9SMat Martineau if (l2cap_seq_list_contains(&chan->srej_list, txseq)) { 46914b51dae9SMat Martineau BT_DBG("Unexpected SREJ - not requested"); 46924b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED_SREJ; 46934b51dae9SMat Martineau } 46944b51dae9SMat Martineau } 46954b51dae9SMat Martineau 46964b51dae9SMat Martineau if (chan->expected_tx_seq == txseq) { 46974b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 46984b51dae9SMat Martineau chan->tx_win) { 46994b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 47004b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 47014b51dae9SMat Martineau } else { 47024b51dae9SMat Martineau BT_DBG("Expected"); 47034b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED; 47044b51dae9SMat Martineau } 47054b51dae9SMat Martineau } 47064b51dae9SMat Martineau 47074b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) < 47084b51dae9SMat Martineau __seq_offset(chan, chan->expected_tx_seq, 47094b51dae9SMat Martineau chan->last_acked_seq)){ 47104b51dae9SMat Martineau BT_DBG("Duplicate - expected_tx_seq later than txseq"); 47114b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE; 47124b51dae9SMat Martineau } 47134b51dae9SMat Martineau 47144b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) { 47154b51dae9SMat Martineau /* A source of invalid packets is a "double poll" condition, 47164b51dae9SMat Martineau * where delays cause us to send multiple poll packets. If 47174b51dae9SMat Martineau * the remote stack receives and processes both polls, 47184b51dae9SMat Martineau * sequence numbers can wrap around in such a way that a 47194b51dae9SMat Martineau * resent frame has a sequence number that looks like new data 47204b51dae9SMat Martineau * with a sequence gap. This would trigger an erroneous SREJ 47214b51dae9SMat Martineau * request. 47224b51dae9SMat Martineau * 47234b51dae9SMat Martineau * Fortunately, this is impossible with a tx window that's 47244b51dae9SMat Martineau * less than half of the maximum sequence number, which allows 47254b51dae9SMat Martineau * invalid frames to be safely ignored. 47264b51dae9SMat Martineau * 47274b51dae9SMat Martineau * With tx window sizes greater than half of the tx window 47284b51dae9SMat Martineau * maximum, the frame is invalid and cannot be ignored. This 47294b51dae9SMat Martineau * causes a disconnect. 47304b51dae9SMat Martineau */ 47314b51dae9SMat Martineau 47324b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 47334b51dae9SMat Martineau BT_DBG("Invalid/Ignore - txseq outside tx window"); 47344b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 47354b51dae9SMat Martineau } else { 47364b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 47374b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 47384b51dae9SMat Martineau } 47394b51dae9SMat Martineau } else { 47404b51dae9SMat Martineau BT_DBG("Unexpected - txseq indicates missing frames"); 47414b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED; 47424b51dae9SMat Martineau } 47434b51dae9SMat Martineau } 47444b51dae9SMat Martineau 4745d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan, 4746d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 4747d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 4748d2a7ac5dSMat Martineau { 4749d2a7ac5dSMat Martineau int err = 0; 4750d2a7ac5dSMat Martineau bool skb_in_use = 0; 4751d2a7ac5dSMat Martineau 4752d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 4753d2a7ac5dSMat Martineau event); 4754d2a7ac5dSMat Martineau 4755d2a7ac5dSMat Martineau switch (event) { 4756d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 4757d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, control->txseq)) { 4758d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 4759d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4760d2a7ac5dSMat Martineau 4761d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 4762d2a7ac5dSMat Martineau BT_DBG("Busy, discarding expected seq %d", 4763d2a7ac5dSMat Martineau control->txseq); 4764d2a7ac5dSMat Martineau break; 4765d2a7ac5dSMat Martineau } 4766d2a7ac5dSMat Martineau 4767d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, 4768d2a7ac5dSMat Martineau control->txseq); 4769d2a7ac5dSMat Martineau 4770d2a7ac5dSMat Martineau chan->buffer_seq = chan->expected_tx_seq; 4771d2a7ac5dSMat Martineau skb_in_use = 1; 4772d2a7ac5dSMat Martineau 4773d2a7ac5dSMat Martineau err = l2cap_reassemble_sdu(chan, skb, control); 4774d2a7ac5dSMat Martineau if (err) 4775d2a7ac5dSMat Martineau break; 4776d2a7ac5dSMat Martineau 4777d2a7ac5dSMat Martineau if (control->final) { 4778d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 4779d2a7ac5dSMat Martineau &chan->conn_state)) { 4780d2a7ac5dSMat Martineau control->final = 0; 4781d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 4782d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 4783d2a7ac5dSMat Martineau } 4784d2a7ac5dSMat Martineau } 4785d2a7ac5dSMat Martineau 4786d2a7ac5dSMat Martineau if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 4787d2a7ac5dSMat Martineau l2cap_send_ack(chan); 4788d2a7ac5dSMat Martineau break; 4789d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 4790d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4791d2a7ac5dSMat Martineau 4792d2a7ac5dSMat Martineau /* Can't issue SREJ frames in the local busy state. 4793d2a7ac5dSMat Martineau * Drop this frame, it will be seen as missing 4794d2a7ac5dSMat Martineau * when local busy is exited. 4795d2a7ac5dSMat Martineau */ 4796d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 4797d2a7ac5dSMat Martineau BT_DBG("Busy, discarding unexpected seq %d", 4798d2a7ac5dSMat Martineau control->txseq); 4799d2a7ac5dSMat Martineau break; 4800d2a7ac5dSMat Martineau } 4801d2a7ac5dSMat Martineau 4802d2a7ac5dSMat Martineau /* There was a gap in the sequence, so an SREJ 4803d2a7ac5dSMat Martineau * must be sent for each missing frame. The 4804d2a7ac5dSMat Martineau * current frame is stored for later use. 4805d2a7ac5dSMat Martineau */ 4806d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4807d2a7ac5dSMat Martineau skb_in_use = 1; 4808d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4809d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4810d2a7ac5dSMat Martineau 4811d2a7ac5dSMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 4812d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 4813d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 4814d2a7ac5dSMat Martineau 4815d2a7ac5dSMat Martineau chan->rx_state = L2CAP_RX_STATE_SREJ_SENT; 4816d2a7ac5dSMat Martineau break; 4817d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 4818d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4819d2a7ac5dSMat Martineau break; 4820d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 4821d2a7ac5dSMat Martineau break; 4822d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 4823d2a7ac5dSMat Martineau default: 4824d2a7ac5dSMat Martineau l2cap_send_disconn_req(chan->conn, chan, 4825d2a7ac5dSMat Martineau ECONNRESET); 4826d2a7ac5dSMat Martineau break; 4827d2a7ac5dSMat Martineau } 4828d2a7ac5dSMat Martineau break; 4829d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 4830d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4831d2a7ac5dSMat Martineau if (control->final) { 4832d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4833d2a7ac5dSMat Martineau 4834d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 4835d2a7ac5dSMat Martineau &chan->conn_state)) { 4836d2a7ac5dSMat Martineau control->final = 0; 4837d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 4838d2a7ac5dSMat Martineau } 4839d2a7ac5dSMat Martineau 4840d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 4841d2a7ac5dSMat Martineau } else if (control->poll) { 4842d2a7ac5dSMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 4843d2a7ac5dSMat Martineau } else { 4844d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 4845d2a7ac5dSMat Martineau &chan->conn_state) && 4846d2a7ac5dSMat Martineau chan->unacked_frames) 4847d2a7ac5dSMat Martineau __set_retrans_timer(chan); 4848d2a7ac5dSMat Martineau 4849d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 4850d2a7ac5dSMat Martineau } 4851d2a7ac5dSMat Martineau break; 4852d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 4853d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4854d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4855d2a7ac5dSMat Martineau if (control && control->poll) { 4856d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 4857d2a7ac5dSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 4858d2a7ac5dSMat Martineau } 4859d2a7ac5dSMat Martineau __clear_retrans_timer(chan); 4860d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 4861d2a7ac5dSMat Martineau break; 4862d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 4863d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 4864d2a7ac5dSMat Martineau break; 4865d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 4866d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 4867d2a7ac5dSMat Martineau break; 4868d2a7ac5dSMat Martineau default: 4869d2a7ac5dSMat Martineau break; 4870d2a7ac5dSMat Martineau } 4871d2a7ac5dSMat Martineau 4872d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 4873d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 4874d2a7ac5dSMat Martineau kfree_skb(skb); 4875d2a7ac5dSMat Martineau } 4876d2a7ac5dSMat Martineau 4877d2a7ac5dSMat Martineau return err; 4878d2a7ac5dSMat Martineau } 4879d2a7ac5dSMat Martineau 4880d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, 4881d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 4882d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 4883d2a7ac5dSMat Martineau { 4884d2a7ac5dSMat Martineau int err = 0; 4885d2a7ac5dSMat Martineau u16 txseq = control->txseq; 4886d2a7ac5dSMat Martineau bool skb_in_use = 0; 4887d2a7ac5dSMat Martineau 4888d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 4889d2a7ac5dSMat Martineau event); 4890d2a7ac5dSMat Martineau 4891d2a7ac5dSMat Martineau switch (event) { 4892d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 4893d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, txseq)) { 4894d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 4895d2a7ac5dSMat Martineau /* Keep frame for reassembly later */ 4896d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4897d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4898d2a7ac5dSMat Martineau skb_in_use = 1; 4899d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4900d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4901d2a7ac5dSMat Martineau 4902d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 4903d2a7ac5dSMat Martineau break; 4904d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED_SREJ: 4905d2a7ac5dSMat Martineau l2cap_seq_list_pop(&chan->srej_list); 4906d2a7ac5dSMat Martineau 4907d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4908d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4909d2a7ac5dSMat Martineau skb_in_use = 1; 4910d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4911d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4912d2a7ac5dSMat Martineau 4913d2a7ac5dSMat Martineau err = l2cap_rx_queued_iframes(chan); 4914d2a7ac5dSMat Martineau if (err) 4915d2a7ac5dSMat Martineau break; 4916d2a7ac5dSMat Martineau 4917d2a7ac5dSMat Martineau break; 4918d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 4919d2a7ac5dSMat Martineau /* Got a frame that can't be reassembled yet. 4920d2a7ac5dSMat Martineau * Save it for later, and send SREJs to cover 4921d2a7ac5dSMat Martineau * the missing frames. 4922d2a7ac5dSMat Martineau */ 4923d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4924d2a7ac5dSMat Martineau skb_in_use = 1; 4925d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4926d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4927d2a7ac5dSMat Martineau 4928d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4929d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 4930d2a7ac5dSMat Martineau break; 4931d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED_SREJ: 4932d2a7ac5dSMat Martineau /* This frame was requested with an SREJ, but 4933d2a7ac5dSMat Martineau * some expected retransmitted frames are 4934d2a7ac5dSMat Martineau * missing. Request retransmission of missing 4935d2a7ac5dSMat Martineau * SREJ'd frames. 4936d2a7ac5dSMat Martineau */ 4937d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4938d2a7ac5dSMat Martineau skb_in_use = 1; 4939d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4940d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4941d2a7ac5dSMat Martineau 4942d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4943d2a7ac5dSMat Martineau l2cap_send_srej_list(chan, control->txseq); 4944d2a7ac5dSMat Martineau break; 4945d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE_SREJ: 4946d2a7ac5dSMat Martineau /* We've already queued this frame. Drop this copy. */ 4947d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4948d2a7ac5dSMat Martineau break; 4949d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 4950d2a7ac5dSMat Martineau /* Expecting a later sequence number, so this frame 4951d2a7ac5dSMat Martineau * was already received. Ignore it completely. 4952d2a7ac5dSMat Martineau */ 4953d2a7ac5dSMat Martineau break; 4954d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 4955d2a7ac5dSMat Martineau break; 4956d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 4957d2a7ac5dSMat Martineau default: 4958d2a7ac5dSMat Martineau l2cap_send_disconn_req(chan->conn, chan, 4959d2a7ac5dSMat Martineau ECONNRESET); 4960d2a7ac5dSMat Martineau break; 4961d2a7ac5dSMat Martineau } 4962d2a7ac5dSMat Martineau break; 4963d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 4964d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4965d2a7ac5dSMat Martineau if (control->final) { 4966d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4967d2a7ac5dSMat Martineau 4968d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 4969d2a7ac5dSMat Martineau &chan->conn_state)) { 4970d2a7ac5dSMat Martineau control->final = 0; 4971d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 4972d2a7ac5dSMat Martineau } 4973d2a7ac5dSMat Martineau 4974d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 4975d2a7ac5dSMat Martineau } else if (control->poll) { 4976d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 4977d2a7ac5dSMat Martineau &chan->conn_state) && 4978d2a7ac5dSMat Martineau chan->unacked_frames) { 4979d2a7ac5dSMat Martineau __set_retrans_timer(chan); 4980d2a7ac5dSMat Martineau } 4981d2a7ac5dSMat Martineau 4982d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 4983d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 4984d2a7ac5dSMat Martineau } else { 4985d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 4986d2a7ac5dSMat Martineau &chan->conn_state) && 4987d2a7ac5dSMat Martineau chan->unacked_frames) 4988d2a7ac5dSMat Martineau __set_retrans_timer(chan); 4989d2a7ac5dSMat Martineau 4990d2a7ac5dSMat Martineau l2cap_send_ack(chan); 4991d2a7ac5dSMat Martineau } 4992d2a7ac5dSMat Martineau break; 4993d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 4994d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4995d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4996d2a7ac5dSMat Martineau if (control->poll) { 4997d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 4998d2a7ac5dSMat Martineau } else { 4999d2a7ac5dSMat Martineau struct l2cap_ctrl rr_control; 5000d2a7ac5dSMat Martineau memset(&rr_control, 0, sizeof(rr_control)); 5001d2a7ac5dSMat Martineau rr_control.sframe = 1; 5002d2a7ac5dSMat Martineau rr_control.super = L2CAP_SUPER_RR; 5003d2a7ac5dSMat Martineau rr_control.reqseq = chan->buffer_seq; 5004d2a7ac5dSMat Martineau l2cap_send_sframe(chan, &rr_control); 5005d2a7ac5dSMat Martineau } 5006d2a7ac5dSMat Martineau 5007d2a7ac5dSMat Martineau break; 5008d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 5009d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 5010d2a7ac5dSMat Martineau break; 5011d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 5012d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 5013d2a7ac5dSMat Martineau break; 5014d2a7ac5dSMat Martineau } 5015d2a7ac5dSMat Martineau 5016d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 5017d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 5018d2a7ac5dSMat Martineau kfree_skb(skb); 5019d2a7ac5dSMat Martineau } 5020d2a7ac5dSMat Martineau 5021d2a7ac5dSMat Martineau return err; 5022d2a7ac5dSMat Martineau } 5023d2a7ac5dSMat Martineau 5024d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq) 5025d2a7ac5dSMat Martineau { 5026d2a7ac5dSMat Martineau /* Make sure reqseq is for a packet that has been sent but not acked */ 5027d2a7ac5dSMat Martineau u16 unacked; 5028d2a7ac5dSMat Martineau 5029d2a7ac5dSMat Martineau unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq); 5030d2a7ac5dSMat Martineau return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked; 5031d2a7ac5dSMat Martineau } 5032d2a7ac5dSMat Martineau 5033cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 5034cec8ab6eSMat Martineau struct sk_buff *skb, u8 event) 50350a708f8fSGustavo F. Padovan { 5036d2a7ac5dSMat Martineau int err = 0; 5037d2a7ac5dSMat Martineau 5038d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan, 5039d2a7ac5dSMat Martineau control, skb, event, chan->rx_state); 5040d2a7ac5dSMat Martineau 5041d2a7ac5dSMat Martineau if (__valid_reqseq(chan, control->reqseq)) { 5042d2a7ac5dSMat Martineau switch (chan->rx_state) { 5043d2a7ac5dSMat Martineau case L2CAP_RX_STATE_RECV: 5044d2a7ac5dSMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 5045d2a7ac5dSMat Martineau break; 5046d2a7ac5dSMat Martineau case L2CAP_RX_STATE_SREJ_SENT: 5047d2a7ac5dSMat Martineau err = l2cap_rx_state_srej_sent(chan, control, skb, 5048d2a7ac5dSMat Martineau event); 5049d2a7ac5dSMat Martineau break; 5050d2a7ac5dSMat Martineau default: 5051d2a7ac5dSMat Martineau /* shut it down */ 5052d2a7ac5dSMat Martineau break; 5053d2a7ac5dSMat Martineau } 5054d2a7ac5dSMat Martineau } else { 5055d2a7ac5dSMat Martineau BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d", 5056d2a7ac5dSMat Martineau control->reqseq, chan->next_tx_seq, 5057d2a7ac5dSMat Martineau chan->expected_ack_seq); 5058d2a7ac5dSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 5059d2a7ac5dSMat Martineau } 5060d2a7ac5dSMat Martineau 5061d2a7ac5dSMat Martineau return err; 5062cec8ab6eSMat Martineau } 5063cec8ab6eSMat Martineau 5064cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 5065cec8ab6eSMat Martineau struct sk_buff *skb) 5066cec8ab6eSMat Martineau { 50674b51dae9SMat Martineau int err = 0; 50684b51dae9SMat Martineau 50694b51dae9SMat Martineau BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb, 50704b51dae9SMat Martineau chan->rx_state); 50714b51dae9SMat Martineau 50724b51dae9SMat Martineau if (l2cap_classify_txseq(chan, control->txseq) == 50734b51dae9SMat Martineau L2CAP_TXSEQ_EXPECTED) { 50744b51dae9SMat Martineau l2cap_pass_to_tx(chan, control); 50754b51dae9SMat Martineau 50764b51dae9SMat Martineau BT_DBG("buffer_seq %d->%d", chan->buffer_seq, 50774b51dae9SMat Martineau __next_seq(chan, chan->buffer_seq)); 50784b51dae9SMat Martineau 50794b51dae9SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 50804b51dae9SMat Martineau 50814b51dae9SMat Martineau l2cap_reassemble_sdu(chan, skb, control); 50824b51dae9SMat Martineau } else { 50834b51dae9SMat Martineau if (chan->sdu) { 50844b51dae9SMat Martineau kfree_skb(chan->sdu); 50854b51dae9SMat Martineau chan->sdu = NULL; 50864b51dae9SMat Martineau } 50874b51dae9SMat Martineau chan->sdu_last_frag = NULL; 50884b51dae9SMat Martineau chan->sdu_len = 0; 50894b51dae9SMat Martineau 50904b51dae9SMat Martineau if (skb) { 50914b51dae9SMat Martineau BT_DBG("Freeing %p", skb); 50924b51dae9SMat Martineau kfree_skb(skb); 50934b51dae9SMat Martineau } 50944b51dae9SMat Martineau } 50954b51dae9SMat Martineau 50964b51dae9SMat Martineau chan->last_acked_seq = control->txseq; 50974b51dae9SMat Martineau chan->expected_tx_seq = __next_seq(chan, control->txseq); 50984b51dae9SMat Martineau 50994b51dae9SMat Martineau return err; 5100cec8ab6eSMat Martineau } 5101cec8ab6eSMat Martineau 5102cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 5103cec8ab6eSMat Martineau { 5104cec8ab6eSMat Martineau struct l2cap_ctrl *control = &bt_cb(skb)->control; 5105cec8ab6eSMat Martineau u16 len; 5106cec8ab6eSMat Martineau u8 event; 51070a708f8fSGustavo F. Padovan 5108b76bbd66SMat Martineau __unpack_control(chan, skb); 5109b76bbd66SMat Martineau 51100a708f8fSGustavo F. Padovan len = skb->len; 51110a708f8fSGustavo F. Padovan 51120a708f8fSGustavo F. Padovan /* 51130a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here. 51140a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery 5115cec8ab6eSMat Martineau * procedures and ask for retransmission. 51160a708f8fSGustavo F. Padovan */ 511747d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 51180a708f8fSGustavo F. Padovan goto drop; 51190a708f8fSGustavo F. Padovan 5120cec8ab6eSMat Martineau if (!control->sframe && control->sar == L2CAP_SAR_START) 512103a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 51220a708f8fSGustavo F. Padovan 512347d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 512403a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 51250a708f8fSGustavo F. Padovan 512647d1ec61SGustavo F. Padovan if (len > chan->mps) { 51278c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 51280a708f8fSGustavo F. Padovan goto drop; 51290a708f8fSGustavo F. Padovan } 51300a708f8fSGustavo F. Padovan 5131cec8ab6eSMat Martineau if (!control->sframe) { 5132cec8ab6eSMat Martineau int err; 51330a708f8fSGustavo F. Padovan 5134cec8ab6eSMat Martineau BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d", 5135cec8ab6eSMat Martineau control->sar, control->reqseq, control->final, 5136cec8ab6eSMat Martineau control->txseq); 5137836be934SAndrei Emeltchenko 5138cec8ab6eSMat Martineau /* Validate F-bit - F=0 always valid, F=1 only 5139cec8ab6eSMat Martineau * valid in TX WAIT_F 5140cec8ab6eSMat Martineau */ 5141cec8ab6eSMat Martineau if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F) 51420a708f8fSGustavo F. Padovan goto drop; 51430a708f8fSGustavo F. Padovan 5144cec8ab6eSMat Martineau if (chan->mode != L2CAP_MODE_STREAMING) { 5145cec8ab6eSMat Martineau event = L2CAP_EV_RECV_IFRAME; 5146cec8ab6eSMat Martineau err = l2cap_rx(chan, control, skb, event); 51470a708f8fSGustavo F. Padovan } else { 5148cec8ab6eSMat Martineau err = l2cap_stream_rx(chan, control, skb); 5149cec8ab6eSMat Martineau } 5150cec8ab6eSMat Martineau 5151cec8ab6eSMat Martineau if (err) 5152cec8ab6eSMat Martineau l2cap_send_disconn_req(chan->conn, chan, 5153cec8ab6eSMat Martineau ECONNRESET); 5154cec8ab6eSMat Martineau } else { 5155cec8ab6eSMat Martineau const u8 rx_func_to_event[4] = { 5156cec8ab6eSMat Martineau L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ, 5157cec8ab6eSMat Martineau L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ 5158cec8ab6eSMat Martineau }; 5159cec8ab6eSMat Martineau 5160cec8ab6eSMat Martineau /* Only I-frames are expected in streaming mode */ 5161cec8ab6eSMat Martineau if (chan->mode == L2CAP_MODE_STREAMING) 5162cec8ab6eSMat Martineau goto drop; 5163cec8ab6eSMat Martineau 5164cec8ab6eSMat Martineau BT_DBG("sframe reqseq %d, final %d, poll %d, super %d", 5165cec8ab6eSMat Martineau control->reqseq, control->final, control->poll, 5166cec8ab6eSMat Martineau control->super); 5167cec8ab6eSMat Martineau 51680a708f8fSGustavo F. Padovan if (len != 0) { 51690a708f8fSGustavo F. Padovan BT_ERR("%d", len); 51708c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 51710a708f8fSGustavo F. Padovan goto drop; 51720a708f8fSGustavo F. Padovan } 51730a708f8fSGustavo F. Padovan 5174cec8ab6eSMat Martineau /* Validate F and P bits */ 5175cec8ab6eSMat Martineau if (control->final && (control->poll || 5176cec8ab6eSMat Martineau chan->tx_state != L2CAP_TX_STATE_WAIT_F)) 5177cec8ab6eSMat Martineau goto drop; 5178cec8ab6eSMat Martineau 5179cec8ab6eSMat Martineau event = rx_func_to_event[control->super]; 5180cec8ab6eSMat Martineau if (l2cap_rx(chan, control, skb, event)) 5181cec8ab6eSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 51820a708f8fSGustavo F. Padovan } 51830a708f8fSGustavo F. Padovan 51840a708f8fSGustavo F. Padovan return 0; 51850a708f8fSGustavo F. Padovan 51860a708f8fSGustavo F. Padovan drop: 51870a708f8fSGustavo F. Padovan kfree_skb(skb); 51880a708f8fSGustavo F. Padovan return 0; 51890a708f8fSGustavo F. Padovan } 51900a708f8fSGustavo F. Padovan 51910a708f8fSGustavo F. Padovan static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb) 51920a708f8fSGustavo F. Padovan { 519348454079SGustavo F. Padovan struct l2cap_chan *chan; 51940a708f8fSGustavo F. Padovan 5195baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 519648454079SGustavo F. Padovan if (!chan) { 51970a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid); 51986be36555SAndrei Emeltchenko /* Drop packet and return */ 51993379013bSDan Carpenter kfree_skb(skb); 52006be36555SAndrei Emeltchenko return 0; 52010a708f8fSGustavo F. Padovan } 52020a708f8fSGustavo F. Padovan 520349208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len); 52040a708f8fSGustavo F. Padovan 520589bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 52060a708f8fSGustavo F. Padovan goto drop; 52070a708f8fSGustavo F. Padovan 52080c1bc5c6SGustavo F. Padovan switch (chan->mode) { 52090a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 52100a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here 52110a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable. 52120a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't 52130a708f8fSGustavo F. Padovan * provide flow control mechanism. */ 52140a708f8fSGustavo F. Padovan 52150c1bc5c6SGustavo F. Padovan if (chan->imtu < skb->len) 52160a708f8fSGustavo F. Padovan goto drop; 52170a708f8fSGustavo F. Padovan 521823070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 52190a708f8fSGustavo F. Padovan goto done; 52200a708f8fSGustavo F. Padovan break; 52210a708f8fSGustavo F. Padovan 52220a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 52230a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 5224cec8ab6eSMat Martineau l2cap_data_rcv(chan, skb); 52250a708f8fSGustavo F. Padovan goto done; 52260a708f8fSGustavo F. Padovan 52270a708f8fSGustavo F. Padovan default: 52280c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); 52290a708f8fSGustavo F. Padovan break; 52300a708f8fSGustavo F. Padovan } 52310a708f8fSGustavo F. Padovan 52320a708f8fSGustavo F. Padovan drop: 52330a708f8fSGustavo F. Padovan kfree_skb(skb); 52340a708f8fSGustavo F. Padovan 52350a708f8fSGustavo F. Padovan done: 52366be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 52370a708f8fSGustavo F. Padovan 52380a708f8fSGustavo F. Padovan return 0; 52390a708f8fSGustavo F. Padovan } 52400a708f8fSGustavo F. Padovan 52410a708f8fSGustavo F. Padovan static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb) 52420a708f8fSGustavo F. Padovan { 524323691d75SGustavo F. Padovan struct l2cap_chan *chan; 52440a708f8fSGustavo F. Padovan 5245c2287681SIdo Yariv chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst); 524623691d75SGustavo F. Padovan if (!chan) 52470a708f8fSGustavo F. Padovan goto drop; 52480a708f8fSGustavo F. Padovan 52495b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 52500a708f8fSGustavo F. Padovan 525189bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 52520a708f8fSGustavo F. Padovan goto drop; 52530a708f8fSGustavo F. Padovan 5254e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 52550a708f8fSGustavo F. Padovan goto drop; 52560a708f8fSGustavo F. Padovan 525723070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 52585b4cedaaSAndrei Emeltchenko return 0; 52590a708f8fSGustavo F. Padovan 52600a708f8fSGustavo F. Padovan drop: 52610a708f8fSGustavo F. Padovan kfree_skb(skb); 52620a708f8fSGustavo F. Padovan 52630a708f8fSGustavo F. Padovan return 0; 52640a708f8fSGustavo F. Padovan } 52650a708f8fSGustavo F. Padovan 5266d9b88702SAndrei Emeltchenko static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid, 5267d9b88702SAndrei Emeltchenko struct sk_buff *skb) 52689f69bda6SGustavo F. Padovan { 526923691d75SGustavo F. Padovan struct l2cap_chan *chan; 52709f69bda6SGustavo F. Padovan 5271c2287681SIdo Yariv chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst); 527223691d75SGustavo F. Padovan if (!chan) 52739f69bda6SGustavo F. Padovan goto drop; 52749f69bda6SGustavo F. Padovan 52755b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 52769f69bda6SGustavo F. Padovan 527789bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 52789f69bda6SGustavo F. Padovan goto drop; 52799f69bda6SGustavo F. Padovan 5280e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 52819f69bda6SGustavo F. Padovan goto drop; 52829f69bda6SGustavo F. Padovan 528323070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 52845b4cedaaSAndrei Emeltchenko return 0; 52859f69bda6SGustavo F. Padovan 52869f69bda6SGustavo F. Padovan drop: 52879f69bda6SGustavo F. Padovan kfree_skb(skb); 52889f69bda6SGustavo F. Padovan 52899f69bda6SGustavo F. Padovan return 0; 52909f69bda6SGustavo F. Padovan } 52919f69bda6SGustavo F. Padovan 52920a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) 52930a708f8fSGustavo F. Padovan { 52940a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data; 52950a708f8fSGustavo F. Padovan u16 cid, len; 52960a708f8fSGustavo F. Padovan __le16 psm; 52970a708f8fSGustavo F. Padovan 52980a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE); 52990a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid); 53000a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len); 53010a708f8fSGustavo F. Padovan 53020a708f8fSGustavo F. Padovan if (len != skb->len) { 53030a708f8fSGustavo F. Padovan kfree_skb(skb); 53040a708f8fSGustavo F. Padovan return; 53050a708f8fSGustavo F. Padovan } 53060a708f8fSGustavo F. Padovan 53070a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid); 53080a708f8fSGustavo F. Padovan 53090a708f8fSGustavo F. Padovan switch (cid) { 53103300d9a9SClaudio Takahasi case L2CAP_CID_LE_SIGNALING: 53110a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING: 53120a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb); 53130a708f8fSGustavo F. Padovan break; 53140a708f8fSGustavo F. Padovan 53150a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS: 5316097db76cSAndrei Emeltchenko psm = get_unaligned((__le16 *) skb->data); 53170a708f8fSGustavo F. Padovan skb_pull(skb, 2); 53180a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb); 53190a708f8fSGustavo F. Padovan break; 53200a708f8fSGustavo F. Padovan 53219f69bda6SGustavo F. Padovan case L2CAP_CID_LE_DATA: 53229f69bda6SGustavo F. Padovan l2cap_att_channel(conn, cid, skb); 53239f69bda6SGustavo F. Padovan break; 53249f69bda6SGustavo F. Padovan 5325b501d6a1SAnderson Briglia case L2CAP_CID_SMP: 5326b501d6a1SAnderson Briglia if (smp_sig_channel(conn, skb)) 5327b501d6a1SAnderson Briglia l2cap_conn_del(conn->hcon, EACCES); 5328b501d6a1SAnderson Briglia break; 5329b501d6a1SAnderson Briglia 53300a708f8fSGustavo F. Padovan default: 53310a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb); 53320a708f8fSGustavo F. Padovan break; 53330a708f8fSGustavo F. Padovan } 53340a708f8fSGustavo F. Padovan } 53350a708f8fSGustavo F. Padovan 53360a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */ 53370a708f8fSGustavo F. Padovan 5338686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) 53390a708f8fSGustavo F. Padovan { 53400a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0; 534123691d75SGustavo F. Padovan struct l2cap_chan *c; 53420a708f8fSGustavo F. Padovan 53430a708f8fSGustavo F. Padovan BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); 53440a708f8fSGustavo F. Padovan 53450a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */ 534623691d75SGustavo F. Padovan read_lock(&chan_list_lock); 534723691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 534823691d75SGustavo F. Padovan struct sock *sk = c->sk; 53494343478fSGustavo F. Padovan 535089bc500eSGustavo F. Padovan if (c->state != BT_LISTEN) 53510a708f8fSGustavo F. Padovan continue; 53520a708f8fSGustavo F. Padovan 53530a708f8fSGustavo F. Padovan if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { 53540a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT; 535543bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 53560a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER; 53570a708f8fSGustavo F. Padovan exact++; 53580a708f8fSGustavo F. Padovan } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { 53590a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT; 536043bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 53610a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER; 53620a708f8fSGustavo F. Padovan } 53630a708f8fSGustavo F. Padovan } 536423691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 53650a708f8fSGustavo F. Padovan 53660a708f8fSGustavo F. Padovan return exact ? lm1 : lm2; 53670a708f8fSGustavo F. Padovan } 53680a708f8fSGustavo F. Padovan 5369686ebf28SUlisses Furquim int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) 53700a708f8fSGustavo F. Padovan { 53710a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 53720a708f8fSGustavo F. Padovan 53730a708f8fSGustavo F. Padovan BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); 53740a708f8fSGustavo F. Padovan 53750a708f8fSGustavo F. Padovan if (!status) { 53760a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, status); 53770a708f8fSGustavo F. Padovan if (conn) 53780a708f8fSGustavo F. Padovan l2cap_conn_ready(conn); 53790a708f8fSGustavo F. Padovan } else 5380e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status)); 53810a708f8fSGustavo F. Padovan 53820a708f8fSGustavo F. Padovan return 0; 53830a708f8fSGustavo F. Padovan } 53840a708f8fSGustavo F. Padovan 5385686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon) 53860a708f8fSGustavo F. Padovan { 53870a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 53880a708f8fSGustavo F. Padovan 53890a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon); 53900a708f8fSGustavo F. Padovan 5391686ebf28SUlisses Furquim if (!conn) 53929f5a0d7bSAndrei Emeltchenko return HCI_ERROR_REMOTE_USER_TERM; 53930a708f8fSGustavo F. Padovan return conn->disc_reason; 53940a708f8fSGustavo F. Padovan } 53950a708f8fSGustavo F. Padovan 5396686ebf28SUlisses Furquim int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) 53970a708f8fSGustavo F. Padovan { 53980a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason); 53990a708f8fSGustavo F. Padovan 5400e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason)); 54010a708f8fSGustavo F. Padovan return 0; 54020a708f8fSGustavo F. Padovan } 54030a708f8fSGustavo F. Padovan 54044343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) 54050a708f8fSGustavo F. Padovan { 5406715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 54070a708f8fSGustavo F. Padovan return; 54080a708f8fSGustavo F. Padovan 54090a708f8fSGustavo F. Padovan if (encrypt == 0x00) { 54104343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) { 5411ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); 54124343478fSGustavo F. Padovan } else if (chan->sec_level == BT_SECURITY_HIGH) 54130f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED); 54140a708f8fSGustavo F. Padovan } else { 54154343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) 5416c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 54170a708f8fSGustavo F. Padovan } 54180a708f8fSGustavo F. Padovan } 54190a708f8fSGustavo F. Padovan 5420686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) 54210a708f8fSGustavo F. Padovan { 54220a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 542348454079SGustavo F. Padovan struct l2cap_chan *chan; 54240a708f8fSGustavo F. Padovan 54250a708f8fSGustavo F. Padovan if (!conn) 54260a708f8fSGustavo F. Padovan return 0; 54270a708f8fSGustavo F. Padovan 54280a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 54290a708f8fSGustavo F. Padovan 5430160dc6acSVinicius Costa Gomes if (hcon->type == LE_LINK) { 543135d4adccSHemant Gupta if (!status && encrypt) 5432160dc6acSVinicius Costa Gomes smp_distribute_keys(conn, 0); 543317cd3f37SUlisses Furquim cancel_delayed_work(&conn->security_timer); 5434160dc6acSVinicius Costa Gomes } 5435160dc6acSVinicius Costa Gomes 54363df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 54370a708f8fSGustavo F. Padovan 54383df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 54396be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 54400a708f8fSGustavo F. Padovan 5441f1cb9af5SVinicius Costa Gomes BT_DBG("chan->scid %d", chan->scid); 5442f1cb9af5SVinicius Costa Gomes 5443f1cb9af5SVinicius Costa Gomes if (chan->scid == L2CAP_CID_LE_DATA) { 5444f1cb9af5SVinicius Costa Gomes if (!status && encrypt) { 5445f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level; 5446cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 5447f1cb9af5SVinicius Costa Gomes } 5448f1cb9af5SVinicius Costa Gomes 54496be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 5450f1cb9af5SVinicius Costa Gomes continue; 5451f1cb9af5SVinicius Costa Gomes } 5452f1cb9af5SVinicius Costa Gomes 5453c1360a1cSGustavo F. Padovan if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) { 54546be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 54550a708f8fSGustavo F. Padovan continue; 54560a708f8fSGustavo F. Padovan } 54570a708f8fSGustavo F. Padovan 545889bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED || 545989bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) { 5460a7d7723aSGustavo Padovan struct sock *sk = chan->sk; 5461a7d7723aSGustavo Padovan 5462c5daa683SGustavo Padovan clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); 5463a7d7723aSGustavo Padovan sk->sk_state_change(sk); 5464a7d7723aSGustavo Padovan 54654343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt); 54666be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 54670a708f8fSGustavo F. Padovan continue; 54680a708f8fSGustavo F. Padovan } 54690a708f8fSGustavo F. Padovan 547089bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 54710a708f8fSGustavo F. Padovan if (!status) { 54729b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 54730a708f8fSGustavo F. Padovan } else { 5474ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 54750a708f8fSGustavo F. Padovan } 547689bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 54776be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 54780a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 5479df3c3931SJohan Hedberg __u16 res, stat; 54800a708f8fSGustavo F. Padovan 54816be36555SAndrei Emeltchenko lock_sock(sk); 54826be36555SAndrei Emeltchenko 54830a708f8fSGustavo F. Padovan if (!status) { 5484c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, 5485c5daa683SGustavo Padovan &bt_sk(sk)->flags)) { 5486df3c3931SJohan Hedberg struct sock *parent = bt_sk(sk)->parent; 5487df3c3931SJohan Hedberg res = L2CAP_CR_PEND; 5488df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND; 548905e9a2f6SIlia Kolomisnky if (parent) 5490df3c3931SJohan Hedberg parent->sk_data_ready(parent, 0); 5491df3c3931SJohan Hedberg } else { 54920e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 5493df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS; 5494df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 5495df3c3931SJohan Hedberg } 54960a708f8fSGustavo F. Padovan } else { 54970e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_DISCONN); 5498ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 5499df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK; 5500df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 55010a708f8fSGustavo F. Padovan } 55020a708f8fSGustavo F. Padovan 55036be36555SAndrei Emeltchenko release_sock(sk); 55046be36555SAndrei Emeltchenko 5505fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 5506fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 5507df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res); 5508df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat); 5509fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 5510fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 55110a708f8fSGustavo F. Padovan } 55120a708f8fSGustavo F. Padovan 55136be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 55140a708f8fSGustavo F. Padovan } 55150a708f8fSGustavo F. Padovan 55163df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 55170a708f8fSGustavo F. Padovan 55180a708f8fSGustavo F. Padovan return 0; 55190a708f8fSGustavo F. Padovan } 55200a708f8fSGustavo F. Padovan 5521686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) 55220a708f8fSGustavo F. Padovan { 55230a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 55240a708f8fSGustavo F. Padovan 55250a708f8fSGustavo F. Padovan if (!conn) 55260a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, 0); 55270a708f8fSGustavo F. Padovan 55280a708f8fSGustavo F. Padovan if (!conn) 55290a708f8fSGustavo F. Padovan goto drop; 55300a708f8fSGustavo F. Padovan 55310a708f8fSGustavo F. Padovan BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); 55320a708f8fSGustavo F. Padovan 55330a708f8fSGustavo F. Padovan if (!(flags & ACL_CONT)) { 55340a708f8fSGustavo F. Padovan struct l2cap_hdr *hdr; 55350a708f8fSGustavo F. Padovan int len; 55360a708f8fSGustavo F. Padovan 55370a708f8fSGustavo F. Padovan if (conn->rx_len) { 55380a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len); 55390a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 55400a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 55410a708f8fSGustavo F. Padovan conn->rx_len = 0; 55420a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 55430a708f8fSGustavo F. Padovan } 55440a708f8fSGustavo F. Padovan 55450a708f8fSGustavo F. Padovan /* Start fragment always begin with Basic L2CAP header */ 55460a708f8fSGustavo F. Padovan if (skb->len < L2CAP_HDR_SIZE) { 55470a708f8fSGustavo F. Padovan BT_ERR("Frame is too short (len %d)", skb->len); 55480a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 55490a708f8fSGustavo F. Padovan goto drop; 55500a708f8fSGustavo F. Padovan } 55510a708f8fSGustavo F. Padovan 55520a708f8fSGustavo F. Padovan hdr = (struct l2cap_hdr *) skb->data; 55530a708f8fSGustavo F. Padovan len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; 55540a708f8fSGustavo F. Padovan 55550a708f8fSGustavo F. Padovan if (len == skb->len) { 55560a708f8fSGustavo F. Padovan /* Complete frame received */ 55570a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb); 55580a708f8fSGustavo F. Padovan return 0; 55590a708f8fSGustavo F. Padovan } 55600a708f8fSGustavo F. Padovan 55610a708f8fSGustavo F. Padovan BT_DBG("Start: total len %d, frag len %d", len, skb->len); 55620a708f8fSGustavo F. Padovan 55630a708f8fSGustavo F. Padovan if (skb->len > len) { 55640a708f8fSGustavo F. Padovan BT_ERR("Frame is too long (len %d, expected len %d)", 55650a708f8fSGustavo F. Padovan skb->len, len); 55660a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 55670a708f8fSGustavo F. Padovan goto drop; 55680a708f8fSGustavo F. Padovan } 55690a708f8fSGustavo F. Padovan 55700a708f8fSGustavo F. Padovan /* Allocate skb for the complete frame (with header) */ 55710a708f8fSGustavo F. Padovan conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC); 55720a708f8fSGustavo F. Padovan if (!conn->rx_skb) 55730a708f8fSGustavo F. Padovan goto drop; 55740a708f8fSGustavo F. Padovan 55750a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 55760a708f8fSGustavo F. Padovan skb->len); 55770a708f8fSGustavo F. Padovan conn->rx_len = len - skb->len; 55780a708f8fSGustavo F. Padovan } else { 55790a708f8fSGustavo F. Padovan BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); 55800a708f8fSGustavo F. Padovan 55810a708f8fSGustavo F. Padovan if (!conn->rx_len) { 55820a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len); 55830a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 55840a708f8fSGustavo F. Padovan goto drop; 55850a708f8fSGustavo F. Padovan } 55860a708f8fSGustavo F. Padovan 55870a708f8fSGustavo F. Padovan if (skb->len > conn->rx_len) { 55880a708f8fSGustavo F. Padovan BT_ERR("Fragment is too long (len %d, expected %d)", 55890a708f8fSGustavo F. Padovan skb->len, conn->rx_len); 55900a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 55910a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 55920a708f8fSGustavo F. Padovan conn->rx_len = 0; 55930a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 55940a708f8fSGustavo F. Padovan goto drop; 55950a708f8fSGustavo F. Padovan } 55960a708f8fSGustavo F. Padovan 55970a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 55980a708f8fSGustavo F. Padovan skb->len); 55990a708f8fSGustavo F. Padovan conn->rx_len -= skb->len; 56000a708f8fSGustavo F. Padovan 56010a708f8fSGustavo F. Padovan if (!conn->rx_len) { 56020a708f8fSGustavo F. Padovan /* Complete frame received */ 56030a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, conn->rx_skb); 56040a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 56050a708f8fSGustavo F. Padovan } 56060a708f8fSGustavo F. Padovan } 56070a708f8fSGustavo F. Padovan 56080a708f8fSGustavo F. Padovan drop: 56090a708f8fSGustavo F. Padovan kfree_skb(skb); 56100a708f8fSGustavo F. Padovan return 0; 56110a708f8fSGustavo F. Padovan } 56120a708f8fSGustavo F. Padovan 56130a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p) 56140a708f8fSGustavo F. Padovan { 561523691d75SGustavo F. Padovan struct l2cap_chan *c; 56160a708f8fSGustavo F. Padovan 5617333055f2SGustavo F. Padovan read_lock(&chan_list_lock); 56180a708f8fSGustavo F. Padovan 561923691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 562023691d75SGustavo F. Padovan struct sock *sk = c->sk; 56210a708f8fSGustavo F. Padovan 5622903d343eSGustavo F. Padovan seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", 56230a708f8fSGustavo F. Padovan batostr(&bt_sk(sk)->src), 56240a708f8fSGustavo F. Padovan batostr(&bt_sk(sk)->dst), 562589bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm), 562623691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu, 562723691d75SGustavo F. Padovan c->sec_level, c->mode); 56280a708f8fSGustavo F. Padovan } 56290a708f8fSGustavo F. Padovan 5630333055f2SGustavo F. Padovan read_unlock(&chan_list_lock); 56310a708f8fSGustavo F. Padovan 56320a708f8fSGustavo F. Padovan return 0; 56330a708f8fSGustavo F. Padovan } 56340a708f8fSGustavo F. Padovan 56350a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file) 56360a708f8fSGustavo F. Padovan { 56370a708f8fSGustavo F. Padovan return single_open(file, l2cap_debugfs_show, inode->i_private); 56380a708f8fSGustavo F. Padovan } 56390a708f8fSGustavo F. Padovan 56400a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = { 56410a708f8fSGustavo F. Padovan .open = l2cap_debugfs_open, 56420a708f8fSGustavo F. Padovan .read = seq_read, 56430a708f8fSGustavo F. Padovan .llseek = seq_lseek, 56440a708f8fSGustavo F. Padovan .release = single_release, 56450a708f8fSGustavo F. Padovan }; 56460a708f8fSGustavo F. Padovan 56470a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs; 56480a708f8fSGustavo F. Padovan 564964274518SGustavo F. Padovan int __init l2cap_init(void) 56500a708f8fSGustavo F. Padovan { 56510a708f8fSGustavo F. Padovan int err; 56520a708f8fSGustavo F. Padovan 5653bb58f747SGustavo F. Padovan err = l2cap_init_sockets(); 56540a708f8fSGustavo F. Padovan if (err < 0) 56550a708f8fSGustavo F. Padovan return err; 56560a708f8fSGustavo F. Padovan 56570a708f8fSGustavo F. Padovan if (bt_debugfs) { 56580a708f8fSGustavo F. Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, 56590a708f8fSGustavo F. Padovan bt_debugfs, NULL, &l2cap_debugfs_fops); 56600a708f8fSGustavo F. Padovan if (!l2cap_debugfs) 56610a708f8fSGustavo F. Padovan BT_ERR("Failed to create L2CAP debug file"); 56620a708f8fSGustavo F. Padovan } 56630a708f8fSGustavo F. Padovan 56640a708f8fSGustavo F. Padovan return 0; 56650a708f8fSGustavo F. Padovan } 56660a708f8fSGustavo F. Padovan 566764274518SGustavo F. Padovan void l2cap_exit(void) 56680a708f8fSGustavo F. Padovan { 56690a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs); 5670bb58f747SGustavo F. Padovan l2cap_cleanup_sockets(); 56710a708f8fSGustavo F. Padovan } 56720a708f8fSGustavo F. Padovan 56730a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644); 56740a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); 5675