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 60eb939922SRusty Russell bool disable_ertm; 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 760a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */ 7771ba0e56SGustavo F. Padovan 78baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid) 790a708f8fSGustavo F. Padovan { 803df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 81baa7e1faSGustavo F. Padovan 823df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 833df91ea2SAndrei Emeltchenko if (c->dcid == cid) 843df91ea2SAndrei Emeltchenko return c; 850a708f8fSGustavo F. Padovan } 863df91ea2SAndrei Emeltchenko return NULL; 87baa7e1faSGustavo F. Padovan } 880a708f8fSGustavo F. Padovan 89baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) 900a708f8fSGustavo F. Padovan { 913df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 92baa7e1faSGustavo F. Padovan 933df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 943df91ea2SAndrei Emeltchenko if (c->scid == cid) 953df91ea2SAndrei Emeltchenko return c; 960a708f8fSGustavo F. Padovan } 973df91ea2SAndrei Emeltchenko return NULL; 98baa7e1faSGustavo F. Padovan } 990a708f8fSGustavo F. Padovan 1000a708f8fSGustavo F. Padovan /* Find channel with given SCID. 1010a708f8fSGustavo F. Padovan * Returns locked socket */ 102baa7e1faSGustavo F. Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) 1030a708f8fSGustavo F. Padovan { 10448454079SGustavo F. Padovan struct l2cap_chan *c; 105baa7e1faSGustavo F. Padovan 1063df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 107baa7e1faSGustavo F. Padovan c = __l2cap_get_chan_by_scid(conn, cid); 1083df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 1093df91ea2SAndrei Emeltchenko 11048454079SGustavo F. Padovan return c; 1110a708f8fSGustavo F. Padovan } 1120a708f8fSGustavo F. Padovan 113baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident) 1140a708f8fSGustavo F. Padovan { 1153df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 116baa7e1faSGustavo F. Padovan 1173df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 1183df91ea2SAndrei Emeltchenko if (c->ident == ident) 1193df91ea2SAndrei Emeltchenko return c; 1200a708f8fSGustavo F. Padovan } 1213df91ea2SAndrei Emeltchenko return NULL; 122baa7e1faSGustavo F. Padovan } 1230a708f8fSGustavo F. Padovan 12423691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src) 1259e4425ffSGustavo F. Padovan { 12623691d75SGustavo F. Padovan struct l2cap_chan *c; 1279e4425ffSGustavo F. Padovan 12823691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 12923691d75SGustavo F. Padovan if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src)) 13023691d75SGustavo F. Padovan return c; 1319e4425ffSGustavo F. Padovan } 132250938cbSSzymon Janc return NULL; 133250938cbSSzymon Janc } 1349e4425ffSGustavo F. Padovan 1359e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) 1369e4425ffSGustavo F. Padovan { 13773b2ec18SGustavo F. Padovan int err; 13873b2ec18SGustavo F. Padovan 139333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 1409e4425ffSGustavo F. Padovan 14123691d75SGustavo F. Padovan if (psm && __l2cap_global_chan_by_addr(psm, src)) { 14273b2ec18SGustavo F. Padovan err = -EADDRINUSE; 14373b2ec18SGustavo F. Padovan goto done; 1449e4425ffSGustavo F. Padovan } 1459e4425ffSGustavo F. Padovan 14673b2ec18SGustavo F. Padovan if (psm) { 1479e4425ffSGustavo F. Padovan chan->psm = psm; 1489e4425ffSGustavo F. Padovan chan->sport = psm; 14973b2ec18SGustavo F. Padovan err = 0; 15073b2ec18SGustavo F. Padovan } else { 15173b2ec18SGustavo F. Padovan u16 p; 1529e4425ffSGustavo F. Padovan 15373b2ec18SGustavo F. Padovan err = -EINVAL; 15473b2ec18SGustavo F. Padovan for (p = 0x1001; p < 0x1100; p += 2) 15523691d75SGustavo F. Padovan if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) { 15673b2ec18SGustavo F. Padovan chan->psm = cpu_to_le16(p); 15773b2ec18SGustavo F. Padovan chan->sport = cpu_to_le16(p); 15873b2ec18SGustavo F. Padovan err = 0; 15973b2ec18SGustavo F. Padovan break; 16073b2ec18SGustavo F. Padovan } 16173b2ec18SGustavo F. Padovan } 16273b2ec18SGustavo F. Padovan 16373b2ec18SGustavo F. Padovan done: 164333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 16573b2ec18SGustavo F. Padovan return err; 1669e4425ffSGustavo F. Padovan } 1679e4425ffSGustavo F. Padovan 1689e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) 1699e4425ffSGustavo F. Padovan { 170333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 1719e4425ffSGustavo F. Padovan 1729e4425ffSGustavo F. Padovan chan->scid = scid; 1739e4425ffSGustavo F. Padovan 174333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 1759e4425ffSGustavo F. Padovan 1769e4425ffSGustavo F. Padovan return 0; 1779e4425ffSGustavo F. Padovan } 1789e4425ffSGustavo F. Padovan 179baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn) 1800a708f8fSGustavo F. Padovan { 1810a708f8fSGustavo F. Padovan u16 cid = L2CAP_CID_DYN_START; 1820a708f8fSGustavo F. Padovan 1830a708f8fSGustavo F. Padovan for (; cid < L2CAP_CID_DYN_END; cid++) { 184baa7e1faSGustavo F. Padovan if (!__l2cap_get_chan_by_scid(conn, cid)) 1850a708f8fSGustavo F. Padovan return cid; 1860a708f8fSGustavo F. Padovan } 1870a708f8fSGustavo F. Padovan 1880a708f8fSGustavo F. Padovan return 0; 1890a708f8fSGustavo F. Padovan } 1900a708f8fSGustavo F. Padovan 1910e587be7SAndrei Emeltchenko static void __l2cap_state_change(struct l2cap_chan *chan, int state) 19289bc500eSGustavo F. Padovan { 19342d2d87cSAndrei Emeltchenko BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state), 194badaaa00SGustavo F. Padovan state_to_string(state)); 195badaaa00SGustavo F. Padovan 19689bc500eSGustavo F. Padovan chan->state = state; 19789bc500eSGustavo F. Padovan chan->ops->state_change(chan->data, state); 19889bc500eSGustavo F. Padovan } 19989bc500eSGustavo F. Padovan 2000e587be7SAndrei Emeltchenko static void l2cap_state_change(struct l2cap_chan *chan, int state) 2010e587be7SAndrei Emeltchenko { 2020e587be7SAndrei Emeltchenko struct sock *sk = chan->sk; 2030e587be7SAndrei Emeltchenko 2040e587be7SAndrei Emeltchenko lock_sock(sk); 2050e587be7SAndrei Emeltchenko __l2cap_state_change(chan, state); 2060e587be7SAndrei Emeltchenko release_sock(sk); 2070e587be7SAndrei Emeltchenko } 2080e587be7SAndrei Emeltchenko 2092e0052e4SAndrei Emeltchenko static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err) 2102e0052e4SAndrei Emeltchenko { 2112e0052e4SAndrei Emeltchenko struct sock *sk = chan->sk; 2122e0052e4SAndrei Emeltchenko 2132e0052e4SAndrei Emeltchenko sk->sk_err = err; 2142e0052e4SAndrei Emeltchenko } 2152e0052e4SAndrei Emeltchenko 2162e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err) 2172e0052e4SAndrei Emeltchenko { 2182e0052e4SAndrei Emeltchenko struct sock *sk = chan->sk; 2192e0052e4SAndrei Emeltchenko 2202e0052e4SAndrei Emeltchenko lock_sock(sk); 2212e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 2222e0052e4SAndrei Emeltchenko release_sock(sk); 2232e0052e4SAndrei Emeltchenko } 2242e0052e4SAndrei Emeltchenko 2253c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */ 2263c588192SMat Martineau 2273c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for 2283c588192SMat Martineau * SREJ requests that are received and for frames that are to be 2293c588192SMat Martineau * retransmitted. These seq_list functions implement a singly-linked 2303c588192SMat Martineau * list in an array, where membership in the list can also be checked 2313c588192SMat Martineau * in constant time. Items can also be added to the tail of the list 2323c588192SMat Martineau * and removed from the head in constant time, without further memory 2333c588192SMat Martineau * allocs or frees. 2343c588192SMat Martineau */ 2353c588192SMat Martineau 2363c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size) 2373c588192SMat Martineau { 2383c588192SMat Martineau size_t alloc_size, i; 2393c588192SMat Martineau 2403c588192SMat Martineau /* Allocated size is a power of 2 to map sequence numbers 2413c588192SMat Martineau * (which may be up to 14 bits) in to a smaller array that is 2423c588192SMat Martineau * sized for the negotiated ERTM transmit windows. 2433c588192SMat Martineau */ 2443c588192SMat Martineau alloc_size = roundup_pow_of_two(size); 2453c588192SMat Martineau 2463c588192SMat Martineau seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL); 2473c588192SMat Martineau if (!seq_list->list) 2483c588192SMat Martineau return -ENOMEM; 2493c588192SMat Martineau 2503c588192SMat Martineau seq_list->mask = alloc_size - 1; 2513c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 2523c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 2533c588192SMat Martineau for (i = 0; i < alloc_size; i++) 2543c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 2553c588192SMat Martineau 2563c588192SMat Martineau return 0; 2573c588192SMat Martineau } 2583c588192SMat Martineau 2593c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list) 2603c588192SMat Martineau { 2613c588192SMat Martineau kfree(seq_list->list); 2623c588192SMat Martineau } 2633c588192SMat Martineau 2643c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list, 2653c588192SMat Martineau u16 seq) 2663c588192SMat Martineau { 2673c588192SMat Martineau /* Constant-time check for list membership */ 2683c588192SMat Martineau return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR; 2693c588192SMat Martineau } 2703c588192SMat Martineau 2713c588192SMat Martineau static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq) 2723c588192SMat Martineau { 2733c588192SMat Martineau u16 mask = seq_list->mask; 2743c588192SMat Martineau 2753c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) { 2763c588192SMat Martineau /* In case someone tries to pop the head of an empty list */ 2773c588192SMat Martineau return L2CAP_SEQ_LIST_CLEAR; 2783c588192SMat Martineau } else if (seq_list->head == seq) { 2793c588192SMat Martineau /* Head can be removed in constant time */ 2803c588192SMat Martineau seq_list->head = seq_list->list[seq & mask]; 2813c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; 2823c588192SMat Martineau 2833c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_TAIL) { 2843c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 2853c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 2863c588192SMat Martineau } 2873c588192SMat Martineau } else { 2883c588192SMat Martineau /* Walk the list to find the sequence number */ 2893c588192SMat Martineau u16 prev = seq_list->head; 2903c588192SMat Martineau while (seq_list->list[prev & mask] != seq) { 2913c588192SMat Martineau prev = seq_list->list[prev & mask]; 2923c588192SMat Martineau if (prev == L2CAP_SEQ_LIST_TAIL) 2933c588192SMat Martineau return L2CAP_SEQ_LIST_CLEAR; 2943c588192SMat Martineau } 2953c588192SMat Martineau 2963c588192SMat Martineau /* Unlink the number from the list and clear it */ 2973c588192SMat Martineau seq_list->list[prev & mask] = seq_list->list[seq & mask]; 2983c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; 2993c588192SMat Martineau if (seq_list->tail == seq) 3003c588192SMat Martineau seq_list->tail = prev; 3013c588192SMat Martineau } 3023c588192SMat Martineau return seq; 3033c588192SMat Martineau } 3043c588192SMat Martineau 3053c588192SMat Martineau static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list) 3063c588192SMat Martineau { 3073c588192SMat Martineau /* Remove the head in constant time */ 3083c588192SMat Martineau return l2cap_seq_list_remove(seq_list, seq_list->head); 3093c588192SMat Martineau } 3103c588192SMat Martineau 3113c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list) 3123c588192SMat Martineau { 3133c588192SMat Martineau if (seq_list->head != L2CAP_SEQ_LIST_CLEAR) { 3143c588192SMat Martineau u16 i; 3153c588192SMat Martineau for (i = 0; i <= seq_list->mask; i++) 3163c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 3173c588192SMat Martineau 3183c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3193c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3203c588192SMat Martineau } 3213c588192SMat Martineau } 3223c588192SMat Martineau 3233c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq) 3243c588192SMat Martineau { 3253c588192SMat Martineau u16 mask = seq_list->mask; 3263c588192SMat Martineau 3273c588192SMat Martineau /* All appends happen in constant time */ 3283c588192SMat Martineau 3293c588192SMat Martineau if (seq_list->list[seq & mask] == L2CAP_SEQ_LIST_CLEAR) { 3303c588192SMat Martineau if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR) 3313c588192SMat Martineau seq_list->head = seq; 3323c588192SMat Martineau else 3333c588192SMat Martineau seq_list->list[seq_list->tail & mask] = seq; 3343c588192SMat Martineau 3353c588192SMat Martineau seq_list->tail = seq; 3363c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL; 3373c588192SMat Martineau } 3383c588192SMat Martineau } 3393c588192SMat Martineau 340721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work) 341ab07801dSGustavo F. Padovan { 342721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 343721c4181SGustavo F. Padovan chan_timer.work); 3443df91ea2SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 345ab07801dSGustavo F. Padovan int reason; 346ab07801dSGustavo F. Padovan 347e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 348ab07801dSGustavo F. Padovan 3493df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 3506be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 351ab07801dSGustavo F. Padovan 35289bc500eSGustavo F. Padovan if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) 353ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 35489bc500eSGustavo F. Padovan else if (chan->state == BT_CONNECT && 355ab07801dSGustavo F. Padovan chan->sec_level != BT_SECURITY_SDP) 356ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 357ab07801dSGustavo F. Padovan else 358ab07801dSGustavo F. Padovan reason = ETIMEDOUT; 359ab07801dSGustavo F. Padovan 3600f852724SGustavo F. Padovan l2cap_chan_close(chan, reason); 361ab07801dSGustavo F. Padovan 3626be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 363ab07801dSGustavo F. Padovan 364ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 3653df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 3663df91ea2SAndrei Emeltchenko 367371fd835SUlisses Furquim l2cap_chan_put(chan); 368ab07801dSGustavo F. Padovan } 369ab07801dSGustavo F. Padovan 370eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void) 3710a708f8fSGustavo F. Padovan { 37248454079SGustavo F. Padovan struct l2cap_chan *chan; 3730a708f8fSGustavo F. Padovan 37448454079SGustavo F. Padovan chan = kzalloc(sizeof(*chan), GFP_ATOMIC); 37548454079SGustavo F. Padovan if (!chan) 37648454079SGustavo F. Padovan return NULL; 3770a708f8fSGustavo F. Padovan 378c03b355eSAndrei Emeltchenko mutex_init(&chan->lock); 379c03b355eSAndrei Emeltchenko 380333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 38123691d75SGustavo F. Padovan list_add(&chan->global_l, &chan_list); 382333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 38323691d75SGustavo F. Padovan 384721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout); 385ab07801dSGustavo F. Padovan 38689bc500eSGustavo F. Padovan chan->state = BT_OPEN; 38789bc500eSGustavo F. Padovan 38871ba0e56SGustavo F. Padovan atomic_set(&chan->refcnt, 1); 38971ba0e56SGustavo F. Padovan 390eef1d9b6SGustavo Padovan BT_DBG("chan %p", chan); 391abc545b8SSzymon Janc 39248454079SGustavo F. Padovan return chan; 3930a708f8fSGustavo F. Padovan } 3940a708f8fSGustavo F. Padovan 39523691d75SGustavo F. Padovan void l2cap_chan_destroy(struct l2cap_chan *chan) 3966ff5abbfSGustavo F. Padovan { 397333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 39823691d75SGustavo F. Padovan list_del(&chan->global_l); 399333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 40023691d75SGustavo F. Padovan 401371fd835SUlisses Furquim l2cap_chan_put(chan); 4026ff5abbfSGustavo F. Padovan } 4036ff5abbfSGustavo F. Padovan 404bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan) 405bd4b1653SAndrei Emeltchenko { 406bd4b1653SAndrei Emeltchenko chan->fcs = L2CAP_FCS_CRC16; 407bd4b1653SAndrei Emeltchenko chan->max_tx = L2CAP_DEFAULT_MAX_TX; 408bd4b1653SAndrei Emeltchenko chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; 409bd4b1653SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 410bd4b1653SAndrei Emeltchenko chan->sec_level = BT_SECURITY_LOW; 411bd4b1653SAndrei Emeltchenko 412bd4b1653SAndrei Emeltchenko set_bit(FLAG_FORCE_ACTIVE, &chan->flags); 413bd4b1653SAndrei Emeltchenko } 414bd4b1653SAndrei Emeltchenko 41514a28491SAndrei Emeltchenko static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 4160a708f8fSGustavo F. Padovan { 4170a708f8fSGustavo F. Padovan BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, 418097db76cSAndrei Emeltchenko __le16_to_cpu(chan->psm), chan->dcid); 4190a708f8fSGustavo F. Padovan 4209f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 4210a708f8fSGustavo F. Padovan 4228c1d787bSGustavo F. Padovan chan->conn = conn; 4230a708f8fSGustavo F. Padovan 4245491120eSAndrei Emeltchenko switch (chan->chan_type) { 4255491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_ORIENTED: 426b62f328bSVille Tervo if (conn->hcon->type == LE_LINK) { 427b62f328bSVille Tervo /* LE connection */ 4280c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_LE_DEFAULT_MTU; 429fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_LE_DATA; 430fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_LE_DATA; 431b62f328bSVille Tervo } else { 4320a708f8fSGustavo F. Padovan /* Alloc CID for connection-oriented socket */ 433fe4128e0SGustavo F. Padovan chan->scid = l2cap_alloc_cid(conn); 4340c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 435b62f328bSVille Tervo } 4365491120eSAndrei Emeltchenko break; 4375491120eSAndrei Emeltchenko 4385491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_LESS: 4390a708f8fSGustavo F. Padovan /* Connectionless socket */ 440fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_CONN_LESS; 441fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_CONN_LESS; 4420c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 4435491120eSAndrei Emeltchenko break; 4445491120eSAndrei Emeltchenko 4455491120eSAndrei Emeltchenko default: 4460a708f8fSGustavo F. Padovan /* Raw socket can send/recv signalling messages only */ 447fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_SIGNALING; 448fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_SIGNALING; 4490c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 4500a708f8fSGustavo F. Padovan } 4510a708f8fSGustavo F. Padovan 4528f7975b1SAndrei Emeltchenko chan->local_id = L2CAP_BESTEFFORT_ID; 4538f7975b1SAndrei Emeltchenko chan->local_stype = L2CAP_SERV_BESTEFFORT; 4548f7975b1SAndrei Emeltchenko chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE; 4558f7975b1SAndrei Emeltchenko chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME; 4568f7975b1SAndrei Emeltchenko chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT; 4578f7975b1SAndrei Emeltchenko chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO; 4588f7975b1SAndrei Emeltchenko 459371fd835SUlisses Furquim l2cap_chan_hold(chan); 460baa7e1faSGustavo F. Padovan 4613df91ea2SAndrei Emeltchenko list_add(&chan->list, &conn->chan_l); 462643162a8SAndrei Emeltchenko } 463643162a8SAndrei Emeltchenko 46414a28491SAndrei Emeltchenko static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 465643162a8SAndrei Emeltchenko { 466643162a8SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 467643162a8SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 4683df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4690a708f8fSGustavo F. Padovan } 4700a708f8fSGustavo F. Padovan 4714519de9aSGustavo F. Padovan static void l2cap_chan_del(struct l2cap_chan *chan, int err) 4720a708f8fSGustavo F. Padovan { 47348454079SGustavo F. Padovan struct sock *sk = chan->sk; 4748c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 4750a708f8fSGustavo F. Padovan struct sock *parent = bt_sk(sk)->parent; 4760a708f8fSGustavo F. Padovan 477c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 4780a708f8fSGustavo F. Padovan 47949208c9cSGustavo F. Padovan BT_DBG("chan %p, conn %p, err %d", chan, conn, err); 4800a708f8fSGustavo F. Padovan 4810a708f8fSGustavo F. Padovan if (conn) { 482baa7e1faSGustavo F. Padovan /* Delete from channel list */ 4833df91ea2SAndrei Emeltchenko list_del(&chan->list); 4843d57dc68SGustavo F. Padovan 485371fd835SUlisses Furquim l2cap_chan_put(chan); 486baa7e1faSGustavo F. Padovan 4878c1d787bSGustavo F. Padovan chan->conn = NULL; 4880a708f8fSGustavo F. Padovan hci_conn_put(conn->hcon); 4890a708f8fSGustavo F. Padovan } 4900a708f8fSGustavo F. Padovan 4916be36555SAndrei Emeltchenko lock_sock(sk); 4926be36555SAndrei Emeltchenko 4930e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CLOSED); 4940a708f8fSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 4950a708f8fSGustavo F. Padovan 4960a708f8fSGustavo F. Padovan if (err) 4972e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 4980a708f8fSGustavo F. Padovan 4990a708f8fSGustavo F. Padovan if (parent) { 5000a708f8fSGustavo F. Padovan bt_accept_unlink(sk); 5010a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 5020a708f8fSGustavo F. Padovan } else 5030a708f8fSGustavo F. Padovan sk->sk_state_change(sk); 5040a708f8fSGustavo F. Padovan 5056be36555SAndrei Emeltchenko release_sock(sk); 5066be36555SAndrei Emeltchenko 507c1360a1cSGustavo F. Padovan if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) && 508c1360a1cSGustavo F. Padovan test_bit(CONF_INPUT_DONE, &chan->conf_state))) 5096ff5abbfSGustavo F. Padovan return; 5102ead70b8SGustavo F. Padovan 51158d35f87SGustavo F. Padovan skb_queue_purge(&chan->tx_q); 5120a708f8fSGustavo F. Padovan 5130c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_ERTM) { 5140a708f8fSGustavo F. Padovan struct srej_list *l, *tmp; 5150a708f8fSGustavo F. Padovan 5161a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 5171a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 5181a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 5190a708f8fSGustavo F. Padovan 520f1c6775bSGustavo F. Padovan skb_queue_purge(&chan->srej_q); 5210a708f8fSGustavo F. Padovan 5223c588192SMat Martineau l2cap_seq_list_free(&chan->srej_list); 5233c588192SMat Martineau l2cap_seq_list_free(&chan->retrans_list); 52439d5a3eeSGustavo F. Padovan list_for_each_entry_safe(l, tmp, &chan->srej_l, list) { 5250a708f8fSGustavo F. Padovan list_del(&l->list); 5260a708f8fSGustavo F. Padovan kfree(l); 5270a708f8fSGustavo F. Padovan } 5280a708f8fSGustavo F. Padovan } 5290a708f8fSGustavo F. Padovan } 5300a708f8fSGustavo F. Padovan 5314519de9aSGustavo F. Padovan static void l2cap_chan_cleanup_listen(struct sock *parent) 5324519de9aSGustavo F. Padovan { 5334519de9aSGustavo F. Padovan struct sock *sk; 5344519de9aSGustavo F. Padovan 5354519de9aSGustavo F. Padovan BT_DBG("parent %p", parent); 5364519de9aSGustavo F. Padovan 5374519de9aSGustavo F. Padovan /* Close not yet accepted channels */ 5380f852724SGustavo F. Padovan while ((sk = bt_accept_dequeue(parent, NULL))) { 539ba3bd0eeSGustavo F. Padovan struct l2cap_chan *chan = l2cap_pi(sk)->chan; 5403df91ea2SAndrei Emeltchenko 5416be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 542c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 543ba3bd0eeSGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 5446be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 5453df91ea2SAndrei Emeltchenko 546ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 5470f852724SGustavo F. Padovan } 5484519de9aSGustavo F. Padovan } 5494519de9aSGustavo F. Padovan 5500f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason) 5514519de9aSGustavo F. Padovan { 5524519de9aSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 5534519de9aSGustavo F. Padovan struct sock *sk = chan->sk; 5544519de9aSGustavo F. Padovan 555e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s sk %p", chan, 556e05dcc32SAndrei Emeltchenko state_to_string(chan->state), sk); 5574519de9aSGustavo F. Padovan 55889bc500eSGustavo F. Padovan switch (chan->state) { 5594519de9aSGustavo F. Padovan case BT_LISTEN: 5606be36555SAndrei Emeltchenko lock_sock(sk); 5614519de9aSGustavo F. Padovan l2cap_chan_cleanup_listen(sk); 56289bc500eSGustavo F. Padovan 5630e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CLOSED); 56489bc500eSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 5656be36555SAndrei Emeltchenko release_sock(sk); 5664519de9aSGustavo F. Padovan break; 5674519de9aSGustavo F. Padovan 5684519de9aSGustavo F. Padovan case BT_CONNECTED: 5694519de9aSGustavo F. Padovan case BT_CONFIG: 570715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && 5714519de9aSGustavo F. Padovan conn->hcon->type == ACL_LINK) { 572c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 5734519de9aSGustavo F. Padovan l2cap_send_disconn_req(conn, chan, reason); 5744519de9aSGustavo F. Padovan } else 5754519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 5764519de9aSGustavo F. Padovan break; 5774519de9aSGustavo F. Padovan 5784519de9aSGustavo F. Padovan case BT_CONNECT2: 579715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && 5804519de9aSGustavo F. Padovan conn->hcon->type == ACL_LINK) { 5814519de9aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 5824519de9aSGustavo F. Padovan __u16 result; 5834519de9aSGustavo F. Padovan 5844519de9aSGustavo F. Padovan if (bt_sk(sk)->defer_setup) 5854519de9aSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 5864519de9aSGustavo F. Padovan else 5874519de9aSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 58889bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_DISCONN); 5894519de9aSGustavo F. Padovan 5904519de9aSGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 5914519de9aSGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 5924519de9aSGustavo F. Padovan rsp.result = cpu_to_le16(result); 5934519de9aSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 5944519de9aSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 5954519de9aSGustavo F. Padovan sizeof(rsp), &rsp); 5964519de9aSGustavo F. Padovan } 5974519de9aSGustavo F. Padovan 5984519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 5994519de9aSGustavo F. Padovan break; 6004519de9aSGustavo F. Padovan 6014519de9aSGustavo F. Padovan case BT_CONNECT: 6024519de9aSGustavo F. Padovan case BT_DISCONN: 6034519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 6044519de9aSGustavo F. Padovan break; 6054519de9aSGustavo F. Padovan 6064519de9aSGustavo F. Padovan default: 6076be36555SAndrei Emeltchenko lock_sock(sk); 6084519de9aSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 6096be36555SAndrei Emeltchenko release_sock(sk); 6104519de9aSGustavo F. Padovan break; 6114519de9aSGustavo F. Padovan } 6124519de9aSGustavo F. Padovan } 6134519de9aSGustavo F. Padovan 6144343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) 6150a708f8fSGustavo F. Padovan { 616715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_RAW) { 6174343478fSGustavo F. Padovan switch (chan->sec_level) { 6180a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 6190a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING_MITM; 6200a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 6210a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING; 6220a708f8fSGustavo F. Padovan default: 6230a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 6240a708f8fSGustavo F. Padovan } 625fe4128e0SGustavo F. Padovan } else if (chan->psm == cpu_to_le16(0x0001)) { 6264343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_LOW) 6274343478fSGustavo F. Padovan chan->sec_level = BT_SECURITY_SDP; 6280a708f8fSGustavo F. Padovan 6294343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_HIGH) 6300a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING_MITM; 6310a708f8fSGustavo F. Padovan else 6320a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 6330a708f8fSGustavo F. Padovan } else { 6344343478fSGustavo F. Padovan switch (chan->sec_level) { 6350a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 6360a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING_MITM; 6370a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 6380a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING; 6390a708f8fSGustavo F. Padovan default: 6400a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 6410a708f8fSGustavo F. Padovan } 6420a708f8fSGustavo F. Padovan } 6430a708f8fSGustavo F. Padovan } 6440a708f8fSGustavo F. Padovan 6450a708f8fSGustavo F. Padovan /* Service level security */ 646d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan) 6470a708f8fSGustavo F. Padovan { 6488c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 6490a708f8fSGustavo F. Padovan __u8 auth_type; 6500a708f8fSGustavo F. Padovan 6514343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 6520a708f8fSGustavo F. Padovan 6534343478fSGustavo F. Padovan return hci_conn_security(conn->hcon, chan->sec_level, auth_type); 6540a708f8fSGustavo F. Padovan } 6550a708f8fSGustavo F. Padovan 656b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn) 6570a708f8fSGustavo F. Padovan { 6580a708f8fSGustavo F. Padovan u8 id; 6590a708f8fSGustavo F. Padovan 6600a708f8fSGustavo F. Padovan /* Get next available identificator. 6610a708f8fSGustavo F. Padovan * 1 - 128 are used by kernel. 6620a708f8fSGustavo F. Padovan * 129 - 199 are reserved. 6630a708f8fSGustavo F. Padovan * 200 - 254 are used by utilities like l2ping, etc. 6640a708f8fSGustavo F. Padovan */ 6650a708f8fSGustavo F. Padovan 666333055f2SGustavo F. Padovan spin_lock(&conn->lock); 6670a708f8fSGustavo F. Padovan 6680a708f8fSGustavo F. Padovan if (++conn->tx_ident > 128) 6690a708f8fSGustavo F. Padovan conn->tx_ident = 1; 6700a708f8fSGustavo F. Padovan 6710a708f8fSGustavo F. Padovan id = conn->tx_ident; 6720a708f8fSGustavo F. Padovan 673333055f2SGustavo F. Padovan spin_unlock(&conn->lock); 6740a708f8fSGustavo F. Padovan 6750a708f8fSGustavo F. Padovan return id; 6760a708f8fSGustavo F. Padovan } 6770a708f8fSGustavo F. Padovan 6784519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) 6790a708f8fSGustavo F. Padovan { 6800a708f8fSGustavo F. Padovan struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); 6810a708f8fSGustavo F. Padovan u8 flags; 6820a708f8fSGustavo F. Padovan 6830a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x", code); 6840a708f8fSGustavo F. Padovan 6850a708f8fSGustavo F. Padovan if (!skb) 6860a708f8fSGustavo F. Padovan return; 6870a708f8fSGustavo F. Padovan 6880a708f8fSGustavo F. Padovan if (lmp_no_flush_capable(conn->hcon->hdev)) 6890a708f8fSGustavo F. Padovan flags = ACL_START_NO_FLUSH; 6900a708f8fSGustavo F. Padovan else 6910a708f8fSGustavo F. Padovan flags = ACL_START; 6920a708f8fSGustavo F. Padovan 69314b12d0bSJaikumar Ganesh bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON; 6945e59b791SLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 69514b12d0bSJaikumar Ganesh 69673d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, flags); 6970a708f8fSGustavo F. Padovan } 6980a708f8fSGustavo F. Padovan 69973d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) 70073d80debSLuiz Augusto von Dentz { 70173d80debSLuiz Augusto von Dentz struct hci_conn *hcon = chan->conn->hcon; 70273d80debSLuiz Augusto von Dentz u16 flags; 70373d80debSLuiz Augusto von Dentz 70473d80debSLuiz Augusto von Dentz BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, 70573d80debSLuiz Augusto von Dentz skb->priority); 70673d80debSLuiz Augusto von Dentz 70773d80debSLuiz Augusto von Dentz if (!test_bit(FLAG_FLUSHABLE, &chan->flags) && 70873d80debSLuiz Augusto von Dentz lmp_no_flush_capable(hcon->hdev)) 70973d80debSLuiz Augusto von Dentz flags = ACL_START_NO_FLUSH; 71073d80debSLuiz Augusto von Dentz else 71173d80debSLuiz Augusto von Dentz flags = ACL_START; 71273d80debSLuiz Augusto von Dentz 71373d80debSLuiz Augusto von Dentz bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); 71473d80debSLuiz Augusto von Dentz hci_send_acl(chan->conn->hchan, skb, flags); 7150a708f8fSGustavo F. Padovan } 7160a708f8fSGustavo F. Padovan 717b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control) 718b5c6aaedSMat Martineau { 719b5c6aaedSMat Martineau control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT; 720b5c6aaedSMat Martineau control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT; 721b5c6aaedSMat Martineau 722b5c6aaedSMat Martineau if (enh & L2CAP_CTRL_FRAME_TYPE) { 723b5c6aaedSMat Martineau /* S-Frame */ 724b5c6aaedSMat Martineau control->sframe = 1; 725b5c6aaedSMat Martineau control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT; 726b5c6aaedSMat Martineau control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT; 727b5c6aaedSMat Martineau 728b5c6aaedSMat Martineau control->sar = 0; 729b5c6aaedSMat Martineau control->txseq = 0; 730b5c6aaedSMat Martineau } else { 731b5c6aaedSMat Martineau /* I-Frame */ 732b5c6aaedSMat Martineau control->sframe = 0; 733b5c6aaedSMat Martineau control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT; 734b5c6aaedSMat Martineau control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT; 735b5c6aaedSMat Martineau 736b5c6aaedSMat Martineau control->poll = 0; 737b5c6aaedSMat Martineau control->super = 0; 738b5c6aaedSMat Martineau } 739b5c6aaedSMat Martineau } 740b5c6aaedSMat Martineau 741b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control) 742b5c6aaedSMat Martineau { 743b5c6aaedSMat Martineau control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT; 744b5c6aaedSMat Martineau control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT; 745b5c6aaedSMat Martineau 746b5c6aaedSMat Martineau if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) { 747b5c6aaedSMat Martineau /* S-Frame */ 748b5c6aaedSMat Martineau control->sframe = 1; 749b5c6aaedSMat Martineau control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT; 750b5c6aaedSMat Martineau control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT; 751b5c6aaedSMat Martineau 752b5c6aaedSMat Martineau control->sar = 0; 753b5c6aaedSMat Martineau control->txseq = 0; 754b5c6aaedSMat Martineau } else { 755b5c6aaedSMat Martineau /* I-Frame */ 756b5c6aaedSMat Martineau control->sframe = 0; 757b5c6aaedSMat Martineau control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT; 758b5c6aaedSMat Martineau control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT; 759b5c6aaedSMat Martineau 760b5c6aaedSMat Martineau control->poll = 0; 761b5c6aaedSMat Martineau control->super = 0; 762b5c6aaedSMat Martineau } 763b5c6aaedSMat Martineau } 764b5c6aaedSMat Martineau 765b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan, 766b5c6aaedSMat Martineau struct sk_buff *skb) 767b5c6aaedSMat Martineau { 768b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 769b5c6aaedSMat Martineau __unpack_extended_control(get_unaligned_le32(skb->data), 770b5c6aaedSMat Martineau &bt_cb(skb)->control); 771b5c6aaedSMat Martineau } else { 772b5c6aaedSMat Martineau __unpack_enhanced_control(get_unaligned_le16(skb->data), 773b5c6aaedSMat Martineau &bt_cb(skb)->control); 774b5c6aaedSMat Martineau } 775b5c6aaedSMat Martineau } 776b5c6aaedSMat Martineau 777b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control) 778b5c6aaedSMat Martineau { 779b5c6aaedSMat Martineau u32 packed; 780b5c6aaedSMat Martineau 781b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT; 782b5c6aaedSMat Martineau packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT; 783b5c6aaedSMat Martineau 784b5c6aaedSMat Martineau if (control->sframe) { 785b5c6aaedSMat Martineau packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT; 786b5c6aaedSMat Martineau packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT; 787b5c6aaedSMat Martineau packed |= L2CAP_EXT_CTRL_FRAME_TYPE; 788b5c6aaedSMat Martineau } else { 789b5c6aaedSMat Martineau packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT; 790b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT; 791b5c6aaedSMat Martineau } 792b5c6aaedSMat Martineau 793b5c6aaedSMat Martineau return packed; 794b5c6aaedSMat Martineau } 795b5c6aaedSMat Martineau 796b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control) 797b5c6aaedSMat Martineau { 798b5c6aaedSMat Martineau u16 packed; 799b5c6aaedSMat Martineau 800b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT; 801b5c6aaedSMat Martineau packed |= control->final << L2CAP_CTRL_FINAL_SHIFT; 802b5c6aaedSMat Martineau 803b5c6aaedSMat Martineau if (control->sframe) { 804b5c6aaedSMat Martineau packed |= control->poll << L2CAP_CTRL_POLL_SHIFT; 805b5c6aaedSMat Martineau packed |= control->super << L2CAP_CTRL_SUPER_SHIFT; 806b5c6aaedSMat Martineau packed |= L2CAP_CTRL_FRAME_TYPE; 807b5c6aaedSMat Martineau } else { 808b5c6aaedSMat Martineau packed |= control->sar << L2CAP_CTRL_SAR_SHIFT; 809b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT; 810b5c6aaedSMat Martineau } 811b5c6aaedSMat Martineau 812b5c6aaedSMat Martineau return packed; 813b5c6aaedSMat Martineau } 814b5c6aaedSMat Martineau 815b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan, 816b5c6aaedSMat Martineau struct l2cap_ctrl *control, 817b5c6aaedSMat Martineau struct sk_buff *skb) 818b5c6aaedSMat Martineau { 819b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 820b5c6aaedSMat Martineau put_unaligned_le32(__pack_extended_control(control), 821b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 822b5c6aaedSMat Martineau } else { 823b5c6aaedSMat Martineau put_unaligned_le16(__pack_enhanced_control(control), 824b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 825b5c6aaedSMat Martineau } 826b5c6aaedSMat Martineau } 827b5c6aaedSMat Martineau 82888843ab0SAndrei Emeltchenko static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control) 8290a708f8fSGustavo F. Padovan { 8300a708f8fSGustavo F. Padovan struct sk_buff *skb; 8310a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 8328c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 833e4ca6d98SAndrei Emeltchenko int count, hlen; 8340a708f8fSGustavo F. Padovan 83589bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 8360a708f8fSGustavo F. Padovan return; 8370a708f8fSGustavo F. Padovan 838e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 839e4ca6d98SAndrei Emeltchenko hlen = L2CAP_EXT_HDR_SIZE; 840e4ca6d98SAndrei Emeltchenko else 841e4ca6d98SAndrei Emeltchenko hlen = L2CAP_ENH_HDR_SIZE; 8420a708f8fSGustavo F. Padovan 8430a708f8fSGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 84403a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 8450a708f8fSGustavo F. Padovan 84688843ab0SAndrei Emeltchenko BT_DBG("chan %p, control 0x%8.8x", chan, control); 8470a708f8fSGustavo F. Padovan 8480a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, hlen); 849793c2f1cSAndrei Emeltchenko 850793c2f1cSAndrei Emeltchenko control |= __set_sframe(chan); 8510a708f8fSGustavo F. Padovan 852e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 85303f6715dSAndrei Emeltchenko control |= __set_ctrl_final(chan); 8540a708f8fSGustavo F. Padovan 855e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state)) 856e3781735SAndrei Emeltchenko control |= __set_ctrl_poll(chan); 8570a708f8fSGustavo F. Padovan 8580a708f8fSGustavo F. Padovan skb = bt_skb_alloc(count, GFP_ATOMIC); 8590a708f8fSGustavo F. Padovan if (!skb) 8600a708f8fSGustavo F. Padovan return; 8610a708f8fSGustavo F. Padovan 8620a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 8630a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); 864fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 86588843ab0SAndrei Emeltchenko 86688843ab0SAndrei Emeltchenko __put_control(chan, control, skb_put(skb, __ctrl_size(chan))); 8670a708f8fSGustavo F. Padovan 86847d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 86903a51213SAndrei Emeltchenko u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE); 87003a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 8710a708f8fSGustavo F. Padovan } 8720a708f8fSGustavo F. Padovan 87373d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 87473d80debSLuiz Augusto von Dentz l2cap_do_send(chan, skb); 8750a708f8fSGustavo F. Padovan } 8760a708f8fSGustavo F. Padovan 87788843ab0SAndrei Emeltchenko static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control) 8780a708f8fSGustavo F. Padovan { 879e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 880ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); 881e2ab4353SGustavo F. Padovan set_bit(CONN_RNR_SENT, &chan->conn_state); 8820a708f8fSGustavo F. Padovan } else 883ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 8840a708f8fSGustavo F. Padovan 8850b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 8860a708f8fSGustavo F. Padovan 887525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 8880a708f8fSGustavo F. Padovan } 8890a708f8fSGustavo F. Padovan 890b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) 8910a708f8fSGustavo F. Padovan { 892c1360a1cSGustavo F. Padovan return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); 8930a708f8fSGustavo F. Padovan } 8940a708f8fSGustavo F. Padovan 8959b27f350SAndrei Emeltchenko static void l2cap_send_conn_req(struct l2cap_chan *chan) 8969b27f350SAndrei Emeltchenko { 8979b27f350SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 8989b27f350SAndrei Emeltchenko struct l2cap_conn_req req; 8999b27f350SAndrei Emeltchenko 9009b27f350SAndrei Emeltchenko req.scid = cpu_to_le16(chan->scid); 9019b27f350SAndrei Emeltchenko req.psm = chan->psm; 9029b27f350SAndrei Emeltchenko 9039b27f350SAndrei Emeltchenko chan->ident = l2cap_get_ident(conn); 9049b27f350SAndrei Emeltchenko 9059b27f350SAndrei Emeltchenko set_bit(CONF_CONNECT_PEND, &chan->conf_state); 9069b27f350SAndrei Emeltchenko 9079b27f350SAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); 9089b27f350SAndrei Emeltchenko } 9099b27f350SAndrei Emeltchenko 9109f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan) 9119f0caeb1SVinicius Costa Gomes { 9129f0caeb1SVinicius Costa Gomes struct sock *sk = chan->sk; 9139f0caeb1SVinicius Costa Gomes struct sock *parent; 9149f0caeb1SVinicius Costa Gomes 9159f0caeb1SVinicius Costa Gomes lock_sock(sk); 9169f0caeb1SVinicius Costa Gomes 9179f0caeb1SVinicius Costa Gomes parent = bt_sk(sk)->parent; 9189f0caeb1SVinicius Costa Gomes 9199f0caeb1SVinicius Costa Gomes BT_DBG("sk %p, parent %p", sk, parent); 9209f0caeb1SVinicius Costa Gomes 9219f0caeb1SVinicius Costa Gomes chan->conf_state = 0; 9229f0caeb1SVinicius Costa Gomes __clear_chan_timer(chan); 9239f0caeb1SVinicius Costa Gomes 9249f0caeb1SVinicius Costa Gomes __l2cap_state_change(chan, BT_CONNECTED); 9259f0caeb1SVinicius Costa Gomes sk->sk_state_change(sk); 9269f0caeb1SVinicius Costa Gomes 9279f0caeb1SVinicius Costa Gomes if (parent) 9289f0caeb1SVinicius Costa Gomes parent->sk_data_ready(parent, 0); 9299f0caeb1SVinicius Costa Gomes 9309f0caeb1SVinicius Costa Gomes release_sock(sk); 9319f0caeb1SVinicius Costa Gomes } 9329f0caeb1SVinicius Costa Gomes 933fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan) 9340a708f8fSGustavo F. Padovan { 9358c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 9360a708f8fSGustavo F. Padovan 9379f0caeb1SVinicius Costa Gomes if (conn->hcon->type == LE_LINK) { 9389f0caeb1SVinicius Costa Gomes l2cap_chan_ready(chan); 9399f0caeb1SVinicius Costa Gomes return; 9409f0caeb1SVinicius Costa Gomes } 9419f0caeb1SVinicius Costa Gomes 9420a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { 9430a708f8fSGustavo F. Padovan if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) 9440a708f8fSGustavo F. Padovan return; 9450a708f8fSGustavo F. Padovan 946d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan) && 9479b27f350SAndrei Emeltchenko __l2cap_no_conn_pending(chan)) 9489b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 9490a708f8fSGustavo F. Padovan } else { 9500a708f8fSGustavo F. Padovan struct l2cap_info_req req; 9510a708f8fSGustavo F. Padovan req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 9520a708f8fSGustavo F. Padovan 9530a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 9540a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 9550a708f8fSGustavo F. Padovan 956ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 9570a708f8fSGustavo F. Padovan 9580a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 9590a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 9600a708f8fSGustavo F. Padovan } 9610a708f8fSGustavo F. Padovan } 9620a708f8fSGustavo F. Padovan 9630a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) 9640a708f8fSGustavo F. Padovan { 9650a708f8fSGustavo F. Padovan u32 local_feat_mask = l2cap_feat_mask; 9660a708f8fSGustavo F. Padovan if (!disable_ertm) 9670a708f8fSGustavo F. Padovan local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING; 9680a708f8fSGustavo F. Padovan 9690a708f8fSGustavo F. Padovan switch (mode) { 9700a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 9710a708f8fSGustavo F. Padovan return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask; 9720a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 9730a708f8fSGustavo F. Padovan return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask; 9740a708f8fSGustavo F. Padovan default: 9750a708f8fSGustavo F. Padovan return 0x00; 9760a708f8fSGustavo F. Padovan } 9770a708f8fSGustavo F. Padovan } 9780a708f8fSGustavo F. Padovan 9794519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err) 9800a708f8fSGustavo F. Padovan { 9816be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 9820a708f8fSGustavo F. Padovan struct l2cap_disconn_req req; 9830a708f8fSGustavo F. Padovan 9840a708f8fSGustavo F. Padovan if (!conn) 9850a708f8fSGustavo F. Padovan return; 9860a708f8fSGustavo F. Padovan 9870c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_ERTM) { 9881a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 9891a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 9901a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 9910a708f8fSGustavo F. Padovan } 9920a708f8fSGustavo F. Padovan 993fe4128e0SGustavo F. Padovan req.dcid = cpu_to_le16(chan->dcid); 994fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 9950a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 9960a708f8fSGustavo F. Padovan L2CAP_DISCONN_REQ, sizeof(req), &req); 9970a708f8fSGustavo F. Padovan 9986be36555SAndrei Emeltchenko lock_sock(sk); 9990e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_DISCONN); 10002e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 10016be36555SAndrei Emeltchenko release_sock(sk); 10020a708f8fSGustavo F. Padovan } 10030a708f8fSGustavo F. Padovan 10040a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */ 10050a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn) 10060a708f8fSGustavo F. Padovan { 10073df91ea2SAndrei Emeltchenko struct l2cap_chan *chan, *tmp; 10080a708f8fSGustavo F. Padovan 10090a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 10100a708f8fSGustavo F. Padovan 10113df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 10120a708f8fSGustavo F. Padovan 10133df91ea2SAndrei Emeltchenko list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 101448454079SGustavo F. Padovan struct sock *sk = chan->sk; 1015baa7e1faSGustavo F. Padovan 10166be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 10170a708f8fSGustavo F. Padovan 1018715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 10196be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10200a708f8fSGustavo F. Padovan continue; 10210a708f8fSGustavo F. Padovan } 10220a708f8fSGustavo F. Padovan 102389bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 1024d45fc423SGustavo F. Padovan if (!l2cap_chan_check_security(chan) || 1025b4450035SGustavo F. Padovan !__l2cap_no_conn_pending(chan)) { 10266be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10270a708f8fSGustavo F. Padovan continue; 10280a708f8fSGustavo F. Padovan } 10290a708f8fSGustavo F. Padovan 1030c1360a1cSGustavo F. Padovan if (!l2cap_mode_supported(chan->mode, conn->feat_mask) 1031c1360a1cSGustavo F. Padovan && test_bit(CONF_STATE2_DEVICE, 1032c1360a1cSGustavo F. Padovan &chan->conf_state)) { 10330f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 10346be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10350a708f8fSGustavo F. Padovan continue; 10360a708f8fSGustavo F. Padovan } 10370a708f8fSGustavo F. Padovan 10389b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 10390a708f8fSGustavo F. Padovan 104089bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 10410a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 10420a708f8fSGustavo F. Padovan char buf[128]; 1043fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 1044fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 10450a708f8fSGustavo F. Padovan 1046d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 10476be36555SAndrei Emeltchenko lock_sock(sk); 10480a708f8fSGustavo F. Padovan if (bt_sk(sk)->defer_setup) { 10490a708f8fSGustavo F. Padovan struct sock *parent = bt_sk(sk)->parent; 10500a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_PEND); 10510a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND); 105205e9a2f6SIlia Kolomisnky if (parent) 10530a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 10540a708f8fSGustavo F. Padovan 10550a708f8fSGustavo F. Padovan } else { 10560e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 10570a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 10580a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 10590a708f8fSGustavo F. Padovan } 10606be36555SAndrei Emeltchenko release_sock(sk); 10610a708f8fSGustavo F. Padovan } else { 10620a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_PEND); 10630a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND); 10640a708f8fSGustavo F. Padovan } 10650a708f8fSGustavo F. Padovan 1066fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 1067fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 10680a708f8fSGustavo F. Padovan 1069c1360a1cSGustavo F. Padovan if (test_bit(CONF_REQ_SENT, &chan->conf_state) || 10700a708f8fSGustavo F. Padovan rsp.result != L2CAP_CR_SUCCESS) { 10716be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10720a708f8fSGustavo F. Padovan continue; 10730a708f8fSGustavo F. Padovan } 10740a708f8fSGustavo F. Padovan 1075c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 10760a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 107773ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 107873ffa904SGustavo F. Padovan chan->num_conf_req++; 10790a708f8fSGustavo F. Padovan } 10800a708f8fSGustavo F. Padovan 10816be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10820a708f8fSGustavo F. Padovan } 10830a708f8fSGustavo F. Padovan 10843df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 10850a708f8fSGustavo F. Padovan } 10860a708f8fSGustavo F. Padovan 1087c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr. 1088b62f328bSVille Tervo * Returns closest match, locked. 1089b62f328bSVille Tervo */ 1090d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, 1091c2287681SIdo Yariv bdaddr_t *src, 1092c2287681SIdo Yariv bdaddr_t *dst) 1093b62f328bSVille Tervo { 109423691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 1095b62f328bSVille Tervo 109623691d75SGustavo F. Padovan read_lock(&chan_list_lock); 1097b62f328bSVille Tervo 109823691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 109923691d75SGustavo F. Padovan struct sock *sk = c->sk; 1100fe4128e0SGustavo F. Padovan 110189bc500eSGustavo F. Padovan if (state && c->state != state) 1102b62f328bSVille Tervo continue; 1103b62f328bSVille Tervo 110423691d75SGustavo F. Padovan if (c->scid == cid) { 1105c2287681SIdo Yariv int src_match, dst_match; 1106c2287681SIdo Yariv int src_any, dst_any; 1107c2287681SIdo Yariv 1108b62f328bSVille Tervo /* Exact match. */ 1109c2287681SIdo Yariv src_match = !bacmp(&bt_sk(sk)->src, src); 1110c2287681SIdo Yariv dst_match = !bacmp(&bt_sk(sk)->dst, dst); 1111c2287681SIdo Yariv if (src_match && dst_match) { 111223691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 111323691d75SGustavo F. Padovan return c; 111423691d75SGustavo F. Padovan } 1115b62f328bSVille Tervo 1116b62f328bSVille Tervo /* Closest match */ 1117c2287681SIdo Yariv src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY); 1118c2287681SIdo Yariv dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY); 1119c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1120c2287681SIdo Yariv (src_any && dst_any)) 112123691d75SGustavo F. Padovan c1 = c; 1122b62f328bSVille Tervo } 1123b62f328bSVille Tervo } 1124280f294fSGustavo F. Padovan 112523691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 1126b62f328bSVille Tervo 112723691d75SGustavo F. Padovan return c1; 1128b62f328bSVille Tervo } 1129b62f328bSVille Tervo 1130b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn) 1131b62f328bSVille Tervo { 1132c916fbe4SGustavo F. Padovan struct sock *parent, *sk; 113323691d75SGustavo F. Padovan struct l2cap_chan *chan, *pchan; 1134b62f328bSVille Tervo 1135b62f328bSVille Tervo BT_DBG(""); 1136b62f328bSVille Tervo 1137b62f328bSVille Tervo /* Check if we have socket listening on cid */ 113823691d75SGustavo F. Padovan pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA, 1139c2287681SIdo Yariv conn->src, conn->dst); 114023691d75SGustavo F. Padovan if (!pchan) 1141b62f328bSVille Tervo return; 1142b62f328bSVille Tervo 114323691d75SGustavo F. Padovan parent = pchan->sk; 114423691d75SGustavo F. Padovan 1145aa2ac881SGustavo F. Padovan lock_sock(parent); 114662f3a2cfSGustavo F. Padovan 1147b62f328bSVille Tervo /* Check for backlog size */ 1148b62f328bSVille Tervo if (sk_acceptq_is_full(parent)) { 1149b62f328bSVille Tervo BT_DBG("backlog full %d", parent->sk_ack_backlog); 1150b62f328bSVille Tervo goto clean; 1151b62f328bSVille Tervo } 1152b62f328bSVille Tervo 115380808e43SGustavo F. Padovan chan = pchan->ops->new_connection(pchan->data); 115480808e43SGustavo F. Padovan if (!chan) 1155b62f328bSVille Tervo goto clean; 1156b62f328bSVille Tervo 115780808e43SGustavo F. Padovan sk = chan->sk; 11585d41ce1dSGustavo F. Padovan 1159b62f328bSVille Tervo hci_conn_hold(conn->hcon); 1160b62f328bSVille Tervo 1161b62f328bSVille Tervo bacpy(&bt_sk(sk)->src, conn->src); 1162b62f328bSVille Tervo bacpy(&bt_sk(sk)->dst, conn->dst); 1163b62f328bSVille Tervo 1164d1010240SGustavo F. Padovan bt_accept_enqueue(parent, sk); 1165d1010240SGustavo F. Padovan 11663d57dc68SGustavo F. Padovan l2cap_chan_add(conn, chan); 116748454079SGustavo F. Padovan 1168c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 1169b62f328bSVille Tervo 11700e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECTED); 1171b62f328bSVille Tervo parent->sk_data_ready(parent, 0); 1172b62f328bSVille Tervo 1173b62f328bSVille Tervo clean: 1174aa2ac881SGustavo F. Padovan release_sock(parent); 1175b62f328bSVille Tervo } 1176b62f328bSVille Tervo 11770a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn) 11780a708f8fSGustavo F. Padovan { 117948454079SGustavo F. Padovan struct l2cap_chan *chan; 11800a708f8fSGustavo F. Padovan 11810a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 11820a708f8fSGustavo F. Padovan 1183b62f328bSVille Tervo if (!conn->hcon->out && conn->hcon->type == LE_LINK) 1184b62f328bSVille Tervo l2cap_le_conn_ready(conn); 1185b62f328bSVille Tervo 1186160dc6acSVinicius Costa Gomes if (conn->hcon->out && conn->hcon->type == LE_LINK) 1187160dc6acSVinicius Costa Gomes smp_conn_security(conn, conn->hcon->pending_sec_level); 1188160dc6acSVinicius Costa Gomes 11893df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 11900a708f8fSGustavo F. Padovan 11913df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1192baa7e1faSGustavo F. Padovan 11936be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 11940a708f8fSGustavo F. Padovan 119563128451SVinicius Costa Gomes if (conn->hcon->type == LE_LINK) { 1196b501d6a1SAnderson Briglia if (smp_conn_security(conn, chan->sec_level)) 1197cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 1198acd7d370SVille Tervo 119963128451SVinicius Costa Gomes } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 12006be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 1201c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 12026be36555SAndrei Emeltchenko lock_sock(sk); 12030e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECTED); 12040a708f8fSGustavo F. Padovan sk->sk_state_change(sk); 12056be36555SAndrei Emeltchenko release_sock(sk); 1206b501d6a1SAnderson Briglia 120789bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT) 1208fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 12090a708f8fSGustavo F. Padovan 12106be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 12110a708f8fSGustavo F. Padovan } 12120a708f8fSGustavo F. Padovan 12133df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 12140a708f8fSGustavo F. Padovan } 12150a708f8fSGustavo F. Padovan 12160a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */ 12170a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) 12180a708f8fSGustavo F. Padovan { 121948454079SGustavo F. Padovan struct l2cap_chan *chan; 12200a708f8fSGustavo F. Padovan 12210a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 12220a708f8fSGustavo F. Padovan 12233df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 12240a708f8fSGustavo F. Padovan 12253df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1226ecf61bdbSAndrei Emeltchenko if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) 12272e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 12280a708f8fSGustavo F. Padovan } 12290a708f8fSGustavo F. Padovan 12303df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 12310a708f8fSGustavo F. Padovan } 12320a708f8fSGustavo F. Padovan 1233f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work) 12340a708f8fSGustavo F. Padovan { 1235f878fcadSGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 1236030013d8SGustavo F. Padovan info_timer.work); 12370a708f8fSGustavo F. Padovan 12380a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 12390a708f8fSGustavo F. Padovan conn->info_ident = 0; 12400a708f8fSGustavo F. Padovan 12410a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 12420a708f8fSGustavo F. Padovan } 12430a708f8fSGustavo F. Padovan 12445d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err) 12455d3de7dfSVinicius Costa Gomes { 12465d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 12475d3de7dfSVinicius Costa Gomes struct l2cap_chan *chan, *l; 12485d3de7dfSVinicius Costa Gomes 12495d3de7dfSVinicius Costa Gomes if (!conn) 12505d3de7dfSVinicius Costa Gomes return; 12515d3de7dfSVinicius Costa Gomes 12525d3de7dfSVinicius Costa Gomes BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); 12535d3de7dfSVinicius Costa Gomes 12545d3de7dfSVinicius Costa Gomes kfree_skb(conn->rx_skb); 12555d3de7dfSVinicius Costa Gomes 12563df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 12573df91ea2SAndrei Emeltchenko 12585d3de7dfSVinicius Costa Gomes /* Kill channels */ 12595d3de7dfSVinicius Costa Gomes list_for_each_entry_safe(chan, l, &conn->chan_l, list) { 126061d6ef3eSMat Martineau l2cap_chan_hold(chan); 12616be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 12626be36555SAndrei Emeltchenko 12635d3de7dfSVinicius Costa Gomes l2cap_chan_del(chan, err); 12646be36555SAndrei Emeltchenko 12656be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 12666be36555SAndrei Emeltchenko 12675d3de7dfSVinicius Costa Gomes chan->ops->close(chan->data); 126861d6ef3eSMat Martineau l2cap_chan_put(chan); 12695d3de7dfSVinicius Costa Gomes } 12705d3de7dfSVinicius Costa Gomes 12713df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 12723df91ea2SAndrei Emeltchenko 127373d80debSLuiz Augusto von Dentz hci_chan_del(conn->hchan); 127473d80debSLuiz Augusto von Dentz 12755d3de7dfSVinicius Costa Gomes if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1276127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->info_timer); 12775d3de7dfSVinicius Costa Gomes 127851a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) { 1279127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->security_timer); 12808aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 1281d26a2345SVinicius Costa Gomes } 12825d3de7dfSVinicius Costa Gomes 12835d3de7dfSVinicius Costa Gomes hcon->l2cap_data = NULL; 12845d3de7dfSVinicius Costa Gomes kfree(conn); 12855d3de7dfSVinicius Costa Gomes } 12865d3de7dfSVinicius Costa Gomes 12876c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work) 12885d3de7dfSVinicius Costa Gomes { 12896c9d42a1SGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 12906c9d42a1SGustavo F. Padovan security_timer.work); 12915d3de7dfSVinicius Costa Gomes 12925d3de7dfSVinicius Costa Gomes l2cap_conn_del(conn->hcon, ETIMEDOUT); 12935d3de7dfSVinicius Costa Gomes } 12945d3de7dfSVinicius Costa Gomes 12950a708f8fSGustavo F. Padovan static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) 12960a708f8fSGustavo F. Padovan { 12970a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 129873d80debSLuiz Augusto von Dentz struct hci_chan *hchan; 12990a708f8fSGustavo F. Padovan 13000a708f8fSGustavo F. Padovan if (conn || status) 13010a708f8fSGustavo F. Padovan return conn; 13020a708f8fSGustavo F. Padovan 130373d80debSLuiz Augusto von Dentz hchan = hci_chan_create(hcon); 130473d80debSLuiz Augusto von Dentz if (!hchan) 13050a708f8fSGustavo F. Padovan return NULL; 13060a708f8fSGustavo F. Padovan 130773d80debSLuiz Augusto von Dentz conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC); 130873d80debSLuiz Augusto von Dentz if (!conn) { 130973d80debSLuiz Augusto von Dentz hci_chan_del(hchan); 131073d80debSLuiz Augusto von Dentz return NULL; 131173d80debSLuiz Augusto von Dentz } 131273d80debSLuiz Augusto von Dentz 13130a708f8fSGustavo F. Padovan hcon->l2cap_data = conn; 13140a708f8fSGustavo F. Padovan conn->hcon = hcon; 131573d80debSLuiz Augusto von Dentz conn->hchan = hchan; 13160a708f8fSGustavo F. Padovan 131773d80debSLuiz Augusto von Dentz BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); 13180a708f8fSGustavo F. Padovan 1319acd7d370SVille Tervo if (hcon->hdev->le_mtu && hcon->type == LE_LINK) 1320acd7d370SVille Tervo conn->mtu = hcon->hdev->le_mtu; 1321acd7d370SVille Tervo else 13220a708f8fSGustavo F. Padovan conn->mtu = hcon->hdev->acl_mtu; 1323acd7d370SVille Tervo 13240a708f8fSGustavo F. Padovan conn->src = &hcon->hdev->bdaddr; 13250a708f8fSGustavo F. Padovan conn->dst = &hcon->dst; 13260a708f8fSGustavo F. Padovan 13270a708f8fSGustavo F. Padovan conn->feat_mask = 0; 13280a708f8fSGustavo F. Padovan 13290a708f8fSGustavo F. Padovan spin_lock_init(&conn->lock); 13303df91ea2SAndrei Emeltchenko mutex_init(&conn->chan_lock); 1331baa7e1faSGustavo F. Padovan 1332baa7e1faSGustavo F. Padovan INIT_LIST_HEAD(&conn->chan_l); 13330a708f8fSGustavo F. Padovan 13345d3de7dfSVinicius Costa Gomes if (hcon->type == LE_LINK) 13356c9d42a1SGustavo F. Padovan INIT_DELAYED_WORK(&conn->security_timer, security_timeout); 13365d3de7dfSVinicius Costa Gomes else 1337030013d8SGustavo F. Padovan INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); 13380a708f8fSGustavo F. Padovan 13399f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 13400a708f8fSGustavo F. Padovan 13410a708f8fSGustavo F. Padovan return conn; 13420a708f8fSGustavo F. Padovan } 13430a708f8fSGustavo F. Padovan 13440a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */ 13450a708f8fSGustavo F. Padovan 1346c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr. 13470a708f8fSGustavo F. Padovan * Returns closest match. 13480a708f8fSGustavo F. Padovan */ 1349c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, 1350c2287681SIdo Yariv bdaddr_t *src, 1351c2287681SIdo Yariv bdaddr_t *dst) 13520a708f8fSGustavo F. Padovan { 135323691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 13540a708f8fSGustavo F. Padovan 135523691d75SGustavo F. Padovan read_lock(&chan_list_lock); 13560a708f8fSGustavo F. Padovan 135723691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 135823691d75SGustavo F. Padovan struct sock *sk = c->sk; 1359fe4128e0SGustavo F. Padovan 136089bc500eSGustavo F. Padovan if (state && c->state != state) 13610a708f8fSGustavo F. Padovan continue; 13620a708f8fSGustavo F. Padovan 136323691d75SGustavo F. Padovan if (c->psm == psm) { 1364c2287681SIdo Yariv int src_match, dst_match; 1365c2287681SIdo Yariv int src_any, dst_any; 1366c2287681SIdo Yariv 13670a708f8fSGustavo F. Padovan /* Exact match. */ 1368c2287681SIdo Yariv src_match = !bacmp(&bt_sk(sk)->src, src); 1369c2287681SIdo Yariv dst_match = !bacmp(&bt_sk(sk)->dst, dst); 1370c2287681SIdo Yariv if (src_match && dst_match) { 1371a7567b20SJohannes Berg read_unlock(&chan_list_lock); 137223691d75SGustavo F. Padovan return c; 137323691d75SGustavo F. Padovan } 13740a708f8fSGustavo F. Padovan 13750a708f8fSGustavo F. Padovan /* Closest match */ 1376c2287681SIdo Yariv src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY); 1377c2287681SIdo Yariv dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY); 1378c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1379c2287681SIdo Yariv (src_any && dst_any)) 138023691d75SGustavo F. Padovan c1 = c; 13810a708f8fSGustavo F. Padovan } 13820a708f8fSGustavo F. Padovan } 13830a708f8fSGustavo F. Padovan 138423691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 13850a708f8fSGustavo F. Padovan 138623691d75SGustavo F. Padovan return c1; 13870a708f8fSGustavo F. Padovan } 13880a708f8fSGustavo F. Padovan 13898e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, 13908e9f9892SAndre Guedes bdaddr_t *dst, u8 dst_type) 13910a708f8fSGustavo F. Padovan { 13925d41ce1dSGustavo F. Padovan struct sock *sk = chan->sk; 13930a708f8fSGustavo F. Padovan bdaddr_t *src = &bt_sk(sk)->src; 13940a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 13950a708f8fSGustavo F. Padovan struct hci_conn *hcon; 13960a708f8fSGustavo F. Padovan struct hci_dev *hdev; 13970a708f8fSGustavo F. Padovan __u8 auth_type; 13980a708f8fSGustavo F. Padovan int err; 13990a708f8fSGustavo F. Padovan 14008e9f9892SAndre Guedes BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst), 14018e9f9892SAndre Guedes dst_type, __le16_to_cpu(chan->psm)); 14020a708f8fSGustavo F. Padovan 14030a708f8fSGustavo F. Padovan hdev = hci_get_route(dst, src); 14040a708f8fSGustavo F. Padovan if (!hdev) 14050a708f8fSGustavo F. Padovan return -EHOSTUNREACH; 14060a708f8fSGustavo F. Padovan 140709fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 14080a708f8fSGustavo F. Padovan 14096be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 141003a00194SGustavo F. Padovan 141103a00194SGustavo F. Padovan /* PSM must be odd and lsb of upper byte must be 0 */ 141203a00194SGustavo F. Padovan if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid && 141303a00194SGustavo F. Padovan chan->chan_type != L2CAP_CHAN_RAW) { 141403a00194SGustavo F. Padovan err = -EINVAL; 141503a00194SGustavo F. Padovan goto done; 141603a00194SGustavo F. Padovan } 141703a00194SGustavo F. Padovan 141803a00194SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) { 141903a00194SGustavo F. Padovan err = -EINVAL; 142003a00194SGustavo F. Padovan goto done; 142103a00194SGustavo F. Padovan } 142203a00194SGustavo F. Padovan 142303a00194SGustavo F. Padovan switch (chan->mode) { 142403a00194SGustavo F. Padovan case L2CAP_MODE_BASIC: 142503a00194SGustavo F. Padovan break; 142603a00194SGustavo F. Padovan case L2CAP_MODE_ERTM: 142703a00194SGustavo F. Padovan case L2CAP_MODE_STREAMING: 142803a00194SGustavo F. Padovan if (!disable_ertm) 142903a00194SGustavo F. Padovan break; 143003a00194SGustavo F. Padovan /* fall through */ 143103a00194SGustavo F. Padovan default: 143203a00194SGustavo F. Padovan err = -ENOTSUPP; 143303a00194SGustavo F. Padovan goto done; 143403a00194SGustavo F. Padovan } 143503a00194SGustavo F. Padovan 14366be36555SAndrei Emeltchenko lock_sock(sk); 14376be36555SAndrei Emeltchenko 143803a00194SGustavo F. Padovan switch (sk->sk_state) { 143903a00194SGustavo F. Padovan case BT_CONNECT: 144003a00194SGustavo F. Padovan case BT_CONNECT2: 144103a00194SGustavo F. Padovan case BT_CONFIG: 144203a00194SGustavo F. Padovan /* Already connecting */ 144303a00194SGustavo F. Padovan err = 0; 14446be36555SAndrei Emeltchenko release_sock(sk); 144503a00194SGustavo F. Padovan goto done; 144603a00194SGustavo F. Padovan 144703a00194SGustavo F. Padovan case BT_CONNECTED: 144803a00194SGustavo F. Padovan /* Already connected */ 144903a00194SGustavo F. Padovan err = -EISCONN; 14506be36555SAndrei Emeltchenko release_sock(sk); 145103a00194SGustavo F. Padovan goto done; 145203a00194SGustavo F. Padovan 145303a00194SGustavo F. Padovan case BT_OPEN: 145403a00194SGustavo F. Padovan case BT_BOUND: 145503a00194SGustavo F. Padovan /* Can connect */ 145603a00194SGustavo F. Padovan break; 145703a00194SGustavo F. Padovan 145803a00194SGustavo F. Padovan default: 145903a00194SGustavo F. Padovan err = -EBADFD; 14606be36555SAndrei Emeltchenko release_sock(sk); 146103a00194SGustavo F. Padovan goto done; 146203a00194SGustavo F. Padovan } 146303a00194SGustavo F. Padovan 146403a00194SGustavo F. Padovan /* Set destination address and psm */ 14659219b2a0SGustavo F. Padovan bacpy(&bt_sk(sk)->dst, dst); 14666be36555SAndrei Emeltchenko 14676be36555SAndrei Emeltchenko release_sock(sk); 14686be36555SAndrei Emeltchenko 146903a00194SGustavo F. Padovan chan->psm = psm; 147003a00194SGustavo F. Padovan chan->dcid = cid; 14710a708f8fSGustavo F. Padovan 14724343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 14730a708f8fSGustavo F. Padovan 1474fe4128e0SGustavo F. Padovan if (chan->dcid == L2CAP_CID_LE_DATA) 14758e9f9892SAndre Guedes hcon = hci_connect(hdev, LE_LINK, dst, dst_type, 14764343478fSGustavo F. Padovan chan->sec_level, auth_type); 1477acd7d370SVille Tervo else 14788e9f9892SAndre Guedes hcon = hci_connect(hdev, ACL_LINK, dst, dst_type, 14794343478fSGustavo F. Padovan chan->sec_level, auth_type); 1480acd7d370SVille Tervo 148130e76272SVille Tervo if (IS_ERR(hcon)) { 148230e76272SVille Tervo err = PTR_ERR(hcon); 14830a708f8fSGustavo F. Padovan goto done; 148430e76272SVille Tervo } 14850a708f8fSGustavo F. Padovan 14860a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, 0); 14870a708f8fSGustavo F. Padovan if (!conn) { 14880a708f8fSGustavo F. Padovan hci_conn_put(hcon); 148930e76272SVille Tervo err = -ENOMEM; 14900a708f8fSGustavo F. Padovan goto done; 14910a708f8fSGustavo F. Padovan } 14920a708f8fSGustavo F. Padovan 14939f0caeb1SVinicius Costa Gomes if (hcon->type == LE_LINK) { 14949f0caeb1SVinicius Costa Gomes err = 0; 14959f0caeb1SVinicius Costa Gomes 14969f0caeb1SVinicius Costa Gomes if (!list_empty(&conn->chan_l)) { 14979f0caeb1SVinicius Costa Gomes err = -EBUSY; 14989f0caeb1SVinicius Costa Gomes hci_conn_put(hcon); 14999f0caeb1SVinicius Costa Gomes } 15009f0caeb1SVinicius Costa Gomes 15019f0caeb1SVinicius Costa Gomes if (err) 15029f0caeb1SVinicius Costa Gomes goto done; 15039f0caeb1SVinicius Costa Gomes } 15049f0caeb1SVinicius Costa Gomes 15050a708f8fSGustavo F. Padovan /* Update source addr of the socket */ 15060a708f8fSGustavo F. Padovan bacpy(src, conn->src); 15070a708f8fSGustavo F. Padovan 15086be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 150948454079SGustavo F. Padovan l2cap_chan_add(conn, chan); 15106be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 151148454079SGustavo F. Padovan 15126be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECT); 1513c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 15140a708f8fSGustavo F. Padovan 15150a708f8fSGustavo F. Padovan if (hcon->state == BT_CONNECTED) { 1516715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1517c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 1518d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) 15196be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECTED); 15200a708f8fSGustavo F. Padovan } else 1521fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 15220a708f8fSGustavo F. Padovan } 15230a708f8fSGustavo F. Padovan 152430e76272SVille Tervo err = 0; 152530e76272SVille Tervo 15260a708f8fSGustavo F. Padovan done: 15276be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 152809fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 15290a708f8fSGustavo F. Padovan hci_dev_put(hdev); 15300a708f8fSGustavo F. Padovan return err; 15310a708f8fSGustavo F. Padovan } 15320a708f8fSGustavo F. Padovan 1533dcba0dbaSGustavo F. Padovan int __l2cap_wait_ack(struct sock *sk) 15340a708f8fSGustavo F. Padovan { 15358c1d787bSGustavo F. Padovan struct l2cap_chan *chan = l2cap_pi(sk)->chan; 15360a708f8fSGustavo F. Padovan DECLARE_WAITQUEUE(wait, current); 15370a708f8fSGustavo F. Padovan int err = 0; 15380a708f8fSGustavo F. Padovan int timeo = HZ/5; 15390a708f8fSGustavo F. Padovan 15400a708f8fSGustavo F. Padovan add_wait_queue(sk_sleep(sk), &wait); 15410a708f8fSGustavo F. Padovan set_current_state(TASK_INTERRUPTIBLE); 1542a71a0cf4SPeter Hurley while (chan->unacked_frames > 0 && chan->conn) { 15430a708f8fSGustavo F. Padovan if (!timeo) 15440a708f8fSGustavo F. Padovan timeo = HZ/5; 15450a708f8fSGustavo F. Padovan 15460a708f8fSGustavo F. Padovan if (signal_pending(current)) { 15470a708f8fSGustavo F. Padovan err = sock_intr_errno(timeo); 15480a708f8fSGustavo F. Padovan break; 15490a708f8fSGustavo F. Padovan } 15500a708f8fSGustavo F. Padovan 15510a708f8fSGustavo F. Padovan release_sock(sk); 15520a708f8fSGustavo F. Padovan timeo = schedule_timeout(timeo); 15530a708f8fSGustavo F. Padovan lock_sock(sk); 1554a71a0cf4SPeter Hurley set_current_state(TASK_INTERRUPTIBLE); 15550a708f8fSGustavo F. Padovan 15560a708f8fSGustavo F. Padovan err = sock_error(sk); 15570a708f8fSGustavo F. Padovan if (err) 15580a708f8fSGustavo F. Padovan break; 15590a708f8fSGustavo F. Padovan } 15600a708f8fSGustavo F. Padovan set_current_state(TASK_RUNNING); 15610a708f8fSGustavo F. Padovan remove_wait_queue(sk_sleep(sk), &wait); 15620a708f8fSGustavo F. Padovan return err; 15630a708f8fSGustavo F. Padovan } 15640a708f8fSGustavo F. Padovan 1565721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work) 15660a708f8fSGustavo F. Padovan { 1567721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1568721c4181SGustavo F. Padovan monitor_timer.work); 15690a708f8fSGustavo F. Padovan 1570525cd185SGustavo F. Padovan BT_DBG("chan %p", chan); 15710a708f8fSGustavo F. Padovan 15726be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 15736be36555SAndrei Emeltchenko 15742c03a7a4SGustavo F. Padovan if (chan->retry_count >= chan->remote_max_tx) { 15758c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); 15766be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 15778d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 15780a708f8fSGustavo F. Padovan return; 15790a708f8fSGustavo F. Padovan } 15800a708f8fSGustavo F. Padovan 15816a026610SGustavo F. Padovan chan->retry_count++; 15821a09bcb9SGustavo F. Padovan __set_monitor_timer(chan); 15830a708f8fSGustavo F. Padovan 1584525cd185SGustavo F. Padovan l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); 15856be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 15868d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 15870a708f8fSGustavo F. Padovan } 15880a708f8fSGustavo F. Padovan 1589721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work) 15900a708f8fSGustavo F. Padovan { 1591721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1592721c4181SGustavo F. Padovan retrans_timer.work); 15930a708f8fSGustavo F. Padovan 159449208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 15950a708f8fSGustavo F. Padovan 15966be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 15976be36555SAndrei Emeltchenko 15986a026610SGustavo F. Padovan chan->retry_count = 1; 15991a09bcb9SGustavo F. Padovan __set_monitor_timer(chan); 16000a708f8fSGustavo F. Padovan 1601e2ab4353SGustavo F. Padovan set_bit(CONN_WAIT_F, &chan->conn_state); 16020a708f8fSGustavo F. Padovan 1603525cd185SGustavo F. Padovan l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); 16046be36555SAndrei Emeltchenko 16056be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16068d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 16070a708f8fSGustavo F. Padovan } 16080a708f8fSGustavo F. Padovan 160942e5c802SGustavo F. Padovan static void l2cap_drop_acked_frames(struct l2cap_chan *chan) 16100a708f8fSGustavo F. Padovan { 16110a708f8fSGustavo F. Padovan struct sk_buff *skb; 16120a708f8fSGustavo F. Padovan 161358d35f87SGustavo F. Padovan while ((skb = skb_peek(&chan->tx_q)) && 16146a026610SGustavo F. Padovan chan->unacked_frames) { 16153ce3514fSMat Martineau if (bt_cb(skb)->control.txseq == chan->expected_ack_seq) 16160a708f8fSGustavo F. Padovan break; 16170a708f8fSGustavo F. Padovan 161858d35f87SGustavo F. Padovan skb = skb_dequeue(&chan->tx_q); 16190a708f8fSGustavo F. Padovan kfree_skb(skb); 16200a708f8fSGustavo F. Padovan 16216a026610SGustavo F. Padovan chan->unacked_frames--; 16220a708f8fSGustavo F. Padovan } 16230a708f8fSGustavo F. Padovan 16246a026610SGustavo F. Padovan if (!chan->unacked_frames) 16251a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 16260a708f8fSGustavo F. Padovan } 16270a708f8fSGustavo F. Padovan 162867c9e840SSzymon Janc static void l2cap_streaming_send(struct l2cap_chan *chan) 16290a708f8fSGustavo F. Padovan { 16300a708f8fSGustavo F. Padovan struct sk_buff *skb; 163188843ab0SAndrei Emeltchenko u32 control; 163288843ab0SAndrei Emeltchenko u16 fcs; 16330a708f8fSGustavo F. Padovan 163458d35f87SGustavo F. Padovan while ((skb = skb_dequeue(&chan->tx_q))) { 163588843ab0SAndrei Emeltchenko control = __get_control(chan, skb->data + L2CAP_HDR_SIZE); 1636fb45de7dSAndrei Emeltchenko control |= __set_txseq(chan, chan->next_tx_seq); 163794122bbeSMat Martineau control |= __set_ctrl_sar(chan, bt_cb(skb)->control.sar); 163888843ab0SAndrei Emeltchenko __put_control(chan, control, skb->data + L2CAP_HDR_SIZE); 16390a708f8fSGustavo F. Padovan 164047d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 164103a51213SAndrei Emeltchenko fcs = crc16(0, (u8 *)skb->data, 164203a51213SAndrei Emeltchenko skb->len - L2CAP_FCS_SIZE); 164303a51213SAndrei Emeltchenko put_unaligned_le16(fcs, 164403a51213SAndrei Emeltchenko skb->data + skb->len - L2CAP_FCS_SIZE); 16450a708f8fSGustavo F. Padovan } 16460a708f8fSGustavo F. Padovan 16474343478fSGustavo F. Padovan l2cap_do_send(chan, skb); 16480a708f8fSGustavo F. Padovan 1649836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 16500a708f8fSGustavo F. Padovan } 16510a708f8fSGustavo F. Padovan } 16520a708f8fSGustavo F. Padovan 1653fb45de7dSAndrei Emeltchenko static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq) 16540a708f8fSGustavo F. Padovan { 16550a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 165688843ab0SAndrei Emeltchenko u16 fcs; 165788843ab0SAndrei Emeltchenko u32 control; 16580a708f8fSGustavo F. Padovan 165958d35f87SGustavo F. Padovan skb = skb_peek(&chan->tx_q); 16600a708f8fSGustavo F. Padovan if (!skb) 16610a708f8fSGustavo F. Padovan return; 16620a708f8fSGustavo F. Padovan 16633ce3514fSMat Martineau while (bt_cb(skb)->control.txseq != tx_seq) { 166458d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 16650a708f8fSGustavo F. Padovan return; 16660a708f8fSGustavo F. Padovan 1667d1726b6dSSzymon Janc skb = skb_queue_next(&chan->tx_q, skb); 1668d1726b6dSSzymon Janc } 16690a708f8fSGustavo F. Padovan 16703ce3514fSMat Martineau if (bt_cb(skb)->control.retries == chan->remote_max_tx && 16713ce3514fSMat Martineau chan->remote_max_tx) { 16728c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); 16730a708f8fSGustavo F. Padovan return; 16740a708f8fSGustavo F. Padovan } 16750a708f8fSGustavo F. Padovan 16760a708f8fSGustavo F. Padovan tx_skb = skb_clone(skb, GFP_ATOMIC); 16773ce3514fSMat Martineau bt_cb(skb)->control.retries++; 167888843ab0SAndrei Emeltchenko 167988843ab0SAndrei Emeltchenko control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE); 16807e0ef6eeSAndrei Emeltchenko control &= __get_sar_mask(chan); 16810a708f8fSGustavo F. Padovan 1682e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 168303f6715dSAndrei Emeltchenko control |= __set_ctrl_final(chan); 16840a708f8fSGustavo F. Padovan 16850b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 1686fb45de7dSAndrei Emeltchenko control |= __set_txseq(chan, tx_seq); 16870a708f8fSGustavo F. Padovan 168888843ab0SAndrei Emeltchenko __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE); 16890a708f8fSGustavo F. Padovan 169047d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 169103a51213SAndrei Emeltchenko fcs = crc16(0, (u8 *)tx_skb->data, 169203a51213SAndrei Emeltchenko tx_skb->len - L2CAP_FCS_SIZE); 169303a51213SAndrei Emeltchenko put_unaligned_le16(fcs, 169403a51213SAndrei Emeltchenko tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE); 16950a708f8fSGustavo F. Padovan } 16960a708f8fSGustavo F. Padovan 16974343478fSGustavo F. Padovan l2cap_do_send(chan, tx_skb); 16980a708f8fSGustavo F. Padovan } 16990a708f8fSGustavo F. Padovan 170067c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan) 17010a708f8fSGustavo F. Padovan { 17020a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 170388843ab0SAndrei Emeltchenko u16 fcs; 170488843ab0SAndrei Emeltchenko u32 control; 17050a708f8fSGustavo F. Padovan int nsent = 0; 17060a708f8fSGustavo F. Padovan 170789bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 17080a708f8fSGustavo F. Padovan return -ENOTCONN; 17090a708f8fSGustavo F. Padovan 171094122bbeSMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 171194122bbeSMat Martineau return 0; 171294122bbeSMat Martineau 171358d35f87SGustavo F. Padovan while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) { 17140a708f8fSGustavo F. Padovan 17153ce3514fSMat Martineau if (bt_cb(skb)->control.retries == chan->remote_max_tx && 17163ce3514fSMat Martineau chan->remote_max_tx) { 17178c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); 17180a708f8fSGustavo F. Padovan break; 17190a708f8fSGustavo F. Padovan } 17200a708f8fSGustavo F. Padovan 17210a708f8fSGustavo F. Padovan tx_skb = skb_clone(skb, GFP_ATOMIC); 17220a708f8fSGustavo F. Padovan 17233ce3514fSMat Martineau bt_cb(skb)->control.retries++; 17240a708f8fSGustavo F. Padovan 172588843ab0SAndrei Emeltchenko control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE); 17267e0ef6eeSAndrei Emeltchenko control &= __get_sar_mask(chan); 17270a708f8fSGustavo F. Padovan 1728e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 172903f6715dSAndrei Emeltchenko control |= __set_ctrl_final(chan); 1730e2ab4353SGustavo F. Padovan 17310b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 1732fb45de7dSAndrei Emeltchenko control |= __set_txseq(chan, chan->next_tx_seq); 173394122bbeSMat Martineau control |= __set_ctrl_sar(chan, bt_cb(skb)->control.sar); 17340a708f8fSGustavo F. Padovan 173588843ab0SAndrei Emeltchenko __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE); 17360a708f8fSGustavo F. Padovan 173747d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 173803a51213SAndrei Emeltchenko fcs = crc16(0, (u8 *)skb->data, 173903a51213SAndrei Emeltchenko tx_skb->len - L2CAP_FCS_SIZE); 174003a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb->data + 174103a51213SAndrei Emeltchenko tx_skb->len - L2CAP_FCS_SIZE); 17420a708f8fSGustavo F. Padovan } 17430a708f8fSGustavo F. Padovan 17444343478fSGustavo F. Padovan l2cap_do_send(chan, tx_skb); 17450a708f8fSGustavo F. Padovan 17461a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 17470a708f8fSGustavo F. Padovan 17483ce3514fSMat Martineau bt_cb(skb)->control.txseq = chan->next_tx_seq; 1749836be934SAndrei Emeltchenko 1750836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 17510a708f8fSGustavo F. Padovan 17523ce3514fSMat Martineau if (bt_cb(skb)->control.retries == 1) { 17536a026610SGustavo F. Padovan chan->unacked_frames++; 1754930fa4aeSSzymon Janc 1755930fa4aeSSzymon Janc if (!nsent++) 1756930fa4aeSSzymon Janc __clear_ack_timer(chan); 17578ed7a0aeSSzymon Janc } 175823e9fde2SSuraj Sumangala 17596a026610SGustavo F. Padovan chan->frames_sent++; 17600a708f8fSGustavo F. Padovan 176158d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 176258d35f87SGustavo F. Padovan chan->tx_send_head = NULL; 17630a708f8fSGustavo F. Padovan else 176458d35f87SGustavo F. Padovan chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); 17650a708f8fSGustavo F. Padovan } 17660a708f8fSGustavo F. Padovan 17670a708f8fSGustavo F. Padovan return nsent; 17680a708f8fSGustavo F. Padovan } 17690a708f8fSGustavo F. Padovan 1770525cd185SGustavo F. Padovan static int l2cap_retransmit_frames(struct l2cap_chan *chan) 17710a708f8fSGustavo F. Padovan { 17720a708f8fSGustavo F. Padovan int ret; 17730a708f8fSGustavo F. Padovan 177458d35f87SGustavo F. Padovan if (!skb_queue_empty(&chan->tx_q)) 177558d35f87SGustavo F. Padovan chan->tx_send_head = chan->tx_q.next; 17760a708f8fSGustavo F. Padovan 177742e5c802SGustavo F. Padovan chan->next_tx_seq = chan->expected_ack_seq; 1778525cd185SGustavo F. Padovan ret = l2cap_ertm_send(chan); 17790a708f8fSGustavo F. Padovan return ret; 17800a708f8fSGustavo F. Padovan } 17810a708f8fSGustavo F. Padovan 1782b17e73bbSSzymon Janc static void __l2cap_send_ack(struct l2cap_chan *chan) 17830a708f8fSGustavo F. Padovan { 178488843ab0SAndrei Emeltchenko u32 control = 0; 17850a708f8fSGustavo F. Padovan 17860b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 17870a708f8fSGustavo F. Padovan 1788e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 1789ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); 1790e2ab4353SGustavo F. Padovan set_bit(CONN_RNR_SENT, &chan->conn_state); 1791525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 17920a708f8fSGustavo F. Padovan return; 17930a708f8fSGustavo F. Padovan } 17940a708f8fSGustavo F. Padovan 1795525cd185SGustavo F. Padovan if (l2cap_ertm_send(chan) > 0) 17960a708f8fSGustavo F. Padovan return; 17970a708f8fSGustavo F. Padovan 1798ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 1799525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 18000a708f8fSGustavo F. Padovan } 18010a708f8fSGustavo F. Padovan 1802b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan) 1803b17e73bbSSzymon Janc { 1804b17e73bbSSzymon Janc __clear_ack_timer(chan); 1805b17e73bbSSzymon Janc __l2cap_send_ack(chan); 1806b17e73bbSSzymon Janc } 1807b17e73bbSSzymon Janc 1808525cd185SGustavo F. Padovan static void l2cap_send_srejtail(struct l2cap_chan *chan) 18090a708f8fSGustavo F. Padovan { 18100a708f8fSGustavo F. Padovan struct srej_list *tail; 181188843ab0SAndrei Emeltchenko u32 control; 18120a708f8fSGustavo F. Padovan 1813ab784b73SAndrei Emeltchenko control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ); 181403f6715dSAndrei Emeltchenko control |= __set_ctrl_final(chan); 18150a708f8fSGustavo F. Padovan 181639d5a3eeSGustavo F. Padovan tail = list_entry((&chan->srej_l)->prev, struct srej_list, list); 18170b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, tail->tx_seq); 18180a708f8fSGustavo F. Padovan 1819525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 18200a708f8fSGustavo F. Padovan } 18210a708f8fSGustavo F. Padovan 182204124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, 182304124681SGustavo F. Padovan struct msghdr *msg, int len, 182404124681SGustavo F. Padovan int count, struct sk_buff *skb) 18250a708f8fSGustavo F. Padovan { 18260952a57aSAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 18270a708f8fSGustavo F. Padovan struct sk_buff **frag; 182890338947SGustavo Padovan int sent = 0; 18290a708f8fSGustavo F. Padovan 18300a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) 18310a708f8fSGustavo F. Padovan return -EFAULT; 18320a708f8fSGustavo F. Padovan 18330a708f8fSGustavo F. Padovan sent += count; 18340a708f8fSGustavo F. Padovan len -= count; 18350a708f8fSGustavo F. Padovan 18360a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 18370a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 18380a708f8fSGustavo F. Padovan while (len) { 1839*fbe00700SGustavo Padovan struct sk_buff *tmp; 1840*fbe00700SGustavo Padovan 18410a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 18420a708f8fSGustavo F. Padovan 1843*fbe00700SGustavo Padovan tmp = chan->ops->alloc_skb(chan, count, 184490338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 1845*fbe00700SGustavo Padovan if (IS_ERR(tmp)) 1846*fbe00700SGustavo Padovan return PTR_ERR(tmp); 18472f7719ceSAndrei Emeltchenko 1848*fbe00700SGustavo Padovan *frag = tmp; 1849*fbe00700SGustavo Padovan 18500a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) 18510a708f8fSGustavo F. Padovan return -EFAULT; 18520a708f8fSGustavo F. Padovan 18535e59b791SLuiz Augusto von Dentz (*frag)->priority = skb->priority; 18545e59b791SLuiz Augusto von Dentz 18550a708f8fSGustavo F. Padovan sent += count; 18560a708f8fSGustavo F. Padovan len -= count; 18570a708f8fSGustavo F. Padovan 18580a708f8fSGustavo F. Padovan frag = &(*frag)->next; 18590a708f8fSGustavo F. Padovan } 18600a708f8fSGustavo F. Padovan 18610a708f8fSGustavo F. Padovan return sent; 18620a708f8fSGustavo F. Padovan } 18630a708f8fSGustavo F. Padovan 18645e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, 18655e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 18665e59b791SLuiz Augusto von Dentz u32 priority) 18670a708f8fSGustavo F. Padovan { 18688c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 18690a708f8fSGustavo F. Padovan struct sk_buff *skb; 187003a51213SAndrei Emeltchenko int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; 18710a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 18720a708f8fSGustavo F. Padovan 18736d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d priority %u", chan, (int)len, priority); 18740a708f8fSGustavo F. Padovan 18750a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 18762f7719ceSAndrei Emeltchenko 18772f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 187890338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 187990338947SGustavo Padovan if (IS_ERR(skb)) 188090338947SGustavo Padovan return skb; 18810a708f8fSGustavo F. Padovan 18825e59b791SLuiz Augusto von Dentz skb->priority = priority; 18835e59b791SLuiz Augusto von Dentz 18840a708f8fSGustavo F. Padovan /* Create L2CAP header */ 18850a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 1886fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 1887daf6a78cSAndrei Emeltchenko lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); 1888daf6a78cSAndrei Emeltchenko put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE)); 18890a708f8fSGustavo F. Padovan 18900952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 18910a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 18920a708f8fSGustavo F. Padovan kfree_skb(skb); 18930a708f8fSGustavo F. Padovan return ERR_PTR(err); 18940a708f8fSGustavo F. Padovan } 18950a708f8fSGustavo F. Padovan return skb; 18960a708f8fSGustavo F. Padovan } 18970a708f8fSGustavo F. Padovan 18985e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, 18995e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 19005e59b791SLuiz Augusto von Dentz u32 priority) 19010a708f8fSGustavo F. Padovan { 19028c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 19030a708f8fSGustavo F. Padovan struct sk_buff *skb; 1904f2ba7faeSGustavo Padovan int err, count; 19050a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 19060a708f8fSGustavo F. Padovan 19076d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d", chan, (int)len); 19080a708f8fSGustavo F. Padovan 1909f2ba7faeSGustavo Padovan count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); 19102f7719ceSAndrei Emeltchenko 1911f2ba7faeSGustavo Padovan skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE, 191290338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 191390338947SGustavo Padovan if (IS_ERR(skb)) 191490338947SGustavo Padovan return skb; 19150a708f8fSGustavo F. Padovan 19165e59b791SLuiz Augusto von Dentz skb->priority = priority; 19175e59b791SLuiz Augusto von Dentz 19180a708f8fSGustavo F. Padovan /* Create L2CAP header */ 19190a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 1920fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 19216ff9b5efSGustavo Padovan lh->len = cpu_to_le16(len); 19220a708f8fSGustavo F. Padovan 19230952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 19240a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 19250a708f8fSGustavo F. Padovan kfree_skb(skb); 19260a708f8fSGustavo F. Padovan return ERR_PTR(err); 19270a708f8fSGustavo F. Padovan } 19280a708f8fSGustavo F. Padovan return skb; 19290a708f8fSGustavo F. Padovan } 19300a708f8fSGustavo F. Padovan 1931ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, 1932ab0ff76dSLuiz Augusto von Dentz struct msghdr *msg, size_t len, 193394122bbeSMat Martineau u16 sdulen) 19340a708f8fSGustavo F. Padovan { 19358c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 19360a708f8fSGustavo F. Padovan struct sk_buff *skb; 1937e4ca6d98SAndrei Emeltchenko int err, count, hlen; 19380a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 19390a708f8fSGustavo F. Padovan 19406d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d", chan, (int)len); 19410a708f8fSGustavo F. Padovan 19420a708f8fSGustavo F. Padovan if (!conn) 19430a708f8fSGustavo F. Padovan return ERR_PTR(-ENOTCONN); 19440a708f8fSGustavo F. Padovan 1945e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1946e4ca6d98SAndrei Emeltchenko hlen = L2CAP_EXT_HDR_SIZE; 1947e4ca6d98SAndrei Emeltchenko else 1948e4ca6d98SAndrei Emeltchenko hlen = L2CAP_ENH_HDR_SIZE; 1949e4ca6d98SAndrei Emeltchenko 19500a708f8fSGustavo F. Padovan if (sdulen) 195103a51213SAndrei Emeltchenko hlen += L2CAP_SDULEN_SIZE; 19520a708f8fSGustavo F. Padovan 195347d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 195403a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 19550a708f8fSGustavo F. Padovan 19560a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 19572f7719ceSAndrei Emeltchenko 19582f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 195990338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 196090338947SGustavo Padovan if (IS_ERR(skb)) 196190338947SGustavo Padovan return skb; 19620a708f8fSGustavo F. Padovan 19630a708f8fSGustavo F. Padovan /* Create L2CAP header */ 19640a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 1965fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 19660a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 196788843ab0SAndrei Emeltchenko 196894122bbeSMat Martineau __put_control(chan, 0, skb_put(skb, __ctrl_size(chan))); 196988843ab0SAndrei Emeltchenko 19700a708f8fSGustavo F. Padovan if (sdulen) 197103a51213SAndrei Emeltchenko put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 19720a708f8fSGustavo F. Padovan 19730952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 19740a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 19750a708f8fSGustavo F. Padovan kfree_skb(skb); 19760a708f8fSGustavo F. Padovan return ERR_PTR(err); 19770a708f8fSGustavo F. Padovan } 19780a708f8fSGustavo F. Padovan 197947d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 198003a51213SAndrei Emeltchenko put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE)); 19810a708f8fSGustavo F. Padovan 19823ce3514fSMat Martineau bt_cb(skb)->control.retries = 0; 19830a708f8fSGustavo F. Padovan return skb; 19840a708f8fSGustavo F. Padovan } 19850a708f8fSGustavo F. Padovan 198694122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan, 198794122bbeSMat Martineau struct sk_buff_head *seg_queue, 198894122bbeSMat Martineau struct msghdr *msg, size_t len) 19890a708f8fSGustavo F. Padovan { 19900a708f8fSGustavo F. Padovan struct sk_buff *skb; 199194122bbeSMat Martineau u16 sdu_len; 199294122bbeSMat Martineau size_t pdu_len; 199394122bbeSMat Martineau int err = 0; 199494122bbeSMat Martineau u8 sar; 19950a708f8fSGustavo F. Padovan 199694122bbeSMat Martineau BT_DBG("chan %p, msg %p, len %d", chan, msg, (int)len); 19970a708f8fSGustavo F. Padovan 199894122bbeSMat Martineau /* It is critical that ERTM PDUs fit in a single HCI fragment, 199994122bbeSMat Martineau * so fragmented skbs are not used. The HCI layer's handling 200094122bbeSMat Martineau * of fragmented skbs is not compatible with ERTM's queueing. 200194122bbeSMat Martineau */ 200294122bbeSMat Martineau 200394122bbeSMat Martineau /* PDU size is derived from the HCI MTU */ 200494122bbeSMat Martineau pdu_len = chan->conn->mtu; 200594122bbeSMat Martineau 200694122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); 200794122bbeSMat Martineau 200894122bbeSMat Martineau /* Adjust for largest possible L2CAP overhead. */ 200994122bbeSMat Martineau pdu_len -= L2CAP_EXT_HDR_SIZE + L2CAP_FCS_SIZE; 201094122bbeSMat Martineau 201194122bbeSMat Martineau /* Remote device may have requested smaller PDUs */ 201294122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, chan->remote_mps); 201394122bbeSMat Martineau 201494122bbeSMat Martineau if (len <= pdu_len) { 201594122bbeSMat Martineau sar = L2CAP_SAR_UNSEGMENTED; 201694122bbeSMat Martineau sdu_len = 0; 201794122bbeSMat Martineau pdu_len = len; 201894122bbeSMat Martineau } else { 201994122bbeSMat Martineau sar = L2CAP_SAR_START; 202094122bbeSMat Martineau sdu_len = len; 202194122bbeSMat Martineau pdu_len -= L2CAP_SDULEN_SIZE; 202294122bbeSMat Martineau } 20230a708f8fSGustavo F. Padovan 20240a708f8fSGustavo F. Padovan while (len > 0) { 202594122bbeSMat Martineau skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len); 20260a708f8fSGustavo F. Padovan 20270a708f8fSGustavo F. Padovan if (IS_ERR(skb)) { 202894122bbeSMat Martineau __skb_queue_purge(seg_queue); 20290a708f8fSGustavo F. Padovan return PTR_ERR(skb); 20300a708f8fSGustavo F. Padovan } 20310a708f8fSGustavo F. Padovan 203294122bbeSMat Martineau bt_cb(skb)->control.sar = sar; 203394122bbeSMat Martineau __skb_queue_tail(seg_queue, skb); 20340a708f8fSGustavo F. Padovan 203594122bbeSMat Martineau len -= pdu_len; 203694122bbeSMat Martineau if (sdu_len) { 203794122bbeSMat Martineau sdu_len = 0; 203894122bbeSMat Martineau pdu_len += L2CAP_SDULEN_SIZE; 203994122bbeSMat Martineau } 204094122bbeSMat Martineau 204194122bbeSMat Martineau if (len <= pdu_len) { 204294122bbeSMat Martineau sar = L2CAP_SAR_END; 204394122bbeSMat Martineau pdu_len = len; 204494122bbeSMat Martineau } else { 204594122bbeSMat Martineau sar = L2CAP_SAR_CONTINUE; 204694122bbeSMat Martineau } 204794122bbeSMat Martineau } 204894122bbeSMat Martineau 204994122bbeSMat Martineau return err; 20500a708f8fSGustavo F. Padovan } 20510a708f8fSGustavo F. Padovan 20525e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, 20535e59b791SLuiz Augusto von Dentz u32 priority) 20549a91a04aSGustavo F. Padovan { 20559a91a04aSGustavo F. Padovan struct sk_buff *skb; 20569a91a04aSGustavo F. Padovan int err; 205794122bbeSMat Martineau struct sk_buff_head seg_queue; 20589a91a04aSGustavo F. Padovan 20599a91a04aSGustavo F. Padovan /* Connectionless channel */ 2060715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { 20615e59b791SLuiz Augusto von Dentz skb = l2cap_create_connless_pdu(chan, msg, len, priority); 20629a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 20639a91a04aSGustavo F. Padovan return PTR_ERR(skb); 20649a91a04aSGustavo F. Padovan 20659a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 20669a91a04aSGustavo F. Padovan return len; 20679a91a04aSGustavo F. Padovan } 20689a91a04aSGustavo F. Padovan 20699a91a04aSGustavo F. Padovan switch (chan->mode) { 20709a91a04aSGustavo F. Padovan case L2CAP_MODE_BASIC: 20719a91a04aSGustavo F. Padovan /* Check outgoing MTU */ 20729a91a04aSGustavo F. Padovan if (len > chan->omtu) 20739a91a04aSGustavo F. Padovan return -EMSGSIZE; 20749a91a04aSGustavo F. Padovan 20759a91a04aSGustavo F. Padovan /* Create a basic PDU */ 20765e59b791SLuiz Augusto von Dentz skb = l2cap_create_basic_pdu(chan, msg, len, priority); 20779a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 20789a91a04aSGustavo F. Padovan return PTR_ERR(skb); 20799a91a04aSGustavo F. Padovan 20809a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 20819a91a04aSGustavo F. Padovan err = len; 20829a91a04aSGustavo F. Padovan break; 20839a91a04aSGustavo F. Padovan 20849a91a04aSGustavo F. Padovan case L2CAP_MODE_ERTM: 20859a91a04aSGustavo F. Padovan case L2CAP_MODE_STREAMING: 208694122bbeSMat Martineau /* Check outgoing MTU */ 208794122bbeSMat Martineau if (len > chan->omtu) { 208894122bbeSMat Martineau err = -EMSGSIZE; 20899a91a04aSGustavo F. Padovan break; 20909a91a04aSGustavo F. Padovan } 20919a91a04aSGustavo F. Padovan 209294122bbeSMat Martineau __skb_queue_head_init(&seg_queue); 209394122bbeSMat Martineau 209494122bbeSMat Martineau /* Do segmentation before calling in to the state machine, 209594122bbeSMat Martineau * since it's possible to block while waiting for memory 209694122bbeSMat Martineau * allocation. 209794122bbeSMat Martineau */ 209894122bbeSMat Martineau err = l2cap_segment_sdu(chan, &seg_queue, msg, len); 209994122bbeSMat Martineau 210094122bbeSMat Martineau /* The channel could have been closed while segmenting, 210194122bbeSMat Martineau * check that it is still connected. 210294122bbeSMat Martineau */ 210394122bbeSMat Martineau if (chan->state != BT_CONNECTED) { 210494122bbeSMat Martineau __skb_queue_purge(&seg_queue); 210594122bbeSMat Martineau err = -ENOTCONN; 21069a91a04aSGustavo F. Padovan } 21079a91a04aSGustavo F. Padovan 210894122bbeSMat Martineau if (err) 210994122bbeSMat Martineau break; 211094122bbeSMat Martineau 2111577cfaebSMat Martineau if (chan->mode == L2CAP_MODE_ERTM && chan->tx_send_head == NULL) 2112577cfaebSMat Martineau chan->tx_send_head = seg_queue.next; 211394122bbeSMat Martineau skb_queue_splice_tail_init(&seg_queue, &chan->tx_q); 2114577cfaebSMat Martineau 211594122bbeSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) 21169a91a04aSGustavo F. Padovan err = l2cap_ertm_send(chan); 211794122bbeSMat Martineau else 211894122bbeSMat Martineau l2cap_streaming_send(chan); 211994122bbeSMat Martineau 21209a91a04aSGustavo F. Padovan if (err >= 0) 21219a91a04aSGustavo F. Padovan err = len; 21229a91a04aSGustavo F. Padovan 212394122bbeSMat Martineau /* If the skbs were not queued for sending, they'll still be in 212494122bbeSMat Martineau * seg_queue and need to be purged. 212594122bbeSMat Martineau */ 212694122bbeSMat Martineau __skb_queue_purge(&seg_queue); 21279a91a04aSGustavo F. Padovan break; 21289a91a04aSGustavo F. Padovan 21299a91a04aSGustavo F. Padovan default: 21309a91a04aSGustavo F. Padovan BT_DBG("bad state %1.1x", chan->mode); 21319a91a04aSGustavo F. Padovan err = -EBADFD; 21329a91a04aSGustavo F. Padovan } 21339a91a04aSGustavo F. Padovan 21349a91a04aSGustavo F. Padovan return err; 21359a91a04aSGustavo F. Padovan } 21369a91a04aSGustavo F. Padovan 21370a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */ 21380a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 21390a708f8fSGustavo F. Padovan { 21400a708f8fSGustavo F. Padovan struct sk_buff *nskb; 214148454079SGustavo F. Padovan struct l2cap_chan *chan; 21420a708f8fSGustavo F. Padovan 21430a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 21440a708f8fSGustavo F. Padovan 21453df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 21463d57dc68SGustavo F. Padovan 21473df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 214848454079SGustavo F. Padovan struct sock *sk = chan->sk; 2149715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW) 21500a708f8fSGustavo F. Padovan continue; 21510a708f8fSGustavo F. Padovan 21520a708f8fSGustavo F. Padovan /* Don't send frame to the socket it came from */ 21530a708f8fSGustavo F. Padovan if (skb->sk == sk) 21540a708f8fSGustavo F. Padovan continue; 21550a708f8fSGustavo F. Padovan nskb = skb_clone(skb, GFP_ATOMIC); 21560a708f8fSGustavo F. Padovan if (!nskb) 21570a708f8fSGustavo F. Padovan continue; 21580a708f8fSGustavo F. Padovan 215923070494SGustavo F. Padovan if (chan->ops->recv(chan->data, nskb)) 21600a708f8fSGustavo F. Padovan kfree_skb(nskb); 21610a708f8fSGustavo F. Padovan } 21623d57dc68SGustavo F. Padovan 21633df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 21640a708f8fSGustavo F. Padovan } 21650a708f8fSGustavo F. Padovan 21660a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */ 21670a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 21680a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data) 21690a708f8fSGustavo F. Padovan { 21700a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag; 21710a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd; 21720a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 21730a708f8fSGustavo F. Padovan int len, count; 21740a708f8fSGustavo F. Padovan 21750a708f8fSGustavo F. Padovan BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d", 21760a708f8fSGustavo F. Padovan conn, code, ident, dlen); 21770a708f8fSGustavo F. Padovan 21780a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; 21790a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 21800a708f8fSGustavo F. Padovan 21810a708f8fSGustavo F. Padovan skb = bt_skb_alloc(count, GFP_ATOMIC); 21820a708f8fSGustavo F. Padovan if (!skb) 21830a708f8fSGustavo F. Padovan return NULL; 21840a708f8fSGustavo F. Padovan 21850a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 21860a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); 21873300d9a9SClaudio Takahasi 21883300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 21893300d9a9SClaudio Takahasi lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING); 21903300d9a9SClaudio Takahasi else 21910a708f8fSGustavo F. Padovan lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING); 21920a708f8fSGustavo F. Padovan 21930a708f8fSGustavo F. Padovan cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); 21940a708f8fSGustavo F. Padovan cmd->code = code; 21950a708f8fSGustavo F. Padovan cmd->ident = ident; 21960a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen); 21970a708f8fSGustavo F. Padovan 21980a708f8fSGustavo F. Padovan if (dlen) { 21990a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE; 22000a708f8fSGustavo F. Padovan memcpy(skb_put(skb, count), data, count); 22010a708f8fSGustavo F. Padovan data += count; 22020a708f8fSGustavo F. Padovan } 22030a708f8fSGustavo F. Padovan 22040a708f8fSGustavo F. Padovan len -= skb->len; 22050a708f8fSGustavo F. Padovan 22060a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 22070a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 22080a708f8fSGustavo F. Padovan while (len) { 22090a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 22100a708f8fSGustavo F. Padovan 22110a708f8fSGustavo F. Padovan *frag = bt_skb_alloc(count, GFP_ATOMIC); 22120a708f8fSGustavo F. Padovan if (!*frag) 22130a708f8fSGustavo F. Padovan goto fail; 22140a708f8fSGustavo F. Padovan 22150a708f8fSGustavo F. Padovan memcpy(skb_put(*frag, count), data, count); 22160a708f8fSGustavo F. Padovan 22170a708f8fSGustavo F. Padovan len -= count; 22180a708f8fSGustavo F. Padovan data += count; 22190a708f8fSGustavo F. Padovan 22200a708f8fSGustavo F. Padovan frag = &(*frag)->next; 22210a708f8fSGustavo F. Padovan } 22220a708f8fSGustavo F. Padovan 22230a708f8fSGustavo F. Padovan return skb; 22240a708f8fSGustavo F. Padovan 22250a708f8fSGustavo F. Padovan fail: 22260a708f8fSGustavo F. Padovan kfree_skb(skb); 22270a708f8fSGustavo F. Padovan return NULL; 22280a708f8fSGustavo F. Padovan } 22290a708f8fSGustavo F. Padovan 22300a708f8fSGustavo F. Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val) 22310a708f8fSGustavo F. Padovan { 22320a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 22330a708f8fSGustavo F. Padovan int len; 22340a708f8fSGustavo F. Padovan 22350a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len; 22360a708f8fSGustavo F. Padovan *ptr += len; 22370a708f8fSGustavo F. Padovan 22380a708f8fSGustavo F. Padovan *type = opt->type; 22390a708f8fSGustavo F. Padovan *olen = opt->len; 22400a708f8fSGustavo F. Padovan 22410a708f8fSGustavo F. Padovan switch (opt->len) { 22420a708f8fSGustavo F. Padovan case 1: 22430a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val); 22440a708f8fSGustavo F. Padovan break; 22450a708f8fSGustavo F. Padovan 22460a708f8fSGustavo F. Padovan case 2: 22470a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val); 22480a708f8fSGustavo F. Padovan break; 22490a708f8fSGustavo F. Padovan 22500a708f8fSGustavo F. Padovan case 4: 22510a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val); 22520a708f8fSGustavo F. Padovan break; 22530a708f8fSGustavo F. Padovan 22540a708f8fSGustavo F. Padovan default: 22550a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val; 22560a708f8fSGustavo F. Padovan break; 22570a708f8fSGustavo F. Padovan } 22580a708f8fSGustavo F. Padovan 22590a708f8fSGustavo F. Padovan BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val); 22600a708f8fSGustavo F. Padovan return len; 22610a708f8fSGustavo F. Padovan } 22620a708f8fSGustavo F. Padovan 22630a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) 22640a708f8fSGustavo F. Padovan { 22650a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 22660a708f8fSGustavo F. Padovan 22670a708f8fSGustavo F. Padovan BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val); 22680a708f8fSGustavo F. Padovan 22690a708f8fSGustavo F. Padovan opt->type = type; 22700a708f8fSGustavo F. Padovan opt->len = len; 22710a708f8fSGustavo F. Padovan 22720a708f8fSGustavo F. Padovan switch (len) { 22730a708f8fSGustavo F. Padovan case 1: 22740a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val; 22750a708f8fSGustavo F. Padovan break; 22760a708f8fSGustavo F. Padovan 22770a708f8fSGustavo F. Padovan case 2: 22780a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val); 22790a708f8fSGustavo F. Padovan break; 22800a708f8fSGustavo F. Padovan 22810a708f8fSGustavo F. Padovan case 4: 22820a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val); 22830a708f8fSGustavo F. Padovan break; 22840a708f8fSGustavo F. Padovan 22850a708f8fSGustavo F. Padovan default: 22860a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len); 22870a708f8fSGustavo F. Padovan break; 22880a708f8fSGustavo F. Padovan } 22890a708f8fSGustavo F. Padovan 22900a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len; 22910a708f8fSGustavo F. Padovan } 22920a708f8fSGustavo F. Padovan 2293f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) 2294f89cef09SAndrei Emeltchenko { 2295f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs; 2296f89cef09SAndrei Emeltchenko 2297f89cef09SAndrei Emeltchenko switch (chan->mode) { 2298f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM: 2299f89cef09SAndrei Emeltchenko efs.id = chan->local_id; 2300f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype; 2301f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 2302f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 2303f89cef09SAndrei Emeltchenko efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); 2304f89cef09SAndrei Emeltchenko efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO); 2305f89cef09SAndrei Emeltchenko break; 2306f89cef09SAndrei Emeltchenko 2307f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING: 2308f89cef09SAndrei Emeltchenko efs.id = 1; 2309f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT; 2310f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 2311f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 2312f89cef09SAndrei Emeltchenko efs.acc_lat = 0; 2313f89cef09SAndrei Emeltchenko efs.flush_to = 0; 2314f89cef09SAndrei Emeltchenko break; 2315f89cef09SAndrei Emeltchenko 2316f89cef09SAndrei Emeltchenko default: 2317f89cef09SAndrei Emeltchenko return; 2318f89cef09SAndrei Emeltchenko } 2319f89cef09SAndrei Emeltchenko 2320f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), 2321f89cef09SAndrei Emeltchenko (unsigned long) &efs); 2322f89cef09SAndrei Emeltchenko } 2323f89cef09SAndrei Emeltchenko 2324721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work) 23250a708f8fSGustavo F. Padovan { 2326721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 2327721c4181SGustavo F. Padovan ack_timer.work); 23280a708f8fSGustavo F. Padovan 23292fb9b3d4SGustavo F. Padovan BT_DBG("chan %p", chan); 23302fb9b3d4SGustavo F. Padovan 23316be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 23326be36555SAndrei Emeltchenko 2333b17e73bbSSzymon Janc __l2cap_send_ack(chan); 23346be36555SAndrei Emeltchenko 23356be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 233609bfb2eeSSzymon Janc 233709bfb2eeSSzymon Janc l2cap_chan_put(chan); 23380a708f8fSGustavo F. Padovan } 23390a708f8fSGustavo F. Padovan 23403c588192SMat Martineau static inline int l2cap_ertm_init(struct l2cap_chan *chan) 23410a708f8fSGustavo F. Padovan { 23423c588192SMat Martineau int err; 23433c588192SMat Martineau 2344105bdf9eSMat Martineau chan->next_tx_seq = 0; 2345105bdf9eSMat Martineau chan->expected_tx_seq = 0; 234642e5c802SGustavo F. Padovan chan->expected_ack_seq = 0; 23476a026610SGustavo F. Padovan chan->unacked_frames = 0; 234842e5c802SGustavo F. Padovan chan->buffer_seq = 0; 23496a026610SGustavo F. Padovan chan->num_acked = 0; 23506a026610SGustavo F. Padovan chan->frames_sent = 0; 2351105bdf9eSMat Martineau chan->last_acked_seq = 0; 2352105bdf9eSMat Martineau chan->sdu = NULL; 2353105bdf9eSMat Martineau chan->sdu_last_frag = NULL; 2354105bdf9eSMat Martineau chan->sdu_len = 0; 2355105bdf9eSMat Martineau 2356d34c34fbSMat Martineau skb_queue_head_init(&chan->tx_q); 2357d34c34fbSMat Martineau 2358105bdf9eSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 2359105bdf9eSMat Martineau return 0; 2360105bdf9eSMat Martineau 2361105bdf9eSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2362105bdf9eSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 23630a708f8fSGustavo F. Padovan 2364721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout); 2365721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout); 2366721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout); 23670a708f8fSGustavo F. Padovan 2368f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q); 23690a708f8fSGustavo F. Padovan 237039d5a3eeSGustavo F. Padovan INIT_LIST_HEAD(&chan->srej_l); 23713c588192SMat Martineau err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win); 23723c588192SMat Martineau if (err < 0) 23733c588192SMat Martineau return err; 23743c588192SMat Martineau 23753c588192SMat Martineau return l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win); 23760a708f8fSGustavo F. Padovan } 23770a708f8fSGustavo F. Padovan 23780a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) 23790a708f8fSGustavo F. Padovan { 23800a708f8fSGustavo F. Padovan switch (mode) { 23810a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 23820a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 23830a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask)) 23840a708f8fSGustavo F. Padovan return mode; 23850a708f8fSGustavo F. Padovan /* fall through */ 23860a708f8fSGustavo F. Padovan default: 23870a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC; 23880a708f8fSGustavo F. Padovan } 23890a708f8fSGustavo F. Padovan } 23900a708f8fSGustavo F. Padovan 23916327eb98SAndrei Emeltchenko static inline bool __l2cap_ews_supported(struct l2cap_chan *chan) 23926327eb98SAndrei Emeltchenko { 23936327eb98SAndrei Emeltchenko return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW; 23946327eb98SAndrei Emeltchenko } 23956327eb98SAndrei Emeltchenko 2396f89cef09SAndrei Emeltchenko static inline bool __l2cap_efs_supported(struct l2cap_chan *chan) 2397f89cef09SAndrei Emeltchenko { 2398f89cef09SAndrei Emeltchenko return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW; 2399f89cef09SAndrei Emeltchenko } 2400f89cef09SAndrei Emeltchenko 24016327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan) 24026327eb98SAndrei Emeltchenko { 24036327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && 2404836be934SAndrei Emeltchenko __l2cap_ews_supported(chan)) { 24056327eb98SAndrei Emeltchenko /* use extended control field */ 24066327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 2407836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 2408836be934SAndrei Emeltchenko } else { 24096327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win, 24106327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 2411836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 2412836be934SAndrei Emeltchenko } 24136327eb98SAndrei Emeltchenko } 24146327eb98SAndrei Emeltchenko 2415710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) 24160a708f8fSGustavo F. Padovan { 24170a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 24180c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode }; 24190a708f8fSGustavo F. Padovan void *ptr = req->data; 2420c8f79162SAndrei Emeltchenko u16 size; 24210a708f8fSGustavo F. Padovan 242249208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 24230a708f8fSGustavo F. Padovan 242473ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp) 24250a708f8fSGustavo F. Padovan goto done; 24260a708f8fSGustavo F. Padovan 24270c1bc5c6SGustavo F. Padovan switch (chan->mode) { 24280a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 24290a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 2430c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) 24310a708f8fSGustavo F. Padovan break; 24320a708f8fSGustavo F. Padovan 2433f89cef09SAndrei Emeltchenko if (__l2cap_efs_supported(chan)) 2434f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 2435f89cef09SAndrei Emeltchenko 24360a708f8fSGustavo F. Padovan /* fall through */ 24370a708f8fSGustavo F. Padovan default: 24388c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); 24390a708f8fSGustavo F. Padovan break; 24400a708f8fSGustavo F. Padovan } 24410a708f8fSGustavo F. Padovan 24420a708f8fSGustavo F. Padovan done: 24430c1bc5c6SGustavo F. Padovan if (chan->imtu != L2CAP_DEFAULT_MTU) 24440c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 24450a708f8fSGustavo F. Padovan 24460c1bc5c6SGustavo F. Padovan switch (chan->mode) { 24470a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 24488c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && 24498c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) 24500a708f8fSGustavo F. Padovan break; 24510a708f8fSGustavo F. Padovan 24520a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC; 24530a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 24540a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 24550a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 24560a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 24570a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0; 24580a708f8fSGustavo F. Padovan 24590a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 24600a708f8fSGustavo F. Padovan (unsigned long) &rfc); 24610a708f8fSGustavo F. Padovan break; 24620a708f8fSGustavo F. Padovan 24630a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 24640a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM; 246547d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx; 24660a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 24670a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 2468c8f79162SAndrei Emeltchenko 2469c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 2470c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2471c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2472c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2473c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 24740a708f8fSGustavo F. Padovan 24756327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan); 24766327eb98SAndrei Emeltchenko 24776327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win, 24786327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 24790a708f8fSGustavo F. Padovan 24800a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 24810a708f8fSGustavo F. Padovan (unsigned long) &rfc); 24820a708f8fSGustavo F. Padovan 2483f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 2484f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 2485f89cef09SAndrei Emeltchenko 24868c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) 24870a708f8fSGustavo F. Padovan break; 24880a708f8fSGustavo F. Padovan 248947d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 2490c1360a1cSGustavo F. Padovan test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { 249147d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 249247d1ec61SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); 24930a708f8fSGustavo F. Padovan } 24946327eb98SAndrei Emeltchenko 24956327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 24966327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 24976327eb98SAndrei Emeltchenko chan->tx_win); 24980a708f8fSGustavo F. Padovan break; 24990a708f8fSGustavo F. Padovan 25000a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 25010a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING; 25020a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 25030a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 25040a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 25050a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 2506c8f79162SAndrei Emeltchenko 2507c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 2508c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2509c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2510c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2511c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 25120a708f8fSGustavo F. Padovan 25130a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 25140a708f8fSGustavo F. Padovan (unsigned long) &rfc); 25150a708f8fSGustavo F. Padovan 2516f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 2517f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 2518f89cef09SAndrei Emeltchenko 25198c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) 25200a708f8fSGustavo F. Padovan break; 25210a708f8fSGustavo F. Padovan 252247d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 2523c1360a1cSGustavo F. Padovan test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { 252447d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 252547d1ec61SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); 25260a708f8fSGustavo F. Padovan } 25270a708f8fSGustavo F. Padovan break; 25280a708f8fSGustavo F. Padovan } 25290a708f8fSGustavo F. Padovan 2530fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 25310a708f8fSGustavo F. Padovan req->flags = cpu_to_le16(0); 25320a708f8fSGustavo F. Padovan 25330a708f8fSGustavo F. Padovan return ptr - data; 25340a708f8fSGustavo F. Padovan } 25350a708f8fSGustavo F. Padovan 253673ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) 25370a708f8fSGustavo F. Padovan { 25380a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 25390a708f8fSGustavo F. Padovan void *ptr = rsp->data; 254073ffa904SGustavo F. Padovan void *req = chan->conf_req; 254173ffa904SGustavo F. Padovan int len = chan->conf_len; 25420a708f8fSGustavo F. Padovan int type, hint, olen; 25430a708f8fSGustavo F. Padovan unsigned long val; 25440a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 254542dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs; 254642dceae2SAndrei Emeltchenko u8 remote_efs = 0; 25470a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU; 25480a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS; 2549c8f79162SAndrei Emeltchenko u16 size; 25500a708f8fSGustavo F. Padovan 255173ffa904SGustavo F. Padovan BT_DBG("chan %p", chan); 25520a708f8fSGustavo F. Padovan 25530a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 25540a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val); 25550a708f8fSGustavo F. Padovan 25560a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT; 25570a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK; 25580a708f8fSGustavo F. Padovan 25590a708f8fSGustavo F. Padovan switch (type) { 25600a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 25610a708f8fSGustavo F. Padovan mtu = val; 25620a708f8fSGustavo F. Padovan break; 25630a708f8fSGustavo F. Padovan 25640a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 25650c1bc5c6SGustavo F. Padovan chan->flush_to = val; 25660a708f8fSGustavo F. Padovan break; 25670a708f8fSGustavo F. Padovan 25680a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS: 25690a708f8fSGustavo F. Padovan break; 25700a708f8fSGustavo F. Padovan 25710a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 25720a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 25730a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen); 25740a708f8fSGustavo F. Padovan break; 25750a708f8fSGustavo F. Padovan 25760a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS: 25770a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE) 2578c1360a1cSGustavo F. Padovan set_bit(CONF_NO_FCS_RECV, &chan->conf_state); 257942dceae2SAndrei Emeltchenko break; 25800a708f8fSGustavo F. Padovan 258142dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS: 258242dceae2SAndrei Emeltchenko remote_efs = 1; 258342dceae2SAndrei Emeltchenko if (olen == sizeof(efs)) 258442dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen); 25850a708f8fSGustavo F. Padovan break; 25860a708f8fSGustavo F. Padovan 25876327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 25886327eb98SAndrei Emeltchenko if (!enable_hs) 25896327eb98SAndrei Emeltchenko return -ECONNREFUSED; 25906327eb98SAndrei Emeltchenko 25916327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 25926327eb98SAndrei Emeltchenko set_bit(CONF_EWS_RECV, &chan->conf_state); 2593836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 25946327eb98SAndrei Emeltchenko chan->remote_tx_win = val; 25950a708f8fSGustavo F. Padovan break; 25960a708f8fSGustavo F. Padovan 25970a708f8fSGustavo F. Padovan default: 25980a708f8fSGustavo F. Padovan if (hint) 25990a708f8fSGustavo F. Padovan break; 26000a708f8fSGustavo F. Padovan 26010a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN; 26020a708f8fSGustavo F. Padovan *((u8 *) ptr++) = type; 26030a708f8fSGustavo F. Padovan break; 26040a708f8fSGustavo F. Padovan } 26050a708f8fSGustavo F. Padovan } 26060a708f8fSGustavo F. Padovan 260773ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1) 26080a708f8fSGustavo F. Padovan goto done; 26090a708f8fSGustavo F. Padovan 26100c1bc5c6SGustavo F. Padovan switch (chan->mode) { 26110a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 26120a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 2613c1360a1cSGustavo F. Padovan if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { 26140c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, 26158c1d787bSGustavo F. Padovan chan->conn->feat_mask); 26160a708f8fSGustavo F. Padovan break; 26170a708f8fSGustavo F. Padovan } 26180a708f8fSGustavo F. Padovan 261942dceae2SAndrei Emeltchenko if (remote_efs) { 262042dceae2SAndrei Emeltchenko if (__l2cap_efs_supported(chan)) 262142dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 262242dceae2SAndrei Emeltchenko else 262342dceae2SAndrei Emeltchenko return -ECONNREFUSED; 262442dceae2SAndrei Emeltchenko } 262542dceae2SAndrei Emeltchenko 26260c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) 26270a708f8fSGustavo F. Padovan return -ECONNREFUSED; 26280a708f8fSGustavo F. Padovan 26290a708f8fSGustavo F. Padovan break; 26300a708f8fSGustavo F. Padovan } 26310a708f8fSGustavo F. Padovan 26320a708f8fSGustavo F. Padovan done: 26330c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) { 26340a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 26350c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 26360a708f8fSGustavo F. Padovan 263773ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1) 26380a708f8fSGustavo F. Padovan return -ECONNREFUSED; 26390a708f8fSGustavo F. Padovan 26400a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 26410a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 26420a708f8fSGustavo F. Padovan } 26430a708f8fSGustavo F. Padovan 26440a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) { 26450a708f8fSGustavo F. Padovan /* Configure output options and let the other side know 26460a708f8fSGustavo F. Padovan * which ones we don't like. */ 26470a708f8fSGustavo F. Padovan 26480a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU) 26490a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 26500a708f8fSGustavo F. Padovan else { 26510c1bc5c6SGustavo F. Padovan chan->omtu = mtu; 2652c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state); 26530a708f8fSGustavo F. Padovan } 26540c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); 26550a708f8fSGustavo F. Padovan 265642dceae2SAndrei Emeltchenko if (remote_efs) { 265742dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 265842dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 265942dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) { 266042dceae2SAndrei Emeltchenko 266142dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT; 266242dceae2SAndrei Emeltchenko 266342dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1) 266442dceae2SAndrei Emeltchenko return -ECONNREFUSED; 266542dceae2SAndrei Emeltchenko 266642dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 266742dceae2SAndrei Emeltchenko sizeof(efs), 266842dceae2SAndrei Emeltchenko (unsigned long) &efs); 26690e8b207eSAndrei Emeltchenko } else { 26703e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */ 26710e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING; 26720e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 267342dceae2SAndrei Emeltchenko } 267442dceae2SAndrei Emeltchenko } 267542dceae2SAndrei Emeltchenko 26760a708f8fSGustavo F. Padovan switch (rfc.mode) { 26770a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 267847d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 2679c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 26800a708f8fSGustavo F. Padovan break; 26810a708f8fSGustavo F. Padovan 26820a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 26836327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state)) 26842c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size; 26856327eb98SAndrei Emeltchenko else 26866327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; 26876327eb98SAndrei Emeltchenko 26882c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit; 26890a708f8fSGustavo F. Padovan 2690c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 2691c8f79162SAndrei Emeltchenko chan->conn->mtu - 2692c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2693c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2694c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2695c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 2696c8f79162SAndrei Emeltchenko chan->remote_mps = size; 26970a708f8fSGustavo F. Padovan 26980a708f8fSGustavo F. Padovan rfc.retrans_timeout = 26994fd21a88SAndrei Emeltchenko __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 27000a708f8fSGustavo F. Padovan rfc.monitor_timeout = 27014fd21a88SAndrei Emeltchenko __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 27020a708f8fSGustavo F. Padovan 2703c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 27040a708f8fSGustavo F. Padovan 27050a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 27060a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 27070a708f8fSGustavo F. Padovan 270842dceae2SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 270942dceae2SAndrei Emeltchenko chan->remote_id = efs.id; 271042dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype; 271142dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu); 271242dceae2SAndrei Emeltchenko chan->remote_flush_to = 271342dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to); 271442dceae2SAndrei Emeltchenko chan->remote_acc_lat = 271542dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat); 271642dceae2SAndrei Emeltchenko chan->remote_sdu_itime = 271742dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 271842dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 271942dceae2SAndrei Emeltchenko sizeof(efs), (unsigned long) &efs); 272042dceae2SAndrei Emeltchenko } 27210a708f8fSGustavo F. Padovan break; 27220a708f8fSGustavo F. Padovan 27230a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 2724c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 2725c8f79162SAndrei Emeltchenko chan->conn->mtu - 2726c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2727c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2728c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2729c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 2730c8f79162SAndrei Emeltchenko chan->remote_mps = size; 27310a708f8fSGustavo F. Padovan 2732c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 27330a708f8fSGustavo F. Padovan 27340a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 27350a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 27360a708f8fSGustavo F. Padovan 27370a708f8fSGustavo F. Padovan break; 27380a708f8fSGustavo F. Padovan 27390a708f8fSGustavo F. Padovan default: 27400a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 27410a708f8fSGustavo F. Padovan 27420a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc)); 27430c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 27440a708f8fSGustavo F. Padovan } 27450a708f8fSGustavo F. Padovan 27460a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) 2747c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 27480a708f8fSGustavo F. Padovan } 2749fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 27500a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 27510a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(0x0000); 27520a708f8fSGustavo F. Padovan 27530a708f8fSGustavo F. Padovan return ptr - data; 27540a708f8fSGustavo F. Padovan } 27550a708f8fSGustavo F. Padovan 2756b4450035SGustavo F. Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result) 27570a708f8fSGustavo F. Padovan { 27580a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 27590a708f8fSGustavo F. Padovan void *ptr = req->data; 27600a708f8fSGustavo F. Padovan int type, olen; 27610a708f8fSGustavo F. Padovan unsigned long val; 276236e999a8SMat Martineau struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 276366af7aafSAndrei Emeltchenko struct l2cap_conf_efs efs; 27640a708f8fSGustavo F. Padovan 2765fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); 27660a708f8fSGustavo F. Padovan 27670a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 27680a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 27690a708f8fSGustavo F. Padovan 27700a708f8fSGustavo F. Padovan switch (type) { 27710a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 27720a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) { 27730a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT; 27740c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU; 27750a708f8fSGustavo F. Padovan } else 27760c1bc5c6SGustavo F. Padovan chan->imtu = val; 27770c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 27780a708f8fSGustavo F. Padovan break; 27790a708f8fSGustavo F. Padovan 27800a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 27810c1bc5c6SGustavo F. Padovan chan->flush_to = val; 27820a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 27830c1bc5c6SGustavo F. Padovan 2, chan->flush_to); 27840a708f8fSGustavo F. Padovan break; 27850a708f8fSGustavo F. Padovan 27860a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 27870a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 27880a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 27890a708f8fSGustavo F. Padovan 2790c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && 27910c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode) 27920a708f8fSGustavo F. Padovan return -ECONNREFUSED; 27930a708f8fSGustavo F. Padovan 279447d1ec61SGustavo F. Padovan chan->fcs = 0; 27950a708f8fSGustavo F. Padovan 27960a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 27970a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 27980a708f8fSGustavo F. Padovan break; 27996327eb98SAndrei Emeltchenko 28006327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 28016327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, val, 28026327eb98SAndrei Emeltchenko L2CAP_DEFAULT_EXT_WINDOW); 28033e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 28043e6b3b95SGustavo F. Padovan chan->tx_win); 28056327eb98SAndrei Emeltchenko break; 280666af7aafSAndrei Emeltchenko 280766af7aafSAndrei Emeltchenko case L2CAP_CONF_EFS: 280866af7aafSAndrei Emeltchenko if (olen == sizeof(efs)) 280966af7aafSAndrei Emeltchenko memcpy(&efs, (void *)val, olen); 281066af7aafSAndrei Emeltchenko 281166af7aafSAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 281266af7aafSAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 281366af7aafSAndrei Emeltchenko efs.stype != chan->local_stype) 281466af7aafSAndrei Emeltchenko return -ECONNREFUSED; 281566af7aafSAndrei Emeltchenko 281666af7aafSAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 281766af7aafSAndrei Emeltchenko sizeof(efs), (unsigned long) &efs); 281866af7aafSAndrei Emeltchenko break; 28190a708f8fSGustavo F. Padovan } 28200a708f8fSGustavo F. Padovan } 28210a708f8fSGustavo F. Padovan 28220c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) 28230a708f8fSGustavo F. Padovan return -ECONNREFUSED; 28240a708f8fSGustavo F. Padovan 28250c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode; 28260a708f8fSGustavo F. Padovan 28270e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) { 28280a708f8fSGustavo F. Padovan switch (rfc.mode) { 28290a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 283047d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 283147d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 283247d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 283366af7aafSAndrei Emeltchenko 283466af7aafSAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 283566af7aafSAndrei Emeltchenko chan->local_msdu = le16_to_cpu(efs.msdu); 283666af7aafSAndrei Emeltchenko chan->local_sdu_itime = 283766af7aafSAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 283866af7aafSAndrei Emeltchenko chan->local_acc_lat = le32_to_cpu(efs.acc_lat); 283966af7aafSAndrei Emeltchenko chan->local_flush_to = 284066af7aafSAndrei Emeltchenko le32_to_cpu(efs.flush_to); 284166af7aafSAndrei Emeltchenko } 28420a708f8fSGustavo F. Padovan break; 284366af7aafSAndrei Emeltchenko 28440a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 284547d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 28460a708f8fSGustavo F. Padovan } 28470a708f8fSGustavo F. Padovan } 28480a708f8fSGustavo F. Padovan 2849fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 28500a708f8fSGustavo F. Padovan req->flags = cpu_to_le16(0x0000); 28510a708f8fSGustavo F. Padovan 28520a708f8fSGustavo F. Padovan return ptr - data; 28530a708f8fSGustavo F. Padovan } 28540a708f8fSGustavo F. Padovan 2855fe4128e0SGustavo F. Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags) 28560a708f8fSGustavo F. Padovan { 28570a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 28580a708f8fSGustavo F. Padovan void *ptr = rsp->data; 28590a708f8fSGustavo F. Padovan 2860fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan); 28610a708f8fSGustavo F. Padovan 2862fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 28630a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 28640a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags); 28650a708f8fSGustavo F. Padovan 28660a708f8fSGustavo F. Padovan return ptr - data; 28670a708f8fSGustavo F. Padovan } 28680a708f8fSGustavo F. Padovan 28698c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) 2870710f9b0aSGustavo F. Padovan { 2871710f9b0aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 28728c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 2873710f9b0aSGustavo F. Padovan u8 buf[128]; 2874710f9b0aSGustavo F. Padovan 2875fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 2876fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 2877710f9b0aSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 2878710f9b0aSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 2879710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, 2880710f9b0aSGustavo F. Padovan L2CAP_CONN_RSP, sizeof(rsp), &rsp); 2881710f9b0aSGustavo F. Padovan 2882c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 2883710f9b0aSGustavo F. Padovan return; 2884710f9b0aSGustavo F. Padovan 2885710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 2886710f9b0aSGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 2887710f9b0aSGustavo F. Padovan chan->num_conf_req++; 2888710f9b0aSGustavo F. Padovan } 2889710f9b0aSGustavo F. Padovan 289047d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) 28910a708f8fSGustavo F. Padovan { 28920a708f8fSGustavo F. Padovan int type, olen; 28930a708f8fSGustavo F. Padovan unsigned long val; 28940a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc; 28950a708f8fSGustavo F. Padovan 289647d1ec61SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); 28970a708f8fSGustavo F. Padovan 28980c1bc5c6SGustavo F. Padovan if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) 28990a708f8fSGustavo F. Padovan return; 29000a708f8fSGustavo F. Padovan 29010a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 29020a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 29030a708f8fSGustavo F. Padovan 29040a708f8fSGustavo F. Padovan switch (type) { 29050a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 29060a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 29070a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 29080a708f8fSGustavo F. Padovan goto done; 29090a708f8fSGustavo F. Padovan } 29100a708f8fSGustavo F. Padovan } 29110a708f8fSGustavo F. Padovan 291236e999a8SMat Martineau /* Use sane default values in case a misbehaving remote device 291336e999a8SMat Martineau * did not send an RFC option. 291436e999a8SMat Martineau */ 291536e999a8SMat Martineau rfc.mode = chan->mode; 291636e999a8SMat Martineau rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 291736e999a8SMat Martineau rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 291836e999a8SMat Martineau rfc.max_pdu_size = cpu_to_le16(chan->imtu); 291936e999a8SMat Martineau 292036e999a8SMat Martineau BT_ERR("Expected RFC option was not found, using defaults"); 292136e999a8SMat Martineau 29220a708f8fSGustavo F. Padovan done: 29230a708f8fSGustavo F. Padovan switch (rfc.mode) { 29240a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 292547d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 292647d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 292747d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 29280a708f8fSGustavo F. Padovan break; 29290a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 293047d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 29310a708f8fSGustavo F. Padovan } 29320a708f8fSGustavo F. Padovan } 29330a708f8fSGustavo F. Padovan 29340a708f8fSGustavo F. Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 29350a708f8fSGustavo F. Padovan { 2936e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 29370a708f8fSGustavo F. Padovan 2938e2fd318eSIlia Kolomisnky if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) 29390a708f8fSGustavo F. Padovan return 0; 29400a708f8fSGustavo F. Padovan 29410a708f8fSGustavo F. Padovan if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && 29420a708f8fSGustavo F. Padovan cmd->ident == conn->info_ident) { 294317cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 29440a708f8fSGustavo F. Padovan 29450a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 29460a708f8fSGustavo F. Padovan conn->info_ident = 0; 29470a708f8fSGustavo F. Padovan 29480a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 29490a708f8fSGustavo F. Padovan } 29500a708f8fSGustavo F. Padovan 29510a708f8fSGustavo F. Padovan return 0; 29520a708f8fSGustavo F. Padovan } 29530a708f8fSGustavo F. Padovan 29540a708f8fSGustavo F. Padovan static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 29550a708f8fSGustavo F. Padovan { 29560a708f8fSGustavo F. Padovan struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 29570a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 295823691d75SGustavo F. Padovan struct l2cap_chan *chan = NULL, *pchan; 29590a708f8fSGustavo F. Padovan struct sock *parent, *sk = NULL; 29600a708f8fSGustavo F. Padovan int result, status = L2CAP_CS_NO_INFO; 29610a708f8fSGustavo F. Padovan 29620a708f8fSGustavo F. Padovan u16 dcid = 0, scid = __le16_to_cpu(req->scid); 29630a708f8fSGustavo F. Padovan __le16 psm = req->psm; 29640a708f8fSGustavo F. Padovan 2965097db76cSAndrei Emeltchenko BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); 29660a708f8fSGustavo F. Padovan 29670a708f8fSGustavo F. Padovan /* Check if we have socket listening on psm */ 2968c2287681SIdo Yariv pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst); 296923691d75SGustavo F. Padovan if (!pchan) { 29700a708f8fSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 29710a708f8fSGustavo F. Padovan goto sendresp; 29720a708f8fSGustavo F. Padovan } 29730a708f8fSGustavo F. Padovan 297423691d75SGustavo F. Padovan parent = pchan->sk; 297523691d75SGustavo F. Padovan 29763df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 2977aa2ac881SGustavo F. Padovan lock_sock(parent); 29780a708f8fSGustavo F. Padovan 29790a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */ 29800a708f8fSGustavo F. Padovan if (psm != cpu_to_le16(0x0001) && 29810a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) { 29829f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_AUTH_FAILURE; 29830a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 29840a708f8fSGustavo F. Padovan goto response; 29850a708f8fSGustavo F. Padovan } 29860a708f8fSGustavo F. Padovan 29870a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM; 29880a708f8fSGustavo F. Padovan 29890a708f8fSGustavo F. Padovan /* Check for backlog size */ 29900a708f8fSGustavo F. Padovan if (sk_acceptq_is_full(parent)) { 29910a708f8fSGustavo F. Padovan BT_DBG("backlog full %d", parent->sk_ack_backlog); 29920a708f8fSGustavo F. Padovan goto response; 29930a708f8fSGustavo F. Padovan } 29940a708f8fSGustavo F. Padovan 299580808e43SGustavo F. Padovan chan = pchan->ops->new_connection(pchan->data); 299680808e43SGustavo F. Padovan if (!chan) 29970a708f8fSGustavo F. Padovan goto response; 29980a708f8fSGustavo F. Padovan 299980808e43SGustavo F. Padovan sk = chan->sk; 300080808e43SGustavo F. Padovan 30010a708f8fSGustavo F. Padovan /* Check if we already have channel with that dcid */ 3002baa7e1faSGustavo F. Padovan if (__l2cap_get_chan_by_dcid(conn, scid)) { 30030a708f8fSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 3004ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 30050a708f8fSGustavo F. Padovan goto response; 30060a708f8fSGustavo F. Padovan } 30070a708f8fSGustavo F. Padovan 30080a708f8fSGustavo F. Padovan hci_conn_hold(conn->hcon); 30090a708f8fSGustavo F. Padovan 30100a708f8fSGustavo F. Padovan bacpy(&bt_sk(sk)->src, conn->src); 30110a708f8fSGustavo F. Padovan bacpy(&bt_sk(sk)->dst, conn->dst); 3012fe4128e0SGustavo F. Padovan chan->psm = psm; 3013fe4128e0SGustavo F. Padovan chan->dcid = scid; 30140a708f8fSGustavo F. Padovan 3015d1010240SGustavo F. Padovan bt_accept_enqueue(parent, sk); 3016d1010240SGustavo F. Padovan 30176be36555SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 301848454079SGustavo F. Padovan 3019fe4128e0SGustavo F. Padovan dcid = chan->scid; 30200a708f8fSGustavo F. Padovan 3021c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 30220a708f8fSGustavo F. Padovan 3023fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident; 30240a708f8fSGustavo F. Padovan 30250a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { 3026d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 30270a708f8fSGustavo F. Padovan if (bt_sk(sk)->defer_setup) { 30280e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 30290a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 30300a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND; 30310a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 30320a708f8fSGustavo F. Padovan } else { 30330e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 30340a708f8fSGustavo F. Padovan result = L2CAP_CR_SUCCESS; 30350a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 30360a708f8fSGustavo F. Padovan } 30370a708f8fSGustavo F. Padovan } else { 30380e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 30390a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 30400a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND; 30410a708f8fSGustavo F. Padovan } 30420a708f8fSGustavo F. Padovan } else { 30430e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 30440a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 30450a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 30460a708f8fSGustavo F. Padovan } 30470a708f8fSGustavo F. Padovan 30480a708f8fSGustavo F. Padovan response: 3049aa2ac881SGustavo F. Padovan release_sock(parent); 30503df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 30510a708f8fSGustavo F. Padovan 30520a708f8fSGustavo F. Padovan sendresp: 30530a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid); 30540a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid); 30550a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result); 30560a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status); 30570a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); 30580a708f8fSGustavo F. Padovan 30590a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { 30600a708f8fSGustavo F. Padovan struct l2cap_info_req info; 30610a708f8fSGustavo F. Padovan info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 30620a708f8fSGustavo F. Padovan 30630a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 30640a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 30650a708f8fSGustavo F. Padovan 3066ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 30670a708f8fSGustavo F. Padovan 30680a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 30690a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(info), &info); 30700a708f8fSGustavo F. Padovan } 30710a708f8fSGustavo F. Padovan 3072c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && 30730a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) { 30740a708f8fSGustavo F. Padovan u8 buf[128]; 3075c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 30760a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 307773ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 307873ffa904SGustavo F. Padovan chan->num_conf_req++; 30790a708f8fSGustavo F. Padovan } 30800a708f8fSGustavo F. Padovan 30810a708f8fSGustavo F. Padovan return 0; 30820a708f8fSGustavo F. Padovan } 30830a708f8fSGustavo F. Padovan 30840a708f8fSGustavo F. Padovan static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 30850a708f8fSGustavo F. Padovan { 30860a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; 30870a708f8fSGustavo F. Padovan u16 scid, dcid, result, status; 308848454079SGustavo F. Padovan struct l2cap_chan *chan; 30890a708f8fSGustavo F. Padovan u8 req[128]; 30903df91ea2SAndrei Emeltchenko int err; 30910a708f8fSGustavo F. Padovan 30920a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 30930a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 30940a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 30950a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status); 30960a708f8fSGustavo F. Padovan 30971b009c98SAndrei Emeltchenko BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", 30981b009c98SAndrei Emeltchenko dcid, scid, result, status); 30990a708f8fSGustavo F. Padovan 31003df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 31013df91ea2SAndrei Emeltchenko 31020a708f8fSGustavo F. Padovan if (scid) { 31033df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 31043df91ea2SAndrei Emeltchenko if (!chan) { 31053df91ea2SAndrei Emeltchenko err = -EFAULT; 31063df91ea2SAndrei Emeltchenko goto unlock; 31073df91ea2SAndrei Emeltchenko } 31080a708f8fSGustavo F. Padovan } else { 31093df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 31103df91ea2SAndrei Emeltchenko if (!chan) { 31113df91ea2SAndrei Emeltchenko err = -EFAULT; 31123df91ea2SAndrei Emeltchenko goto unlock; 31133df91ea2SAndrei Emeltchenko } 31140a708f8fSGustavo F. Padovan } 31150a708f8fSGustavo F. Padovan 31163df91ea2SAndrei Emeltchenko err = 0; 31173df91ea2SAndrei Emeltchenko 31186be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 311948454079SGustavo F. Padovan 31200a708f8fSGustavo F. Padovan switch (result) { 31210a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS: 312289bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 3123fc7f8a7eSGustavo F. Padovan chan->ident = 0; 3124fe4128e0SGustavo F. Padovan chan->dcid = dcid; 3125c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state); 31260a708f8fSGustavo F. Padovan 3127c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 31280a708f8fSGustavo F. Padovan break; 31290a708f8fSGustavo F. Padovan 31300a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 313173ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, req), req); 313273ffa904SGustavo F. Padovan chan->num_conf_req++; 31330a708f8fSGustavo F. Padovan break; 31340a708f8fSGustavo F. Padovan 31350a708f8fSGustavo F. Padovan case L2CAP_CR_PEND: 3136c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 31370a708f8fSGustavo F. Padovan break; 31380a708f8fSGustavo F. Padovan 31390a708f8fSGustavo F. Padovan default: 314048454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED); 31410a708f8fSGustavo F. Padovan break; 31420a708f8fSGustavo F. Padovan } 31430a708f8fSGustavo F. Padovan 31446be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 31453df91ea2SAndrei Emeltchenko 31463df91ea2SAndrei Emeltchenko unlock: 31473df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 31483df91ea2SAndrei Emeltchenko 31493df91ea2SAndrei Emeltchenko return err; 31500a708f8fSGustavo F. Padovan } 31510a708f8fSGustavo F. Padovan 315247d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan) 31530a708f8fSGustavo F. Padovan { 31540a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both 31550a708f8fSGustavo F. Padovan * sides request it. 31560a708f8fSGustavo F. Padovan */ 31570c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) 315847d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3159c1360a1cSGustavo F. Padovan else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) 316047d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16; 31610a708f8fSGustavo F. Padovan } 31620a708f8fSGustavo F. Padovan 31630a708f8fSGustavo F. Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 31640a708f8fSGustavo F. Padovan { 31650a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; 31660a708f8fSGustavo F. Padovan u16 dcid, flags; 31670a708f8fSGustavo F. Padovan u8 rsp[64]; 316848454079SGustavo F. Padovan struct l2cap_chan *chan; 31693c588192SMat Martineau int len, err = 0; 31700a708f8fSGustavo F. Padovan 31710a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 31720a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags); 31730a708f8fSGustavo F. Padovan 31740a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); 31750a708f8fSGustavo F. Padovan 3176baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid); 317748454079SGustavo F. Padovan if (!chan) 31780a708f8fSGustavo F. Padovan return -ENOENT; 31790a708f8fSGustavo F. Padovan 31806be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 318148454079SGustavo F. Padovan 3182033b1142SDavid S. Miller if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { 3183e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_cid rej; 31840a708f8fSGustavo F. Padovan 3185e2fd318eSIlia Kolomisnky rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID); 3186e2fd318eSIlia Kolomisnky rej.scid = cpu_to_le16(chan->scid); 3187e2fd318eSIlia Kolomisnky rej.dcid = cpu_to_le16(chan->dcid); 3188e2fd318eSIlia Kolomisnky 31890a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 31900a708f8fSGustavo F. Padovan sizeof(rej), &rej); 31910a708f8fSGustavo F. Padovan goto unlock; 31920a708f8fSGustavo F. Padovan } 31930a708f8fSGustavo F. Padovan 31940a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */ 31950a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req); 31967ac28817SDan Rosenberg if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) { 31970a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 3198fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 31990a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp); 32000a708f8fSGustavo F. Padovan goto unlock; 32010a708f8fSGustavo F. Padovan } 32020a708f8fSGustavo F. Padovan 32030a708f8fSGustavo F. Padovan /* Store config. */ 320473ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len); 320573ffa904SGustavo F. Padovan chan->conf_len += len; 32060a708f8fSGustavo F. Padovan 32070a708f8fSGustavo F. Padovan if (flags & 0x0001) { 32080a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */ 32090a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 3210fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 32110a708f8fSGustavo F. Padovan L2CAP_CONF_SUCCESS, 0x0001), rsp); 32120a708f8fSGustavo F. Padovan goto unlock; 32130a708f8fSGustavo F. Padovan } 32140a708f8fSGustavo F. Padovan 32150a708f8fSGustavo F. Padovan /* Complete config. */ 321673ffa904SGustavo F. Padovan len = l2cap_parse_conf_req(chan, rsp); 32170a708f8fSGustavo F. Padovan if (len < 0) { 3218e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 32190a708f8fSGustavo F. Padovan goto unlock; 32200a708f8fSGustavo F. Padovan } 32210a708f8fSGustavo F. Padovan 32220a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); 322373ffa904SGustavo F. Padovan chan->num_conf_rsp++; 32240a708f8fSGustavo F. Padovan 32250a708f8fSGustavo F. Padovan /* Reset config buffer. */ 322673ffa904SGustavo F. Padovan chan->conf_len = 0; 32270a708f8fSGustavo F. Padovan 3228c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) 32290a708f8fSGustavo F. Padovan goto unlock; 32300a708f8fSGustavo F. Padovan 3231c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 323247d1ec61SGustavo F. Padovan set_default_fcs(chan); 32330a708f8fSGustavo F. Padovan 323489bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECTED); 32350a708f8fSGustavo F. Padovan 3236105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 3237105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 32383c588192SMat Martineau err = l2cap_ertm_init(chan); 32390a708f8fSGustavo F. Padovan 32403c588192SMat Martineau if (err < 0) 32413c588192SMat Martineau l2cap_send_disconn_req(chan->conn, chan, -err); 32423c588192SMat Martineau else 3243cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 32443c588192SMat Martineau 32450a708f8fSGustavo F. Padovan goto unlock; 32460a708f8fSGustavo F. Padovan } 32470a708f8fSGustavo F. Padovan 3248c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { 32490a708f8fSGustavo F. Padovan u8 buf[64]; 32500a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 325173ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 325273ffa904SGustavo F. Padovan chan->num_conf_req++; 32530a708f8fSGustavo F. Padovan } 32540a708f8fSGustavo F. Padovan 32550e8b207eSAndrei Emeltchenko /* Got Conf Rsp PENDING from remote side and asume we sent 32560e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */ 32570e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && 32580e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 32590e8b207eSAndrei Emeltchenko 32600e8b207eSAndrei Emeltchenko /* check compatibility */ 32610e8b207eSAndrei Emeltchenko 32620e8b207eSAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 32630e8b207eSAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 32640e8b207eSAndrei Emeltchenko 32650e8b207eSAndrei Emeltchenko l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 32660e8b207eSAndrei Emeltchenko l2cap_build_conf_rsp(chan, rsp, 32670e8b207eSAndrei Emeltchenko L2CAP_CONF_SUCCESS, 0x0000), rsp); 32680e8b207eSAndrei Emeltchenko } 32690e8b207eSAndrei Emeltchenko 32700a708f8fSGustavo F. Padovan unlock: 32716be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 32723c588192SMat Martineau return err; 32730a708f8fSGustavo F. Padovan } 32740a708f8fSGustavo F. Padovan 32750a708f8fSGustavo F. Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 32760a708f8fSGustavo F. Padovan { 32770a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; 32780a708f8fSGustavo F. Padovan u16 scid, flags, result; 327948454079SGustavo F. Padovan struct l2cap_chan *chan; 328061386cbaSAndrei Emeltchenko int len = le16_to_cpu(cmd->len) - sizeof(*rsp); 32813c588192SMat Martineau int err = 0; 32820a708f8fSGustavo F. Padovan 32830a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 32840a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags); 32850a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 32860a708f8fSGustavo F. Padovan 328761386cbaSAndrei Emeltchenko BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags, 328861386cbaSAndrei Emeltchenko result, len); 32890a708f8fSGustavo F. Padovan 3290baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 329148454079SGustavo F. Padovan if (!chan) 32920a708f8fSGustavo F. Padovan return 0; 32930a708f8fSGustavo F. Padovan 32946be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 329548454079SGustavo F. Padovan 32960a708f8fSGustavo F. Padovan switch (result) { 32970a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS: 329847d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len); 32990e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state); 33000a708f8fSGustavo F. Padovan break; 33010a708f8fSGustavo F. Padovan 33020e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING: 33030e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state); 33040e8b207eSAndrei Emeltchenko 33050e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 33060e8b207eSAndrei Emeltchenko char buf[64]; 33070e8b207eSAndrei Emeltchenko 33080e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len, 33090e8b207eSAndrei Emeltchenko buf, &result); 33100e8b207eSAndrei Emeltchenko if (len < 0) { 33110e8b207eSAndrei Emeltchenko l2cap_send_disconn_req(conn, chan, ECONNRESET); 33120e8b207eSAndrei Emeltchenko goto done; 33130e8b207eSAndrei Emeltchenko } 33140e8b207eSAndrei Emeltchenko 33150e8b207eSAndrei Emeltchenko /* check compatibility */ 33160e8b207eSAndrei Emeltchenko 33170e8b207eSAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 33180e8b207eSAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 33190e8b207eSAndrei Emeltchenko 33200e8b207eSAndrei Emeltchenko l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 33210e8b207eSAndrei Emeltchenko l2cap_build_conf_rsp(chan, buf, 33220e8b207eSAndrei Emeltchenko L2CAP_CONF_SUCCESS, 0x0000), buf); 33230e8b207eSAndrei Emeltchenko } 33240e8b207eSAndrei Emeltchenko goto done; 33250e8b207eSAndrei Emeltchenko 33260a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT: 332773ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { 33280a708f8fSGustavo F. Padovan char req[64]; 33290a708f8fSGustavo F. Padovan 33300a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { 3331e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 33320a708f8fSGustavo F. Padovan goto done; 33330a708f8fSGustavo F. Padovan } 33340a708f8fSGustavo F. Padovan 33350a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */ 33360a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS; 3337b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len, 3338b4450035SGustavo F. Padovan req, &result); 33390a708f8fSGustavo F. Padovan if (len < 0) { 3340e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 33410a708f8fSGustavo F. Padovan goto done; 33420a708f8fSGustavo F. Padovan } 33430a708f8fSGustavo F. Padovan 33440a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 33450a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req); 334673ffa904SGustavo F. Padovan chan->num_conf_req++; 33470a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS) 33480a708f8fSGustavo F. Padovan goto done; 33490a708f8fSGustavo F. Padovan break; 33500a708f8fSGustavo F. Padovan } 33510a708f8fSGustavo F. Padovan 33520a708f8fSGustavo F. Padovan default: 33536be36555SAndrei Emeltchenko l2cap_chan_set_err(chan, ECONNRESET); 33542e0052e4SAndrei Emeltchenko 3355ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); 3356e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 33570a708f8fSGustavo F. Padovan goto done; 33580a708f8fSGustavo F. Padovan } 33590a708f8fSGustavo F. Padovan 33600a708f8fSGustavo F. Padovan if (flags & 0x01) 33610a708f8fSGustavo F. Padovan goto done; 33620a708f8fSGustavo F. Padovan 3363c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state); 33640a708f8fSGustavo F. Padovan 3365c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { 336647d1ec61SGustavo F. Padovan set_default_fcs(chan); 33670a708f8fSGustavo F. Padovan 336889bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECTED); 3369105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 3370105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 33713c588192SMat Martineau err = l2cap_ertm_init(chan); 33720a708f8fSGustavo F. Padovan 33733c588192SMat Martineau if (err < 0) 33743c588192SMat Martineau l2cap_send_disconn_req(chan->conn, chan, -err); 33753c588192SMat Martineau else 3376cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 33770a708f8fSGustavo F. Padovan } 33780a708f8fSGustavo F. Padovan 33790a708f8fSGustavo F. Padovan done: 33806be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 33813c588192SMat Martineau return err; 33820a708f8fSGustavo F. Padovan } 33830a708f8fSGustavo F. Padovan 33840a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 33850a708f8fSGustavo F. Padovan { 33860a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; 33870a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp; 33880a708f8fSGustavo F. Padovan u16 dcid, scid; 338948454079SGustavo F. Padovan struct l2cap_chan *chan; 33900a708f8fSGustavo F. Padovan struct sock *sk; 33910a708f8fSGustavo F. Padovan 33920a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid); 33930a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 33940a708f8fSGustavo F. Padovan 33950a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); 33960a708f8fSGustavo F. Padovan 33973df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 33983df91ea2SAndrei Emeltchenko 33993df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, dcid); 34003df91ea2SAndrei Emeltchenko if (!chan) { 34013df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 34020a708f8fSGustavo F. Padovan return 0; 34033df91ea2SAndrei Emeltchenko } 34040a708f8fSGustavo F. Padovan 34056be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 34066be36555SAndrei Emeltchenko 340748454079SGustavo F. Padovan sk = chan->sk; 340848454079SGustavo F. Padovan 3409fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3410fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 34110a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); 34120a708f8fSGustavo F. Padovan 34136be36555SAndrei Emeltchenko lock_sock(sk); 34140a708f8fSGustavo F. Padovan sk->sk_shutdown = SHUTDOWN_MASK; 34156be36555SAndrei Emeltchenko release_sock(sk); 34160a708f8fSGustavo F. Padovan 341761d6ef3eSMat Martineau l2cap_chan_hold(chan); 341848454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET); 34196be36555SAndrei Emeltchenko 34206be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 34210a708f8fSGustavo F. Padovan 3422ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 342361d6ef3eSMat Martineau l2cap_chan_put(chan); 34243df91ea2SAndrei Emeltchenko 34253df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 34263df91ea2SAndrei Emeltchenko 34270a708f8fSGustavo F. Padovan return 0; 34280a708f8fSGustavo F. Padovan } 34290a708f8fSGustavo F. Padovan 34300a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 34310a708f8fSGustavo F. Padovan { 34320a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; 34330a708f8fSGustavo F. Padovan u16 dcid, scid; 343448454079SGustavo F. Padovan struct l2cap_chan *chan; 34350a708f8fSGustavo F. Padovan 34360a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 34370a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 34380a708f8fSGustavo F. Padovan 34390a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); 34400a708f8fSGustavo F. Padovan 34413df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 34423df91ea2SAndrei Emeltchenko 34433df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 34443df91ea2SAndrei Emeltchenko if (!chan) { 34453df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 34460a708f8fSGustavo F. Padovan return 0; 34473df91ea2SAndrei Emeltchenko } 34480a708f8fSGustavo F. Padovan 34496be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 345048454079SGustavo F. Padovan 345161d6ef3eSMat Martineau l2cap_chan_hold(chan); 345248454079SGustavo F. Padovan l2cap_chan_del(chan, 0); 34536be36555SAndrei Emeltchenko 34546be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 34550a708f8fSGustavo F. Padovan 3456ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 345761d6ef3eSMat Martineau l2cap_chan_put(chan); 34583df91ea2SAndrei Emeltchenko 34593df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 34603df91ea2SAndrei Emeltchenko 34610a708f8fSGustavo F. Padovan return 0; 34620a708f8fSGustavo F. Padovan } 34630a708f8fSGustavo F. Padovan 34640a708f8fSGustavo F. Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 34650a708f8fSGustavo F. Padovan { 34660a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data; 34670a708f8fSGustavo F. Padovan u16 type; 34680a708f8fSGustavo F. Padovan 34690a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type); 34700a708f8fSGustavo F. Padovan 34710a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type); 34720a708f8fSGustavo F. Padovan 34730a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) { 34740a708f8fSGustavo F. Padovan u8 buf[8]; 34750a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask; 34760a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 34770a708f8fSGustavo F. Padovan rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 34780a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 34790a708f8fSGustavo F. Padovan if (!disable_ertm) 34800a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING 34810a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS; 3482a5fd6f30SAndrei Emeltchenko if (enable_hs) 34836327eb98SAndrei Emeltchenko feat_mask |= L2CAP_FEAT_EXT_FLOW 34846327eb98SAndrei Emeltchenko | L2CAP_FEAT_EXT_WINDOW; 3485a5fd6f30SAndrei Emeltchenko 34860a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data); 34870a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 34880a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(buf), buf); 34890a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) { 34900a708f8fSGustavo F. Padovan u8 buf[12]; 34910a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 349250a147cdSMat Martineau 349350a147cdSMat Martineau if (enable_hs) 349450a147cdSMat Martineau l2cap_fixed_chan[0] |= L2CAP_FC_A2MP; 349550a147cdSMat Martineau else 349650a147cdSMat Martineau l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP; 349750a147cdSMat Martineau 34980a708f8fSGustavo F. Padovan rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 34990a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 3500c6337ea6SAndrei Emeltchenko memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); 35010a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 35020a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(buf), buf); 35030a708f8fSGustavo F. Padovan } else { 35040a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp; 35050a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type); 35060a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP); 35070a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 35080a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(rsp), &rsp); 35090a708f8fSGustavo F. Padovan } 35100a708f8fSGustavo F. Padovan 35110a708f8fSGustavo F. Padovan return 0; 35120a708f8fSGustavo F. Padovan } 35130a708f8fSGustavo F. Padovan 35140a708f8fSGustavo F. Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 35150a708f8fSGustavo F. Padovan { 35160a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; 35170a708f8fSGustavo F. Padovan u16 type, result; 35180a708f8fSGustavo F. Padovan 35190a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type); 35200a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 35210a708f8fSGustavo F. Padovan 35220a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); 35230a708f8fSGustavo F. Padovan 3524e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */ 3525e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident || 3526e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 3527e90165beSAndrei Emeltchenko return 0; 3528e90165beSAndrei Emeltchenko 352917cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 35300a708f8fSGustavo F. Padovan 35310a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) { 35320a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 35330a708f8fSGustavo F. Padovan conn->info_ident = 0; 35340a708f8fSGustavo F. Padovan 35350a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 35360a708f8fSGustavo F. Padovan 35370a708f8fSGustavo F. Padovan return 0; 35380a708f8fSGustavo F. Padovan } 35390a708f8fSGustavo F. Padovan 3540978c93b9SAndrei Emeltchenko switch (type) { 3541978c93b9SAndrei Emeltchenko case L2CAP_IT_FEAT_MASK: 35420a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data); 35430a708f8fSGustavo F. Padovan 35440a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { 35450a708f8fSGustavo F. Padovan struct l2cap_info_req req; 35460a708f8fSGustavo F. Padovan req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 35470a708f8fSGustavo F. Padovan 35480a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 35490a708f8fSGustavo F. Padovan 35500a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 35510a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 35520a708f8fSGustavo F. Padovan } else { 35530a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 35540a708f8fSGustavo F. Padovan conn->info_ident = 0; 35550a708f8fSGustavo F. Padovan 35560a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 35570a708f8fSGustavo F. Padovan } 3558978c93b9SAndrei Emeltchenko break; 3559978c93b9SAndrei Emeltchenko 3560978c93b9SAndrei Emeltchenko case L2CAP_IT_FIXED_CHAN: 3561978c93b9SAndrei Emeltchenko conn->fixed_chan_mask = rsp->data[0]; 35620a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 35630a708f8fSGustavo F. Padovan conn->info_ident = 0; 35640a708f8fSGustavo F. Padovan 35650a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 3566978c93b9SAndrei Emeltchenko break; 35670a708f8fSGustavo F. Padovan } 35680a708f8fSGustavo F. Padovan 35690a708f8fSGustavo F. Padovan return 0; 35700a708f8fSGustavo F. Padovan } 35710a708f8fSGustavo F. Padovan 3572f94ff6ffSMat Martineau static inline int l2cap_create_channel_req(struct l2cap_conn *conn, 3573f94ff6ffSMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, 3574f94ff6ffSMat Martineau void *data) 3575f94ff6ffSMat Martineau { 3576f94ff6ffSMat Martineau struct l2cap_create_chan_req *req = data; 3577f94ff6ffSMat Martineau struct l2cap_create_chan_rsp rsp; 3578f94ff6ffSMat Martineau u16 psm, scid; 3579f94ff6ffSMat Martineau 3580f94ff6ffSMat Martineau if (cmd_len != sizeof(*req)) 3581f94ff6ffSMat Martineau return -EPROTO; 3582f94ff6ffSMat Martineau 3583f94ff6ffSMat Martineau if (!enable_hs) 3584f94ff6ffSMat Martineau return -EINVAL; 3585f94ff6ffSMat Martineau 3586f94ff6ffSMat Martineau psm = le16_to_cpu(req->psm); 3587f94ff6ffSMat Martineau scid = le16_to_cpu(req->scid); 3588f94ff6ffSMat Martineau 3589f94ff6ffSMat Martineau BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id); 3590f94ff6ffSMat Martineau 3591f94ff6ffSMat Martineau /* Placeholder: Always reject */ 3592f94ff6ffSMat Martineau rsp.dcid = 0; 3593f94ff6ffSMat Martineau rsp.scid = cpu_to_le16(scid); 35948ce0c498SAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM); 35958ce0c498SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 3596f94ff6ffSMat Martineau 3597f94ff6ffSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, 3598f94ff6ffSMat Martineau sizeof(rsp), &rsp); 3599f94ff6ffSMat Martineau 3600f94ff6ffSMat Martineau return 0; 3601f94ff6ffSMat Martineau } 3602f94ff6ffSMat Martineau 3603f94ff6ffSMat Martineau static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn, 3604f94ff6ffSMat Martineau struct l2cap_cmd_hdr *cmd, void *data) 3605f94ff6ffSMat Martineau { 3606f94ff6ffSMat Martineau BT_DBG("conn %p", conn); 3607f94ff6ffSMat Martineau 3608f94ff6ffSMat Martineau return l2cap_connect_rsp(conn, cmd, data); 3609f94ff6ffSMat Martineau } 3610f94ff6ffSMat Martineau 36118d5a04a1SMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident, 36128d5a04a1SMat Martineau u16 icid, u16 result) 36138d5a04a1SMat Martineau { 36148d5a04a1SMat Martineau struct l2cap_move_chan_rsp rsp; 36158d5a04a1SMat Martineau 36168d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 36178d5a04a1SMat Martineau 36188d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 36198d5a04a1SMat Martineau rsp.result = cpu_to_le16(result); 36208d5a04a1SMat Martineau 36218d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp); 36228d5a04a1SMat Martineau } 36238d5a04a1SMat Martineau 36248d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn, 36258d5a04a1SMat Martineau struct l2cap_chan *chan, u16 icid, u16 result) 36268d5a04a1SMat Martineau { 36278d5a04a1SMat Martineau struct l2cap_move_chan_cfm cfm; 36288d5a04a1SMat Martineau u8 ident; 36298d5a04a1SMat Martineau 36308d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 36318d5a04a1SMat Martineau 36328d5a04a1SMat Martineau ident = l2cap_get_ident(conn); 36338d5a04a1SMat Martineau if (chan) 36348d5a04a1SMat Martineau chan->ident = ident; 36358d5a04a1SMat Martineau 36368d5a04a1SMat Martineau cfm.icid = cpu_to_le16(icid); 36378d5a04a1SMat Martineau cfm.result = cpu_to_le16(result); 36388d5a04a1SMat Martineau 36398d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm); 36408d5a04a1SMat Martineau } 36418d5a04a1SMat Martineau 36428d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, 36438d5a04a1SMat Martineau u16 icid) 36448d5a04a1SMat Martineau { 36458d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp rsp; 36468d5a04a1SMat Martineau 36478d5a04a1SMat Martineau BT_DBG("icid %d", icid); 36488d5a04a1SMat Martineau 36498d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 36508d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp); 36518d5a04a1SMat Martineau } 36528d5a04a1SMat Martineau 36538d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn, 36548d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 36558d5a04a1SMat Martineau { 36568d5a04a1SMat Martineau struct l2cap_move_chan_req *req = data; 36578d5a04a1SMat Martineau u16 icid = 0; 36588d5a04a1SMat Martineau u16 result = L2CAP_MR_NOT_ALLOWED; 36598d5a04a1SMat Martineau 36608d5a04a1SMat Martineau if (cmd_len != sizeof(*req)) 36618d5a04a1SMat Martineau return -EPROTO; 36628d5a04a1SMat Martineau 36638d5a04a1SMat Martineau icid = le16_to_cpu(req->icid); 36648d5a04a1SMat Martineau 36658d5a04a1SMat Martineau BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id); 36668d5a04a1SMat Martineau 36678d5a04a1SMat Martineau if (!enable_hs) 36688d5a04a1SMat Martineau return -EINVAL; 36698d5a04a1SMat Martineau 36708d5a04a1SMat Martineau /* Placeholder: Always refuse */ 36718d5a04a1SMat Martineau l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result); 36728d5a04a1SMat Martineau 36738d5a04a1SMat Martineau return 0; 36748d5a04a1SMat Martineau } 36758d5a04a1SMat Martineau 36768d5a04a1SMat Martineau static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn, 36778d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 36788d5a04a1SMat Martineau { 36798d5a04a1SMat Martineau struct l2cap_move_chan_rsp *rsp = data; 36808d5a04a1SMat Martineau u16 icid, result; 36818d5a04a1SMat Martineau 36828d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 36838d5a04a1SMat Martineau return -EPROTO; 36848d5a04a1SMat Martineau 36858d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 36868d5a04a1SMat Martineau result = le16_to_cpu(rsp->result); 36878d5a04a1SMat Martineau 36888d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 36898d5a04a1SMat Martineau 36908d5a04a1SMat Martineau /* Placeholder: Always unconfirmed */ 36918d5a04a1SMat Martineau l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED); 36928d5a04a1SMat Martineau 36938d5a04a1SMat Martineau return 0; 36948d5a04a1SMat Martineau } 36958d5a04a1SMat Martineau 36968d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn, 36978d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 36988d5a04a1SMat Martineau { 36998d5a04a1SMat Martineau struct l2cap_move_chan_cfm *cfm = data; 37008d5a04a1SMat Martineau u16 icid, result; 37018d5a04a1SMat Martineau 37028d5a04a1SMat Martineau if (cmd_len != sizeof(*cfm)) 37038d5a04a1SMat Martineau return -EPROTO; 37048d5a04a1SMat Martineau 37058d5a04a1SMat Martineau icid = le16_to_cpu(cfm->icid); 37068d5a04a1SMat Martineau result = le16_to_cpu(cfm->result); 37078d5a04a1SMat Martineau 37088d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 37098d5a04a1SMat Martineau 37108d5a04a1SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 37118d5a04a1SMat Martineau 37128d5a04a1SMat Martineau return 0; 37138d5a04a1SMat Martineau } 37148d5a04a1SMat Martineau 37158d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, 37168d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 37178d5a04a1SMat Martineau { 37188d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp *rsp = data; 37198d5a04a1SMat Martineau u16 icid; 37208d5a04a1SMat Martineau 37218d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 37228d5a04a1SMat Martineau return -EPROTO; 37238d5a04a1SMat Martineau 37248d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 37258d5a04a1SMat Martineau 37268d5a04a1SMat Martineau BT_DBG("icid %d", icid); 37278d5a04a1SMat Martineau 37288d5a04a1SMat Martineau return 0; 37298d5a04a1SMat Martineau } 37308d5a04a1SMat Martineau 3731e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency, 3732de73115aSClaudio Takahasi u16 to_multiplier) 3733de73115aSClaudio Takahasi { 3734de73115aSClaudio Takahasi u16 max_latency; 3735de73115aSClaudio Takahasi 3736de73115aSClaudio Takahasi if (min > max || min < 6 || max > 3200) 3737de73115aSClaudio Takahasi return -EINVAL; 3738de73115aSClaudio Takahasi 3739de73115aSClaudio Takahasi if (to_multiplier < 10 || to_multiplier > 3200) 3740de73115aSClaudio Takahasi return -EINVAL; 3741de73115aSClaudio Takahasi 3742de73115aSClaudio Takahasi if (max >= to_multiplier * 8) 3743de73115aSClaudio Takahasi return -EINVAL; 3744de73115aSClaudio Takahasi 3745de73115aSClaudio Takahasi max_latency = (to_multiplier * 8 / max) - 1; 3746de73115aSClaudio Takahasi if (latency > 499 || latency > max_latency) 3747de73115aSClaudio Takahasi return -EINVAL; 3748de73115aSClaudio Takahasi 3749de73115aSClaudio Takahasi return 0; 3750de73115aSClaudio Takahasi } 3751de73115aSClaudio Takahasi 3752de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, 3753de73115aSClaudio Takahasi struct l2cap_cmd_hdr *cmd, u8 *data) 3754de73115aSClaudio Takahasi { 3755de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon; 3756de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req; 3757de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp; 3758de73115aSClaudio Takahasi u16 min, max, latency, to_multiplier, cmd_len; 37592ce603ebSClaudio Takahasi int err; 3760de73115aSClaudio Takahasi 3761de73115aSClaudio Takahasi if (!(hcon->link_mode & HCI_LM_MASTER)) 3762de73115aSClaudio Takahasi return -EINVAL; 3763de73115aSClaudio Takahasi 3764de73115aSClaudio Takahasi cmd_len = __le16_to_cpu(cmd->len); 3765de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) 3766de73115aSClaudio Takahasi return -EPROTO; 3767de73115aSClaudio Takahasi 3768de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data; 3769de73115aSClaudio Takahasi min = __le16_to_cpu(req->min); 3770de73115aSClaudio Takahasi max = __le16_to_cpu(req->max); 3771de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency); 3772de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier); 3773de73115aSClaudio Takahasi 3774de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", 3775de73115aSClaudio Takahasi min, max, latency, to_multiplier); 3776de73115aSClaudio Takahasi 3777de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp)); 37782ce603ebSClaudio Takahasi 37792ce603ebSClaudio Takahasi err = l2cap_check_conn_param(min, max, latency, to_multiplier); 37802ce603ebSClaudio Takahasi if (err) 3781de73115aSClaudio Takahasi rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); 3782de73115aSClaudio Takahasi else 3783de73115aSClaudio Takahasi rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); 3784de73115aSClaudio Takahasi 3785de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, 3786de73115aSClaudio Takahasi sizeof(rsp), &rsp); 3787de73115aSClaudio Takahasi 37882ce603ebSClaudio Takahasi if (!err) 37892ce603ebSClaudio Takahasi hci_le_conn_update(hcon, min, max, latency, to_multiplier); 37902ce603ebSClaudio Takahasi 3791de73115aSClaudio Takahasi return 0; 3792de73115aSClaudio Takahasi } 3793de73115aSClaudio Takahasi 37943300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, 37953300d9a9SClaudio Takahasi struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 37963300d9a9SClaudio Takahasi { 37973300d9a9SClaudio Takahasi int err = 0; 37983300d9a9SClaudio Takahasi 37993300d9a9SClaudio Takahasi switch (cmd->code) { 38003300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 38013300d9a9SClaudio Takahasi l2cap_command_rej(conn, cmd, data); 38023300d9a9SClaudio Takahasi break; 38033300d9a9SClaudio Takahasi 38043300d9a9SClaudio Takahasi case L2CAP_CONN_REQ: 38053300d9a9SClaudio Takahasi err = l2cap_connect_req(conn, cmd, data); 38063300d9a9SClaudio Takahasi break; 38073300d9a9SClaudio Takahasi 38083300d9a9SClaudio Takahasi case L2CAP_CONN_RSP: 38093300d9a9SClaudio Takahasi err = l2cap_connect_rsp(conn, cmd, data); 38103300d9a9SClaudio Takahasi break; 38113300d9a9SClaudio Takahasi 38123300d9a9SClaudio Takahasi case L2CAP_CONF_REQ: 38133300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data); 38143300d9a9SClaudio Takahasi break; 38153300d9a9SClaudio Takahasi 38163300d9a9SClaudio Takahasi case L2CAP_CONF_RSP: 38173300d9a9SClaudio Takahasi err = l2cap_config_rsp(conn, cmd, data); 38183300d9a9SClaudio Takahasi break; 38193300d9a9SClaudio Takahasi 38203300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ: 38213300d9a9SClaudio Takahasi err = l2cap_disconnect_req(conn, cmd, data); 38223300d9a9SClaudio Takahasi break; 38233300d9a9SClaudio Takahasi 38243300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP: 38253300d9a9SClaudio Takahasi err = l2cap_disconnect_rsp(conn, cmd, data); 38263300d9a9SClaudio Takahasi break; 38273300d9a9SClaudio Takahasi 38283300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ: 38293300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data); 38303300d9a9SClaudio Takahasi break; 38313300d9a9SClaudio Takahasi 38323300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP: 38333300d9a9SClaudio Takahasi break; 38343300d9a9SClaudio Takahasi 38353300d9a9SClaudio Takahasi case L2CAP_INFO_REQ: 38363300d9a9SClaudio Takahasi err = l2cap_information_req(conn, cmd, data); 38373300d9a9SClaudio Takahasi break; 38383300d9a9SClaudio Takahasi 38393300d9a9SClaudio Takahasi case L2CAP_INFO_RSP: 38403300d9a9SClaudio Takahasi err = l2cap_information_rsp(conn, cmd, data); 38413300d9a9SClaudio Takahasi break; 38423300d9a9SClaudio Takahasi 3843f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_REQ: 3844f94ff6ffSMat Martineau err = l2cap_create_channel_req(conn, cmd, cmd_len, data); 3845f94ff6ffSMat Martineau break; 3846f94ff6ffSMat Martineau 3847f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_RSP: 3848f94ff6ffSMat Martineau err = l2cap_create_channel_rsp(conn, cmd, data); 3849f94ff6ffSMat Martineau break; 3850f94ff6ffSMat Martineau 38518d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_REQ: 38528d5a04a1SMat Martineau err = l2cap_move_channel_req(conn, cmd, cmd_len, data); 38538d5a04a1SMat Martineau break; 38548d5a04a1SMat Martineau 38558d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_RSP: 38568d5a04a1SMat Martineau err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data); 38578d5a04a1SMat Martineau break; 38588d5a04a1SMat Martineau 38598d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM: 38608d5a04a1SMat Martineau err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data); 38618d5a04a1SMat Martineau break; 38628d5a04a1SMat Martineau 38638d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM_RSP: 38648d5a04a1SMat Martineau err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data); 38658d5a04a1SMat Martineau break; 38668d5a04a1SMat Martineau 38673300d9a9SClaudio Takahasi default: 38683300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code); 38693300d9a9SClaudio Takahasi err = -EINVAL; 38703300d9a9SClaudio Takahasi break; 38713300d9a9SClaudio Takahasi } 38723300d9a9SClaudio Takahasi 38733300d9a9SClaudio Takahasi return err; 38743300d9a9SClaudio Takahasi } 38753300d9a9SClaudio Takahasi 38763300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, 38773300d9a9SClaudio Takahasi struct l2cap_cmd_hdr *cmd, u8 *data) 38783300d9a9SClaudio Takahasi { 38793300d9a9SClaudio Takahasi switch (cmd->code) { 38803300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 38813300d9a9SClaudio Takahasi return 0; 38823300d9a9SClaudio Takahasi 38833300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ: 3884de73115aSClaudio Takahasi return l2cap_conn_param_update_req(conn, cmd, data); 38853300d9a9SClaudio Takahasi 38863300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP: 38873300d9a9SClaudio Takahasi return 0; 38883300d9a9SClaudio Takahasi 38893300d9a9SClaudio Takahasi default: 38903300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code); 38913300d9a9SClaudio Takahasi return -EINVAL; 38923300d9a9SClaudio Takahasi } 38933300d9a9SClaudio Takahasi } 38943300d9a9SClaudio Takahasi 38953300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn, 38963300d9a9SClaudio Takahasi struct sk_buff *skb) 38970a708f8fSGustavo F. Padovan { 38980a708f8fSGustavo F. Padovan u8 *data = skb->data; 38990a708f8fSGustavo F. Padovan int len = skb->len; 39000a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr cmd; 39013300d9a9SClaudio Takahasi int err; 39020a708f8fSGustavo F. Padovan 39030a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb); 39040a708f8fSGustavo F. Padovan 39050a708f8fSGustavo F. Padovan while (len >= L2CAP_CMD_HDR_SIZE) { 39060a708f8fSGustavo F. Padovan u16 cmd_len; 39070a708f8fSGustavo F. Padovan memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); 39080a708f8fSGustavo F. Padovan data += L2CAP_CMD_HDR_SIZE; 39090a708f8fSGustavo F. Padovan len -= L2CAP_CMD_HDR_SIZE; 39100a708f8fSGustavo F. Padovan 39110a708f8fSGustavo F. Padovan cmd_len = le16_to_cpu(cmd.len); 39120a708f8fSGustavo F. Padovan 39130a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident); 39140a708f8fSGustavo F. Padovan 39150a708f8fSGustavo F. Padovan if (cmd_len > len || !cmd.ident) { 39160a708f8fSGustavo F. Padovan BT_DBG("corrupted command"); 39170a708f8fSGustavo F. Padovan break; 39180a708f8fSGustavo F. Padovan } 39190a708f8fSGustavo F. Padovan 39203300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 39213300d9a9SClaudio Takahasi err = l2cap_le_sig_cmd(conn, &cmd, data); 39223300d9a9SClaudio Takahasi else 39233300d9a9SClaudio Takahasi err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data); 39240a708f8fSGustavo F. Padovan 39250a708f8fSGustavo F. Padovan if (err) { 3926e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk rej; 39272c6d1a2eSGustavo F. Padovan 39282c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err); 39290a708f8fSGustavo F. Padovan 39300a708f8fSGustavo F. Padovan /* FIXME: Map err to a valid reason */ 3931e2fd318eSIlia Kolomisnky rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 39320a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); 39330a708f8fSGustavo F. Padovan } 39340a708f8fSGustavo F. Padovan 39350a708f8fSGustavo F. Padovan data += cmd_len; 39360a708f8fSGustavo F. Padovan len -= cmd_len; 39370a708f8fSGustavo F. Padovan } 39380a708f8fSGustavo F. Padovan 39390a708f8fSGustavo F. Padovan kfree_skb(skb); 39400a708f8fSGustavo F. Padovan } 39410a708f8fSGustavo F. Padovan 394247d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) 39430a708f8fSGustavo F. Padovan { 39440a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs; 3945e4ca6d98SAndrei Emeltchenko int hdr_size; 3946e4ca6d98SAndrei Emeltchenko 3947e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 3948e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE; 3949e4ca6d98SAndrei Emeltchenko else 3950e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE; 39510a708f8fSGustavo F. Padovan 395247d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 395303a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE); 39540a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len); 39550a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); 39560a708f8fSGustavo F. Padovan 39570a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs) 39580a708f8fSGustavo F. Padovan return -EBADMSG; 39590a708f8fSGustavo F. Padovan } 39600a708f8fSGustavo F. Padovan return 0; 39610a708f8fSGustavo F. Padovan } 39620a708f8fSGustavo F. Padovan 3963525cd185SGustavo F. Padovan static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) 39640a708f8fSGustavo F. Padovan { 396588843ab0SAndrei Emeltchenko u32 control = 0; 39660a708f8fSGustavo F. Padovan 39676a026610SGustavo F. Padovan chan->frames_sent = 0; 39680a708f8fSGustavo F. Padovan 39690b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 39700a708f8fSGustavo F. Padovan 3971e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 3972ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); 3973525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 3974e2ab4353SGustavo F. Padovan set_bit(CONN_RNR_SENT, &chan->conn_state); 39750a708f8fSGustavo F. Padovan } 39760a708f8fSGustavo F. Padovan 3977e2ab4353SGustavo F. Padovan if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 3978525cd185SGustavo F. Padovan l2cap_retransmit_frames(chan); 39790a708f8fSGustavo F. Padovan 3980525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 39810a708f8fSGustavo F. Padovan 3982e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 39836a026610SGustavo F. Padovan chan->frames_sent == 0) { 3984ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 3985525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 39860a708f8fSGustavo F. Padovan } 39870a708f8fSGustavo F. Padovan } 39880a708f8fSGustavo F. Padovan 3989fb45de7dSAndrei Emeltchenko static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u16 tx_seq, u8 sar) 39900a708f8fSGustavo F. Padovan { 39910a708f8fSGustavo F. Padovan struct sk_buff *next_skb; 39920a708f8fSGustavo F. Padovan int tx_seq_offset, next_tx_seq_offset; 39930a708f8fSGustavo F. Padovan 39943ce3514fSMat Martineau bt_cb(skb)->control.txseq = tx_seq; 39953ce3514fSMat Martineau bt_cb(skb)->control.sar = sar; 39960a708f8fSGustavo F. Padovan 3997f1c6775bSGustavo F. Padovan next_skb = skb_peek(&chan->srej_q); 39980a708f8fSGustavo F. Padovan 3999836be934SAndrei Emeltchenko tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq); 40000a708f8fSGustavo F. Padovan 4001039d9572SSzymon Janc while (next_skb) { 40023ce3514fSMat Martineau if (bt_cb(next_skb)->control.txseq == tx_seq) 40030a708f8fSGustavo F. Padovan return -EINVAL; 40040a708f8fSGustavo F. Padovan 4005836be934SAndrei Emeltchenko next_tx_seq_offset = __seq_offset(chan, 40063ce3514fSMat Martineau bt_cb(next_skb)->control.txseq, chan->buffer_seq); 40070a708f8fSGustavo F. Padovan 40080a708f8fSGustavo F. Padovan if (next_tx_seq_offset > tx_seq_offset) { 4009f1c6775bSGustavo F. Padovan __skb_queue_before(&chan->srej_q, next_skb, skb); 40100a708f8fSGustavo F. Padovan return 0; 40110a708f8fSGustavo F. Padovan } 40120a708f8fSGustavo F. Padovan 4013f1c6775bSGustavo F. Padovan if (skb_queue_is_last(&chan->srej_q, next_skb)) 4014039d9572SSzymon Janc next_skb = NULL; 4015039d9572SSzymon Janc else 4016039d9572SSzymon Janc next_skb = skb_queue_next(&chan->srej_q, next_skb); 4017039d9572SSzymon Janc } 40180a708f8fSGustavo F. Padovan 4019f1c6775bSGustavo F. Padovan __skb_queue_tail(&chan->srej_q, skb); 40200a708f8fSGustavo F. Padovan 40210a708f8fSGustavo F. Padovan return 0; 40220a708f8fSGustavo F. Padovan } 40230a708f8fSGustavo F. Padovan 402484084a31SMat Martineau static void append_skb_frag(struct sk_buff *skb, 402584084a31SMat Martineau struct sk_buff *new_frag, struct sk_buff **last_frag) 40260a708f8fSGustavo F. Padovan { 402784084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments 402884084a31SMat Martineau * skb->data_len reflects only data in fragments 402984084a31SMat Martineau */ 403084084a31SMat Martineau if (!skb_has_frag_list(skb)) 403184084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag; 403284084a31SMat Martineau 403384084a31SMat Martineau new_frag->next = NULL; 403484084a31SMat Martineau 403584084a31SMat Martineau (*last_frag)->next = new_frag; 403684084a31SMat Martineau *last_frag = new_frag; 403784084a31SMat Martineau 403884084a31SMat Martineau skb->len += new_frag->len; 403984084a31SMat Martineau skb->data_len += new_frag->len; 404084084a31SMat Martineau skb->truesize += new_frag->truesize; 404184084a31SMat Martineau } 404284084a31SMat Martineau 404388843ab0SAndrei Emeltchenko static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control) 404484084a31SMat Martineau { 404584084a31SMat Martineau int err = -EINVAL; 40460a708f8fSGustavo F. Padovan 40477e0ef6eeSAndrei Emeltchenko switch (__get_ctrl_sar(chan, control)) { 40487e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED: 404984084a31SMat Martineau if (chan->sdu) 405084084a31SMat Martineau break; 40510a708f8fSGustavo F. Padovan 405284084a31SMat Martineau err = chan->ops->recv(chan->data, skb); 405384084a31SMat Martineau break; 40540a708f8fSGustavo F. Padovan 40557e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START: 405684084a31SMat Martineau if (chan->sdu) 405784084a31SMat Martineau break; 40580a708f8fSGustavo F. Padovan 40596f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data); 406003a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE); 40610a708f8fSGustavo F. Padovan 406284084a31SMat Martineau if (chan->sdu_len > chan->imtu) { 406384084a31SMat Martineau err = -EMSGSIZE; 406484084a31SMat Martineau break; 406584084a31SMat Martineau } 40660a708f8fSGustavo F. Padovan 406784084a31SMat Martineau if (skb->len >= chan->sdu_len) 406884084a31SMat Martineau break; 406984084a31SMat Martineau 407084084a31SMat Martineau chan->sdu = skb; 407184084a31SMat Martineau chan->sdu_last_frag = skb; 407284084a31SMat Martineau 407384084a31SMat Martineau skb = NULL; 407484084a31SMat Martineau err = 0; 40750a708f8fSGustavo F. Padovan break; 40760a708f8fSGustavo F. Padovan 40777e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE: 40786f61fd47SGustavo F. Padovan if (!chan->sdu) 407984084a31SMat Martineau break; 40800a708f8fSGustavo F. Padovan 408184084a31SMat Martineau append_skb_frag(chan->sdu, skb, 408284084a31SMat Martineau &chan->sdu_last_frag); 408384084a31SMat Martineau skb = NULL; 40840a708f8fSGustavo F. Padovan 408584084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len) 408684084a31SMat Martineau break; 40870a708f8fSGustavo F. Padovan 408884084a31SMat Martineau err = 0; 40890a708f8fSGustavo F. Padovan break; 40900a708f8fSGustavo F. Padovan 40917e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END: 40926f61fd47SGustavo F. Padovan if (!chan->sdu) 409384084a31SMat Martineau break; 40940a708f8fSGustavo F. Padovan 409584084a31SMat Martineau append_skb_frag(chan->sdu, skb, 409684084a31SMat Martineau &chan->sdu_last_frag); 409784084a31SMat Martineau skb = NULL; 40980a708f8fSGustavo F. Padovan 409984084a31SMat Martineau if (chan->sdu->len != chan->sdu_len) 410084084a31SMat Martineau break; 41010a708f8fSGustavo F. Padovan 410284084a31SMat Martineau err = chan->ops->recv(chan->data, chan->sdu); 41030a708f8fSGustavo F. Padovan 410484084a31SMat Martineau if (!err) { 410584084a31SMat Martineau /* Reassembly complete */ 410684084a31SMat Martineau chan->sdu = NULL; 410784084a31SMat Martineau chan->sdu_last_frag = NULL; 410884084a31SMat Martineau chan->sdu_len = 0; 41090a708f8fSGustavo F. Padovan } 41100a708f8fSGustavo F. Padovan break; 41110a708f8fSGustavo F. Padovan } 41120a708f8fSGustavo F. Padovan 411384084a31SMat Martineau if (err) { 41140a708f8fSGustavo F. Padovan kfree_skb(skb); 41156f61fd47SGustavo F. Padovan kfree_skb(chan->sdu); 41166f61fd47SGustavo F. Padovan chan->sdu = NULL; 411784084a31SMat Martineau chan->sdu_last_frag = NULL; 411884084a31SMat Martineau chan->sdu_len = 0; 411984084a31SMat Martineau } 41200a708f8fSGustavo F. Padovan 412184084a31SMat Martineau return err; 41220a708f8fSGustavo F. Padovan } 41230a708f8fSGustavo F. Padovan 412426f880d2SMat Martineau static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan) 41250a708f8fSGustavo F. Padovan { 412626f880d2SMat Martineau BT_DBG("chan %p, Enter local busy", chan); 412726f880d2SMat Martineau 412826f880d2SMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 41293c588192SMat Martineau l2cap_seq_list_clear(&chan->srej_list); 413026f880d2SMat Martineau 413177f918bcSSzymon Janc __set_ack_timer(chan); 41320a708f8fSGustavo F. Padovan } 41330a708f8fSGustavo F. Padovan 413426f880d2SMat Martineau static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan) 413526f880d2SMat Martineau { 413688843ab0SAndrei Emeltchenko u32 control; 41370a708f8fSGustavo F. Padovan 4138e2ab4353SGustavo F. Padovan if (!test_bit(CONN_RNR_SENT, &chan->conn_state)) 41390a708f8fSGustavo F. Padovan goto done; 41400a708f8fSGustavo F. Padovan 41410b209faeSAndrei Emeltchenko control = __set_reqseq(chan, chan->buffer_seq); 4142e3781735SAndrei Emeltchenko control |= __set_ctrl_poll(chan); 4143ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 4144525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 41456a026610SGustavo F. Padovan chan->retry_count = 1; 41460a708f8fSGustavo F. Padovan 41471a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 41481a09bcb9SGustavo F. Padovan __set_monitor_timer(chan); 41490a708f8fSGustavo F. Padovan 4150e2ab4353SGustavo F. Padovan set_bit(CONN_WAIT_F, &chan->conn_state); 41510a708f8fSGustavo F. Padovan 41520a708f8fSGustavo F. Padovan done: 4153e2ab4353SGustavo F. Padovan clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 4154e2ab4353SGustavo F. Padovan clear_bit(CONN_RNR_SENT, &chan->conn_state); 41550a708f8fSGustavo F. Padovan 415649208c9cSGustavo F. Padovan BT_DBG("chan %p, Exit local busy", chan); 41570a708f8fSGustavo F. Padovan } 41580a708f8fSGustavo F. Padovan 4159e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 41600a708f8fSGustavo F. Padovan { 4161e328140fSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) { 4162e328140fSMat Martineau if (busy) 416326f880d2SMat Martineau l2cap_ertm_enter_local_busy(chan); 4164e328140fSMat Martineau else 4165e328140fSMat Martineau l2cap_ertm_exit_local_busy(chan); 41660a708f8fSGustavo F. Padovan } 41670a708f8fSGustavo F. Padovan } 41680a708f8fSGustavo F. Padovan 4169fb45de7dSAndrei Emeltchenko static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq) 41700a708f8fSGustavo F. Padovan { 41710a708f8fSGustavo F. Padovan struct sk_buff *skb; 417288843ab0SAndrei Emeltchenko u32 control; 41730a708f8fSGustavo F. Padovan 4174e328140fSMat Martineau while ((skb = skb_peek(&chan->srej_q)) && 4175e328140fSMat Martineau !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 4176e328140fSMat Martineau int err; 4177e328140fSMat Martineau 41783ce3514fSMat Martineau if (bt_cb(skb)->control.txseq != tx_seq) 41790a708f8fSGustavo F. Padovan break; 41800a708f8fSGustavo F. Padovan 4181f1c6775bSGustavo F. Padovan skb = skb_dequeue(&chan->srej_q); 41823ce3514fSMat Martineau control = __set_ctrl_sar(chan, bt_cb(skb)->control.sar); 418384084a31SMat Martineau err = l2cap_reassemble_sdu(chan, skb, control); 4184e328140fSMat Martineau 4185e328140fSMat Martineau if (err < 0) { 4186e328140fSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 4187e328140fSMat Martineau break; 4188e328140fSMat Martineau } 4189e328140fSMat Martineau 4190836be934SAndrei Emeltchenko chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej); 4191836be934SAndrei Emeltchenko tx_seq = __next_seq(chan, tx_seq); 41920a708f8fSGustavo F. Padovan } 41930a708f8fSGustavo F. Padovan } 41940a708f8fSGustavo F. Padovan 4195fb45de7dSAndrei Emeltchenko static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq) 41960a708f8fSGustavo F. Padovan { 41970a708f8fSGustavo F. Padovan struct srej_list *l, *tmp; 419888843ab0SAndrei Emeltchenko u32 control; 41990a708f8fSGustavo F. Padovan 420039d5a3eeSGustavo F. Padovan list_for_each_entry_safe(l, tmp, &chan->srej_l, list) { 42010a708f8fSGustavo F. Padovan if (l->tx_seq == tx_seq) { 42020a708f8fSGustavo F. Padovan list_del(&l->list); 42030a708f8fSGustavo F. Padovan kfree(l); 42040a708f8fSGustavo F. Padovan return; 42050a708f8fSGustavo F. Padovan } 4206ab784b73SAndrei Emeltchenko control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ); 42070b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, l->tx_seq); 4208525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 42090a708f8fSGustavo F. Padovan list_del(&l->list); 421039d5a3eeSGustavo F. Padovan list_add_tail(&l->list, &chan->srej_l); 42110a708f8fSGustavo F. Padovan } 42120a708f8fSGustavo F. Padovan } 42130a708f8fSGustavo F. Padovan 4214aef89f21SSzymon Janc static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq) 42150a708f8fSGustavo F. Padovan { 42160a708f8fSGustavo F. Padovan struct srej_list *new; 421788843ab0SAndrei Emeltchenko u32 control; 42180a708f8fSGustavo F. Padovan 421942e5c802SGustavo F. Padovan while (tx_seq != chan->expected_tx_seq) { 4220ab784b73SAndrei Emeltchenko control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ); 42210b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->expected_tx_seq); 42223c588192SMat Martineau l2cap_seq_list_append(&chan->srej_list, chan->expected_tx_seq); 4223525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 42240a708f8fSGustavo F. Padovan 42250a708f8fSGustavo F. Padovan new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); 4226aef89f21SSzymon Janc if (!new) 4227aef89f21SSzymon Janc return -ENOMEM; 4228aef89f21SSzymon Janc 422942e5c802SGustavo F. Padovan new->tx_seq = chan->expected_tx_seq; 4230836be934SAndrei Emeltchenko 4231836be934SAndrei Emeltchenko chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); 4232836be934SAndrei Emeltchenko 423339d5a3eeSGustavo F. Padovan list_add_tail(&new->list, &chan->srej_l); 42340a708f8fSGustavo F. Padovan } 4235836be934SAndrei Emeltchenko 4236836be934SAndrei Emeltchenko chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); 4237aef89f21SSzymon Janc 4238aef89f21SSzymon Janc return 0; 42390a708f8fSGustavo F. Padovan } 42400a708f8fSGustavo F. Padovan 424188843ab0SAndrei Emeltchenko static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb) 42420a708f8fSGustavo F. Padovan { 4243fb45de7dSAndrei Emeltchenko u16 tx_seq = __get_txseq(chan, rx_control); 42440b209faeSAndrei Emeltchenko u16 req_seq = __get_reqseq(chan, rx_control); 42457e0ef6eeSAndrei Emeltchenko u8 sar = __get_ctrl_sar(chan, rx_control); 42460a708f8fSGustavo F. Padovan int tx_seq_offset, expected_tx_seq_offset; 424747d1ec61SGustavo F. Padovan int num_to_ack = (chan->tx_win/6) + 1; 42480a708f8fSGustavo F. Padovan int err = 0; 42490a708f8fSGustavo F. Padovan 425088843ab0SAndrei Emeltchenko BT_DBG("chan %p len %d tx_seq %d rx_control 0x%8.8x", chan, skb->len, 4251525cd185SGustavo F. Padovan tx_seq, rx_control); 42520a708f8fSGustavo F. Padovan 425303f6715dSAndrei Emeltchenko if (__is_ctrl_final(chan, rx_control) && 4254e2ab4353SGustavo F. Padovan test_bit(CONN_WAIT_F, &chan->conn_state)) { 42551a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 42566a026610SGustavo F. Padovan if (chan->unacked_frames > 0) 42571a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 4258e2ab4353SGustavo F. Padovan clear_bit(CONN_WAIT_F, &chan->conn_state); 42590a708f8fSGustavo F. Padovan } 42600a708f8fSGustavo F. Padovan 426142e5c802SGustavo F. Padovan chan->expected_ack_seq = req_seq; 426242e5c802SGustavo F. Padovan l2cap_drop_acked_frames(chan); 42630a708f8fSGustavo F. Padovan 4264836be934SAndrei Emeltchenko tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq); 42650a708f8fSGustavo F. Padovan 42660a708f8fSGustavo F. Padovan /* invalid tx_seq */ 426747d1ec61SGustavo F. Padovan if (tx_seq_offset >= chan->tx_win) { 42688c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 42690a708f8fSGustavo F. Padovan goto drop; 42700a708f8fSGustavo F. Padovan } 42710a708f8fSGustavo F. Padovan 427277f918bcSSzymon Janc if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 427377f918bcSSzymon Janc if (!test_bit(CONN_RNR_SENT, &chan->conn_state)) 427477f918bcSSzymon Janc l2cap_send_ack(chan); 42750a708f8fSGustavo F. Padovan goto drop; 427677f918bcSSzymon Janc } 42770a708f8fSGustavo F. Padovan 427802f1b641SMat Martineau if (tx_seq == chan->expected_tx_seq) 427902f1b641SMat Martineau goto expected; 428002f1b641SMat Martineau 4281e2ab4353SGustavo F. Padovan if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) { 42820a708f8fSGustavo F. Padovan struct srej_list *first; 42830a708f8fSGustavo F. Padovan 428439d5a3eeSGustavo F. Padovan first = list_first_entry(&chan->srej_l, 42850a708f8fSGustavo F. Padovan struct srej_list, list); 42860a708f8fSGustavo F. Padovan if (tx_seq == first->tx_seq) { 428742e5c802SGustavo F. Padovan l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); 4288525cd185SGustavo F. Padovan l2cap_check_srej_gap(chan, tx_seq); 42890a708f8fSGustavo F. Padovan 42900a708f8fSGustavo F. Padovan list_del(&first->list); 42910a708f8fSGustavo F. Padovan kfree(first); 42920a708f8fSGustavo F. Padovan 429339d5a3eeSGustavo F. Padovan if (list_empty(&chan->srej_l)) { 429442e5c802SGustavo F. Padovan chan->buffer_seq = chan->buffer_seq_srej; 4295e2ab4353SGustavo F. Padovan clear_bit(CONN_SREJ_SENT, &chan->conn_state); 4296525cd185SGustavo F. Padovan l2cap_send_ack(chan); 429749208c9cSGustavo F. Padovan BT_DBG("chan %p, Exit SREJ_SENT", chan); 42980a708f8fSGustavo F. Padovan } 42990a708f8fSGustavo F. Padovan } else { 43000a708f8fSGustavo F. Padovan struct srej_list *l; 43010a708f8fSGustavo F. Padovan 43020a708f8fSGustavo F. Padovan /* duplicated tx_seq */ 430342e5c802SGustavo F. Padovan if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0) 43040a708f8fSGustavo F. Padovan goto drop; 43050a708f8fSGustavo F. Padovan 430639d5a3eeSGustavo F. Padovan list_for_each_entry(l, &chan->srej_l, list) { 43070a708f8fSGustavo F. Padovan if (l->tx_seq == tx_seq) { 4308525cd185SGustavo F. Padovan l2cap_resend_srejframe(chan, tx_seq); 43090a708f8fSGustavo F. Padovan return 0; 43100a708f8fSGustavo F. Padovan } 43110a708f8fSGustavo F. Padovan } 4312aef89f21SSzymon Janc 4313aef89f21SSzymon Janc err = l2cap_send_srejframe(chan, tx_seq); 4314aef89f21SSzymon Janc if (err < 0) { 4315aef89f21SSzymon Janc l2cap_send_disconn_req(chan->conn, chan, -err); 4316aef89f21SSzymon Janc return err; 4317aef89f21SSzymon Janc } 43180a708f8fSGustavo F. Padovan } 43190a708f8fSGustavo F. Padovan } else { 4320836be934SAndrei Emeltchenko expected_tx_seq_offset = __seq_offset(chan, 4321836be934SAndrei Emeltchenko chan->expected_tx_seq, chan->buffer_seq); 43220a708f8fSGustavo F. Padovan 43230a708f8fSGustavo F. Padovan /* duplicated tx_seq */ 43240a708f8fSGustavo F. Padovan if (tx_seq_offset < expected_tx_seq_offset) 43250a708f8fSGustavo F. Padovan goto drop; 43260a708f8fSGustavo F. Padovan 4327e2ab4353SGustavo F. Padovan set_bit(CONN_SREJ_SENT, &chan->conn_state); 43280a708f8fSGustavo F. Padovan 432949208c9cSGustavo F. Padovan BT_DBG("chan %p, Enter SREJ", chan); 43300a708f8fSGustavo F. Padovan 433139d5a3eeSGustavo F. Padovan INIT_LIST_HEAD(&chan->srej_l); 433242e5c802SGustavo F. Padovan chan->buffer_seq_srej = chan->buffer_seq; 43330a708f8fSGustavo F. Padovan 4334f1c6775bSGustavo F. Padovan __skb_queue_head_init(&chan->srej_q); 433542e5c802SGustavo F. Padovan l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); 43360a708f8fSGustavo F. Padovan 43370ef3ef0fSSzymon Janc /* Set P-bit only if there are some I-frames to ack. */ 43380ef3ef0fSSzymon Janc if (__clear_ack_timer(chan)) 4339e2ab4353SGustavo F. Padovan set_bit(CONN_SEND_PBIT, &chan->conn_state); 43400a708f8fSGustavo F. Padovan 4341aef89f21SSzymon Janc err = l2cap_send_srejframe(chan, tx_seq); 4342aef89f21SSzymon Janc if (err < 0) { 4343aef89f21SSzymon Janc l2cap_send_disconn_req(chan->conn, chan, -err); 4344aef89f21SSzymon Janc return err; 4345aef89f21SSzymon Janc } 43460a708f8fSGustavo F. Padovan } 43470a708f8fSGustavo F. Padovan return 0; 43480a708f8fSGustavo F. Padovan 43490a708f8fSGustavo F. Padovan expected: 4350836be934SAndrei Emeltchenko chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); 43510a708f8fSGustavo F. Padovan 4352e2ab4353SGustavo F. Padovan if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) { 43533ce3514fSMat Martineau bt_cb(skb)->control.txseq = tx_seq; 43543ce3514fSMat Martineau bt_cb(skb)->control.sar = sar; 4355f1c6775bSGustavo F. Padovan __skb_queue_tail(&chan->srej_q, skb); 43560a708f8fSGustavo F. Padovan return 0; 43570a708f8fSGustavo F. Padovan } 43580a708f8fSGustavo F. Padovan 435984084a31SMat Martineau err = l2cap_reassemble_sdu(chan, skb, rx_control); 4360836be934SAndrei Emeltchenko chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 4361836be934SAndrei Emeltchenko 4362e328140fSMat Martineau if (err < 0) { 4363e328140fSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 4364e328140fSMat Martineau return err; 4365e328140fSMat Martineau } 43660a708f8fSGustavo F. Padovan 436703f6715dSAndrei Emeltchenko if (__is_ctrl_final(chan, rx_control)) { 4368e2ab4353SGustavo F. Padovan if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 4369525cd185SGustavo F. Padovan l2cap_retransmit_frames(chan); 43700a708f8fSGustavo F. Padovan } 43710a708f8fSGustavo F. Padovan 43720a708f8fSGustavo F. Padovan 43736a026610SGustavo F. Padovan chan->num_acked = (chan->num_acked + 1) % num_to_ack; 43746a026610SGustavo F. Padovan if (chan->num_acked == num_to_ack - 1) 4375525cd185SGustavo F. Padovan l2cap_send_ack(chan); 43764d611e4dSGustavo F. Padovan else 43774d611e4dSGustavo F. Padovan __set_ack_timer(chan); 43780a708f8fSGustavo F. Padovan 43790a708f8fSGustavo F. Padovan return 0; 43800a708f8fSGustavo F. Padovan 43810a708f8fSGustavo F. Padovan drop: 43820a708f8fSGustavo F. Padovan kfree_skb(skb); 43830a708f8fSGustavo F. Padovan return 0; 43840a708f8fSGustavo F. Padovan } 43850a708f8fSGustavo F. Padovan 438688843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control) 43870a708f8fSGustavo F. Padovan { 438888843ab0SAndrei Emeltchenko BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, 43890b209faeSAndrei Emeltchenko __get_reqseq(chan, rx_control), rx_control); 43900a708f8fSGustavo F. Padovan 43910b209faeSAndrei Emeltchenko chan->expected_ack_seq = __get_reqseq(chan, rx_control); 439242e5c802SGustavo F. Padovan l2cap_drop_acked_frames(chan); 43930a708f8fSGustavo F. Padovan 4394e3781735SAndrei Emeltchenko if (__is_ctrl_poll(chan, rx_control)) { 4395e2ab4353SGustavo F. Padovan set_bit(CONN_SEND_FBIT, &chan->conn_state); 4396e2ab4353SGustavo F. Padovan if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) { 4397e2ab4353SGustavo F. Padovan if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 43986a026610SGustavo F. Padovan (chan->unacked_frames > 0)) 43991a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 44000a708f8fSGustavo F. Padovan 4401e2ab4353SGustavo F. Padovan clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4402525cd185SGustavo F. Padovan l2cap_send_srejtail(chan); 44030a708f8fSGustavo F. Padovan } else { 4404525cd185SGustavo F. Padovan l2cap_send_i_or_rr_or_rnr(chan); 44050a708f8fSGustavo F. Padovan } 44060a708f8fSGustavo F. Padovan 440703f6715dSAndrei Emeltchenko } else if (__is_ctrl_final(chan, rx_control)) { 4408e2ab4353SGustavo F. Padovan clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 44090a708f8fSGustavo F. Padovan 4410e2ab4353SGustavo F. Padovan if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 4411525cd185SGustavo F. Padovan l2cap_retransmit_frames(chan); 44120a708f8fSGustavo F. Padovan 44130a708f8fSGustavo F. Padovan } else { 4414e2ab4353SGustavo F. Padovan if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 44156a026610SGustavo F. Padovan (chan->unacked_frames > 0)) 44161a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 44170a708f8fSGustavo F. Padovan 4418e2ab4353SGustavo F. Padovan clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4419e2ab4353SGustavo F. Padovan if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) 4420525cd185SGustavo F. Padovan l2cap_send_ack(chan); 44210a708f8fSGustavo F. Padovan else 4422525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 44230a708f8fSGustavo F. Padovan } 44240a708f8fSGustavo F. Padovan } 44250a708f8fSGustavo F. Padovan 442688843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control) 44270a708f8fSGustavo F. Padovan { 44280b209faeSAndrei Emeltchenko u16 tx_seq = __get_reqseq(chan, rx_control); 44290a708f8fSGustavo F. Padovan 443088843ab0SAndrei Emeltchenko BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control); 44310a708f8fSGustavo F. Padovan 4432e2ab4353SGustavo F. Padovan clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 44330a708f8fSGustavo F. Padovan 443442e5c802SGustavo F. Padovan chan->expected_ack_seq = tx_seq; 443542e5c802SGustavo F. Padovan l2cap_drop_acked_frames(chan); 44360a708f8fSGustavo F. Padovan 443703f6715dSAndrei Emeltchenko if (__is_ctrl_final(chan, rx_control)) { 4438e2ab4353SGustavo F. Padovan if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 4439525cd185SGustavo F. Padovan l2cap_retransmit_frames(chan); 44400a708f8fSGustavo F. Padovan } else { 4441525cd185SGustavo F. Padovan l2cap_retransmit_frames(chan); 44420a708f8fSGustavo F. Padovan 4443e2ab4353SGustavo F. Padovan if (test_bit(CONN_WAIT_F, &chan->conn_state)) 4444e2ab4353SGustavo F. Padovan set_bit(CONN_REJ_ACT, &chan->conn_state); 44450a708f8fSGustavo F. Padovan } 44460a708f8fSGustavo F. Padovan } 444788843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control) 44480a708f8fSGustavo F. Padovan { 44490b209faeSAndrei Emeltchenko u16 tx_seq = __get_reqseq(chan, rx_control); 44500a708f8fSGustavo F. Padovan 445188843ab0SAndrei Emeltchenko BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control); 44520a708f8fSGustavo F. Padovan 4453e2ab4353SGustavo F. Padovan clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 44540a708f8fSGustavo F. Padovan 4455e3781735SAndrei Emeltchenko if (__is_ctrl_poll(chan, rx_control)) { 445642e5c802SGustavo F. Padovan chan->expected_ack_seq = tx_seq; 445742e5c802SGustavo F. Padovan l2cap_drop_acked_frames(chan); 44580a708f8fSGustavo F. Padovan 4459e2ab4353SGustavo F. Padovan set_bit(CONN_SEND_FBIT, &chan->conn_state); 4460525cd185SGustavo F. Padovan l2cap_retransmit_one_frame(chan, tx_seq); 44610a708f8fSGustavo F. Padovan 4462525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 44630a708f8fSGustavo F. Padovan 4464e2ab4353SGustavo F. Padovan if (test_bit(CONN_WAIT_F, &chan->conn_state)) { 44656a026610SGustavo F. Padovan chan->srej_save_reqseq = tx_seq; 4466e2ab4353SGustavo F. Padovan set_bit(CONN_SREJ_ACT, &chan->conn_state); 44670a708f8fSGustavo F. Padovan } 446803f6715dSAndrei Emeltchenko } else if (__is_ctrl_final(chan, rx_control)) { 4469e2ab4353SGustavo F. Padovan if (test_bit(CONN_SREJ_ACT, &chan->conn_state) && 44706a026610SGustavo F. Padovan chan->srej_save_reqseq == tx_seq) 4471e2ab4353SGustavo F. Padovan clear_bit(CONN_SREJ_ACT, &chan->conn_state); 44720a708f8fSGustavo F. Padovan else 4473525cd185SGustavo F. Padovan l2cap_retransmit_one_frame(chan, tx_seq); 44740a708f8fSGustavo F. Padovan } else { 4475525cd185SGustavo F. Padovan l2cap_retransmit_one_frame(chan, tx_seq); 4476e2ab4353SGustavo F. Padovan if (test_bit(CONN_WAIT_F, &chan->conn_state)) { 44776a026610SGustavo F. Padovan chan->srej_save_reqseq = tx_seq; 4478e2ab4353SGustavo F. Padovan set_bit(CONN_SREJ_ACT, &chan->conn_state); 44790a708f8fSGustavo F. Padovan } 44800a708f8fSGustavo F. Padovan } 44810a708f8fSGustavo F. Padovan } 44820a708f8fSGustavo F. Padovan 448388843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control) 44840a708f8fSGustavo F. Padovan { 44850b209faeSAndrei Emeltchenko u16 tx_seq = __get_reqseq(chan, rx_control); 44860a708f8fSGustavo F. Padovan 448788843ab0SAndrei Emeltchenko BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control); 44880a708f8fSGustavo F. Padovan 4489e2ab4353SGustavo F. Padovan set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 449042e5c802SGustavo F. Padovan chan->expected_ack_seq = tx_seq; 449142e5c802SGustavo F. Padovan l2cap_drop_acked_frames(chan); 44920a708f8fSGustavo F. Padovan 4493e3781735SAndrei Emeltchenko if (__is_ctrl_poll(chan, rx_control)) 4494e2ab4353SGustavo F. Padovan set_bit(CONN_SEND_FBIT, &chan->conn_state); 44950a708f8fSGustavo F. Padovan 4496e2ab4353SGustavo F. Padovan if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) { 44971a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 4498e3781735SAndrei Emeltchenko if (__is_ctrl_poll(chan, rx_control)) 4499525cd185SGustavo F. Padovan l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL); 45000a708f8fSGustavo F. Padovan return; 45010a708f8fSGustavo F. Padovan } 45020a708f8fSGustavo F. Padovan 4503e3781735SAndrei Emeltchenko if (__is_ctrl_poll(chan, rx_control)) { 4504525cd185SGustavo F. Padovan l2cap_send_srejtail(chan); 4505ab784b73SAndrei Emeltchenko } else { 4506ab784b73SAndrei Emeltchenko rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR); 4507ab784b73SAndrei Emeltchenko l2cap_send_sframe(chan, rx_control); 4508ab784b73SAndrei Emeltchenko } 45090a708f8fSGustavo F. Padovan } 45100a708f8fSGustavo F. Padovan 451188843ab0SAndrei Emeltchenko static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb) 45120a708f8fSGustavo F. Padovan { 451388843ab0SAndrei Emeltchenko BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len); 45140a708f8fSGustavo F. Padovan 451503f6715dSAndrei Emeltchenko if (__is_ctrl_final(chan, rx_control) && 4516e2ab4353SGustavo F. Padovan test_bit(CONN_WAIT_F, &chan->conn_state)) { 45171a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 45186a026610SGustavo F. Padovan if (chan->unacked_frames > 0) 45191a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 4520e2ab4353SGustavo F. Padovan clear_bit(CONN_WAIT_F, &chan->conn_state); 45210a708f8fSGustavo F. Padovan } 45220a708f8fSGustavo F. Padovan 4523ab784b73SAndrei Emeltchenko switch (__get_ctrl_super(chan, rx_control)) { 4524ab784b73SAndrei Emeltchenko case L2CAP_SUPER_RR: 4525525cd185SGustavo F. Padovan l2cap_data_channel_rrframe(chan, rx_control); 45260a708f8fSGustavo F. Padovan break; 45270a708f8fSGustavo F. Padovan 4528ab784b73SAndrei Emeltchenko case L2CAP_SUPER_REJ: 4529525cd185SGustavo F. Padovan l2cap_data_channel_rejframe(chan, rx_control); 45300a708f8fSGustavo F. Padovan break; 45310a708f8fSGustavo F. Padovan 4532ab784b73SAndrei Emeltchenko case L2CAP_SUPER_SREJ: 4533525cd185SGustavo F. Padovan l2cap_data_channel_srejframe(chan, rx_control); 45340a708f8fSGustavo F. Padovan break; 45350a708f8fSGustavo F. Padovan 4536ab784b73SAndrei Emeltchenko case L2CAP_SUPER_RNR: 4537525cd185SGustavo F. Padovan l2cap_data_channel_rnrframe(chan, rx_control); 45380a708f8fSGustavo F. Padovan break; 45390a708f8fSGustavo F. Padovan } 45400a708f8fSGustavo F. Padovan 45410a708f8fSGustavo F. Padovan kfree_skb(skb); 45420a708f8fSGustavo F. Padovan return 0; 45430a708f8fSGustavo F. Padovan } 45440a708f8fSGustavo F. Padovan 4545cad8f1d0SSzymon Janc static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 45460a708f8fSGustavo F. Padovan { 454788843ab0SAndrei Emeltchenko u32 control; 45480b209faeSAndrei Emeltchenko u16 req_seq; 45490a708f8fSGustavo F. Padovan int len, next_tx_seq_offset, req_seq_offset; 45500a708f8fSGustavo F. Padovan 4551b76bbd66SMat Martineau __unpack_control(chan, skb); 4552b76bbd66SMat Martineau 455388843ab0SAndrei Emeltchenko control = __get_control(chan, skb->data); 455488843ab0SAndrei Emeltchenko skb_pull(skb, __ctrl_size(chan)); 45550a708f8fSGustavo F. Padovan len = skb->len; 45560a708f8fSGustavo F. Padovan 45570a708f8fSGustavo F. Padovan /* 45580a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here. 45590a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery 45600a708f8fSGustavo F. Padovan * procedures and ask retransmission. 45610a708f8fSGustavo F. Padovan */ 456247d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 45630a708f8fSGustavo F. Padovan goto drop; 45640a708f8fSGustavo F. Padovan 4565793c2f1cSAndrei Emeltchenko if (__is_sar_start(chan, control) && !__is_sframe(chan, control)) 456603a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 45670a708f8fSGustavo F. Padovan 456847d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 456903a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 45700a708f8fSGustavo F. Padovan 457147d1ec61SGustavo F. Padovan if (len > chan->mps) { 45728c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 45730a708f8fSGustavo F. Padovan goto drop; 45740a708f8fSGustavo F. Padovan } 45750a708f8fSGustavo F. Padovan 45760b209faeSAndrei Emeltchenko req_seq = __get_reqseq(chan, control); 45770a708f8fSGustavo F. Padovan 4578836be934SAndrei Emeltchenko req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq); 4579836be934SAndrei Emeltchenko 4580836be934SAndrei Emeltchenko next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq, 4581836be934SAndrei Emeltchenko chan->expected_ack_seq); 45820a708f8fSGustavo F. Padovan 45830a708f8fSGustavo F. Padovan /* check for invalid req-seq */ 45840a708f8fSGustavo F. Padovan if (req_seq_offset > next_tx_seq_offset) { 45858c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 45860a708f8fSGustavo F. Padovan goto drop; 45870a708f8fSGustavo F. Padovan } 45880a708f8fSGustavo F. Padovan 4589793c2f1cSAndrei Emeltchenko if (!__is_sframe(chan, control)) { 45900a708f8fSGustavo F. Padovan if (len < 0) { 45918c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 45920a708f8fSGustavo F. Padovan goto drop; 45930a708f8fSGustavo F. Padovan } 45940a708f8fSGustavo F. Padovan 4595525cd185SGustavo F. Padovan l2cap_data_channel_iframe(chan, control, skb); 45960a708f8fSGustavo F. Padovan } else { 45970a708f8fSGustavo F. Padovan if (len != 0) { 45980a708f8fSGustavo F. Padovan BT_ERR("%d", len); 45998c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 46000a708f8fSGustavo F. Padovan goto drop; 46010a708f8fSGustavo F. Padovan } 46020a708f8fSGustavo F. Padovan 4603525cd185SGustavo F. Padovan l2cap_data_channel_sframe(chan, control, skb); 46040a708f8fSGustavo F. Padovan } 46050a708f8fSGustavo F. Padovan 46060a708f8fSGustavo F. Padovan return 0; 46070a708f8fSGustavo F. Padovan 46080a708f8fSGustavo F. Padovan drop: 46090a708f8fSGustavo F. Padovan kfree_skb(skb); 46100a708f8fSGustavo F. Padovan return 0; 46110a708f8fSGustavo F. Padovan } 46120a708f8fSGustavo F. Padovan 46130a708f8fSGustavo F. Padovan static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb) 46140a708f8fSGustavo F. Padovan { 461548454079SGustavo F. Padovan struct l2cap_chan *chan; 461688843ab0SAndrei Emeltchenko u32 control; 4617fb45de7dSAndrei Emeltchenko u16 tx_seq; 46180a708f8fSGustavo F. Padovan int len; 46190a708f8fSGustavo F. Padovan 4620baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 462148454079SGustavo F. Padovan if (!chan) { 46220a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid); 46236be36555SAndrei Emeltchenko /* Drop packet and return */ 46243379013bSDan Carpenter kfree_skb(skb); 46256be36555SAndrei Emeltchenko return 0; 46260a708f8fSGustavo F. Padovan } 46270a708f8fSGustavo F. Padovan 46286be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 46290a708f8fSGustavo F. Padovan 463049208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len); 46310a708f8fSGustavo F. Padovan 463289bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 46330a708f8fSGustavo F. Padovan goto drop; 46340a708f8fSGustavo F. Padovan 46350c1bc5c6SGustavo F. Padovan switch (chan->mode) { 46360a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 46370a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here 46380a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable. 46390a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't 46400a708f8fSGustavo F. Padovan * provide flow control mechanism. */ 46410a708f8fSGustavo F. Padovan 46420c1bc5c6SGustavo F. Padovan if (chan->imtu < skb->len) 46430a708f8fSGustavo F. Padovan goto drop; 46440a708f8fSGustavo F. Padovan 464523070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 46460a708f8fSGustavo F. Padovan goto done; 46470a708f8fSGustavo F. Padovan break; 46480a708f8fSGustavo F. Padovan 46490a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 46505ef8cb9eSAndrei Emeltchenko l2cap_ertm_data_rcv(chan, skb); 46510a708f8fSGustavo F. Padovan 46520a708f8fSGustavo F. Padovan goto done; 46530a708f8fSGustavo F. Padovan 46540a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 465588843ab0SAndrei Emeltchenko control = __get_control(chan, skb->data); 465688843ab0SAndrei Emeltchenko skb_pull(skb, __ctrl_size(chan)); 46570a708f8fSGustavo F. Padovan len = skb->len; 46580a708f8fSGustavo F. Padovan 465947d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 46600a708f8fSGustavo F. Padovan goto drop; 46610a708f8fSGustavo F. Padovan 46627e0ef6eeSAndrei Emeltchenko if (__is_sar_start(chan, control)) 466303a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 46640a708f8fSGustavo F. Padovan 466547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 466603a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 46670a708f8fSGustavo F. Padovan 4668793c2f1cSAndrei Emeltchenko if (len > chan->mps || len < 0 || __is_sframe(chan, control)) 46690a708f8fSGustavo F. Padovan goto drop; 46700a708f8fSGustavo F. Padovan 4671fb45de7dSAndrei Emeltchenko tx_seq = __get_txseq(chan, control); 46720a708f8fSGustavo F. Padovan 467384084a31SMat Martineau if (chan->expected_tx_seq != tx_seq) { 467484084a31SMat Martineau /* Frame(s) missing - must discard partial SDU */ 467584084a31SMat Martineau kfree_skb(chan->sdu); 467684084a31SMat Martineau chan->sdu = NULL; 467784084a31SMat Martineau chan->sdu_last_frag = NULL; 467884084a31SMat Martineau chan->sdu_len = 0; 467984084a31SMat Martineau 468084084a31SMat Martineau /* TODO: Notify userland of missing data */ 468184084a31SMat Martineau } 468284084a31SMat Martineau 4683836be934SAndrei Emeltchenko chan->expected_tx_seq = __next_seq(chan, tx_seq); 46840a708f8fSGustavo F. Padovan 468584084a31SMat Martineau if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE) 468684084a31SMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 46870a708f8fSGustavo F. Padovan 46880a708f8fSGustavo F. Padovan goto done; 46890a708f8fSGustavo F. Padovan 46900a708f8fSGustavo F. Padovan default: 46910c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); 46920a708f8fSGustavo F. Padovan break; 46930a708f8fSGustavo F. Padovan } 46940a708f8fSGustavo F. Padovan 46950a708f8fSGustavo F. Padovan drop: 46960a708f8fSGustavo F. Padovan kfree_skb(skb); 46970a708f8fSGustavo F. Padovan 46980a708f8fSGustavo F. Padovan done: 46996be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 47000a708f8fSGustavo F. Padovan 47010a708f8fSGustavo F. Padovan return 0; 47020a708f8fSGustavo F. Padovan } 47030a708f8fSGustavo F. Padovan 47040a708f8fSGustavo F. Padovan static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb) 47050a708f8fSGustavo F. Padovan { 470623691d75SGustavo F. Padovan struct l2cap_chan *chan; 47070a708f8fSGustavo F. Padovan 4708c2287681SIdo Yariv chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst); 470923691d75SGustavo F. Padovan if (!chan) 47100a708f8fSGustavo F. Padovan goto drop; 47110a708f8fSGustavo F. Padovan 47125b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 47130a708f8fSGustavo F. Padovan 471489bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 47150a708f8fSGustavo F. Padovan goto drop; 47160a708f8fSGustavo F. Padovan 4717e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 47180a708f8fSGustavo F. Padovan goto drop; 47190a708f8fSGustavo F. Padovan 472023070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 47215b4cedaaSAndrei Emeltchenko return 0; 47220a708f8fSGustavo F. Padovan 47230a708f8fSGustavo F. Padovan drop: 47240a708f8fSGustavo F. Padovan kfree_skb(skb); 47250a708f8fSGustavo F. Padovan 47260a708f8fSGustavo F. Padovan return 0; 47270a708f8fSGustavo F. Padovan } 47280a708f8fSGustavo F. Padovan 4729d9b88702SAndrei Emeltchenko static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid, 4730d9b88702SAndrei Emeltchenko struct sk_buff *skb) 47319f69bda6SGustavo F. Padovan { 473223691d75SGustavo F. Padovan struct l2cap_chan *chan; 47339f69bda6SGustavo F. Padovan 4734c2287681SIdo Yariv chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst); 473523691d75SGustavo F. Padovan if (!chan) 47369f69bda6SGustavo F. Padovan goto drop; 47379f69bda6SGustavo F. Padovan 47385b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 47399f69bda6SGustavo F. Padovan 474089bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 47419f69bda6SGustavo F. Padovan goto drop; 47429f69bda6SGustavo F. Padovan 4743e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 47449f69bda6SGustavo F. Padovan goto drop; 47459f69bda6SGustavo F. Padovan 474623070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 47475b4cedaaSAndrei Emeltchenko return 0; 47489f69bda6SGustavo F. Padovan 47499f69bda6SGustavo F. Padovan drop: 47509f69bda6SGustavo F. Padovan kfree_skb(skb); 47519f69bda6SGustavo F. Padovan 47529f69bda6SGustavo F. Padovan return 0; 47539f69bda6SGustavo F. Padovan } 47549f69bda6SGustavo F. Padovan 47550a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) 47560a708f8fSGustavo F. Padovan { 47570a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data; 47580a708f8fSGustavo F. Padovan u16 cid, len; 47590a708f8fSGustavo F. Padovan __le16 psm; 47600a708f8fSGustavo F. Padovan 47610a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE); 47620a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid); 47630a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len); 47640a708f8fSGustavo F. Padovan 47650a708f8fSGustavo F. Padovan if (len != skb->len) { 47660a708f8fSGustavo F. Padovan kfree_skb(skb); 47670a708f8fSGustavo F. Padovan return; 47680a708f8fSGustavo F. Padovan } 47690a708f8fSGustavo F. Padovan 47700a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid); 47710a708f8fSGustavo F. Padovan 47720a708f8fSGustavo F. Padovan switch (cid) { 47733300d9a9SClaudio Takahasi case L2CAP_CID_LE_SIGNALING: 47740a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING: 47750a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb); 47760a708f8fSGustavo F. Padovan break; 47770a708f8fSGustavo F. Padovan 47780a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS: 4779097db76cSAndrei Emeltchenko psm = get_unaligned((__le16 *) skb->data); 47800a708f8fSGustavo F. Padovan skb_pull(skb, 2); 47810a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb); 47820a708f8fSGustavo F. Padovan break; 47830a708f8fSGustavo F. Padovan 47849f69bda6SGustavo F. Padovan case L2CAP_CID_LE_DATA: 47859f69bda6SGustavo F. Padovan l2cap_att_channel(conn, cid, skb); 47869f69bda6SGustavo F. Padovan break; 47879f69bda6SGustavo F. Padovan 4788b501d6a1SAnderson Briglia case L2CAP_CID_SMP: 4789b501d6a1SAnderson Briglia if (smp_sig_channel(conn, skb)) 4790b501d6a1SAnderson Briglia l2cap_conn_del(conn->hcon, EACCES); 4791b501d6a1SAnderson Briglia break; 4792b501d6a1SAnderson Briglia 47930a708f8fSGustavo F. Padovan default: 47940a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb); 47950a708f8fSGustavo F. Padovan break; 47960a708f8fSGustavo F. Padovan } 47970a708f8fSGustavo F. Padovan } 47980a708f8fSGustavo F. Padovan 47990a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */ 48000a708f8fSGustavo F. Padovan 4801686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) 48020a708f8fSGustavo F. Padovan { 48030a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0; 480423691d75SGustavo F. Padovan struct l2cap_chan *c; 48050a708f8fSGustavo F. Padovan 48060a708f8fSGustavo F. Padovan BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); 48070a708f8fSGustavo F. Padovan 48080a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */ 480923691d75SGustavo F. Padovan read_lock(&chan_list_lock); 481023691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 481123691d75SGustavo F. Padovan struct sock *sk = c->sk; 48124343478fSGustavo F. Padovan 481389bc500eSGustavo F. Padovan if (c->state != BT_LISTEN) 48140a708f8fSGustavo F. Padovan continue; 48150a708f8fSGustavo F. Padovan 48160a708f8fSGustavo F. Padovan if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { 48170a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT; 481843bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 48190a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER; 48200a708f8fSGustavo F. Padovan exact++; 48210a708f8fSGustavo F. Padovan } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { 48220a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT; 482343bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 48240a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER; 48250a708f8fSGustavo F. Padovan } 48260a708f8fSGustavo F. Padovan } 482723691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 48280a708f8fSGustavo F. Padovan 48290a708f8fSGustavo F. Padovan return exact ? lm1 : lm2; 48300a708f8fSGustavo F. Padovan } 48310a708f8fSGustavo F. Padovan 4832686ebf28SUlisses Furquim int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) 48330a708f8fSGustavo F. Padovan { 48340a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 48350a708f8fSGustavo F. Padovan 48360a708f8fSGustavo F. Padovan BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); 48370a708f8fSGustavo F. Padovan 48380a708f8fSGustavo F. Padovan if (!status) { 48390a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, status); 48400a708f8fSGustavo F. Padovan if (conn) 48410a708f8fSGustavo F. Padovan l2cap_conn_ready(conn); 48420a708f8fSGustavo F. Padovan } else 4843e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status)); 48440a708f8fSGustavo F. Padovan 48450a708f8fSGustavo F. Padovan return 0; 48460a708f8fSGustavo F. Padovan } 48470a708f8fSGustavo F. Padovan 4848686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon) 48490a708f8fSGustavo F. Padovan { 48500a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 48510a708f8fSGustavo F. Padovan 48520a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon); 48530a708f8fSGustavo F. Padovan 4854686ebf28SUlisses Furquim if (!conn) 48559f5a0d7bSAndrei Emeltchenko return HCI_ERROR_REMOTE_USER_TERM; 48560a708f8fSGustavo F. Padovan return conn->disc_reason; 48570a708f8fSGustavo F. Padovan } 48580a708f8fSGustavo F. Padovan 4859686ebf28SUlisses Furquim int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) 48600a708f8fSGustavo F. Padovan { 48610a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason); 48620a708f8fSGustavo F. Padovan 4863e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason)); 48640a708f8fSGustavo F. Padovan return 0; 48650a708f8fSGustavo F. Padovan } 48660a708f8fSGustavo F. Padovan 48674343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) 48680a708f8fSGustavo F. Padovan { 4869715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 48700a708f8fSGustavo F. Padovan return; 48710a708f8fSGustavo F. Padovan 48720a708f8fSGustavo F. Padovan if (encrypt == 0x00) { 48734343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) { 4874ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); 48754343478fSGustavo F. Padovan } else if (chan->sec_level == BT_SECURITY_HIGH) 48760f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED); 48770a708f8fSGustavo F. Padovan } else { 48784343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) 4879c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 48800a708f8fSGustavo F. Padovan } 48810a708f8fSGustavo F. Padovan } 48820a708f8fSGustavo F. Padovan 4883686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) 48840a708f8fSGustavo F. Padovan { 48850a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 488648454079SGustavo F. Padovan struct l2cap_chan *chan; 48870a708f8fSGustavo F. Padovan 48880a708f8fSGustavo F. Padovan if (!conn) 48890a708f8fSGustavo F. Padovan return 0; 48900a708f8fSGustavo F. Padovan 48910a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 48920a708f8fSGustavo F. Padovan 4893160dc6acSVinicius Costa Gomes if (hcon->type == LE_LINK) { 489435d4adccSHemant Gupta if (!status && encrypt) 4895160dc6acSVinicius Costa Gomes smp_distribute_keys(conn, 0); 489617cd3f37SUlisses Furquim cancel_delayed_work(&conn->security_timer); 4897160dc6acSVinicius Costa Gomes } 4898160dc6acSVinicius Costa Gomes 48993df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 49000a708f8fSGustavo F. Padovan 49013df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 49026be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 49030a708f8fSGustavo F. Padovan 4904f1cb9af5SVinicius Costa Gomes BT_DBG("chan->scid %d", chan->scid); 4905f1cb9af5SVinicius Costa Gomes 4906f1cb9af5SVinicius Costa Gomes if (chan->scid == L2CAP_CID_LE_DATA) { 4907f1cb9af5SVinicius Costa Gomes if (!status && encrypt) { 4908f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level; 4909cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 4910f1cb9af5SVinicius Costa Gomes } 4911f1cb9af5SVinicius Costa Gomes 49126be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 4913f1cb9af5SVinicius Costa Gomes continue; 4914f1cb9af5SVinicius Costa Gomes } 4915f1cb9af5SVinicius Costa Gomes 4916c1360a1cSGustavo F. Padovan if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) { 49176be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 49180a708f8fSGustavo F. Padovan continue; 49190a708f8fSGustavo F. Padovan } 49200a708f8fSGustavo F. Padovan 492189bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED || 492289bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) { 4923a7d7723aSGustavo Padovan struct sock *sk = chan->sk; 4924a7d7723aSGustavo Padovan 4925a7d7723aSGustavo Padovan bt_sk(sk)->suspended = false; 4926a7d7723aSGustavo Padovan sk->sk_state_change(sk); 4927a7d7723aSGustavo Padovan 49284343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt); 49296be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 49300a708f8fSGustavo F. Padovan continue; 49310a708f8fSGustavo F. Padovan } 49320a708f8fSGustavo F. Padovan 493389bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 49340a708f8fSGustavo F. Padovan if (!status) { 49359b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 49360a708f8fSGustavo F. Padovan } else { 4937ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 49380a708f8fSGustavo F. Padovan } 493989bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 49406be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 49410a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 4942df3c3931SJohan Hedberg __u16 res, stat; 49430a708f8fSGustavo F. Padovan 49446be36555SAndrei Emeltchenko lock_sock(sk); 49456be36555SAndrei Emeltchenko 49460a708f8fSGustavo F. Padovan if (!status) { 4947df3c3931SJohan Hedberg if (bt_sk(sk)->defer_setup) { 4948df3c3931SJohan Hedberg struct sock *parent = bt_sk(sk)->parent; 4949df3c3931SJohan Hedberg res = L2CAP_CR_PEND; 4950df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND; 495105e9a2f6SIlia Kolomisnky if (parent) 4952df3c3931SJohan Hedberg parent->sk_data_ready(parent, 0); 4953df3c3931SJohan Hedberg } else { 49540e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 4955df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS; 4956df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 4957df3c3931SJohan Hedberg } 49580a708f8fSGustavo F. Padovan } else { 49590e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_DISCONN); 4960ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 4961df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK; 4962df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 49630a708f8fSGustavo F. Padovan } 49640a708f8fSGustavo F. Padovan 49656be36555SAndrei Emeltchenko release_sock(sk); 49666be36555SAndrei Emeltchenko 4967fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 4968fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 4969df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res); 4970df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat); 4971fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 4972fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 49730a708f8fSGustavo F. Padovan } 49740a708f8fSGustavo F. Padovan 49756be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 49760a708f8fSGustavo F. Padovan } 49770a708f8fSGustavo F. Padovan 49783df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 49790a708f8fSGustavo F. Padovan 49800a708f8fSGustavo F. Padovan return 0; 49810a708f8fSGustavo F. Padovan } 49820a708f8fSGustavo F. Padovan 4983686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) 49840a708f8fSGustavo F. Padovan { 49850a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 49860a708f8fSGustavo F. Padovan 49870a708f8fSGustavo F. Padovan if (!conn) 49880a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, 0); 49890a708f8fSGustavo F. Padovan 49900a708f8fSGustavo F. Padovan if (!conn) 49910a708f8fSGustavo F. Padovan goto drop; 49920a708f8fSGustavo F. Padovan 49930a708f8fSGustavo F. Padovan BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); 49940a708f8fSGustavo F. Padovan 49950a708f8fSGustavo F. Padovan if (!(flags & ACL_CONT)) { 49960a708f8fSGustavo F. Padovan struct l2cap_hdr *hdr; 499748454079SGustavo F. Padovan struct l2cap_chan *chan; 49980a708f8fSGustavo F. Padovan u16 cid; 49990a708f8fSGustavo F. Padovan int len; 50000a708f8fSGustavo F. Padovan 50010a708f8fSGustavo F. Padovan if (conn->rx_len) { 50020a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len); 50030a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 50040a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 50050a708f8fSGustavo F. Padovan conn->rx_len = 0; 50060a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 50070a708f8fSGustavo F. Padovan } 50080a708f8fSGustavo F. Padovan 50090a708f8fSGustavo F. Padovan /* Start fragment always begin with Basic L2CAP header */ 50100a708f8fSGustavo F. Padovan if (skb->len < L2CAP_HDR_SIZE) { 50110a708f8fSGustavo F. Padovan BT_ERR("Frame is too short (len %d)", skb->len); 50120a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 50130a708f8fSGustavo F. Padovan goto drop; 50140a708f8fSGustavo F. Padovan } 50150a708f8fSGustavo F. Padovan 50160a708f8fSGustavo F. Padovan hdr = (struct l2cap_hdr *) skb->data; 50170a708f8fSGustavo F. Padovan len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; 50180a708f8fSGustavo F. Padovan cid = __le16_to_cpu(hdr->cid); 50190a708f8fSGustavo F. Padovan 50200a708f8fSGustavo F. Padovan if (len == skb->len) { 50210a708f8fSGustavo F. Padovan /* Complete frame received */ 50220a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb); 50230a708f8fSGustavo F. Padovan return 0; 50240a708f8fSGustavo F. Padovan } 50250a708f8fSGustavo F. Padovan 50260a708f8fSGustavo F. Padovan BT_DBG("Start: total len %d, frag len %d", len, skb->len); 50270a708f8fSGustavo F. Padovan 50280a708f8fSGustavo F. Padovan if (skb->len > len) { 50290a708f8fSGustavo F. Padovan BT_ERR("Frame is too long (len %d, expected len %d)", 50300a708f8fSGustavo F. Padovan skb->len, len); 50310a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 50320a708f8fSGustavo F. Padovan goto drop; 50330a708f8fSGustavo F. Padovan } 50340a708f8fSGustavo F. Padovan 5035baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 50360a708f8fSGustavo F. Padovan 503748454079SGustavo F. Padovan if (chan && chan->sk) { 503848454079SGustavo F. Padovan struct sock *sk = chan->sk; 50393df91ea2SAndrei Emeltchenko lock_sock(sk); 504048454079SGustavo F. Padovan 50410c1bc5c6SGustavo F. Padovan if (chan->imtu < len - L2CAP_HDR_SIZE) { 504248454079SGustavo F. Padovan BT_ERR("Frame exceeding recv MTU (len %d, " 504348454079SGustavo F. Padovan "MTU %d)", len, 50440c1bc5c6SGustavo F. Padovan chan->imtu); 5045aa2ac881SGustavo F. Padovan release_sock(sk); 50460a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 50470a708f8fSGustavo F. Padovan goto drop; 50480a708f8fSGustavo F. Padovan } 5049aa2ac881SGustavo F. Padovan release_sock(sk); 505048454079SGustavo F. Padovan } 50510a708f8fSGustavo F. Padovan 50520a708f8fSGustavo F. Padovan /* Allocate skb for the complete frame (with header) */ 50530a708f8fSGustavo F. Padovan conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC); 50540a708f8fSGustavo F. Padovan if (!conn->rx_skb) 50550a708f8fSGustavo F. Padovan goto drop; 50560a708f8fSGustavo F. Padovan 50570a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 50580a708f8fSGustavo F. Padovan skb->len); 50590a708f8fSGustavo F. Padovan conn->rx_len = len - skb->len; 50600a708f8fSGustavo F. Padovan } else { 50610a708f8fSGustavo F. Padovan BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); 50620a708f8fSGustavo F. Padovan 50630a708f8fSGustavo F. Padovan if (!conn->rx_len) { 50640a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len); 50650a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 50660a708f8fSGustavo F. Padovan goto drop; 50670a708f8fSGustavo F. Padovan } 50680a708f8fSGustavo F. Padovan 50690a708f8fSGustavo F. Padovan if (skb->len > conn->rx_len) { 50700a708f8fSGustavo F. Padovan BT_ERR("Fragment is too long (len %d, expected %d)", 50710a708f8fSGustavo F. Padovan skb->len, conn->rx_len); 50720a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 50730a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 50740a708f8fSGustavo F. Padovan conn->rx_len = 0; 50750a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 50760a708f8fSGustavo F. Padovan goto drop; 50770a708f8fSGustavo F. Padovan } 50780a708f8fSGustavo F. Padovan 50790a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 50800a708f8fSGustavo F. Padovan skb->len); 50810a708f8fSGustavo F. Padovan conn->rx_len -= skb->len; 50820a708f8fSGustavo F. Padovan 50830a708f8fSGustavo F. Padovan if (!conn->rx_len) { 50840a708f8fSGustavo F. Padovan /* Complete frame received */ 50850a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, conn->rx_skb); 50860a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 50870a708f8fSGustavo F. Padovan } 50880a708f8fSGustavo F. Padovan } 50890a708f8fSGustavo F. Padovan 50900a708f8fSGustavo F. Padovan drop: 50910a708f8fSGustavo F. Padovan kfree_skb(skb); 50920a708f8fSGustavo F. Padovan return 0; 50930a708f8fSGustavo F. Padovan } 50940a708f8fSGustavo F. Padovan 50950a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p) 50960a708f8fSGustavo F. Padovan { 509723691d75SGustavo F. Padovan struct l2cap_chan *c; 50980a708f8fSGustavo F. Padovan 5099333055f2SGustavo F. Padovan read_lock(&chan_list_lock); 51000a708f8fSGustavo F. Padovan 510123691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 510223691d75SGustavo F. Padovan struct sock *sk = c->sk; 51030a708f8fSGustavo F. Padovan 5104903d343eSGustavo F. Padovan seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", 51050a708f8fSGustavo F. Padovan batostr(&bt_sk(sk)->src), 51060a708f8fSGustavo F. Padovan batostr(&bt_sk(sk)->dst), 510789bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm), 510823691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu, 510923691d75SGustavo F. Padovan c->sec_level, c->mode); 51100a708f8fSGustavo F. Padovan } 51110a708f8fSGustavo F. Padovan 5112333055f2SGustavo F. Padovan read_unlock(&chan_list_lock); 51130a708f8fSGustavo F. Padovan 51140a708f8fSGustavo F. Padovan return 0; 51150a708f8fSGustavo F. Padovan } 51160a708f8fSGustavo F. Padovan 51170a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file) 51180a708f8fSGustavo F. Padovan { 51190a708f8fSGustavo F. Padovan return single_open(file, l2cap_debugfs_show, inode->i_private); 51200a708f8fSGustavo F. Padovan } 51210a708f8fSGustavo F. Padovan 51220a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = { 51230a708f8fSGustavo F. Padovan .open = l2cap_debugfs_open, 51240a708f8fSGustavo F. Padovan .read = seq_read, 51250a708f8fSGustavo F. Padovan .llseek = seq_lseek, 51260a708f8fSGustavo F. Padovan .release = single_release, 51270a708f8fSGustavo F. Padovan }; 51280a708f8fSGustavo F. Padovan 51290a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs; 51300a708f8fSGustavo F. Padovan 513164274518SGustavo F. Padovan int __init l2cap_init(void) 51320a708f8fSGustavo F. Padovan { 51330a708f8fSGustavo F. Padovan int err; 51340a708f8fSGustavo F. Padovan 5135bb58f747SGustavo F. Padovan err = l2cap_init_sockets(); 51360a708f8fSGustavo F. Padovan if (err < 0) 51370a708f8fSGustavo F. Padovan return err; 51380a708f8fSGustavo F. Padovan 51390a708f8fSGustavo F. Padovan if (bt_debugfs) { 51400a708f8fSGustavo F. Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, 51410a708f8fSGustavo F. Padovan bt_debugfs, NULL, &l2cap_debugfs_fops); 51420a708f8fSGustavo F. Padovan if (!l2cap_debugfs) 51430a708f8fSGustavo F. Padovan BT_ERR("Failed to create L2CAP debug file"); 51440a708f8fSGustavo F. Padovan } 51450a708f8fSGustavo F. Padovan 51460a708f8fSGustavo F. Padovan return 0; 51470a708f8fSGustavo F. Padovan } 51480a708f8fSGustavo F. Padovan 514964274518SGustavo F. Padovan void l2cap_exit(void) 51500a708f8fSGustavo F. Padovan { 51510a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs); 5152bb58f747SGustavo F. Padovan l2cap_cleanup_sockets(); 51530a708f8fSGustavo F. Padovan } 51540a708f8fSGustavo F. Padovan 51550a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644); 51560a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); 5157