10a708f8fSGustavo F. Padovan /* 20a708f8fSGustavo F. Padovan BlueZ - Bluetooth protocol stack for Linux 30a708f8fSGustavo F. Padovan Copyright (C) 2000-2001 Qualcomm Incorporated 40a708f8fSGustavo F. Padovan Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org> 50a708f8fSGustavo F. Padovan Copyright (C) 2010 Google Inc. 6590051deSGustavo F. Padovan Copyright (C) 2011 ProFUSION Embedded Systems 7422e925bSMat Martineau Copyright (c) 2012 Code Aurora Forum. All rights reserved. 80a708f8fSGustavo F. Padovan 90a708f8fSGustavo F. Padovan Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> 100a708f8fSGustavo F. Padovan 110a708f8fSGustavo F. Padovan This program is free software; you can redistribute it and/or modify 120a708f8fSGustavo F. Padovan it under the terms of the GNU General Public License version 2 as 130a708f8fSGustavo F. Padovan published by the Free Software Foundation; 140a708f8fSGustavo F. Padovan 150a708f8fSGustavo F. Padovan THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 160a708f8fSGustavo F. Padovan OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 170a708f8fSGustavo F. Padovan FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 180a708f8fSGustavo F. Padovan IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 190a708f8fSGustavo F. Padovan CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 200a708f8fSGustavo F. Padovan WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 210a708f8fSGustavo F. Padovan ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 220a708f8fSGustavo F. Padovan OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 230a708f8fSGustavo F. Padovan 240a708f8fSGustavo F. Padovan ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 250a708f8fSGustavo F. Padovan COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 260a708f8fSGustavo F. Padovan SOFTWARE IS DISCLAIMED. 270a708f8fSGustavo F. Padovan */ 280a708f8fSGustavo F. Padovan 29bb58f747SGustavo F. Padovan /* Bluetooth L2CAP core. */ 300a708f8fSGustavo F. Padovan 310a708f8fSGustavo F. Padovan #include <linux/module.h> 320a708f8fSGustavo F. Padovan 330a708f8fSGustavo F. Padovan #include <linux/types.h> 340a708f8fSGustavo F. Padovan #include <linux/capability.h> 350a708f8fSGustavo F. Padovan #include <linux/errno.h> 360a708f8fSGustavo F. Padovan #include <linux/kernel.h> 370a708f8fSGustavo F. Padovan #include <linux/sched.h> 380a708f8fSGustavo F. Padovan #include <linux/slab.h> 390a708f8fSGustavo F. Padovan #include <linux/poll.h> 400a708f8fSGustavo F. Padovan #include <linux/fcntl.h> 410a708f8fSGustavo F. Padovan #include <linux/init.h> 420a708f8fSGustavo F. Padovan #include <linux/interrupt.h> 430a708f8fSGustavo F. Padovan #include <linux/socket.h> 440a708f8fSGustavo F. Padovan #include <linux/skbuff.h> 450a708f8fSGustavo F. Padovan #include <linux/list.h> 460a708f8fSGustavo F. Padovan #include <linux/device.h> 470a708f8fSGustavo F. Padovan #include <linux/debugfs.h> 480a708f8fSGustavo F. Padovan #include <linux/seq_file.h> 490a708f8fSGustavo F. Padovan #include <linux/uaccess.h> 500a708f8fSGustavo F. Padovan #include <linux/crc16.h> 510a708f8fSGustavo F. Padovan #include <net/sock.h> 520a708f8fSGustavo F. Padovan 530a708f8fSGustavo F. Padovan #include <asm/unaligned.h> 540a708f8fSGustavo F. Padovan 550a708f8fSGustavo F. Padovan #include <net/bluetooth/bluetooth.h> 560a708f8fSGustavo F. Padovan #include <net/bluetooth/hci_core.h> 570a708f8fSGustavo F. Padovan #include <net/bluetooth/l2cap.h> 58b501d6a1SAnderson Briglia #include <net/bluetooth/smp.h> 590a708f8fSGustavo F. Padovan 60b191e031SMat Martineau bool disable_ertm = 1; 610a708f8fSGustavo F. Padovan 620a708f8fSGustavo F. Padovan static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; 6350a147cdSMat Martineau static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, }; 640a708f8fSGustavo F. Padovan 65b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list); 66b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock); 670a708f8fSGustavo F. Padovan 680a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 690a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data); 704519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 714519de9aSGustavo F. Padovan void *data); 72710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); 734519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, 744519de9aSGustavo F. Padovan struct l2cap_chan *chan, int err); 750a708f8fSGustavo F. Padovan 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. 101ef191adeSMat Martineau * Returns locked channel. */ 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); 108ef191adeSMat Martineau if (c) 109ef191adeSMat Martineau l2cap_chan_lock(c); 1103df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 1113df91ea2SAndrei Emeltchenko 11248454079SGustavo F. Padovan return c; 1130a708f8fSGustavo F. Padovan } 1140a708f8fSGustavo F. Padovan 115baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident) 1160a708f8fSGustavo F. Padovan { 1173df91ea2SAndrei Emeltchenko struct l2cap_chan *c; 118baa7e1faSGustavo F. Padovan 1193df91ea2SAndrei Emeltchenko list_for_each_entry(c, &conn->chan_l, list) { 1203df91ea2SAndrei Emeltchenko if (c->ident == ident) 1213df91ea2SAndrei Emeltchenko return c; 1220a708f8fSGustavo F. Padovan } 1233df91ea2SAndrei Emeltchenko return NULL; 124baa7e1faSGustavo F. Padovan } 1250a708f8fSGustavo F. Padovan 12623691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src) 1279e4425ffSGustavo F. Padovan { 12823691d75SGustavo F. Padovan struct l2cap_chan *c; 1299e4425ffSGustavo F. Padovan 13023691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 13123691d75SGustavo F. Padovan if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src)) 13223691d75SGustavo F. Padovan return c; 1339e4425ffSGustavo F. Padovan } 134250938cbSSzymon Janc return NULL; 135250938cbSSzymon Janc } 1369e4425ffSGustavo F. Padovan 1379e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) 1389e4425ffSGustavo F. Padovan { 13973b2ec18SGustavo F. Padovan int err; 14073b2ec18SGustavo F. Padovan 141333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 1429e4425ffSGustavo F. Padovan 14323691d75SGustavo F. Padovan if (psm && __l2cap_global_chan_by_addr(psm, src)) { 14473b2ec18SGustavo F. Padovan err = -EADDRINUSE; 14573b2ec18SGustavo F. Padovan goto done; 1469e4425ffSGustavo F. Padovan } 1479e4425ffSGustavo F. Padovan 14873b2ec18SGustavo F. Padovan if (psm) { 1499e4425ffSGustavo F. Padovan chan->psm = psm; 1509e4425ffSGustavo F. Padovan chan->sport = psm; 15173b2ec18SGustavo F. Padovan err = 0; 15273b2ec18SGustavo F. Padovan } else { 15373b2ec18SGustavo F. Padovan u16 p; 1549e4425ffSGustavo F. Padovan 15573b2ec18SGustavo F. Padovan err = -EINVAL; 15673b2ec18SGustavo F. Padovan for (p = 0x1001; p < 0x1100; p += 2) 15723691d75SGustavo F. Padovan if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) { 15873b2ec18SGustavo F. Padovan chan->psm = cpu_to_le16(p); 15973b2ec18SGustavo F. Padovan chan->sport = cpu_to_le16(p); 16073b2ec18SGustavo F. Padovan err = 0; 16173b2ec18SGustavo F. Padovan break; 16273b2ec18SGustavo F. Padovan } 16373b2ec18SGustavo F. Padovan } 16473b2ec18SGustavo F. Padovan 16573b2ec18SGustavo F. Padovan done: 166333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 16773b2ec18SGustavo F. Padovan return err; 1689e4425ffSGustavo F. Padovan } 1699e4425ffSGustavo F. Padovan 1709e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) 1719e4425ffSGustavo F. Padovan { 172333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 1739e4425ffSGustavo F. Padovan 1749e4425ffSGustavo F. Padovan chan->scid = scid; 1759e4425ffSGustavo F. Padovan 176333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 1779e4425ffSGustavo F. Padovan 1789e4425ffSGustavo F. Padovan return 0; 1799e4425ffSGustavo F. Padovan } 1809e4425ffSGustavo F. Padovan 181baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn) 1820a708f8fSGustavo F. Padovan { 1830a708f8fSGustavo F. Padovan u16 cid = L2CAP_CID_DYN_START; 1840a708f8fSGustavo F. Padovan 1850a708f8fSGustavo F. Padovan for (; cid < L2CAP_CID_DYN_END; cid++) { 186baa7e1faSGustavo F. Padovan if (!__l2cap_get_chan_by_scid(conn, cid)) 1870a708f8fSGustavo F. Padovan return cid; 1880a708f8fSGustavo F. Padovan } 1890a708f8fSGustavo F. Padovan 1900a708f8fSGustavo F. Padovan return 0; 1910a708f8fSGustavo F. Padovan } 1920a708f8fSGustavo F. Padovan 1930e587be7SAndrei Emeltchenko static void __l2cap_state_change(struct l2cap_chan *chan, int state) 19489bc500eSGustavo F. Padovan { 19542d2d87cSAndrei Emeltchenko BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state), 196badaaa00SGustavo F. Padovan state_to_string(state)); 197badaaa00SGustavo F. Padovan 19889bc500eSGustavo F. Padovan chan->state = state; 19989bc500eSGustavo F. Padovan chan->ops->state_change(chan->data, state); 20089bc500eSGustavo F. Padovan } 20189bc500eSGustavo F. Padovan 2020e587be7SAndrei Emeltchenko static void l2cap_state_change(struct l2cap_chan *chan, int state) 2030e587be7SAndrei Emeltchenko { 2040e587be7SAndrei Emeltchenko struct sock *sk = chan->sk; 2050e587be7SAndrei Emeltchenko 2060e587be7SAndrei Emeltchenko lock_sock(sk); 2070e587be7SAndrei Emeltchenko __l2cap_state_change(chan, state); 2080e587be7SAndrei Emeltchenko release_sock(sk); 2090e587be7SAndrei Emeltchenko } 2100e587be7SAndrei Emeltchenko 2112e0052e4SAndrei Emeltchenko static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err) 2122e0052e4SAndrei Emeltchenko { 2132e0052e4SAndrei Emeltchenko struct sock *sk = chan->sk; 2142e0052e4SAndrei Emeltchenko 2152e0052e4SAndrei Emeltchenko sk->sk_err = err; 2162e0052e4SAndrei Emeltchenko } 2172e0052e4SAndrei Emeltchenko 2182e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err) 2192e0052e4SAndrei Emeltchenko { 2202e0052e4SAndrei Emeltchenko struct sock *sk = chan->sk; 2212e0052e4SAndrei Emeltchenko 2222e0052e4SAndrei Emeltchenko lock_sock(sk); 2232e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 2242e0052e4SAndrei Emeltchenko release_sock(sk); 2252e0052e4SAndrei Emeltchenko } 2262e0052e4SAndrei Emeltchenko 2273c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */ 2283c588192SMat Martineau 2293c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for 2303c588192SMat Martineau * SREJ requests that are received and for frames that are to be 2313c588192SMat Martineau * retransmitted. These seq_list functions implement a singly-linked 2323c588192SMat Martineau * list in an array, where membership in the list can also be checked 2333c588192SMat Martineau * in constant time. Items can also be added to the tail of the list 2343c588192SMat Martineau * and removed from the head in constant time, without further memory 2353c588192SMat Martineau * allocs or frees. 2363c588192SMat Martineau */ 2373c588192SMat Martineau 2383c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size) 2393c588192SMat Martineau { 2403c588192SMat Martineau size_t alloc_size, i; 2413c588192SMat Martineau 2423c588192SMat Martineau /* Allocated size is a power of 2 to map sequence numbers 2433c588192SMat Martineau * (which may be up to 14 bits) in to a smaller array that is 2443c588192SMat Martineau * sized for the negotiated ERTM transmit windows. 2453c588192SMat Martineau */ 2463c588192SMat Martineau alloc_size = roundup_pow_of_two(size); 2473c588192SMat Martineau 2483c588192SMat Martineau seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL); 2493c588192SMat Martineau if (!seq_list->list) 2503c588192SMat Martineau return -ENOMEM; 2513c588192SMat Martineau 2523c588192SMat Martineau seq_list->mask = alloc_size - 1; 2533c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 2543c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 2553c588192SMat Martineau for (i = 0; i < alloc_size; i++) 2563c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 2573c588192SMat Martineau 2583c588192SMat Martineau return 0; 2593c588192SMat Martineau } 2603c588192SMat Martineau 2613c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list) 2623c588192SMat Martineau { 2633c588192SMat Martineau kfree(seq_list->list); 2643c588192SMat Martineau } 2653c588192SMat Martineau 2663c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list, 2673c588192SMat Martineau u16 seq) 2683c588192SMat Martineau { 2693c588192SMat Martineau /* Constant-time check for list membership */ 2703c588192SMat Martineau return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR; 2713c588192SMat Martineau } 2723c588192SMat Martineau 2733c588192SMat Martineau static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq) 2743c588192SMat Martineau { 2753c588192SMat Martineau u16 mask = seq_list->mask; 2763c588192SMat Martineau 2773c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) { 2783c588192SMat Martineau /* In case someone tries to pop the head of an empty list */ 2793c588192SMat Martineau return L2CAP_SEQ_LIST_CLEAR; 2803c588192SMat Martineau } else if (seq_list->head == seq) { 2813c588192SMat Martineau /* Head can be removed in constant time */ 2823c588192SMat Martineau seq_list->head = seq_list->list[seq & mask]; 2833c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; 2843c588192SMat Martineau 2853c588192SMat Martineau if (seq_list->head == L2CAP_SEQ_LIST_TAIL) { 2863c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 2873c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 2883c588192SMat Martineau } 2893c588192SMat Martineau } else { 2903c588192SMat Martineau /* Walk the list to find the sequence number */ 2913c588192SMat Martineau u16 prev = seq_list->head; 2923c588192SMat Martineau while (seq_list->list[prev & mask] != seq) { 2933c588192SMat Martineau prev = seq_list->list[prev & mask]; 2943c588192SMat Martineau if (prev == L2CAP_SEQ_LIST_TAIL) 2953c588192SMat Martineau return L2CAP_SEQ_LIST_CLEAR; 2963c588192SMat Martineau } 2973c588192SMat Martineau 2983c588192SMat Martineau /* Unlink the number from the list and clear it */ 2993c588192SMat Martineau seq_list->list[prev & mask] = seq_list->list[seq & mask]; 3003c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; 3013c588192SMat Martineau if (seq_list->tail == seq) 3023c588192SMat Martineau seq_list->tail = prev; 3033c588192SMat Martineau } 3043c588192SMat Martineau return seq; 3053c588192SMat Martineau } 3063c588192SMat Martineau 3073c588192SMat Martineau static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list) 3083c588192SMat Martineau { 3093c588192SMat Martineau /* Remove the head in constant time */ 3103c588192SMat Martineau return l2cap_seq_list_remove(seq_list, seq_list->head); 3113c588192SMat Martineau } 3123c588192SMat Martineau 3133c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list) 3143c588192SMat Martineau { 3153c588192SMat Martineau u16 i; 316f522ae36SGustavo Padovan 317f522ae36SGustavo Padovan if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) 318f522ae36SGustavo Padovan return; 319f522ae36SGustavo Padovan 3203c588192SMat Martineau for (i = 0; i <= seq_list->mask; i++) 3213c588192SMat Martineau seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR; 3223c588192SMat Martineau 3233c588192SMat Martineau seq_list->head = L2CAP_SEQ_LIST_CLEAR; 3243c588192SMat Martineau seq_list->tail = L2CAP_SEQ_LIST_CLEAR; 3253c588192SMat Martineau } 3263c588192SMat Martineau 3273c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq) 3283c588192SMat Martineau { 3293c588192SMat Martineau u16 mask = seq_list->mask; 3303c588192SMat Martineau 3313c588192SMat Martineau /* All appends happen in constant time */ 3323c588192SMat Martineau 333f522ae36SGustavo Padovan if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR) 334f522ae36SGustavo Padovan return; 335f522ae36SGustavo Padovan 3363c588192SMat Martineau if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR) 3373c588192SMat Martineau seq_list->head = seq; 3383c588192SMat Martineau else 3393c588192SMat Martineau seq_list->list[seq_list->tail & mask] = seq; 3403c588192SMat Martineau 3413c588192SMat Martineau seq_list->tail = seq; 3423c588192SMat Martineau seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL; 3433c588192SMat Martineau } 3443c588192SMat Martineau 345721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work) 346ab07801dSGustavo F. Padovan { 347721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 348721c4181SGustavo F. Padovan chan_timer.work); 3493df91ea2SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 350ab07801dSGustavo F. Padovan int reason; 351ab07801dSGustavo F. Padovan 352e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); 353ab07801dSGustavo F. Padovan 3543df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 3556be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 356ab07801dSGustavo F. Padovan 35789bc500eSGustavo F. Padovan if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) 358ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 35989bc500eSGustavo F. Padovan else if (chan->state == BT_CONNECT && 360ab07801dSGustavo F. Padovan chan->sec_level != BT_SECURITY_SDP) 361ab07801dSGustavo F. Padovan reason = ECONNREFUSED; 362ab07801dSGustavo F. Padovan else 363ab07801dSGustavo F. Padovan reason = ETIMEDOUT; 364ab07801dSGustavo F. Padovan 3650f852724SGustavo F. Padovan l2cap_chan_close(chan, reason); 366ab07801dSGustavo F. Padovan 3676be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 368ab07801dSGustavo F. Padovan 369ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 3703df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 3713df91ea2SAndrei Emeltchenko 372371fd835SUlisses Furquim l2cap_chan_put(chan); 373ab07801dSGustavo F. Padovan } 374ab07801dSGustavo F. Padovan 375eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void) 3760a708f8fSGustavo F. Padovan { 37748454079SGustavo F. Padovan struct l2cap_chan *chan; 3780a708f8fSGustavo F. Padovan 37948454079SGustavo F. Padovan chan = kzalloc(sizeof(*chan), GFP_ATOMIC); 38048454079SGustavo F. Padovan if (!chan) 38148454079SGustavo F. Padovan return NULL; 3820a708f8fSGustavo F. Padovan 383c03b355eSAndrei Emeltchenko mutex_init(&chan->lock); 384c03b355eSAndrei Emeltchenko 385333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 38623691d75SGustavo F. Padovan list_add(&chan->global_l, &chan_list); 387333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 38823691d75SGustavo F. Padovan 389721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout); 390ab07801dSGustavo F. Padovan 39189bc500eSGustavo F. Padovan chan->state = BT_OPEN; 39289bc500eSGustavo F. Padovan 39371ba0e56SGustavo F. Padovan atomic_set(&chan->refcnt, 1); 39471ba0e56SGustavo F. Padovan 3952827011fSMat Martineau /* This flag is cleared in l2cap_chan_ready() */ 3962827011fSMat Martineau set_bit(CONF_NOT_COMPLETE, &chan->conf_state); 3972827011fSMat Martineau 398eef1d9b6SGustavo Padovan BT_DBG("chan %p", chan); 399abc545b8SSzymon Janc 40048454079SGustavo F. Padovan return chan; 4010a708f8fSGustavo F. Padovan } 4020a708f8fSGustavo F. Padovan 40323691d75SGustavo F. Padovan void l2cap_chan_destroy(struct l2cap_chan *chan) 4046ff5abbfSGustavo F. Padovan { 405333055f2SGustavo F. Padovan write_lock(&chan_list_lock); 40623691d75SGustavo F. Padovan list_del(&chan->global_l); 407333055f2SGustavo F. Padovan write_unlock(&chan_list_lock); 40823691d75SGustavo F. Padovan 409371fd835SUlisses Furquim l2cap_chan_put(chan); 4106ff5abbfSGustavo F. Padovan } 4116ff5abbfSGustavo F. Padovan 412bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan) 413bd4b1653SAndrei Emeltchenko { 414bd4b1653SAndrei Emeltchenko chan->fcs = L2CAP_FCS_CRC16; 415bd4b1653SAndrei Emeltchenko chan->max_tx = L2CAP_DEFAULT_MAX_TX; 416bd4b1653SAndrei Emeltchenko chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; 417bd4b1653SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 418bd4b1653SAndrei Emeltchenko chan->sec_level = BT_SECURITY_LOW; 419bd4b1653SAndrei Emeltchenko 420bd4b1653SAndrei Emeltchenko set_bit(FLAG_FORCE_ACTIVE, &chan->flags); 421bd4b1653SAndrei Emeltchenko } 422bd4b1653SAndrei Emeltchenko 42314a28491SAndrei Emeltchenko static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 4240a708f8fSGustavo F. Padovan { 4250a708f8fSGustavo F. Padovan BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, 426097db76cSAndrei Emeltchenko __le16_to_cpu(chan->psm), chan->dcid); 4270a708f8fSGustavo F. Padovan 4289f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 4290a708f8fSGustavo F. Padovan 4308c1d787bSGustavo F. Padovan chan->conn = conn; 4310a708f8fSGustavo F. Padovan 4325491120eSAndrei Emeltchenko switch (chan->chan_type) { 4335491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_ORIENTED: 434b62f328bSVille Tervo if (conn->hcon->type == LE_LINK) { 435b62f328bSVille Tervo /* LE connection */ 4360c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_LE_DEFAULT_MTU; 437fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_LE_DATA; 438fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_LE_DATA; 439b62f328bSVille Tervo } else { 4400a708f8fSGustavo F. Padovan /* Alloc CID for connection-oriented socket */ 441fe4128e0SGustavo F. Padovan chan->scid = l2cap_alloc_cid(conn); 4420c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 443b62f328bSVille Tervo } 4445491120eSAndrei Emeltchenko break; 4455491120eSAndrei Emeltchenko 4465491120eSAndrei Emeltchenko case L2CAP_CHAN_CONN_LESS: 4470a708f8fSGustavo F. Padovan /* Connectionless socket */ 448fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_CONN_LESS; 449fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_CONN_LESS; 4500c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 4515491120eSAndrei Emeltchenko break; 4525491120eSAndrei Emeltchenko 4535491120eSAndrei Emeltchenko default: 4540a708f8fSGustavo F. Padovan /* Raw socket can send/recv signalling messages only */ 455fe4128e0SGustavo F. Padovan chan->scid = L2CAP_CID_SIGNALING; 456fe4128e0SGustavo F. Padovan chan->dcid = L2CAP_CID_SIGNALING; 4570c1bc5c6SGustavo F. Padovan chan->omtu = L2CAP_DEFAULT_MTU; 4580a708f8fSGustavo F. Padovan } 4590a708f8fSGustavo F. Padovan 4608f7975b1SAndrei Emeltchenko chan->local_id = L2CAP_BESTEFFORT_ID; 4618f7975b1SAndrei Emeltchenko chan->local_stype = L2CAP_SERV_BESTEFFORT; 4628f7975b1SAndrei Emeltchenko chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE; 4638f7975b1SAndrei Emeltchenko chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME; 4648f7975b1SAndrei Emeltchenko chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT; 4658f7975b1SAndrei Emeltchenko chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO; 4668f7975b1SAndrei Emeltchenko 467371fd835SUlisses Furquim l2cap_chan_hold(chan); 468baa7e1faSGustavo F. Padovan 4693df91ea2SAndrei Emeltchenko list_add(&chan->list, &conn->chan_l); 470643162a8SAndrei Emeltchenko } 471643162a8SAndrei Emeltchenko 47214a28491SAndrei Emeltchenko static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 473643162a8SAndrei Emeltchenko { 474643162a8SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 475643162a8SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 4763df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 4770a708f8fSGustavo F. Padovan } 4780a708f8fSGustavo F. Padovan 4794519de9aSGustavo F. Padovan static void l2cap_chan_del(struct l2cap_chan *chan, int err) 4800a708f8fSGustavo F. Padovan { 48148454079SGustavo F. Padovan struct sock *sk = chan->sk; 4828c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 4830a708f8fSGustavo F. Padovan struct sock *parent = bt_sk(sk)->parent; 4840a708f8fSGustavo F. Padovan 485c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 4860a708f8fSGustavo F. Padovan 48749208c9cSGustavo F. Padovan BT_DBG("chan %p, conn %p, err %d", chan, conn, err); 4880a708f8fSGustavo F. Padovan 4890a708f8fSGustavo F. Padovan if (conn) { 490baa7e1faSGustavo F. Padovan /* Delete from channel list */ 4913df91ea2SAndrei Emeltchenko list_del(&chan->list); 4923d57dc68SGustavo F. Padovan 493371fd835SUlisses Furquim l2cap_chan_put(chan); 494baa7e1faSGustavo F. Padovan 4958c1d787bSGustavo F. Padovan chan->conn = NULL; 4960a708f8fSGustavo F. Padovan hci_conn_put(conn->hcon); 4970a708f8fSGustavo F. Padovan } 4980a708f8fSGustavo F. Padovan 4996be36555SAndrei Emeltchenko lock_sock(sk); 5006be36555SAndrei Emeltchenko 5010e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CLOSED); 5020a708f8fSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 5030a708f8fSGustavo F. Padovan 5040a708f8fSGustavo F. Padovan if (err) 5052e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 5060a708f8fSGustavo F. Padovan 5070a708f8fSGustavo F. Padovan if (parent) { 5080a708f8fSGustavo F. Padovan bt_accept_unlink(sk); 5090a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 5100a708f8fSGustavo F. Padovan } else 5110a708f8fSGustavo F. Padovan sk->sk_state_change(sk); 5120a708f8fSGustavo F. Padovan 5136be36555SAndrei Emeltchenko release_sock(sk); 5146be36555SAndrei Emeltchenko 5152827011fSMat Martineau if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) 5166ff5abbfSGustavo F. Padovan return; 5172ead70b8SGustavo F. Padovan 51858d35f87SGustavo F. Padovan skb_queue_purge(&chan->tx_q); 5190a708f8fSGustavo F. Padovan 5200c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_ERTM) { 5210a708f8fSGustavo F. Padovan struct srej_list *l, *tmp; 5220a708f8fSGustavo F. Padovan 5231a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 5241a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 5251a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 5260a708f8fSGustavo F. Padovan 527f1c6775bSGustavo F. Padovan skb_queue_purge(&chan->srej_q); 5280a708f8fSGustavo F. Padovan 5293c588192SMat Martineau l2cap_seq_list_free(&chan->srej_list); 5303c588192SMat Martineau l2cap_seq_list_free(&chan->retrans_list); 53139d5a3eeSGustavo F. Padovan list_for_each_entry_safe(l, tmp, &chan->srej_l, list) { 5320a708f8fSGustavo F. Padovan list_del(&l->list); 5330a708f8fSGustavo F. Padovan kfree(l); 5340a708f8fSGustavo F. Padovan } 5350a708f8fSGustavo F. Padovan } 5360a708f8fSGustavo F. Padovan } 5370a708f8fSGustavo F. Padovan 5384519de9aSGustavo F. Padovan static void l2cap_chan_cleanup_listen(struct sock *parent) 5394519de9aSGustavo F. Padovan { 5404519de9aSGustavo F. Padovan struct sock *sk; 5414519de9aSGustavo F. Padovan 5424519de9aSGustavo F. Padovan BT_DBG("parent %p", parent); 5434519de9aSGustavo F. Padovan 5444519de9aSGustavo F. Padovan /* Close not yet accepted channels */ 5450f852724SGustavo F. Padovan while ((sk = bt_accept_dequeue(parent, NULL))) { 546ba3bd0eeSGustavo F. Padovan struct l2cap_chan *chan = l2cap_pi(sk)->chan; 5473df91ea2SAndrei Emeltchenko 5486be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 549c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 550ba3bd0eeSGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 5516be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 5523df91ea2SAndrei Emeltchenko 553ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 5540f852724SGustavo F. Padovan } 5554519de9aSGustavo F. Padovan } 5564519de9aSGustavo F. Padovan 5570f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason) 5584519de9aSGustavo F. Padovan { 5594519de9aSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 5604519de9aSGustavo F. Padovan struct sock *sk = chan->sk; 5614519de9aSGustavo F. Padovan 562e05dcc32SAndrei Emeltchenko BT_DBG("chan %p state %s sk %p", chan, 563e05dcc32SAndrei Emeltchenko state_to_string(chan->state), sk); 5644519de9aSGustavo F. Padovan 56589bc500eSGustavo F. Padovan switch (chan->state) { 5664519de9aSGustavo F. Padovan case BT_LISTEN: 5676be36555SAndrei Emeltchenko lock_sock(sk); 5684519de9aSGustavo F. Padovan l2cap_chan_cleanup_listen(sk); 56989bc500eSGustavo F. Padovan 5700e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CLOSED); 57189bc500eSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 5726be36555SAndrei Emeltchenko release_sock(sk); 5734519de9aSGustavo F. Padovan break; 5744519de9aSGustavo F. Padovan 5754519de9aSGustavo F. Padovan case BT_CONNECTED: 5764519de9aSGustavo F. Padovan case BT_CONFIG: 577715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && 5784519de9aSGustavo F. Padovan conn->hcon->type == ACL_LINK) { 579c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 5804519de9aSGustavo F. Padovan l2cap_send_disconn_req(conn, chan, reason); 5814519de9aSGustavo F. Padovan } else 5824519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 5834519de9aSGustavo F. Padovan break; 5844519de9aSGustavo F. Padovan 5854519de9aSGustavo F. Padovan case BT_CONNECT2: 586715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && 5874519de9aSGustavo F. Padovan conn->hcon->type == ACL_LINK) { 5884519de9aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 5894519de9aSGustavo F. Padovan __u16 result; 5904519de9aSGustavo F. Padovan 591c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) 5924519de9aSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 5934519de9aSGustavo F. Padovan else 5944519de9aSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 59589bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_DISCONN); 5964519de9aSGustavo F. Padovan 5974519de9aSGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 5984519de9aSGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 5994519de9aSGustavo F. Padovan rsp.result = cpu_to_le16(result); 6004519de9aSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 6014519de9aSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 6024519de9aSGustavo F. Padovan sizeof(rsp), &rsp); 6034519de9aSGustavo F. Padovan } 6044519de9aSGustavo F. Padovan 6054519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 6064519de9aSGustavo F. Padovan break; 6074519de9aSGustavo F. Padovan 6084519de9aSGustavo F. Padovan case BT_CONNECT: 6094519de9aSGustavo F. Padovan case BT_DISCONN: 6104519de9aSGustavo F. Padovan l2cap_chan_del(chan, reason); 6114519de9aSGustavo F. Padovan break; 6124519de9aSGustavo F. Padovan 6134519de9aSGustavo F. Padovan default: 6146be36555SAndrei Emeltchenko lock_sock(sk); 6154519de9aSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 6166be36555SAndrei Emeltchenko release_sock(sk); 6174519de9aSGustavo F. Padovan break; 6184519de9aSGustavo F. Padovan } 6194519de9aSGustavo F. Padovan } 6204519de9aSGustavo F. Padovan 6214343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) 6220a708f8fSGustavo F. Padovan { 623715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_RAW) { 6244343478fSGustavo F. Padovan switch (chan->sec_level) { 6250a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 6260a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING_MITM; 6270a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 6280a708f8fSGustavo F. Padovan return HCI_AT_DEDICATED_BONDING; 6290a708f8fSGustavo F. Padovan default: 6300a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 6310a708f8fSGustavo F. Padovan } 632fe4128e0SGustavo F. Padovan } else if (chan->psm == cpu_to_le16(0x0001)) { 6334343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_LOW) 6344343478fSGustavo F. Padovan chan->sec_level = BT_SECURITY_SDP; 6350a708f8fSGustavo F. Padovan 6364343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_HIGH) 6370a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING_MITM; 6380a708f8fSGustavo F. Padovan else 6390a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 6400a708f8fSGustavo F. Padovan } else { 6414343478fSGustavo F. Padovan switch (chan->sec_level) { 6420a708f8fSGustavo F. Padovan case BT_SECURITY_HIGH: 6430a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING_MITM; 6440a708f8fSGustavo F. Padovan case BT_SECURITY_MEDIUM: 6450a708f8fSGustavo F. Padovan return HCI_AT_GENERAL_BONDING; 6460a708f8fSGustavo F. Padovan default: 6470a708f8fSGustavo F. Padovan return HCI_AT_NO_BONDING; 6480a708f8fSGustavo F. Padovan } 6490a708f8fSGustavo F. Padovan } 6500a708f8fSGustavo F. Padovan } 6510a708f8fSGustavo F. Padovan 6520a708f8fSGustavo F. Padovan /* Service level security */ 653d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan) 6540a708f8fSGustavo F. Padovan { 6558c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 6560a708f8fSGustavo F. Padovan __u8 auth_type; 6570a708f8fSGustavo F. Padovan 6584343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 6590a708f8fSGustavo F. Padovan 6604343478fSGustavo F. Padovan return hci_conn_security(conn->hcon, chan->sec_level, auth_type); 6610a708f8fSGustavo F. Padovan } 6620a708f8fSGustavo F. Padovan 663b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn) 6640a708f8fSGustavo F. Padovan { 6650a708f8fSGustavo F. Padovan u8 id; 6660a708f8fSGustavo F. Padovan 6670a708f8fSGustavo F. Padovan /* Get next available identificator. 6680a708f8fSGustavo F. Padovan * 1 - 128 are used by kernel. 6690a708f8fSGustavo F. Padovan * 129 - 199 are reserved. 6700a708f8fSGustavo F. Padovan * 200 - 254 are used by utilities like l2ping, etc. 6710a708f8fSGustavo F. Padovan */ 6720a708f8fSGustavo F. Padovan 673333055f2SGustavo F. Padovan spin_lock(&conn->lock); 6740a708f8fSGustavo F. Padovan 6750a708f8fSGustavo F. Padovan if (++conn->tx_ident > 128) 6760a708f8fSGustavo F. Padovan conn->tx_ident = 1; 6770a708f8fSGustavo F. Padovan 6780a708f8fSGustavo F. Padovan id = conn->tx_ident; 6790a708f8fSGustavo F. Padovan 680333055f2SGustavo F. Padovan spin_unlock(&conn->lock); 6810a708f8fSGustavo F. Padovan 6820a708f8fSGustavo F. Padovan return id; 6830a708f8fSGustavo F. Padovan } 6840a708f8fSGustavo F. Padovan 6854519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) 6860a708f8fSGustavo F. Padovan { 6870a708f8fSGustavo F. Padovan struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); 6880a708f8fSGustavo F. Padovan u8 flags; 6890a708f8fSGustavo F. Padovan 6900a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x", code); 6910a708f8fSGustavo F. Padovan 6920a708f8fSGustavo F. Padovan if (!skb) 6930a708f8fSGustavo F. Padovan return; 6940a708f8fSGustavo F. Padovan 6950a708f8fSGustavo F. Padovan if (lmp_no_flush_capable(conn->hcon->hdev)) 6960a708f8fSGustavo F. Padovan flags = ACL_START_NO_FLUSH; 6970a708f8fSGustavo F. Padovan else 6980a708f8fSGustavo F. Padovan flags = ACL_START; 6990a708f8fSGustavo F. Padovan 70014b12d0bSJaikumar Ganesh bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON; 7015e59b791SLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 70214b12d0bSJaikumar Ganesh 70373d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, flags); 7040a708f8fSGustavo F. Padovan } 7050a708f8fSGustavo F. Padovan 70673d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) 70773d80debSLuiz Augusto von Dentz { 70873d80debSLuiz Augusto von Dentz struct hci_conn *hcon = chan->conn->hcon; 70973d80debSLuiz Augusto von Dentz u16 flags; 71073d80debSLuiz Augusto von Dentz 71173d80debSLuiz Augusto von Dentz BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, 71273d80debSLuiz Augusto von Dentz skb->priority); 71373d80debSLuiz Augusto von Dentz 71473d80debSLuiz Augusto von Dentz if (!test_bit(FLAG_FLUSHABLE, &chan->flags) && 71573d80debSLuiz Augusto von Dentz lmp_no_flush_capable(hcon->hdev)) 71673d80debSLuiz Augusto von Dentz flags = ACL_START_NO_FLUSH; 71773d80debSLuiz Augusto von Dentz else 71873d80debSLuiz Augusto von Dentz flags = ACL_START; 71973d80debSLuiz Augusto von Dentz 72073d80debSLuiz Augusto von Dentz bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); 72173d80debSLuiz Augusto von Dentz hci_send_acl(chan->conn->hchan, skb, flags); 7220a708f8fSGustavo F. Padovan } 7230a708f8fSGustavo F. Padovan 724b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control) 725b5c6aaedSMat Martineau { 726b5c6aaedSMat Martineau control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT; 727b5c6aaedSMat Martineau control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT; 728b5c6aaedSMat Martineau 729b5c6aaedSMat Martineau if (enh & L2CAP_CTRL_FRAME_TYPE) { 730b5c6aaedSMat Martineau /* S-Frame */ 731b5c6aaedSMat Martineau control->sframe = 1; 732b5c6aaedSMat Martineau control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT; 733b5c6aaedSMat Martineau control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT; 734b5c6aaedSMat Martineau 735b5c6aaedSMat Martineau control->sar = 0; 736b5c6aaedSMat Martineau control->txseq = 0; 737b5c6aaedSMat Martineau } else { 738b5c6aaedSMat Martineau /* I-Frame */ 739b5c6aaedSMat Martineau control->sframe = 0; 740b5c6aaedSMat Martineau control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT; 741b5c6aaedSMat Martineau control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT; 742b5c6aaedSMat Martineau 743b5c6aaedSMat Martineau control->poll = 0; 744b5c6aaedSMat Martineau control->super = 0; 745b5c6aaedSMat Martineau } 746b5c6aaedSMat Martineau } 747b5c6aaedSMat Martineau 748b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control) 749b5c6aaedSMat Martineau { 750b5c6aaedSMat Martineau control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT; 751b5c6aaedSMat Martineau control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT; 752b5c6aaedSMat Martineau 753b5c6aaedSMat Martineau if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) { 754b5c6aaedSMat Martineau /* S-Frame */ 755b5c6aaedSMat Martineau control->sframe = 1; 756b5c6aaedSMat Martineau control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT; 757b5c6aaedSMat Martineau control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT; 758b5c6aaedSMat Martineau 759b5c6aaedSMat Martineau control->sar = 0; 760b5c6aaedSMat Martineau control->txseq = 0; 761b5c6aaedSMat Martineau } else { 762b5c6aaedSMat Martineau /* I-Frame */ 763b5c6aaedSMat Martineau control->sframe = 0; 764b5c6aaedSMat Martineau control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT; 765b5c6aaedSMat Martineau control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT; 766b5c6aaedSMat Martineau 767b5c6aaedSMat Martineau control->poll = 0; 768b5c6aaedSMat Martineau control->super = 0; 769b5c6aaedSMat Martineau } 770b5c6aaedSMat Martineau } 771b5c6aaedSMat Martineau 772b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan, 773b5c6aaedSMat Martineau struct sk_buff *skb) 774b5c6aaedSMat Martineau { 775b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 776b5c6aaedSMat Martineau __unpack_extended_control(get_unaligned_le32(skb->data), 777b5c6aaedSMat Martineau &bt_cb(skb)->control); 778b5c6aaedSMat Martineau } else { 779b5c6aaedSMat Martineau __unpack_enhanced_control(get_unaligned_le16(skb->data), 780b5c6aaedSMat Martineau &bt_cb(skb)->control); 781b5c6aaedSMat Martineau } 782b5c6aaedSMat Martineau } 783b5c6aaedSMat Martineau 784b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control) 785b5c6aaedSMat Martineau { 786b5c6aaedSMat Martineau u32 packed; 787b5c6aaedSMat Martineau 788b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT; 789b5c6aaedSMat Martineau packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT; 790b5c6aaedSMat Martineau 791b5c6aaedSMat Martineau if (control->sframe) { 792b5c6aaedSMat Martineau packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT; 793b5c6aaedSMat Martineau packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT; 794b5c6aaedSMat Martineau packed |= L2CAP_EXT_CTRL_FRAME_TYPE; 795b5c6aaedSMat Martineau } else { 796b5c6aaedSMat Martineau packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT; 797b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT; 798b5c6aaedSMat Martineau } 799b5c6aaedSMat Martineau 800b5c6aaedSMat Martineau return packed; 801b5c6aaedSMat Martineau } 802b5c6aaedSMat Martineau 803b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control) 804b5c6aaedSMat Martineau { 805b5c6aaedSMat Martineau u16 packed; 806b5c6aaedSMat Martineau 807b5c6aaedSMat Martineau packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT; 808b5c6aaedSMat Martineau packed |= control->final << L2CAP_CTRL_FINAL_SHIFT; 809b5c6aaedSMat Martineau 810b5c6aaedSMat Martineau if (control->sframe) { 811b5c6aaedSMat Martineau packed |= control->poll << L2CAP_CTRL_POLL_SHIFT; 812b5c6aaedSMat Martineau packed |= control->super << L2CAP_CTRL_SUPER_SHIFT; 813b5c6aaedSMat Martineau packed |= L2CAP_CTRL_FRAME_TYPE; 814b5c6aaedSMat Martineau } else { 815b5c6aaedSMat Martineau packed |= control->sar << L2CAP_CTRL_SAR_SHIFT; 816b5c6aaedSMat Martineau packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT; 817b5c6aaedSMat Martineau } 818b5c6aaedSMat Martineau 819b5c6aaedSMat Martineau return packed; 820b5c6aaedSMat Martineau } 821b5c6aaedSMat Martineau 822b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan, 823b5c6aaedSMat Martineau struct l2cap_ctrl *control, 824b5c6aaedSMat Martineau struct sk_buff *skb) 825b5c6aaedSMat Martineau { 826b5c6aaedSMat Martineau if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { 827b5c6aaedSMat Martineau put_unaligned_le32(__pack_extended_control(control), 828b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 829b5c6aaedSMat Martineau } else { 830b5c6aaedSMat Martineau put_unaligned_le16(__pack_enhanced_control(control), 831b5c6aaedSMat Martineau skb->data + L2CAP_HDR_SIZE); 832b5c6aaedSMat Martineau } 833b5c6aaedSMat Martineau } 834b5c6aaedSMat Martineau 83588843ab0SAndrei Emeltchenko static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control) 8360a708f8fSGustavo F. Padovan { 8370a708f8fSGustavo F. Padovan struct sk_buff *skb; 8380a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 8398c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 840e4ca6d98SAndrei Emeltchenko int count, hlen; 8410a708f8fSGustavo F. Padovan 84289bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 8430a708f8fSGustavo F. Padovan return; 8440a708f8fSGustavo F. Padovan 845e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 846e4ca6d98SAndrei Emeltchenko hlen = L2CAP_EXT_HDR_SIZE; 847e4ca6d98SAndrei Emeltchenko else 848e4ca6d98SAndrei Emeltchenko hlen = L2CAP_ENH_HDR_SIZE; 8490a708f8fSGustavo F. Padovan 8500a708f8fSGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 85103a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 8520a708f8fSGustavo F. Padovan 85388843ab0SAndrei Emeltchenko BT_DBG("chan %p, control 0x%8.8x", chan, control); 8540a708f8fSGustavo F. Padovan 8550a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, hlen); 856793c2f1cSAndrei Emeltchenko 857793c2f1cSAndrei Emeltchenko control |= __set_sframe(chan); 8580a708f8fSGustavo F. Padovan 859e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 86003f6715dSAndrei Emeltchenko control |= __set_ctrl_final(chan); 8610a708f8fSGustavo F. Padovan 862e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state)) 863e3781735SAndrei Emeltchenko control |= __set_ctrl_poll(chan); 8640a708f8fSGustavo F. Padovan 8650a708f8fSGustavo F. Padovan skb = bt_skb_alloc(count, GFP_ATOMIC); 8660a708f8fSGustavo F. Padovan if (!skb) 8670a708f8fSGustavo F. Padovan return; 8680a708f8fSGustavo F. Padovan 8690a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 8700a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); 871fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 87288843ab0SAndrei Emeltchenko 87388843ab0SAndrei Emeltchenko __put_control(chan, control, skb_put(skb, __ctrl_size(chan))); 8740a708f8fSGustavo F. Padovan 87547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 87603a51213SAndrei Emeltchenko u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE); 87703a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 8780a708f8fSGustavo F. Padovan } 8790a708f8fSGustavo F. Padovan 88073d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 88173d80debSLuiz Augusto von Dentz l2cap_do_send(chan, skb); 8820a708f8fSGustavo F. Padovan } 8830a708f8fSGustavo F. Padovan 88488843ab0SAndrei Emeltchenko static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control) 8850a708f8fSGustavo F. Padovan { 886e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 887ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); 888e2ab4353SGustavo F. Padovan set_bit(CONN_RNR_SENT, &chan->conn_state); 8890a708f8fSGustavo F. Padovan } else 890ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 8910a708f8fSGustavo F. Padovan 8920b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 8930a708f8fSGustavo F. Padovan 894525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 8950a708f8fSGustavo F. Padovan } 8960a708f8fSGustavo F. Padovan 897b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) 8980a708f8fSGustavo F. Padovan { 899c1360a1cSGustavo F. Padovan return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); 9000a708f8fSGustavo F. Padovan } 9010a708f8fSGustavo F. Padovan 9029b27f350SAndrei Emeltchenko static void l2cap_send_conn_req(struct l2cap_chan *chan) 9039b27f350SAndrei Emeltchenko { 9049b27f350SAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 9059b27f350SAndrei Emeltchenko struct l2cap_conn_req req; 9069b27f350SAndrei Emeltchenko 9079b27f350SAndrei Emeltchenko req.scid = cpu_to_le16(chan->scid); 9089b27f350SAndrei Emeltchenko req.psm = chan->psm; 9099b27f350SAndrei Emeltchenko 9109b27f350SAndrei Emeltchenko chan->ident = l2cap_get_ident(conn); 9119b27f350SAndrei Emeltchenko 9129b27f350SAndrei Emeltchenko set_bit(CONF_CONNECT_PEND, &chan->conf_state); 9139b27f350SAndrei Emeltchenko 9149b27f350SAndrei Emeltchenko l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); 9159b27f350SAndrei Emeltchenko } 9169b27f350SAndrei Emeltchenko 9179f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan) 9189f0caeb1SVinicius Costa Gomes { 9199f0caeb1SVinicius Costa Gomes struct sock *sk = chan->sk; 9209f0caeb1SVinicius Costa Gomes struct sock *parent; 9219f0caeb1SVinicius Costa Gomes 9229f0caeb1SVinicius Costa Gomes lock_sock(sk); 9239f0caeb1SVinicius Costa Gomes 9249f0caeb1SVinicius Costa Gomes parent = bt_sk(sk)->parent; 9259f0caeb1SVinicius Costa Gomes 9269f0caeb1SVinicius Costa Gomes BT_DBG("sk %p, parent %p", sk, parent); 9279f0caeb1SVinicius Costa Gomes 9282827011fSMat Martineau /* This clears all conf flags, including CONF_NOT_COMPLETE */ 9299f0caeb1SVinicius Costa Gomes chan->conf_state = 0; 9309f0caeb1SVinicius Costa Gomes __clear_chan_timer(chan); 9319f0caeb1SVinicius Costa Gomes 9329f0caeb1SVinicius Costa Gomes __l2cap_state_change(chan, BT_CONNECTED); 9339f0caeb1SVinicius Costa Gomes sk->sk_state_change(sk); 9349f0caeb1SVinicius Costa Gomes 9359f0caeb1SVinicius Costa Gomes if (parent) 9369f0caeb1SVinicius Costa Gomes parent->sk_data_ready(parent, 0); 9379f0caeb1SVinicius Costa Gomes 9389f0caeb1SVinicius Costa Gomes release_sock(sk); 9399f0caeb1SVinicius Costa Gomes } 9409f0caeb1SVinicius Costa Gomes 941fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan) 9420a708f8fSGustavo F. Padovan { 9438c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 9440a708f8fSGustavo F. Padovan 9459f0caeb1SVinicius Costa Gomes if (conn->hcon->type == LE_LINK) { 9469f0caeb1SVinicius Costa Gomes l2cap_chan_ready(chan); 9479f0caeb1SVinicius Costa Gomes return; 9489f0caeb1SVinicius Costa Gomes } 9499f0caeb1SVinicius Costa Gomes 9500a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { 9510a708f8fSGustavo F. Padovan if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) 9520a708f8fSGustavo F. Padovan return; 9530a708f8fSGustavo F. Padovan 954d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan) && 9559b27f350SAndrei Emeltchenko __l2cap_no_conn_pending(chan)) 9569b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 9570a708f8fSGustavo F. Padovan } else { 9580a708f8fSGustavo F. Padovan struct l2cap_info_req req; 9590a708f8fSGustavo F. Padovan req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 9600a708f8fSGustavo F. Padovan 9610a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 9620a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 9630a708f8fSGustavo F. Padovan 964ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 9650a708f8fSGustavo F. Padovan 9660a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 9670a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 9680a708f8fSGustavo F. Padovan } 9690a708f8fSGustavo F. Padovan } 9700a708f8fSGustavo F. Padovan 9710a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) 9720a708f8fSGustavo F. Padovan { 9730a708f8fSGustavo F. Padovan u32 local_feat_mask = l2cap_feat_mask; 9740a708f8fSGustavo F. Padovan if (!disable_ertm) 9750a708f8fSGustavo F. Padovan local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING; 9760a708f8fSGustavo F. Padovan 9770a708f8fSGustavo F. Padovan switch (mode) { 9780a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 9790a708f8fSGustavo F. Padovan return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask; 9800a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 9810a708f8fSGustavo F. Padovan return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask; 9820a708f8fSGustavo F. Padovan default: 9830a708f8fSGustavo F. Padovan return 0x00; 9840a708f8fSGustavo F. Padovan } 9850a708f8fSGustavo F. Padovan } 9860a708f8fSGustavo F. Padovan 9874519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err) 9880a708f8fSGustavo F. Padovan { 9896be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 9900a708f8fSGustavo F. Padovan struct l2cap_disconn_req req; 9910a708f8fSGustavo F. Padovan 9920a708f8fSGustavo F. Padovan if (!conn) 9930a708f8fSGustavo F. Padovan return; 9940a708f8fSGustavo F. Padovan 9950c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_ERTM) { 9961a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 9971a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 9981a09bcb9SGustavo F. Padovan __clear_ack_timer(chan); 9990a708f8fSGustavo F. Padovan } 10000a708f8fSGustavo F. Padovan 1001fe4128e0SGustavo F. Padovan req.dcid = cpu_to_le16(chan->dcid); 1002fe4128e0SGustavo F. Padovan req.scid = cpu_to_le16(chan->scid); 10030a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 10040a708f8fSGustavo F. Padovan L2CAP_DISCONN_REQ, sizeof(req), &req); 10050a708f8fSGustavo F. Padovan 10066be36555SAndrei Emeltchenko lock_sock(sk); 10070e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_DISCONN); 10082e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 10096be36555SAndrei Emeltchenko release_sock(sk); 10100a708f8fSGustavo F. Padovan } 10110a708f8fSGustavo F. Padovan 10120a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */ 10130a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn) 10140a708f8fSGustavo F. Padovan { 10153df91ea2SAndrei Emeltchenko struct l2cap_chan *chan, *tmp; 10160a708f8fSGustavo F. Padovan 10170a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 10180a708f8fSGustavo F. Padovan 10193df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 10200a708f8fSGustavo F. Padovan 10213df91ea2SAndrei Emeltchenko list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 102248454079SGustavo F. Padovan struct sock *sk = chan->sk; 1023baa7e1faSGustavo F. Padovan 10246be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 10250a708f8fSGustavo F. Padovan 1026715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 10276be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10280a708f8fSGustavo F. Padovan continue; 10290a708f8fSGustavo F. Padovan } 10300a708f8fSGustavo F. Padovan 103189bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 1032d45fc423SGustavo F. Padovan if (!l2cap_chan_check_security(chan) || 1033b4450035SGustavo F. Padovan !__l2cap_no_conn_pending(chan)) { 10346be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10350a708f8fSGustavo F. Padovan continue; 10360a708f8fSGustavo F. Padovan } 10370a708f8fSGustavo F. Padovan 1038c1360a1cSGustavo F. Padovan if (!l2cap_mode_supported(chan->mode, conn->feat_mask) 1039c1360a1cSGustavo F. Padovan && test_bit(CONF_STATE2_DEVICE, 1040c1360a1cSGustavo F. Padovan &chan->conf_state)) { 10410f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNRESET); 10426be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10430a708f8fSGustavo F. Padovan continue; 10440a708f8fSGustavo F. Padovan } 10450a708f8fSGustavo F. Padovan 10469b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 10470a708f8fSGustavo F. Padovan 104889bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 10490a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 10500a708f8fSGustavo F. Padovan char buf[128]; 1051fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 1052fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 10530a708f8fSGustavo F. Padovan 1054d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 10556be36555SAndrei Emeltchenko lock_sock(sk); 1056c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, 1057c5daa683SGustavo Padovan &bt_sk(sk)->flags)) { 10580a708f8fSGustavo F. Padovan struct sock *parent = bt_sk(sk)->parent; 10590a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_PEND); 10600a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND); 106105e9a2f6SIlia Kolomisnky if (parent) 10620a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 10630a708f8fSGustavo F. Padovan 10640a708f8fSGustavo F. Padovan } else { 10650e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 10660a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 10670a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 10680a708f8fSGustavo F. Padovan } 10696be36555SAndrei Emeltchenko release_sock(sk); 10700a708f8fSGustavo F. Padovan } else { 10710a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_PEND); 10720a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND); 10730a708f8fSGustavo F. Padovan } 10740a708f8fSGustavo F. Padovan 1075fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 1076fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 10770a708f8fSGustavo F. Padovan 1078c1360a1cSGustavo F. Padovan if (test_bit(CONF_REQ_SENT, &chan->conf_state) || 10790a708f8fSGustavo F. Padovan rsp.result != L2CAP_CR_SUCCESS) { 10806be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10810a708f8fSGustavo F. Padovan continue; 10820a708f8fSGustavo F. Padovan } 10830a708f8fSGustavo F. Padovan 1084c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 10850a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 108673ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 108773ffa904SGustavo F. Padovan chan->num_conf_req++; 10880a708f8fSGustavo F. Padovan } 10890a708f8fSGustavo F. Padovan 10906be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 10910a708f8fSGustavo F. Padovan } 10920a708f8fSGustavo F. Padovan 10933df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 10940a708f8fSGustavo F. Padovan } 10950a708f8fSGustavo F. Padovan 1096c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr. 1097b62f328bSVille Tervo * Returns closest match, locked. 1098b62f328bSVille Tervo */ 1099d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, 1100c2287681SIdo Yariv bdaddr_t *src, 1101c2287681SIdo Yariv bdaddr_t *dst) 1102b62f328bSVille Tervo { 110323691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 1104b62f328bSVille Tervo 110523691d75SGustavo F. Padovan read_lock(&chan_list_lock); 1106b62f328bSVille Tervo 110723691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 110823691d75SGustavo F. Padovan struct sock *sk = c->sk; 1109fe4128e0SGustavo F. Padovan 111089bc500eSGustavo F. Padovan if (state && c->state != state) 1111b62f328bSVille Tervo continue; 1112b62f328bSVille Tervo 111323691d75SGustavo F. Padovan if (c->scid == cid) { 1114c2287681SIdo Yariv int src_match, dst_match; 1115c2287681SIdo Yariv int src_any, dst_any; 1116c2287681SIdo Yariv 1117b62f328bSVille Tervo /* Exact match. */ 1118c2287681SIdo Yariv src_match = !bacmp(&bt_sk(sk)->src, src); 1119c2287681SIdo Yariv dst_match = !bacmp(&bt_sk(sk)->dst, dst); 1120c2287681SIdo Yariv if (src_match && dst_match) { 112123691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 112223691d75SGustavo F. Padovan return c; 112323691d75SGustavo F. Padovan } 1124b62f328bSVille Tervo 1125b62f328bSVille Tervo /* Closest match */ 1126c2287681SIdo Yariv src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY); 1127c2287681SIdo Yariv dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY); 1128c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1129c2287681SIdo Yariv (src_any && dst_any)) 113023691d75SGustavo F. Padovan c1 = c; 1131b62f328bSVille Tervo } 1132b62f328bSVille Tervo } 1133280f294fSGustavo F. Padovan 113423691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 1135b62f328bSVille Tervo 113623691d75SGustavo F. Padovan return c1; 1137b62f328bSVille Tervo } 1138b62f328bSVille Tervo 1139b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn) 1140b62f328bSVille Tervo { 1141c916fbe4SGustavo F. Padovan struct sock *parent, *sk; 114223691d75SGustavo F. Padovan struct l2cap_chan *chan, *pchan; 1143b62f328bSVille Tervo 1144b62f328bSVille Tervo BT_DBG(""); 1145b62f328bSVille Tervo 1146b62f328bSVille Tervo /* Check if we have socket listening on cid */ 114723691d75SGustavo F. Padovan pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA, 1148c2287681SIdo Yariv conn->src, conn->dst); 114923691d75SGustavo F. Padovan if (!pchan) 1150b62f328bSVille Tervo return; 1151b62f328bSVille Tervo 115223691d75SGustavo F. Padovan parent = pchan->sk; 115323691d75SGustavo F. Padovan 1154aa2ac881SGustavo F. Padovan lock_sock(parent); 115562f3a2cfSGustavo F. Padovan 1156b62f328bSVille Tervo /* Check for backlog size */ 1157b62f328bSVille Tervo if (sk_acceptq_is_full(parent)) { 1158b62f328bSVille Tervo BT_DBG("backlog full %d", parent->sk_ack_backlog); 1159b62f328bSVille Tervo goto clean; 1160b62f328bSVille Tervo } 1161b62f328bSVille Tervo 116280808e43SGustavo F. Padovan chan = pchan->ops->new_connection(pchan->data); 116380808e43SGustavo F. Padovan if (!chan) 1164b62f328bSVille Tervo goto clean; 1165b62f328bSVille Tervo 116680808e43SGustavo F. Padovan sk = chan->sk; 11675d41ce1dSGustavo F. Padovan 1168b62f328bSVille Tervo hci_conn_hold(conn->hcon); 1169b62f328bSVille Tervo 1170b62f328bSVille Tervo bacpy(&bt_sk(sk)->src, conn->src); 1171b62f328bSVille Tervo bacpy(&bt_sk(sk)->dst, conn->dst); 1172b62f328bSVille Tervo 1173d1010240SGustavo F. Padovan bt_accept_enqueue(parent, sk); 1174d1010240SGustavo F. Padovan 11753d57dc68SGustavo F. Padovan l2cap_chan_add(conn, chan); 117648454079SGustavo F. Padovan 1177c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 1178b62f328bSVille Tervo 11790e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECTED); 1180b62f328bSVille Tervo parent->sk_data_ready(parent, 0); 1181b62f328bSVille Tervo 1182b62f328bSVille Tervo clean: 1183aa2ac881SGustavo F. Padovan release_sock(parent); 1184b62f328bSVille Tervo } 1185b62f328bSVille Tervo 11860a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn) 11870a708f8fSGustavo F. Padovan { 118848454079SGustavo F. Padovan struct l2cap_chan *chan; 11890a708f8fSGustavo F. Padovan 11900a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 11910a708f8fSGustavo F. Padovan 1192b62f328bSVille Tervo if (!conn->hcon->out && conn->hcon->type == LE_LINK) 1193b62f328bSVille Tervo l2cap_le_conn_ready(conn); 1194b62f328bSVille Tervo 1195160dc6acSVinicius Costa Gomes if (conn->hcon->out && conn->hcon->type == LE_LINK) 1196160dc6acSVinicius Costa Gomes smp_conn_security(conn, conn->hcon->pending_sec_level); 1197160dc6acSVinicius Costa Gomes 11983df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 11990a708f8fSGustavo F. Padovan 12003df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1201baa7e1faSGustavo F. Padovan 12026be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 12030a708f8fSGustavo F. Padovan 120463128451SVinicius Costa Gomes if (conn->hcon->type == LE_LINK) { 1205b501d6a1SAnderson Briglia if (smp_conn_security(conn, chan->sec_level)) 1206cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 1207acd7d370SVille Tervo 120863128451SVinicius Costa Gomes } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 12096be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 1210c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 12116be36555SAndrei Emeltchenko lock_sock(sk); 12120e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECTED); 12130a708f8fSGustavo F. Padovan sk->sk_state_change(sk); 12146be36555SAndrei Emeltchenko release_sock(sk); 1215b501d6a1SAnderson Briglia 121689bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT) 1217fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 12180a708f8fSGustavo F. Padovan 12196be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 12200a708f8fSGustavo F. Padovan } 12210a708f8fSGustavo F. Padovan 12223df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 12230a708f8fSGustavo F. Padovan } 12240a708f8fSGustavo F. Padovan 12250a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */ 12260a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) 12270a708f8fSGustavo F. Padovan { 122848454079SGustavo F. Padovan struct l2cap_chan *chan; 12290a708f8fSGustavo F. Padovan 12300a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 12310a708f8fSGustavo F. Padovan 12323df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 12330a708f8fSGustavo F. Padovan 12343df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 1235ecf61bdbSAndrei Emeltchenko if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) 12362e0052e4SAndrei Emeltchenko __l2cap_chan_set_err(chan, err); 12370a708f8fSGustavo F. Padovan } 12380a708f8fSGustavo F. Padovan 12393df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 12400a708f8fSGustavo F. Padovan } 12410a708f8fSGustavo F. Padovan 1242f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work) 12430a708f8fSGustavo F. Padovan { 1244f878fcadSGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 1245030013d8SGustavo F. Padovan info_timer.work); 12460a708f8fSGustavo F. Padovan 12470a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 12480a708f8fSGustavo F. Padovan conn->info_ident = 0; 12490a708f8fSGustavo F. Padovan 12500a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 12510a708f8fSGustavo F. Padovan } 12520a708f8fSGustavo F. Padovan 12535d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err) 12545d3de7dfSVinicius Costa Gomes { 12555d3de7dfSVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 12565d3de7dfSVinicius Costa Gomes struct l2cap_chan *chan, *l; 12575d3de7dfSVinicius Costa Gomes 12585d3de7dfSVinicius Costa Gomes if (!conn) 12595d3de7dfSVinicius Costa Gomes return; 12605d3de7dfSVinicius Costa Gomes 12615d3de7dfSVinicius Costa Gomes BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); 12625d3de7dfSVinicius Costa Gomes 12635d3de7dfSVinicius Costa Gomes kfree_skb(conn->rx_skb); 12645d3de7dfSVinicius Costa Gomes 12653df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 12663df91ea2SAndrei Emeltchenko 12675d3de7dfSVinicius Costa Gomes /* Kill channels */ 12685d3de7dfSVinicius Costa Gomes list_for_each_entry_safe(chan, l, &conn->chan_l, list) { 126961d6ef3eSMat Martineau l2cap_chan_hold(chan); 12706be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 12716be36555SAndrei Emeltchenko 12725d3de7dfSVinicius Costa Gomes l2cap_chan_del(chan, err); 12736be36555SAndrei Emeltchenko 12746be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 12756be36555SAndrei Emeltchenko 12765d3de7dfSVinicius Costa Gomes chan->ops->close(chan->data); 127761d6ef3eSMat Martineau l2cap_chan_put(chan); 12785d3de7dfSVinicius Costa Gomes } 12795d3de7dfSVinicius Costa Gomes 12803df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 12813df91ea2SAndrei Emeltchenko 128273d80debSLuiz Augusto von Dentz hci_chan_del(conn->hchan); 128373d80debSLuiz Augusto von Dentz 12845d3de7dfSVinicius Costa Gomes if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1285127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->info_timer); 12865d3de7dfSVinicius Costa Gomes 128751a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) { 1288127074bfSUlisses Furquim cancel_delayed_work_sync(&conn->security_timer); 12898aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 1290d26a2345SVinicius Costa Gomes } 12915d3de7dfSVinicius Costa Gomes 12925d3de7dfSVinicius Costa Gomes hcon->l2cap_data = NULL; 12935d3de7dfSVinicius Costa Gomes kfree(conn); 12945d3de7dfSVinicius Costa Gomes } 12955d3de7dfSVinicius Costa Gomes 12966c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work) 12975d3de7dfSVinicius Costa Gomes { 12986c9d42a1SGustavo F. Padovan struct l2cap_conn *conn = container_of(work, struct l2cap_conn, 12996c9d42a1SGustavo F. Padovan security_timer.work); 13005d3de7dfSVinicius Costa Gomes 13015d3de7dfSVinicius Costa Gomes l2cap_conn_del(conn->hcon, ETIMEDOUT); 13025d3de7dfSVinicius Costa Gomes } 13035d3de7dfSVinicius Costa Gomes 13040a708f8fSGustavo F. Padovan static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) 13050a708f8fSGustavo F. Padovan { 13060a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 130773d80debSLuiz Augusto von Dentz struct hci_chan *hchan; 13080a708f8fSGustavo F. Padovan 13090a708f8fSGustavo F. Padovan if (conn || status) 13100a708f8fSGustavo F. Padovan return conn; 13110a708f8fSGustavo F. Padovan 131273d80debSLuiz Augusto von Dentz hchan = hci_chan_create(hcon); 131373d80debSLuiz Augusto von Dentz if (!hchan) 13140a708f8fSGustavo F. Padovan return NULL; 13150a708f8fSGustavo F. Padovan 131673d80debSLuiz Augusto von Dentz conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC); 131773d80debSLuiz Augusto von Dentz if (!conn) { 131873d80debSLuiz Augusto von Dentz hci_chan_del(hchan); 131973d80debSLuiz Augusto von Dentz return NULL; 132073d80debSLuiz Augusto von Dentz } 132173d80debSLuiz Augusto von Dentz 13220a708f8fSGustavo F. Padovan hcon->l2cap_data = conn; 13230a708f8fSGustavo F. Padovan conn->hcon = hcon; 132473d80debSLuiz Augusto von Dentz conn->hchan = hchan; 13250a708f8fSGustavo F. Padovan 132673d80debSLuiz Augusto von Dentz BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); 13270a708f8fSGustavo F. Padovan 1328acd7d370SVille Tervo if (hcon->hdev->le_mtu && hcon->type == LE_LINK) 1329acd7d370SVille Tervo conn->mtu = hcon->hdev->le_mtu; 1330acd7d370SVille Tervo else 13310a708f8fSGustavo F. Padovan conn->mtu = hcon->hdev->acl_mtu; 1332acd7d370SVille Tervo 13330a708f8fSGustavo F. Padovan conn->src = &hcon->hdev->bdaddr; 13340a708f8fSGustavo F. Padovan conn->dst = &hcon->dst; 13350a708f8fSGustavo F. Padovan 13360a708f8fSGustavo F. Padovan conn->feat_mask = 0; 13370a708f8fSGustavo F. Padovan 13380a708f8fSGustavo F. Padovan spin_lock_init(&conn->lock); 13393df91ea2SAndrei Emeltchenko mutex_init(&conn->chan_lock); 1340baa7e1faSGustavo F. Padovan 1341baa7e1faSGustavo F. Padovan INIT_LIST_HEAD(&conn->chan_l); 13420a708f8fSGustavo F. Padovan 13435d3de7dfSVinicius Costa Gomes if (hcon->type == LE_LINK) 13446c9d42a1SGustavo F. Padovan INIT_DELAYED_WORK(&conn->security_timer, security_timeout); 13455d3de7dfSVinicius Costa Gomes else 1346030013d8SGustavo F. Padovan INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); 13470a708f8fSGustavo F. Padovan 13489f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; 13490a708f8fSGustavo F. Padovan 13500a708f8fSGustavo F. Padovan return conn; 13510a708f8fSGustavo F. Padovan } 13520a708f8fSGustavo F. Padovan 13530a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */ 13540a708f8fSGustavo F. Padovan 1355c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr. 13560a708f8fSGustavo F. Padovan * Returns closest match. 13570a708f8fSGustavo F. Padovan */ 1358c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, 1359c2287681SIdo Yariv bdaddr_t *src, 1360c2287681SIdo Yariv bdaddr_t *dst) 13610a708f8fSGustavo F. Padovan { 136223691d75SGustavo F. Padovan struct l2cap_chan *c, *c1 = NULL; 13630a708f8fSGustavo F. Padovan 136423691d75SGustavo F. Padovan read_lock(&chan_list_lock); 13650a708f8fSGustavo F. Padovan 136623691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 136723691d75SGustavo F. Padovan struct sock *sk = c->sk; 1368fe4128e0SGustavo F. Padovan 136989bc500eSGustavo F. Padovan if (state && c->state != state) 13700a708f8fSGustavo F. Padovan continue; 13710a708f8fSGustavo F. Padovan 137223691d75SGustavo F. Padovan if (c->psm == psm) { 1373c2287681SIdo Yariv int src_match, dst_match; 1374c2287681SIdo Yariv int src_any, dst_any; 1375c2287681SIdo Yariv 13760a708f8fSGustavo F. Padovan /* Exact match. */ 1377c2287681SIdo Yariv src_match = !bacmp(&bt_sk(sk)->src, src); 1378c2287681SIdo Yariv dst_match = !bacmp(&bt_sk(sk)->dst, dst); 1379c2287681SIdo Yariv if (src_match && dst_match) { 1380a7567b20SJohannes Berg read_unlock(&chan_list_lock); 138123691d75SGustavo F. Padovan return c; 138223691d75SGustavo F. Padovan } 13830a708f8fSGustavo F. Padovan 13840a708f8fSGustavo F. Padovan /* Closest match */ 1385c2287681SIdo Yariv src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY); 1386c2287681SIdo Yariv dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY); 1387c2287681SIdo Yariv if ((src_match && dst_any) || (src_any && dst_match) || 1388c2287681SIdo Yariv (src_any && dst_any)) 138923691d75SGustavo F. Padovan c1 = c; 13900a708f8fSGustavo F. Padovan } 13910a708f8fSGustavo F. Padovan } 13920a708f8fSGustavo F. Padovan 139323691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 13940a708f8fSGustavo F. Padovan 139523691d75SGustavo F. Padovan return c1; 13960a708f8fSGustavo F. Padovan } 13970a708f8fSGustavo F. Padovan 13988e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, 13998e9f9892SAndre Guedes bdaddr_t *dst, u8 dst_type) 14000a708f8fSGustavo F. Padovan { 14015d41ce1dSGustavo F. Padovan struct sock *sk = chan->sk; 14020a708f8fSGustavo F. Padovan bdaddr_t *src = &bt_sk(sk)->src; 14030a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 14040a708f8fSGustavo F. Padovan struct hci_conn *hcon; 14050a708f8fSGustavo F. Padovan struct hci_dev *hdev; 14060a708f8fSGustavo F. Padovan __u8 auth_type; 14070a708f8fSGustavo F. Padovan int err; 14080a708f8fSGustavo F. Padovan 14098e9f9892SAndre Guedes BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst), 14108e9f9892SAndre Guedes dst_type, __le16_to_cpu(chan->psm)); 14110a708f8fSGustavo F. Padovan 14120a708f8fSGustavo F. Padovan hdev = hci_get_route(dst, src); 14130a708f8fSGustavo F. Padovan if (!hdev) 14140a708f8fSGustavo F. Padovan return -EHOSTUNREACH; 14150a708f8fSGustavo F. Padovan 141609fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 14170a708f8fSGustavo F. Padovan 14186be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 141903a00194SGustavo F. Padovan 142003a00194SGustavo F. Padovan /* PSM must be odd and lsb of upper byte must be 0 */ 142103a00194SGustavo F. Padovan if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid && 142203a00194SGustavo F. Padovan chan->chan_type != L2CAP_CHAN_RAW) { 142303a00194SGustavo F. Padovan err = -EINVAL; 142403a00194SGustavo F. Padovan goto done; 142503a00194SGustavo F. Padovan } 142603a00194SGustavo F. Padovan 142703a00194SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) { 142803a00194SGustavo F. Padovan err = -EINVAL; 142903a00194SGustavo F. Padovan goto done; 143003a00194SGustavo F. Padovan } 143103a00194SGustavo F. Padovan 143203a00194SGustavo F. Padovan switch (chan->mode) { 143303a00194SGustavo F. Padovan case L2CAP_MODE_BASIC: 143403a00194SGustavo F. Padovan break; 143503a00194SGustavo F. Padovan case L2CAP_MODE_ERTM: 143603a00194SGustavo F. Padovan case L2CAP_MODE_STREAMING: 143703a00194SGustavo F. Padovan if (!disable_ertm) 143803a00194SGustavo F. Padovan break; 143903a00194SGustavo F. Padovan /* fall through */ 144003a00194SGustavo F. Padovan default: 144103a00194SGustavo F. Padovan err = -ENOTSUPP; 144203a00194SGustavo F. Padovan goto done; 144303a00194SGustavo F. Padovan } 144403a00194SGustavo F. Padovan 14456be36555SAndrei Emeltchenko lock_sock(sk); 14466be36555SAndrei Emeltchenko 144703a00194SGustavo F. Padovan switch (sk->sk_state) { 144803a00194SGustavo F. Padovan case BT_CONNECT: 144903a00194SGustavo F. Padovan case BT_CONNECT2: 145003a00194SGustavo F. Padovan case BT_CONFIG: 145103a00194SGustavo F. Padovan /* Already connecting */ 145203a00194SGustavo F. Padovan err = 0; 14536be36555SAndrei Emeltchenko release_sock(sk); 145403a00194SGustavo F. Padovan goto done; 145503a00194SGustavo F. Padovan 145603a00194SGustavo F. Padovan case BT_CONNECTED: 145703a00194SGustavo F. Padovan /* Already connected */ 145803a00194SGustavo F. Padovan err = -EISCONN; 14596be36555SAndrei Emeltchenko release_sock(sk); 146003a00194SGustavo F. Padovan goto done; 146103a00194SGustavo F. Padovan 146203a00194SGustavo F. Padovan case BT_OPEN: 146303a00194SGustavo F. Padovan case BT_BOUND: 146403a00194SGustavo F. Padovan /* Can connect */ 146503a00194SGustavo F. Padovan break; 146603a00194SGustavo F. Padovan 146703a00194SGustavo F. Padovan default: 146803a00194SGustavo F. Padovan err = -EBADFD; 14696be36555SAndrei Emeltchenko release_sock(sk); 147003a00194SGustavo F. Padovan goto done; 147103a00194SGustavo F. Padovan } 147203a00194SGustavo F. Padovan 147303a00194SGustavo F. Padovan /* Set destination address and psm */ 14749219b2a0SGustavo F. Padovan bacpy(&bt_sk(sk)->dst, dst); 14756be36555SAndrei Emeltchenko 14766be36555SAndrei Emeltchenko release_sock(sk); 14776be36555SAndrei Emeltchenko 147803a00194SGustavo F. Padovan chan->psm = psm; 147903a00194SGustavo F. Padovan chan->dcid = cid; 14800a708f8fSGustavo F. Padovan 14814343478fSGustavo F. Padovan auth_type = l2cap_get_auth_type(chan); 14820a708f8fSGustavo F. Padovan 1483fe4128e0SGustavo F. Padovan if (chan->dcid == L2CAP_CID_LE_DATA) 14848e9f9892SAndre Guedes hcon = hci_connect(hdev, LE_LINK, dst, dst_type, 14854343478fSGustavo F. Padovan chan->sec_level, auth_type); 1486acd7d370SVille Tervo else 14878e9f9892SAndre Guedes hcon = hci_connect(hdev, ACL_LINK, dst, dst_type, 14884343478fSGustavo F. Padovan chan->sec_level, auth_type); 1489acd7d370SVille Tervo 149030e76272SVille Tervo if (IS_ERR(hcon)) { 149130e76272SVille Tervo err = PTR_ERR(hcon); 14920a708f8fSGustavo F. Padovan goto done; 149330e76272SVille Tervo } 14940a708f8fSGustavo F. Padovan 14950a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, 0); 14960a708f8fSGustavo F. Padovan if (!conn) { 14970a708f8fSGustavo F. Padovan hci_conn_put(hcon); 149830e76272SVille Tervo err = -ENOMEM; 14990a708f8fSGustavo F. Padovan goto done; 15000a708f8fSGustavo F. Padovan } 15010a708f8fSGustavo F. Padovan 15029f0caeb1SVinicius Costa Gomes if (hcon->type == LE_LINK) { 15039f0caeb1SVinicius Costa Gomes err = 0; 15049f0caeb1SVinicius Costa Gomes 15059f0caeb1SVinicius Costa Gomes if (!list_empty(&conn->chan_l)) { 15069f0caeb1SVinicius Costa Gomes err = -EBUSY; 15079f0caeb1SVinicius Costa Gomes hci_conn_put(hcon); 15089f0caeb1SVinicius Costa Gomes } 15099f0caeb1SVinicius Costa Gomes 15109f0caeb1SVinicius Costa Gomes if (err) 15119f0caeb1SVinicius Costa Gomes goto done; 15129f0caeb1SVinicius Costa Gomes } 15139f0caeb1SVinicius Costa Gomes 15140a708f8fSGustavo F. Padovan /* Update source addr of the socket */ 15150a708f8fSGustavo F. Padovan bacpy(src, conn->src); 15160a708f8fSGustavo F. Padovan 15176be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 151848454079SGustavo F. Padovan l2cap_chan_add(conn, chan); 15196be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 152048454079SGustavo F. Padovan 15216be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECT); 1522c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 15230a708f8fSGustavo F. Padovan 15240a708f8fSGustavo F. Padovan if (hcon->state == BT_CONNECTED) { 1525715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 1526c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 1527d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) 15286be36555SAndrei Emeltchenko l2cap_state_change(chan, BT_CONNECTED); 15290a708f8fSGustavo F. Padovan } else 1530fc7f8a7eSGustavo F. Padovan l2cap_do_start(chan); 15310a708f8fSGustavo F. Padovan } 15320a708f8fSGustavo F. Padovan 153330e76272SVille Tervo err = 0; 153430e76272SVille Tervo 15350a708f8fSGustavo F. Padovan done: 15366be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 153709fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 15380a708f8fSGustavo F. Padovan hci_dev_put(hdev); 15390a708f8fSGustavo F. Padovan return err; 15400a708f8fSGustavo F. Padovan } 15410a708f8fSGustavo F. Padovan 1542dcba0dbaSGustavo F. Padovan int __l2cap_wait_ack(struct sock *sk) 15430a708f8fSGustavo F. Padovan { 15448c1d787bSGustavo F. Padovan struct l2cap_chan *chan = l2cap_pi(sk)->chan; 15450a708f8fSGustavo F. Padovan DECLARE_WAITQUEUE(wait, current); 15460a708f8fSGustavo F. Padovan int err = 0; 15470a708f8fSGustavo F. Padovan int timeo = HZ/5; 15480a708f8fSGustavo F. Padovan 15490a708f8fSGustavo F. Padovan add_wait_queue(sk_sleep(sk), &wait); 15500a708f8fSGustavo F. Padovan set_current_state(TASK_INTERRUPTIBLE); 1551a71a0cf4SPeter Hurley while (chan->unacked_frames > 0 && chan->conn) { 15520a708f8fSGustavo F. Padovan if (!timeo) 15530a708f8fSGustavo F. Padovan timeo = HZ/5; 15540a708f8fSGustavo F. Padovan 15550a708f8fSGustavo F. Padovan if (signal_pending(current)) { 15560a708f8fSGustavo F. Padovan err = sock_intr_errno(timeo); 15570a708f8fSGustavo F. Padovan break; 15580a708f8fSGustavo F. Padovan } 15590a708f8fSGustavo F. Padovan 15600a708f8fSGustavo F. Padovan release_sock(sk); 15610a708f8fSGustavo F. Padovan timeo = schedule_timeout(timeo); 15620a708f8fSGustavo F. Padovan lock_sock(sk); 1563a71a0cf4SPeter Hurley set_current_state(TASK_INTERRUPTIBLE); 15640a708f8fSGustavo F. Padovan 15650a708f8fSGustavo F. Padovan err = sock_error(sk); 15660a708f8fSGustavo F. Padovan if (err) 15670a708f8fSGustavo F. Padovan break; 15680a708f8fSGustavo F. Padovan } 15690a708f8fSGustavo F. Padovan set_current_state(TASK_RUNNING); 15700a708f8fSGustavo F. Padovan remove_wait_queue(sk_sleep(sk), &wait); 15710a708f8fSGustavo F. Padovan return err; 15720a708f8fSGustavo F. Padovan } 15730a708f8fSGustavo F. Padovan 1574721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work) 15750a708f8fSGustavo F. Padovan { 1576721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1577721c4181SGustavo F. Padovan monitor_timer.work); 15780a708f8fSGustavo F. Padovan 1579525cd185SGustavo F. Padovan BT_DBG("chan %p", chan); 15800a708f8fSGustavo F. Padovan 15816be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 15826be36555SAndrei Emeltchenko 15832c03a7a4SGustavo F. Padovan if (chan->retry_count >= chan->remote_max_tx) { 15848c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); 15856be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 15868d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 15870a708f8fSGustavo F. Padovan return; 15880a708f8fSGustavo F. Padovan } 15890a708f8fSGustavo F. Padovan 15906a026610SGustavo F. Padovan chan->retry_count++; 15911a09bcb9SGustavo F. Padovan __set_monitor_timer(chan); 15920a708f8fSGustavo F. Padovan 1593525cd185SGustavo F. Padovan l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); 15946be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 15958d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 15960a708f8fSGustavo F. Padovan } 15970a708f8fSGustavo F. Padovan 1598721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work) 15990a708f8fSGustavo F. Padovan { 1600721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 1601721c4181SGustavo F. Padovan retrans_timer.work); 16020a708f8fSGustavo F. Padovan 160349208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 16040a708f8fSGustavo F. Padovan 16056be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 16066be36555SAndrei Emeltchenko 16076a026610SGustavo F. Padovan chan->retry_count = 1; 16081a09bcb9SGustavo F. Padovan __set_monitor_timer(chan); 16090a708f8fSGustavo F. Padovan 1610e2ab4353SGustavo F. Padovan set_bit(CONN_WAIT_F, &chan->conn_state); 16110a708f8fSGustavo F. Padovan 1612525cd185SGustavo F. Padovan l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); 16136be36555SAndrei Emeltchenko 16146be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 16158d7e1c7fSAndrei Emeltchenko l2cap_chan_put(chan); 16160a708f8fSGustavo F. Padovan } 16170a708f8fSGustavo F. Padovan 161842e5c802SGustavo F. Padovan static void l2cap_drop_acked_frames(struct l2cap_chan *chan) 16190a708f8fSGustavo F. Padovan { 16200a708f8fSGustavo F. Padovan struct sk_buff *skb; 16210a708f8fSGustavo F. Padovan 162258d35f87SGustavo F. Padovan while ((skb = skb_peek(&chan->tx_q)) && 16236a026610SGustavo F. Padovan chan->unacked_frames) { 16243ce3514fSMat Martineau if (bt_cb(skb)->control.txseq == chan->expected_ack_seq) 16250a708f8fSGustavo F. Padovan break; 16260a708f8fSGustavo F. Padovan 162758d35f87SGustavo F. Padovan skb = skb_dequeue(&chan->tx_q); 16280a708f8fSGustavo F. Padovan kfree_skb(skb); 16290a708f8fSGustavo F. Padovan 16306a026610SGustavo F. Padovan chan->unacked_frames--; 16310a708f8fSGustavo F. Padovan } 16320a708f8fSGustavo F. Padovan 16336a026610SGustavo F. Padovan if (!chan->unacked_frames) 16341a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 16350a708f8fSGustavo F. Padovan } 16360a708f8fSGustavo F. Padovan 163767c9e840SSzymon Janc static void l2cap_streaming_send(struct l2cap_chan *chan) 16380a708f8fSGustavo F. Padovan { 16390a708f8fSGustavo F. Padovan struct sk_buff *skb; 164088843ab0SAndrei Emeltchenko u32 control; 164188843ab0SAndrei Emeltchenko u16 fcs; 16420a708f8fSGustavo F. Padovan 164358d35f87SGustavo F. Padovan while ((skb = skb_dequeue(&chan->tx_q))) { 164488843ab0SAndrei Emeltchenko control = __get_control(chan, skb->data + L2CAP_HDR_SIZE); 1645fb45de7dSAndrei Emeltchenko control |= __set_txseq(chan, chan->next_tx_seq); 164694122bbeSMat Martineau control |= __set_ctrl_sar(chan, bt_cb(skb)->control.sar); 164788843ab0SAndrei Emeltchenko __put_control(chan, control, skb->data + L2CAP_HDR_SIZE); 16480a708f8fSGustavo F. Padovan 164947d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 165003a51213SAndrei Emeltchenko fcs = crc16(0, (u8 *)skb->data, 165103a51213SAndrei Emeltchenko skb->len - L2CAP_FCS_SIZE); 165203a51213SAndrei Emeltchenko put_unaligned_le16(fcs, 165303a51213SAndrei Emeltchenko skb->data + skb->len - L2CAP_FCS_SIZE); 16540a708f8fSGustavo F. Padovan } 16550a708f8fSGustavo F. Padovan 16564343478fSGustavo F. Padovan l2cap_do_send(chan, skb); 16570a708f8fSGustavo F. Padovan 1658836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 16590a708f8fSGustavo F. Padovan } 16600a708f8fSGustavo F. Padovan } 16610a708f8fSGustavo F. Padovan 1662fb45de7dSAndrei Emeltchenko static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq) 16630a708f8fSGustavo F. Padovan { 16640a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 166588843ab0SAndrei Emeltchenko u16 fcs; 166688843ab0SAndrei Emeltchenko u32 control; 16670a708f8fSGustavo F. Padovan 166858d35f87SGustavo F. Padovan skb = skb_peek(&chan->tx_q); 16690a708f8fSGustavo F. Padovan if (!skb) 16700a708f8fSGustavo F. Padovan return; 16710a708f8fSGustavo F. Padovan 16723ce3514fSMat Martineau while (bt_cb(skb)->control.txseq != tx_seq) { 167358d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 16740a708f8fSGustavo F. Padovan return; 16750a708f8fSGustavo F. Padovan 1676d1726b6dSSzymon Janc skb = skb_queue_next(&chan->tx_q, skb); 1677d1726b6dSSzymon Janc } 16780a708f8fSGustavo F. Padovan 16793ce3514fSMat Martineau if (bt_cb(skb)->control.retries == chan->remote_max_tx && 16803ce3514fSMat Martineau chan->remote_max_tx) { 16818c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); 16820a708f8fSGustavo F. Padovan return; 16830a708f8fSGustavo F. Padovan } 16840a708f8fSGustavo F. Padovan 16850a708f8fSGustavo F. Padovan tx_skb = skb_clone(skb, GFP_ATOMIC); 16863ce3514fSMat Martineau bt_cb(skb)->control.retries++; 168788843ab0SAndrei Emeltchenko 168888843ab0SAndrei Emeltchenko control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE); 16897e0ef6eeSAndrei Emeltchenko control &= __get_sar_mask(chan); 16900a708f8fSGustavo F. Padovan 1691e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 169203f6715dSAndrei Emeltchenko control |= __set_ctrl_final(chan); 16930a708f8fSGustavo F. Padovan 16940b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 1695fb45de7dSAndrei Emeltchenko control |= __set_txseq(chan, tx_seq); 16960a708f8fSGustavo F. Padovan 169788843ab0SAndrei Emeltchenko __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE); 16980a708f8fSGustavo F. Padovan 169947d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 170003a51213SAndrei Emeltchenko fcs = crc16(0, (u8 *)tx_skb->data, 170103a51213SAndrei Emeltchenko tx_skb->len - L2CAP_FCS_SIZE); 170203a51213SAndrei Emeltchenko put_unaligned_le16(fcs, 170303a51213SAndrei Emeltchenko tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE); 17040a708f8fSGustavo F. Padovan } 17050a708f8fSGustavo F. Padovan 17064343478fSGustavo F. Padovan l2cap_do_send(chan, tx_skb); 17070a708f8fSGustavo F. Padovan } 17080a708f8fSGustavo F. Padovan 170967c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan) 17100a708f8fSGustavo F. Padovan { 17110a708f8fSGustavo F. Padovan struct sk_buff *skb, *tx_skb; 171288843ab0SAndrei Emeltchenko u16 fcs; 171388843ab0SAndrei Emeltchenko u32 control; 17140a708f8fSGustavo F. Padovan int nsent = 0; 17150a708f8fSGustavo F. Padovan 171689bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 17170a708f8fSGustavo F. Padovan return -ENOTCONN; 17180a708f8fSGustavo F. Padovan 171994122bbeSMat Martineau if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 172094122bbeSMat Martineau return 0; 172194122bbeSMat Martineau 172258d35f87SGustavo F. Padovan while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) { 17230a708f8fSGustavo F. Padovan 17243ce3514fSMat Martineau if (bt_cb(skb)->control.retries == chan->remote_max_tx && 17253ce3514fSMat Martineau chan->remote_max_tx) { 17268c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); 17270a708f8fSGustavo F. Padovan break; 17280a708f8fSGustavo F. Padovan } 17290a708f8fSGustavo F. Padovan 17300a708f8fSGustavo F. Padovan tx_skb = skb_clone(skb, GFP_ATOMIC); 17310a708f8fSGustavo F. Padovan 17323ce3514fSMat Martineau bt_cb(skb)->control.retries++; 17330a708f8fSGustavo F. Padovan 173488843ab0SAndrei Emeltchenko control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE); 17357e0ef6eeSAndrei Emeltchenko control &= __get_sar_mask(chan); 17360a708f8fSGustavo F. Padovan 1737e2ab4353SGustavo F. Padovan if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) 173803f6715dSAndrei Emeltchenko control |= __set_ctrl_final(chan); 1739e2ab4353SGustavo F. Padovan 17400b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 1741fb45de7dSAndrei Emeltchenko control |= __set_txseq(chan, chan->next_tx_seq); 174294122bbeSMat Martineau control |= __set_ctrl_sar(chan, bt_cb(skb)->control.sar); 17430a708f8fSGustavo F. Padovan 174488843ab0SAndrei Emeltchenko __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE); 17450a708f8fSGustavo F. Padovan 174647d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 174703a51213SAndrei Emeltchenko fcs = crc16(0, (u8 *)skb->data, 174803a51213SAndrei Emeltchenko tx_skb->len - L2CAP_FCS_SIZE); 174903a51213SAndrei Emeltchenko put_unaligned_le16(fcs, skb->data + 175003a51213SAndrei Emeltchenko tx_skb->len - L2CAP_FCS_SIZE); 17510a708f8fSGustavo F. Padovan } 17520a708f8fSGustavo F. Padovan 17534343478fSGustavo F. Padovan l2cap_do_send(chan, tx_skb); 17540a708f8fSGustavo F. Padovan 17551a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 17560a708f8fSGustavo F. Padovan 17573ce3514fSMat Martineau bt_cb(skb)->control.txseq = chan->next_tx_seq; 1758836be934SAndrei Emeltchenko 1759836be934SAndrei Emeltchenko chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 17600a708f8fSGustavo F. Padovan 17613ce3514fSMat Martineau if (bt_cb(skb)->control.retries == 1) { 17626a026610SGustavo F. Padovan chan->unacked_frames++; 1763930fa4aeSSzymon Janc 1764930fa4aeSSzymon Janc if (!nsent++) 1765930fa4aeSSzymon Janc __clear_ack_timer(chan); 17668ed7a0aeSSzymon Janc } 176723e9fde2SSuraj Sumangala 17686a026610SGustavo F. Padovan chan->frames_sent++; 17690a708f8fSGustavo F. Padovan 177058d35f87SGustavo F. Padovan if (skb_queue_is_last(&chan->tx_q, skb)) 177158d35f87SGustavo F. Padovan chan->tx_send_head = NULL; 17720a708f8fSGustavo F. Padovan else 177358d35f87SGustavo F. Padovan chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); 17740a708f8fSGustavo F. Padovan } 17750a708f8fSGustavo F. Padovan 17760a708f8fSGustavo F. Padovan return nsent; 17770a708f8fSGustavo F. Padovan } 17780a708f8fSGustavo F. Padovan 1779525cd185SGustavo F. Padovan static int l2cap_retransmit_frames(struct l2cap_chan *chan) 17800a708f8fSGustavo F. Padovan { 17810a708f8fSGustavo F. Padovan int ret; 17820a708f8fSGustavo F. Padovan 178358d35f87SGustavo F. Padovan if (!skb_queue_empty(&chan->tx_q)) 178458d35f87SGustavo F. Padovan chan->tx_send_head = chan->tx_q.next; 17850a708f8fSGustavo F. Padovan 178642e5c802SGustavo F. Padovan chan->next_tx_seq = chan->expected_ack_seq; 1787525cd185SGustavo F. Padovan ret = l2cap_ertm_send(chan); 17880a708f8fSGustavo F. Padovan return ret; 17890a708f8fSGustavo F. Padovan } 17900a708f8fSGustavo F. Padovan 1791b17e73bbSSzymon Janc static void __l2cap_send_ack(struct l2cap_chan *chan) 17920a708f8fSGustavo F. Padovan { 179388843ab0SAndrei Emeltchenko u32 control = 0; 17940a708f8fSGustavo F. Padovan 17950b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 17960a708f8fSGustavo F. Padovan 1797e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 1798ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); 1799e2ab4353SGustavo F. Padovan set_bit(CONN_RNR_SENT, &chan->conn_state); 1800525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 18010a708f8fSGustavo F. Padovan return; 18020a708f8fSGustavo F. Padovan } 18030a708f8fSGustavo F. Padovan 1804525cd185SGustavo F. Padovan if (l2cap_ertm_send(chan) > 0) 18050a708f8fSGustavo F. Padovan return; 18060a708f8fSGustavo F. Padovan 1807ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 1808525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 18090a708f8fSGustavo F. Padovan } 18100a708f8fSGustavo F. Padovan 1811b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan) 1812b17e73bbSSzymon Janc { 1813b17e73bbSSzymon Janc __clear_ack_timer(chan); 1814b17e73bbSSzymon Janc __l2cap_send_ack(chan); 1815b17e73bbSSzymon Janc } 1816b17e73bbSSzymon Janc 1817525cd185SGustavo F. Padovan static void l2cap_send_srejtail(struct l2cap_chan *chan) 18180a708f8fSGustavo F. Padovan { 18190a708f8fSGustavo F. Padovan struct srej_list *tail; 182088843ab0SAndrei Emeltchenko u32 control; 18210a708f8fSGustavo F. Padovan 1822ab784b73SAndrei Emeltchenko control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ); 182303f6715dSAndrei Emeltchenko control |= __set_ctrl_final(chan); 18240a708f8fSGustavo F. Padovan 182539d5a3eeSGustavo F. Padovan tail = list_entry((&chan->srej_l)->prev, struct srej_list, list); 18260b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, tail->tx_seq); 18270a708f8fSGustavo F. Padovan 1828525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 18290a708f8fSGustavo F. Padovan } 18300a708f8fSGustavo F. Padovan 183104124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, 183204124681SGustavo F. Padovan struct msghdr *msg, int len, 183304124681SGustavo F. Padovan int count, struct sk_buff *skb) 18340a708f8fSGustavo F. Padovan { 18350952a57aSAndrei Emeltchenko struct l2cap_conn *conn = chan->conn; 18360a708f8fSGustavo F. Padovan struct sk_buff **frag; 183790338947SGustavo Padovan int sent = 0; 18380a708f8fSGustavo F. Padovan 18390a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) 18400a708f8fSGustavo F. Padovan return -EFAULT; 18410a708f8fSGustavo F. Padovan 18420a708f8fSGustavo F. Padovan sent += count; 18430a708f8fSGustavo F. Padovan len -= count; 18440a708f8fSGustavo F. Padovan 18450a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 18460a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 18470a708f8fSGustavo F. Padovan while (len) { 1848fbe00700SGustavo Padovan struct sk_buff *tmp; 1849fbe00700SGustavo Padovan 18500a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 18510a708f8fSGustavo F. Padovan 1852fbe00700SGustavo Padovan tmp = chan->ops->alloc_skb(chan, count, 185390338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 1854fbe00700SGustavo Padovan if (IS_ERR(tmp)) 1855fbe00700SGustavo Padovan return PTR_ERR(tmp); 18562f7719ceSAndrei Emeltchenko 1857fbe00700SGustavo Padovan *frag = tmp; 1858fbe00700SGustavo Padovan 18590a708f8fSGustavo F. Padovan if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) 18600a708f8fSGustavo F. Padovan return -EFAULT; 18610a708f8fSGustavo F. Padovan 18625e59b791SLuiz Augusto von Dentz (*frag)->priority = skb->priority; 18635e59b791SLuiz Augusto von Dentz 18640a708f8fSGustavo F. Padovan sent += count; 18650a708f8fSGustavo F. Padovan len -= count; 18660a708f8fSGustavo F. Padovan 18672d0ed3d5SGustavo Padovan skb->len += (*frag)->len; 18682d0ed3d5SGustavo Padovan skb->data_len += (*frag)->len; 18692d0ed3d5SGustavo Padovan 18700a708f8fSGustavo F. Padovan frag = &(*frag)->next; 18710a708f8fSGustavo F. Padovan } 18720a708f8fSGustavo F. Padovan 18730a708f8fSGustavo F. Padovan return sent; 18740a708f8fSGustavo F. Padovan } 18750a708f8fSGustavo F. Padovan 18765e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, 18775e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 18785e59b791SLuiz Augusto von Dentz u32 priority) 18790a708f8fSGustavo F. Padovan { 18808c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 18810a708f8fSGustavo F. Padovan struct sk_buff *skb; 188203a51213SAndrei Emeltchenko int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; 18830a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 18840a708f8fSGustavo F. Padovan 18856d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d priority %u", chan, (int)len, priority); 18860a708f8fSGustavo F. Padovan 18870a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 18882f7719ceSAndrei Emeltchenko 18892f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 189090338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 189190338947SGustavo Padovan if (IS_ERR(skb)) 189290338947SGustavo Padovan return skb; 18930a708f8fSGustavo F. Padovan 18945e59b791SLuiz Augusto von Dentz skb->priority = priority; 18955e59b791SLuiz Augusto von Dentz 18960a708f8fSGustavo F. Padovan /* Create L2CAP header */ 18970a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 1898fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 1899daf6a78cSAndrei Emeltchenko lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); 1900daf6a78cSAndrei Emeltchenko put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE)); 19010a708f8fSGustavo F. Padovan 19020952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 19030a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 19040a708f8fSGustavo F. Padovan kfree_skb(skb); 19050a708f8fSGustavo F. Padovan return ERR_PTR(err); 19060a708f8fSGustavo F. Padovan } 19070a708f8fSGustavo F. Padovan return skb; 19080a708f8fSGustavo F. Padovan } 19090a708f8fSGustavo F. Padovan 19105e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, 19115e59b791SLuiz Augusto von Dentz struct msghdr *msg, size_t len, 19125e59b791SLuiz Augusto von Dentz u32 priority) 19130a708f8fSGustavo F. Padovan { 19148c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 19150a708f8fSGustavo F. Padovan struct sk_buff *skb; 1916f2ba7faeSGustavo Padovan int err, count; 19170a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 19180a708f8fSGustavo F. Padovan 19196d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d", chan, (int)len); 19200a708f8fSGustavo F. Padovan 1921f2ba7faeSGustavo Padovan count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); 19222f7719ceSAndrei Emeltchenko 1923f2ba7faeSGustavo Padovan skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE, 192490338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 192590338947SGustavo Padovan if (IS_ERR(skb)) 192690338947SGustavo Padovan return skb; 19270a708f8fSGustavo F. Padovan 19285e59b791SLuiz Augusto von Dentz skb->priority = priority; 19295e59b791SLuiz Augusto von Dentz 19300a708f8fSGustavo F. Padovan /* Create L2CAP header */ 19310a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 1932fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 19336ff9b5efSGustavo Padovan lh->len = cpu_to_le16(len); 19340a708f8fSGustavo F. Padovan 19350952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 19360a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 19370a708f8fSGustavo F. Padovan kfree_skb(skb); 19380a708f8fSGustavo F. Padovan return ERR_PTR(err); 19390a708f8fSGustavo F. Padovan } 19400a708f8fSGustavo F. Padovan return skb; 19410a708f8fSGustavo F. Padovan } 19420a708f8fSGustavo F. Padovan 1943ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, 1944ab0ff76dSLuiz Augusto von Dentz struct msghdr *msg, size_t len, 194594122bbeSMat Martineau u16 sdulen) 19460a708f8fSGustavo F. Padovan { 19478c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 19480a708f8fSGustavo F. Padovan struct sk_buff *skb; 1949e4ca6d98SAndrei Emeltchenko int err, count, hlen; 19500a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 19510a708f8fSGustavo F. Padovan 19526d5922b0SAndrei Emeltchenko BT_DBG("chan %p len %d", chan, (int)len); 19530a708f8fSGustavo F. Padovan 19540a708f8fSGustavo F. Padovan if (!conn) 19550a708f8fSGustavo F. Padovan return ERR_PTR(-ENOTCONN); 19560a708f8fSGustavo F. Padovan 1957e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 1958e4ca6d98SAndrei Emeltchenko hlen = L2CAP_EXT_HDR_SIZE; 1959e4ca6d98SAndrei Emeltchenko else 1960e4ca6d98SAndrei Emeltchenko hlen = L2CAP_ENH_HDR_SIZE; 1961e4ca6d98SAndrei Emeltchenko 19620a708f8fSGustavo F. Padovan if (sdulen) 196303a51213SAndrei Emeltchenko hlen += L2CAP_SDULEN_SIZE; 19640a708f8fSGustavo F. Padovan 196547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 196603a51213SAndrei Emeltchenko hlen += L2CAP_FCS_SIZE; 19670a708f8fSGustavo F. Padovan 19680a708f8fSGustavo F. Padovan count = min_t(unsigned int, (conn->mtu - hlen), len); 19692f7719ceSAndrei Emeltchenko 19702f7719ceSAndrei Emeltchenko skb = chan->ops->alloc_skb(chan, count + hlen, 197190338947SGustavo Padovan msg->msg_flags & MSG_DONTWAIT); 197290338947SGustavo Padovan if (IS_ERR(skb)) 197390338947SGustavo Padovan return skb; 19740a708f8fSGustavo F. Padovan 19750a708f8fSGustavo F. Padovan /* Create L2CAP header */ 19760a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 1977fe4128e0SGustavo F. Padovan lh->cid = cpu_to_le16(chan->dcid); 19780a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); 197988843ab0SAndrei Emeltchenko 198094122bbeSMat Martineau __put_control(chan, 0, skb_put(skb, __ctrl_size(chan))); 198188843ab0SAndrei Emeltchenko 19820a708f8fSGustavo F. Padovan if (sdulen) 198303a51213SAndrei Emeltchenko put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); 19840a708f8fSGustavo F. Padovan 19850952a57aSAndrei Emeltchenko err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); 19860a708f8fSGustavo F. Padovan if (unlikely(err < 0)) { 19870a708f8fSGustavo F. Padovan kfree_skb(skb); 19880a708f8fSGustavo F. Padovan return ERR_PTR(err); 19890a708f8fSGustavo F. Padovan } 19900a708f8fSGustavo F. Padovan 199147d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 199203a51213SAndrei Emeltchenko put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE)); 19930a708f8fSGustavo F. Padovan 19943ce3514fSMat Martineau bt_cb(skb)->control.retries = 0; 19950a708f8fSGustavo F. Padovan return skb; 19960a708f8fSGustavo F. Padovan } 19970a708f8fSGustavo F. Padovan 199894122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan, 199994122bbeSMat Martineau struct sk_buff_head *seg_queue, 200094122bbeSMat Martineau struct msghdr *msg, size_t len) 20010a708f8fSGustavo F. Padovan { 20020a708f8fSGustavo F. Padovan struct sk_buff *skb; 200394122bbeSMat Martineau u16 sdu_len; 200494122bbeSMat Martineau size_t pdu_len; 200594122bbeSMat Martineau int err = 0; 200694122bbeSMat Martineau u8 sar; 20070a708f8fSGustavo F. Padovan 200894122bbeSMat Martineau BT_DBG("chan %p, msg %p, len %d", chan, msg, (int)len); 20090a708f8fSGustavo F. Padovan 201094122bbeSMat Martineau /* It is critical that ERTM PDUs fit in a single HCI fragment, 201194122bbeSMat Martineau * so fragmented skbs are not used. The HCI layer's handling 201294122bbeSMat Martineau * of fragmented skbs is not compatible with ERTM's queueing. 201394122bbeSMat Martineau */ 201494122bbeSMat Martineau 201594122bbeSMat Martineau /* PDU size is derived from the HCI MTU */ 201694122bbeSMat Martineau pdu_len = chan->conn->mtu; 201794122bbeSMat Martineau 201894122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); 201994122bbeSMat Martineau 202094122bbeSMat Martineau /* Adjust for largest possible L2CAP overhead. */ 202194122bbeSMat Martineau pdu_len -= L2CAP_EXT_HDR_SIZE + L2CAP_FCS_SIZE; 202294122bbeSMat Martineau 202394122bbeSMat Martineau /* Remote device may have requested smaller PDUs */ 202494122bbeSMat Martineau pdu_len = min_t(size_t, pdu_len, chan->remote_mps); 202594122bbeSMat Martineau 202694122bbeSMat Martineau if (len <= pdu_len) { 202794122bbeSMat Martineau sar = L2CAP_SAR_UNSEGMENTED; 202894122bbeSMat Martineau sdu_len = 0; 202994122bbeSMat Martineau pdu_len = len; 203094122bbeSMat Martineau } else { 203194122bbeSMat Martineau sar = L2CAP_SAR_START; 203294122bbeSMat Martineau sdu_len = len; 203394122bbeSMat Martineau pdu_len -= L2CAP_SDULEN_SIZE; 203494122bbeSMat Martineau } 20350a708f8fSGustavo F. Padovan 20360a708f8fSGustavo F. Padovan while (len > 0) { 203794122bbeSMat Martineau skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len); 20380a708f8fSGustavo F. Padovan 20390a708f8fSGustavo F. Padovan if (IS_ERR(skb)) { 204094122bbeSMat Martineau __skb_queue_purge(seg_queue); 20410a708f8fSGustavo F. Padovan return PTR_ERR(skb); 20420a708f8fSGustavo F. Padovan } 20430a708f8fSGustavo F. Padovan 204494122bbeSMat Martineau bt_cb(skb)->control.sar = sar; 204594122bbeSMat Martineau __skb_queue_tail(seg_queue, skb); 20460a708f8fSGustavo F. Padovan 204794122bbeSMat Martineau len -= pdu_len; 204894122bbeSMat Martineau if (sdu_len) { 204994122bbeSMat Martineau sdu_len = 0; 205094122bbeSMat Martineau pdu_len += L2CAP_SDULEN_SIZE; 205194122bbeSMat Martineau } 205294122bbeSMat Martineau 205394122bbeSMat Martineau if (len <= pdu_len) { 205494122bbeSMat Martineau sar = L2CAP_SAR_END; 205594122bbeSMat Martineau pdu_len = len; 205694122bbeSMat Martineau } else { 205794122bbeSMat Martineau sar = L2CAP_SAR_CONTINUE; 205894122bbeSMat Martineau } 205994122bbeSMat Martineau } 206094122bbeSMat Martineau 206194122bbeSMat Martineau return err; 20620a708f8fSGustavo F. Padovan } 20630a708f8fSGustavo F. Padovan 20645e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, 20655e59b791SLuiz Augusto von Dentz u32 priority) 20669a91a04aSGustavo F. Padovan { 20679a91a04aSGustavo F. Padovan struct sk_buff *skb; 20689a91a04aSGustavo F. Padovan int err; 206994122bbeSMat Martineau struct sk_buff_head seg_queue; 20709a91a04aSGustavo F. Padovan 20719a91a04aSGustavo F. Padovan /* Connectionless channel */ 2072715ec005SGustavo F. Padovan if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { 20735e59b791SLuiz Augusto von Dentz skb = l2cap_create_connless_pdu(chan, msg, len, priority); 20749a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 20759a91a04aSGustavo F. Padovan return PTR_ERR(skb); 20769a91a04aSGustavo F. Padovan 20779a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 20789a91a04aSGustavo F. Padovan return len; 20799a91a04aSGustavo F. Padovan } 20809a91a04aSGustavo F. Padovan 20819a91a04aSGustavo F. Padovan switch (chan->mode) { 20829a91a04aSGustavo F. Padovan case L2CAP_MODE_BASIC: 20839a91a04aSGustavo F. Padovan /* Check outgoing MTU */ 20849a91a04aSGustavo F. Padovan if (len > chan->omtu) 20859a91a04aSGustavo F. Padovan return -EMSGSIZE; 20869a91a04aSGustavo F. Padovan 20879a91a04aSGustavo F. Padovan /* Create a basic PDU */ 20885e59b791SLuiz Augusto von Dentz skb = l2cap_create_basic_pdu(chan, msg, len, priority); 20899a91a04aSGustavo F. Padovan if (IS_ERR(skb)) 20909a91a04aSGustavo F. Padovan return PTR_ERR(skb); 20919a91a04aSGustavo F. Padovan 20929a91a04aSGustavo F. Padovan l2cap_do_send(chan, skb); 20939a91a04aSGustavo F. Padovan err = len; 20949a91a04aSGustavo F. Padovan break; 20959a91a04aSGustavo F. Padovan 20969a91a04aSGustavo F. Padovan case L2CAP_MODE_ERTM: 20979a91a04aSGustavo F. Padovan case L2CAP_MODE_STREAMING: 209894122bbeSMat Martineau /* Check outgoing MTU */ 209994122bbeSMat Martineau if (len > chan->omtu) { 210094122bbeSMat Martineau err = -EMSGSIZE; 21019a91a04aSGustavo F. Padovan break; 21029a91a04aSGustavo F. Padovan } 21039a91a04aSGustavo F. Padovan 210494122bbeSMat Martineau __skb_queue_head_init(&seg_queue); 210594122bbeSMat Martineau 210694122bbeSMat Martineau /* Do segmentation before calling in to the state machine, 210794122bbeSMat Martineau * since it's possible to block while waiting for memory 210894122bbeSMat Martineau * allocation. 210994122bbeSMat Martineau */ 211094122bbeSMat Martineau err = l2cap_segment_sdu(chan, &seg_queue, msg, len); 211194122bbeSMat Martineau 211294122bbeSMat Martineau /* The channel could have been closed while segmenting, 211394122bbeSMat Martineau * check that it is still connected. 211494122bbeSMat Martineau */ 211594122bbeSMat Martineau if (chan->state != BT_CONNECTED) { 211694122bbeSMat Martineau __skb_queue_purge(&seg_queue); 211794122bbeSMat Martineau err = -ENOTCONN; 21189a91a04aSGustavo F. Padovan } 21199a91a04aSGustavo F. Padovan 212094122bbeSMat Martineau if (err) 212194122bbeSMat Martineau break; 212294122bbeSMat Martineau 2123577cfaebSMat Martineau if (chan->mode == L2CAP_MODE_ERTM && chan->tx_send_head == NULL) 2124577cfaebSMat Martineau chan->tx_send_head = seg_queue.next; 212594122bbeSMat Martineau skb_queue_splice_tail_init(&seg_queue, &chan->tx_q); 2126577cfaebSMat Martineau 212794122bbeSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) 21289a91a04aSGustavo F. Padovan err = l2cap_ertm_send(chan); 212994122bbeSMat Martineau else 213094122bbeSMat Martineau l2cap_streaming_send(chan); 213194122bbeSMat Martineau 21329a91a04aSGustavo F. Padovan if (err >= 0) 21339a91a04aSGustavo F. Padovan err = len; 21349a91a04aSGustavo F. Padovan 213594122bbeSMat Martineau /* If the skbs were not queued for sending, they'll still be in 213694122bbeSMat Martineau * seg_queue and need to be purged. 213794122bbeSMat Martineau */ 213894122bbeSMat Martineau __skb_queue_purge(&seg_queue); 21399a91a04aSGustavo F. Padovan break; 21409a91a04aSGustavo F. Padovan 21419a91a04aSGustavo F. Padovan default: 21429a91a04aSGustavo F. Padovan BT_DBG("bad state %1.1x", chan->mode); 21439a91a04aSGustavo F. Padovan err = -EBADFD; 21449a91a04aSGustavo F. Padovan } 21459a91a04aSGustavo F. Padovan 21469a91a04aSGustavo F. Padovan return err; 21479a91a04aSGustavo F. Padovan } 21489a91a04aSGustavo F. Padovan 21490a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */ 21500a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 21510a708f8fSGustavo F. Padovan { 21520a708f8fSGustavo F. Padovan struct sk_buff *nskb; 215348454079SGustavo F. Padovan struct l2cap_chan *chan; 21540a708f8fSGustavo F. Padovan 21550a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 21560a708f8fSGustavo F. Padovan 21573df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 21583d57dc68SGustavo F. Padovan 21593df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 216048454079SGustavo F. Padovan struct sock *sk = chan->sk; 2161715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_RAW) 21620a708f8fSGustavo F. Padovan continue; 21630a708f8fSGustavo F. Padovan 21640a708f8fSGustavo F. Padovan /* Don't send frame to the socket it came from */ 21650a708f8fSGustavo F. Padovan if (skb->sk == sk) 21660a708f8fSGustavo F. Padovan continue; 21670a708f8fSGustavo F. Padovan nskb = skb_clone(skb, GFP_ATOMIC); 21680a708f8fSGustavo F. Padovan if (!nskb) 21690a708f8fSGustavo F. Padovan continue; 21700a708f8fSGustavo F. Padovan 217123070494SGustavo F. Padovan if (chan->ops->recv(chan->data, nskb)) 21720a708f8fSGustavo F. Padovan kfree_skb(nskb); 21730a708f8fSGustavo F. Padovan } 21743d57dc68SGustavo F. Padovan 21753df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 21760a708f8fSGustavo F. Padovan } 21770a708f8fSGustavo F. Padovan 21780a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */ 21790a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 21800a708f8fSGustavo F. Padovan u8 code, u8 ident, u16 dlen, void *data) 21810a708f8fSGustavo F. Padovan { 21820a708f8fSGustavo F. Padovan struct sk_buff *skb, **frag; 21830a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr *cmd; 21840a708f8fSGustavo F. Padovan struct l2cap_hdr *lh; 21850a708f8fSGustavo F. Padovan int len, count; 21860a708f8fSGustavo F. Padovan 21870a708f8fSGustavo F. Padovan BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d", 21880a708f8fSGustavo F. Padovan conn, code, ident, dlen); 21890a708f8fSGustavo F. Padovan 21900a708f8fSGustavo F. Padovan len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; 21910a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 21920a708f8fSGustavo F. Padovan 21930a708f8fSGustavo F. Padovan skb = bt_skb_alloc(count, GFP_ATOMIC); 21940a708f8fSGustavo F. Padovan if (!skb) 21950a708f8fSGustavo F. Padovan return NULL; 21960a708f8fSGustavo F. Padovan 21970a708f8fSGustavo F. Padovan lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 21980a708f8fSGustavo F. Padovan lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); 21993300d9a9SClaudio Takahasi 22003300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 22013300d9a9SClaudio Takahasi lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING); 22023300d9a9SClaudio Takahasi else 22030a708f8fSGustavo F. Padovan lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING); 22040a708f8fSGustavo F. Padovan 22050a708f8fSGustavo F. Padovan cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); 22060a708f8fSGustavo F. Padovan cmd->code = code; 22070a708f8fSGustavo F. Padovan cmd->ident = ident; 22080a708f8fSGustavo F. Padovan cmd->len = cpu_to_le16(dlen); 22090a708f8fSGustavo F. Padovan 22100a708f8fSGustavo F. Padovan if (dlen) { 22110a708f8fSGustavo F. Padovan count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE; 22120a708f8fSGustavo F. Padovan memcpy(skb_put(skb, count), data, count); 22130a708f8fSGustavo F. Padovan data += count; 22140a708f8fSGustavo F. Padovan } 22150a708f8fSGustavo F. Padovan 22160a708f8fSGustavo F. Padovan len -= skb->len; 22170a708f8fSGustavo F. Padovan 22180a708f8fSGustavo F. Padovan /* Continuation fragments (no L2CAP header) */ 22190a708f8fSGustavo F. Padovan frag = &skb_shinfo(skb)->frag_list; 22200a708f8fSGustavo F. Padovan while (len) { 22210a708f8fSGustavo F. Padovan count = min_t(unsigned int, conn->mtu, len); 22220a708f8fSGustavo F. Padovan 22230a708f8fSGustavo F. Padovan *frag = bt_skb_alloc(count, GFP_ATOMIC); 22240a708f8fSGustavo F. Padovan if (!*frag) 22250a708f8fSGustavo F. Padovan goto fail; 22260a708f8fSGustavo F. Padovan 22270a708f8fSGustavo F. Padovan memcpy(skb_put(*frag, count), data, count); 22280a708f8fSGustavo F. Padovan 22290a708f8fSGustavo F. Padovan len -= count; 22300a708f8fSGustavo F. Padovan data += count; 22310a708f8fSGustavo F. Padovan 22320a708f8fSGustavo F. Padovan frag = &(*frag)->next; 22330a708f8fSGustavo F. Padovan } 22340a708f8fSGustavo F. Padovan 22350a708f8fSGustavo F. Padovan return skb; 22360a708f8fSGustavo F. Padovan 22370a708f8fSGustavo F. Padovan fail: 22380a708f8fSGustavo F. Padovan kfree_skb(skb); 22390a708f8fSGustavo F. Padovan return NULL; 22400a708f8fSGustavo F. Padovan } 22410a708f8fSGustavo F. Padovan 22420a708f8fSGustavo F. Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val) 22430a708f8fSGustavo F. Padovan { 22440a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 22450a708f8fSGustavo F. Padovan int len; 22460a708f8fSGustavo F. Padovan 22470a708f8fSGustavo F. Padovan len = L2CAP_CONF_OPT_SIZE + opt->len; 22480a708f8fSGustavo F. Padovan *ptr += len; 22490a708f8fSGustavo F. Padovan 22500a708f8fSGustavo F. Padovan *type = opt->type; 22510a708f8fSGustavo F. Padovan *olen = opt->len; 22520a708f8fSGustavo F. Padovan 22530a708f8fSGustavo F. Padovan switch (opt->len) { 22540a708f8fSGustavo F. Padovan case 1: 22550a708f8fSGustavo F. Padovan *val = *((u8 *) opt->val); 22560a708f8fSGustavo F. Padovan break; 22570a708f8fSGustavo F. Padovan 22580a708f8fSGustavo F. Padovan case 2: 22590a708f8fSGustavo F. Padovan *val = get_unaligned_le16(opt->val); 22600a708f8fSGustavo F. Padovan break; 22610a708f8fSGustavo F. Padovan 22620a708f8fSGustavo F. Padovan case 4: 22630a708f8fSGustavo F. Padovan *val = get_unaligned_le32(opt->val); 22640a708f8fSGustavo F. Padovan break; 22650a708f8fSGustavo F. Padovan 22660a708f8fSGustavo F. Padovan default: 22670a708f8fSGustavo F. Padovan *val = (unsigned long) opt->val; 22680a708f8fSGustavo F. Padovan break; 22690a708f8fSGustavo F. Padovan } 22700a708f8fSGustavo F. Padovan 22710a708f8fSGustavo F. Padovan BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val); 22720a708f8fSGustavo F. Padovan return len; 22730a708f8fSGustavo F. Padovan } 22740a708f8fSGustavo F. Padovan 22750a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) 22760a708f8fSGustavo F. Padovan { 22770a708f8fSGustavo F. Padovan struct l2cap_conf_opt *opt = *ptr; 22780a708f8fSGustavo F. Padovan 22790a708f8fSGustavo F. Padovan BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val); 22800a708f8fSGustavo F. Padovan 22810a708f8fSGustavo F. Padovan opt->type = type; 22820a708f8fSGustavo F. Padovan opt->len = len; 22830a708f8fSGustavo F. Padovan 22840a708f8fSGustavo F. Padovan switch (len) { 22850a708f8fSGustavo F. Padovan case 1: 22860a708f8fSGustavo F. Padovan *((u8 *) opt->val) = val; 22870a708f8fSGustavo F. Padovan break; 22880a708f8fSGustavo F. Padovan 22890a708f8fSGustavo F. Padovan case 2: 22900a708f8fSGustavo F. Padovan put_unaligned_le16(val, opt->val); 22910a708f8fSGustavo F. Padovan break; 22920a708f8fSGustavo F. Padovan 22930a708f8fSGustavo F. Padovan case 4: 22940a708f8fSGustavo F. Padovan put_unaligned_le32(val, opt->val); 22950a708f8fSGustavo F. Padovan break; 22960a708f8fSGustavo F. Padovan 22970a708f8fSGustavo F. Padovan default: 22980a708f8fSGustavo F. Padovan memcpy(opt->val, (void *) val, len); 22990a708f8fSGustavo F. Padovan break; 23000a708f8fSGustavo F. Padovan } 23010a708f8fSGustavo F. Padovan 23020a708f8fSGustavo F. Padovan *ptr += L2CAP_CONF_OPT_SIZE + len; 23030a708f8fSGustavo F. Padovan } 23040a708f8fSGustavo F. Padovan 2305f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) 2306f89cef09SAndrei Emeltchenko { 2307f89cef09SAndrei Emeltchenko struct l2cap_conf_efs efs; 2308f89cef09SAndrei Emeltchenko 2309f89cef09SAndrei Emeltchenko switch (chan->mode) { 2310f89cef09SAndrei Emeltchenko case L2CAP_MODE_ERTM: 2311f89cef09SAndrei Emeltchenko efs.id = chan->local_id; 2312f89cef09SAndrei Emeltchenko efs.stype = chan->local_stype; 2313f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 2314f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 2315f89cef09SAndrei Emeltchenko efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); 2316f89cef09SAndrei Emeltchenko efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO); 2317f89cef09SAndrei Emeltchenko break; 2318f89cef09SAndrei Emeltchenko 2319f89cef09SAndrei Emeltchenko case L2CAP_MODE_STREAMING: 2320f89cef09SAndrei Emeltchenko efs.id = 1; 2321f89cef09SAndrei Emeltchenko efs.stype = L2CAP_SERV_BESTEFFORT; 2322f89cef09SAndrei Emeltchenko efs.msdu = cpu_to_le16(chan->local_msdu); 2323f89cef09SAndrei Emeltchenko efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); 2324f89cef09SAndrei Emeltchenko efs.acc_lat = 0; 2325f89cef09SAndrei Emeltchenko efs.flush_to = 0; 2326f89cef09SAndrei Emeltchenko break; 2327f89cef09SAndrei Emeltchenko 2328f89cef09SAndrei Emeltchenko default: 2329f89cef09SAndrei Emeltchenko return; 2330f89cef09SAndrei Emeltchenko } 2331f89cef09SAndrei Emeltchenko 2332f89cef09SAndrei Emeltchenko l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), 2333f89cef09SAndrei Emeltchenko (unsigned long) &efs); 2334f89cef09SAndrei Emeltchenko } 2335f89cef09SAndrei Emeltchenko 2336721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work) 23370a708f8fSGustavo F. Padovan { 2338721c4181SGustavo F. Padovan struct l2cap_chan *chan = container_of(work, struct l2cap_chan, 2339721c4181SGustavo F. Padovan ack_timer.work); 23400a708f8fSGustavo F. Padovan 23412fb9b3d4SGustavo F. Padovan BT_DBG("chan %p", chan); 23422fb9b3d4SGustavo F. Padovan 23436be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 23446be36555SAndrei Emeltchenko 2345b17e73bbSSzymon Janc __l2cap_send_ack(chan); 23466be36555SAndrei Emeltchenko 23476be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 234809bfb2eeSSzymon Janc 234909bfb2eeSSzymon Janc l2cap_chan_put(chan); 23500a708f8fSGustavo F. Padovan } 23510a708f8fSGustavo F. Padovan 23523c588192SMat Martineau static inline int l2cap_ertm_init(struct l2cap_chan *chan) 23530a708f8fSGustavo F. Padovan { 23543c588192SMat Martineau int err; 23553c588192SMat Martineau 2356105bdf9eSMat Martineau chan->next_tx_seq = 0; 2357105bdf9eSMat Martineau chan->expected_tx_seq = 0; 235842e5c802SGustavo F. Padovan chan->expected_ack_seq = 0; 23596a026610SGustavo F. Padovan chan->unacked_frames = 0; 236042e5c802SGustavo F. Padovan chan->buffer_seq = 0; 23616a026610SGustavo F. Padovan chan->num_acked = 0; 23626a026610SGustavo F. Padovan chan->frames_sent = 0; 2363105bdf9eSMat Martineau chan->last_acked_seq = 0; 2364105bdf9eSMat Martineau chan->sdu = NULL; 2365105bdf9eSMat Martineau chan->sdu_last_frag = NULL; 2366105bdf9eSMat Martineau chan->sdu_len = 0; 2367105bdf9eSMat Martineau 2368d34c34fbSMat Martineau skb_queue_head_init(&chan->tx_q); 2369d34c34fbSMat Martineau 2370105bdf9eSMat Martineau if (chan->mode != L2CAP_MODE_ERTM) 2371105bdf9eSMat Martineau return 0; 2372105bdf9eSMat Martineau 2373105bdf9eSMat Martineau chan->rx_state = L2CAP_RX_STATE_RECV; 2374105bdf9eSMat Martineau chan->tx_state = L2CAP_TX_STATE_XMIT; 23750a708f8fSGustavo F. Padovan 2376721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout); 2377721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout); 2378721c4181SGustavo F. Padovan INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout); 23790a708f8fSGustavo F. Padovan 2380f1c6775bSGustavo F. Padovan skb_queue_head_init(&chan->srej_q); 23810a708f8fSGustavo F. Padovan 238239d5a3eeSGustavo F. Padovan INIT_LIST_HEAD(&chan->srej_l); 23833c588192SMat Martineau err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win); 23843c588192SMat Martineau if (err < 0) 23853c588192SMat Martineau return err; 23863c588192SMat Martineau 23879dc9affcSMat Martineau err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win); 23889dc9affcSMat Martineau if (err < 0) 23899dc9affcSMat Martineau l2cap_seq_list_free(&chan->srej_list); 23909dc9affcSMat Martineau 23919dc9affcSMat Martineau return err; 23920a708f8fSGustavo F. Padovan } 23930a708f8fSGustavo F. Padovan 23940a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) 23950a708f8fSGustavo F. Padovan { 23960a708f8fSGustavo F. Padovan switch (mode) { 23970a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 23980a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 23990a708f8fSGustavo F. Padovan if (l2cap_mode_supported(mode, remote_feat_mask)) 24000a708f8fSGustavo F. Padovan return mode; 24010a708f8fSGustavo F. Padovan /* fall through */ 24020a708f8fSGustavo F. Padovan default: 24030a708f8fSGustavo F. Padovan return L2CAP_MODE_BASIC; 24040a708f8fSGustavo F. Padovan } 24050a708f8fSGustavo F. Padovan } 24060a708f8fSGustavo F. Padovan 24076327eb98SAndrei Emeltchenko static inline bool __l2cap_ews_supported(struct l2cap_chan *chan) 24086327eb98SAndrei Emeltchenko { 24096327eb98SAndrei Emeltchenko return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW; 24106327eb98SAndrei Emeltchenko } 24116327eb98SAndrei Emeltchenko 2412f89cef09SAndrei Emeltchenko static inline bool __l2cap_efs_supported(struct l2cap_chan *chan) 2413f89cef09SAndrei Emeltchenko { 2414f89cef09SAndrei Emeltchenko return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW; 2415f89cef09SAndrei Emeltchenko } 2416f89cef09SAndrei Emeltchenko 24176327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan) 24186327eb98SAndrei Emeltchenko { 24196327eb98SAndrei Emeltchenko if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && 2420836be934SAndrei Emeltchenko __l2cap_ews_supported(chan)) { 24216327eb98SAndrei Emeltchenko /* use extended control field */ 24226327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 2423836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 2424836be934SAndrei Emeltchenko } else { 24256327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, chan->tx_win, 24266327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 2427836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; 2428836be934SAndrei Emeltchenko } 24296327eb98SAndrei Emeltchenko } 24306327eb98SAndrei Emeltchenko 2431710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) 24320a708f8fSGustavo F. Padovan { 24330a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 24340c1bc5c6SGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = chan->mode }; 24350a708f8fSGustavo F. Padovan void *ptr = req->data; 2436c8f79162SAndrei Emeltchenko u16 size; 24370a708f8fSGustavo F. Padovan 243849208c9cSGustavo F. Padovan BT_DBG("chan %p", chan); 24390a708f8fSGustavo F. Padovan 244073ffa904SGustavo F. Padovan if (chan->num_conf_req || chan->num_conf_rsp) 24410a708f8fSGustavo F. Padovan goto done; 24420a708f8fSGustavo F. Padovan 24430c1bc5c6SGustavo F. Padovan switch (chan->mode) { 24440a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 24450a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 2446c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) 24470a708f8fSGustavo F. Padovan break; 24480a708f8fSGustavo F. Padovan 2449f89cef09SAndrei Emeltchenko if (__l2cap_efs_supported(chan)) 2450f89cef09SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 2451f89cef09SAndrei Emeltchenko 24520a708f8fSGustavo F. Padovan /* fall through */ 24530a708f8fSGustavo F. Padovan default: 24548c1d787bSGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); 24550a708f8fSGustavo F. Padovan break; 24560a708f8fSGustavo F. Padovan } 24570a708f8fSGustavo F. Padovan 24580a708f8fSGustavo F. Padovan done: 24590c1bc5c6SGustavo F. Padovan if (chan->imtu != L2CAP_DEFAULT_MTU) 24600c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 24610a708f8fSGustavo F. Padovan 24620c1bc5c6SGustavo F. Padovan switch (chan->mode) { 24630a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 24648c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && 24658c1d787bSGustavo F. Padovan !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) 24660a708f8fSGustavo F. Padovan break; 24670a708f8fSGustavo F. Padovan 24680a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_BASIC; 24690a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 24700a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 24710a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 24720a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 24730a708f8fSGustavo F. Padovan rfc.max_pdu_size = 0; 24740a708f8fSGustavo F. Padovan 24750a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 24760a708f8fSGustavo F. Padovan (unsigned long) &rfc); 24770a708f8fSGustavo F. Padovan break; 24780a708f8fSGustavo F. Padovan 24790a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 24800a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_ERTM; 248147d1ec61SGustavo F. Padovan rfc.max_transmit = chan->max_tx; 24820a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 24830a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 2484c8f79162SAndrei Emeltchenko 2485c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 2486c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2487c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2488c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2489c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 24900a708f8fSGustavo F. Padovan 24916327eb98SAndrei Emeltchenko l2cap_txwin_setup(chan); 24926327eb98SAndrei Emeltchenko 24936327eb98SAndrei Emeltchenko rfc.txwin_size = min_t(u16, chan->tx_win, 24946327eb98SAndrei Emeltchenko L2CAP_DEFAULT_TX_WINDOW); 24950a708f8fSGustavo F. Padovan 24960a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 24970a708f8fSGustavo F. Padovan (unsigned long) &rfc); 24980a708f8fSGustavo F. Padovan 2499f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 2500f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 2501f89cef09SAndrei Emeltchenko 25028c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) 25030a708f8fSGustavo F. Padovan break; 25040a708f8fSGustavo F. Padovan 250547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 2506c1360a1cSGustavo F. Padovan test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { 250747d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 250847d1ec61SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); 25090a708f8fSGustavo F. Padovan } 25106327eb98SAndrei Emeltchenko 25116327eb98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 25126327eb98SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 25136327eb98SAndrei Emeltchenko chan->tx_win); 25140a708f8fSGustavo F. Padovan break; 25150a708f8fSGustavo F. Padovan 25160a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 25170a708f8fSGustavo F. Padovan rfc.mode = L2CAP_MODE_STREAMING; 25180a708f8fSGustavo F. Padovan rfc.txwin_size = 0; 25190a708f8fSGustavo F. Padovan rfc.max_transmit = 0; 25200a708f8fSGustavo F. Padovan rfc.retrans_timeout = 0; 25210a708f8fSGustavo F. Padovan rfc.monitor_timeout = 0; 2522c8f79162SAndrei Emeltchenko 2523c8f79162SAndrei Emeltchenko size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - 2524c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2525c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2526c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2527c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 25280a708f8fSGustavo F. Padovan 25290a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), 25300a708f8fSGustavo F. Padovan (unsigned long) &rfc); 25310a708f8fSGustavo F. Padovan 2532f89cef09SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) 2533f89cef09SAndrei Emeltchenko l2cap_add_opt_efs(&ptr, chan); 2534f89cef09SAndrei Emeltchenko 25358c1d787bSGustavo F. Padovan if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) 25360a708f8fSGustavo F. Padovan break; 25370a708f8fSGustavo F. Padovan 253847d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_NONE || 2539c1360a1cSGustavo F. Padovan test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { 254047d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 254147d1ec61SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); 25420a708f8fSGustavo F. Padovan } 25430a708f8fSGustavo F. Padovan break; 25440a708f8fSGustavo F. Padovan } 25450a708f8fSGustavo F. Padovan 2546fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 25470a708f8fSGustavo F. Padovan req->flags = cpu_to_le16(0); 25480a708f8fSGustavo F. Padovan 25490a708f8fSGustavo F. Padovan return ptr - data; 25500a708f8fSGustavo F. Padovan } 25510a708f8fSGustavo F. Padovan 255273ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) 25530a708f8fSGustavo F. Padovan { 25540a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 25550a708f8fSGustavo F. Padovan void *ptr = rsp->data; 255673ffa904SGustavo F. Padovan void *req = chan->conf_req; 255773ffa904SGustavo F. Padovan int len = chan->conf_len; 25580a708f8fSGustavo F. Padovan int type, hint, olen; 25590a708f8fSGustavo F. Padovan unsigned long val; 25600a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 256142dceae2SAndrei Emeltchenko struct l2cap_conf_efs efs; 256242dceae2SAndrei Emeltchenko u8 remote_efs = 0; 25630a708f8fSGustavo F. Padovan u16 mtu = L2CAP_DEFAULT_MTU; 25640a708f8fSGustavo F. Padovan u16 result = L2CAP_CONF_SUCCESS; 2565c8f79162SAndrei Emeltchenko u16 size; 25660a708f8fSGustavo F. Padovan 256773ffa904SGustavo F. Padovan BT_DBG("chan %p", chan); 25680a708f8fSGustavo F. Padovan 25690a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 25700a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&req, &type, &olen, &val); 25710a708f8fSGustavo F. Padovan 25720a708f8fSGustavo F. Padovan hint = type & L2CAP_CONF_HINT; 25730a708f8fSGustavo F. Padovan type &= L2CAP_CONF_MASK; 25740a708f8fSGustavo F. Padovan 25750a708f8fSGustavo F. Padovan switch (type) { 25760a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 25770a708f8fSGustavo F. Padovan mtu = val; 25780a708f8fSGustavo F. Padovan break; 25790a708f8fSGustavo F. Padovan 25800a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 25810c1bc5c6SGustavo F. Padovan chan->flush_to = val; 25820a708f8fSGustavo F. Padovan break; 25830a708f8fSGustavo F. Padovan 25840a708f8fSGustavo F. Padovan case L2CAP_CONF_QOS: 25850a708f8fSGustavo F. Padovan break; 25860a708f8fSGustavo F. Padovan 25870a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 25880a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 25890a708f8fSGustavo F. Padovan memcpy(&rfc, (void *) val, olen); 25900a708f8fSGustavo F. Padovan break; 25910a708f8fSGustavo F. Padovan 25920a708f8fSGustavo F. Padovan case L2CAP_CONF_FCS: 25930a708f8fSGustavo F. Padovan if (val == L2CAP_FCS_NONE) 2594c1360a1cSGustavo F. Padovan set_bit(CONF_NO_FCS_RECV, &chan->conf_state); 259542dceae2SAndrei Emeltchenko break; 25960a708f8fSGustavo F. Padovan 259742dceae2SAndrei Emeltchenko case L2CAP_CONF_EFS: 259842dceae2SAndrei Emeltchenko remote_efs = 1; 259942dceae2SAndrei Emeltchenko if (olen == sizeof(efs)) 260042dceae2SAndrei Emeltchenko memcpy(&efs, (void *) val, olen); 26010a708f8fSGustavo F. Padovan break; 26020a708f8fSGustavo F. Padovan 26036327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 26046327eb98SAndrei Emeltchenko if (!enable_hs) 26056327eb98SAndrei Emeltchenko return -ECONNREFUSED; 26066327eb98SAndrei Emeltchenko 26076327eb98SAndrei Emeltchenko set_bit(FLAG_EXT_CTRL, &chan->flags); 26086327eb98SAndrei Emeltchenko set_bit(CONF_EWS_RECV, &chan->conf_state); 2609836be934SAndrei Emeltchenko chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; 26106327eb98SAndrei Emeltchenko chan->remote_tx_win = val; 26110a708f8fSGustavo F. Padovan break; 26120a708f8fSGustavo F. Padovan 26130a708f8fSGustavo F. Padovan default: 26140a708f8fSGustavo F. Padovan if (hint) 26150a708f8fSGustavo F. Padovan break; 26160a708f8fSGustavo F. Padovan 26170a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNKNOWN; 26180a708f8fSGustavo F. Padovan *((u8 *) ptr++) = type; 26190a708f8fSGustavo F. Padovan break; 26200a708f8fSGustavo F. Padovan } 26210a708f8fSGustavo F. Padovan } 26220a708f8fSGustavo F. Padovan 262373ffa904SGustavo F. Padovan if (chan->num_conf_rsp || chan->num_conf_req > 1) 26240a708f8fSGustavo F. Padovan goto done; 26250a708f8fSGustavo F. Padovan 26260c1bc5c6SGustavo F. Padovan switch (chan->mode) { 26270a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 26280a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 2629c1360a1cSGustavo F. Padovan if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { 26300c1bc5c6SGustavo F. Padovan chan->mode = l2cap_select_mode(rfc.mode, 26318c1d787bSGustavo F. Padovan chan->conn->feat_mask); 26320a708f8fSGustavo F. Padovan break; 26330a708f8fSGustavo F. Padovan } 26340a708f8fSGustavo F. Padovan 263542dceae2SAndrei Emeltchenko if (remote_efs) { 263642dceae2SAndrei Emeltchenko if (__l2cap_efs_supported(chan)) 263742dceae2SAndrei Emeltchenko set_bit(FLAG_EFS_ENABLE, &chan->flags); 263842dceae2SAndrei Emeltchenko else 263942dceae2SAndrei Emeltchenko return -ECONNREFUSED; 264042dceae2SAndrei Emeltchenko } 264142dceae2SAndrei Emeltchenko 26420c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) 26430a708f8fSGustavo F. Padovan return -ECONNREFUSED; 26440a708f8fSGustavo F. Padovan 26450a708f8fSGustavo F. Padovan break; 26460a708f8fSGustavo F. Padovan } 26470a708f8fSGustavo F. Padovan 26480a708f8fSGustavo F. Padovan done: 26490c1bc5c6SGustavo F. Padovan if (chan->mode != rfc.mode) { 26500a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 26510c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 26520a708f8fSGustavo F. Padovan 265373ffa904SGustavo F. Padovan if (chan->num_conf_rsp == 1) 26540a708f8fSGustavo F. Padovan return -ECONNREFUSED; 26550a708f8fSGustavo F. Padovan 26560a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 26570a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 26580a708f8fSGustavo F. Padovan } 26590a708f8fSGustavo F. Padovan 26600a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) { 26610a708f8fSGustavo F. Padovan /* Configure output options and let the other side know 26620a708f8fSGustavo F. Padovan * which ones we don't like. */ 26630a708f8fSGustavo F. Padovan 26640a708f8fSGustavo F. Padovan if (mtu < L2CAP_DEFAULT_MIN_MTU) 26650a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 26660a708f8fSGustavo F. Padovan else { 26670c1bc5c6SGustavo F. Padovan chan->omtu = mtu; 2668c1360a1cSGustavo F. Padovan set_bit(CONF_MTU_DONE, &chan->conf_state); 26690a708f8fSGustavo F. Padovan } 26700c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); 26710a708f8fSGustavo F. Padovan 267242dceae2SAndrei Emeltchenko if (remote_efs) { 267342dceae2SAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 267442dceae2SAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 267542dceae2SAndrei Emeltchenko efs.stype != chan->local_stype) { 267642dceae2SAndrei Emeltchenko 267742dceae2SAndrei Emeltchenko result = L2CAP_CONF_UNACCEPT; 267842dceae2SAndrei Emeltchenko 267942dceae2SAndrei Emeltchenko if (chan->num_conf_req >= 1) 268042dceae2SAndrei Emeltchenko return -ECONNREFUSED; 268142dceae2SAndrei Emeltchenko 268242dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 268342dceae2SAndrei Emeltchenko sizeof(efs), 268442dceae2SAndrei Emeltchenko (unsigned long) &efs); 26850e8b207eSAndrei Emeltchenko } else { 26863e6b3b95SGustavo F. Padovan /* Send PENDING Conf Rsp */ 26870e8b207eSAndrei Emeltchenko result = L2CAP_CONF_PENDING; 26880e8b207eSAndrei Emeltchenko set_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 268942dceae2SAndrei Emeltchenko } 269042dceae2SAndrei Emeltchenko } 269142dceae2SAndrei Emeltchenko 26920a708f8fSGustavo F. Padovan switch (rfc.mode) { 26930a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 269447d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 2695c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 26960a708f8fSGustavo F. Padovan break; 26970a708f8fSGustavo F. Padovan 26980a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 26996327eb98SAndrei Emeltchenko if (!test_bit(CONF_EWS_RECV, &chan->conf_state)) 27002c03a7a4SGustavo F. Padovan chan->remote_tx_win = rfc.txwin_size; 27016327eb98SAndrei Emeltchenko else 27026327eb98SAndrei Emeltchenko rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; 27036327eb98SAndrei Emeltchenko 27042c03a7a4SGustavo F. Padovan chan->remote_max_tx = rfc.max_transmit; 27050a708f8fSGustavo F. Padovan 2706c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 2707c8f79162SAndrei Emeltchenko chan->conn->mtu - 2708c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2709c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2710c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2711c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 2712c8f79162SAndrei Emeltchenko chan->remote_mps = size; 27130a708f8fSGustavo F. Padovan 27140a708f8fSGustavo F. Padovan rfc.retrans_timeout = 27154fd21a88SAndrei Emeltchenko __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 27160a708f8fSGustavo F. Padovan rfc.monitor_timeout = 27174fd21a88SAndrei Emeltchenko __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 27180a708f8fSGustavo F. Padovan 2719c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 27200a708f8fSGustavo F. Padovan 27210a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 27220a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 27230a708f8fSGustavo F. Padovan 272442dceae2SAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 272542dceae2SAndrei Emeltchenko chan->remote_id = efs.id; 272642dceae2SAndrei Emeltchenko chan->remote_stype = efs.stype; 272742dceae2SAndrei Emeltchenko chan->remote_msdu = le16_to_cpu(efs.msdu); 272842dceae2SAndrei Emeltchenko chan->remote_flush_to = 272942dceae2SAndrei Emeltchenko le32_to_cpu(efs.flush_to); 273042dceae2SAndrei Emeltchenko chan->remote_acc_lat = 273142dceae2SAndrei Emeltchenko le32_to_cpu(efs.acc_lat); 273242dceae2SAndrei Emeltchenko chan->remote_sdu_itime = 273342dceae2SAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 273442dceae2SAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 273542dceae2SAndrei Emeltchenko sizeof(efs), (unsigned long) &efs); 273642dceae2SAndrei Emeltchenko } 27370a708f8fSGustavo F. Padovan break; 27380a708f8fSGustavo F. Padovan 27390a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 2740c8f79162SAndrei Emeltchenko size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), 2741c8f79162SAndrei Emeltchenko chan->conn->mtu - 2742c8f79162SAndrei Emeltchenko L2CAP_EXT_HDR_SIZE - 2743c8f79162SAndrei Emeltchenko L2CAP_SDULEN_SIZE - 2744c8f79162SAndrei Emeltchenko L2CAP_FCS_SIZE); 2745c8f79162SAndrei Emeltchenko rfc.max_pdu_size = cpu_to_le16(size); 2746c8f79162SAndrei Emeltchenko chan->remote_mps = size; 27470a708f8fSGustavo F. Padovan 2748c1360a1cSGustavo F. Padovan set_bit(CONF_MODE_DONE, &chan->conf_state); 27490a708f8fSGustavo F. Padovan 27500a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 27510a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 27520a708f8fSGustavo F. Padovan 27530a708f8fSGustavo F. Padovan break; 27540a708f8fSGustavo F. Padovan 27550a708f8fSGustavo F. Padovan default: 27560a708f8fSGustavo F. Padovan result = L2CAP_CONF_UNACCEPT; 27570a708f8fSGustavo F. Padovan 27580a708f8fSGustavo F. Padovan memset(&rfc, 0, sizeof(rfc)); 27590c1bc5c6SGustavo F. Padovan rfc.mode = chan->mode; 27600a708f8fSGustavo F. Padovan } 27610a708f8fSGustavo F. Padovan 27620a708f8fSGustavo F. Padovan if (result == L2CAP_CONF_SUCCESS) 2763c1360a1cSGustavo F. Padovan set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 27640a708f8fSGustavo F. Padovan } 2765fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 27660a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 27670a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(0x0000); 27680a708f8fSGustavo F. Padovan 27690a708f8fSGustavo F. Padovan return ptr - data; 27700a708f8fSGustavo F. Padovan } 27710a708f8fSGustavo F. Padovan 2772b4450035SGustavo F. Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result) 27730a708f8fSGustavo F. Padovan { 27740a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = data; 27750a708f8fSGustavo F. Padovan void *ptr = req->data; 27760a708f8fSGustavo F. Padovan int type, olen; 27770a708f8fSGustavo F. Padovan unsigned long val; 277836e999a8SMat Martineau struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 277966af7aafSAndrei Emeltchenko struct l2cap_conf_efs efs; 27800a708f8fSGustavo F. Padovan 2781fe4128e0SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); 27820a708f8fSGustavo F. Padovan 27830a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 27840a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 27850a708f8fSGustavo F. Padovan 27860a708f8fSGustavo F. Padovan switch (type) { 27870a708f8fSGustavo F. Padovan case L2CAP_CONF_MTU: 27880a708f8fSGustavo F. Padovan if (val < L2CAP_DEFAULT_MIN_MTU) { 27890a708f8fSGustavo F. Padovan *result = L2CAP_CONF_UNACCEPT; 27900c1bc5c6SGustavo F. Padovan chan->imtu = L2CAP_DEFAULT_MIN_MTU; 27910a708f8fSGustavo F. Padovan } else 27920c1bc5c6SGustavo F. Padovan chan->imtu = val; 27930c1bc5c6SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); 27940a708f8fSGustavo F. Padovan break; 27950a708f8fSGustavo F. Padovan 27960a708f8fSGustavo F. Padovan case L2CAP_CONF_FLUSH_TO: 27970c1bc5c6SGustavo F. Padovan chan->flush_to = val; 27980a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 27990c1bc5c6SGustavo F. Padovan 2, chan->flush_to); 28000a708f8fSGustavo F. Padovan break; 28010a708f8fSGustavo F. Padovan 28020a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 28030a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 28040a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 28050a708f8fSGustavo F. Padovan 2806c1360a1cSGustavo F. Padovan if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && 28070c1bc5c6SGustavo F. Padovan rfc.mode != chan->mode) 28080a708f8fSGustavo F. Padovan return -ECONNREFUSED; 28090a708f8fSGustavo F. Padovan 281047d1ec61SGustavo F. Padovan chan->fcs = 0; 28110a708f8fSGustavo F. Padovan 28120a708f8fSGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, 28130a708f8fSGustavo F. Padovan sizeof(rfc), (unsigned long) &rfc); 28140a708f8fSGustavo F. Padovan break; 28156327eb98SAndrei Emeltchenko 28166327eb98SAndrei Emeltchenko case L2CAP_CONF_EWS: 28176327eb98SAndrei Emeltchenko chan->tx_win = min_t(u16, val, 28186327eb98SAndrei Emeltchenko L2CAP_DEFAULT_EXT_WINDOW); 28193e6b3b95SGustavo F. Padovan l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, 28203e6b3b95SGustavo F. Padovan chan->tx_win); 28216327eb98SAndrei Emeltchenko break; 282266af7aafSAndrei Emeltchenko 282366af7aafSAndrei Emeltchenko case L2CAP_CONF_EFS: 282466af7aafSAndrei Emeltchenko if (olen == sizeof(efs)) 282566af7aafSAndrei Emeltchenko memcpy(&efs, (void *)val, olen); 282666af7aafSAndrei Emeltchenko 282766af7aafSAndrei Emeltchenko if (chan->local_stype != L2CAP_SERV_NOTRAFIC && 282866af7aafSAndrei Emeltchenko efs.stype != L2CAP_SERV_NOTRAFIC && 282966af7aafSAndrei Emeltchenko efs.stype != chan->local_stype) 283066af7aafSAndrei Emeltchenko return -ECONNREFUSED; 283166af7aafSAndrei Emeltchenko 283266af7aafSAndrei Emeltchenko l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, 283366af7aafSAndrei Emeltchenko sizeof(efs), (unsigned long) &efs); 283466af7aafSAndrei Emeltchenko break; 28350a708f8fSGustavo F. Padovan } 28360a708f8fSGustavo F. Padovan } 28370a708f8fSGustavo F. Padovan 28380c1bc5c6SGustavo F. Padovan if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) 28390a708f8fSGustavo F. Padovan return -ECONNREFUSED; 28400a708f8fSGustavo F. Padovan 28410c1bc5c6SGustavo F. Padovan chan->mode = rfc.mode; 28420a708f8fSGustavo F. Padovan 28430e8b207eSAndrei Emeltchenko if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) { 28440a708f8fSGustavo F. Padovan switch (rfc.mode) { 28450a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 284647d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 284747d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 284847d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 284966af7aafSAndrei Emeltchenko 285066af7aafSAndrei Emeltchenko if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { 285166af7aafSAndrei Emeltchenko chan->local_msdu = le16_to_cpu(efs.msdu); 285266af7aafSAndrei Emeltchenko chan->local_sdu_itime = 285366af7aafSAndrei Emeltchenko le32_to_cpu(efs.sdu_itime); 285466af7aafSAndrei Emeltchenko chan->local_acc_lat = le32_to_cpu(efs.acc_lat); 285566af7aafSAndrei Emeltchenko chan->local_flush_to = 285666af7aafSAndrei Emeltchenko le32_to_cpu(efs.flush_to); 285766af7aafSAndrei Emeltchenko } 28580a708f8fSGustavo F. Padovan break; 285966af7aafSAndrei Emeltchenko 28600a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 286147d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 28620a708f8fSGustavo F. Padovan } 28630a708f8fSGustavo F. Padovan } 28640a708f8fSGustavo F. Padovan 2865fe4128e0SGustavo F. Padovan req->dcid = cpu_to_le16(chan->dcid); 28660a708f8fSGustavo F. Padovan req->flags = cpu_to_le16(0x0000); 28670a708f8fSGustavo F. Padovan 28680a708f8fSGustavo F. Padovan return ptr - data; 28690a708f8fSGustavo F. Padovan } 28700a708f8fSGustavo F. Padovan 2871fe4128e0SGustavo F. Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags) 28720a708f8fSGustavo F. Padovan { 28730a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = data; 28740a708f8fSGustavo F. Padovan void *ptr = rsp->data; 28750a708f8fSGustavo F. Padovan 2876fe4128e0SGustavo F. Padovan BT_DBG("chan %p", chan); 28770a708f8fSGustavo F. Padovan 2878fe4128e0SGustavo F. Padovan rsp->scid = cpu_to_le16(chan->dcid); 28790a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(result); 28800a708f8fSGustavo F. Padovan rsp->flags = cpu_to_le16(flags); 28810a708f8fSGustavo F. Padovan 28820a708f8fSGustavo F. Padovan return ptr - data; 28830a708f8fSGustavo F. Padovan } 28840a708f8fSGustavo F. Padovan 28858c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) 2886710f9b0aSGustavo F. Padovan { 2887710f9b0aSGustavo F. Padovan struct l2cap_conn_rsp rsp; 28888c1d787bSGustavo F. Padovan struct l2cap_conn *conn = chan->conn; 2889710f9b0aSGustavo F. Padovan u8 buf[128]; 2890710f9b0aSGustavo F. Padovan 2891fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 2892fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 2893710f9b0aSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 2894710f9b0aSGustavo F. Padovan rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 2895710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, 2896710f9b0aSGustavo F. Padovan L2CAP_CONN_RSP, sizeof(rsp), &rsp); 2897710f9b0aSGustavo F. Padovan 2898c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 2899710f9b0aSGustavo F. Padovan return; 2900710f9b0aSGustavo F. Padovan 2901710f9b0aSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 2902710f9b0aSGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 2903710f9b0aSGustavo F. Padovan chan->num_conf_req++; 2904710f9b0aSGustavo F. Padovan } 2905710f9b0aSGustavo F. Padovan 290647d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) 29070a708f8fSGustavo F. Padovan { 29080a708f8fSGustavo F. Padovan int type, olen; 29090a708f8fSGustavo F. Padovan unsigned long val; 29100a708f8fSGustavo F. Padovan struct l2cap_conf_rfc rfc; 29110a708f8fSGustavo F. Padovan 291247d1ec61SGustavo F. Padovan BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); 29130a708f8fSGustavo F. Padovan 29140c1bc5c6SGustavo F. Padovan if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) 29150a708f8fSGustavo F. Padovan return; 29160a708f8fSGustavo F. Padovan 29170a708f8fSGustavo F. Padovan while (len >= L2CAP_CONF_OPT_SIZE) { 29180a708f8fSGustavo F. Padovan len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); 29190a708f8fSGustavo F. Padovan 29200a708f8fSGustavo F. Padovan switch (type) { 29210a708f8fSGustavo F. Padovan case L2CAP_CONF_RFC: 29220a708f8fSGustavo F. Padovan if (olen == sizeof(rfc)) 29230a708f8fSGustavo F. Padovan memcpy(&rfc, (void *)val, olen); 29240a708f8fSGustavo F. Padovan goto done; 29250a708f8fSGustavo F. Padovan } 29260a708f8fSGustavo F. Padovan } 29270a708f8fSGustavo F. Padovan 292836e999a8SMat Martineau /* Use sane default values in case a misbehaving remote device 292936e999a8SMat Martineau * did not send an RFC option. 293036e999a8SMat Martineau */ 293136e999a8SMat Martineau rfc.mode = chan->mode; 293236e999a8SMat Martineau rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); 293336e999a8SMat Martineau rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); 293436e999a8SMat Martineau rfc.max_pdu_size = cpu_to_le16(chan->imtu); 293536e999a8SMat Martineau 293636e999a8SMat Martineau BT_ERR("Expected RFC option was not found, using defaults"); 293736e999a8SMat Martineau 29380a708f8fSGustavo F. Padovan done: 29390a708f8fSGustavo F. Padovan switch (rfc.mode) { 29400a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 294147d1ec61SGustavo F. Padovan chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); 294247d1ec61SGustavo F. Padovan chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); 294347d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 29440a708f8fSGustavo F. Padovan break; 29450a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 294647d1ec61SGustavo F. Padovan chan->mps = le16_to_cpu(rfc.max_pdu_size); 29470a708f8fSGustavo F. Padovan } 29480a708f8fSGustavo F. Padovan } 29490a708f8fSGustavo F. Padovan 29500a708f8fSGustavo F. Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 29510a708f8fSGustavo F. Padovan { 2952e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; 29530a708f8fSGustavo F. Padovan 2954e2fd318eSIlia Kolomisnky if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) 29550a708f8fSGustavo F. Padovan return 0; 29560a708f8fSGustavo F. Padovan 29570a708f8fSGustavo F. Padovan if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && 29580a708f8fSGustavo F. Padovan cmd->ident == conn->info_ident) { 295917cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 29600a708f8fSGustavo F. Padovan 29610a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 29620a708f8fSGustavo F. Padovan conn->info_ident = 0; 29630a708f8fSGustavo F. Padovan 29640a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 29650a708f8fSGustavo F. Padovan } 29660a708f8fSGustavo F. Padovan 29670a708f8fSGustavo F. Padovan return 0; 29680a708f8fSGustavo F. Padovan } 29690a708f8fSGustavo F. Padovan 29700a708f8fSGustavo F. Padovan static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 29710a708f8fSGustavo F. Padovan { 29720a708f8fSGustavo F. Padovan struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 29730a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 297423691d75SGustavo F. Padovan struct l2cap_chan *chan = NULL, *pchan; 29750a708f8fSGustavo F. Padovan struct sock *parent, *sk = NULL; 29760a708f8fSGustavo F. Padovan int result, status = L2CAP_CS_NO_INFO; 29770a708f8fSGustavo F. Padovan 29780a708f8fSGustavo F. Padovan u16 dcid = 0, scid = __le16_to_cpu(req->scid); 29790a708f8fSGustavo F. Padovan __le16 psm = req->psm; 29800a708f8fSGustavo F. Padovan 2981097db76cSAndrei Emeltchenko BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); 29820a708f8fSGustavo F. Padovan 29830a708f8fSGustavo F. Padovan /* Check if we have socket listening on psm */ 2984c2287681SIdo Yariv pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst); 298523691d75SGustavo F. Padovan if (!pchan) { 29860a708f8fSGustavo F. Padovan result = L2CAP_CR_BAD_PSM; 29870a708f8fSGustavo F. Padovan goto sendresp; 29880a708f8fSGustavo F. Padovan } 29890a708f8fSGustavo F. Padovan 299023691d75SGustavo F. Padovan parent = pchan->sk; 299123691d75SGustavo F. Padovan 29923df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 2993aa2ac881SGustavo F. Padovan lock_sock(parent); 29940a708f8fSGustavo F. Padovan 29950a708f8fSGustavo F. Padovan /* Check if the ACL is secure enough (if not SDP) */ 29960a708f8fSGustavo F. Padovan if (psm != cpu_to_le16(0x0001) && 29970a708f8fSGustavo F. Padovan !hci_conn_check_link_mode(conn->hcon)) { 29989f5a0d7bSAndrei Emeltchenko conn->disc_reason = HCI_ERROR_AUTH_FAILURE; 29990a708f8fSGustavo F. Padovan result = L2CAP_CR_SEC_BLOCK; 30000a708f8fSGustavo F. Padovan goto response; 30010a708f8fSGustavo F. Padovan } 30020a708f8fSGustavo F. Padovan 30030a708f8fSGustavo F. Padovan result = L2CAP_CR_NO_MEM; 30040a708f8fSGustavo F. Padovan 30050a708f8fSGustavo F. Padovan /* Check for backlog size */ 30060a708f8fSGustavo F. Padovan if (sk_acceptq_is_full(parent)) { 30070a708f8fSGustavo F. Padovan BT_DBG("backlog full %d", parent->sk_ack_backlog); 30080a708f8fSGustavo F. Padovan goto response; 30090a708f8fSGustavo F. Padovan } 30100a708f8fSGustavo F. Padovan 301180808e43SGustavo F. Padovan chan = pchan->ops->new_connection(pchan->data); 301280808e43SGustavo F. Padovan if (!chan) 30130a708f8fSGustavo F. Padovan goto response; 30140a708f8fSGustavo F. Padovan 301580808e43SGustavo F. Padovan sk = chan->sk; 301680808e43SGustavo F. Padovan 30170a708f8fSGustavo F. Padovan /* Check if we already have channel with that dcid */ 3018baa7e1faSGustavo F. Padovan if (__l2cap_get_chan_by_dcid(conn, scid)) { 30190a708f8fSGustavo F. Padovan sock_set_flag(sk, SOCK_ZAPPED); 3020ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 30210a708f8fSGustavo F. Padovan goto response; 30220a708f8fSGustavo F. Padovan } 30230a708f8fSGustavo F. Padovan 30240a708f8fSGustavo F. Padovan hci_conn_hold(conn->hcon); 30250a708f8fSGustavo F. Padovan 30260a708f8fSGustavo F. Padovan bacpy(&bt_sk(sk)->src, conn->src); 30270a708f8fSGustavo F. Padovan bacpy(&bt_sk(sk)->dst, conn->dst); 3028fe4128e0SGustavo F. Padovan chan->psm = psm; 3029fe4128e0SGustavo F. Padovan chan->dcid = scid; 30300a708f8fSGustavo F. Padovan 3031d1010240SGustavo F. Padovan bt_accept_enqueue(parent, sk); 3032d1010240SGustavo F. Padovan 30336be36555SAndrei Emeltchenko __l2cap_chan_add(conn, chan); 303448454079SGustavo F. Padovan 3035fe4128e0SGustavo F. Padovan dcid = chan->scid; 30360a708f8fSGustavo F. Padovan 3037c9b66675SGustavo F. Padovan __set_chan_timer(chan, sk->sk_sndtimeo); 30380a708f8fSGustavo F. Padovan 3039fc7f8a7eSGustavo F. Padovan chan->ident = cmd->ident; 30400a708f8fSGustavo F. Padovan 30410a708f8fSGustavo F. Padovan if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { 3042d45fc423SGustavo F. Padovan if (l2cap_chan_check_security(chan)) { 3043c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) { 30440e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 30450a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 30460a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHOR_PEND; 30470a708f8fSGustavo F. Padovan parent->sk_data_ready(parent, 0); 30480a708f8fSGustavo F. Padovan } else { 30490e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 30500a708f8fSGustavo F. Padovan result = L2CAP_CR_SUCCESS; 30510a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 30520a708f8fSGustavo F. Padovan } 30530a708f8fSGustavo F. Padovan } else { 30540e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 30550a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 30560a708f8fSGustavo F. Padovan status = L2CAP_CS_AUTHEN_PEND; 30570a708f8fSGustavo F. Padovan } 30580a708f8fSGustavo F. Padovan } else { 30590e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONNECT2); 30600a708f8fSGustavo F. Padovan result = L2CAP_CR_PEND; 30610a708f8fSGustavo F. Padovan status = L2CAP_CS_NO_INFO; 30620a708f8fSGustavo F. Padovan } 30630a708f8fSGustavo F. Padovan 30640a708f8fSGustavo F. Padovan response: 3065aa2ac881SGustavo F. Padovan release_sock(parent); 30663df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 30670a708f8fSGustavo F. Padovan 30680a708f8fSGustavo F. Padovan sendresp: 30690a708f8fSGustavo F. Padovan rsp.scid = cpu_to_le16(scid); 30700a708f8fSGustavo F. Padovan rsp.dcid = cpu_to_le16(dcid); 30710a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(result); 30720a708f8fSGustavo F. Padovan rsp.status = cpu_to_le16(status); 30730a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); 30740a708f8fSGustavo F. Padovan 30750a708f8fSGustavo F. Padovan if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { 30760a708f8fSGustavo F. Padovan struct l2cap_info_req info; 30770a708f8fSGustavo F. Padovan info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 30780a708f8fSGustavo F. Padovan 30790a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; 30800a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 30810a708f8fSGustavo F. Padovan 3082ba13ccd9SMarcel Holtmann schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); 30830a708f8fSGustavo F. Padovan 30840a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 30850a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(info), &info); 30860a708f8fSGustavo F. Padovan } 30870a708f8fSGustavo F. Padovan 3088c1360a1cSGustavo F. Padovan if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && 30890a708f8fSGustavo F. Padovan result == L2CAP_CR_SUCCESS) { 30900a708f8fSGustavo F. Padovan u8 buf[128]; 3091c1360a1cSGustavo F. Padovan set_bit(CONF_REQ_SENT, &chan->conf_state); 30920a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 309373ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 309473ffa904SGustavo F. Padovan chan->num_conf_req++; 30950a708f8fSGustavo F. Padovan } 30960a708f8fSGustavo F. Padovan 30970a708f8fSGustavo F. Padovan return 0; 30980a708f8fSGustavo F. Padovan } 30990a708f8fSGustavo F. Padovan 31000a708f8fSGustavo F. Padovan static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 31010a708f8fSGustavo F. Padovan { 31020a708f8fSGustavo F. Padovan struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; 31030a708f8fSGustavo F. Padovan u16 scid, dcid, result, status; 310448454079SGustavo F. Padovan struct l2cap_chan *chan; 31050a708f8fSGustavo F. Padovan u8 req[128]; 31063df91ea2SAndrei Emeltchenko int err; 31070a708f8fSGustavo F. Padovan 31080a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 31090a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 31100a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 31110a708f8fSGustavo F. Padovan status = __le16_to_cpu(rsp->status); 31120a708f8fSGustavo F. Padovan 31131b009c98SAndrei Emeltchenko BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", 31141b009c98SAndrei Emeltchenko dcid, scid, result, status); 31150a708f8fSGustavo F. Padovan 31163df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 31173df91ea2SAndrei Emeltchenko 31180a708f8fSGustavo F. Padovan if (scid) { 31193df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 31203df91ea2SAndrei Emeltchenko if (!chan) { 31213df91ea2SAndrei Emeltchenko err = -EFAULT; 31223df91ea2SAndrei Emeltchenko goto unlock; 31233df91ea2SAndrei Emeltchenko } 31240a708f8fSGustavo F. Padovan } else { 31253df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_ident(conn, cmd->ident); 31263df91ea2SAndrei Emeltchenko if (!chan) { 31273df91ea2SAndrei Emeltchenko err = -EFAULT; 31283df91ea2SAndrei Emeltchenko goto unlock; 31293df91ea2SAndrei Emeltchenko } 31300a708f8fSGustavo F. Padovan } 31310a708f8fSGustavo F. Padovan 31323df91ea2SAndrei Emeltchenko err = 0; 31333df91ea2SAndrei Emeltchenko 31346be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 313548454079SGustavo F. Padovan 31360a708f8fSGustavo F. Padovan switch (result) { 31370a708f8fSGustavo F. Padovan case L2CAP_CR_SUCCESS: 313889bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONFIG); 3139fc7f8a7eSGustavo F. Padovan chan->ident = 0; 3140fe4128e0SGustavo F. Padovan chan->dcid = dcid; 3141c1360a1cSGustavo F. Padovan clear_bit(CONF_CONNECT_PEND, &chan->conf_state); 31420a708f8fSGustavo F. Padovan 3143c1360a1cSGustavo F. Padovan if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) 31440a708f8fSGustavo F. Padovan break; 31450a708f8fSGustavo F. Padovan 31460a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 314773ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, req), req); 314873ffa904SGustavo F. Padovan chan->num_conf_req++; 31490a708f8fSGustavo F. Padovan break; 31500a708f8fSGustavo F. Padovan 31510a708f8fSGustavo F. Padovan case L2CAP_CR_PEND: 3152c1360a1cSGustavo F. Padovan set_bit(CONF_CONNECT_PEND, &chan->conf_state); 31530a708f8fSGustavo F. Padovan break; 31540a708f8fSGustavo F. Padovan 31550a708f8fSGustavo F. Padovan default: 315648454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNREFUSED); 31570a708f8fSGustavo F. Padovan break; 31580a708f8fSGustavo F. Padovan } 31590a708f8fSGustavo F. Padovan 31606be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 31613df91ea2SAndrei Emeltchenko 31623df91ea2SAndrei Emeltchenko unlock: 31633df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 31643df91ea2SAndrei Emeltchenko 31653df91ea2SAndrei Emeltchenko return err; 31660a708f8fSGustavo F. Padovan } 31670a708f8fSGustavo F. Padovan 316847d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan) 31690a708f8fSGustavo F. Padovan { 31700a708f8fSGustavo F. Padovan /* FCS is enabled only in ERTM or streaming mode, if one or both 31710a708f8fSGustavo F. Padovan * sides request it. 31720a708f8fSGustavo F. Padovan */ 31730c1bc5c6SGustavo F. Padovan if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) 317447d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_NONE; 3175c1360a1cSGustavo F. Padovan else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) 317647d1ec61SGustavo F. Padovan chan->fcs = L2CAP_FCS_CRC16; 31770a708f8fSGustavo F. Padovan } 31780a708f8fSGustavo F. Padovan 31790a708f8fSGustavo F. Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 31800a708f8fSGustavo F. Padovan { 31810a708f8fSGustavo F. Padovan struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; 31820a708f8fSGustavo F. Padovan u16 dcid, flags; 31830a708f8fSGustavo F. Padovan u8 rsp[64]; 318448454079SGustavo F. Padovan struct l2cap_chan *chan; 31853c588192SMat Martineau int len, err = 0; 31860a708f8fSGustavo F. Padovan 31870a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 31880a708f8fSGustavo F. Padovan flags = __le16_to_cpu(req->flags); 31890a708f8fSGustavo F. Padovan 31900a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); 31910a708f8fSGustavo F. Padovan 3192baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, dcid); 319348454079SGustavo F. Padovan if (!chan) 31940a708f8fSGustavo F. Padovan return -ENOENT; 31950a708f8fSGustavo F. Padovan 3196033b1142SDavid S. Miller if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { 3197e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_cid rej; 31980a708f8fSGustavo F. Padovan 3199e2fd318eSIlia Kolomisnky rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID); 3200e2fd318eSIlia Kolomisnky rej.scid = cpu_to_le16(chan->scid); 3201e2fd318eSIlia Kolomisnky rej.dcid = cpu_to_le16(chan->dcid); 3202e2fd318eSIlia Kolomisnky 32030a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, 32040a708f8fSGustavo F. Padovan sizeof(rej), &rej); 32050a708f8fSGustavo F. Padovan goto unlock; 32060a708f8fSGustavo F. Padovan } 32070a708f8fSGustavo F. Padovan 32080a708f8fSGustavo F. Padovan /* Reject if config buffer is too small. */ 32090a708f8fSGustavo F. Padovan len = cmd_len - sizeof(*req); 32107ac28817SDan Rosenberg if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) { 32110a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 3212fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 32130a708f8fSGustavo F. Padovan L2CAP_CONF_REJECT, flags), rsp); 32140a708f8fSGustavo F. Padovan goto unlock; 32150a708f8fSGustavo F. Padovan } 32160a708f8fSGustavo F. Padovan 32170a708f8fSGustavo F. Padovan /* Store config. */ 321873ffa904SGustavo F. Padovan memcpy(chan->conf_req + chan->conf_len, req->data, len); 321973ffa904SGustavo F. Padovan chan->conf_len += len; 32200a708f8fSGustavo F. Padovan 32210a708f8fSGustavo F. Padovan if (flags & 0x0001) { 32220a708f8fSGustavo F. Padovan /* Incomplete config. Send empty response. */ 32230a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 3224fe4128e0SGustavo F. Padovan l2cap_build_conf_rsp(chan, rsp, 32250a708f8fSGustavo F. Padovan L2CAP_CONF_SUCCESS, 0x0001), rsp); 32260a708f8fSGustavo F. Padovan goto unlock; 32270a708f8fSGustavo F. Padovan } 32280a708f8fSGustavo F. Padovan 32290a708f8fSGustavo F. Padovan /* Complete config. */ 323073ffa904SGustavo F. Padovan len = l2cap_parse_conf_req(chan, rsp); 32310a708f8fSGustavo F. Padovan if (len < 0) { 3232e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 32330a708f8fSGustavo F. Padovan goto unlock; 32340a708f8fSGustavo F. Padovan } 32350a708f8fSGustavo F. Padovan 32360a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); 323773ffa904SGustavo F. Padovan chan->num_conf_rsp++; 32380a708f8fSGustavo F. Padovan 32390a708f8fSGustavo F. Padovan /* Reset config buffer. */ 324073ffa904SGustavo F. Padovan chan->conf_len = 0; 32410a708f8fSGustavo F. Padovan 3242c1360a1cSGustavo F. Padovan if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) 32430a708f8fSGustavo F. Padovan goto unlock; 32440a708f8fSGustavo F. Padovan 3245c1360a1cSGustavo F. Padovan if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { 324647d1ec61SGustavo F. Padovan set_default_fcs(chan); 32470a708f8fSGustavo F. Padovan 324889bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECTED); 32490a708f8fSGustavo F. Padovan 3250105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 3251105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 32523c588192SMat Martineau err = l2cap_ertm_init(chan); 32530a708f8fSGustavo F. Padovan 32543c588192SMat Martineau if (err < 0) 32553c588192SMat Martineau l2cap_send_disconn_req(chan->conn, chan, -err); 32563c588192SMat Martineau else 3257cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 32583c588192SMat Martineau 32590a708f8fSGustavo F. Padovan goto unlock; 32600a708f8fSGustavo F. Padovan } 32610a708f8fSGustavo F. Padovan 3262c1360a1cSGustavo F. Padovan if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { 32630a708f8fSGustavo F. Padovan u8 buf[64]; 32640a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 326573ffa904SGustavo F. Padovan l2cap_build_conf_req(chan, buf), buf); 326673ffa904SGustavo F. Padovan chan->num_conf_req++; 32670a708f8fSGustavo F. Padovan } 32680a708f8fSGustavo F. Padovan 32690e8b207eSAndrei Emeltchenko /* Got Conf Rsp PENDING from remote side and asume we sent 32700e8b207eSAndrei Emeltchenko Conf Rsp PENDING in the code above */ 32710e8b207eSAndrei Emeltchenko if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && 32720e8b207eSAndrei Emeltchenko test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 32730e8b207eSAndrei Emeltchenko 32740e8b207eSAndrei Emeltchenko /* check compatibility */ 32750e8b207eSAndrei Emeltchenko 32760e8b207eSAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 32770e8b207eSAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 32780e8b207eSAndrei Emeltchenko 32790e8b207eSAndrei Emeltchenko l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 32800e8b207eSAndrei Emeltchenko l2cap_build_conf_rsp(chan, rsp, 32810e8b207eSAndrei Emeltchenko L2CAP_CONF_SUCCESS, 0x0000), rsp); 32820e8b207eSAndrei Emeltchenko } 32830e8b207eSAndrei Emeltchenko 32840a708f8fSGustavo F. Padovan unlock: 32856be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 32863c588192SMat Martineau return err; 32870a708f8fSGustavo F. Padovan } 32880a708f8fSGustavo F. Padovan 32890a708f8fSGustavo F. Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 32900a708f8fSGustavo F. Padovan { 32910a708f8fSGustavo F. Padovan struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; 32920a708f8fSGustavo F. Padovan u16 scid, flags, result; 329348454079SGustavo F. Padovan struct l2cap_chan *chan; 329461386cbaSAndrei Emeltchenko int len = le16_to_cpu(cmd->len) - sizeof(*rsp); 32953c588192SMat Martineau int err = 0; 32960a708f8fSGustavo F. Padovan 32970a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 32980a708f8fSGustavo F. Padovan flags = __le16_to_cpu(rsp->flags); 32990a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 33000a708f8fSGustavo F. Padovan 330161386cbaSAndrei Emeltchenko BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags, 330261386cbaSAndrei Emeltchenko result, len); 33030a708f8fSGustavo F. Padovan 3304baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, scid); 330548454079SGustavo F. Padovan if (!chan) 33060a708f8fSGustavo F. Padovan return 0; 33070a708f8fSGustavo F. Padovan 33080a708f8fSGustavo F. Padovan switch (result) { 33090a708f8fSGustavo F. Padovan case L2CAP_CONF_SUCCESS: 331047d1ec61SGustavo F. Padovan l2cap_conf_rfc_get(chan, rsp->data, len); 33110e8b207eSAndrei Emeltchenko clear_bit(CONF_REM_CONF_PEND, &chan->conf_state); 33120a708f8fSGustavo F. Padovan break; 33130a708f8fSGustavo F. Padovan 33140e8b207eSAndrei Emeltchenko case L2CAP_CONF_PENDING: 33150e8b207eSAndrei Emeltchenko set_bit(CONF_REM_CONF_PEND, &chan->conf_state); 33160e8b207eSAndrei Emeltchenko 33170e8b207eSAndrei Emeltchenko if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { 33180e8b207eSAndrei Emeltchenko char buf[64]; 33190e8b207eSAndrei Emeltchenko 33200e8b207eSAndrei Emeltchenko len = l2cap_parse_conf_rsp(chan, rsp->data, len, 33210e8b207eSAndrei Emeltchenko buf, &result); 33220e8b207eSAndrei Emeltchenko if (len < 0) { 33230e8b207eSAndrei Emeltchenko l2cap_send_disconn_req(conn, chan, ECONNRESET); 33240e8b207eSAndrei Emeltchenko goto done; 33250e8b207eSAndrei Emeltchenko } 33260e8b207eSAndrei Emeltchenko 33270e8b207eSAndrei Emeltchenko /* check compatibility */ 33280e8b207eSAndrei Emeltchenko 33290e8b207eSAndrei Emeltchenko clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); 33300e8b207eSAndrei Emeltchenko set_bit(CONF_OUTPUT_DONE, &chan->conf_state); 33310e8b207eSAndrei Emeltchenko 33320e8b207eSAndrei Emeltchenko l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 33330e8b207eSAndrei Emeltchenko l2cap_build_conf_rsp(chan, buf, 33340e8b207eSAndrei Emeltchenko L2CAP_CONF_SUCCESS, 0x0000), buf); 33350e8b207eSAndrei Emeltchenko } 33360e8b207eSAndrei Emeltchenko goto done; 33370e8b207eSAndrei Emeltchenko 33380a708f8fSGustavo F. Padovan case L2CAP_CONF_UNACCEPT: 333973ffa904SGustavo F. Padovan if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { 33400a708f8fSGustavo F. Padovan char req[64]; 33410a708f8fSGustavo F. Padovan 33420a708f8fSGustavo F. Padovan if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { 3343e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 33440a708f8fSGustavo F. Padovan goto done; 33450a708f8fSGustavo F. Padovan } 33460a708f8fSGustavo F. Padovan 33470a708f8fSGustavo F. Padovan /* throw out any old stored conf requests */ 33480a708f8fSGustavo F. Padovan result = L2CAP_CONF_SUCCESS; 3349b4450035SGustavo F. Padovan len = l2cap_parse_conf_rsp(chan, rsp->data, len, 3350b4450035SGustavo F. Padovan req, &result); 33510a708f8fSGustavo F. Padovan if (len < 0) { 3352e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 33530a708f8fSGustavo F. Padovan goto done; 33540a708f8fSGustavo F. Padovan } 33550a708f8fSGustavo F. Padovan 33560a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, l2cap_get_ident(conn), 33570a708f8fSGustavo F. Padovan L2CAP_CONF_REQ, len, req); 335873ffa904SGustavo F. Padovan chan->num_conf_req++; 33590a708f8fSGustavo F. Padovan if (result != L2CAP_CONF_SUCCESS) 33600a708f8fSGustavo F. Padovan goto done; 33610a708f8fSGustavo F. Padovan break; 33620a708f8fSGustavo F. Padovan } 33630a708f8fSGustavo F. Padovan 33640a708f8fSGustavo F. Padovan default: 33656be36555SAndrei Emeltchenko l2cap_chan_set_err(chan, ECONNRESET); 33662e0052e4SAndrei Emeltchenko 3367ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); 3368e92c8e70SGustavo F. Padovan l2cap_send_disconn_req(conn, chan, ECONNRESET); 33690a708f8fSGustavo F. Padovan goto done; 33700a708f8fSGustavo F. Padovan } 33710a708f8fSGustavo F. Padovan 33720a708f8fSGustavo F. Padovan if (flags & 0x01) 33730a708f8fSGustavo F. Padovan goto done; 33740a708f8fSGustavo F. Padovan 3375c1360a1cSGustavo F. Padovan set_bit(CONF_INPUT_DONE, &chan->conf_state); 33760a708f8fSGustavo F. Padovan 3377c1360a1cSGustavo F. Padovan if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { 337847d1ec61SGustavo F. Padovan set_default_fcs(chan); 33790a708f8fSGustavo F. Padovan 338089bc500eSGustavo F. Padovan l2cap_state_change(chan, BT_CONNECTED); 3381105bdf9eSMat Martineau if (chan->mode == L2CAP_MODE_ERTM || 3382105bdf9eSMat Martineau chan->mode == L2CAP_MODE_STREAMING) 33833c588192SMat Martineau err = l2cap_ertm_init(chan); 33840a708f8fSGustavo F. Padovan 33853c588192SMat Martineau if (err < 0) 33863c588192SMat Martineau l2cap_send_disconn_req(chan->conn, chan, -err); 33873c588192SMat Martineau else 3388cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 33890a708f8fSGustavo F. Padovan } 33900a708f8fSGustavo F. Padovan 33910a708f8fSGustavo F. Padovan done: 33926be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 33933c588192SMat Martineau return err; 33940a708f8fSGustavo F. Padovan } 33950a708f8fSGustavo F. Padovan 33960a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 33970a708f8fSGustavo F. Padovan { 33980a708f8fSGustavo F. Padovan struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; 33990a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp rsp; 34000a708f8fSGustavo F. Padovan u16 dcid, scid; 340148454079SGustavo F. Padovan struct l2cap_chan *chan; 34020a708f8fSGustavo F. Padovan struct sock *sk; 34030a708f8fSGustavo F. Padovan 34040a708f8fSGustavo F. Padovan scid = __le16_to_cpu(req->scid); 34050a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(req->dcid); 34060a708f8fSGustavo F. Padovan 34070a708f8fSGustavo F. Padovan BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); 34080a708f8fSGustavo F. Padovan 34093df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 34103df91ea2SAndrei Emeltchenko 34113df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, dcid); 34123df91ea2SAndrei Emeltchenko if (!chan) { 34133df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 34140a708f8fSGustavo F. Padovan return 0; 34153df91ea2SAndrei Emeltchenko } 34160a708f8fSGustavo F. Padovan 34176be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 34186be36555SAndrei Emeltchenko 341948454079SGustavo F. Padovan sk = chan->sk; 342048454079SGustavo F. Padovan 3421fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 3422fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 34230a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); 34240a708f8fSGustavo F. Padovan 34256be36555SAndrei Emeltchenko lock_sock(sk); 34260a708f8fSGustavo F. Padovan sk->sk_shutdown = SHUTDOWN_MASK; 34276be36555SAndrei Emeltchenko release_sock(sk); 34280a708f8fSGustavo F. Padovan 342961d6ef3eSMat Martineau l2cap_chan_hold(chan); 343048454079SGustavo F. Padovan l2cap_chan_del(chan, ECONNRESET); 34316be36555SAndrei Emeltchenko 34326be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 34330a708f8fSGustavo F. Padovan 3434ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 343561d6ef3eSMat Martineau l2cap_chan_put(chan); 34363df91ea2SAndrei Emeltchenko 34373df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 34383df91ea2SAndrei Emeltchenko 34390a708f8fSGustavo F. Padovan return 0; 34400a708f8fSGustavo F. Padovan } 34410a708f8fSGustavo F. Padovan 34420a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 34430a708f8fSGustavo F. Padovan { 34440a708f8fSGustavo F. Padovan struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; 34450a708f8fSGustavo F. Padovan u16 dcid, scid; 344648454079SGustavo F. Padovan struct l2cap_chan *chan; 34470a708f8fSGustavo F. Padovan 34480a708f8fSGustavo F. Padovan scid = __le16_to_cpu(rsp->scid); 34490a708f8fSGustavo F. Padovan dcid = __le16_to_cpu(rsp->dcid); 34500a708f8fSGustavo F. Padovan 34510a708f8fSGustavo F. Padovan BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); 34520a708f8fSGustavo F. Padovan 34533df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 34543df91ea2SAndrei Emeltchenko 34553df91ea2SAndrei Emeltchenko chan = __l2cap_get_chan_by_scid(conn, scid); 34563df91ea2SAndrei Emeltchenko if (!chan) { 34573df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 34580a708f8fSGustavo F. Padovan return 0; 34593df91ea2SAndrei Emeltchenko } 34600a708f8fSGustavo F. Padovan 34616be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 346248454079SGustavo F. Padovan 346361d6ef3eSMat Martineau l2cap_chan_hold(chan); 346448454079SGustavo F. Padovan l2cap_chan_del(chan, 0); 34656be36555SAndrei Emeltchenko 34666be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 34670a708f8fSGustavo F. Padovan 3468ba3bd0eeSGustavo F. Padovan chan->ops->close(chan->data); 346961d6ef3eSMat Martineau l2cap_chan_put(chan); 34703df91ea2SAndrei Emeltchenko 34713df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 34723df91ea2SAndrei Emeltchenko 34730a708f8fSGustavo F. Padovan return 0; 34740a708f8fSGustavo F. Padovan } 34750a708f8fSGustavo F. Padovan 34760a708f8fSGustavo F. Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 34770a708f8fSGustavo F. Padovan { 34780a708f8fSGustavo F. Padovan struct l2cap_info_req *req = (struct l2cap_info_req *) data; 34790a708f8fSGustavo F. Padovan u16 type; 34800a708f8fSGustavo F. Padovan 34810a708f8fSGustavo F. Padovan type = __le16_to_cpu(req->type); 34820a708f8fSGustavo F. Padovan 34830a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x", type); 34840a708f8fSGustavo F. Padovan 34850a708f8fSGustavo F. Padovan if (type == L2CAP_IT_FEAT_MASK) { 34860a708f8fSGustavo F. Padovan u8 buf[8]; 34870a708f8fSGustavo F. Padovan u32 feat_mask = l2cap_feat_mask; 34880a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 34890a708f8fSGustavo F. Padovan rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK); 34900a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 34910a708f8fSGustavo F. Padovan if (!disable_ertm) 34920a708f8fSGustavo F. Padovan feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING 34930a708f8fSGustavo F. Padovan | L2CAP_FEAT_FCS; 3494a5fd6f30SAndrei Emeltchenko if (enable_hs) 34956327eb98SAndrei Emeltchenko feat_mask |= L2CAP_FEAT_EXT_FLOW 34966327eb98SAndrei Emeltchenko | L2CAP_FEAT_EXT_WINDOW; 3497a5fd6f30SAndrei Emeltchenko 34980a708f8fSGustavo F. Padovan put_unaligned_le32(feat_mask, rsp->data); 34990a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 35000a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(buf), buf); 35010a708f8fSGustavo F. Padovan } else if (type == L2CAP_IT_FIXED_CHAN) { 35020a708f8fSGustavo F. Padovan u8 buf[12]; 35030a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 350450a147cdSMat Martineau 350550a147cdSMat Martineau if (enable_hs) 350650a147cdSMat Martineau l2cap_fixed_chan[0] |= L2CAP_FC_A2MP; 350750a147cdSMat Martineau else 350850a147cdSMat Martineau l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP; 350950a147cdSMat Martineau 35100a708f8fSGustavo F. Padovan rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 35110a708f8fSGustavo F. Padovan rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 3512c6337ea6SAndrei Emeltchenko memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); 35130a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 35140a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(buf), buf); 35150a708f8fSGustavo F. Padovan } else { 35160a708f8fSGustavo F. Padovan struct l2cap_info_rsp rsp; 35170a708f8fSGustavo F. Padovan rsp.type = cpu_to_le16(type); 35180a708f8fSGustavo F. Padovan rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP); 35190a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd->ident, 35200a708f8fSGustavo F. Padovan L2CAP_INFO_RSP, sizeof(rsp), &rsp); 35210a708f8fSGustavo F. Padovan } 35220a708f8fSGustavo F. Padovan 35230a708f8fSGustavo F. Padovan return 0; 35240a708f8fSGustavo F. Padovan } 35250a708f8fSGustavo F. Padovan 35260a708f8fSGustavo F. Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) 35270a708f8fSGustavo F. Padovan { 35280a708f8fSGustavo F. Padovan struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; 35290a708f8fSGustavo F. Padovan u16 type, result; 35300a708f8fSGustavo F. Padovan 35310a708f8fSGustavo F. Padovan type = __le16_to_cpu(rsp->type); 35320a708f8fSGustavo F. Padovan result = __le16_to_cpu(rsp->result); 35330a708f8fSGustavo F. Padovan 35340a708f8fSGustavo F. Padovan BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); 35350a708f8fSGustavo F. Padovan 3536e90165beSAndrei Emeltchenko /* L2CAP Info req/rsp are unbound to channels, add extra checks */ 3537e90165beSAndrei Emeltchenko if (cmd->ident != conn->info_ident || 3538e90165beSAndrei Emeltchenko conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) 3539e90165beSAndrei Emeltchenko return 0; 3540e90165beSAndrei Emeltchenko 354117cd3f37SUlisses Furquim cancel_delayed_work(&conn->info_timer); 35420a708f8fSGustavo F. Padovan 35430a708f8fSGustavo F. Padovan if (result != L2CAP_IR_SUCCESS) { 35440a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 35450a708f8fSGustavo F. Padovan conn->info_ident = 0; 35460a708f8fSGustavo F. Padovan 35470a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 35480a708f8fSGustavo F. Padovan 35490a708f8fSGustavo F. Padovan return 0; 35500a708f8fSGustavo F. Padovan } 35510a708f8fSGustavo F. Padovan 3552978c93b9SAndrei Emeltchenko switch (type) { 3553978c93b9SAndrei Emeltchenko case L2CAP_IT_FEAT_MASK: 35540a708f8fSGustavo F. Padovan conn->feat_mask = get_unaligned_le32(rsp->data); 35550a708f8fSGustavo F. Padovan 35560a708f8fSGustavo F. Padovan if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { 35570a708f8fSGustavo F. Padovan struct l2cap_info_req req; 35580a708f8fSGustavo F. Padovan req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 35590a708f8fSGustavo F. Padovan 35600a708f8fSGustavo F. Padovan conn->info_ident = l2cap_get_ident(conn); 35610a708f8fSGustavo F. Padovan 35620a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, conn->info_ident, 35630a708f8fSGustavo F. Padovan L2CAP_INFO_REQ, sizeof(req), &req); 35640a708f8fSGustavo F. Padovan } else { 35650a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 35660a708f8fSGustavo F. Padovan conn->info_ident = 0; 35670a708f8fSGustavo F. Padovan 35680a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 35690a708f8fSGustavo F. Padovan } 3570978c93b9SAndrei Emeltchenko break; 3571978c93b9SAndrei Emeltchenko 3572978c93b9SAndrei Emeltchenko case L2CAP_IT_FIXED_CHAN: 3573978c93b9SAndrei Emeltchenko conn->fixed_chan_mask = rsp->data[0]; 35740a708f8fSGustavo F. Padovan conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 35750a708f8fSGustavo F. Padovan conn->info_ident = 0; 35760a708f8fSGustavo F. Padovan 35770a708f8fSGustavo F. Padovan l2cap_conn_start(conn); 3578978c93b9SAndrei Emeltchenko break; 35790a708f8fSGustavo F. Padovan } 35800a708f8fSGustavo F. Padovan 35810a708f8fSGustavo F. Padovan return 0; 35820a708f8fSGustavo F. Padovan } 35830a708f8fSGustavo F. Padovan 3584f94ff6ffSMat Martineau static inline int l2cap_create_channel_req(struct l2cap_conn *conn, 3585f94ff6ffSMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, 3586f94ff6ffSMat Martineau void *data) 3587f94ff6ffSMat Martineau { 3588f94ff6ffSMat Martineau struct l2cap_create_chan_req *req = data; 3589f94ff6ffSMat Martineau struct l2cap_create_chan_rsp rsp; 3590f94ff6ffSMat Martineau u16 psm, scid; 3591f94ff6ffSMat Martineau 3592f94ff6ffSMat Martineau if (cmd_len != sizeof(*req)) 3593f94ff6ffSMat Martineau return -EPROTO; 3594f94ff6ffSMat Martineau 3595f94ff6ffSMat Martineau if (!enable_hs) 3596f94ff6ffSMat Martineau return -EINVAL; 3597f94ff6ffSMat Martineau 3598f94ff6ffSMat Martineau psm = le16_to_cpu(req->psm); 3599f94ff6ffSMat Martineau scid = le16_to_cpu(req->scid); 3600f94ff6ffSMat Martineau 3601f94ff6ffSMat Martineau BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id); 3602f94ff6ffSMat Martineau 3603f94ff6ffSMat Martineau /* Placeholder: Always reject */ 3604f94ff6ffSMat Martineau rsp.dcid = 0; 3605f94ff6ffSMat Martineau rsp.scid = cpu_to_le16(scid); 36068ce0c498SAndrei Emeltchenko rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM); 36078ce0c498SAndrei Emeltchenko rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 3608f94ff6ffSMat Martineau 3609f94ff6ffSMat Martineau l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, 3610f94ff6ffSMat Martineau sizeof(rsp), &rsp); 3611f94ff6ffSMat Martineau 3612f94ff6ffSMat Martineau return 0; 3613f94ff6ffSMat Martineau } 3614f94ff6ffSMat Martineau 3615f94ff6ffSMat Martineau static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn, 3616f94ff6ffSMat Martineau struct l2cap_cmd_hdr *cmd, void *data) 3617f94ff6ffSMat Martineau { 3618f94ff6ffSMat Martineau BT_DBG("conn %p", conn); 3619f94ff6ffSMat Martineau 3620f94ff6ffSMat Martineau return l2cap_connect_rsp(conn, cmd, data); 3621f94ff6ffSMat Martineau } 3622f94ff6ffSMat Martineau 36238d5a04a1SMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident, 36248d5a04a1SMat Martineau u16 icid, u16 result) 36258d5a04a1SMat Martineau { 36268d5a04a1SMat Martineau struct l2cap_move_chan_rsp rsp; 36278d5a04a1SMat Martineau 36288d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 36298d5a04a1SMat Martineau 36308d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 36318d5a04a1SMat Martineau rsp.result = cpu_to_le16(result); 36328d5a04a1SMat Martineau 36338d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp); 36348d5a04a1SMat Martineau } 36358d5a04a1SMat Martineau 36368d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn, 36378d5a04a1SMat Martineau struct l2cap_chan *chan, u16 icid, u16 result) 36388d5a04a1SMat Martineau { 36398d5a04a1SMat Martineau struct l2cap_move_chan_cfm cfm; 36408d5a04a1SMat Martineau u8 ident; 36418d5a04a1SMat Martineau 36428d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 36438d5a04a1SMat Martineau 36448d5a04a1SMat Martineau ident = l2cap_get_ident(conn); 36458d5a04a1SMat Martineau if (chan) 36468d5a04a1SMat Martineau chan->ident = ident; 36478d5a04a1SMat Martineau 36488d5a04a1SMat Martineau cfm.icid = cpu_to_le16(icid); 36498d5a04a1SMat Martineau cfm.result = cpu_to_le16(result); 36508d5a04a1SMat Martineau 36518d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm); 36528d5a04a1SMat Martineau } 36538d5a04a1SMat Martineau 36548d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, 36558d5a04a1SMat Martineau u16 icid) 36568d5a04a1SMat Martineau { 36578d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp rsp; 36588d5a04a1SMat Martineau 36598d5a04a1SMat Martineau BT_DBG("icid %d", icid); 36608d5a04a1SMat Martineau 36618d5a04a1SMat Martineau rsp.icid = cpu_to_le16(icid); 36628d5a04a1SMat Martineau l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp); 36638d5a04a1SMat Martineau } 36648d5a04a1SMat Martineau 36658d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn, 36668d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 36678d5a04a1SMat Martineau { 36688d5a04a1SMat Martineau struct l2cap_move_chan_req *req = data; 36698d5a04a1SMat Martineau u16 icid = 0; 36708d5a04a1SMat Martineau u16 result = L2CAP_MR_NOT_ALLOWED; 36718d5a04a1SMat Martineau 36728d5a04a1SMat Martineau if (cmd_len != sizeof(*req)) 36738d5a04a1SMat Martineau return -EPROTO; 36748d5a04a1SMat Martineau 36758d5a04a1SMat Martineau icid = le16_to_cpu(req->icid); 36768d5a04a1SMat Martineau 36778d5a04a1SMat Martineau BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id); 36788d5a04a1SMat Martineau 36798d5a04a1SMat Martineau if (!enable_hs) 36808d5a04a1SMat Martineau return -EINVAL; 36818d5a04a1SMat Martineau 36828d5a04a1SMat Martineau /* Placeholder: Always refuse */ 36838d5a04a1SMat Martineau l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result); 36848d5a04a1SMat Martineau 36858d5a04a1SMat Martineau return 0; 36868d5a04a1SMat Martineau } 36878d5a04a1SMat Martineau 36888d5a04a1SMat Martineau static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn, 36898d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 36908d5a04a1SMat Martineau { 36918d5a04a1SMat Martineau struct l2cap_move_chan_rsp *rsp = data; 36928d5a04a1SMat Martineau u16 icid, result; 36938d5a04a1SMat Martineau 36948d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 36958d5a04a1SMat Martineau return -EPROTO; 36968d5a04a1SMat Martineau 36978d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 36988d5a04a1SMat Martineau result = le16_to_cpu(rsp->result); 36998d5a04a1SMat Martineau 37008d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 37018d5a04a1SMat Martineau 37028d5a04a1SMat Martineau /* Placeholder: Always unconfirmed */ 37038d5a04a1SMat Martineau l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED); 37048d5a04a1SMat Martineau 37058d5a04a1SMat Martineau return 0; 37068d5a04a1SMat Martineau } 37078d5a04a1SMat Martineau 37088d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn, 37098d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 37108d5a04a1SMat Martineau { 37118d5a04a1SMat Martineau struct l2cap_move_chan_cfm *cfm = data; 37128d5a04a1SMat Martineau u16 icid, result; 37138d5a04a1SMat Martineau 37148d5a04a1SMat Martineau if (cmd_len != sizeof(*cfm)) 37158d5a04a1SMat Martineau return -EPROTO; 37168d5a04a1SMat Martineau 37178d5a04a1SMat Martineau icid = le16_to_cpu(cfm->icid); 37188d5a04a1SMat Martineau result = le16_to_cpu(cfm->result); 37198d5a04a1SMat Martineau 37208d5a04a1SMat Martineau BT_DBG("icid %d, result %d", icid, result); 37218d5a04a1SMat Martineau 37228d5a04a1SMat Martineau l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); 37238d5a04a1SMat Martineau 37248d5a04a1SMat Martineau return 0; 37258d5a04a1SMat Martineau } 37268d5a04a1SMat Martineau 37278d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, 37288d5a04a1SMat Martineau struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data) 37298d5a04a1SMat Martineau { 37308d5a04a1SMat Martineau struct l2cap_move_chan_cfm_rsp *rsp = data; 37318d5a04a1SMat Martineau u16 icid; 37328d5a04a1SMat Martineau 37338d5a04a1SMat Martineau if (cmd_len != sizeof(*rsp)) 37348d5a04a1SMat Martineau return -EPROTO; 37358d5a04a1SMat Martineau 37368d5a04a1SMat Martineau icid = le16_to_cpu(rsp->icid); 37378d5a04a1SMat Martineau 37388d5a04a1SMat Martineau BT_DBG("icid %d", icid); 37398d5a04a1SMat Martineau 37408d5a04a1SMat Martineau return 0; 37418d5a04a1SMat Martineau } 37428d5a04a1SMat Martineau 3743e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency, 3744de73115aSClaudio Takahasi u16 to_multiplier) 3745de73115aSClaudio Takahasi { 3746de73115aSClaudio Takahasi u16 max_latency; 3747de73115aSClaudio Takahasi 3748de73115aSClaudio Takahasi if (min > max || min < 6 || max > 3200) 3749de73115aSClaudio Takahasi return -EINVAL; 3750de73115aSClaudio Takahasi 3751de73115aSClaudio Takahasi if (to_multiplier < 10 || to_multiplier > 3200) 3752de73115aSClaudio Takahasi return -EINVAL; 3753de73115aSClaudio Takahasi 3754de73115aSClaudio Takahasi if (max >= to_multiplier * 8) 3755de73115aSClaudio Takahasi return -EINVAL; 3756de73115aSClaudio Takahasi 3757de73115aSClaudio Takahasi max_latency = (to_multiplier * 8 / max) - 1; 3758de73115aSClaudio Takahasi if (latency > 499 || latency > max_latency) 3759de73115aSClaudio Takahasi return -EINVAL; 3760de73115aSClaudio Takahasi 3761de73115aSClaudio Takahasi return 0; 3762de73115aSClaudio Takahasi } 3763de73115aSClaudio Takahasi 3764de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, 3765de73115aSClaudio Takahasi struct l2cap_cmd_hdr *cmd, u8 *data) 3766de73115aSClaudio Takahasi { 3767de73115aSClaudio Takahasi struct hci_conn *hcon = conn->hcon; 3768de73115aSClaudio Takahasi struct l2cap_conn_param_update_req *req; 3769de73115aSClaudio Takahasi struct l2cap_conn_param_update_rsp rsp; 3770de73115aSClaudio Takahasi u16 min, max, latency, to_multiplier, cmd_len; 37712ce603ebSClaudio Takahasi int err; 3772de73115aSClaudio Takahasi 3773de73115aSClaudio Takahasi if (!(hcon->link_mode & HCI_LM_MASTER)) 3774de73115aSClaudio Takahasi return -EINVAL; 3775de73115aSClaudio Takahasi 3776de73115aSClaudio Takahasi cmd_len = __le16_to_cpu(cmd->len); 3777de73115aSClaudio Takahasi if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) 3778de73115aSClaudio Takahasi return -EPROTO; 3779de73115aSClaudio Takahasi 3780de73115aSClaudio Takahasi req = (struct l2cap_conn_param_update_req *) data; 3781de73115aSClaudio Takahasi min = __le16_to_cpu(req->min); 3782de73115aSClaudio Takahasi max = __le16_to_cpu(req->max); 3783de73115aSClaudio Takahasi latency = __le16_to_cpu(req->latency); 3784de73115aSClaudio Takahasi to_multiplier = __le16_to_cpu(req->to_multiplier); 3785de73115aSClaudio Takahasi 3786de73115aSClaudio Takahasi BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", 3787de73115aSClaudio Takahasi min, max, latency, to_multiplier); 3788de73115aSClaudio Takahasi 3789de73115aSClaudio Takahasi memset(&rsp, 0, sizeof(rsp)); 37902ce603ebSClaudio Takahasi 37912ce603ebSClaudio Takahasi err = l2cap_check_conn_param(min, max, latency, to_multiplier); 37922ce603ebSClaudio Takahasi if (err) 3793de73115aSClaudio Takahasi rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); 3794de73115aSClaudio Takahasi else 3795de73115aSClaudio Takahasi rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); 3796de73115aSClaudio Takahasi 3797de73115aSClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, 3798de73115aSClaudio Takahasi sizeof(rsp), &rsp); 3799de73115aSClaudio Takahasi 38002ce603ebSClaudio Takahasi if (!err) 38012ce603ebSClaudio Takahasi hci_le_conn_update(hcon, min, max, latency, to_multiplier); 38022ce603ebSClaudio Takahasi 3803de73115aSClaudio Takahasi return 0; 3804de73115aSClaudio Takahasi } 3805de73115aSClaudio Takahasi 38063300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, 38073300d9a9SClaudio Takahasi struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) 38083300d9a9SClaudio Takahasi { 38093300d9a9SClaudio Takahasi int err = 0; 38103300d9a9SClaudio Takahasi 38113300d9a9SClaudio Takahasi switch (cmd->code) { 38123300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 38133300d9a9SClaudio Takahasi l2cap_command_rej(conn, cmd, data); 38143300d9a9SClaudio Takahasi break; 38153300d9a9SClaudio Takahasi 38163300d9a9SClaudio Takahasi case L2CAP_CONN_REQ: 38173300d9a9SClaudio Takahasi err = l2cap_connect_req(conn, cmd, data); 38183300d9a9SClaudio Takahasi break; 38193300d9a9SClaudio Takahasi 38203300d9a9SClaudio Takahasi case L2CAP_CONN_RSP: 38213300d9a9SClaudio Takahasi err = l2cap_connect_rsp(conn, cmd, data); 38223300d9a9SClaudio Takahasi break; 38233300d9a9SClaudio Takahasi 38243300d9a9SClaudio Takahasi case L2CAP_CONF_REQ: 38253300d9a9SClaudio Takahasi err = l2cap_config_req(conn, cmd, cmd_len, data); 38263300d9a9SClaudio Takahasi break; 38273300d9a9SClaudio Takahasi 38283300d9a9SClaudio Takahasi case L2CAP_CONF_RSP: 38293300d9a9SClaudio Takahasi err = l2cap_config_rsp(conn, cmd, data); 38303300d9a9SClaudio Takahasi break; 38313300d9a9SClaudio Takahasi 38323300d9a9SClaudio Takahasi case L2CAP_DISCONN_REQ: 38333300d9a9SClaudio Takahasi err = l2cap_disconnect_req(conn, cmd, data); 38343300d9a9SClaudio Takahasi break; 38353300d9a9SClaudio Takahasi 38363300d9a9SClaudio Takahasi case L2CAP_DISCONN_RSP: 38373300d9a9SClaudio Takahasi err = l2cap_disconnect_rsp(conn, cmd, data); 38383300d9a9SClaudio Takahasi break; 38393300d9a9SClaudio Takahasi 38403300d9a9SClaudio Takahasi case L2CAP_ECHO_REQ: 38413300d9a9SClaudio Takahasi l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data); 38423300d9a9SClaudio Takahasi break; 38433300d9a9SClaudio Takahasi 38443300d9a9SClaudio Takahasi case L2CAP_ECHO_RSP: 38453300d9a9SClaudio Takahasi break; 38463300d9a9SClaudio Takahasi 38473300d9a9SClaudio Takahasi case L2CAP_INFO_REQ: 38483300d9a9SClaudio Takahasi err = l2cap_information_req(conn, cmd, data); 38493300d9a9SClaudio Takahasi break; 38503300d9a9SClaudio Takahasi 38513300d9a9SClaudio Takahasi case L2CAP_INFO_RSP: 38523300d9a9SClaudio Takahasi err = l2cap_information_rsp(conn, cmd, data); 38533300d9a9SClaudio Takahasi break; 38543300d9a9SClaudio Takahasi 3855f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_REQ: 3856f94ff6ffSMat Martineau err = l2cap_create_channel_req(conn, cmd, cmd_len, data); 3857f94ff6ffSMat Martineau break; 3858f94ff6ffSMat Martineau 3859f94ff6ffSMat Martineau case L2CAP_CREATE_CHAN_RSP: 3860f94ff6ffSMat Martineau err = l2cap_create_channel_rsp(conn, cmd, data); 3861f94ff6ffSMat Martineau break; 3862f94ff6ffSMat Martineau 38638d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_REQ: 38648d5a04a1SMat Martineau err = l2cap_move_channel_req(conn, cmd, cmd_len, data); 38658d5a04a1SMat Martineau break; 38668d5a04a1SMat Martineau 38678d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_RSP: 38688d5a04a1SMat Martineau err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data); 38698d5a04a1SMat Martineau break; 38708d5a04a1SMat Martineau 38718d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM: 38728d5a04a1SMat Martineau err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data); 38738d5a04a1SMat Martineau break; 38748d5a04a1SMat Martineau 38758d5a04a1SMat Martineau case L2CAP_MOVE_CHAN_CFM_RSP: 38768d5a04a1SMat Martineau err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data); 38778d5a04a1SMat Martineau break; 38788d5a04a1SMat Martineau 38793300d9a9SClaudio Takahasi default: 38803300d9a9SClaudio Takahasi BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code); 38813300d9a9SClaudio Takahasi err = -EINVAL; 38823300d9a9SClaudio Takahasi break; 38833300d9a9SClaudio Takahasi } 38843300d9a9SClaudio Takahasi 38853300d9a9SClaudio Takahasi return err; 38863300d9a9SClaudio Takahasi } 38873300d9a9SClaudio Takahasi 38883300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, 38893300d9a9SClaudio Takahasi struct l2cap_cmd_hdr *cmd, u8 *data) 38903300d9a9SClaudio Takahasi { 38913300d9a9SClaudio Takahasi switch (cmd->code) { 38923300d9a9SClaudio Takahasi case L2CAP_COMMAND_REJ: 38933300d9a9SClaudio Takahasi return 0; 38943300d9a9SClaudio Takahasi 38953300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_REQ: 3896de73115aSClaudio Takahasi return l2cap_conn_param_update_req(conn, cmd, data); 38973300d9a9SClaudio Takahasi 38983300d9a9SClaudio Takahasi case L2CAP_CONN_PARAM_UPDATE_RSP: 38993300d9a9SClaudio Takahasi return 0; 39003300d9a9SClaudio Takahasi 39013300d9a9SClaudio Takahasi default: 39023300d9a9SClaudio Takahasi BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code); 39033300d9a9SClaudio Takahasi return -EINVAL; 39043300d9a9SClaudio Takahasi } 39053300d9a9SClaudio Takahasi } 39063300d9a9SClaudio Takahasi 39073300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn, 39083300d9a9SClaudio Takahasi struct sk_buff *skb) 39090a708f8fSGustavo F. Padovan { 39100a708f8fSGustavo F. Padovan u8 *data = skb->data; 39110a708f8fSGustavo F. Padovan int len = skb->len; 39120a708f8fSGustavo F. Padovan struct l2cap_cmd_hdr cmd; 39133300d9a9SClaudio Takahasi int err; 39140a708f8fSGustavo F. Padovan 39150a708f8fSGustavo F. Padovan l2cap_raw_recv(conn, skb); 39160a708f8fSGustavo F. Padovan 39170a708f8fSGustavo F. Padovan while (len >= L2CAP_CMD_HDR_SIZE) { 39180a708f8fSGustavo F. Padovan u16 cmd_len; 39190a708f8fSGustavo F. Padovan memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); 39200a708f8fSGustavo F. Padovan data += L2CAP_CMD_HDR_SIZE; 39210a708f8fSGustavo F. Padovan len -= L2CAP_CMD_HDR_SIZE; 39220a708f8fSGustavo F. Padovan 39230a708f8fSGustavo F. Padovan cmd_len = le16_to_cpu(cmd.len); 39240a708f8fSGustavo F. Padovan 39250a708f8fSGustavo F. Padovan BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident); 39260a708f8fSGustavo F. Padovan 39270a708f8fSGustavo F. Padovan if (cmd_len > len || !cmd.ident) { 39280a708f8fSGustavo F. Padovan BT_DBG("corrupted command"); 39290a708f8fSGustavo F. Padovan break; 39300a708f8fSGustavo F. Padovan } 39310a708f8fSGustavo F. Padovan 39323300d9a9SClaudio Takahasi if (conn->hcon->type == LE_LINK) 39333300d9a9SClaudio Takahasi err = l2cap_le_sig_cmd(conn, &cmd, data); 39343300d9a9SClaudio Takahasi else 39353300d9a9SClaudio Takahasi err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data); 39360a708f8fSGustavo F. Padovan 39370a708f8fSGustavo F. Padovan if (err) { 3938e2fd318eSIlia Kolomisnky struct l2cap_cmd_rej_unk rej; 39392c6d1a2eSGustavo F. Padovan 39402c6d1a2eSGustavo F. Padovan BT_ERR("Wrong link type (%d)", err); 39410a708f8fSGustavo F. Padovan 39420a708f8fSGustavo F. Padovan /* FIXME: Map err to a valid reason */ 3943e2fd318eSIlia Kolomisnky rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); 39440a708f8fSGustavo F. Padovan l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); 39450a708f8fSGustavo F. Padovan } 39460a708f8fSGustavo F. Padovan 39470a708f8fSGustavo F. Padovan data += cmd_len; 39480a708f8fSGustavo F. Padovan len -= cmd_len; 39490a708f8fSGustavo F. Padovan } 39500a708f8fSGustavo F. Padovan 39510a708f8fSGustavo F. Padovan kfree_skb(skb); 39520a708f8fSGustavo F. Padovan } 39530a708f8fSGustavo F. Padovan 395447d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) 39550a708f8fSGustavo F. Padovan { 39560a708f8fSGustavo F. Padovan u16 our_fcs, rcv_fcs; 3957e4ca6d98SAndrei Emeltchenko int hdr_size; 3958e4ca6d98SAndrei Emeltchenko 3959e4ca6d98SAndrei Emeltchenko if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 3960e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_EXT_HDR_SIZE; 3961e4ca6d98SAndrei Emeltchenko else 3962e4ca6d98SAndrei Emeltchenko hdr_size = L2CAP_ENH_HDR_SIZE; 39630a708f8fSGustavo F. Padovan 396447d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) { 396503a51213SAndrei Emeltchenko skb_trim(skb, skb->len - L2CAP_FCS_SIZE); 39660a708f8fSGustavo F. Padovan rcv_fcs = get_unaligned_le16(skb->data + skb->len); 39670a708f8fSGustavo F. Padovan our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); 39680a708f8fSGustavo F. Padovan 39690a708f8fSGustavo F. Padovan if (our_fcs != rcv_fcs) 39700a708f8fSGustavo F. Padovan return -EBADMSG; 39710a708f8fSGustavo F. Padovan } 39720a708f8fSGustavo F. Padovan return 0; 39730a708f8fSGustavo F. Padovan } 39740a708f8fSGustavo F. Padovan 3975525cd185SGustavo F. Padovan static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) 39760a708f8fSGustavo F. Padovan { 397788843ab0SAndrei Emeltchenko u32 control = 0; 39780a708f8fSGustavo F. Padovan 39796a026610SGustavo F. Padovan chan->frames_sent = 0; 39800a708f8fSGustavo F. Padovan 39810b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->buffer_seq); 39820a708f8fSGustavo F. Padovan 3983e2ab4353SGustavo F. Padovan if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 3984ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); 3985525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 3986e2ab4353SGustavo F. Padovan set_bit(CONN_RNR_SENT, &chan->conn_state); 39870a708f8fSGustavo F. Padovan } 39880a708f8fSGustavo F. Padovan 3989e2ab4353SGustavo F. Padovan if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 3990525cd185SGustavo F. Padovan l2cap_retransmit_frames(chan); 39910a708f8fSGustavo F. Padovan 3992525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 39930a708f8fSGustavo F. Padovan 3994e2ab4353SGustavo F. Padovan if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 39956a026610SGustavo F. Padovan chan->frames_sent == 0) { 3996ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 3997525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 39980a708f8fSGustavo F. Padovan } 39990a708f8fSGustavo F. Padovan } 40000a708f8fSGustavo F. Padovan 4001fb45de7dSAndrei Emeltchenko static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u16 tx_seq, u8 sar) 40020a708f8fSGustavo F. Padovan { 40030a708f8fSGustavo F. Padovan struct sk_buff *next_skb; 40040a708f8fSGustavo F. Padovan int tx_seq_offset, next_tx_seq_offset; 40050a708f8fSGustavo F. Padovan 40063ce3514fSMat Martineau bt_cb(skb)->control.txseq = tx_seq; 40073ce3514fSMat Martineau bt_cb(skb)->control.sar = sar; 40080a708f8fSGustavo F. Padovan 4009f1c6775bSGustavo F. Padovan next_skb = skb_peek(&chan->srej_q); 40100a708f8fSGustavo F. Padovan 4011836be934SAndrei Emeltchenko tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq); 40120a708f8fSGustavo F. Padovan 4013039d9572SSzymon Janc while (next_skb) { 40143ce3514fSMat Martineau if (bt_cb(next_skb)->control.txseq == tx_seq) 40150a708f8fSGustavo F. Padovan return -EINVAL; 40160a708f8fSGustavo F. Padovan 4017836be934SAndrei Emeltchenko next_tx_seq_offset = __seq_offset(chan, 40183ce3514fSMat Martineau bt_cb(next_skb)->control.txseq, chan->buffer_seq); 40190a708f8fSGustavo F. Padovan 40200a708f8fSGustavo F. Padovan if (next_tx_seq_offset > tx_seq_offset) { 4021f1c6775bSGustavo F. Padovan __skb_queue_before(&chan->srej_q, next_skb, skb); 40220a708f8fSGustavo F. Padovan return 0; 40230a708f8fSGustavo F. Padovan } 40240a708f8fSGustavo F. Padovan 4025f1c6775bSGustavo F. Padovan if (skb_queue_is_last(&chan->srej_q, next_skb)) 4026039d9572SSzymon Janc next_skb = NULL; 4027039d9572SSzymon Janc else 4028039d9572SSzymon Janc next_skb = skb_queue_next(&chan->srej_q, next_skb); 4029039d9572SSzymon Janc } 40300a708f8fSGustavo F. Padovan 4031f1c6775bSGustavo F. Padovan __skb_queue_tail(&chan->srej_q, skb); 40320a708f8fSGustavo F. Padovan 40330a708f8fSGustavo F. Padovan return 0; 40340a708f8fSGustavo F. Padovan } 40350a708f8fSGustavo F. Padovan 403684084a31SMat Martineau static void append_skb_frag(struct sk_buff *skb, 403784084a31SMat Martineau struct sk_buff *new_frag, struct sk_buff **last_frag) 40380a708f8fSGustavo F. Padovan { 403984084a31SMat Martineau /* skb->len reflects data in skb as well as all fragments 404084084a31SMat Martineau * skb->data_len reflects only data in fragments 404184084a31SMat Martineau */ 404284084a31SMat Martineau if (!skb_has_frag_list(skb)) 404384084a31SMat Martineau skb_shinfo(skb)->frag_list = new_frag; 404484084a31SMat Martineau 404584084a31SMat Martineau new_frag->next = NULL; 404684084a31SMat Martineau 404784084a31SMat Martineau (*last_frag)->next = new_frag; 404884084a31SMat Martineau *last_frag = new_frag; 404984084a31SMat Martineau 405084084a31SMat Martineau skb->len += new_frag->len; 405184084a31SMat Martineau skb->data_len += new_frag->len; 405284084a31SMat Martineau skb->truesize += new_frag->truesize; 405384084a31SMat Martineau } 405484084a31SMat Martineau 405588843ab0SAndrei Emeltchenko static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control) 405684084a31SMat Martineau { 405784084a31SMat Martineau int err = -EINVAL; 40580a708f8fSGustavo F. Padovan 40597e0ef6eeSAndrei Emeltchenko switch (__get_ctrl_sar(chan, control)) { 40607e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_UNSEGMENTED: 406184084a31SMat Martineau if (chan->sdu) 406284084a31SMat Martineau break; 40630a708f8fSGustavo F. Padovan 406484084a31SMat Martineau err = chan->ops->recv(chan->data, skb); 406584084a31SMat Martineau break; 40660a708f8fSGustavo F. Padovan 40677e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_START: 406884084a31SMat Martineau if (chan->sdu) 406984084a31SMat Martineau break; 40700a708f8fSGustavo F. Padovan 40716f61fd47SGustavo F. Padovan chan->sdu_len = get_unaligned_le16(skb->data); 407203a51213SAndrei Emeltchenko skb_pull(skb, L2CAP_SDULEN_SIZE); 40730a708f8fSGustavo F. Padovan 407484084a31SMat Martineau if (chan->sdu_len > chan->imtu) { 407584084a31SMat Martineau err = -EMSGSIZE; 407684084a31SMat Martineau break; 407784084a31SMat Martineau } 40780a708f8fSGustavo F. Padovan 407984084a31SMat Martineau if (skb->len >= chan->sdu_len) 408084084a31SMat Martineau break; 408184084a31SMat Martineau 408284084a31SMat Martineau chan->sdu = skb; 408384084a31SMat Martineau chan->sdu_last_frag = skb; 408484084a31SMat Martineau 408584084a31SMat Martineau skb = NULL; 408684084a31SMat Martineau err = 0; 40870a708f8fSGustavo F. Padovan break; 40880a708f8fSGustavo F. Padovan 40897e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_CONTINUE: 40906f61fd47SGustavo F. Padovan if (!chan->sdu) 409184084a31SMat Martineau break; 40920a708f8fSGustavo F. Padovan 409384084a31SMat Martineau append_skb_frag(chan->sdu, skb, 409484084a31SMat Martineau &chan->sdu_last_frag); 409584084a31SMat Martineau skb = NULL; 40960a708f8fSGustavo F. Padovan 409784084a31SMat Martineau if (chan->sdu->len >= chan->sdu_len) 409884084a31SMat Martineau break; 40990a708f8fSGustavo F. Padovan 410084084a31SMat Martineau err = 0; 41010a708f8fSGustavo F. Padovan break; 41020a708f8fSGustavo F. Padovan 41037e0ef6eeSAndrei Emeltchenko case L2CAP_SAR_END: 41046f61fd47SGustavo F. Padovan if (!chan->sdu) 410584084a31SMat Martineau break; 41060a708f8fSGustavo F. Padovan 410784084a31SMat Martineau append_skb_frag(chan->sdu, skb, 410884084a31SMat Martineau &chan->sdu_last_frag); 410984084a31SMat Martineau skb = NULL; 41100a708f8fSGustavo F. Padovan 411184084a31SMat Martineau if (chan->sdu->len != chan->sdu_len) 411284084a31SMat Martineau break; 41130a708f8fSGustavo F. Padovan 411484084a31SMat Martineau err = chan->ops->recv(chan->data, chan->sdu); 41150a708f8fSGustavo F. Padovan 411684084a31SMat Martineau if (!err) { 411784084a31SMat Martineau /* Reassembly complete */ 411884084a31SMat Martineau chan->sdu = NULL; 411984084a31SMat Martineau chan->sdu_last_frag = NULL; 412084084a31SMat Martineau chan->sdu_len = 0; 41210a708f8fSGustavo F. Padovan } 41220a708f8fSGustavo F. Padovan break; 41230a708f8fSGustavo F. Padovan } 41240a708f8fSGustavo F. Padovan 412584084a31SMat Martineau if (err) { 41260a708f8fSGustavo F. Padovan kfree_skb(skb); 41276f61fd47SGustavo F. Padovan kfree_skb(chan->sdu); 41286f61fd47SGustavo F. Padovan chan->sdu = NULL; 412984084a31SMat Martineau chan->sdu_last_frag = NULL; 413084084a31SMat Martineau chan->sdu_len = 0; 413184084a31SMat Martineau } 41320a708f8fSGustavo F. Padovan 413384084a31SMat Martineau return err; 41340a708f8fSGustavo F. Padovan } 41350a708f8fSGustavo F. Padovan 413626f880d2SMat Martineau static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan) 41370a708f8fSGustavo F. Padovan { 413826f880d2SMat Martineau BT_DBG("chan %p, Enter local busy", chan); 413926f880d2SMat Martineau 414026f880d2SMat Martineau set_bit(CONN_LOCAL_BUSY, &chan->conn_state); 41413c588192SMat Martineau l2cap_seq_list_clear(&chan->srej_list); 414226f880d2SMat Martineau 414377f918bcSSzymon Janc __set_ack_timer(chan); 41440a708f8fSGustavo F. Padovan } 41450a708f8fSGustavo F. Padovan 414626f880d2SMat Martineau static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan) 414726f880d2SMat Martineau { 414888843ab0SAndrei Emeltchenko u32 control; 41490a708f8fSGustavo F. Padovan 4150e2ab4353SGustavo F. Padovan if (!test_bit(CONN_RNR_SENT, &chan->conn_state)) 41510a708f8fSGustavo F. Padovan goto done; 41520a708f8fSGustavo F. Padovan 41530b209faeSAndrei Emeltchenko control = __set_reqseq(chan, chan->buffer_seq); 4154e3781735SAndrei Emeltchenko control |= __set_ctrl_poll(chan); 4155ab784b73SAndrei Emeltchenko control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 4156525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 41576a026610SGustavo F. Padovan chan->retry_count = 1; 41580a708f8fSGustavo F. Padovan 41591a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 41601a09bcb9SGustavo F. Padovan __set_monitor_timer(chan); 41610a708f8fSGustavo F. Padovan 4162e2ab4353SGustavo F. Padovan set_bit(CONN_WAIT_F, &chan->conn_state); 41630a708f8fSGustavo F. Padovan 41640a708f8fSGustavo F. Padovan done: 4165e2ab4353SGustavo F. Padovan clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); 4166e2ab4353SGustavo F. Padovan clear_bit(CONN_RNR_SENT, &chan->conn_state); 41670a708f8fSGustavo F. Padovan 416849208c9cSGustavo F. Padovan BT_DBG("chan %p, Exit local busy", chan); 41690a708f8fSGustavo F. Padovan } 41700a708f8fSGustavo F. Padovan 4171e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 41720a708f8fSGustavo F. Padovan { 4173e328140fSMat Martineau if (chan->mode == L2CAP_MODE_ERTM) { 4174e328140fSMat Martineau if (busy) 417526f880d2SMat Martineau l2cap_ertm_enter_local_busy(chan); 4176e328140fSMat Martineau else 4177e328140fSMat Martineau l2cap_ertm_exit_local_busy(chan); 41780a708f8fSGustavo F. Padovan } 41790a708f8fSGustavo F. Padovan } 41800a708f8fSGustavo F. Padovan 4181fb45de7dSAndrei Emeltchenko static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq) 41820a708f8fSGustavo F. Padovan { 41830a708f8fSGustavo F. Padovan struct sk_buff *skb; 418488843ab0SAndrei Emeltchenko u32 control; 41850a708f8fSGustavo F. Padovan 4186e328140fSMat Martineau while ((skb = skb_peek(&chan->srej_q)) && 4187e328140fSMat Martineau !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 4188e328140fSMat Martineau int err; 4189e328140fSMat Martineau 41903ce3514fSMat Martineau if (bt_cb(skb)->control.txseq != tx_seq) 41910a708f8fSGustavo F. Padovan break; 41920a708f8fSGustavo F. Padovan 4193f1c6775bSGustavo F. Padovan skb = skb_dequeue(&chan->srej_q); 41943ce3514fSMat Martineau control = __set_ctrl_sar(chan, bt_cb(skb)->control.sar); 419584084a31SMat Martineau err = l2cap_reassemble_sdu(chan, skb, control); 4196e328140fSMat Martineau 4197e328140fSMat Martineau if (err < 0) { 4198e328140fSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 4199e328140fSMat Martineau break; 4200e328140fSMat Martineau } 4201e328140fSMat Martineau 4202836be934SAndrei Emeltchenko chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej); 4203836be934SAndrei Emeltchenko tx_seq = __next_seq(chan, tx_seq); 42040a708f8fSGustavo F. Padovan } 42050a708f8fSGustavo F. Padovan } 42060a708f8fSGustavo F. Padovan 4207fb45de7dSAndrei Emeltchenko static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq) 42080a708f8fSGustavo F. Padovan { 42090a708f8fSGustavo F. Padovan struct srej_list *l, *tmp; 421088843ab0SAndrei Emeltchenko u32 control; 42110a708f8fSGustavo F. Padovan 421239d5a3eeSGustavo F. Padovan list_for_each_entry_safe(l, tmp, &chan->srej_l, list) { 42130a708f8fSGustavo F. Padovan if (l->tx_seq == tx_seq) { 42140a708f8fSGustavo F. Padovan list_del(&l->list); 42150a708f8fSGustavo F. Padovan kfree(l); 42160a708f8fSGustavo F. Padovan return; 42170a708f8fSGustavo F. Padovan } 4218ab784b73SAndrei Emeltchenko control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ); 42190b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, l->tx_seq); 4220525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 42210a708f8fSGustavo F. Padovan list_del(&l->list); 422239d5a3eeSGustavo F. Padovan list_add_tail(&l->list, &chan->srej_l); 42230a708f8fSGustavo F. Padovan } 42240a708f8fSGustavo F. Padovan } 42250a708f8fSGustavo F. Padovan 4226aef89f21SSzymon Janc static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq) 42270a708f8fSGustavo F. Padovan { 42280a708f8fSGustavo F. Padovan struct srej_list *new; 422988843ab0SAndrei Emeltchenko u32 control; 42300a708f8fSGustavo F. Padovan 423142e5c802SGustavo F. Padovan while (tx_seq != chan->expected_tx_seq) { 4232ab784b73SAndrei Emeltchenko control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ); 42330b209faeSAndrei Emeltchenko control |= __set_reqseq(chan, chan->expected_tx_seq); 42343c588192SMat Martineau l2cap_seq_list_append(&chan->srej_list, chan->expected_tx_seq); 4235525cd185SGustavo F. Padovan l2cap_send_sframe(chan, control); 42360a708f8fSGustavo F. Padovan 42370a708f8fSGustavo F. Padovan new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); 4238aef89f21SSzymon Janc if (!new) 4239aef89f21SSzymon Janc return -ENOMEM; 4240aef89f21SSzymon Janc 424142e5c802SGustavo F. Padovan new->tx_seq = chan->expected_tx_seq; 4242836be934SAndrei Emeltchenko 4243836be934SAndrei Emeltchenko chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); 4244836be934SAndrei Emeltchenko 424539d5a3eeSGustavo F. Padovan list_add_tail(&new->list, &chan->srej_l); 42460a708f8fSGustavo F. Padovan } 4247836be934SAndrei Emeltchenko 4248836be934SAndrei Emeltchenko chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); 4249aef89f21SSzymon Janc 4250aef89f21SSzymon Janc return 0; 42510a708f8fSGustavo F. Padovan } 42520a708f8fSGustavo F. Padovan 425388843ab0SAndrei Emeltchenko static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb) 42540a708f8fSGustavo F. Padovan { 4255fb45de7dSAndrei Emeltchenko u16 tx_seq = __get_txseq(chan, rx_control); 42560b209faeSAndrei Emeltchenko u16 req_seq = __get_reqseq(chan, rx_control); 42577e0ef6eeSAndrei Emeltchenko u8 sar = __get_ctrl_sar(chan, rx_control); 42580a708f8fSGustavo F. Padovan int tx_seq_offset, expected_tx_seq_offset; 425947d1ec61SGustavo F. Padovan int num_to_ack = (chan->tx_win/6) + 1; 42600a708f8fSGustavo F. Padovan int err = 0; 42610a708f8fSGustavo F. Padovan 426288843ab0SAndrei Emeltchenko BT_DBG("chan %p len %d tx_seq %d rx_control 0x%8.8x", chan, skb->len, 4263525cd185SGustavo F. Padovan tx_seq, rx_control); 42640a708f8fSGustavo F. Padovan 426503f6715dSAndrei Emeltchenko if (__is_ctrl_final(chan, rx_control) && 4266e2ab4353SGustavo F. Padovan test_bit(CONN_WAIT_F, &chan->conn_state)) { 42671a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 42686a026610SGustavo F. Padovan if (chan->unacked_frames > 0) 42691a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 4270e2ab4353SGustavo F. Padovan clear_bit(CONN_WAIT_F, &chan->conn_state); 42710a708f8fSGustavo F. Padovan } 42720a708f8fSGustavo F. Padovan 427342e5c802SGustavo F. Padovan chan->expected_ack_seq = req_seq; 427442e5c802SGustavo F. Padovan l2cap_drop_acked_frames(chan); 42750a708f8fSGustavo F. Padovan 4276836be934SAndrei Emeltchenko tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq); 42770a708f8fSGustavo F. Padovan 42780a708f8fSGustavo F. Padovan /* invalid tx_seq */ 427947d1ec61SGustavo F. Padovan if (tx_seq_offset >= chan->tx_win) { 42808c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 42810a708f8fSGustavo F. Padovan goto drop; 42820a708f8fSGustavo F. Padovan } 42830a708f8fSGustavo F. Padovan 428477f918bcSSzymon Janc if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 428577f918bcSSzymon Janc if (!test_bit(CONN_RNR_SENT, &chan->conn_state)) 428677f918bcSSzymon Janc l2cap_send_ack(chan); 42870a708f8fSGustavo F. Padovan goto drop; 428877f918bcSSzymon Janc } 42890a708f8fSGustavo F. Padovan 429002f1b641SMat Martineau if (tx_seq == chan->expected_tx_seq) 429102f1b641SMat Martineau goto expected; 429202f1b641SMat Martineau 4293e2ab4353SGustavo F. Padovan if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) { 42940a708f8fSGustavo F. Padovan struct srej_list *first; 42950a708f8fSGustavo F. Padovan 429639d5a3eeSGustavo F. Padovan first = list_first_entry(&chan->srej_l, 42970a708f8fSGustavo F. Padovan struct srej_list, list); 42980a708f8fSGustavo F. Padovan if (tx_seq == first->tx_seq) { 429942e5c802SGustavo F. Padovan l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); 4300525cd185SGustavo F. Padovan l2cap_check_srej_gap(chan, tx_seq); 43010a708f8fSGustavo F. Padovan 43020a708f8fSGustavo F. Padovan list_del(&first->list); 43030a708f8fSGustavo F. Padovan kfree(first); 43040a708f8fSGustavo F. Padovan 430539d5a3eeSGustavo F. Padovan if (list_empty(&chan->srej_l)) { 430642e5c802SGustavo F. Padovan chan->buffer_seq = chan->buffer_seq_srej; 4307e2ab4353SGustavo F. Padovan clear_bit(CONN_SREJ_SENT, &chan->conn_state); 4308525cd185SGustavo F. Padovan l2cap_send_ack(chan); 430949208c9cSGustavo F. Padovan BT_DBG("chan %p, Exit SREJ_SENT", chan); 43100a708f8fSGustavo F. Padovan } 43110a708f8fSGustavo F. Padovan } else { 43120a708f8fSGustavo F. Padovan struct srej_list *l; 43130a708f8fSGustavo F. Padovan 43140a708f8fSGustavo F. Padovan /* duplicated tx_seq */ 431542e5c802SGustavo F. Padovan if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0) 43160a708f8fSGustavo F. Padovan goto drop; 43170a708f8fSGustavo F. Padovan 431839d5a3eeSGustavo F. Padovan list_for_each_entry(l, &chan->srej_l, list) { 43190a708f8fSGustavo F. Padovan if (l->tx_seq == tx_seq) { 4320525cd185SGustavo F. Padovan l2cap_resend_srejframe(chan, tx_seq); 43210a708f8fSGustavo F. Padovan return 0; 43220a708f8fSGustavo F. Padovan } 43230a708f8fSGustavo F. Padovan } 4324aef89f21SSzymon Janc 4325aef89f21SSzymon Janc err = l2cap_send_srejframe(chan, tx_seq); 4326aef89f21SSzymon Janc if (err < 0) { 4327aef89f21SSzymon Janc l2cap_send_disconn_req(chan->conn, chan, -err); 4328aef89f21SSzymon Janc return err; 4329aef89f21SSzymon Janc } 43300a708f8fSGustavo F. Padovan } 43310a708f8fSGustavo F. Padovan } else { 4332836be934SAndrei Emeltchenko expected_tx_seq_offset = __seq_offset(chan, 4333836be934SAndrei Emeltchenko chan->expected_tx_seq, chan->buffer_seq); 43340a708f8fSGustavo F. Padovan 43350a708f8fSGustavo F. Padovan /* duplicated tx_seq */ 43360a708f8fSGustavo F. Padovan if (tx_seq_offset < expected_tx_seq_offset) 43370a708f8fSGustavo F. Padovan goto drop; 43380a708f8fSGustavo F. Padovan 4339e2ab4353SGustavo F. Padovan set_bit(CONN_SREJ_SENT, &chan->conn_state); 43400a708f8fSGustavo F. Padovan 434149208c9cSGustavo F. Padovan BT_DBG("chan %p, Enter SREJ", chan); 43420a708f8fSGustavo F. Padovan 434339d5a3eeSGustavo F. Padovan INIT_LIST_HEAD(&chan->srej_l); 434442e5c802SGustavo F. Padovan chan->buffer_seq_srej = chan->buffer_seq; 43450a708f8fSGustavo F. Padovan 4346f1c6775bSGustavo F. Padovan __skb_queue_head_init(&chan->srej_q); 434742e5c802SGustavo F. Padovan l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); 43480a708f8fSGustavo F. Padovan 43490ef3ef0fSSzymon Janc /* Set P-bit only if there are some I-frames to ack. */ 43500ef3ef0fSSzymon Janc if (__clear_ack_timer(chan)) 4351e2ab4353SGustavo F. Padovan set_bit(CONN_SEND_PBIT, &chan->conn_state); 43520a708f8fSGustavo F. Padovan 4353aef89f21SSzymon Janc err = l2cap_send_srejframe(chan, tx_seq); 4354aef89f21SSzymon Janc if (err < 0) { 4355aef89f21SSzymon Janc l2cap_send_disconn_req(chan->conn, chan, -err); 4356aef89f21SSzymon Janc return err; 4357aef89f21SSzymon Janc } 43580a708f8fSGustavo F. Padovan } 43590a708f8fSGustavo F. Padovan return 0; 43600a708f8fSGustavo F. Padovan 43610a708f8fSGustavo F. Padovan expected: 4362836be934SAndrei Emeltchenko chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); 43630a708f8fSGustavo F. Padovan 4364e2ab4353SGustavo F. Padovan if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) { 43653ce3514fSMat Martineau bt_cb(skb)->control.txseq = tx_seq; 43663ce3514fSMat Martineau bt_cb(skb)->control.sar = sar; 4367f1c6775bSGustavo F. Padovan __skb_queue_tail(&chan->srej_q, skb); 43680a708f8fSGustavo F. Padovan return 0; 43690a708f8fSGustavo F. Padovan } 43700a708f8fSGustavo F. Padovan 437184084a31SMat Martineau err = l2cap_reassemble_sdu(chan, skb, rx_control); 4372836be934SAndrei Emeltchenko chan->buffer_seq = __next_seq(chan, chan->buffer_seq); 4373836be934SAndrei Emeltchenko 4374e328140fSMat Martineau if (err < 0) { 4375e328140fSMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 4376e328140fSMat Martineau return err; 4377e328140fSMat Martineau } 43780a708f8fSGustavo F. Padovan 437903f6715dSAndrei Emeltchenko if (__is_ctrl_final(chan, rx_control)) { 4380e2ab4353SGustavo F. Padovan if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 4381525cd185SGustavo F. Padovan l2cap_retransmit_frames(chan); 43820a708f8fSGustavo F. Padovan } 43830a708f8fSGustavo F. Padovan 43840a708f8fSGustavo F. Padovan 43856a026610SGustavo F. Padovan chan->num_acked = (chan->num_acked + 1) % num_to_ack; 43866a026610SGustavo F. Padovan if (chan->num_acked == num_to_ack - 1) 4387525cd185SGustavo F. Padovan l2cap_send_ack(chan); 43884d611e4dSGustavo F. Padovan else 43894d611e4dSGustavo F. Padovan __set_ack_timer(chan); 43900a708f8fSGustavo F. Padovan 43910a708f8fSGustavo F. Padovan return 0; 43920a708f8fSGustavo F. Padovan 43930a708f8fSGustavo F. Padovan drop: 43940a708f8fSGustavo F. Padovan kfree_skb(skb); 43950a708f8fSGustavo F. Padovan return 0; 43960a708f8fSGustavo F. Padovan } 43970a708f8fSGustavo F. Padovan 439888843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control) 43990a708f8fSGustavo F. Padovan { 440088843ab0SAndrei Emeltchenko BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, 44010b209faeSAndrei Emeltchenko __get_reqseq(chan, rx_control), rx_control); 44020a708f8fSGustavo F. Padovan 44030b209faeSAndrei Emeltchenko chan->expected_ack_seq = __get_reqseq(chan, rx_control); 440442e5c802SGustavo F. Padovan l2cap_drop_acked_frames(chan); 44050a708f8fSGustavo F. Padovan 4406e3781735SAndrei Emeltchenko if (__is_ctrl_poll(chan, rx_control)) { 4407e2ab4353SGustavo F. Padovan set_bit(CONN_SEND_FBIT, &chan->conn_state); 4408e2ab4353SGustavo F. Padovan if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) { 4409e2ab4353SGustavo F. Padovan if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 44106a026610SGustavo F. Padovan (chan->unacked_frames > 0)) 44111a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 44120a708f8fSGustavo F. Padovan 4413e2ab4353SGustavo F. Padovan clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4414525cd185SGustavo F. Padovan l2cap_send_srejtail(chan); 44150a708f8fSGustavo F. Padovan } else { 4416525cd185SGustavo F. Padovan l2cap_send_i_or_rr_or_rnr(chan); 44170a708f8fSGustavo F. Padovan } 44180a708f8fSGustavo F. Padovan 441903f6715dSAndrei Emeltchenko } else if (__is_ctrl_final(chan, rx_control)) { 4420e2ab4353SGustavo F. Padovan clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 44210a708f8fSGustavo F. Padovan 4422e2ab4353SGustavo F. Padovan if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 4423525cd185SGustavo F. Padovan l2cap_retransmit_frames(chan); 44240a708f8fSGustavo F. Padovan 44250a708f8fSGustavo F. Padovan } else { 4426e2ab4353SGustavo F. Padovan if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) && 44276a026610SGustavo F. Padovan (chan->unacked_frames > 0)) 44281a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 44290a708f8fSGustavo F. Padovan 4430e2ab4353SGustavo F. Padovan clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 4431e2ab4353SGustavo F. Padovan if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) 4432525cd185SGustavo F. Padovan l2cap_send_ack(chan); 44330a708f8fSGustavo F. Padovan else 4434525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 44350a708f8fSGustavo F. Padovan } 44360a708f8fSGustavo F. Padovan } 44370a708f8fSGustavo F. Padovan 443888843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control) 44390a708f8fSGustavo F. Padovan { 44400b209faeSAndrei Emeltchenko u16 tx_seq = __get_reqseq(chan, rx_control); 44410a708f8fSGustavo F. Padovan 444288843ab0SAndrei Emeltchenko BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control); 44430a708f8fSGustavo F. Padovan 4444e2ab4353SGustavo F. Padovan clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 44450a708f8fSGustavo F. Padovan 444642e5c802SGustavo F. Padovan chan->expected_ack_seq = tx_seq; 444742e5c802SGustavo F. Padovan l2cap_drop_acked_frames(chan); 44480a708f8fSGustavo F. Padovan 444903f6715dSAndrei Emeltchenko if (__is_ctrl_final(chan, rx_control)) { 4450e2ab4353SGustavo F. Padovan if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 4451525cd185SGustavo F. Padovan l2cap_retransmit_frames(chan); 44520a708f8fSGustavo F. Padovan } else { 4453525cd185SGustavo F. Padovan l2cap_retransmit_frames(chan); 44540a708f8fSGustavo F. Padovan 4455e2ab4353SGustavo F. Padovan if (test_bit(CONN_WAIT_F, &chan->conn_state)) 4456e2ab4353SGustavo F. Padovan set_bit(CONN_REJ_ACT, &chan->conn_state); 44570a708f8fSGustavo F. Padovan } 44580a708f8fSGustavo F. Padovan } 445988843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control) 44600a708f8fSGustavo F. Padovan { 44610b209faeSAndrei Emeltchenko u16 tx_seq = __get_reqseq(chan, rx_control); 44620a708f8fSGustavo F. Padovan 446388843ab0SAndrei Emeltchenko BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control); 44640a708f8fSGustavo F. Padovan 4465e2ab4353SGustavo F. Padovan clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); 44660a708f8fSGustavo F. Padovan 4467e3781735SAndrei Emeltchenko if (__is_ctrl_poll(chan, rx_control)) { 446842e5c802SGustavo F. Padovan chan->expected_ack_seq = tx_seq; 446942e5c802SGustavo F. Padovan l2cap_drop_acked_frames(chan); 44700a708f8fSGustavo F. Padovan 4471e2ab4353SGustavo F. Padovan set_bit(CONN_SEND_FBIT, &chan->conn_state); 4472525cd185SGustavo F. Padovan l2cap_retransmit_one_frame(chan, tx_seq); 44730a708f8fSGustavo F. Padovan 4474525cd185SGustavo F. Padovan l2cap_ertm_send(chan); 44750a708f8fSGustavo F. Padovan 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 } 448003f6715dSAndrei Emeltchenko } else if (__is_ctrl_final(chan, rx_control)) { 4481e2ab4353SGustavo F. Padovan if (test_bit(CONN_SREJ_ACT, &chan->conn_state) && 44826a026610SGustavo F. Padovan chan->srej_save_reqseq == tx_seq) 4483e2ab4353SGustavo F. Padovan clear_bit(CONN_SREJ_ACT, &chan->conn_state); 44840a708f8fSGustavo F. Padovan else 4485525cd185SGustavo F. Padovan l2cap_retransmit_one_frame(chan, tx_seq); 44860a708f8fSGustavo F. Padovan } else { 4487525cd185SGustavo F. Padovan l2cap_retransmit_one_frame(chan, tx_seq); 4488e2ab4353SGustavo F. Padovan if (test_bit(CONN_WAIT_F, &chan->conn_state)) { 44896a026610SGustavo F. Padovan chan->srej_save_reqseq = tx_seq; 4490e2ab4353SGustavo F. Padovan set_bit(CONN_SREJ_ACT, &chan->conn_state); 44910a708f8fSGustavo F. Padovan } 44920a708f8fSGustavo F. Padovan } 44930a708f8fSGustavo F. Padovan } 44940a708f8fSGustavo F. Padovan 449588843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control) 44960a708f8fSGustavo F. Padovan { 44970b209faeSAndrei Emeltchenko u16 tx_seq = __get_reqseq(chan, rx_control); 44980a708f8fSGustavo F. Padovan 449988843ab0SAndrei Emeltchenko BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control); 45000a708f8fSGustavo F. Padovan 4501e2ab4353SGustavo F. Padovan set_bit(CONN_REMOTE_BUSY, &chan->conn_state); 450242e5c802SGustavo F. Padovan chan->expected_ack_seq = tx_seq; 450342e5c802SGustavo F. Padovan l2cap_drop_acked_frames(chan); 45040a708f8fSGustavo F. Padovan 4505e3781735SAndrei Emeltchenko if (__is_ctrl_poll(chan, rx_control)) 4506e2ab4353SGustavo F. Padovan set_bit(CONN_SEND_FBIT, &chan->conn_state); 45070a708f8fSGustavo F. Padovan 4508e2ab4353SGustavo F. Padovan if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) { 45091a09bcb9SGustavo F. Padovan __clear_retrans_timer(chan); 4510e3781735SAndrei Emeltchenko if (__is_ctrl_poll(chan, rx_control)) 4511525cd185SGustavo F. Padovan l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL); 45120a708f8fSGustavo F. Padovan return; 45130a708f8fSGustavo F. Padovan } 45140a708f8fSGustavo F. Padovan 4515e3781735SAndrei Emeltchenko if (__is_ctrl_poll(chan, rx_control)) { 4516525cd185SGustavo F. Padovan l2cap_send_srejtail(chan); 4517ab784b73SAndrei Emeltchenko } else { 4518ab784b73SAndrei Emeltchenko rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR); 4519ab784b73SAndrei Emeltchenko l2cap_send_sframe(chan, rx_control); 4520ab784b73SAndrei Emeltchenko } 45210a708f8fSGustavo F. Padovan } 45220a708f8fSGustavo F. Padovan 452388843ab0SAndrei Emeltchenko static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb) 45240a708f8fSGustavo F. Padovan { 452588843ab0SAndrei Emeltchenko BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len); 45260a708f8fSGustavo F. Padovan 452703f6715dSAndrei Emeltchenko if (__is_ctrl_final(chan, rx_control) && 4528e2ab4353SGustavo F. Padovan test_bit(CONN_WAIT_F, &chan->conn_state)) { 45291a09bcb9SGustavo F. Padovan __clear_monitor_timer(chan); 45306a026610SGustavo F. Padovan if (chan->unacked_frames > 0) 45311a09bcb9SGustavo F. Padovan __set_retrans_timer(chan); 4532e2ab4353SGustavo F. Padovan clear_bit(CONN_WAIT_F, &chan->conn_state); 45330a708f8fSGustavo F. Padovan } 45340a708f8fSGustavo F. Padovan 4535ab784b73SAndrei Emeltchenko switch (__get_ctrl_super(chan, rx_control)) { 4536ab784b73SAndrei Emeltchenko case L2CAP_SUPER_RR: 4537525cd185SGustavo F. Padovan l2cap_data_channel_rrframe(chan, rx_control); 45380a708f8fSGustavo F. Padovan break; 45390a708f8fSGustavo F. Padovan 4540ab784b73SAndrei Emeltchenko case L2CAP_SUPER_REJ: 4541525cd185SGustavo F. Padovan l2cap_data_channel_rejframe(chan, rx_control); 45420a708f8fSGustavo F. Padovan break; 45430a708f8fSGustavo F. Padovan 4544ab784b73SAndrei Emeltchenko case L2CAP_SUPER_SREJ: 4545525cd185SGustavo F. Padovan l2cap_data_channel_srejframe(chan, rx_control); 45460a708f8fSGustavo F. Padovan break; 45470a708f8fSGustavo F. Padovan 4548ab784b73SAndrei Emeltchenko case L2CAP_SUPER_RNR: 4549525cd185SGustavo F. Padovan l2cap_data_channel_rnrframe(chan, rx_control); 45500a708f8fSGustavo F. Padovan break; 45510a708f8fSGustavo F. Padovan } 45520a708f8fSGustavo F. Padovan 45530a708f8fSGustavo F. Padovan kfree_skb(skb); 45540a708f8fSGustavo F. Padovan return 0; 45550a708f8fSGustavo F. Padovan } 45560a708f8fSGustavo F. Padovan 4557cad8f1d0SSzymon Janc static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) 45580a708f8fSGustavo F. Padovan { 455988843ab0SAndrei Emeltchenko u32 control; 45600b209faeSAndrei Emeltchenko u16 req_seq; 45610a708f8fSGustavo F. Padovan int len, next_tx_seq_offset, req_seq_offset; 45620a708f8fSGustavo F. Padovan 4563b76bbd66SMat Martineau __unpack_control(chan, skb); 4564b76bbd66SMat Martineau 456588843ab0SAndrei Emeltchenko control = __get_control(chan, skb->data); 456688843ab0SAndrei Emeltchenko skb_pull(skb, __ctrl_size(chan)); 45670a708f8fSGustavo F. Padovan len = skb->len; 45680a708f8fSGustavo F. Padovan 45690a708f8fSGustavo F. Padovan /* 45700a708f8fSGustavo F. Padovan * We can just drop the corrupted I-frame here. 45710a708f8fSGustavo F. Padovan * Receiver will miss it and start proper recovery 45720a708f8fSGustavo F. Padovan * procedures and ask retransmission. 45730a708f8fSGustavo F. Padovan */ 457447d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 45750a708f8fSGustavo F. Padovan goto drop; 45760a708f8fSGustavo F. Padovan 4577793c2f1cSAndrei Emeltchenko if (__is_sar_start(chan, control) && !__is_sframe(chan, control)) 457803a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 45790a708f8fSGustavo F. Padovan 458047d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 458103a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 45820a708f8fSGustavo F. Padovan 458347d1ec61SGustavo F. Padovan if (len > chan->mps) { 45848c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 45850a708f8fSGustavo F. Padovan goto drop; 45860a708f8fSGustavo F. Padovan } 45870a708f8fSGustavo F. Padovan 45880b209faeSAndrei Emeltchenko req_seq = __get_reqseq(chan, control); 45890a708f8fSGustavo F. Padovan 4590836be934SAndrei Emeltchenko req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq); 4591836be934SAndrei Emeltchenko 4592836be934SAndrei Emeltchenko next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq, 4593836be934SAndrei Emeltchenko chan->expected_ack_seq); 45940a708f8fSGustavo F. Padovan 45950a708f8fSGustavo F. Padovan /* check for invalid req-seq */ 45960a708f8fSGustavo F. Padovan if (req_seq_offset > next_tx_seq_offset) { 45978c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 45980a708f8fSGustavo F. Padovan goto drop; 45990a708f8fSGustavo F. Padovan } 46000a708f8fSGustavo F. Padovan 4601793c2f1cSAndrei Emeltchenko if (!__is_sframe(chan, control)) { 46020a708f8fSGustavo F. Padovan if (len < 0) { 46038c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 46040a708f8fSGustavo F. Padovan goto drop; 46050a708f8fSGustavo F. Padovan } 46060a708f8fSGustavo F. Padovan 4607525cd185SGustavo F. Padovan l2cap_data_channel_iframe(chan, control, skb); 46080a708f8fSGustavo F. Padovan } else { 46090a708f8fSGustavo F. Padovan if (len != 0) { 46100a708f8fSGustavo F. Padovan BT_ERR("%d", len); 46118c1d787bSGustavo F. Padovan l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 46120a708f8fSGustavo F. Padovan goto drop; 46130a708f8fSGustavo F. Padovan } 46140a708f8fSGustavo F. Padovan 4615525cd185SGustavo F. Padovan l2cap_data_channel_sframe(chan, control, skb); 46160a708f8fSGustavo F. Padovan } 46170a708f8fSGustavo F. Padovan 46180a708f8fSGustavo F. Padovan return 0; 46190a708f8fSGustavo F. Padovan 46200a708f8fSGustavo F. Padovan drop: 46210a708f8fSGustavo F. Padovan kfree_skb(skb); 46220a708f8fSGustavo F. Padovan return 0; 46230a708f8fSGustavo F. Padovan } 46240a708f8fSGustavo F. Padovan 46250a708f8fSGustavo F. Padovan static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb) 46260a708f8fSGustavo F. Padovan { 462748454079SGustavo F. Padovan struct l2cap_chan *chan; 462888843ab0SAndrei Emeltchenko u32 control; 4629fb45de7dSAndrei Emeltchenko u16 tx_seq; 46300a708f8fSGustavo F. Padovan int len; 46310a708f8fSGustavo F. Padovan 4632baa7e1faSGustavo F. Padovan chan = l2cap_get_chan_by_scid(conn, cid); 463348454079SGustavo F. Padovan if (!chan) { 46340a708f8fSGustavo F. Padovan BT_DBG("unknown cid 0x%4.4x", cid); 46356be36555SAndrei Emeltchenko /* Drop packet and return */ 46363379013bSDan Carpenter kfree_skb(skb); 46376be36555SAndrei Emeltchenko return 0; 46380a708f8fSGustavo F. Padovan } 46390a708f8fSGustavo F. Padovan 464049208c9cSGustavo F. Padovan BT_DBG("chan %p, len %d", chan, skb->len); 46410a708f8fSGustavo F. Padovan 464289bc500eSGustavo F. Padovan if (chan->state != BT_CONNECTED) 46430a708f8fSGustavo F. Padovan goto drop; 46440a708f8fSGustavo F. Padovan 46450c1bc5c6SGustavo F. Padovan switch (chan->mode) { 46460a708f8fSGustavo F. Padovan case L2CAP_MODE_BASIC: 46470a708f8fSGustavo F. Padovan /* If socket recv buffers overflows we drop data here 46480a708f8fSGustavo F. Padovan * which is *bad* because L2CAP has to be reliable. 46490a708f8fSGustavo F. Padovan * But we don't have any other choice. L2CAP doesn't 46500a708f8fSGustavo F. Padovan * provide flow control mechanism. */ 46510a708f8fSGustavo F. Padovan 46520c1bc5c6SGustavo F. Padovan if (chan->imtu < skb->len) 46530a708f8fSGustavo F. Padovan goto drop; 46540a708f8fSGustavo F. Padovan 465523070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 46560a708f8fSGustavo F. Padovan goto done; 46570a708f8fSGustavo F. Padovan break; 46580a708f8fSGustavo F. Padovan 46590a708f8fSGustavo F. Padovan case L2CAP_MODE_ERTM: 46605ef8cb9eSAndrei Emeltchenko l2cap_ertm_data_rcv(chan, skb); 46610a708f8fSGustavo F. Padovan 46620a708f8fSGustavo F. Padovan goto done; 46630a708f8fSGustavo F. Padovan 46640a708f8fSGustavo F. Padovan case L2CAP_MODE_STREAMING: 466588843ab0SAndrei Emeltchenko control = __get_control(chan, skb->data); 466688843ab0SAndrei Emeltchenko skb_pull(skb, __ctrl_size(chan)); 46670a708f8fSGustavo F. Padovan len = skb->len; 46680a708f8fSGustavo F. Padovan 466947d1ec61SGustavo F. Padovan if (l2cap_check_fcs(chan, skb)) 46700a708f8fSGustavo F. Padovan goto drop; 46710a708f8fSGustavo F. Padovan 46727e0ef6eeSAndrei Emeltchenko if (__is_sar_start(chan, control)) 467303a51213SAndrei Emeltchenko len -= L2CAP_SDULEN_SIZE; 46740a708f8fSGustavo F. Padovan 467547d1ec61SGustavo F. Padovan if (chan->fcs == L2CAP_FCS_CRC16) 467603a51213SAndrei Emeltchenko len -= L2CAP_FCS_SIZE; 46770a708f8fSGustavo F. Padovan 4678793c2f1cSAndrei Emeltchenko if (len > chan->mps || len < 0 || __is_sframe(chan, control)) 46790a708f8fSGustavo F. Padovan goto drop; 46800a708f8fSGustavo F. Padovan 4681fb45de7dSAndrei Emeltchenko tx_seq = __get_txseq(chan, control); 46820a708f8fSGustavo F. Padovan 468384084a31SMat Martineau if (chan->expected_tx_seq != tx_seq) { 468484084a31SMat Martineau /* Frame(s) missing - must discard partial SDU */ 468584084a31SMat Martineau kfree_skb(chan->sdu); 468684084a31SMat Martineau chan->sdu = NULL; 468784084a31SMat Martineau chan->sdu_last_frag = NULL; 468884084a31SMat Martineau chan->sdu_len = 0; 468984084a31SMat Martineau 469084084a31SMat Martineau /* TODO: Notify userland of missing data */ 469184084a31SMat Martineau } 469284084a31SMat Martineau 4693836be934SAndrei Emeltchenko chan->expected_tx_seq = __next_seq(chan, tx_seq); 46940a708f8fSGustavo F. Padovan 469584084a31SMat Martineau if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE) 469684084a31SMat Martineau l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 46970a708f8fSGustavo F. Padovan 46980a708f8fSGustavo F. Padovan goto done; 46990a708f8fSGustavo F. Padovan 47000a708f8fSGustavo F. Padovan default: 47010c1bc5c6SGustavo F. Padovan BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); 47020a708f8fSGustavo F. Padovan break; 47030a708f8fSGustavo F. Padovan } 47040a708f8fSGustavo F. Padovan 47050a708f8fSGustavo F. Padovan drop: 47060a708f8fSGustavo F. Padovan kfree_skb(skb); 47070a708f8fSGustavo F. Padovan 47080a708f8fSGustavo F. Padovan done: 47096be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 47100a708f8fSGustavo F. Padovan 47110a708f8fSGustavo F. Padovan return 0; 47120a708f8fSGustavo F. Padovan } 47130a708f8fSGustavo F. Padovan 47140a708f8fSGustavo F. Padovan static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb) 47150a708f8fSGustavo F. Padovan { 471623691d75SGustavo F. Padovan struct l2cap_chan *chan; 47170a708f8fSGustavo F. Padovan 4718c2287681SIdo Yariv chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst); 471923691d75SGustavo F. Padovan if (!chan) 47200a708f8fSGustavo F. Padovan goto drop; 47210a708f8fSGustavo F. Padovan 47225b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 47230a708f8fSGustavo F. Padovan 472489bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 47250a708f8fSGustavo F. Padovan goto drop; 47260a708f8fSGustavo F. Padovan 4727e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 47280a708f8fSGustavo F. Padovan goto drop; 47290a708f8fSGustavo F. Padovan 473023070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 47315b4cedaaSAndrei Emeltchenko return 0; 47320a708f8fSGustavo F. Padovan 47330a708f8fSGustavo F. Padovan drop: 47340a708f8fSGustavo F. Padovan kfree_skb(skb); 47350a708f8fSGustavo F. Padovan 47360a708f8fSGustavo F. Padovan return 0; 47370a708f8fSGustavo F. Padovan } 47380a708f8fSGustavo F. Padovan 4739d9b88702SAndrei Emeltchenko static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid, 4740d9b88702SAndrei Emeltchenko struct sk_buff *skb) 47419f69bda6SGustavo F. Padovan { 474223691d75SGustavo F. Padovan struct l2cap_chan *chan; 47439f69bda6SGustavo F. Padovan 4744c2287681SIdo Yariv chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst); 474523691d75SGustavo F. Padovan if (!chan) 47469f69bda6SGustavo F. Padovan goto drop; 47479f69bda6SGustavo F. Padovan 47485b4cedaaSAndrei Emeltchenko BT_DBG("chan %p, len %d", chan, skb->len); 47499f69bda6SGustavo F. Padovan 475089bc500eSGustavo F. Padovan if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) 47519f69bda6SGustavo F. Padovan goto drop; 47529f69bda6SGustavo F. Padovan 4753e13e21dcSVinicius Costa Gomes if (chan->imtu < skb->len) 47549f69bda6SGustavo F. Padovan goto drop; 47559f69bda6SGustavo F. Padovan 475623070494SGustavo F. Padovan if (!chan->ops->recv(chan->data, skb)) 47575b4cedaaSAndrei Emeltchenko return 0; 47589f69bda6SGustavo F. Padovan 47599f69bda6SGustavo F. Padovan drop: 47609f69bda6SGustavo F. Padovan kfree_skb(skb); 47619f69bda6SGustavo F. Padovan 47629f69bda6SGustavo F. Padovan return 0; 47639f69bda6SGustavo F. Padovan } 47649f69bda6SGustavo F. Padovan 47650a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) 47660a708f8fSGustavo F. Padovan { 47670a708f8fSGustavo F. Padovan struct l2cap_hdr *lh = (void *) skb->data; 47680a708f8fSGustavo F. Padovan u16 cid, len; 47690a708f8fSGustavo F. Padovan __le16 psm; 47700a708f8fSGustavo F. Padovan 47710a708f8fSGustavo F. Padovan skb_pull(skb, L2CAP_HDR_SIZE); 47720a708f8fSGustavo F. Padovan cid = __le16_to_cpu(lh->cid); 47730a708f8fSGustavo F. Padovan len = __le16_to_cpu(lh->len); 47740a708f8fSGustavo F. Padovan 47750a708f8fSGustavo F. Padovan if (len != skb->len) { 47760a708f8fSGustavo F. Padovan kfree_skb(skb); 47770a708f8fSGustavo F. Padovan return; 47780a708f8fSGustavo F. Padovan } 47790a708f8fSGustavo F. Padovan 47800a708f8fSGustavo F. Padovan BT_DBG("len %d, cid 0x%4.4x", len, cid); 47810a708f8fSGustavo F. Padovan 47820a708f8fSGustavo F. Padovan switch (cid) { 47833300d9a9SClaudio Takahasi case L2CAP_CID_LE_SIGNALING: 47840a708f8fSGustavo F. Padovan case L2CAP_CID_SIGNALING: 47850a708f8fSGustavo F. Padovan l2cap_sig_channel(conn, skb); 47860a708f8fSGustavo F. Padovan break; 47870a708f8fSGustavo F. Padovan 47880a708f8fSGustavo F. Padovan case L2CAP_CID_CONN_LESS: 4789097db76cSAndrei Emeltchenko psm = get_unaligned((__le16 *) skb->data); 47900a708f8fSGustavo F. Padovan skb_pull(skb, 2); 47910a708f8fSGustavo F. Padovan l2cap_conless_channel(conn, psm, skb); 47920a708f8fSGustavo F. Padovan break; 47930a708f8fSGustavo F. Padovan 47949f69bda6SGustavo F. Padovan case L2CAP_CID_LE_DATA: 47959f69bda6SGustavo F. Padovan l2cap_att_channel(conn, cid, skb); 47969f69bda6SGustavo F. Padovan break; 47979f69bda6SGustavo F. Padovan 4798b501d6a1SAnderson Briglia case L2CAP_CID_SMP: 4799b501d6a1SAnderson Briglia if (smp_sig_channel(conn, skb)) 4800b501d6a1SAnderson Briglia l2cap_conn_del(conn->hcon, EACCES); 4801b501d6a1SAnderson Briglia break; 4802b501d6a1SAnderson Briglia 48030a708f8fSGustavo F. Padovan default: 48040a708f8fSGustavo F. Padovan l2cap_data_channel(conn, cid, skb); 48050a708f8fSGustavo F. Padovan break; 48060a708f8fSGustavo F. Padovan } 48070a708f8fSGustavo F. Padovan } 48080a708f8fSGustavo F. Padovan 48090a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */ 48100a708f8fSGustavo F. Padovan 4811686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) 48120a708f8fSGustavo F. Padovan { 48130a708f8fSGustavo F. Padovan int exact = 0, lm1 = 0, lm2 = 0; 481423691d75SGustavo F. Padovan struct l2cap_chan *c; 48150a708f8fSGustavo F. Padovan 48160a708f8fSGustavo F. Padovan BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); 48170a708f8fSGustavo F. Padovan 48180a708f8fSGustavo F. Padovan /* Find listening sockets and check their link_mode */ 481923691d75SGustavo F. Padovan read_lock(&chan_list_lock); 482023691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 482123691d75SGustavo F. Padovan struct sock *sk = c->sk; 48224343478fSGustavo F. Padovan 482389bc500eSGustavo F. Padovan if (c->state != BT_LISTEN) 48240a708f8fSGustavo F. Padovan continue; 48250a708f8fSGustavo F. Padovan 48260a708f8fSGustavo F. Padovan if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { 48270a708f8fSGustavo F. Padovan lm1 |= HCI_LM_ACCEPT; 482843bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 48290a708f8fSGustavo F. Padovan lm1 |= HCI_LM_MASTER; 48300a708f8fSGustavo F. Padovan exact++; 48310a708f8fSGustavo F. Padovan } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { 48320a708f8fSGustavo F. Padovan lm2 |= HCI_LM_ACCEPT; 483343bd0f32SAndrei Emeltchenko if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) 48340a708f8fSGustavo F. Padovan lm2 |= HCI_LM_MASTER; 48350a708f8fSGustavo F. Padovan } 48360a708f8fSGustavo F. Padovan } 483723691d75SGustavo F. Padovan read_unlock(&chan_list_lock); 48380a708f8fSGustavo F. Padovan 48390a708f8fSGustavo F. Padovan return exact ? lm1 : lm2; 48400a708f8fSGustavo F. Padovan } 48410a708f8fSGustavo F. Padovan 4842686ebf28SUlisses Furquim int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) 48430a708f8fSGustavo F. Padovan { 48440a708f8fSGustavo F. Padovan struct l2cap_conn *conn; 48450a708f8fSGustavo F. Padovan 48460a708f8fSGustavo F. Padovan BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); 48470a708f8fSGustavo F. Padovan 48480a708f8fSGustavo F. Padovan if (!status) { 48490a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, status); 48500a708f8fSGustavo F. Padovan if (conn) 48510a708f8fSGustavo F. Padovan l2cap_conn_ready(conn); 48520a708f8fSGustavo F. Padovan } else 4853e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(status)); 48540a708f8fSGustavo F. Padovan 48550a708f8fSGustavo F. Padovan return 0; 48560a708f8fSGustavo F. Padovan } 48570a708f8fSGustavo F. Padovan 4858686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon) 48590a708f8fSGustavo F. Padovan { 48600a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 48610a708f8fSGustavo F. Padovan 48620a708f8fSGustavo F. Padovan BT_DBG("hcon %p", hcon); 48630a708f8fSGustavo F. Padovan 4864686ebf28SUlisses Furquim if (!conn) 48659f5a0d7bSAndrei Emeltchenko return HCI_ERROR_REMOTE_USER_TERM; 48660a708f8fSGustavo F. Padovan return conn->disc_reason; 48670a708f8fSGustavo F. Padovan } 48680a708f8fSGustavo F. Padovan 4869686ebf28SUlisses Furquim int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) 48700a708f8fSGustavo F. Padovan { 48710a708f8fSGustavo F. Padovan BT_DBG("hcon %p reason %d", hcon, reason); 48720a708f8fSGustavo F. Padovan 4873e175072fSJoe Perches l2cap_conn_del(hcon, bt_to_errno(reason)); 48740a708f8fSGustavo F. Padovan return 0; 48750a708f8fSGustavo F. Padovan } 48760a708f8fSGustavo F. Padovan 48774343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) 48780a708f8fSGustavo F. Padovan { 4879715ec005SGustavo F. Padovan if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) 48800a708f8fSGustavo F. Padovan return; 48810a708f8fSGustavo F. Padovan 48820a708f8fSGustavo F. Padovan if (encrypt == 0x00) { 48834343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) { 4884ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); 48854343478fSGustavo F. Padovan } else if (chan->sec_level == BT_SECURITY_HIGH) 48860f852724SGustavo F. Padovan l2cap_chan_close(chan, ECONNREFUSED); 48870a708f8fSGustavo F. Padovan } else { 48884343478fSGustavo F. Padovan if (chan->sec_level == BT_SECURITY_MEDIUM) 4889c9b66675SGustavo F. Padovan __clear_chan_timer(chan); 48900a708f8fSGustavo F. Padovan } 48910a708f8fSGustavo F. Padovan } 48920a708f8fSGustavo F. Padovan 4893686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) 48940a708f8fSGustavo F. Padovan { 48950a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 489648454079SGustavo F. Padovan struct l2cap_chan *chan; 48970a708f8fSGustavo F. Padovan 48980a708f8fSGustavo F. Padovan if (!conn) 48990a708f8fSGustavo F. Padovan return 0; 49000a708f8fSGustavo F. Padovan 49010a708f8fSGustavo F. Padovan BT_DBG("conn %p", conn); 49020a708f8fSGustavo F. Padovan 4903160dc6acSVinicius Costa Gomes if (hcon->type == LE_LINK) { 490435d4adccSHemant Gupta if (!status && encrypt) 4905160dc6acSVinicius Costa Gomes smp_distribute_keys(conn, 0); 490617cd3f37SUlisses Furquim cancel_delayed_work(&conn->security_timer); 4907160dc6acSVinicius Costa Gomes } 4908160dc6acSVinicius Costa Gomes 49093df91ea2SAndrei Emeltchenko mutex_lock(&conn->chan_lock); 49100a708f8fSGustavo F. Padovan 49113df91ea2SAndrei Emeltchenko list_for_each_entry(chan, &conn->chan_l, list) { 49126be36555SAndrei Emeltchenko l2cap_chan_lock(chan); 49130a708f8fSGustavo F. Padovan 4914f1cb9af5SVinicius Costa Gomes BT_DBG("chan->scid %d", chan->scid); 4915f1cb9af5SVinicius Costa Gomes 4916f1cb9af5SVinicius Costa Gomes if (chan->scid == L2CAP_CID_LE_DATA) { 4917f1cb9af5SVinicius Costa Gomes if (!status && encrypt) { 4918f1cb9af5SVinicius Costa Gomes chan->sec_level = hcon->sec_level; 4919cf4cd009SAndrei Emeltchenko l2cap_chan_ready(chan); 4920f1cb9af5SVinicius Costa Gomes } 4921f1cb9af5SVinicius Costa Gomes 49226be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 4923f1cb9af5SVinicius Costa Gomes continue; 4924f1cb9af5SVinicius Costa Gomes } 4925f1cb9af5SVinicius Costa Gomes 4926c1360a1cSGustavo F. Padovan if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) { 49276be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 49280a708f8fSGustavo F. Padovan continue; 49290a708f8fSGustavo F. Padovan } 49300a708f8fSGustavo F. Padovan 493189bc500eSGustavo F. Padovan if (!status && (chan->state == BT_CONNECTED || 493289bc500eSGustavo F. Padovan chan->state == BT_CONFIG)) { 4933a7d7723aSGustavo Padovan struct sock *sk = chan->sk; 4934a7d7723aSGustavo Padovan 4935c5daa683SGustavo Padovan clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); 4936a7d7723aSGustavo Padovan sk->sk_state_change(sk); 4937a7d7723aSGustavo Padovan 49384343478fSGustavo F. Padovan l2cap_check_encryption(chan, encrypt); 49396be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 49400a708f8fSGustavo F. Padovan continue; 49410a708f8fSGustavo F. Padovan } 49420a708f8fSGustavo F. Padovan 494389bc500eSGustavo F. Padovan if (chan->state == BT_CONNECT) { 49440a708f8fSGustavo F. Padovan if (!status) { 49459b27f350SAndrei Emeltchenko l2cap_send_conn_req(chan); 49460a708f8fSGustavo F. Padovan } else { 4947ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 49480a708f8fSGustavo F. Padovan } 494989bc500eSGustavo F. Padovan } else if (chan->state == BT_CONNECT2) { 49506be36555SAndrei Emeltchenko struct sock *sk = chan->sk; 49510a708f8fSGustavo F. Padovan struct l2cap_conn_rsp rsp; 4952df3c3931SJohan Hedberg __u16 res, stat; 49530a708f8fSGustavo F. Padovan 49546be36555SAndrei Emeltchenko lock_sock(sk); 49556be36555SAndrei Emeltchenko 49560a708f8fSGustavo F. Padovan if (!status) { 4957c5daa683SGustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, 4958c5daa683SGustavo Padovan &bt_sk(sk)->flags)) { 4959df3c3931SJohan Hedberg struct sock *parent = bt_sk(sk)->parent; 4960df3c3931SJohan Hedberg res = L2CAP_CR_PEND; 4961df3c3931SJohan Hedberg stat = L2CAP_CS_AUTHOR_PEND; 496205e9a2f6SIlia Kolomisnky if (parent) 4963df3c3931SJohan Hedberg parent->sk_data_ready(parent, 0); 4964df3c3931SJohan Hedberg } else { 49650e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_CONFIG); 4966df3c3931SJohan Hedberg res = L2CAP_CR_SUCCESS; 4967df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 4968df3c3931SJohan Hedberg } 49690a708f8fSGustavo F. Padovan } else { 49700e587be7SAndrei Emeltchenko __l2cap_state_change(chan, BT_DISCONN); 4971ba13ccd9SMarcel Holtmann __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 4972df3c3931SJohan Hedberg res = L2CAP_CR_SEC_BLOCK; 4973df3c3931SJohan Hedberg stat = L2CAP_CS_NO_INFO; 49740a708f8fSGustavo F. Padovan } 49750a708f8fSGustavo F. Padovan 49766be36555SAndrei Emeltchenko release_sock(sk); 49776be36555SAndrei Emeltchenko 4978fe4128e0SGustavo F. Padovan rsp.scid = cpu_to_le16(chan->dcid); 4979fe4128e0SGustavo F. Padovan rsp.dcid = cpu_to_le16(chan->scid); 4980df3c3931SJohan Hedberg rsp.result = cpu_to_le16(res); 4981df3c3931SJohan Hedberg rsp.status = cpu_to_le16(stat); 4982fc7f8a7eSGustavo F. Padovan l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, 4983fc7f8a7eSGustavo F. Padovan sizeof(rsp), &rsp); 49840a708f8fSGustavo F. Padovan } 49850a708f8fSGustavo F. Padovan 49866be36555SAndrei Emeltchenko l2cap_chan_unlock(chan); 49870a708f8fSGustavo F. Padovan } 49880a708f8fSGustavo F. Padovan 49893df91ea2SAndrei Emeltchenko mutex_unlock(&conn->chan_lock); 49900a708f8fSGustavo F. Padovan 49910a708f8fSGustavo F. Padovan return 0; 49920a708f8fSGustavo F. Padovan } 49930a708f8fSGustavo F. Padovan 4994686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) 49950a708f8fSGustavo F. Padovan { 49960a708f8fSGustavo F. Padovan struct l2cap_conn *conn = hcon->l2cap_data; 49970a708f8fSGustavo F. Padovan 49980a708f8fSGustavo F. Padovan if (!conn) 49990a708f8fSGustavo F. Padovan conn = l2cap_conn_add(hcon, 0); 50000a708f8fSGustavo F. Padovan 50010a708f8fSGustavo F. Padovan if (!conn) 50020a708f8fSGustavo F. Padovan goto drop; 50030a708f8fSGustavo F. Padovan 50040a708f8fSGustavo F. Padovan BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); 50050a708f8fSGustavo F. Padovan 50060a708f8fSGustavo F. Padovan if (!(flags & ACL_CONT)) { 50070a708f8fSGustavo F. Padovan struct l2cap_hdr *hdr; 50080a708f8fSGustavo F. Padovan int len; 50090a708f8fSGustavo F. Padovan 50100a708f8fSGustavo F. Padovan if (conn->rx_len) { 50110a708f8fSGustavo F. Padovan BT_ERR("Unexpected start frame (len %d)", skb->len); 50120a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 50130a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 50140a708f8fSGustavo F. Padovan conn->rx_len = 0; 50150a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 50160a708f8fSGustavo F. Padovan } 50170a708f8fSGustavo F. Padovan 50180a708f8fSGustavo F. Padovan /* Start fragment always begin with Basic L2CAP header */ 50190a708f8fSGustavo F. Padovan if (skb->len < L2CAP_HDR_SIZE) { 50200a708f8fSGustavo F. Padovan BT_ERR("Frame is too short (len %d)", skb->len); 50210a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 50220a708f8fSGustavo F. Padovan goto drop; 50230a708f8fSGustavo F. Padovan } 50240a708f8fSGustavo F. Padovan 50250a708f8fSGustavo F. Padovan hdr = (struct l2cap_hdr *) skb->data; 50260a708f8fSGustavo F. Padovan len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; 50270a708f8fSGustavo F. Padovan 50280a708f8fSGustavo F. Padovan if (len == skb->len) { 50290a708f8fSGustavo F. Padovan /* Complete frame received */ 50300a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, skb); 50310a708f8fSGustavo F. Padovan return 0; 50320a708f8fSGustavo F. Padovan } 50330a708f8fSGustavo F. Padovan 50340a708f8fSGustavo F. Padovan BT_DBG("Start: total len %d, frag len %d", len, skb->len); 50350a708f8fSGustavo F. Padovan 50360a708f8fSGustavo F. Padovan if (skb->len > len) { 50370a708f8fSGustavo F. Padovan BT_ERR("Frame is too long (len %d, expected len %d)", 50380a708f8fSGustavo F. Padovan skb->len, len); 50390a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 50400a708f8fSGustavo F. Padovan goto drop; 50410a708f8fSGustavo F. Padovan } 50420a708f8fSGustavo F. Padovan 50430a708f8fSGustavo F. Padovan /* Allocate skb for the complete frame (with header) */ 50440a708f8fSGustavo F. Padovan conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC); 50450a708f8fSGustavo F. Padovan if (!conn->rx_skb) 50460a708f8fSGustavo F. Padovan goto drop; 50470a708f8fSGustavo F. Padovan 50480a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 50490a708f8fSGustavo F. Padovan skb->len); 50500a708f8fSGustavo F. Padovan conn->rx_len = len - skb->len; 50510a708f8fSGustavo F. Padovan } else { 50520a708f8fSGustavo F. Padovan BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); 50530a708f8fSGustavo F. Padovan 50540a708f8fSGustavo F. Padovan if (!conn->rx_len) { 50550a708f8fSGustavo F. Padovan BT_ERR("Unexpected continuation frame (len %d)", skb->len); 50560a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 50570a708f8fSGustavo F. Padovan goto drop; 50580a708f8fSGustavo F. Padovan } 50590a708f8fSGustavo F. Padovan 50600a708f8fSGustavo F. Padovan if (skb->len > conn->rx_len) { 50610a708f8fSGustavo F. Padovan BT_ERR("Fragment is too long (len %d, expected %d)", 50620a708f8fSGustavo F. Padovan skb->len, conn->rx_len); 50630a708f8fSGustavo F. Padovan kfree_skb(conn->rx_skb); 50640a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 50650a708f8fSGustavo F. Padovan conn->rx_len = 0; 50660a708f8fSGustavo F. Padovan l2cap_conn_unreliable(conn, ECOMM); 50670a708f8fSGustavo F. Padovan goto drop; 50680a708f8fSGustavo F. Padovan } 50690a708f8fSGustavo F. Padovan 50700a708f8fSGustavo F. Padovan skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), 50710a708f8fSGustavo F. Padovan skb->len); 50720a708f8fSGustavo F. Padovan conn->rx_len -= skb->len; 50730a708f8fSGustavo F. Padovan 50740a708f8fSGustavo F. Padovan if (!conn->rx_len) { 50750a708f8fSGustavo F. Padovan /* Complete frame received */ 50760a708f8fSGustavo F. Padovan l2cap_recv_frame(conn, conn->rx_skb); 50770a708f8fSGustavo F. Padovan conn->rx_skb = NULL; 50780a708f8fSGustavo F. Padovan } 50790a708f8fSGustavo F. Padovan } 50800a708f8fSGustavo F. Padovan 50810a708f8fSGustavo F. Padovan drop: 50820a708f8fSGustavo F. Padovan kfree_skb(skb); 50830a708f8fSGustavo F. Padovan return 0; 50840a708f8fSGustavo F. Padovan } 50850a708f8fSGustavo F. Padovan 50860a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p) 50870a708f8fSGustavo F. Padovan { 508823691d75SGustavo F. Padovan struct l2cap_chan *c; 50890a708f8fSGustavo F. Padovan 5090333055f2SGustavo F. Padovan read_lock(&chan_list_lock); 50910a708f8fSGustavo F. Padovan 509223691d75SGustavo F. Padovan list_for_each_entry(c, &chan_list, global_l) { 509323691d75SGustavo F. Padovan struct sock *sk = c->sk; 50940a708f8fSGustavo F. Padovan 5095903d343eSGustavo F. Padovan seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", 50960a708f8fSGustavo F. Padovan batostr(&bt_sk(sk)->src), 50970a708f8fSGustavo F. Padovan batostr(&bt_sk(sk)->dst), 509889bc500eSGustavo F. Padovan c->state, __le16_to_cpu(c->psm), 509923691d75SGustavo F. Padovan c->scid, c->dcid, c->imtu, c->omtu, 510023691d75SGustavo F. Padovan c->sec_level, c->mode); 51010a708f8fSGustavo F. Padovan } 51020a708f8fSGustavo F. Padovan 5103333055f2SGustavo F. Padovan read_unlock(&chan_list_lock); 51040a708f8fSGustavo F. Padovan 51050a708f8fSGustavo F. Padovan return 0; 51060a708f8fSGustavo F. Padovan } 51070a708f8fSGustavo F. Padovan 51080a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file) 51090a708f8fSGustavo F. Padovan { 51100a708f8fSGustavo F. Padovan return single_open(file, l2cap_debugfs_show, inode->i_private); 51110a708f8fSGustavo F. Padovan } 51120a708f8fSGustavo F. Padovan 51130a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = { 51140a708f8fSGustavo F. Padovan .open = l2cap_debugfs_open, 51150a708f8fSGustavo F. Padovan .read = seq_read, 51160a708f8fSGustavo F. Padovan .llseek = seq_lseek, 51170a708f8fSGustavo F. Padovan .release = single_release, 51180a708f8fSGustavo F. Padovan }; 51190a708f8fSGustavo F. Padovan 51200a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs; 51210a708f8fSGustavo F. Padovan 512264274518SGustavo F. Padovan int __init l2cap_init(void) 51230a708f8fSGustavo F. Padovan { 51240a708f8fSGustavo F. Padovan int err; 51250a708f8fSGustavo F. Padovan 5126bb58f747SGustavo F. Padovan err = l2cap_init_sockets(); 51270a708f8fSGustavo F. Padovan if (err < 0) 51280a708f8fSGustavo F. Padovan return err; 51290a708f8fSGustavo F. Padovan 51300a708f8fSGustavo F. Padovan if (bt_debugfs) { 51310a708f8fSGustavo F. Padovan l2cap_debugfs = debugfs_create_file("l2cap", 0444, 51320a708f8fSGustavo F. Padovan bt_debugfs, NULL, &l2cap_debugfs_fops); 51330a708f8fSGustavo F. Padovan if (!l2cap_debugfs) 51340a708f8fSGustavo F. Padovan BT_ERR("Failed to create L2CAP debug file"); 51350a708f8fSGustavo F. Padovan } 51360a708f8fSGustavo F. Padovan 51370a708f8fSGustavo F. Padovan return 0; 51380a708f8fSGustavo F. Padovan } 51390a708f8fSGustavo F. Padovan 514064274518SGustavo F. Padovan void l2cap_exit(void) 51410a708f8fSGustavo F. Padovan { 51420a708f8fSGustavo F. Padovan debugfs_remove(l2cap_debugfs); 5143bb58f747SGustavo F. Padovan l2cap_cleanup_sockets(); 51440a708f8fSGustavo F. Padovan } 51450a708f8fSGustavo F. Padovan 51460a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644); 51470a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); 5148