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 1763525cd185SGustavo F. Padovan static int l2cap_retransmit_frames(struct l2cap_chan *chan) 17640a708f8fSGustavo F. Padovan { 17650a708f8fSGustavo F. Padovan int ret; 17660a708f8fSGustavo F. Padovan 176758d35f87SGustavo F. Padovan if (!skb_queue_empty(&chan->tx_q)) 176858d35f87SGustavo F. Padovan chan->tx_send_head = chan->tx_q.next; 17690a708f8fSGustavo F. Padovan 177042e5c802SGustavo F. Padovan chan->next_tx_seq = chan->expected_ack_seq; 1771525cd185SGustavo F. Padovan ret = l2cap_ertm_send(chan); 17720a708f8fSGustavo F. Padovan return ret; 17730a708f8fSGustavo F. Padovan } 17740a708f8fSGustavo F. Padovan 1775b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan) 1776b17e73bbSSzymon Janc { 17770a0aba42SMat Martineau struct l2cap_ctrl control; 17780a0aba42SMat Martineau u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq, 17790a0aba42SMat Martineau chan->last_acked_seq); 17800a0aba42SMat Martineau int threshold; 17810a0aba42SMat Martineau 17820a0aba42SMat Martineau BT_DBG("chan %p last_acked_seq %d buffer_seq %d", 17830a0aba42SMat Martineau chan, chan->last_acked_seq, chan->buffer_seq); 17840a0aba42SMat Martineau 17850a0aba42SMat Martineau memset(&control, 0, sizeof(control)); 17860a0aba42SMat Martineau control.sframe = 1; 17870a0aba42SMat Martineau 17880a0aba42SMat Martineau if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 17890a0aba42SMat Martineau chan->rx_state == L2CAP_RX_STATE_RECV) { 1790b17e73bbSSzymon Janc __clear_ack_timer(chan); 17910a0aba42SMat Martineau control.super = L2CAP_SUPER_RNR; 17920a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 17930a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 17940a0aba42SMat Martineau } else { 17950a0aba42SMat Martineau if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) { 17960a0aba42SMat Martineau l2cap_ertm_send(chan); 17970a0aba42SMat Martineau /* If any i-frames were sent, they included an ack */ 17980a0aba42SMat Martineau if (chan->buffer_seq == chan->last_acked_seq) 17990a0aba42SMat Martineau frames_to_ack = 0; 18000a0aba42SMat Martineau } 18010a0aba42SMat Martineau 18020a0aba42SMat Martineau /* Ack now if the tx window is 3/4ths full. 18030a0aba42SMat Martineau * Calculate without mul or div 18040a0aba42SMat Martineau */ 18050a0aba42SMat Martineau threshold = chan->tx_win; 18060a0aba42SMat Martineau threshold += threshold << 1; 18070a0aba42SMat Martineau threshold >>= 2; 18080a0aba42SMat Martineau 18090a0aba42SMat Martineau BT_DBG("frames_to_ack %d, threshold %d", (int)frames_to_ack, 18100a0aba42SMat Martineau threshold); 18110a0aba42SMat Martineau 18120a0aba42SMat Martineau if (frames_to_ack >= threshold) { 18130a0aba42SMat Martineau __clear_ack_timer(chan); 18140a0aba42SMat Martineau control.super = L2CAP_SUPER_RR; 18150a0aba42SMat Martineau control.reqseq = chan->buffer_seq; 18160a0aba42SMat Martineau l2cap_send_sframe(chan, &control); 18170a0aba42SMat Martineau frames_to_ack = 0; 18180a0aba42SMat Martineau } 18190a0aba42SMat Martineau 18200a0aba42SMat Martineau if (frames_to_ack) 18210a0aba42SMat Martineau __set_ack_timer(chan); 18220a0aba42SMat Martineau } 1823b17e73bbSSzymon Janc } 1824b17e73bbSSzymon Janc 182504124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, 182604124681SGustavo F. Padovan struct msghdr *msg, int len, 182704124681SGustavo F. Padovan int count, struct sk_buff *skb) 18280a708f8fSGustavo F. Padovan { 18290952a57aSAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 18300a708f8fSGustavo F. Padovan struct sk_buff **frag; 183190338947SGustavo Padovan int sent = 0; 18320a708f8fSGustavo F. Padovan 18330a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) 18340a708f8fSGustavo F. Padovan return -EFAULT; 18350a708f8fSGustavo F. Padovan 18360a708f8fSGustavo F. Padovan sent += count; 18370a708f8fSGustavo F. Padovan len -= count; 18380a708f8fSGustavo F. Padovan 18390a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 18400a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 18410a708f8fSGustavo F. Padovan while (len) { 1842fbe00700SGustavo Padovan struct sk_buff *tmp; 1843fbe00700SGustavo Padovan 18440a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 18450a708f8fSGustavo F. Padovan 1846fbe00700SGustavo Padovan tmp = chan->ops->alloc_skb(chan, count, 184790338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 1848fbe00700SGustavo Padovan if (IS_ERR(tmp)) 1849fbe00700SGustavo Padovan return PTR_ERR(tmp); 18502f7719ceSAndrei Emeltchenko 1851fbe00700SGustavo Padovan *frag = tmp; 1852fbe00700SGustavo Padovan 18530a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) 18540a708f8fSGustavo F. Padovan return -EFAULT; 18550a708f8fSGustavo F. Padovan 18565e59b791SLuiz Augusto von Dentz (*frag)->priority = skb->priority; 18575e59b791SLuiz Augusto von Dentz 18580a708f8fSGustavo F. Padovan sent += count; 18590a708f8fSGustavo F. Padovan len -= count; 18600a708f8fSGustavo F. Padovan 18612d0ed3d5SGustavo Padovan skb->len += (*frag)->len; 18622d0ed3d5SGustavo Padovan skb->data_len += (*frag)->len; 18632d0ed3d5SGustavo Padovan 18640a708f8fSGustavo F. Padovan frag = &(*frag)->next; 18650a708f8fSGustavo F. Padovan } 18660a708f8fSGustavo F. Padovan 18670a708f8fSGustavo F. Padovan return sent; 18680a708f8fSGustavo F. Padovan } 18690a708f8fSGustavo F. Padovan 18705e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, 18715e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 18725e59b791SLuiz Augusto von Dentz u32 priority) 18730a708f8fSGustavo F. Padovan { 18748c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 18750a708f8fSGustavo F. Padovan struct sk_buff *skb; 187603a51213SAndrei Emeltchenko int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; 18770a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 18780a708f8fSGustavo F. Padovan 18796d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d priority %u", chan, (int)len, priority); 18800a708f8fSGustavo F. Padovan 18810a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 18822f7719ceSAndrei Emeltchenko 18832f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 188490338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 188590338947SGustavo Padovan if (IS_ERR(skb)) 188690338947SGustavo Padovan return skb; 18870a708f8fSGustavo F. Padovan 18885e59b791SLuiz Augusto von Dentz skb->priority = priority; 18895e59b791SLuiz Augusto von Dentz 18900a708f8fSGustavo F. Padovan /* Create L2CAP header */ 18910a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 1892fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 1893daf6a78cSAndrei Emeltchenko lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); 1894daf6a78cSAndrei Emeltchenko put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE)); 18950a708f8fSGustavo F. Padovan 18960952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 18970a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 18980a708f8fSGustavo F. Padovan kfree_skb(skb); 18990a708f8fSGustavo F. Padovan return ERR_PTR(err); 19000a708f8fSGustavo F. Padovan } 19010a708f8fSGustavo F. Padovan return skb; 19020a708f8fSGustavo F. Padovan } 19030a708f8fSGustavo F. Padovan 19045e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, 19055e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 19065e59b791SLuiz Augusto von Dentz u32 priority) 19070a708f8fSGustavo F. Padovan { 19088c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 19090a708f8fSGustavo F. Padovan struct sk_buff *skb; 1910f2ba7faeSGustavo Padovan int err, count; 19110a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 19120a708f8fSGustavo F. Padovan 19136d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d", chan, (int)len); 19140a708f8fSGustavo F. Padovan 1915f2ba7faeSGustavo Padovan count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); 19162f7719ceSAndrei Emeltchenko 1917f2ba7faeSGustavo Padovan skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE, 191890338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 191990338947SGustavo Padovan if (IS_ERR(skb)) 192090338947SGustavo Padovan return skb; 19210a708f8fSGustavo F. Padovan 19225e59b791SLuiz Augusto von Dentz skb->priority = priority; 19235e59b791SLuiz Augusto von Dentz 19240a708f8fSGustavo F. Padovan /* Create L2CAP header */ 19250a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 1926fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 19276ff9b5efSGustavo Padovan lh->len = cpu_to_le16(len); 19280a708f8fSGustavo F. Padovan 19290952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 19300a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 19310a708f8fSGustavo F. Padovan kfree_skb(skb); 19320a708f8fSGustavo F. Padovan return ERR_PTR(err); 19330a708f8fSGustavo F. Padovan } 19340a708f8fSGustavo F. Padovan return skb; 19350a708f8fSGustavo F. Padovan } 19360a708f8fSGustavo F. Padovan 1937ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, 1938ab0ff76dSLuiz Augusto von Dentz struct msghdr *msg, size_t len, 193994122bbeSMat Martineau u16 sdulen) 19400a708f8fSGustavo F. Padovan { 19418c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 19420a708f8fSGustavo F. Padovan struct sk_buff *skb; 1943e4ca6d98SAndrei Emeltchenko int err, count, hlen; 19440a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 19450a708f8fSGustavo F. Padovan 19466d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d", chan, (int)len); 19470a708f8fSGustavo F. Padovan 19480a708f8fSGustavo F. Padovan if (!conn) 19490a708f8fSGustavo F. Padovan return ERR_PTR(-ENOTCONN); 19500a708f8fSGustavo F. Padovan 1951e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1952e4ca6d98SAndrei Emeltchenko hlen = L2CAP_EXT_HDR_SIZE; 1953e4ca6d98SAndrei Emeltchenko else 1954e4ca6d98SAndrei Emeltchenko hlen = L2CAP_ENH_HDR_SIZE; 1955e4ca6d98SAndrei Emeltchenko 19560a708f8fSGustavo F. Padovan if (sdulen) 195703a51213SAndrei Emeltchenko hlen += L2CAP_SDULEN_SIZE; 19580a708f8fSGustavo F. Padovan 195947d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 196003a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 19610a708f8fSGustavo F. Padovan 19620a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 19632f7719ceSAndrei Emeltchenko 19642f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 196590338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 196690338947SGustavo Padovan if (IS_ERR(skb)) 196790338947SGustavo Padovan return skb; 19680a708f8fSGustavo F. Padovan 19690a708f8fSGustavo F. Padovan /* Create L2CAP header */ 19700a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 1971fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 19720a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 197388843ab0SAndrei Emeltchenko 197418a48e76SMat Martineau /* Control header is populated later */ 197518a48e76SMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 197618a48e76SMat Martineau put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); 197718a48e76SMat Martineau else 197818a48e76SMat Martineau put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); 197988843ab0SAndrei Emeltchenko 19800a708f8fSGustavo F. Padovan if (sdulen) 198103a51213SAndrei Emeltchenko put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 19820a708f8fSGustavo F. Padovan 19830952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 19840a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 19850a708f8fSGustavo F. Padovan kfree_skb(skb); 19860a708f8fSGustavo F. Padovan return ERR_PTR(err); 19870a708f8fSGustavo F. Padovan } 19880a708f8fSGustavo F. Padovan 198918a48e76SMat Martineau bt_cb(skb)->control.fcs = chan->fcs; 19903ce3514fSMat Martineau bt_cb(skb)->control.retries = 0; 19910a708f8fSGustavo F. Padovan return skb; 19920a708f8fSGustavo F. Padovan } 19930a708f8fSGustavo F. Padovan 199494122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan, 199594122bbeSMat Martineau struct sk_buff_head *seg_queue, 199694122bbeSMat Martineau struct msghdr *msg, size_t len) 19970a708f8fSGustavo F. Padovan { 19980a708f8fSGustavo F. Padovan struct sk_buff *skb; 199994122bbeSMat Martineau u16 sdu_len; 200094122bbeSMat Martineau size_t pdu_len; 200194122bbeSMat Martineau int err = 0; 200294122bbeSMat Martineau u8 sar; 20030a708f8fSGustavo F. Padovan 200494122bbeSMat Martineau BT_DBG("chan %p, msg %p, len %d", chan, msg, (int)len); 20050a708f8fSGustavo F. Padovan 200694122bbeSMat Martineau /* It is critical that ERTM PDUs fit in a single HCI fragment, 200794122bbeSMat Martineau * so fragmented skbs are not used. The HCI layer's handling 200894122bbeSMat Martineau * of fragmented skbs is not compatible with ERTM's queueing. 200994122bbeSMat Martineau */ 201094122bbeSMat Martineau 201194122bbeSMat Martineau /* PDU size is derived from the HCI MTU */ 201294122bbeSMat Martineau pdu_len = chan->conn->mtu; 201394122bbeSMat Martineau 201494122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); 201594122bbeSMat Martineau 201694122bbeSMat Martineau /* Adjust for largest possible L2CAP overhead. */ 201794122bbeSMat Martineau pdu_len -= L2CAP_EXT_HDR_SIZE + L2CAP_FCS_SIZE; 201894122bbeSMat Martineau 201994122bbeSMat Martineau /* Remote device may have requested smaller PDUs */ 202094122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, chan->remote_mps); 202194122bbeSMat Martineau 202294122bbeSMat Martineau if (len <= pdu_len) { 202394122bbeSMat Martineau sar = L2CAP_SAR_UNSEGMENTED; 202494122bbeSMat Martineau sdu_len = 0; 202594122bbeSMat Martineau pdu_len = len; 202694122bbeSMat Martineau } else { 202794122bbeSMat Martineau sar = L2CAP_SAR_START; 202894122bbeSMat Martineau sdu_len = len; 202994122bbeSMat Martineau pdu_len -= L2CAP_SDULEN_SIZE; 203094122bbeSMat Martineau } 20310a708f8fSGustavo F. Padovan 20320a708f8fSGustavo F. Padovan while (len > 0) { 203394122bbeSMat Martineau skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len); 20340a708f8fSGustavo F. Padovan 20350a708f8fSGustavo F. Padovan if (IS_ERR(skb)) { 203694122bbeSMat Martineau __skb_queue_purge(seg_queue); 20370a708f8fSGustavo F. Padovan return PTR_ERR(skb); 20380a708f8fSGustavo F. Padovan } 20390a708f8fSGustavo F. Padovan 204094122bbeSMat Martineau bt_cb(skb)->control.sar = sar; 204194122bbeSMat Martineau __skb_queue_tail(seg_queue, skb); 20420a708f8fSGustavo F. Padovan 204394122bbeSMat Martineau len -= pdu_len; 204494122bbeSMat Martineau if (sdu_len) { 204594122bbeSMat Martineau sdu_len = 0; 204694122bbeSMat Martineau pdu_len += L2CAP_SDULEN_SIZE; 204794122bbeSMat Martineau } 204894122bbeSMat Martineau 204994122bbeSMat Martineau if (len <= pdu_len) { 205094122bbeSMat Martineau sar = L2CAP_SAR_END; 205194122bbeSMat Martineau pdu_len = len; 205294122bbeSMat Martineau } else { 205394122bbeSMat Martineau sar = L2CAP_SAR_CONTINUE; 205494122bbeSMat Martineau } 205594122bbeSMat Martineau } 205694122bbeSMat Martineau 205794122bbeSMat Martineau return err; 20580a708f8fSGustavo F. Padovan } 20590a708f8fSGustavo F. Padovan 20605e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, 20615e59b791SLuiz Augusto von Dentz u32 priority) 20629a91a04aSGustavo F. Padovan { 20639a91a04aSGustavo F. Padovan struct sk_buff *skb; 20649a91a04aSGustavo F. Padovan int err; 206594122bbeSMat Martineau struct sk_buff_head seg_queue; 20669a91a04aSGustavo F. Padovan 20679a91a04aSGustavo F. Padovan /* Connectionless channel */ 2068715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { 20695e59b791SLuiz Augusto von Dentz skb = l2cap_create_connless_pdu(chan, msg, len, priority); 20709a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 20719a91a04aSGustavo F. Padovan return PTR_ERR(skb); 20729a91a04aSGustavo F. Padovan 20739a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 20749a91a04aSGustavo F. Padovan return len; 20759a91a04aSGustavo F. Padovan } 20769a91a04aSGustavo F. Padovan 20779a91a04aSGustavo F. Padovan switch (chan->mode) { 20789a91a04aSGustavo F. Padovan case L2CAP_MODE_BASIC: 20799a91a04aSGustavo F. Padovan /* Check outgoing MTU */ 20809a91a04aSGustavo F. Padovan if (len > chan->omtu) 20819a91a04aSGustavo F. Padovan return -EMSGSIZE; 20829a91a04aSGustavo F. Padovan 20839a91a04aSGustavo F. Padovan /* Create a basic PDU */ 20845e59b791SLuiz Augusto von Dentz skb = l2cap_create_basic_pdu(chan, msg, len, priority); 20859a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 20869a91a04aSGustavo F. Padovan return PTR_ERR(skb); 20879a91a04aSGustavo F. Padovan 20889a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 20899a91a04aSGustavo F. Padovan err = len; 20909a91a04aSGustavo F. Padovan break; 20919a91a04aSGustavo F. Padovan 20929a91a04aSGustavo F. Padovan case L2CAP_MODE_ERTM: 20939a91a04aSGustavo F. Padovan case L2CAP_MODE_STREAMING: 209494122bbeSMat Martineau /* Check outgoing MTU */ 209594122bbeSMat Martineau if (len > chan->omtu) { 209694122bbeSMat Martineau err = -EMSGSIZE; 20979a91a04aSGustavo F. Padovan break; 20989a91a04aSGustavo F. Padovan } 20999a91a04aSGustavo F. Padovan 210094122bbeSMat Martineau __skb_queue_head_init(&seg_queue); 210194122bbeSMat Martineau 210294122bbeSMat Martineau /* Do segmentation before calling in to the state machine, 210394122bbeSMat Martineau * since it's possible to block while waiting for memory 210494122bbeSMat Martineau * allocation. 210594122bbeSMat Martineau */ 210694122bbeSMat Martineau err = l2cap_segment_sdu(chan, &seg_queue, msg, len); 210794122bbeSMat Martineau 210894122bbeSMat Martineau /* The channel could have been closed while segmenting, 210994122bbeSMat Martineau * check that it is still connected. 211094122bbeSMat Martineau */ 211194122bbeSMat Martineau if (chan->state != BT_CONNECTED) { 211294122bbeSMat Martineau __skb_queue_purge(&seg_queue); 211394122bbeSMat Martineau err = -ENOTCONN; 21149a91a04aSGustavo F. Padovan } 21159a91a04aSGustavo F. Padovan 211694122bbeSMat Martineau if (err) 211794122bbeSMat Martineau break; 211894122bbeSMat Martineau 21193733937dSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) 2120608bcc6dSMat Martineau err = l2cap_tx(chan, 0, &seg_queue, 2121608bcc6dSMat Martineau L2CAP_EV_DATA_REQUEST); 21223733937dSMat Martineau else 21233733937dSMat Martineau err = l2cap_streaming_send(chan, &seg_queue); 212494122bbeSMat Martineau 2125608bcc6dSMat Martineau if (!err) 21269a91a04aSGustavo F. Padovan err = len; 21279a91a04aSGustavo F. Padovan 212894122bbeSMat Martineau /* If the skbs were not queued for sending, they'll still be in 212994122bbeSMat Martineau * seg_queue and need to be purged. 213094122bbeSMat Martineau */ 213194122bbeSMat Martineau __skb_queue_purge(&seg_queue); 21329a91a04aSGustavo F. Padovan break; 21339a91a04aSGustavo F. Padovan 21349a91a04aSGustavo F. Padovan default: 21359a91a04aSGustavo F. Padovan BT_DBG("bad state %1.1x", chan->mode); 21369a91a04aSGustavo F. Padovan err = -EBADFD; 21379a91a04aSGustavo F. Padovan } 21389a91a04aSGustavo F. Padovan 21399a91a04aSGustavo F. Padovan return err; 21409a91a04aSGustavo F. Padovan } 21419a91a04aSGustavo F. Padovan 2142608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq) 2143608bcc6dSMat Martineau { 2144608bcc6dSMat Martineau struct sk_buff *acked_skb; 2145608bcc6dSMat Martineau u16 ackseq; 2146608bcc6dSMat Martineau 2147608bcc6dSMat Martineau BT_DBG("chan %p, reqseq %d", chan, reqseq); 2148608bcc6dSMat Martineau 2149608bcc6dSMat Martineau if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq) 2150608bcc6dSMat Martineau return; 2151608bcc6dSMat Martineau 2152608bcc6dSMat Martineau BT_DBG("expected_ack_seq %d, unacked_frames %d", 2153608bcc6dSMat Martineau chan->expected_ack_seq, chan->unacked_frames); 2154608bcc6dSMat Martineau 2155608bcc6dSMat Martineau for (ackseq = chan->expected_ack_seq; ackseq != reqseq; 2156608bcc6dSMat Martineau ackseq = __next_seq(chan, ackseq)) { 2157608bcc6dSMat Martineau 2158608bcc6dSMat Martineau acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq); 2159608bcc6dSMat Martineau if (acked_skb) { 2160608bcc6dSMat Martineau skb_unlink(acked_skb, &chan->tx_q); 2161608bcc6dSMat Martineau kfree_skb(acked_skb); 2162608bcc6dSMat Martineau chan->unacked_frames--; 2163608bcc6dSMat Martineau } 2164608bcc6dSMat Martineau } 2165608bcc6dSMat Martineau 2166608bcc6dSMat Martineau chan->expected_ack_seq = reqseq; 2167608bcc6dSMat Martineau 2168608bcc6dSMat Martineau if (chan->unacked_frames == 0) 2169608bcc6dSMat Martineau __clear_retrans_timer(chan); 2170608bcc6dSMat Martineau 2171608bcc6dSMat Martineau BT_DBG("unacked_frames %d", (int) chan->unacked_frames); 2172608bcc6dSMat Martineau } 2173608bcc6dSMat Martineau 2174608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan) 2175608bcc6dSMat Martineau { 2176608bcc6dSMat Martineau BT_DBG("chan %p", chan); 2177608bcc6dSMat Martineau 2178608bcc6dSMat Martineau chan->expected_tx_seq = chan->buffer_seq; 2179608bcc6dSMat Martineau l2cap_seq_list_clear(&chan->srej_list); 2180608bcc6dSMat Martineau skb_queue_purge(&chan->srej_q); 2181608bcc6dSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2182608bcc6dSMat Martineau } 2183608bcc6dSMat Martineau 2184608bcc6dSMat Martineau static int l2cap_tx_state_xmit(struct l2cap_chan *chan, 2185608bcc6dSMat Martineau struct l2cap_ctrl *control, 2186608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2187608bcc6dSMat Martineau { 2188608bcc6dSMat Martineau int err = 0; 2189608bcc6dSMat Martineau 2190608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2191608bcc6dSMat Martineau event); 2192608bcc6dSMat Martineau 2193608bcc6dSMat Martineau switch (event) { 2194608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2195608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2196608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2197608bcc6dSMat Martineau 2198608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2199608bcc6dSMat Martineau l2cap_ertm_send(chan); 2200608bcc6dSMat Martineau break; 2201608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2202608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2203608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2204608bcc6dSMat Martineau 2205608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2206608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2207608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2208608bcc6dSMat Martineau */ 2209608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2210608bcc6dSMat Martineau } 2211608bcc6dSMat Martineau 2212608bcc6dSMat Martineau l2cap_send_ack(chan); 2213608bcc6dSMat Martineau 2214608bcc6dSMat Martineau break; 2215608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2216608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2217608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2218608bcc6dSMat Martineau 2219608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2220608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2221608bcc6dSMat Martineau 2222608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2223608bcc6dSMat Martineau local_control.sframe = 1; 2224608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2225608bcc6dSMat Martineau local_control.poll = 1; 2226608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2227a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2228608bcc6dSMat Martineau 2229608bcc6dSMat Martineau chan->retry_count = 1; 2230608bcc6dSMat Martineau __set_monitor_timer(chan); 2231608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2232608bcc6dSMat Martineau } 2233608bcc6dSMat Martineau break; 2234608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2235608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2236608bcc6dSMat Martineau break; 2237608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2238608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2239608bcc6dSMat Martineau chan->retry_count = 1; 2240608bcc6dSMat Martineau __set_monitor_timer(chan); 2241608bcc6dSMat Martineau __clear_ack_timer(chan); 2242608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2243608bcc6dSMat Martineau break; 2244608bcc6dSMat Martineau case L2CAP_EV_RETRANS_TO: 2245608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2246608bcc6dSMat Martineau chan->retry_count = 1; 2247608bcc6dSMat Martineau __set_monitor_timer(chan); 2248608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2249608bcc6dSMat Martineau break; 2250608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2251608bcc6dSMat Martineau /* Nothing to process */ 2252608bcc6dSMat Martineau break; 2253608bcc6dSMat Martineau default: 2254608bcc6dSMat Martineau break; 2255608bcc6dSMat Martineau } 2256608bcc6dSMat Martineau 2257608bcc6dSMat Martineau return err; 2258608bcc6dSMat Martineau } 2259608bcc6dSMat Martineau 2260608bcc6dSMat Martineau static int l2cap_tx_state_wait_f(struct l2cap_chan *chan, 2261608bcc6dSMat Martineau struct l2cap_ctrl *control, 2262608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2263608bcc6dSMat Martineau { 2264608bcc6dSMat Martineau int err = 0; 2265608bcc6dSMat Martineau 2266608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, 2267608bcc6dSMat Martineau event); 2268608bcc6dSMat Martineau 2269608bcc6dSMat Martineau switch (event) { 2270608bcc6dSMat Martineau case L2CAP_EV_DATA_REQUEST: 2271608bcc6dSMat Martineau if (chan->tx_send_head == NULL) 2272608bcc6dSMat Martineau chan->tx_send_head = skb_peek(skbs); 2273608bcc6dSMat Martineau /* Queue data, but don't send. */ 2274608bcc6dSMat Martineau skb_queue_splice_tail_init(skbs, &chan->tx_q); 2275608bcc6dSMat Martineau break; 2276608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_DETECTED: 2277608bcc6dSMat Martineau BT_DBG("Enter LOCAL_BUSY"); 2278608bcc6dSMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2279608bcc6dSMat Martineau 2280608bcc6dSMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 2281608bcc6dSMat Martineau /* The SREJ_SENT state must be aborted if we are to 2282608bcc6dSMat Martineau * enter the LOCAL_BUSY state. 2283608bcc6dSMat Martineau */ 2284608bcc6dSMat Martineau l2cap_abort_rx_srej_sent(chan); 2285608bcc6dSMat Martineau } 2286608bcc6dSMat Martineau 2287608bcc6dSMat Martineau l2cap_send_ack(chan); 2288608bcc6dSMat Martineau 2289608bcc6dSMat Martineau break; 2290608bcc6dSMat Martineau case L2CAP_EV_LOCAL_BUSY_CLEAR: 2291608bcc6dSMat Martineau BT_DBG("Exit LOCAL_BUSY"); 2292608bcc6dSMat Martineau clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 2293608bcc6dSMat Martineau 2294608bcc6dSMat Martineau if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { 2295608bcc6dSMat Martineau struct l2cap_ctrl local_control; 2296608bcc6dSMat Martineau memset(&local_control, 0, sizeof(local_control)); 2297608bcc6dSMat Martineau local_control.sframe = 1; 2298608bcc6dSMat Martineau local_control.super = L2CAP_SUPER_RR; 2299608bcc6dSMat Martineau local_control.poll = 1; 2300608bcc6dSMat Martineau local_control.reqseq = chan->buffer_seq; 2301a67d7f6fSMat Martineau l2cap_send_sframe(chan, &local_control); 2302608bcc6dSMat Martineau 2303608bcc6dSMat Martineau chan->retry_count = 1; 2304608bcc6dSMat Martineau __set_monitor_timer(chan); 2305608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_WAIT_F; 2306608bcc6dSMat Martineau } 2307608bcc6dSMat Martineau break; 2308608bcc6dSMat Martineau case L2CAP_EV_RECV_REQSEQ_AND_FBIT: 2309608bcc6dSMat Martineau l2cap_process_reqseq(chan, control->reqseq); 2310608bcc6dSMat Martineau 2311608bcc6dSMat Martineau /* Fall through */ 2312608bcc6dSMat Martineau 2313608bcc6dSMat Martineau case L2CAP_EV_RECV_FBIT: 2314608bcc6dSMat Martineau if (control && control->final) { 2315608bcc6dSMat Martineau __clear_monitor_timer(chan); 2316608bcc6dSMat Martineau if (chan->unacked_frames > 0) 2317608bcc6dSMat Martineau __set_retrans_timer(chan); 2318608bcc6dSMat Martineau chan->retry_count = 0; 2319608bcc6dSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 2320608bcc6dSMat Martineau BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state); 2321608bcc6dSMat Martineau } 2322608bcc6dSMat Martineau break; 2323608bcc6dSMat Martineau case L2CAP_EV_EXPLICIT_POLL: 2324608bcc6dSMat Martineau /* Ignore */ 2325608bcc6dSMat Martineau break; 2326608bcc6dSMat Martineau case L2CAP_EV_MONITOR_TO: 2327608bcc6dSMat Martineau if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) { 2328608bcc6dSMat Martineau l2cap_send_rr_or_rnr(chan, 1); 2329608bcc6dSMat Martineau __set_monitor_timer(chan); 2330608bcc6dSMat Martineau chan->retry_count++; 2331608bcc6dSMat Martineau } else { 2332608bcc6dSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); 2333608bcc6dSMat Martineau } 2334608bcc6dSMat Martineau break; 2335608bcc6dSMat Martineau default: 2336608bcc6dSMat Martineau break; 2337608bcc6dSMat Martineau } 2338608bcc6dSMat Martineau 2339608bcc6dSMat Martineau return err; 2340608bcc6dSMat Martineau } 2341608bcc6dSMat Martineau 2342608bcc6dSMat Martineau static int l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 2343608bcc6dSMat Martineau struct sk_buff_head *skbs, u8 event) 2344608bcc6dSMat Martineau { 2345608bcc6dSMat Martineau int err = 0; 2346608bcc6dSMat Martineau 2347608bcc6dSMat Martineau BT_DBG("chan %p, control %p, skbs %p, event %d, state %d", 2348608bcc6dSMat Martineau chan, control, skbs, event, chan->tx_state); 2349608bcc6dSMat Martineau 2350608bcc6dSMat Martineau switch (chan->tx_state) { 2351608bcc6dSMat Martineau case L2CAP_TX_STATE_XMIT: 2352608bcc6dSMat Martineau err = l2cap_tx_state_xmit(chan, control, skbs, event); 2353608bcc6dSMat Martineau break; 2354608bcc6dSMat Martineau case L2CAP_TX_STATE_WAIT_F: 2355608bcc6dSMat Martineau err = l2cap_tx_state_wait_f(chan, control, skbs, event); 2356608bcc6dSMat Martineau break; 2357608bcc6dSMat Martineau default: 2358608bcc6dSMat Martineau /* Ignore event */ 2359608bcc6dSMat Martineau break; 2360608bcc6dSMat Martineau } 2361608bcc6dSMat Martineau 2362608bcc6dSMat Martineau return err; 2363608bcc6dSMat Martineau } 2364608bcc6dSMat Martineau 23654b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan, 23664b51dae9SMat Martineau struct l2cap_ctrl *control) 23674b51dae9SMat Martineau { 23684b51dae9SMat Martineau BT_DBG("chan %p, control %p", chan, control); 23694b51dae9SMat Martineau l2cap_tx(chan, control, 0, L2CAP_EV_RECV_REQSEQ_AND_FBIT); 23704b51dae9SMat Martineau } 23714b51dae9SMat Martineau 23720a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */ 23730a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 23740a708f8fSGustavo F. Padovan { 23750a708f8fSGustavo F. Padovan struct sk_buff *nskb; 237648454079SGustavo F. Padovan struct l2cap_chan *chan; 23770a708f8fSGustavo F. Padovan 23780a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 23790a708f8fSGustavo F. Padovan 23803df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 23813d57dc68SGustavo F. Padovan 23823df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 238348454079SGustavo F. Padovan struct sock *sk = chan->sk; 2384715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW) 23850a708f8fSGustavo F. Padovan continue; 23860a708f8fSGustavo F. Padovan 23870a708f8fSGustavo F. Padovan /* Don't send frame to the socket it came from */ 23880a708f8fSGustavo F. Padovan if (skb->sk == sk) 23890a708f8fSGustavo F. Padovan continue; 23900a708f8fSGustavo F. Padovan nskb = skb_clone(skb, GFP_ATOMIC); 23910a708f8fSGustavo F. Padovan if (!nskb) 23920a708f8fSGustavo F. Padovan continue; 23930a708f8fSGustavo F. Padovan 239423070494SGustavo F. Padovan if (chan->ops->recv(chan->data, nskb)) 23950a708f8fSGustavo F. Padovan kfree_skb(nskb); 23960a708f8fSGustavo F. Padovan } 23973d57dc68SGustavo F. Padovan 23983df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 23990a708f8fSGustavo F. Padovan } 24000a708f8fSGustavo F. Padovan 24010a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */ 24020a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 24030a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data) 24040a708f8fSGustavo F. Padovan { 24050a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag; 24060a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd; 24070a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 24080a708f8fSGustavo F. Padovan int len, count; 24090a708f8fSGustavo F. Padovan 24100a708f8fSGustavo F. Padovan BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d", 24110a708f8fSGustavo F. Padovan conn, code, ident, dlen); 24120a708f8fSGustavo F. Padovan 24130a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; 24140a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 24150a708f8fSGustavo F. Padovan 24160a708f8fSGustavo F. Padovan skb = bt_skb_alloc(count, GFP_ATOMIC); 24170a708f8fSGustavo F. Padovan if (!skb) 24180a708f8fSGustavo F. Padovan return NULL; 24190a708f8fSGustavo F. Padovan 24200a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 24210a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); 24223300d9a9SClaudio Takahasi 24233300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 24243300d9a9SClaudio Takahasi lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING); 24253300d9a9SClaudio Takahasi else 24260a708f8fSGustavo F. Padovan lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING); 24270a708f8fSGustavo F. Padovan 24280a708f8fSGustavo F. Padovan cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); 24290a708f8fSGustavo F. Padovan cmd->code = code; 24300a708f8fSGustavo F. Padovan cmd->ident = ident; 24310a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen); 24320a708f8fSGustavo F. Padovan 24330a708f8fSGustavo F. Padovan if (dlen) { 24340a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE; 24350a708f8fSGustavo F. Padovan memcpy(skb_put(skb, count), data, count); 24360a708f8fSGustavo F. Padovan data += count; 24370a708f8fSGustavo F. Padovan } 24380a708f8fSGustavo F. Padovan 24390a708f8fSGustavo F. Padovan len -= skb->len; 24400a708f8fSGustavo F. Padovan 24410a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 24420a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 24430a708f8fSGustavo F. Padovan while (len) { 24440a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 24450a708f8fSGustavo F. Padovan 24460a708f8fSGustavo F. Padovan *frag = bt_skb_alloc(count, GFP_ATOMIC); 24470a708f8fSGustavo F. Padovan if (!*frag) 24480a708f8fSGustavo F. Padovan goto fail; 24490a708f8fSGustavo F. Padovan 24500a708f8fSGustavo F. Padovan memcpy(skb_put(*frag, count), data, count); 24510a708f8fSGustavo F. Padovan 24520a708f8fSGustavo F. Padovan len -= count; 24530a708f8fSGustavo F. Padovan data += count; 24540a708f8fSGustavo F. Padovan 24550a708f8fSGustavo F. Padovan frag = &(*frag)->next; 24560a708f8fSGustavo F. Padovan } 24570a708f8fSGustavo F. Padovan 24580a708f8fSGustavo F. Padovan return skb; 24590a708f8fSGustavo F. Padovan 24600a708f8fSGustavo F. Padovan fail: 24610a708f8fSGustavo F. Padovan kfree_skb(skb); 24620a708f8fSGustavo F. Padovan return NULL; 24630a708f8fSGustavo F. Padovan } 24640a708f8fSGustavo F. Padovan 24650a708f8fSGustavo F. Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val) 24660a708f8fSGustavo F. Padovan { 24670a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 24680a708f8fSGustavo F. Padovan int len; 24690a708f8fSGustavo F. Padovan 24700a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len; 24710a708f8fSGustavo F. Padovan *ptr += len; 24720a708f8fSGustavo F. Padovan 24730a708f8fSGustavo F. Padovan *type = opt->type; 24740a708f8fSGustavo F. Padovan *olen = opt->len; 24750a708f8fSGustavo F. Padovan 24760a708f8fSGustavo F. Padovan switch (opt->len) { 24770a708f8fSGustavo F. Padovan case 1: 24780a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val); 24790a708f8fSGustavo F. Padovan break; 24800a708f8fSGustavo F. Padovan 24810a708f8fSGustavo F. Padovan case 2: 24820a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val); 24830a708f8fSGustavo F. Padovan break; 24840a708f8fSGustavo F. Padovan 24850a708f8fSGustavo F. Padovan case 4: 24860a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val); 24870a708f8fSGustavo F. Padovan break; 24880a708f8fSGustavo F. Padovan 24890a708f8fSGustavo F. Padovan default: 24900a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val; 24910a708f8fSGustavo F. Padovan break; 24920a708f8fSGustavo F. Padovan } 24930a708f8fSGustavo F. Padovan 24940a708f8fSGustavo F. Padovan BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val); 24950a708f8fSGustavo F. Padovan return len; 24960a708f8fSGustavo F. Padovan } 24970a708f8fSGustavo F. Padovan 24980a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) 24990a708f8fSGustavo F. Padovan { 25000a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 25010a708f8fSGustavo F. Padovan 25020a708f8fSGustavo F. Padovan BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val); 25030a708f8fSGustavo F. Padovan 25040a708f8fSGustavo F. Padovan opt->type = type; 25050a708f8fSGustavo F. Padovan opt->len = len; 25060a708f8fSGustavo F. Padovan 25070a708f8fSGustavo F. Padovan switch (len) { 25080a708f8fSGustavo F. Padovan case 1: 25090a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val; 25100a708f8fSGustavo F. Padovan break; 25110a708f8fSGustavo F. Padovan 25120a708f8fSGustavo F. Padovan case 2: 25130a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val); 25140a708f8fSGustavo F. Padovan break; 25150a708f8fSGustavo F. Padovan 25160a708f8fSGustavo F. Padovan case 4: 25170a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val); 25180a708f8fSGustavo F. Padovan break; 25190a708f8fSGustavo F. Padovan 25200a708f8fSGustavo F. Padovan default: 25210a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len); 25220a708f8fSGustavo F. Padovan break; 25230a708f8fSGustavo F. Padovan } 25240a708f8fSGustavo F. Padovan 25250a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len; 25260a708f8fSGustavo F. Padovan } 25270a708f8fSGustavo F. Padovan 2528f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) 2529f89cef09SAndrei Emeltchenko { 2530f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs; 2531f89cef09SAndrei Emeltchenko 2532f89cef09SAndrei Emeltchenko switch (chan->mode) { 2533f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM: 2534f89cef09SAndrei Emeltchenko efs.id = chan->local_id; 2535f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype; 2536f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 2537f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 2538f89cef09SAndrei Emeltchenko efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); 2539f89cef09SAndrei Emeltchenko efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO); 2540f89cef09SAndrei Emeltchenko break; 2541f89cef09SAndrei Emeltchenko 2542f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING: 2543f89cef09SAndrei Emeltchenko efs.id = 1; 2544f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT; 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 = 0; 2548f89cef09SAndrei Emeltchenko efs.flush_to = 0; 2549f89cef09SAndrei Emeltchenko break; 2550f89cef09SAndrei Emeltchenko 2551f89cef09SAndrei Emeltchenko default: 2552f89cef09SAndrei Emeltchenko return; 2553f89cef09SAndrei Emeltchenko } 2554f89cef09SAndrei Emeltchenko 2555f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), 2556f89cef09SAndrei Emeltchenko (unsigned long) &efs); 2557f89cef09SAndrei Emeltchenko } 2558f89cef09SAndrei Emeltchenko 2559721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work) 25600a708f8fSGustavo F. Padovan { 2561721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 2562721c4181SGustavo F. Padovan ack_timer.work); 25630a708f8fSGustavo F. Padovan 25642fb9b3d4SGustavo F. Padovan BT_DBG("chan %p", chan); 25652fb9b3d4SGustavo F. Padovan 25666be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 25676be36555SAndrei Emeltchenko 25680a0aba42SMat Martineau l2cap_send_ack(chan); 25696be36555SAndrei Emeltchenko 25706be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 257109bfb2eeSSzymon Janc 257209bfb2eeSSzymon Janc l2cap_chan_put(chan); 25730a708f8fSGustavo F. Padovan } 25740a708f8fSGustavo F. Padovan 25753c588192SMat Martineau static inline int l2cap_ertm_init(struct l2cap_chan *chan) 25760a708f8fSGustavo F. Padovan { 25773c588192SMat Martineau int err; 25783c588192SMat Martineau 2579105bdf9eSMat Martineau chan->next_tx_seq = 0; 2580105bdf9eSMat Martineau chan->expected_tx_seq = 0; 258142e5c802SGustavo F. Padovan chan->expected_ack_seq = 0; 25826a026610SGustavo F. Padovan chan->unacked_frames = 0; 258342e5c802SGustavo F. Padovan chan->buffer_seq = 0; 25846a026610SGustavo F. Padovan chan->frames_sent = 0; 2585105bdf9eSMat Martineau chan->last_acked_seq = 0; 2586105bdf9eSMat Martineau chan->sdu = NULL; 2587105bdf9eSMat Martineau chan->sdu_last_frag = NULL; 2588105bdf9eSMat Martineau chan->sdu_len = 0; 2589105bdf9eSMat Martineau 2590d34c34fbSMat Martineau skb_queue_head_init(&chan->tx_q); 2591d34c34fbSMat Martineau 2592105bdf9eSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 2593105bdf9eSMat Martineau return 0; 2594105bdf9eSMat Martineau 2595105bdf9eSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2596105bdf9eSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 25970a708f8fSGustavo F. Padovan 2598721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout); 2599721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout); 2600721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout); 26010a708f8fSGustavo F. Padovan 2602f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q); 26030a708f8fSGustavo F. Padovan 26043c588192SMat Martineau err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win); 26053c588192SMat Martineau if (err < 0) 26063c588192SMat Martineau return err; 26073c588192SMat Martineau 26089dc9affcSMat Martineau err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win); 26099dc9affcSMat Martineau if (err < 0) 26109dc9affcSMat Martineau l2cap_seq_list_free(&chan->srej_list); 26119dc9affcSMat Martineau 26129dc9affcSMat Martineau return err; 26130a708f8fSGustavo F. Padovan } 26140a708f8fSGustavo F. Padovan 26150a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) 26160a708f8fSGustavo F. Padovan { 26170a708f8fSGustavo F. Padovan switch (mode) { 26180a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 26190a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 26200a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask)) 26210a708f8fSGustavo F. Padovan return mode; 26220a708f8fSGustavo F. Padovan /* fall through */ 26230a708f8fSGustavo F. Padovan default: 26240a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC; 26250a708f8fSGustavo F. Padovan } 26260a708f8fSGustavo F. Padovan } 26270a708f8fSGustavo F. Padovan 26286327eb98SAndrei Emeltchenko static inline bool __l2cap_ews_supported(struct l2cap_chan *chan) 26296327eb98SAndrei Emeltchenko { 26306327eb98SAndrei Emeltchenko return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW; 26316327eb98SAndrei Emeltchenko } 26326327eb98SAndrei Emeltchenko 2633f89cef09SAndrei Emeltchenko static inline bool __l2cap_efs_supported(struct l2cap_chan *chan) 2634f89cef09SAndrei Emeltchenko { 2635f89cef09SAndrei Emeltchenko return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW; 2636f89cef09SAndrei Emeltchenko } 2637f89cef09SAndrei Emeltchenko 26386327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan) 26396327eb98SAndrei Emeltchenko { 26406327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && 2641836be934SAndrei Emeltchenko __l2cap_ews_supported(chan)) { 26426327eb98SAndrei Emeltchenko /* use extended control field */ 26436327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 2644836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 2645836be934SAndrei Emeltchenko } else { 26466327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win, 26476327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 2648836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 2649836be934SAndrei Emeltchenko } 26506327eb98SAndrei Emeltchenko } 26516327eb98SAndrei Emeltchenko 2652710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) 26530a708f8fSGustavo F. Padovan { 26540a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 26550c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode }; 26560a708f8fSGustavo F. Padovan void *ptr = req->data; 2657c8f79162SAndrei Emeltchenko u16 size; 26580a708f8fSGustavo F. Padovan 265949208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 26600a708f8fSGustavo F. Padovan 266173ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp) 26620a708f8fSGustavo F. Padovan goto done; 26630a708f8fSGustavo F. Padovan 26640c1bc5c6SGustavo F. Padovan switch (chan->mode) { 26650a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 26660a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 2667c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) 26680a708f8fSGustavo F. Padovan break; 26690a708f8fSGustavo F. Padovan 2670f89cef09SAndrei Emeltchenko if (__l2cap_efs_supported(chan)) 2671f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 2672f89cef09SAndrei Emeltchenko 26730a708f8fSGustavo F. Padovan /* fall through */ 26740a708f8fSGustavo F. Padovan default: 26758c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); 26760a708f8fSGustavo F. Padovan break; 26770a708f8fSGustavo F. Padovan } 26780a708f8fSGustavo F. Padovan 26790a708f8fSGustavo F. Padovan done: 26800c1bc5c6SGustavo F. Padovan if (chan->imtu != L2CAP_DEFAULT_MTU) 26810c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 26820a708f8fSGustavo F. Padovan 26830c1bc5c6SGustavo F. Padovan switch (chan->mode) { 26840a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 26858c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && 26868c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) 26870a708f8fSGustavo F. Padovan break; 26880a708f8fSGustavo F. Padovan 26890a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC; 26900a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 26910a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 26920a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 26930a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 26940a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0; 26950a708f8fSGustavo F. Padovan 26960a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 26970a708f8fSGustavo F. Padovan (unsigned long) &rfc); 26980a708f8fSGustavo F. Padovan break; 26990a708f8fSGustavo F. Padovan 27000a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 27010a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM; 270247d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx; 27030a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 27040a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 2705c8f79162SAndrei Emeltchenko 2706c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 2707c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2708c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2709c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2710c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 27110a708f8fSGustavo F. Padovan 27126327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan); 27136327eb98SAndrei Emeltchenko 27146327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win, 27156327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 27160a708f8fSGustavo F. Padovan 27170a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 27180a708f8fSGustavo F. Padovan (unsigned long) &rfc); 27190a708f8fSGustavo F. Padovan 2720f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 2721f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 2722f89cef09SAndrei Emeltchenko 27238c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) 27240a708f8fSGustavo F. Padovan break; 27250a708f8fSGustavo F. Padovan 272647d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 2727c1360a1cSGustavo F. Padovan test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { 272847d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 272947d1ec61SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); 27300a708f8fSGustavo F. Padovan } 27316327eb98SAndrei Emeltchenko 27326327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 27336327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 27346327eb98SAndrei Emeltchenko chan->tx_win); 27350a708f8fSGustavo F. Padovan break; 27360a708f8fSGustavo F. Padovan 27370a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 27380a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING; 27390a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 27400a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 27410a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 27420a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 2743c8f79162SAndrei Emeltchenko 2744c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 2745c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2746c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2747c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2748c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 27490a708f8fSGustavo F. Padovan 27500a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 27510a708f8fSGustavo F. Padovan (unsigned long) &rfc); 27520a708f8fSGustavo F. Padovan 2753f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 2754f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 2755f89cef09SAndrei Emeltchenko 27568c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) 27570a708f8fSGustavo F. Padovan break; 27580a708f8fSGustavo F. Padovan 275947d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 2760c1360a1cSGustavo F. Padovan test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { 276147d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 276247d1ec61SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); 27630a708f8fSGustavo F. Padovan } 27640a708f8fSGustavo F. Padovan break; 27650a708f8fSGustavo F. Padovan } 27660a708f8fSGustavo F. Padovan 2767fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 27680a708f8fSGustavo F. Padovan req->flags = cpu_to_le16(0); 27690a708f8fSGustavo F. Padovan 27700a708f8fSGustavo F. Padovan return ptr - data; 27710a708f8fSGustavo F. Padovan } 27720a708f8fSGustavo F. Padovan 277373ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) 27740a708f8fSGustavo F. Padovan { 27750a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 27760a708f8fSGustavo F. Padovan void *ptr = rsp->data; 277773ffa904SGustavo F. Padovan void *req = chan->conf_req; 277873ffa904SGustavo F. Padovan int len = chan->conf_len; 27790a708f8fSGustavo F. Padovan int type, hint, olen; 27800a708f8fSGustavo F. Padovan unsigned long val; 27810a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 278242dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs; 278342dceae2SAndrei Emeltchenko u8 remote_efs = 0; 27840a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU; 27850a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS; 2786c8f79162SAndrei Emeltchenko u16 size; 27870a708f8fSGustavo F. Padovan 278873ffa904SGustavo F. Padovan BT_DBG("chan %p", chan); 27890a708f8fSGustavo F. Padovan 27900a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 27910a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val); 27920a708f8fSGustavo F. Padovan 27930a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT; 27940a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK; 27950a708f8fSGustavo F. Padovan 27960a708f8fSGustavo F. Padovan switch (type) { 27970a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 27980a708f8fSGustavo F. Padovan mtu = val; 27990a708f8fSGustavo F. Padovan break; 28000a708f8fSGustavo F. Padovan 28010a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 28020c1bc5c6SGustavo F. Padovan chan->flush_to = val; 28030a708f8fSGustavo F. Padovan break; 28040a708f8fSGustavo F. Padovan 28050a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS: 28060a708f8fSGustavo F. Padovan break; 28070a708f8fSGustavo F. Padovan 28080a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 28090a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 28100a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen); 28110a708f8fSGustavo F. Padovan break; 28120a708f8fSGustavo F. Padovan 28130a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS: 28140a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE) 2815c1360a1cSGustavo F. Padovan set_bit(CONF_NO_FCS_RECV, &chan->conf_state); 281642dceae2SAndrei Emeltchenko break; 28170a708f8fSGustavo F. Padovan 281842dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS: 281942dceae2SAndrei Emeltchenko remote_efs = 1; 282042dceae2SAndrei Emeltchenko if (olen == sizeof(efs)) 282142dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen); 28220a708f8fSGustavo F. Padovan break; 28230a708f8fSGustavo F. Padovan 28246327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 28256327eb98SAndrei Emeltchenko if (!enable_hs) 28266327eb98SAndrei Emeltchenko return -ECONNREFUSED; 28276327eb98SAndrei Emeltchenko 28286327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 28296327eb98SAndrei Emeltchenko set_bit(CONF_EWS_RECV, &chan->conf_state); 2830836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 28316327eb98SAndrei Emeltchenko chan->remote_tx_win = val; 28320a708f8fSGustavo F. Padovan break; 28330a708f8fSGustavo F. Padovan 28340a708f8fSGustavo F. Padovan default: 28350a708f8fSGustavo F. Padovan if (hint) 28360a708f8fSGustavo F. Padovan break; 28370a708f8fSGustavo F. Padovan 28380a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN; 28390a708f8fSGustavo F. Padovan *((u8 *) ptr++) = type; 28400a708f8fSGustavo F. Padovan break; 28410a708f8fSGustavo F. Padovan } 28420a708f8fSGustavo F. Padovan } 28430a708f8fSGustavo F. Padovan 284473ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1) 28450a708f8fSGustavo F. Padovan goto done; 28460a708f8fSGustavo F. Padovan 28470c1bc5c6SGustavo F. Padovan switch (chan->mode) { 28480a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 28490a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 2850c1360a1cSGustavo F. Padovan if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { 28510c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, 28528c1d787bSGustavo F. Padovan chan->conn->feat_mask); 28530a708f8fSGustavo F. Padovan break; 28540a708f8fSGustavo F. Padovan } 28550a708f8fSGustavo F. Padovan 285642dceae2SAndrei Emeltchenko if (remote_efs) { 285742dceae2SAndrei Emeltchenko if (__l2cap_efs_supported(chan)) 285842dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 285942dceae2SAndrei Emeltchenko else 286042dceae2SAndrei Emeltchenko return -ECONNREFUSED; 286142dceae2SAndrei Emeltchenko } 286242dceae2SAndrei Emeltchenko 28630c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) 28640a708f8fSGustavo F. Padovan return -ECONNREFUSED; 28650a708f8fSGustavo F. Padovan 28660a708f8fSGustavo F. Padovan break; 28670a708f8fSGustavo F. Padovan } 28680a708f8fSGustavo F. Padovan 28690a708f8fSGustavo F. Padovan done: 28700c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) { 28710a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 28720c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 28730a708f8fSGustavo F. Padovan 287473ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1) 28750a708f8fSGustavo F. Padovan return -ECONNREFUSED; 28760a708f8fSGustavo F. Padovan 28770a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 28780a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 28790a708f8fSGustavo F. Padovan } 28800a708f8fSGustavo F. Padovan 28810a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) { 28820a708f8fSGustavo F. Padovan /* Configure output options and let the other side know 28830a708f8fSGustavo F. Padovan * which ones we don't like. */ 28840a708f8fSGustavo F. Padovan 28850a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU) 28860a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 28870a708f8fSGustavo F. Padovan else { 28880c1bc5c6SGustavo F. Padovan chan->omtu = mtu; 2889c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state); 28900a708f8fSGustavo F. Padovan } 28910c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); 28920a708f8fSGustavo F. Padovan 289342dceae2SAndrei Emeltchenko if (remote_efs) { 289442dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 289542dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 289642dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) { 289742dceae2SAndrei Emeltchenko 289842dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT; 289942dceae2SAndrei Emeltchenko 290042dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1) 290142dceae2SAndrei Emeltchenko return -ECONNREFUSED; 290242dceae2SAndrei Emeltchenko 290342dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 290442dceae2SAndrei Emeltchenko sizeof(efs), 290542dceae2SAndrei Emeltchenko (unsigned long) &efs); 29060e8b207eSAndrei Emeltchenko } else { 29073e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */ 29080e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING; 29090e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 291042dceae2SAndrei Emeltchenko } 291142dceae2SAndrei Emeltchenko } 291242dceae2SAndrei Emeltchenko 29130a708f8fSGustavo F. Padovan switch (rfc.mode) { 29140a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 291547d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 2916c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 29170a708f8fSGustavo F. Padovan break; 29180a708f8fSGustavo F. Padovan 29190a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 29206327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state)) 29212c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size; 29226327eb98SAndrei Emeltchenko else 29236327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; 29246327eb98SAndrei Emeltchenko 29252c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit; 29260a708f8fSGustavo F. Padovan 2927c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 2928c8f79162SAndrei Emeltchenko chan->conn->mtu - 2929c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2930c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2931c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2932c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 2933c8f79162SAndrei Emeltchenko chan->remote_mps = size; 29340a708f8fSGustavo F. Padovan 29350a708f8fSGustavo F. Padovan rfc.retrans_timeout = 29364fd21a88SAndrei Emeltchenko __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 29370a708f8fSGustavo F. Padovan rfc.monitor_timeout = 29384fd21a88SAndrei Emeltchenko __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 29390a708f8fSGustavo F. Padovan 2940c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 29410a708f8fSGustavo F. Padovan 29420a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 29430a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 29440a708f8fSGustavo F. Padovan 294542dceae2SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 294642dceae2SAndrei Emeltchenko chan->remote_id = efs.id; 294742dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype; 294842dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu); 294942dceae2SAndrei Emeltchenko chan->remote_flush_to = 295042dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to); 295142dceae2SAndrei Emeltchenko chan->remote_acc_lat = 295242dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat); 295342dceae2SAndrei Emeltchenko chan->remote_sdu_itime = 295442dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 295542dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 295642dceae2SAndrei Emeltchenko sizeof(efs), (unsigned long) &efs); 295742dceae2SAndrei Emeltchenko } 29580a708f8fSGustavo F. Padovan break; 29590a708f8fSGustavo F. Padovan 29600a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 2961c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 2962c8f79162SAndrei Emeltchenko chan->conn->mtu - 2963c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2964c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2965c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2966c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 2967c8f79162SAndrei Emeltchenko chan->remote_mps = size; 29680a708f8fSGustavo F. Padovan 2969c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 29700a708f8fSGustavo F. Padovan 29710a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 29720a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 29730a708f8fSGustavo F. Padovan 29740a708f8fSGustavo F. Padovan break; 29750a708f8fSGustavo F. Padovan 29760a708f8fSGustavo F. Padovan default: 29770a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 29780a708f8fSGustavo F. Padovan 29790a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc)); 29800c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 29810a708f8fSGustavo F. Padovan } 29820a708f8fSGustavo F. Padovan 29830a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) 2984c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 29850a708f8fSGustavo F. Padovan } 2986fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 29870a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 29880a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(0x0000); 29890a708f8fSGustavo F. Padovan 29900a708f8fSGustavo F. Padovan return ptr - data; 29910a708f8fSGustavo F. Padovan } 29920a708f8fSGustavo F. Padovan 2993b4450035SGustavo F. Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result) 29940a708f8fSGustavo F. Padovan { 29950a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 29960a708f8fSGustavo F. Padovan void *ptr = req->data; 29970a708f8fSGustavo F. Padovan int type, olen; 29980a708f8fSGustavo F. Padovan unsigned long val; 299936e999a8SMat Martineau struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 300066af7aafSAndrei Emeltchenko struct l2cap_conf_efs efs; 30010a708f8fSGustavo F. Padovan 3002fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); 30030a708f8fSGustavo F. Padovan 30040a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 30050a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 30060a708f8fSGustavo F. Padovan 30070a708f8fSGustavo F. Padovan switch (type) { 30080a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 30090a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) { 30100a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT; 30110c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU; 30120a708f8fSGustavo F. Padovan } else 30130c1bc5c6SGustavo F. Padovan chan->imtu = val; 30140c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 30150a708f8fSGustavo F. Padovan break; 30160a708f8fSGustavo F. Padovan 30170a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 30180c1bc5c6SGustavo F. Padovan chan->flush_to = val; 30190a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 30200c1bc5c6SGustavo F. Padovan 2, chan->flush_to); 30210a708f8fSGustavo F. Padovan break; 30220a708f8fSGustavo F. Padovan 30230a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 30240a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 30250a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 30260a708f8fSGustavo F. Padovan 3027c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && 30280c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode) 30290a708f8fSGustavo F. Padovan return -ECONNREFUSED; 30300a708f8fSGustavo F. Padovan 303147d1ec61SGustavo F. Padovan chan->fcs = 0; 30320a708f8fSGustavo F. Padovan 30330a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 30340a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 30350a708f8fSGustavo F. Padovan break; 30366327eb98SAndrei Emeltchenko 30376327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 30386327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, val, 30396327eb98SAndrei Emeltchenko L2CAP_DEFAULT_EXT_WINDOW); 30403e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 30413e6b3b95SGustavo F. Padovan chan->tx_win); 30426327eb98SAndrei Emeltchenko break; 304366af7aafSAndrei Emeltchenko 304466af7aafSAndrei Emeltchenko case L2CAP_CONF_EFS: 304566af7aafSAndrei Emeltchenko if (olen == sizeof(efs)) 304666af7aafSAndrei Emeltchenko memcpy(&efs, (void *)val, olen); 304766af7aafSAndrei Emeltchenko 304866af7aafSAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 304966af7aafSAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 305066af7aafSAndrei Emeltchenko efs.stype != chan->local_stype) 305166af7aafSAndrei Emeltchenko return -ECONNREFUSED; 305266af7aafSAndrei Emeltchenko 305366af7aafSAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 305466af7aafSAndrei Emeltchenko sizeof(efs), (unsigned long) &efs); 305566af7aafSAndrei Emeltchenko break; 30560a708f8fSGustavo F. Padovan } 30570a708f8fSGustavo F. Padovan } 30580a708f8fSGustavo F. Padovan 30590c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) 30600a708f8fSGustavo F. Padovan return -ECONNREFUSED; 30610a708f8fSGustavo F. Padovan 30620c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode; 30630a708f8fSGustavo F. Padovan 30640e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) { 30650a708f8fSGustavo F. Padovan switch (rfc.mode) { 30660a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 306747d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 306847d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 306947d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 307066af7aafSAndrei Emeltchenko 307166af7aafSAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 307266af7aafSAndrei Emeltchenko chan->local_msdu = le16_to_cpu(efs.msdu); 307366af7aafSAndrei Emeltchenko chan->local_sdu_itime = 307466af7aafSAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 307566af7aafSAndrei Emeltchenko chan->local_acc_lat = le32_to_cpu(efs.acc_lat); 307666af7aafSAndrei Emeltchenko chan->local_flush_to = 307766af7aafSAndrei Emeltchenko le32_to_cpu(efs.flush_to); 307866af7aafSAndrei Emeltchenko } 30790a708f8fSGustavo F. Padovan break; 308066af7aafSAndrei Emeltchenko 30810a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 308247d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 30830a708f8fSGustavo F. Padovan } 30840a708f8fSGustavo F. Padovan } 30850a708f8fSGustavo F. Padovan 3086fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 30870a708f8fSGustavo F. Padovan req->flags = cpu_to_le16(0x0000); 30880a708f8fSGustavo F. Padovan 30890a708f8fSGustavo F. Padovan return ptr - data; 30900a708f8fSGustavo F. Padovan } 30910a708f8fSGustavo F. Padovan 3092fe4128e0SGustavo F. Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags) 30930a708f8fSGustavo F. Padovan { 30940a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 30950a708f8fSGustavo F. Padovan void *ptr = rsp->data; 30960a708f8fSGustavo F. Padovan 3097fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan); 30980a708f8fSGustavo F. Padovan 3099fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 31000a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 31010a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags); 31020a708f8fSGustavo F. Padovan 31030a708f8fSGustavo F. Padovan return ptr - data; 31040a708f8fSGustavo F. Padovan } 31050a708f8fSGustavo F. Padovan 31068c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) 3107710f9b0aSGustavo F. Padovan { 3108710f9b0aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 31098c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 3110710f9b0aSGustavo F. Padovan u8 buf[128]; 3111710f9b0aSGustavo F. Padovan 3112fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 3113fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3114710f9b0aSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 3115710f9b0aSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 3116710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, 3117710f9b0aSGustavo F. Padovan L2CAP_CONN_RSP, sizeof(rsp), &rsp); 3118710f9b0aSGustavo F. Padovan 3119c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 3120710f9b0aSGustavo F. Padovan return; 3121710f9b0aSGustavo F. Padovan 3122710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 3123710f9b0aSGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 3124710f9b0aSGustavo F. Padovan chan->num_conf_req++; 3125710f9b0aSGustavo F. Padovan } 3126710f9b0aSGustavo F. Padovan 312747d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) 31280a708f8fSGustavo F. Padovan { 31290a708f8fSGustavo F. Padovan int type, olen; 31300a708f8fSGustavo F. Padovan unsigned long val; 31310a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc; 31320a708f8fSGustavo F. Padovan 313347d1ec61SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); 31340a708f8fSGustavo F. Padovan 31350c1bc5c6SGustavo F. Padovan if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) 31360a708f8fSGustavo F. Padovan return; 31370a708f8fSGustavo F. Padovan 31380a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 31390a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 31400a708f8fSGustavo F. Padovan 31410a708f8fSGustavo F. Padovan switch (type) { 31420a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 31430a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 31440a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 31450a708f8fSGustavo F. Padovan goto done; 31460a708f8fSGustavo F. Padovan } 31470a708f8fSGustavo F. Padovan } 31480a708f8fSGustavo F. Padovan 314936e999a8SMat Martineau /* Use sane default values in case a misbehaving remote device 315036e999a8SMat Martineau * did not send an RFC option. 315136e999a8SMat Martineau */ 315236e999a8SMat Martineau rfc.mode = chan->mode; 315336e999a8SMat Martineau rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 315436e999a8SMat Martineau rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 315536e999a8SMat Martineau rfc.max_pdu_size = cpu_to_le16(chan->imtu); 315636e999a8SMat Martineau 315736e999a8SMat Martineau BT_ERR("Expected RFC option was not found, using defaults"); 315836e999a8SMat Martineau 31590a708f8fSGustavo F. Padovan done: 31600a708f8fSGustavo F. Padovan switch (rfc.mode) { 31610a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 316247d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 316347d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 316447d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 31650a708f8fSGustavo F. Padovan break; 31660a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 316747d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 31680a708f8fSGustavo F. Padovan } 31690a708f8fSGustavo F. Padovan } 31700a708f8fSGustavo F. Padovan 31710a708f8fSGustavo F. Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 31720a708f8fSGustavo F. Padovan { 3173e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 31740a708f8fSGustavo F. Padovan 3175e2fd318eSIlia Kolomisnky if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) 31760a708f8fSGustavo F. Padovan return 0; 31770a708f8fSGustavo F. Padovan 31780a708f8fSGustavo F. Padovan if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && 31790a708f8fSGustavo F. Padovan cmd->ident == conn->info_ident) { 318017cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 31810a708f8fSGustavo F. Padovan 31820a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 31830a708f8fSGustavo F. Padovan conn->info_ident = 0; 31840a708f8fSGustavo F. Padovan 31850a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 31860a708f8fSGustavo F. Padovan } 31870a708f8fSGustavo F. Padovan 31880a708f8fSGustavo F. Padovan return 0; 31890a708f8fSGustavo F. Padovan } 31900a708f8fSGustavo F. Padovan 31910a708f8fSGustavo F. Padovan static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 31920a708f8fSGustavo F. Padovan { 31930a708f8fSGustavo F. Padovan struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 31940a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 319523691d75SGustavo F. Padovan struct l2cap_chan *chan = NULL, *pchan; 31960a708f8fSGustavo F. Padovan struct sock *parent, *sk = NULL; 31970a708f8fSGustavo F. Padovan int result, status = L2CAP_CS_NO_INFO; 31980a708f8fSGustavo F. Padovan 31990a708f8fSGustavo F. Padovan u16 dcid = 0, scid = __le16_to_cpu(req->scid); 32000a708f8fSGustavo F. Padovan __le16 psm = req->psm; 32010a708f8fSGustavo F. Padovan 3202097db76cSAndrei Emeltchenko BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); 32030a708f8fSGustavo F. Padovan 32040a708f8fSGustavo F. Padovan /* Check if we have socket listening on psm */ 3205c2287681SIdo Yariv pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst); 320623691d75SGustavo F. Padovan if (!pchan) { 32070a708f8fSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 32080a708f8fSGustavo F. Padovan goto sendresp; 32090a708f8fSGustavo F. Padovan } 32100a708f8fSGustavo F. Padovan 321123691d75SGustavo F. Padovan parent = pchan->sk; 321223691d75SGustavo F. Padovan 32133df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 3214aa2ac881SGustavo F. Padovan lock_sock(parent); 32150a708f8fSGustavo F. Padovan 32160a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */ 32170a708f8fSGustavo F. Padovan if (psm != cpu_to_le16(0x0001) && 32180a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) { 32199f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_AUTH_FAILURE; 32200a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 32210a708f8fSGustavo F. Padovan goto response; 32220a708f8fSGustavo F. Padovan } 32230a708f8fSGustavo F. Padovan 32240a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM; 32250a708f8fSGustavo F. Padovan 32260a708f8fSGustavo F. Padovan /* Check for backlog size */ 32270a708f8fSGustavo F. Padovan if (sk_acceptq_is_full(parent)) { 32280a708f8fSGustavo F. Padovan BT_DBG("backlog full %d", parent->sk_ack_backlog); 32290a708f8fSGustavo F. Padovan goto response; 32300a708f8fSGustavo F. Padovan } 32310a708f8fSGustavo F. Padovan 323280808e43SGustavo F. Padovan chan = pchan->ops->new_connection(pchan->data); 323380808e43SGustavo F. Padovan if (!chan) 32340a708f8fSGustavo F. Padovan goto response; 32350a708f8fSGustavo F. Padovan 323680808e43SGustavo F. Padovan sk = chan->sk; 323780808e43SGustavo F. Padovan 32380a708f8fSGustavo F. Padovan /* Check if we already have channel with that dcid */ 3239baa7e1faSGustavo F. Padovan if (__l2cap_get_chan_by_dcid(conn, scid)) { 32400a708f8fSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 3241ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 32420a708f8fSGustavo F. Padovan goto response; 32430a708f8fSGustavo F. Padovan } 32440a708f8fSGustavo F. Padovan 32450a708f8fSGustavo F. Padovan hci_conn_hold(conn->hcon); 32460a708f8fSGustavo F. Padovan 32470a708f8fSGustavo F. Padovan bacpy(&bt_sk(sk)->src, conn->src); 32480a708f8fSGustavo F. Padovan bacpy(&bt_sk(sk)->dst, conn->dst); 3249fe4128e0SGustavo F. Padovan chan->psm = psm; 3250fe4128e0SGustavo F. Padovan chan->dcid = scid; 32510a708f8fSGustavo F. Padovan 3252d1010240SGustavo F. Padovan bt_accept_enqueue(parent, sk); 3253d1010240SGustavo F. Padovan 32546be36555SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 325548454079SGustavo F. Padovan 3256fe4128e0SGustavo F. Padovan dcid = chan->scid; 32570a708f8fSGustavo F. Padovan 3258c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 32590a708f8fSGustavo F. Padovan 3260fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident; 32610a708f8fSGustavo F. Padovan 32620a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { 3263d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 3264c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) { 32650e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 32660a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 32670a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND; 32680a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 32690a708f8fSGustavo F. Padovan } else { 32700e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 32710a708f8fSGustavo F. Padovan result = L2CAP_CR_SUCCESS; 32720a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 32730a708f8fSGustavo F. Padovan } 32740a708f8fSGustavo F. Padovan } else { 32750e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 32760a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 32770a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND; 32780a708f8fSGustavo F. Padovan } 32790a708f8fSGustavo F. Padovan } else { 32800e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 32810a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 32820a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 32830a708f8fSGustavo F. Padovan } 32840a708f8fSGustavo F. Padovan 32850a708f8fSGustavo F. Padovan response: 3286aa2ac881SGustavo F. Padovan release_sock(parent); 32873df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 32880a708f8fSGustavo F. Padovan 32890a708f8fSGustavo F. Padovan sendresp: 32900a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid); 32910a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid); 32920a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result); 32930a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status); 32940a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); 32950a708f8fSGustavo F. Padovan 32960a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { 32970a708f8fSGustavo F. Padovan struct l2cap_info_req info; 32980a708f8fSGustavo F. Padovan info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 32990a708f8fSGustavo F. Padovan 33000a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 33010a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 33020a708f8fSGustavo F. Padovan 3303ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 33040a708f8fSGustavo F. Padovan 33050a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 33060a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(info), &info); 33070a708f8fSGustavo F. Padovan } 33080a708f8fSGustavo F. Padovan 3309c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && 33100a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) { 33110a708f8fSGustavo F. Padovan u8 buf[128]; 3312c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 33130a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 331473ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 331573ffa904SGustavo F. Padovan chan->num_conf_req++; 33160a708f8fSGustavo F. Padovan } 33170a708f8fSGustavo F. Padovan 33180a708f8fSGustavo F. Padovan return 0; 33190a708f8fSGustavo F. Padovan } 33200a708f8fSGustavo F. Padovan 33210a708f8fSGustavo F. Padovan static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 33220a708f8fSGustavo F. Padovan { 33230a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; 33240a708f8fSGustavo F. Padovan u16 scid, dcid, result, status; 332548454079SGustavo F. Padovan struct l2cap_chan *chan; 33260a708f8fSGustavo F. Padovan u8 req[128]; 33273df91ea2SAndrei Emeltchenko int err; 33280a708f8fSGustavo F. Padovan 33290a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 33300a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 33310a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 33320a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status); 33330a708f8fSGustavo F. Padovan 33341b009c98SAndrei Emeltchenko BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", 33351b009c98SAndrei Emeltchenko dcid, scid, result, status); 33360a708f8fSGustavo F. Padovan 33373df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 33383df91ea2SAndrei Emeltchenko 33390a708f8fSGustavo F. Padovan if (scid) { 33403df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 33413df91ea2SAndrei Emeltchenko if (!chan) { 33423df91ea2SAndrei Emeltchenko err = -EFAULT; 33433df91ea2SAndrei Emeltchenko goto unlock; 33443df91ea2SAndrei Emeltchenko } 33450a708f8fSGustavo F. Padovan } else { 33463df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 33473df91ea2SAndrei Emeltchenko if (!chan) { 33483df91ea2SAndrei Emeltchenko err = -EFAULT; 33493df91ea2SAndrei Emeltchenko goto unlock; 33503df91ea2SAndrei Emeltchenko } 33510a708f8fSGustavo F. Padovan } 33520a708f8fSGustavo F. Padovan 33533df91ea2SAndrei Emeltchenko err = 0; 33543df91ea2SAndrei Emeltchenko 33556be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 335648454079SGustavo F. Padovan 33570a708f8fSGustavo F. Padovan switch (result) { 33580a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS: 335989bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 3360fc7f8a7eSGustavo F. Padovan chan->ident = 0; 3361fe4128e0SGustavo F. Padovan chan->dcid = dcid; 3362c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state); 33630a708f8fSGustavo F. Padovan 3364c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 33650a708f8fSGustavo F. Padovan break; 33660a708f8fSGustavo F. Padovan 33670a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 336873ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, req), req); 336973ffa904SGustavo F. Padovan chan->num_conf_req++; 33700a708f8fSGustavo F. Padovan break; 33710a708f8fSGustavo F. Padovan 33720a708f8fSGustavo F. Padovan case L2CAP_CR_PEND: 3373c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 33740a708f8fSGustavo F. Padovan break; 33750a708f8fSGustavo F. Padovan 33760a708f8fSGustavo F. Padovan default: 337748454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED); 33780a708f8fSGustavo F. Padovan break; 33790a708f8fSGustavo F. Padovan } 33800a708f8fSGustavo F. Padovan 33816be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 33823df91ea2SAndrei Emeltchenko 33833df91ea2SAndrei Emeltchenko unlock: 33843df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 33853df91ea2SAndrei Emeltchenko 33863df91ea2SAndrei Emeltchenko return err; 33870a708f8fSGustavo F. Padovan } 33880a708f8fSGustavo F. Padovan 338947d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan) 33900a708f8fSGustavo F. Padovan { 33910a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both 33920a708f8fSGustavo F. Padovan * sides request it. 33930a708f8fSGustavo F. Padovan */ 33940c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) 339547d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3396c1360a1cSGustavo F. Padovan else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) 339747d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16; 33980a708f8fSGustavo F. Padovan } 33990a708f8fSGustavo F. Padovan 34000a708f8fSGustavo F. Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 34010a708f8fSGustavo F. Padovan { 34020a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; 34030a708f8fSGustavo F. Padovan u16 dcid, flags; 34040a708f8fSGustavo F. Padovan u8 rsp[64]; 340548454079SGustavo F. Padovan struct l2cap_chan *chan; 34063c588192SMat Martineau int len, err = 0; 34070a708f8fSGustavo F. Padovan 34080a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 34090a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags); 34100a708f8fSGustavo F. Padovan 34110a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); 34120a708f8fSGustavo F. Padovan 3413baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid); 341448454079SGustavo F. Padovan if (!chan) 34150a708f8fSGustavo F. Padovan return -ENOENT; 34160a708f8fSGustavo F. Padovan 3417033b1142SDavid S. Miller if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { 3418e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_cid rej; 34190a708f8fSGustavo F. Padovan 3420e2fd318eSIlia Kolomisnky rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID); 3421e2fd318eSIlia Kolomisnky rej.scid = cpu_to_le16(chan->scid); 3422e2fd318eSIlia Kolomisnky rej.dcid = cpu_to_le16(chan->dcid); 3423e2fd318eSIlia Kolomisnky 34240a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 34250a708f8fSGustavo F. Padovan sizeof(rej), &rej); 34260a708f8fSGustavo F. Padovan goto unlock; 34270a708f8fSGustavo F. Padovan } 34280a708f8fSGustavo F. Padovan 34290a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */ 34300a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req); 34317ac28817SDan Rosenberg if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) { 34320a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 3433fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 34340a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp); 34350a708f8fSGustavo F. Padovan goto unlock; 34360a708f8fSGustavo F. Padovan } 34370a708f8fSGustavo F. Padovan 34380a708f8fSGustavo F. Padovan /* Store config. */ 343973ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len); 344073ffa904SGustavo F. Padovan chan->conf_len += len; 34410a708f8fSGustavo F. Padovan 34420a708f8fSGustavo F. Padovan if (flags & 0x0001) { 34430a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */ 34440a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 3445fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 34460a708f8fSGustavo F. Padovan L2CAP_CONF_SUCCESS, 0x0001), rsp); 34470a708f8fSGustavo F. Padovan goto unlock; 34480a708f8fSGustavo F. Padovan } 34490a708f8fSGustavo F. Padovan 34500a708f8fSGustavo F. Padovan /* Complete config. */ 345173ffa904SGustavo F. Padovan len = l2cap_parse_conf_req(chan, rsp); 34520a708f8fSGustavo F. Padovan if (len < 0) { 3453e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 34540a708f8fSGustavo F. Padovan goto unlock; 34550a708f8fSGustavo F. Padovan } 34560a708f8fSGustavo F. Padovan 34570a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); 345873ffa904SGustavo F. Padovan chan->num_conf_rsp++; 34590a708f8fSGustavo F. Padovan 34600a708f8fSGustavo F. Padovan /* Reset config buffer. */ 346173ffa904SGustavo F. Padovan chan->conf_len = 0; 34620a708f8fSGustavo F. Padovan 3463c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) 34640a708f8fSGustavo F. Padovan goto unlock; 34650a708f8fSGustavo F. Padovan 3466c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 346747d1ec61SGustavo F. Padovan set_default_fcs(chan); 34680a708f8fSGustavo F. Padovan 346989bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECTED); 34700a708f8fSGustavo F. Padovan 3471105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 3472105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 34733c588192SMat Martineau err = l2cap_ertm_init(chan); 34740a708f8fSGustavo F. Padovan 34753c588192SMat Martineau if (err < 0) 34763c588192SMat Martineau l2cap_send_disconn_req(chan->conn, chan, -err); 34773c588192SMat Martineau else 3478cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 34793c588192SMat Martineau 34800a708f8fSGustavo F. Padovan goto unlock; 34810a708f8fSGustavo F. Padovan } 34820a708f8fSGustavo F. Padovan 3483c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { 34840a708f8fSGustavo F. Padovan u8 buf[64]; 34850a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 348673ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 348773ffa904SGustavo F. Padovan chan->num_conf_req++; 34880a708f8fSGustavo F. Padovan } 34890a708f8fSGustavo F. Padovan 34900e8b207eSAndrei Emeltchenko /* Got Conf Rsp PENDING from remote side and asume we sent 34910e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */ 34920e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && 34930e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 34940e8b207eSAndrei Emeltchenko 34950e8b207eSAndrei Emeltchenko /* check compatibility */ 34960e8b207eSAndrei Emeltchenko 34970e8b207eSAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 34980e8b207eSAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 34990e8b207eSAndrei Emeltchenko 35000e8b207eSAndrei Emeltchenko l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 35010e8b207eSAndrei Emeltchenko l2cap_build_conf_rsp(chan, rsp, 35020e8b207eSAndrei Emeltchenko L2CAP_CONF_SUCCESS, 0x0000), rsp); 35030e8b207eSAndrei Emeltchenko } 35040e8b207eSAndrei Emeltchenko 35050a708f8fSGustavo F. Padovan unlock: 35066be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 35073c588192SMat Martineau return err; 35080a708f8fSGustavo F. Padovan } 35090a708f8fSGustavo F. Padovan 35100a708f8fSGustavo F. Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 35110a708f8fSGustavo F. Padovan { 35120a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; 35130a708f8fSGustavo F. Padovan u16 scid, flags, result; 351448454079SGustavo F. Padovan struct l2cap_chan *chan; 351561386cbaSAndrei Emeltchenko int len = le16_to_cpu(cmd->len) - sizeof(*rsp); 35163c588192SMat Martineau int err = 0; 35170a708f8fSGustavo F. Padovan 35180a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 35190a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags); 35200a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 35210a708f8fSGustavo F. Padovan 352261386cbaSAndrei Emeltchenko BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags, 352361386cbaSAndrei Emeltchenko result, len); 35240a708f8fSGustavo F. Padovan 3525baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 352648454079SGustavo F. Padovan if (!chan) 35270a708f8fSGustavo F. Padovan return 0; 35280a708f8fSGustavo F. Padovan 35290a708f8fSGustavo F. Padovan switch (result) { 35300a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS: 353147d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len); 35320e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state); 35330a708f8fSGustavo F. Padovan break; 35340a708f8fSGustavo F. Padovan 35350e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING: 35360e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state); 35370e8b207eSAndrei Emeltchenko 35380e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 35390e8b207eSAndrei Emeltchenko char buf[64]; 35400e8b207eSAndrei Emeltchenko 35410e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len, 35420e8b207eSAndrei Emeltchenko buf, &result); 35430e8b207eSAndrei Emeltchenko if (len < 0) { 35440e8b207eSAndrei Emeltchenko l2cap_send_disconn_req(conn, chan, ECONNRESET); 35450e8b207eSAndrei Emeltchenko goto done; 35460e8b207eSAndrei Emeltchenko } 35470e8b207eSAndrei Emeltchenko 35480e8b207eSAndrei Emeltchenko /* check compatibility */ 35490e8b207eSAndrei Emeltchenko 35500e8b207eSAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 35510e8b207eSAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 35520e8b207eSAndrei Emeltchenko 35530e8b207eSAndrei Emeltchenko l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 35540e8b207eSAndrei Emeltchenko l2cap_build_conf_rsp(chan, buf, 35550e8b207eSAndrei Emeltchenko L2CAP_CONF_SUCCESS, 0x0000), buf); 35560e8b207eSAndrei Emeltchenko } 35570e8b207eSAndrei Emeltchenko goto done; 35580e8b207eSAndrei Emeltchenko 35590a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT: 356073ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { 35610a708f8fSGustavo F. Padovan char req[64]; 35620a708f8fSGustavo F. Padovan 35630a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { 3564e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 35650a708f8fSGustavo F. Padovan goto done; 35660a708f8fSGustavo F. Padovan } 35670a708f8fSGustavo F. Padovan 35680a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */ 35690a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS; 3570b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len, 3571b4450035SGustavo F. Padovan req, &result); 35720a708f8fSGustavo F. Padovan if (len < 0) { 3573e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 35740a708f8fSGustavo F. Padovan goto done; 35750a708f8fSGustavo F. Padovan } 35760a708f8fSGustavo F. Padovan 35770a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 35780a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req); 357973ffa904SGustavo F. Padovan chan->num_conf_req++; 35800a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS) 35810a708f8fSGustavo F. Padovan goto done; 35820a708f8fSGustavo F. Padovan break; 35830a708f8fSGustavo F. Padovan } 35840a708f8fSGustavo F. Padovan 35850a708f8fSGustavo F. Padovan default: 35866be36555SAndrei Emeltchenko l2cap_chan_set_err(chan, ECONNRESET); 35872e0052e4SAndrei Emeltchenko 3588ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); 3589e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 35900a708f8fSGustavo F. Padovan goto done; 35910a708f8fSGustavo F. Padovan } 35920a708f8fSGustavo F. Padovan 35930a708f8fSGustavo F. Padovan if (flags & 0x01) 35940a708f8fSGustavo F. Padovan goto done; 35950a708f8fSGustavo F. Padovan 3596c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state); 35970a708f8fSGustavo F. Padovan 3598c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { 359947d1ec61SGustavo F. Padovan set_default_fcs(chan); 36000a708f8fSGustavo F. Padovan 360189bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECTED); 3602105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 3603105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 36043c588192SMat Martineau err = l2cap_ertm_init(chan); 36050a708f8fSGustavo F. Padovan 36063c588192SMat Martineau if (err < 0) 36073c588192SMat Martineau l2cap_send_disconn_req(chan->conn, chan, -err); 36083c588192SMat Martineau else 3609cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 36100a708f8fSGustavo F. Padovan } 36110a708f8fSGustavo F. Padovan 36120a708f8fSGustavo F. Padovan done: 36136be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 36143c588192SMat Martineau return err; 36150a708f8fSGustavo F. Padovan } 36160a708f8fSGustavo F. Padovan 36170a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 36180a708f8fSGustavo F. Padovan { 36190a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; 36200a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp; 36210a708f8fSGustavo F. Padovan u16 dcid, scid; 362248454079SGustavo F. Padovan struct l2cap_chan *chan; 36230a708f8fSGustavo F. Padovan struct sock *sk; 36240a708f8fSGustavo F. Padovan 36250a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid); 36260a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 36270a708f8fSGustavo F. Padovan 36280a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); 36290a708f8fSGustavo F. Padovan 36303df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 36313df91ea2SAndrei Emeltchenko 36323df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, dcid); 36333df91ea2SAndrei Emeltchenko if (!chan) { 36343df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 36350a708f8fSGustavo F. Padovan return 0; 36363df91ea2SAndrei Emeltchenko } 36370a708f8fSGustavo F. Padovan 36386be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 36396be36555SAndrei Emeltchenko 364048454079SGustavo F. Padovan sk = chan->sk; 364148454079SGustavo F. Padovan 3642fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3643fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 36440a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); 36450a708f8fSGustavo F. Padovan 36466be36555SAndrei Emeltchenko lock_sock(sk); 36470a708f8fSGustavo F. Padovan sk->sk_shutdown = SHUTDOWN_MASK; 36486be36555SAndrei Emeltchenko release_sock(sk); 36490a708f8fSGustavo F. Padovan 365061d6ef3eSMat Martineau l2cap_chan_hold(chan); 365148454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET); 36526be36555SAndrei Emeltchenko 36536be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 36540a708f8fSGustavo F. Padovan 3655ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 365661d6ef3eSMat Martineau l2cap_chan_put(chan); 36573df91ea2SAndrei Emeltchenko 36583df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 36593df91ea2SAndrei Emeltchenko 36600a708f8fSGustavo F. Padovan return 0; 36610a708f8fSGustavo F. Padovan } 36620a708f8fSGustavo F. Padovan 36630a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 36640a708f8fSGustavo F. Padovan { 36650a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; 36660a708f8fSGustavo F. Padovan u16 dcid, scid; 366748454079SGustavo F. Padovan struct l2cap_chan *chan; 36680a708f8fSGustavo F. Padovan 36690a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 36700a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 36710a708f8fSGustavo F. Padovan 36720a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); 36730a708f8fSGustavo F. Padovan 36743df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 36753df91ea2SAndrei Emeltchenko 36763df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 36773df91ea2SAndrei Emeltchenko if (!chan) { 36783df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 36790a708f8fSGustavo F. Padovan return 0; 36803df91ea2SAndrei Emeltchenko } 36810a708f8fSGustavo F. Padovan 36826be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 368348454079SGustavo F. Padovan 368461d6ef3eSMat Martineau l2cap_chan_hold(chan); 368548454079SGustavo F. Padovan l2cap_chan_del(chan, 0); 36866be36555SAndrei Emeltchenko 36876be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 36880a708f8fSGustavo F. Padovan 3689ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 369061d6ef3eSMat Martineau l2cap_chan_put(chan); 36913df91ea2SAndrei Emeltchenko 36923df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 36933df91ea2SAndrei Emeltchenko 36940a708f8fSGustavo F. Padovan return 0; 36950a708f8fSGustavo F. Padovan } 36960a708f8fSGustavo F. Padovan 36970a708f8fSGustavo F. Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 36980a708f8fSGustavo F. Padovan { 36990a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data; 37000a708f8fSGustavo F. Padovan u16 type; 37010a708f8fSGustavo F. Padovan 37020a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type); 37030a708f8fSGustavo F. Padovan 37040a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type); 37050a708f8fSGustavo F. Padovan 37060a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) { 37070a708f8fSGustavo F. Padovan u8 buf[8]; 37080a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask; 37090a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 37100a708f8fSGustavo F. Padovan rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 37110a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 37120a708f8fSGustavo F. Padovan if (!disable_ertm) 37130a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING 37140a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS; 3715a5fd6f30SAndrei Emeltchenko if (enable_hs) 37166327eb98SAndrei Emeltchenko feat_mask |= L2CAP_FEAT_EXT_FLOW 37176327eb98SAndrei Emeltchenko | L2CAP_FEAT_EXT_WINDOW; 3718a5fd6f30SAndrei Emeltchenko 37190a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data); 37200a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 37210a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(buf), buf); 37220a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) { 37230a708f8fSGustavo F. Padovan u8 buf[12]; 37240a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 372550a147cdSMat Martineau 372650a147cdSMat Martineau if (enable_hs) 372750a147cdSMat Martineau l2cap_fixed_chan[0] |= L2CAP_FC_A2MP; 372850a147cdSMat Martineau else 372950a147cdSMat Martineau l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP; 373050a147cdSMat Martineau 37310a708f8fSGustavo F. Padovan rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 37320a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 3733c6337ea6SAndrei Emeltchenko memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); 37340a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 37350a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(buf), buf); 37360a708f8fSGustavo F. Padovan } else { 37370a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp; 37380a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type); 37390a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP); 37400a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 37410a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(rsp), &rsp); 37420a708f8fSGustavo F. Padovan } 37430a708f8fSGustavo F. Padovan 37440a708f8fSGustavo F. Padovan return 0; 37450a708f8fSGustavo F. Padovan } 37460a708f8fSGustavo F. Padovan 37470a708f8fSGustavo F. Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 37480a708f8fSGustavo F. Padovan { 37490a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; 37500a708f8fSGustavo F. Padovan u16 type, result; 37510a708f8fSGustavo F. Padovan 37520a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type); 37530a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 37540a708f8fSGustavo F. Padovan 37550a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); 37560a708f8fSGustavo F. Padovan 3757e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */ 3758e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident || 3759e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 3760e90165beSAndrei Emeltchenko return 0; 3761e90165beSAndrei Emeltchenko 376217cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 37630a708f8fSGustavo F. Padovan 37640a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) { 37650a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 37660a708f8fSGustavo F. Padovan conn->info_ident = 0; 37670a708f8fSGustavo F. Padovan 37680a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 37690a708f8fSGustavo F. Padovan 37700a708f8fSGustavo F. Padovan return 0; 37710a708f8fSGustavo F. Padovan } 37720a708f8fSGustavo F. Padovan 3773978c93b9SAndrei Emeltchenko switch (type) { 3774978c93b9SAndrei Emeltchenko case L2CAP_IT_FEAT_MASK: 37750a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data); 37760a708f8fSGustavo F. Padovan 37770a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { 37780a708f8fSGustavo F. Padovan struct l2cap_info_req req; 37790a708f8fSGustavo F. Padovan req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 37800a708f8fSGustavo F. Padovan 37810a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 37820a708f8fSGustavo F. Padovan 37830a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 37840a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 37850a708f8fSGustavo F. Padovan } else { 37860a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 37870a708f8fSGustavo F. Padovan conn->info_ident = 0; 37880a708f8fSGustavo F. Padovan 37890a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 37900a708f8fSGustavo F. Padovan } 3791978c93b9SAndrei Emeltchenko break; 3792978c93b9SAndrei Emeltchenko 3793978c93b9SAndrei Emeltchenko case L2CAP_IT_FIXED_CHAN: 3794978c93b9SAndrei Emeltchenko conn->fixed_chan_mask = rsp->data[0]; 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); 3799978c93b9SAndrei Emeltchenko break; 38000a708f8fSGustavo F. Padovan } 38010a708f8fSGustavo F. Padovan 38020a708f8fSGustavo F. Padovan return 0; 38030a708f8fSGustavo F. Padovan } 38040a708f8fSGustavo F. Padovan 3805f94ff6ffSMat Martineau static inline int l2cap_create_channel_req(struct l2cap_conn *conn, 3806f94ff6ffSMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, 3807f94ff6ffSMat Martineau void *data) 3808f94ff6ffSMat Martineau { 3809f94ff6ffSMat Martineau struct l2cap_create_chan_req *req = data; 3810f94ff6ffSMat Martineau struct l2cap_create_chan_rsp rsp; 3811f94ff6ffSMat Martineau u16 psm, scid; 3812f94ff6ffSMat Martineau 3813f94ff6ffSMat Martineau if (cmd_len != sizeof(*req)) 3814f94ff6ffSMat Martineau return -EPROTO; 3815f94ff6ffSMat Martineau 3816f94ff6ffSMat Martineau if (!enable_hs) 3817f94ff6ffSMat Martineau return -EINVAL; 3818f94ff6ffSMat Martineau 3819f94ff6ffSMat Martineau psm = le16_to_cpu(req->psm); 3820f94ff6ffSMat Martineau scid = le16_to_cpu(req->scid); 3821f94ff6ffSMat Martineau 3822f94ff6ffSMat Martineau BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id); 3823f94ff6ffSMat Martineau 3824f94ff6ffSMat Martineau /* Placeholder: Always reject */ 3825f94ff6ffSMat Martineau rsp.dcid = 0; 3826f94ff6ffSMat Martineau rsp.scid = cpu_to_le16(scid); 38278ce0c498SAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM); 38288ce0c498SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 3829f94ff6ffSMat Martineau 3830f94ff6ffSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, 3831f94ff6ffSMat Martineau sizeof(rsp), &rsp); 3832f94ff6ffSMat Martineau 3833f94ff6ffSMat Martineau return 0; 3834f94ff6ffSMat Martineau } 3835f94ff6ffSMat Martineau 3836f94ff6ffSMat Martineau static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn, 3837f94ff6ffSMat Martineau struct l2cap_cmd_hdr *cmd, void *data) 3838f94ff6ffSMat Martineau { 3839f94ff6ffSMat Martineau BT_DBG("conn %p", conn); 3840f94ff6ffSMat Martineau 3841f94ff6ffSMat Martineau return l2cap_connect_rsp(conn, cmd, data); 3842f94ff6ffSMat Martineau } 3843f94ff6ffSMat Martineau 38448d5a04a1SMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident, 38458d5a04a1SMat Martineau u16 icid, u16 result) 38468d5a04a1SMat Martineau { 38478d5a04a1SMat Martineau struct l2cap_move_chan_rsp rsp; 38488d5a04a1SMat Martineau 38498d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 38508d5a04a1SMat Martineau 38518d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 38528d5a04a1SMat Martineau rsp.result = cpu_to_le16(result); 38538d5a04a1SMat Martineau 38548d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp); 38558d5a04a1SMat Martineau } 38568d5a04a1SMat Martineau 38578d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn, 38588d5a04a1SMat Martineau struct l2cap_chan *chan, u16 icid, u16 result) 38598d5a04a1SMat Martineau { 38608d5a04a1SMat Martineau struct l2cap_move_chan_cfm cfm; 38618d5a04a1SMat Martineau u8 ident; 38628d5a04a1SMat Martineau 38638d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 38648d5a04a1SMat Martineau 38658d5a04a1SMat Martineau ident = l2cap_get_ident(conn); 38668d5a04a1SMat Martineau if (chan) 38678d5a04a1SMat Martineau chan->ident = ident; 38688d5a04a1SMat Martineau 38698d5a04a1SMat Martineau cfm.icid = cpu_to_le16(icid); 38708d5a04a1SMat Martineau cfm.result = cpu_to_le16(result); 38718d5a04a1SMat Martineau 38728d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm); 38738d5a04a1SMat Martineau } 38748d5a04a1SMat Martineau 38758d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, 38768d5a04a1SMat Martineau u16 icid) 38778d5a04a1SMat Martineau { 38788d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp rsp; 38798d5a04a1SMat Martineau 38808d5a04a1SMat Martineau BT_DBG("icid %d", icid); 38818d5a04a1SMat Martineau 38828d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 38838d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp); 38848d5a04a1SMat Martineau } 38858d5a04a1SMat Martineau 38868d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn, 38878d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 38888d5a04a1SMat Martineau { 38898d5a04a1SMat Martineau struct l2cap_move_chan_req *req = data; 38908d5a04a1SMat Martineau u16 icid = 0; 38918d5a04a1SMat Martineau u16 result = L2CAP_MR_NOT_ALLOWED; 38928d5a04a1SMat Martineau 38938d5a04a1SMat Martineau if (cmd_len != sizeof(*req)) 38948d5a04a1SMat Martineau return -EPROTO; 38958d5a04a1SMat Martineau 38968d5a04a1SMat Martineau icid = le16_to_cpu(req->icid); 38978d5a04a1SMat Martineau 38988d5a04a1SMat Martineau BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id); 38998d5a04a1SMat Martineau 39008d5a04a1SMat Martineau if (!enable_hs) 39018d5a04a1SMat Martineau return -EINVAL; 39028d5a04a1SMat Martineau 39038d5a04a1SMat Martineau /* Placeholder: Always refuse */ 39048d5a04a1SMat Martineau l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result); 39058d5a04a1SMat Martineau 39068d5a04a1SMat Martineau return 0; 39078d5a04a1SMat Martineau } 39088d5a04a1SMat Martineau 39098d5a04a1SMat Martineau static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn, 39108d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 39118d5a04a1SMat Martineau { 39128d5a04a1SMat Martineau struct l2cap_move_chan_rsp *rsp = data; 39138d5a04a1SMat Martineau u16 icid, result; 39148d5a04a1SMat Martineau 39158d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 39168d5a04a1SMat Martineau return -EPROTO; 39178d5a04a1SMat Martineau 39188d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 39198d5a04a1SMat Martineau result = le16_to_cpu(rsp->result); 39208d5a04a1SMat Martineau 39218d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 39228d5a04a1SMat Martineau 39238d5a04a1SMat Martineau /* Placeholder: Always unconfirmed */ 39248d5a04a1SMat Martineau l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED); 39258d5a04a1SMat Martineau 39268d5a04a1SMat Martineau return 0; 39278d5a04a1SMat Martineau } 39288d5a04a1SMat Martineau 39298d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn, 39308d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 39318d5a04a1SMat Martineau { 39328d5a04a1SMat Martineau struct l2cap_move_chan_cfm *cfm = data; 39338d5a04a1SMat Martineau u16 icid, result; 39348d5a04a1SMat Martineau 39358d5a04a1SMat Martineau if (cmd_len != sizeof(*cfm)) 39368d5a04a1SMat Martineau return -EPROTO; 39378d5a04a1SMat Martineau 39388d5a04a1SMat Martineau icid = le16_to_cpu(cfm->icid); 39398d5a04a1SMat Martineau result = le16_to_cpu(cfm->result); 39408d5a04a1SMat Martineau 39418d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 39428d5a04a1SMat Martineau 39438d5a04a1SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 39448d5a04a1SMat Martineau 39458d5a04a1SMat Martineau return 0; 39468d5a04a1SMat Martineau } 39478d5a04a1SMat Martineau 39488d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, 39498d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 39508d5a04a1SMat Martineau { 39518d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp *rsp = data; 39528d5a04a1SMat Martineau u16 icid; 39538d5a04a1SMat Martineau 39548d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 39558d5a04a1SMat Martineau return -EPROTO; 39568d5a04a1SMat Martineau 39578d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 39588d5a04a1SMat Martineau 39598d5a04a1SMat Martineau BT_DBG("icid %d", icid); 39608d5a04a1SMat Martineau 39618d5a04a1SMat Martineau return 0; 39628d5a04a1SMat Martineau } 39638d5a04a1SMat Martineau 3964e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency, 3965de73115aSClaudio Takahasi u16 to_multiplier) 3966de73115aSClaudio Takahasi { 3967de73115aSClaudio Takahasi u16 max_latency; 3968de73115aSClaudio Takahasi 3969de73115aSClaudio Takahasi if (min > max || min < 6 || max > 3200) 3970de73115aSClaudio Takahasi return -EINVAL; 3971de73115aSClaudio Takahasi 3972de73115aSClaudio Takahasi if (to_multiplier < 10 || to_multiplier > 3200) 3973de73115aSClaudio Takahasi return -EINVAL; 3974de73115aSClaudio Takahasi 3975de73115aSClaudio Takahasi if (max >= to_multiplier * 8) 3976de73115aSClaudio Takahasi return -EINVAL; 3977de73115aSClaudio Takahasi 3978de73115aSClaudio Takahasi max_latency = (to_multiplier * 8 / max) - 1; 3979de73115aSClaudio Takahasi if (latency > 499 || latency > max_latency) 3980de73115aSClaudio Takahasi return -EINVAL; 3981de73115aSClaudio Takahasi 3982de73115aSClaudio Takahasi return 0; 3983de73115aSClaudio Takahasi } 3984de73115aSClaudio Takahasi 3985de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, 3986de73115aSClaudio Takahasi struct l2cap_cmd_hdr *cmd, u8 *data) 3987de73115aSClaudio Takahasi { 3988de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon; 3989de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req; 3990de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp; 3991de73115aSClaudio Takahasi u16 min, max, latency, to_multiplier, cmd_len; 39922ce603ebSClaudio Takahasi int err; 3993de73115aSClaudio Takahasi 3994de73115aSClaudio Takahasi if (!(hcon->link_mode & HCI_LM_MASTER)) 3995de73115aSClaudio Takahasi return -EINVAL; 3996de73115aSClaudio Takahasi 3997de73115aSClaudio Takahasi cmd_len = __le16_to_cpu(cmd->len); 3998de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) 3999de73115aSClaudio Takahasi return -EPROTO; 4000de73115aSClaudio Takahasi 4001de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data; 4002de73115aSClaudio Takahasi min = __le16_to_cpu(req->min); 4003de73115aSClaudio Takahasi max = __le16_to_cpu(req->max); 4004de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency); 4005de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier); 4006de73115aSClaudio Takahasi 4007de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", 4008de73115aSClaudio Takahasi min, max, latency, to_multiplier); 4009de73115aSClaudio Takahasi 4010de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp)); 40112ce603ebSClaudio Takahasi 40122ce603ebSClaudio Takahasi err = l2cap_check_conn_param(min, max, latency, to_multiplier); 40132ce603ebSClaudio Takahasi if (err) 4014de73115aSClaudio Takahasi rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); 4015de73115aSClaudio Takahasi else 4016de73115aSClaudio Takahasi rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); 4017de73115aSClaudio Takahasi 4018de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, 4019de73115aSClaudio Takahasi sizeof(rsp), &rsp); 4020de73115aSClaudio Takahasi 40212ce603ebSClaudio Takahasi if (!err) 40222ce603ebSClaudio Takahasi hci_le_conn_update(hcon, min, max, latency, to_multiplier); 40232ce603ebSClaudio Takahasi 4024de73115aSClaudio Takahasi return 0; 4025de73115aSClaudio Takahasi } 4026de73115aSClaudio Takahasi 40273300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, 40283300d9a9SClaudio Takahasi struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 40293300d9a9SClaudio Takahasi { 40303300d9a9SClaudio Takahasi int err = 0; 40313300d9a9SClaudio Takahasi 40323300d9a9SClaudio Takahasi switch (cmd->code) { 40333300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 40343300d9a9SClaudio Takahasi l2cap_command_rej(conn, cmd, data); 40353300d9a9SClaudio Takahasi break; 40363300d9a9SClaudio Takahasi 40373300d9a9SClaudio Takahasi case L2CAP_CONN_REQ: 40383300d9a9SClaudio Takahasi err = l2cap_connect_req(conn, cmd, data); 40393300d9a9SClaudio Takahasi break; 40403300d9a9SClaudio Takahasi 40413300d9a9SClaudio Takahasi case L2CAP_CONN_RSP: 40423300d9a9SClaudio Takahasi err = l2cap_connect_rsp(conn, cmd, data); 40433300d9a9SClaudio Takahasi break; 40443300d9a9SClaudio Takahasi 40453300d9a9SClaudio Takahasi case L2CAP_CONF_REQ: 40463300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data); 40473300d9a9SClaudio Takahasi break; 40483300d9a9SClaudio Takahasi 40493300d9a9SClaudio Takahasi case L2CAP_CONF_RSP: 40503300d9a9SClaudio Takahasi err = l2cap_config_rsp(conn, cmd, data); 40513300d9a9SClaudio Takahasi break; 40523300d9a9SClaudio Takahasi 40533300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ: 40543300d9a9SClaudio Takahasi err = l2cap_disconnect_req(conn, cmd, data); 40553300d9a9SClaudio Takahasi break; 40563300d9a9SClaudio Takahasi 40573300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP: 40583300d9a9SClaudio Takahasi err = l2cap_disconnect_rsp(conn, cmd, data); 40593300d9a9SClaudio Takahasi break; 40603300d9a9SClaudio Takahasi 40613300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ: 40623300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data); 40633300d9a9SClaudio Takahasi break; 40643300d9a9SClaudio Takahasi 40653300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP: 40663300d9a9SClaudio Takahasi break; 40673300d9a9SClaudio Takahasi 40683300d9a9SClaudio Takahasi case L2CAP_INFO_REQ: 40693300d9a9SClaudio Takahasi err = l2cap_information_req(conn, cmd, data); 40703300d9a9SClaudio Takahasi break; 40713300d9a9SClaudio Takahasi 40723300d9a9SClaudio Takahasi case L2CAP_INFO_RSP: 40733300d9a9SClaudio Takahasi err = l2cap_information_rsp(conn, cmd, data); 40743300d9a9SClaudio Takahasi break; 40753300d9a9SClaudio Takahasi 4076f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_REQ: 4077f94ff6ffSMat Martineau err = l2cap_create_channel_req(conn, cmd, cmd_len, data); 4078f94ff6ffSMat Martineau break; 4079f94ff6ffSMat Martineau 4080f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_RSP: 4081f94ff6ffSMat Martineau err = l2cap_create_channel_rsp(conn, cmd, data); 4082f94ff6ffSMat Martineau break; 4083f94ff6ffSMat Martineau 40848d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_REQ: 40858d5a04a1SMat Martineau err = l2cap_move_channel_req(conn, cmd, cmd_len, data); 40868d5a04a1SMat Martineau break; 40878d5a04a1SMat Martineau 40888d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_RSP: 40898d5a04a1SMat Martineau err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data); 40908d5a04a1SMat Martineau break; 40918d5a04a1SMat Martineau 40928d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM: 40938d5a04a1SMat Martineau err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data); 40948d5a04a1SMat Martineau break; 40958d5a04a1SMat Martineau 40968d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM_RSP: 40978d5a04a1SMat Martineau err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data); 40988d5a04a1SMat Martineau break; 40998d5a04a1SMat Martineau 41003300d9a9SClaudio Takahasi default: 41013300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code); 41023300d9a9SClaudio Takahasi err = -EINVAL; 41033300d9a9SClaudio Takahasi break; 41043300d9a9SClaudio Takahasi } 41053300d9a9SClaudio Takahasi 41063300d9a9SClaudio Takahasi return err; 41073300d9a9SClaudio Takahasi } 41083300d9a9SClaudio Takahasi 41093300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, 41103300d9a9SClaudio Takahasi struct l2cap_cmd_hdr *cmd, u8 *data) 41113300d9a9SClaudio Takahasi { 41123300d9a9SClaudio Takahasi switch (cmd->code) { 41133300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 41143300d9a9SClaudio Takahasi return 0; 41153300d9a9SClaudio Takahasi 41163300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ: 4117de73115aSClaudio Takahasi return l2cap_conn_param_update_req(conn, cmd, data); 41183300d9a9SClaudio Takahasi 41193300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP: 41203300d9a9SClaudio Takahasi return 0; 41213300d9a9SClaudio Takahasi 41223300d9a9SClaudio Takahasi default: 41233300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code); 41243300d9a9SClaudio Takahasi return -EINVAL; 41253300d9a9SClaudio Takahasi } 41263300d9a9SClaudio Takahasi } 41273300d9a9SClaudio Takahasi 41283300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn, 41293300d9a9SClaudio Takahasi struct sk_buff *skb) 41300a708f8fSGustavo F. Padovan { 41310a708f8fSGustavo F. Padovan u8 *data = skb->data; 41320a708f8fSGustavo F. Padovan int len = skb->len; 41330a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr cmd; 41343300d9a9SClaudio Takahasi int err; 41350a708f8fSGustavo F. Padovan 41360a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb); 41370a708f8fSGustavo F. Padovan 41380a708f8fSGustavo F. Padovan while (len >= L2CAP_CMD_HDR_SIZE) { 41390a708f8fSGustavo F. Padovan u16 cmd_len; 41400a708f8fSGustavo F. Padovan memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); 41410a708f8fSGustavo F. Padovan data += L2CAP_CMD_HDR_SIZE; 41420a708f8fSGustavo F. Padovan len -= L2CAP_CMD_HDR_SIZE; 41430a708f8fSGustavo F. Padovan 41440a708f8fSGustavo F. Padovan cmd_len = le16_to_cpu(cmd.len); 41450a708f8fSGustavo F. Padovan 41460a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident); 41470a708f8fSGustavo F. Padovan 41480a708f8fSGustavo F. Padovan if (cmd_len > len || !cmd.ident) { 41490a708f8fSGustavo F. Padovan BT_DBG("corrupted command"); 41500a708f8fSGustavo F. Padovan break; 41510a708f8fSGustavo F. Padovan } 41520a708f8fSGustavo F. Padovan 41533300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 41543300d9a9SClaudio Takahasi err = l2cap_le_sig_cmd(conn, &cmd, data); 41553300d9a9SClaudio Takahasi else 41563300d9a9SClaudio Takahasi err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data); 41570a708f8fSGustavo F. Padovan 41580a708f8fSGustavo F. Padovan if (err) { 4159e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk rej; 41602c6d1a2eSGustavo F. Padovan 41612c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err); 41620a708f8fSGustavo F. Padovan 41630a708f8fSGustavo F. Padovan /* FIXME: Map err to a valid reason */ 4164e2fd318eSIlia Kolomisnky rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 41650a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); 41660a708f8fSGustavo F. Padovan } 41670a708f8fSGustavo F. Padovan 41680a708f8fSGustavo F. Padovan data += cmd_len; 41690a708f8fSGustavo F. Padovan len -= cmd_len; 41700a708f8fSGustavo F. Padovan } 41710a708f8fSGustavo F. Padovan 41720a708f8fSGustavo F. Padovan kfree_skb(skb); 41730a708f8fSGustavo F. Padovan } 41740a708f8fSGustavo F. Padovan 417547d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) 41760a708f8fSGustavo F. Padovan { 41770a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs; 4178e4ca6d98SAndrei Emeltchenko int hdr_size; 4179e4ca6d98SAndrei Emeltchenko 4180e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 4181e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE; 4182e4ca6d98SAndrei Emeltchenko else 4183e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE; 41840a708f8fSGustavo F. Padovan 418547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 418603a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE); 41870a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len); 41880a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); 41890a708f8fSGustavo F. Padovan 41900a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs) 41910a708f8fSGustavo F. Padovan return -EBADMSG; 41920a708f8fSGustavo F. Padovan } 41930a708f8fSGustavo F. Padovan return 0; 41940a708f8fSGustavo F. Padovan } 41950a708f8fSGustavo F. Padovan 4196525cd185SGustavo F. Padovan static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) 41970a708f8fSGustavo F. Padovan { 419888843ab0SAndrei Emeltchenko u32 control = 0; 41990a708f8fSGustavo F. Padovan 42006a026610SGustavo F. Padovan chan->frames_sent = 0; 42010a708f8fSGustavo F. Padovan 42020b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 42030a708f8fSGustavo F. Padovan 4204e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 4205ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); 4206e2ab4353SGustavo F. Padovan set_bit(CONN_RNR_SENT, &chan->conn_state); 42070a708f8fSGustavo F. Padovan } 42080a708f8fSGustavo F. Padovan 4209e2ab4353SGustavo F. Padovan if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 4210525cd185SGustavo F. Padovan l2cap_retransmit_frames(chan); 42110a708f8fSGustavo F. Padovan 4212525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 42130a708f8fSGustavo F. Padovan 4214e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 42156a026610SGustavo F. Padovan chan->frames_sent == 0) { 4216ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 42170a708f8fSGustavo F. Padovan } 42180a708f8fSGustavo F. Padovan } 42190a708f8fSGustavo F. Padovan 422084084a31SMat Martineau static void append_skb_frag(struct sk_buff *skb, 422184084a31SMat Martineau struct sk_buff *new_frag, struct sk_buff **last_frag) 42220a708f8fSGustavo F. Padovan { 422384084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments 422484084a31SMat Martineau * skb->data_len reflects only data in fragments 422584084a31SMat Martineau */ 422684084a31SMat Martineau if (!skb_has_frag_list(skb)) 422784084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag; 422884084a31SMat Martineau 422984084a31SMat Martineau new_frag->next = NULL; 423084084a31SMat Martineau 423184084a31SMat Martineau (*last_frag)->next = new_frag; 423284084a31SMat Martineau *last_frag = new_frag; 423384084a31SMat Martineau 423484084a31SMat Martineau skb->len += new_frag->len; 423584084a31SMat Martineau skb->data_len += new_frag->len; 423684084a31SMat Martineau skb->truesize += new_frag->truesize; 423784084a31SMat Martineau } 423884084a31SMat Martineau 42394b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, 42404b51dae9SMat Martineau struct l2cap_ctrl *control) 424184084a31SMat Martineau { 424284084a31SMat Martineau int err = -EINVAL; 42430a708f8fSGustavo F. Padovan 42444b51dae9SMat Martineau switch (control->sar) { 42457e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED: 424684084a31SMat Martineau if (chan->sdu) 424784084a31SMat Martineau break; 42480a708f8fSGustavo F. Padovan 424984084a31SMat Martineau err = chan->ops->recv(chan->data, skb); 425084084a31SMat Martineau break; 42510a708f8fSGustavo F. Padovan 42527e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START: 425384084a31SMat Martineau if (chan->sdu) 425484084a31SMat Martineau break; 42550a708f8fSGustavo F. Padovan 42566f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data); 425703a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE); 42580a708f8fSGustavo F. Padovan 425984084a31SMat Martineau if (chan->sdu_len > chan->imtu) { 426084084a31SMat Martineau err = -EMSGSIZE; 426184084a31SMat Martineau break; 426284084a31SMat Martineau } 42630a708f8fSGustavo F. Padovan 426484084a31SMat Martineau if (skb->len >= chan->sdu_len) 426584084a31SMat Martineau break; 426684084a31SMat Martineau 426784084a31SMat Martineau chan->sdu = skb; 426884084a31SMat Martineau chan->sdu_last_frag = skb; 426984084a31SMat Martineau 427084084a31SMat Martineau skb = NULL; 427184084a31SMat Martineau err = 0; 42720a708f8fSGustavo F. Padovan break; 42730a708f8fSGustavo F. Padovan 42747e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE: 42756f61fd47SGustavo F. Padovan if (!chan->sdu) 427684084a31SMat Martineau break; 42770a708f8fSGustavo F. Padovan 427884084a31SMat Martineau append_skb_frag(chan->sdu, skb, 427984084a31SMat Martineau &chan->sdu_last_frag); 428084084a31SMat Martineau skb = NULL; 42810a708f8fSGustavo F. Padovan 428284084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len) 428384084a31SMat Martineau break; 42840a708f8fSGustavo F. Padovan 428584084a31SMat Martineau err = 0; 42860a708f8fSGustavo F. Padovan break; 42870a708f8fSGustavo F. Padovan 42887e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END: 42896f61fd47SGustavo F. Padovan if (!chan->sdu) 429084084a31SMat Martineau break; 42910a708f8fSGustavo F. Padovan 429284084a31SMat Martineau append_skb_frag(chan->sdu, skb, 429384084a31SMat Martineau &chan->sdu_last_frag); 429484084a31SMat Martineau skb = NULL; 42950a708f8fSGustavo F. Padovan 429684084a31SMat Martineau if (chan->sdu->len != chan->sdu_len) 429784084a31SMat Martineau break; 42980a708f8fSGustavo F. Padovan 429984084a31SMat Martineau err = chan->ops->recv(chan->data, chan->sdu); 43000a708f8fSGustavo F. Padovan 430184084a31SMat Martineau if (!err) { 430284084a31SMat Martineau /* Reassembly complete */ 430384084a31SMat Martineau chan->sdu = NULL; 430484084a31SMat Martineau chan->sdu_last_frag = NULL; 430584084a31SMat Martineau chan->sdu_len = 0; 43060a708f8fSGustavo F. Padovan } 43070a708f8fSGustavo F. Padovan break; 43080a708f8fSGustavo F. Padovan } 43090a708f8fSGustavo F. Padovan 431084084a31SMat Martineau if (err) { 43110a708f8fSGustavo F. Padovan kfree_skb(skb); 43126f61fd47SGustavo F. Padovan kfree_skb(chan->sdu); 43136f61fd47SGustavo F. Padovan chan->sdu = NULL; 431484084a31SMat Martineau chan->sdu_last_frag = NULL; 431584084a31SMat Martineau chan->sdu_len = 0; 431684084a31SMat Martineau } 43170a708f8fSGustavo F. Padovan 431884084a31SMat Martineau return err; 43190a708f8fSGustavo F. Padovan } 43200a708f8fSGustavo F. Padovan 4321e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 43220a708f8fSGustavo F. Padovan { 432361aa4f5bSMat Martineau u8 event; 432461aa4f5bSMat Martineau 432561aa4f5bSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 432661aa4f5bSMat Martineau return; 432761aa4f5bSMat Martineau 432861aa4f5bSMat Martineau event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR; 432961aa4f5bSMat Martineau l2cap_tx(chan, 0, 0, event); 43300a708f8fSGustavo F. Padovan } 43310a708f8fSGustavo F. Padovan 43324b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) 43334b51dae9SMat Martineau { 43344b51dae9SMat Martineau BT_DBG("chan %p, txseq %d", chan, txseq); 43354b51dae9SMat Martineau 43364b51dae9SMat Martineau BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq, 43374b51dae9SMat Martineau chan->expected_tx_seq); 43384b51dae9SMat Martineau 43394b51dae9SMat Martineau if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { 43404b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 43414b51dae9SMat Martineau chan->tx_win) { 43424b51dae9SMat Martineau /* See notes below regarding "double poll" and 43434b51dae9SMat Martineau * invalid packets. 43444b51dae9SMat Martineau */ 43454b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 43464b51dae9SMat Martineau BT_DBG("Invalid/Ignore - after SREJ"); 43474b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 43484b51dae9SMat Martineau } else { 43494b51dae9SMat Martineau BT_DBG("Invalid - in window after SREJ sent"); 43504b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 43514b51dae9SMat Martineau } 43524b51dae9SMat Martineau } 43534b51dae9SMat Martineau 43544b51dae9SMat Martineau if (chan->srej_list.head == txseq) { 43554b51dae9SMat Martineau BT_DBG("Expected SREJ"); 43564b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED_SREJ; 43574b51dae9SMat Martineau } 43584b51dae9SMat Martineau 43594b51dae9SMat Martineau if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) { 43604b51dae9SMat Martineau BT_DBG("Duplicate SREJ - txseq already stored"); 43614b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE_SREJ; 43624b51dae9SMat Martineau } 43634b51dae9SMat Martineau 43644b51dae9SMat Martineau if (l2cap_seq_list_contains(&chan->srej_list, txseq)) { 43654b51dae9SMat Martineau BT_DBG("Unexpected SREJ - not requested"); 43664b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED_SREJ; 43674b51dae9SMat Martineau } 43684b51dae9SMat Martineau } 43694b51dae9SMat Martineau 43704b51dae9SMat Martineau if (chan->expected_tx_seq == txseq) { 43714b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= 43724b51dae9SMat Martineau chan->tx_win) { 43734b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 43744b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 43754b51dae9SMat Martineau } else { 43764b51dae9SMat Martineau BT_DBG("Expected"); 43774b51dae9SMat Martineau return L2CAP_TXSEQ_EXPECTED; 43784b51dae9SMat Martineau } 43794b51dae9SMat Martineau } 43804b51dae9SMat Martineau 43814b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) < 43824b51dae9SMat Martineau __seq_offset(chan, chan->expected_tx_seq, 43834b51dae9SMat Martineau chan->last_acked_seq)){ 43844b51dae9SMat Martineau BT_DBG("Duplicate - expected_tx_seq later than txseq"); 43854b51dae9SMat Martineau return L2CAP_TXSEQ_DUPLICATE; 43864b51dae9SMat Martineau } 43874b51dae9SMat Martineau 43884b51dae9SMat Martineau if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) { 43894b51dae9SMat Martineau /* A source of invalid packets is a "double poll" condition, 43904b51dae9SMat Martineau * where delays cause us to send multiple poll packets. If 43914b51dae9SMat Martineau * the remote stack receives and processes both polls, 43924b51dae9SMat Martineau * sequence numbers can wrap around in such a way that a 43934b51dae9SMat Martineau * resent frame has a sequence number that looks like new data 43944b51dae9SMat Martineau * with a sequence gap. This would trigger an erroneous SREJ 43954b51dae9SMat Martineau * request. 43964b51dae9SMat Martineau * 43974b51dae9SMat Martineau * Fortunately, this is impossible with a tx window that's 43984b51dae9SMat Martineau * less than half of the maximum sequence number, which allows 43994b51dae9SMat Martineau * invalid frames to be safely ignored. 44004b51dae9SMat Martineau * 44014b51dae9SMat Martineau * With tx window sizes greater than half of the tx window 44024b51dae9SMat Martineau * maximum, the frame is invalid and cannot be ignored. This 44034b51dae9SMat Martineau * causes a disconnect. 44044b51dae9SMat Martineau */ 44054b51dae9SMat Martineau 44064b51dae9SMat Martineau if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { 44074b51dae9SMat Martineau BT_DBG("Invalid/Ignore - txseq outside tx window"); 44084b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID_IGNORE; 44094b51dae9SMat Martineau } else { 44104b51dae9SMat Martineau BT_DBG("Invalid - txseq outside tx window"); 44114b51dae9SMat Martineau return L2CAP_TXSEQ_INVALID; 44124b51dae9SMat Martineau } 44134b51dae9SMat Martineau } else { 44144b51dae9SMat Martineau BT_DBG("Unexpected - txseq indicates missing frames"); 44154b51dae9SMat Martineau return L2CAP_TXSEQ_UNEXPECTED; 44164b51dae9SMat Martineau } 44174b51dae9SMat Martineau } 44184b51dae9SMat Martineau 4419cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 4420cec8ab6eSMat Martineau struct sk_buff *skb, u8 event) 44210a708f8fSGustavo F. Padovan { 4422cec8ab6eSMat Martineau /* Placeholder */ 4423cec8ab6eSMat Martineau return -ENOTSUPP; 4424cec8ab6eSMat Martineau } 4425cec8ab6eSMat Martineau 4426cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, 4427cec8ab6eSMat Martineau struct sk_buff *skb) 4428cec8ab6eSMat Martineau { 44294b51dae9SMat Martineau int err = 0; 44304b51dae9SMat Martineau 44314b51dae9SMat Martineau BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb, 44324b51dae9SMat Martineau chan->rx_state); 44334b51dae9SMat Martineau 44344b51dae9SMat Martineau if (l2cap_classify_txseq(chan, control->txseq) == 44354b51dae9SMat Martineau L2CAP_TXSEQ_EXPECTED) { 44364b51dae9SMat Martineau l2cap_pass_to_tx(chan, control); 44374b51dae9SMat Martineau 44384b51dae9SMat Martineau BT_DBG("buffer_seq %d->%d", chan->buffer_seq, 44394b51dae9SMat Martineau __next_seq(chan, chan->buffer_seq)); 44404b51dae9SMat Martineau 44414b51dae9SMat Martineau chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 44424b51dae9SMat Martineau 44434b51dae9SMat Martineau l2cap_reassemble_sdu(chan, skb, control); 44444b51dae9SMat Martineau } else { 44454b51dae9SMat Martineau if (chan->sdu) { 44464b51dae9SMat Martineau kfree_skb(chan->sdu); 44474b51dae9SMat Martineau chan->sdu = NULL; 44484b51dae9SMat Martineau } 44494b51dae9SMat Martineau chan->sdu_last_frag = NULL; 44504b51dae9SMat Martineau chan->sdu_len = 0; 44514b51dae9SMat Martineau 44524b51dae9SMat Martineau if (skb) { 44534b51dae9SMat Martineau BT_DBG("Freeing %p", skb); 44544b51dae9SMat Martineau kfree_skb(skb); 44554b51dae9SMat Martineau } 44564b51dae9SMat Martineau } 44574b51dae9SMat Martineau 44584b51dae9SMat Martineau chan->last_acked_seq = control->txseq; 44594b51dae9SMat Martineau chan->expected_tx_seq = __next_seq(chan, control->txseq); 44604b51dae9SMat Martineau 44614b51dae9SMat Martineau return err; 4462cec8ab6eSMat Martineau } 4463cec8ab6eSMat Martineau 4464cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 4465cec8ab6eSMat Martineau { 4466cec8ab6eSMat Martineau struct l2cap_ctrl *control = &bt_cb(skb)->control; 4467cec8ab6eSMat Martineau u16 len; 4468cec8ab6eSMat Martineau u8 event; 44690a708f8fSGustavo F. Padovan 4470b76bbd66SMat Martineau __unpack_control(chan, skb); 4471b76bbd66SMat Martineau 44720a708f8fSGustavo F. Padovan len = skb->len; 44730a708f8fSGustavo F. Padovan 44740a708f8fSGustavo F. Padovan /* 44750a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here. 44760a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery 4477cec8ab6eSMat Martineau * procedures and ask for retransmission. 44780a708f8fSGustavo F. Padovan */ 447947d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 44800a708f8fSGustavo F. Padovan goto drop; 44810a708f8fSGustavo F. Padovan 4482cec8ab6eSMat Martineau if (!control->sframe && control->sar == L2CAP_SAR_START) 448303a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 44840a708f8fSGustavo F. Padovan 448547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 448603a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 44870a708f8fSGustavo F. Padovan 448847d1ec61SGustavo F. Padovan if (len > chan->mps) { 44898c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 44900a708f8fSGustavo F. Padovan goto drop; 44910a708f8fSGustavo F. Padovan } 44920a708f8fSGustavo F. Padovan 4493cec8ab6eSMat Martineau if (!control->sframe) { 4494cec8ab6eSMat Martineau int err; 44950a708f8fSGustavo F. Padovan 4496cec8ab6eSMat Martineau BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d", 4497cec8ab6eSMat Martineau control->sar, control->reqseq, control->final, 4498cec8ab6eSMat Martineau control->txseq); 4499836be934SAndrei Emeltchenko 4500cec8ab6eSMat Martineau /* Validate F-bit - F=0 always valid, F=1 only 4501cec8ab6eSMat Martineau * valid in TX WAIT_F 4502cec8ab6eSMat Martineau */ 4503cec8ab6eSMat Martineau if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F) 45040a708f8fSGustavo F. Padovan goto drop; 45050a708f8fSGustavo F. Padovan 4506cec8ab6eSMat Martineau if (chan->mode != L2CAP_MODE_STREAMING) { 4507cec8ab6eSMat Martineau event = L2CAP_EV_RECV_IFRAME; 4508cec8ab6eSMat Martineau err = l2cap_rx(chan, control, skb, event); 45090a708f8fSGustavo F. Padovan } else { 4510cec8ab6eSMat Martineau err = l2cap_stream_rx(chan, control, skb); 4511cec8ab6eSMat Martineau } 4512cec8ab6eSMat Martineau 4513cec8ab6eSMat Martineau if (err) 4514cec8ab6eSMat Martineau l2cap_send_disconn_req(chan->conn, chan, 4515cec8ab6eSMat Martineau ECONNRESET); 4516cec8ab6eSMat Martineau } else { 4517cec8ab6eSMat Martineau const u8 rx_func_to_event[4] = { 4518cec8ab6eSMat Martineau L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ, 4519cec8ab6eSMat Martineau L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ 4520cec8ab6eSMat Martineau }; 4521cec8ab6eSMat Martineau 4522cec8ab6eSMat Martineau /* Only I-frames are expected in streaming mode */ 4523cec8ab6eSMat Martineau if (chan->mode == L2CAP_MODE_STREAMING) 4524cec8ab6eSMat Martineau goto drop; 4525cec8ab6eSMat Martineau 4526cec8ab6eSMat Martineau BT_DBG("sframe reqseq %d, final %d, poll %d, super %d", 4527cec8ab6eSMat Martineau control->reqseq, control->final, control->poll, 4528cec8ab6eSMat Martineau control->super); 4529cec8ab6eSMat Martineau 45300a708f8fSGustavo F. Padovan if (len != 0) { 45310a708f8fSGustavo F. Padovan BT_ERR("%d", len); 45328c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 45330a708f8fSGustavo F. Padovan goto drop; 45340a708f8fSGustavo F. Padovan } 45350a708f8fSGustavo F. Padovan 4536cec8ab6eSMat Martineau /* Validate F and P bits */ 4537cec8ab6eSMat Martineau if (control->final && (control->poll || 4538cec8ab6eSMat Martineau chan->tx_state != L2CAP_TX_STATE_WAIT_F)) 4539cec8ab6eSMat Martineau goto drop; 4540cec8ab6eSMat Martineau 4541cec8ab6eSMat Martineau event = rx_func_to_event[control->super]; 4542cec8ab6eSMat Martineau if (l2cap_rx(chan, control, skb, event)) 4543cec8ab6eSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 45440a708f8fSGustavo F. Padovan } 45450a708f8fSGustavo F. Padovan 45460a708f8fSGustavo F. Padovan return 0; 45470a708f8fSGustavo F. Padovan 45480a708f8fSGustavo F. Padovan drop: 45490a708f8fSGustavo F. Padovan kfree_skb(skb); 45500a708f8fSGustavo F. Padovan return 0; 45510a708f8fSGustavo F. Padovan } 45520a708f8fSGustavo F. Padovan 45530a708f8fSGustavo F. Padovan static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb) 45540a708f8fSGustavo F. Padovan { 455548454079SGustavo F. Padovan struct l2cap_chan *chan; 45560a708f8fSGustavo F. Padovan 4557baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 455848454079SGustavo F. Padovan if (!chan) { 45590a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid); 45606be36555SAndrei Emeltchenko /* Drop packet and return */ 45613379013bSDan Carpenter kfree_skb(skb); 45626be36555SAndrei Emeltchenko return 0; 45630a708f8fSGustavo F. Padovan } 45640a708f8fSGustavo F. Padovan 456549208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len); 45660a708f8fSGustavo F. Padovan 456789bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 45680a708f8fSGustavo F. Padovan goto drop; 45690a708f8fSGustavo F. Padovan 45700c1bc5c6SGustavo F. Padovan switch (chan->mode) { 45710a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 45720a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here 45730a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable. 45740a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't 45750a708f8fSGustavo F. Padovan * provide flow control mechanism. */ 45760a708f8fSGustavo F. Padovan 45770c1bc5c6SGustavo F. Padovan if (chan->imtu < skb->len) 45780a708f8fSGustavo F. Padovan goto drop; 45790a708f8fSGustavo F. Padovan 458023070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 45810a708f8fSGustavo F. Padovan goto done; 45820a708f8fSGustavo F. Padovan break; 45830a708f8fSGustavo F. Padovan 45840a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 45850a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 4586cec8ab6eSMat Martineau l2cap_data_rcv(chan, skb); 45870a708f8fSGustavo F. Padovan goto done; 45880a708f8fSGustavo F. Padovan 45890a708f8fSGustavo F. Padovan default: 45900c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); 45910a708f8fSGustavo F. Padovan break; 45920a708f8fSGustavo F. Padovan } 45930a708f8fSGustavo F. Padovan 45940a708f8fSGustavo F. Padovan drop: 45950a708f8fSGustavo F. Padovan kfree_skb(skb); 45960a708f8fSGustavo F. Padovan 45970a708f8fSGustavo F. Padovan done: 45986be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 45990a708f8fSGustavo F. Padovan 46000a708f8fSGustavo F. Padovan return 0; 46010a708f8fSGustavo F. Padovan } 46020a708f8fSGustavo F. Padovan 46030a708f8fSGustavo F. Padovan static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb) 46040a708f8fSGustavo F. Padovan { 460523691d75SGustavo F. Padovan struct l2cap_chan *chan; 46060a708f8fSGustavo F. Padovan 4607c2287681SIdo Yariv chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst); 460823691d75SGustavo F. Padovan if (!chan) 46090a708f8fSGustavo F. Padovan goto drop; 46100a708f8fSGustavo F. Padovan 46115b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 46120a708f8fSGustavo F. Padovan 461389bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 46140a708f8fSGustavo F. Padovan goto drop; 46150a708f8fSGustavo F. Padovan 4616e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 46170a708f8fSGustavo F. Padovan goto drop; 46180a708f8fSGustavo F. Padovan 461923070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 46205b4cedaaSAndrei Emeltchenko return 0; 46210a708f8fSGustavo F. Padovan 46220a708f8fSGustavo F. Padovan drop: 46230a708f8fSGustavo F. Padovan kfree_skb(skb); 46240a708f8fSGustavo F. Padovan 46250a708f8fSGustavo F. Padovan return 0; 46260a708f8fSGustavo F. Padovan } 46270a708f8fSGustavo F. Padovan 4628d9b88702SAndrei Emeltchenko static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid, 4629d9b88702SAndrei Emeltchenko struct sk_buff *skb) 46309f69bda6SGustavo F. Padovan { 463123691d75SGustavo F. Padovan struct l2cap_chan *chan; 46329f69bda6SGustavo F. Padovan 4633c2287681SIdo Yariv chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst); 463423691d75SGustavo F. Padovan if (!chan) 46359f69bda6SGustavo F. Padovan goto drop; 46369f69bda6SGustavo F. Padovan 46375b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 46389f69bda6SGustavo F. Padovan 463989bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 46409f69bda6SGustavo F. Padovan goto drop; 46419f69bda6SGustavo F. Padovan 4642e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 46439f69bda6SGustavo F. Padovan goto drop; 46449f69bda6SGustavo F. Padovan 464523070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 46465b4cedaaSAndrei Emeltchenko return 0; 46479f69bda6SGustavo F. Padovan 46489f69bda6SGustavo F. Padovan drop: 46499f69bda6SGustavo F. Padovan kfree_skb(skb); 46509f69bda6SGustavo F. Padovan 46519f69bda6SGustavo F. Padovan return 0; 46529f69bda6SGustavo F. Padovan } 46539f69bda6SGustavo F. Padovan 46540a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) 46550a708f8fSGustavo F. Padovan { 46560a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data; 46570a708f8fSGustavo F. Padovan u16 cid, len; 46580a708f8fSGustavo F. Padovan __le16 psm; 46590a708f8fSGustavo F. Padovan 46600a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE); 46610a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid); 46620a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len); 46630a708f8fSGustavo F. Padovan 46640a708f8fSGustavo F. Padovan if (len != skb->len) { 46650a708f8fSGustavo F. Padovan kfree_skb(skb); 46660a708f8fSGustavo F. Padovan return; 46670a708f8fSGustavo F. Padovan } 46680a708f8fSGustavo F. Padovan 46690a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid); 46700a708f8fSGustavo F. Padovan 46710a708f8fSGustavo F. Padovan switch (cid) { 46723300d9a9SClaudio Takahasi case L2CAP_CID_LE_SIGNALING: 46730a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING: 46740a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb); 46750a708f8fSGustavo F. Padovan break; 46760a708f8fSGustavo F. Padovan 46770a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS: 4678097db76cSAndrei Emeltchenko psm = get_unaligned((__le16 *) skb->data); 46790a708f8fSGustavo F. Padovan skb_pull(skb, 2); 46800a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb); 46810a708f8fSGustavo F. Padovan break; 46820a708f8fSGustavo F. Padovan 46839f69bda6SGustavo F. Padovan case L2CAP_CID_LE_DATA: 46849f69bda6SGustavo F. Padovan l2cap_att_channel(conn, cid, skb); 46859f69bda6SGustavo F. Padovan break; 46869f69bda6SGustavo F. Padovan 4687b501d6a1SAnderson Briglia case L2CAP_CID_SMP: 4688b501d6a1SAnderson Briglia if (smp_sig_channel(conn, skb)) 4689b501d6a1SAnderson Briglia l2cap_conn_del(conn->hcon, EACCES); 4690b501d6a1SAnderson Briglia break; 4691b501d6a1SAnderson Briglia 46920a708f8fSGustavo F. Padovan default: 46930a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb); 46940a708f8fSGustavo F. Padovan break; 46950a708f8fSGustavo F. Padovan } 46960a708f8fSGustavo F. Padovan } 46970a708f8fSGustavo F. Padovan 46980a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */ 46990a708f8fSGustavo F. Padovan 4700686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) 47010a708f8fSGustavo F. Padovan { 47020a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0; 470323691d75SGustavo F. Padovan struct l2cap_chan *c; 47040a708f8fSGustavo F. Padovan 47050a708f8fSGustavo F. Padovan BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); 47060a708f8fSGustavo F. Padovan 47070a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */ 470823691d75SGustavo F. Padovan read_lock(&chan_list_lock); 470923691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 471023691d75SGustavo F. Padovan struct sock *sk = c->sk; 47114343478fSGustavo F. Padovan 471289bc500eSGustavo F. Padovan if (c->state != BT_LISTEN) 47130a708f8fSGustavo F. Padovan continue; 47140a708f8fSGustavo F. Padovan 47150a708f8fSGustavo F. Padovan if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { 47160a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT; 471743bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 47180a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER; 47190a708f8fSGustavo F. Padovan exact++; 47200a708f8fSGustavo F. Padovan } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { 47210a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT; 472243bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 47230a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER; 47240a708f8fSGustavo F. Padovan } 47250a708f8fSGustavo F. Padovan } 472623691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 47270a708f8fSGustavo F. Padovan 47280a708f8fSGustavo F. Padovan return exact ? lm1 : lm2; 47290a708f8fSGustavo F. Padovan } 47300a708f8fSGustavo F. Padovan 4731686ebf28SUlisses Furquim int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) 47320a708f8fSGustavo F. Padovan { 47330a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 47340a708f8fSGustavo F. Padovan 47350a708f8fSGustavo F. Padovan BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); 47360a708f8fSGustavo F. Padovan 47370a708f8fSGustavo F. Padovan if (!status) { 47380a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, status); 47390a708f8fSGustavo F. Padovan if (conn) 47400a708f8fSGustavo F. Padovan l2cap_conn_ready(conn); 47410a708f8fSGustavo F. Padovan } else 4742e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status)); 47430a708f8fSGustavo F. Padovan 47440a708f8fSGustavo F. Padovan return 0; 47450a708f8fSGustavo F. Padovan } 47460a708f8fSGustavo F. Padovan 4747686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon) 47480a708f8fSGustavo F. Padovan { 47490a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 47500a708f8fSGustavo F. Padovan 47510a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon); 47520a708f8fSGustavo F. Padovan 4753686ebf28SUlisses Furquim if (!conn) 47549f5a0d7bSAndrei Emeltchenko return HCI_ERROR_REMOTE_USER_TERM; 47550a708f8fSGustavo F. Padovan return conn->disc_reason; 47560a708f8fSGustavo F. Padovan } 47570a708f8fSGustavo F. Padovan 4758686ebf28SUlisses Furquim int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) 47590a708f8fSGustavo F. Padovan { 47600a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason); 47610a708f8fSGustavo F. Padovan 4762e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason)); 47630a708f8fSGustavo F. Padovan return 0; 47640a708f8fSGustavo F. Padovan } 47650a708f8fSGustavo F. Padovan 47664343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) 47670a708f8fSGustavo F. Padovan { 4768715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 47690a708f8fSGustavo F. Padovan return; 47700a708f8fSGustavo F. Padovan 47710a708f8fSGustavo F. Padovan if (encrypt == 0x00) { 47724343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) { 4773ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); 47744343478fSGustavo F. Padovan } else if (chan->sec_level == BT_SECURITY_HIGH) 47750f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED); 47760a708f8fSGustavo F. Padovan } else { 47774343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) 4778c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 47790a708f8fSGustavo F. Padovan } 47800a708f8fSGustavo F. Padovan } 47810a708f8fSGustavo F. Padovan 4782686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) 47830a708f8fSGustavo F. Padovan { 47840a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 478548454079SGustavo F. Padovan struct l2cap_chan *chan; 47860a708f8fSGustavo F. Padovan 47870a708f8fSGustavo F. Padovan if (!conn) 47880a708f8fSGustavo F. Padovan return 0; 47890a708f8fSGustavo F. Padovan 47900a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 47910a708f8fSGustavo F. Padovan 4792160dc6acSVinicius Costa Gomes if (hcon->type == LE_LINK) { 479335d4adccSHemant Gupta if (!status && encrypt) 4794160dc6acSVinicius Costa Gomes smp_distribute_keys(conn, 0); 479517cd3f37SUlisses Furquim cancel_delayed_work(&conn->security_timer); 4796160dc6acSVinicius Costa Gomes } 4797160dc6acSVinicius Costa Gomes 47983df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 47990a708f8fSGustavo F. Padovan 48003df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 48016be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 48020a708f8fSGustavo F. Padovan 4803f1cb9af5SVinicius Costa Gomes BT_DBG("chan->scid %d", chan->scid); 4804f1cb9af5SVinicius Costa Gomes 4805f1cb9af5SVinicius Costa Gomes if (chan->scid == L2CAP_CID_LE_DATA) { 4806f1cb9af5SVinicius Costa Gomes if (!status && encrypt) { 4807f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level; 4808cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 4809f1cb9af5SVinicius Costa Gomes } 4810f1cb9af5SVinicius Costa Gomes 48116be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 4812f1cb9af5SVinicius Costa Gomes continue; 4813f1cb9af5SVinicius Costa Gomes } 4814f1cb9af5SVinicius Costa Gomes 4815c1360a1cSGustavo F. Padovan if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) { 48166be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 48170a708f8fSGustavo F. Padovan continue; 48180a708f8fSGustavo F. Padovan } 48190a708f8fSGustavo F. Padovan 482089bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED || 482189bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) { 4822a7d7723aSGustavo Padovan struct sock *sk = chan->sk; 4823a7d7723aSGustavo Padovan 4824c5daa683SGustavo Padovan clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); 4825a7d7723aSGustavo Padovan sk->sk_state_change(sk); 4826a7d7723aSGustavo Padovan 48274343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt); 48286be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 48290a708f8fSGustavo F. Padovan continue; 48300a708f8fSGustavo F. Padovan } 48310a708f8fSGustavo F. Padovan 483289bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 48330a708f8fSGustavo F. Padovan if (!status) { 48349b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 48350a708f8fSGustavo F. Padovan } else { 4836ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 48370a708f8fSGustavo F. Padovan } 483889bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 48396be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 48400a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 4841df3c3931SJohan Hedberg __u16 res, stat; 48420a708f8fSGustavo F. Padovan 48436be36555SAndrei Emeltchenko lock_sock(sk); 48446be36555SAndrei Emeltchenko 48450a708f8fSGustavo F. Padovan if (!status) { 4846c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, 4847c5daa683SGustavo Padovan &bt_sk(sk)->flags)) { 4848df3c3931SJohan Hedberg struct sock *parent = bt_sk(sk)->parent; 4849df3c3931SJohan Hedberg res = L2CAP_CR_PEND; 4850df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND; 485105e9a2f6SIlia Kolomisnky if (parent) 4852df3c3931SJohan Hedberg parent->sk_data_ready(parent, 0); 4853df3c3931SJohan Hedberg } else { 48540e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 4855df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS; 4856df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 4857df3c3931SJohan Hedberg } 48580a708f8fSGustavo F. Padovan } else { 48590e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_DISCONN); 4860ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 4861df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK; 4862df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 48630a708f8fSGustavo F. Padovan } 48640a708f8fSGustavo F. Padovan 48656be36555SAndrei Emeltchenko release_sock(sk); 48666be36555SAndrei Emeltchenko 4867fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 4868fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 4869df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res); 4870df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat); 4871fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 4872fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 48730a708f8fSGustavo F. Padovan } 48740a708f8fSGustavo F. Padovan 48756be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 48760a708f8fSGustavo F. Padovan } 48770a708f8fSGustavo F. Padovan 48783df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 48790a708f8fSGustavo F. Padovan 48800a708f8fSGustavo F. Padovan return 0; 48810a708f8fSGustavo F. Padovan } 48820a708f8fSGustavo F. Padovan 4883686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) 48840a708f8fSGustavo F. Padovan { 48850a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 48860a708f8fSGustavo F. Padovan 48870a708f8fSGustavo F. Padovan if (!conn) 48880a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, 0); 48890a708f8fSGustavo F. Padovan 48900a708f8fSGustavo F. Padovan if (!conn) 48910a708f8fSGustavo F. Padovan goto drop; 48920a708f8fSGustavo F. Padovan 48930a708f8fSGustavo F. Padovan BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); 48940a708f8fSGustavo F. Padovan 48950a708f8fSGustavo F. Padovan if (!(flags & ACL_CONT)) { 48960a708f8fSGustavo F. Padovan struct l2cap_hdr *hdr; 48970a708f8fSGustavo F. Padovan int len; 48980a708f8fSGustavo F. Padovan 48990a708f8fSGustavo F. Padovan if (conn->rx_len) { 49000a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len); 49010a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 49020a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 49030a708f8fSGustavo F. Padovan conn->rx_len = 0; 49040a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 49050a708f8fSGustavo F. Padovan } 49060a708f8fSGustavo F. Padovan 49070a708f8fSGustavo F. Padovan /* Start fragment always begin with Basic L2CAP header */ 49080a708f8fSGustavo F. Padovan if (skb->len < L2CAP_HDR_SIZE) { 49090a708f8fSGustavo F. Padovan BT_ERR("Frame is too short (len %d)", skb->len); 49100a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 49110a708f8fSGustavo F. Padovan goto drop; 49120a708f8fSGustavo F. Padovan } 49130a708f8fSGustavo F. Padovan 49140a708f8fSGustavo F. Padovan hdr = (struct l2cap_hdr *) skb->data; 49150a708f8fSGustavo F. Padovan len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; 49160a708f8fSGustavo F. Padovan 49170a708f8fSGustavo F. Padovan if (len == skb->len) { 49180a708f8fSGustavo F. Padovan /* Complete frame received */ 49190a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb); 49200a708f8fSGustavo F. Padovan return 0; 49210a708f8fSGustavo F. Padovan } 49220a708f8fSGustavo F. Padovan 49230a708f8fSGustavo F. Padovan BT_DBG("Start: total len %d, frag len %d", len, skb->len); 49240a708f8fSGustavo F. Padovan 49250a708f8fSGustavo F. Padovan if (skb->len > len) { 49260a708f8fSGustavo F. Padovan BT_ERR("Frame is too long (len %d, expected len %d)", 49270a708f8fSGustavo F. Padovan skb->len, len); 49280a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 49290a708f8fSGustavo F. Padovan goto drop; 49300a708f8fSGustavo F. Padovan } 49310a708f8fSGustavo F. Padovan 49320a708f8fSGustavo F. Padovan /* Allocate skb for the complete frame (with header) */ 49330a708f8fSGustavo F. Padovan conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC); 49340a708f8fSGustavo F. Padovan if (!conn->rx_skb) 49350a708f8fSGustavo F. Padovan goto drop; 49360a708f8fSGustavo F. Padovan 49370a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 49380a708f8fSGustavo F. Padovan skb->len); 49390a708f8fSGustavo F. Padovan conn->rx_len = len - skb->len; 49400a708f8fSGustavo F. Padovan } else { 49410a708f8fSGustavo F. Padovan BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); 49420a708f8fSGustavo F. Padovan 49430a708f8fSGustavo F. Padovan if (!conn->rx_len) { 49440a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len); 49450a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 49460a708f8fSGustavo F. Padovan goto drop; 49470a708f8fSGustavo F. Padovan } 49480a708f8fSGustavo F. Padovan 49490a708f8fSGustavo F. Padovan if (skb->len > conn->rx_len) { 49500a708f8fSGustavo F. Padovan BT_ERR("Fragment is too long (len %d, expected %d)", 49510a708f8fSGustavo F. Padovan skb->len, conn->rx_len); 49520a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 49530a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 49540a708f8fSGustavo F. Padovan conn->rx_len = 0; 49550a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 49560a708f8fSGustavo F. Padovan goto drop; 49570a708f8fSGustavo F. Padovan } 49580a708f8fSGustavo F. Padovan 49590a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 49600a708f8fSGustavo F. Padovan skb->len); 49610a708f8fSGustavo F. Padovan conn->rx_len -= skb->len; 49620a708f8fSGustavo F. Padovan 49630a708f8fSGustavo F. Padovan if (!conn->rx_len) { 49640a708f8fSGustavo F. Padovan /* Complete frame received */ 49650a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, conn->rx_skb); 49660a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 49670a708f8fSGustavo F. Padovan } 49680a708f8fSGustavo F. Padovan } 49690a708f8fSGustavo F. Padovan 49700a708f8fSGustavo F. Padovan drop: 49710a708f8fSGustavo F. Padovan kfree_skb(skb); 49720a708f8fSGustavo F. Padovan return 0; 49730a708f8fSGustavo F. Padovan } 49740a708f8fSGustavo F. Padovan 49750a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p) 49760a708f8fSGustavo F. Padovan { 497723691d75SGustavo F. Padovan struct l2cap_chan *c; 49780a708f8fSGustavo F. Padovan 4979333055f2SGustavo F. Padovan read_lock(&chan_list_lock); 49800a708f8fSGustavo F. Padovan 498123691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 498223691d75SGustavo F. Padovan struct sock *sk = c->sk; 49830a708f8fSGustavo F. Padovan 4984903d343eSGustavo F. Padovan seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", 49850a708f8fSGustavo F. Padovan batostr(&bt_sk(sk)->src), 49860a708f8fSGustavo F. Padovan batostr(&bt_sk(sk)->dst), 498789bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm), 498823691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu, 498923691d75SGustavo F. Padovan c->sec_level, c->mode); 49900a708f8fSGustavo F. Padovan } 49910a708f8fSGustavo F. Padovan 4992333055f2SGustavo F. Padovan read_unlock(&chan_list_lock); 49930a708f8fSGustavo F. Padovan 49940a708f8fSGustavo F. Padovan return 0; 49950a708f8fSGustavo F. Padovan } 49960a708f8fSGustavo F. Padovan 49970a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file) 49980a708f8fSGustavo F. Padovan { 49990a708f8fSGustavo F. Padovan return single_open(file, l2cap_debugfs_show, inode->i_private); 50000a708f8fSGustavo F. Padovan } 50010a708f8fSGustavo F. Padovan 50020a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = { 50030a708f8fSGustavo F. Padovan .open = l2cap_debugfs_open, 50040a708f8fSGustavo F. Padovan .read = seq_read, 50050a708f8fSGustavo F. Padovan .llseek = seq_lseek, 50060a708f8fSGustavo F. Padovan .release = single_release, 50070a708f8fSGustavo F. Padovan }; 50080a708f8fSGustavo F. Padovan 50090a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs; 50100a708f8fSGustavo F. Padovan 501164274518SGustavo F. Padovan int __init l2cap_init(void) 50120a708f8fSGustavo F. Padovan { 50130a708f8fSGustavo F. Padovan int err; 50140a708f8fSGustavo F. Padovan 5015bb58f747SGustavo F. Padovan err = l2cap_init_sockets(); 50160a708f8fSGustavo F. Padovan if (err < 0) 50170a708f8fSGustavo F. Padovan return err; 50180a708f8fSGustavo F. Padovan 50190a708f8fSGustavo F. Padovan if (bt_debugfs) { 50200a708f8fSGustavo F. Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, 50210a708f8fSGustavo F. Padovan bt_debugfs, NULL, &l2cap_debugfs_fops); 50220a708f8fSGustavo F. Padovan if (!l2cap_debugfs) 50230a708f8fSGustavo F. Padovan BT_ERR("Failed to create L2CAP debug file"); 50240a708f8fSGustavo F. Padovan } 50250a708f8fSGustavo F. Padovan 50260a708f8fSGustavo F. Padovan return 0; 50270a708f8fSGustavo F. Padovan } 50280a708f8fSGustavo F. Padovan 502964274518SGustavo F. Padovan void l2cap_exit(void) 50300a708f8fSGustavo F. Padovan { 50310a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs); 5032bb58f747SGustavo F. Padovan l2cap_cleanup_sockets(); 50330a708f8fSGustavo F. Padovan } 50340a708f8fSGustavo F. Padovan 50350a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644); 50360a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); 5037