10a708f8fSGustavo F. Padovan /* 20a708f8fSGustavo F. Padovan BlueZ - Bluetooth protocol stack for Linux 30a708f8fSGustavo F. Padovan Copyright (C) 2000-2001 Qualcomm Incorporated 40a708f8fSGustavo F. Padovan Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org> 50a708f8fSGustavo F. Padovan Copyright (C) 2010 Google Inc. 6590051deSGustavo F. Padovan Copyright (C) 2011 ProFUSION Embedded Systems 7422e925bSMat Martineau Copyright (c) 2012 Code Aurora Forum. All rights reserved. 80a708f8fSGustavo F. Padovan 90a708f8fSGustavo F. Padovan Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> 100a708f8fSGustavo F. Padovan 110a708f8fSGustavo F. Padovan This program is free software; you can redistribute it and/or modify 120a708f8fSGustavo F. Padovan it under the terms of the GNU General Public License version 2 as 130a708f8fSGustavo F. Padovan published by the Free Software Foundation; 140a708f8fSGustavo F. Padovan 150a708f8fSGustavo F. Padovan THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 160a708f8fSGustavo F. Padovan OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 170a708f8fSGustavo F. Padovan FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 180a708f8fSGustavo F. Padovan IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 190a708f8fSGustavo F. Padovan CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 200a708f8fSGustavo F. Padovan WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 210a708f8fSGustavo F. Padovan ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 220a708f8fSGustavo F. Padovan OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 230a708f8fSGustavo F. Padovan 240a708f8fSGustavo F. Padovan ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 250a708f8fSGustavo F. Padovan COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 260a708f8fSGustavo F. Padovan SOFTWARE IS DISCLAIMED. 270a708f8fSGustavo F. Padovan */ 280a708f8fSGustavo F. Padovan 29bb58f747SGustavo F. Padovan /* Bluetooth L2CAP core. */ 300a708f8fSGustavo F. Padovan 310a708f8fSGustavo F. Padovan #include <linux/module.h> 320a708f8fSGustavo F. Padovan 330a708f8fSGustavo F. Padovan #include <linux/types.h> 340a708f8fSGustavo F. Padovan #include <linux/capability.h> 350a708f8fSGustavo F. Padovan #include <linux/errno.h> 360a708f8fSGustavo F. Padovan #include <linux/kernel.h> 370a708f8fSGustavo F. Padovan #include <linux/sched.h> 380a708f8fSGustavo F. Padovan #include <linux/slab.h> 390a708f8fSGustavo F. Padovan #include <linux/poll.h> 400a708f8fSGustavo F. Padovan #include <linux/fcntl.h> 410a708f8fSGustavo F. Padovan #include <linux/init.h> 420a708f8fSGustavo F. Padovan #include <linux/interrupt.h> 430a708f8fSGustavo F. Padovan #include <linux/socket.h> 440a708f8fSGustavo F. Padovan #include <linux/skbuff.h> 450a708f8fSGustavo F. Padovan #include <linux/list.h> 460a708f8fSGustavo F. Padovan #include <linux/device.h> 470a708f8fSGustavo F. Padovan #include <linux/debugfs.h> 480a708f8fSGustavo F. Padovan #include <linux/seq_file.h> 490a708f8fSGustavo F. Padovan #include <linux/uaccess.h> 500a708f8fSGustavo F. Padovan #include <linux/crc16.h> 510a708f8fSGustavo F. Padovan #include <net/sock.h> 520a708f8fSGustavo F. Padovan 530a708f8fSGustavo F. Padovan #include <asm/unaligned.h> 540a708f8fSGustavo F. Padovan 550a708f8fSGustavo F. Padovan #include <net/bluetooth/bluetooth.h> 560a708f8fSGustavo F. Padovan #include <net/bluetooth/hci_core.h> 570a708f8fSGustavo F. Padovan #include <net/bluetooth/l2cap.h> 58b501d6a1SAnderson Briglia #include <net/bluetooth/smp.h> 590a708f8fSGustavo F. Padovan 60b191e031SMat Martineau bool disable_ertm = 1; 610a708f8fSGustavo F. Padovan 620a708f8fSGustavo F. Padovan static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; 6350a147cdSMat Martineau static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, }; 640a708f8fSGustavo F. Padovan 65b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list); 66b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock); 670a708f8fSGustavo F. Padovan 680a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 690a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data); 704519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 714519de9aSGustavo F. Padovan void *data); 72710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); 734519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, 744519de9aSGustavo F. Padovan struct l2cap_chan *chan, int err); 750a708f8fSGustavo F. Padovan 76608bcc6dSMat Martineau static int l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 77608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event); 78608bcc6dSMat Martineau 790a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */ 8071ba0e56SGustavo F. Padovan 81baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid) 820a708f8fSGustavo F. Padovan { 833df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 84baa7e1faSGustavo F. Padovan 853df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 863df91ea2SAndrei Emeltchenko if (c->dcid == cid) 873df91ea2SAndrei Emeltchenko return c; 880a708f8fSGustavo F. Padovan } 893df91ea2SAndrei Emeltchenko return NULL; 90baa7e1faSGustavo F. Padovan } 910a708f8fSGustavo F. Padovan 92baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) 930a708f8fSGustavo F. Padovan { 943df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 95baa7e1faSGustavo F. Padovan 963df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 973df91ea2SAndrei Emeltchenko if (c->scid == cid) 983df91ea2SAndrei Emeltchenko return c; 990a708f8fSGustavo F. Padovan } 1003df91ea2SAndrei Emeltchenko return NULL; 101baa7e1faSGustavo F. Padovan } 1020a708f8fSGustavo F. Padovan 1030a708f8fSGustavo F. Padovan /* Find channel with given SCID. 104ef191adeSMat Martineau * Returns locked channel. */ 105baa7e1faSGustavo F. Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) 1060a708f8fSGustavo F. Padovan { 10748454079SGustavo F. Padovan struct l2cap_chan *c; 108baa7e1faSGustavo F. Padovan 1093df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 110baa7e1faSGustavo F. Padovan c = __l2cap_get_chan_by_scid(conn, cid); 111ef191adeSMat Martineau if (c) 112ef191adeSMat Martineau l2cap_chan_lock(c); 1133df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 1143df91ea2SAndrei Emeltchenko 11548454079SGustavo F. Padovan return c; 1160a708f8fSGustavo F. Padovan } 1170a708f8fSGustavo F. Padovan 118baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident) 1190a708f8fSGustavo F. Padovan { 1203df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 121baa7e1faSGustavo F. Padovan 1223df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 1233df91ea2SAndrei Emeltchenko if (c->ident == ident) 1243df91ea2SAndrei Emeltchenko return c; 1250a708f8fSGustavo F. Padovan } 1263df91ea2SAndrei Emeltchenko return NULL; 127baa7e1faSGustavo F. Padovan } 1280a708f8fSGustavo F. Padovan 12923691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src) 1309e4425ffSGustavo F. Padovan { 13123691d75SGustavo F. Padovan struct l2cap_chan *c; 1329e4425ffSGustavo F. Padovan 13323691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 13423691d75SGustavo F. Padovan if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src)) 13523691d75SGustavo F. Padovan return c; 1369e4425ffSGustavo F. Padovan } 137250938cbSSzymon Janc return NULL; 138250938cbSSzymon Janc } 1399e4425ffSGustavo F. Padovan 1409e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) 1419e4425ffSGustavo F. Padovan { 14273b2ec18SGustavo F. Padovan int err; 14373b2ec18SGustavo F. Padovan 144333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 1459e4425ffSGustavo F. Padovan 14623691d75SGustavo F. Padovan if (psm && __l2cap_global_chan_by_addr(psm, src)) { 14773b2ec18SGustavo F. Padovan err = -EADDRINUSE; 14873b2ec18SGustavo F. Padovan goto done; 1499e4425ffSGustavo F. Padovan } 1509e4425ffSGustavo F. Padovan 15173b2ec18SGustavo F. Padovan if (psm) { 1529e4425ffSGustavo F. Padovan chan->psm = psm; 1539e4425ffSGustavo F. Padovan chan->sport = psm; 15473b2ec18SGustavo F. Padovan err = 0; 15573b2ec18SGustavo F. Padovan } else { 15673b2ec18SGustavo F. Padovan u16 p; 1579e4425ffSGustavo F. Padovan 15873b2ec18SGustavo F. Padovan err = -EINVAL; 15973b2ec18SGustavo F. Padovan for (p = 0x1001; p < 0x1100; p += 2) 16023691d75SGustavo F. Padovan if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) { 16173b2ec18SGustavo F. Padovan chan->psm = cpu_to_le16(p); 16273b2ec18SGustavo F. Padovan chan->sport = cpu_to_le16(p); 16373b2ec18SGustavo F. Padovan err = 0; 16473b2ec18SGustavo F. Padovan break; 16573b2ec18SGustavo F. Padovan } 16673b2ec18SGustavo F. Padovan } 16773b2ec18SGustavo F. Padovan 16873b2ec18SGustavo F. Padovan done: 169333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 17073b2ec18SGustavo F. Padovan return err; 1719e4425ffSGustavo F. Padovan } 1729e4425ffSGustavo F. Padovan 1739e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) 1749e4425ffSGustavo F. Padovan { 175333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 1769e4425ffSGustavo F. Padovan 1779e4425ffSGustavo F. Padovan chan->scid = scid; 1789e4425ffSGustavo F. Padovan 179333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 1809e4425ffSGustavo F. Padovan 1819e4425ffSGustavo F. Padovan return 0; 1829e4425ffSGustavo F. Padovan } 1839e4425ffSGustavo F. Padovan 184baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn) 1850a708f8fSGustavo F. Padovan { 1860a708f8fSGustavo F. Padovan u16 cid = L2CAP_CID_DYN_START; 1870a708f8fSGustavo F. Padovan 1880a708f8fSGustavo F. Padovan for (; cid < L2CAP_CID_DYN_END; cid++) { 189baa7e1faSGustavo F. Padovan if (!__l2cap_get_chan_by_scid(conn, cid)) 1900a708f8fSGustavo F. Padovan return cid; 1910a708f8fSGustavo F. Padovan } 1920a708f8fSGustavo F. Padovan 1930a708f8fSGustavo F. Padovan return 0; 1940a708f8fSGustavo F. Padovan } 1950a708f8fSGustavo F. Padovan 1960e587be7SAndrei Emeltchenko static void __l2cap_state_change(struct l2cap_chan *chan, int state) 19789bc500eSGustavo F. Padovan { 19842d2d87cSAndrei Emeltchenko BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state), 199badaaa00SGustavo F. Padovan state_to_string(state)); 200badaaa00SGustavo F. Padovan 20189bc500eSGustavo F. Padovan chan->state = state; 20289bc500eSGustavo F. Padovan chan->ops->state_change(chan->data, state); 20389bc500eSGustavo F. Padovan } 20489bc500eSGustavo F. Padovan 2050e587be7SAndrei Emeltchenko static void l2cap_state_change(struct l2cap_chan *chan, int state) 2060e587be7SAndrei Emeltchenko { 2070e587be7SAndrei Emeltchenko struct sock *sk = chan->sk; 2080e587be7SAndrei Emeltchenko 2090e587be7SAndrei Emeltchenko lock_sock(sk); 2100e587be7SAndrei Emeltchenko __l2cap_state_change(chan, state); 2110e587be7SAndrei Emeltchenko release_sock(sk); 2120e587be7SAndrei Emeltchenko } 2130e587be7SAndrei Emeltchenko 2142e0052e4SAndrei Emeltchenko static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err) 2152e0052e4SAndrei Emeltchenko { 2162e0052e4SAndrei Emeltchenko struct sock *sk = chan->sk; 2172e0052e4SAndrei Emeltchenko 2182e0052e4SAndrei Emeltchenko sk->sk_err = err; 2192e0052e4SAndrei Emeltchenko } 2202e0052e4SAndrei Emeltchenko 2212e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err) 2222e0052e4SAndrei Emeltchenko { 2232e0052e4SAndrei Emeltchenko struct sock *sk = chan->sk; 2242e0052e4SAndrei Emeltchenko 2252e0052e4SAndrei Emeltchenko lock_sock(sk); 2262e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 2272e0052e4SAndrei Emeltchenko release_sock(sk); 2282e0052e4SAndrei Emeltchenko } 2292e0052e4SAndrei Emeltchenko 230608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head, 231608bcc6dSMat Martineau u16 seq) 232608bcc6dSMat Martineau { 233608bcc6dSMat Martineau struct sk_buff *skb; 234608bcc6dSMat Martineau 235608bcc6dSMat Martineau skb_queue_walk(head, skb) { 236608bcc6dSMat Martineau if (bt_cb(skb)->control.txseq == seq) 237608bcc6dSMat Martineau return skb; 238608bcc6dSMat Martineau } 239608bcc6dSMat Martineau 240608bcc6dSMat Martineau return NULL; 241608bcc6dSMat Martineau } 242608bcc6dSMat Martineau 2433c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */ 2443c588192SMat Martineau 2453c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for 2463c588192SMat Martineau * SREJ requests that are received and for frames that are to be 2473c588192SMat Martineau * retransmitted. These seq_list functions implement a singly-linked 2483c588192SMat Martineau * list in an array, where membership in the list can also be checked 2493c588192SMat Martineau * in constant time. Items can also be added to the tail of the list 2503c588192SMat Martineau * and removed from the head in constant time, without further memory 2513c588192SMat Martineau * allocs or frees. 2523c588192SMat Martineau */ 2533c588192SMat Martineau 2543c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size) 2553c588192SMat Martineau { 2563c588192SMat Martineau size_t alloc_size, i; 2573c588192SMat Martineau 2583c588192SMat Martineau /* Allocated size is a power of 2 to map sequence numbers 2593c588192SMat Martineau * (which may be up to 14 bits) in to a smaller array that is 2603c588192SMat Martineau * sized for the negotiated ERTM transmit windows. 2613c588192SMat Martineau */ 2623c588192SMat Martineau alloc_size = roundup_pow_of_two(size); 2633c588192SMat Martineau 2643c588192SMat Martineau seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL); 2653c588192SMat Martineau if (!seq_list->list) 2663c588192SMat Martineau return -ENOMEM; 2673c588192SMat Martineau 2683c588192SMat Martineau seq_list->mask = alloc_size - 1; 2693c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 2703c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 2713c588192SMat Martineau for (i = 0; i < alloc_size; i++) 2723c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 2733c588192SMat Martineau 2743c588192SMat Martineau return 0; 2753c588192SMat Martineau } 2763c588192SMat Martineau 2773c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list) 2783c588192SMat Martineau { 2793c588192SMat Martineau kfree(seq_list->list); 2803c588192SMat Martineau } 2813c588192SMat Martineau 2823c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list, 2833c588192SMat Martineau u16 seq) 2843c588192SMat Martineau { 2853c588192SMat Martineau /* Constant-time check for list membership */ 2863c588192SMat Martineau return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR; 2873c588192SMat Martineau } 2883c588192SMat Martineau 2893c588192SMat Martineau static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq) 2903c588192SMat Martineau { 2913c588192SMat Martineau u16 mask = seq_list->mask; 2923c588192SMat Martineau 2933c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) { 2943c588192SMat Martineau /* In case someone tries to pop the head of an empty list */ 2953c588192SMat Martineau return L2CAP_SEQ_LIST_CLEAR; 2963c588192SMat Martineau } else if (seq_list->head == seq) { 2973c588192SMat Martineau /* Head can be removed in constant time */ 2983c588192SMat Martineau seq_list->head = seq_list->list[seq & mask]; 2993c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; 3003c588192SMat Martineau 3013c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_TAIL) { 3023c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3033c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3043c588192SMat Martineau } 3053c588192SMat Martineau } else { 3063c588192SMat Martineau /* Walk the list to find the sequence number */ 3073c588192SMat Martineau u16 prev = seq_list->head; 3083c588192SMat Martineau while (seq_list->list[prev & mask] != seq) { 3093c588192SMat Martineau prev = seq_list->list[prev & mask]; 3103c588192SMat Martineau if (prev == L2CAP_SEQ_LIST_TAIL) 3113c588192SMat Martineau return L2CAP_SEQ_LIST_CLEAR; 3123c588192SMat Martineau } 3133c588192SMat Martineau 3143c588192SMat Martineau /* Unlink the number from the list and clear it */ 3153c588192SMat Martineau seq_list->list[prev & mask] = seq_list->list[seq & mask]; 3163c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; 3173c588192SMat Martineau if (seq_list->tail == seq) 3183c588192SMat Martineau seq_list->tail = prev; 3193c588192SMat Martineau } 3203c588192SMat Martineau return seq; 3213c588192SMat Martineau } 3223c588192SMat Martineau 3233c588192SMat Martineau static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list) 3243c588192SMat Martineau { 3253c588192SMat Martineau /* Remove the head in constant time */ 3263c588192SMat Martineau return l2cap_seq_list_remove(seq_list, seq_list->head); 3273c588192SMat Martineau } 3283c588192SMat Martineau 3293c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list) 3303c588192SMat Martineau { 3313c588192SMat Martineau u16 i; 332f522ae36SGustavo Padovan 333f522ae36SGustavo Padovan if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) 334f522ae36SGustavo Padovan return; 335f522ae36SGustavo Padovan 3363c588192SMat Martineau for (i = 0; i <= seq_list->mask; i++) 3373c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 3383c588192SMat Martineau 3393c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3403c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3413c588192SMat Martineau } 3423c588192SMat Martineau 3433c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq) 3443c588192SMat Martineau { 3453c588192SMat Martineau u16 mask = seq_list->mask; 3463c588192SMat Martineau 3473c588192SMat Martineau /* All appends happen in constant time */ 3483c588192SMat Martineau 349f522ae36SGustavo Padovan if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR) 350f522ae36SGustavo Padovan return; 351f522ae36SGustavo Padovan 3523c588192SMat Martineau if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR) 3533c588192SMat Martineau seq_list->head = seq; 3543c588192SMat Martineau else 3553c588192SMat Martineau seq_list->list[seq_list->tail & mask] = seq; 3563c588192SMat Martineau 3573c588192SMat Martineau seq_list->tail = seq; 3583c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL; 3593c588192SMat Martineau } 3603c588192SMat Martineau 361721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work) 362ab07801dSGustavo F. Padovan { 363721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 364721c4181SGustavo F. Padovan chan_timer.work); 3653df91ea2SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 366ab07801dSGustavo F. Padovan int reason; 367ab07801dSGustavo F. Padovan 368e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 369ab07801dSGustavo F. Padovan 3703df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 3716be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 372ab07801dSGustavo F. Padovan 37389bc500eSGustavo F. Padovan if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) 374ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 37589bc500eSGustavo F. Padovan else if (chan->state == BT_CONNECT && 376ab07801dSGustavo F. Padovan chan->sec_level != BT_SECURITY_SDP) 377ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 378ab07801dSGustavo F. Padovan else 379ab07801dSGustavo F. Padovan reason = ETIMEDOUT; 380ab07801dSGustavo F. Padovan 3810f852724SGustavo F. Padovan l2cap_chan_close(chan, reason); 382ab07801dSGustavo F. Padovan 3836be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 384ab07801dSGustavo F. Padovan 385ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 3863df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 3873df91ea2SAndrei Emeltchenko 388371fd835SUlisses Furquim l2cap_chan_put(chan); 389ab07801dSGustavo F. Padovan } 390ab07801dSGustavo F. Padovan 391eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void) 3920a708f8fSGustavo F. Padovan { 39348454079SGustavo F. Padovan struct l2cap_chan *chan; 3940a708f8fSGustavo F. Padovan 39548454079SGustavo F. Padovan chan = kzalloc(sizeof(*chan), GFP_ATOMIC); 39648454079SGustavo F. Padovan if (!chan) 39748454079SGustavo F. Padovan return NULL; 3980a708f8fSGustavo F. Padovan 399c03b355eSAndrei Emeltchenko mutex_init(&chan->lock); 400c03b355eSAndrei Emeltchenko 401333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 40223691d75SGustavo F. Padovan list_add(&chan->global_l, &chan_list); 403333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 40423691d75SGustavo F. Padovan 405721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout); 406ab07801dSGustavo F. Padovan 40789bc500eSGustavo F. Padovan chan->state = BT_OPEN; 40889bc500eSGustavo F. Padovan 40971ba0e56SGustavo F. Padovan atomic_set(&chan->refcnt, 1); 41071ba0e56SGustavo F. Padovan 4112827011fSMat Martineau /* This flag is cleared in l2cap_chan_ready() */ 4122827011fSMat Martineau set_bit(CONF_NOT_COMPLETE, &chan->conf_state); 4132827011fSMat Martineau 414eef1d9b6SGustavo Padovan BT_DBG("chan %p", chan); 415abc545b8SSzymon Janc 41648454079SGustavo F. Padovan return chan; 4170a708f8fSGustavo F. Padovan } 4180a708f8fSGustavo F. Padovan 41923691d75SGustavo F. Padovan void l2cap_chan_destroy(struct l2cap_chan *chan) 4206ff5abbfSGustavo F. Padovan { 421333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 42223691d75SGustavo F. Padovan list_del(&chan->global_l); 423333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 42423691d75SGustavo F. Padovan 425371fd835SUlisses Furquim l2cap_chan_put(chan); 4266ff5abbfSGustavo F. Padovan } 4276ff5abbfSGustavo F. Padovan 428bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan) 429bd4b1653SAndrei Emeltchenko { 430bd4b1653SAndrei Emeltchenko chan->fcs = L2CAP_FCS_CRC16; 431bd4b1653SAndrei Emeltchenko chan->max_tx = L2CAP_DEFAULT_MAX_TX; 432bd4b1653SAndrei Emeltchenko chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; 433bd4b1653SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 434bd4b1653SAndrei Emeltchenko chan->sec_level = BT_SECURITY_LOW; 435bd4b1653SAndrei Emeltchenko 436bd4b1653SAndrei Emeltchenko set_bit(FLAG_FORCE_ACTIVE, &chan->flags); 437bd4b1653SAndrei Emeltchenko } 438bd4b1653SAndrei Emeltchenko 43914a28491SAndrei Emeltchenko static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 4400a708f8fSGustavo F. Padovan { 4410a708f8fSGustavo F. Padovan BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, 442097db76cSAndrei Emeltchenko __le16_to_cpu(chan->psm), chan->dcid); 4430a708f8fSGustavo F. Padovan 4449f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 4450a708f8fSGustavo F. Padovan 4468c1d787bSGustavo F. Padovan chan->conn = conn; 4470a708f8fSGustavo F. Padovan 4485491120eSAndrei Emeltchenko switch (chan->chan_type) { 4495491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_ORIENTED: 450b62f328bSVille Tervo if (conn->hcon->type == LE_LINK) { 451b62f328bSVille Tervo /* LE connection */ 4520c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_LE_DEFAULT_MTU; 453fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_LE_DATA; 454fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_LE_DATA; 455b62f328bSVille Tervo } else { 4560a708f8fSGustavo F. Padovan /* Alloc CID for connection-oriented socket */ 457fe4128e0SGustavo F. Padovan chan->scid = l2cap_alloc_cid(conn); 4580c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 459b62f328bSVille Tervo } 4605491120eSAndrei Emeltchenko break; 4615491120eSAndrei Emeltchenko 4625491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_LESS: 4630a708f8fSGustavo F. Padovan /* Connectionless socket */ 464fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_CONN_LESS; 465fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_CONN_LESS; 4660c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 4675491120eSAndrei Emeltchenko break; 4685491120eSAndrei Emeltchenko 4695491120eSAndrei Emeltchenko default: 4700a708f8fSGustavo F. Padovan /* Raw socket can send/recv signalling messages only */ 471fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_SIGNALING; 472fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_SIGNALING; 4730c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 4740a708f8fSGustavo F. Padovan } 4750a708f8fSGustavo F. Padovan 4768f7975b1SAndrei Emeltchenko chan->local_id = L2CAP_BESTEFFORT_ID; 4778f7975b1SAndrei Emeltchenko chan->local_stype = L2CAP_SERV_BESTEFFORT; 4788f7975b1SAndrei Emeltchenko chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE; 4798f7975b1SAndrei Emeltchenko chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME; 4808f7975b1SAndrei Emeltchenko chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT; 4818f7975b1SAndrei Emeltchenko chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO; 4828f7975b1SAndrei Emeltchenko 483371fd835SUlisses Furquim l2cap_chan_hold(chan); 484baa7e1faSGustavo F. Padovan 4853df91ea2SAndrei Emeltchenko list_add(&chan->list, &conn->chan_l); 486643162a8SAndrei Emeltchenko } 487643162a8SAndrei Emeltchenko 48814a28491SAndrei Emeltchenko static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 489643162a8SAndrei Emeltchenko { 490643162a8SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 491643162a8SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 4923df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4930a708f8fSGustavo F. Padovan } 4940a708f8fSGustavo F. Padovan 4954519de9aSGustavo F. Padovan static void l2cap_chan_del(struct l2cap_chan *chan, int err) 4960a708f8fSGustavo F. Padovan { 49748454079SGustavo F. Padovan struct sock *sk = chan->sk; 4988c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 4990a708f8fSGustavo F. Padovan struct sock *parent = bt_sk(sk)->parent; 5000a708f8fSGustavo F. Padovan 501c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 5020a708f8fSGustavo F. Padovan 50349208c9cSGustavo F. Padovan BT_DBG("chan %p, conn %p, err %d", chan, conn, err); 5040a708f8fSGustavo F. Padovan 5050a708f8fSGustavo F. Padovan if (conn) { 506baa7e1faSGustavo F. Padovan /* Delete from channel list */ 5073df91ea2SAndrei Emeltchenko list_del(&chan->list); 5083d57dc68SGustavo F. Padovan 509371fd835SUlisses Furquim l2cap_chan_put(chan); 510baa7e1faSGustavo F. Padovan 5118c1d787bSGustavo F. Padovan chan->conn = NULL; 5120a708f8fSGustavo F. Padovan hci_conn_put(conn->hcon); 5130a708f8fSGustavo F. Padovan } 5140a708f8fSGustavo F. Padovan 5156be36555SAndrei Emeltchenko lock_sock(sk); 5166be36555SAndrei Emeltchenko 5170e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CLOSED); 5180a708f8fSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 5190a708f8fSGustavo F. Padovan 5200a708f8fSGustavo F. Padovan if (err) 5212e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 5220a708f8fSGustavo F. Padovan 5230a708f8fSGustavo F. Padovan if (parent) { 5240a708f8fSGustavo F. Padovan bt_accept_unlink(sk); 5250a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 5260a708f8fSGustavo F. Padovan } else 5270a708f8fSGustavo F. Padovan sk->sk_state_change(sk); 5280a708f8fSGustavo F. Padovan 5296be36555SAndrei Emeltchenko release_sock(sk); 5306be36555SAndrei Emeltchenko 5312827011fSMat Martineau if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) 5326ff5abbfSGustavo F. Padovan return; 5332ead70b8SGustavo F. Padovan 53458d35f87SGustavo F. Padovan skb_queue_purge(&chan->tx_q); 5350a708f8fSGustavo F. Padovan 5360c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_ERTM) { 5371a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 5381a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 5391a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 5400a708f8fSGustavo F. Padovan 541f1c6775bSGustavo F. Padovan skb_queue_purge(&chan->srej_q); 5420a708f8fSGustavo F. Padovan 5433c588192SMat Martineau l2cap_seq_list_free(&chan->srej_list); 5443c588192SMat Martineau l2cap_seq_list_free(&chan->retrans_list); 5450a708f8fSGustavo F. Padovan } 5460a708f8fSGustavo F. Padovan } 5470a708f8fSGustavo F. Padovan 5484519de9aSGustavo F. Padovan static void l2cap_chan_cleanup_listen(struct sock *parent) 5494519de9aSGustavo F. Padovan { 5504519de9aSGustavo F. Padovan struct sock *sk; 5514519de9aSGustavo F. Padovan 5524519de9aSGustavo F. Padovan BT_DBG("parent %p", parent); 5534519de9aSGustavo F. Padovan 5544519de9aSGustavo F. Padovan /* Close not yet accepted channels */ 5550f852724SGustavo F. Padovan while ((sk = bt_accept_dequeue(parent, NULL))) { 556ba3bd0eeSGustavo F. Padovan struct l2cap_chan *chan = l2cap_pi(sk)->chan; 5573df91ea2SAndrei Emeltchenko 5586be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 559c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 560ba3bd0eeSGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 5616be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 5623df91ea2SAndrei Emeltchenko 563ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 5640f852724SGustavo F. Padovan } 5654519de9aSGustavo F. Padovan } 5664519de9aSGustavo F. Padovan 5670f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason) 5684519de9aSGustavo F. Padovan { 5694519de9aSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 5704519de9aSGustavo F. Padovan struct sock *sk = chan->sk; 5714519de9aSGustavo F. Padovan 572e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s sk %p", chan, 573e05dcc32SAndrei Emeltchenko state_to_string(chan->state), sk); 5744519de9aSGustavo F. Padovan 57589bc500eSGustavo F. Padovan switch (chan->state) { 5764519de9aSGustavo F. Padovan case BT_LISTEN: 5776be36555SAndrei Emeltchenko lock_sock(sk); 5784519de9aSGustavo F. Padovan l2cap_chan_cleanup_listen(sk); 57989bc500eSGustavo F. Padovan 5800e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CLOSED); 58189bc500eSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 5826be36555SAndrei Emeltchenko release_sock(sk); 5834519de9aSGustavo F. Padovan break; 5844519de9aSGustavo F. Padovan 5854519de9aSGustavo F. Padovan case BT_CONNECTED: 5864519de9aSGustavo F. Padovan case BT_CONFIG: 587715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && 5884519de9aSGustavo F. Padovan conn->hcon->type == ACL_LINK) { 589c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 5904519de9aSGustavo F. Padovan l2cap_send_disconn_req(conn, chan, reason); 5914519de9aSGustavo F. Padovan } else 5924519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 5934519de9aSGustavo F. Padovan break; 5944519de9aSGustavo F. Padovan 5954519de9aSGustavo F. Padovan case BT_CONNECT2: 596715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && 5974519de9aSGustavo F. Padovan conn->hcon->type == ACL_LINK) { 5984519de9aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 5994519de9aSGustavo F. Padovan __u16 result; 6004519de9aSGustavo F. Padovan 601c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) 6024519de9aSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 6034519de9aSGustavo F. Padovan else 6044519de9aSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 60589bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_DISCONN); 6064519de9aSGustavo F. Padovan 6074519de9aSGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 6084519de9aSGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 6094519de9aSGustavo F. Padovan rsp.result = cpu_to_le16(result); 6104519de9aSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 6114519de9aSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 6124519de9aSGustavo F. Padovan sizeof(rsp), &rsp); 6134519de9aSGustavo F. Padovan } 6144519de9aSGustavo F. Padovan 6154519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 6164519de9aSGustavo F. Padovan break; 6174519de9aSGustavo F. Padovan 6184519de9aSGustavo F. Padovan case BT_CONNECT: 6194519de9aSGustavo F. Padovan case BT_DISCONN: 6204519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 6214519de9aSGustavo F. Padovan break; 6224519de9aSGustavo F. Padovan 6234519de9aSGustavo F. Padovan default: 6246be36555SAndrei Emeltchenko lock_sock(sk); 6254519de9aSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 6266be36555SAndrei Emeltchenko release_sock(sk); 6274519de9aSGustavo F. Padovan break; 6284519de9aSGustavo F. Padovan } 6294519de9aSGustavo F. Padovan } 6304519de9aSGustavo F. Padovan 6314343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) 6320a708f8fSGustavo F. Padovan { 633715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_RAW) { 6344343478fSGustavo F. Padovan switch (chan->sec_level) { 6350a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 6360a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING_MITM; 6370a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 6380a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING; 6390a708f8fSGustavo F. Padovan default: 6400a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 6410a708f8fSGustavo F. Padovan } 642fe4128e0SGustavo F. Padovan } else if (chan->psm == cpu_to_le16(0x0001)) { 6434343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_LOW) 6444343478fSGustavo F. Padovan chan->sec_level = BT_SECURITY_SDP; 6450a708f8fSGustavo F. Padovan 6464343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_HIGH) 6470a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING_MITM; 6480a708f8fSGustavo F. Padovan else 6490a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 6500a708f8fSGustavo F. Padovan } else { 6514343478fSGustavo F. Padovan switch (chan->sec_level) { 6520a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 6530a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING_MITM; 6540a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 6550a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING; 6560a708f8fSGustavo F. Padovan default: 6570a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 6580a708f8fSGustavo F. Padovan } 6590a708f8fSGustavo F. Padovan } 6600a708f8fSGustavo F. Padovan } 6610a708f8fSGustavo F. Padovan 6620a708f8fSGustavo F. Padovan /* Service level security */ 663d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan) 6640a708f8fSGustavo F. Padovan { 6658c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 6660a708f8fSGustavo F. Padovan __u8 auth_type; 6670a708f8fSGustavo F. Padovan 6684343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 6690a708f8fSGustavo F. Padovan 6704343478fSGustavo F. Padovan return hci_conn_security(conn->hcon, chan->sec_level, auth_type); 6710a708f8fSGustavo F. Padovan } 6720a708f8fSGustavo F. Padovan 673b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn) 6740a708f8fSGustavo F. Padovan { 6750a708f8fSGustavo F. Padovan u8 id; 6760a708f8fSGustavo F. Padovan 6770a708f8fSGustavo F. Padovan /* Get next available identificator. 6780a708f8fSGustavo F. Padovan * 1 - 128 are used by kernel. 6790a708f8fSGustavo F. Padovan * 129 - 199 are reserved. 6800a708f8fSGustavo F. Padovan * 200 - 254 are used by utilities like l2ping, etc. 6810a708f8fSGustavo F. Padovan */ 6820a708f8fSGustavo F. Padovan 683333055f2SGustavo F. Padovan spin_lock(&conn->lock); 6840a708f8fSGustavo F. Padovan 6850a708f8fSGustavo F. Padovan if (++conn->tx_ident > 128) 6860a708f8fSGustavo F. Padovan conn->tx_ident = 1; 6870a708f8fSGustavo F. Padovan 6880a708f8fSGustavo F. Padovan id = conn->tx_ident; 6890a708f8fSGustavo F. Padovan 690333055f2SGustavo F. Padovan spin_unlock(&conn->lock); 6910a708f8fSGustavo F. Padovan 6920a708f8fSGustavo F. Padovan return id; 6930a708f8fSGustavo F. Padovan } 6940a708f8fSGustavo F. Padovan 6954519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) 6960a708f8fSGustavo F. Padovan { 6970a708f8fSGustavo F. Padovan struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); 6980a708f8fSGustavo F. Padovan u8 flags; 6990a708f8fSGustavo F. Padovan 7000a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x", code); 7010a708f8fSGustavo F. Padovan 7020a708f8fSGustavo F. Padovan if (!skb) 7030a708f8fSGustavo F. Padovan return; 7040a708f8fSGustavo F. Padovan 7050a708f8fSGustavo F. Padovan if (lmp_no_flush_capable(conn->hcon->hdev)) 7060a708f8fSGustavo F. Padovan flags = ACL_START_NO_FLUSH; 7070a708f8fSGustavo F. Padovan else 7080a708f8fSGustavo F. Padovan flags = ACL_START; 7090a708f8fSGustavo F. Padovan 71014b12d0bSJaikumar Ganesh bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON; 7115e59b791SLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 71214b12d0bSJaikumar Ganesh 71373d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, flags); 7140a708f8fSGustavo F. Padovan } 7150a708f8fSGustavo F. Padovan 71673d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) 71773d80debSLuiz Augusto von Dentz { 71873d80debSLuiz Augusto von Dentz struct hci_conn *hcon = chan->conn->hcon; 71973d80debSLuiz Augusto von Dentz u16 flags; 72073d80debSLuiz Augusto von Dentz 72173d80debSLuiz Augusto von Dentz BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, 72273d80debSLuiz Augusto von Dentz skb->priority); 72373d80debSLuiz Augusto von Dentz 72473d80debSLuiz Augusto von Dentz if (!test_bit(FLAG_FLUSHABLE, &chan->flags) && 72573d80debSLuiz Augusto von Dentz lmp_no_flush_capable(hcon->hdev)) 72673d80debSLuiz Augusto von Dentz flags = ACL_START_NO_FLUSH; 72773d80debSLuiz Augusto von Dentz else 72873d80debSLuiz Augusto von Dentz flags = ACL_START; 72973d80debSLuiz Augusto von Dentz 73073d80debSLuiz Augusto von Dentz bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); 73173d80debSLuiz Augusto von Dentz hci_send_acl(chan->conn->hchan, skb, flags); 7320a708f8fSGustavo F. Padovan } 7330a708f8fSGustavo F. Padovan 734b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control) 735b5c6aaedSMat Martineau { 736b5c6aaedSMat Martineau control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT; 737b5c6aaedSMat Martineau control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT; 738b5c6aaedSMat Martineau 739b5c6aaedSMat Martineau if (enh & L2CAP_CTRL_FRAME_TYPE) { 740b5c6aaedSMat Martineau /* S-Frame */ 741b5c6aaedSMat Martineau control->sframe = 1; 742b5c6aaedSMat Martineau control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT; 743b5c6aaedSMat Martineau control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT; 744b5c6aaedSMat Martineau 745b5c6aaedSMat Martineau control->sar = 0; 746b5c6aaedSMat Martineau control->txseq = 0; 747b5c6aaedSMat Martineau } else { 748b5c6aaedSMat Martineau /* I-Frame */ 749b5c6aaedSMat Martineau control->sframe = 0; 750b5c6aaedSMat Martineau control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT; 751b5c6aaedSMat Martineau control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT; 752b5c6aaedSMat Martineau 753b5c6aaedSMat Martineau control->poll = 0; 754b5c6aaedSMat Martineau control->super = 0; 755b5c6aaedSMat Martineau } 756b5c6aaedSMat Martineau } 757b5c6aaedSMat Martineau 758b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control) 759b5c6aaedSMat Martineau { 760b5c6aaedSMat Martineau control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT; 761b5c6aaedSMat Martineau control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT; 762b5c6aaedSMat Martineau 763b5c6aaedSMat Martineau if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) { 764b5c6aaedSMat Martineau /* S-Frame */ 765b5c6aaedSMat Martineau control->sframe = 1; 766b5c6aaedSMat Martineau control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT; 767b5c6aaedSMat Martineau control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT; 768b5c6aaedSMat Martineau 769b5c6aaedSMat Martineau control->sar = 0; 770b5c6aaedSMat Martineau control->txseq = 0; 771b5c6aaedSMat Martineau } else { 772b5c6aaedSMat Martineau /* I-Frame */ 773b5c6aaedSMat Martineau control->sframe = 0; 774b5c6aaedSMat Martineau control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT; 775b5c6aaedSMat Martineau control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT; 776b5c6aaedSMat Martineau 777b5c6aaedSMat Martineau control->poll = 0; 778b5c6aaedSMat Martineau control->super = 0; 779b5c6aaedSMat Martineau } 780b5c6aaedSMat Martineau } 781b5c6aaedSMat Martineau 782b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan, 783b5c6aaedSMat Martineau struct sk_buff *skb) 784b5c6aaedSMat Martineau { 785b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 786b5c6aaedSMat Martineau __unpack_extended_control(get_unaligned_le32(skb->data), 787b5c6aaedSMat Martineau &bt_cb(skb)->control); 788cec8ab6eSMat Martineau skb_pull(skb, L2CAP_EXT_CTRL_SIZE); 789b5c6aaedSMat Martineau } else { 790b5c6aaedSMat Martineau __unpack_enhanced_control(get_unaligned_le16(skb->data), 791b5c6aaedSMat Martineau &bt_cb(skb)->control); 792cec8ab6eSMat Martineau skb_pull(skb, L2CAP_ENH_CTRL_SIZE); 793b5c6aaedSMat Martineau } 794b5c6aaedSMat Martineau } 795b5c6aaedSMat Martineau 796b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control) 797b5c6aaedSMat Martineau { 798b5c6aaedSMat Martineau u32 packed; 799b5c6aaedSMat Martineau 800b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT; 801b5c6aaedSMat Martineau packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT; 802b5c6aaedSMat Martineau 803b5c6aaedSMat Martineau if (control->sframe) { 804b5c6aaedSMat Martineau packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT; 805b5c6aaedSMat Martineau packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT; 806b5c6aaedSMat Martineau packed |= L2CAP_EXT_CTRL_FRAME_TYPE; 807b5c6aaedSMat Martineau } else { 808b5c6aaedSMat Martineau packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT; 809b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT; 810b5c6aaedSMat Martineau } 811b5c6aaedSMat Martineau 812b5c6aaedSMat Martineau return packed; 813b5c6aaedSMat Martineau } 814b5c6aaedSMat Martineau 815b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control) 816b5c6aaedSMat Martineau { 817b5c6aaedSMat Martineau u16 packed; 818b5c6aaedSMat Martineau 819b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT; 820b5c6aaedSMat Martineau packed |= control->final << L2CAP_CTRL_FINAL_SHIFT; 821b5c6aaedSMat Martineau 822b5c6aaedSMat Martineau if (control->sframe) { 823b5c6aaedSMat Martineau packed |= control->poll << L2CAP_CTRL_POLL_SHIFT; 824b5c6aaedSMat Martineau packed |= control->super << L2CAP_CTRL_SUPER_SHIFT; 825b5c6aaedSMat Martineau packed |= L2CAP_CTRL_FRAME_TYPE; 826b5c6aaedSMat Martineau } else { 827b5c6aaedSMat Martineau packed |= control->sar << L2CAP_CTRL_SAR_SHIFT; 828b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT; 829b5c6aaedSMat Martineau } 830b5c6aaedSMat Martineau 831b5c6aaedSMat Martineau return packed; 832b5c6aaedSMat Martineau } 833b5c6aaedSMat Martineau 834b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan, 835b5c6aaedSMat Martineau struct l2cap_ctrl *control, 836b5c6aaedSMat Martineau struct sk_buff *skb) 837b5c6aaedSMat Martineau { 838b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 839b5c6aaedSMat Martineau put_unaligned_le32(__pack_extended_control(control), 840b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 841b5c6aaedSMat Martineau } else { 842b5c6aaedSMat Martineau put_unaligned_le16(__pack_enhanced_control(control), 843b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 844b5c6aaedSMat Martineau } 845b5c6aaedSMat Martineau } 846b5c6aaedSMat Martineau 847a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan, 848a67d7f6fSMat Martineau u32 control) 8490a708f8fSGustavo F. Padovan { 8500a708f8fSGustavo F. Padovan struct sk_buff *skb; 8510a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 852a67d7f6fSMat Martineau int hlen; 8530a708f8fSGustavo F. Padovan 854e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 855e4ca6d98SAndrei Emeltchenko hlen = L2CAP_EXT_HDR_SIZE; 856e4ca6d98SAndrei Emeltchenko else 857e4ca6d98SAndrei Emeltchenko hlen = L2CAP_ENH_HDR_SIZE; 8580a708f8fSGustavo F. Padovan 8590a708f8fSGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 86003a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 8610a708f8fSGustavo F. Padovan 862a67d7f6fSMat Martineau skb = bt_skb_alloc(hlen, GFP_KERNEL); 8630a708f8fSGustavo F. Padovan 8640a708f8fSGustavo F. Padovan if (!skb) 865a67d7f6fSMat Martineau return ERR_PTR(-ENOMEM); 8660a708f8fSGustavo F. Padovan 8670a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 8680a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); 869fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 87088843ab0SAndrei Emeltchenko 871a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 872a67d7f6fSMat Martineau put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 873a67d7f6fSMat Martineau else 874a67d7f6fSMat Martineau put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 8750a708f8fSGustavo F. Padovan 87647d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 877a67d7f6fSMat Martineau u16 fcs = crc16(0, (u8 *)skb->data, skb->len); 87803a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 8790a708f8fSGustavo F. Padovan } 8800a708f8fSGustavo F. Padovan 88173d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 882a67d7f6fSMat Martineau return skb; 883a67d7f6fSMat Martineau } 884a67d7f6fSMat Martineau 885a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan, 886a67d7f6fSMat Martineau struct l2cap_ctrl *control) 887a67d7f6fSMat Martineau { 888a67d7f6fSMat Martineau struct sk_buff *skb; 889a67d7f6fSMat Martineau u32 control_field; 890a67d7f6fSMat Martineau 891a67d7f6fSMat Martineau BT_DBG("chan %p, control %p", chan, control); 892a67d7f6fSMat Martineau 893a67d7f6fSMat Martineau if (!control->sframe) 894a67d7f6fSMat Martineau return; 895a67d7f6fSMat Martineau 896a67d7f6fSMat Martineau if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) && 897a67d7f6fSMat Martineau !control->poll) 898a67d7f6fSMat Martineau control->final = 1; 899a67d7f6fSMat Martineau 900a67d7f6fSMat Martineau if (control->super == L2CAP_SUPER_RR) 901a67d7f6fSMat Martineau clear_bit(CONN_RNR_SENT, &chan->conn_state); 902a67d7f6fSMat Martineau else if (control->super == L2CAP_SUPER_RNR) 903a67d7f6fSMat Martineau set_bit(CONN_RNR_SENT, &chan->conn_state); 904a67d7f6fSMat Martineau 905a67d7f6fSMat Martineau if (control->super != L2CAP_SUPER_SREJ) { 906a67d7f6fSMat Martineau chan->last_acked_seq = control->reqseq; 907a67d7f6fSMat Martineau __clear_ack_timer(chan); 908a67d7f6fSMat Martineau } 909a67d7f6fSMat Martineau 910a67d7f6fSMat Martineau BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq, 911a67d7f6fSMat Martineau control->final, control->poll, control->super); 912a67d7f6fSMat Martineau 913a67d7f6fSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 914a67d7f6fSMat Martineau control_field = __pack_extended_control(control); 915a67d7f6fSMat Martineau else 916a67d7f6fSMat Martineau control_field = __pack_enhanced_control(control); 917a67d7f6fSMat Martineau 918a67d7f6fSMat Martineau skb = l2cap_create_sframe_pdu(chan, control_field); 919a67d7f6fSMat Martineau if (!IS_ERR(skb)) 92073d80debSLuiz Augusto von Dentz l2cap_do_send(chan, skb); 9210a708f8fSGustavo F. Padovan } 9220a708f8fSGustavo F. Padovan 92388843ab0SAndrei Emeltchenko static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control) 9240a708f8fSGustavo F. Padovan { 925e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 926ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); 927e2ab4353SGustavo F. Padovan set_bit(CONN_RNR_SENT, &chan->conn_state); 9280a708f8fSGustavo F. Padovan } else 929ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 9300a708f8fSGustavo F. Padovan 9310b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 9320a708f8fSGustavo F. Padovan } 9330a708f8fSGustavo F. Padovan 934b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) 9350a708f8fSGustavo F. Padovan { 936c1360a1cSGustavo F. Padovan return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); 9370a708f8fSGustavo F. Padovan } 9380a708f8fSGustavo F. Padovan 9399b27f350SAndrei Emeltchenko static void l2cap_send_conn_req(struct l2cap_chan *chan) 9409b27f350SAndrei Emeltchenko { 9419b27f350SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 9429b27f350SAndrei Emeltchenko struct l2cap_conn_req req; 9439b27f350SAndrei Emeltchenko 9449b27f350SAndrei Emeltchenko req.scid = cpu_to_le16(chan->scid); 9459b27f350SAndrei Emeltchenko req.psm = chan->psm; 9469b27f350SAndrei Emeltchenko 9479b27f350SAndrei Emeltchenko chan->ident = l2cap_get_ident(conn); 9489b27f350SAndrei Emeltchenko 9499b27f350SAndrei Emeltchenko set_bit(CONF_CONNECT_PEND, &chan->conf_state); 9509b27f350SAndrei Emeltchenko 9519b27f350SAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); 9529b27f350SAndrei Emeltchenko } 9539b27f350SAndrei Emeltchenko 9549f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan) 9559f0caeb1SVinicius Costa Gomes { 9569f0caeb1SVinicius Costa Gomes struct sock *sk = chan->sk; 9579f0caeb1SVinicius Costa Gomes struct sock *parent; 9589f0caeb1SVinicius Costa Gomes 9599f0caeb1SVinicius Costa Gomes lock_sock(sk); 9609f0caeb1SVinicius Costa Gomes 9619f0caeb1SVinicius Costa Gomes parent = bt_sk(sk)->parent; 9629f0caeb1SVinicius Costa Gomes 9639f0caeb1SVinicius Costa Gomes BT_DBG("sk %p, parent %p", sk, parent); 9649f0caeb1SVinicius Costa Gomes 9652827011fSMat Martineau /* This clears all conf flags, including CONF_NOT_COMPLETE */ 9669f0caeb1SVinicius Costa Gomes chan->conf_state = 0; 9679f0caeb1SVinicius Costa Gomes __clear_chan_timer(chan); 9689f0caeb1SVinicius Costa Gomes 9699f0caeb1SVinicius Costa Gomes __l2cap_state_change(chan, BT_CONNECTED); 9709f0caeb1SVinicius Costa Gomes sk->sk_state_change(sk); 9719f0caeb1SVinicius Costa Gomes 9729f0caeb1SVinicius Costa Gomes if (parent) 9739f0caeb1SVinicius Costa Gomes parent->sk_data_ready(parent, 0); 9749f0caeb1SVinicius Costa Gomes 9759f0caeb1SVinicius Costa Gomes release_sock(sk); 9769f0caeb1SVinicius Costa Gomes } 9779f0caeb1SVinicius Costa Gomes 978fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan) 9790a708f8fSGustavo F. Padovan { 9808c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 9810a708f8fSGustavo F. Padovan 9829f0caeb1SVinicius Costa Gomes if (conn->hcon->type == LE_LINK) { 9839f0caeb1SVinicius Costa Gomes l2cap_chan_ready(chan); 9849f0caeb1SVinicius Costa Gomes return; 9859f0caeb1SVinicius Costa Gomes } 9869f0caeb1SVinicius Costa Gomes 9870a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { 9880a708f8fSGustavo F. Padovan if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) 9890a708f8fSGustavo F. Padovan return; 9900a708f8fSGustavo F. Padovan 991d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan) && 9929b27f350SAndrei Emeltchenko __l2cap_no_conn_pending(chan)) 9939b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 9940a708f8fSGustavo F. Padovan } else { 9950a708f8fSGustavo F. Padovan struct l2cap_info_req req; 9960a708f8fSGustavo F. Padovan req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 9970a708f8fSGustavo F. Padovan 9980a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 9990a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 10000a708f8fSGustavo F. Padovan 1001ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 10020a708f8fSGustavo F. Padovan 10030a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 10040a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 10050a708f8fSGustavo F. Padovan } 10060a708f8fSGustavo F. Padovan } 10070a708f8fSGustavo F. Padovan 10080a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) 10090a708f8fSGustavo F. Padovan { 10100a708f8fSGustavo F. Padovan u32 local_feat_mask = l2cap_feat_mask; 10110a708f8fSGustavo F. Padovan if (!disable_ertm) 10120a708f8fSGustavo F. Padovan local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING; 10130a708f8fSGustavo F. Padovan 10140a708f8fSGustavo F. Padovan switch (mode) { 10150a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 10160a708f8fSGustavo F. Padovan return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask; 10170a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 10180a708f8fSGustavo F. Padovan return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask; 10190a708f8fSGustavo F. Padovan default: 10200a708f8fSGustavo F. Padovan return 0x00; 10210a708f8fSGustavo F. Padovan } 10220a708f8fSGustavo F. Padovan } 10230a708f8fSGustavo F. Padovan 10244519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err) 10250a708f8fSGustavo F. Padovan { 10266be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 10270a708f8fSGustavo F. Padovan struct l2cap_disconn_req req; 10280a708f8fSGustavo F. Padovan 10290a708f8fSGustavo F. Padovan if (!conn) 10300a708f8fSGustavo F. Padovan return; 10310a708f8fSGustavo F. Padovan 10320c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_ERTM) { 10331a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 10341a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 10351a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 10360a708f8fSGustavo F. Padovan } 10370a708f8fSGustavo F. Padovan 1038fe4128e0SGustavo F. Padovan req.dcid = cpu_to_le16(chan->dcid); 1039fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 10400a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 10410a708f8fSGustavo F. Padovan L2CAP_DISCONN_REQ, sizeof(req), &req); 10420a708f8fSGustavo F. Padovan 10436be36555SAndrei Emeltchenko lock_sock(sk); 10440e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_DISCONN); 10452e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 10466be36555SAndrei Emeltchenko release_sock(sk); 10470a708f8fSGustavo F. Padovan } 10480a708f8fSGustavo F. Padovan 10490a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */ 10500a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn) 10510a708f8fSGustavo F. Padovan { 10523df91ea2SAndrei Emeltchenko struct l2cap_chan *chan, *tmp; 10530a708f8fSGustavo F. Padovan 10540a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 10550a708f8fSGustavo F. Padovan 10563df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 10570a708f8fSGustavo F. Padovan 10583df91ea2SAndrei Emeltchenko list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 105948454079SGustavo F. Padovan struct sock *sk = chan->sk; 1060baa7e1faSGustavo F. Padovan 10616be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 10620a708f8fSGustavo F. Padovan 1063715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 10646be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10650a708f8fSGustavo F. Padovan continue; 10660a708f8fSGustavo F. Padovan } 10670a708f8fSGustavo F. Padovan 106889bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 1069d45fc423SGustavo F. Padovan if (!l2cap_chan_check_security(chan) || 1070b4450035SGustavo F. Padovan !__l2cap_no_conn_pending(chan)) { 10716be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10720a708f8fSGustavo F. Padovan continue; 10730a708f8fSGustavo F. Padovan } 10740a708f8fSGustavo F. Padovan 1075c1360a1cSGustavo F. Padovan if (!l2cap_mode_supported(chan->mode, conn->feat_mask) 1076c1360a1cSGustavo F. Padovan && test_bit(CONF_STATE2_DEVICE, 1077c1360a1cSGustavo F. Padovan &chan->conf_state)) { 10780f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 10796be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10800a708f8fSGustavo F. Padovan continue; 10810a708f8fSGustavo F. Padovan } 10820a708f8fSGustavo F. Padovan 10839b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 10840a708f8fSGustavo F. Padovan 108589bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 10860a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 10870a708f8fSGustavo F. Padovan char buf[128]; 1088fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 1089fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 10900a708f8fSGustavo F. Padovan 1091d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 10926be36555SAndrei Emeltchenko lock_sock(sk); 1093c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, 1094c5daa683SGustavo Padovan &bt_sk(sk)->flags)) { 10950a708f8fSGustavo F. Padovan struct sock *parent = bt_sk(sk)->parent; 10960a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_PEND); 10970a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND); 109805e9a2f6SIlia Kolomisnky if (parent) 10990a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 11000a708f8fSGustavo F. Padovan 11010a708f8fSGustavo F. Padovan } else { 11020e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 11030a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 11040a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 11050a708f8fSGustavo F. Padovan } 11066be36555SAndrei Emeltchenko release_sock(sk); 11070a708f8fSGustavo F. Padovan } else { 11080a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_PEND); 11090a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND); 11100a708f8fSGustavo F. Padovan } 11110a708f8fSGustavo F. Padovan 1112fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 1113fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 11140a708f8fSGustavo F. Padovan 1115c1360a1cSGustavo F. Padovan if (test_bit(CONF_REQ_SENT, &chan->conf_state) || 11160a708f8fSGustavo F. Padovan rsp.result != L2CAP_CR_SUCCESS) { 11176be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 11180a708f8fSGustavo F. Padovan continue; 11190a708f8fSGustavo F. Padovan } 11200a708f8fSGustavo F. Padovan 1121c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 11220a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 112373ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 112473ffa904SGustavo F. Padovan chan->num_conf_req++; 11250a708f8fSGustavo F. Padovan } 11260a708f8fSGustavo F. Padovan 11276be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 11280a708f8fSGustavo F. Padovan } 11290a708f8fSGustavo F. Padovan 11303df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 11310a708f8fSGustavo F. Padovan } 11320a708f8fSGustavo F. Padovan 1133c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr. 1134b62f328bSVille Tervo * Returns closest match, locked. 1135b62f328bSVille Tervo */ 1136d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, 1137c2287681SIdo Yariv bdaddr_t *src, 1138c2287681SIdo Yariv bdaddr_t *dst) 1139b62f328bSVille Tervo { 114023691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 1141b62f328bSVille Tervo 114223691d75SGustavo F. Padovan read_lock(&chan_list_lock); 1143b62f328bSVille Tervo 114423691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 114523691d75SGustavo F. Padovan struct sock *sk = c->sk; 1146fe4128e0SGustavo F. Padovan 114789bc500eSGustavo F. Padovan if (state && c->state != state) 1148b62f328bSVille Tervo continue; 1149b62f328bSVille Tervo 115023691d75SGustavo F. Padovan if (c->scid == cid) { 1151c2287681SIdo Yariv int src_match, dst_match; 1152c2287681SIdo Yariv int src_any, dst_any; 1153c2287681SIdo Yariv 1154b62f328bSVille Tervo /* Exact match. */ 1155c2287681SIdo Yariv src_match = !bacmp(&bt_sk(sk)->src, src); 1156c2287681SIdo Yariv dst_match = !bacmp(&bt_sk(sk)->dst, dst); 1157c2287681SIdo Yariv if (src_match && dst_match) { 115823691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 115923691d75SGustavo F. Padovan return c; 116023691d75SGustavo F. Padovan } 1161b62f328bSVille Tervo 1162b62f328bSVille Tervo /* Closest match */ 1163c2287681SIdo Yariv src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY); 1164c2287681SIdo Yariv dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY); 1165c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1166c2287681SIdo Yariv (src_any && dst_any)) 116723691d75SGustavo F. Padovan c1 = c; 1168b62f328bSVille Tervo } 1169b62f328bSVille Tervo } 1170280f294fSGustavo F. Padovan 117123691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 1172b62f328bSVille Tervo 117323691d75SGustavo F. Padovan return c1; 1174b62f328bSVille Tervo } 1175b62f328bSVille Tervo 1176b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn) 1177b62f328bSVille Tervo { 1178c916fbe4SGustavo F. Padovan struct sock *parent, *sk; 117923691d75SGustavo F. Padovan struct l2cap_chan *chan, *pchan; 1180b62f328bSVille Tervo 1181b62f328bSVille Tervo BT_DBG(""); 1182b62f328bSVille Tervo 1183b62f328bSVille Tervo /* Check if we have socket listening on cid */ 118423691d75SGustavo F. Padovan pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA, 1185c2287681SIdo Yariv conn->src, conn->dst); 118623691d75SGustavo F. Padovan if (!pchan) 1187b62f328bSVille Tervo return; 1188b62f328bSVille Tervo 118923691d75SGustavo F. Padovan parent = pchan->sk; 119023691d75SGustavo F. Padovan 1191aa2ac881SGustavo F. Padovan lock_sock(parent); 119262f3a2cfSGustavo F. Padovan 1193b62f328bSVille Tervo /* Check for backlog size */ 1194b62f328bSVille Tervo if (sk_acceptq_is_full(parent)) { 1195b62f328bSVille Tervo BT_DBG("backlog full %d", parent->sk_ack_backlog); 1196b62f328bSVille Tervo goto clean; 1197b62f328bSVille Tervo } 1198b62f328bSVille Tervo 119980808e43SGustavo F. Padovan chan = pchan->ops->new_connection(pchan->data); 120080808e43SGustavo F. Padovan if (!chan) 1201b62f328bSVille Tervo goto clean; 1202b62f328bSVille Tervo 120380808e43SGustavo F. Padovan sk = chan->sk; 12045d41ce1dSGustavo F. Padovan 1205b62f328bSVille Tervo hci_conn_hold(conn->hcon); 1206b62f328bSVille Tervo 1207b62f328bSVille Tervo bacpy(&bt_sk(sk)->src, conn->src); 1208b62f328bSVille Tervo bacpy(&bt_sk(sk)->dst, conn->dst); 1209b62f328bSVille Tervo 1210d1010240SGustavo F. Padovan bt_accept_enqueue(parent, sk); 1211d1010240SGustavo F. Padovan 12123d57dc68SGustavo F. Padovan l2cap_chan_add(conn, chan); 121348454079SGustavo F. Padovan 1214c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 1215b62f328bSVille Tervo 12160e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECTED); 1217b62f328bSVille Tervo parent->sk_data_ready(parent, 0); 1218b62f328bSVille Tervo 1219b62f328bSVille Tervo clean: 1220aa2ac881SGustavo F. Padovan release_sock(parent); 1221b62f328bSVille Tervo } 1222b62f328bSVille Tervo 12230a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn) 12240a708f8fSGustavo F. Padovan { 122548454079SGustavo F. Padovan struct l2cap_chan *chan; 12260a708f8fSGustavo F. Padovan 12270a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 12280a708f8fSGustavo F. Padovan 1229b62f328bSVille Tervo if (!conn->hcon->out && conn->hcon->type == LE_LINK) 1230b62f328bSVille Tervo l2cap_le_conn_ready(conn); 1231b62f328bSVille Tervo 1232160dc6acSVinicius Costa Gomes if (conn->hcon->out && conn->hcon->type == LE_LINK) 1233160dc6acSVinicius Costa Gomes smp_conn_security(conn, conn->hcon->pending_sec_level); 1234160dc6acSVinicius Costa Gomes 12353df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 12360a708f8fSGustavo F. Padovan 12373df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1238baa7e1faSGustavo F. Padovan 12396be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 12400a708f8fSGustavo F. Padovan 124163128451SVinicius Costa Gomes if (conn->hcon->type == LE_LINK) { 1242b501d6a1SAnderson Briglia if (smp_conn_security(conn, chan->sec_level)) 1243cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 1244acd7d370SVille Tervo 124563128451SVinicius Costa Gomes } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 12466be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 1247c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 12486be36555SAndrei Emeltchenko lock_sock(sk); 12490e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECTED); 12500a708f8fSGustavo F. Padovan sk->sk_state_change(sk); 12516be36555SAndrei Emeltchenko release_sock(sk); 1252b501d6a1SAnderson Briglia 125389bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT) 1254fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 12550a708f8fSGustavo F. Padovan 12566be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 12570a708f8fSGustavo F. Padovan } 12580a708f8fSGustavo F. Padovan 12593df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 12600a708f8fSGustavo F. Padovan } 12610a708f8fSGustavo F. Padovan 12620a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */ 12630a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) 12640a708f8fSGustavo F. Padovan { 126548454079SGustavo F. Padovan struct l2cap_chan *chan; 12660a708f8fSGustavo F. Padovan 12670a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 12680a708f8fSGustavo F. Padovan 12693df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 12700a708f8fSGustavo F. Padovan 12713df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1272ecf61bdbSAndrei Emeltchenko if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) 12732e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 12740a708f8fSGustavo F. Padovan } 12750a708f8fSGustavo F. Padovan 12763df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 12770a708f8fSGustavo F. Padovan } 12780a708f8fSGustavo F. Padovan 1279f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work) 12800a708f8fSGustavo F. Padovan { 1281f878fcadSGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 1282030013d8SGustavo F. Padovan info_timer.work); 12830a708f8fSGustavo F. Padovan 12840a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 12850a708f8fSGustavo F. Padovan conn->info_ident = 0; 12860a708f8fSGustavo F. Padovan 12870a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 12880a708f8fSGustavo F. Padovan } 12890a708f8fSGustavo F. Padovan 12905d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err) 12915d3de7dfSVinicius Costa Gomes { 12925d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 12935d3de7dfSVinicius Costa Gomes struct l2cap_chan *chan, *l; 12945d3de7dfSVinicius Costa Gomes 12955d3de7dfSVinicius Costa Gomes if (!conn) 12965d3de7dfSVinicius Costa Gomes return; 12975d3de7dfSVinicius Costa Gomes 12985d3de7dfSVinicius Costa Gomes BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); 12995d3de7dfSVinicius Costa Gomes 13005d3de7dfSVinicius Costa Gomes kfree_skb(conn->rx_skb); 13015d3de7dfSVinicius Costa Gomes 13023df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 13033df91ea2SAndrei Emeltchenko 13045d3de7dfSVinicius Costa Gomes /* Kill channels */ 13055d3de7dfSVinicius Costa Gomes list_for_each_entry_safe(chan, l, &conn->chan_l, list) { 130661d6ef3eSMat Martineau l2cap_chan_hold(chan); 13076be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 13086be36555SAndrei Emeltchenko 13095d3de7dfSVinicius Costa Gomes l2cap_chan_del(chan, err); 13106be36555SAndrei Emeltchenko 13116be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 13126be36555SAndrei Emeltchenko 13135d3de7dfSVinicius Costa Gomes chan->ops->close(chan->data); 131461d6ef3eSMat Martineau l2cap_chan_put(chan); 13155d3de7dfSVinicius Costa Gomes } 13165d3de7dfSVinicius Costa Gomes 13173df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 13183df91ea2SAndrei Emeltchenko 131973d80debSLuiz Augusto von Dentz hci_chan_del(conn->hchan); 132073d80debSLuiz Augusto von Dentz 13215d3de7dfSVinicius Costa Gomes if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1322127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->info_timer); 13235d3de7dfSVinicius Costa Gomes 132451a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) { 1325127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->security_timer); 13268aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 1327d26a2345SVinicius Costa Gomes } 13285d3de7dfSVinicius Costa Gomes 13295d3de7dfSVinicius Costa Gomes hcon->l2cap_data = NULL; 13305d3de7dfSVinicius Costa Gomes kfree(conn); 13315d3de7dfSVinicius Costa Gomes } 13325d3de7dfSVinicius Costa Gomes 13336c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work) 13345d3de7dfSVinicius Costa Gomes { 13356c9d42a1SGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 13366c9d42a1SGustavo F. Padovan security_timer.work); 13375d3de7dfSVinicius Costa Gomes 13385d3de7dfSVinicius Costa Gomes l2cap_conn_del(conn->hcon, ETIMEDOUT); 13395d3de7dfSVinicius Costa Gomes } 13405d3de7dfSVinicius Costa Gomes 13410a708f8fSGustavo F. Padovan static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) 13420a708f8fSGustavo F. Padovan { 13430a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 134473d80debSLuiz Augusto von Dentz struct hci_chan *hchan; 13450a708f8fSGustavo F. Padovan 13460a708f8fSGustavo F. Padovan if (conn || status) 13470a708f8fSGustavo F. Padovan return conn; 13480a708f8fSGustavo F. Padovan 134973d80debSLuiz Augusto von Dentz hchan = hci_chan_create(hcon); 135073d80debSLuiz Augusto von Dentz if (!hchan) 13510a708f8fSGustavo F. Padovan return NULL; 13520a708f8fSGustavo F. Padovan 135373d80debSLuiz Augusto von Dentz conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC); 135473d80debSLuiz Augusto von Dentz if (!conn) { 135573d80debSLuiz Augusto von Dentz hci_chan_del(hchan); 135673d80debSLuiz Augusto von Dentz return NULL; 135773d80debSLuiz Augusto von Dentz } 135873d80debSLuiz Augusto von Dentz 13590a708f8fSGustavo F. Padovan hcon->l2cap_data = conn; 13600a708f8fSGustavo F. Padovan conn->hcon = hcon; 136173d80debSLuiz Augusto von Dentz conn->hchan = hchan; 13620a708f8fSGustavo F. Padovan 136373d80debSLuiz Augusto von Dentz BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); 13640a708f8fSGustavo F. Padovan 1365acd7d370SVille Tervo if (hcon->hdev->le_mtu && hcon->type == LE_LINK) 1366acd7d370SVille Tervo conn->mtu = hcon->hdev->le_mtu; 1367acd7d370SVille Tervo else 13680a708f8fSGustavo F. Padovan conn->mtu = hcon->hdev->acl_mtu; 1369acd7d370SVille Tervo 13700a708f8fSGustavo F. Padovan conn->src = &hcon->hdev->bdaddr; 13710a708f8fSGustavo F. Padovan conn->dst = &hcon->dst; 13720a708f8fSGustavo F. Padovan 13730a708f8fSGustavo F. Padovan conn->feat_mask = 0; 13740a708f8fSGustavo F. Padovan 13750a708f8fSGustavo F. Padovan spin_lock_init(&conn->lock); 13763df91ea2SAndrei Emeltchenko mutex_init(&conn->chan_lock); 1377baa7e1faSGustavo F. Padovan 1378baa7e1faSGustavo F. Padovan INIT_LIST_HEAD(&conn->chan_l); 13790a708f8fSGustavo F. Padovan 13805d3de7dfSVinicius Costa Gomes if (hcon->type == LE_LINK) 13816c9d42a1SGustavo F. Padovan INIT_DELAYED_WORK(&conn->security_timer, security_timeout); 13825d3de7dfSVinicius Costa Gomes else 1383030013d8SGustavo F. Padovan INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); 13840a708f8fSGustavo F. Padovan 13859f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 13860a708f8fSGustavo F. Padovan 13870a708f8fSGustavo F. Padovan return conn; 13880a708f8fSGustavo F. Padovan } 13890a708f8fSGustavo F. Padovan 13900a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */ 13910a708f8fSGustavo F. Padovan 1392c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr. 13930a708f8fSGustavo F. Padovan * Returns closest match. 13940a708f8fSGustavo F. Padovan */ 1395c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, 1396c2287681SIdo Yariv bdaddr_t *src, 1397c2287681SIdo Yariv bdaddr_t *dst) 13980a708f8fSGustavo F. Padovan { 139923691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 14000a708f8fSGustavo F. Padovan 140123691d75SGustavo F. Padovan read_lock(&chan_list_lock); 14020a708f8fSGustavo F. Padovan 140323691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 140423691d75SGustavo F. Padovan struct sock *sk = c->sk; 1405fe4128e0SGustavo F. Padovan 140689bc500eSGustavo F. Padovan if (state && c->state != state) 14070a708f8fSGustavo F. Padovan continue; 14080a708f8fSGustavo F. Padovan 140923691d75SGustavo F. Padovan if (c->psm == psm) { 1410c2287681SIdo Yariv int src_match, dst_match; 1411c2287681SIdo Yariv int src_any, dst_any; 1412c2287681SIdo Yariv 14130a708f8fSGustavo F. Padovan /* Exact match. */ 1414c2287681SIdo Yariv src_match = !bacmp(&bt_sk(sk)->src, src); 1415c2287681SIdo Yariv dst_match = !bacmp(&bt_sk(sk)->dst, dst); 1416c2287681SIdo Yariv if (src_match && dst_match) { 1417a7567b20SJohannes Berg read_unlock(&chan_list_lock); 141823691d75SGustavo F. Padovan return c; 141923691d75SGustavo F. Padovan } 14200a708f8fSGustavo F. Padovan 14210a708f8fSGustavo F. Padovan /* Closest match */ 1422c2287681SIdo Yariv src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY); 1423c2287681SIdo Yariv dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY); 1424c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1425c2287681SIdo Yariv (src_any && dst_any)) 142623691d75SGustavo F. Padovan c1 = c; 14270a708f8fSGustavo F. Padovan } 14280a708f8fSGustavo F. Padovan } 14290a708f8fSGustavo F. Padovan 143023691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 14310a708f8fSGustavo F. Padovan 143223691d75SGustavo F. Padovan return c1; 14330a708f8fSGustavo F. Padovan } 14340a708f8fSGustavo F. Padovan 14358e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, 14368e9f9892SAndre Guedes bdaddr_t *dst, u8 dst_type) 14370a708f8fSGustavo F. Padovan { 14385d41ce1dSGustavo F. Padovan struct sock *sk = chan->sk; 14390a708f8fSGustavo F. Padovan bdaddr_t *src = &bt_sk(sk)->src; 14400a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 14410a708f8fSGustavo F. Padovan struct hci_conn *hcon; 14420a708f8fSGustavo F. Padovan struct hci_dev *hdev; 14430a708f8fSGustavo F. Padovan __u8 auth_type; 14440a708f8fSGustavo F. Padovan int err; 14450a708f8fSGustavo F. Padovan 14468e9f9892SAndre Guedes BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst), 14478e9f9892SAndre Guedes dst_type, __le16_to_cpu(chan->psm)); 14480a708f8fSGustavo F. Padovan 14490a708f8fSGustavo F. Padovan hdev = hci_get_route(dst, src); 14500a708f8fSGustavo F. Padovan if (!hdev) 14510a708f8fSGustavo F. Padovan return -EHOSTUNREACH; 14520a708f8fSGustavo F. Padovan 145309fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 14540a708f8fSGustavo F. Padovan 14556be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 145603a00194SGustavo F. Padovan 145703a00194SGustavo F. Padovan /* PSM must be odd and lsb of upper byte must be 0 */ 145803a00194SGustavo F. Padovan if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid && 145903a00194SGustavo F. Padovan chan->chan_type != L2CAP_CHAN_RAW) { 146003a00194SGustavo F. Padovan err = -EINVAL; 146103a00194SGustavo F. Padovan goto done; 146203a00194SGustavo F. Padovan } 146303a00194SGustavo F. Padovan 146403a00194SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) { 146503a00194SGustavo F. Padovan err = -EINVAL; 146603a00194SGustavo F. Padovan goto done; 146703a00194SGustavo F. Padovan } 146803a00194SGustavo F. Padovan 146903a00194SGustavo F. Padovan switch (chan->mode) { 147003a00194SGustavo F. Padovan case L2CAP_MODE_BASIC: 147103a00194SGustavo F. Padovan break; 147203a00194SGustavo F. Padovan case L2CAP_MODE_ERTM: 147303a00194SGustavo F. Padovan case L2CAP_MODE_STREAMING: 147403a00194SGustavo F. Padovan if (!disable_ertm) 147503a00194SGustavo F. Padovan break; 147603a00194SGustavo F. Padovan /* fall through */ 147703a00194SGustavo F. Padovan default: 147803a00194SGustavo F. Padovan err = -ENOTSUPP; 147903a00194SGustavo F. Padovan goto done; 148003a00194SGustavo F. Padovan } 148103a00194SGustavo F. Padovan 14826be36555SAndrei Emeltchenko lock_sock(sk); 14836be36555SAndrei Emeltchenko 148403a00194SGustavo F. Padovan switch (sk->sk_state) { 148503a00194SGustavo F. Padovan case BT_CONNECT: 148603a00194SGustavo F. Padovan case BT_CONNECT2: 148703a00194SGustavo F. Padovan case BT_CONFIG: 148803a00194SGustavo F. Padovan /* Already connecting */ 148903a00194SGustavo F. Padovan err = 0; 14906be36555SAndrei Emeltchenko release_sock(sk); 149103a00194SGustavo F. Padovan goto done; 149203a00194SGustavo F. Padovan 149303a00194SGustavo F. Padovan case BT_CONNECTED: 149403a00194SGustavo F. Padovan /* Already connected */ 149503a00194SGustavo F. Padovan err = -EISCONN; 14966be36555SAndrei Emeltchenko release_sock(sk); 149703a00194SGustavo F. Padovan goto done; 149803a00194SGustavo F. Padovan 149903a00194SGustavo F. Padovan case BT_OPEN: 150003a00194SGustavo F. Padovan case BT_BOUND: 150103a00194SGustavo F. Padovan /* Can connect */ 150203a00194SGustavo F. Padovan break; 150303a00194SGustavo F. Padovan 150403a00194SGustavo F. Padovan default: 150503a00194SGustavo F. Padovan err = -EBADFD; 15066be36555SAndrei Emeltchenko release_sock(sk); 150703a00194SGustavo F. Padovan goto done; 150803a00194SGustavo F. Padovan } 150903a00194SGustavo F. Padovan 151003a00194SGustavo F. Padovan /* Set destination address and psm */ 15119219b2a0SGustavo F. Padovan bacpy(&bt_sk(sk)->dst, dst); 15126be36555SAndrei Emeltchenko 15136be36555SAndrei Emeltchenko release_sock(sk); 15146be36555SAndrei Emeltchenko 151503a00194SGustavo F. Padovan chan->psm = psm; 151603a00194SGustavo F. Padovan chan->dcid = cid; 15170a708f8fSGustavo F. Padovan 15184343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 15190a708f8fSGustavo F. Padovan 1520fe4128e0SGustavo F. Padovan if (chan->dcid == L2CAP_CID_LE_DATA) 15218e9f9892SAndre Guedes hcon = hci_connect(hdev, LE_LINK, dst, dst_type, 15224343478fSGustavo F. Padovan chan->sec_level, auth_type); 1523acd7d370SVille Tervo else 15248e9f9892SAndre Guedes hcon = hci_connect(hdev, ACL_LINK, dst, dst_type, 15254343478fSGustavo F. Padovan chan->sec_level, auth_type); 1526acd7d370SVille Tervo 152730e76272SVille Tervo if (IS_ERR(hcon)) { 152830e76272SVille Tervo err = PTR_ERR(hcon); 15290a708f8fSGustavo F. Padovan goto done; 153030e76272SVille Tervo } 15310a708f8fSGustavo F. Padovan 15320a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, 0); 15330a708f8fSGustavo F. Padovan if (!conn) { 15340a708f8fSGustavo F. Padovan hci_conn_put(hcon); 153530e76272SVille Tervo err = -ENOMEM; 15360a708f8fSGustavo F. Padovan goto done; 15370a708f8fSGustavo F. Padovan } 15380a708f8fSGustavo F. Padovan 15399f0caeb1SVinicius Costa Gomes if (hcon->type == LE_LINK) { 15409f0caeb1SVinicius Costa Gomes err = 0; 15419f0caeb1SVinicius Costa Gomes 15429f0caeb1SVinicius Costa Gomes if (!list_empty(&conn->chan_l)) { 15439f0caeb1SVinicius Costa Gomes err = -EBUSY; 15449f0caeb1SVinicius Costa Gomes hci_conn_put(hcon); 15459f0caeb1SVinicius Costa Gomes } 15469f0caeb1SVinicius Costa Gomes 15479f0caeb1SVinicius Costa Gomes if (err) 15489f0caeb1SVinicius Costa Gomes goto done; 15499f0caeb1SVinicius Costa Gomes } 15509f0caeb1SVinicius Costa Gomes 15510a708f8fSGustavo F. Padovan /* Update source addr of the socket */ 15520a708f8fSGustavo F. Padovan bacpy(src, conn->src); 15530a708f8fSGustavo F. Padovan 15546be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 155548454079SGustavo F. Padovan l2cap_chan_add(conn, chan); 15566be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 155748454079SGustavo F. Padovan 15586be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECT); 1559c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 15600a708f8fSGustavo F. Padovan 15610a708f8fSGustavo F. Padovan if (hcon->state == BT_CONNECTED) { 1562715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1563c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 1564d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) 15656be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECTED); 15660a708f8fSGustavo F. Padovan } else 1567fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 15680a708f8fSGustavo F. Padovan } 15690a708f8fSGustavo F. Padovan 157030e76272SVille Tervo err = 0; 157130e76272SVille Tervo 15720a708f8fSGustavo F. Padovan done: 15736be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 157409fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 15750a708f8fSGustavo F. Padovan hci_dev_put(hdev); 15760a708f8fSGustavo F. Padovan return err; 15770a708f8fSGustavo F. Padovan } 15780a708f8fSGustavo F. Padovan 1579dcba0dbaSGustavo F. Padovan int __l2cap_wait_ack(struct sock *sk) 15800a708f8fSGustavo F. Padovan { 15818c1d787bSGustavo F. Padovan struct l2cap_chan *chan = l2cap_pi(sk)->chan; 15820a708f8fSGustavo F. Padovan DECLARE_WAITQUEUE(wait, current); 15830a708f8fSGustavo F. Padovan int err = 0; 15840a708f8fSGustavo F. Padovan int timeo = HZ/5; 15850a708f8fSGustavo F. Padovan 15860a708f8fSGustavo F. Padovan add_wait_queue(sk_sleep(sk), &wait); 15870a708f8fSGustavo F. Padovan set_current_state(TASK_INTERRUPTIBLE); 1588a71a0cf4SPeter Hurley while (chan->unacked_frames > 0 && chan->conn) { 15890a708f8fSGustavo F. Padovan if (!timeo) 15900a708f8fSGustavo F. Padovan timeo = HZ/5; 15910a708f8fSGustavo F. Padovan 15920a708f8fSGustavo F. Padovan if (signal_pending(current)) { 15930a708f8fSGustavo F. Padovan err = sock_intr_errno(timeo); 15940a708f8fSGustavo F. Padovan break; 15950a708f8fSGustavo F. Padovan } 15960a708f8fSGustavo F. Padovan 15970a708f8fSGustavo F. Padovan release_sock(sk); 15980a708f8fSGustavo F. Padovan timeo = schedule_timeout(timeo); 15990a708f8fSGustavo F. Padovan lock_sock(sk); 1600a71a0cf4SPeter Hurley set_current_state(TASK_INTERRUPTIBLE); 16010a708f8fSGustavo F. Padovan 16020a708f8fSGustavo F. Padovan err = sock_error(sk); 16030a708f8fSGustavo F. Padovan if (err) 16040a708f8fSGustavo F. Padovan break; 16050a708f8fSGustavo F. Padovan } 16060a708f8fSGustavo F. Padovan set_current_state(TASK_RUNNING); 16070a708f8fSGustavo F. Padovan remove_wait_queue(sk_sleep(sk), &wait); 16080a708f8fSGustavo F. Padovan return err; 16090a708f8fSGustavo F. Padovan } 16100a708f8fSGustavo F. Padovan 1611721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work) 16120a708f8fSGustavo F. Padovan { 1613721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1614721c4181SGustavo F. Padovan monitor_timer.work); 16150a708f8fSGustavo F. Padovan 1616525cd185SGustavo F. Padovan BT_DBG("chan %p", chan); 16170a708f8fSGustavo F. Padovan 16186be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 16196be36555SAndrei Emeltchenko 16202c03a7a4SGustavo F. Padovan if (chan->retry_count >= chan->remote_max_tx) { 16218c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); 16226be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16238d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 16240a708f8fSGustavo F. Padovan return; 16250a708f8fSGustavo F. Padovan } 16260a708f8fSGustavo F. Padovan 16276a026610SGustavo F. Padovan chan->retry_count++; 16281a09bcb9SGustavo F. Padovan __set_monitor_timer(chan); 16290a708f8fSGustavo F. Padovan 1630525cd185SGustavo F. Padovan l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); 16316be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16328d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 16330a708f8fSGustavo F. Padovan } 16340a708f8fSGustavo F. Padovan 1635721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work) 16360a708f8fSGustavo F. Padovan { 1637721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1638721c4181SGustavo F. Padovan retrans_timer.work); 16390a708f8fSGustavo F. Padovan 164049208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 16410a708f8fSGustavo F. Padovan 16426be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 16436be36555SAndrei Emeltchenko 16446a026610SGustavo F. Padovan chan->retry_count = 1; 16451a09bcb9SGustavo F. Padovan __set_monitor_timer(chan); 16460a708f8fSGustavo F. Padovan 1647e2ab4353SGustavo F. Padovan set_bit(CONN_WAIT_F, &chan->conn_state); 16480a708f8fSGustavo F. Padovan 1649525cd185SGustavo F. Padovan l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); 16506be36555SAndrei Emeltchenko 16516be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16528d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 16530a708f8fSGustavo F. Padovan } 16540a708f8fSGustavo F. Padovan 16553733937dSMat Martineau static int l2cap_streaming_send(struct l2cap_chan *chan, 16563733937dSMat Martineau struct sk_buff_head *skbs) 16570a708f8fSGustavo F. Padovan { 16580a708f8fSGustavo F. Padovan struct sk_buff *skb; 16593733937dSMat Martineau struct l2cap_ctrl *control; 16600a708f8fSGustavo F. Padovan 16613733937dSMat Martineau BT_DBG("chan %p, skbs %p", chan, skbs); 16623733937dSMat Martineau 16633733937dSMat Martineau if (chan->state != BT_CONNECTED) 16643733937dSMat Martineau return -ENOTCONN; 16653733937dSMat Martineau 16663733937dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 16673733937dSMat Martineau 16683733937dSMat Martineau while (!skb_queue_empty(&chan->tx_q)) { 16693733937dSMat Martineau 16703733937dSMat Martineau skb = skb_dequeue(&chan->tx_q); 16713733937dSMat Martineau 16723733937dSMat Martineau bt_cb(skb)->control.retries = 1; 16733733937dSMat Martineau control = &bt_cb(skb)->control; 16743733937dSMat Martineau 16753733937dSMat Martineau control->reqseq = 0; 16763733937dSMat Martineau control->txseq = chan->next_tx_seq; 16773733937dSMat Martineau 16783733937dSMat Martineau __pack_control(chan, control, skb); 16790a708f8fSGustavo F. Padovan 168047d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 16813733937dSMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 16823733937dSMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 16830a708f8fSGustavo F. Padovan } 16840a708f8fSGustavo F. Padovan 16854343478fSGustavo F. Padovan l2cap_do_send(chan, skb); 16860a708f8fSGustavo F. Padovan 16873733937dSMat Martineau BT_DBG("Sent txseq %d", (int)control->txseq); 16883733937dSMat Martineau 1689836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 16903733937dSMat Martineau chan->frames_sent++; 16910a708f8fSGustavo F. Padovan } 16923733937dSMat Martineau 16933733937dSMat Martineau return 0; 16940a708f8fSGustavo F. Padovan } 16950a708f8fSGustavo F. Padovan 169667c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan) 16970a708f8fSGustavo F. Padovan { 16980a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 169918a48e76SMat Martineau struct l2cap_ctrl *control; 170018a48e76SMat Martineau int sent = 0; 170118a48e76SMat Martineau 170218a48e76SMat Martineau BT_DBG("chan %p", chan); 17030a708f8fSGustavo F. Padovan 170489bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 17050a708f8fSGustavo F. Padovan return -ENOTCONN; 17060a708f8fSGustavo F. Padovan 170794122bbeSMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 170894122bbeSMat Martineau return 0; 170994122bbeSMat Martineau 171018a48e76SMat Martineau while (chan->tx_send_head && 171118a48e76SMat Martineau chan->unacked_frames < chan->remote_tx_win && 171218a48e76SMat Martineau chan->tx_state == L2CAP_TX_STATE_XMIT) { 17130a708f8fSGustavo F. Padovan 171418a48e76SMat Martineau skb = chan->tx_send_head; 17150a708f8fSGustavo F. Padovan 171618a48e76SMat Martineau bt_cb(skb)->control.retries = 1; 171718a48e76SMat Martineau control = &bt_cb(skb)->control; 17180a708f8fSGustavo F. Padovan 1719e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 172018a48e76SMat Martineau control->final = 1; 1721e2ab4353SGustavo F. Padovan 172218a48e76SMat Martineau control->reqseq = chan->buffer_seq; 172318a48e76SMat Martineau chan->last_acked_seq = chan->buffer_seq; 172418a48e76SMat Martineau control->txseq = chan->next_tx_seq; 17250a708f8fSGustavo F. Padovan 172618a48e76SMat Martineau __pack_control(chan, control, skb); 17270a708f8fSGustavo F. Padovan 172847d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 172918a48e76SMat Martineau u16 fcs = crc16(0, (u8 *) skb->data, skb->len); 173018a48e76SMat Martineau put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 17310a708f8fSGustavo F. Padovan } 17320a708f8fSGustavo F. Padovan 173318a48e76SMat Martineau /* Clone after data has been modified. Data is assumed to be 173418a48e76SMat Martineau read-only (for locking purposes) on cloned sk_buffs. 173518a48e76SMat Martineau */ 173618a48e76SMat Martineau tx_skb = skb_clone(skb, GFP_KERNEL); 173718a48e76SMat Martineau 173818a48e76SMat Martineau if (!tx_skb) 173918a48e76SMat Martineau break; 17400a708f8fSGustavo F. Padovan 17411a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 17420a708f8fSGustavo F. Padovan 1743836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 17446a026610SGustavo F. Padovan chan->unacked_frames++; 17456a026610SGustavo F. Padovan chan->frames_sent++; 174618a48e76SMat Martineau sent++; 17470a708f8fSGustavo F. Padovan 174858d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 174958d35f87SGustavo F. Padovan chan->tx_send_head = NULL; 17500a708f8fSGustavo F. Padovan else 175158d35f87SGustavo F. Padovan chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); 175218a48e76SMat Martineau 175318a48e76SMat Martineau l2cap_do_send(chan, tx_skb); 175418a48e76SMat Martineau BT_DBG("Sent txseq %d", (int)control->txseq); 17550a708f8fSGustavo F. Padovan } 17560a708f8fSGustavo F. Padovan 175718a48e76SMat Martineau BT_DBG("Sent %d, %d unacked, %d in ERTM queue", sent, 175818a48e76SMat Martineau (int) chan->unacked_frames, skb_queue_len(&chan->tx_q)); 175918a48e76SMat Martineau 176018a48e76SMat Martineau return sent; 17610a708f8fSGustavo F. Padovan } 17620a708f8fSGustavo F. Padovan 1763d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan, 1764d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 1765d2a7ac5dSMat Martineau { 1766d2a7ac5dSMat Martineau /* Placeholder */ 1767d2a7ac5dSMat Martineau } 1768d2a7ac5dSMat Martineau 1769b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan) 1770b17e73bbSSzymon Janc { 17710a0aba42SMat Martineau struct l2cap_ctrl control; 17720a0aba42SMat Martineau u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq, 17730a0aba42SMat Martineau chan->last_acked_seq); 17740a0aba42SMat Martineau int threshold; 17750a0aba42SMat Martineau 17760a0aba42SMat Martineau BT_DBG("chan %p last_acked_seq %d buffer_seq %d", 17770a0aba42SMat Martineau chan, chan->last_acked_seq, chan->buffer_seq); 17780a0aba42SMat Martineau 17790a0aba42SMat Martineau memset(&control, 0, sizeof(control)); 17800a0aba42SMat Martineau control.sframe = 1; 17810a0aba42SMat Martineau 17820a0aba42SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 17830a0aba42SMat Martineau chan->rx_state == L2CAP_RX_STATE_RECV) { 1784b17e73bbSSzymon Janc __clear_ack_timer(chan); 17850a0aba42SMat Martineau control.super = L2CAP_SUPER_RNR; 17860a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 17870a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 17880a0aba42SMat Martineau } else { 17890a0aba42SMat Martineau if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) { 17900a0aba42SMat Martineau l2cap_ertm_send(chan); 17910a0aba42SMat Martineau /* If any i-frames were sent, they included an ack */ 17920a0aba42SMat Martineau if (chan->buffer_seq == chan->last_acked_seq) 17930a0aba42SMat Martineau frames_to_ack = 0; 17940a0aba42SMat Martineau } 17950a0aba42SMat Martineau 17960a0aba42SMat Martineau /* Ack now if the tx window is 3/4ths full. 17970a0aba42SMat Martineau * Calculate without mul or div 17980a0aba42SMat Martineau */ 17990a0aba42SMat Martineau threshold = chan->tx_win; 18000a0aba42SMat Martineau threshold += threshold << 1; 18010a0aba42SMat Martineau threshold >>= 2; 18020a0aba42SMat Martineau 18030a0aba42SMat Martineau BT_DBG("frames_to_ack %d, threshold %d", (int)frames_to_ack, 18040a0aba42SMat Martineau threshold); 18050a0aba42SMat Martineau 18060a0aba42SMat Martineau if (frames_to_ack >= threshold) { 18070a0aba42SMat Martineau __clear_ack_timer(chan); 18080a0aba42SMat Martineau control.super = L2CAP_SUPER_RR; 18090a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 18100a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 18110a0aba42SMat Martineau frames_to_ack = 0; 18120a0aba42SMat Martineau } 18130a0aba42SMat Martineau 18140a0aba42SMat Martineau if (frames_to_ack) 18150a0aba42SMat Martineau __set_ack_timer(chan); 18160a0aba42SMat Martineau } 1817b17e73bbSSzymon Janc } 1818b17e73bbSSzymon Janc 181904124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, 182004124681SGustavo F. Padovan struct msghdr *msg, int len, 182104124681SGustavo F. Padovan int count, struct sk_buff *skb) 18220a708f8fSGustavo F. Padovan { 18230952a57aSAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 18240a708f8fSGustavo F. Padovan struct sk_buff **frag; 182590338947SGustavo Padovan int sent = 0; 18260a708f8fSGustavo F. Padovan 18270a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) 18280a708f8fSGustavo F. Padovan return -EFAULT; 18290a708f8fSGustavo F. Padovan 18300a708f8fSGustavo F. Padovan sent += count; 18310a708f8fSGustavo F. Padovan len -= count; 18320a708f8fSGustavo F. Padovan 18330a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 18340a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 18350a708f8fSGustavo F. Padovan while (len) { 1836fbe00700SGustavo Padovan struct sk_buff *tmp; 1837fbe00700SGustavo Padovan 18380a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 18390a708f8fSGustavo F. Padovan 1840fbe00700SGustavo Padovan tmp = chan->ops->alloc_skb(chan, count, 184190338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 1842fbe00700SGustavo Padovan if (IS_ERR(tmp)) 1843fbe00700SGustavo Padovan return PTR_ERR(tmp); 18442f7719ceSAndrei Emeltchenko 1845fbe00700SGustavo Padovan *frag = tmp; 1846fbe00700SGustavo Padovan 18470a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) 18480a708f8fSGustavo F. Padovan return -EFAULT; 18490a708f8fSGustavo F. Padovan 18505e59b791SLuiz Augusto von Dentz (*frag)->priority = skb->priority; 18515e59b791SLuiz Augusto von Dentz 18520a708f8fSGustavo F. Padovan sent += count; 18530a708f8fSGustavo F. Padovan len -= count; 18540a708f8fSGustavo F. Padovan 18552d0ed3d5SGustavo Padovan skb->len += (*frag)->len; 18562d0ed3d5SGustavo Padovan skb->data_len += (*frag)->len; 18572d0ed3d5SGustavo Padovan 18580a708f8fSGustavo F. Padovan frag = &(*frag)->next; 18590a708f8fSGustavo F. Padovan } 18600a708f8fSGustavo F. Padovan 18610a708f8fSGustavo F. Padovan return sent; 18620a708f8fSGustavo F. Padovan } 18630a708f8fSGustavo F. Padovan 18645e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, 18655e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 18665e59b791SLuiz Augusto von Dentz u32 priority) 18670a708f8fSGustavo F. Padovan { 18688c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 18690a708f8fSGustavo F. Padovan struct sk_buff *skb; 187003a51213SAndrei Emeltchenko int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; 18710a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 18720a708f8fSGustavo F. Padovan 18736d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d priority %u", chan, (int)len, priority); 18740a708f8fSGustavo F. Padovan 18750a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 18762f7719ceSAndrei Emeltchenko 18772f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 187890338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 187990338947SGustavo Padovan if (IS_ERR(skb)) 188090338947SGustavo Padovan return skb; 18810a708f8fSGustavo F. Padovan 18825e59b791SLuiz Augusto von Dentz skb->priority = priority; 18835e59b791SLuiz Augusto von Dentz 18840a708f8fSGustavo F. Padovan /* Create L2CAP header */ 18850a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 1886fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 1887daf6a78cSAndrei Emeltchenko lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); 1888daf6a78cSAndrei Emeltchenko put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE)); 18890a708f8fSGustavo F. Padovan 18900952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 18910a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 18920a708f8fSGustavo F. Padovan kfree_skb(skb); 18930a708f8fSGustavo F. Padovan return ERR_PTR(err); 18940a708f8fSGustavo F. Padovan } 18950a708f8fSGustavo F. Padovan return skb; 18960a708f8fSGustavo F. Padovan } 18970a708f8fSGustavo F. Padovan 18985e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, 18995e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 19005e59b791SLuiz Augusto von Dentz u32 priority) 19010a708f8fSGustavo F. Padovan { 19028c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 19030a708f8fSGustavo F. Padovan struct sk_buff *skb; 1904f2ba7faeSGustavo Padovan int err, count; 19050a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 19060a708f8fSGustavo F. Padovan 19076d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d", chan, (int)len); 19080a708f8fSGustavo F. Padovan 1909f2ba7faeSGustavo Padovan count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); 19102f7719ceSAndrei Emeltchenko 1911f2ba7faeSGustavo Padovan skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE, 191290338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 191390338947SGustavo Padovan if (IS_ERR(skb)) 191490338947SGustavo Padovan return skb; 19150a708f8fSGustavo F. Padovan 19165e59b791SLuiz Augusto von Dentz skb->priority = priority; 19175e59b791SLuiz Augusto von Dentz 19180a708f8fSGustavo F. Padovan /* Create L2CAP header */ 19190a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 1920fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 19216ff9b5efSGustavo Padovan lh->len = cpu_to_le16(len); 19220a708f8fSGustavo F. Padovan 19230952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 19240a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 19250a708f8fSGustavo F. Padovan kfree_skb(skb); 19260a708f8fSGustavo F. Padovan return ERR_PTR(err); 19270a708f8fSGustavo F. Padovan } 19280a708f8fSGustavo F. Padovan return skb; 19290a708f8fSGustavo F. Padovan } 19300a708f8fSGustavo F. Padovan 1931ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, 1932ab0ff76dSLuiz Augusto von Dentz struct msghdr *msg, size_t len, 193394122bbeSMat Martineau u16 sdulen) 19340a708f8fSGustavo F. Padovan { 19358c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 19360a708f8fSGustavo F. Padovan struct sk_buff *skb; 1937e4ca6d98SAndrei Emeltchenko int err, count, hlen; 19380a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 19390a708f8fSGustavo F. Padovan 19406d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d", chan, (int)len); 19410a708f8fSGustavo F. Padovan 19420a708f8fSGustavo F. Padovan if (!conn) 19430a708f8fSGustavo F. Padovan return ERR_PTR(-ENOTCONN); 19440a708f8fSGustavo F. Padovan 1945e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1946e4ca6d98SAndrei Emeltchenko hlen = L2CAP_EXT_HDR_SIZE; 1947e4ca6d98SAndrei Emeltchenko else 1948e4ca6d98SAndrei Emeltchenko hlen = L2CAP_ENH_HDR_SIZE; 1949e4ca6d98SAndrei Emeltchenko 19500a708f8fSGustavo F. Padovan if (sdulen) 195103a51213SAndrei Emeltchenko hlen += L2CAP_SDULEN_SIZE; 19520a708f8fSGustavo F. Padovan 195347d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 195403a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 19550a708f8fSGustavo F. Padovan 19560a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 19572f7719ceSAndrei Emeltchenko 19582f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 195990338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 196090338947SGustavo Padovan if (IS_ERR(skb)) 196190338947SGustavo Padovan return skb; 19620a708f8fSGustavo F. Padovan 19630a708f8fSGustavo F. Padovan /* Create L2CAP header */ 19640a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 1965fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 19660a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 196788843ab0SAndrei Emeltchenko 196818a48e76SMat Martineau /* Control header is populated later */ 196918a48e76SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 197018a48e76SMat Martineau put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 197118a48e76SMat Martineau else 197218a48e76SMat Martineau put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 197388843ab0SAndrei Emeltchenko 19740a708f8fSGustavo F. Padovan if (sdulen) 197503a51213SAndrei Emeltchenko put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 19760a708f8fSGustavo F. Padovan 19770952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 19780a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 19790a708f8fSGustavo F. Padovan kfree_skb(skb); 19800a708f8fSGustavo F. Padovan return ERR_PTR(err); 19810a708f8fSGustavo F. Padovan } 19820a708f8fSGustavo F. Padovan 198318a48e76SMat Martineau bt_cb(skb)->control.fcs = chan->fcs; 19843ce3514fSMat Martineau bt_cb(skb)->control.retries = 0; 19850a708f8fSGustavo F. Padovan return skb; 19860a708f8fSGustavo F. Padovan } 19870a708f8fSGustavo F. Padovan 198894122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan, 198994122bbeSMat Martineau struct sk_buff_head *seg_queue, 199094122bbeSMat Martineau struct msghdr *msg, size_t len) 19910a708f8fSGustavo F. Padovan { 19920a708f8fSGustavo F. Padovan struct sk_buff *skb; 199394122bbeSMat Martineau u16 sdu_len; 199494122bbeSMat Martineau size_t pdu_len; 199594122bbeSMat Martineau int err = 0; 199694122bbeSMat Martineau u8 sar; 19970a708f8fSGustavo F. Padovan 199894122bbeSMat Martineau BT_DBG("chan %p, msg %p, len %d", chan, msg, (int)len); 19990a708f8fSGustavo F. Padovan 200094122bbeSMat Martineau /* It is critical that ERTM PDUs fit in a single HCI fragment, 200194122bbeSMat Martineau * so fragmented skbs are not used. The HCI layer's handling 200294122bbeSMat Martineau * of fragmented skbs is not compatible with ERTM's queueing. 200394122bbeSMat Martineau */ 200494122bbeSMat Martineau 200594122bbeSMat Martineau /* PDU size is derived from the HCI MTU */ 200694122bbeSMat Martineau pdu_len = chan->conn->mtu; 200794122bbeSMat Martineau 200894122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); 200994122bbeSMat Martineau 201094122bbeSMat Martineau /* Adjust for largest possible L2CAP overhead. */ 201194122bbeSMat Martineau pdu_len -= L2CAP_EXT_HDR_SIZE + L2CAP_FCS_SIZE; 201294122bbeSMat Martineau 201394122bbeSMat Martineau /* Remote device may have requested smaller PDUs */ 201494122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, chan->remote_mps); 201594122bbeSMat Martineau 201694122bbeSMat Martineau if (len <= pdu_len) { 201794122bbeSMat Martineau sar = L2CAP_SAR_UNSEGMENTED; 201894122bbeSMat Martineau sdu_len = 0; 201994122bbeSMat Martineau pdu_len = len; 202094122bbeSMat Martineau } else { 202194122bbeSMat Martineau sar = L2CAP_SAR_START; 202294122bbeSMat Martineau sdu_len = len; 202394122bbeSMat Martineau pdu_len -= L2CAP_SDULEN_SIZE; 202494122bbeSMat Martineau } 20250a708f8fSGustavo F. Padovan 20260a708f8fSGustavo F. Padovan while (len > 0) { 202794122bbeSMat Martineau skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len); 20280a708f8fSGustavo F. Padovan 20290a708f8fSGustavo F. Padovan if (IS_ERR(skb)) { 203094122bbeSMat Martineau __skb_queue_purge(seg_queue); 20310a708f8fSGustavo F. Padovan return PTR_ERR(skb); 20320a708f8fSGustavo F. Padovan } 20330a708f8fSGustavo F. Padovan 203494122bbeSMat Martineau bt_cb(skb)->control.sar = sar; 203594122bbeSMat Martineau __skb_queue_tail(seg_queue, skb); 20360a708f8fSGustavo F. Padovan 203794122bbeSMat Martineau len -= pdu_len; 203894122bbeSMat Martineau if (sdu_len) { 203994122bbeSMat Martineau sdu_len = 0; 204094122bbeSMat Martineau pdu_len += L2CAP_SDULEN_SIZE; 204194122bbeSMat Martineau } 204294122bbeSMat Martineau 204394122bbeSMat Martineau if (len <= pdu_len) { 204494122bbeSMat Martineau sar = L2CAP_SAR_END; 204594122bbeSMat Martineau pdu_len = len; 204694122bbeSMat Martineau } else { 204794122bbeSMat Martineau sar = L2CAP_SAR_CONTINUE; 204894122bbeSMat Martineau } 204994122bbeSMat Martineau } 205094122bbeSMat Martineau 205194122bbeSMat Martineau return err; 20520a708f8fSGustavo F. Padovan } 20530a708f8fSGustavo F. Padovan 20545e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, 20555e59b791SLuiz Augusto von Dentz u32 priority) 20569a91a04aSGustavo F. Padovan { 20579a91a04aSGustavo F. Padovan struct sk_buff *skb; 20589a91a04aSGustavo F. Padovan int err; 205994122bbeSMat Martineau struct sk_buff_head seg_queue; 20609a91a04aSGustavo F. Padovan 20619a91a04aSGustavo F. Padovan /* Connectionless channel */ 2062715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { 20635e59b791SLuiz Augusto von Dentz skb = l2cap_create_connless_pdu(chan, msg, len, priority); 20649a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 20659a91a04aSGustavo F. Padovan return PTR_ERR(skb); 20669a91a04aSGustavo F. Padovan 20679a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 20689a91a04aSGustavo F. Padovan return len; 20699a91a04aSGustavo F. Padovan } 20709a91a04aSGustavo F. Padovan 20719a91a04aSGustavo F. Padovan switch (chan->mode) { 20729a91a04aSGustavo F. Padovan case L2CAP_MODE_BASIC: 20739a91a04aSGustavo F. Padovan /* Check outgoing MTU */ 20749a91a04aSGustavo F. Padovan if (len > chan->omtu) 20759a91a04aSGustavo F. Padovan return -EMSGSIZE; 20769a91a04aSGustavo F. Padovan 20779a91a04aSGustavo F. Padovan /* Create a basic PDU */ 20785e59b791SLuiz Augusto von Dentz skb = l2cap_create_basic_pdu(chan, msg, len, priority); 20799a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 20809a91a04aSGustavo F. Padovan return PTR_ERR(skb); 20819a91a04aSGustavo F. Padovan 20829a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 20839a91a04aSGustavo F. Padovan err = len; 20849a91a04aSGustavo F. Padovan break; 20859a91a04aSGustavo F. Padovan 20869a91a04aSGustavo F. Padovan case L2CAP_MODE_ERTM: 20879a91a04aSGustavo F. Padovan case L2CAP_MODE_STREAMING: 208894122bbeSMat Martineau /* Check outgoing MTU */ 208994122bbeSMat Martineau if (len > chan->omtu) { 209094122bbeSMat Martineau err = -EMSGSIZE; 20919a91a04aSGustavo F. Padovan break; 20929a91a04aSGustavo F. Padovan } 20939a91a04aSGustavo F. Padovan 209494122bbeSMat Martineau __skb_queue_head_init(&seg_queue); 209594122bbeSMat Martineau 209694122bbeSMat Martineau /* Do segmentation before calling in to the state machine, 209794122bbeSMat Martineau * since it's possible to block while waiting for memory 209894122bbeSMat Martineau * allocation. 209994122bbeSMat Martineau */ 210094122bbeSMat Martineau err = l2cap_segment_sdu(chan, &seg_queue, msg, len); 210194122bbeSMat Martineau 210294122bbeSMat Martineau /* The channel could have been closed while segmenting, 210394122bbeSMat Martineau * check that it is still connected. 210494122bbeSMat Martineau */ 210594122bbeSMat Martineau if (chan->state != BT_CONNECTED) { 210694122bbeSMat Martineau __skb_queue_purge(&seg_queue); 210794122bbeSMat Martineau err = -ENOTCONN; 21089a91a04aSGustavo F. Padovan } 21099a91a04aSGustavo F. Padovan 211094122bbeSMat Martineau if (err) 211194122bbeSMat Martineau break; 211294122bbeSMat Martineau 21133733937dSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) 2114608bcc6dSMat Martineau err = l2cap_tx(chan, 0, &seg_queue, 2115608bcc6dSMat Martineau L2CAP_EV_DATA_REQUEST); 21163733937dSMat Martineau else 21173733937dSMat Martineau err = l2cap_streaming_send(chan, &seg_queue); 211894122bbeSMat Martineau 2119608bcc6dSMat Martineau if (!err) 21209a91a04aSGustavo F. Padovan err = len; 21219a91a04aSGustavo F. Padovan 212294122bbeSMat Martineau /* If the skbs were not queued for sending, they'll still be in 212394122bbeSMat Martineau * seg_queue and need to be purged. 212494122bbeSMat Martineau */ 212594122bbeSMat Martineau __skb_queue_purge(&seg_queue); 21269a91a04aSGustavo F. Padovan break; 21279a91a04aSGustavo F. Padovan 21289a91a04aSGustavo F. Padovan default: 21299a91a04aSGustavo F. Padovan BT_DBG("bad state %1.1x", chan->mode); 21309a91a04aSGustavo F. Padovan err = -EBADFD; 21319a91a04aSGustavo F. Padovan } 21329a91a04aSGustavo F. Padovan 21339a91a04aSGustavo F. Padovan return err; 21349a91a04aSGustavo F. Padovan } 21359a91a04aSGustavo F. Padovan 2136d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq) 2137d2a7ac5dSMat Martineau { 2138d2a7ac5dSMat Martineau /* Placeholder */ 2139d2a7ac5dSMat Martineau } 2140d2a7ac5dSMat Martineau 2141d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan) 2142d2a7ac5dSMat Martineau { 2143d2a7ac5dSMat Martineau /* Placeholder */ 2144d2a7ac5dSMat Martineau } 2145d2a7ac5dSMat Martineau 2146d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq) 2147d2a7ac5dSMat Martineau { 2148d2a7ac5dSMat Martineau /* Placeholder */ 2149d2a7ac5dSMat Martineau } 2150d2a7ac5dSMat Martineau 2151608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq) 2152608bcc6dSMat Martineau { 2153608bcc6dSMat Martineau struct sk_buff *acked_skb; 2154608bcc6dSMat Martineau u16 ackseq; 2155608bcc6dSMat Martineau 2156608bcc6dSMat Martineau BT_DBG("chan %p, reqseq %d", chan, reqseq); 2157608bcc6dSMat Martineau 2158608bcc6dSMat Martineau if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq) 2159608bcc6dSMat Martineau return; 2160608bcc6dSMat Martineau 2161608bcc6dSMat Martineau BT_DBG("expected_ack_seq %d, unacked_frames %d", 2162608bcc6dSMat Martineau chan->expected_ack_seq, chan->unacked_frames); 2163608bcc6dSMat Martineau 2164608bcc6dSMat Martineau for (ackseq = chan->expected_ack_seq; ackseq != reqseq; 2165608bcc6dSMat Martineau ackseq = __next_seq(chan, ackseq)) { 2166608bcc6dSMat Martineau 2167608bcc6dSMat Martineau acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq); 2168608bcc6dSMat Martineau if (acked_skb) { 2169608bcc6dSMat Martineau skb_unlink(acked_skb, &chan->tx_q); 2170608bcc6dSMat Martineau kfree_skb(acked_skb); 2171608bcc6dSMat Martineau chan->unacked_frames--; 2172608bcc6dSMat Martineau } 2173608bcc6dSMat Martineau } 2174608bcc6dSMat Martineau 2175608bcc6dSMat Martineau chan->expected_ack_seq = reqseq; 2176608bcc6dSMat Martineau 2177608bcc6dSMat Martineau if (chan->unacked_frames == 0) 2178608bcc6dSMat Martineau __clear_retrans_timer(chan); 2179608bcc6dSMat Martineau 2180608bcc6dSMat Martineau BT_DBG("unacked_frames %d", (int) chan->unacked_frames); 2181608bcc6dSMat Martineau } 2182608bcc6dSMat Martineau 2183608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan) 2184608bcc6dSMat Martineau { 2185608bcc6dSMat Martineau BT_DBG("chan %p", chan); 2186608bcc6dSMat Martineau 2187608bcc6dSMat Martineau chan->expected_tx_seq = chan->buffer_seq; 2188608bcc6dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 2189608bcc6dSMat Martineau skb_queue_purge(&chan->srej_q); 2190608bcc6dSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2191608bcc6dSMat Martineau } 2192608bcc6dSMat Martineau 2193608bcc6dSMat Martineau static int l2cap_tx_state_xmit(struct l2cap_chan *chan, 2194608bcc6dSMat Martineau struct l2cap_ctrl *control, 2195608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2196608bcc6dSMat Martineau { 2197608bcc6dSMat Martineau int err = 0; 2198608bcc6dSMat Martineau 2199608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2200608bcc6dSMat Martineau event); 2201608bcc6dSMat Martineau 2202608bcc6dSMat Martineau switch (event) { 2203608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2204608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2205608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2206608bcc6dSMat Martineau 2207608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2208608bcc6dSMat Martineau l2cap_ertm_send(chan); 2209608bcc6dSMat Martineau break; 2210608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2211608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2212608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2213608bcc6dSMat Martineau 2214608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2215608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2216608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2217608bcc6dSMat Martineau */ 2218608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2219608bcc6dSMat Martineau } 2220608bcc6dSMat Martineau 2221608bcc6dSMat Martineau l2cap_send_ack(chan); 2222608bcc6dSMat Martineau 2223608bcc6dSMat Martineau break; 2224608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2225608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2226608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2227608bcc6dSMat Martineau 2228608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2229608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2230608bcc6dSMat Martineau 2231608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2232608bcc6dSMat Martineau local_control.sframe = 1; 2233608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2234608bcc6dSMat Martineau local_control.poll = 1; 2235608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2236a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2237608bcc6dSMat Martineau 2238608bcc6dSMat Martineau chan->retry_count = 1; 2239608bcc6dSMat Martineau __set_monitor_timer(chan); 2240608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2241608bcc6dSMat Martineau } 2242608bcc6dSMat Martineau break; 2243608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2244608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2245608bcc6dSMat Martineau break; 2246608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2247608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2248608bcc6dSMat Martineau chan->retry_count = 1; 2249608bcc6dSMat Martineau __set_monitor_timer(chan); 2250608bcc6dSMat Martineau __clear_ack_timer(chan); 2251608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2252608bcc6dSMat Martineau break; 2253608bcc6dSMat Martineau case L2CAP_EV_RETRANS_TO: 2254608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2255608bcc6dSMat Martineau chan->retry_count = 1; 2256608bcc6dSMat Martineau __set_monitor_timer(chan); 2257608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2258608bcc6dSMat Martineau break; 2259608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2260608bcc6dSMat Martineau /* Nothing to process */ 2261608bcc6dSMat Martineau break; 2262608bcc6dSMat Martineau default: 2263608bcc6dSMat Martineau break; 2264608bcc6dSMat Martineau } 2265608bcc6dSMat Martineau 2266608bcc6dSMat Martineau return err; 2267608bcc6dSMat Martineau } 2268608bcc6dSMat Martineau 2269608bcc6dSMat Martineau static int l2cap_tx_state_wait_f(struct l2cap_chan *chan, 2270608bcc6dSMat Martineau struct l2cap_ctrl *control, 2271608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2272608bcc6dSMat Martineau { 2273608bcc6dSMat Martineau int err = 0; 2274608bcc6dSMat Martineau 2275608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2276608bcc6dSMat Martineau event); 2277608bcc6dSMat Martineau 2278608bcc6dSMat Martineau switch (event) { 2279608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2280608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2281608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2282608bcc6dSMat Martineau /* Queue data, but don't send. */ 2283608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2284608bcc6dSMat Martineau break; 2285608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2286608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2287608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2288608bcc6dSMat Martineau 2289608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2290608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2291608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2292608bcc6dSMat Martineau */ 2293608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2294608bcc6dSMat Martineau } 2295608bcc6dSMat Martineau 2296608bcc6dSMat Martineau l2cap_send_ack(chan); 2297608bcc6dSMat Martineau 2298608bcc6dSMat Martineau break; 2299608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2300608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2301608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2302608bcc6dSMat Martineau 2303608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2304608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2305608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2306608bcc6dSMat Martineau local_control.sframe = 1; 2307608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2308608bcc6dSMat Martineau local_control.poll = 1; 2309608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2310a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2311608bcc6dSMat Martineau 2312608bcc6dSMat Martineau chan->retry_count = 1; 2313608bcc6dSMat Martineau __set_monitor_timer(chan); 2314608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2315608bcc6dSMat Martineau } 2316608bcc6dSMat Martineau break; 2317608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2318608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2319608bcc6dSMat Martineau 2320608bcc6dSMat Martineau /* Fall through */ 2321608bcc6dSMat Martineau 2322608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2323608bcc6dSMat Martineau if (control && control->final) { 2324608bcc6dSMat Martineau __clear_monitor_timer(chan); 2325608bcc6dSMat Martineau if (chan->unacked_frames > 0) 2326608bcc6dSMat Martineau __set_retrans_timer(chan); 2327608bcc6dSMat Martineau chan->retry_count = 0; 2328608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 2329608bcc6dSMat Martineau BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state); 2330608bcc6dSMat Martineau } 2331608bcc6dSMat Martineau break; 2332608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2333608bcc6dSMat Martineau /* Ignore */ 2334608bcc6dSMat Martineau break; 2335608bcc6dSMat Martineau case L2CAP_EV_MONITOR_TO: 2336608bcc6dSMat Martineau if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) { 2337608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2338608bcc6dSMat Martineau __set_monitor_timer(chan); 2339608bcc6dSMat Martineau chan->retry_count++; 2340608bcc6dSMat Martineau } else { 2341608bcc6dSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); 2342608bcc6dSMat Martineau } 2343608bcc6dSMat Martineau break; 2344608bcc6dSMat Martineau default: 2345608bcc6dSMat Martineau break; 2346608bcc6dSMat Martineau } 2347608bcc6dSMat Martineau 2348608bcc6dSMat Martineau return err; 2349608bcc6dSMat Martineau } 2350608bcc6dSMat Martineau 2351608bcc6dSMat Martineau static int l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 2352608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2353608bcc6dSMat Martineau { 2354608bcc6dSMat Martineau int err = 0; 2355608bcc6dSMat Martineau 2356608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d, state %d", 2357608bcc6dSMat Martineau chan, control, skbs, event, chan->tx_state); 2358608bcc6dSMat Martineau 2359608bcc6dSMat Martineau switch (chan->tx_state) { 2360608bcc6dSMat Martineau case L2CAP_TX_STATE_XMIT: 2361608bcc6dSMat Martineau err = l2cap_tx_state_xmit(chan, control, skbs, event); 2362608bcc6dSMat Martineau break; 2363608bcc6dSMat Martineau case L2CAP_TX_STATE_WAIT_F: 2364608bcc6dSMat Martineau err = l2cap_tx_state_wait_f(chan, control, skbs, event); 2365608bcc6dSMat Martineau break; 2366608bcc6dSMat Martineau default: 2367608bcc6dSMat Martineau /* Ignore event */ 2368608bcc6dSMat Martineau break; 2369608bcc6dSMat Martineau } 2370608bcc6dSMat Martineau 2371608bcc6dSMat Martineau return err; 2372608bcc6dSMat Martineau } 2373608bcc6dSMat Martineau 23744b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan, 23754b51dae9SMat Martineau struct l2cap_ctrl *control) 23764b51dae9SMat Martineau { 23774b51dae9SMat Martineau BT_DBG("chan %p, control %p", chan, control); 23784b51dae9SMat Martineau l2cap_tx(chan, control, 0, L2CAP_EV_RECV_REQSEQ_AND_FBIT); 23794b51dae9SMat Martineau } 23804b51dae9SMat Martineau 23810a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */ 23820a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 23830a708f8fSGustavo F. Padovan { 23840a708f8fSGustavo F. Padovan struct sk_buff *nskb; 238548454079SGustavo F. Padovan struct l2cap_chan *chan; 23860a708f8fSGustavo F. Padovan 23870a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 23880a708f8fSGustavo F. Padovan 23893df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 23903d57dc68SGustavo F. Padovan 23913df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 239248454079SGustavo F. Padovan struct sock *sk = chan->sk; 2393715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW) 23940a708f8fSGustavo F. Padovan continue; 23950a708f8fSGustavo F. Padovan 23960a708f8fSGustavo F. Padovan /* Don't send frame to the socket it came from */ 23970a708f8fSGustavo F. Padovan if (skb->sk == sk) 23980a708f8fSGustavo F. Padovan continue; 23990a708f8fSGustavo F. Padovan nskb = skb_clone(skb, GFP_ATOMIC); 24000a708f8fSGustavo F. Padovan if (!nskb) 24010a708f8fSGustavo F. Padovan continue; 24020a708f8fSGustavo F. Padovan 240323070494SGustavo F. Padovan if (chan->ops->recv(chan->data, nskb)) 24040a708f8fSGustavo F. Padovan kfree_skb(nskb); 24050a708f8fSGustavo F. Padovan } 24063d57dc68SGustavo F. Padovan 24073df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 24080a708f8fSGustavo F. Padovan } 24090a708f8fSGustavo F. Padovan 24100a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */ 24110a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 24120a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data) 24130a708f8fSGustavo F. Padovan { 24140a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag; 24150a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd; 24160a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 24170a708f8fSGustavo F. Padovan int len, count; 24180a708f8fSGustavo F. Padovan 24190a708f8fSGustavo F. Padovan BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d", 24200a708f8fSGustavo F. Padovan conn, code, ident, dlen); 24210a708f8fSGustavo F. Padovan 24220a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; 24230a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 24240a708f8fSGustavo F. Padovan 24250a708f8fSGustavo F. Padovan skb = bt_skb_alloc(count, GFP_ATOMIC); 24260a708f8fSGustavo F. Padovan if (!skb) 24270a708f8fSGustavo F. Padovan return NULL; 24280a708f8fSGustavo F. Padovan 24290a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 24300a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); 24313300d9a9SClaudio Takahasi 24323300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 24333300d9a9SClaudio Takahasi lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING); 24343300d9a9SClaudio Takahasi else 24350a708f8fSGustavo F. Padovan lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING); 24360a708f8fSGustavo F. Padovan 24370a708f8fSGustavo F. Padovan cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); 24380a708f8fSGustavo F. Padovan cmd->code = code; 24390a708f8fSGustavo F. Padovan cmd->ident = ident; 24400a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen); 24410a708f8fSGustavo F. Padovan 24420a708f8fSGustavo F. Padovan if (dlen) { 24430a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE; 24440a708f8fSGustavo F. Padovan memcpy(skb_put(skb, count), data, count); 24450a708f8fSGustavo F. Padovan data += count; 24460a708f8fSGustavo F. Padovan } 24470a708f8fSGustavo F. Padovan 24480a708f8fSGustavo F. Padovan len -= skb->len; 24490a708f8fSGustavo F. Padovan 24500a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 24510a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 24520a708f8fSGustavo F. Padovan while (len) { 24530a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 24540a708f8fSGustavo F. Padovan 24550a708f8fSGustavo F. Padovan *frag = bt_skb_alloc(count, GFP_ATOMIC); 24560a708f8fSGustavo F. Padovan if (!*frag) 24570a708f8fSGustavo F. Padovan goto fail; 24580a708f8fSGustavo F. Padovan 24590a708f8fSGustavo F. Padovan memcpy(skb_put(*frag, count), data, count); 24600a708f8fSGustavo F. Padovan 24610a708f8fSGustavo F. Padovan len -= count; 24620a708f8fSGustavo F. Padovan data += count; 24630a708f8fSGustavo F. Padovan 24640a708f8fSGustavo F. Padovan frag = &(*frag)->next; 24650a708f8fSGustavo F. Padovan } 24660a708f8fSGustavo F. Padovan 24670a708f8fSGustavo F. Padovan return skb; 24680a708f8fSGustavo F. Padovan 24690a708f8fSGustavo F. Padovan fail: 24700a708f8fSGustavo F. Padovan kfree_skb(skb); 24710a708f8fSGustavo F. Padovan return NULL; 24720a708f8fSGustavo F. Padovan } 24730a708f8fSGustavo F. Padovan 24740a708f8fSGustavo F. Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val) 24750a708f8fSGustavo F. Padovan { 24760a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 24770a708f8fSGustavo F. Padovan int len; 24780a708f8fSGustavo F. Padovan 24790a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len; 24800a708f8fSGustavo F. Padovan *ptr += len; 24810a708f8fSGustavo F. Padovan 24820a708f8fSGustavo F. Padovan *type = opt->type; 24830a708f8fSGustavo F. Padovan *olen = opt->len; 24840a708f8fSGustavo F. Padovan 24850a708f8fSGustavo F. Padovan switch (opt->len) { 24860a708f8fSGustavo F. Padovan case 1: 24870a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val); 24880a708f8fSGustavo F. Padovan break; 24890a708f8fSGustavo F. Padovan 24900a708f8fSGustavo F. Padovan case 2: 24910a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val); 24920a708f8fSGustavo F. Padovan break; 24930a708f8fSGustavo F. Padovan 24940a708f8fSGustavo F. Padovan case 4: 24950a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val); 24960a708f8fSGustavo F. Padovan break; 24970a708f8fSGustavo F. Padovan 24980a708f8fSGustavo F. Padovan default: 24990a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val; 25000a708f8fSGustavo F. Padovan break; 25010a708f8fSGustavo F. Padovan } 25020a708f8fSGustavo F. Padovan 25030a708f8fSGustavo F. Padovan BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val); 25040a708f8fSGustavo F. Padovan return len; 25050a708f8fSGustavo F. Padovan } 25060a708f8fSGustavo F. Padovan 25070a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) 25080a708f8fSGustavo F. Padovan { 25090a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 25100a708f8fSGustavo F. Padovan 25110a708f8fSGustavo F. Padovan BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val); 25120a708f8fSGustavo F. Padovan 25130a708f8fSGustavo F. Padovan opt->type = type; 25140a708f8fSGustavo F. Padovan opt->len = len; 25150a708f8fSGustavo F. Padovan 25160a708f8fSGustavo F. Padovan switch (len) { 25170a708f8fSGustavo F. Padovan case 1: 25180a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val; 25190a708f8fSGustavo F. Padovan break; 25200a708f8fSGustavo F. Padovan 25210a708f8fSGustavo F. Padovan case 2: 25220a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val); 25230a708f8fSGustavo F. Padovan break; 25240a708f8fSGustavo F. Padovan 25250a708f8fSGustavo F. Padovan case 4: 25260a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val); 25270a708f8fSGustavo F. Padovan break; 25280a708f8fSGustavo F. Padovan 25290a708f8fSGustavo F. Padovan default: 25300a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len); 25310a708f8fSGustavo F. Padovan break; 25320a708f8fSGustavo F. Padovan } 25330a708f8fSGustavo F. Padovan 25340a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len; 25350a708f8fSGustavo F. Padovan } 25360a708f8fSGustavo F. Padovan 2537f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) 2538f89cef09SAndrei Emeltchenko { 2539f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs; 2540f89cef09SAndrei Emeltchenko 2541f89cef09SAndrei Emeltchenko switch (chan->mode) { 2542f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM: 2543f89cef09SAndrei Emeltchenko efs.id = chan->local_id; 2544f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype; 2545f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 2546f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 2547f89cef09SAndrei Emeltchenko efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); 2548f89cef09SAndrei Emeltchenko efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO); 2549f89cef09SAndrei Emeltchenko break; 2550f89cef09SAndrei Emeltchenko 2551f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING: 2552f89cef09SAndrei Emeltchenko efs.id = 1; 2553f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT; 2554f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 2555f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 2556f89cef09SAndrei Emeltchenko efs.acc_lat = 0; 2557f89cef09SAndrei Emeltchenko efs.flush_to = 0; 2558f89cef09SAndrei Emeltchenko break; 2559f89cef09SAndrei Emeltchenko 2560f89cef09SAndrei Emeltchenko default: 2561f89cef09SAndrei Emeltchenko return; 2562f89cef09SAndrei Emeltchenko } 2563f89cef09SAndrei Emeltchenko 2564f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), 2565f89cef09SAndrei Emeltchenko (unsigned long) &efs); 2566f89cef09SAndrei Emeltchenko } 2567f89cef09SAndrei Emeltchenko 2568721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work) 25690a708f8fSGustavo F. Padovan { 2570721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 2571721c4181SGustavo F. Padovan ack_timer.work); 25720a708f8fSGustavo F. Padovan 25732fb9b3d4SGustavo F. Padovan BT_DBG("chan %p", chan); 25742fb9b3d4SGustavo F. Padovan 25756be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 25766be36555SAndrei Emeltchenko 25770a0aba42SMat Martineau l2cap_send_ack(chan); 25786be36555SAndrei Emeltchenko 25796be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 258009bfb2eeSSzymon Janc 258109bfb2eeSSzymon Janc l2cap_chan_put(chan); 25820a708f8fSGustavo F. Padovan } 25830a708f8fSGustavo F. Padovan 25843c588192SMat Martineau static inline int l2cap_ertm_init(struct l2cap_chan *chan) 25850a708f8fSGustavo F. Padovan { 25863c588192SMat Martineau int err; 25873c588192SMat Martineau 2588105bdf9eSMat Martineau chan->next_tx_seq = 0; 2589105bdf9eSMat Martineau chan->expected_tx_seq = 0; 259042e5c802SGustavo F. Padovan chan->expected_ack_seq = 0; 25916a026610SGustavo F. Padovan chan->unacked_frames = 0; 259242e5c802SGustavo F. Padovan chan->buffer_seq = 0; 25936a026610SGustavo F. Padovan chan->frames_sent = 0; 2594105bdf9eSMat Martineau chan->last_acked_seq = 0; 2595105bdf9eSMat Martineau chan->sdu = NULL; 2596105bdf9eSMat Martineau chan->sdu_last_frag = NULL; 2597105bdf9eSMat Martineau chan->sdu_len = 0; 2598105bdf9eSMat Martineau 2599d34c34fbSMat Martineau skb_queue_head_init(&chan->tx_q); 2600d34c34fbSMat Martineau 2601105bdf9eSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 2602105bdf9eSMat Martineau return 0; 2603105bdf9eSMat Martineau 2604105bdf9eSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2605105bdf9eSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 26060a708f8fSGustavo F. Padovan 2607721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout); 2608721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout); 2609721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout); 26100a708f8fSGustavo F. Padovan 2611f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q); 26120a708f8fSGustavo F. Padovan 26133c588192SMat Martineau err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win); 26143c588192SMat Martineau if (err < 0) 26153c588192SMat Martineau return err; 26163c588192SMat Martineau 26179dc9affcSMat Martineau err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win); 26189dc9affcSMat Martineau if (err < 0) 26199dc9affcSMat Martineau l2cap_seq_list_free(&chan->srej_list); 26209dc9affcSMat Martineau 26219dc9affcSMat Martineau return err; 26220a708f8fSGustavo F. Padovan } 26230a708f8fSGustavo F. Padovan 26240a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) 26250a708f8fSGustavo F. Padovan { 26260a708f8fSGustavo F. Padovan switch (mode) { 26270a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 26280a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 26290a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask)) 26300a708f8fSGustavo F. Padovan return mode; 26310a708f8fSGustavo F. Padovan /* fall through */ 26320a708f8fSGustavo F. Padovan default: 26330a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC; 26340a708f8fSGustavo F. Padovan } 26350a708f8fSGustavo F. Padovan } 26360a708f8fSGustavo F. Padovan 26376327eb98SAndrei Emeltchenko static inline bool __l2cap_ews_supported(struct l2cap_chan *chan) 26386327eb98SAndrei Emeltchenko { 26396327eb98SAndrei Emeltchenko return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW; 26406327eb98SAndrei Emeltchenko } 26416327eb98SAndrei Emeltchenko 2642f89cef09SAndrei Emeltchenko static inline bool __l2cap_efs_supported(struct l2cap_chan *chan) 2643f89cef09SAndrei Emeltchenko { 2644f89cef09SAndrei Emeltchenko return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW; 2645f89cef09SAndrei Emeltchenko } 2646f89cef09SAndrei Emeltchenko 26476327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan) 26486327eb98SAndrei Emeltchenko { 26496327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && 2650836be934SAndrei Emeltchenko __l2cap_ews_supported(chan)) { 26516327eb98SAndrei Emeltchenko /* use extended control field */ 26526327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 2653836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 2654836be934SAndrei Emeltchenko } else { 26556327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win, 26566327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 2657836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 2658836be934SAndrei Emeltchenko } 26596327eb98SAndrei Emeltchenko } 26606327eb98SAndrei Emeltchenko 2661710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) 26620a708f8fSGustavo F. Padovan { 26630a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 26640c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode }; 26650a708f8fSGustavo F. Padovan void *ptr = req->data; 2666c8f79162SAndrei Emeltchenko u16 size; 26670a708f8fSGustavo F. Padovan 266849208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 26690a708f8fSGustavo F. Padovan 267073ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp) 26710a708f8fSGustavo F. Padovan goto done; 26720a708f8fSGustavo F. Padovan 26730c1bc5c6SGustavo F. Padovan switch (chan->mode) { 26740a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 26750a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 2676c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) 26770a708f8fSGustavo F. Padovan break; 26780a708f8fSGustavo F. Padovan 2679f89cef09SAndrei Emeltchenko if (__l2cap_efs_supported(chan)) 2680f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 2681f89cef09SAndrei Emeltchenko 26820a708f8fSGustavo F. Padovan /* fall through */ 26830a708f8fSGustavo F. Padovan default: 26848c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); 26850a708f8fSGustavo F. Padovan break; 26860a708f8fSGustavo F. Padovan } 26870a708f8fSGustavo F. Padovan 26880a708f8fSGustavo F. Padovan done: 26890c1bc5c6SGustavo F. Padovan if (chan->imtu != L2CAP_DEFAULT_MTU) 26900c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 26910a708f8fSGustavo F. Padovan 26920c1bc5c6SGustavo F. Padovan switch (chan->mode) { 26930a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 26948c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && 26958c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) 26960a708f8fSGustavo F. Padovan break; 26970a708f8fSGustavo F. Padovan 26980a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC; 26990a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 27000a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 27010a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 27020a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 27030a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0; 27040a708f8fSGustavo F. Padovan 27050a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 27060a708f8fSGustavo F. Padovan (unsigned long) &rfc); 27070a708f8fSGustavo F. Padovan break; 27080a708f8fSGustavo F. Padovan 27090a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 27100a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM; 271147d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx; 27120a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 27130a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 2714c8f79162SAndrei Emeltchenko 2715c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 2716c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2717c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2718c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2719c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 27200a708f8fSGustavo F. Padovan 27216327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan); 27226327eb98SAndrei Emeltchenko 27236327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win, 27246327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 27250a708f8fSGustavo F. Padovan 27260a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 27270a708f8fSGustavo F. Padovan (unsigned long) &rfc); 27280a708f8fSGustavo F. Padovan 2729f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 2730f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 2731f89cef09SAndrei Emeltchenko 27328c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) 27330a708f8fSGustavo F. Padovan break; 27340a708f8fSGustavo F. Padovan 273547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 2736c1360a1cSGustavo F. Padovan test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { 273747d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 273847d1ec61SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); 27390a708f8fSGustavo F. Padovan } 27406327eb98SAndrei Emeltchenko 27416327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 27426327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 27436327eb98SAndrei Emeltchenko chan->tx_win); 27440a708f8fSGustavo F. Padovan break; 27450a708f8fSGustavo F. Padovan 27460a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 27470a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING; 27480a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 27490a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 27500a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 27510a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 2752c8f79162SAndrei Emeltchenko 2753c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 2754c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2755c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2756c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2757c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 27580a708f8fSGustavo F. Padovan 27590a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 27600a708f8fSGustavo F. Padovan (unsigned long) &rfc); 27610a708f8fSGustavo F. Padovan 2762f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 2763f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 2764f89cef09SAndrei Emeltchenko 27658c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) 27660a708f8fSGustavo F. Padovan break; 27670a708f8fSGustavo F. Padovan 276847d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 2769c1360a1cSGustavo F. Padovan test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { 277047d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 277147d1ec61SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); 27720a708f8fSGustavo F. Padovan } 27730a708f8fSGustavo F. Padovan break; 27740a708f8fSGustavo F. Padovan } 27750a708f8fSGustavo F. Padovan 2776fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 27770a708f8fSGustavo F. Padovan req->flags = cpu_to_le16(0); 27780a708f8fSGustavo F. Padovan 27790a708f8fSGustavo F. Padovan return ptr - data; 27800a708f8fSGustavo F. Padovan } 27810a708f8fSGustavo F. Padovan 278273ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) 27830a708f8fSGustavo F. Padovan { 27840a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 27850a708f8fSGustavo F. Padovan void *ptr = rsp->data; 278673ffa904SGustavo F. Padovan void *req = chan->conf_req; 278773ffa904SGustavo F. Padovan int len = chan->conf_len; 27880a708f8fSGustavo F. Padovan int type, hint, olen; 27890a708f8fSGustavo F. Padovan unsigned long val; 27900a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 279142dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs; 279242dceae2SAndrei Emeltchenko u8 remote_efs = 0; 27930a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU; 27940a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS; 2795c8f79162SAndrei Emeltchenko u16 size; 27960a708f8fSGustavo F. Padovan 279773ffa904SGustavo F. Padovan BT_DBG("chan %p", chan); 27980a708f8fSGustavo F. Padovan 27990a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 28000a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val); 28010a708f8fSGustavo F. Padovan 28020a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT; 28030a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK; 28040a708f8fSGustavo F. Padovan 28050a708f8fSGustavo F. Padovan switch (type) { 28060a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 28070a708f8fSGustavo F. Padovan mtu = val; 28080a708f8fSGustavo F. Padovan break; 28090a708f8fSGustavo F. Padovan 28100a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 28110c1bc5c6SGustavo F. Padovan chan->flush_to = val; 28120a708f8fSGustavo F. Padovan break; 28130a708f8fSGustavo F. Padovan 28140a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS: 28150a708f8fSGustavo F. Padovan break; 28160a708f8fSGustavo F. Padovan 28170a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 28180a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 28190a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen); 28200a708f8fSGustavo F. Padovan break; 28210a708f8fSGustavo F. Padovan 28220a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS: 28230a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE) 2824c1360a1cSGustavo F. Padovan set_bit(CONF_NO_FCS_RECV, &chan->conf_state); 282542dceae2SAndrei Emeltchenko break; 28260a708f8fSGustavo F. Padovan 282742dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS: 282842dceae2SAndrei Emeltchenko remote_efs = 1; 282942dceae2SAndrei Emeltchenko if (olen == sizeof(efs)) 283042dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen); 28310a708f8fSGustavo F. Padovan break; 28320a708f8fSGustavo F. Padovan 28336327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 28346327eb98SAndrei Emeltchenko if (!enable_hs) 28356327eb98SAndrei Emeltchenko return -ECONNREFUSED; 28366327eb98SAndrei Emeltchenko 28376327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 28386327eb98SAndrei Emeltchenko set_bit(CONF_EWS_RECV, &chan->conf_state); 2839836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 28406327eb98SAndrei Emeltchenko chan->remote_tx_win = val; 28410a708f8fSGustavo F. Padovan break; 28420a708f8fSGustavo F. Padovan 28430a708f8fSGustavo F. Padovan default: 28440a708f8fSGustavo F. Padovan if (hint) 28450a708f8fSGustavo F. Padovan break; 28460a708f8fSGustavo F. Padovan 28470a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN; 28480a708f8fSGustavo F. Padovan *((u8 *) ptr++) = type; 28490a708f8fSGustavo F. Padovan break; 28500a708f8fSGustavo F. Padovan } 28510a708f8fSGustavo F. Padovan } 28520a708f8fSGustavo F. Padovan 285373ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1) 28540a708f8fSGustavo F. Padovan goto done; 28550a708f8fSGustavo F. Padovan 28560c1bc5c6SGustavo F. Padovan switch (chan->mode) { 28570a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 28580a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 2859c1360a1cSGustavo F. Padovan if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { 28600c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, 28618c1d787bSGustavo F. Padovan chan->conn->feat_mask); 28620a708f8fSGustavo F. Padovan break; 28630a708f8fSGustavo F. Padovan } 28640a708f8fSGustavo F. Padovan 286542dceae2SAndrei Emeltchenko if (remote_efs) { 286642dceae2SAndrei Emeltchenko if (__l2cap_efs_supported(chan)) 286742dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 286842dceae2SAndrei Emeltchenko else 286942dceae2SAndrei Emeltchenko return -ECONNREFUSED; 287042dceae2SAndrei Emeltchenko } 287142dceae2SAndrei Emeltchenko 28720c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) 28730a708f8fSGustavo F. Padovan return -ECONNREFUSED; 28740a708f8fSGustavo F. Padovan 28750a708f8fSGustavo F. Padovan break; 28760a708f8fSGustavo F. Padovan } 28770a708f8fSGustavo F. Padovan 28780a708f8fSGustavo F. Padovan done: 28790c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) { 28800a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 28810c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 28820a708f8fSGustavo F. Padovan 288373ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1) 28840a708f8fSGustavo F. Padovan return -ECONNREFUSED; 28850a708f8fSGustavo F. Padovan 28860a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 28870a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 28880a708f8fSGustavo F. Padovan } 28890a708f8fSGustavo F. Padovan 28900a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) { 28910a708f8fSGustavo F. Padovan /* Configure output options and let the other side know 28920a708f8fSGustavo F. Padovan * which ones we don't like. */ 28930a708f8fSGustavo F. Padovan 28940a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU) 28950a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 28960a708f8fSGustavo F. Padovan else { 28970c1bc5c6SGustavo F. Padovan chan->omtu = mtu; 2898c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state); 28990a708f8fSGustavo F. Padovan } 29000c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); 29010a708f8fSGustavo F. Padovan 290242dceae2SAndrei Emeltchenko if (remote_efs) { 290342dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 290442dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 290542dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) { 290642dceae2SAndrei Emeltchenko 290742dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT; 290842dceae2SAndrei Emeltchenko 290942dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1) 291042dceae2SAndrei Emeltchenko return -ECONNREFUSED; 291142dceae2SAndrei Emeltchenko 291242dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 291342dceae2SAndrei Emeltchenko sizeof(efs), 291442dceae2SAndrei Emeltchenko (unsigned long) &efs); 29150e8b207eSAndrei Emeltchenko } else { 29163e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */ 29170e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING; 29180e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 291942dceae2SAndrei Emeltchenko } 292042dceae2SAndrei Emeltchenko } 292142dceae2SAndrei Emeltchenko 29220a708f8fSGustavo F. Padovan switch (rfc.mode) { 29230a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 292447d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 2925c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 29260a708f8fSGustavo F. Padovan break; 29270a708f8fSGustavo F. Padovan 29280a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 29296327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state)) 29302c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size; 29316327eb98SAndrei Emeltchenko else 29326327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; 29336327eb98SAndrei Emeltchenko 29342c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit; 29350a708f8fSGustavo F. Padovan 2936c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 2937c8f79162SAndrei Emeltchenko chan->conn->mtu - 2938c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2939c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2940c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2941c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 2942c8f79162SAndrei Emeltchenko chan->remote_mps = size; 29430a708f8fSGustavo F. Padovan 29440a708f8fSGustavo F. Padovan rfc.retrans_timeout = 29454fd21a88SAndrei Emeltchenko __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 29460a708f8fSGustavo F. Padovan rfc.monitor_timeout = 29474fd21a88SAndrei Emeltchenko __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 29480a708f8fSGustavo F. Padovan 2949c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 29500a708f8fSGustavo F. Padovan 29510a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 29520a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 29530a708f8fSGustavo F. Padovan 295442dceae2SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 295542dceae2SAndrei Emeltchenko chan->remote_id = efs.id; 295642dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype; 295742dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu); 295842dceae2SAndrei Emeltchenko chan->remote_flush_to = 295942dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to); 296042dceae2SAndrei Emeltchenko chan->remote_acc_lat = 296142dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat); 296242dceae2SAndrei Emeltchenko chan->remote_sdu_itime = 296342dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 296442dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 296542dceae2SAndrei Emeltchenko sizeof(efs), (unsigned long) &efs); 296642dceae2SAndrei Emeltchenko } 29670a708f8fSGustavo F. Padovan break; 29680a708f8fSGustavo F. Padovan 29690a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 2970c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 2971c8f79162SAndrei Emeltchenko chan->conn->mtu - 2972c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2973c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2974c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2975c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 2976c8f79162SAndrei Emeltchenko chan->remote_mps = size; 29770a708f8fSGustavo F. Padovan 2978c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 29790a708f8fSGustavo F. Padovan 29800a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 29810a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 29820a708f8fSGustavo F. Padovan 29830a708f8fSGustavo F. Padovan break; 29840a708f8fSGustavo F. Padovan 29850a708f8fSGustavo F. Padovan default: 29860a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 29870a708f8fSGustavo F. Padovan 29880a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc)); 29890c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 29900a708f8fSGustavo F. Padovan } 29910a708f8fSGustavo F. Padovan 29920a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) 2993c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 29940a708f8fSGustavo F. Padovan } 2995fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 29960a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 29970a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(0x0000); 29980a708f8fSGustavo F. Padovan 29990a708f8fSGustavo F. Padovan return ptr - data; 30000a708f8fSGustavo F. Padovan } 30010a708f8fSGustavo F. Padovan 3002b4450035SGustavo F. Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result) 30030a708f8fSGustavo F. Padovan { 30040a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 30050a708f8fSGustavo F. Padovan void *ptr = req->data; 30060a708f8fSGustavo F. Padovan int type, olen; 30070a708f8fSGustavo F. Padovan unsigned long val; 300836e999a8SMat Martineau struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 300966af7aafSAndrei Emeltchenko struct l2cap_conf_efs efs; 30100a708f8fSGustavo F. Padovan 3011fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); 30120a708f8fSGustavo F. Padovan 30130a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 30140a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 30150a708f8fSGustavo F. Padovan 30160a708f8fSGustavo F. Padovan switch (type) { 30170a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 30180a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) { 30190a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT; 30200c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU; 30210a708f8fSGustavo F. Padovan } else 30220c1bc5c6SGustavo F. Padovan chan->imtu = val; 30230c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 30240a708f8fSGustavo F. Padovan break; 30250a708f8fSGustavo F. Padovan 30260a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 30270c1bc5c6SGustavo F. Padovan chan->flush_to = val; 30280a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 30290c1bc5c6SGustavo F. Padovan 2, chan->flush_to); 30300a708f8fSGustavo F. Padovan break; 30310a708f8fSGustavo F. Padovan 30320a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 30330a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 30340a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 30350a708f8fSGustavo F. Padovan 3036c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && 30370c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode) 30380a708f8fSGustavo F. Padovan return -ECONNREFUSED; 30390a708f8fSGustavo F. Padovan 304047d1ec61SGustavo F. Padovan chan->fcs = 0; 30410a708f8fSGustavo F. Padovan 30420a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 30430a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 30440a708f8fSGustavo F. Padovan break; 30456327eb98SAndrei Emeltchenko 30466327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 30476327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, val, 30486327eb98SAndrei Emeltchenko L2CAP_DEFAULT_EXT_WINDOW); 30493e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 30503e6b3b95SGustavo F. Padovan chan->tx_win); 30516327eb98SAndrei Emeltchenko break; 305266af7aafSAndrei Emeltchenko 305366af7aafSAndrei Emeltchenko case L2CAP_CONF_EFS: 305466af7aafSAndrei Emeltchenko if (olen == sizeof(efs)) 305566af7aafSAndrei Emeltchenko memcpy(&efs, (void *)val, olen); 305666af7aafSAndrei Emeltchenko 305766af7aafSAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 305866af7aafSAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 305966af7aafSAndrei Emeltchenko efs.stype != chan->local_stype) 306066af7aafSAndrei Emeltchenko return -ECONNREFUSED; 306166af7aafSAndrei Emeltchenko 306266af7aafSAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 306366af7aafSAndrei Emeltchenko sizeof(efs), (unsigned long) &efs); 306466af7aafSAndrei Emeltchenko break; 30650a708f8fSGustavo F. Padovan } 30660a708f8fSGustavo F. Padovan } 30670a708f8fSGustavo F. Padovan 30680c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) 30690a708f8fSGustavo F. Padovan return -ECONNREFUSED; 30700a708f8fSGustavo F. Padovan 30710c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode; 30720a708f8fSGustavo F. Padovan 30730e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) { 30740a708f8fSGustavo F. Padovan switch (rfc.mode) { 30750a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 307647d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 307747d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 307847d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 307966af7aafSAndrei Emeltchenko 308066af7aafSAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 308166af7aafSAndrei Emeltchenko chan->local_msdu = le16_to_cpu(efs.msdu); 308266af7aafSAndrei Emeltchenko chan->local_sdu_itime = 308366af7aafSAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 308466af7aafSAndrei Emeltchenko chan->local_acc_lat = le32_to_cpu(efs.acc_lat); 308566af7aafSAndrei Emeltchenko chan->local_flush_to = 308666af7aafSAndrei Emeltchenko le32_to_cpu(efs.flush_to); 308766af7aafSAndrei Emeltchenko } 30880a708f8fSGustavo F. Padovan break; 308966af7aafSAndrei Emeltchenko 30900a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 309147d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 30920a708f8fSGustavo F. Padovan } 30930a708f8fSGustavo F. Padovan } 30940a708f8fSGustavo F. Padovan 3095fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 30960a708f8fSGustavo F. Padovan req->flags = cpu_to_le16(0x0000); 30970a708f8fSGustavo F. Padovan 30980a708f8fSGustavo F. Padovan return ptr - data; 30990a708f8fSGustavo F. Padovan } 31000a708f8fSGustavo F. Padovan 3101fe4128e0SGustavo F. Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags) 31020a708f8fSGustavo F. Padovan { 31030a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 31040a708f8fSGustavo F. Padovan void *ptr = rsp->data; 31050a708f8fSGustavo F. Padovan 3106fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan); 31070a708f8fSGustavo F. Padovan 3108fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 31090a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 31100a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags); 31110a708f8fSGustavo F. Padovan 31120a708f8fSGustavo F. Padovan return ptr - data; 31130a708f8fSGustavo F. Padovan } 31140a708f8fSGustavo F. Padovan 31158c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) 3116710f9b0aSGustavo F. Padovan { 3117710f9b0aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 31188c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 3119710f9b0aSGustavo F. Padovan u8 buf[128]; 3120710f9b0aSGustavo F. Padovan 3121fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 3122fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3123710f9b0aSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 3124710f9b0aSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 3125710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, 3126710f9b0aSGustavo F. Padovan L2CAP_CONN_RSP, sizeof(rsp), &rsp); 3127710f9b0aSGustavo F. Padovan 3128c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 3129710f9b0aSGustavo F. Padovan return; 3130710f9b0aSGustavo F. Padovan 3131710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 3132710f9b0aSGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 3133710f9b0aSGustavo F. Padovan chan->num_conf_req++; 3134710f9b0aSGustavo F. Padovan } 3135710f9b0aSGustavo F. Padovan 313647d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) 31370a708f8fSGustavo F. Padovan { 31380a708f8fSGustavo F. Padovan int type, olen; 31390a708f8fSGustavo F. Padovan unsigned long val; 31400a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc; 31410a708f8fSGustavo F. Padovan 314247d1ec61SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); 31430a708f8fSGustavo F. Padovan 31440c1bc5c6SGustavo F. Padovan if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) 31450a708f8fSGustavo F. Padovan return; 31460a708f8fSGustavo F. Padovan 31470a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 31480a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 31490a708f8fSGustavo F. Padovan 31500a708f8fSGustavo F. Padovan switch (type) { 31510a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 31520a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 31530a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 31540a708f8fSGustavo F. Padovan goto done; 31550a708f8fSGustavo F. Padovan } 31560a708f8fSGustavo F. Padovan } 31570a708f8fSGustavo F. Padovan 315836e999a8SMat Martineau /* Use sane default values in case a misbehaving remote device 315936e999a8SMat Martineau * did not send an RFC option. 316036e999a8SMat Martineau */ 316136e999a8SMat Martineau rfc.mode = chan->mode; 316236e999a8SMat Martineau rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 316336e999a8SMat Martineau rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 316436e999a8SMat Martineau rfc.max_pdu_size = cpu_to_le16(chan->imtu); 316536e999a8SMat Martineau 316636e999a8SMat Martineau BT_ERR("Expected RFC option was not found, using defaults"); 316736e999a8SMat Martineau 31680a708f8fSGustavo F. Padovan done: 31690a708f8fSGustavo F. Padovan switch (rfc.mode) { 31700a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 317147d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 317247d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 317347d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 31740a708f8fSGustavo F. Padovan break; 31750a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 317647d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 31770a708f8fSGustavo F. Padovan } 31780a708f8fSGustavo F. Padovan } 31790a708f8fSGustavo F. Padovan 31800a708f8fSGustavo F. Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 31810a708f8fSGustavo F. Padovan { 3182e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 31830a708f8fSGustavo F. Padovan 3184e2fd318eSIlia Kolomisnky if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) 31850a708f8fSGustavo F. Padovan return 0; 31860a708f8fSGustavo F. Padovan 31870a708f8fSGustavo F. Padovan if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && 31880a708f8fSGustavo F. Padovan cmd->ident == conn->info_ident) { 318917cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 31900a708f8fSGustavo F. Padovan 31910a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 31920a708f8fSGustavo F. Padovan conn->info_ident = 0; 31930a708f8fSGustavo F. Padovan 31940a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 31950a708f8fSGustavo F. Padovan } 31960a708f8fSGustavo F. Padovan 31970a708f8fSGustavo F. Padovan return 0; 31980a708f8fSGustavo F. Padovan } 31990a708f8fSGustavo F. Padovan 32000a708f8fSGustavo F. Padovan static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 32010a708f8fSGustavo F. Padovan { 32020a708f8fSGustavo F. Padovan struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 32030a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 320423691d75SGustavo F. Padovan struct l2cap_chan *chan = NULL, *pchan; 32050a708f8fSGustavo F. Padovan struct sock *parent, *sk = NULL; 32060a708f8fSGustavo F. Padovan int result, status = L2CAP_CS_NO_INFO; 32070a708f8fSGustavo F. Padovan 32080a708f8fSGustavo F. Padovan u16 dcid = 0, scid = __le16_to_cpu(req->scid); 32090a708f8fSGustavo F. Padovan __le16 psm = req->psm; 32100a708f8fSGustavo F. Padovan 3211097db76cSAndrei Emeltchenko BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); 32120a708f8fSGustavo F. Padovan 32130a708f8fSGustavo F. Padovan /* Check if we have socket listening on psm */ 3214c2287681SIdo Yariv pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst); 321523691d75SGustavo F. Padovan if (!pchan) { 32160a708f8fSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 32170a708f8fSGustavo F. Padovan goto sendresp; 32180a708f8fSGustavo F. Padovan } 32190a708f8fSGustavo F. Padovan 322023691d75SGustavo F. Padovan parent = pchan->sk; 322123691d75SGustavo F. Padovan 32223df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 3223aa2ac881SGustavo F. Padovan lock_sock(parent); 32240a708f8fSGustavo F. Padovan 32250a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */ 32260a708f8fSGustavo F. Padovan if (psm != cpu_to_le16(0x0001) && 32270a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) { 32289f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_AUTH_FAILURE; 32290a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 32300a708f8fSGustavo F. Padovan goto response; 32310a708f8fSGustavo F. Padovan } 32320a708f8fSGustavo F. Padovan 32330a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM; 32340a708f8fSGustavo F. Padovan 32350a708f8fSGustavo F. Padovan /* Check for backlog size */ 32360a708f8fSGustavo F. Padovan if (sk_acceptq_is_full(parent)) { 32370a708f8fSGustavo F. Padovan BT_DBG("backlog full %d", parent->sk_ack_backlog); 32380a708f8fSGustavo F. Padovan goto response; 32390a708f8fSGustavo F. Padovan } 32400a708f8fSGustavo F. Padovan 324180808e43SGustavo F. Padovan chan = pchan->ops->new_connection(pchan->data); 324280808e43SGustavo F. Padovan if (!chan) 32430a708f8fSGustavo F. Padovan goto response; 32440a708f8fSGustavo F. Padovan 324580808e43SGustavo F. Padovan sk = chan->sk; 324680808e43SGustavo F. Padovan 32470a708f8fSGustavo F. Padovan /* Check if we already have channel with that dcid */ 3248baa7e1faSGustavo F. Padovan if (__l2cap_get_chan_by_dcid(conn, scid)) { 32490a708f8fSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 3250ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 32510a708f8fSGustavo F. Padovan goto response; 32520a708f8fSGustavo F. Padovan } 32530a708f8fSGustavo F. Padovan 32540a708f8fSGustavo F. Padovan hci_conn_hold(conn->hcon); 32550a708f8fSGustavo F. Padovan 32560a708f8fSGustavo F. Padovan bacpy(&bt_sk(sk)->src, conn->src); 32570a708f8fSGustavo F. Padovan bacpy(&bt_sk(sk)->dst, conn->dst); 3258fe4128e0SGustavo F. Padovan chan->psm = psm; 3259fe4128e0SGustavo F. Padovan chan->dcid = scid; 32600a708f8fSGustavo F. Padovan 3261d1010240SGustavo F. Padovan bt_accept_enqueue(parent, sk); 3262d1010240SGustavo F. Padovan 32636be36555SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 326448454079SGustavo F. Padovan 3265fe4128e0SGustavo F. Padovan dcid = chan->scid; 32660a708f8fSGustavo F. Padovan 3267c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 32680a708f8fSGustavo F. Padovan 3269fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident; 32700a708f8fSGustavo F. Padovan 32710a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { 3272d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 3273c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) { 32740e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 32750a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 32760a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND; 32770a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 32780a708f8fSGustavo F. Padovan } else { 32790e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 32800a708f8fSGustavo F. Padovan result = L2CAP_CR_SUCCESS; 32810a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 32820a708f8fSGustavo F. Padovan } 32830a708f8fSGustavo F. Padovan } else { 32840e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 32850a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 32860a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND; 32870a708f8fSGustavo F. Padovan } 32880a708f8fSGustavo F. Padovan } else { 32890e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 32900a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 32910a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 32920a708f8fSGustavo F. Padovan } 32930a708f8fSGustavo F. Padovan 32940a708f8fSGustavo F. Padovan response: 3295aa2ac881SGustavo F. Padovan release_sock(parent); 32963df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 32970a708f8fSGustavo F. Padovan 32980a708f8fSGustavo F. Padovan sendresp: 32990a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid); 33000a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid); 33010a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result); 33020a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status); 33030a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); 33040a708f8fSGustavo F. Padovan 33050a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { 33060a708f8fSGustavo F. Padovan struct l2cap_info_req info; 33070a708f8fSGustavo F. Padovan info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 33080a708f8fSGustavo F. Padovan 33090a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 33100a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 33110a708f8fSGustavo F. Padovan 3312ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 33130a708f8fSGustavo F. Padovan 33140a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 33150a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(info), &info); 33160a708f8fSGustavo F. Padovan } 33170a708f8fSGustavo F. Padovan 3318c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && 33190a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) { 33200a708f8fSGustavo F. Padovan u8 buf[128]; 3321c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 33220a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 332373ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 332473ffa904SGustavo F. Padovan chan->num_conf_req++; 33250a708f8fSGustavo F. Padovan } 33260a708f8fSGustavo F. Padovan 33270a708f8fSGustavo F. Padovan return 0; 33280a708f8fSGustavo F. Padovan } 33290a708f8fSGustavo F. Padovan 33300a708f8fSGustavo F. Padovan static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 33310a708f8fSGustavo F. Padovan { 33320a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; 33330a708f8fSGustavo F. Padovan u16 scid, dcid, result, status; 333448454079SGustavo F. Padovan struct l2cap_chan *chan; 33350a708f8fSGustavo F. Padovan u8 req[128]; 33363df91ea2SAndrei Emeltchenko int err; 33370a708f8fSGustavo F. Padovan 33380a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 33390a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 33400a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 33410a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status); 33420a708f8fSGustavo F. Padovan 33431b009c98SAndrei Emeltchenko BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", 33441b009c98SAndrei Emeltchenko dcid, scid, result, status); 33450a708f8fSGustavo F. Padovan 33463df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 33473df91ea2SAndrei Emeltchenko 33480a708f8fSGustavo F. Padovan if (scid) { 33493df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 33503df91ea2SAndrei Emeltchenko if (!chan) { 33513df91ea2SAndrei Emeltchenko err = -EFAULT; 33523df91ea2SAndrei Emeltchenko goto unlock; 33533df91ea2SAndrei Emeltchenko } 33540a708f8fSGustavo F. Padovan } else { 33553df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 33563df91ea2SAndrei Emeltchenko if (!chan) { 33573df91ea2SAndrei Emeltchenko err = -EFAULT; 33583df91ea2SAndrei Emeltchenko goto unlock; 33593df91ea2SAndrei Emeltchenko } 33600a708f8fSGustavo F. Padovan } 33610a708f8fSGustavo F. Padovan 33623df91ea2SAndrei Emeltchenko err = 0; 33633df91ea2SAndrei Emeltchenko 33646be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 336548454079SGustavo F. Padovan 33660a708f8fSGustavo F. Padovan switch (result) { 33670a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS: 336889bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 3369fc7f8a7eSGustavo F. Padovan chan->ident = 0; 3370fe4128e0SGustavo F. Padovan chan->dcid = dcid; 3371c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state); 33720a708f8fSGustavo F. Padovan 3373c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 33740a708f8fSGustavo F. Padovan break; 33750a708f8fSGustavo F. Padovan 33760a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 337773ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, req), req); 337873ffa904SGustavo F. Padovan chan->num_conf_req++; 33790a708f8fSGustavo F. Padovan break; 33800a708f8fSGustavo F. Padovan 33810a708f8fSGustavo F. Padovan case L2CAP_CR_PEND: 3382c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 33830a708f8fSGustavo F. Padovan break; 33840a708f8fSGustavo F. Padovan 33850a708f8fSGustavo F. Padovan default: 338648454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED); 33870a708f8fSGustavo F. Padovan break; 33880a708f8fSGustavo F. Padovan } 33890a708f8fSGustavo F. Padovan 33906be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 33913df91ea2SAndrei Emeltchenko 33923df91ea2SAndrei Emeltchenko unlock: 33933df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 33943df91ea2SAndrei Emeltchenko 33953df91ea2SAndrei Emeltchenko return err; 33960a708f8fSGustavo F. Padovan } 33970a708f8fSGustavo F. Padovan 339847d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan) 33990a708f8fSGustavo F. Padovan { 34000a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both 34010a708f8fSGustavo F. Padovan * sides request it. 34020a708f8fSGustavo F. Padovan */ 34030c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) 340447d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3405c1360a1cSGustavo F. Padovan else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) 340647d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16; 34070a708f8fSGustavo F. Padovan } 34080a708f8fSGustavo F. Padovan 34090a708f8fSGustavo F. Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 34100a708f8fSGustavo F. Padovan { 34110a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; 34120a708f8fSGustavo F. Padovan u16 dcid, flags; 34130a708f8fSGustavo F. Padovan u8 rsp[64]; 341448454079SGustavo F. Padovan struct l2cap_chan *chan; 34153c588192SMat Martineau int len, err = 0; 34160a708f8fSGustavo F. Padovan 34170a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 34180a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags); 34190a708f8fSGustavo F. Padovan 34200a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); 34210a708f8fSGustavo F. Padovan 3422baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid); 342348454079SGustavo F. Padovan if (!chan) 34240a708f8fSGustavo F. Padovan return -ENOENT; 34250a708f8fSGustavo F. Padovan 3426033b1142SDavid S. Miller if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { 3427e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_cid rej; 34280a708f8fSGustavo F. Padovan 3429e2fd318eSIlia Kolomisnky rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID); 3430e2fd318eSIlia Kolomisnky rej.scid = cpu_to_le16(chan->scid); 3431e2fd318eSIlia Kolomisnky rej.dcid = cpu_to_le16(chan->dcid); 3432e2fd318eSIlia Kolomisnky 34330a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 34340a708f8fSGustavo F. Padovan sizeof(rej), &rej); 34350a708f8fSGustavo F. Padovan goto unlock; 34360a708f8fSGustavo F. Padovan } 34370a708f8fSGustavo F. Padovan 34380a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */ 34390a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req); 34407ac28817SDan Rosenberg if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) { 34410a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 3442fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 34430a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp); 34440a708f8fSGustavo F. Padovan goto unlock; 34450a708f8fSGustavo F. Padovan } 34460a708f8fSGustavo F. Padovan 34470a708f8fSGustavo F. Padovan /* Store config. */ 344873ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len); 344973ffa904SGustavo F. Padovan chan->conf_len += len; 34500a708f8fSGustavo F. Padovan 34510a708f8fSGustavo F. Padovan if (flags & 0x0001) { 34520a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */ 34530a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 3454fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 34550a708f8fSGustavo F. Padovan L2CAP_CONF_SUCCESS, 0x0001), rsp); 34560a708f8fSGustavo F. Padovan goto unlock; 34570a708f8fSGustavo F. Padovan } 34580a708f8fSGustavo F. Padovan 34590a708f8fSGustavo F. Padovan /* Complete config. */ 346073ffa904SGustavo F. Padovan len = l2cap_parse_conf_req(chan, rsp); 34610a708f8fSGustavo F. Padovan if (len < 0) { 3462e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 34630a708f8fSGustavo F. Padovan goto unlock; 34640a708f8fSGustavo F. Padovan } 34650a708f8fSGustavo F. Padovan 34660a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); 346773ffa904SGustavo F. Padovan chan->num_conf_rsp++; 34680a708f8fSGustavo F. Padovan 34690a708f8fSGustavo F. Padovan /* Reset config buffer. */ 347073ffa904SGustavo F. Padovan chan->conf_len = 0; 34710a708f8fSGustavo F. Padovan 3472c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) 34730a708f8fSGustavo F. Padovan goto unlock; 34740a708f8fSGustavo F. Padovan 3475c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 347647d1ec61SGustavo F. Padovan set_default_fcs(chan); 34770a708f8fSGustavo F. Padovan 347889bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECTED); 34790a708f8fSGustavo F. Padovan 3480105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 3481105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 34823c588192SMat Martineau err = l2cap_ertm_init(chan); 34830a708f8fSGustavo F. Padovan 34843c588192SMat Martineau if (err < 0) 34853c588192SMat Martineau l2cap_send_disconn_req(chan->conn, chan, -err); 34863c588192SMat Martineau else 3487cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 34883c588192SMat Martineau 34890a708f8fSGustavo F. Padovan goto unlock; 34900a708f8fSGustavo F. Padovan } 34910a708f8fSGustavo F. Padovan 3492c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { 34930a708f8fSGustavo F. Padovan u8 buf[64]; 34940a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 349573ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 349673ffa904SGustavo F. Padovan chan->num_conf_req++; 34970a708f8fSGustavo F. Padovan } 34980a708f8fSGustavo F. Padovan 34990e8b207eSAndrei Emeltchenko /* Got Conf Rsp PENDING from remote side and asume we sent 35000e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */ 35010e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && 35020e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 35030e8b207eSAndrei Emeltchenko 35040e8b207eSAndrei Emeltchenko /* check compatibility */ 35050e8b207eSAndrei Emeltchenko 35060e8b207eSAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 35070e8b207eSAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 35080e8b207eSAndrei Emeltchenko 35090e8b207eSAndrei Emeltchenko l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 35100e8b207eSAndrei Emeltchenko l2cap_build_conf_rsp(chan, rsp, 35110e8b207eSAndrei Emeltchenko L2CAP_CONF_SUCCESS, 0x0000), rsp); 35120e8b207eSAndrei Emeltchenko } 35130e8b207eSAndrei Emeltchenko 35140a708f8fSGustavo F. Padovan unlock: 35156be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 35163c588192SMat Martineau return err; 35170a708f8fSGustavo F. Padovan } 35180a708f8fSGustavo F. Padovan 35190a708f8fSGustavo F. Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 35200a708f8fSGustavo F. Padovan { 35210a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; 35220a708f8fSGustavo F. Padovan u16 scid, flags, result; 352348454079SGustavo F. Padovan struct l2cap_chan *chan; 352461386cbaSAndrei Emeltchenko int len = le16_to_cpu(cmd->len) - sizeof(*rsp); 35253c588192SMat Martineau int err = 0; 35260a708f8fSGustavo F. Padovan 35270a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 35280a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags); 35290a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 35300a708f8fSGustavo F. Padovan 353161386cbaSAndrei Emeltchenko BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags, 353261386cbaSAndrei Emeltchenko result, len); 35330a708f8fSGustavo F. Padovan 3534baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 353548454079SGustavo F. Padovan if (!chan) 35360a708f8fSGustavo F. Padovan return 0; 35370a708f8fSGustavo F. Padovan 35380a708f8fSGustavo F. Padovan switch (result) { 35390a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS: 354047d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len); 35410e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state); 35420a708f8fSGustavo F. Padovan break; 35430a708f8fSGustavo F. Padovan 35440e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING: 35450e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state); 35460e8b207eSAndrei Emeltchenko 35470e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 35480e8b207eSAndrei Emeltchenko char buf[64]; 35490e8b207eSAndrei Emeltchenko 35500e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len, 35510e8b207eSAndrei Emeltchenko buf, &result); 35520e8b207eSAndrei Emeltchenko if (len < 0) { 35530e8b207eSAndrei Emeltchenko l2cap_send_disconn_req(conn, chan, ECONNRESET); 35540e8b207eSAndrei Emeltchenko goto done; 35550e8b207eSAndrei Emeltchenko } 35560e8b207eSAndrei Emeltchenko 35570e8b207eSAndrei Emeltchenko /* check compatibility */ 35580e8b207eSAndrei Emeltchenko 35590e8b207eSAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 35600e8b207eSAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 35610e8b207eSAndrei Emeltchenko 35620e8b207eSAndrei Emeltchenko l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 35630e8b207eSAndrei Emeltchenko l2cap_build_conf_rsp(chan, buf, 35640e8b207eSAndrei Emeltchenko L2CAP_CONF_SUCCESS, 0x0000), buf); 35650e8b207eSAndrei Emeltchenko } 35660e8b207eSAndrei Emeltchenko goto done; 35670e8b207eSAndrei Emeltchenko 35680a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT: 356973ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { 35700a708f8fSGustavo F. Padovan char req[64]; 35710a708f8fSGustavo F. Padovan 35720a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { 3573e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 35740a708f8fSGustavo F. Padovan goto done; 35750a708f8fSGustavo F. Padovan } 35760a708f8fSGustavo F. Padovan 35770a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */ 35780a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS; 3579b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len, 3580b4450035SGustavo F. Padovan req, &result); 35810a708f8fSGustavo F. Padovan if (len < 0) { 3582e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 35830a708f8fSGustavo F. Padovan goto done; 35840a708f8fSGustavo F. Padovan } 35850a708f8fSGustavo F. Padovan 35860a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 35870a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req); 358873ffa904SGustavo F. Padovan chan->num_conf_req++; 35890a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS) 35900a708f8fSGustavo F. Padovan goto done; 35910a708f8fSGustavo F. Padovan break; 35920a708f8fSGustavo F. Padovan } 35930a708f8fSGustavo F. Padovan 35940a708f8fSGustavo F. Padovan default: 35956be36555SAndrei Emeltchenko l2cap_chan_set_err(chan, ECONNRESET); 35962e0052e4SAndrei Emeltchenko 3597ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); 3598e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 35990a708f8fSGustavo F. Padovan goto done; 36000a708f8fSGustavo F. Padovan } 36010a708f8fSGustavo F. Padovan 36020a708f8fSGustavo F. Padovan if (flags & 0x01) 36030a708f8fSGustavo F. Padovan goto done; 36040a708f8fSGustavo F. Padovan 3605c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state); 36060a708f8fSGustavo F. Padovan 3607c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { 360847d1ec61SGustavo F. Padovan set_default_fcs(chan); 36090a708f8fSGustavo F. Padovan 361089bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECTED); 3611105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 3612105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 36133c588192SMat Martineau err = l2cap_ertm_init(chan); 36140a708f8fSGustavo F. Padovan 36153c588192SMat Martineau if (err < 0) 36163c588192SMat Martineau l2cap_send_disconn_req(chan->conn, chan, -err); 36173c588192SMat Martineau else 3618cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 36190a708f8fSGustavo F. Padovan } 36200a708f8fSGustavo F. Padovan 36210a708f8fSGustavo F. Padovan done: 36226be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 36233c588192SMat Martineau return err; 36240a708f8fSGustavo F. Padovan } 36250a708f8fSGustavo F. Padovan 36260a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 36270a708f8fSGustavo F. Padovan { 36280a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; 36290a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp; 36300a708f8fSGustavo F. Padovan u16 dcid, scid; 363148454079SGustavo F. Padovan struct l2cap_chan *chan; 36320a708f8fSGustavo F. Padovan struct sock *sk; 36330a708f8fSGustavo F. Padovan 36340a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid); 36350a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 36360a708f8fSGustavo F. Padovan 36370a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); 36380a708f8fSGustavo F. Padovan 36393df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 36403df91ea2SAndrei Emeltchenko 36413df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, dcid); 36423df91ea2SAndrei Emeltchenko if (!chan) { 36433df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 36440a708f8fSGustavo F. Padovan return 0; 36453df91ea2SAndrei Emeltchenko } 36460a708f8fSGustavo F. Padovan 36476be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 36486be36555SAndrei Emeltchenko 364948454079SGustavo F. Padovan sk = chan->sk; 365048454079SGustavo F. Padovan 3651fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3652fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 36530a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); 36540a708f8fSGustavo F. Padovan 36556be36555SAndrei Emeltchenko lock_sock(sk); 36560a708f8fSGustavo F. Padovan sk->sk_shutdown = SHUTDOWN_MASK; 36576be36555SAndrei Emeltchenko release_sock(sk); 36580a708f8fSGustavo F. Padovan 365961d6ef3eSMat Martineau l2cap_chan_hold(chan); 366048454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET); 36616be36555SAndrei Emeltchenko 36626be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 36630a708f8fSGustavo F. Padovan 3664ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 366561d6ef3eSMat Martineau l2cap_chan_put(chan); 36663df91ea2SAndrei Emeltchenko 36673df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 36683df91ea2SAndrei Emeltchenko 36690a708f8fSGustavo F. Padovan return 0; 36700a708f8fSGustavo F. Padovan } 36710a708f8fSGustavo F. Padovan 36720a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 36730a708f8fSGustavo F. Padovan { 36740a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; 36750a708f8fSGustavo F. Padovan u16 dcid, scid; 367648454079SGustavo F. Padovan struct l2cap_chan *chan; 36770a708f8fSGustavo F. Padovan 36780a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 36790a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 36800a708f8fSGustavo F. Padovan 36810a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); 36820a708f8fSGustavo F. Padovan 36833df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 36843df91ea2SAndrei Emeltchenko 36853df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 36863df91ea2SAndrei Emeltchenko if (!chan) { 36873df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 36880a708f8fSGustavo F. Padovan return 0; 36893df91ea2SAndrei Emeltchenko } 36900a708f8fSGustavo F. Padovan 36916be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 369248454079SGustavo F. Padovan 369361d6ef3eSMat Martineau l2cap_chan_hold(chan); 369448454079SGustavo F. Padovan l2cap_chan_del(chan, 0); 36956be36555SAndrei Emeltchenko 36966be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 36970a708f8fSGustavo F. Padovan 3698ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 369961d6ef3eSMat Martineau l2cap_chan_put(chan); 37003df91ea2SAndrei Emeltchenko 37013df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 37023df91ea2SAndrei Emeltchenko 37030a708f8fSGustavo F. Padovan return 0; 37040a708f8fSGustavo F. Padovan } 37050a708f8fSGustavo F. Padovan 37060a708f8fSGustavo F. Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 37070a708f8fSGustavo F. Padovan { 37080a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data; 37090a708f8fSGustavo F. Padovan u16 type; 37100a708f8fSGustavo F. Padovan 37110a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type); 37120a708f8fSGustavo F. Padovan 37130a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type); 37140a708f8fSGustavo F. Padovan 37150a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) { 37160a708f8fSGustavo F. Padovan u8 buf[8]; 37170a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask; 37180a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 37190a708f8fSGustavo F. Padovan rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 37200a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 37210a708f8fSGustavo F. Padovan if (!disable_ertm) 37220a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING 37230a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS; 3724a5fd6f30SAndrei Emeltchenko if (enable_hs) 37256327eb98SAndrei Emeltchenko feat_mask |= L2CAP_FEAT_EXT_FLOW 37266327eb98SAndrei Emeltchenko | L2CAP_FEAT_EXT_WINDOW; 3727a5fd6f30SAndrei Emeltchenko 37280a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data); 37290a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 37300a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(buf), buf); 37310a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) { 37320a708f8fSGustavo F. Padovan u8 buf[12]; 37330a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 373450a147cdSMat Martineau 373550a147cdSMat Martineau if (enable_hs) 373650a147cdSMat Martineau l2cap_fixed_chan[0] |= L2CAP_FC_A2MP; 373750a147cdSMat Martineau else 373850a147cdSMat Martineau l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP; 373950a147cdSMat Martineau 37400a708f8fSGustavo F. Padovan rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 37410a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 3742c6337ea6SAndrei Emeltchenko memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); 37430a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 37440a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(buf), buf); 37450a708f8fSGustavo F. Padovan } else { 37460a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp; 37470a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type); 37480a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP); 37490a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 37500a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(rsp), &rsp); 37510a708f8fSGustavo F. Padovan } 37520a708f8fSGustavo F. Padovan 37530a708f8fSGustavo F. Padovan return 0; 37540a708f8fSGustavo F. Padovan } 37550a708f8fSGustavo F. Padovan 37560a708f8fSGustavo F. Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 37570a708f8fSGustavo F. Padovan { 37580a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; 37590a708f8fSGustavo F. Padovan u16 type, result; 37600a708f8fSGustavo F. Padovan 37610a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type); 37620a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 37630a708f8fSGustavo F. Padovan 37640a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); 37650a708f8fSGustavo F. Padovan 3766e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */ 3767e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident || 3768e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 3769e90165beSAndrei Emeltchenko return 0; 3770e90165beSAndrei Emeltchenko 377117cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 37720a708f8fSGustavo F. Padovan 37730a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) { 37740a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 37750a708f8fSGustavo F. Padovan conn->info_ident = 0; 37760a708f8fSGustavo F. Padovan 37770a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 37780a708f8fSGustavo F. Padovan 37790a708f8fSGustavo F. Padovan return 0; 37800a708f8fSGustavo F. Padovan } 37810a708f8fSGustavo F. Padovan 3782978c93b9SAndrei Emeltchenko switch (type) { 3783978c93b9SAndrei Emeltchenko case L2CAP_IT_FEAT_MASK: 37840a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data); 37850a708f8fSGustavo F. Padovan 37860a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { 37870a708f8fSGustavo F. Padovan struct l2cap_info_req req; 37880a708f8fSGustavo F. Padovan req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 37890a708f8fSGustavo F. Padovan 37900a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 37910a708f8fSGustavo F. Padovan 37920a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 37930a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 37940a708f8fSGustavo F. Padovan } else { 37950a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 37960a708f8fSGustavo F. Padovan conn->info_ident = 0; 37970a708f8fSGustavo F. Padovan 37980a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 37990a708f8fSGustavo F. Padovan } 3800978c93b9SAndrei Emeltchenko break; 3801978c93b9SAndrei Emeltchenko 3802978c93b9SAndrei Emeltchenko case L2CAP_IT_FIXED_CHAN: 3803978c93b9SAndrei Emeltchenko conn->fixed_chan_mask = rsp->data[0]; 38040a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 38050a708f8fSGustavo F. Padovan conn->info_ident = 0; 38060a708f8fSGustavo F. Padovan 38070a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 3808978c93b9SAndrei Emeltchenko break; 38090a708f8fSGustavo F. Padovan } 38100a708f8fSGustavo F. Padovan 38110a708f8fSGustavo F. Padovan return 0; 38120a708f8fSGustavo F. Padovan } 38130a708f8fSGustavo F. Padovan 3814f94ff6ffSMat Martineau static inline int l2cap_create_channel_req(struct l2cap_conn *conn, 3815f94ff6ffSMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, 3816f94ff6ffSMat Martineau void *data) 3817f94ff6ffSMat Martineau { 3818f94ff6ffSMat Martineau struct l2cap_create_chan_req *req = data; 3819f94ff6ffSMat Martineau struct l2cap_create_chan_rsp rsp; 3820f94ff6ffSMat Martineau u16 psm, scid; 3821f94ff6ffSMat Martineau 3822f94ff6ffSMat Martineau if (cmd_len != sizeof(*req)) 3823f94ff6ffSMat Martineau return -EPROTO; 3824f94ff6ffSMat Martineau 3825f94ff6ffSMat Martineau if (!enable_hs) 3826f94ff6ffSMat Martineau return -EINVAL; 3827f94ff6ffSMat Martineau 3828f94ff6ffSMat Martineau psm = le16_to_cpu(req->psm); 3829f94ff6ffSMat Martineau scid = le16_to_cpu(req->scid); 3830f94ff6ffSMat Martineau 3831f94ff6ffSMat Martineau BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id); 3832f94ff6ffSMat Martineau 3833f94ff6ffSMat Martineau /* Placeholder: Always reject */ 3834f94ff6ffSMat Martineau rsp.dcid = 0; 3835f94ff6ffSMat Martineau rsp.scid = cpu_to_le16(scid); 38368ce0c498SAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM); 38378ce0c498SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 3838f94ff6ffSMat Martineau 3839f94ff6ffSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, 3840f94ff6ffSMat Martineau sizeof(rsp), &rsp); 3841f94ff6ffSMat Martineau 3842f94ff6ffSMat Martineau return 0; 3843f94ff6ffSMat Martineau } 3844f94ff6ffSMat Martineau 3845f94ff6ffSMat Martineau static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn, 3846f94ff6ffSMat Martineau struct l2cap_cmd_hdr *cmd, void *data) 3847f94ff6ffSMat Martineau { 3848f94ff6ffSMat Martineau BT_DBG("conn %p", conn); 3849f94ff6ffSMat Martineau 3850f94ff6ffSMat Martineau return l2cap_connect_rsp(conn, cmd, data); 3851f94ff6ffSMat Martineau } 3852f94ff6ffSMat Martineau 38538d5a04a1SMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident, 38548d5a04a1SMat Martineau u16 icid, u16 result) 38558d5a04a1SMat Martineau { 38568d5a04a1SMat Martineau struct l2cap_move_chan_rsp rsp; 38578d5a04a1SMat Martineau 38588d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 38598d5a04a1SMat Martineau 38608d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 38618d5a04a1SMat Martineau rsp.result = cpu_to_le16(result); 38628d5a04a1SMat Martineau 38638d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp); 38648d5a04a1SMat Martineau } 38658d5a04a1SMat Martineau 38668d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn, 38678d5a04a1SMat Martineau struct l2cap_chan *chan, u16 icid, u16 result) 38688d5a04a1SMat Martineau { 38698d5a04a1SMat Martineau struct l2cap_move_chan_cfm cfm; 38708d5a04a1SMat Martineau u8 ident; 38718d5a04a1SMat Martineau 38728d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 38738d5a04a1SMat Martineau 38748d5a04a1SMat Martineau ident = l2cap_get_ident(conn); 38758d5a04a1SMat Martineau if (chan) 38768d5a04a1SMat Martineau chan->ident = ident; 38778d5a04a1SMat Martineau 38788d5a04a1SMat Martineau cfm.icid = cpu_to_le16(icid); 38798d5a04a1SMat Martineau cfm.result = cpu_to_le16(result); 38808d5a04a1SMat Martineau 38818d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm); 38828d5a04a1SMat Martineau } 38838d5a04a1SMat Martineau 38848d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, 38858d5a04a1SMat Martineau u16 icid) 38868d5a04a1SMat Martineau { 38878d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp rsp; 38888d5a04a1SMat Martineau 38898d5a04a1SMat Martineau BT_DBG("icid %d", icid); 38908d5a04a1SMat Martineau 38918d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 38928d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp); 38938d5a04a1SMat Martineau } 38948d5a04a1SMat Martineau 38958d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn, 38968d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 38978d5a04a1SMat Martineau { 38988d5a04a1SMat Martineau struct l2cap_move_chan_req *req = data; 38998d5a04a1SMat Martineau u16 icid = 0; 39008d5a04a1SMat Martineau u16 result = L2CAP_MR_NOT_ALLOWED; 39018d5a04a1SMat Martineau 39028d5a04a1SMat Martineau if (cmd_len != sizeof(*req)) 39038d5a04a1SMat Martineau return -EPROTO; 39048d5a04a1SMat Martineau 39058d5a04a1SMat Martineau icid = le16_to_cpu(req->icid); 39068d5a04a1SMat Martineau 39078d5a04a1SMat Martineau BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id); 39088d5a04a1SMat Martineau 39098d5a04a1SMat Martineau if (!enable_hs) 39108d5a04a1SMat Martineau return -EINVAL; 39118d5a04a1SMat Martineau 39128d5a04a1SMat Martineau /* Placeholder: Always refuse */ 39138d5a04a1SMat Martineau l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result); 39148d5a04a1SMat Martineau 39158d5a04a1SMat Martineau return 0; 39168d5a04a1SMat Martineau } 39178d5a04a1SMat Martineau 39188d5a04a1SMat Martineau static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn, 39198d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 39208d5a04a1SMat Martineau { 39218d5a04a1SMat Martineau struct l2cap_move_chan_rsp *rsp = data; 39228d5a04a1SMat Martineau u16 icid, result; 39238d5a04a1SMat Martineau 39248d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 39258d5a04a1SMat Martineau return -EPROTO; 39268d5a04a1SMat Martineau 39278d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 39288d5a04a1SMat Martineau result = le16_to_cpu(rsp->result); 39298d5a04a1SMat Martineau 39308d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 39318d5a04a1SMat Martineau 39328d5a04a1SMat Martineau /* Placeholder: Always unconfirmed */ 39338d5a04a1SMat Martineau l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED); 39348d5a04a1SMat Martineau 39358d5a04a1SMat Martineau return 0; 39368d5a04a1SMat Martineau } 39378d5a04a1SMat Martineau 39388d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn, 39398d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 39408d5a04a1SMat Martineau { 39418d5a04a1SMat Martineau struct l2cap_move_chan_cfm *cfm = data; 39428d5a04a1SMat Martineau u16 icid, result; 39438d5a04a1SMat Martineau 39448d5a04a1SMat Martineau if (cmd_len != sizeof(*cfm)) 39458d5a04a1SMat Martineau return -EPROTO; 39468d5a04a1SMat Martineau 39478d5a04a1SMat Martineau icid = le16_to_cpu(cfm->icid); 39488d5a04a1SMat Martineau result = le16_to_cpu(cfm->result); 39498d5a04a1SMat Martineau 39508d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 39518d5a04a1SMat Martineau 39528d5a04a1SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 39538d5a04a1SMat Martineau 39548d5a04a1SMat Martineau return 0; 39558d5a04a1SMat Martineau } 39568d5a04a1SMat Martineau 39578d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, 39588d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 39598d5a04a1SMat Martineau { 39608d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp *rsp = data; 39618d5a04a1SMat Martineau u16 icid; 39628d5a04a1SMat Martineau 39638d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 39648d5a04a1SMat Martineau return -EPROTO; 39658d5a04a1SMat Martineau 39668d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 39678d5a04a1SMat Martineau 39688d5a04a1SMat Martineau BT_DBG("icid %d", icid); 39698d5a04a1SMat Martineau 39708d5a04a1SMat Martineau return 0; 39718d5a04a1SMat Martineau } 39728d5a04a1SMat Martineau 3973e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency, 3974de73115aSClaudio Takahasi u16 to_multiplier) 3975de73115aSClaudio Takahasi { 3976de73115aSClaudio Takahasi u16 max_latency; 3977de73115aSClaudio Takahasi 3978de73115aSClaudio Takahasi if (min > max || min < 6 || max > 3200) 3979de73115aSClaudio Takahasi return -EINVAL; 3980de73115aSClaudio Takahasi 3981de73115aSClaudio Takahasi if (to_multiplier < 10 || to_multiplier > 3200) 3982de73115aSClaudio Takahasi return -EINVAL; 3983de73115aSClaudio Takahasi 3984de73115aSClaudio Takahasi if (max >= to_multiplier * 8) 3985de73115aSClaudio Takahasi return -EINVAL; 3986de73115aSClaudio Takahasi 3987de73115aSClaudio Takahasi max_latency = (to_multiplier * 8 / max) - 1; 3988de73115aSClaudio Takahasi if (latency > 499 || latency > max_latency) 3989de73115aSClaudio Takahasi return -EINVAL; 3990de73115aSClaudio Takahasi 3991de73115aSClaudio Takahasi return 0; 3992de73115aSClaudio Takahasi } 3993de73115aSClaudio Takahasi 3994de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, 3995de73115aSClaudio Takahasi struct l2cap_cmd_hdr *cmd, u8 *data) 3996de73115aSClaudio Takahasi { 3997de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon; 3998de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req; 3999de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp; 4000de73115aSClaudio Takahasi u16 min, max, latency, to_multiplier, cmd_len; 40012ce603ebSClaudio Takahasi int err; 4002de73115aSClaudio Takahasi 4003de73115aSClaudio Takahasi if (!(hcon->link_mode & HCI_LM_MASTER)) 4004de73115aSClaudio Takahasi return -EINVAL; 4005de73115aSClaudio Takahasi 4006de73115aSClaudio Takahasi cmd_len = __le16_to_cpu(cmd->len); 4007de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) 4008de73115aSClaudio Takahasi return -EPROTO; 4009de73115aSClaudio Takahasi 4010de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data; 4011de73115aSClaudio Takahasi min = __le16_to_cpu(req->min); 4012de73115aSClaudio Takahasi max = __le16_to_cpu(req->max); 4013de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency); 4014de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier); 4015de73115aSClaudio Takahasi 4016de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", 4017de73115aSClaudio Takahasi min, max, latency, to_multiplier); 4018de73115aSClaudio Takahasi 4019de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp)); 40202ce603ebSClaudio Takahasi 40212ce603ebSClaudio Takahasi err = l2cap_check_conn_param(min, max, latency, to_multiplier); 40222ce603ebSClaudio Takahasi if (err) 4023de73115aSClaudio Takahasi rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); 4024de73115aSClaudio Takahasi else 4025de73115aSClaudio Takahasi rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); 4026de73115aSClaudio Takahasi 4027de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, 4028de73115aSClaudio Takahasi sizeof(rsp), &rsp); 4029de73115aSClaudio Takahasi 40302ce603ebSClaudio Takahasi if (!err) 40312ce603ebSClaudio Takahasi hci_le_conn_update(hcon, min, max, latency, to_multiplier); 40322ce603ebSClaudio Takahasi 4033de73115aSClaudio Takahasi return 0; 4034de73115aSClaudio Takahasi } 4035de73115aSClaudio Takahasi 40363300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, 40373300d9a9SClaudio Takahasi struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 40383300d9a9SClaudio Takahasi { 40393300d9a9SClaudio Takahasi int err = 0; 40403300d9a9SClaudio Takahasi 40413300d9a9SClaudio Takahasi switch (cmd->code) { 40423300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 40433300d9a9SClaudio Takahasi l2cap_command_rej(conn, cmd, data); 40443300d9a9SClaudio Takahasi break; 40453300d9a9SClaudio Takahasi 40463300d9a9SClaudio Takahasi case L2CAP_CONN_REQ: 40473300d9a9SClaudio Takahasi err = l2cap_connect_req(conn, cmd, data); 40483300d9a9SClaudio Takahasi break; 40493300d9a9SClaudio Takahasi 40503300d9a9SClaudio Takahasi case L2CAP_CONN_RSP: 40513300d9a9SClaudio Takahasi err = l2cap_connect_rsp(conn, cmd, data); 40523300d9a9SClaudio Takahasi break; 40533300d9a9SClaudio Takahasi 40543300d9a9SClaudio Takahasi case L2CAP_CONF_REQ: 40553300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data); 40563300d9a9SClaudio Takahasi break; 40573300d9a9SClaudio Takahasi 40583300d9a9SClaudio Takahasi case L2CAP_CONF_RSP: 40593300d9a9SClaudio Takahasi err = l2cap_config_rsp(conn, cmd, data); 40603300d9a9SClaudio Takahasi break; 40613300d9a9SClaudio Takahasi 40623300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ: 40633300d9a9SClaudio Takahasi err = l2cap_disconnect_req(conn, cmd, data); 40643300d9a9SClaudio Takahasi break; 40653300d9a9SClaudio Takahasi 40663300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP: 40673300d9a9SClaudio Takahasi err = l2cap_disconnect_rsp(conn, cmd, data); 40683300d9a9SClaudio Takahasi break; 40693300d9a9SClaudio Takahasi 40703300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ: 40713300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data); 40723300d9a9SClaudio Takahasi break; 40733300d9a9SClaudio Takahasi 40743300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP: 40753300d9a9SClaudio Takahasi break; 40763300d9a9SClaudio Takahasi 40773300d9a9SClaudio Takahasi case L2CAP_INFO_REQ: 40783300d9a9SClaudio Takahasi err = l2cap_information_req(conn, cmd, data); 40793300d9a9SClaudio Takahasi break; 40803300d9a9SClaudio Takahasi 40813300d9a9SClaudio Takahasi case L2CAP_INFO_RSP: 40823300d9a9SClaudio Takahasi err = l2cap_information_rsp(conn, cmd, data); 40833300d9a9SClaudio Takahasi break; 40843300d9a9SClaudio Takahasi 4085f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_REQ: 4086f94ff6ffSMat Martineau err = l2cap_create_channel_req(conn, cmd, cmd_len, data); 4087f94ff6ffSMat Martineau break; 4088f94ff6ffSMat Martineau 4089f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_RSP: 4090f94ff6ffSMat Martineau err = l2cap_create_channel_rsp(conn, cmd, data); 4091f94ff6ffSMat Martineau break; 4092f94ff6ffSMat Martineau 40938d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_REQ: 40948d5a04a1SMat Martineau err = l2cap_move_channel_req(conn, cmd, cmd_len, data); 40958d5a04a1SMat Martineau break; 40968d5a04a1SMat Martineau 40978d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_RSP: 40988d5a04a1SMat Martineau err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data); 40998d5a04a1SMat Martineau break; 41008d5a04a1SMat Martineau 41018d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM: 41028d5a04a1SMat Martineau err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data); 41038d5a04a1SMat Martineau break; 41048d5a04a1SMat Martineau 41058d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM_RSP: 41068d5a04a1SMat Martineau err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data); 41078d5a04a1SMat Martineau break; 41088d5a04a1SMat Martineau 41093300d9a9SClaudio Takahasi default: 41103300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code); 41113300d9a9SClaudio Takahasi err = -EINVAL; 41123300d9a9SClaudio Takahasi break; 41133300d9a9SClaudio Takahasi } 41143300d9a9SClaudio Takahasi 41153300d9a9SClaudio Takahasi return err; 41163300d9a9SClaudio Takahasi } 41173300d9a9SClaudio Takahasi 41183300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, 41193300d9a9SClaudio Takahasi struct l2cap_cmd_hdr *cmd, u8 *data) 41203300d9a9SClaudio Takahasi { 41213300d9a9SClaudio Takahasi switch (cmd->code) { 41223300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 41233300d9a9SClaudio Takahasi return 0; 41243300d9a9SClaudio Takahasi 41253300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ: 4126de73115aSClaudio Takahasi return l2cap_conn_param_update_req(conn, cmd, data); 41273300d9a9SClaudio Takahasi 41283300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP: 41293300d9a9SClaudio Takahasi return 0; 41303300d9a9SClaudio Takahasi 41313300d9a9SClaudio Takahasi default: 41323300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code); 41333300d9a9SClaudio Takahasi return -EINVAL; 41343300d9a9SClaudio Takahasi } 41353300d9a9SClaudio Takahasi } 41363300d9a9SClaudio Takahasi 41373300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn, 41383300d9a9SClaudio Takahasi struct sk_buff *skb) 41390a708f8fSGustavo F. Padovan { 41400a708f8fSGustavo F. Padovan u8 *data = skb->data; 41410a708f8fSGustavo F. Padovan int len = skb->len; 41420a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr cmd; 41433300d9a9SClaudio Takahasi int err; 41440a708f8fSGustavo F. Padovan 41450a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb); 41460a708f8fSGustavo F. Padovan 41470a708f8fSGustavo F. Padovan while (len >= L2CAP_CMD_HDR_SIZE) { 41480a708f8fSGustavo F. Padovan u16 cmd_len; 41490a708f8fSGustavo F. Padovan memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); 41500a708f8fSGustavo F. Padovan data += L2CAP_CMD_HDR_SIZE; 41510a708f8fSGustavo F. Padovan len -= L2CAP_CMD_HDR_SIZE; 41520a708f8fSGustavo F. Padovan 41530a708f8fSGustavo F. Padovan cmd_len = le16_to_cpu(cmd.len); 41540a708f8fSGustavo F. Padovan 41550a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident); 41560a708f8fSGustavo F. Padovan 41570a708f8fSGustavo F. Padovan if (cmd_len > len || !cmd.ident) { 41580a708f8fSGustavo F. Padovan BT_DBG("corrupted command"); 41590a708f8fSGustavo F. Padovan break; 41600a708f8fSGustavo F. Padovan } 41610a708f8fSGustavo F. Padovan 41623300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 41633300d9a9SClaudio Takahasi err = l2cap_le_sig_cmd(conn, &cmd, data); 41643300d9a9SClaudio Takahasi else 41653300d9a9SClaudio Takahasi err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data); 41660a708f8fSGustavo F. Padovan 41670a708f8fSGustavo F. Padovan if (err) { 4168e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk rej; 41692c6d1a2eSGustavo F. Padovan 41702c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err); 41710a708f8fSGustavo F. Padovan 41720a708f8fSGustavo F. Padovan /* FIXME: Map err to a valid reason */ 4173e2fd318eSIlia Kolomisnky rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 41740a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); 41750a708f8fSGustavo F. Padovan } 41760a708f8fSGustavo F. Padovan 41770a708f8fSGustavo F. Padovan data += cmd_len; 41780a708f8fSGustavo F. Padovan len -= cmd_len; 41790a708f8fSGustavo F. Padovan } 41800a708f8fSGustavo F. Padovan 41810a708f8fSGustavo F. Padovan kfree_skb(skb); 41820a708f8fSGustavo F. Padovan } 41830a708f8fSGustavo F. Padovan 418447d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) 41850a708f8fSGustavo F. Padovan { 41860a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs; 4187e4ca6d98SAndrei Emeltchenko int hdr_size; 4188e4ca6d98SAndrei Emeltchenko 4189e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 4190e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE; 4191e4ca6d98SAndrei Emeltchenko else 4192e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE; 41930a708f8fSGustavo F. Padovan 419447d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 419503a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE); 41960a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len); 41970a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); 41980a708f8fSGustavo F. Padovan 41990a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs) 42000a708f8fSGustavo F. Padovan return -EBADMSG; 42010a708f8fSGustavo F. Padovan } 42020a708f8fSGustavo F. Padovan return 0; 42030a708f8fSGustavo F. Padovan } 42040a708f8fSGustavo F. Padovan 4205525cd185SGustavo F. Padovan static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) 42060a708f8fSGustavo F. Padovan { 4207e31f7633SMat Martineau struct l2cap_ctrl control; 42080a708f8fSGustavo F. Padovan 4209e31f7633SMat Martineau BT_DBG("chan %p", chan); 42100a708f8fSGustavo F. Padovan 4211e31f7633SMat Martineau memset(&control, 0, sizeof(control)); 4212e31f7633SMat Martineau control.sframe = 1; 4213e31f7633SMat Martineau control.final = 1; 4214e31f7633SMat Martineau control.reqseq = chan->buffer_seq; 4215e31f7633SMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 42160a708f8fSGustavo F. Padovan 4217e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 4218e31f7633SMat Martineau control.super = L2CAP_SUPER_RNR; 4219e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 42200a708f8fSGustavo F. Padovan } 42210a708f8fSGustavo F. Padovan 4222e31f7633SMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 4223e31f7633SMat Martineau chan->unacked_frames > 0) 4224e31f7633SMat Martineau __set_retrans_timer(chan); 42250a708f8fSGustavo F. Padovan 4226e31f7633SMat Martineau /* Send pending iframes */ 4227525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 42280a708f8fSGustavo F. Padovan 4229e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 4230e31f7633SMat Martineau test_bit(CONN_SEND_FBIT, &chan->conn_state)) { 4231e31f7633SMat Martineau /* F-bit wasn't sent in an s-frame or i-frame yet, so 4232e31f7633SMat Martineau * send it now. 4233e31f7633SMat Martineau */ 4234e31f7633SMat Martineau control.super = L2CAP_SUPER_RR; 4235e31f7633SMat Martineau l2cap_send_sframe(chan, &control); 42360a708f8fSGustavo F. Padovan } 42370a708f8fSGustavo F. Padovan } 42380a708f8fSGustavo F. Padovan 423984084a31SMat Martineau static void append_skb_frag(struct sk_buff *skb, 424084084a31SMat Martineau struct sk_buff *new_frag, struct sk_buff **last_frag) 42410a708f8fSGustavo F. Padovan { 424284084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments 424384084a31SMat Martineau * skb->data_len reflects only data in fragments 424484084a31SMat Martineau */ 424584084a31SMat Martineau if (!skb_has_frag_list(skb)) 424684084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag; 424784084a31SMat Martineau 424884084a31SMat Martineau new_frag->next = NULL; 424984084a31SMat Martineau 425084084a31SMat Martineau (*last_frag)->next = new_frag; 425184084a31SMat Martineau *last_frag = new_frag; 425284084a31SMat Martineau 425384084a31SMat Martineau skb->len += new_frag->len; 425484084a31SMat Martineau skb->data_len += new_frag->len; 425584084a31SMat Martineau skb->truesize += new_frag->truesize; 425684084a31SMat Martineau } 425784084a31SMat Martineau 42584b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, 42594b51dae9SMat Martineau struct l2cap_ctrl *control) 426084084a31SMat Martineau { 426184084a31SMat Martineau int err = -EINVAL; 42620a708f8fSGustavo F. Padovan 42634b51dae9SMat Martineau switch (control->sar) { 42647e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED: 426584084a31SMat Martineau if (chan->sdu) 426684084a31SMat Martineau break; 42670a708f8fSGustavo F. Padovan 426884084a31SMat Martineau err = chan->ops->recv(chan->data, skb); 426984084a31SMat Martineau break; 42700a708f8fSGustavo F. Padovan 42717e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START: 427284084a31SMat Martineau if (chan->sdu) 427384084a31SMat Martineau break; 42740a708f8fSGustavo F. Padovan 42756f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data); 427603a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE); 42770a708f8fSGustavo F. Padovan 427884084a31SMat Martineau if (chan->sdu_len > chan->imtu) { 427984084a31SMat Martineau err = -EMSGSIZE; 428084084a31SMat Martineau break; 428184084a31SMat Martineau } 42820a708f8fSGustavo F. Padovan 428384084a31SMat Martineau if (skb->len >= chan->sdu_len) 428484084a31SMat Martineau break; 428584084a31SMat Martineau 428684084a31SMat Martineau chan->sdu = skb; 428784084a31SMat Martineau chan->sdu_last_frag = skb; 428884084a31SMat Martineau 428984084a31SMat Martineau skb = NULL; 429084084a31SMat Martineau err = 0; 42910a708f8fSGustavo F. Padovan break; 42920a708f8fSGustavo F. Padovan 42937e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE: 42946f61fd47SGustavo F. Padovan if (!chan->sdu) 429584084a31SMat Martineau break; 42960a708f8fSGustavo F. Padovan 429784084a31SMat Martineau append_skb_frag(chan->sdu, skb, 429884084a31SMat Martineau &chan->sdu_last_frag); 429984084a31SMat Martineau skb = NULL; 43000a708f8fSGustavo F. Padovan 430184084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len) 430284084a31SMat Martineau break; 43030a708f8fSGustavo F. Padovan 430484084a31SMat Martineau err = 0; 43050a708f8fSGustavo F. Padovan break; 43060a708f8fSGustavo F. Padovan 43077e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END: 43086f61fd47SGustavo F. Padovan if (!chan->sdu) 430984084a31SMat Martineau break; 43100a708f8fSGustavo F. Padovan 431184084a31SMat Martineau append_skb_frag(chan->sdu, skb, 431284084a31SMat Martineau &chan->sdu_last_frag); 431384084a31SMat Martineau skb = NULL; 43140a708f8fSGustavo F. Padovan 431584084a31SMat Martineau if (chan->sdu->len != chan->sdu_len) 431684084a31SMat Martineau break; 43170a708f8fSGustavo F. Padovan 431884084a31SMat Martineau err = chan->ops->recv(chan->data, chan->sdu); 43190a708f8fSGustavo F. Padovan 432084084a31SMat Martineau if (!err) { 432184084a31SMat Martineau /* Reassembly complete */ 432284084a31SMat Martineau chan->sdu = NULL; 432384084a31SMat Martineau chan->sdu_last_frag = NULL; 432484084a31SMat Martineau chan->sdu_len = 0; 43250a708f8fSGustavo F. Padovan } 43260a708f8fSGustavo F. Padovan break; 43270a708f8fSGustavo F. Padovan } 43280a708f8fSGustavo F. Padovan 432984084a31SMat Martineau if (err) { 43300a708f8fSGustavo F. Padovan kfree_skb(skb); 43316f61fd47SGustavo F. Padovan kfree_skb(chan->sdu); 43326f61fd47SGustavo F. Padovan chan->sdu = NULL; 433384084a31SMat Martineau chan->sdu_last_frag = NULL; 433484084a31SMat Martineau chan->sdu_len = 0; 433584084a31SMat Martineau } 43360a708f8fSGustavo F. Padovan 433784084a31SMat Martineau return err; 43380a708f8fSGustavo F. Padovan } 43390a708f8fSGustavo F. Padovan 4340e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 43410a708f8fSGustavo F. Padovan { 434261aa4f5bSMat Martineau u8 event; 434361aa4f5bSMat Martineau 434461aa4f5bSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 434561aa4f5bSMat Martineau return; 434661aa4f5bSMat Martineau 434761aa4f5bSMat Martineau event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR; 434861aa4f5bSMat Martineau l2cap_tx(chan, 0, 0, event); 43490a708f8fSGustavo F. Padovan } 43500a708f8fSGustavo F. Padovan 4351d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan) 4352d2a7ac5dSMat Martineau { 4353d2a7ac5dSMat Martineau /* Placeholder */ 4354d2a7ac5dSMat Martineau return 0; 4355d2a7ac5dSMat Martineau } 4356d2a7ac5dSMat Martineau 4357d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan, 4358d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 4359d2a7ac5dSMat Martineau { 4360d2a7ac5dSMat Martineau /* Placeholder */ 4361d2a7ac5dSMat Martineau } 4362d2a7ac5dSMat Martineau 4363d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan, 4364d2a7ac5dSMat Martineau struct l2cap_ctrl *control) 4365d2a7ac5dSMat Martineau { 4366d2a7ac5dSMat Martineau /* Placeholder */ 4367d2a7ac5dSMat Martineau } 4368d2a7ac5dSMat Martineau 43694b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) 43704b51dae9SMat Martineau { 43714b51dae9SMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 43724b51dae9SMat Martineau 43734b51dae9SMat Martineau BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq, 43744b51dae9SMat Martineau chan->expected_tx_seq); 43754b51dae9SMat Martineau 43764b51dae9SMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 43774b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 43784b51dae9SMat Martineau chan->tx_win) { 43794b51dae9SMat Martineau /* See notes below regarding "double poll" and 43804b51dae9SMat Martineau * invalid packets. 43814b51dae9SMat Martineau */ 43824b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 43834b51dae9SMat Martineau BT_DBG("Invalid/Ignore - after SREJ"); 43844b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 43854b51dae9SMat Martineau } else { 43864b51dae9SMat Martineau BT_DBG("Invalid - in window after SREJ sent"); 43874b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 43884b51dae9SMat Martineau } 43894b51dae9SMat Martineau } 43904b51dae9SMat Martineau 43914b51dae9SMat Martineau if (chan->srej_list.head == txseq) { 43924b51dae9SMat Martineau BT_DBG("Expected SREJ"); 43934b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED_SREJ; 43944b51dae9SMat Martineau } 43954b51dae9SMat Martineau 43964b51dae9SMat Martineau if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) { 43974b51dae9SMat Martineau BT_DBG("Duplicate SREJ - txseq already stored"); 43984b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE_SREJ; 43994b51dae9SMat Martineau } 44004b51dae9SMat Martineau 44014b51dae9SMat Martineau if (l2cap_seq_list_contains(&chan->srej_list, txseq)) { 44024b51dae9SMat Martineau BT_DBG("Unexpected SREJ - not requested"); 44034b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED_SREJ; 44044b51dae9SMat Martineau } 44054b51dae9SMat Martineau } 44064b51dae9SMat Martineau 44074b51dae9SMat Martineau if (chan->expected_tx_seq == txseq) { 44084b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 44094b51dae9SMat Martineau chan->tx_win) { 44104b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 44114b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 44124b51dae9SMat Martineau } else { 44134b51dae9SMat Martineau BT_DBG("Expected"); 44144b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED; 44154b51dae9SMat Martineau } 44164b51dae9SMat Martineau } 44174b51dae9SMat Martineau 44184b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) < 44194b51dae9SMat Martineau __seq_offset(chan, chan->expected_tx_seq, 44204b51dae9SMat Martineau chan->last_acked_seq)){ 44214b51dae9SMat Martineau BT_DBG("Duplicate - expected_tx_seq later than txseq"); 44224b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE; 44234b51dae9SMat Martineau } 44244b51dae9SMat Martineau 44254b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) { 44264b51dae9SMat Martineau /* A source of invalid packets is a "double poll" condition, 44274b51dae9SMat Martineau * where delays cause us to send multiple poll packets. If 44284b51dae9SMat Martineau * the remote stack receives and processes both polls, 44294b51dae9SMat Martineau * sequence numbers can wrap around in such a way that a 44304b51dae9SMat Martineau * resent frame has a sequence number that looks like new data 44314b51dae9SMat Martineau * with a sequence gap. This would trigger an erroneous SREJ 44324b51dae9SMat Martineau * request. 44334b51dae9SMat Martineau * 44344b51dae9SMat Martineau * Fortunately, this is impossible with a tx window that's 44354b51dae9SMat Martineau * less than half of the maximum sequence number, which allows 44364b51dae9SMat Martineau * invalid frames to be safely ignored. 44374b51dae9SMat Martineau * 44384b51dae9SMat Martineau * With tx window sizes greater than half of the tx window 44394b51dae9SMat Martineau * maximum, the frame is invalid and cannot be ignored. This 44404b51dae9SMat Martineau * causes a disconnect. 44414b51dae9SMat Martineau */ 44424b51dae9SMat Martineau 44434b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 44444b51dae9SMat Martineau BT_DBG("Invalid/Ignore - txseq outside tx window"); 44454b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 44464b51dae9SMat Martineau } else { 44474b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 44484b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 44494b51dae9SMat Martineau } 44504b51dae9SMat Martineau } else { 44514b51dae9SMat Martineau BT_DBG("Unexpected - txseq indicates missing frames"); 44524b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED; 44534b51dae9SMat Martineau } 44544b51dae9SMat Martineau } 44554b51dae9SMat Martineau 4456d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan, 4457d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 4458d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 4459d2a7ac5dSMat Martineau { 4460d2a7ac5dSMat Martineau int err = 0; 4461d2a7ac5dSMat Martineau bool skb_in_use = 0; 4462d2a7ac5dSMat Martineau 4463d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 4464d2a7ac5dSMat Martineau event); 4465d2a7ac5dSMat Martineau 4466d2a7ac5dSMat Martineau switch (event) { 4467d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 4468d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, control->txseq)) { 4469d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 4470d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4471d2a7ac5dSMat Martineau 4472d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 4473d2a7ac5dSMat Martineau BT_DBG("Busy, discarding expected seq %d", 4474d2a7ac5dSMat Martineau control->txseq); 4475d2a7ac5dSMat Martineau break; 4476d2a7ac5dSMat Martineau } 4477d2a7ac5dSMat Martineau 4478d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, 4479d2a7ac5dSMat Martineau control->txseq); 4480d2a7ac5dSMat Martineau 4481d2a7ac5dSMat Martineau chan->buffer_seq = chan->expected_tx_seq; 4482d2a7ac5dSMat Martineau skb_in_use = 1; 4483d2a7ac5dSMat Martineau 4484d2a7ac5dSMat Martineau err = l2cap_reassemble_sdu(chan, skb, control); 4485d2a7ac5dSMat Martineau if (err) 4486d2a7ac5dSMat Martineau break; 4487d2a7ac5dSMat Martineau 4488d2a7ac5dSMat Martineau if (control->final) { 4489d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 4490d2a7ac5dSMat Martineau &chan->conn_state)) { 4491d2a7ac5dSMat Martineau control->final = 0; 4492d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 4493d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 4494d2a7ac5dSMat Martineau } 4495d2a7ac5dSMat Martineau } 4496d2a7ac5dSMat Martineau 4497d2a7ac5dSMat Martineau if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) 4498d2a7ac5dSMat Martineau l2cap_send_ack(chan); 4499d2a7ac5dSMat Martineau break; 4500d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 4501d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4502d2a7ac5dSMat Martineau 4503d2a7ac5dSMat Martineau /* Can't issue SREJ frames in the local busy state. 4504d2a7ac5dSMat Martineau * Drop this frame, it will be seen as missing 4505d2a7ac5dSMat Martineau * when local busy is exited. 4506d2a7ac5dSMat Martineau */ 4507d2a7ac5dSMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 4508d2a7ac5dSMat Martineau BT_DBG("Busy, discarding unexpected seq %d", 4509d2a7ac5dSMat Martineau control->txseq); 4510d2a7ac5dSMat Martineau break; 4511d2a7ac5dSMat Martineau } 4512d2a7ac5dSMat Martineau 4513d2a7ac5dSMat Martineau /* There was a gap in the sequence, so an SREJ 4514d2a7ac5dSMat Martineau * must be sent for each missing frame. The 4515d2a7ac5dSMat Martineau * current frame is stored for later use. 4516d2a7ac5dSMat Martineau */ 4517d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4518d2a7ac5dSMat Martineau skb_in_use = 1; 4519d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4520d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4521d2a7ac5dSMat Martineau 4522d2a7ac5dSMat Martineau clear_bit(CONN_SREJ_ACT, &chan->conn_state); 4523d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 4524d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 4525d2a7ac5dSMat Martineau 4526d2a7ac5dSMat Martineau chan->rx_state = L2CAP_RX_STATE_SREJ_SENT; 4527d2a7ac5dSMat Martineau break; 4528d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 4529d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4530d2a7ac5dSMat Martineau break; 4531d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 4532d2a7ac5dSMat Martineau break; 4533d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 4534d2a7ac5dSMat Martineau default: 4535d2a7ac5dSMat Martineau l2cap_send_disconn_req(chan->conn, chan, 4536d2a7ac5dSMat Martineau ECONNRESET); 4537d2a7ac5dSMat Martineau break; 4538d2a7ac5dSMat Martineau } 4539d2a7ac5dSMat Martineau break; 4540d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 4541d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4542d2a7ac5dSMat Martineau if (control->final) { 4543d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4544d2a7ac5dSMat Martineau 4545d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 4546d2a7ac5dSMat Martineau &chan->conn_state)) { 4547d2a7ac5dSMat Martineau control->final = 0; 4548d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 4549d2a7ac5dSMat Martineau } 4550d2a7ac5dSMat Martineau 4551d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 4552d2a7ac5dSMat Martineau } else if (control->poll) { 4553d2a7ac5dSMat Martineau l2cap_send_i_or_rr_or_rnr(chan); 4554d2a7ac5dSMat Martineau } else { 4555d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 4556d2a7ac5dSMat Martineau &chan->conn_state) && 4557d2a7ac5dSMat Martineau chan->unacked_frames) 4558d2a7ac5dSMat Martineau __set_retrans_timer(chan); 4559d2a7ac5dSMat Martineau 4560d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 4561d2a7ac5dSMat Martineau } 4562d2a7ac5dSMat Martineau break; 4563d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 4564d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4565d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4566d2a7ac5dSMat Martineau if (control && control->poll) { 4567d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 4568d2a7ac5dSMat Martineau l2cap_send_rr_or_rnr(chan, 0); 4569d2a7ac5dSMat Martineau } 4570d2a7ac5dSMat Martineau __clear_retrans_timer(chan); 4571d2a7ac5dSMat Martineau l2cap_seq_list_clear(&chan->retrans_list); 4572d2a7ac5dSMat Martineau break; 4573d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 4574d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 4575d2a7ac5dSMat Martineau break; 4576d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 4577d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 4578d2a7ac5dSMat Martineau break; 4579d2a7ac5dSMat Martineau default: 4580d2a7ac5dSMat Martineau break; 4581d2a7ac5dSMat Martineau } 4582d2a7ac5dSMat Martineau 4583d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 4584d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 4585d2a7ac5dSMat Martineau kfree_skb(skb); 4586d2a7ac5dSMat Martineau } 4587d2a7ac5dSMat Martineau 4588d2a7ac5dSMat Martineau return err; 4589d2a7ac5dSMat Martineau } 4590d2a7ac5dSMat Martineau 4591d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, 4592d2a7ac5dSMat Martineau struct l2cap_ctrl *control, 4593d2a7ac5dSMat Martineau struct sk_buff *skb, u8 event) 4594d2a7ac5dSMat Martineau { 4595d2a7ac5dSMat Martineau int err = 0; 4596d2a7ac5dSMat Martineau u16 txseq = control->txseq; 4597d2a7ac5dSMat Martineau bool skb_in_use = 0; 4598d2a7ac5dSMat Martineau 4599d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, 4600d2a7ac5dSMat Martineau event); 4601d2a7ac5dSMat Martineau 4602d2a7ac5dSMat Martineau switch (event) { 4603d2a7ac5dSMat Martineau case L2CAP_EV_RECV_IFRAME: 4604d2a7ac5dSMat Martineau switch (l2cap_classify_txseq(chan, txseq)) { 4605d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED: 4606d2a7ac5dSMat Martineau /* Keep frame for reassembly later */ 4607d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4608d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4609d2a7ac5dSMat Martineau skb_in_use = 1; 4610d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4611d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4612d2a7ac5dSMat Martineau 4613d2a7ac5dSMat Martineau chan->expected_tx_seq = __next_seq(chan, txseq); 4614d2a7ac5dSMat Martineau break; 4615d2a7ac5dSMat Martineau case L2CAP_TXSEQ_EXPECTED_SREJ: 4616d2a7ac5dSMat Martineau l2cap_seq_list_pop(&chan->srej_list); 4617d2a7ac5dSMat Martineau 4618d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4619d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4620d2a7ac5dSMat Martineau skb_in_use = 1; 4621d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4622d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4623d2a7ac5dSMat Martineau 4624d2a7ac5dSMat Martineau err = l2cap_rx_queued_iframes(chan); 4625d2a7ac5dSMat Martineau if (err) 4626d2a7ac5dSMat Martineau break; 4627d2a7ac5dSMat Martineau 4628d2a7ac5dSMat Martineau break; 4629d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED: 4630d2a7ac5dSMat Martineau /* Got a frame that can't be reassembled yet. 4631d2a7ac5dSMat Martineau * Save it for later, and send SREJs to cover 4632d2a7ac5dSMat Martineau * the missing frames. 4633d2a7ac5dSMat Martineau */ 4634d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4635d2a7ac5dSMat Martineau skb_in_use = 1; 4636d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4637d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4638d2a7ac5dSMat Martineau 4639d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4640d2a7ac5dSMat Martineau l2cap_send_srej(chan, control->txseq); 4641d2a7ac5dSMat Martineau break; 4642d2a7ac5dSMat Martineau case L2CAP_TXSEQ_UNEXPECTED_SREJ: 4643d2a7ac5dSMat Martineau /* This frame was requested with an SREJ, but 4644d2a7ac5dSMat Martineau * some expected retransmitted frames are 4645d2a7ac5dSMat Martineau * missing. Request retransmission of missing 4646d2a7ac5dSMat Martineau * SREJ'd frames. 4647d2a7ac5dSMat Martineau */ 4648d2a7ac5dSMat Martineau skb_queue_tail(&chan->srej_q, skb); 4649d2a7ac5dSMat Martineau skb_in_use = 1; 4650d2a7ac5dSMat Martineau BT_DBG("Queued %p (queue len %d)", skb, 4651d2a7ac5dSMat Martineau skb_queue_len(&chan->srej_q)); 4652d2a7ac5dSMat Martineau 4653d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4654d2a7ac5dSMat Martineau l2cap_send_srej_list(chan, control->txseq); 4655d2a7ac5dSMat Martineau break; 4656d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE_SREJ: 4657d2a7ac5dSMat Martineau /* We've already queued this frame. Drop this copy. */ 4658d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4659d2a7ac5dSMat Martineau break; 4660d2a7ac5dSMat Martineau case L2CAP_TXSEQ_DUPLICATE: 4661d2a7ac5dSMat Martineau /* Expecting a later sequence number, so this frame 4662d2a7ac5dSMat Martineau * was already received. Ignore it completely. 4663d2a7ac5dSMat Martineau */ 4664d2a7ac5dSMat Martineau break; 4665d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID_IGNORE: 4666d2a7ac5dSMat Martineau break; 4667d2a7ac5dSMat Martineau case L2CAP_TXSEQ_INVALID: 4668d2a7ac5dSMat Martineau default: 4669d2a7ac5dSMat Martineau l2cap_send_disconn_req(chan->conn, chan, 4670d2a7ac5dSMat Martineau ECONNRESET); 4671d2a7ac5dSMat Martineau break; 4672d2a7ac5dSMat Martineau } 4673d2a7ac5dSMat Martineau break; 4674d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RR: 4675d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4676d2a7ac5dSMat Martineau if (control->final) { 4677d2a7ac5dSMat Martineau clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4678d2a7ac5dSMat Martineau 4679d2a7ac5dSMat Martineau if (!test_and_clear_bit(CONN_REJ_ACT, 4680d2a7ac5dSMat Martineau &chan->conn_state)) { 4681d2a7ac5dSMat Martineau control->final = 0; 4682d2a7ac5dSMat Martineau l2cap_retransmit_all(chan, control); 4683d2a7ac5dSMat Martineau } 4684d2a7ac5dSMat Martineau 4685d2a7ac5dSMat Martineau l2cap_ertm_send(chan); 4686d2a7ac5dSMat Martineau } else if (control->poll) { 4687d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 4688d2a7ac5dSMat Martineau &chan->conn_state) && 4689d2a7ac5dSMat Martineau chan->unacked_frames) { 4690d2a7ac5dSMat Martineau __set_retrans_timer(chan); 4691d2a7ac5dSMat Martineau } 4692d2a7ac5dSMat Martineau 4693d2a7ac5dSMat Martineau set_bit(CONN_SEND_FBIT, &chan->conn_state); 4694d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 4695d2a7ac5dSMat Martineau } else { 4696d2a7ac5dSMat Martineau if (test_and_clear_bit(CONN_REMOTE_BUSY, 4697d2a7ac5dSMat Martineau &chan->conn_state) && 4698d2a7ac5dSMat Martineau chan->unacked_frames) 4699d2a7ac5dSMat Martineau __set_retrans_timer(chan); 4700d2a7ac5dSMat Martineau 4701d2a7ac5dSMat Martineau l2cap_send_ack(chan); 4702d2a7ac5dSMat Martineau } 4703d2a7ac5dSMat Martineau break; 4704d2a7ac5dSMat Martineau case L2CAP_EV_RECV_RNR: 4705d2a7ac5dSMat Martineau set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4706d2a7ac5dSMat Martineau l2cap_pass_to_tx(chan, control); 4707d2a7ac5dSMat Martineau if (control->poll) { 4708d2a7ac5dSMat Martineau l2cap_send_srej_tail(chan); 4709d2a7ac5dSMat Martineau } else { 4710d2a7ac5dSMat Martineau struct l2cap_ctrl rr_control; 4711d2a7ac5dSMat Martineau memset(&rr_control, 0, sizeof(rr_control)); 4712d2a7ac5dSMat Martineau rr_control.sframe = 1; 4713d2a7ac5dSMat Martineau rr_control.super = L2CAP_SUPER_RR; 4714d2a7ac5dSMat Martineau rr_control.reqseq = chan->buffer_seq; 4715d2a7ac5dSMat Martineau l2cap_send_sframe(chan, &rr_control); 4716d2a7ac5dSMat Martineau } 4717d2a7ac5dSMat Martineau 4718d2a7ac5dSMat Martineau break; 4719d2a7ac5dSMat Martineau case L2CAP_EV_RECV_REJ: 4720d2a7ac5dSMat Martineau l2cap_handle_rej(chan, control); 4721d2a7ac5dSMat Martineau break; 4722d2a7ac5dSMat Martineau case L2CAP_EV_RECV_SREJ: 4723d2a7ac5dSMat Martineau l2cap_handle_srej(chan, control); 4724d2a7ac5dSMat Martineau break; 4725d2a7ac5dSMat Martineau } 4726d2a7ac5dSMat Martineau 4727d2a7ac5dSMat Martineau if (skb && !skb_in_use) { 4728d2a7ac5dSMat Martineau BT_DBG("Freeing %p", skb); 4729d2a7ac5dSMat Martineau kfree_skb(skb); 4730d2a7ac5dSMat Martineau } 4731d2a7ac5dSMat Martineau 4732d2a7ac5dSMat Martineau return err; 4733d2a7ac5dSMat Martineau } 4734d2a7ac5dSMat Martineau 4735d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq) 4736d2a7ac5dSMat Martineau { 4737d2a7ac5dSMat Martineau /* Make sure reqseq is for a packet that has been sent but not acked */ 4738d2a7ac5dSMat Martineau u16 unacked; 4739d2a7ac5dSMat Martineau 4740d2a7ac5dSMat Martineau unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq); 4741d2a7ac5dSMat Martineau return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked; 4742d2a7ac5dSMat Martineau } 4743d2a7ac5dSMat Martineau 4744cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 4745cec8ab6eSMat Martineau struct sk_buff *skb, u8 event) 47460a708f8fSGustavo F. Padovan { 4747d2a7ac5dSMat Martineau int err = 0; 4748d2a7ac5dSMat Martineau 4749d2a7ac5dSMat Martineau BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan, 4750d2a7ac5dSMat Martineau control, skb, event, chan->rx_state); 4751d2a7ac5dSMat Martineau 4752d2a7ac5dSMat Martineau if (__valid_reqseq(chan, control->reqseq)) { 4753d2a7ac5dSMat Martineau switch (chan->rx_state) { 4754d2a7ac5dSMat Martineau case L2CAP_RX_STATE_RECV: 4755d2a7ac5dSMat Martineau err = l2cap_rx_state_recv(chan, control, skb, event); 4756d2a7ac5dSMat Martineau break; 4757d2a7ac5dSMat Martineau case L2CAP_RX_STATE_SREJ_SENT: 4758d2a7ac5dSMat Martineau err = l2cap_rx_state_srej_sent(chan, control, skb, 4759d2a7ac5dSMat Martineau event); 4760d2a7ac5dSMat Martineau break; 4761d2a7ac5dSMat Martineau default: 4762d2a7ac5dSMat Martineau /* shut it down */ 4763d2a7ac5dSMat Martineau break; 4764d2a7ac5dSMat Martineau } 4765d2a7ac5dSMat Martineau } else { 4766d2a7ac5dSMat Martineau BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d", 4767d2a7ac5dSMat Martineau control->reqseq, chan->next_tx_seq, 4768d2a7ac5dSMat Martineau chan->expected_ack_seq); 4769d2a7ac5dSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 4770d2a7ac5dSMat Martineau } 4771d2a7ac5dSMat Martineau 4772d2a7ac5dSMat Martineau return err; 4773cec8ab6eSMat Martineau } 4774cec8ab6eSMat Martineau 4775cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 4776cec8ab6eSMat Martineau struct sk_buff *skb) 4777cec8ab6eSMat Martineau { 47784b51dae9SMat Martineau int err = 0; 47794b51dae9SMat Martineau 47804b51dae9SMat Martineau BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb, 47814b51dae9SMat Martineau chan->rx_state); 47824b51dae9SMat Martineau 47834b51dae9SMat Martineau if (l2cap_classify_txseq(chan, control->txseq) == 47844b51dae9SMat Martineau L2CAP_TXSEQ_EXPECTED) { 47854b51dae9SMat Martineau l2cap_pass_to_tx(chan, control); 47864b51dae9SMat Martineau 47874b51dae9SMat Martineau BT_DBG("buffer_seq %d->%d", chan->buffer_seq, 47884b51dae9SMat Martineau __next_seq(chan, chan->buffer_seq)); 47894b51dae9SMat Martineau 47904b51dae9SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 47914b51dae9SMat Martineau 47924b51dae9SMat Martineau l2cap_reassemble_sdu(chan, skb, control); 47934b51dae9SMat Martineau } else { 47944b51dae9SMat Martineau if (chan->sdu) { 47954b51dae9SMat Martineau kfree_skb(chan->sdu); 47964b51dae9SMat Martineau chan->sdu = NULL; 47974b51dae9SMat Martineau } 47984b51dae9SMat Martineau chan->sdu_last_frag = NULL; 47994b51dae9SMat Martineau chan->sdu_len = 0; 48004b51dae9SMat Martineau 48014b51dae9SMat Martineau if (skb) { 48024b51dae9SMat Martineau BT_DBG("Freeing %p", skb); 48034b51dae9SMat Martineau kfree_skb(skb); 48044b51dae9SMat Martineau } 48054b51dae9SMat Martineau } 48064b51dae9SMat Martineau 48074b51dae9SMat Martineau chan->last_acked_seq = control->txseq; 48084b51dae9SMat Martineau chan->expected_tx_seq = __next_seq(chan, control->txseq); 48094b51dae9SMat Martineau 48104b51dae9SMat Martineau return err; 4811cec8ab6eSMat Martineau } 4812cec8ab6eSMat Martineau 4813cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 4814cec8ab6eSMat Martineau { 4815cec8ab6eSMat Martineau struct l2cap_ctrl *control = &bt_cb(skb)->control; 4816cec8ab6eSMat Martineau u16 len; 4817cec8ab6eSMat Martineau u8 event; 48180a708f8fSGustavo F. Padovan 4819b76bbd66SMat Martineau __unpack_control(chan, skb); 4820b76bbd66SMat Martineau 48210a708f8fSGustavo F. Padovan len = skb->len; 48220a708f8fSGustavo F. Padovan 48230a708f8fSGustavo F. Padovan /* 48240a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here. 48250a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery 4826cec8ab6eSMat Martineau * procedures and ask for retransmission. 48270a708f8fSGustavo F. Padovan */ 482847d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 48290a708f8fSGustavo F. Padovan goto drop; 48300a708f8fSGustavo F. Padovan 4831cec8ab6eSMat Martineau if (!control->sframe && control->sar == L2CAP_SAR_START) 483203a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 48330a708f8fSGustavo F. Padovan 483447d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 483503a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 48360a708f8fSGustavo F. Padovan 483747d1ec61SGustavo F. Padovan if (len > chan->mps) { 48388c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 48390a708f8fSGustavo F. Padovan goto drop; 48400a708f8fSGustavo F. Padovan } 48410a708f8fSGustavo F. Padovan 4842cec8ab6eSMat Martineau if (!control->sframe) { 4843cec8ab6eSMat Martineau int err; 48440a708f8fSGustavo F. Padovan 4845cec8ab6eSMat Martineau BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d", 4846cec8ab6eSMat Martineau control->sar, control->reqseq, control->final, 4847cec8ab6eSMat Martineau control->txseq); 4848836be934SAndrei Emeltchenko 4849cec8ab6eSMat Martineau /* Validate F-bit - F=0 always valid, F=1 only 4850cec8ab6eSMat Martineau * valid in TX WAIT_F 4851cec8ab6eSMat Martineau */ 4852cec8ab6eSMat Martineau if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F) 48530a708f8fSGustavo F. Padovan goto drop; 48540a708f8fSGustavo F. Padovan 4855cec8ab6eSMat Martineau if (chan->mode != L2CAP_MODE_STREAMING) { 4856cec8ab6eSMat Martineau event = L2CAP_EV_RECV_IFRAME; 4857cec8ab6eSMat Martineau err = l2cap_rx(chan, control, skb, event); 48580a708f8fSGustavo F. Padovan } else { 4859cec8ab6eSMat Martineau err = l2cap_stream_rx(chan, control, skb); 4860cec8ab6eSMat Martineau } 4861cec8ab6eSMat Martineau 4862cec8ab6eSMat Martineau if (err) 4863cec8ab6eSMat Martineau l2cap_send_disconn_req(chan->conn, chan, 4864cec8ab6eSMat Martineau ECONNRESET); 4865cec8ab6eSMat Martineau } else { 4866cec8ab6eSMat Martineau const u8 rx_func_to_event[4] = { 4867cec8ab6eSMat Martineau L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ, 4868cec8ab6eSMat Martineau L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ 4869cec8ab6eSMat Martineau }; 4870cec8ab6eSMat Martineau 4871cec8ab6eSMat Martineau /* Only I-frames are expected in streaming mode */ 4872cec8ab6eSMat Martineau if (chan->mode == L2CAP_MODE_STREAMING) 4873cec8ab6eSMat Martineau goto drop; 4874cec8ab6eSMat Martineau 4875cec8ab6eSMat Martineau BT_DBG("sframe reqseq %d, final %d, poll %d, super %d", 4876cec8ab6eSMat Martineau control->reqseq, control->final, control->poll, 4877cec8ab6eSMat Martineau control->super); 4878cec8ab6eSMat Martineau 48790a708f8fSGustavo F. Padovan if (len != 0) { 48800a708f8fSGustavo F. Padovan BT_ERR("%d", len); 48818c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 48820a708f8fSGustavo F. Padovan goto drop; 48830a708f8fSGustavo F. Padovan } 48840a708f8fSGustavo F. Padovan 4885cec8ab6eSMat Martineau /* Validate F and P bits */ 4886cec8ab6eSMat Martineau if (control->final && (control->poll || 4887cec8ab6eSMat Martineau chan->tx_state != L2CAP_TX_STATE_WAIT_F)) 4888cec8ab6eSMat Martineau goto drop; 4889cec8ab6eSMat Martineau 4890cec8ab6eSMat Martineau event = rx_func_to_event[control->super]; 4891cec8ab6eSMat Martineau if (l2cap_rx(chan, control, skb, event)) 4892cec8ab6eSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 48930a708f8fSGustavo F. Padovan } 48940a708f8fSGustavo F. Padovan 48950a708f8fSGustavo F. Padovan return 0; 48960a708f8fSGustavo F. Padovan 48970a708f8fSGustavo F. Padovan drop: 48980a708f8fSGustavo F. Padovan kfree_skb(skb); 48990a708f8fSGustavo F. Padovan return 0; 49000a708f8fSGustavo F. Padovan } 49010a708f8fSGustavo F. Padovan 49020a708f8fSGustavo F. Padovan static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb) 49030a708f8fSGustavo F. Padovan { 490448454079SGustavo F. Padovan struct l2cap_chan *chan; 49050a708f8fSGustavo F. Padovan 4906baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 490748454079SGustavo F. Padovan if (!chan) { 49080a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid); 49096be36555SAndrei Emeltchenko /* Drop packet and return */ 49103379013bSDan Carpenter kfree_skb(skb); 49116be36555SAndrei Emeltchenko return 0; 49120a708f8fSGustavo F. Padovan } 49130a708f8fSGustavo F. Padovan 491449208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len); 49150a708f8fSGustavo F. Padovan 491689bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 49170a708f8fSGustavo F. Padovan goto drop; 49180a708f8fSGustavo F. Padovan 49190c1bc5c6SGustavo F. Padovan switch (chan->mode) { 49200a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 49210a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here 49220a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable. 49230a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't 49240a708f8fSGustavo F. Padovan * provide flow control mechanism. */ 49250a708f8fSGustavo F. Padovan 49260c1bc5c6SGustavo F. Padovan if (chan->imtu < skb->len) 49270a708f8fSGustavo F. Padovan goto drop; 49280a708f8fSGustavo F. Padovan 492923070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 49300a708f8fSGustavo F. Padovan goto done; 49310a708f8fSGustavo F. Padovan break; 49320a708f8fSGustavo F. Padovan 49330a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 49340a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 4935cec8ab6eSMat Martineau l2cap_data_rcv(chan, skb); 49360a708f8fSGustavo F. Padovan goto done; 49370a708f8fSGustavo F. Padovan 49380a708f8fSGustavo F. Padovan default: 49390c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); 49400a708f8fSGustavo F. Padovan break; 49410a708f8fSGustavo F. Padovan } 49420a708f8fSGustavo F. Padovan 49430a708f8fSGustavo F. Padovan drop: 49440a708f8fSGustavo F. Padovan kfree_skb(skb); 49450a708f8fSGustavo F. Padovan 49460a708f8fSGustavo F. Padovan done: 49476be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 49480a708f8fSGustavo F. Padovan 49490a708f8fSGustavo F. Padovan return 0; 49500a708f8fSGustavo F. Padovan } 49510a708f8fSGustavo F. Padovan 49520a708f8fSGustavo F. Padovan static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb) 49530a708f8fSGustavo F. Padovan { 495423691d75SGustavo F. Padovan struct l2cap_chan *chan; 49550a708f8fSGustavo F. Padovan 4956c2287681SIdo Yariv chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst); 495723691d75SGustavo F. Padovan if (!chan) 49580a708f8fSGustavo F. Padovan goto drop; 49590a708f8fSGustavo F. Padovan 49605b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 49610a708f8fSGustavo F. Padovan 496289bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 49630a708f8fSGustavo F. Padovan goto drop; 49640a708f8fSGustavo F. Padovan 4965e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 49660a708f8fSGustavo F. Padovan goto drop; 49670a708f8fSGustavo F. Padovan 496823070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 49695b4cedaaSAndrei Emeltchenko return 0; 49700a708f8fSGustavo F. Padovan 49710a708f8fSGustavo F. Padovan drop: 49720a708f8fSGustavo F. Padovan kfree_skb(skb); 49730a708f8fSGustavo F. Padovan 49740a708f8fSGustavo F. Padovan return 0; 49750a708f8fSGustavo F. Padovan } 49760a708f8fSGustavo F. Padovan 4977d9b88702SAndrei Emeltchenko static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid, 4978d9b88702SAndrei Emeltchenko struct sk_buff *skb) 49799f69bda6SGustavo F. Padovan { 498023691d75SGustavo F. Padovan struct l2cap_chan *chan; 49819f69bda6SGustavo F. Padovan 4982c2287681SIdo Yariv chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst); 498323691d75SGustavo F. Padovan if (!chan) 49849f69bda6SGustavo F. Padovan goto drop; 49859f69bda6SGustavo F. Padovan 49865b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 49879f69bda6SGustavo F. Padovan 498889bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 49899f69bda6SGustavo F. Padovan goto drop; 49909f69bda6SGustavo F. Padovan 4991e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 49929f69bda6SGustavo F. Padovan goto drop; 49939f69bda6SGustavo F. Padovan 499423070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 49955b4cedaaSAndrei Emeltchenko return 0; 49969f69bda6SGustavo F. Padovan 49979f69bda6SGustavo F. Padovan drop: 49989f69bda6SGustavo F. Padovan kfree_skb(skb); 49999f69bda6SGustavo F. Padovan 50009f69bda6SGustavo F. Padovan return 0; 50019f69bda6SGustavo F. Padovan } 50029f69bda6SGustavo F. Padovan 50030a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) 50040a708f8fSGustavo F. Padovan { 50050a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data; 50060a708f8fSGustavo F. Padovan u16 cid, len; 50070a708f8fSGustavo F. Padovan __le16 psm; 50080a708f8fSGustavo F. Padovan 50090a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE); 50100a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid); 50110a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len); 50120a708f8fSGustavo F. Padovan 50130a708f8fSGustavo F. Padovan if (len != skb->len) { 50140a708f8fSGustavo F. Padovan kfree_skb(skb); 50150a708f8fSGustavo F. Padovan return; 50160a708f8fSGustavo F. Padovan } 50170a708f8fSGustavo F. Padovan 50180a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid); 50190a708f8fSGustavo F. Padovan 50200a708f8fSGustavo F. Padovan switch (cid) { 50213300d9a9SClaudio Takahasi case L2CAP_CID_LE_SIGNALING: 50220a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING: 50230a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb); 50240a708f8fSGustavo F. Padovan break; 50250a708f8fSGustavo F. Padovan 50260a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS: 5027097db76cSAndrei Emeltchenko psm = get_unaligned((__le16 *) skb->data); 50280a708f8fSGustavo F. Padovan skb_pull(skb, 2); 50290a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb); 50300a708f8fSGustavo F. Padovan break; 50310a708f8fSGustavo F. Padovan 50329f69bda6SGustavo F. Padovan case L2CAP_CID_LE_DATA: 50339f69bda6SGustavo F. Padovan l2cap_att_channel(conn, cid, skb); 50349f69bda6SGustavo F. Padovan break; 50359f69bda6SGustavo F. Padovan 5036b501d6a1SAnderson Briglia case L2CAP_CID_SMP: 5037b501d6a1SAnderson Briglia if (smp_sig_channel(conn, skb)) 5038b501d6a1SAnderson Briglia l2cap_conn_del(conn->hcon, EACCES); 5039b501d6a1SAnderson Briglia break; 5040b501d6a1SAnderson Briglia 50410a708f8fSGustavo F. Padovan default: 50420a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb); 50430a708f8fSGustavo F. Padovan break; 50440a708f8fSGustavo F. Padovan } 50450a708f8fSGustavo F. Padovan } 50460a708f8fSGustavo F. Padovan 50470a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */ 50480a708f8fSGustavo F. Padovan 5049686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) 50500a708f8fSGustavo F. Padovan { 50510a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0; 505223691d75SGustavo F. Padovan struct l2cap_chan *c; 50530a708f8fSGustavo F. Padovan 50540a708f8fSGustavo F. Padovan BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); 50550a708f8fSGustavo F. Padovan 50560a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */ 505723691d75SGustavo F. Padovan read_lock(&chan_list_lock); 505823691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 505923691d75SGustavo F. Padovan struct sock *sk = c->sk; 50604343478fSGustavo F. Padovan 506189bc500eSGustavo F. Padovan if (c->state != BT_LISTEN) 50620a708f8fSGustavo F. Padovan continue; 50630a708f8fSGustavo F. Padovan 50640a708f8fSGustavo F. Padovan if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { 50650a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT; 506643bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 50670a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER; 50680a708f8fSGustavo F. Padovan exact++; 50690a708f8fSGustavo F. Padovan } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { 50700a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT; 507143bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 50720a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER; 50730a708f8fSGustavo F. Padovan } 50740a708f8fSGustavo F. Padovan } 507523691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 50760a708f8fSGustavo F. Padovan 50770a708f8fSGustavo F. Padovan return exact ? lm1 : lm2; 50780a708f8fSGustavo F. Padovan } 50790a708f8fSGustavo F. Padovan 5080686ebf28SUlisses Furquim int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) 50810a708f8fSGustavo F. Padovan { 50820a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 50830a708f8fSGustavo F. Padovan 50840a708f8fSGustavo F. Padovan BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); 50850a708f8fSGustavo F. Padovan 50860a708f8fSGustavo F. Padovan if (!status) { 50870a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, status); 50880a708f8fSGustavo F. Padovan if (conn) 50890a708f8fSGustavo F. Padovan l2cap_conn_ready(conn); 50900a708f8fSGustavo F. Padovan } else 5091e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status)); 50920a708f8fSGustavo F. Padovan 50930a708f8fSGustavo F. Padovan return 0; 50940a708f8fSGustavo F. Padovan } 50950a708f8fSGustavo F. Padovan 5096686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon) 50970a708f8fSGustavo F. Padovan { 50980a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 50990a708f8fSGustavo F. Padovan 51000a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon); 51010a708f8fSGustavo F. Padovan 5102686ebf28SUlisses Furquim if (!conn) 51039f5a0d7bSAndrei Emeltchenko return HCI_ERROR_REMOTE_USER_TERM; 51040a708f8fSGustavo F. Padovan return conn->disc_reason; 51050a708f8fSGustavo F. Padovan } 51060a708f8fSGustavo F. Padovan 5107686ebf28SUlisses Furquim int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) 51080a708f8fSGustavo F. Padovan { 51090a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason); 51100a708f8fSGustavo F. Padovan 5111e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason)); 51120a708f8fSGustavo F. Padovan return 0; 51130a708f8fSGustavo F. Padovan } 51140a708f8fSGustavo F. Padovan 51154343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) 51160a708f8fSGustavo F. Padovan { 5117715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 51180a708f8fSGustavo F. Padovan return; 51190a708f8fSGustavo F. Padovan 51200a708f8fSGustavo F. Padovan if (encrypt == 0x00) { 51214343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) { 5122ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); 51234343478fSGustavo F. Padovan } else if (chan->sec_level == BT_SECURITY_HIGH) 51240f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED); 51250a708f8fSGustavo F. Padovan } else { 51264343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) 5127c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 51280a708f8fSGustavo F. Padovan } 51290a708f8fSGustavo F. Padovan } 51300a708f8fSGustavo F. Padovan 5131686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) 51320a708f8fSGustavo F. Padovan { 51330a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 513448454079SGustavo F. Padovan struct l2cap_chan *chan; 51350a708f8fSGustavo F. Padovan 51360a708f8fSGustavo F. Padovan if (!conn) 51370a708f8fSGustavo F. Padovan return 0; 51380a708f8fSGustavo F. Padovan 51390a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 51400a708f8fSGustavo F. Padovan 5141160dc6acSVinicius Costa Gomes if (hcon->type == LE_LINK) { 514235d4adccSHemant Gupta if (!status && encrypt) 5143160dc6acSVinicius Costa Gomes smp_distribute_keys(conn, 0); 514417cd3f37SUlisses Furquim cancel_delayed_work(&conn->security_timer); 5145160dc6acSVinicius Costa Gomes } 5146160dc6acSVinicius Costa Gomes 51473df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 51480a708f8fSGustavo F. Padovan 51493df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 51506be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 51510a708f8fSGustavo F. Padovan 5152f1cb9af5SVinicius Costa Gomes BT_DBG("chan->scid %d", chan->scid); 5153f1cb9af5SVinicius Costa Gomes 5154f1cb9af5SVinicius Costa Gomes if (chan->scid == L2CAP_CID_LE_DATA) { 5155f1cb9af5SVinicius Costa Gomes if (!status && encrypt) { 5156f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level; 5157cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 5158f1cb9af5SVinicius Costa Gomes } 5159f1cb9af5SVinicius Costa Gomes 51606be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 5161f1cb9af5SVinicius Costa Gomes continue; 5162f1cb9af5SVinicius Costa Gomes } 5163f1cb9af5SVinicius Costa Gomes 5164c1360a1cSGustavo F. Padovan if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) { 51656be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 51660a708f8fSGustavo F. Padovan continue; 51670a708f8fSGustavo F. Padovan } 51680a708f8fSGustavo F. Padovan 516989bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED || 517089bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) { 5171a7d7723aSGustavo Padovan struct sock *sk = chan->sk; 5172a7d7723aSGustavo Padovan 5173c5daa683SGustavo Padovan clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); 5174a7d7723aSGustavo Padovan sk->sk_state_change(sk); 5175a7d7723aSGustavo Padovan 51764343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt); 51776be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 51780a708f8fSGustavo F. Padovan continue; 51790a708f8fSGustavo F. Padovan } 51800a708f8fSGustavo F. Padovan 518189bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 51820a708f8fSGustavo F. Padovan if (!status) { 51839b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 51840a708f8fSGustavo F. Padovan } else { 5185ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 51860a708f8fSGustavo F. Padovan } 518789bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 51886be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 51890a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 5190df3c3931SJohan Hedberg __u16 res, stat; 51910a708f8fSGustavo F. Padovan 51926be36555SAndrei Emeltchenko lock_sock(sk); 51936be36555SAndrei Emeltchenko 51940a708f8fSGustavo F. Padovan if (!status) { 5195c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, 5196c5daa683SGustavo Padovan &bt_sk(sk)->flags)) { 5197df3c3931SJohan Hedberg struct sock *parent = bt_sk(sk)->parent; 5198df3c3931SJohan Hedberg res = L2CAP_CR_PEND; 5199df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND; 520005e9a2f6SIlia Kolomisnky if (parent) 5201df3c3931SJohan Hedberg parent->sk_data_ready(parent, 0); 5202df3c3931SJohan Hedberg } else { 52030e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 5204df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS; 5205df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 5206df3c3931SJohan Hedberg } 52070a708f8fSGustavo F. Padovan } else { 52080e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_DISCONN); 5209ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 5210df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK; 5211df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 52120a708f8fSGustavo F. Padovan } 52130a708f8fSGustavo F. Padovan 52146be36555SAndrei Emeltchenko release_sock(sk); 52156be36555SAndrei Emeltchenko 5216fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 5217fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 5218df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res); 5219df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat); 5220fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 5221fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 52220a708f8fSGustavo F. Padovan } 52230a708f8fSGustavo F. Padovan 52246be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 52250a708f8fSGustavo F. Padovan } 52260a708f8fSGustavo F. Padovan 52273df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 52280a708f8fSGustavo F. Padovan 52290a708f8fSGustavo F. Padovan return 0; 52300a708f8fSGustavo F. Padovan } 52310a708f8fSGustavo F. Padovan 5232686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) 52330a708f8fSGustavo F. Padovan { 52340a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 52350a708f8fSGustavo F. Padovan 52360a708f8fSGustavo F. Padovan if (!conn) 52370a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, 0); 52380a708f8fSGustavo F. Padovan 52390a708f8fSGustavo F. Padovan if (!conn) 52400a708f8fSGustavo F. Padovan goto drop; 52410a708f8fSGustavo F. Padovan 52420a708f8fSGustavo F. Padovan BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); 52430a708f8fSGustavo F. Padovan 52440a708f8fSGustavo F. Padovan if (!(flags & ACL_CONT)) { 52450a708f8fSGustavo F. Padovan struct l2cap_hdr *hdr; 52460a708f8fSGustavo F. Padovan int len; 52470a708f8fSGustavo F. Padovan 52480a708f8fSGustavo F. Padovan if (conn->rx_len) { 52490a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len); 52500a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 52510a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 52520a708f8fSGustavo F. Padovan conn->rx_len = 0; 52530a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 52540a708f8fSGustavo F. Padovan } 52550a708f8fSGustavo F. Padovan 52560a708f8fSGustavo F. Padovan /* Start fragment always begin with Basic L2CAP header */ 52570a708f8fSGustavo F. Padovan if (skb->len < L2CAP_HDR_SIZE) { 52580a708f8fSGustavo F. Padovan BT_ERR("Frame is too short (len %d)", skb->len); 52590a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 52600a708f8fSGustavo F. Padovan goto drop; 52610a708f8fSGustavo F. Padovan } 52620a708f8fSGustavo F. Padovan 52630a708f8fSGustavo F. Padovan hdr = (struct l2cap_hdr *) skb->data; 52640a708f8fSGustavo F. Padovan len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; 52650a708f8fSGustavo F. Padovan 52660a708f8fSGustavo F. Padovan if (len == skb->len) { 52670a708f8fSGustavo F. Padovan /* Complete frame received */ 52680a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb); 52690a708f8fSGustavo F. Padovan return 0; 52700a708f8fSGustavo F. Padovan } 52710a708f8fSGustavo F. Padovan 52720a708f8fSGustavo F. Padovan BT_DBG("Start: total len %d, frag len %d", len, skb->len); 52730a708f8fSGustavo F. Padovan 52740a708f8fSGustavo F. Padovan if (skb->len > len) { 52750a708f8fSGustavo F. Padovan BT_ERR("Frame is too long (len %d, expected len %d)", 52760a708f8fSGustavo F. Padovan skb->len, len); 52770a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 52780a708f8fSGustavo F. Padovan goto drop; 52790a708f8fSGustavo F. Padovan } 52800a708f8fSGustavo F. Padovan 52810a708f8fSGustavo F. Padovan /* Allocate skb for the complete frame (with header) */ 52820a708f8fSGustavo F. Padovan conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC); 52830a708f8fSGustavo F. Padovan if (!conn->rx_skb) 52840a708f8fSGustavo F. Padovan goto drop; 52850a708f8fSGustavo F. Padovan 52860a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 52870a708f8fSGustavo F. Padovan skb->len); 52880a708f8fSGustavo F. Padovan conn->rx_len = len - skb->len; 52890a708f8fSGustavo F. Padovan } else { 52900a708f8fSGustavo F. Padovan BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); 52910a708f8fSGustavo F. Padovan 52920a708f8fSGustavo F. Padovan if (!conn->rx_len) { 52930a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len); 52940a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 52950a708f8fSGustavo F. Padovan goto drop; 52960a708f8fSGustavo F. Padovan } 52970a708f8fSGustavo F. Padovan 52980a708f8fSGustavo F. Padovan if (skb->len > conn->rx_len) { 52990a708f8fSGustavo F. Padovan BT_ERR("Fragment is too long (len %d, expected %d)", 53000a708f8fSGustavo F. Padovan skb->len, conn->rx_len); 53010a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 53020a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 53030a708f8fSGustavo F. Padovan conn->rx_len = 0; 53040a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 53050a708f8fSGustavo F. Padovan goto drop; 53060a708f8fSGustavo F. Padovan } 53070a708f8fSGustavo F. Padovan 53080a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 53090a708f8fSGustavo F. Padovan skb->len); 53100a708f8fSGustavo F. Padovan conn->rx_len -= skb->len; 53110a708f8fSGustavo F. Padovan 53120a708f8fSGustavo F. Padovan if (!conn->rx_len) { 53130a708f8fSGustavo F. Padovan /* Complete frame received */ 53140a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, conn->rx_skb); 53150a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 53160a708f8fSGustavo F. Padovan } 53170a708f8fSGustavo F. Padovan } 53180a708f8fSGustavo F. Padovan 53190a708f8fSGustavo F. Padovan drop: 53200a708f8fSGustavo F. Padovan kfree_skb(skb); 53210a708f8fSGustavo F. Padovan return 0; 53220a708f8fSGustavo F. Padovan } 53230a708f8fSGustavo F. Padovan 53240a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p) 53250a708f8fSGustavo F. Padovan { 532623691d75SGustavo F. Padovan struct l2cap_chan *c; 53270a708f8fSGustavo F. Padovan 5328333055f2SGustavo F. Padovan read_lock(&chan_list_lock); 53290a708f8fSGustavo F. Padovan 533023691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 533123691d75SGustavo F. Padovan struct sock *sk = c->sk; 53320a708f8fSGustavo F. Padovan 5333903d343eSGustavo F. Padovan seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", 53340a708f8fSGustavo F. Padovan batostr(&bt_sk(sk)->src), 53350a708f8fSGustavo F. Padovan batostr(&bt_sk(sk)->dst), 533689bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm), 533723691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu, 533823691d75SGustavo F. Padovan c->sec_level, c->mode); 53390a708f8fSGustavo F. Padovan } 53400a708f8fSGustavo F. Padovan 5341333055f2SGustavo F. Padovan read_unlock(&chan_list_lock); 53420a708f8fSGustavo F. Padovan 53430a708f8fSGustavo F. Padovan return 0; 53440a708f8fSGustavo F. Padovan } 53450a708f8fSGustavo F. Padovan 53460a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file) 53470a708f8fSGustavo F. Padovan { 53480a708f8fSGustavo F. Padovan return single_open(file, l2cap_debugfs_show, inode->i_private); 53490a708f8fSGustavo F. Padovan } 53500a708f8fSGustavo F. Padovan 53510a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = { 53520a708f8fSGustavo F. Padovan .open = l2cap_debugfs_open, 53530a708f8fSGustavo F. Padovan .read = seq_read, 53540a708f8fSGustavo F. Padovan .llseek = seq_lseek, 53550a708f8fSGustavo F. Padovan .release = single_release, 53560a708f8fSGustavo F. Padovan }; 53570a708f8fSGustavo F. Padovan 53580a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs; 53590a708f8fSGustavo F. Padovan 536064274518SGustavo F. Padovan int __init l2cap_init(void) 53610a708f8fSGustavo F. Padovan { 53620a708f8fSGustavo F. Padovan int err; 53630a708f8fSGustavo F. Padovan 5364bb58f747SGustavo F. Padovan err = l2cap_init_sockets(); 53650a708f8fSGustavo F. Padovan if (err < 0) 53660a708f8fSGustavo F. Padovan return err; 53670a708f8fSGustavo F. Padovan 53680a708f8fSGustavo F. Padovan if (bt_debugfs) { 53690a708f8fSGustavo F. Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, 53700a708f8fSGustavo F. Padovan bt_debugfs, NULL, &l2cap_debugfs_fops); 53710a708f8fSGustavo F. Padovan if (!l2cap_debugfs) 53720a708f8fSGustavo F. Padovan BT_ERR("Failed to create L2CAP debug file"); 53730a708f8fSGustavo F. Padovan } 53740a708f8fSGustavo F. Padovan 53750a708f8fSGustavo F. Padovan return 0; 53760a708f8fSGustavo F. Padovan } 53770a708f8fSGustavo F. Padovan 537864274518SGustavo F. Padovan void l2cap_exit(void) 53790a708f8fSGustavo F. Padovan { 53800a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs); 5381bb58f747SGustavo F. Padovan l2cap_cleanup_sockets(); 53820a708f8fSGustavo F. Padovan } 53830a708f8fSGustavo F. Padovan 53840a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644); 53850a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); 5386